verificationtest

package
v0.1.0 Latest Latest
Warning

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

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

README

verificationtest

The conformance suite for an auth.VerificationStore, the store single-use verification tokens live in (email and reset links, magic links, OAuth state, passkey ceremonies). A custom store proves itself with one call instead of finding out in production that a reset link worked twice.

func TestMyStore(t *testing.T) {
	verificationtest.Run(t, func(t *testing.T) auth.VerificationStore {
		return mystore.New(freshKeyspace(t))
	})
}

open is called once per case, so each case must start empty: a store on a shared server returns a store with a fresh key prefix, and a store on the shared auth_verification table deletes the rows of verificationtest.PurposeA and PurposeB first (the cases reuse token hashes, which the table keeps unique).

The rules it checks: Consume returns what Insert saved, once; a wrong purpose is refused and spends nothing; a token at or after its expiry is refused; Racers concurrent Consume calls on one token spend it exactly once; ConsumeAll ends one purpose for one identifier and no other, and not a token issued after it; DeleteIdentifiers ends every purpose of the identifiers it names; Sweep never removes a live token; and a store that promises exclusive inserts (auth.ExclusiveVerificationStore reporting true) refuses a duplicate hash with auth.ErrTokenExists, and of Racers concurrent inserts of one hash stores exactly one. The suite's own tests run each rule against a store that breaks it, so every case is seen to fail.

The core's SQL store (on SQLite, Postgres and MySQL in integration/), auth.NewMemoryVerificationStore, auth.NewStorageVerificationStore and contrib/redis NewVerificationStore all run it. It imports only the standard library and the core.

Documentation

Overview

Package verificationtest checks a VerificationStore against the contract every verification store must keep, so a custom store proves itself with one call rather than by finding out in production that a reset link worked twice. The core's SQL and memory stores and contrib/redis run it.

It imports only the standard library and the core, so a store's own tests can use it whatever else they depend on.

Index

Constants

View Source
const (
	PurposeA auth.Purpose = "verificationtest_a"
	PurposeB auth.Purpose = "verificationtest_b"
)

PurposeA and PurposeB are the purposes every case files its tokens under, exported so a store on a shared table can clear them before each case (the cases reuse token hashes, which the SQL table keeps unique).

View Source
const Racers = 8

Racers is how many goroutines spend one token at once in the single-use case: enough to interleave on any store, few enough for SQLite's single writer.

Variables

This section is empty.

Functions

func Run

func Run(t *testing.T, open func(t *testing.T) auth.VerificationStore)

Run checks the store that open returns. open is called once per case, so every case starts empty; a store backed by a shared server should return a store with a fresh key prefix or a cleared keyspace each time.

Types

type T

type T interface {
	Fatal(args ...any)
	Fatalf(format string, args ...any)
}

T is the part of testing.T a case uses. An interface so the suite's own tests can run a case against a store that breaks a rule and read the failure, which is how the suite proves it would catch that rule.

Jump to

Keyboard shortcuts

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