drivertest

package
v0.10.1 Latest Latest
Warning

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

Go to latest
Published: Oct 29, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Overview

Package drivertest is the conformance suite every hopper driver must pass.

A driver's tests call Run with a Fixture that hands out isolated, migrated databases and implements the few engine-specific hooks the suite needs to set up situations (an expired lease, a stuck job) that no queue operation produces on its own.

func TestConformance(t *testing.T) {
	drivertest.Run(t, pgxFixture{})
}

The suite covers inserting (including unique keys and replace), claiming (order, ownership, expiry, SKIP LOCKED), every finalize transition and its fencing to the claim (also inside a caller's transaction), snooze reasons, leases, claims by ID and their job leases, leader election, rescue candidates, cancel, retry, TTL expiry, listing, queues, periodic slots, stats, notifications and history maintenance. What depends on whether the engine locks rows or runs one writer at a time (driver.Capabilities.SingleWriter) is tested either way. Engine-specific behavior, such as how partitions are managed, belongs in the driver's own tests; RunPostgres has the tests of what hopper's Postgres drivers share.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ReattachRevalidates added in v0.8.0

func ReattachRevalidates(exec func(query string), queryText func(query string) string) bool

ReattachRevalidates reports whether attaching a partition's index again marks its parent valid, as Postgres does from the May 2026 releases (18.4, 17.10, 16.14, 15.18, 14.23) on, which decides whether HistoryIndex can repair an outcome table's index or reports it in HistoryIndexResult.Invalid. It runs the driver's own probe: the parent's index left invalid by dropping the one partition without an index, then attached again. exec runs a statement and queryText returns the single text value a query selects, both on a Postgres database a test owns.

func Run

func Run[TTx any](t *testing.T, f Fixture[TTx])

Run runs the suite.

func RunPostgres added in v0.8.0

func RunPostgres[TTx any](t *testing.T, f PostgresFixture[TTx])

RunPostgres runs the tests of what hopper's Postgres drivers share, which a Postgres driver passes besides Run's.

Types

type Fixture

type Fixture[TTx any] interface {
	// NewDriver returns a driver on a fresh database with hopper's schema
	// installed, torn down when the test ends.
	NewDriver(t *testing.T) driver.Driver[TTx]
	// Begin starts a transaction. The suite calls commit or rollback.
	Begin(ctx context.Context, t *testing.T, d driver.Driver[TTx]) (tx TTx, commit, rollback func() error)
	// ExpireLease makes a client's lease expired, as a partition or a long
	// pause would.
	ExpireLease(ctx context.Context, t *testing.T, d driver.Driver[TTx], clientID int64)
	// ExpireLeader makes the leader lease expired.
	ExpireLeader(ctx context.Context, t *testing.T, d driver.Driver[TTx])
	// MakeClaimable moves a job's scheduled time to now.
	MakeClaimable(ctx context.Context, t *testing.T, d driver.Driver[TTx], id driver.JobID)
	// AgeAttempt backdates a running job's attempted time by age.
	AgeAttempt(ctx context.Context, t *testing.T, d driver.Driver[TTx], id driver.JobID, age time.Duration)
	// ExpireJobLease makes the job lease of a job claimed by ID expired, as
	// a worker that stopped renewing it would. CountJobLeases counts the job
	// lease rows the engine keeps.
	ExpireJobLease(ctx context.Context, t *testing.T, d driver.Driver[TTx], id driver.JobID)
	CountJobLeases(ctx context.Context, t *testing.T, d driver.Driver[TTx]) int
	// AgeClientStart backdates a client's start by age; a negative age
	// moves it ahead.
	AgeClientStart(ctx context.Context, t *testing.T, d driver.Driver[TTx], clientID int64, age time.Duration)
	// CountLive and CountHistory count jobs in the live table and in history.
	CountLive(ctx context.Context, t *testing.T, d driver.Driver[TTx]) int
	CountHistory(ctx context.Context, t *testing.T, d driver.Driver[TTx]) int
	// ExpireJob moves a live job's TTL deadline a second into the past.
	ExpireJob(ctx context.Context, t *testing.T, d driver.Driver[TTx], id driver.JobID)
	// StaleWake marks a running job as woken by JobRetryOrderingKey a second
	// before its attempt began, as a wake during an earlier attempt would.
	StaleWake(ctx context.Context, t *testing.T, d driver.Driver[TTx], id driver.JobID)
	// MakePending puts a live job back in the pending state, as a client
	// that stopped before promoting it would leave it.
	MakePending(ctx context.Context, t *testing.T, d driver.Driver[TTx], id driver.JobID)
	// SnoozeReason reads a live job's stored snooze reason, or "" for none,
	// which the driver's reads show only for a scheduled job. The suite
	// calls it from any goroutine. SetSnoozeReason stores one, as a client
	// of an earlier release, which cleared it neither on claim nor on
	// finalize, can leave it on a job that is not snoozed.
	SnoozeReason(ctx context.Context, t *testing.T, d driver.Driver[TTx], id driver.JobID) string
	SetSnoozeReason(ctx context.Context, t *testing.T, d driver.Driver[TTx], id driver.JobID, reason string)
	// SetProgress stores a JSON value as a live job's progress as it is, as
	// a direct SQL write could.
	SetProgress(ctx context.Context, t *testing.T, d driver.Driver[TTx], id driver.JobID, value string)
	// CountEdges counts the dependency edges the engine keeps for workflow
	// jobs that have not finished.
	CountEdges(ctx context.Context, t *testing.T, d driver.Driver[TTx]) int
	// CountJobResults counts the dependency results the engine keeps for
	// workflow steps' claims. DeleteJobResult deletes a job's, as a job
	// finished before the engine recorded them has none. OrphanJobResult
	// copies a job's to a workflow that does not exist, as a client of an
	// earlier release, completing a workflow, leaves one.
	CountJobResults(ctx context.Context, t *testing.T, d driver.Driver[TTx]) int
	DeleteJobResult(ctx context.Context, t *testing.T, d driver.Driver[TTx], id driver.JobID)
	OrphanJobResult(ctx context.Context, t *testing.T, d driver.Driver[TTx], id driver.JobID)
	// WaitForLockWait waits until a statement on the driver's database
	// waits for a lock another transaction holds, so that a test knows its
	// competing statement is blocked rather than not yet started.
	WaitForLockWait(ctx context.Context, t *testing.T, d driver.Driver[TTx])
}

Fixture gives the suite a database per test and the hooks it needs. The hooks report a failure with t.Error rather than t.Fatal when the suite may call them from another goroutine, as SnoozeReason says.

type Postgres added in v0.8.0

type Postgres[TTx any] struct {
	// SQL runs statements on a driver's database, as PostgresFixture's Exec
	// and QueryText describe.
	SQL interface {
		Exec(ctx context.Context, t *testing.T, d driver.Driver[TTx], query string, args ...any)
		QueryText(ctx context.Context, t *testing.T, d driver.Driver[TTx], query string, args ...any) string
	}
}

Postgres implements a PostgresFixture's hooks that are statements on hopper's Postgres schema, for the fixtures of hopper's Postgres drivers to embed, which then implement only NewDriver, Begin and SQL.

func (Postgres[TTx]) AgeAttempt added in v0.8.0

func (p Postgres[TTx]) AgeAttempt(ctx context.Context, t *testing.T, d driver.Driver[TTx], id driver.JobID, age time.Duration)

AgeAttempt implements Fixture.

func (Postgres[TTx]) AgeClientStart added in v0.9.0

func (p Postgres[TTx]) AgeClientStart(ctx context.Context, t *testing.T, d driver.Driver[TTx], clientID int64, age time.Duration)

AgeClientStart implements Fixture.

func (Postgres[TTx]) CountEdges added in v0.8.0

func (p Postgres[TTx]) CountEdges(ctx context.Context, t *testing.T, d driver.Driver[TTx]) int

CountEdges implements Fixture.

func (Postgres[TTx]) CountHistory added in v0.8.0

func (p Postgres[TTx]) CountHistory(ctx context.Context, t *testing.T, d driver.Driver[TTx]) int

CountHistory implements Fixture.

func (Postgres[TTx]) CountJobLeases added in v0.9.0

func (p Postgres[TTx]) CountJobLeases(ctx context.Context, t *testing.T, d driver.Driver[TTx]) int

CountJobLeases implements Fixture.

func (Postgres[TTx]) CountJobResults added in v0.10.0

func (p Postgres[TTx]) CountJobResults(ctx context.Context, t *testing.T, d driver.Driver[TTx]) int

CountJobResults implements Fixture.

func (Postgres[TTx]) CountLive added in v0.8.0

func (p Postgres[TTx]) CountLive(ctx context.Context, t *testing.T, d driver.Driver[TTx]) int

CountLive implements Fixture.

func (Postgres[TTx]) DeleteJobResult added in v0.10.0

func (p Postgres[TTx]) DeleteJobResult(ctx context.Context, t *testing.T, d driver.Driver[TTx], id driver.JobID)

DeleteJobResult implements Fixture.

func (Postgres[TTx]) Exec added in v0.8.0

func (p Postgres[TTx]) Exec(ctx context.Context, t *testing.T, d driver.Driver[TTx], query string, args ...any)

Exec implements PostgresFixture.

func (Postgres[TTx]) ExpireJob added in v0.8.0

func (p Postgres[TTx]) ExpireJob(ctx context.Context, t *testing.T, d driver.Driver[TTx], id driver.JobID)

ExpireJob implements Fixture.

func (Postgres[TTx]) ExpireJobLease added in v0.9.0

func (p Postgres[TTx]) ExpireJobLease(ctx context.Context, t *testing.T, d driver.Driver[TTx], id driver.JobID)

ExpireJobLease implements Fixture.

func (Postgres[TTx]) ExpireLeader added in v0.8.0

func (p Postgres[TTx]) ExpireLeader(ctx context.Context, t *testing.T, d driver.Driver[TTx])

ExpireLeader implements Fixture.

func (Postgres[TTx]) ExpireLease added in v0.8.0

func (p Postgres[TTx]) ExpireLease(ctx context.Context, t *testing.T, d driver.Driver[TTx], clientID int64)

ExpireLease implements Fixture.

func (Postgres[TTx]) MakeClaimable added in v0.8.0

func (p Postgres[TTx]) MakeClaimable(ctx context.Context, t *testing.T, d driver.Driver[TTx], id driver.JobID)

MakeClaimable implements Fixture.

func (Postgres[TTx]) MakePending added in v0.8.0

func (p Postgres[TTx]) MakePending(ctx context.Context, t *testing.T, d driver.Driver[TTx], id driver.JobID)

MakePending implements Fixture.

func (Postgres[TTx]) OrphanJobResult added in v0.10.0

func (p Postgres[TTx]) OrphanJobResult(ctx context.Context, t *testing.T, d driver.Driver[TTx], id driver.JobID)

OrphanJobResult implements Fixture.

func (Postgres[TTx]) QueryText added in v0.8.0

func (p Postgres[TTx]) QueryText(ctx context.Context, t *testing.T, d driver.Driver[TTx], query string, args ...any) string

QueryText implements PostgresFixture.

func (Postgres[TTx]) SetProgress added in v0.8.0

func (p Postgres[TTx]) SetProgress(ctx context.Context, t *testing.T, d driver.Driver[TTx], id driver.JobID, value string)

SetProgress implements Fixture.

func (Postgres[TTx]) SetSnoozeReason added in v0.8.0

func (p Postgres[TTx]) SetSnoozeReason(ctx context.Context, t *testing.T, d driver.Driver[TTx], id driver.JobID, reason string)

SetSnoozeReason implements Fixture.

func (Postgres[TTx]) SnoozeReason added in v0.8.0

func (p Postgres[TTx]) SnoozeReason(ctx context.Context, t *testing.T, d driver.Driver[TTx], id driver.JobID) string

SnoozeReason implements Fixture.

func (Postgres[TTx]) StaleWake added in v0.8.0

func (p Postgres[TTx]) StaleWake(ctx context.Context, t *testing.T, d driver.Driver[TTx], id driver.JobID)

StaleWake implements Fixture.

func (Postgres[TTx]) WaitForLockWait added in v0.8.0

func (p Postgres[TTx]) WaitForLockWait(ctx context.Context, t *testing.T, d driver.Driver[TTx])

WaitForLockWait implements Fixture: a statement on the driver's schema, whose name is in every statement's text, waits for a lock.

type PostgresFixture added in v0.8.0

type PostgresFixture[TTx any] interface {
	Fixture[TTx]
	// Exec runs a SQL statement with hopper's tables on the search path, for
	// rows the suite writes directly, such as those a client of the previous
	// release leaves behind. QueryText returns the single text value a query
	// selects, for what the driver's reads do not show. Both report a
	// failure with t.Error rather than t.Fatal, so the suite may call them
	// from any goroutine.
	Exec(ctx context.Context, t *testing.T, d driver.Driver[TTx], query string, args ...any)
	QueryText(ctx context.Context, t *testing.T, d driver.Driver[TTx], query string, args ...any) string
}

PostgresFixture is the Fixture of one of hopper's Postgres drivers, which can also run SQL on hopper's schema. RunPostgres runs, with it, the tests of what those drivers share beyond the driver interface: history's partitions and their indexes, the tags tables and their triggers, the rows clients of earlier releases leave, and the planner statistics the leader keeps.

Jump to

Keyboard shortcuts

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