diff --git a/migrator/migrator.go b/migrator/migrator.go index f581f714..cab266a3 100644 --- a/migrator/migrator.go +++ b/migrator/migrator.go @@ -542,7 +542,11 @@ func (m Migrator) ReorderModels(values []interface{}, autoAdd bool) (results []i } for _, value := range values { - parseDependence(value, true) + if v, ok := value.(string); ok { + results = append(results, v) + } else { + parseDependence(value, true) + } } for _, name := range modelNames { diff --git a/tests/create.go b/tests/create.go index ec57b8ee..09464674 100644 --- a/tests/create.go +++ b/tests/create.go @@ -2,6 +2,7 @@ package tests import ( "strconv" + "testing" "time" ) @@ -16,7 +17,7 @@ type Config struct { Friends int } -func GetUser(name string, config Config) User { +func GetUser(name string, config Config) *User { var ( birthday = time.Now() user = User{ @@ -43,23 +44,136 @@ func GetUser(name string, config Config) User { } if config.Manager { - manager := GetUser(name+"_manager", Config{}) - user.Manager = &manager + user.Manager = GetUser(name+"_manager", Config{}) } for i := 0; i < config.Team; i++ { - user.Team = append(user.Team, GetUser(name+"_team_"+strconv.Itoa(i+1), Config{})) + user.Team = append(user.Team, *GetUser(name+"_team_"+strconv.Itoa(i+1), Config{})) } for i := 0; i < config.Languages; i++ { - name := "Locale_" + strconv.Itoa(i+0) - user.Languages = append(user.Languages, Language{Code: name, Name: name}) + name := name + "_locale_" + strconv.Itoa(i+0) + language := Language{Code: name, Name: name} + DB.Create(&language) + user.Languages = append(user.Languages, language) } for i := 0; i < config.Friends; i++ { - f := GetUser(name+"_friend_"+strconv.Itoa(i+1), Config{}) - user.Friends = append(user.Friends, &f) + user.Friends = append(user.Friends, GetUser(name+"_friend_"+strconv.Itoa(i+1), Config{})) } - return user + return &user +} + +func CheckPet(t *testing.T, pet Pet, expect Pet) { + AssertObjEqual(t, pet, expect, "ID", "CreatedAt", "UpdatedAt", "DeletedAt", "UserID", "Name") + + AssertObjEqual(t, pet.Toy, expect.Toy, "ID", "CreatedAt", "UpdatedAt", "DeletedAt", "Name", "OwnerID", "OwnerType") + + if expect.Toy.Name != "" && expect.Toy.OwnerType != "pets" { + t.Errorf("toys's OwnerType, expect: %v, got %v", "pets", expect.Toy.OwnerType) + } +} + +func CheckUser(t *testing.T, user User, expect User) { + if user.ID != 0 { + var newUser User + if err := DB.Where("id = ?", user.ID).First(&newUser).Error; err != nil { + t.Fatalf("errors happened when query: %v", err) + } else { + AssertObjEqual(t, newUser, user, "ID", "CreatedAt", "UpdatedAt", "DeletedAt", "Name", "Age", "Birthday", "CompanyID", "ManagerID", "Active") + } + } + + AssertObjEqual(t, user, expect, "ID", "CreatedAt", "UpdatedAt", "DeletedAt", "Name", "Age", "Birthday", "CompanyID", "ManagerID", "Active") + + t.Run("Account", func(t *testing.T) { + AssertObjEqual(t, user.Account, expect.Account, "ID", "CreatedAt", "UpdatedAt", "DeletedAt", "UserID", "Number") + + if user.Account.Number != "" { + if !user.Account.UserID.Valid { + t.Errorf("Account's foreign key should be saved") + } else { + var account Account + DB.First(&account, "user_id = ?", user.ID) + AssertObjEqual(t, account, user.Account, "ID", "CreatedAt", "UpdatedAt", "DeletedAt", "UserID", "Number") + } + } + }) + + t.Run("Pets", func(t *testing.T) { + if len(user.Pets) != len(expect.Pets) { + t.Errorf("pets should equal, expect: %v, got %v", len(expect.Pets), len(user.Pets)) + } + + for idx, pet := range user.Pets { + if pet == nil || expect.Pets[idx] == nil { + t.Errorf("pets#%v should equal, expect: %v, got %v", idx, expect.Pets[idx], pet) + } else { + CheckPet(t, *pet, *expect.Pets[idx]) + } + } + }) + + t.Run("Toys", func(t *testing.T) { + if len(user.Toys) != len(expect.Toys) { + t.Errorf("toys should equal, expect: %v, got %v", len(expect.Toys), len(user.Toys)) + } + + for idx, toy := range user.Toys { + if toy.OwnerType != "users" { + t.Errorf("toys's OwnerType, expect: %v, got %v", "users", toy.OwnerType) + } + + AssertObjEqual(t, toy, expect.Toys[idx], "ID", "CreatedAt", "UpdatedAt", "Name", "OwnerID", "OwnerType") + } + }) + + t.Run("Company", func(t *testing.T) { + AssertObjEqual(t, user.Company, expect.Company, "ID", "Name") + }) + + t.Run("Manager", func(t *testing.T) { + if user.Manager != nil { + if user.ManagerID == nil { + t.Errorf("Manager's foreign key should be saved") + } else { + var manager User + DB.First(&manager, "id = ?", *user.ManagerID) + AssertObjEqual(t, manager, user.Manager, "ID", "CreatedAt", "UpdatedAt", "DeletedAt", "Name", "Age", "Birthday", "CompanyID", "ManagerID", "Active") + } + } else if user.ManagerID != nil { + t.Errorf("Manager should not be created for zero value, got: %+v", user.ManagerID) + } + }) + + t.Run("Team", func(t *testing.T) { + if len(user.Team) != len(expect.Team) { + t.Errorf("Team should equal, expect: %v, got %v", len(expect.Team), len(user.Team)) + } + + for idx, team := range user.Team { + AssertObjEqual(t, team, expect.Team[idx], "ID", "CreatedAt", "UpdatedAt", "DeletedAt", "Name", "Age", "Birthday", "CompanyID", "ManagerID", "Active") + } + }) + + t.Run("Languages", func(t *testing.T) { + if len(user.Languages) != len(expect.Languages) { + t.Errorf("Languages should equal, expect: %v, got %v", len(expect.Languages), len(user.Languages)) + } + + for idx, language := range user.Languages { + AssertObjEqual(t, language, expect.Languages[idx], "Code", "Name") + } + }) + + t.Run("Friends", func(t *testing.T) { + if len(user.Friends) != len(expect.Friends) { + t.Errorf("Friends should equal, expect: %v, got %v", len(expect.Friends), len(user.Friends)) + } + + for idx, friend := range user.Friends { + AssertObjEqual(t, friend, expect.Friends[idx], "ID", "CreatedAt", "UpdatedAt", "DeletedAt", "Name", "Age", "Birthday", "CompanyID", "ManagerID", "Active") + } + }) } diff --git a/tests/create_test.go b/tests/create_test.go index 471cecf6..9241e0a6 100644 --- a/tests/create_test.go +++ b/tests/create_test.go @@ -7,7 +7,7 @@ import ( ) func TestCreate(t *testing.T) { - var user = GetUser("create", Config{}) + var user = *GetUser("create", Config{}) if err := DB.Create(&user).Error; err != nil { t.Fatalf("errors happened when create: %v", err) @@ -27,165 +27,104 @@ func TestCreate(t *testing.T) { var newUser User if err := DB.Where("id = ?", user.ID).First(&newUser).Error; err != nil { - t.Errorf("errors happened when query: %v", err) + t.Fatalf("errors happened when query: %v", err) } else { - AssertObjEqual(t, newUser, user, "Name", "Age", "Birthday") + CheckUser(t, newUser, user) } } -func TestCreateWithBelongsToAssociations(t *testing.T) { - check := func(t *testing.T, user User, old User) { - if old.Company.Name != "" { - if user.CompanyID == nil { - t.Errorf("Company's foreign key should be saved") - } else { - var company Company - DB.First(&company, "id = ?", *user.CompanyID) - if company.Name != old.Company.Name { - t.Errorf("Company's name should be same") - } else if user.Company.Name != old.Company.Name { - t.Errorf("Company's name should be same") - } - } - } else if user.CompanyID != nil { - t.Errorf("Company should not be created for zero value, got: %+v", user.CompanyID) - } +func TestCreateWithAssociations(t *testing.T) { + var user = *GetUser("create_with_belongs_to", Config{ + Account: true, + Pets: 2, + Toys: 3, + Company: true, + Manager: true, + Team: 4, + Languages: 3, + Friends: 1, + }) - if old.Manager != nil { - if user.ManagerID == nil { - t.Errorf("Manager's foreign key should be saved") - } else { - var manager User - DB.First(&manager, "id = ?", *user.ManagerID) - if manager.Name != user.Manager.Name { - t.Errorf("Manager's name should be same") - } else if user.Manager.Name != old.Manager.Name { - t.Errorf("Manager's name should be same") - } - } - } else if user.ManagerID != nil { - t.Errorf("Manager should not be created for zero value, got: %+v", user.ManagerID) - } + if err := DB.Create(&user).Error; err != nil { + t.Fatalf("errors happened when create: %v", err) } - t.Run("Struct", func(t *testing.T) { - var user = User{ - Name: "create", - Age: 18, - Birthday: Now(), - Company: Company{Name: "company-belongs-to-association"}, - Manager: &User{Name: "manager-belongs-to-association"}, - } + CheckUser(t, user, user) - if err := DB.Create(&user).Error; err != nil { - t.Fatalf("errors happened when create: %v", err) - } - - check(t, user, user) - - var user2 User - DB.Preload("Company").Preload("Manager").Find(&user2, "id = ?", user.ID) - check(t, user2, user) - }) - - t.Run("BulkInsert", func(t *testing.T) { - var users = []User{{ - Name: "create-1", - Age: 18, - Birthday: Now(), - Company: Company{Name: "company-belongs-to-association-1"}, - Manager: &User{Name: "manager-belongs-to-association-1"}, - }, { - Name: "create-2", - Age: 28, - Birthday: Now(), - Company: Company{Name: "company-belongs-to-association-2"}, - }, { - Name: "create-3", - Age: 38, - Birthday: Now(), - Company: Company{Name: "company-belongs-to-association-3"}, - Manager: &User{Name: "manager-belongs-to-association-3"}, - }} - - if err := DB.Create(&users).Error; err != nil { - t.Fatalf("errors happened when create: %v", err) - } - - var userIDs []uint - for _, user := range users { - userIDs = append(userIDs, user.ID) - check(t, user, user) - } - - t.Run("Preload", func(t *testing.T) { - var users2 []User - DB.Preload("Company").Preload("Manager").Find(&users2, "id IN ?", userIDs) - for idx, user := range users2 { - check(t, user, users[idx]) - } - }) - }) - - t.Run("BulkInsertPtrData", func(t *testing.T) { - var users = []*User{{ - Name: "create-1", - Age: 18, - Birthday: Now(), - Company: Company{Name: "company-belongs-to-association-1"}, - Manager: &User{Name: "manager-belongs-to-association-1"}, - }, { - Name: "create-2", - Age: 28, - Birthday: Now(), - Company: Company{Name: "company-belongs-to-association-2"}, - }, { - Name: "create-3", - Age: 38, - Birthday: Now(), - Company: Company{Name: "company-belongs-to-association-3"}, - Manager: &User{Name: "manager-belongs-to-association-3"}, - }} - - if err := DB.Create(&users).Error; err != nil { - t.Fatalf("errors happened when create: %v", err) - } - - for _, user := range users { - check(t, *user, *user) - } - }) - - t.Run("BulkInsertWithoutPtr", func(t *testing.T) { - var users = []*User{{ - Name: "create-1", - Age: 18, - Birthday: Now(), - Company: Company{Name: "company-belongs-to-association-1"}, - Manager: &User{Name: "manager-belongs-to-association-1"}, - }, { - Name: "create-2", - Age: 28, - Birthday: Now(), - Company: Company{Name: "company-belongs-to-association-2"}, - }, { - Name: "create-3", - Age: 38, - Birthday: Now(), - Company: Company{Name: "company-belongs-to-association-3"}, - Manager: &User{Name: "manager-belongs-to-association-3"}, - }} - - if err := DB.Create(users).Error; err != nil { - t.Fatalf("errors happened when create: %v", err) - } - - for _, user := range users { - check(t, *user, *user) - } - }) + var user2 User + DB.Preload("Account").Preload("Pets").Preload("Toys").Preload("Company").Preload("Manager").Preload("Team").Preload("Languages").Find(&user2, "id = ?", user.ID) + CheckUser(t, user2, user) } +// func TestBulkCreateWithBelongsTo(t *testing.T) { +// users := []User{ +// *GetUser("create_with_belongs_to_1", Config{Company: true, Manager: true}), +// *GetUser("create_with_belongs_to_2", Config{Company: true, Manager: false}), +// *GetUser("create_with_belongs_to_3", Config{Company: false, Manager: true}), +// *GetUser("create_with_belongs_to_4", Config{Company: true, Manager: true}), +// } + +// if err := DB.Create(&users).Error; err != nil { +// t.Fatalf("errors happened when create: %v", err) +// } + +// var userIDs []uint +// for _, user := range users { +// userIDs = append(userIDs, user.ID) +// CheckUser(t, user, user) +// } + +// var users2 []User +// DB.Preload("Company").Preload("Manager").Find(&users2, "id IN ?", userIDs) +// for idx, user := range users2 { +// CheckUser(t, user, users[idx]) +// } +// } + +// func TestBulkCreatePtrDataWithBelongsTo(t *testing.T) { +// users := []*User{ +// GetUser("create_with_belongs_to_1", Config{Company: true, Manager: true}), +// GetUser("create_with_belongs_to_2", Config{Company: true, Manager: false}), +// GetUser("create_with_belongs_to_3", Config{Company: false, Manager: true}), +// GetUser("create_with_belongs_to_4", Config{Company: true, Manager: true}), +// } + +// if err := DB.Create(&users).Error; err != nil { +// t.Fatalf("errors happened when create: %v", err) +// } + +// var userIDs []uint +// for _, user := range users { +// userIDs = append(userIDs, user.ID) +// CheckUser(t, *user, *user) +// } + +// var users2 []User +// DB.Preload("Company").Preload("Manager").Find(&users2, "id IN ?", userIDs) +// for idx, user := range users2 { +// CheckUser(t, user, *users[idx]) +// } +// } + +// func TestBulkCreateWithoutPtrWithBelongsTo(t *testing.T) { +// users := []*User{ +// GetUser("create_with_belongs_to_1", Config{Company: true, Manager: true}), +// GetUser("create_with_belongs_to_2", Config{Company: true, Manager: false}), +// GetUser("create_with_belongs_to_3", Config{Company: false, Manager: true}), +// GetUser("create_with_belongs_to_4", Config{Company: true, Manager: true}), +// } + +// if err := DB.Create(&users).Error; err != nil { +// t.Fatalf("errors happened when create: %v", err) +// } + +// var userIDs []uint +// for _, user := range users { +// userIDs = append(userIDs, user.ID) +// CheckUser(t, *user, *user) +// } +// } + // func TestCreateHasOneAssociations(t *testing.T, db *gorm.DB) { // check := func(t *testing.T, user User, old User) { // if user.Account.ID == 0 { diff --git a/tests/main_test.go b/tests/main_test.go index 7324ed9e..3e329454 100644 --- a/tests/main_test.go +++ b/tests/main_test.go @@ -36,6 +36,8 @@ func RunMigrations() { rand.Seed(time.Now().UnixNano()) rand.Shuffle(len(allModels), func(i, j int) { allModels[i], allModels[j] = allModels[j], allModels[i] }) + DB.Migrator().DropTable("user_friends", "user_speak") + if err = DB.Migrator().DropTable(allModels...); err != nil { log.Printf("Failed to drop table, got error %v\n", err) os.Exit(1) diff --git a/tests/utils.go b/tests/utils.go index 9d61c422..cb4e4fcc 100644 --- a/tests/utils.go +++ b/tests/utils.go @@ -29,6 +29,15 @@ func AssertEqual(t *testing.T, got, expect interface{}) { } } + if got == expect { + return + } + + if reflect.Indirect(reflect.ValueOf(got)).IsValid() != reflect.Indirect(reflect.ValueOf(expect)).IsValid() { + t.Errorf("expect: %+v, got %+v", expect, got) + return + } + if got != nil { got = reflect.Indirect(reflect.ValueOf(got)).Interface() }