Documentation
¶
Overview ¶
Package enginetest provides reusable contract-test machinery for the interfaces declared in sdk/engine — engine.Engine and engine.Host today, more if the engine package grows.
Modeled on net/http/httptest, testing/iotest, and gocloud.dev/blob/drivertest: a single sibling package next to its subject covers every contract-checking surface the parent package exposes. The Go convention is one xxxtest sub-package per parent package, not one per interface — see the stdlib examples linked above. Importable from any concrete implementation's *_test files; contains exclusively test-support code; nothing in here should be referenced from non-test production paths.
What lives here ¶
RunSuite — the standard contract every engine.Engine implementation should pass. New engines add a one-liner:
func TestEngineContract(t *testing.T) { enginetest.RunSuite(t, func() (engine.Engine, enginetest.Capabilities) { return newMyEngine(), enginetest.Capabilities{} }) }
HostSuite — the standard contract every engine.Host implementation should pass. Hosts (NoopHost, vessel sandboxHost, OTel-instrumented HostFuncs, third-party hosts) add a one-liner:
func TestMyHost_Contract(t *testing.T) { enginetest.HostSuite(t, func() engine.Host { return newMyHost() }) }
MockHost — a minimal Host implementation that records every interaction, lets tests inject interrupts / user replies, and exposes the captured envelopes / usage / checkpoints for assertion. Engines may use it directly in their own tests instead of re-implementing the full Host surface.
What does NOT live here ¶
This package does not enumerate engine- or host-specific behaviours (graph-edge ordering, script-language semantics, vessel sandbox-specific bus routing, …). It only asserts what every implementation of the targeted interface is contractually obliged to do. Implementation-specific tests live next to the implementation.
Index ¶
- func HostSuite(t *testing.T, f HostFactory, caps ...HostCapabilities)
- func RunSuite(t *testing.T, f Factory)
- type Capabilities
- type Factory
- type HostCapabilities
- type HostFactory
- type MockHost
- func (h *MockHost) AskUser(_ context.Context, p engine.UserPrompt) (engine.UserReply, error)
- func (h *MockHost) Checkpoint(_ context.Context, cp engine.Checkpoint) error
- func (h *MockHost) Checkpoints() []engine.Checkpoint
- func (h *MockHost) Envelopes() []event.Envelope
- func (h *MockHost) Interrupt(cause engine.Cause, detail string)
- func (h *MockHost) Interrupts() <-chan engine.Interrupt
- func (h *MockHost) Prompts() []engine.UserPrompt
- func (h *MockHost) Publish(_ context.Context, env event.Envelope) error
- func (h *MockHost) ReportUsage(_ context.Context, usage model.TokenUsage) error
- func (h *MockHost) SetCheckpointError(err error)
- func (h *MockHost) SetPublishError(err error)
- func (h *MockHost) SetUserReply(reply *engine.UserReply)
- func (h *MockHost) TotalUsage() model.TokenUsage
- func (h *MockHost) Usages() []model.TokenUsage
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func HostSuite ¶ added in v0.3.4
func HostSuite(t *testing.T, f HostFactory, caps ...HostCapabilities)
HostSuite runs every applicable contract subtest against hosts produced by f. Each subtest builds a fresh host so failures isolate cleanly.
func RunSuite ¶
RunSuite runs every contract test that applies to the engine produced by f. Engines should call this from their own *_test.go:
func TestEngineContract(t *testing.T) {
enginetest.RunSuite(t, func() (engine.Engine, enginetest.Capabilities) {
return graph.NewEngine(), enginetest.Capabilities{SupportsResume: true}
})
}
Each subtest constructs a fresh engine, so failures isolate cleanly. The whole suite must pass for an implementation to be considered engine.Engine-compliant.
Types ¶
type Capabilities ¶
type Capabilities struct {
// SupportsResume is true when the engine implements Run.ResumeFrom
// (i.e. given a non-nil ResumeFrom whose ExecID matches Run.ID it
// resumes the run rather than returning errdefs.NotAvailable).
//
// Engines that implement engine.Resumer with stricter CanResume
// admission rules (e.g. graph runner requires cp.Step to be a
// real node id) MAY surface errdefs.Validation when the suite's
// minimal test checkpoint fails admission; the suite accepts
// that as a valid SupportsResume=true outcome since the engine
// honestly rejected an unworkable resume request.
SupportsResume bool
}
Capabilities lets an engine declare which optional behaviours it implements. The contract suite uses this to skip resume-specific subtests when the engine has SupportsResume == false (those subtests instead assert the engine returns NotAvailable).
type Factory ¶
type Factory func() (engine.Engine, Capabilities)
Factory builds a fresh engine and reports its capabilities. The suite calls Factory once per subtest so subtests do not share engine state.
Engines that take no construction arguments can wrap a constructor:
enginetest.RunSuite(t, enginetest.NewFactory(graph.NewEngine))
or implement Factory directly when the construction needs more setup.
type HostCapabilities ¶ added in v0.3.4
type HostCapabilities struct {
// SkipAskUserNotAvailable is true when the host is expected
// to SUCCEED on AskUser (a real UI host with a configured
// UserPrompter). The suite then asserts the call returns a
// non-zero reply rather than allowing NotAvailable.
SkipAskUserNotAvailable bool
// SkipPublishConcurrency is true when the host's Publish
// implementation is intentionally serial (e.g. a writer-locked
// log shipper that must preserve order). The suite then runs
// the Publish concurrency probe sequentially so the test
// reflects the real serial-only contract.
SkipPublishConcurrency bool
// AcceptsBudgetExceeded, when true, indicates the host's
// ReportUsage MAY return an errdefs.BudgetExceeded error for
// the suite's zero-usage probe (= unusual but legal for hosts
// pre-configured with a zero budget). When false (default),
// the suite asserts ReportUsage(0-usage) returns nil.
AcceptsBudgetExceeded bool
}
HostCapabilities lets a host opt out of subtests that don't apply. Most hosts pass the zero value (= every subtest runs).
type HostFactory ¶ added in v0.3.4
HostFactory builds a fresh engine.Host for each subtest. The suite invokes it once per case so subtests do not share host state.
type MockHost ¶
type MockHost struct {
// contains filtered or unexported fields
}
MockHost is a fully-featured engine.Host for tests. It records every interaction and lets the test inject cooperative interrupts and user replies.
All methods are safe for concurrent use; any number of goroutines inside the engine may call them while the test inspects state.
Zero value is NOT ready to use. Call NewMockHost which pre-allocates the channels.
func NewMockHost ¶
func NewMockHost() *MockHost
NewMockHost returns a ready-to-use MockHost. The interrupt channel is buffered so MockHost.Interrupt never blocks the test goroutine when the engine has not yet reached its select on Interrupts().
func (*MockHost) AskUser ¶
AskUser records the prompt and returns the configured reply, or a NotAvailable error when no reply has been set.
func (*MockHost) Checkpoint ¶
Checkpoint records cp and returns the configured checkpointErr.
func (*MockHost) Checkpoints ¶
func (h *MockHost) Checkpoints() []engine.Checkpoint
Checkpoints returns a copy of every checkpoint the engine submitted.
func (*MockHost) Interrupt ¶
Interrupt queues an interrupt for the engine. Non-blocking: if the buffer is full the call drops the new signal silently — tests that care should call only once or assert via MockHost.Envelopes that the engine has reached its select.
func (*MockHost) Interrupts ¶
Interrupts returns the cooperative-interrupt channel.
func (*MockHost) Prompts ¶
func (h *MockHost) Prompts() []engine.UserPrompt
Prompts returns a copy of every UserPrompt the engine submitted.
func (*MockHost) Publish ¶
Publish records the envelope and returns the configured publishErr (default nil).
func (*MockHost) ReportUsage ¶
ReportUsage records the usage delta. Multiple calls are kept in order so tests can assert per-call totals; sum them with MockHost.TotalUsage when only the total matters.
func (*MockHost) SetCheckpointError ¶
SetCheckpointError configures all subsequent Checkpoint calls to return err. Pass nil to clear.
func (*MockHost) SetPublishError ¶
SetPublishError configures all subsequent Publish calls to return err. Pass nil to clear.
func (*MockHost) SetUserReply ¶
SetUserReply configures what AskUser returns. Pass nil to revert to the NotAvailable default.
func (*MockHost) TotalUsage ¶
func (h *MockHost) TotalUsage() model.TokenUsage
TotalUsage sums every recorded usage report.
func (*MockHost) Usages ¶
func (h *MockHost) Usages() []model.TokenUsage
Usages returns a copy of every usage report.