parsectest

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jun 5, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package parsectest provides test helpers for code that embeds or integrates against the parsec library. The shape mirrors net/http's httptest: one-call constructors that return a ready instance, with teardown registered through testing.TB.Cleanup.

Typical use:

func TestMyPublisher(t *testing.T) {
    p := parsectest.New(t)
    ch, err := p.OpenPublic("public:webapp.system.status", time.Minute)
    // ... exercise your code against p ...
}

NewServer additionally mounts the parsec HTTP surface on a *httptest.Server so tests can hit the websocket / Twirp / manifest endpoints over real HTTP:

func TestMyClient(t *testing.T) {
    inst := parsectest.NewServer(t)
    bearer := inst.MintMgmt(t, "ops", time.Hour)
    // ... point a Twirp client at inst.BaseURL with bearer ...
}

NewWithRedis spins up an in-process miniredis and wires the broker, channel registry, keyring, DLQ, and rate limiter to it — useful for exercising the multi-node code paths without a real Redis container.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Instance

type Instance struct {
	*parsec.Parsec

	// Service is the surface-agnostic business layer. RPC handlers,
	// admin endpoints, and CLI adapters all sit on top of it. Useful
	// when test code wants to call into the same logic the HTTP layer
	// would invoke.
	Service *service.Service

	// Server is the *httptest.Server hosting the parsec HTTP surface
	// (Twirp + websocket + manifest + healthz). Non-nil only when the
	// instance was built via NewServer.
	Server *httptest.Server

	// BaseURL is Server.URL (no trailing slash). Empty when Server is nil.
	BaseURL string
	// contains filtered or unexported fields
}

Instance is a running *parsec.Parsec bound to test lifetime. The embedded pointer exposes the full library API. Server + BaseURL are populated only when the instance was constructed via NewServer.

func New

func New(t testing.TB, opts ...Option) *Instance

New constructs a *parsec.Parsec with ephemeral state and in-memory everything, starts Run in a goroutine, and registers cleanup via t.Cleanup. The returned Instance does not expose an HTTP server — use NewServer for that.

func NewServer

func NewServer(t testing.TB, opts ...Option) *Instance

NewServer constructs an Instance and additionally mounts the parsec HTTP surface on a *httptest.Server. Bearer middleware is wired through the parsec verifier — mint a mgmt bearer with i.MintMgmt before calling any management endpoint.

func NewServerWithRedis

func NewServerWithRedis(t testing.TB, opts ...Option) *Instance

NewServerWithRedis is NewWithRedis composed with NewServer — the returned Instance has both the *httptest.Server and the miniredis backing.

func NewWithRedis

func NewWithRedis(t testing.TB, opts ...Option) *Instance

NewWithRedis returns an *Instance backed by an in-process miniredis. The miniredis instance is started, attached to parsec as both the go-redis client AND the broker RedisAddr (so the centrifuge Redis broker swap kicks in), and torn down on t.Cleanup.

Use this when a test needs to exercise the multi-node code paths (Redis broker, Redis channel registry, Redis-watched keyring, Redis DLQ, Redis rate limiter) without a docker container.

Note: miniredis implements the Redis wire protocol in Go but is not byte-identical to real Redis on every command. The vast majority of parsec code paths are covered; if a specific Lua script under test hits an edge miniredis does not emulate, point WithRedis at a real container instead.

func (*Instance) MintAccess

func (i *Instance) MintAccess(t testing.TB, subject, channel string, ttl time.Duration) string

MintAccess returns an access token authorizing subject to subscribe to channel. The channel must be one that the test has already CreatePrivate'd (or that the subject otherwise has scope for) — this helper does not auto-open channels.

ttl is clamped by the issuer's AccessTTL ceiling.

func (*Instance) MintMgmt

func (i *Instance) MintMgmt(t testing.TB, subject string, ttl time.Duration) string

MintMgmt returns a mgmt bearer for the named subject. ttl is clamped to [1h, 7d] by the issuer.

func (*Instance) MintPair

func (i *Instance) MintPair(t testing.TB, subject, channel string, ttl time.Duration) auth.PairResult

MintPair returns the full access + refresh credential pair for a subject + channel. Tests that exercise the refresh-token round-trip (e.g. integration tests against the public RefreshToken RPC) want both halves.

func (*Instance) MintRefresh

func (i *Instance) MintRefresh(t testing.TB, subject, channel string, ttl time.Duration) string

MintRefresh returns a refresh token for subject + channel.

type Option

type Option func(*config)

Option configures the Instance prior to construction.

func WithLogger

func WithLogger(l *slog.Logger) Option

WithLogger overrides the default discard logger. Useful when a test wants to see parsec's boot warnings.

func WithOptions

func WithOptions(fn func(*parsec.Options)) Option

WithOptions exposes the underlying parsec.Options for the corner cases where a test needs a setting parsectest does not surface directly. Returned closure receives a pointer to the options before parsec.New runs; mutate freely.

func WithRateLimits

func WithRateLimits(rl ratelimit.RateLimits) Option

WithRateLimits attaches per-bucket rate limits. Pass the zero value of a Limit to leave a bucket unlimited.

func WithRedis

func WithRedis(client redis.UniversalClient) Option

WithRedis attaches a pre-built go-redis client. The broker, registry, keyring, DLQ, and rate limiter all switch to the Redis backends. Use NewWithRedis for an automatic miniredis-backed setup.

func WithSink

func WithSink(s sinks.Sink) Option

WithSink registers a sink with the instance's sink registry before parsec.New wraps the registry in retry/DLQ. The sink's Name() must be unique within the registry.

func WithStateDir

func WithStateDir(dir string) Option

WithStateDir overrides the default t.TempDir() keyring location. Most tests should not need this — the default is already isolated.

Jump to

Keyboard shortcuts

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