From 4a680f03b3b6158c0b71016758c30dc5111d5f22 Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Mon, 5 Oct 2026 11:43:04 +0200 Subject: [PATCH] Test internal/drawstate and the module packages each package may import --- builtins_test.go | 2 +- fejkdata_test.go | 10 ++--- imports_test.go | 66 ++++++++++++++++++++++++++++ internal/drawstate/drawstate_test.go | 40 +++++++++++++++++ path_test.go | 2 +- render_test.go | 4 +- 6 files changed, 114 insertions(+), 10 deletions(-) create mode 100644 imports_test.go create mode 100644 internal/drawstate/drawstate_test.go diff --git a/builtins_test.go b/builtins_test.go index eca2dbd..a195b05 100644 --- a/builtins_test.go +++ b/builtins_test.go @@ -105,7 +105,7 @@ func TestBuiltinChecksums(t *testing.T) { // TestBuiltinSeqPerGenerator pins seq's contract: a counter from 1, advancing on // each call, named counters independent, and the whole thing scoped to one -// generatorState so a fresh Generator restarts at 1. +// draw state so a fresh Generator restarts at 1. func TestBuiltinSeqPerGenerator(t *testing.T) { f := engine(1) for i := 1; i <= 5; i++ { diff --git a/fejkdata_test.go b/fejkdata_test.go index f108855..d66f3c3 100644 --- a/fejkdata_test.go +++ b/fejkdata_test.go @@ -7,6 +7,8 @@ import ( "strings" "testing" "testing/fstest" + + "github.com/larvit/fejkdata/internal/drawstate" ) // newGenerator creates a generator over a single data directory, failing on @@ -96,11 +98,7 @@ func fakeTemplate(t *testing.T, f *Generator, s string) string { // engine builds a seeded generator with no loaded categories, for rendering tests. func engine(seed uint64) *Generator { - s, err := newRand(seed, true) - if err != nil { - panic(err) - } - return &Generator{rand: s} + return &Generator{draws: drawstate.New(seed)} } // parse unmarshals a JSON template fragment into its dynamic form. @@ -135,5 +133,5 @@ func compiled(t *testing.T, s string) node { func mustRender(t *testing.T, f *Generator, s string) string { t.Helper() - return renderOnce(f.rand, compiled(t, s)) + return renderOnce(f.draws, compiled(t, s)) } diff --git a/imports_test.go b/imports_test.go new file mode 100644 index 0000000..4174ca7 --- /dev/null +++ b/imports_test.go @@ -0,0 +1,66 @@ +package fejkdata + +import ( + "errors" + "go/build" + "io/fs" + "path/filepath" + "slices" + "strings" + "testing" +) + +// TestPackageImports holds each package in the module to the module packages it may import. +func TestPackageImports(t *testing.T) { + const module = "github.com/larvit/fejkdata" + allowed := map[string][]string{ + ".": {"internal/drawstate"}, + "cmd/fejkdata": {"."}, + "internal/drawstate": nil, + } + seen := map[string]bool{} + err := filepath.WalkDir(".", func(dir string, d fs.DirEntry, err error) error { + if err != nil || !d.IsDir() { + return err + } + if dir != "." && (strings.HasPrefix(d.Name(), ".") || d.Name() == "testdata") { + return filepath.SkipDir + } + pkg, err := build.ImportDir(dir, 0) + var noGo *build.NoGoError + if errors.As(err, &noGo) { + return nil + } + if err != nil { + return err + } + dir = filepath.ToSlash(dir) + seen[dir] = true + may, listed := allowed[dir] + if !listed { + t.Errorf("package %s is not listed: add the module packages it may import", dir) + return nil + } + for _, imp := range slices.Concat(pkg.Imports, pkg.TestImports, pkg.XTestImports) { + if imp != module && !strings.HasPrefix(imp, module+"/") { + continue + } + rel := strings.TrimPrefix(strings.TrimPrefix(imp, module), "/") + if rel == "" { + rel = "." + } + if rel != dir && !slices.Contains(may, rel) { + t.Errorf("package %s imports %s, which its list does not allow", dir, rel) + } + } + return nil + }) + if err != nil { + t.Fatal(err) + } + for dir := range allowed { + if !seen[dir] { + t.Errorf("listed package %s does not exist", dir) + } + } +} diff --git a/internal/drawstate/drawstate_test.go b/internal/drawstate/drawstate_test.go new file mode 100644 index 0000000..0c79192 --- /dev/null +++ b/internal/drawstate/drawstate_test.go @@ -0,0 +1,40 @@ +package drawstate + +import "testing" + +func TestOneSeedDrawsOneSequence(t *testing.T) { + a, b := New(42), New(42) + for i := 0; i < 50; i++ { + if x, y := a.Uint64(), b.Uint64(); x != y { + t.Fatalf("seed 42 diverged at draw %d: %d != %d", i, x, y) + } + } +} + +func TestTwoSeedsDrawTwoSequences(t *testing.T) { + a, b := New(1), New(2) + for i := 0; i < 50; i++ { + if a.Uint64() != b.Uint64() { + return + } + } + t.Fatal("seeds 1 and 2 drew identical sequences") +} + +func TestCountersCountFromOneEach(t *testing.T) { + s := New(1) + for want := uint64(1); want <= 3; want++ { + if got := s.Next(""); got != want { + t.Fatalf("Next(\"\") = %d, want %d", got, want) + } + } + if got := s.Next("orders"); got != 1 { + t.Fatalf("Next(orders) = %d, want its own count from 1", got) + } + if got := s.Next(""); got != 4 { + t.Fatalf("Next(\"\") after Next(orders) = %d, want 4", got) + } + if got := New(1).Next(""); got != 1 { + t.Fatalf("a new state's Next = %d, want 1", got) + } +} diff --git a/path_test.go b/path_test.go index c69b9a6..aa2425a 100644 --- a/path_test.go +++ b/path_test.go @@ -35,7 +35,7 @@ func TestDrawStepsPanicsOnAStepItsNodeLacks(t *testing.T) { t.Errorf("drawSteps(plain, f) recovered %v, want a panic naming the missing field", r) } }() - drawSteps(engine(1).rand, compiled(t, `"plain"`), []pathStep{{kind: stepField, name: "f"}}, &pinSet{}, nil, nil) + drawSteps(engine(1).draws, compiled(t, `"plain"`), []pathStep{{kind: stepField, name: "f"}}, &pinSet{}, nil, nil) } func TestDeepDottedPath(t *testing.T) { diff --git a/render_test.go b/render_test.go index 10939bd..d9ac367 100644 --- a/render_test.go +++ b/render_test.go @@ -43,7 +43,7 @@ func TestGrowIsALowerBound(t *testing.T) { } for i := 0; i < 50; i++ { var frames frameStack - if got := len(expand(f.rand, tmpl, renderScope{frames: &frames})); got < tmpl.compiled.grow { + if got := len(expand(f.draws, tmpl, renderScope{frames: &frames})); got < tmpl.compiled.grow { t.Errorf("format %q: expand emitted %d bytes, below grow %d", format, got, tmpl.compiled.grow) } } @@ -113,7 +113,7 @@ func TestNodeSwitchesHandleEveryKind(t *testing.T) { "prove": func(n node) { (&valueProof{}).prove(n) }, "render": func(n node) { var frames frameStack - render(engine(1).rand, n, renderScope{frames: &frames, row: renderedRow{tbl, 0}}) + render(engine(1).draws, n, renderScope{frames: &frames, row: renderedRow{tbl, 0}}) }, "renderEdges": func(n node) { renderEdges(n) }, "stepInto": func(n node) { _, _ = stepInto(n, "x") },