2020-02-02 09:40:44 +03:00
package tests
import (
2020-05-30 16:05:27 +03:00
"database/sql/driver"
"fmt"
2020-02-02 09:40:44 +03:00
"reflect"
2020-05-23 18:50:48 +03:00
"sort"
"strconv"
"strings"
2020-02-02 09:40:44 +03:00
"testing"
2020-03-02 18:43:34 +03:00
"time"
2020-05-23 18:50:48 +03:00
"github.com/jinzhu/gorm/utils"
2020-02-02 09:40:44 +03:00
)
2020-05-23 18:50:48 +03:00
type Config struct {
Account bool
Pets int
Toys int
Company bool
Manager bool
Team int
Languages int
Friends int
}
func GetUser ( name string , config Config ) * User {
var (
2020-05-30 19:42:52 +03:00
birthday = time . Now ( ) . Round ( time . Second )
2020-05-23 18:50:48 +03:00
user = User {
Name : name ,
Age : 18 ,
Birthday : & birthday ,
}
)
if config . Account {
user . Account = Account { Number : name + "_account" }
}
for i := 0 ; i < config . Pets ; i ++ {
user . Pets = append ( user . Pets , & Pet { Name : name + "_pet_" + strconv . Itoa ( i + 1 ) } )
}
for i := 0 ; i < config . Toys ; i ++ {
user . Toys = append ( user . Toys , Toy { Name : name + "_toy_" + strconv . Itoa ( i + 1 ) } )
}
if config . Company {
user . Company = Company { Name : "company-" + name }
}
if config . 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 { } ) )
}
for i := 0 ; i < config . Languages ; i ++ {
name := name + "_locale_" + strconv . Itoa ( i + 1 )
language := Language { Code : name , Name : name }
DB . Create ( & language )
user . Languages = append ( user . Languages , language )
}
for i := 0 ; i < config . Friends ; i ++ {
user . Friends = append ( user . Friends , GetUser ( name + "_friend_" + strconv . Itoa ( i + 1 ) , Config { } ) )
}
return & user
}
2020-03-04 06:32:36 +03:00
func AssertObjEqual ( t * testing . T , r , e interface { } , names ... string ) {
2020-02-02 09:40:44 +03:00
for _ , name := range names {
got := reflect . Indirect ( reflect . ValueOf ( r ) ) . FieldByName ( name ) . Interface ( )
2020-03-04 06:32:36 +03:00
expect := reflect . Indirect ( reflect . ValueOf ( e ) ) . FieldByName ( name ) . Interface ( )
t . Run ( name , func ( t * testing . T ) {
AssertEqual ( t , got , expect )
} )
}
}
2020-02-02 09:40:44 +03:00
2020-03-04 06:32:36 +03:00
func AssertEqual ( t * testing . T , got , expect interface { } ) {
if ! reflect . DeepEqual ( got , expect ) {
isEqual := func ( ) {
2020-03-02 18:43:34 +03:00
if curTime , ok := got . ( time . Time ) ; ok {
format := "2006-01-02T15:04:05Z07:00"
2020-05-23 18:50:48 +03:00
2020-05-30 09:29:05 +03:00
if curTime . Round ( time . Second ) . Format ( format ) != expect . ( time . Time ) . Round ( time . Second ) . Format ( format ) {
2020-05-30 13:50:20 +03:00
t . Errorf ( "%v: expect: %v, got %v after time round" , utils . FileWithLineNum ( ) , expect . ( time . Time ) . Round ( time . Second ) . Format ( format ) , curTime . Round ( time . Second ) . Format ( format ) )
2020-03-02 18:43:34 +03:00
}
2020-05-30 16:05:27 +03:00
} else if fmt . Sprint ( got ) != fmt . Sprint ( expect ) {
2020-05-23 18:50:48 +03:00
t . Errorf ( "%v: expect: %#v, got %#v" , utils . FileWithLineNum ( ) , expect , got )
2020-03-02 18:43:34 +03:00
}
2020-02-02 09:40:44 +03:00
}
2020-03-04 06:32:36 +03:00
2020-05-30 16:05:27 +03:00
if fmt . Sprint ( got ) == fmt . Sprint ( expect ) {
2020-05-23 11:38:13 +03:00
return
}
if reflect . Indirect ( reflect . ValueOf ( got ) ) . IsValid ( ) != reflect . Indirect ( reflect . ValueOf ( expect ) ) . IsValid ( ) {
2020-05-23 18:50:48 +03:00
t . Errorf ( "%v: expect: %+v, got %+v" , utils . FileWithLineNum ( ) , expect , got )
2020-05-23 11:38:13 +03:00
return
}
2020-05-30 16:05:27 +03:00
if valuer , ok := got . ( driver . Valuer ) ; ok {
got , _ = valuer . Value ( )
}
if valuer , ok := expect . ( driver . Valuer ) ; ok {
expect , _ = valuer . Value ( )
}
2020-03-04 06:32:36 +03:00
if got != nil {
got = reflect . Indirect ( reflect . ValueOf ( got ) ) . Interface ( )
}
if expect != nil {
expect = reflect . Indirect ( reflect . ValueOf ( expect ) ) . Interface ( )
}
2020-05-30 20:21:16 +03:00
if reflect . ValueOf ( got ) . IsValid ( ) != reflect . ValueOf ( expect ) . IsValid ( ) {
t . Errorf ( "%v: expect: %+v, got %+v" , utils . FileWithLineNum ( ) , expect , got )
return
}
2020-03-04 06:32:36 +03:00
if reflect . ValueOf ( got ) . Type ( ) . ConvertibleTo ( reflect . ValueOf ( expect ) . Type ( ) ) {
got = reflect . ValueOf ( got ) . Convert ( reflect . ValueOf ( expect ) . Type ( ) ) . Interface ( )
isEqual ( )
} else if reflect . ValueOf ( expect ) . Type ( ) . ConvertibleTo ( reflect . ValueOf ( got ) . Type ( ) ) {
expect = reflect . ValueOf ( got ) . Convert ( reflect . ValueOf ( got ) . Type ( ) ) . Interface ( )
isEqual ( )
}
2020-02-02 09:40:44 +03:00
}
}
2020-05-23 18:50:48 +03:00
func CheckPet ( t * testing . T , pet Pet , expect Pet ) {
if pet . ID != 0 {
var newPet Pet
if err := DB . Where ( "id = ?" , pet . ID ) . First ( & newPet ) . Error ; err != nil {
t . Fatalf ( "errors happened when query: %v" , err )
} else {
AssertObjEqual ( t , newPet , pet , "ID" , "CreatedAt" , "UpdatedAt" , "DeletedAt" , "UserID" , "Name" )
}
}
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 ) )
}
sort . Slice ( user . Pets , func ( i , j int ) bool {
return user . Pets [ i ] . ID > user . Pets [ j ] . ID
} )
sort . Slice ( expect . Pets , func ( i , j int ) bool {
return expect . Pets [ i ] . ID > expect . Pets [ j ] . ID
} )
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 ) )
}
sort . Slice ( user . Toys , func ( i , j int ) bool {
return user . Toys [ i ] . ID > user . Toys [ j ] . ID
} )
sort . Slice ( expect . Toys , func ( i , j int ) bool {
return expect . Toys [ i ] . ID > expect . Toys [ j ] . ID
} )
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 ) )
}
sort . Slice ( user . Team , func ( i , j int ) bool {
return user . Team [ i ] . ID > user . Team [ j ] . ID
} )
sort . Slice ( expect . Team , func ( i , j int ) bool {
return expect . Team [ i ] . ID > expect . Team [ j ] . ID
} )
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 ) )
}
sort . Slice ( user . Languages , func ( i , j int ) bool {
return strings . Compare ( user . Languages [ i ] . Code , user . Languages [ j ] . Code ) > 0
} )
sort . Slice ( expect . Languages , func ( i , j int ) bool {
return strings . Compare ( expect . Languages [ i ] . Code , expect . Languages [ j ] . Code ) > 0
} )
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 ) )
}
sort . Slice ( user . Friends , func ( i , j int ) bool {
return user . Friends [ i ] . ID > user . Friends [ j ] . ID
} )
sort . Slice ( expect . Friends , func ( i , j int ) bool {
return expect . Friends [ i ] . ID > expect . Friends [ j ] . ID
} )
for idx , friend := range user . Friends {
AssertObjEqual ( t , friend , expect . Friends [ idx ] , "ID" , "CreatedAt" , "UpdatedAt" , "DeletedAt" , "Name" , "Age" , "Birthday" , "CompanyID" , "ManagerID" , "Active" )
}
} )
}