package gateway import ( "compress/gzip" "io" "os" "path/filepath" "reflect" "strings" "testing" "time" ) func TestQualificationCatalogMatchesSection7(t *testing.T) { media := qualificationMediaProfiles() if len(media) != 3 { t.Fatalf("media profile count = %d, want 3", len(media)) } wantMedia := []qualificationMediaProfile{ {Name: "1080p60-h264", Codec: "h264", BitrateKbps: 20000, Duration: 10 * time.Minute, Warmup: time.Second, PacketBytes: 1179}, {Name: "1440p120-hevc", Codec: "hevc", BitrateKbps: 50000, Duration: 10 * time.Minute, Warmup: time.Second, PacketBytes: 1179}, {Name: "4k60-hevc", Codec: "hevc", BitrateKbps: 80000, Duration: 10 * time.Minute, Warmup: time.Second, PacketBytes: 1179}, } if !reflect.DeepEqual(media, wantMedia) { t.Fatalf("media profiles = %#v, want %#v", media, wantMedia) } impairments := qualificationImpairmentProfiles() wantImpairments := []qualificationImpairmentProfile{ {Name: "baseline", RTT: 20 * time.Millisecond}, {Name: "latency", RTT: 150 * time.Millisecond}, {Name: "jitter", RTT: 50 * time.Millisecond, Jitter: 30 * time.Millisecond}, {Name: "loss", RTT: 50 * time.Millisecond, Jitter: 10 * time.Millisecond, LossPercent: 5}, {Name: "reorder", RTT: 100 * time.Millisecond, Jitter: 10 * time.Millisecond, LossPercent: 1, Reorder: true}, {Name: "constrained", RTT: 50 * time.Millisecond, Jitter: 10 * time.Millisecond, LossPercent: 2, Reorder: true, CapacitySteps: []int{25, 50}}, } if !reflect.DeepEqual(impairments, wantImpairments) { t.Fatalf("impairment profiles = %#v, want %#v", impairments, wantImpairments) } } func TestQualificationOutputAndStatisticsFailClosed(t *testing.T) { if err := validateQualificationOutputDir("relative/evidence"); err == nil { t.Fatal("relative evidence directory was accepted") } if err := validateQualificationOutputDir(filepath.Join(t.TempDir(), "evidence")); err != nil { t.Fatalf("absolute evidence directory rejected: %v", err) } summary, err := summarizeQualificationSamples([]time.Duration{ time.Millisecond, 2 * time.Millisecond, 3 * time.Millisecond, 4 * time.Millisecond, 5 * time.Millisecond, }) if err != nil { t.Fatal(err) } if summary.Count != 5 || summary.Min != time.Millisecond || summary.Median != 3*time.Millisecond || summary.P90 != 5*time.Millisecond || summary.P95 != 5*time.Millisecond || summary.P99 != 5*time.Millisecond || summary.Max != 5*time.Millisecond || summary.Mean != 3*time.Millisecond || summary.Histogram["le_5ms"] != 5 { t.Fatalf("summary = %#v", summary) } if err := enforceQualificationProcessingGate(summary); err != nil { t.Fatalf("5 ms p95 rejected: %v", err) } summary.P95++ if err := enforceQualificationProcessingGate(summary); err == nil { t.Fatal("p95 above 5 ms was accepted") } } func TestQualificationShortProcessingWritesRawArtifact(t *testing.T) { profile := qualificationMediaProfile{ Name: "smoke", Codec: "h264", BitrateKbps: 1000, Duration: 200 * time.Millisecond, Warmup: time.Millisecond, PacketBytes: 100, } rawPath := filepath.Join(t.TempDir(), "processing.csv.gz") summary, err := runQualificationProcessing(profile, rawPath) if err != nil { t.Fatal(err) } if summary.Count < 1 || summary.RawSamplesSHA256 == "" || summary.RawSamplesBytes < 1 { t.Fatalf("processing summary = %#v", summary) } file, err := os.Open(rawPath) if err != nil { t.Fatal(err) } defer file.Close() reader, err := gzip.NewReader(file) if err != nil { t.Fatal(err) } raw, err := io.ReadAll(reader) if err != nil { t.Fatal(err) } if err := reader.Close(); err != nil { t.Fatal(err) } if !strings.HasPrefix(string(raw), "elapsed_ns,processing_ns\n") || strings.Count(string(raw), "\n") != int(summary.Count)+1 { t.Fatalf("raw sample rows do not match summary count: %q", raw) } } func TestQualificationProcessingPreservesPayload(t *testing.T) { payload := qualificationPayload(qualificationMediaProfiles()[0]) processed, elapsed, err := processQualificationPayload(7, payload) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(processed, payload) { t.Fatal("encoded payload mutated") } if elapsed <= 0 { t.Fatalf("processing duration = %s", elapsed) } } func TestQualificationImpairmentIsDeterministicAndBounded(t *testing.T) { profile := qualificationImpairmentProfiles()[3] first, err := runQualificationImpairment(profile, qualificationMediaProfiles()[0], 10_000) if err != nil { t.Fatal(err) } second, err := runQualificationImpairment(profile, qualificationMediaProfiles()[0], 10_000) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(first, second) { t.Fatalf("impairment run is not deterministic:\n%#v\n%#v", first, second) } if first.Sent != 10_000 || first.Delivered+first.Dropped != first.Sent || first.ObservedLossPercent < 4.8 || first.ObservedLossPercent > 5.2 || first.MaxQueuePackets > qualificationImpairmentQueuePackets { t.Fatalf("impairment observation = %#v", first) } if _, err := runQualificationImpairment(profile, qualificationMediaProfiles()[0], qualificationImpairmentMaxPackets+1); err == nil { t.Fatal("unbounded impairment packet count was accepted") } } func TestQualificationUsesPublicQUICAndProductionPacer(t *testing.T) { qualificationTraverseProfiles(t, qualificationMediaProfiles()) evidence, err := qualificationPacerEvidence() if err != nil { t.Fatal(err) } if len(evidence.PerFlowBytes) != 8 || len(evidence.CapacitySteps) != 2 || evidence.JainIndex < 0.99 { t.Fatalf("pacer evidence = %#v", evidence) } }