carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package rolloutwords
2
3import (
4 "fmt"
5 "strings"
6 "testing"
7
8 "github.com/carlosframework/platform/internal/status"
9)
10
11func allWords() map[string]string {
12 out := map[string]string{
13 "EventSwapping": EventSwapping, "EventSwapped": EventSwapped, "EventSwapFailed": EventSwapFailed,
14 "EventHoldDown": EventHoldDown, "EventCohortHalted": EventCohortHalted,
15 "EventFallbackServed": EventFallbackServed, "EventConfigPending": EventConfigPending,
16 "EventStagingRefused": EventStagingRefused, "EventBounceInstance": EventBounceInstance,
17 "EventBounceSidecar": EventBounceSidecar, "StateHeld": StateHeld, "StateRollingOut": StateRollingOut,
18 "StateAsleep": StateAsleep, "StateConfigPending": StateConfigPending, "reasonUnknown": reasonUnknown,
19 }
20 for k, v := range causes {
21 out["cause "+k] = v
22 }
23 for k, v := range reasons {
24 out["reason "+k] = v
25 }
26 // Add unavailability phrases
27 for k, v := range unavailablePhrases {
28 out["unavailable "+k] = v
29 }
30 out["unavailableUnknown"] = unavailableUnknown
31 return out
32}
33
34func TestNoEmDashInAnyWord(t *testing.T) {
35 for name, s := range allWords() {
36 if strings.ContainsRune(s, '—') {
37 t.Errorf("%s carries an em dash: %q", name, s)
38 }
39 }
40}
41
42// The emit sites fill these verbs in this order; an approved rewording must
43// keep them, and carry no other verb.
44func TestVerbsAreWhereTheCallersPutThem(t *testing.T) {
45 words := allWords()
46 for name, want := range map[string]int{
47 "EventSwapping": 2, "EventSwapped": 2, "EventSwapFailed": 3, "EventHoldDown": 1,
48 "EventCohortHalted": 3, "EventFallbackServed": 2, "EventConfigPending": 2,
49 "EventStagingRefused": 1, "EventBounceInstance": 1, "EventBounceSidecar": 1,
50 "StateHeld": 1, "StateRollingOut": 0, "StateAsleep": 1, "StateConfigPending": 0, "reasonUnknown": 1,
51 "unavailableUnknown": 1,
52 } {
53 s := words[name]
54 if strings.Count(s, "%s") != want || strings.Count(s, "%") != want {
55 t.Errorf("%s = %q: want exactly %d %%s verbs and no other verb", name, s, want)
56 }
57 }
58 for name, s := range words {
59 if (strings.HasPrefix(name, "cause ") || strings.HasPrefix(name, "reason ") || strings.HasPrefix(name, "unavailable ")) && strings.Contains(s, "%") {
60 t.Errorf("%s = %q: a phrase is filled into other strings and carries no verb", name, s)
61 }
62 }
63}
64
65func TestEveryCauseAndReasonHasAPhrase(t *testing.T) {
66 for _, c := range []string{"release", "install", "retry", "restart", "config"} {
67 if causes[c] == "" {
68 t.Errorf("cause %q has no phrase", c)
69 }
70 }
71 for _, r := range []string{status.ReasonHealth, status.ReasonSettle, status.ReasonExit, status.ReasonStaging, status.ReasonReused} {
72 if reasons[r] == "" {
73 t.Errorf("reason %q (plan 5's word) has no phrase", r)
74 }
75 }
76 if got := Cause("future"); got != "future" {
77 t.Errorf("Cause(future) = %q, want the word itself", got)
78 }
79 if got, want := Reason("future"), fmt.Sprintf(reasonUnknown, "future"); got != want {
80 t.Errorf("Reason(future) = %q, want %q", got, want)
81 }
82}
83
84func TestEveryUnavailableCodeHasAPhrase(t *testing.T) {
85 // Declined codes
86 for _, code := range []string{"no-cgroup-delegation", "no-generation-control", "generations-off", "host-claims-on", "cgroup-placement-failed"} {
87 phrase := Unavailable(code)
88 if phrase == "" {
89 t.Errorf("Unavailable(%q) = empty string", code)
90 }
91 if phrase == fmt.Sprintf(unavailableUnknown, code) {
92 t.Errorf("Unavailable(%q) fell through to unknown format", code)
93 }
94 if UnavailableRefuses(code) {
95 t.Errorf("UnavailableRefuses(%q) = true, want false", code)
96 }
97 }
98 // Refusing codes
99 for _, code := range []string{"no-deploy-store", "no-release-key", "failure-book-unreadable"} {
100 phrase := Unavailable(code)
101 if phrase == "" {
102 t.Errorf("Unavailable(%q) = empty string", code)
103 }
104 if phrase == fmt.Sprintf(unavailableUnknown, code) {
105 t.Errorf("Unavailable(%q) fell through to unknown format", code)
106 }
107 if !UnavailableRefuses(code) {
108 t.Errorf("UnavailableRefuses(%q) = false, want true", code)
109 }
110 }
111 // Unknown code
112 if got := Unavailable("future"); got != fmt.Sprintf(unavailableUnknown, "future") {
113 t.Errorf("Unavailable(future) = %q, want %q", got, fmt.Sprintf(unavailableUnknown, "future"))
114 }
115 if UnavailableRefuses("future") {
116 t.Errorf("UnavailableRefuses(future) = true, want false")
117 }
118}
119
120// UnavailableDeclines is true for exactly the five codes under which a box
121// runs today's stop-then-start paths. A refusing code is not one, and nor is
122// a code this binary does not know: a reader cannot assume a newer box's
123// problem leaves its instances safe to wake.
124func TestUnavailableDeclinesOnlyTheKnownDeclinedCodes(t *testing.T) {
125 for _, code := range []string{"no-cgroup-delegation", "no-generation-control", "generations-off", "host-claims-on", "cgroup-placement-failed"} {
126 if !UnavailableDeclines(code) {
127 t.Errorf("UnavailableDeclines(%q) = false, want true", code)
128 }
129 }
130 for _, code := range []string{"no-deploy-store", "no-release-key", "failure-book-unreadable", "future", ""} {
131 if UnavailableDeclines(code) {
132 t.Errorf("UnavailableDeclines(%q) = true, want false", code)
133 }
134 }
135}
136
137func TestHostClaimsDeclineReadsAsADecline(t *testing.T) {
138 if Unavailable("host-claims-on") != unavailableDeclined || !UnavailableDeclines("host-claims-on") || UnavailableRefuses("host-claims-on") {
139 t.Fatal("host-claims-on must read and act as a decline")
140 }
141}
142
143// A box whose arm-time test placement failed (#272) declines like the
144// others, in the same approved words: it adds no member-facing text.
145func TestPlacementFailedDeclineReadsAsADecline(t *testing.T) {
146 if Unavailable("cgroup-placement-failed") != unavailableDeclined || !UnavailableDeclines("cgroup-placement-failed") || UnavailableRefuses("cgroup-placement-failed") {
147 t.Fatal("cgroup-placement-failed must read and act as a decline")
148 }
149}
150