Files
mesh-catalog/modules/mesh-build-go/cmd/mesh-build-go/integration.go
T

99 lines
3.6 KiB
Go

package main
// The integration level (novox/hq ADR 0445 §2 §3, ADR 0470; issue 1486): `go test -tags integration` over the
// workspace, against a throwaway postgres and a throwaway bus started for this run alone, handed to the tests as
// MESH_TEST_POSTGRES and MESH_TEST_NATS. Its setup (compiling, the store, the bus) and its running time are measured and
// judged apart, 30 s and 60 s; both servers are stopped and the run's directory removed whatever the tests did.
import (
"context"
"fmt"
"os"
"path/filepath"
"strconv"
"strings"
"time"
"git.novox.be/novox/mesh-sdk/go/buildstep"
)
// The integration level's bounds (ADR 0445 §3).
const (
IntegrationSetup = 30 * time.Second
IntegrationRun = 60 * time.Second
)
func (m *Module) integrationBounds() Bounds {
b := m.IntegrationBounds
if b.Setup <= 0 {
b.Setup = IntegrationSetup
}
if b.Run <= 0 {
b.Run = IntegrationRun
}
return b
}
func (m *Module) integration(ctx context.Context, workspace, tree string, packages []string, pattern string) (res *TestResult, err error) {
major, err := m.checkPostgres(ctx)
if err != nil {
return nil, err // a *buildstep.Refusal: this level only
}
if !m.Inside {
// The store, the bus and the tests run together in one shut-off process (level.go), so the tests reach the
// level's own store and bus and nothing else.
return m.integrationShutOff(ctx, workspace, packages, pattern)
}
return m.integrationHere(ctx, workspace, tree, packages, pattern, major)
}
// integrationHere is the level itself, in the shut-off process: the store and the bus started for the run, the tests
// compiled and run against them, both stopped and the run's directory removed however it ends.
func (m *Module) integrationHere(ctx context.Context, workspace, tree string, packages []string, pattern string, major int) (res *TestResult, err error) {
run := filepath.Join(m.Work, workspace, "run-"+buildstep.NewID())
if err := os.MkdirAll(run, 0o700); err != nil {
return nil, err
}
// The run's directory goes, and the servers stop, however the level ends: passed, failed, a panic.
defer os.RemoveAll(run)
began := m.clock()
dirs, err := m.goModDirs(ctx, tree)
if err != nil {
return nil, err
}
postgres, stopStore, err := m.startStore(ctx, run)
if err != nil {
return nil, fmt.Errorf("the integration level's store: %w", err)
}
defer stopStore()
nats, stopBus, err := m.startBus(ctx, filepath.Join(run, "nats"))
if err != nil {
return nil, fmt.Errorf("the integration level's bus: %w", err)
}
defer stopBus()
env := append([]string{"MESH_TEST_POSTGRES=" + postgres, "MESH_TEST_NATS=" + nats}, m.checkEnv(workspace, nil)...)
// Compiling counts as setup: the tests are built once, here, with the addresses a TestMain may read, and the run
// below finds them built. Whether they compile is for the run to say; its failure is not read here.
// Only the directories the selected packages lie in compile (ADR 0536 §3); no selection is every directory.
byDir, err := packagesByDir(tree, dirs, packages)
if err != nil {
return nil, err
}
for _, d := range dirs {
if len(byDir[d]) == 0 {
continue
}
m.Run(ctx, append(m.goEnvFor(filepath.Join(tree, d)), env...), "go", append([]string{"-C", filepath.Join(tree, d), "test", "-tags", strings.Join(integrationTags, ","), "-run", "^$", "-count=1"}, byDir[d]...)...)
}
setup := m.clock().Sub(began)
return m.runLevel(ctx, tree, levelOpts{
workspace: workspace, run: pattern,
level: LevelIntegration, tags: integrationTags, packages: packages, bounds: m.integrationBounds(),
env: env,
setup: setup, wall: true,
store: "postgres " + strconv.Itoa(major), bus: "nats-server " + m.Recipe.NatsServer,
})
}