github.com/systematiccaos/gorm@v1.22.6/schema/field_test.go (about) 1 package schema_test 2 3 import ( 4 "database/sql" 5 "reflect" 6 "sync" 7 "testing" 8 "time" 9 10 "github.com/systematiccaos/gorm" 11 "github.com/systematiccaos/gorm/schema" 12 "github.com/systematiccaos/gorm/utils/tests" 13 ) 14 15 func TestFieldValuerAndSetter(t *testing.T) { 16 var ( 17 userSchema, _ = schema.Parse(&tests.User{}, &sync.Map{}, schema.NamingStrategy{}) 18 user = tests.User{ 19 Model: gorm.Model{ 20 ID: 10, 21 CreatedAt: time.Now(), 22 UpdatedAt: time.Now(), 23 DeletedAt: gorm.DeletedAt{Time: time.Now(), Valid: true}, 24 }, 25 Name: "valuer_and_setter", 26 Age: 18, 27 Birthday: tests.Now(), 28 Active: true, 29 } 30 reflectValue = reflect.ValueOf(&user) 31 ) 32 33 // test valuer 34 values := map[string]interface{}{ 35 "name": user.Name, 36 "id": user.ID, 37 "created_at": user.CreatedAt, 38 "updated_at": user.UpdatedAt, 39 "deleted_at": user.DeletedAt, 40 "age": user.Age, 41 "birthday": user.Birthday, 42 "active": true, 43 } 44 checkField(t, userSchema, reflectValue, values) 45 46 var f *bool 47 // test setter 48 newValues := map[string]interface{}{ 49 "name": "valuer_and_setter_2", 50 "id": 2, 51 "created_at": time.Now(), 52 "updated_at": nil, 53 "deleted_at": time.Now(), 54 "age": 20, 55 "birthday": time.Now(), 56 "active": f, 57 } 58 59 for k, v := range newValues { 60 if err := userSchema.FieldsByDBName[k].Set(reflectValue, v); err != nil { 61 t.Errorf("no error should happen when assign value to field %v, but got %v", k, err) 62 } 63 } 64 newValues["updated_at"] = time.Time{} 65 newValues["active"] = false 66 checkField(t, userSchema, reflectValue, newValues) 67 68 // test valuer and other type 69 age := myint(10) 70 var nilTime *time.Time 71 newValues2 := map[string]interface{}{ 72 "name": sql.NullString{String: "valuer_and_setter_3", Valid: true}, 73 "id": &sql.NullInt64{Int64: 3, Valid: true}, 74 "created_at": tests.Now(), 75 "updated_at": nilTime, 76 "deleted_at": time.Now(), 77 "age": &age, 78 "birthday": mytime(time.Now()), 79 "active": mybool(true), 80 } 81 82 for k, v := range newValues2 { 83 if err := userSchema.FieldsByDBName[k].Set(reflectValue, v); err != nil { 84 t.Errorf("no error should happen when assign value to field %v, but got %v", k, err) 85 } 86 } 87 newValues2["updated_at"] = time.Time{} 88 checkField(t, userSchema, reflectValue, newValues2) 89 } 90 91 func TestPointerFieldValuerAndSetter(t *testing.T) { 92 var ( 93 userSchema, _ = schema.Parse(&User{}, &sync.Map{}, schema.NamingStrategy{}) 94 name = "pointer_field_valuer_and_setter" 95 age uint = 18 96 active = true 97 user = User{ 98 Model: &gorm.Model{ 99 ID: 10, 100 CreatedAt: time.Now(), 101 DeletedAt: gorm.DeletedAt{Time: time.Now(), Valid: true}, 102 }, 103 Name: &name, 104 Age: &age, 105 Birthday: tests.Now(), 106 Active: &active, 107 } 108 reflectValue = reflect.ValueOf(&user) 109 ) 110 111 // test valuer 112 values := map[string]interface{}{ 113 "name": user.Name, 114 "id": user.ID, 115 "created_at": user.CreatedAt, 116 "deleted_at": user.DeletedAt, 117 "age": user.Age, 118 "birthday": user.Birthday, 119 "active": true, 120 } 121 checkField(t, userSchema, reflectValue, values) 122 123 // test setter 124 newValues := map[string]interface{}{ 125 "name": "valuer_and_setter_2", 126 "id": 2, 127 "created_at": time.Now(), 128 "deleted_at": time.Now(), 129 "age": 20, 130 "birthday": time.Now(), 131 "active": false, 132 } 133 134 for k, v := range newValues { 135 if err := userSchema.FieldsByDBName[k].Set(reflectValue, v); err != nil { 136 t.Errorf("no error should happen when assign value to field %v, but got %v", k, err) 137 } 138 } 139 checkField(t, userSchema, reflectValue, newValues) 140 141 // test valuer and other type 142 age2 := myint(10) 143 newValues2 := map[string]interface{}{ 144 "name": sql.NullString{String: "valuer_and_setter_3", Valid: true}, 145 "id": &sql.NullInt64{Int64: 3, Valid: true}, 146 "created_at": tests.Now(), 147 "deleted_at": time.Now(), 148 "age": &age2, 149 "birthday": mytime(time.Now()), 150 "active": mybool(true), 151 } 152 153 for k, v := range newValues2 { 154 if err := userSchema.FieldsByDBName[k].Set(reflectValue, v); err != nil { 155 t.Errorf("no error should happen when assign value to field %v, but got %v", k, err) 156 } 157 } 158 checkField(t, userSchema, reflectValue, newValues2) 159 } 160 161 func TestAdvancedDataTypeValuerAndSetter(t *testing.T) { 162 var ( 163 userSchema, _ = schema.Parse(&AdvancedDataTypeUser{}, &sync.Map{}, schema.NamingStrategy{}) 164 name = "advanced_data_type_valuer_and_setter" 165 deletedAt = mytime(time.Now()) 166 isAdmin = mybool(false) 167 user = AdvancedDataTypeUser{ 168 ID: sql.NullInt64{Int64: 10, Valid: true}, 169 Name: &sql.NullString{String: name, Valid: true}, 170 Birthday: sql.NullTime{Time: time.Now(), Valid: true}, 171 RegisteredAt: mytime(time.Now()), 172 DeletedAt: &deletedAt, 173 Active: mybool(true), 174 Admin: &isAdmin, 175 } 176 reflectValue = reflect.ValueOf(&user) 177 ) 178 179 // test valuer 180 values := map[string]interface{}{ 181 "id": user.ID, 182 "name": user.Name, 183 "birthday": user.Birthday, 184 "registered_at": user.RegisteredAt, 185 "deleted_at": user.DeletedAt, 186 "active": user.Active, 187 "admin": user.Admin, 188 } 189 checkField(t, userSchema, reflectValue, values) 190 191 // test setter 192 newDeletedAt := mytime(time.Now()) 193 newIsAdmin := mybool(true) 194 newValues := map[string]interface{}{ 195 "id": sql.NullInt64{Int64: 1, Valid: true}, 196 "name": &sql.NullString{String: name + "rename", Valid: true}, 197 "birthday": time.Now(), 198 "registered_at": mytime(time.Now()), 199 "deleted_at": &newDeletedAt, 200 "active": mybool(false), 201 "admin": &newIsAdmin, 202 } 203 204 for k, v := range newValues { 205 if err := userSchema.FieldsByDBName[k].Set(reflectValue, v); err != nil { 206 t.Errorf("no error should happen when assign value to field %v, but got %v", k, err) 207 } 208 } 209 checkField(t, userSchema, reflectValue, newValues) 210 211 newValues2 := map[string]interface{}{ 212 "id": 5, 213 "name": name + "rename2", 214 "birthday": time.Now(), 215 "registered_at": time.Now(), 216 "deleted_at": time.Now(), 217 "active": true, 218 "admin": false, 219 } 220 221 for k, v := range newValues2 { 222 if err := userSchema.FieldsByDBName[k].Set(reflectValue, v); err != nil { 223 t.Errorf("no error should happen when assign value to field %v, but got %v", k, err) 224 } 225 } 226 checkField(t, userSchema, reflectValue, newValues2) 227 } 228 229 type UserWithPermissionControl struct { 230 ID uint 231 Name string `gorm:"-"` 232 Name2 string `gorm:"->"` 233 Name3 string `gorm:"<-"` 234 Name4 string `gorm:"<-:create"` 235 Name5 string `gorm:"<-:update"` 236 Name6 string `gorm:"<-:create,update"` 237 Name7 string `gorm:"->:false;<-:create,update"` 238 Name8 string `gorm:"->;-:migration"` 239 } 240 241 func TestParseFieldWithPermission(t *testing.T) { 242 user, err := schema.Parse(&UserWithPermissionControl{}, &sync.Map{}, schema.NamingStrategy{}) 243 if err != nil { 244 t.Fatalf("Failed to parse user with permission, got error %v", err) 245 } 246 247 fields := []*schema.Field{ 248 {Name: "ID", DBName: "id", BindNames: []string{"ID"}, DataType: schema.Uint, PrimaryKey: true, Size: 64, Creatable: true, Updatable: true, Readable: true, HasDefaultValue: true, AutoIncrement: true}, 249 {Name: "Name", DBName: "", BindNames: []string{"Name"}, DataType: "", Tag: `gorm:"-"`, Creatable: false, Updatable: false, Readable: false}, 250 {Name: "Name2", DBName: "name2", BindNames: []string{"Name2"}, DataType: schema.String, Tag: `gorm:"->"`, Creatable: false, Updatable: false, Readable: true}, 251 {Name: "Name3", DBName: "name3", BindNames: []string{"Name3"}, DataType: schema.String, Tag: `gorm:"<-"`, Creatable: true, Updatable: true, Readable: true}, 252 {Name: "Name4", DBName: "name4", BindNames: []string{"Name4"}, DataType: schema.String, Tag: `gorm:"<-:create"`, Creatable: true, Updatable: false, Readable: true}, 253 {Name: "Name5", DBName: "name5", BindNames: []string{"Name5"}, DataType: schema.String, Tag: `gorm:"<-:update"`, Creatable: false, Updatable: true, Readable: true}, 254 {Name: "Name6", DBName: "name6", BindNames: []string{"Name6"}, DataType: schema.String, Tag: `gorm:"<-:create,update"`, Creatable: true, Updatable: true, Readable: true}, 255 {Name: "Name7", DBName: "name7", BindNames: []string{"Name7"}, DataType: schema.String, Tag: `gorm:"->:false;<-:create,update"`, Creatable: true, Updatable: true, Readable: false}, 256 {Name: "Name8", DBName: "name8", BindNames: []string{"Name8"}, DataType: schema.String, Tag: `gorm:"->;-:migration"`, Creatable: false, Updatable: false, Readable: true, IgnoreMigration: true}, 257 } 258 259 for _, f := range fields { 260 checkSchemaField(t, user, f, func(f *schema.Field) {}) 261 } 262 } 263 264 type ID int64 265 type INT int 266 type INT8 int8 267 type INT16 int16 268 type INT32 int32 269 type INT64 int64 270 type UINT uint 271 type UINT8 uint8 272 type UINT16 uint16 273 type UINT32 uint32 274 type UINT64 uint64 275 type FLOAT32 float32 276 type FLOAT64 float64 277 type BOOL bool 278 type STRING string 279 type TypeAlias struct { 280 ID 281 INT `gorm:"column:fint"` 282 INT8 `gorm:"column:fint8"` 283 INT16 `gorm:"column:fint16"` 284 INT32 `gorm:"column:fint32"` 285 INT64 `gorm:"column:fint64"` 286 UINT `gorm:"column:fuint"` 287 UINT8 `gorm:"column:fuint8"` 288 UINT16 `gorm:"column:fuint16"` 289 UINT32 `gorm:"column:fuint32"` 290 UINT64 `gorm:"column:fuint64"` 291 FLOAT32 `gorm:"column:ffloat32"` 292 FLOAT64 `gorm:"column:ffloat64"` 293 BOOL `gorm:"column:fbool"` 294 STRING `gorm:"column:fstring"` 295 } 296 297 func TestTypeAliasField(t *testing.T) { 298 alias, err := schema.Parse(&TypeAlias{}, &sync.Map{}, schema.NamingStrategy{}) 299 if err != nil { 300 t.Fatalf("Failed to parse TypeAlias with permission, got error %v", err) 301 } 302 303 fields := []*schema.Field{ 304 {Name: "ID", DBName: "id", BindNames: []string{"ID"}, DataType: schema.Int, Creatable: true, Updatable: true, Readable: true, Size: 64, PrimaryKey: true, HasDefaultValue: true, AutoIncrement: true}, 305 {Name: "INT", DBName: "fint", BindNames: []string{"INT"}, DataType: schema.Int, Creatable: true, Updatable: true, Readable: true, Size: 64, Tag: `gorm:"column:fint"`}, 306 {Name: "INT8", DBName: "fint8", BindNames: []string{"INT8"}, DataType: schema.Int, Creatable: true, Updatable: true, Readable: true, Size: 8, Tag: `gorm:"column:fint8"`}, 307 {Name: "INT16", DBName: "fint16", BindNames: []string{"INT16"}, DataType: schema.Int, Creatable: true, Updatable: true, Readable: true, Size: 16, Tag: `gorm:"column:fint16"`}, 308 {Name: "INT32", DBName: "fint32", BindNames: []string{"INT32"}, DataType: schema.Int, Creatable: true, Updatable: true, Readable: true, Size: 32, Tag: `gorm:"column:fint32"`}, 309 {Name: "INT64", DBName: "fint64", BindNames: []string{"INT64"}, DataType: schema.Int, Creatable: true, Updatable: true, Readable: true, Size: 64, Tag: `gorm:"column:fint64"`}, 310 {Name: "UINT", DBName: "fuint", BindNames: []string{"UINT"}, DataType: schema.Uint, Creatable: true, Updatable: true, Readable: true, Size: 64, Tag: `gorm:"column:fuint"`}, 311 {Name: "UINT8", DBName: "fuint8", BindNames: []string{"UINT8"}, DataType: schema.Uint, Creatable: true, Updatable: true, Readable: true, Size: 8, Tag: `gorm:"column:fuint8"`}, 312 {Name: "UINT16", DBName: "fuint16", BindNames: []string{"UINT16"}, DataType: schema.Uint, Creatable: true, Updatable: true, Readable: true, Size: 16, Tag: `gorm:"column:fuint16"`}, 313 {Name: "UINT32", DBName: "fuint32", BindNames: []string{"UINT32"}, DataType: schema.Uint, Creatable: true, Updatable: true, Readable: true, Size: 32, Tag: `gorm:"column:fuint32"`}, 314 {Name: "UINT64", DBName: "fuint64", BindNames: []string{"UINT64"}, DataType: schema.Uint, Creatable: true, Updatable: true, Readable: true, Size: 64, Tag: `gorm:"column:fuint64"`}, 315 {Name: "FLOAT32", DBName: "ffloat32", BindNames: []string{"FLOAT32"}, DataType: schema.Float, Creatable: true, Updatable: true, Readable: true, Size: 32, Tag: `gorm:"column:ffloat32"`}, 316 {Name: "FLOAT64", DBName: "ffloat64", BindNames: []string{"FLOAT64"}, DataType: schema.Float, Creatable: true, Updatable: true, Readable: true, Size: 64, Tag: `gorm:"column:ffloat64"`}, 317 {Name: "BOOL", DBName: "fbool", BindNames: []string{"BOOL"}, DataType: schema.Bool, Creatable: true, Updatable: true, Readable: true, Tag: `gorm:"column:fbool"`}, 318 {Name: "STRING", DBName: "fstring", BindNames: []string{"STRING"}, DataType: schema.String, Creatable: true, Updatable: true, Readable: true, Tag: `gorm:"column:fstring"`}, 319 } 320 321 for _, f := range fields { 322 checkSchemaField(t, alias, f, func(f *schema.Field) {}) 323 } 324 }