From d256dd72ff2c5773316c7825d6906cf05e3add1e Mon Sep 17 00:00:00 2001 From: Crash-- Date: Sun, 10 May 2026 21:16:41 +0200 Subject: [PATCH] test(rabbitmq): bootstrap global CouchDB views in TestMain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tests in this package call lifecycle.Create / instance.Get directly without going through testutils.NewSetup → GetTestInstance → stack.Start, so they never trigger couchdb.InitGlobalDB themselves. They've historically relied on the side effect of earlier model/* test packages bootstrapping the global DB and on the design doc persisting in the shared CouchDB service across test binaries. Go's test result cache (persisted via actions/setup-go cache) can let those packages be skipped, breaking the implicit dependency. The CI flake on PR #4716 manifested as TestSyncCreatedOrgContact failing with "CouchDB(not_found): missing" because instance.Service.Get queried _design/domain-and-aliases on a global instances DB where that design doc had never been created. A more robust fix would be to make instance.Service.Get treat any CouchDB "not_found" as ErrNotFound (it currently only handles no_db_file / "Database does not exist."). That would remove the implicit dependency for every package, not just this one. The repercussions on other Get callers haven't been fully audited yet, so this localized bootstrap stays in place until the broader change is vetted. Co-Authored-By: Claude Opus 4.7 (1M context) --- pkg/rabbitmq/main_test.go | 74 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 pkg/rabbitmq/main_test.go diff --git a/pkg/rabbitmq/main_test.go b/pkg/rabbitmq/main_test.go new file mode 100644 index 00000000000..8d3edb10f85 --- /dev/null +++ b/pkg/rabbitmq/main_test.go @@ -0,0 +1,74 @@ +package rabbitmq_test + +import ( + "context" + "log" + "os" + "strings" + "testing" + + "github.com/cozy/cozy-stack/pkg/config/config" + "github.com/cozy/cozy-stack/pkg/couchdb" + "github.com/spf13/viper" +) + +// TestMain bootstraps the views and indexes that production stacks create +// at startup via stack.Start → couchdb.InitGlobalDB. Tests in this package +// call lifecycle.Create / instance.Get directly without going through +// testutils.NewSetup → GetTestInstance → stack.Start, so they never trigger +// that init themselves. +// +// They've historically relied on the side effect that earlier model/* test +// packages bootstrap the global DB and that the design doc persists in the +// shared CouchDB service across test binaries — but Go's test result cache +// can let those packages be skipped (cached "ok"), and then this implicit +// dependency breaks. See the CI flake debugged on PR #4716: the second +// lifecycle.Create call inside TestSyncCreatedOrgContact failed with +// "CouchDB(not_found): missing" because instance.Service.Get queried +// _design/domain-and-aliases on the global instances DB and that design +// doc had never been created. +// +// TODO: the more robust fix is to make instance.Service.Get treat any +// CouchDB "not_found" as ErrNotFound (it currently only handles +// no_db_file / "Database does not exist."). That would remove the implicit +// dependency for every package, not just this one. The repercussions on +// other Get callers haven't been fully audited though, so this localized +// bootstrap stays in place until that broader change is vetted. +func TestMain(m *testing.M) { + if err := loadTestConfigForMain(); err != nil { + log.Fatalf("rabbitmq tests: could not load test config: %s", err) + } + // Best-effort: if CouchDB is unreachable, individual tests that need it + // will fail via testutils.NeedCouchdb(t). We don't want TestMain itself + // to hard-fail in environments where CouchDB is intentionally absent. + if _, err := couchdb.CheckStatus(context.Background()); err == nil { + if err := couchdb.InitGlobalDB(context.Background()); err != nil { + log.Printf("rabbitmq tests: could not init global CouchDB: %s", err) + } + } + os.Exit(m.Run()) +} + +// loadTestConfigForMain mirrors config.UseTestFile but without the +// *testing.T plumbing so it can be called from TestMain. +func loadTestConfigForMain() error { + v := viper.New() + v.SetConfigName("cozy.test") + v.AddConfigPath("$HOME/.cozy") + v.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) + v.SetEnvPrefix("cozy") + v.AutomaticEnv() + v.SetDefault("host", "localhost") + v.SetDefault("port", 8080) + v.SetDefault("assets", "./assets") + v.SetDefault("subdomains", "nested") + v.SetDefault("fs.url", "mem://test") + v.SetDefault("couchdb.url", "http://localhost:5984/") + v.SetDefault("log.level", "info") + if err := v.ReadInConfig(); err != nil { + if _, isMissing := err.(viper.ConfigFileNotFoundError); !isMissing { + return err + } + } + return config.UseViper(v) +}