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
|
||||
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
|
||||
user = User{Name: "invalid-user-with-invalid-belongs-to-foreign-key", CompanyID: &unexistCompanyID}
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,6 +95,8 @@ func TestMany2ManyAssociation(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestMany2ManyOmitAssociations(t *testing.T) {
|
||||
tidbSkip(t, "not support the foreign key feature")
|
||||
|
||||
user := *GetUser("many2many_omit_associations", Config{Languages: 2})
|
||||
|
||||
if err := DB.Omit("Languages.*").Create(&user).Error; err == nil {
|
||||
|
|
|
@ -71,6 +71,8 @@ func TestAssociationNotNullClear(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestForeignKeyConstraints(t *testing.T) {
|
||||
tidbSkip(t, "not support the foreign key feature")
|
||||
|
||||
type Profile struct {
|
||||
ID uint
|
||||
Name string
|
||||
|
@ -126,6 +128,8 @@ func TestForeignKeyConstraints(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestForeignKeyConstraintsBelongsTo(t *testing.T) {
|
||||
tidbSkip(t, "not support the foreign key feature")
|
||||
|
||||
type Profile struct {
|
||||
ID uint
|
||||
Name string
|
||||
|
|
|
@ -29,3 +29,8 @@ services:
|
|||
- MSSQL_DB=gorm
|
||||
- MSSQL_USER=gorm
|
||||
- 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/mattn/go-sqlite3 v1.14.16 // 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/sqlite v1.4.4
|
||||
gorm.io/driver/sqlserver v1.4.2
|
||||
gorm.io/gorm v1.24.3
|
||||
gorm.io/gorm v1.24.5
|
||||
)
|
||||
|
||||
replace gorm.io/gorm => ../
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package tests_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
"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) {
|
||||
tidbSkip(t, "use another test case")
|
||||
|
||||
sqlite := DB.Dialector.Name() == "sqlite"
|
||||
sqlserver := DB.Dialector.Name() == "sqlserver"
|
||||
|
||||
|
@ -853,6 +983,8 @@ func TestUniqueColumn(t *testing.T) {
|
|||
AssertEqual(t, "", value)
|
||||
AssertEqual(t, false, ok)
|
||||
|
||||
tidbSkip(t, "can't change column constraint")
|
||||
|
||||
// null -> empty string
|
||||
err = DB.Table("unique_tests").AutoMigrate(&UniqueTest3{})
|
||||
if err != nil {
|
||||
|
|
|
@ -29,7 +29,7 @@ func TestRow(t *testing.T) {
|
|||
}
|
||||
|
||||
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`
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
dialects=("sqlite" "mysql" "postgres" "sqlserver")
|
||||
dialects=("sqlite" "mysql" "postgres" "sqlserver" "tidb")
|
||||
|
||||
if [[ $(pwd) == *"gorm/tests"* ]]; then
|
||||
cd ..
|
||||
|
|
|
@ -21,6 +21,7 @@ var (
|
|||
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"
|
||||
sqlserverDSN = "sqlserver://gorm:LoremIpsum86@localhost:9930?database=gorm"
|
||||
tidbDSN = "root:@tcp(localhost:9940)/test?charset=utf8&parseTime=True&loc=Local"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -80,6 +81,12 @@ func OpenTestConnection() (db *gorm.DB, err error) {
|
|||
dbDSN = sqlserverDSN
|
||||
}
|
||||
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:
|
||||
log.Println("testing sqlite3...")
|
||||
db, err = gorm.Open(sqlite.Open(filepath.Join(os.TempDir(), "gorm.db")), &gorm.Config{})
|
||||
|
|
Loading…
Reference in New Issue