testutil

package
v0.3.0-alpha.3 Latest Latest
Warning

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

Go to latest
Published: May 10, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package testutil provides shared test helpers and realistic fixtures for the gramaton test suite. Import this package in any *_test.go file to get access to engine setup, record builders, and a pre-populated store with ~50 records.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AssertDirMode

func AssertDirMode(t *testing.T, path string, want os.FileMode)

AssertDirMode is AssertFileMode for directories. Same Windows caveat: the mode-bit assertion is skipped on Windows but the path is verified to exist and to be a directory.

func AssertFileMode

func AssertFileMode(t *testing.T, path string, want os.FileMode)

AssertFileMode verifies a regular file's mode matches `want` on POSIX systems. On Windows the mode-bit assertion is skipped (Windows reports a fixed 0o666 / 0o444 based on the read-only flag and does not honor full POSIX mode bits) but the file's existence + non-directory-ness is still verified so callers retain a basic correctness check.

Use this in place of direct `info.Mode().Perm() != 0o600` checks when the test runs on every platform.

func Edge

func Edge(t *testing.T, eng *core.Engine, sourceID, targetID, edgeType string, weight float64)

Edge creates an edge between two records.

func EdgeDirect

func EdgeDirect(eng *core.Engine, sourceID, targetID, edgeType string, weight float64)

EdgeDirect creates an edge without requiring *testing.T.

func NewEngine

func NewEngine(t *testing.T) *core.Engine

NewEngine creates a minimal engine backed by a temp directory. No embedding or LLM providers configured.

func RegisterEngineCleanup

func RegisterEngineCleanup(t *testing.T, eng *core.Engine)

RegisterEngineCleanup attaches a t.Cleanup that calls eng.Close before the test's TempDir auto-cleanup runs. Required for any test that constructs an engine via core.LoadEngineWithOptions on a directory created by t.TempDir: without this, the engine's bbolt file handles outlive the test and Windows refuses to unlink them (POSIX inode semantics paper over the leak on Linux/macOS).

t.Cleanup runs LIFO -- registering this AFTER t.TempDir's auto- cleanup means engine.Close fires FIRST, draining bbolt handles before RemoveAll.

engine.Close is idempotent. Errors during close are surfaced via t.Logf rather than t.Errorf so a teardown hiccup doesn't fail an otherwise-healthy test.

func Timeout

func Timeout(base time.Duration) time.Duration

Timeout scales a base test timeout for the host platform. Windows runners (especially under race detector) are 3-5x slower than Linux or macOS for I/O-heavy paths, and many of our async tests use short hard-coded timeouts (1-5s) that cleanly fit POSIX timing but fail on Windows CI through no fault of the code under test.

Use this when a test waits on an event with a deadline:

pollUntilTerminal(t, a, jobID, testutil.Timeout(5*time.Second))

On Linux/macOS this returns base unchanged. On Windows it returns 5 * base. We initially used 3x but observed multiple legitimate flakes at the 30s/45s boundary (chunkNumBlocker waitParked, blockingInjector waitEntered, TestConcurrentReadsAndWrites under race). 5x is the documented upper end of "Windows under race can be 3-5x slower in practice"; the 1.5x buffer over realistic max gives genuine deadlocks ~50s to surface (still well under any per-package go-test budget).

Types

type PopulatedStore

