Documentation
¶
Overview ¶
Package testutil provides testing utilities for daemon functionality. It enables dual-mode testing where commands can be tested both with a running daemon and in direct mode (no daemon).
Index ¶
- Constants
- func IsDaemonMode() bool
- func NewTestClient() *daemon.Client
- func RequireDaemon(t *testing.T)
- func RequireNoDaemon(t *testing.T)
- func RunDualMode(t *testing.T, tests []DualModeTest)
- func StartTestDaemon(t *testing.T, tmpDir string) (cleanup func())
- func TestDaemonConfig(tmpDir string) *daemon.Config
- func WaitForDaemon(t *testing.T, timeout time.Duration) error
- type DualModeTest
- type Fault
- type FaultConfig
- type MockDaemondeprecated
- func (m *MockDaemon) CallCount(msgType string) int
- func (m *MockDaemon) GetCalls() []RPCCall
- func (m *MockDaemon) ResetCalls()
- func (m *MockDaemon) Start(t *testing.T)
- func (m *MockDaemon) Stop()
- func (m *MockDaemon) WithResponse(msgType string, response any) *MockDaemon
- func (m *MockDaemon) WithStatus(status *daemon.StatusData) *MockDaemon
- func (m *MockDaemon) WithSyncError(err error) *MockDaemon
- type Mode
- type OxFaultConfig
- type OxFaultDaemon
- func NewCorruptDaemon(t *testing.T) *OxFaultDaemon
- func NewCrashingDaemon(t *testing.T) *OxFaultDaemon
- func NewFaultDaemon(t *testing.T, config FaultConfig) *OxFaultDaemon
- func NewFlakyDaemon(t *testing.T, dropEveryN int) *OxFaultDaemon
- func NewHealthyFaultDaemon(t *testing.T) *OxFaultDaemon
- func NewHungDaemon(t *testing.T) *OxFaultDaemon
- func NewOxCorruptDaemon(t *testing.T) *OxFaultDaemon
- func NewOxCrashingDaemon(t *testing.T) *OxFaultDaemon
- func NewOxFaultDaemon(t *testing.T, config OxFaultConfig) *OxFaultDaemon
- func NewOxFlakyDaemon(t *testing.T, dropEveryN int) *OxFaultDaemon
- func NewOxHealthyFaultDaemon(t *testing.T) *OxFaultDaemon
- func NewOxHungDaemon(t *testing.T) *OxFaultDaemon
- func NewOxSlowDaemon(t *testing.T, delay time.Duration) *OxFaultDaemon
- func NewSlowDaemon(t *testing.T, delay time.Duration) *OxFaultDaemon
- type RPCCall
- type TestEnvironment
Examples ¶
Constants ¶
const ( FaultNone = faultdaemon.FaultNone FaultHangOnAccept = faultdaemon.FaultHangOnAccept FaultHangBeforeResponse = faultdaemon.FaultHangBeforeResponse FaultSlowResponse = faultdaemon.FaultSlowResponse FaultCorruptResponse = faultdaemon.FaultCorruptResponse FaultPartialResponse = faultdaemon.FaultPartialResponse FaultCloseImmediately = faultdaemon.FaultCloseImmediately FaultCloseAfterRead = faultdaemon.FaultCloseAfterRead FaultDropConnection = faultdaemon.FaultDropConnection FaultPanicInHandler = faultdaemon.FaultPanicInHandler FaultDeadlock = faultdaemon.FaultDeadlock FaultMultipleResponses = faultdaemon.FaultMultipleResponses FaultResponseWithoutNewline = faultdaemon.FaultResponseWithoutNewline FaultChunkedResponse = faultdaemon.FaultChunkedResponse FaultSlowAccept = faultdaemon.FaultSlowAccept FaultRefuseAfterAccept = faultdaemon.FaultRefuseAfterAccept FaultVerySlowResponse = faultdaemon.FaultVerySlowResponse FaultResponseTooLarge = faultdaemon.FaultResponseTooLarge FaultInvalidJSON = faultdaemon.FaultInvalidJSON FaultEmbeddedNewlines = faultdaemon.FaultEmbeddedNewlines FaultWriteHalfThenHang = faultdaemon.FaultWriteHalfThenHang )
Fault constant aliases
Variables ¶
This section is empty.
Functions ¶
func IsDaemonMode ¶
func IsDaemonMode() bool
IsDaemonMode returns true if we're running in daemon mode. Useful for tests that need to behave differently based on daemon availability.
func NewTestClient ¶
NewTestClient creates a daemon client with test-appropriate timeout. Uses 500ms (vs 50ms production default) for test stability under load.
func RequireDaemon ¶
RequireDaemon skips the test if no daemon is running.
func RequireNoDaemon ¶
RequireNoDaemon skips the test if a daemon is running.
func RunDualMode ¶
func RunDualMode(t *testing.T, tests []DualModeTest)
RunDualMode executes tests in both daemon and direct modes. Each test runs twice: once with a daemon and once without. Note: Tests do not run in parallel because daemon mode requires modifying environment variables, which conflicts with t.Parallel().
func StartTestDaemon ¶
StartTestDaemon starts a real daemon in a temp directory for testing. Returns a cleanup function that must be called to stop the daemon.
Usage:
cleanup := StartTestDaemon(t, tmpDir) defer cleanup() // ... run tests that interact with daemon ...
func TestDaemonConfig ¶
TestDaemonConfig returns a daemon config suitable for testing.
Types ¶
type DualModeTest ¶
type DualModeTest struct {
// Name is the test name (will have mode suffix appended).
Name string
// Test is the test function. Mode indicates whether the daemon is running.
// Test should use mode to determine how to execute the command.
Test func(t *testing.T, mode Mode)
// SkipDaemon skips daemon mode test if true.
SkipDaemon bool
// SkipDirect skips direct mode test if true.
SkipDirect bool
}
DualModeTest defines a test that should work in both daemon and direct modes. This ensures commands function correctly regardless of daemon availability.
Example ¶
ExampleDualModeTest demonstrates how to use DualModeTest.
// define tests that work in both modes
tests := []DualModeTest{
{
Name: "command_works_with_and_without_daemon",
Test: func(t *testing.T, mode Mode) {
// your command logic here
// use mode to check which mode we're in
if mode == ModeDaemon {
// daemon-specific assertions
} else {
// direct mode assertions
}
},
},
}
// run in a test function:
// RunDualMode(t, tests)
_ = tests
type FaultConfig ¶
type FaultConfig struct {
// Fault is the failure mode to inject.
Fault Fault
// SlowResponseDelay is the delay for slow response faults.
SlowResponseDelay time.Duration
// DropEveryN drops every Nth connection for drop connection fault.
DropEveryN int
// FaultOnMessageType restricts the fault to a specific message type.
// Other message types respond normally.
FaultOnMessageType string
// StatusResponse overrides the daemon's status response.
StatusResponse *daemon.StatusData
// DoctorResponse overrides the daemon's doctor response.
DoctorResponse *daemon.DoctorResponse
// CheckoutResponse overrides the daemon's checkout response.
CheckoutResponse *daemon.CheckoutResult
// SyncError is the error to return for sync requests.
SyncError error
}
FaultConfig is the backward-compatible config struct for tests. It mirrors the old API where fields were at the top level.
type MockDaemon
deprecated
type MockDaemon struct {
// Responses maps message types to their responses.
// Key is the message type (e.g., "status", "sync").
Responses map[string]any
// StatusResponse is the status to return for status requests.
StatusResponse *daemon.StatusData
// SyncError is the error to return for sync requests (nil = success).
SyncError error
// Calls records all RPC calls made to the mock.
Calls []RPCCall
// contains filtered or unexported fields
}
MockDaemon provides a mock daemon for unit tests. It records all RPC calls and returns configurable responses.
Deprecated: Use OxFaultDaemon for new tests. It provides the same functionality plus fault injection capabilities.
Example ¶
ExampleMockDaemon demonstrates how to use MockDaemon.
// in a test function:
// env := NewTestEnvironment(t)
// mock := env.StartMock()
//
// configure mock responses:
// mock.StatusResponse = &daemon.StatusData{Running: true}
// mock.SyncError = errors.New("test error")
//
// make assertions:
// client := daemon.NewClient()
// err := client.Ping()
// assert.NoError(t, err)
// assert.Equal(t, 1, mock.CallCount(daemon.MsgTypePing))
func (*MockDaemon) CallCount ¶
func (m *MockDaemon) CallCount(msgType string) int
CallCount returns the number of calls of a specific type.
func (*MockDaemon) GetCalls ¶
func (m *MockDaemon) GetCalls() []RPCCall
GetCalls returns a copy of all recorded calls.
func (*MockDaemon) ResetCalls ¶
func (m *MockDaemon) ResetCalls()
ResetCalls clears all recorded calls.
func (*MockDaemon) Start ¶
func (m *MockDaemon) Start(t *testing.T)
Start starts the mock daemon on the default socket path. Call this after setting environment variables for XDG_RUNTIME_DIR.
func (*MockDaemon) WithResponse ¶
func (m *MockDaemon) WithResponse(msgType string, response any) *MockDaemon
WithResponse adds a custom response for a message type.
func (*MockDaemon) WithStatus ¶
func (m *MockDaemon) WithStatus(status *daemon.StatusData) *MockDaemon
WithStatus configures the status response.
func (*MockDaemon) WithSyncError ¶
func (m *MockDaemon) WithSyncError(err error) *MockDaemon
WithSyncError configures sync to return an error.
type OxFaultConfig ¶
type OxFaultConfig struct {
// Embedded generic config
faultdaemon.Config
// StatusResponse is returned for status requests.
StatusResponse *daemon.StatusData
// DoctorResponse is returned for doctor requests.
DoctorResponse *daemon.DoctorResponse
// CheckoutResponse is returned for checkout requests.
CheckoutResponse *daemon.CheckoutResult
// SyncError is the error to return for sync requests (nil = success).
SyncError error
// CustomResponses maps message types to custom response data.
// Value will be marshaled to JSON and wrapped in daemon.Response.
CustomResponses map[string]any
}
OxFaultConfig extends generic fault config with ox-specific responses.
type OxFaultDaemon ¶
type OxFaultDaemon struct {
*faultdaemon.FaultDaemon
// contains filtered or unexported fields
}
OxFaultDaemon wraps the generic FaultDaemon with ox protocol knowledge. It generates ox-specific responses (daemon.Response) for incoming messages.
func NewCorruptDaemon ¶
func NewCorruptDaemon(t *testing.T) *OxFaultDaemon
NewCorruptDaemon creates a daemon that sends garbage responses.
func NewCrashingDaemon ¶
func NewCrashingDaemon(t *testing.T) *OxFaultDaemon
NewCrashingDaemon creates a daemon that closes connections immediately.
func NewFaultDaemon ¶
func NewFaultDaemon(t *testing.T, config FaultConfig) *OxFaultDaemon
NewFaultDaemon creates an ox fault daemon with the given config.
func NewFlakyDaemon ¶
func NewFlakyDaemon(t *testing.T, dropEveryN int) *OxFaultDaemon
NewFlakyDaemon creates a daemon that drops every Nth connection.
func NewHealthyFaultDaemon ¶
func NewHealthyFaultDaemon(t *testing.T) *OxFaultDaemon
NewHealthyFaultDaemon creates a fault daemon with no faults.
func NewHungDaemon ¶
func NewHungDaemon(t *testing.T) *OxFaultDaemon
NewHungDaemon creates a daemon that accepts connections but never responds.
func NewOxCorruptDaemon ¶
func NewOxCorruptDaemon(t *testing.T) *OxFaultDaemon
NewOxCorruptDaemon creates a daemon that sends garbage responses.
func NewOxCrashingDaemon ¶
func NewOxCrashingDaemon(t *testing.T) *OxFaultDaemon
NewOxCrashingDaemon creates a daemon that closes connections immediately.
func NewOxFaultDaemon ¶
func NewOxFaultDaemon(t *testing.T, config OxFaultConfig) *OxFaultDaemon
NewOxFaultDaemon creates an ox-specific fault daemon for testing. It understands ox IPC protocol and generates appropriate responses.
func NewOxFlakyDaemon ¶
func NewOxFlakyDaemon(t *testing.T, dropEveryN int) *OxFaultDaemon
NewOxFlakyDaemon creates a daemon that drops every Nth connection.
func NewOxHealthyFaultDaemon ¶
func NewOxHealthyFaultDaemon(t *testing.T) *OxFaultDaemon
NewOxHealthyFaultDaemon creates a fault daemon with no faults (for baseline testing).
func NewOxHungDaemon ¶
func NewOxHungDaemon(t *testing.T) *OxFaultDaemon
NewOxHungDaemon creates a daemon that accepts connections but never responds.
func NewOxSlowDaemon ¶
func NewOxSlowDaemon(t *testing.T, delay time.Duration) *OxFaultDaemon
NewOxSlowDaemon creates a daemon that responds after a delay.
func NewSlowDaemon ¶
func NewSlowDaemon(t *testing.T, delay time.Duration) *OxFaultDaemon
NewSlowDaemon creates a daemon that responds after a delay.
func (*OxFaultDaemon) SetOxConfig ¶
func (d *OxFaultDaemon) SetOxConfig(config OxFaultConfig)
SetOxConfig updates the ox-specific configuration.
type RPCCall ¶
type RPCCall struct {
Type string
Payload json.RawMessage
Timestamp time.Time
}
RPCCall records an RPC call made to the mock daemon.
type TestEnvironment ¶
type TestEnvironment struct {
TmpDir string
LedgerDir string
ProjectDir string
// contains filtered or unexported fields
}
TestEnvironment sets up an isolated test environment for daemon tests. Returns a cleanup function that must be called to restore the environment.
func NewTestEnvironment ¶
func NewTestEnvironment(t *testing.T) *TestEnvironment
NewTestEnvironment creates a new isolated test environment. Sets up XDG directories to isolate tests from user's real config.
func (*TestEnvironment) StartDaemon ¶
func (e *TestEnvironment) StartDaemon() func()
StartDaemon starts a test daemon using this environment.
func (*TestEnvironment) StartFault ¶
func (e *TestEnvironment) StartFault(config OxFaultConfig) *OxFaultDaemon
StartFault starts an ox fault daemon using this environment. This provides access to all fault injection modes while understanding ox protocol.
func (*TestEnvironment) StartMock ¶
func (e *TestEnvironment) StartMock() *MockDaemon
StartMock starts a mock daemon using this environment. Deprecated: Use StartFault for new tests.