Files
fejkdata/shipped_test.go
T

214 lines
5.4 KiB
Go

package fejkdata
import (
"bytes"
"fmt"
"go/format"
"io/fs"
"os"
"reflect"
"slices"
"sort"
"sync"
"testing"
)
const shippedIndexFile = "shippedindex.go"
// newShippedWhole loads every shipped category in New, as a --data-path load does, so a test
// reads the whole shipped tree.
func newShippedWhole(t testing.TB, opts ...Option) *Generator {
t.Helper()
data, err := fs.Sub(shippedFS, "data")
if err != nil {
t.Fatal(err)
}
f, err := New(append([]Option{WithoutShippedData(), WithDataFS(data)}, opts...)...)
if err != nil {
t.Fatalf("New() = %v", err)
}
return f
}
// loadedCategories is the dot path of every category f has parsed and linked.
func loadedCategories(f *Generator) []string {
var out []string
for _, s := range categorySites(&f.root) {
out = append(out, s.path)
}
return out
}
// REPIN=1 rewrites the index.
func TestShippedIndexIsCurrent(t *testing.T) {
got, err := shippedIndexSource(newShippedWhole(t))
if err != nil {
t.Fatal(err)
}
if os.Getenv("REPIN") == "1" {
if err := os.WriteFile(shippedIndexFile, got, 0o644); err != nil {
t.Fatal(err)
}
return
}
want, err := os.ReadFile(shippedIndexFile)
if err != nil {
t.Fatal(err)
}
if string(got) != string(want) {
t.Fatalf("%s is stale for data/; rewrite it with REPIN=1", shippedIndexFile)
}
}
func shippedIndexSource(whole *Generator) ([]byte, error) {
var b bytes.Buffer
b.WriteString("// Code generated by TestShippedIndexIsCurrent with REPIN=1. DO NOT EDIT.\n\npackage fejkdata\n\nvar shippedIndex = map[string]shippedEntry{\n")
for _, s := range categorySites(&whole.root) {
fmt.Fprintf(&b, "%q: {", s.path)
if t, isTable := s.n.(*table); isTable && t.parentIndex >= 0 {
fmt.Fprintf(&b, "parent: %q, ", t.header[t.parentIndex])
}
ps := paths(s.n)
sort.Strings(ps)
fmt.Fprintf(&b, "paths: %#v},\n", ps)
}
b.WriteString("}\n")
return format.Source(b.Bytes())
}
func TestNewLoadsNoShippedCategory(t *testing.T) {
f, err := New()
if err != nil {
t.Fatalf("New() = %v", err)
}
if got := loadedCategories(f); len(got) > 0 {
t.Fatalf("New() loaded %v", got)
}
}
func TestReachingACategoryLoadsWhatItReads(t *testing.T) {
for _, tc := range []struct {
reach func(f *Generator) error
want, absent []string
}{
{
reach: func(f *Generator) error { _, err := f.Fake("sv_SE.person.first"); return err },
want: []string{"sv_SE.first-name", "sv_SE.last-name", "sv_SE.person", "sv_SE.sex", "sv_SE.title"},
},
{
reach: func(f *Generator) error { _, err := f.Fake("geo.SE.region"); return err },
want: []string{"geo.SE.locality", "geo.SE.municipality", "geo.SE.postal-code", "geo.SE.region", "geo.SE.street"},
absent: []string{"geo.SE.address", "geo.US.region"},
},
{
reach: func(f *Generator) error { _, err := f.FakeTemplate("{/misc.territory[SE].name}"); return err },
want: []string{"misc.territory", "misc.timezone"},
absent: []string{"misc.tld"},
},
{
reach: func(f *Generator) error { _, err := f.FakeRecord("misc.uuid"); return err },
want: []string{"misc.uuid"},
absent: []string{"misc.objectid"},
},
{
reach: func(f *Generator) error {
var v struct {
Name string `fake:"sv_SE.first-name"`
}
return f.FakeStruct(&v)
},
want: []string{"sv_SE.first-name"},
absent: []string{"sv_SE.person"},
},
} {
f, err := New()
if err != nil {
t.Fatalf("New() = %v", err)
}
if err := tc.reach(f); err != nil {
t.Fatal(err)
}
got := loadedCategories(f)
for _, w := range tc.want {
if !slices.Contains(got, w) {
t.Errorf("loaded %v, want %s among them", got, w)
}
}
for _, a := range tc.absent {
if slices.Contains(got, a) {
t.Errorf("loaded %v, want %s left unloaded", got, a)
}
}
}
}
func TestADataPathLoadsTheShippedSetWhole(t *testing.T) {
f, err := New(WithDataPath(writeData(t, map[string]string{"x": `"y"`})))
if err != nil {
t.Fatalf("New() = %v", err)
}
if got, want := loadedCategories(f), loadedCategories(newShippedWhole(t, WithDataPath(writeData(t, map[string]string{"x": `"y"`})))); !reflect.DeepEqual(got, want) {
t.Fatalf("loaded %v, want %v", got, want)
}
}
func TestOnDemandRendersAsTheWholeLoad(t *testing.T) {
whole := newShippedWhole(t)
paths := whole.List()
lazy, err := New()
if err != nil {
t.Fatalf("New() = %v", err)
}
if got := lazy.List(); !reflect.DeepEqual(got, paths) {
t.Fatalf("List() on demand = %v, want %v", got, paths)
}
a, err := New(WithSeed(7))
if err != nil {
t.Fatal(err)
}
b := newShippedWhole(t, WithSeed(7))
for _, p := range paths {
for range 3 {
got, gotErr := a.Fake(p)
want, wantErr := b.Fake(p)
if got != want || (gotErr == nil) != (wantErr == nil) {
t.Fatalf("Fake(%q) on demand = %q, %v; whole = %q, %v", p, got, gotErr, want, wantErr)
}
}
}
}
func TestEveryShippedCategoryLoadsAlone(t *testing.T) {
for p := range shippedIndex {
f, err := New()
if err != nil {
t.Fatalf("New() = %v", err)
}
if _, err := f.Fake(p); err != nil {
t.Errorf("Fake(%q) on a fresh New() = %v", p, err)
}
}
}
func TestListRunsBesideAnOnDemandLoad(t *testing.T) {
f, err := New()
if err != nil {
t.Fatalf("New() = %v", err)
}
var wg sync.WaitGroup
for _, p := range []string{"sv_SE.person", "geo.US.address", "misc.territory"} {
wg.Add(2)
go func() {
defer wg.Done()
if _, err := f.Fake(p); err != nil {
t.Error(err)
}
}()
go func() {
defer wg.Done()
f.List()
}()
}
wg.Wait()
}