QuiltedConformanceSuite

abstract class QuiltedConformanceSuite<S : Quilted<S>>

Reusable contract test suite for Quilted (delta-state CRDT) implementations.

Subclass and implement samples to bind any type under test; every Test encodes a law a conforming join-semilattice must satisfy. Lives in commonMain of :kuilt-conformance (not a module's commonTest) so every CRDT type can subclass it from its own test source set.

class GCounterConformanceTest : QuiltedConformanceSuite<GCounter>() {
override fun samples(): List<GCounter> = listOf(/* representative values */)
}

samples must return at least three distinct values for the associativity and absorption checks to be meaningful; more variety is better. That floor is checked — by samplesMeetTheEvidenceFloor, since #2312. It spent a long time documented and unenforced, which is the shape a precondition takes when every binding written so far happens to satisfy it. The type's equals must reflect lattice equality — the laws are checked with ==, and so is the floor.

A type that can retire additionally sets retirementIsMeaningful and names the assert/retire/re-assert shape, plus the subject predicate that makes the retirement observable, in retirementReAssertion; see samplesReAssertAfterRetirement for why that shape is the one a hand-picked list keeps missing, and why naming the three states alone did not pin it. What counts as retiring is defined once, in us.tractat.kuilt.conformance.lattice.OpKind — including the reading this surface is licensed to take that the lattice bindings are not.

Constructors

Link copied to clipboard
constructor()

Properties

Link copied to clipboard

Whether this type can retire — stop showing something it once showed, while still only moving up the lattice.

Functions

Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard

Three of this binding's samples, in causal order, spelling out the shape a retiring type is easiest to get wrong on: one that asserts something, a later one that retires it, and a later one still that re-asserts it — together with the predicate that reads that "something" off the binding's public value surface.

Link copied to clipboard
abstract fun samples(): List<S>

Representative, distinct sample values — at least DISTINCT_SAMPLE_FLOOR of them, distinct by ==, enforced by samplesMeetTheEvidenceFloor.

Link copied to clipboard

The four laws below were handed enough evidence to have tested anything: at least DISTINCT_SAMPLE_FLOOR pairwise-distinct samples.

Link copied to clipboard

A binding that can retire must keep a sample that re-asserts what an earlier sample retired — assert, retire, assert again.