Test that a typo under loaded modules names no module to add, that reads names namespaces, that a mounted module names its files by its namespace, and that a namespace reaches a subfolder
This commit is contained in:
+44
-17
@@ -44,9 +44,6 @@ type shippedModule struct {
|
||||
namespace string
|
||||
}
|
||||
|
||||
// importPath is the Go package the module's FS is exported from.
|
||||
func (m shippedModule) importPath() string { return "github.com/larvit/fejkdata/data/" + m.dir }
|
||||
|
||||
// holds reports whether the category at path is the module's.
|
||||
func (m shippedModule) holds(path string) bool { return strings.HasPrefix(path, m.namespace+".") }
|
||||
|
||||
@@ -68,10 +65,14 @@ func (m shippedModule) whole(t testing.TB) fs.FS {
|
||||
return out
|
||||
}
|
||||
|
||||
// shippedModules is every module data.Modules lists, each beside its folder under data/.
|
||||
// shippedModules is every module data.Modules lists, each beside its folder under data/: its
|
||||
// namespace in lower case without separators.
|
||||
func shippedModules(t testing.TB) []shippedModule {
|
||||
t.Helper()
|
||||
out := []shippedModule{{enus.FS, "enus", "en_US"}, {geose.FS, "geose", "geo.SE"}, {geous.FS, "geous", "geo.US"}, {misc.FS, "misc", "misc"}, {svse.FS, "svse", "sv_SE"}}
|
||||
out := []shippedModule{{fsys: enus.FS, namespace: "en_US"}, {fsys: geose.FS, namespace: "geo.SE"}, {fsys: geous.FS, namespace: "geo.US"}, {fsys: misc.FS, namespace: "misc"}, {fsys: svse.FS, namespace: "sv_SE"}}
|
||||
for i := range out {
|
||||
out[i].dir = strings.ToLower(strings.NewReplacer(".", "", "_", "").Replace(out[i].namespace))
|
||||
}
|
||||
var listed []fs.FS
|
||||
for _, m := range out {
|
||||
listed = append(listed, m.fsys)
|
||||
@@ -171,7 +172,7 @@ func shippedManifests(whole *Generator, modules []shippedModule) ([][]byte, erro
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// readsOf is every module module i reads, directly or through another, by import path.
|
||||
// readsOf is the namespace of every module module i reads, directly or through another.
|
||||
func readsOf(i int, direct [][]int, modules []shippedModule) []string {
|
||||
seen := map[int]bool{i: true}
|
||||
queue := slices.Clone(direct[i])
|
||||
@@ -182,7 +183,7 @@ func readsOf(i int, direct [][]int, modules []shippedModule) []string {
|
||||
continue
|
||||
}
|
||||
seen[j] = true
|
||||
out = append(out, modules[j].importPath())
|
||||
out = append(out, modules[j].namespace)
|
||||
queue = append(queue, direct[j]...)
|
||||
}
|
||||
sort.Strings(out)
|
||||
@@ -211,7 +212,7 @@ func TestEachShippedModuleRendersBesideTheModulesItReads(t *testing.T) {
|
||||
}
|
||||
set := []fs.FS{m.fsys}
|
||||
for _, read := range manifest.Reads {
|
||||
i := slices.IndexFunc(modules, func(r shippedModule) bool { return r.importPath() == read })
|
||||
i := slices.IndexFunc(modules, func(r shippedModule) bool { return r.namespace == read })
|
||||
if i < 0 {
|
||||
t.Fatalf("%s reads %s, which no shipped module is", m.dir, read)
|
||||
}
|
||||
@@ -234,7 +235,7 @@ func TestAReadNoModuleProvidesNamesTheReadersModules(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("New(WithDataFS(svse.FS)) = %v", err)
|
||||
}
|
||||
if _, err := f.Fake("sv_SE.address"); err == nil || !strings.Contains(err.Error(), "is a module missing? The loaded modules read github.com/larvit/fejkdata/data/geose") {
|
||||
if _, err := f.Fake("sv_SE.address"); err == nil || !strings.Contains(err.Error(), "is a module missing? The loaded modules read geo.SE, which nothing loaded provides") {
|
||||
t.Errorf(`Fake("sv_SE.address") = %v, want the module it reads named`, err)
|
||||
}
|
||||
for name, opt := range map[string]Option{
|
||||
@@ -253,23 +254,23 @@ func TestAReadNoModuleProvidesNamesTheReadersModules(t *testing.T) {
|
||||
|
||||
func TestADataPathManifestNamesWhatItReads(t *testing.T) {
|
||||
dir := writeFiles(t, map[string]string{
|
||||
".fejkdata.json": `{"reads": ["example.com/places"]}`,
|
||||
".fejkdata.json": `{"reads": ["places"]}`,
|
||||
"x.json": `"{/place}"`,
|
||||
})
|
||||
if _, err := New(WithDataPath(dir)); err == nil || !strings.Contains(err.Error(), "is a module missing? The loaded modules read example.com/places") {
|
||||
if _, err := New(WithDataPath(dir)); err == nil || !strings.Contains(err.Error(), "is a module missing? The loaded modules read places, which nothing loaded provides") {
|
||||
t.Errorf("New = %v, want the module x reads named", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAnIndexedModuleNamesWhatItReads(t *testing.T) {
|
||||
f, err := New(WithDataFS(fstest.MapFS{
|
||||
".fejkdata.json": {Data: []byte(`{"index": {"x": {"paths": [""]}}, "reads": ["example.com/places"]}`)},
|
||||
".fejkdata.json": {Data: []byte(`{"index": {"x": {"paths": [""]}}, "reads": ["places"]}`)},
|
||||
"x.json": {Data: []byte(`"{/place}"`)},
|
||||
}))
|
||||
if err != nil {
|
||||
t.Fatalf("New = %v", err)
|
||||
}
|
||||
const note = "is a module missing? The loaded modules read example.com/places"
|
||||
const note = "is a module missing? The loaded modules read places, which nothing loaded provides"
|
||||
for name, reach := range map[string]func() error{
|
||||
"Fake": func() error { _, err := f.Fake("x"); return err },
|
||||
"FakeTemplate": func() error { _, err := f.FakeTemplate("{/x}"); return err },
|
||||
@@ -288,23 +289,49 @@ func TestAnIndexedModuleNamesWhatItReads(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestATypoUnderLoadedModulesNamesNoModule(t *testing.T) {
|
||||
for name, opts := range map[string][]Option{
|
||||
"every shipped module": {withShipped()},
|
||||
"a stand-in providing what a module reads": {WithDataFS(svse.FS, fstest.MapFS{"geo/SE/address.json": {Data: []byte(`"x"`)}})},
|
||||
} {
|
||||
_, err := New(append(opts, WithDataPath(writeData(t, map[string]string{"x": `"{/sv_SE.persn}"`})))...)
|
||||
if err == nil || !strings.HasSuffix(err.Error(), `no entry "persn", and no loaded manifest names a module to add`) {
|
||||
t.Errorf("%s: New = %v, want the typo reported with no module to add", name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAMountedModuleNamesItsFilesByItsNamespace(t *testing.T) {
|
||||
_, err := New(WithDataFS(fstest.MapFS{
|
||||
".fejkdata.json": {Data: []byte(`{"namespace": "my.data"}`)},
|
||||
"word.json": {Data: []byte(`{`)},
|
||||
}))
|
||||
if err == nil || !strings.Contains(err.Error(), "my/data/word.json") {
|
||||
t.Errorf("New = %v, want the broken file named under its namespace", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestANamespaceMountsAModuleUnderIt(t *testing.T) {
|
||||
for name, opt := range map[string]Option{
|
||||
"a data path": WithDataPath(writeFiles(t, map[string]string{
|
||||
".fejkdata.json": `{"namespace": "my.data"}`,
|
||||
"word.json": `"hej"`,
|
||||
"sub/word.json": `"hej"`,
|
||||
})),
|
||||
"an indexed source": WithDataFS(fstest.MapFS{
|
||||
".fejkdata.json": {Data: []byte(`{"index": {"my.data.word": {"paths": [""]}}, "namespace": "my.data"}`)},
|
||||
".fejkdata.json": {Data: []byte(`{"index": {"my.data.word": {"paths": [""]}, "my.data.sub.word": {"paths": [""]}}, "namespace": "my.data"}`)},
|
||||
"word.json": {Data: []byte(`"hej"`)},
|
||||
"sub/word.json": {Data: []byte(`"hej"`)},
|
||||
}),
|
||||
} {
|
||||
f, err := New(opt)
|
||||
if err != nil {
|
||||
t.Fatalf("New(%s) = %v", name, err)
|
||||
}
|
||||
if got := fake(t, f, "my.data.word"); got != "hej" {
|
||||
t.Errorf("%s: my.data.word = %q, want hej", name, got)
|
||||
for _, p := range []string{"my.data.word", "my.data.sub.word"} {
|
||||
if got := fake(t, f, p); got != "hej" {
|
||||
t.Errorf("%s: %s = %q, want hej", name, p, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -479,7 +506,7 @@ func TestABrokenManifestFailsNewNamingEveryMistake(t *testing.T) {
|
||||
`{"index": {"a": {"paths": [""], "parent": "b"}}}`: {`parent "b" names no entry`},
|
||||
`{"index": {"a": {"paths": [""], "reads": ["b"]}}}`: {`unknown key "reads"`},
|
||||
`{"reads": "b"}`: {"reads must be a list, not a string"},
|
||||
`{"reads": ["", 3]}`: {"reads item 1 is empty", "reads item 2 must be a string, not a number"},
|
||||
`{"reads": ["", 3]}`: {"reads item 1:", "reads item 2 must be a string, not a number"},
|
||||
`{"reads": ["a", "a"]}`: {`reads item 2 repeats "a"`},
|
||||
`{"namespace": 5}`: {"namespace must be a string, not a number"},
|
||||
`{"namespace": "a..b"}`: {`namespace "a..b"`},
|
||||
|
||||
Reference in New Issue
Block a user