Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4859c1a916 |
6 changed files with 34 additions and 9 deletions
|
|
@ -352,6 +352,11 @@ namespace GameCult.Caching.Tests
|
|||
private static readonly Rec[] RepullAfter = Items_(("item:a1", "A"), ("item:b1", "B"), ("item:b2", "B"), ("item:c1", "A"));
|
||||
private static readonly Rec[] KeyCaseRecords = Items_(("a", "S"), ("z", "S"), ("B", "T"), ("C", "T"));
|
||||
private static readonly Rec[] HolderCaseRecords = Items_(("a", "S"), ("A", "S"));
|
||||
private static readonly Rec[] CrossSchemaRecords = { new("x:1", Alpha, "P"), new("y:1", Beta, "P") };
|
||||
// Distinct under any trim, case-fold, NFC or NFKC of the value: 'S' and 's', 'S' and 'S ', NFC and NFD, fullwidth S.
|
||||
private static readonly Rec[] DistinctValueRecords = Items_(
|
||||
("k:1", "S"), ("k:2", "s"), ("k:3", "S "), ("k:4", "\u00E9"), ("k:5", "e\u0301"), ("k:6", "\uFF33"), ("k:7", " S"));
|
||||
private static readonly Rec[] NormalKeyRecords = Items_(("\u00E9", "S"), ("e\u0301", "S"));
|
||||
private static readonly Rec[] KeyPunctuationRecords = Items_(("_", "S"), ("a", "S"), ("Z", "T"), ("b", "T"));
|
||||
private static readonly Rec[] SurrogateGroupRecords = Items_(("\uE000", "S"), ("\uE000b", "S"), ("\U0001F600", "T"), ("\U0001F600b", "T"));
|
||||
|
||||
|
|
@ -362,6 +367,8 @@ namespace GameCult.Caching.Tests
|
|||
("key-case-store.cc", KeyCaseRecords), ("key-punctuation-store.cc", KeyPunctuationRecords),
|
||||
("surrogate-groups-store.cc", SurrogateGroupRecords),
|
||||
("holder-case-store.cc", HolderCaseRecords),
|
||||
("cross-schema-store.cc", CrossSchemaRecords), ("distinct-values-store.cc", DistinctValueRecords),
|
||||
("normal-keys-store.cc", NormalKeyRecords),
|
||||
};
|
||||
|
||||
private static readonly Refusal SurrogateRefusal = new("k\U0001F600", "k\uE000", Item, "Sku");
|
||||
|
|
@ -371,6 +378,7 @@ namespace GameCult.Caching.Tests
|
|||
private static readonly Refusal RepullRefusal = new("item:a1", "item:c1", Item, "Sku");
|
||||
private static readonly Refusal KeyCaseRefusal = new("B", "C", Item, "Sku");
|
||||
private static readonly Refusal HolderCaseRefusal = new("A", "a", Item, "Sku");
|
||||
private static readonly Refusal NormalKeyRefusal = new("e\u0301", "\u00E9", Item, "Sku");
|
||||
private static readonly Refusal KeyPunctuationRefusal = new("Z", "b", Item, "Sku");
|
||||
private static readonly Refusal SurrogateGroupRefusal = new("\U0001F600", "\U0001F600b", Item, "Sku");
|
||||
|
||||
|
|
@ -410,6 +418,18 @@ namespace GameCult.Caching.Tests
|
|||
new("load-holders-by-case", new[] { Open("holder-case-store.cc") }, HolderCaseRefusal),
|
||||
// Row 25: the held `a` is replaced only by the exact key `a`, never by `A`.
|
||||
new("batch-replaced-by-case", new[] { Open(), Commit(Items_(("a", "S"))), Commit(Items_(("A", "S"))) }, HolderCaseRefusal),
|
||||
// Rows 26-31: identity is exact. One value in two schemas is two groups; values differing in case, trailing or leading space, normalisation form or width are two values; keys differing only by normalisation form are two holders.
|
||||
new("batch-value-in-two-schemas", new[] { Open(), Commit(CrossSchemaRecords) }, null),
|
||||
new("load-value-in-two-schemas", new[] { Open("cross-schema-store.cc") }, null),
|
||||
new("batch-distinct-values", new[] { Open(), Commit(DistinctValueRecords) }, null),
|
||||
new("load-distinct-values", new[] { Open("distinct-values-store.cc") }, null),
|
||||
new("batch-keys-by-normal-form", new[] { Open(), Commit(NormalKeyRecords) }, NormalKeyRefusal),
|
||||
new("load-keys-by-normal-form", new[] { Open("normal-keys-store.cc") }, NormalKeyRefusal),
|
||||
// Rows 32-33: one landing record sharing two unique aliases with a held one; the least alias by code unit is named ('Alt' before 'Sku'; 'Sku' before 'alt').
|
||||
new("put-onto-a-held-pair", new[] { Open(), Commit(new Rec("m", Pair, "S", "X")), Commit(new Rec("a", Pair, "S", "X")) },
|
||||
new Refusal("a", "m", Pair, "Alt")),
|
||||
new("put-onto-a-held-alias-pair", new[] { Open(), Commit(new Rec("m", Alias, "S", "X")), Commit(new Rec("a", Alias, "S", "X")) },
|
||||
new Refusal("a", "m", Alias, "Sku")),
|
||||
};
|
||||
|
||||
private static byte[] RefusalStoreBytes(Rec[] records)
|
||||
|
|
@ -603,7 +623,7 @@ namespace GameCult.Caching.Tests
|
|||
}
|
||||
|
||||
Assert.That(failed, Is.Empty, "rows that failed");
|
||||
Assert.That(walked, Is.EqualTo(25));
|
||||
Assert.That(walked, Is.EqualTo(33));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ reviewed commit. Other runtimes are held to the same canonical text and the same
|
|||
`" "` and `item:d` holds Sku `U+0085`. Written through a role Sku.
|
||||
- `blank-store.cc`: the same, only `item:c` and `item:d`.
|
||||
- `pair-store.cc`, `surrogate-store.cc`, `types-store.cc`, `repull-before.cc`, `repull-after.cc`, `alias-store.cc`,
|
||||
`key-case-store.cc`, `key-punctuation-store.cc`, `surrogate-groups-store.cc`, `holder-case-store.cc`: single-file stores written like
|
||||
`key-case-store.cc`, `key-punctuation-store.cc`, `surrogate-groups-store.cc`, `holder-case-store.cc`, `cross-schema-store.cc`, `distinct-values-store.cc`, `normal-keys-store.cc`: single-file stores written like
|
||||
`duplicate-store.cc`, through roles, for the rows of `refusals.msgpack` that open or pull them. Schemas
|
||||
`tests.unique_item`, `tests.uq_pair` (Sku and Alt both unique), `tests.uq_alias` (Sku and `alt` both unique),
|
||||
`tests.uq_alpha` and `tests.uq_beta`, each slots `[0: Sku string, 1: second string]`, schema version the name plus
|
||||
|
|
@ -51,24 +51,29 @@ last succeeds and the last refuses with exactly the RULE text built from those f
|
|||
byte-identical. Schemas are those of the store files above; `second` is `Category` (plain) except in `tests.uq_pair`
|
||||
and `tests.uq_alias`, where it is `Alt` (unique, alias `Alt` and `alt` respectively).
|
||||
|
||||
The 13 rows of the spec are a floor; rows 14-25 extend it with orderings that a code-point, case-insensitive or
|
||||
The 13 rows of the spec are a floor; rows 14-33 extend it with orderings that a code-point, case-insensitive or
|
||||
culture compare would flip. Rows, in file order: 1 batch-later-value-staged-first, 2 batch-surrogate-keys, 3
|
||||
batch-interleaved-types, 4 batch-two-aliases, 5 held-then-landing, 6 held-in-the-least-group, 7 swap-off-a-held-value,
|
||||
8 load-two-aliases, 9 load-surrogate-keys, 10 load-interleaved-types, 11 repull-held-pair, 12 load-repull-after, 13
|
||||
commit-onto-a-loaded-holder, 14 batch-key-case (`B` before `a`), 15 batch-key-punctuation (`Z` before `_` before `a`),
|
||||
16 batch-key-case-in-a-group, 17 batch-surrogate-groups (U+1F600 before U+E000, the reverse of code-point order), 18
|
||||
batch-alias-case (alias `Sku` before `alt`), 19 load-alias-case, 20 load-key-case, 21 load-key-punctuation, 22
|
||||
load-surrogate-groups, 23 batch-holders-by-case (`a` and `A` holding one value: `A` before `a`), 24 load-holders-by-case, 25 batch-replaced-by-case (held `a`, then a commit of `A` on its value: `A` does not replace `a`).
|
||||
Rows 19-22 and 24 open a store holding the records of rows 18, 14, 15, 17 and 23, so a runtime with no batch
|
||||
load-surrogate-groups, 23 batch-holders-by-case (`a` and `A` holding one value: `A` before `a`), 24 load-holders-by-case, 25 batch-replaced-by-case (held `a`, then a commit of `A` on its value: `A` does not replace `a`),
|
||||
26 batch-value-in-two-schemas (one value in `tests.uq_alpha` and `tests.uq_beta` at two keys: two groups, success), 27
|
||||
load-value-in-two-schemas, 28 batch-distinct-values (`S`, `s`, `S `, ` S`, U+00E9, `e`+U+0301, U+FF33 are seven values: success), 29
|
||||
load-distinct-values, 30 batch-keys-by-normal-form (keys U+00E9 and `e`+U+0301 holding one value are two holders, `e`+U+0301 first),
|
||||
31 load-keys-by-normal-form, 32 put-onto-a-held-pair (held `m` and landing `a` share Sku and Alt in `tests.uq_pair`, one record per
|
||||
commit: `Alt` is named before `Sku`), 33 put-onto-a-held-alias-pair (the same in `tests.uq_alias`: `Sku` before `alt`).
|
||||
Rows 19-22, 24, 27, 29 and 31 open a store holding the records of rows 18, 14, 15, 17, 23, 26, 28 and 30, so a runtime with no batch
|
||||
commit still walks alias and cross-group key order.
|
||||
|
||||
A runtime performs every row its API can perform and asserts the count it walks. These are the counts a runtime must
|
||||
assert, not a statement of which runtimes walk them today:
|
||||
|
||||
- C# and Rust: all 25.
|
||||
- Python: 24, every row but 3 (`put_envelopes` takes one type).
|
||||
- TypeScript: 12, the rows that only open or pull a store: 5, 8, 9, 10, 11, 12, 13, 19, 20, 21, 22 and 24 (no batch commit, so no
|
||||
row 1-4, 6, 7, 14-18, 23 or 25; `variants:idea:unique-index-runtimes.ts-batch-commit`).
|
||||
- C# and Rust: all 33.
|
||||
- Python: 31, every row but 3 and 26 (`put_envelopes` takes one type, so no batch of two types).
|
||||
- TypeScript: 18, the rows with no multi-record commit: 5, 8, 9, 10, 11, 12, 13, 19, 20, 21, 22, 24, 25, 27, 29, 31, 32 and 33
|
||||
(no batch commit, so no row 1-4, 6, 7, 14-18, 23, 26, 28 or 30; `variants:idea:unique-index-runtimes.ts-batch-commit`).
|
||||
|
||||
Not pinned: the schema-name tiebreak. Record keys are unique across a whole cache, so two types never hold the same key and
|
||||
two groups can never tie on alias and key pair; the final `schema` comparison cannot decide a refusal.
|
||||
|
|
|
|||
BIN
tests/vectors/unique-index/cross-schema-store.cc
Normal file
BIN
tests/vectors/unique-index/cross-schema-store.cc
Normal file
Binary file not shown.
BIN
tests/vectors/unique-index/distinct-values-store.cc
Normal file
BIN
tests/vectors/unique-index/distinct-values-store.cc
Normal file
Binary file not shown.
BIN
tests/vectors/unique-index/normal-keys-store.cc
Normal file
BIN
tests/vectors/unique-index/normal-keys-store.cc
Normal file
Binary file not shown.
Binary file not shown.
Loading…
Reference in a new issue