From 6e2555aee6963ed1a9bb4e73e8af55e35cc61e33 Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Sun, 11 Oct 2026 11:49:18 +0200 Subject: [PATCH] Test that a load failing on a read nothing provides names every module the loaded manifests read --- data.go | 27 +++++++-------------------- index.go | 17 +++++++---------- reference_test.go | 2 +- resolve.go | 30 +++++++----------------------- shipped_test.go | 10 +++++----- 5 files changed, 27 insertions(+), 59 deletions(-) diff --git a/data.go b/data.go index e565c23..68dbc53 100644 --- a/data.go +++ b/data.go @@ -9,40 +9,29 @@ import ( // loadSources merges sources in order, the last winning a clash. A source whose manifest // carries an index leaves its categories unloaded; every other source loads here, with // the unloaded categories it needs. -// docs/decisions.md#a-source-whose-manifest-carries-an-index-loads-each-category-on-first-reach-any-other-loads-in-new-with-what-it-reads func loadSources(sources []datafiles.Source) (folder, error) { root := folder{children: map[string]node{}} - walked := map[string][]string{} for _, src := range sources { - if err := addSource(&root, src, walked); err != nil { + if err := addSource(&root, src); err != nil { return folder{}, err } } - sites := categorySites(&root) - for i := range sites { - sites[i].defaultModules = walked[sites[i].path] - } - return root, loadReached(&root, sites, nil) + return root, loadReached(&root, categorySites(&root), nil) } -// addSource places src's categories in root. For each category it loads now, it records in -// walked the modules src reads by default. -func addSource(root *folder, src datafiles.Source, walked map[string][]string) error { +func addSource(root *folder, src datafiles.Source) error { m, err := src.Manifest() if err != nil { return err } if m.Index != nil { - placeIndex(root, src, m) + placeIndex(root, src, m.Index) return nil } g := &folder{children: map[string]node{}} if err := src.Walk(compileInto(func(dir []string) *folder { return madeFolder(g, dir) })); err != nil { return err } - for _, s := range categorySites(g) { - walked[s.path] = m.Reads - } mergeFolder(root, g) return nil } @@ -88,13 +77,11 @@ func mergeFolder(dst, src *folder) { // single inline node. type nodeSet func(fn func(label string, n node) error) error -// categorySite is a loaded category, where it sits, its own dot path, and the modules its -// source reads by default. +// categorySite is a loaded category, where it sits and its own dot path. type categorySite struct { categoryAt - n node - path string - defaultModules []string + n node + path string } // categorySites lists every category under root, folders and names in sorted order. diff --git a/index.go b/index.go index 5d59045..fa1c67e 100644 --- a/index.go +++ b/index.go @@ -11,20 +11,18 @@ import ( "github.com/larvit/fejkdata/internal/grammar" ) -// indexed is a category an index names and no call has reached yet, the source holding it, -// and the modules that source reads by default. +// indexed is a category an index names and no call has reached yet, and the source holding it. type indexed struct { - entry datafiles.IndexEntry - src datafiles.Source - defaultModules []string + entry datafiles.IndexEntry + src datafiles.Source } -// placeIndex sets every category m's index names as unloaded in root, in place of what +// placeIndex sets every category the index names as unloaded in root, in place of what // root holds at its path. -func placeIndex(root *folder, src datafiles.Source, m datafiles.Manifest) { - for _, p := range sortedNames(m.Index) { +func placeIndex(root *folder, src datafiles.Source, index map[string]datafiles.IndexEntry) { + for _, p := range sortedNames(index) { segs := strings.Split(p, ".") - madeFolder(root, segs[:len(segs)-1]).putUnloaded(segs[len(segs)-1], &indexed{entry: m.Index[p], src: src, defaultModules: m.Reads}) + madeFolder(root, segs[:len(segs)-1]).putUnloaded(segs[len(segs)-1], &indexed{entry: index[p], src: src}) } } @@ -149,7 +147,6 @@ func (b *batch) load(root *folder, queue []categoryAt) error { return err } s := siteIn(c.dir, c.in, c.name) - s.defaultModules = x.defaultModules *b = append(*b, loaded{site: s, was: x}) if parent := parentOf(s.n); parent != x.entry.Parent { return fmt.Errorf("%s: the index entry for %s %s, and its table %s", x.src.ManifestPath(), s.path, namesParent(x.entry.Parent), namesParent(parent)) diff --git a/reference_test.go b/reference_test.go index 30b55cb..8a323d0 100644 --- a/reference_test.go +++ b/reference_test.go @@ -206,7 +206,7 @@ func TestNewErrorPathIsCanonical(t *testing.T) { { "bad reference reached through another reference", map[string]string{"a": `"{/b}"`, "b": `"{/nope}"`}, - `fejkdata: b: reference {/nope}: no entry "nope", and the module holding b names no module it reads by default`, + `fejkdata: b: reference {/nope}: no entry "nope", and no loaded module names a module it reads by default`, }, } for _, c := range cases { diff --git a/resolve.go b/resolve.go index 32144f2..6ad41bd 100644 --- a/resolve.go +++ b/resolve.go @@ -1,18 +1,15 @@ package fejkdata import ( - "errors" "fmt" - "strings" ) -// templateSite is a template to resolve, with its folder and its category, both empty for an -// inline template, and eachNode's label for it. +// templateSite is a template to resolve, with its folder and category, both empty for an inline +// template, and eachNode's label for it. type templateSite struct { - t *template - folder []string - label string - category *categorySite + t *template + folder []string + label string } // resolveCategoryTemplates resolves every template of the categories, once all data is merged, so a @@ -22,7 +19,7 @@ func resolveCategoryTemplates(sites []categorySite, root map[string]node) error for _, s := range sites { if err := eachNode(s.n, s.path, func(label string, n node) error { if t, isTemplate := n.(*template); isTemplate { - ts = append(ts, templateSite{t: t, folder: s.dir, label: label, category: &s}) + ts = append(ts, templateSite{t: t, folder: s.dir, label: label}) } return nil }); err != nil { @@ -59,7 +56,7 @@ func resolveTemplates(ts []templateSite, root map[string]node) error { for _, s := range ts { refs, err := s.t.resolveRefs(s.folder, s.label, root) if err != nil { - return s.withDefaultModules(err) + return err } s.t.refs = refs } @@ -90,16 +87,3 @@ func resolveTemplates(ts []templateSite, root map[string]node) error { } return nil } - -// Where err is a category's reference finding nothing, withDefaultModules adds the modules the -// category's source reads by default, or says it reads none. -func (s templateSite) withDefaultModules(err error) error { - var ne noEntry - if s.category == nil || !errors.As(err, &ne) { - return err - } - if modules := s.category.defaultModules; len(modules) > 0 { - return fmt.Errorf("%w; the module holding %s reads by default %s", err, s.category.path, strings.Join(modules, ", ")) - } - return fmt.Errorf("%w, and the module holding %s names no module it reads by default", err, s.category.path) -} diff --git a/shipped_test.go b/shipped_test.go index eeff0d7..7ab659b 100644 --- a/shipped_test.go +++ b/shipped_test.go @@ -215,7 +215,7 @@ func TestAReadNoModuleProvidesNamesTheReadersModules(t *testing.T) { if err != nil { t.Fatalf("New(WithDataFS(sv_SE.FS)) = %v", err) } - if _, err := f.Fake("sv_SE.address"); err == nil || !strings.Contains(err.Error(), "the module holding sv_SE.address reads by default github.com/larvit/fejkdata/data/geo/SE") { + if _, err := f.Fake("sv_SE.address"); err == nil || !strings.Contains(err.Error(), "the loaded modules read by default github.com/larvit/fejkdata/data/geo/SE") { t.Errorf(`Fake("sv_SE.address") = %v, want the module it reads named`, err) } for name, opt := range map[string]Option{ @@ -226,8 +226,8 @@ func TestAReadNoModuleProvidesNamesTheReadersModules(t *testing.T) { if err == nil { _, err = f.Fake("x") } - if err == nil || !strings.Contains(err.Error(), "the module holding x names no module it reads by default") { - t.Errorf("%s: x = %v, want it said that x's module names none", name, err) + if err == nil || !strings.Contains(err.Error(), "no loaded module names a module it reads by default") { + t.Errorf("%s: x = %v, want it said that no loaded module names one", name, err) } } } @@ -237,7 +237,7 @@ func TestADataPathManifestNamesWhatItReads(t *testing.T) { ".fejkdata.json": `{"reads": ["example.com/places"]}`, "x.json": `"{/place}"`, }) - if _, err := New(WithDataPath(dir)); err == nil || !strings.Contains(err.Error(), "the module holding x reads by default example.com/places") { + if _, err := New(WithDataPath(dir)); err == nil || !strings.Contains(err.Error(), "the loaded modules read by default example.com/places") { t.Errorf("New = %v, want the module x reads named", err) } } @@ -250,7 +250,7 @@ func TestAnIndexedModuleNamesWhatItReads(t *testing.T) { if err != nil { t.Fatalf("New = %v", err) } - if _, err := f.Fake("x"); err == nil || !strings.Contains(err.Error(), "the module holding x reads by default example.com/places") { + if _, err := f.Fake("x"); err == nil || !strings.Contains(err.Error(), "the loaded modules read by default example.com/places") { t.Errorf(`Fake("x") = %v, want the module x reads named`, err) } }