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 ComponentStopTest(t *testing.T, bus *busevents.EventBus, startFunc, stopFunc func())
- func CreateTestConfigMap(name, namespace, resourceVersion string, data map[string]string) *unstructured.Unstructured
- func CreateTestSecret(name, namespace, resourceVersion string, data map[string]interface{}) *unstructured.Unstructured
- func CreateTestSecretWithStringData(name, namespace, resourceVersion string, data map[string]string) *unstructured.Unstructured
- func CreateTestSecretWithTLS(name, namespace, resourceVersion string, certPEM, keyPEM []byte) *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
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 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 ComponentStopTest ¶
ComponentStopTest tests that a component stops cleanly when Stop() is called. This is a common pattern across controller components.
The startFunc should start the component in blocking mode (e.g., component.Start(ctx)). The stopFunc should trigger the component to stop (e.g., component.Stop()).
Example:
testutil.ComponentStopTest(t, bus,
func(ctx context.Context) { component.Start(ctx) },
func() { component.Stop() })
func CreateTestConfigMap ¶
func CreateTestConfigMap(name, namespace, resourceVersion string, data map[string]string) *unstructured.Unstructured
CreateTestConfigMap creates an unstructured ConfigMap for testing.
Example:
cm := testutil.CreateTestConfigMap("my-config", "default", "12345",
map[string]string{"key": "value"})
func CreateTestSecret ¶
func CreateTestSecret(name, namespace, resourceVersion string, data map[string]interface{}) *unstructured.Unstructured
CreateTestSecret creates an unstructured Secret for testing. This is a common fixture used by multiple loader components.
Example:
secret := testutil.CreateTestSecret("test-secret", "test-ns", "12345", map[string]interface{}{
"username": "admin",
"password": "secret",
})
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 CreateTestSecretWithTLS ¶
func CreateTestSecretWithTLS(name, namespace, resourceVersion string, certPEM, keyPEM []byte) *unstructured.Unstructured
CreateTestSecretWithTLS creates an unstructured TLS Secret for testing. The cert and key are base64-encoded as Kubernetes expects for Secret data.
Example:
secret := testutil.CreateTestSecretWithTLS("my-tls", "default", "12345",
[]byte("-----BEGIN CERTIFICATE-----\n..."),
[]byte("-----BEGIN PRIVATE KEY-----\n..."))
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 TestCertLoaderComponent_StartWithContextCancel(t *testing.T) {
bus, logger := testutil.NewTestBusAndLogger()
component := NewCertLoaderComponent(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 TestCertLoaderComponent_StartAndStop(t *testing.T) {
bus, logger := testutil.NewTestBusAndLogger()
component := NewCertLoaderComponent(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 ¶
This section is empty.