Test that a stale index entry fails its first reach naming the manifest, that such a failure wraps ErrLoad and exits 1, and that a data path naming a file says it is no directory
This commit is contained in:
@@ -790,3 +790,20 @@ func TestRunRecordOfAFieldlessPath(t *testing.T) {
|
|||||||
t.Errorf("stdout = %q, want nothing", out)
|
t.Errorf("stdout = %q, want nothing", out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestADataPathCategoryFailingAtFirstReachExits1(t *testing.T) {
|
||||||
|
dir := t.TempDir()
|
||||||
|
for name, data := range map[string]string{
|
||||||
|
".fejkdata.json": `{"index": {"bad": {"paths": [""]}}}`,
|
||||||
|
"bad.json": `"{/nope}"`,
|
||||||
|
} {
|
||||||
|
if err := os.WriteFile(filepath.Join(dir, name), []byte(data), 0o644); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, args := range [][]string{{"-d", dir}, {"-d", dir, "--format", "json"}} {
|
||||||
|
if code, _, errb := runOut("{/bad}", args...); code != 1 || !strings.Contains(errb, "{/nope}") {
|
||||||
|
t.Errorf("%v on a category failing to load = %d, %q; want exit 1 naming the reference", args, code, errb)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+2
-2
@@ -205,8 +205,8 @@ func TestNewErrors(t *testing.T) {
|
|||||||
if err := os.WriteFile(file, []byte("{}"), 0o644); err != nil {
|
if err := os.WriteFile(file, []byte("{}"), 0o644); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if _, err := New(WithoutShippedData(), WithDataPath(file)); err == nil {
|
if _, err := New(WithoutShippedData(), WithDataPath(file)); err == nil || !strings.Contains(err.Error(), "xx_XX is not a directory") {
|
||||||
t.Error("New(file) = nil error, want not-a-directory error")
|
t.Errorf("New(file) = %v, want not-a-directory error", err)
|
||||||
}
|
}
|
||||||
// Invalid JSON in a category file fails.
|
// Invalid JSON in a category file fails.
|
||||||
if _, err := New(WithoutShippedData(), WithDataPath(writeData(t, map[string]string{"broken": `{ not json`}))); err == nil {
|
if _, err := New(WithoutShippedData(), WithDataPath(writeData(t, map[string]string{"broken": `{ not json`}))); err == nil {
|
||||||
|
|||||||
+37
-22
@@ -3,12 +3,12 @@ package fejkdata
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"reflect"
|
"reflect"
|
||||||
"slices"
|
"slices"
|
||||||
"sort"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -79,12 +79,7 @@ func shippedManifest(whole *Generator) ([]byte, error) {
|
|||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
b.WriteString("{\n\t\"index\": {")
|
b.WriteString("{\n\t\"index\": {")
|
||||||
for i, s := range categorySites(&whole.root) {
|
for i, s := range categorySites(&whole.root) {
|
||||||
e := datafiles.IndexEntry{Paths: paths(s.n, false), Reads: categoryReads(&whole.root, s)}
|
line, err := json.Marshal(indexEntry(&whole.root, s))
|
||||||
if t, isTable := s.n.(*table); isTable {
|
|
||||||
e.Parent = t.rows.Options().Parent
|
|
||||||
}
|
|
||||||
sort.Strings(e.Paths)
|
|
||||||
line, err := json.Marshal(e)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -100,14 +95,10 @@ func shippedManifest(whole *Generator) ([]byte, error) {
|
|||||||
|
|
||||||
func shippedIndex(t *testing.T) map[string]datafiles.IndexEntry {
|
func shippedIndex(t *testing.T) map[string]datafiles.IndexEntry {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
b, err := os.ReadFile(shippedManifestFile)
|
m, err := shippedSource.Manifest()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
var m datafiles.Manifest
|
|
||||||
if err := json.Unmarshal(b, &m); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
return m.Index
|
return m.Index
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,6 +246,9 @@ func TestAnIndexedCategoryFailsAtFirstReachAndEveryReachAfter(t *testing.T) {
|
|||||||
if first == nil || !strings.Contains(first.Error(), "{/nope}") {
|
if first == nil || !strings.Contains(first.Error(), "{/nope}") {
|
||||||
t.Fatalf(`Fake("bad") = %v, want an error naming {/nope}`, first)
|
t.Fatalf(`Fake("bad") = %v, want an error naming {/nope}`, first)
|
||||||
}
|
}
|
||||||
|
if !errors.Is(first, ErrLoad) {
|
||||||
|
t.Fatalf(`Fake("bad") = %v, want it to wrap ErrLoad`, first)
|
||||||
|
}
|
||||||
if _, again := f.Fake("bad"); again == nil || again.Error() != first.Error() {
|
if _, again := f.Fake("bad"); again == nil || again.Error() != first.Error() {
|
||||||
t.Fatalf(`Fake("bad") again = %v, want %v`, again, first)
|
t.Fatalf(`Fake("bad") again = %v, want %v`, again, first)
|
||||||
}
|
}
|
||||||
@@ -268,6 +262,9 @@ 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": {"a": {"paths": [""], "parent": "b"}}}`: `parent "b" names no entry`,
|
||||||
|
`{"index": {"a": {"paths": [""], "reads": ["b..c"]}}}`: "b..c",
|
||||||
} {
|
} {
|
||||||
_, err := New(WithoutShippedData(), WithDataFS(fstest.MapFS{".fejkdata.json": {Data: []byte(manifest)}}))
|
_, err := New(WithoutShippedData(), WithDataFS(fstest.MapFS{".fejkdata.json": {Data: []byte(manifest)}}))
|
||||||
if err == nil || !strings.Contains(err.Error(), want) {
|
if err == nil || !strings.Contains(err.Error(), want) {
|
||||||
@@ -346,16 +343,34 @@ func TestListRunsBesideAnOnDemandLoad(t *testing.T) {
|
|||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
// categoryReads is the sorted path of every other category s's templates reference.
|
func TestAStaleIndexEntryFailsItsFirstReachNamingTheManifest(t *testing.T) {
|
||||||
func categoryReads(root *folder, s categorySite) []string {
|
table := map[string]string{
|
||||||
seen := map[string]bool{s.path: true}
|
"country.json": `{"format":"{name}","rows":"country.tsv","key":"code"}`,
|
||||||
var out []string
|
"country.tsv": "code\tname\nSE\tSweden\n",
|
||||||
for _, c := range referenced(root, s.dir, siteNodes([]categorySite{s})) {
|
"city.json": `{"format":"{name}","rows":"city.tsv","key":"name","parent":"country"}`,
|
||||||
if p := c.path(); !seen[p] {
|
"city.tsv": "name\tcountry\nOslo\tSE\n",
|
||||||
seen[p] = true
|
"word.json": `{"format":"{a}","a":"x"}`,
|
||||||
out = append(out, p)
|
}
|
||||||
|
for index, reach := range map[string]string{
|
||||||
|
`{"index": {"word": {"paths": [""]}}}`: "word",
|
||||||
|
`{"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",
|
||||||
|
} {
|
||||||
|
fsys := fstest.MapFS{".fejkdata.json": {Data: []byte(index)}}
|
||||||
|
for name, data := range table {
|
||||||
|
fsys[name] = &fstest.MapFile{Data: []byte(data)}
|
||||||
|
}
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sort.Strings(out)
|
|
||||||
return out
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user