Skip to content

Commit

Permalink
#1, check duplicated definitions of a field (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
nauyey authored Jan 15, 2018
1 parent 82b62b0 commit a3bf873
Show file tree
Hide file tree
Showing 2 changed files with 208 additions and 6 deletions.
49 changes: 43 additions & 6 deletions def/define.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ import (
// Associations
// Multilevel Fields

// TODO: check field duplicate definitions
// TODO: generate association tree and check associations circle

const (
invalidFieldNameErr = "invalid field name %s to define factory of %s"
invalidFieldValueTypeErr = "cannot use value (type %v) as type %v of field %s to define factory of %s"
nestedAssociationErr = "association %s error: nested associations isn't allowed"
nestedTraitErr = "Trait %s error: nested traits is not allowed"
callbackInAssociationErr = "%s is not allowed in Associations"
invalidFieldNameErr = "invalid field name %s to define factory of %s"
invalidFieldValueTypeErr = "cannot use value (type %v) as type %v of field %s to define factory of %s"
nestedAssociationErr = "association %s error: nested associations isn't allowed"
nestedTraitErr = "Trait %s error: nested traits is not allowed"
callbackInAssociationErr = "%s is not allowed in Associations"
duplicateFieldDefinitionErr = "duplicate definition of field %s"
)

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

if ok := definedField(f, name); ok {
return fmt.Errorf(duplicateFieldDefinitionErr, name)
}

f.FiledValues[name] = value
return nil
}
Expand All @@ -101,6 +105,10 @@ func SequenceField(name string, first int64, value factory.SequenceFieldValue) d
return fmt.Errorf(invalidFieldNameErr, name, f.ModelType.Name())
}

if ok := definedField(f, name); ok {
return fmt.Errorf(duplicateFieldDefinitionErr, name)
}

f.AddSequenceFiledValue(name, first, value)
return nil
}
Expand All @@ -113,6 +121,10 @@ func DynamicField(name string, value factory.DynamicFieldValue) definitionOption
return fmt.Errorf(invalidFieldNameErr, name, f.ModelType.Name())
}

if ok := definedField(f, name); ok {
return fmt.Errorf(duplicateFieldDefinitionErr, name)
}

f.DynamicFieldValues[name] = value
return nil
}
Expand Down Expand Up @@ -145,6 +157,10 @@ func Association(name, referenceField, associationReferenceField string, origina
}
}

if ok := definedField(f, name); ok {
return fmt.Errorf(duplicateFieldDefinitionErr, name)
}

f.AssociationFieldValues[name] = associationFieldValue

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

return field, true
}

func definedField(f *factory.Factory, name string) bool {
// FiledValues
if _, ok := f.FiledValues[name]; ok {
return true
}
// SequenceFiledValues
if _, ok := f.SequenceFiledValues[name]; ok {
return true
}
// DynamicFieldValues
if _, ok := f.DynamicFieldValues[name]; ok {
return true
}
// AssociationFieldValues
if _, ok := f.AssociationFieldValues[name]; ok {
return true
}

return false
}
165 changes: 165 additions & 0 deletions def/define_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package def_test

import (
"strings"
"testing"

"github.com/nauyey/factory/def"
)

type testUser struct {
ID int64
Name string
NickName string
Age int32
Country string
}

type testBlog struct {
ID int64
Title string
Content string
AuthorID int64
Author *testUser
}

func TestDuplicateDefinition(t *testing.T) {
const duplicateDefinitionErr = "duplicate definition of field"

// test def.Field
(func() {
defer func() {
err := recover()
if err == nil {
t.Fatalf("def.NewFactory should panic by duplicate field definition")
}
if ok := strings.Contains(err.(error).Error(), duplicateDefinitionErr); !ok {
t.Fatalf("expects err: \"%s\" contains \"%s\"", err.(error).Error(), duplicateDefinitionErr)
}
}()

def.NewFactory(testUser{}, "",
def.Field("Name", "test name"),
def.Field("Name", "test name 2"),
)
})()

// test def.SequenceField
(func() {
defer func() {
err := recover()
if err == nil {
t.Fatalf("def.NewFactory should panic by duplicate field definition")
}
if ok := strings.Contains(err.(error).Error(), duplicateDefinitionErr); !ok {
t.Fatalf("expects err: \"%s\" contains \"%s\"", err.(error).Error(), duplicateDefinitionErr)
}
}()

def.NewFactory(testUser{}, "",
def.SequenceField("ID", 1, func(n int64) (interface{}, error) {
return n, nil
}),
def.SequenceField("ID", 10, func(n int64) (interface{}, error) {
return n, nil
}),
)
})()

// test def.DynamicField
(func() {
defer func() {
err := recover()
if err == nil {
t.Fatalf("def.NewFactory should panic by duplicate field definition")
}
if ok := strings.Contains(err.(error).Error(), duplicateDefinitionErr); !ok {
t.Fatalf("expects err: \"%s\" contains \"%s\"", err.(error).Error(), duplicateDefinitionErr)
}
}()

def.NewFactory(testUser{}, "",
def.DynamicField("Age", func(model interface{}) (interface{}, error) {
return 16, nil
}),
def.DynamicField("Age", func(model interface{}) (interface{}, error) {
return 16, nil
}),
)
})()

// test def.Association
(func() {
defer func() {
err := recover()
if err == nil {
t.Fatalf("def.NewFactory should panic by duplicate field definition")
}
if ok := strings.Contains(err.(error).Error(), duplicateDefinitionErr); !ok {
t.Fatalf("expects err: \"%s\" contains \"%s\"", err.(error).Error(), duplicateDefinitionErr)
}
}()

// define user factory
userFactory := def.NewFactory(testUser{}, "")

def.NewFactory(testBlog{}, "",
def.Association("Author", "AuthorID", "ID", userFactory,
def.Field("Name", "blog author name"),
),
def.Association("Author", "AuthorID", "ID", userFactory,
def.Field("Name", "blog author name"),
),
)
})()

// test mixed duplication
(func() {
defer func() {
err := recover()
if err == nil {
t.Fatalf("def.NewFactory should panic by duplicate field definition")
}
if ok := strings.Contains(err.(error).Error(), duplicateDefinitionErr); !ok {
t.Fatalf("expects err: \"%s\" contains \"%s\"", err.(error).Error(), duplicateDefinitionErr)
}
}()

def.NewFactory(testUser{}, "",
def.Field("ID", int64(20)),
def.SequenceField("ID", 10, func(n int64) (interface{}, error) {
return n, nil
}),
)
})()

// test duplication in def.Trait
(func() {
defer func() {
err := recover()
if err == nil {
t.Fatalf("def.NewFactory should panic by duplicate field definition")
}
if ok := strings.Contains(err.(error).Error(), duplicateDefinitionErr); !ok {
t.Fatalf("expects err: \"%s\" contains \"%s\"", err.(error).Error(), duplicateDefinitionErr)
}
}()

def.NewFactory(testUser{}, "",
def.Trait("Chinese",
def.Field("Name", "小明"),
def.Field("Name", "test name"),
def.Field("Country", "China"),
),
)
})()

// test def.Trait overrides definitions in def.NewFactory will not panic
def.NewFactory(testUser{}, "",
def.Field("Name", "test name"),
def.Trait("Chinese",
def.Field("Name", "小明"),
def.Field("Country", "China"),
),
)
}

0 comments on commit a3bf873

Please sign in to comment.