commentstest

package
v0.0.0-...-f467036 Latest Latest
Warning

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

Go to latest
Published: Oct 11, 2026 License: AGPL-3.0 Imports: 9 Imported by: 0

Documentation

Overview

Package commentstest is the conformance suite every comments.Store implementation must pass.

It exists because the parts of the contract most likely to diverge between backends are the ones nobody notices: List's ordering, whether a returned slice aliases stored state, and whether two concurrent Adds both survive. A backend that gets those subtly wrong still passes a hand-written smoke test and then behaves differently in production from the one the tests ran against.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func RunAll

func RunAll(t *testing.T, f Factory)

RunAll runs every conformance suite against f.

func RunConcurrencyTests

func RunConcurrencyTests(t *testing.T, f Factory)

RunConcurrencyTests pins that concurrent writes to one target do not lose updates.

This is the read-modify-write hazard: a backend that reads a thread, appends, and writes it back without serializing will drop comments under load — and will pass every sequential test.

func RunCountTests

func RunCountTests(t *testing.T, f Factory)

RunCountTests pins the batched thread size (TKT-WA25G2).

Count is a third read path onto the rows List serves, so it must agree with List on the key: per face, resolved comments included, and absent rather than zero for an empty thread.

func RunDeleteTests

func RunDeleteTests(t *testing.T, f Factory)

RunDeleteTests pins deletion.

func RunEmptyTests

func RunEmptyTests(t *testing.T, f Factory)

RunEmptyTests pins the empty-target contract.

func RunFaceTests

func RunFaceTests(t *testing.T, f Factory)

RunFaceTests pins the per-face contract (FEAT-9CD2MX).

Comments are scoped to a content state: a remark on the draft is not a remark on the published version, and the read gate is per face too. The key is entity.FormatStateRef, so the DEFAULT face keeps the bare id — which is what lets faces arrive without migrating a single stored comment.

func RunGetTests

func RunGetTests(t *testing.T, f Factory)

RunGetTests pins the single-comment read (TKT-4LG36M).

Get exists so the database backends can serve an authorization check from their primary key instead of reading a whole thread. That makes it a SECOND read path onto the same rows, and a second path is exactly where backends drift: the risk is not that Get fails outright but that it disagrees with List in some corner — a different zone on a timestamp, a face it resolves through that List would not.

func RunIsolationTests

func RunIsolationTests(t *testing.T, f Factory)

RunIsolationTests pins that targets do not bleed into each other.

func RunKeyFidelityTests

func RunKeyFidelityTests(t *testing.T, f Factory)

RunKeyFidelityTests pins that a backend treats an entity id as EXACT BYTES: case is significant, and a multi-byte id re-keys correctly.

Separate from RunAll because neither is a contract every backend can honor. filecomments keys on a filename, so on a case-insensitive filesystem (macOS, Windows) "TKT-1@draft.yaml" and "tkt-1@draft.yaml" ARE one file, and it refuses a non-ASCII id outright rather than build an unsafe path. Those are sound decisions for a file backend, not defects — but they mean the guarantee below can only be asked of the database backends.

For those two it is a real hazard rather than a hypothetical. SQLite's LIKE is ASCII case-INSENSITIVE by default while "=" is byte-exact, so the two arms of one query silently match different row sets — and a different set again from PostgreSQL's COLLATE "C". Separately, both compute the moved key with SQL's substring()/substr(), which count CHARACTERS where Go's len() counts BYTES; slicing at the wrong offset re-keys a thread to a corrupt target and returns nil.

Whether two ids differing only by case can coexist at all, and whether an id may hold a multi-byte rune, are questions for the store and for entity.ValidateID — answered elsewhere, by invariants these packages deliberately do not import. This fixes the answer the BACKENDS give, so it holds however those questions are later answered.

func RunOrderingTests

func RunOrderingTests(t *testing.T, f Factory)

RunOrderingTests pins the ordering contract: oldest first, ID breaking ties.

func RunRenameTests

func RunRenameTests(t *testing.T, f Factory)

RunRenameTests pins the re-key path.

This is the behavior that keeps comments reachable across an entity rename: the store emits exactly one rename callback, so if this is wrong the comments remain on disk under an ID nothing resolves to.

func RunRoundTripTests

func RunRoundTripTests(t *testing.T, f Factory)

RunRoundTripTests pins that every field survives storage unchanged.

func RunUpdateTests

func RunUpdateTests(t *testing.T, f Factory)

RunUpdateTests pins which fields an update may change.

Types

type Factory

type Factory func(t *testing.T) comments.Store

Factory builds a fresh, empty store for one subtest.

Jump to

Keyboard shortcuts

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