package testbus import ( "os" "path/filepath" "regexp" "strings" "testing" "encoding/json" "github.com/nats-io/nats.go" ) // **The bus the tests run is the bus the mesh runs** (novox/hq ADR 0227 rule 9, to-be 45 §9). The server // linked into the tests is held to the release the catalogue's bus image is — read from beside this // checkout — and, in a merge check that has the facts snapshot, to the release the mesh's bus server says // it runs. A bus upgrade moves the catalogue's pin; this then fails until the tests' pin moves with it, // so the controller is never tested against a bus the mesh no longer runs, or not yet. func TestTheBusTheTestsRunIsTheBusTheMeshRuns(t *testing.T) { dockerfile := filepath.Join("..", "..", "..", "mesh-catalog", "modules", "nats", "Dockerfile") raw, err := os.ReadFile(dockerfile) switch { case err == nil: pinned := regexp.MustCompile(`upstream: nats ([0-9.]+)-alpine`).FindSubmatch(raw) if pinned == nil { t.Fatalf("%s says no release its digest is", dockerfile) } if string(pinned[1]) != Version { t.Errorf("the tests run bus %s and the catalogue's bus image is %s: move go.mod's nats-server pin "+ "(and `go mod vendor`) with the image", Version, pinned[1]) } case os.IsNotExist(err): t.Logf("the catalogue is not beside this checkout, so its bus image is not compared") default: t.Fatal(err) } path := os.Getenv("MESH_FACTS") if path == "" { t.Logf("no MESH_FACTS: the bus the mesh runs is compared in a merge check, which has it") return } body, err := os.ReadFile(path) if err != nil { t.Fatal(err) } // Read as little of the snapshot as this needs (internal/facts holds the whole shape). var f struct { Taken string `json:"taken"` Versions struct { Bus string `json:"bus"` } `json:"versions"` } if err := json.Unmarshal(body, &f); err != nil { t.Fatal(err) } if f.Versions.Bus != "" && strings.TrimPrefix(f.Versions.Bus, "v") != Version { t.Errorf("the tests run bus %s and the mesh's bus runs %s (facts of %s)", Version, f.Versions.Bus, f.Taken) } } // A test's bus is its own: what one test makes, the next never sees. func TestEveryTestHasABusOfItsOwn(t *testing.T) { seen := map[string]bool{} for i := 0; i < 2; i++ { t.Run("one", func(t *testing.T) { url := URL(t) if seen[url] { t.Fatalf("two tests were handed %s", url) } seen[url] = true conn, err := nats.Connect(url) if err != nil { t.Fatal(err) } defer conn.Close() js, err := conn.JetStream() if err != nil { t.Fatal(err) } if _, err := js.StreamInfo("EVENTS"); err == nil { t.Fatal("a stream an earlier test made is here") } if _, err := js.AddStream(&nats.StreamConfig{Name: "EVENTS", Subjects: []string{"mesh.>"}}); err != nil { t.Fatal(err) } }) } // Asked twice, one test reaches one bus. if a, b := URL(t), URL(t); a != b { t.Errorf("one test was handed two buses: %s and %s", a, b) } if v := strings.Count(Version, "."); v != 2 { t.Errorf("the server's release reads %q", Version) } }