Documentation
¶
Overview ¶
Package testutil provides shared test helpers for controller package tests. These helpers reduce code duplication across test files by providing: - Standard EventBus and Logger creation - Event waiting utilities with timeout - Component lifecycle testing helpers - Timing constants to replace magic numbers
Index ¶
- Constants
- func AssertNoEvent[T any](t *testing.T, eventChan <-chan busevents.Event, timeout time.Duration)
- func CreateTestSecretWithStringData(name, namespace, resourceVersion string, data map[string]string) *unstructured.Unstructured
- func DrainChannel(eventChan <-chan busevents.Event)
- func NewTestBus() *busevents.EventBus
- func NewTestBusAndLogger() (*busevents.EventBus, *slog.Logger)
- func NewTestLogger() *slog.Logger
- func RunComponentContextCancel(t *testing.T, bus *busevents.EventBus, startFunc func(context.Context) error)
- func RunComponentStartStop(t *testing.T, bus *busevents.EventBus, startFunc func(context.Context) error, ...)
- func WaitForEvent[T any](t *testing.T, eventChan <-chan busevents.Event, timeout time.Duration) T
- func WaitForEventWithPredicate[T any](t *testing.T, eventChan <-chan busevents.Event, timeout time.Duration, ...) T
- type RenderCycleFixture
- func (f *RenderCycleFixture) Artifacts(tb testing.TB, files *dataplane.AuxiliaryFiles, ...) *renderartifact.Snapshot
- func (f *RenderCycleFixture) Snapshot(tb testing.TB, config string, status *templating.StatusPatchSnapshot, ...) *rendercycle.Snapshot
- func (f *RenderCycleFixture) SnapshotWithEffects(tb testing.TB, config string, plan *renderplan.Plan, ...) *rendercycle.Snapshot
Constants ¶
const ( // StartupDelay is the time to wait for components to initialize after starting. StartupDelay = 50 * time.Millisecond // DebounceWait is the time to wait for debounce timers to fire. DebounceWait = 100 * time.Millisecond // EventTimeout is the default timeout for waiting on a single event. EventTimeout = 500 * time.Millisecond // LongTimeout is used for operations that may take longer (e.g., component stop). LongTimeout = 1 * time.Second // VeryLongTimeout is used for integration-style tests within unit test files. VeryLongTimeout = 2 * time.Second // NoEventTimeout is a shorter timeout for verifying no event is received. NoEventTimeout = 200 * time.Millisecond )
Timing constants to replace magic numbers in tests. These provide consistent, documented values for test synchronization.
const MinimalHAProxyConfig = `` /* 226-byte string literal not displayed */
MinimalHAProxyConfig is the smallest config that passes `haproxy -c`: one frontend, one backend, one server. Render/validate tests that only need *some* valid config use this so a change to what "valid" means is one edit.
const ValidHAProxyConfigTemplate = `` /* 266-byte string literal not displayed */
ValidHAProxyConfigTemplate is a minimal valid HAProxy configuration template that passes HAProxy syntax validation. Use this in tests that need to render and validate HAProxy configurations.
Variables ¶
This section is empty.
Functions ¶
func AssertNoEvent ¶
AssertNoEvent verifies that no event of type T is received within the timeout. This is useful for testing that certain events are NOT published.
Example:
testutil.AssertNoEvent[*events.ConfigParsedEvent](t, eventChan, testutil.NoEventTimeout)
func CreateTestSecretWithStringData ¶
func CreateTestSecretWithStringData(name, namespace, resourceVersion string, data map[string]string) *unstructured.Unstructured
CreateTestSecretWithStringData creates an unstructured Secret with string data. This is useful for credentials secrets that don't need base64 encoding in tests.
Example:
secret := testutil.CreateTestSecretWithStringData("creds", "default", "12345",
map[string]string{"username": "admin", "password": "secret"})
func DrainChannel ¶
DrainChannel empties all pending events from the channel without blocking. Useful for clearing events between test phases.
func NewTestBus ¶
NewTestBus creates an EventBus with a standard buffer size for tests.
func NewTestBusAndLogger ¶
NewTestBusAndLogger creates both an EventBus and Logger for tests. This is the most common setup pattern across controller tests.
func NewTestLogger ¶
NewTestLogger creates a logger that writes to stderr with error level. This minimizes noise in test output while still capturing errors.
func RunComponentContextCancel ¶
func RunComponentContextCancel(t *testing.T, bus *busevents.EventBus, startFunc func(context.Context) error)
RunComponentContextCancel tests that a component stops cleanly when context is cancelled. This reduces boilerplate for the common test pattern in controller components.
Example:
func TestMyComponent_StartWithContextCancel(t *testing.T) {
bus, logger := testutil.NewTestBusAndLogger()
component := NewMyComponent(bus, logger)
testutil.RunComponentContextCancel(t, bus, component.Start)
}
func RunComponentStartStop ¶
func RunComponentStartStop(t *testing.T, bus *busevents.EventBus, startFunc func(context.Context) error, stopFunc func())
RunComponentStartStop tests that a component starts and stops cleanly. This reduces boilerplate for the common test pattern in controller components.
Example:
func TestMyComponent_StartAndStop(t *testing.T) {
bus, logger := testutil.NewTestBusAndLogger()
component := NewMyComponent(bus, logger)
testutil.RunComponentStartStop(t, bus, component.Start, component.Stop)
}
func WaitForEvent ¶
WaitForEvent waits for an event of type T on the channel, failing the test on timeout. It skips over events of other types until finding a matching one.
Example:
event := testutil.WaitForEvent[*events.ConfigParsedEvent](t, eventChan, testutil.EventTimeout) assert.Equal(t, "v1", event.Version)
func WaitForEventWithPredicate ¶
func WaitForEventWithPredicate[T any](t *testing.T, eventChan <-chan busevents.Event, timeout time.Duration, predicate func(T) bool) T
WaitForEventWithPredicate waits for an event of type T that satisfies the predicate. Useful when you need to match on event fields, not just type.
Example:
event := testutil.WaitForEventWithPredicate(t, eventChan, testutil.EventTimeout,
func(e *events.ConfigParsedEvent) bool { return e.Version == "v2" })
Types ¶
type RenderCycleFixture ¶
type RenderCycleFixture struct {
// contains filtered or unexported fields
}
RenderCycleFixture owns one authenticated test lineage.
func NewRenderCycleFixture ¶
func NewRenderCycleFixture(tb testing.TB) *RenderCycleFixture
NewRenderCycleFixture creates one authenticated lineage with empty artifacts.
func (*RenderCycleFixture) Artifacts ¶
func (f *RenderCycleFixture) Artifacts( tb testing.TB, files *dataplane.AuxiliaryFiles, previous *renderartifact.Snapshot, ) *renderartifact.Snapshot
Artifacts seals auxiliary files in this fixture's output lineage.
func (*RenderCycleFixture) Snapshot ¶
func (f *RenderCycleFixture) Snapshot( tb testing.TB, config string, status *templating.StatusPatchSnapshot, previous *rendercycle.Snapshot, ) *rendercycle.Snapshot
Snapshot seals one output and status set after previous in this lineage.
func (*RenderCycleFixture) SnapshotWithEffects ¶
func (f *RenderCycleFixture) SnapshotWithEffects( tb testing.TB, config string, plan *renderplan.Plan, artifacts *renderartifact.Snapshot, status *templating.StatusPatchSnapshot, events *templating.RenderedEventSnapshot, resources *templating.RenderedResourceSnapshot, previous *rendercycle.Snapshot, ) *rendercycle.Snapshot
SnapshotWithEffects seals one exact test output and effect set.