Make great documentation goal 1.2, and plan the README's reorganisation and the nested-template gaps #33
+1
-1
@@ -105,7 +105,7 @@ func TestBuiltinChecksums(t *testing.T) {
|
|||||||
|
|
||||||
// TestBuiltinSeqPerGenerator pins seq's contract: a counter from 1, advancing on
|
// TestBuiltinSeqPerGenerator pins seq's contract: a counter from 1, advancing on
|
||||||
// each call, named counters independent, and the whole thing scoped to one
|
// 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) {
|
func TestBuiltinSeqPerGenerator(t *testing.T) {
|
||||||
f := engine(1)
|
f := engine(1)
|
||||||
for i := 1; i <= 5; i++ {
|
for i := 1; i <= 5; i++ {
|
||||||
|
|||||||
+4
-6
@@ -7,6 +7,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"testing/fstest"
|
"testing/fstest"
|
||||||
|
|
||||||
|
"github.com/larvit/fejkdata/internal/drawstate"
|
||||||
)
|
)
|
||||||
|
|
||||||
// newGenerator creates a generator over a single data directory, failing on
|
// 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.
|
// engine builds a seeded generator with no loaded categories, for rendering tests.
|
||||||
func engine(seed uint64) *Generator {
|
func engine(seed uint64) *Generator {
|
||||||
s, err := newRand(seed, true)
|
return &Generator{draws: drawstate.New(seed)}
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return &Generator{rand: s}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse unmarshals a JSON template fragment into its dynamic form.
|
// 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 {
|
func mustRender(t *testing.T, f *Generator, s string) string {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
return renderOnce(f.rand, compiled(t, s))
|
return renderOnce(f.draws, compiled(t, s))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -35,7 +35,7 @@ func TestDrawStepsPanicsOnAStepItsNodeLacks(t *testing.T) {
|
|||||||
t.Errorf("drawSteps(plain, f) recovered %v, want a panic naming the missing field", r)
|
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) {
|
func TestDeepDottedPath(t *testing.T) {
|
||||||
|
|||||||
+2
-2
@@ -43,7 +43,7 @@ func TestGrowIsALowerBound(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for i := 0; i < 50; i++ {
|
for i := 0; i < 50; i++ {
|
||||||
var frames frameStack
|
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)
|
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) },
|
"prove": func(n node) { (&valueProof{}).prove(n) },
|
||||||
"render": func(n node) {
|
"render": func(n node) {
|
||||||
var frames frameStack
|
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) },
|
"renderEdges": func(n node) { renderEdges(n) },
|
||||||
"stepInto": func(n node) { _, _ = stepInto(n, "x") },
|
"stepInto": func(n node) { _, _ = stepInto(n, "x") },
|
||||||
|
|||||||
Reference in New Issue
Block a user