type PopulatedStore struct {
	// Work cluster (6 records)
	WorkReorg      string // episodic: team restructured
	WorkNewManager string // episodic: new manager started
	WorkDeadline   string // temporal: project due date
	WorkMeeting    string // procedural: meeting cadence
	WorkOldTool    string // historical, superseded: old project tool
	WorkNewTool    string // durable: new project tool (supersedes old)

	// Health cluster (6 records)
	HealthDoctorVisit  string // episodic: annual checkup notes
	HealthExercise     string // procedural: exercise routine
	HealthAllergy      string // immutable: allergy info
	HealthSleep        string // semantic: sleep discovery
	HealthSupplement   string // refuted: supplement claim
	HealthPrescription string // temporal: prescription reminder

	// Cooking cluster (5 records)
	CookingRecipe       string // procedural: favorite recipe
	CookingSubstitution string // semantic: ingredient substitution
	CookingDinnerParty  string // episodic: dinner party menu
	CookingDietary      string // durable: dietary constraint
	CookingTechnique    string // procedural: technique tip

	// Travel cluster (5 records)
	TravelSeat     string // immutable: flight seat preference
	TravelPacking  string // procedural: packing list
	TravelTrip     string // ephemeral: upcoming trip
	TravelLoyalty  string // durable: loyalty program info
	TravelPassport string // temporal: passport renewal deadline

	// Finance cluster (4 records)
	FinanceBudget     string // procedural: budget rule
	FinanceExpense    string // procedural: expense process
	FinanceTax        string // temporal: tax deadline
	FinanceInvestment string // speculative: investment idea

	// Learning cluster (4 records)
	LearnBook      string // reference: book recommendation
	LearnCourse    string // episodic: course notes
	LearnRetention string // semantic: spaced repetition
	LearnContested string // contested: study technique

	// People (4 records)
	PersonVendor   string // temporal: vendor contact
	PersonNeighbor string // durable: neighbor info
	PersonBirthday string // durable: friend's birthday
	PersonDoctor   string // durable: doctor recommendation

	// TODOs (5 records)
	TodoOpen      string // unresolved, high importance
	TodoCompleted string // resolved: completed
	TodoAbandoned string // resolved: abandoned
	TodoObsolete  string // resolved: obsolete
	TodoOpenLow   string // unresolved, low importance

	// Orphans (4 records) -- no keywords, no edges
	Orphan1 string
	Orphan2 string
	Orphan3 string
	Orphan4 string

	// Pending (3 records) -- unclassified
	Pending1 string
	Pending2 string
	Pending3 string

	// Ephemeral/stale (3 records)
	EphemeralRecent  string // created today
	EphemeralStale   string // created 2 weeks ago, never accessed
	EphemeralMeeting string // yesterday's meeting agenda

	// Chunked (1 parent + 3 chunks)
	ChunkedParent string
	Chunk1        string
	Chunk2        string
	Chunk3        string
}

PopulatedStore is the set of record IDs from a pre-populated engine. Fields are grouped by category for easy access in tests.

func PopulatedEngine

func PopulatedEngine(t *testing.T) (*core.Engine, *PopulatedStore)

PopulatedEngine creates a new engine pre-loaded with ~50 realistic records covering every axis: all temporalities, knowledge types, epistemic statuses, resolution states, edge types, orphans, pending records, chunks, and multiple keyword clusters for concept emergence.

All timestamps are deterministic relative to now, so tests don't flake. Embeddings use simple deterministic vectors grouped by cluster.

type RecordBuilder

type RecordBuilder struct {
	// contains filtered or unexported fields
}

RecordBuilder constructs a graph node with a fluent API.

func Record

func Record(content string) *RecordBuilder

Record starts building a new record with the given content.

func (*RecordBuilder) AccessCount

func (b *RecordBuilder) AccessCount(n int64) *RecordBuilder

func (*RecordBuilder) Add

func (b *RecordBuilder) Add(t *testing.T, eng *core.Engine) string

Add inserts the record into the engine and returns its ID. Acquires and releases the write lock.

func (*RecordBuilder) AddDirect

func (b *RecordBuilder) AddDirect(eng *core.Engine) string

AddDirect inserts the record without requiring *testing.T. Use in TestMain or other contexts where *testing.T is unavailable.

func (*RecordBuilder) Confidence

func (b *RecordBuilder) Confidence(v float64) *RecordBuilder

func (*RecordBuilder) CreatedAt

func (b *RecordBuilder) CreatedAt(t time.Time) *RecordBuilder

func (*RecordBuilder) Embedding

func (b *RecordBuilder) Embedding(vec []float32) *RecordBuilder

func (*RecordBuilder) EpistemicStatus

func (b *RecordBuilder) EpistemicStatus(v string) *RecordBuilder

func (*RecordBuilder) Importance

func (b *RecordBuilder) Importance(v float64) *RecordBuilder

func (*RecordBuilder) Keywords

func (b *RecordBuilder) Keywords(kw ...string) *RecordBuilder

func (*RecordBuilder) KnowledgeType

func (b *RecordBuilder) KnowledgeType(v string) *RecordBuilder

func (*RecordBuilder) LastAccessed

func (b *RecordBuilder) LastAccessed(t time.Time) *RecordBuilder

func (*RecordBuilder) Pending

func (b *RecordBuilder) Pending() *RecordBuilder

func (*RecordBuilder) Resolution

func (b *RecordBuilder) Resolution(v string) *RecordBuilder

func (*RecordBuilder) ResolvedAt

func (b *RecordBuilder) ResolvedAt(t time.Time) *RecordBuilder

func (*RecordBuilder) SourceRef

func (b *RecordBuilder) SourceRef(v string) *RecordBuilder

func (*RecordBuilder) Summary

func (b *RecordBuilder) Summary(v string) *RecordBuilder

func (*RecordBuilder) Temporality

func (b *RecordBuilder) Temporality(v string) *RecordBuilder

func (*RecordBuilder) ValidUntil

func (b *RecordBuilder) ValidUntil(t time.Time) *RecordBuilder

Jump to

Keyboard shortcuts

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