conformance

package
v0.0.3 Latest Latest
Warning

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

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

Documentation

Overview

Package conformance is fabriq's cross-port conformance kit: one exported Case table per capability port, run against BOTH the in-memory fabriqtest fakes and the real adapters, so the fakes cannot silently drift from Postgres / FalkorDB / Elasticsearch truth.

The defining property is "drift becomes a failing test": if the fake's List ordering changes, or a real adapter's filter semantics diverge from the fake's, a conformance subtest goes red — at go-test speed for the fakes, under the integration build tag for the adapters.

Deliberate fake-vs-real divergences (the fake serializes transactions, stores raw time-series points only, has no relevance scorer, …) are encoded as Capability requirements on individual cases and gated through skip-or-assert-degraded logic. Every capability is justified in the reviewed ledger (ledger.go); introducing a new divergence is mechanically forced through a ledger edit.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func RunAll

func RunAll(t *testing.T, b Backend)

RunAll runs every applicable port suite against b. Ports the backend does not implement (nil Env field) are skipped wholesale. Each port is probed before calling its suite so one unimplemented port does not halt the others via a suite-level t.Skip. Follow-on plans add RunGraph, RunSearch, RunSpatial, RunTimeseries, RunCommandStore and RunProjectionState here.

func RunBlob

func RunBlob(t *testing.T, b Backend)

RunBlob drives a backend through the byte-plane case table. Backends that do not wire Env.Blob are skipped; capability-gated cases skip when the backend lacks the capability.

func RunRelational

func RunRelational(t *testing.T, b Backend)

RunRelational runs the relational conformance suite against b. It skips the whole suite when the backend does not implement the relational port, and gates each capability-requiring case via skip-or-assert-degrade.

func RunVector added in v0.0.3

func RunVector(t *testing.T, b Backend)

RunVector exercises the VectorQuerier port: upsert/similar ordering, get hit/miss, point delete, metadata-filtered similar, and delete-by-meta. Skipped when the backend does not implement the vector port.

Types

type Backend

type Backend interface {
	// Name identifies the backend in subtest names and skip reasons, e.g.
	// "fake", "postgres", "falkordb", "elasticsearch".
	Name() string

	// Capabilities are the behaviors this backend supports exactly.
	Capabilities() CapabilitySet

	// Setup returns a fresh, isolated environment for ONE case. The backend
	// registers its own t.Cleanup. Isolation is by unique tenant; no
	// truncation is required.
	Setup(t *testing.T) *Env
}

Backend is one system-under-test: the fakes, or a real adapter set over a container. The conformance runner drives it through the shared Case tables.

type BlobCase

type BlobCase struct {
	Name     string
	Requires []Capability
	Run      func(t *testing.T, env *Env)
}

BlobCase is one byte-plane behavior, run identically against every backend that wires Env.Blob. Capability-gated cases skip when Requires is unmet.

func BlobCases

func BlobCases() []BlobCase

BlobCases is the shared byte-plane case table.

type Capability

type Capability string

Capability names a behavior a backend either supports exactly or legitimately diverges on. Cases that Require a capability the system-under-test lacks are skipped or asserted-degraded.

const (
	// CapConcurrentTx: real optimistic-concurrency version conflicts (the
	// fake serializes transactions one at a time).
	CapConcurrentTx Capability = "concurrent-tx"
	// CapBucketedAgg: TimescaleDB time_bucket aggregation (the fake stores
	// raw points only).
	CapBucketedAgg Capability = "ts-bucketed-agg"
	// CapRelevanceScore: real full-text relevance ranking (the fake returns
	// id-order, having no scorer).
	CapRelevanceScore Capability = "search-relevance"
	// CapRawSQL: the relational raw-SQL escape hatch (the fake has no SQL
	// engine).
	CapRawSQL Capability = "raw-sql"
	// CapRawCypher: uncanned openCypher (the fake serves canned responses).
	CapRawCypher Capability = "raw-cypher"
	// CapPersistence: survives a reopen (the fakes are in-memory).
	CapPersistence Capability = "cross-restart"
	// CapBlobPresign: the byte store issues presigned client-direct URLs.
	CapBlobPresign Capability = "blob-presign"
	// CapBlobMultipart: the byte store supports resumable multipart uploads.
	CapBlobMultipart Capability = "blob-multipart"
	// CapBlobRange: the byte store supports byte-range reads.
	CapBlobRange Capability = "blob-range"
)

type CapabilitySet

type CapabilitySet map[Capability]bool

CapabilitySet is the set of capabilities a backend supports exactly.

func (CapabilitySet) Has

func (c CapabilitySet) Has(want Capability) bool

Has reports whether the set contains want.

type Degradation

type Degradation struct {
	// ExpectErrIs requires errors.Is(err, ExpectErrIs).
	ExpectErrIs error
	// ExpectErrContains requires the error message to contain this substring.
	ExpectErrContains string
}

Degradation describes what a backend lacking a case's required capability must return INSTEAD of the happy-path result. Set one of the two fields.

type Env

type Env struct {
	Ctx         context.Context         // unique primary tenant for this case
	ForeignCtx  context.Context         // a second, distinct tenant over the same store
	Registry    *registry.Registry      // domain.RegisterAll(reg)
	Exec        *command.Executor       // write path; nil → command/store suite skips
	Relational  query.RelationalQuerier // nil → relational suite skips
	Graph       query.GraphQuerier
	Search      query.SearchQuerier
	Vector      query.VectorQuerier
	Spatial     query.SpatialQuerier
	TS          query.TSQuerier
	Projection  projection.StateReader
	Blob        blob.Store // nil → blob suite skips
	GraphTarget string     // fresh graph/projection target for this case
	// EmbeddingDim is the dimension required by the vector store.
	// 0 means "no fixed dimension" (the fake accepts any size; RunVector uses
	// 3-dimensional test vectors). Set to 768 for the postgres backend, which
	// enforces the schema-declared vector(768) column.
	EmbeddingDim int
}

Env is one isolated case environment. A nil port field means "not implemented by this backend" — that port's whole suite is skipped.

type RelationalCase

type RelationalCase struct {
	Name     string
	Requires []Capability // capabilities the happy path needs
	Degrade  *Degradation // when a Required capability is absent, assert this instead of skipping
	Seed     []SeedAsset
	// Run executes the read under test. ids maps SeedAsset.Name -> minted id.
	Run       func(env *Env, ids map[string]string) ([]*domain.Asset, error)
	WantNames []string // expected asset Names, in order
}

RelationalCase is one conformance scenario for query.RelationalQuerier.

func RelationalCases

func RelationalCases() []RelationalCase

RelationalCases is the canonical relational conformance table. Universal cases (no Requires) must pass on EVERY backend; capability-gated cases run where supported and skip/assert-degrade elsewhere.

type SeedAsset

type SeedAsset struct {
	Name, Kind, Serial, SiteID string
}

SeedAsset is one asset to create before a relational case runs. Ids are minted by the command path; cases address rows by Name.

Jump to

Keyboard shortcuts

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