Skip to content

Commit a3bf873

Browse files
authored
#1, check duplicated definitions of a field (#4)
1 parent 82b62b0 commit a3bf873

File tree

2 files changed

+208
-6
lines changed

2 files changed

+208
-6
lines changed

def/define.go

+43-6
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@ import (
1818
// Associations
1919
// Multilevel Fields
2020

21-
// TODO: check field duplicate definitions
2221
// TODO: generate association tree and check associations circle
2322

2423
const (
25-
invalidFieldNameErr = "invalid field name %s to define factory of %s"
26-
invalidFieldValueTypeErr = "cannot use value (type %v) as type %v of field %s to define factory of %s"
27-
nestedAssociationErr = "association %s error: nested associations isn't allowed"
28-
nestedTraitErr = "Trait %s error: nested traits is not allowed"
29-
callbackInAssociationErr = "%s is not allowed in Associations"
24+
invalidFieldNameErr = "invalid field name %s to define factory of %s"
25+
invalidFieldValueTypeErr = "cannot use value (type %v) as type %v of field %s to define factory of %s"
26+
nestedAssociationErr = "association %s error: nested associations isn't allowed"
27+
nestedTraitErr = "Trait %s error: nested traits is not allowed"
28+
callbackInAssociationErr = "%s is not allowed in Associations"
29+
duplicateFieldDefinitionErr = "duplicate definition of field %s"
3030
)
3131

3232
func newDefaultFactory(model interface{}, table string) *factory.Factory {
@@ -88,6 +88,10 @@ func Field(name string, value interface{}) definitionOption {
8888
return fmt.Errorf(invalidFieldValueTypeErr, valueType, field.Type, name, f.ModelType.Name())
8989
}
9090

91+
if ok := definedField(f, name); ok {
92+
return fmt.Errorf(duplicateFieldDefinitionErr, name)
93+
}
94+
9195
f.FiledValues[name] = value
9296
return nil
9397
}
@@ -101,6 +105,10 @@ func SequenceField(name string, first int64, value factory.SequenceFieldValue) d
101105
return fmt.Errorf(invalidFieldNameErr, name, f.ModelType.Name())
102106
}
103107

108+
if ok := definedField(f, name); ok {
109+
return fmt.Errorf(duplicateFieldDefinitionErr, name)
110+
}
111+
104112
f.AddSequenceFiledValue(name, first, value)
105113
return nil
106114
}
@@ -113,6 +121,10 @@ func DynamicField(name string, value factory.DynamicFieldValue) definitionOption
113121
return fmt.Errorf(invalidFieldNameErr, name, f.ModelType.Name())
114122
}
115123

124+
if ok := definedField(f, name); ok {
125+
return fmt.Errorf(duplicateFieldDefinitionErr, name)
126+
}
127+
116128
f.DynamicFieldValues[name] = value
117129
return nil
118130
}
@@ -145,6 +157,10 @@ func Association(name, referenceField, associationReferenceField string, origina
145157
}
146158
}
147159

160+
if ok := definedField(f, name); ok {
161+
return fmt.Errorf(duplicateFieldDefinitionErr, name)
162+
}
163+
148164
f.AssociationFieldValues[name] = associationFieldValue
149165

150166
return nil
@@ -310,3 +326,24 @@ func structFieldByName(typ reflect.Type, name string) (*reflect.StructField, boo
310326

311327
return field, true
312328
}
329+
330+
func definedField(f *factory.Factory, name string) bool {
331+
// FiledValues
332+
if _, ok := f.FiledValues[name]; ok {
333+
return true
334+
}
335+
// SequenceFiledValues
336+
if _, ok := f.SequenceFiledValues[name]; ok {
337+
return true
338+
}
339+
// DynamicFieldValues
340+
if _, ok := f.DynamicFieldValues[name]; ok {
341+
return true
342+
}
343+
// AssociationFieldValues
344+
if _, ok := f.AssociationFieldValues[name]; ok {
345+
return true
346+
}
347+
348+
return false
349+
}

def/define_test.go

