Tests for the every-arm rule on paths through a choice, and the List/Fake contract

This commit is contained in:
lilleman
2026-08-27 23:04:46 +02:00
committed by lilleman-tw
parent 2d8fcae4f4
commit 7d5d03e393
2 changed files with 56 additions and 1 deletions
+29
View File
@@ -89,6 +89,35 @@ func TestDescendIntoLiteralErrors(t *testing.T) {
} }
} }
// TestPathThroughChoice pins the rule that makes a dotted path predictable: a
// choice consumes no segment, so a path may step through one only when every
// variant carries the rest of it. Otherwise the same path would render or fail
// depending on which variant the rng picked.
func TestPathThroughChoice(t *testing.T) {
dir := writeData(t, map[string]string{
"every": `[{"format":"{f}","f":["1"]},{"format":"{f}","f":["2"]}]`,
"notall": `[{"format":"{f}","f":["1"]},["plain"]]`,
})
f := newFakes(t, dir, WithSeed(1))
for i := 0; i < 200; i++ {
if got := fake(t, f, "every.f"); got != "1" && got != "2" {
t.Fatalf("every.f = %q, want 1 or 2", got)
}
}
var first string
for i := 0; i < 200; i++ {
_, err := f.Fake("notall.f")
if err == nil {
t.Fatal("notall.f = nil error, want the same failure every call")
}
if i == 0 {
first = err.Error()
} else if err.Error() != first {
t.Fatalf("notall.f error varies between calls:\n %s\n %s", first, err.Error())
}
}
}
// --- category root shapes --- // --- category root shapes ---
func TestCategoryRootShapes(t *testing.T) { func TestCategoryRootShapes(t *testing.T) {
+27 -1
View File
@@ -4,6 +4,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"reflect" "reflect"
"slices"
"testing" "testing"
) )
@@ -14,9 +15,11 @@ func TestList(t *testing.T) {
"person": `{"format":"{first} {last}","first":["A"],"last":["B"]}`, "person": `{"format":"{first} {last}","first":["A"],"last":["B"]}`,
"word": `["x", "y"]`, "word": `["x", "y"]`,
"geo/city": `["Z"]`, "geo/city": `["Z"]`,
// Only the fields every variant carries are addressable, so "extra" is not.
"coin": `[{"format":"{code}","code":["A"],"name":["Aa"]},{"format":"{code}","code":["B"],"name":["Bb"],"extra":["x"]}]`,
}) })
got := newFakes(t, dir, WithSeed(1)).List() got := newFakes(t, dir, WithSeed(1)).List()
want := []string{"geo.city", "person", "person.first", "person.last", "word"} want := []string{"coin", "coin.code", "coin.name", "geo.city", "person", "person.first", "person.last", "word"}
if !reflect.DeepEqual(got, want) { if !reflect.DeepEqual(got, want) {
t.Fatalf("List() = %v, want %v", got, want) t.Fatalf("List() = %v, want %v", got, want)
} }
@@ -131,3 +134,26 @@ func TestMultiPathMergesFolders(t *testing.T) {
t.Fatalf("sv_SE.shared = %q, want b (last loaded wins)", got) t.Fatalf("sv_SE.shared = %q, want b (last loaded wins)", got)
} }
} }
// TestListedPathsAllRender is the contract between List and Fake over the shipped
// tree: everything List advertises renders, every time, and the sub-fields the
// README advertises are discoverable.
func TestListedPathsAllRender(t *testing.T) {
f := newFakes(t, "data", WithSeed(4))
paths := f.List()
if len(paths) < 50 {
t.Fatalf("List() = %d paths, want the whole shipped tree", len(paths))
}
for _, p := range paths {
for i := 0; i < 20; i++ {
if _, err := f.Fake(p); err != nil {
t.Fatalf("Fake(%q) = %v, but List() advertises it", p, err)
}
}
}
for _, p := range []string{"misc.car.maker", "misc.country.alpha2", "misc.currency.symbol", "misc.httpstatus.code", "misc.mimetype.ext"} {
if !slices.Contains(paths, p) {
t.Errorf("List() omits %q, which the README advertises and Fake renders", p)
}
}
}