harness

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Apr 3, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AssertConfigPathStable

func AssertConfigPathStable(t *testing.T, configPath, dataDir, sessionID string)

AssertConfigPathStable verifies the config directory path is deterministic and matches the expected scheme: <dataDir>/configs/<sessionID>/

func AssertEventCount

func AssertEventCount(t *testing.T, events []agent.AgentEvent, typ agent.AgentEventType, expected int)

AssertEventCount checks the number of events of a given type.

func AssertEventSequence

func AssertEventSequence(t *testing.T, events []agent.AgentEvent, types ...agent.AgentEventType)

AssertEventSequence verifies that the given event types appear in order in the event stream (not necessarily contiguously).

func AssertNoEventGaps

func AssertNoEventGaps(t *testing.T, events []agent.AgentEvent, maxGap time.Duration)

AssertNoEventGaps verifies there are no time gaps larger than maxGap between consecutive events.

func AssertNormalizedConfidence

func AssertNormalizedConfidence(t *testing.T, events []NormalizedEvent, source string, expectedConfidence EventConfidence)

AssertNormalizedConfidence checks that all events from a given source have the expected confidence level.

func AssertStateTransitions

func AssertStateTransitions(t *testing.T, events []agent.AgentEvent, states ...agent.AgentState)

AssertStateTransitions verifies that state_change events follow the given sequence.

func DumpEventTimeline

func DumpEventTimeline(t *testing.T, events []agent.AgentEvent)

DumpEventTimeline logs the full event timeline for debugging.

Types

type ConfigInjector

type ConfigInjector struct {
	ConfigDir string
	// contains filtered or unexported fields
}

ConfigInjector handles credential and config directory setup for Mode 2 E2E tests. It prepares the managed config directory with driver-specific config and credentials before the driver process launches.

func NewConfigInjector

func NewConfigInjector(t *testing.T, configDir string) *ConfigInjector

NewConfigInjector creates a ConfigInjector for the given config directory.

func (*ConfigInjector) BuildEnvVars

func (ci *ConfigInjector) BuildEnvVars() map[string]string

BuildEnvVars returns environment variables for the driver process that point to the managed config directory.

func (*ConfigInjector) InjectAPIKey

func (ci *ConfigInjector) InjectAPIKey(filename, key string)

InjectAPIKey writes a typical API key credential file.

func (*ConfigInjector) InjectCredentials

func (ci *ConfigInjector) InjectCredentials(creds ...Credential)

InjectCredentials writes credential files into the config directory.

func (*ConfigInjector) InjectDriverConfig

func (ci *ConfigInjector) InjectDriverConfig(filename, config string)

InjectDriverConfig writes driver-specific configuration.

func (*ConfigInjector) ReadCredential

func (ci *ConfigInjector) ReadCredential(relPath string) string

ReadCredential reads a credential file's content.

func (*ConfigInjector) VerifyCredentialExists

func (ci *ConfigInjector) VerifyCredentialExists(relPath string) bool

VerifyCredentialExists checks that a credential file exists at the expected path.

type Credential

type Credential struct {
	RelPath string // path relative to config dir
	Content string // file content
	Mode    os.FileMode
}

Credential represents a credential file to inject.

type DeterministicDriverSimulator

type DeterministicDriverSimulator struct {

	// Callbacks for each source type
	OnPTYOutput func(data []byte)
	OnOTELSpan  func(span OTELData)
	OnHookEvent func(hook HookData)

	// MonitorSubmit allows the simulator to inject events into an AgentMonitor.
	MonitorSubmit func(evt monitor.AgentEvent)
	// contains filtered or unexported fields
}

DeterministicDriverSimulator replays a recorded driver session, emitting PTY output, OTEL spans, and hook events at recorded timestamps. It exercises the real event normalization pipeline without a live driver.

func NewDeterministicDriverSimulator

func NewDeterministicDriverSimulator(entries []ReplayEntry, mode ReplayMode) *DeterministicDriverSimulator

NewDeterministicDriverSimulator creates a simulator from a replay script.

func (*DeterministicDriverSimulator) Run

Run replays all entries, calling the appropriate callbacks. In fast-forward mode, events are dispatched immediately. In real-time mode, inter-event delays are preserved.

type EventConfidence

type EventConfidence string

EventConfidence indicates the fidelity of a normalized event.

