| 1 | package main |
| 2 | |
| 3 | import ( |
| 4 | "encoding/json" |
| 5 | "errors" |
| 6 | "os" |
| 7 | "sort" |
| 8 | "strconv" |
| 9 | "strings" |
| 10 | "testing" |
| 11 | ) |
| 12 | |
| 13 | func TestRegionCLICopy(t *testing.T) { |
| 14 | lines := map[string]string{} |
| 15 | for _, src := range []string{"timezone", "ip", "default", "chosen"} { |
| 16 | lines[src] = regionCreatedLine("P", src) |
| 17 | } |
| 18 | if len(map[string]bool{lines["timezone"]: true, lines["ip"]: true, lines["default"]: true, lines["chosen"]: true}) != 4 { |
| 19 | t.Fatalf("each source needs its own line: %v", lines) |
| 20 | } |
| 21 | if regionCreatedLine("P", "") != lines["default"] { |
| 22 | t.Fatal("an unknown source must read as the default") |
| 23 | } |
| 24 | all := []string{ |
| 25 | regionNotRecordedOldConsole, regionNotAppliedSwitchOff("P"), |
| 26 | instanceCreatedSuffix("stable", "P"), deployRegionMismatch("blog", "P"), |
| 27 | deployRegionUnreadable("blog", errors.New("timeout")), deployRegionUnknown("blog"), |
| 28 | canaryRegionMismatch("c.go.tito.io", "P"), canaryRegionOnFleet("blog", "acme"), |
| 29 | canaryFleetUnknown("blog"), canaryRegionUnconfirmed("c"), |
| 30 | flagRegionAppsCreate, flagRegionDeploy, flagRegionCanary, flagRegionInstancesCreate, |
| 31 | } |
| 32 | for _, s := range append(all, lines["timezone"], lines["ip"], lines["default"], lines["chosen"]) { |
| 33 | if s == "" || strings.Contains(s, "—") || strings.Contains(s, "%!") { |
| 34 | t.Errorf("bad copy %q", s) |
| 35 | } |
| 36 | } |
| 37 | } |
| 38 | |
| 39 | // TestRegionCLICopyMatchesTheApprovedRecord holds region_copy.go to the copy |
| 40 | // record: every record entry filed under region_copy.go must appear in the |
| 41 | // source as its exact quoted Go literal. A substring of a longer string, or |
| 42 | // of an identifier, does not count. |
| 43 | func TestRegionCLICopyMatchesTheApprovedRecord(t *testing.T) { |
| 44 | raw, err := os.ReadFile("docs/superpowers/plans/2026-10-02-nearest-region-copy.json") |
| 45 | if err != nil { |
| 46 | t.Fatal(err) |
| 47 | } |
| 48 | var rec struct { |
| 49 | Entries []struct { |
| 50 | ID string `json:"id"` |
| 51 | File string `json:"file"` |
| 52 | Text string `json:"text"` |
| 53 | } `json:"entries"` |
| 54 | } |
| 55 | if err := json.Unmarshal(raw, &rec); err != nil { |
| 56 | t.Fatal(err) |
| 57 | } |
| 58 | src, err := os.ReadFile("region_copy.go") |
| 59 | if err != nil { |
| 60 | t.Fatal(err) |
| 61 | } |
| 62 | want := []string{"C9", "C10", "C11", "C12", "C13a", "C13b", "C14", "C15", "C15.nohome", "C15b", "C15c", |
| 63 | "C22a", "C22b", "C22c", "C22d", "C25", "C25.nohome", "C30", "C30b", "C30c"} |
| 64 | var got []string |
| 65 | for _, e := range rec.Entries { |
| 66 | if e.File != "region_copy.go" { |
| 67 | continue |
| 68 | } |
| 69 | got = append(got, e.ID) |
| 70 | if e.Text == "" { |
| 71 | t.Errorf("%s: empty record text", e.ID) |
| 72 | continue |
| 73 | } |
| 74 | if !strings.Contains(string(src), strconv.Quote(e.Text)) { |
| 75 | t.Errorf("%s: region_copy.go has no literal %s", e.ID, strconv.Quote(e.Text)) |
| 76 | } |
| 77 | } |
| 78 | // A record entry dropped or re-filed must not shrink this check silently. |
| 79 | sort.Strings(got) |
| 80 | sort.Strings(want) |
| 81 | if strings.Join(got, ",") != strings.Join(want, ",") { |
| 82 | t.Errorf("record entries for region_copy.go = %v, want %v", got, want) |
| 83 | } |
| 84 | } |
| 85 | |
| 86 | // C15 and C25 with no named home region read "the home region", not an empty |
| 87 | // place: the approved .nohome texts. With a place, the approved C15 and C25. |
| 88 | func TestRegionMismatchWithoutAHome(t *testing.T) { |
| 89 | for _, c := range []struct{ name, got, want string }{ |
| 90 | {"C15.nohome", deployRegionMismatch("blog", ""), |
| 91 | "blog already runs in the home region. --region only applies when deploy creates an app. To place one instance elsewhere, use carlos instances create --region."}, |
| 92 | {"C15", deployRegionMismatch("blog", "Ireland"), |
| 93 | "blog already runs in Ireland. --region only applies when deploy creates an app. To place one instance elsewhere, use carlos instances create --region."}, |
| 94 | {"C25.nohome", canaryRegionMismatch("c.go.tito.io", ""), |
| 95 | "canary c.go.tito.io already runs in the home region. --region applies only when canary creates the host. Run carlos canary rm first to start it somewhere else."}, |
| 96 | {"C25", canaryRegionMismatch("c.go.tito.io", "Ireland"), |
| 97 | "canary c.go.tito.io already runs in Ireland. --region applies only when canary creates the host. Run carlos canary rm first to start it somewhere else."}, |
| 98 | } { |
| 99 | if c.got != c.want { |
| 100 | t.Errorf("%s: %q, want %q", c.name, c.got, c.want) |
| 101 | } |
| 102 | } |
| 103 | } |
| 104 | |