The browser and CLI flows both use download/upload/complete; the
/api/tests/{id}/events endpoint and its Runner plumbing were dead code
that could bypass the single-active-test lock via expireActiveLocked
promoting the queue while an SSE stream was still running.
Remove the endpoint, Runner option, DefaultRunner, probe.Run engine and
the frontend subscribe/closeSource leftovers. Add a regression test
asserting the endpoint returns 404 and create responses omit eventsUrl.
105 lines
3.6 KiB
Go
105 lines
3.6 KiB
Go
package probe
|
|
|
|
import (
|
|
"math"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestParseTargetDefaultsPlainHostToPort80(t *testing.T) {
|
|
target, err := ParseTarget(" example.com ")
|
|
if err != nil {
|
|
t.Fatalf("ParseTarget returned error: %v", err)
|
|
}
|
|
|
|
if target.Host != "example.com" {
|
|
t.Fatalf("Host = %q, want example.com", target.Host)
|
|
}
|
|
if target.Port != 80 {
|
|
t.Fatalf("Port = %d, want 80", target.Port)
|
|
}
|
|
if target.Address != "example.com:80" {
|
|
t.Fatalf("Address = %q, want example.com:80", target.Address)
|
|
}
|
|
}
|
|
|
|
func TestParseTargetUsesExplicitPort(t *testing.T) {
|
|
target, err := ParseTarget("103.46.93.38:443")
|
|
if err != nil {
|
|
t.Fatalf("ParseTarget returned error: %v", err)
|
|
}
|
|
|
|
if target.Host != "103.46.93.38" || target.Port != 443 || target.Address != "103.46.93.38:443" {
|
|
t.Fatalf("target = %#v, want host 103.46.93.38 port 443 address 103.46.93.38:443", target)
|
|
}
|
|
}
|
|
|
|
func TestParseTargetDefaultsHTTPSURLToPort443(t *testing.T) {
|
|
target, err := ParseTarget("https://example.com/health")
|
|
if err != nil {
|
|
t.Fatalf("ParseTarget returned error: %v", err)
|
|
}
|
|
|
|
if target.Host != "example.com" || target.Port != 443 || target.Address != "example.com:443" {
|
|
t.Fatalf("target = %#v, want host example.com port 443 address example.com:443", target)
|
|
}
|
|
}
|
|
|
|
func TestParseTargetRejectsBlankAndBadPort(t *testing.T) {
|
|
for _, input := range []string{"", " ", "example.com:abc", "example.com:70000"} {
|
|
if _, err := ParseTarget(input); err == nil {
|
|
t.Fatalf("ParseTarget(%q) succeeded, want error", input)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSummarizeCalculatesLatencyLossJitterAndScore(t *testing.T) {
|
|
start := time.Date(2026, 6, 5, 8, 0, 0, 0, time.UTC)
|
|
samples := []Sample{
|
|
{At: start, Kind: "tcp", Success: true, Latency: 40 * time.Millisecond},
|
|
{At: start.Add(time.Second), Kind: "tcp", Success: true, Latency: 55 * time.Millisecond},
|
|
{At: start.Add(2 * time.Second), Kind: "tcp", Success: false, Error: "timeout"},
|
|
{At: start.Add(3 * time.Second), Kind: "http", Success: true, Latency: 70 * time.Millisecond},
|
|
}
|
|
|
|
summary := Summarize("103.46.93.38:80", start, start.Add(4*time.Second), samples)
|
|
|
|
if summary.Target != "103.46.93.38:80" {
|
|
t.Fatalf("Target = %q, want 103.46.93.38:80", summary.Target)
|
|
}
|
|
if summary.Samples != 4 || summary.Successes != 3 || summary.Failures != 1 {
|
|
t.Fatalf("counts = samples %d successes %d failures %d, want 4/3/1", summary.Samples, summary.Successes, summary.Failures)
|
|
}
|
|
if summary.AvgLatencyMS != 55 {
|
|
t.Fatalf("AvgLatencyMS = %.2f, want 55", summary.AvgLatencyMS)
|
|
}
|
|
if summary.MinLatencyMS != 40 || summary.MaxLatencyMS != 70 {
|
|
t.Fatalf("latency range = %.2f..%.2f, want 40..70", summary.MinLatencyMS, summary.MaxLatencyMS)
|
|
}
|
|
if !nearlyEqual(summary.PacketLossPct, 25, 0.001) {
|
|
t.Fatalf("PacketLossPct = %.4f, want 25", summary.PacketLossPct)
|
|
}
|
|
if !nearlyEqual(summary.JitterMS, 15, 0.001) {
|
|
t.Fatalf("JitterMS = %.4f, want 15", summary.JitterMS)
|
|
}
|
|
if summary.Score <= 0 || summary.Score >= 100 {
|
|
t.Fatalf("Score = %.2f, want positive degraded score below 100", summary.Score)
|
|
}
|
|
}
|
|
|
|
func TestSummarizeHandlesNoSamples(t *testing.T) {
|
|
start := time.Date(2026, 6, 5, 8, 0, 0, 0, time.UTC)
|
|
summary := Summarize("example.com:80", start, start, nil)
|
|
|
|
if summary.Samples != 0 || summary.Successes != 0 || summary.Failures != 0 {
|
|
t.Fatalf("counts = samples %d successes %d failures %d, want all zero", summary.Samples, summary.Successes, summary.Failures)
|
|
}
|
|
if summary.PacketLossPct != 0 || summary.Score != 0 {
|
|
t.Fatalf("empty summary loss %.2f score %.2f, want 0/0", summary.PacketLossPct, summary.Score)
|
|
}
|
|
}
|
|
|
|
func nearlyEqual(got, want, tolerance float64) bool {
|
|
return math.Abs(got-want) <= tolerance
|
|
}
|