-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathkillswitch_test.go
More file actions
128 lines (117 loc) · 3.92 KB
/
Copy pathkillswitch_test.go
File metadata and controls
128 lines (117 loc) · 3.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package gatekit
import (
"os"
"testing"
"time"
)
func TestKillSwitchIndefiniteWhenDurationZero(t *testing.T) {
cfg := testConfig(t)
now := time.Now()
if err := Disable(cfg, 0, now); err != nil {
t.Fatal(err)
}
if !isDisabled(cfg, now) {
t.Error("d=0 should disable indefinitely")
}
if !isDisabled(cfg, now.Add(365*24*time.Hour)) {
t.Error("an indefinite disable must still be active a year later")
}
}
func TestKillSwitchTimedExpiresAfterDuration(t *testing.T) {
cfg := testConfig(t)
now := time.Now()
if err := Disable(cfg, time.Hour, now); err != nil {
t.Fatal(err)
}
if !isDisabled(cfg, now.Add(30*time.Minute)) {
t.Error("should still be disabled within the timed window")
}
if isDisabled(cfg, now.Add(2*time.Hour)) {
t.Error("should no longer be disabled after the timed window elapses")
}
}
// A malformed disable file must never be silently read as "not disabled" --
// that would turn a corrupted state file into an unintended re-enable.
func TestKillSwitchMalformedContentFailsClosed(t *testing.T) {
cfg := testConfig(t)
if err := os.MkdirAll(cfg.StateDir, 0700); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(disabledPath(cfg), []byte("not a timestamp"), 0600); err != nil {
t.Fatal(err)
}
if !isDisabled(cfg, time.Now()) {
t.Error("malformed disable-file content must fail toward disabled, not enabled")
}
}
func TestKillSwitchAbsentFileMeansEnabled(t *testing.T) {
cfg := testConfig(t)
if isDisabled(cfg, time.Now()) {
t.Error("no disable file present should mean not disabled")
}
}
func TestKillSwitchEnableClearsItEarly(t *testing.T) {
cfg := testConfig(t)
now := time.Now()
if err := Disable(cfg, time.Hour, now); err != nil {
t.Fatal(err)
}
if err := Enable(cfg); err != nil {
t.Fatal(err)
}
if isDisabled(cfg, now) {
t.Error("Enable should clear a still-active timed disable immediately")
}
}
func TestKillSwitchEnableOnAbsentFileIsNotError(t *testing.T) {
cfg := testConfig(t)
if err := Enable(cfg); err != nil {
t.Fatalf("Enable with no active disable should be a no-op, not an error: %v", err)
}
}
// The kill switch has no rate limit of its own and must not share the
// bypass/snooze valve's budget -- direct answer to the reply-gate incident
// where an exhausted bypass allowance left Grayson with no way through.
func TestKillSwitchWorksEvenWithBypassRateLimitExhausted(t *testing.T) {
cfg := bypassTestConfig(t)
now := time.Now()
writeSource(t, cfg.SourcesDir, "mod", true, Item{ID: "a", Title: "a", FirstSeenAt: now.Add(-time.Hour)})
// Exhaust the bypass budget.
if r, err := RequestBypass(cfg, now); err != nil || !r.Granted {
t.Fatalf("setup grant 1 failed: %+v, %v", r, err)
}
if r, err := RequestBypass(cfg, now.Add(6*time.Minute)); err != nil || !r.Granted {
t.Fatalf("setup grant 2 failed: %+v, %v", r, err)
}
if r, err := RequestBypass(cfg, now.Add(12*time.Minute)); err != nil || r.Granted {
t.Fatalf("expected the bypass budget to be exhausted: %+v, %v", r, err)
}
// The kill switch must still work, unconditionally.
if err := Disable(cfg, 0, now.Add(13*time.Minute)); err != nil {
t.Fatalf("Disable must succeed regardless of bypass valve state: %v", err)
}
dec, err := Evaluate(cfg, now.Add(13*time.Minute))
if err != nil {
t.Fatal(err)
}
if dec.Blocked {
t.Error("kill switch should unblock even after the bypass rate limit was exhausted")
}
}
// isDisabled is checked before SourcesDir is ever read -- a broken or
// missing sources directory must not stop the kill switch from working.
func TestKillSwitchShortCircuitsBeforeSourcesDirIsRead(t *testing.T) {
cfg := testConfig(t)
cfg.SourcesDir = "/nonexistent/does/not/exist"
now := time.Now()
if err := Disable(cfg, 0, now); err != nil {
t.Fatal(err)
}
dec, err := Evaluate(cfg, now)
if err != nil {
t.Fatalf("Evaluate with kill switch active and a bad SourcesDir must still succeed cleanly: %v", err)
}
if dec.Blocked {
t.Error("a disabled gate must never block, regardless of SourcesDir")
}
}