Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion database/gorm/query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3938,7 +3938,7 @@ func TestTablePrefixAndSingular(t *testing.T) {
}
}

func TestSchema(t *testing.T) {
func TestPostgresSchema(t *testing.T) {
if env.IsWindows() {
t.Skip("Skip test that using Docker")
}
Expand All @@ -3958,6 +3958,26 @@ func TestSchema(t *testing.T) {
assert.True(t, user1.ID > 0)
}

func TestSqlserverSchema(t *testing.T) {
if env.IsWindows() {
t.Skip("Skip test that using Docker")
}

sqlserverDocker := supportdocker.Sqlserver()
require.NoError(t, sqlserverDocker.Ready())

testQuery := NewTestQueryWithSchema(sqlserverDocker, "goravel")
testQuery.CreateTable(TestTableSchema)

schema := Schema{Name: "first_schema"}
assert.Nil(t, testQuery.Query().Create(&schema))
assert.True(t, schema.ID > 0)

var schema1 Schema
assert.Nil(t, testQuery.Query().Where("name", "first_schema").First(&schema1))
assert.True(t, schema1.ID > 0)
}

func paginator(page string, limit string) func(methods contractsorm.Query) contractsorm.Query {
return func(query contractsorm.Query) contractsorm.Query {
page, _ := strconv.Atoi(page)
Expand Down
9 changes: 9 additions & 0 deletions database/gorm/test_models.go
Original file line number Diff line number Diff line change
Expand Up @@ -420,3 +420,12 @@ type Box struct {
func (p *Box) Connection() string {
return "postgres"
}

type Schema struct {
Model
Name string
}

func (r *Schema) TableName() string {
return "goravel.schemas"
}
90 changes: 79 additions & 11 deletions database/gorm/test_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const (
TestTableRoleUser
TestTableUsers
TestTableGoravelUser
TestTableSchema
)

var testContext = context.Background()
Expand Down Expand Up @@ -215,39 +216,48 @@ func NewTestQueryWithSchema(docker testing.DatabaseDriver, schema string) *TestQ
// Create schema before build query with the schema
mockConfig := &mocksconfig.Config{}
mockDriver := getMockDriver(docker, mockConfig, docker.Driver().String())
mockDriver.WithPrefixAndSingular()
mockDriver.Common()
query, err := BuildQuery(testContext, mockConfig, docker.Driver().String(), utils.NewTestLog(), nil)
if err != nil {
panic(fmt.Sprintf("connect to %s failed: %v", docker.Driver().String(), err))
}

if _, err := query.Exec(fmt.Sprintf("CREATE SCHEMA %s", schema)); err != nil {
panic(fmt.Sprintf("create schema %s failed: %v", schema, err))
}

mockConfig = &mocksconfig.Config{}
mockDriver = getMockDriver(docker, mockConfig, docker.Driver().String())
testQuery := &TestQuery{
docker: docker,
mockConfig: mockConfig,
mockDriver: mockDriver,
query: query,
}

mockDriver.WithSchema(schema)
if _, err := query.Exec(fmt.Sprintf(`CREATE SCHEMA "%s"`, schema)); err != nil {
panic(fmt.Sprintf("create schema %s failed: %v", schema, err))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Test coverage for schema operations is adequate, but error scenarios need attention

Based on the verification results, I found that:

  1. Schema creation and basic operations are well-tested for both PostgreSQL and SQL Server in:

    • database/schema/schema_test.go
    • database/gorm/query_test.go
  2. However, error scenarios are not adequately covered:

    • The panic in NewTestQueryWithSchema for unsupported drivers is tested implicitly
    • Schema creation error handling (line 233) lacks explicit test coverage
    • SQL Server schema configuration (lines 584-588) has basic tests but no error scenarios
    • Schema table definitions (lines 1266-1307) have functional tests but lack edge cases

Recommendations:

  • Add test cases for schema creation failures
  • Include error scenarios for SQL Server schema operations
  • Add edge cases for schema table definitions with invalid inputs
🔗 Analysis chain

Improve test coverage for schema operations.

Several critical code paths lack test coverage:

  1. Schema creation error handling
  2. SQL Server schema configuration
  3. Schema table definitions for different databases

Let's verify the existing test coverage:

Would you like me to help create additional test cases to cover these scenarios?

Also applies to: 584-588, 1266-1307


Let's gather more information about the test coverage for schema operations.


Let's check the actual test implementations to verify the coverage of error scenarios.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for existing schema-related tests
# Look for test files that might contain schema-related tests
rg -l "TestSchema|test.*Schema|schema.*Test" --type go

Length of output: 349


Script:

#!/bin/bash
# Check for test cases related to schema creation and error handling
rg "func.*Test.*Schema.*" --type go -A 5

# Check for specific schema creation error tests
rg "TestSchema.*Error|TestCreate.*Schema.*Error" --type go -A 5

# Look for SQL Server schema configuration tests
rg "TestWithSchema|TestSQLServer.*Schema" --type go -A 5

# Check schema table definition tests
rg "TestSchema.*Table|TestCreateTable" --type go -A 5

Length of output: 6846


Script:

#!/bin/bash
# Check the content of schema-related tests
rg "TestPostgresSchema|TestSqlserverSchema" --type go -B 2 -A 20

# Look for panic handling in tests
rg "panic.*schema" --type go -B 2 -A 2

# Check schema creation error handling in tests
rg "create.*schema.*error|schema.*create.*error" --type go -i -B 2 -A 2

Length of output: 7973

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 233-233: database/gorm/test_utils.go#L233
Added line #L233 was not covered by tests

}

if docker.Driver() == contractsdatabase.DriverSqlserver {
return testQuery
}

mockConfig = &mocksconfig.Config{}
mockDriver = getMockDriver(docker, mockConfig, docker.Driver().String())
mockDriver.WithSchema(schema)
query, err = BuildQuery(testContext, mockConfig, docker.Driver().String(), utils.NewTestLog(), nil)
if err != nil {
panic(fmt.Sprintf("connect to %s failed: %v", docker.Driver().String(), err))
}

testQuery.query = query
testQuery = &TestQuery{
docker: docker,
mockConfig: mockConfig,
mockDriver: mockDriver,
query: query,
}

return testQuery
}

func (r *TestQuery) CreateTable(testTables ...TestTable) {
for table, sql := range newTestTables(r.docker.Driver()).All() {
if len(testTables) == 0 || slices.Contains(testTables, table) {
if (len(testTables) == 0 && table != TestTableSchema) || slices.Contains(testTables, table) {
if _, err := r.query.Exec(sql()); err != nil {
panic(fmt.Sprintf("create table %v failed: %v", table, err))
}
Expand Down Expand Up @@ -540,6 +550,8 @@ func NewMockSqlserver(mockConfig *mocksconfig.Config, connection, database, user
func (r *MockSqlserver) Common() {
r.mockConfig.EXPECT().GetString(fmt.Sprintf("database.connections.%s.prefix", r.connection)).Return("")
r.mockConfig.EXPECT().GetBool(fmt.Sprintf("database.connections.%s.singular", r.connection)).Return(false)
r.mockConfig.EXPECT().GetString(fmt.Sprintf("database.connections.%s.schema", r.connection), "dbo").Return("dbo")

r.single()
r.basic()
}
Expand All @@ -554,18 +566,26 @@ func (r *MockSqlserver) ReadWrite(readDatabaseConfig testing.DatabaseConfig) {
r.mockConfig.EXPECT().GetString(fmt.Sprintf("database.connections.%s.dsn", r.connection)).Return("")
r.mockConfig.EXPECT().GetString(fmt.Sprintf("database.connections.%s.prefix", r.connection)).Return("")
r.mockConfig.EXPECT().GetBool(fmt.Sprintf("database.connections.%s.singular", r.connection)).Return(false)
r.mockConfig.EXPECT().GetString(fmt.Sprintf("database.connections.%s.schema", r.connection), "dbo").Return("dbo")

r.basic()
}

func (r *MockSqlserver) WithPrefixAndSingular() {
r.mockConfig.EXPECT().GetString(fmt.Sprintf("database.connections.%s.prefix", r.connection)).Return("goravel_")
r.mockConfig.EXPECT().GetBool(fmt.Sprintf("database.connections.%s.singular", r.connection)).Return(true)
r.mockConfig.EXPECT().GetString(fmt.Sprintf("database.connections.%s.schema", r.connection), "dbo").Return("dbo")

r.single()
r.basic()
}

func (r *MockSqlserver) WithSchema(schema string) {
panic("sqlserver does not support schema for now")
r.mockConfig.EXPECT().GetString(fmt.Sprintf("database.connections.%s.prefix", r.connection)).Return("")
r.mockConfig.EXPECT().GetBool(fmt.Sprintf("database.connections.%s.singular", r.connection)).Return(false)
r.mockConfig.EXPECT().GetString(fmt.Sprintf("database.connections.%s.schema", r.connection), "public").Return(schema)
r.single()
r.basic()
}

func (r *MockSqlserver) basic() {
Expand Down Expand Up @@ -611,6 +631,7 @@ func (r *testTables) All() map[TestTable]func() string {
TestTableRoleUser: r.roleUser,
TestTableUsers: r.users,
TestTableGoravelUser: r.goravelUser,
TestTableSchema: r.schema,
}
}

Expand Down Expand Up @@ -1240,6 +1261,53 @@ CREATE TABLE role_user (
}
}

func (r *testTables) schema() string {
switch r.driver {
case contractsdatabase.DriverMysql:
return `
CREATE TABLE goravel.schemas (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
name varchar(255) NOT NULL,
created_at datetime(3) NOT NULL,
updated_at datetime(3) NOT NULL,
PRIMARY KEY (id),
KEY idx_schemas_created_at (created_at),
KEY idx_schemas_updated_at (updated_at)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
`
case contractsdatabase.DriverPostgres:
return `
CREATE TABLE goravel.schemas (
id SERIAL PRIMARY KEY NOT NULL,
name varchar(255) NOT NULL,
created_at timestamp NOT NULL,
updated_at timestamp NOT NULL
);
`
case contractsdatabase.DriverSqlite:
return `
CREATE TABLE goravel.schemas (
id integer PRIMARY KEY AUTOINCREMENT NOT NULL,
name varchar(255) NOT NULL,
created_at datetime NOT NULL,
updated_at datetime NOT NULL
);
`
case contractsdatabase.DriverSqlserver:
return `
CREATE TABLE goravel.schemas (
id bigint NOT NULL IDENTITY(1,1),
name varchar(255) NOT NULL,
created_at datetime NOT NULL,
updated_at datetime NOT NULL,
PRIMARY KEY (id)
);
`
default:
return ""
}
}

func mockPool(mockConfig *mocksconfig.Config) {
mockConfig.EXPECT().GetInt("database.pool.max_idle_conns", 10).Return(10)
mockConfig.EXPECT().GetInt("database.pool.max_open_conns", 100).Return(100)
Expand Down
64 changes: 56 additions & 8 deletions database/migration/default_migrator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ func (s *DefaultMigratorWithDBSuite) TestStatus() {
}
}

func TestDefaultMigratorWithWithSchema(t *testing.T) {
func TestDefaultMigratorWithPostgresSchema(t *testing.T) {
if env.IsWindows() {
t.Skip("Skip test that using Docker")
}
Expand All @@ -182,6 +182,32 @@ func TestDefaultMigratorWithWithSchema(t *testing.T) {

assert.NoError(t, migrator.Run())
assert.True(t, schema.HasTable("users"))
assert.NoError(t, migrator.Rollback(1, 0))
assert.False(t, schema.HasTable("users"))
}

func TestDefaultMigratorWithSqlserverSchema(t *testing.T) {
if env.IsWindows() {
t.Skip("Skip test that using Docker")
}

sqlserverDocker := docker.Sqlserver()
require.NoError(t, sqlserverDocker.Ready())

sqlserverQuery := gorm.NewTestQueryWithSchema(sqlserverDocker, "goravel")
schema := databaseschema.GetTestSchema(sqlserverQuery, map[contractsdatabase.Driver]*gorm.TestQuery{
contractsdatabase.DriverSqlserver: sqlserverQuery,
})
testMigration := NewTestMigrationWithSqlserverSchema(schema)
schema.Register([]contractsschema.Migration{
testMigration,
})
migrator := NewDefaultMigrator(nil, schema, "migrations")

assert.NoError(t, migrator.Run())
assert.True(t, schema.HasTable("goravel.users"))
assert.NoError(t, migrator.Rollback(1, 0))
assert.False(t, schema.HasTable("goravel.users"))
}

type DefaultMigratorSuite struct {
Expand Down Expand Up @@ -861,9 +887,9 @@ func (s *DefaultMigratorSuite) TestStatus() {
}

func (s *DefaultMigratorSuite) mockRunDown(
mockOrm *mocksorm.Orm,
previousConnection, migrationSignature, table string,
err error,
mockOrm *mocksorm.Orm,
previousConnection, migrationSignature, table string,
err error,
) {
s.mockSchema.EXPECT().GetConnection().Return(previousConnection).Once()
s.mockSchema.EXPECT().Orm().Return(mockOrm).Times(5)
Expand All @@ -888,10 +914,10 @@ func (s *DefaultMigratorSuite) mockRunDown(
}

func (s *DefaultMigratorSuite) mockRunUp(
mockOrm *mocksorm.Orm,
previousConnection, migrationSignature, table string,
batch int,
err error,
mockOrm *mocksorm.Orm,
previousConnection, migrationSignature, table string,
batch int,
err error,
) {
s.mockSchema.EXPECT().GetConnection().Return(previousConnection).Once()
s.mockSchema.EXPECT().Orm().Return(mockOrm).Times(5)
Expand Down Expand Up @@ -937,6 +963,28 @@ func (r *TestMigration) Down() error {
return r.schema.DropIfExists("users")
}

type TestMigrationWithSqlserverSchema struct {
schema contractsschema.Schema
}

func NewTestMigrationWithSqlserverSchema(schema contractsschema.Schema) *TestMigrationWithSqlserverSchema {
return &TestMigrationWithSqlserverSchema{schema: schema}
}

func (r *TestMigrationWithSqlserverSchema) Signature() string {
return "20240817214501_create_users_table"
}

func (r *TestMigrationWithSqlserverSchema) Up() error {
return r.schema.Create("goravel.users", func(table contractsschema.Blueprint) {
table.String("name")
})
}

func (r *TestMigrationWithSqlserverSchema) Down() error {
return r.schema.DropIfExists("goravel.users")
}

type TestConnectionMigration struct {
schema contractsschema.Schema
}
Expand Down
3 changes: 1 addition & 2 deletions database/schema/grammars/wrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,8 @@ func (r *Wrap) Table(table string) string {
}
if strings.Contains(table, ".") {
lastDotIndex := strings.LastIndex(table, ".")
newTable := table[:lastDotIndex] + "." + r.tablePrefix + table[lastDotIndex+1:]

return r.Value(newTable)
return r.Value(table[:lastDotIndex]) + "." + r.Value(r.tablePrefix+table[lastDotIndex+1:])
}

return r.Value(r.tablePrefix + table)
Expand Down
Loading