+165
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
package def_test
2+
3+
import (
4+
"strings"
5+
"testing"
6+
7+
"github.com/nauyey/factory/def"
8+
)
9+
10+
type testUser struct {
11+
ID int64
12+
Name string
13+
NickName string
14+
Age int32
15+
Country string
16+
}
17+
18+
type testBlog struct {
19+
ID int64
20+
Title string
21+
Content string
22+
AuthorID int64
23+
Author *testUser
24+
}
25+
26+
func TestDuplicateDefinition(t *testing.T) {
27+
const duplicateDefinitionErr = "duplicate definition of field"
28+
29+
// test def.Field
30+
(func() {
31+
defer func() {
32+
err := recover()
33+
if err == nil {
34+
t.Fatalf("def.NewFactory should panic by duplicate field definition")
35+
}
36+
if ok := strings.Contains(err.(error).Error(), duplicateDefinitionErr); !ok {
37+
t.Fatalf("expects err: \"%s\" contains \"%s\"", err.(error).Error(), duplicateDefinitionErr)
38+
}
39+
}()
40+
41+
def.NewFactory(testUser{}, "",
42+
def.Field("Name", "test name"),
43+
def.Field("Name", "test name 2"),
44+
)
45+
})()
46+
47+
// test def.SequenceField
48+
(func() {
49+
defer func() {
50+
err := recover()
51+
if err == nil {
52+
t.Fatalf("def.NewFactory should panic by duplicate field definition")
53+
}
54+
if ok := strings.Contains(err.(error).Error(), duplicateDefinitionErr); !ok {
55+
t.Fatalf("expects err: \"%s\" contains \"%s\"", err.(error).Error(), duplicateDefinitionErr)
56+
}
57+
}()
58+
59+
def.NewFactory(testUser{}, "",
60+
def.SequenceField("ID", 1, func(n int64) (interface{}, error) {
61+
return n, nil
62+
}),
63+
def.SequenceField("ID", 10, func(n int64) (interface{}, error) {
64+
return n, nil
65+
}),
66+
)
67+
})()
68+
69+
// test def.DynamicField
70+
(func() {
71+
defer func() {
72+
err := recover()
73+
if err == nil {
74+
t.Fatalf("def.NewFactory should panic by duplicate field definition")
75+
}
76+
if ok := strings.Contains(err.(error).Error(), duplicateDefinitionErr); !ok {
77+
t.Fatalf("expects err: \"%s\" contains \"%s\"", err.(error).Error(), duplicateDefinitionErr)
78+
}
79+
}()
80+
81+
def.NewFactory(testUser{}, "",
82+
def.DynamicField("Age", func(model interface{}) (interface{}, error) {
83+
return 16, nil
84+
}),
85+
def.DynamicField("Age", func(model interface{}) (interface{}, error) {
86+
return 16, nil
87+
}),
88+
)
89+
})()
90+
91+
// test def.Association
92+
(func() {
93+
defer func() {
94+
err := recover()
95+
if err == nil {
96+
t.Fatalf("def.NewFactory should panic by duplicate field definition")
97+
}
98+
if ok := strings.Contains(err.(error).Error(), duplicateDefinitionErr); !ok {
99+
t.Fatalf("expects err: \"%s\" contains \"%s\"", err.(error).Error(), duplicateDefinitionErr)
100+
}
101+
}()
102+
103+
// define user factory
104+
userFactory := def.NewFactory(testUser{}, "")
105+
106+
def.NewFactory(testBlog{}, "",
107+
def.Association("Author", "AuthorID", "ID", userFactory,
108+
def.Field("Name", "blog author name"),
109+
),
110+
def.Association("Author", "AuthorID", "ID", userFactory,
111+
def.Field("Name", "blog author name"),
112+
),
113+
)
114+
})()
115+
116+
// test mixed duplication
117+
(func() {
118+
defer func() {
119+
err := recover()
120+
if err == nil {
121+
t.Fatalf("def.NewFactory should panic by duplicate field definition")
122+
}
123+
if ok := strings.Contains(err.(error).Error(), duplicateDefinitionErr); !ok {
124+
t.Fatalf("expects err: \"%s\" contains \"%s\"", err.(error).Error(), duplicateDefinitionErr)
125+
}
126+
}()
127+
128+
def.NewFactory(testUser{}, "",
129+
def.Field("ID", int64(20)),
130+
def.SequenceField("ID", 10, func(n int64) (interface{}, error) {
131+
return n, nil
132+
}),
133+
)
134+
})()
135+
136+
// test duplication in def.Trait
137+
(func() {
138+
defer func() {
139+
err := recover()
140+
if err == nil {
141+
t.Fatalf("def.NewFactory should panic by duplicate field definition")
142+
}
143+
if ok := strings.Contains(err.(error).Error(), duplicateDefinitionErr); !ok {
144+
t.Fatalf("expects err: \"%s\" contains \"%s\"", err.(error).Error(), duplicateDefinitionErr)
145+
}
146+
}()
147+
148+
def.NewFactory(testUser{}, "",
149+
def.Trait("Chinese",
150+
def.Field("Name", "小明"),
151+
def.Field("Name", "test name"),
152+
def.Field("Country", "China"),
153+
),
154+
)
155+
})()
156+
157+
// test def.Trait overrides definitions in def.NewFactory will not panic
158+
def.NewFactory(testUser{}, "",
159+
def.Field("Name", "test name"),
160+
def.Trait("Chinese",
161+
def.Field("Name", "小明"),
162+
def.Field("Country", "China"),
163+
),
164+
)
165+
}

0 commit comments

Comments
 (0)