Skip to content

Commit

Permalink
feat: [#519] Save container to a temp file (#721)
Browse files Browse the repository at this point in the history
* feat: [#519] Save container to a temp file

* add container

* optimize docker

* chore: update mocks

* only generate one containter

* remove

* remove

* fix ci

* fix ci

* remove

* stop container

* cancel test in windows

* fix ci

* fix ci

* test ci

* test ci

* test ci

* test ci

* test ci

* test ci

* test ./database/...

* move creating db process to NewTestQueries

* create container directly

* chore: update mocks

* remove sqlite

* normal

* update config

* fix postgres

* optimize

* cancel test

* solve AI

---------

Co-authored-by: hwbrzzl <[email protected]>
  • Loading branch information
hwbrzzl and hwbrzzl authored Nov 17, 2024
1 parent 7b133e1 commit 197dd26
Show file tree
Hide file tree
Showing 39 changed files with 1,048 additions and 408 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@
.idea
.DS_Store
.vscode
goravel*
/vendor
22 changes: 14 additions & 8 deletions contracts/testing/testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,32 @@ type Database interface {
}

type DatabaseDriver interface {
// Build the database.
// Build a database container, it doesn't wait for the database to be ready, the Ready method needs to be called if
// you want to check the container status.
Build() error
// Config get database configuration.
Config() DatabaseConfig
// Database returns a new instance with a new database, the Build method needs to be called first.
Database(name string) (DatabaseDriver, error)
// Driver gets the database driver name.
Driver() database.Driver
// Fresh the database.
Fresh() error
// Image gets the database image.
Image(image Image)
// Driver gets the database driver name.
Driver() database.Driver
// Ready checks if the database is ready, the Build method needs to be called first.
Ready() error
// Stop the database.
Stop() error
}

type DatabaseConfig struct {
Host string
Port int
Database string
Username string
Password string
Host string
Port int
Database string
Username string
Password string
ContainerID string
}

type Image struct {
Expand Down
7 changes: 5 additions & 2 deletions database/factory/factory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,17 @@ type FactoryTestSuite struct {

func TestFactoryTestSuite(t *testing.T) {
if env.IsWindows() {
t.Skip("Skipping tests that use Docker")
t.Skip("Skip test that using Docker")
}

suite.Run(t, &FactoryTestSuite{})
}

func (s *FactoryTestSuite) SetupSuite() {
postgresQuery := gorm.NewTestQuery(docker.Postgres())
postgresDocker := docker.Postgres()
s.Require().NoError(postgresDocker.Ready())

postgresQuery := gorm.NewTestQuery(postgresDocker)
postgresQuery.CreateTable(gorm.TestTableHouses, gorm.TestTableUsers)

s.query = postgresQuery.Query()
Expand Down
36 changes: 24 additions & 12 deletions database/gorm/query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ type QueryTestSuite struct {

func TestQueryTestSuite(t *testing.T) {
if env.IsWindows() {
t.Skip("Skipping tests that use Docker")
t.Skip("Skip test that using Docker")
}

suite.Run(t, &QueryTestSuite{})
Expand All @@ -52,6 +52,12 @@ func (s *QueryTestSuite) SetupSuite() {

func (s *QueryTestSuite) SetupTest() {}

func (s *QueryTestSuite) TearDownSuite() {
if s.queries[database.DriverSqlite] != nil {
s.NoError(s.queries[database.DriverSqlite].Docker().Stop())
}
}

func (s *QueryTestSuite) TestAssociation() {
for driver, query := range s.queries {
tests := []struct {
Expand Down Expand Up @@ -3538,7 +3544,7 @@ func (s *QueryTestSuite) TestWith() {
setup: func(description string) {
var user1 User
s.Nil(query.Query().With("Books", func(query contractsorm.Query) contractsorm.Query {
return query.Where("name = ?", "with_book0")
return query.Where("name = ?", "with_book0").Select("id", "user_id", "name")
}).Find(&user1, user.ID))
s.True(user1.ID > 0)
s.Nil(user1.Address)
Expand Down Expand Up @@ -3589,10 +3595,12 @@ func (s *QueryTestSuite) TestWithNesting() {

func TestCustomConnection(t *testing.T) {
if env.IsWindows() {
t.Skip("Skipping tests that use Docker")
t.Skip("Skip test that using Docker")
}

postgresDocker := supportdocker.Postgres()
require.NoError(t, postgresDocker.Ready())

postgresQuery := NewTestQuery(postgresDocker)
postgresQuery.CreateTable(TestTableReviews, TestTableProducts)

Expand Down Expand Up @@ -3629,6 +3637,8 @@ func TestCustomConnection(t *testing.T) {
person := Person{Name: "create_person"}
assert.NotNil(t, query.Create(&person))
assert.True(t, person.ID == 0)

assert.NoError(t, sqliteDocker.Stop())
}

func TestFilterFindConditions(t *testing.T) {
Expand Down Expand Up @@ -3751,7 +3761,7 @@ func TestObserverEvent(t *testing.T) {

func TestReadWriteSeparate(t *testing.T) {
if env.IsWindows() {
t.Skip("Skipping tests that use Docker")
t.Skip("Skip test that using Docker")
}

dbs := NewTestQueries().QueriesOfReadWrite()
Expand All @@ -3763,14 +3773,9 @@ func TestReadWriteSeparate(t *testing.T) {
err error
)
if drive == database.DriverSqlite {
mixQuery, err = db["write"].QueryOfReadWrite(TestReadWriteConfig{
ReadDatabase: db["read"].Docker().Config().Database,
})
mixQuery, err = db["write"].QueryOfReadWrite(db["read"].Docker().Config())
} else {
mixQuery, err = db["write"].QueryOfReadWrite(TestReadWriteConfig{
ReadPort: db["read"].Docker().Config().Port,
WritePort: db["write"].Docker().Config().Port,
})
mixQuery, err = db["write"].QueryOfReadWrite(db["read"].Docker().Config())
}

require.NoError(t, err)
Expand All @@ -3795,11 +3800,14 @@ func TestReadWriteSeparate(t *testing.T) {
assert.True(t, user4.ID > 0)
})
}

assert.NoError(t, dbs[database.DriverSqlite]["read"].Docker().Stop())
assert.NoError(t, dbs[database.DriverSqlite]["write"].Docker().Stop())
}

func TestTablePrefixAndSingular(t *testing.T) {
if env.IsWindows() {
t.Skip("Skipping tests that use Docker")
t.Skip("Skip test that using Docker")
}

dbs := NewTestQueries().QueriesWithPrefixAndSingular()
Expand All @@ -3817,6 +3825,10 @@ func TestTablePrefixAndSingular(t *testing.T) {
assert.True(t, user1.ID > 0)
})
}

if dbs[database.DriverSqlite] != nil {
assert.NoError(t, dbs[database.DriverSqlite].Docker().Stop())
}
}

func paginator(page string, limit string) func(methods contractsorm.Query) contractsorm.Query {
Expand Down
113 changes: 61 additions & 52 deletions database/gorm/test_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,53 +31,35 @@ const (

var testContext = context.Background()

type TestReadWriteConfig struct {
ReadPort int
WritePort int

// Used by Sqlite
ReadDatabase string
}

type testMockDriver interface {
Common()
ReadWrite(config TestReadWriteConfig)
ReadWrite(readDatabaseConfig testing.DatabaseConfig)
WithPrefixAndSingular()
}

type TestQueries struct {
mysqlDockers []testing.DatabaseDriver
postgresDockers []testing.DatabaseDriver
sqliteDockers []testing.DatabaseDriver
sqlserverDockers []testing.DatabaseDriver
}

func NewTestQueries() *TestQueries {
testQueries := &TestQueries{
sqliteDockers: supportdocker.Sqlites(2),
postgresDockers: supportdocker.Postgreses(2),
}

if supportdocker.TestModel == supportdocker.TestModelMinimum {
return testQueries
}

testQueries.mysqlDockers = supportdocker.Mysqls(2)
testQueries.sqlserverDockers = supportdocker.Sqlservers(2)

return testQueries
return &TestQueries{}
}

func (r *TestQueries) Queries() map[contractsdatabase.Driver]*TestQuery {
return r.queries(false)
}

func (r *TestQueries) QueriesOfReadWrite() map[contractsdatabase.Driver]map[string]*TestQuery {
readPostgresQuery := NewTestQuery(r.postgresDockers[0])
writePostgresQuery := NewTestQuery(r.postgresDockers[1])
postgresDockers := supportdocker.Postgreses(2)
sqliteDockers := supportdocker.Sqlites(2)
if err := supportdocker.Ready(postgresDockers...); err != nil {
panic(err)
}

readSqliteQuery := NewTestQuery(r.sqliteDockers[0])
writeSqliteQuery := NewTestQuery(r.sqliteDockers[1])
readPostgresQuery := NewTestQuery(postgresDockers[0])
writePostgresQuery := NewTestQuery(postgresDockers[1])

readSqliteQuery := NewTestQuery(sqliteDockers[0])
writeSqliteQuery := NewTestQuery(sqliteDockers[1])

queries := map[contractsdatabase.Driver]map[string]*TestQuery{
contractsdatabase.DriverPostgres: {
Expand All @@ -94,11 +76,21 @@ func (r *TestQueries) QueriesOfReadWrite() map[contractsdatabase.Driver]map[stri
return queries
}

readMysqlQuery := NewTestQuery(r.mysqlDockers[0])
writeMysqlQuery := NewTestQuery(r.mysqlDockers[1])
// Create all containers first, containers will be returned directly, then check containers status, the speed will be faster.
mysqlDockers := supportdocker.Mysqls(2)
sqlserverDockers := supportdocker.Sqlservers(2)
if err := supportdocker.Ready(mysqlDockers...); err != nil {
panic(err)
}
if err := supportdocker.Ready(sqlserverDockers...); err != nil {
panic(err)
}

readSqlserverQuery := NewTestQuery(r.sqlserverDockers[0])
writeSqlserverQuery := NewTestQuery(r.sqlserverDockers[1])
readMysqlQuery := NewTestQuery(mysqlDockers[0])
writeMysqlQuery := NewTestQuery(mysqlDockers[1])

readSqlserverQuery := NewTestQuery(sqlserverDockers[0])
writeSqlserverQuery := NewTestQuery(sqlserverDockers[1])

queries[contractsdatabase.DriverMysql] = map[string]*TestQuery{
"read": readMysqlQuery,
Expand All @@ -117,22 +109,39 @@ func (r *TestQueries) QueriesWithPrefixAndSingular() map[contractsdatabase.Drive
}

func (r *TestQueries) QueryOfAdditional() *TestQuery {
postgresQuery := NewTestQuery(r.postgresDockers[1])
postgresDocker := supportdocker.Postgres()
if err := supportdocker.Ready(postgresDocker); err != nil {
panic(err)
}
postgresQuery := NewTestQuery(postgresDocker)

return postgresQuery
}

func (r *TestQueries) queries(withPrefixAndSingular bool) map[contractsdatabase.Driver]*TestQuery {
driverToTestQuery := make(map[contractsdatabase.Driver]*TestQuery)
postgresDocker := supportdocker.Postgres()
if err := supportdocker.Ready(postgresDocker); err != nil {
panic(err)
}

driverToDocker := map[contractsdatabase.Driver]testing.DatabaseDriver{
contractsdatabase.DriverPostgres: r.postgresDockers[0],
contractsdatabase.DriverSqlite: r.sqliteDockers[0],
contractsdatabase.DriverPostgres: postgresDocker,
contractsdatabase.DriverSqlite: supportdocker.Sqlite(),
}

if supportdocker.TestModel != supportdocker.TestModelMinimum {
driverToDocker[contractsdatabase.DriverMysql] = r.mysqlDockers[0]
driverToDocker[contractsdatabase.DriverSqlserver] = r.sqlserverDockers[0]
mysqlDocker := supportdocker.Mysql()
sqlserverDocker := supportdocker.Sqlserver()
if err := supportdocker.Ready(mysqlDocker); err != nil {
panic(err)
}
if err := supportdocker.Ready(sqlserverDocker); err != nil {
panic(err)
}

driverToDocker[contractsdatabase.DriverMysql] = mysqlDocker
driverToDocker[contractsdatabase.DriverSqlserver] = sqlserverDocker
}

for driver, docker := range driverToDocker {
Expand Down Expand Up @@ -203,10 +212,10 @@ func (r *TestQuery) Query() orm.Query {
return r.query
}

func (r *TestQuery) QueryOfReadWrite(config TestReadWriteConfig) (orm.Query, error) {
func (r *TestQuery) QueryOfReadWrite(readDatabaseConfig testing.DatabaseConfig) (orm.Query, error) {
mockConfig := &mocksconfig.Config{}
mockDriver := getMockDriver(r.Docker(), mockConfig, r.Docker().Driver().String())
mockDriver.ReadWrite(config)
mockDriver.ReadWrite(readDatabaseConfig)

return BuildQuery(testContext, mockConfig, r.docker.Driver().String(), nil, nil)
}
Expand Down Expand Up @@ -260,12 +269,12 @@ func (r *MockMysql) Common() {
r.basic()
}

func (r *MockMysql) ReadWrite(config TestReadWriteConfig) {
func (r *MockMysql) ReadWrite(readDatabaseConfig testing.DatabaseConfig) {
r.mockConfig.On("Get", fmt.Sprintf("database.connections.%s.read", r.connection)).Return([]contractsdatabase.Config{
{Host: "127.0.0.1", Port: config.ReadPort, Username: r.user, Password: r.password},
{Host: "127.0.0.1", Database: readDatabaseConfig.Database, Port: readDatabaseConfig.Port, Username: r.user, Password: r.password},
})
r.mockConfig.On("Get", fmt.Sprintf("database.connections.%s.write", r.connection)).Return([]contractsdatabase.Config{
{Host: "127.0.0.1", Port: config.WritePort, Username: r.user, Password: r.password},
{Host: "127.0.0.1", Database: r.database, Port: r.port, Username: r.user, Password: r.password},
})
r.mockConfig.On("GetString", fmt.Sprintf("database.connections.%s.prefix", r.connection)).Return("")
r.mockConfig.On("GetBool", fmt.Sprintf("database.connections.%s.singular", r.connection)).Return(false)
Expand Down Expand Up @@ -331,12 +340,12 @@ func (r *MockPostgres) Common() {
r.basic()
}

func (r *MockPostgres) ReadWrite(config TestReadWriteConfig) {
func (r *MockPostgres) ReadWrite(readDatabaseConfig testing.DatabaseConfig) {
r.mockConfig.On("Get", fmt.Sprintf("database.connections.%s.read", r.connection)).Return([]contractsdatabase.Config{
{Host: "127.0.0.1", Port: config.ReadPort, Username: r.user, Password: r.password},
{Host: "127.0.0.1", Database: readDatabaseConfig.Database, Port: readDatabaseConfig.Port, Username: r.user, Password: r.password},
})
r.mockConfig.On("Get", fmt.Sprintf("database.connections.%s.write", r.connection)).Return([]contractsdatabase.Config{
{Host: "127.0.0.1", Port: config.WritePort, Username: r.user, Password: r.password},
{Host: "127.0.0.1", Database: r.database, Port: r.port, Username: r.user, Password: r.password},
})
r.mockConfig.On("GetString", fmt.Sprintf("database.connections.%s.prefix", r.connection)).Return("")
r.mockConfig.On("GetBool", fmt.Sprintf("database.connections.%s.singular", r.connection)).Return(false)
Expand Down Expand Up @@ -396,9 +405,9 @@ func (r *MockSqlite) Common() {
r.basic()
}

func (r *MockSqlite) ReadWrite(config TestReadWriteConfig) {
func (r *MockSqlite) ReadWrite(readDatabaseConfig testing.DatabaseConfig) {
r.mockConfig.On("Get", fmt.Sprintf("database.connections.%s.read", r.connection)).Return([]contractsdatabase.Config{
{Database: config.ReadDatabase},
{Database: readDatabaseConfig.Database},
})
r.mockConfig.On("Get", fmt.Sprintf("database.connections.%s.write", r.connection)).Return([]contractsdatabase.Config{
{Database: r.database},
Expand Down Expand Up @@ -459,12 +468,12 @@ func (r *MockSqlserver) Common() {
r.basic()
}

func (r *MockSqlserver) ReadWrite(config TestReadWriteConfig) {
func (r *MockSqlserver) ReadWrite(readDatabaseConfig testing.DatabaseConfig) {
r.mockConfig.On("Get", fmt.Sprintf("database.connections.%s.read", r.connection)).Return([]contractsdatabase.Config{
{Host: "127.0.0.1", Port: config.ReadPort, Username: r.user, Password: r.password},
{Host: "127.0.0.1", Database: readDatabaseConfig.Database, Port: readDatabaseConfig.Port, Username: r.user, Password: r.password},
})
r.mockConfig.On("Get", fmt.Sprintf("database.connections.%s.write", r.connection)).Return([]contractsdatabase.Config{
{Host: "127.0.0.1", Port: config.WritePort, Username: r.user, Password: r.password},
{Host: "127.0.0.1", Database: r.database, Port: r.port, Username: r.user, Password: r.password},
})
r.mockConfig.On("GetString", fmt.Sprintf("database.connections.%s.prefix", r.connection)).Return("")
r.mockConfig.On("GetBool", fmt.Sprintf("database.connections.%s.singular", r.connection)).Return(false)
Expand Down
Loading

0 comments on commit 197dd26

Please sign in to comment.