testutil

package
v0.0.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 29, 2026 License: MIT Imports: 25 Imported by: 0

Documentation

Overview

Package testutil provides shared testing utilities for the pasture test suite.

LoadFixtures reads a named YAML fixture from the caller's testdata/ directory and unmarshals it into the supplied target value. Tests that rely on this function will fail immediately (via require) if the fixture file is missing or malformed, keeping test failures actionable.

Index

Constants

View Source
const DurableMigrationTable = "dbos_migrations"

DurableMigrationTable is the single-row table the durable runtime keeps its layout version in.

Evidence in the library version pinned in go.mod: dbos/internal/sysdb/sqlite_migrations.go, where RunSqliteMigrations creates `dbos_migrations (version INTEGER NOT NULL PRIMARY KEY)` and reads a single row from it. BuildSqliteMigrations in the same file lists the SQLite migrations 1..41 and then continues at 42, so 41 is the last version the superseded runtime can leave behind.

View Source
const FirstSupportedDurableSchemaVersion = 42

FirstSupportedDurableSchemaVersion is the floor the gate enforces: the first layout version this build's durable runtime introduces. A refusal names it, so a floor that ever moves fails the tests that assert it instead of passing silently.

View Source
const SupersededDurableSchemaVersion = 41

SupersededDurableSchemaVersion is the layout version the superseded durable runtime stopped at, and therefore the version WriteSupersededDurableDatabase records.

Variables

This section is empty.

Functions

func AllTables added in v0.0.8

func AllTables(t *testing.T, path string) []string

AllTables lists every table in a database, for a failure message that names what a writer created.

func CheckpointWAL added in v0.0.8

func CheckpointWAL(dbPath string) error

CheckpointWAL folds a database's write-ahead log back into the main file and truncates it, so the file alone is a complete database and can be copied.

A fixture builder must call this before copying: without it the copy can be missing everything the source wrote since its last checkpoint.

func CopyFile added in v0.0.8

func CopyFile(dst, src string) error

CopyFile copies src to dst using ordinary filesystem bytes. The destination parent directory must already exist and dst must not exist.

It is exported so that other fixture builders copy a prepared database the same way this one does, instead of each writing its own copy loop.

func DatabaseDigest added in v0.0.8

func DatabaseDigest(t *testing.T, path string) string

DatabaseDigest hashes a SQLite database as a whole: the main file AND its two sidecars, each length-prefixed so no rearrangement of bytes between them can collide.

Hashing the main file alone is not enough, and that gap is not theoretical. A writer working under WAL journal mode leaves its pages in the -wal sidecar until a checkpoint runs, so a migration of hundreds of kilobytes can be complete and durable while the main file is untouched. Any later reader — including an older pasture build — replays that sidecar on open and sees the change. A main-file digest therefore reports "nothing was written" for a database that was, in fact, already rewritten.

TAKE IT WHILE NO HANDLE IS OPEN. An open connection under WAL keeps a -shm sidecar alive, and this digest counts the sidecars, so a digest taken with a reader still attached differs from one taken after it closed. Production leaves no sidecar behind, because a refusal closes the handle it opened.

A missing sidecar counts as empty, which is the normal state once the last handle on the file closes.

func DurableRuntimeTables added in v0.0.8

func DurableRuntimeTables(t *testing.T, path string) []string

DurableRuntimeTables reports which of the durable runtime's own tables are present. The gate must leave every one of them absent: each is created by the first layout steps the runtime applies, so any one of them proves the runtime ran against the file.

func GoldenUnifiedDBPath added in v0.0.5

func GoldenUnifiedDBPath(t *testing.T) string

GoldenUnifiedDBPath returns a per-test copy of a pre-migrated unified pasture.db. The golden source is built once per test binary through the real production opener, then copied byte-for-byte for each test that opts in.

func GoleakVerifier added in v0.0.8

func GoleakVerifier() func() error

GoleakVerifier samples the goroutines that are already running, and returns a check that reports the goroutines started after that sample and never stopped.

Call it at the TOP of TestMain, BEFORE m.Run, and call the returned check after m.Run. The order is load-bearing: goleak.IgnoreCurrent samples the live goroutine set when the OPTION IS BUILT, not when the check runs. Building the options after m.Run samples every goroutine the tests leaked, then adds all of them to the ignore list, so the check can never fail.

func LoadFixtures

func LoadFixtures(t *testing.T, name FixtureName, target any)

LoadFixtures reads testdata/<name>.yaml relative to the current working directory (the package under test) and unmarshals the contents into target.

It calls t.Helper() so that failure lines point to the caller, and uses require (not assert) so that the test stops immediately on infrastructure failures rather than proceeding with a zero-value target.

Parameters:

  • t: the active *testing.T (must not be nil).
  • name: one of the FixtureName constants — determines the file path.
  • target: a non-nil pointer that yaml.Unmarshal will populate.

Failure modes (both call t.FailNow via require):

  • The fixture file does not exist at testdata/<name>.yaml.
  • The YAML content cannot be unmarshalled into target.

func OpenGoldenTaskTracker added in v0.0.5

func OpenGoldenTaskTracker(t *testing.T) (protocol.TaskTracker, string)

OpenGoldenTaskTracker opens a copied golden database with migrations explicitly disabled. Migration tests should not use this helper.

func ReadDurableSchemaVersion added in v0.0.8

func ReadDurableSchemaVersion(t *testing.T, path string) int64

ReadDurableSchemaVersion reports the layout version a database records, or 0 when it records none.

func RegisterFixtureDir added in v0.0.8

func RegisterFixtureDir(dir string)

