Documentation
¶
Overview ¶
Package coverage attributes a test to the features it covers, beyond the one its name already claims.
Attribution is by test name first, and that is deliberate: a test called TestSinkClickhouse_InsertsRows costs nothing to attribute and says what it covers to anyone reading it. One test per feature stays the goal.
Some tests genuinely cover several features at once. An end-to-end run reads a Kafka source, drives a handler, writes a sink and commits state -- naming it for one of those and calling the rest uncovered produces false gaps, and a gate that cries wolf gets ignored. Covers records the others.
Reach for it only when a test really does prove several features. If a feature needs a marker to be covered at all, it wants its own test.
Index ¶
- func Covers(t testing.TB, features ...string)
- func Exemptions(integration string) (map[string]bool, error)
- func FeatureFor(integration string) (string, bool, error)
- func Integrations(kind string) ([]string, error)
- func Invariant(t testing.TB, invariant, integration string)
- func Invariants() (map[string]bool, error)
- func IsTestOnly(integration string) (bool, error)
- type ColumnDecl
- type LatticeEntry
- type NullRule
- type TypeDecl
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Covers ¶
Covers records additional features this test proves.
The marker goes to the test log, which `go test -json` carries as output events, so the matrix reads it from ordinary suite output with no plugin and no build tag.
func Exemptions ¶ added in v1.1.0
Exemptions returns the invariants integrations.yml excuses one integration from, as a set.
func FeatureFor ¶ added in v1.1.0
FeatureFor returns the features.yml id an integration attributes to, and whether it has one.
An integration id is not a feature id. sink.noop attributes to sink.console, and a test_only integration attributes to nothing at all. Emitting the integration id as a feature marker put "marks sink.conformance_double" into the feature matrix's unknown list.
func Integrations ¶ added in v1.1.0
Integrations returns the bare type names integrations.yml declares for one kind, sorted.
"sink.clickhouse" is reported as "clickhouse", which is the form the constructor switches use, so a test in each of those packages can hold Kinds() equal to this. An integration the engine can build and the registry does not name has no invariant cells at all, which is the sink.iceberg failure: nothing written down, so nothing can be missing.
func Invariant ¶ added in v1.1.0
Invariant records that this test proved one invariant for one integration.
A feature attributes by test name. An invariant cannot: the conformance harness runs the same code for every integration, so the name says nothing about which one this run was. Only the marker knows, so it carries both ids.
func Invariants ¶ added in v1.1.0
Invariants returns every id invariants.yml declares, as a set.
The conformance harness judges invariants by id, and an id nothing declares reports as an unknown marker rather than as a cell -- the claim would be tested and invisible. A test in the harness holds every id it judges to this set.
func IsTestOnly ¶ added in v1.1.0
IsTestOnly reports whether integrations.yml marks an integration as existing only for tests.
The conformance harness's doubles must name an integration, because a marker carries one. Naming a real sink would credit that sink for what a double did. A test-only id gets no cells, so a double's marker lands nowhere.
Types ¶
type ColumnDecl ¶ added in v1.1.0
type ColumnDecl struct {
// Type is the destination column type, as its DDL spells it.
Type string `yaml:"type"`
// Value overrides the key's canonical value. Empty means the canonical
// one. Only the utf8 row may set it: text is the only thing a destination
// reparses, and a value declared for any other key would be ignored.
Value string `yaml:"value"`
// Expect is what the destination must hold afterwards, as ReadBack renders
// it. Declared rather than recorded from a run: a table copied from the
// sink compares the sink to itself.
Expect string `yaml:"expect"`
// Instant marks a pair the timestamp claim must exercise with the host
// clock moved off UTC. It is how a text value bound for a temporal column
// -- #153's shape, which no Arrow key describes -- reaches that verdict.
Instant bool `yaml:"instant"`
}
ColumnDecl is one destination column type, and what the integration claims about writing this Arrow key into it.
type LatticeEntry ¶ added in v1.1.0
type LatticeEntry struct {
// Key is conformance.CanonicalKey's output for the type, not
// DataType.String(): those differ, and only the canonical form matches
// both what DuckDB emits and what a test constructs.
Key string `yaml:"key"`
// DuckDB names the SQL types a user casts to in handler SQL. The rendered
// integration page is keyed by these, because a user writes a CAST and
// never sees an Arrow type.
DuckDB []string `yaml:"duckdb"`
// Depth is 1 for a scalar, 2 for a container.
Depth int `yaml:"depth"`
}
LatticeEntry is one Arrow type every sink must account for.
func Lattice ¶ added in v1.1.0
func Lattice() ([]LatticeEntry, error)
Lattice returns every Arrow type lattice.yml declares, in file order.
The set is closed, which is what makes a gap visible: a type an integration does not declare is reported rather than absent. An open set lets a type nobody thought of pass unnoticed, which is the sink.iceberg failure -- nothing written down, so nothing could be missing.
type NullRule ¶ added in v1.1.0
NullRule is what an integration does with a null, when the destination column does not say otherwise.
It is separate from TypeDecl because it is one statement about every type rather than one per type: ClickHouse stores a null in a non-Nullable column as the column type's zero value whatever that type is.
func NullElementsFor ¶ added in v1.1.0
NullElementsFor returns an integration's rule for a null held inside a non-null list.
Separate from NullsFor because the answers differ: a ClickHouse column can be Nullable and its Array(T) elements cannot, so the column-level rule says nothing about what a list holds.
type TypeDecl ¶ added in v1.1.0
type TypeDecl struct {
// Key is the lattice.yml key. It is the mapping key in the YAML, so
// TypesFor fills it in rather than the parser.
Key string `yaml:"-"`
// Outcome is exact, coerced or unsupported.
Outcome string `yaml:"outcome"`
// Rule states a coercion in prose, for the rendered page. Required when
// Outcome is coerced: a coercion with no rule is an excuse, and a reader
// cannot predict what their column will hold.
Rule string `yaml:"rule"`
// Code is the errs code an unsupported type must fail with.
Code string `yaml:"code"`
// Columns are the destination column types that accept this key, each
// carrying what to write and what must come back. Every one is exercised,
// and the cell is covered only when all of them pass.
//
// The pair is the unit rather than the key. One Arrow key reaches several
// destinations that demand different content -- DuckDB's VARCHAR is the
// universal text carrier, and ClickHouse reparses text into UUID, Decimal
// and Enum -- so the value belongs here.
Columns []ColumnDecl `yaml:"columns"`
}
TypeDecl is one integration's declared outcome for one Arrow type.