forked from mirror/gorm
feat: add tidb integration test cases (#6014)
* feat: support tidb integration test * feat: update the mysql driver version to test
This commit is contained in:
parent
878ac51e98
commit
02b7e26f6b
|
@ -167,3 +167,36 @@ jobs:
|
||||||
|
|
||||||
- name: Tests
|
- name: Tests
|
||||||
run: GITHUB_ACTION=true GORM_DIALECT=sqlserver GORM_DSN="sqlserver://gorm:LoremIpsum86@localhost:9930?database=gorm" ./tests/tests_all.sh
|
run: GITHUB_ACTION=true GORM_DIALECT=sqlserver GORM_DSN="sqlserver://gorm:LoremIpsum86@localhost:9930?database=gorm" ./tests/tests_all.sh
|
||||||
|
|
||||||
|
tidb:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
dbversion: [ 'v6.5.0' ]
|
||||||
|
go: [ '1.19', '1.18' ]
|
||||||
|
platform: [ ubuntu-latest ]
|
||||||
|
runs-on: ${{ matrix.platform }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Setup TiDB
|
||||||
|
uses: Icemap/tidb-action@main
|
||||||
|
with:
|
||||||
|
port: 9940
|
||||||
|
version: ${{matrix.dbversion}}
|
||||||
|
|
||||||
|
- name: Set up Go 1.x
|
||||||
|
uses: actions/setup-go@v3
|
||||||
|
with:
|
||||||
|
go-version: ${{ matrix.go }}
|
||||||
|
|
||||||
|
- name: Check out code into the Go module directory
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
|
||||||
|
- name: go mod package cache
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: ~/go/pkg/mod
|
||||||
|
key: ${{ runner.os }}-go-${{ matrix.go }}-${{ hashFiles('tests/go.mod') }}
|
||||||
|
|
||||||
|
- name: Tests
|
||||||
|
run: GITHUB_ACTION=true GORM_DIALECT=tidb GORM_DSN="root:@tcp(localhost:9940)/test?charset=utf8&parseTime=True&loc=Local" ./tests/tests_all.sh
|
||||||
|
|
|
@ -138,6 +138,7 @@ func TestBelongsToAssociation(t *testing.T) {
|
||||||
unexistCompanyID := company.ID + 9999999
|
unexistCompanyID := company.ID + 9999999
|
||||||
user = User{Name: "invalid-user-with-invalid-belongs-to-foreign-key", CompanyID: &unexistCompanyID}
|
user = User{Name: "invalid-user-with-invalid-belongs-to-foreign-key", CompanyID: &unexistCompanyID}
|
||||||
if err := DB.Create(&user).Error; err == nil {
|
if err := DB.Create(&user).Error; err == nil {
|
||||||
|
tidbSkip(t, "not support the foreign key feature")
|
||||||
t.Errorf("should have gotten foreign key violation error")
|
t.Errorf("should have gotten foreign key violation error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,6 +95,8 @@ func TestMany2ManyAssociation(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMany2ManyOmitAssociations(t *testing.T) {
|
func TestMany2ManyOmitAssociations(t *testing.T) {
|
||||||
|
tidbSkip(t, "not support the foreign key feature")
|
||||||
|
|
||||||
user := *GetUser("many2many_omit_associations", Config{Languages: 2})
|
user := *GetUser("many2many_omit_associations", Config{Languages: 2})
|
||||||
|
|
||||||
if err := DB.Omit("Languages.*").Create(&user).Error; err == nil {
|
if err := DB.Omit("Languages.*").Create(&user).Error; err == nil {
|
||||||
|
|
|
@ -71,6 +71,8 @@ func TestAssociationNotNullClear(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestForeignKeyConstraints(t *testing.T) {
|
func TestForeignKeyConstraints(t *testing.T) {
|
||||||
|
tidbSkip(t, "not support the foreign key feature")
|
||||||
|
|
||||||
type Profile struct {
|
type Profile struct {
|
||||||
ID uint
|
ID uint
|
||||||
Name string
|
Name string
|
||||||
|
@ -126,6 +128,8 @@ func TestForeignKeyConstraints(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestForeignKeyConstraintsBelongsTo(t *testing.T) {
|
func TestForeignKeyConstraintsBelongsTo(t *testing.T) {
|
||||||
|
tidbSkip(t, "not support the foreign key feature")
|
||||||
|
|
||||||
type Profile struct {
|
type Profile struct {
|
||||||
ID uint
|
ID uint
|
||||||
Name string
|
Name string
|
||||||
|
|
|
@ -29,3 +29,8 @@ services:
|
||||||
- MSSQL_DB=gorm
|
- MSSQL_DB=gorm
|
||||||
- MSSQL_USER=gorm
|
- MSSQL_USER=gorm
|
||||||
- MSSQL_PASSWORD=LoremIpsum86
|
- MSSQL_PASSWORD=LoremIpsum86
|
||||||
|
tidb:
|
||||||
|
image: 'pingcap/tidb:v6.5.0'
|
||||||
|
ports:
|
||||||
|
- 9940:4000
|
||||||
|
command: /tidb-server -store unistore -path "" -lease 0s > tidb.log 2>&1 &
|
||||||
|
|
|
@ -8,11 +8,11 @@ require (
|
||||||
github.com/lib/pq v1.10.7
|
github.com/lib/pq v1.10.7
|
||||||
github.com/mattn/go-sqlite3 v1.14.16 // indirect
|
github.com/mattn/go-sqlite3 v1.14.16 // indirect
|
||||||
golang.org/x/crypto v0.5.0 // indirect
|
golang.org/x/crypto v0.5.0 // indirect
|
||||||
gorm.io/driver/mysql v1.4.5
|
gorm.io/driver/mysql v1.4.6
|
||||||
gorm.io/driver/postgres v1.4.6
|
gorm.io/driver/postgres v1.4.6
|
||||||
gorm.io/driver/sqlite v1.4.4
|
gorm.io/driver/sqlite v1.4.4
|
||||||
gorm.io/driver/sqlserver v1.4.2
|
gorm.io/driver/sqlserver v1.4.2
|
||||||
gorm.io/gorm v1.24.3
|
gorm.io/gorm v1.24.5
|
||||||
)
|
)
|
||||||
|
|
||||||
replace gorm.io/gorm => ../
|
replace gorm.io/gorm => ../
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package tests_test
|
package tests_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -235,3 +236,13 @@ func CheckUser(t *testing.T, user User, expect User) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func tidbSkip(t *testing.T, reason string) {
|
||||||
|
if isTiDB() {
|
||||||
|
t.Skipf("This test case skipped, because of TiDB '%s'", reason)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isTiDB() bool {
|
||||||
|
return os.Getenv("GORM_DIALECT") == "tidb"
|
||||||
|
}
|
||||||
|
|
|
@ -374,7 +374,137 @@ func TestMigrateIndexes(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTiDBMigrateColumns(t *testing.T) {
|
||||||
|
if !isTiDB() {
|
||||||
|
t.Skip()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TiDB can't change column constraint and has auto_random feature
|
||||||
|
type ColumnStruct struct {
|
||||||
|
ID int `gorm:"primarykey;default:auto_random()"`
|
||||||
|
Name string
|
||||||
|
Age int `gorm:"default:18;comment:my age"`
|
||||||
|
Code string `gorm:"unique;comment:my code;"`
|
||||||
|
Code2 string
|
||||||
|
Code3 string `gorm:"unique"`
|
||||||
|
}
|
||||||
|
|
||||||
|
DB.Migrator().DropTable(&ColumnStruct{})
|
||||||
|
|
||||||
|
if err := DB.AutoMigrate(&ColumnStruct{}); err != nil {
|
||||||
|
t.Errorf("Failed to migrate, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ColumnStruct2 struct {
|
||||||
|
ID int `gorm:"primarykey;default:auto_random()"`
|
||||||
|
Name string `gorm:"size:100"`
|
||||||
|
Code string `gorm:"unique;comment:my code2;default:hello"`
|
||||||
|
Code2 string `gorm:"comment:my code2;default:hello"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := DB.Table("column_structs").Migrator().AlterColumn(&ColumnStruct{}, "Name"); err != nil {
|
||||||
|
t.Fatalf("no error should happened when alter column, but got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := DB.Table("column_structs").AutoMigrate(&ColumnStruct2{}); err != nil {
|
||||||
|
t.Fatalf("no error should happened when auto migrate column, but got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if columnTypes, err := DB.Migrator().ColumnTypes(&ColumnStruct{}); err != nil {
|
||||||
|
t.Fatalf("no error should returns for ColumnTypes")
|
||||||
|
} else {
|
||||||
|
stmt := &gorm.Statement{DB: DB}
|
||||||
|
stmt.Parse(&ColumnStruct2{})
|
||||||
|
|
||||||
|
for _, columnType := range columnTypes {
|
||||||
|
switch columnType.Name() {
|
||||||
|
case "id":
|
||||||
|
if v, ok := columnType.PrimaryKey(); !ok || !v {
|
||||||
|
t.Fatalf("column id primary key should be correct, name: %v, column: %#v", columnType.Name(), columnType)
|
||||||
|
}
|
||||||
|
case "name":
|
||||||
|
dataType := DB.Dialector.DataTypeOf(stmt.Schema.LookUpField(columnType.Name()))
|
||||||
|
if !strings.Contains(strings.ToUpper(dataType), strings.ToUpper(columnType.DatabaseTypeName())) {
|
||||||
|
t.Fatalf("column name type should be correct, name: %v, length: %v, expects: %v, column: %#v", columnType.Name(), columnType.DatabaseTypeName(), dataType, columnType)
|
||||||
|
}
|
||||||
|
if length, ok := columnType.Length(); !ok || length != 100 {
|
||||||
|
t.Fatalf("column name length should be correct, name: %v, length: %v, expects: %v, column: %#v", columnType.Name(), length, 100, columnType)
|
||||||
|
}
|
||||||
|
case "age":
|
||||||
|
if v, ok := columnType.DefaultValue(); !ok || v != "18" {
|
||||||
|
t.Fatalf("column age default value should be correct, name: %v, column: %#v", columnType.Name(), columnType)
|
||||||
|
}
|
||||||
|
if v, ok := columnType.Comment(); !ok || v != "my age" {
|
||||||
|
t.Fatalf("column age comment should be correct, name: %v, column: %#v", columnType.Name(), columnType)
|
||||||
|
}
|
||||||
|
case "code":
|
||||||
|
if v, ok := columnType.Unique(); !ok || !v {
|
||||||
|
t.Fatalf("column code unique should be correct, name: %v, column: %#v", columnType.Name(), columnType)
|
||||||
|
}
|
||||||
|
if v, ok := columnType.DefaultValue(); !ok || v != "hello" {
|
||||||
|
t.Fatalf("column code default value should be correct, name: %v, column: %#v, default value: %v", columnType.Name(), columnType, v)
|
||||||
|
}
|
||||||
|
if v, ok := columnType.Comment(); !ok || v != "my code2" {
|
||||||
|
t.Fatalf("column code comment should be correct, name: %v, column: %#v", columnType.Name(), columnType)
|
||||||
|
}
|
||||||
|
case "code2":
|
||||||
|
// Code2 string `gorm:"comment:my code2;default:hello"`
|
||||||
|
if v, ok := columnType.DefaultValue(); !ok || v != "hello" {
|
||||||
|
t.Fatalf("column code default value should be correct, name: %v, column: %#v, default value: %v", columnType.Name(), columnType, v)
|
||||||
|
}
|
||||||
|
if v, ok := columnType.Comment(); !ok || v != "my code2" {
|
||||||
|
t.Fatalf("column code comment should be correct, name: %v, column: %#v", columnType.Name(), columnType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type NewColumnStruct struct {
|
||||||
|
gorm.Model
|
||||||
|
Name string
|
||||||
|
NewName string
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := DB.Table("column_structs").Migrator().AddColumn(&NewColumnStruct{}, "NewName"); err != nil {
|
||||||
|
t.Fatalf("Failed to add column, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !DB.Table("column_structs").Migrator().HasColumn(&NewColumnStruct{}, "NewName") {
|
||||||
|
t.Fatalf("Failed to find added column")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := DB.Table("column_structs").Migrator().DropColumn(&NewColumnStruct{}, "NewName"); err != nil {
|
||||||
|
t.Fatalf("Failed to add column, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if DB.Table("column_structs").Migrator().HasColumn(&NewColumnStruct{}, "NewName") {
|
||||||
|
t.Fatalf("Found deleted column")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := DB.Table("column_structs").Migrator().AddColumn(&NewColumnStruct{}, "NewName"); err != nil {
|
||||||
|
t.Fatalf("Failed to add column, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := DB.Table("column_structs").Migrator().RenameColumn(&NewColumnStruct{}, "NewName", "new_new_name"); err != nil {
|
||||||
|
t.Fatalf("Failed to add column, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !DB.Table("column_structs").Migrator().HasColumn(&NewColumnStruct{}, "new_new_name") {
|
||||||
|
t.Fatalf("Failed to found renamed column")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := DB.Table("column_structs").Migrator().DropColumn(&NewColumnStruct{}, "new_new_name"); err != nil {
|
||||||
|
t.Fatalf("Failed to add column, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if DB.Table("column_structs").Migrator().HasColumn(&NewColumnStruct{}, "new_new_name") {
|
||||||
|
t.Fatalf("Found deleted column")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestMigrateColumns(t *testing.T) {
|
func TestMigrateColumns(t *testing.T) {
|
||||||
|
tidbSkip(t, "use another test case")
|
||||||
|
|
||||||
sqlite := DB.Dialector.Name() == "sqlite"
|
sqlite := DB.Dialector.Name() == "sqlite"
|
||||||
sqlserver := DB.Dialector.Name() == "sqlserver"
|
sqlserver := DB.Dialector.Name() == "sqlserver"
|
||||||
|
|
||||||
|
@ -853,6 +983,8 @@ func TestUniqueColumn(t *testing.T) {
|
||||||
AssertEqual(t, "", value)
|
AssertEqual(t, "", value)
|
||||||
AssertEqual(t, false, ok)
|
AssertEqual(t, false, ok)
|
||||||
|
|
||||||
|
tidbSkip(t, "can't change column constraint")
|
||||||
|
|
||||||
// null -> empty string
|
// null -> empty string
|
||||||
err = DB.Table("unique_tests").AutoMigrate(&UniqueTest3{})
|
err = DB.Table("unique_tests").AutoMigrate(&UniqueTest3{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -29,7 +29,7 @@ func TestRow(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
table := "gorm.users"
|
table := "gorm.users"
|
||||||
if DB.Dialector.Name() != "mysql" {
|
if DB.Dialector.Name() != "mysql" || isTiDB() {
|
||||||
table = "users" // other databases doesn't support select with `database.table`
|
table = "users" // other databases doesn't support select with `database.table`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#!/bin/bash -e
|
#!/bin/bash -e
|
||||||
|
|
||||||
dialects=("sqlite" "mysql" "postgres" "sqlserver")
|
dialects=("sqlite" "mysql" "postgres" "sqlserver" "tidb")
|
||||||
|
|
||||||
if [[ $(pwd) == *"gorm/tests"* ]]; then
|
if [[ $(pwd) == *"gorm/tests"* ]]; then
|
||||||
cd ..
|
cd ..
|
||||||
|
|
|
@ -21,6 +21,7 @@ var (
|
||||||
mysqlDSN = "gorm:gorm@tcp(localhost:9910)/gorm?charset=utf8&parseTime=True&loc=Local"
|
mysqlDSN = "gorm:gorm@tcp(localhost:9910)/gorm?charset=utf8&parseTime=True&loc=Local"
|
||||||
postgresDSN = "user=gorm password=gorm dbname=gorm host=localhost port=9920 sslmode=disable TimeZone=Asia/Shanghai"
|
postgresDSN = "user=gorm password=gorm dbname=gorm host=localhost port=9920 sslmode=disable TimeZone=Asia/Shanghai"
|
||||||
sqlserverDSN = "sqlserver://gorm:LoremIpsum86@localhost:9930?database=gorm"
|
sqlserverDSN = "sqlserver://gorm:LoremIpsum86@localhost:9930?database=gorm"
|
||||||
|
tidbDSN = "root:@tcp(localhost:9940)/test?charset=utf8&parseTime=True&loc=Local"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -80,6 +81,12 @@ func OpenTestConnection() (db *gorm.DB, err error) {
|
||||||
dbDSN = sqlserverDSN
|
dbDSN = sqlserverDSN
|
||||||
}
|
}
|
||||||
db, err = gorm.Open(sqlserver.Open(dbDSN), &gorm.Config{})
|
db, err = gorm.Open(sqlserver.Open(dbDSN), &gorm.Config{})
|
||||||
|
case "tidb":
|
||||||
|
log.Println("testing tidb...")
|
||||||
|
if dbDSN == "" {
|
||||||
|
dbDSN = tidbDSN
|
||||||
|
}
|
||||||
|
db, err = gorm.Open(mysql.Open(dbDSN), &gorm.Config{})
|
||||||
default:
|
default:
|
||||||
log.Println("testing sqlite3...")
|
log.Println("testing sqlite3...")
|
||||||
db, err = gorm.Open(sqlite.Open(filepath.Join(os.TempDir(), "gorm.db")), &gorm.Config{})
|
db, err = gorm.Open(sqlite.Open(filepath.Join(os.TempDir(), "gorm.db")), &gorm.Config{})
|
||||||
|
|
Loading…
Reference in New Issue