Test that a manifest refuses every key and shape it does not define, that a table under a shipped table loads from a data path, that an omitted parent fails the first reach, and pin New's allocations
This commit is contained in:
@@ -174,3 +174,16 @@ func BenchmarkWideTokens100(b *testing.B) {
|
|||||||
func BenchmarkWideTokens500(b *testing.B) {
|
func BenchmarkWideTokens500(b *testing.B) {
|
||||||
benchPath(b, tmpData(b, "wide", wideTokenJSON(500)), "wide")
|
benchPath(b, tmpData(b, "wide", wideTokenJSON(500)), "wide")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New decodes the shipped manifest and loads nothing else.
|
||||||
|
func TestNoNewAllocRegression(t *testing.T) {
|
||||||
|
const base = 2501.0
|
||||||
|
allocs := testing.AllocsPerRun(100, func() {
|
||||||
|
if _, err := New(WithSeed(1)); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if allocs > base*1.10 {
|
||||||
|
t.Errorf("New: %.1f allocs/op regressed past %.1f (baseline %.1f + 10%%); bump the baseline only as a deliberate change", allocs, base*1.10, base)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+55
-29
@@ -9,6 +9,7 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"reflect"
|
"reflect"
|
||||||
"slices"
|
"slices"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -262,7 +263,10 @@ func TestABrokenManifestFailsNew(t *testing.T) {
|
|||||||
`{`: datafiles.ManifestFile,
|
`{`: datafiles.ManifestFile,
|
||||||
`{"indx": {}}`: "indx",
|
`{"indx": {}}`: "indx",
|
||||||
`{"index": {"a..b": {"paths": [""]}}}`: "a..b",
|
`{"index": {"a..b": {"paths": [""]}}}`: "a..b",
|
||||||
`{"index": {}} {}`: "more than one JSON value",
|
`{"index": {}} {}`: "after top-level value",
|
||||||
|
`{"INDEX": {}}`: `unknown key "INDEX"`,
|
||||||
|
`{"index": {"a": {"Paths": [""]}}}`: `unknown key "Paths"`,
|
||||||
|
`{"index": {"a": {}, "b": {}}}`: `"b": paths is missing`,
|
||||||
`{"index": {"a": {"paths": [""], "parent": "b"}}}`: `parent "b" names no entry`,
|
`{"index": {"a": {"paths": [""], "parent": "b"}}}`: `parent "b" names no entry`,
|
||||||
`{"index": {"a": {"paths": [""], "reads": ["b..c"]}}}`: "b..c",
|
`{"index": {"a": {"paths": [""], "reads": ["b..c"]}}}`: "b..c",
|
||||||
} {
|
} {
|
||||||
@@ -343,34 +347,56 @@ func TestListRunsBesideAnOnDemandLoad(t *testing.T) {
|
|||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAStaleIndexEntryFailsItsFirstReachNamingTheManifest(t *testing.T) {
|
func TestAParentColumnItsIndexEntryOmitsFailsTheFirstReachNamingTheManifest(t *testing.T) {
|
||||||
table := map[string]string{
|
f, err := New(WithoutShippedData(), WithDataFS(fstest.MapFS{
|
||||||
"country.json": `{"format":"{name}","rows":"country.tsv","key":"code"}`,
|
".fejkdata.json": {Data: []byte(`{"index": {"city": {"paths": ["", "country", "name"]}, "country": {"paths": ["", "code", "name"]}}}`)},
|
||||||
"country.tsv": "code\tname\nSE\tSweden\n",
|
"country.json": {Data: []byte(`{"format":"{name}","rows":"country.tsv","key":"code"}`)},
|
||||||
"city.json": `{"format":"{name}","rows":"city.tsv","key":"name","parent":"country"}`,
|
"country.tsv": {Data: []byte("code\tname\nSE\tSweden\n")},
|
||||||
"city.tsv": "name\tcountry\nOslo\tSE\n",
|
"city.json": {Data: []byte(`{"format":"{name}","rows":"city.tsv","key":"name","parent":"country"}`)},
|
||||||
"word.json": `{"format":"{a}","a":"x"}`,
|
"city.tsv": {Data: []byte("name\tcountry\nOslo\tSE\n")},
|
||||||
|
}))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("New() = %v", err)
|
||||||
}
|
}
|
||||||
for index, reach := range map[string]string{
|
if _, err := f.Fake("country"); err != nil {
|
||||||
`{"index": {"word": {"paths": [""]}}}`: "word",
|
t.Fatalf(`Fake("country") = %v`, err)
|
||||||
`{"index": {"word": {"paths": ["", "a"], "reads": ["city"]}, "city": {"paths": [""]}, "country": {"paths": [""]}}}`: "word",
|
}
|
||||||
`{"index": {"city": {"paths": ["", "country", "name"]}, "country": {"paths": ["", "city", "city.country", "city.name", "code", "name"]}}}`: "city",
|
_, first := f.Fake("city")
|
||||||
} {
|
if first == nil || !strings.Contains(first.Error(), ".fejkdata.json") || !strings.Contains(first.Error(), `parent ""`) {
|
||||||
fsys := fstest.MapFS{".fejkdata.json": {Data: []byte(index)}}
|
t.Fatalf(`Fake("city") = %v, want the entry's parent named`, first)
|
||||||
for name, data := range table {
|
}
|
||||||
fsys[name] = &fstest.MapFile{Data: []byte(data)}
|
if _, again := f.Fake("city"); again == nil || again.Error() != first.Error() {
|
||||||
}
|
t.Fatalf(`Fake("city") again = %v, want %v`, again, first)
|
||||||
f, err := New(WithoutShippedData(), WithDataFS(fsys))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("New(%s) = %v", index, err)
|
|
||||||
}
|
|
||||||
_, first := f.Fake(reach)
|
|
||||||
if first == nil || !strings.Contains(first.Error(), ".fejkdata.json") || !strings.Contains(first.Error(), "stale") {
|
|
||||||
t.Errorf("Fake(%q) under %s = %v, want the stale entry named", reach, index, first)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if _, again := f.Fake(reach); again == nil || again.Error() != first.Error() {
|
|
||||||
t.Errorf("Fake(%q) again = %v, want %v", reach, again, first)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestADataPathTableUnderAShippedTableLoads(t *testing.T) {
|
||||||
|
f, err := New(WithSeed(1), WithDataPath(writeFiles(t, map[string]string{
|
||||||
|
"sv_SE/nickname.json": `{"format":"{name}","rows":"nickname.tsv","key":"name","parent":"sex"}`,
|
||||||
|
"sv_SE/nickname.tsv": "name\tsex\nKalle\tm\nLotta\tf\n",
|
||||||
|
})))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("New() = %v", err)
|
||||||
|
}
|
||||||
|
if got := fake(t, f, "sv_SE.sex[m].nickname"); got != "Kalle" {
|
||||||
|
t.Fatalf("sv_SE.sex[m].nickname = %q, want Kalle", got)
|
||||||
|
}
|
||||||
|
if got := fake(t, f, "sv_SE.person"); got == "" {
|
||||||
|
t.Fatal("sv_SE.person rendered empty")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// indexEntry is what an index says of the loaded category s.
|
||||||
|
func indexEntry(root *folder, s categorySite) datafiles.IndexEntry {
|
||||||
|
e := datafiles.IndexEntry{Parent: parentOf(s.n), Paths: paths(s.n, false)}
|
||||||
|
sort.Strings(e.Paths)
|
||||||
|
seen := map[string]bool{s.path: true}
|
||||||
|
for _, c := range referenced(root, s.dir, siteNodes([]categorySite{s})) {
|
||||||
|
if p := categoryPath(c.dir, c.name); !seen[p] {
|
||||||
|
seen[p] = true
|
||||||
|
e.Reads = append(e.Reads, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Strings(e.Reads)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user