#!/usr/bin/env bash set -u BASE='https://speed.elijahf.com' PING_TOKENS='eyJleHAiOjE3Nzg5Njk4NjQsIm5vbmNlIjoicWdDUWc2SVJrMWhfRU5SZ0oyazl4ZjN5IiwibWV0aG9kIjoiR0VUIiwicGF0aCI6Ii9waW5nIn0.Tal4s0hMz1qrNWa1A7d2a8tRwqMQ6x8hyoWinPqwuRY eyJleHAiOjE3Nzg5Njk4NjQsIm5vbmNlIjoibTdPRDQ5S2xMY1dQZXQ2MVI2M1pwZVJzIiwibWV0aG9kIjoiR0VUIiwicGF0aCI6Ii9waW5nIn0.iMqjcGSGvtpgXgptlDmfQQdNNd-sXYOGSnZJlL5jjpk eyJleHAiOjE3Nzg5Njk4NjQsIm5vbmNlIjoicjBueTFBTDRkUnREbWMzVjRGVnFmY1VoIiwibWV0aG9kIjoiR0VUIiwicGF0aCI6Ii9waW5nIn0.Vzl2X7QFCpUM8Y3JLJquA1WUDzuWM4o-fsGAgGu8tf4 eyJleHAiOjE3Nzg5Njk4NjQsIm5vbmNlIjoiUElWZVJtQW9NaERfcVJXVWF5Q19FdlMxIiwibWV0aG9kIjoiR0VUIiwicGF0aCI6Ii9waW5nIn0.vVnW0TdfDTSdaHLYVOQeFDzZDhL7sJ2jcRbs095J_Uk eyJleHAiOjE3Nzg5Njk4NjQsIm5vbmNlIjoidXdFWnVXTFJ4ajF0OEc1djY3WFNqNFR1IiwibWV0aG9kIjoiR0VUIiwicGF0aCI6Ii9waW5nIn0.hJVH4uZOX3l05_yPR4HWLfHcyQNyHJwiFDTCKYsDyMg eyJleHAiOjE3Nzg5Njk4NjQsIm5vbmNlIjoibDloTkliZVNvY0NTZElOOHpKZ19kTml2IiwibWV0aG9kIjoiR0VUIiwicGF0aCI6Ii9waW5nIn0.NOO8jypoYlmkbB03_LFcBtrtJ02qZnsZ106PXIVfUlE' DOWNLOAD_TOKEN='eyJleHAiOjE3Nzg5Njk4NjQsIm5vbmNlIjoiMnBFQ2dCWHZRckwzV3MzaDdINkp6OUdhIiwibWV0aG9kIjoiR0VUIiwicGF0aCI6Ii9kb3dubG9hZCIsIm1heEJ5dGVzIjoyNTAwMDAwMH0.z7ReNTgiqqCfaRH1deeDuJEsS6QRAgJsUreZsD-rkdE' UPLOAD_TOKEN='eyJleHAiOjE3Nzg5Njk4NjQsIm5vbmNlIjoicTM5a05KSndjZW05dlo1M3FvWnp6MlFZIiwibWV0aG9kIjoiUE9TVCIsInBhdGgiOiIvdXBsb2FkIiwibWF4Qnl0ZXMiOjEyMDAwMDAwfQ._PoM9Zq9QCs2Ox-ztAkIMTuIfbPIKfskcEHxCS1eejw' DOWNLOAD_BYTES=25000000 UPLOAD_BYTES=12000000 fail() { printf '%s\n' "$1" >&2 exit 1 } have() { command -v "$1" >/dev/null 2>&1 } for bin in curl awk dd head date; do have "$bin" || fail "missing required command: $bin" done printf 'Running speed test...\n\n' PING_SAMPLES='' for token in $PING_TOKENS; do OUT=$(curl -sS -H "Authorization: Bearer $token" -o /dev/null -w "%{http_code} %{time_total}" "$BASE/ping" 2>/dev/null) || fail "latency test failed" CODE=$(printf '%s\n' "$OUT" | awk '{print $1}') TIME=$(printf '%s\n' "$OUT" | awk '{print $2}') [ "$CODE" = "200" ] || fail "latency test failed with HTTP $CODE" MS=$(printf '%s\n' "$TIME" | awk '{printf "%.0f", $1 * 1000}') PING_SAMPLES="$PING_SAMPLES$MS " done PING=$(printf '%s' "$PING_SAMPLES" | awk 'NF { sum += $1; count++ } END { if (count == 0) exit 1; printf "%.0f", sum / count }') || fail "latency calculation failed" JITTER=$(printf '%s' "$PING_SAMPLES" | awk 'NF { v[++n] = $1; sum += $1 } END { if (n < 2) { print 0; exit } avg = sum / n; for (i = 1; i <= n; i++) { d = v[i] - avg; if (d < 0) d = -d; total += d } printf "%.0f", total / n }') || fail "jitter calculation failed" DOWNLOAD_OUT=$(curl -sS -H "Authorization: Bearer $DOWNLOAD_TOKEN" -o /dev/null -w "%{http_code} %{speed_download}" "$BASE/download?bytes=$DOWNLOAD_BYTES" 2>/dev/null) || fail "download test failed" DOWNLOAD_CODE=$(printf '%s\n' "$DOWNLOAD_OUT" | awk '{print $1}') [ "$DOWNLOAD_CODE" = "200" ] || fail "download test failed with HTTP $DOWNLOAD_CODE" DOWNLOAD_MBPS=$(printf '%s\n' "$DOWNLOAD_OUT" | awk '{printf "%.0f", ($2 * 8) / 1000000}') UPLOAD_OUT=$(dd if=/dev/zero bs="$UPLOAD_BYTES" count=1 2>/dev/null | curl -sS -X POST -H "Authorization: Bearer $UPLOAD_TOKEN" -H "Content-Type: application/octet-stream" --data-binary @- -o /dev/null -w "%{http_code} %{speed_upload}" "$BASE/upload" 2>/dev/null) || fail "upload test failed" UPLOAD_CODE=$(printf '%s\n' "$UPLOAD_OUT" | awk '{print $1}') [ "$UPLOAD_CODE" = "200" ] || fail "upload test failed with HTTP $UPLOAD_CODE" UPLOAD_MBPS=$(printf '%s\n' "$UPLOAD_OUT" | awk '{printf "%.0f", ($2 * 8) / 1000000}') printf 'Ping: %s ms\n' "$PING" printf 'Jitter: %s ms\n' "$JITTER" printf 'Download: %s Mbps\n' "$DOWNLOAD_MBPS" printf 'Upload: %s Mbps\n\n' "$UPLOAD_MBPS" printf 'Test completed.\n'