const (
	ConfidenceHigh     EventConfidence = "high"     // from OTEL (highest fidelity)
	ConfidenceMedium   EventConfidence = "medium"   // from hooks (reliable but coarser)
	ConfidenceDegraded EventConfidence = "degraded" // from session-log (fallback)
)

type EventNormalizer

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

EventNormalizer reconciles events from multiple sources using the three-source priority hierarchy: OTEL > hooks > session-log.

func NewEventNormalizer

func NewEventNormalizer() *EventNormalizer

NewEventNormalizer creates a new EventNormalizer.

func (*EventNormalizer) AddEvent

func (n *EventNormalizer) AddEvent(evt agent.AgentEvent, source string)

AddEvent adds a normalized event from a specific source.

func (*EventNormalizer) Events

func (n *EventNormalizer) Events() []NormalizedEvent

Events returns all normalized events in order.

func (*EventNormalizer) ResolveConflicts

func (n *EventNormalizer) ResolveConflicts(window time.Duration) []NormalizedEvent

ResolveConflicts applies the source priority hierarchy to deduplicate events. When multiple sources report the same event type AND identity fields within a time window, the higher-priority source wins. Events with different identity fields (e.g., different tool names or call IDs) are never deduplicated.

type HookData

type HookData struct {
	Event     string `json:"event"`
	SessionID string `json:"session_id,omitempty"`
	ToolName  string `json:"tool_name,omitempty"`
	CallID    string `json:"call_id,omitempty"`
}

HookData holds a hook callback payload.

type NormalizedEvent

type NormalizedEvent struct {
	Event      agent.AgentEvent
	Source     string // "otel", "hook", "session_log"
	Confidence EventConfidence
}

NormalizedEvent is an AgentEvent with source provenance and confidence.

type OTELData

type OTELData struct {
	Span  string         `json:"span"`
	Attrs map[string]any `json:"attrs,omitempty"`
}

OTELData holds a structured OTEL span/event.

type PTYData

type PTYData struct {
	Bytes []byte
}

PTYData holds decoded PTY output bytes.

type ReplayEntry

type ReplayEntry struct {
	Timestamp time.Time       `json:"ts"`
	Source    string          `json:"source"` // "pty", "otel", "hook"
	Data      json.RawMessage `json:"data"`
}

ReplayEntry is a single line in a replay script (JSON Lines format).

func LoadReplayScript

func LoadReplayScript(path string) ([]ReplayEntry, error)

LoadReplayScript loads a replay script from a JSON Lines file.

func ParseReplayScript

func ParseReplayScript(data []byte) ([]ReplayEntry, error)

ParseReplayScript parses replay entries from JSON Lines bytes.

type ReplayMode

type ReplayMode int

ReplayMode controls how inter-event delays are handled.

const (
	// ReplayFastForward replays events with no inter-event delays (CI default).
	ReplayFastForward ReplayMode = iota
	// ReplayRealTime replays events at original recorded timestamps.
	ReplayRealTime
)

type SandboxEnv

type SandboxEnv struct {
	SessionID    string
	WorkspaceDir string
	DataDir      string // sandbox-data-dir (parent of configs/)
	ConfigDir    string // <DataDir>/configs/<SessionID>/
	// contains filtered or unexported fields
}

SandboxEnv provides workspace and session lifecycle helpers for Mode 2 E2E tests. It manages workspace directories that simulate ZFS-backed session storage.

func NewSandboxEnv

func NewSandboxEnv(t *testing.T, cfg SandboxEnvConfig) *SandboxEnv

NewSandboxEnv creates a SandboxEnv with isolated temp directories.

func (*SandboxEnv) ConfigFileExists

func (e *SandboxEnv) ConfigFileExists(relPath string) bool

ConfigFileExists checks if a file exists in the config directory.

func (*SandboxEnv) ConfigPath

func (e *SandboxEnv) ConfigPath() string

ConfigPath returns the config directory path for the session. This validates the path scheme: <sandbox-data-dir>/configs/<session-id>/

func (*SandboxEnv) ReadConfigFile

func (e *SandboxEnv) ReadConfigFile(relPath string) string

ReadConfigFile reads a file from the config directory.

func (*SandboxEnv) ReadWorkspaceFile

func (e *SandboxEnv) ReadWorkspaceFile(relPath string) string

ReadWorkspaceFile reads a file from the workspace directory.

func (*SandboxEnv) SimulateSnapshot

func (e *SandboxEnv) SimulateSnapshot(name string) string

