| index d1bd77d9a..25491628d 100644 |
| --- a/internal/moves/budget_test.go |
| +++ b/internal/moves/budget_test.go |
| @@ -22,7 +22,7 @@ func TestReadinessBudget(t *testing.T) { |
| t.Fatalf("rev 7.4's formula admits %d attempts for a tiny instance in %.0f s, want 2", n, CutWindowDefault) |
| } |
| // the boundary: fixed costs of 70 s leave exactly one attempt; 71 s none |
| - edge := CutEstimate{Stop: 70 - 5, Open: 5, Probe: ProbeSeconds, Settle: SettleSeconds} |
| + edge := CutEstimate{Stop: 70 - OpenBudget, Open: OpenBudget, Probe: ProbeSeconds, Settle: SettleSeconds} |
| if n := edge.AttemptsAdmitted(CutWindowDefault); n != 1 { |
| t.Fatalf("fixed costs of 70 s admit %d attempts, want 1", n) |
| } |
| @@ -147,15 +147,52 @@ func TestEstimateMirrorBar(t *testing.T) { |
| } |
| } |
| |
| -// A zero or missing rate prices a phase at infinity: refused, never admitted. |
| -func TestEstimateZeroRateRefuses(t *testing.T) { |
| - for name, r := range map[string]Rates{ |
| - "cross": {Cross: 0, S3: 250, Disk: 500}, |
| - "s3": {Cross: 10, S3: 0, Disk: 500}, |
| - "disk": {Cross: 10, S3: 250, Disk: 0}, |
| - } { |
| - if n := Estimate(1, r).AttemptsAdmitted(CutWindowDefault); n != 0 { |
| - t.Fatalf("%s rate of zero admits %d attempts, want 0", name, n) |
| +// An unusable input prices the cut at infinity: refused, never admitted. A |
| +// negative rate would otherwise price a phase below zero and let a move in. |
| +func TestEstimateInvalidInputsRefuse(t *testing.T) { |
| + nan, inf := math.NaN(), math.Inf(1) |
| + good := ExampleRates |
| + with := func(f func(r *Rates)) Rates { r := good; f(&r); return r } |
| + cases := map[string]struct { |
| + db float64 |
| + r Rates |
| + }{ |
| + "cross zero": {1, with(func(r *Rates) { r.Cross = 0 })}, |
| + "cross negative": {1, with(func(r *Rates) { r.Cross = -10 })}, |
| + "cross NaN": {1, with(func(r *Rates) { r.Cross = nan })}, |
| + "cross Inf": {1, with(func(r *Rates) { r.Cross = inf })}, |
| + "s3 zero": {1, with(func(r *Rates) { r.S3 = 0 })}, |
| + "s3 negative": {1, with(func(r *Rates) { r.S3 = -250 })}, |
| + "s3 NaN": {1, with(func(r *Rates) { r.S3 = nan })}, |
| + "s3 Inf": {1, with(func(r *Rates) { r.S3 = inf })}, |
| + "disk zero": {1, with(func(r *Rates) { r.Disk = 0 })}, |
| + "disk negative": {1, with(func(r *Rates) { r.Disk = -500 })}, |
| + "disk NaN": {1, with(func(r *Rates) { r.Disk = nan })}, |
| + "disk Inf": {1, with(func(r *Rates) { r.Disk = inf })}, |
| + "bar negative": {1, with(func(r *Rates) { r.MirrorBar = -16 })}, |
| + "bar NaN": {1, with(func(r *Rates) { r.MirrorBar = nan })}, |
| + "bar Inf": {1, with(func(r *Rates) { r.MirrorBar = inf })}, |
| + "db negative": {-2048, good}, |
| + "db NaN": {nan, good}, |
| + "db Inf": {inf, good}, |
| + // a negative database against a negative rate: the quotient is |
| + // positive, and must still be refused |
| + "db and s3 negative": {-1, with(func(r *Rates) { r.S3 = -250 })}, |
| + } |
| + for name, c := range cases { |
| + e := Estimate(c.db, c.r) |
| + if n := e.AttemptsAdmitted(CutWindowDefault); n != 0 { |
| + t.Errorf("%s admits %d attempts, want 0", name, n) |
| } |
| + if n := e.AttemptsAdmitted(1e9); n != 0 { |
| + t.Errorf("%s admits %d attempts in a huge window, want 0", name, n) |
| + } |
| + if f := e.Fixed(); !math.IsInf(f, 1) { |
| + t.Errorf("%s fixed cost %v, want +Inf", name, f) |
| + } |
| + } |
| + // the boundary the refusals must not touch: an empty database is valid |
| + if n := Estimate(0, ExampleRates).AttemptsAdmitted(CutWindowDefault); n != 2 { |
| + t.Errorf("an empty database admits %d attempts, want 2", n) |
| } |
| } |