Add tests model definition and basic fields tests
This commit is contained in:
		
							parent
							
								
									fd9b688084
								
							
						
					
					
						commit
						14724ddeae
					
				| @ -22,7 +22,7 @@ var ( | ||||
| //      gorm.Model
 | ||||
| //    }
 | ||||
| type Model struct { | ||||
| 	ID        uint `gorm:"primary_key"` | ||||
| 	ID        uint `gorm:"primarykey"` | ||||
| 	CreatedAt time.Time | ||||
| 	UpdatedAt time.Time | ||||
| 	DeletedAt *time.Time `gorm:"index"` | ||||
|  | ||||
| @ -54,7 +54,7 @@ func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field { | ||||
| 		Creatable:   true, | ||||
| 		Updatable:   true, | ||||
| 		Tag:         fieldStruct.Tag, | ||||
| 		TagSettings: parseTagSetting(fieldStruct.Tag), | ||||
| 		TagSettings: ParseTagSetting(fieldStruct.Tag), | ||||
| 	} | ||||
| 
 | ||||
| 	for field.FieldType.Kind() == reflect.Ptr { | ||||
| @ -84,7 +84,7 @@ func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field { | ||||
| 				} | ||||
| 
 | ||||
| 				// copy tag settings from valuer
 | ||||
| 				for key, value := range parseTagSetting(field.FieldType.Field(i).Tag) { | ||||
| 				for key, value := range ParseTagSetting(field.FieldType.Field(i).Tag) { | ||||
| 					if _, ok := field.TagSettings[key]; !ok { | ||||
| 						field.TagSettings[key] = value | ||||
| 					} | ||||
| @ -141,7 +141,7 @@ func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field { | ||||
| 		field.DBDataType = val | ||||
| 	} | ||||
| 
 | ||||
| 	switch fieldValue.Kind() { | ||||
| 	switch fieldValue.Elem().Kind() { | ||||
| 	case reflect.Bool: | ||||
| 		field.DataType = Bool | ||||
| 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||||
| @ -153,7 +153,7 @@ func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field { | ||||
| 	case reflect.String: | ||||
| 		field.DataType = String | ||||
| 	case reflect.Struct: | ||||
| 		if _, ok := fieldValue.Interface().(time.Time); ok { | ||||
| 		if _, ok := fieldValue.Interface().(*time.Time); ok { | ||||
| 			field.DataType = Time | ||||
| 		} | ||||
| 	case reflect.Array, reflect.Slice: | ||||
| @ -176,7 +176,7 @@ func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field { | ||||
| 	} | ||||
| 
 | ||||
| 	if _, ok := field.TagSettings["EMBEDDED"]; ok || fieldStruct.Anonymous { | ||||
| 		field.EmbeddedSchema, schema.err = Parse(fieldValue, sync.Map{}, schema.namer) | ||||
| 		field.EmbeddedSchema, schema.err = Parse(fieldValue.Interface(), &sync.Map{}, schema.namer) | ||||
| 		for _, ef := range field.EmbeddedSchema.Fields { | ||||
| 			ef.BindNames = append([]string{fieldStruct.Name}, ef.BindNames...) | ||||
| 
 | ||||
|  | ||||
| @ -6,6 +6,8 @@ import ( | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| 
 | ||||
| 	"github.com/jinzhu/gorm/logger" | ||||
| ) | ||||
| 
 | ||||
| type Schema struct { | ||||
| @ -20,7 +22,7 @@ type Schema struct { | ||||
| 	Relationships           Relationships | ||||
| 	err                     error | ||||
| 	namer                   Namer | ||||
| 	cacheStore              sync.Map | ||||
| 	cacheStore              *sync.Map | ||||
| } | ||||
| 
 | ||||
| func (schema Schema) String() string { | ||||
| @ -38,7 +40,7 @@ func (schema Schema) LookUpField(name string) *Field { | ||||
| } | ||||
| 
 | ||||
| // get data type from dialector
 | ||||
| func Parse(dest interface{}, cacheStore sync.Map, namer Namer) (*Schema, error) { | ||||
| func Parse(dest interface{}, cacheStore *sync.Map, namer Namer) (*Schema, error) { | ||||
| 	modelType := reflect.ValueOf(dest).Type() | ||||
| 	for modelType.Kind() == reflect.Slice || modelType.Kind() == reflect.Ptr { | ||||
| 		modelType = modelType.Elem() | ||||
| @ -62,10 +64,12 @@ func Parse(dest interface{}, cacheStore sync.Map, namer Namer) (*Schema, error) | ||||
| 		FieldsByName:   map[string]*Field{}, | ||||
| 		FieldsByDBName: map[string]*Field{}, | ||||
| 		cacheStore:     cacheStore, | ||||
| 		namer:          namer, | ||||
| 	} | ||||
| 
 | ||||
| 	defer func() { | ||||
| 		if schema.err != nil { | ||||
| 			logger.Default.Error(schema.err.Error()) | ||||
| 			cacheStore.Delete(modelType) | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
							
								
								
									
										78
									
								
								schema/schema_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								schema/schema_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,78 @@ | ||||
| package schema_test | ||||
| 
 | ||||
| import ( | ||||
| 	"reflect" | ||||
| 	"sync" | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/jinzhu/gorm/schema" | ||||
| 	"github.com/jinzhu/gorm/tests" | ||||
| ) | ||||
| 
 | ||||
| func TestParseSchema(t *testing.T) { | ||||
| 	cacheMap := sync.Map{} | ||||
| 	user, err := schema.Parse(&tests.User{}, &cacheMap, schema.NamingStrategy{}) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("failed to parse user, got error %v", err) | ||||
| 	} | ||||
| 
 | ||||
| 	checkSchemaFields(t, user) | ||||
| } | ||||
| 
 | ||||
| func checkSchemaFields(t *testing.T, s *schema.Schema) { | ||||
| 	fields := []schema.Field{ | ||||
| 		schema.Field{ | ||||
| 			Name: "ID", DBName: "id", BindNames: []string{"Model", "ID"}, DataType: schema.Uint, | ||||
| 			PrimaryKey: true, Tag: `gorm:"primarykey"`, TagSettings: map[string]string{"PRIMARYKEY": "PRIMARYKEY"}, | ||||
| 		}, | ||||
| 		schema.Field{Name: "CreatedAt", DBName: "created_at", BindNames: []string{"Model", "CreatedAt"}, DataType: schema.Time}, | ||||
| 		schema.Field{Name: "UpdatedAt", DBName: "updated_at", BindNames: []string{"Model", "UpdatedAt"}, DataType: schema.Time}, | ||||
| 		schema.Field{Name: "DeletedAt", DBName: "deleted_at", BindNames: []string{"Model", "DeletedAt"}, Tag: `gorm:"index"`, DataType: schema.Time}, | ||||
| 		schema.Field{Name: "Name", DBName: "name", BindNames: []string{"Name"}, DataType: schema.String}, | ||||
| 		schema.Field{Name: "Age", DBName: "age", BindNames: []string{"Age"}, DataType: schema.Uint}, | ||||
| 		schema.Field{Name: "Birthday", DBName: "birthday", BindNames: []string{"Birthday"}, DataType: schema.Time}, | ||||
| 		schema.Field{Name: "CompanyID", DBName: "company_id", BindNames: []string{"CompanyID"}, DataType: schema.Int}, | ||||
| 		schema.Field{Name: "ManagerID", DBName: "manager_id", BindNames: []string{"ManagerID"}, DataType: schema.Uint}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, f := range fields { | ||||
| 		f.Creatable = true | ||||
| 		f.Updatable = true | ||||
| 		if f.TagSettings == nil { | ||||
| 			if f.Tag != "" { | ||||
| 				f.TagSettings = schema.ParseTagSetting(f.Tag) | ||||
| 			} else { | ||||
| 				f.TagSettings = map[string]string{} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if foundField, ok := s.FieldsByName[f.Name]; !ok { | ||||
| 			t.Errorf("schema %v failed to look up field with name %v", s, f.Name) | ||||
| 		} else { | ||||
| 			checkSchemaField(t, foundField, f) | ||||
| 
 | ||||
| 			if field, ok := s.FieldsByDBName[f.DBName]; !ok || foundField != field { | ||||
| 				t.Errorf("schema %v failed to look up field with dbname %v", s, f.DBName) | ||||
| 			} | ||||
| 
 | ||||
| 			for _, name := range []string{f.DBName, f.Name} { | ||||
| 				if field := s.LookUpField(name); field == nil || foundField != field { | ||||
| 					t.Errorf("schema %v failed to look up field with dbname %v", s, f.DBName) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func checkSchemaField(t *testing.T, parsedField *schema.Field, field schema.Field) { | ||||
| 	equalFieldNames := []string{"Name", "DBName", "BindNames", "DataType", "DBDataType", "PrimaryKey", "AutoIncrement", "Creatable", "Updatable", "HasDefaultValue", "DefaultValue", "NotNull", "Unique", "Comment", "Size", "Precision", "Tag", "TagSettings"} | ||||
| 
 | ||||
| 	for _, name := range equalFieldNames { | ||||
| 		got := reflect.ValueOf(parsedField).Elem().FieldByName(name).Interface() | ||||
| 		expects := reflect.ValueOf(field).FieldByName(name).Interface() | ||||
| 		if !reflect.DeepEqual(got, expects) { | ||||
| 			t.Errorf("%v is not equal, expects: %v, got %v", name, expects, got) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @ -6,7 +6,7 @@ import ( | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| func parseTagSetting(tags reflect.StructTag) map[string]string { | ||||
| func ParseTagSetting(tags reflect.StructTag) map[string]string { | ||||
| 	setting := map[string]string{} | ||||
| 
 | ||||
| 	for _, value := range strings.Split(tags.Get("gorm"), ";") { | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| package gorm_test | ||||
| package tests_test | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
							
								
								
									
										58
									
								
								tests/model.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								tests/model.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,58 @@ | ||||
| package tests | ||||
| 
 | ||||
| import ( | ||||
| 	"database/sql" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/jinzhu/gorm" | ||||
| ) | ||||
| 
 | ||||
| // User has one `Account` (has one), many `Pets` (has many) and `Toys` (has many - polymorphic)
 | ||||
| // He works in a Company (belongs to), he has a Manager (belongs to - single-table), and also managed a Team (has many - single-table)
 | ||||
| // He speaks many languages (many to many) and has many friends (many to many - single-table)
 | ||||
| // His pet also has one Toy (has one - polymorphic)
 | ||||
| type User struct { | ||||
| 	gorm.Model | ||||
| 	Name      string | ||||
| 	Age       uint | ||||
| 	Birthday  *time.Time | ||||
| 	Account   Account | ||||
| 	Pets      []*Pet | ||||
| 	Toys      []Toy `gorm:"polymorphic:Owner"` | ||||
| 	CompanyID *int | ||||
| 	Company   Company | ||||
| 	ManagerID uint | ||||
| 	Manager   *User | ||||
| 	Team      []User     `foreignkey:ManagerID` | ||||
| 	Friends   []*User    `gorm:"many2many:user_friends"` | ||||
| 	Languages []Language `gorm:"many2many:user_speaks"` | ||||
| } | ||||
| 
 | ||||
| type Account struct { | ||||
| 	gorm.Model | ||||
| 	UserID sql.NullInt64 | ||||
| 	Number string | ||||
| } | ||||
| 
 | ||||
| type Pet struct { | ||||
| 	gorm.Model | ||||
| 	UserID uint | ||||
| 	Name   string | ||||
| 	Toy    Toy `gorm:"polymorphic:Owner;"` | ||||
| } | ||||
| 
 | ||||
| type Toy struct { | ||||
| 	gorm.Model | ||||
| 	OwnerID   string | ||||
| 	OwnerType string | ||||
| } | ||||
| 
 | ||||
| type Company struct { | ||||
| 	ID   uint | ||||
| 	Name string | ||||
| } | ||||
| 
 | ||||
| type Language struct { | ||||
| 	Code string `gorm:primarykey` | ||||
| 	Name string | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Jinzhu
						Jinzhu