| 1 | package geo |
| 2 | |
| 3 | import ( |
| 4 | "encoding/json" |
| 5 | "os" |
| 6 | "regexp" |
| 7 | "strings" |
| 8 | "testing" |
| 9 | ) |
| 10 | |
| 11 | func TestAWSRegionTable(t *testing.T) { |
| 12 | shape := regexp.MustCompile(`^[a-z]{2}(-[a-z]+)+-\d$`) |
| 13 | for code, r := range awsRegions { |
| 14 | if !shape.MatchString(code) { |
| 15 | t.Errorf("%s is not an AWS region code", code) |
| 16 | } |
| 17 | if r.Lat < -90 || r.Lat > 90 || r.Lon < -180 || r.Lon > 180 { |
| 18 | t.Errorf("%s: %v out of range", code, r.Point) |
| 19 | } |
| 20 | if r.Place == "" || strings.Contains(r.Place, "—") { |
| 21 | t.Errorf("%s: place %q empty or contains an em dash", code, r.Place) |
| 22 | } |
| 23 | } |
| 24 | if len(awsRegions) != 34 { |
| 25 | t.Errorf("%d regions, want the 34 of spec C23", len(awsRegions)) |
| 26 | } |
| 27 | if PlaceName("xx-nowhere-1", "zz") != "zz" || PlaceName("", "ie") != "ie" { |
| 28 | t.Error("PlaceName must fall back to the given code") |
| 29 | } |
| 30 | if r, ok := LookupAWSRegion("eu-west-2"); !ok || PlaceName("eu-west-2", "uk") != r.Place { |
| 31 | t.Error("PlaceName must read the table") |
| 32 | } |
| 33 | } |
| 34 | |
| 35 | func TestNearestUsesTheTable(t *testing.T) { |
| 36 | london, _ := ZonePoint("Europe/London") |
| 37 | got, ok := Nearest(london, []Candidate{ |
| 38 | {Code: "", Home: true, AWSRegion: "eu-west-1"}, |
| 39 | {Code: "uk", AWSRegion: "eu-west-2"}, |
| 40 | }) |
| 41 | if !ok || got != "uk" { |
| 42 | t.Fatalf("Nearest from London = (%q, %v), want uk", got, ok) |
| 43 | } |
| 44 | } |
| 45 | |
| 46 | // TestPlaceNamesMatchApprovedRecord fails if any C23-* text in the approved |
| 47 | // copy record is missing from awsregions.go as a whole quoted Go string |
| 48 | // literal, or differs from the table's place for that region. |
| 49 | func TestPlaceNamesMatchApprovedRecord(t *testing.T) { |
| 50 | raw, err := os.ReadFile("../../docs/superpowers/plans/2026-10-02-nearest-region-copy.json") |
| 51 | if err != nil { |
| 52 | t.Fatal(err) |
| 53 | } |
| 54 | var rec struct { |
| 55 | Entries []struct { |
| 56 | ID string `json:"id"` |
| 57 | Text string `json:"text"` |
| 58 | } `json:"entries"` |
| 59 | } |
| 60 | if err := json.Unmarshal(raw, &rec); err != nil { |
| 61 | t.Fatal(err) |
| 62 | } |
| 63 | src, err := os.ReadFile("awsregions.go") |
| 64 | if err != nil { |
| 65 | t.Fatal(err) |
| 66 | } |
| 67 | seen := map[string]bool{} |
| 68 | for _, e := range rec.Entries { |
| 69 | code, ok := strings.CutPrefix(e.ID, "C23-") |
| 70 | if !ok { |
| 71 | continue |
| 72 | } |
| 73 | seen[code] = true |
| 74 | if e.Text == "" { |
| 75 | t.Errorf("%s: empty text in the record", e.ID) |
| 76 | continue |
| 77 | } |
| 78 | if !strings.Contains(string(src), `"`+e.Text+`"`) { |
| 79 | t.Errorf("%s: %q is not a quoted string literal in awsregions.go", e.ID, e.Text) |
| 80 | } |
| 81 | if r, ok := LookupAWSRegion(code); !ok { |
| 82 | t.Errorf("%s: region missing from the table", e.ID) |
| 83 | } else if r.Place != e.Text { |
| 84 | t.Errorf("%s: table place %q, record %q", e.ID, r.Place, e.Text) |
| 85 | } |
| 86 | } |
| 87 | for code := range awsRegions { |
| 88 | if !seen[code] { |
| 89 | t.Errorf("%s: in the table but has no C23 entry in the record", code) |
| 90 | } |
| 91 | } |
| 92 | if len(seen) != 34 { |
| 93 | t.Errorf("%d C23 entries in the record, want 34", len(seen)) |
| 94 | } |
| 95 | } |
| 96 | |