返回 DeepSeek-Reasonix
longrun_test.go
根目录 / cmd / e2ebench / longrun_test.go
1 package main
2
3 import (
4 "strings"
5 "testing"
6 )
7
8 func faultedRun(id string, injected, afterFault int, passed bool) result {
9 r := result{task: task{ID: id}, Attempt: 1, Passed: passed}
10 r.Meter = &meterUsage{Requests: 10, Injected: injected, RequestsAfterFault: afterFault}
11 return r
12 }
13
14 func TestFaultCadenceScalesWithTheRun(t *testing.T) {
15 script, err := parseFaultScript("every:5:500")
16 if err != nil {
17 t.Fatalf("parse: %v", err)
18 }
19 for _, index := range []int{5, 10, 15} {
20 if status, ok := script.statusFor(index); !ok || status != 500 {
21 t.Fatalf("request %d = %d/%v, want an injected 500", index, status, ok)
22 }
23 }
24 for _, index := range []int{1, 4, 6, 9} {
25 if _, ok := script.statusFor(index); ok {
26 t.Fatalf("request %d must be forwarded", index)
27 }
28 }
29 }
30
31 // An absolute index is a targeted failure; a cadence is background pressure.
32 // The targeted one must stay exactly where it was asked for.
33 func TestAbsoluteFaultWinsOverTheCadence(t *testing.T) {
34 script, err := parseFaultScript("10:429,every:5:500")
35 if err != nil {
36 t.Fatalf("parse: %v", err)
37 }
38 if status, _ := script.statusFor(10); status != 429 {
39 t.Fatalf("request 10 = %d, want the targeted 429", status)
40 }
41 if status, _ := script.statusFor(5); status != 500 {
42 t.Fatalf("request 5 = %d, want the cadence 500", status)
43 }
44 }
45
46 func TestFaultScriptRejectsMalformedCadence(t *testing.T) {
47 for _, bad := range []string{"every:5", "every:0:500", "every:x:500", "every:5:200"} {
48 if _, err := parseFaultScript(bad); err == nil {
49 t.Fatalf("%q must be rejected", bad)
50 }
51 }
52 }
53
54 func TestMeterCountsRequestsAfterAFault(t *testing.T) {
55 upstream := okUpstream()
56 script, _ := parseFaultScript("2:429")
57 m, base, stop := meterAgainst(t, upstream, script)
58 defer stop()
59 for range 4 {
60 post(t, base, "/chat/completions", `{"model":"x"}`).Body.Close()
61 }
62 got := m.snapshot()
63 if got.Injected != 1 {
64 t.Fatalf("injected = %d, want 1", got.Injected)
65 }
66 if got.RequestsAfterFault != 2 {
67 t.Fatalf("requests after fault = %d, want 2 (requests 3 and 4)", got.RequestsAfterFault)
68 }
69 }
70
71 func TestMeterCountsNoRequestsAfterFaultWhenTheHarnessGivesUp(t *testing.T) {
72 script, _ := parseFaultScript("2:429")
73 m, base, stop := meterAgainst(t, okUpstream(), script)
74 defer stop()
75 for range 2 {
76 post(t, base, "/chat/completions", `{"model":"x"}`).Body.Close()
77 }
78 if got := m.snapshot(); got.RequestsAfterFault != 0 {
79 t.Fatalf("requests after fault = %d, want 0 — nothing followed the failure", got.RequestsAfterFault)
80 }
81 }
82
83 func TestFaultRecoverySeparatesRetryingFromSolving(t *testing.T) {
84 got := renderFaultRecovery([]result{
85 faultedRun("solved-through", 2, 5, true),
86 faultedRun("retried-but-lost", 1, 4, false),
87 faultedRun("gave-up", 1, 0, false),
88 faultedRun("never-faulted", 0, 0, true),
89 })
90 for _, want := range []string{
91 "**Fault recovery** (3 runs failed on purpose, 4 injections)",
92 "**retried** 67% (2)",
93 "**still solved** 33% (1/3)",
94 "in-run control 100% (1/1 never hit a fault)",
95 } {
96 if !strings.Contains(got, want) {
97 t.Fatalf("recovery line missing %q:\n%s", want, got)
98 }
99 }
100 }
101
102 func TestFaultRecoveryRendersNothingWithoutInjections(t *testing.T) {
103 if got := renderFaultRecovery([]result{faultedRun("clean", 0, 0, true)}); got != "" {
104 t.Fatalf("want no section when nothing was injected, got:\n%s", got)
105 }
106 }
107
107 lines GO