sqltest

package
v0.4.1 Latest Latest
Warning

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

Go to latest
Published: Sep 24, 2026 License: Apache-2.0 Imports: 13 Imported by: 1

Documentation

Overview

Package sqltest is the scripted database/sql driver a consumer's hermetic tests run over: a connector whose connections consume scripted responses in call order and record every statement, prepare, and transaction call they receive. It supports prepare, so prepare-based verification has a harness, and it accepts any argument value unconverted, so tests see the exact Go values a runner bound. It is public because every consumer's unit tier runs over it, the library's own packages included.

It is strict where a real driver is, so a test cannot pass on a path production would reject: a statement with no response scripted for it fails (ErrUnscripted), an argument count that does not match the statement's $N placeholders fails (ErrArguments), and a scripted response that does not fit its call (rows for an exec, an affected count for a query, a row of the wrong width or containing a non-driver.Value) fails (ErrScript). The one leniency it keeps is the argument set: a real driver rejects a value it cannot encode, and this one records it.

Open returns the pool and its Recorder; Dialect is the stub dialect whose MapError wraps every error in a MappedError, so a test proves with one errors.As that an error passed through MapError. ReturningDialect adds the query.Returner capability to it, so a suite covers a returning command's single-statement form as well as its fallback. WithTotal scripts a collection page read under query.TotalExact, whose rows carry the total in a trailing column.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrUnscripted = errors.New("sqltest: unscripted call")
	ErrScript     = errors.New("sqltest: response does not fit the call")
	ErrArguments  = errors.New("sqltest: argument count does not match the placeholders")
)

The driver's own failures, each the counterpart of a failure a real driver or engine raises. A statement no response was scripted for is a statement the test did not expect to run; a response whose shape does not fit the call is a script defect. An argument count that does not match the statement's placeholders is what the engine rejects at bind time.

Functions

This section is empty.

Types

type Call

type Call struct {
	Op        Op
	SQL       string
	Args      []any
	TxOptions driver.TxOptions
}

Call is one recorded driver call. SQL and Args are set for exec, query, and prepare; TxOptions for begin.

type Dialect

type Dialect struct{}

Dialect is the stub dialect: $N placeholders and a MapError that wraps every non-nil error in a *MappedError, so a test proves an error crossed the mapping boundary with one errors.As.

func (Dialect) MapError

func (Dialect) MapError(err error) error

MapError wraps err in a *MappedError; nil stays nil. An already mapped error is returned as is, so double mapping is visible as absence of nesting rather than a crash.

func (Dialect) Name

func (Dialect) Name() string

func (Dialect) Placeholder

func (Dialect) Placeholder(n int) string

type MappedError

type MappedError struct{ Err error }

MappedError marks an error that passed through Dialect.MapError.

func (*MappedError) Error

func (e *MappedError) Error() string

func (*MappedError) Unwrap

func (e *MappedError) Unwrap() error

type Op

type Op string

Op names a recorded driver call.

const (
	OpExec     Op = "exec"
	OpQuery    Op = "query"
	OpPrepare  Op = "prepare"
	OpBegin    Op = "begin"
	OpCommit   Op = "commit"
	OpRollback Op = "rollback"
)

type Recorder

type Recorder struct {

	// FailPrepare, when set, decides whether a prepare of the given text
	// fails; nil means every prepare succeeds.
	FailPrepare func(query string) error
	// FailBegin, FailCommit, FailRollback, FailPing inject failures into the
	// transaction and ping calls.
	FailBegin, FailCommit, FailRollback, FailPing error
	// contains filtered or unexported fields
}

Recorder is the shared state behind every connection a connector hands out: the response queue, the call log, and the failure switches.

func Open

func Open(t testing.TB, responses ...Response) (*sql.DB, *Recorder)

Open returns a pool over a fresh Recorder, closed when the test ends.

func (*Recorder) Calls

func (r *Recorder) Calls() []Call

Calls returns a copy of the call log in order.

func (*Recorder) Ops

func (r *Recorder) Ops() []Op

Ops returns the sequence of operations recorded.

func (*Recorder) Pending

func (r *Recorder) Pending() int

Pending reports how many scripted responses remain unconsumed; a test asserts zero to prove every scripted call happened.

func (*Recorder) Queue

func (r *Recorder) Queue(responses ...Response)

Queue appends responses for later exec and query calls.

func (*Recorder) RowsLeaked

func (r *Recorder) RowsLeaked() int

RowsLeaked reports row sets opened and never closed.

func (*Recorder) SQL

func (r *Recorder) SQL(op Op) []string

SQL returns the statement texts recorded for op, in order.

type Response

type Response struct {
	Err      error
	Affected int64
	Columns  []string
	Rows     [][]driver.Value
}

Response scripts the outcome of the next exec or query call: an error, or the affected count (exec) or the columns and rows (query). An exec response has no columns or rows and a query response no affected count; every row is as wide as Columns and contains driver.Value types only, as a real driver returns them. Prepare, begin, commit, and rollback do not consume responses; their failures are set on the Recorder directly.

func WithTotal added in v0.4.0

func WithTotal(r Response, n int64) Response

WithTotal returns r as a counted collection page returns it: with a trailing count column holding n in every row, from which a query.Projection reads its exact total and which it hides from the scan. A unit suite uses it to script a List or Continue under query.TotalExact without spelling the library's reserved column name. WithTotal leaves r unchanged. An empty r still gains the column, as an empty counted page declares it.

type ReturningDialect added in v0.3.0

type ReturningDialect struct{ Dialect }

ReturningDialect is the stub dialect with the query.Returner capability: it appends "RETURNING <columns>" to an INSERT or UPDATE, as an engine with the clause renders it, and declines any other verb. It lets a consumer's unit suite cover a returning command's single-statement form, where Dialect covers the fallback.

func (ReturningDialect) Returning added in v0.3.0

func (ReturningDialect) Returning(verb query.Verb, body string, columns []string) (string, bool)

Returning appends the RETURNING clause to body for query.Insert and query.Update and declines every other verb.

Jump to

Keyboard shortcuts

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