SimulateSnapshot simulates a ZFS snapshot by creating a copy marker.

func (*SandboxEnv) SnapshotExists

func (e *SandboxEnv) SnapshotExists(name string) bool

SnapshotExists checks if a simulated snapshot exists.

func (*SandboxEnv) WorkspaceFileExists

func (e *SandboxEnv) WorkspaceFileExists(relPath string) bool

WorkspaceFileExists checks if a file exists in the workspace.

func (*SandboxEnv) WriteConfigFile

func (e *SandboxEnv) WriteConfigFile(relPath, content string)

WriteConfigFile creates a file in the config directory.

func (*SandboxEnv) WriteWorkspaceFile

func (e *SandboxEnv) WriteWorkspaceFile(relPath, content string)

WriteWorkspaceFile creates a file in the workspace directory.

type SandboxEnvConfig

type SandboxEnvConfig struct {
	SessionID string
	// DataDir overrides the sandbox data directory (parent of configs/).
	// If empty, a new temp directory is created. Set this to share
	// a data directory across multiple SandboxEnv instances (e.g.,
	// to test config persistence across restart).
	DataDir string
}

SandboxEnvConfig controls SandboxEnv setup.

type TermmuxEnv

type TermmuxEnv struct {
	Session *termmux.Session
	Adapter *agent.TermmuxDriverAdapter
	Monitor *monitor.AgentMonitor
	// contains filtered or unexported fields
}

TermmuxEnv wraps a termmux session with E2E test helpers for PTY launch, attach/detach, event capture, and lifecycle control.

func NewTermmuxEnv

func NewTermmuxEnv(t *testing.T, cfg TermmuxEnvConfig) *TermmuxEnv

NewTermmuxEnv creates a TermmuxEnv with a termmux session and adapter.

func (*TermmuxEnv) Attach

func (e *TermmuxEnv) Attach(clientID string) *termmux.Client

Attach adds a client to the session.

func (*TermmuxEnv) Detach

func (e *TermmuxEnv) Detach(clientID string)

Detach removes a client from the session.

func (*TermmuxEnv) Events

func (e *TermmuxEnv) Events() []agent.AgentEvent

Events returns a snapshot of all captured events.

func (*TermmuxEnv) EventsOfType

func (e *TermmuxEnv) EventsOfType(typ agent.AgentEventType) []agent.AgentEvent

EventsOfType returns all captured events matching the given type.

func (*TermmuxEnv) HasEventSequence

func (e *TermmuxEnv) HasEventSequence(types ...agent.AgentEventType) bool

HasEventSequence checks that the given event types appear in order.

func (*TermmuxEnv) IsPaused

func (e *TermmuxEnv) IsPaused() bool

IsPaused returns whether the session is paused.

func (*TermmuxEnv) IsRunning

func (e *TermmuxEnv) IsRunning() bool

IsRunning returns whether the session's child process is running.

func (*TermmuxEnv) Pause

func (e *TermmuxEnv) Pause() error

Pause pauses the session, gating new interactions.

func (*TermmuxEnv) Resume

func (e *TermmuxEnv) Resume() error

Resume unpauses the session.

func (*TermmuxEnv) Start

func (e *TermmuxEnv) Start(ctx context.Context, prompt string) error

Start launches the termmux session via the adapter.

func (*TermmuxEnv) Stop

func (e *TermmuxEnv) Stop()

Stop stops the session and cleans up.

func (*TermmuxEnv) Wait

func (e *TermmuxEnv) Wait()

Wait blocks until the session exits.

func (*TermmuxEnv) WaitForEvent

func (e *TermmuxEnv) WaitForEvent(t *testing.T, typ agent.AgentEventType, timeout time.Duration) agent.AgentEvent

WaitForEvent waits for an event of the given type with a timeout.

func (*TermmuxEnv) WaitForState

func (e *TermmuxEnv) WaitForState(t *testing.T, state monitor.State, timeout time.Duration)

WaitForState waits for the monitor to reach the given state.

func (*TermmuxEnv) WritePTY

func (e *TermmuxEnv) WritePTY(data []byte) (int, error)

WritePTY writes data to the session's PTY.

type TermmuxEnvConfig

type TermmuxEnvConfig struct {
	SessionID  string
	DriverType string
	Command    string
	Args       []string
	CWD        string
	Env        map[string]string
}

TermmuxEnvConfig controls TermmuxEnv setup.

Jump to

Keyboard shortcuts

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