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 ¶
- func RunAll(t *testing.T, f Factory)
- func RunConcurrencyTests(t *testing.T, f Factory)
- func RunCountTests(t *testing.T, f Factory)
- func RunDeleteTests(t *testing.T, f Factory)
- func RunEmptyTests(t *testing.T, f Factory)
- func RunFaceTests(t *testing.T, f Factory)
- func RunGetTests(t *testing.T, f Factory)
- func RunIsolationTests(t *testing.T, f Factory)
- func RunKeyFidelityTests(t *testing.T, f Factory)
- func RunOrderingTests(t *testing.T, f Factory)
- func RunRenameTests(t *testing.T, f Factory)
- func RunRoundTripTests(t *testing.T, f Factory)
- func RunUpdateTests(t *testing.T, f Factory)
- type Factory
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func RunConcurrencyTests ¶
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 ¶
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 RunEmptyTests ¶
RunEmptyTests pins the empty-target contract.
func RunFaceTests ¶
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 ¶
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 ¶
RunIsolationTests pins that targets do not bleed into each other.
func RunKeyFidelityTests ¶
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 ¶
RunOrderingTests pins the ordering contract: oldest first, ID breaking ties.
func RunRenameTests ¶
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 ¶
RunRoundTripTests pins that every field survives storage unchanged.
func RunUpdateTests ¶
RunUpdateTests pins which fields an update may change.