Files
spinifex/tests/integration/main_test.go
T
brynmailer-mdc a7a62addeb test: rebuild the predastore fixture and service tests on the facade
The fixture wrote a config the strict decoder rejects and built its cluster
through clusterrun, so it now renders a v1 TOML, loads it through LoadConfig and
serves under Run. Loading the real file means the fixture trips over the same
validation an install does. Its data directory holds node-<id> directly, and it
drains on cancellation rather than being abandoned at exit.

The runtime tests drove buildRuntime, serve and the old on-disk layout, all of
which predastore owns now, so they go. What replaces them covers what spinifex
still decides: the flag merge and its precedence, a host id or gate node the
config does not have, and the pid file behind Stop and Status.

Two fixes to earlier commits in this series: the host id conversion moves behind
its own guard, and the node status probes use WaitGroup.Go.
2026-08-11 17:23:42 +10:00

87 lines
3.1 KiB
Go

//go:build integration
package integration
import (
"fmt"
"os"
"path/filepath"
"testing"
testpredastore "github.com/mulgadc/spinifex/tests/fixtures/predastore"
)
// TestMain amortises the embedded NATS+JetStream server across every test in
// this package instead of each StartGateway call booting (and tearing down)
// its own, for two reasons:
//
// 1. spinifex/gateway/ec2/instance's ClientTokenStore is a process-wide
// sync.Once singleton bound to whichever *nats.Conn first initialises it.
// In production a gateway holds one long-lived connection for its whole
// life, so the singleton is correct there. But this test binary runs
// every test in one process, so a per-test embedded server closes that
// first connection the moment its owning test ends — every later
// RunInstances-calling test then inherits a KV handle bound to a dead
// connection. Keeping one server, and never closing an individual
// test's connection early, keeps whichever connection wins the
// singleton alive for the life of the whole binary.
// 2. It cuts per-test startup cost: standing up an embedded JetStream
// server is the dominant fixed cost of StartGateway.
//
// Per-test state isolation is preserved despite the shared server — see the
// accountAuthenticator doc comment in shared_nats.go for how.
func TestMain(m *testing.M) {
policy, err := loadConformancePolicy()
if err != nil {
fmt.Fprintln(os.Stderr, "tests/integration: load AWS conformance policy:", err)
os.Exit(1)
}
mode, err := conformanceModeFromEnvironment()
if err != nil {
fmt.Fprintln(os.Stderr, "tests/integration:", err)
os.Exit(1)
}
h, err := startSharedNATS()
if err != nil {
fmt.Fprintln(os.Stderr, "tests/integration: failed to start shared NATS server:", err)
os.Exit(1)
}
sharedNATSHarness = h
code := m.Run()
// The predastore fixture outlives any single test on purpose, so this is
// the only point at which its cluster goroutines can be drained.
testpredastore.Stop()
report := suiteConformance.report(policy, mode)
fmt.Fprintln(os.Stderr, report)
if blocking := suiteConformance.blocking(policy, mode); blocking != 0 {
fmt.Fprintf(os.Stderr, "tests/integration: %d blocking AWS model conformance violation(s)\n", blocking)
code = 1
}
if reportPath := os.Getenv("AWS_MODEL_CONFORMANCE_REPORT"); reportPath != "" {
if err := os.MkdirAll(filepath.Dir(reportPath), 0o755); err != nil {
fmt.Fprintln(os.Stderr, "tests/integration: create conformance report directory:", err)
code = 1
} else if err := os.WriteFile(reportPath, []byte(report+"\n"), 0o644); err != nil {
fmt.Fprintln(os.Stderr, "tests/integration: write conformance report:", err)
code = 1
}
}
// Connections are closed here, together, rather than per-test: closing
// one early can kill the connection the clienttoken singleton latched
// onto (see above), so every connection's lifetime is pinned to the
// whole binary rather than to any single test.
h.closeAll()
h.srv.Shutdown()
h.srv.WaitForShutdown()
// Only reached on a clean exit; a killed run leaves the store for the
// sweep in startSharedNATS to reclaim.
h.removeStore()
os.Exit(code)
}