Documentation
¶
Overview ¶
Package testutils holds the shared harness for integration tests: network helpers, gRPC and local-transport cluster startup, cluster config builders, and replica-state assertions. Domain-specific helpers (split topologies, data-dir layout checks, ...) stay in their test packages; the application core they all run is one of testcore's playground cores (or NopCore).
Index ¶
- func AllReplicaStates(admin ReplicaStateLister, targets []string) []*transport.ReplicaState
- func BootstrapNodes(t *testing.T, admin *grpc.AdminClient, addrs []string, ids []string, ...)
- func FindLeader(states []*transport.ReplicaState) (*transport.ReplicaState, bool)
- func FindReplicaState(states []*transport.ReplicaState, replicaId string) (*transport.ReplicaState, bool)
- func FreeAddr(t *testing.T) string
- func FreeAddrs(t *testing.T, n int) []string
- func InMemoryNodeConfig() monstera.NodeConfig
- func ListReplicaStates(admin ReplicaStateLister, target string) (map[string]*transport.ReplicaState, error)
- func NewPlaygroundStub(cfg *cluster.Config) *testcore.PlaygroundApiMonsteraStub
- func PushConfig(t *testing.T, admin *grpc.AdminClient, addrs []string, cfg *cluster.Config)
- func RequireLeader(t *testing.T, admin ReplicaStateLister, targets []string, ...)
- func SingleShardConfig(t *testing.T, addrs []string, replicas int) *cluster.Config
- func SingleShardLocalConfig(t *testing.T, nodes int, replicas int) *cluster.Config
- func StartLocalNode(t *testing.T, baseDir, nodeId string, config *cluster.Config, ...) *monstera.Node
- func WaitForListen(t *testing.T, addr string)
- type GrpcCluster
- func (c *GrpcCluster) KillNode(i int)
- func (c *GrpcCluster) StartNode(t *testing.T, nodeConfig monstera.NodeConfig, addr string, ...) *monstera.Node
- func (c *GrpcCluster) StartNodeAt(t *testing.T, baseDir string, nodeConfig monstera.NodeConfig, addr string, ...) *monstera.Node
- func (c *GrpcCluster) Stop()
- type ReplicaStateLister
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AllReplicaStates ¶
func AllReplicaStates(admin ReplicaStateLister, targets []string) []*transport.ReplicaState
AllReplicaStates concatenates the replica states of every target, skipping unreachable ones.
func BootstrapNodes ¶
func BootstrapNodes(t *testing.T, admin *grpc.AdminClient, addrs []string, ids []string, cfg *cluster.Config)
BootstrapNodes provisions node ids[i] at addrs[i] with cfg over the admin plane.
func FindLeader ¶
func FindLeader(states []*transport.ReplicaState) (*transport.ReplicaState, bool)
FindLeader returns the first replica reporting itself the Raft leader.
func FindReplicaState ¶
func FindReplicaState(states []*transport.ReplicaState, replicaId string) (*transport.ReplicaState, bool)
FindReplicaState returns the state of the replica with the given id.
func FreeAddr ¶
FreeAddr returns a currently-free 127.0.0.1 address. There is a small window between closing the probe listener and the node binding it, which is acceptable for a test.
func InMemoryNodeConfig ¶
func InMemoryNodeConfig() monstera.NodeConfig
InMemoryNodeConfig returns the default node config with the in-memory Raft store — the standard configuration for integration tests.
func ListReplicaStates ¶
func ListReplicaStates(admin ReplicaStateLister, target string) (map[string]*transport.ReplicaState, error)
ListReplicaStates returns the replica states of one node, keyed by replica id.
func NewPlaygroundStub ¶
func NewPlaygroundStub(cfg *cluster.Config) *testcore.PlaygroundApiMonsteraStub
NewPlaygroundStub returns a testcore playground stub talking to the cluster described by cfg over gRPC.
func PushConfig ¶
PushConfig validates cfg and installs it on every node.
func RequireLeader ¶
func RequireLeader(t *testing.T, admin ReplicaStateLister, targets []string, replicaIds map[string]bool)
RequireLeader waits until some replica on some target reports itself the Raft leader. A non-nil replicaIds set restricts the wait to those replicas (e.g. one shard's); nil accepts any replica.
func SingleShardConfig ¶
SingleShardConfig builds the standard test topology: nodes "node_1" .. "node_N" at the given addresses, one application "Core" with replication factor `replicas`, and one full-range ACTIVE shard with a replica on each of the first `replicas` nodes (any remaining nodes host nothing — the add-node/move-shard target).
func SingleShardLocalConfig ¶
SingleShardLocalConfig is SingleShardConfig for the local (in-memory) transport, where a node's address is its id.
func StartLocalNode ¶
func StartLocalNode(t *testing.T, baseDir, nodeId string, config *cluster.Config, trans *local.LocalTransport, inMemory bool) *monstera.Node
StartLocalNode creates a monstera node on the local (in-memory) transport, starts it, bootstraps it if fresh, and registers it under its assigned id so peers can reach it (a fresh node has no id until Bootstrap).
func WaitForListen ¶
WaitForListen blocks until something accepts TCP connections on addr.
Types ¶
type GrpcCluster ¶
type GrpcCluster struct {
Nodes []*monstera.Node
Servers []*grpc.GrpcServer
}
GrpcCluster tracks in-process nodes and gRPC servers so they can be torn down in the right order.
func NewGrpcCluster ¶
func NewGrpcCluster(t *testing.T) *GrpcCluster
NewGrpcCluster returns an empty cluster whose Stop is registered as a test cleanup.
func (*GrpcCluster) KillNode ¶
func (c *GrpcCluster) KillNode(i int)
KillNode abruptly stops node i: the gRPC server is hard-stopped first (closing live connections and Raft streams, so peers see a crash rather than a drain), then the node is stopped to release its on-disk stores for a later restart. The slot stays in Nodes/Servers; Stop tolerates it.
func (*GrpcCluster) StartNode ¶
func (c *GrpcCluster) StartNode(t *testing.T, nodeConfig monstera.NodeConfig, addr string, descriptors monstera.ApplicationCoreDescriptors) *monstera.Node
StartNode creates a monstera node with a fresh t.TempDir data dir, starts it (UNPROVISIONED — bootstrap separately), and serves it over gRPC on addr.
func (*GrpcCluster) StartNodeAt ¶
func (c *GrpcCluster) StartNodeAt(t *testing.T, baseDir string, nodeConfig monstera.NodeConfig, addr string, descriptors monstera.ApplicationCoreDescriptors) *monstera.Node
StartNodeAt is StartNode with a caller-owned data dir, so a test can stop a node and start a fresh one over the same durable state (kill/restart scenarios). A dir holding a provisioned node's state comes back READY; a fresh dir comes up UNPROVISIONED.
func (*GrpcCluster) Stop ¶
func (c *GrpcCluster) Stop()
Stop tears the cluster down in two phases: stop every node first (each moves to STOPPED, rejecting Raft RPCs and cancelling its outbound streams), then GracefulStop every server. Stopping all nodes before any server prevents GracefulStop from blocking on Raft streams held open by peers that haven't been stopped yet — which deadlocks once a shard replica spans several running nodes.
type ReplicaStateLister ¶
type ReplicaStateLister interface {
ListReplicaStates(ctx context.Context, target string) ([]*transport.ReplicaState, error)
}
ReplicaStateLister is the one admin-plane call the state helpers need. Both grpc.AdminClient (target = address) and local.LocalTransport (target = node id) satisfy it, so the same assertions work over either harness.