Struct-filling #14
+14
-11
@@ -171,17 +171,20 @@ func TestIsTemplate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for arg, want := range map[string]string{
|
for arg, want := range map[string]string{
|
||||||
"[abc]": `holds a "["`,
|
"[abc]": `holds a "["`,
|
||||||
"[abc].field": `holds a "["`,
|
"[abc].field": `holds a "["`,
|
||||||
"x[1]": `holds a "["`,
|
"x[1]": `holds a "["`,
|
||||||
"a]b": `holds a "]"`,
|
"a]b": `holds a "]"`,
|
||||||
"a}b": `holds a "}"`,
|
"a}b": `holds a "}"`,
|
||||||
`"abc`: `holds a "\""`,
|
`"abc`: `holds a "\""`,
|
||||||
`"a]b`: `holds a "\""`, // the opener the reader typed, not the bracket behind it
|
`"a]b`: `holds a "\""`, // the opener the reader typed, not the bracket behind it
|
||||||
"{/sv_SE.person.last}": "{/sv_SE.person.last} is the path sv_SE.person.last written as a template; write sv_SE.person.last",
|
"{/sv_SE.person.last}": "{/sv_SE.person.last} is the path sv_SE.person.last written as a template; write sv_SE.person.last",
|
||||||
`"{/sv_SE.person}"`: "write sv_SE.person",
|
`"{/sv_SE.person}"`: "write sv_SE.person",
|
||||||
"{.person.last}": "write person.last",
|
"{.person.last}": "write person.last",
|
||||||
"/sv_SE.person": "write sv_SE.person",
|
"/sv_SE.person": "write sv_SE.person",
|
||||||
|
` "{/sv_SE.person}"`: "write sv_SE.person",
|
||||||
|
`{"format":"{/sv_SE.person}"}`: "write sv_SE.person",
|
||||||
|
"//sv_SE.person": "write sv_SE.person",
|
||||||
} {
|
} {
|
||||||
if _, err := IsTemplate(arg); err == nil || !strings.Contains(err.Error(), want) {
|
if _, err := IsTemplate(arg); err == nil || !strings.Contains(err.Error(), want) {
|
||||||
t.Errorf("IsTemplate(%q) = %v; want it rejected naming %s", arg, err, want)
|
t.Errorf("IsTemplate(%q) = %v; want it rejected naming %s", arg, err, want)
|
||||||
|
|||||||
@@ -118,6 +118,13 @@ func TestFakeIsSafeForConcurrentUse(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
tmpl.Fake()
|
tmpl.Fake()
|
||||||
|
var u struct {
|
||||||
|
Last string `fake:"sv_SE.person.last"`
|
||||||
|
}
|
||||||
|
if err := f.FakeStruct(&u); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|||||||
+29
-8
@@ -63,7 +63,8 @@ func TestFakeStructFillsTaggedFields(t *testing.T) {
|
|||||||
zips := map[string]string{"Stockholm": "111 22", "Tranås": "573 31"}
|
zips := map[string]string{"Stockholm": "111 22", "Tranås": "573 31"}
|
||||||
actives, nils := 0, 0
|
actives, nils := 0, 0
|
||||||
for i := 0; i < 100; i++ {
|
for i := 0; i < 100; i++ {
|
||||||
u, twin := structUser{Note: "keep"}, structUser{Note: "keep"}
|
oldNick, oldTwinNick := "old", "old"
|
||||||
|
u, twin := structUser{Nick: &oldNick, Note: "keep"}, structUser{Nick: &oldTwinNick, Note: "keep"}
|
||||||
if err := a.FakeStruct(&u); err != nil {
|
if err := a.FakeStruct(&u); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -79,7 +80,7 @@ func TestFakeStructFillsTaggedFields(t *testing.T) {
|
|||||||
t.Fatalf("places %+v, %+v, want each nested struct one place, the pointer allocated", u.Home, u.Work)
|
t.Fatalf("places %+v, %+v, want each nested struct one place, the pointer allocated", u.Home, u.Work)
|
||||||
case u.ID != int64(i+1) || u.Age < 18 || u.Age > 99 || u.Score < 0 || u.Score > 1 || u.Rank == nil || (*u.Rank != 1 && *u.Rank != 2):
|
case u.ID != int64(i+1) || u.Age < 18 || u.Age > 99 || u.Score < 0 || u.Score > 1 || u.Rank == nil || (*u.Rank != 1 && *u.Rank != 2):
|
||||||
t.Fatalf("typed fields %+v, want each the value its tag draws", u)
|
t.Fatalf("typed fields %+v, want each the value its tag draws", u)
|
||||||
case u.Nick != nil && *u.Nick != "bo", u.Note != "keep", u.hidden != (structPlace{}), u.Skip != nil:
|
case u.Nick != nil && *u.Nick != "bo", u.Note != "keep", u.hidden != (structPlace{}), u.Skip != nil, oldNick != "old":
|
||||||
t.Fatalf("%+v: want Nick nil or bo, and the untagged fields left as they were", u)
|
t.Fatalf("%+v: want Nick nil or bo, and the untagged fields left as they were", u)
|
||||||
}
|
}
|
||||||
if u.Active {
|
if u.Active {
|
||||||
@@ -173,16 +174,16 @@ func TestFakeStructErrors(t *testing.T) {
|
|||||||
}{}, `"Ada" is not an integer`},
|
}{}, `"Ada" is not an integer`},
|
||||||
{&struct {
|
{&struct {
|
||||||
A int8 `fake:"{int(0,300)}"`
|
A int8 `fake:"{int(0,300)}"`
|
||||||
}{}, `"{int(0,300)}" can reach 300, past int8; make it int64`},
|
}{}, `"{int(0,300)}" is not proven within int8; make it int64`},
|
||||||
{&struct {
|
{&struct {
|
||||||
A uint `fake:"{int(-1,5)}"`
|
A uint `fake:"{int(-1,5)}"`
|
||||||
}{}, `"{int(-1,5)}" can reach -1, past uint; make it int64`},
|
}{}, `"{int(-1,5)}" is not proven within uint; make it int64`},
|
||||||
{&struct {
|
{&struct {
|
||||||
A float32 `fake:"[\"1\",\"1e39\"]"`
|
A float32 `fake:"[\"1\",\"1e39\"]"`
|
||||||
}{}, `"1e39" can reach 1e+39, past float32; make it float64`},
|
}{}, `"1e39" is not proven within float32; make it float64`},
|
||||||
{&struct {
|
{&struct {
|
||||||
A int32 `fake:"{seq()}"`
|
A int32 `fake:"{seq()}"`
|
||||||
}{}, `"{seq()}" can reach 9.223372036854776e+18, past int32; make it int64`},
|
}{}, `"{seq()}" is not proven within int32; make it int64`},
|
||||||
{&struct {
|
{&struct {
|
||||||
A bool `fake:"{int(0,1)}"`
|
A bool `fake:"{int(0,1)}"`
|
||||||
}{}, "prints an integer, not a boolean"},
|
}{}, "prints an integer, not a boolean"},
|
||||||
@@ -213,7 +214,7 @@ func TestFakeStructErrors(t *testing.T) {
|
|||||||
{&struct {
|
{&struct {
|
||||||
A string `fake:"-"`
|
A string `fake:"-"`
|
||||||
}{}, `fake:"-" leaves a struct field unfilled`},
|
}{}, `fake:"-" leaves a struct field unfilled`},
|
||||||
{&struct{ *structGiven }{}, "an embedded pointer to an unexported type"},
|
{&struct{ *structGiven }{}, "an unexported embedded pointer field cannot be set"},
|
||||||
{&struct {
|
{&struct {
|
||||||
structGiven
|
structGiven
|
||||||
First string `fake:"person.last"`
|
First string `fake:"person.last"`
|
||||||
@@ -231,8 +232,28 @@ func TestFakeStructErrors(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}{}, ": struct.Trip.A (int): {digits(3)} prints text"},
|
}{}, ": struct.Trip.A (int): {digits(3)} prints text"},
|
||||||
} {
|
} {
|
||||||
if err := f.FakeStruct(c.v); err == nil || !strings.Contains(err.Error(), c.want) {
|
err := f.FakeStruct(c.v)
|
||||||
|
if err == nil || !strings.Contains(err.Error(), c.want) {
|
||||||
t.Errorf("FakeStruct(%T) = %v, want an error containing %q", c.v, err, c.want)
|
t.Errorf("FakeStruct(%T) = %v, want an error containing %q", c.v, err, c.want)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if again := f.FakeStruct(c.v); again == nil || again.Error() != err.Error() {
|
||||||
|
t.Errorf("FakeStruct(%T) again = %v, want the first call's error, %v", c.v, again, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFakeStructBoundsTheRecordsATypeReaches(t *testing.T) {
|
||||||
|
f := structData(t)
|
||||||
|
tree := reflect.TypeOf(structPlace{})
|
||||||
|
for depth := 1; depth <= 10; depth++ {
|
||||||
|
tree = reflect.StructOf([]reflect.StructField{{Name: "L", Type: reflect.PointerTo(tree)}, {Name: "R", Type: reflect.PointerTo(tree)}})
|
||||||
|
err := f.FakeStruct(reflect.New(tree).Interface())
|
||||||
|
switch {
|
||||||
|
case depth < 10 && err != nil:
|
||||||
|
t.Fatalf("a tree %d deep, %d records: FakeStruct = %v, want it filled", depth, 1<<(depth+1)-1, err)
|
||||||
|
case depth == 10 && (err == nil || !strings.Contains(err.Error(), "more than 1024 records") || !strings.Contains(err.Error(), `fake:"-"`)):
|
||||||
|
t.Errorf("a tree 10 deep, 2047 records: FakeStruct = %v, want it refused naming the cap and fake:\"-\"", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user