RegisterFixtureDir records a directory that a fixture builder created and that must outlive the test which built it. RemoveFixtureDirs deletes it later.

Registering the same directory twice is harmless.

func RemoveFixtureDirs added in v0.0.8

func RemoveFixtureDirs()

RemoveFixtureDirs deletes every directory registered so far and forgets them.

Call it from TestMain, AFTER m.Run: a fixture is shared by the whole binary, so it is only safe to remove once every test has finished. It is deliberately silent about failures — a test run must not be reported as failed because a temporary directory could not be deleted — and it is safe to call in a binary that built no fixture at all.

func RequireBlankImport added in v0.0.8

func RequireBlankImport(t *testing.T, goFile, importPath string)

RequireBlankImport fails the test unless goFile contains a blank import (`_ "<importPath>"`) of importPath.

It exists for links that the compiler cannot check. A package registered only through another package's init() has no referenced identifier, so deleting the blank import still compiles and still passes every test that does not reach the run-time registry lookup. The failure then appears at run time, in a binary, on a user's machine. A source scan is the cheapest check that keeps the link present.

goFile is a path relative to the calling test's working directory, which is the directory of the package under test.

func SetEnv added in v0.0.5

func SetEnv(t *testing.T, key, value string)

SetEnv sets an environment variable for the duration of the test and restores the previous value during cleanup.

func SetHermeticEnv added in v0.0.5

func SetHermeticEnv(prefix string) (func(), error)

SetHermeticEnv points HOME and XDG_DATA_HOME at a temporary directory tree for a package-level test run.

Before redirecting HOME it resolves and pins GOCACHE and GOPATH to their effective values (via "go env"). This prevents subprocess go builds inside audit crash tests and cmd/pasture TestMain from resolving GOCACHE/GOPATH through the redirected (throwaway) HOME, which would produce a cold build-cache and module-cache hit on every run. GOCACHE and GOPATH are typically unset in the Nix dev shell, so os.Getenv("GOCACHE") is a no-op; only the toolchain's own resolution gives the real paths.

Sharing the content-addressed build and module caches does not weaken test isolation: per-test SQLite databases remain isolated via --db flags and t.TempDir(); only HOME and XDG_* dirs are redirected for hermeticity.

The returned cleanup function restores all four variables (GOCACHE, GOPATH, HOME, XDG_DATA_HOME) to their original state and removes the temp dir.

func UnsetEnv added in v0.0.5

func UnsetEnv(t *testing.T, key string)

UnsetEnv removes an environment variable for the duration of the test and restores the previous value during cleanup.

func WriteSupersededDurableDatabase added in v0.0.8

func WriteSupersededDurableDatabase(t *testing.T) (string, string)

WriteSupersededDurableDatabase writes a private database whose durable layout is the one the superseded runtime left behind, and returns its path with the digest of the whole database. The digest lets a caller prove that a refusal wrote nothing.

The file is written through the PRODUCTION opener, so it arrives in the exact shape a real pasture database has: WAL journal mode and the same pragmas. A fixture written on plainer settings would be converted to WAL by the first production open, and that conversion alone rewrites the file header — which would read, to a digest assertion, as a writer the gate failed to hold back.

That header rewrite is the ONE change a digest cannot cover by construction: the shared handle's connection string sets the journal mode, and that pragma runs on the gate's own first query, before any refusal is possible. Such a database carries no pasture data, and the refusal says exactly that rather than claiming the file is untouched.

Types

type AcceptanceStore added in v0.0.5

type AcceptanceStore struct {
	Path    string
	Tracker protocol.TaskTracker
}

func OpenAcceptanceStore added in v0.0.5

func OpenAcceptanceStore(t *testing.T) *AcceptanceStore

OpenAcceptanceStore creates a file-backed store through the production opener. Callers seed it through Tracker APIs; this helper intentionally exposes no SQL.

func (*AcceptanceStore) Close added in v0.0.5

func (s *AcceptanceStore) Close(t *testing.T)

func (*AcceptanceStore) Reopen added in v0.0.5

func (s *AcceptanceStore) Reopen(t *testing.T)

type FixtureName

type FixtureName string

FixtureName is a typed string that identifies a YAML fixture file stored under the calling package's testdata/ directory. Using a named type instead of a plain string prevents accidental string literals at call sites.

const (
	// ContentBlock is used by S2–S3 tests (message/content-block scenarios).
	ContentBlock FixtureName = "content_block"

	// CLISmoke is used by S4–S5 tests (CLI smoke / handler scenarios).
	CLISmoke FixtureName = "cli_smoke"

	// ValidateBeforeOpen is used by the pasture CLI tests asserting that invalid
	// epoch/signal/session/slice/phase invocations are rejected by argument
	// validation before the durable database is opened.
	ValidateBeforeOpen FixtureName = "validate_before_open"

	// RunAgentSession is used by the agent-session workflow tests.
	RunAgentSession FixtureName = "run_agent_session"

	// ConfigLoading is used by S3 tests (config loading scenarios).
	ConfigLoading FixtureName = "config_loading"

	// CodegenMarkers is used by S3 codegen tests (marker parsing scenarios).
	CodegenMarkers FixtureName = "markers"

	// CodegenContext is used by S2 codegen tests (context injection scenarios).
	CodegenContext FixtureName = "context"

	// CodegenAgents is used by S6 codegen tests (agent definition generation scenarios).
	CodegenAgents FixtureName = "agents"

	// CodegenSkills is used by S4 codegen tests (SKILL.md generation scenarios).
	CodegenSkills FixtureName = "skills"

	// CodegenSchema is used by S5 codegen tests (schema.xml generation scenarios).
	CodegenSchema FixtureName = "schema"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL