fix(gateway): qualify stepped impairment throughput

This commit is contained in:
sechmachine
2026-07-30 06:59:32 +07:00
parent b7a42dc652
commit 9d627413a0
2 changed files with 28 additions and 14 deletions
+17 -12
View File
@@ -212,26 +212,31 @@ func TestQualificationSixImpairmentProfilesTraverseProductionPath(t *testing.T)
} }
} }
func TestQualificationLossAndSteppedThroughputBounds(t *testing.T) {
profiles := qualificationImpairmentProfiles()
for _, profile := range profiles[3:] {
observation, err := runQualificationImpairment(t, profile, qualificationMediaProfiles()[0],
qualificationImpairmentPacketCount, filepath.Join(t.TempDir(), profile.Name+".csv.gz"))
if err != nil {
t.Fatalf("%s: %v", profile.Name, err)
}
if observation.ObservedThroughputKbps <= 0 ||
profile.Name == "constrained" && len(observation.CapacityStepObservations) != 2 {
t.Fatalf("%s observation = %#v", profile.Name, observation)
}
}
}
func TestQualificationUsesPublicQUICAndProductionPacer(t *testing.T) { func TestQualificationUsesPublicQUICAndProductionPacer(t *testing.T) {
qualificationTraverseProfiles(t, qualificationMediaProfiles()) qualificationTraverseProfiles(t, qualificationMediaProfiles())
evidence, err := qualificationPacerEvidence(t, filepath.Join(t.TempDir(), "fairness.csv.gz"), 2*time.Second, 2*time.Second) evidence, err := qualificationPacerEvidence(t, filepath.Join(t.TempDir(), "fairness.csv.gz"), 2*time.Second, 4*time.Second)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if len(evidence.PerFlowBytes) != 8 || len(evidence.CapacitySteps) != 2 || if len(evidence.PerFlowBytes) != 8 || len(evidence.CapacitySteps) != 2 ||
len(evidence.Series) != 6 || evidence.RawSamplesSHA256 == "" || evidence.JainIndex < 0.99 { len(evidence.Series) != 10 || evidence.RawSamplesSHA256 == "" || evidence.JainIndex < 0.99 {
t.Fatalf("pacer evidence = %#v", evidence) t.Fatalf("pacer evidence = %#v", evidence)
} }
}
func TestQualificationCapacityStepsConvergeWithinTenSeconds(t *testing.T) {
evidence, err := qualificationPacerEvidence(t, filepath.Join(t.TempDir(), "fairness.csv.gz"), 2*time.Second, 10*time.Second)
if err != nil {
t.Fatal(err)
}
if len(evidence.CapacitySteps) != 2 {
t.Fatalf("capacity steps = %#v", evidence.CapacitySteps)
}
for _, step := range evidence.CapacitySteps { for _, step := range evidence.CapacitySteps {
if step.Convergence > 10*time.Second || step.MaximumFiveSecond > step.FiveSecondCap*105/100 { if step.Convergence > 10*time.Second || step.MaximumFiveSecond > step.FiveSecondCap*105/100 {
t.Fatalf("capacity step = %#v", step) t.Fatalf("capacity step = %#v", step)
+11 -2
View File
@@ -1187,8 +1187,17 @@ func runQualificationImpairment(t *testing.T, profile qualificationImpairmentPro
observation.ObservedLossPercent = float64(observation.Dropped) * 100 / float64(packetCount) observation.ObservedLossPercent = float64(observation.Dropped) * 100 / float64(packetCount)
observation.ObservedReorderPercent = float64(observation.ObservedOutOfOrder) * 100 / float64(packetCount) observation.ObservedReorderPercent = float64(observation.ObservedOutOfOrder) * 100 / float64(packetCount)
if packetCount >= qualificationImpairmentPacketCount { if packetCount >= qualificationImpairmentPacketCount {
lowerThroughput := float64(media.BitrateKbps) * (1 - profile.LossPercent/100) * 0.90 capacityFactor := 1.0
upperThroughput := float64(media.BitrateKbps) * 1.05 if len(profile.CapacitySteps) > 0 {
inverseRates := 1.0
for _, reduction := range profile.CapacitySteps {
inverseRates += 100 / float64(100-reduction)
}
capacityFactor = float64(len(profile.CapacitySteps)+1) / inverseRates
}
expectedThroughput := float64(media.BitrateKbps) * (1 - profile.LossPercent/100) * capacityFactor
lowerThroughput := expectedThroughput * 0.90
upperThroughput := expectedThroughput * 1.05
if observation.ObservedThroughputKbps < lowerThroughput || observation.ObservedThroughputKbps > upperThroughput { if observation.ObservedThroughputKbps < lowerThroughput || observation.ObservedThroughputKbps > upperThroughput {
return qualificationImpairmentObservation{}, fmt.Errorf("observed throughput %.2f outside [%.2f,%.2f]", observation.ObservedThroughputKbps, lowerThroughput, upperThroughput) return qualificationImpairmentObservation{}, fmt.Errorf("observed throughput %.2f outside [%.2f,%.2f]", observation.ObservedThroughputKbps, lowerThroughput, upperThroughput)
} }