From 4fd3f63dbebb9220bf083de7e54908e32a6bddc4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2024 10:36:53 +0800 Subject: [PATCH 1/5] chore(deps): Update module google.golang.org/grpc to v1.66.1 (#637) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0bb3a80d2..f45f11b73 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,7 @@ require ( go.uber.org/atomic v1.11.0 golang.org/x/crypto v0.27.0 golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e - google.golang.org/grpc v1.66.0 + google.golang.org/grpc v1.66.1 gorm.io/driver/mysql v1.5.7 gorm.io/driver/postgres v1.5.9 gorm.io/driver/sqlserver v1.5.3 diff --git a/go.sum b/go.sum index 6b7186a31..c00e9ec22 100644 --- a/go.sum +++ b/go.sum @@ -1024,8 +1024,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c= -google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.66.1 h1:hO5qAXR19+/Z44hmvIM4dQFMSYX9XcWsByfoxutBpAM= +google.golang.org/grpc v1.66.1/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From 413083b7cf31758c8adf48cc136bafe21b3c9ff1 Mon Sep 17 00:00:00 2001 From: krishan kumar <84431594+kkumar-gcc@users.noreply.github.com> Date: Wed, 11 Sep 2024 07:29:46 +0530 Subject: [PATCH 2/5] add test cases for regex/regexp rule (#638) --- validation/validation_test.go | 113 ++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/validation/validation_test.go b/validation/validation_test.go index 7c9efa194..e32ff4850 100644 --- a/validation/validation_test.go +++ b/validation/validation_test.go @@ -195,6 +195,119 @@ type Case struct { setup func(Case) } +func TestRule_Regex(t *testing.T) { + validation := NewValidation() + tests := []Case{ + { + description: "success with valid regex match", + setup: func(c Case) { + validator, err := validation.Make(map[string]any{ + "email": "test@example.com", + }, map[string]string{ + "email": "regex:^\\S+@\\S+\\.\\S+$", + }) + assert.Nil(t, err, c.description) + assert.NotNil(t, validator, c.description) + assert.False(t, validator.Fails(), c.description) + }, + }, + { + description: "error with invalid regex match", + setup: func(c Case) { + validator, err := validation.Make(map[string]any{ + "email": "testexample.com", + }, map[string]string{ + "email": "regex:^\\S+@\\S+\\.\\S+$", + }) + assert.Nil(t, err, c.description) + assert.NotNil(t, validator, c.description) + assert.Equal(t, map[string]string{ + "regex": "email value does not pass the regex check", + }, validator.Errors().Get("email")) + }, + }, + { + description: "success with regex and nested structure", + setup: func(c Case) { + validator, err := validation.Make(map[string]any{ + "user": map[string]string{ + "email": "test@example.com", + }, + }, map[string]string{ + "user.email": "regex:^\\S+@\\S+\\.\\S+$", + }) + assert.Nil(t, err, c.description) + assert.NotNil(t, validator, c.description) + assert.False(t, validator.Fails(), c.description) + }, + }, + { + description: "error with regex and nested structure", + setup: func(c Case) { + validator, err := validation.Make(map[string]any{ + "user": map[string]string{ + "email": "testexample.com", + }, + }, map[string]string{ + "user.email": "regex:^\\S+@\\S+\\.\\S+$", + }) + assert.Nil(t, err, c.description) + assert.NotNil(t, validator, c.description) + assert.Equal(t, map[string]string{ + "regex": "user.email value does not pass the regex check", + }, validator.Errors().Get("user.email")) + }, + }, + { + description: "panic when regex pattern is missing", + setup: func(c Case) { + assert.Panics(t, func() { + _, err := validation.Make(map[string]any{ + "email": "test@example.com", + }, map[string]string{ + "email": "regex:", + }) + assert.NotNil(t, err, c.description) + }, c.description) + }, + }, + { + description: "success with valid regexp match", + setup: func(c Case) { + validator, err := validation.Make(map[string]any{ + "phone": "+1-800-555-5555", + }, map[string]string{ + "phone": "regexp:^\\+\\d{1,3}-\\d{3}-\\d{3}-\\d{4}$", + }) + assert.Nil(t, err, c.description) + assert.NotNil(t, validator, c.description) + assert.False(t, validator.Fails(), c.description) + }, + }, + { + description: "error with invalid regexp match", + setup: func(c Case) { + validator, err := validation.Make(map[string]any{ + "phone": "18005555555", + }, map[string]string{ + "phone": "regexp:^\\+\\d{1,3}-\\d{3}-\\d{3}-\\d{4}$", + }) + assert.Nil(t, err, c.description) + assert.NotNil(t, validator, c.description) + assert.Equal(t, map[string]string{ + "regexp": "phone must match pattern ^\\+\\d{1,3}-\\d{3}-\\d{3}-\\d{4}$", + }, validator.Errors().Get("phone")) + }, + }, + } + + for _, test := range tests { + t.Run(test.description, func(t *testing.T) { + test.setup(test) + }) + } +} + func TestRule_Required(t *testing.T) { validation := NewValidation() tests := []Case{ From 97abc6b9d29f797c716baa2338fee53059d231ea Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:47:42 +0800 Subject: [PATCH 3/5] chore(deps): Update module gorm.io/plugin/dbresolver to v1.5.3 (#639) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index f45f11b73..33bc2c41f 100644 --- a/go.mod +++ b/go.mod @@ -41,8 +41,8 @@ require ( gorm.io/driver/mysql v1.5.7 gorm.io/driver/postgres v1.5.9 gorm.io/driver/sqlserver v1.5.3 - gorm.io/gorm v1.25.11 - gorm.io/plugin/dbresolver v1.5.2 + gorm.io/gorm v1.25.12 + gorm.io/plugin/dbresolver v1.5.3 ) require ( diff --git a/go.sum b/go.sum index c00e9ec22..9ff1f7b22 100644 --- a/go.sum +++ b/go.sum @@ -1061,7 +1061,6 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/driver/mysql v1.5.6/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM= gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo= gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM= gorm.io/driver/postgres v1.5.9 h1:DkegyItji119OlcaLjqN11kHoUgZ/j13E0jkJZgD6A8= @@ -1070,10 +1069,10 @@ gorm.io/driver/sqlserver v1.5.3 h1:rjupPS4PVw+rjJkfvr8jn2lJ8BMhT4UW5FwuJY0P3Z0= gorm.io/driver/sqlserver v1.5.3/go.mod h1:B+CZ0/7oFJ6tAlefsKoyxdgDCXJKSgwS2bMOQZT0I00= gorm.io/gorm v1.25.7-0.20240204074919-46816ad31dde/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= -gorm.io/gorm v1.25.11 h1:/Wfyg1B/je1hnDx3sMkX+gAlxrlZpn6X0BXRlwXlvHg= -gorm.io/gorm v1.25.11/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= -gorm.io/plugin/dbresolver v1.5.2 h1:Iut7lW4TXNoVs++I+ra3zxjSxTRj4ocIeFEVp4lLhII= -gorm.io/plugin/dbresolver v1.5.2/go.mod h1:jPh59GOQbO7v7v28ZKZPd45tr+u3vyT+8tHdfdfOWcU= +gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8= +gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= +gorm.io/plugin/dbresolver v1.5.3 h1:wFwINGZZmttuu9h7XpvbDHd8Lf9bb8GNzp/NpAMV2wU= +gorm.io/plugin/dbresolver v1.5.3/go.mod h1:TSrVhaUg2DZAWP3PrHlDlITEJmNOkL0tFTjvTEsQ4XE= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= From 40b9e2a0a57bc024ed210286b7985ba51170074d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=97=E5=AD=90?= Date: Wed, 11 Sep 2024 17:26:51 +0800 Subject: [PATCH 4/5] feat: some optimize (#622) * feat: add benchmark * chore: update mocks * feat: bump go1.22 * workflow: fix benchmark * feat: optimize session * chore: update mocks * feat: add more benchmark cases * fix: tests * revert: session manager Extend * chore: update mocks * fix: lint * fix: tests * fix: tests * feat: optimize code * refactor: change session manager Extend * chore: update mocks * workflow: add govulncheck * workflow: add govulncheck * workflow: add govulncheck * workflow: fix shellcheck * refactor: rename postgresql to postgres * workflow: add nilaway * workflow: optimize nilaway * workflow: Update lint.yml * feat: optimize code * chore: update mocks * workflow: use .github source * workflow: debug * workflow: finish debug * chore: sort --------- Co-authored-by: devhaozi --- .github/workflows/benchmark.yml | 17 ++ .github/workflows/govulncheck.yml | 8 + .github/workflows/mockery.yml | 3 + contracts/database/orm/constants.go | 10 +- contracts/session/manager.go | 4 +- crypt/aes_test.go | 32 ++++ database/console/migrate.go | 10 +- database/console/migrate_command_test.go | 6 +- database/console/migrate_creator.go | 6 +- .../console/migrate_fresh_command_test.go | 4 +- .../console/migrate_refresh_command_test.go | 4 +- .../console/migrate_reset_command_test.go | 4 +- .../console/migrate_rollback_command_test.go | 4 +- .../console/migrate_status_command_test.go | 4 +- database/db/dsn.go | 4 +- database/db/dsn_test.go | 6 +- database/gorm/dialector.go | 10 +- database/gorm/dialector_test.go | 12 +- database/gorm/query.go | 8 +- database/gorm/query_test.go | 128 ++++++------- database/gorm/test_models.go | 2 +- database/gorm/test_utils.go | 98 +++++----- database/gorm/test_utils_test.go | 2 +- database/migration/sql_driver.go | 6 +- database/migration/sql_driver_test.go | 16 +- database/migration/stubs.go | 10 +- database/orm_test.go | 34 ++-- foundation/application_test.go | 1 + go.mod | 2 +- hash/application_test.go | 84 +++++++-- hash/bcrypt.go | 2 +- http/middleware/throttle_test.go | 82 +++++++++ log/logger/daily.go | 2 + log/logrus_writer_test.go | 68 ++++++- mocks/session/Manager.go | 47 ++++- session/driver/file_test.go | 29 ++- session/manager.go | 94 ++++++++-- session/manager_test.go | 171 ++++++++++-------- session/middleware/start_session.go | 5 +- session/middleware/start_session_test.go | 1 + session/service_provider.go | 31 ---- session/session.go | 16 ++ support/docker/{postgresql.go => postgres.go} | 10 +- .../{postgresql_test.go => postgres_test.go} | 44 ++--- support/file/file_test.go | 4 +- testing/docker/database.go | 2 +- testing/docker/database_test.go | 14 +- testing/docker/docker_test.go | 12 +- translation/file_loader_test.go | 42 ++++- translation/translator_test.go | 63 +++++++ validation/errors_test.go | 4 +- 51 files changed, 863 insertions(+), 419 deletions(-) create mode 100644 .github/workflows/benchmark.yml create mode 100644 .github/workflows/govulncheck.yml rename support/docker/{postgresql.go => postgres.go} (92%) rename support/docker/{postgresql_test.go => postgres_test.go} (57%) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml new file mode 100644 index 000000000..251fce321 --- /dev/null +++ b/.github/workflows/benchmark.yml @@ -0,0 +1,17 @@ +name: Benchmark +on: + push: + branches: + - master + paths-ignore: + - "**/*.md" + pull_request: + paths-ignore: + - "**/*.md" +permissions: + contents: write + pull-requests: write +jobs: + benchmark: + uses: goravel/.github/.github/workflows/benchmark.yml@master + secrets: inherit \ No newline at end of file diff --git a/.github/workflows/govulncheck.yml b/.github/workflows/govulncheck.yml new file mode 100644 index 000000000..99b1e830d --- /dev/null +++ b/.github/workflows/govulncheck.yml @@ -0,0 +1,8 @@ +name: Govulncheck +on: + schedule: + - cron: "0 */6 * * *" # Run every 6 hours +jobs: + govulncheck: + uses: goravel/.github/.github/workflows/govulncheck.yml@master + secrets: inherit \ No newline at end of file diff --git a/.github/workflows/mockery.yml b/.github/workflows/mockery.yml index 7259d4b3a..1ae679f1e 100644 --- a/.github/workflows/mockery.yml +++ b/.github/workflows/mockery.yml @@ -1,6 +1,9 @@ name: Mockery on: pull_request: +permissions: + contents: write + pull-requests: write jobs: mockery: runs-on: ubuntu-latest diff --git a/contracts/database/orm/constants.go b/contracts/database/orm/constants.go index 371f144f6..c66bb6600 100644 --- a/contracts/database/orm/constants.go +++ b/contracts/database/orm/constants.go @@ -1,12 +1,10 @@ package orm const ( - DriverMysql Driver = "mysql" - // DriverPostgresql DEPRECATED, use DriverPostgres instead. - DriverPostgresql Driver = "postgresql" - DriverPostgres Driver = "postgres" - DriverSqlite Driver = "sqlite" - DriverSqlserver Driver = "sqlserver" + DriverMysql Driver = "mysql" + DriverPostgres Driver = "postgres" + DriverSqlite Driver = "sqlite" + DriverSqlserver Driver = "sqlserver" ) type Driver string diff --git a/contracts/session/manager.go b/contracts/session/manager.go index 4db8935ac..bf2dd9bfb 100644 --- a/contracts/session/manager.go +++ b/contracts/session/manager.go @@ -6,5 +6,7 @@ type Manager interface { // Driver retrieves the session driver by name. Driver(name ...string) (Driver, error) // Extend extends the session manager with a custom driver. - Extend(driver string, handler func() Driver) Manager + Extend(driver string, handler func() Driver) error + // ReleaseSession releases the session back to the pool. + ReleaseSession(session Session) } diff --git a/crypt/aes_test.go b/crypt/aes_test.go index 455977fdf..697c6e2d1 100644 --- a/crypt/aes_test.go +++ b/crypt/aes_test.go @@ -57,3 +57,35 @@ func (s *AesTestSuite) TestDecryptString() { _, err = s.aes.DecryptString("eyJpdiI6IjEyMzQ1IiwidmFsdWUiOiIxMjM0NSJ9") s.Error(err) } + +func Benchmark_EncryptString(b *testing.B) { + mockConfig := &configmock.Config{} + mockConfig.On("GetString", "app.key").Return("11111111111111111111111111111111").Once() + aes := NewAES(mockConfig, json.NewJson()) + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _, err := aes.EncryptString("Goravel") + if err != nil { + b.Error(err) + } + } +} + +func Benchmark_DecryptString(b *testing.B) { + mockConfig := &configmock.Config{} + mockConfig.On("GetString", "app.key").Return("11111111111111111111111111111111").Once() + aes := NewAES(mockConfig, json.NewJson()) + payload, err := aes.EncryptString("Goravel") + if err != nil { + b.Error(err) + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _, err := aes.DecryptString(payload) + if err != nil { + b.Error(err) + } + } +} diff --git a/database/console/migrate.go b/database/console/migrate.go index 85d4836fe..077006783 100644 --- a/database/console/migrate.go +++ b/database/console/migrate.go @@ -52,14 +52,14 @@ func getMigrate(config config.Config) (*migrate.Migrate, error) { } return migrate.NewWithDatabaseInstance(dir, "mysql", instance) - case orm.DriverPostgresql: + case orm.DriverPostgres: dsn := db.NewDsnImpl(config, connection) - postgresqlDsn := dsn.Postgresql(writeConfigs[0]) - if postgresqlDsn == "" { + postgresDsn := dsn.Postgres(writeConfigs[0]) + if postgresDsn == "" { return nil, nil } - db, err := sql.Open("postgres", postgresqlDsn) + db, err := sql.Open("postgres", postgresDsn) if err != nil { return nil, err } @@ -114,6 +114,6 @@ func getMigrate(config config.Config) (*migrate.Migrate, error) { return migrate.NewWithDatabaseInstance(dir, "sqlserver", instance) default: - return nil, errors.New("database driver only support mysql, postgresql, sqlite and sqlserver") + return nil, errors.New("database driver only support mysql, postgres, sqlite and sqlserver") } } diff --git a/database/console/migrate_command_test.go b/database/console/migrate_command_test.go index 636efa0ee..c9a757354 100644 --- a/database/console/migrate_command_test.go +++ b/database/console/migrate_command_test.go @@ -61,14 +61,14 @@ func TestMigrateCommand(t *testing.T) { }, }, { - name: "postgresql", + name: "postgres", setup: func() { var err error docker := gorm.NewPostgresDocker(docker.Postgres()) query, err = docker.New() assert.Nil(t, err) mockConfig = docker.MockConfig - createPostgresqlMigrations() + createPostgresMigrations() }, }, { @@ -120,7 +120,7 @@ INSERT INTO agents (name, created_at, updated_at) VALUES ('goravel', '2023-03-11 `) } -func createPostgresqlMigrations() { +func createPostgresMigrations() { _ = file.Create("database/migrations/20230311160527_create_agents_table.up.sql", `CREATE TABLE agents ( id SERIAL PRIMARY KEY NOT NULL, diff --git a/database/console/migrate_creator.go b/database/console/migrate_creator.go index 91eeafe04..f50673e5d 100644 --- a/database/console/migrate_creator.go +++ b/database/console/migrate_creator.go @@ -50,12 +50,12 @@ func (receiver *MigrateCreator) getStub(table string, create bool) (string, stri driver := receiver.config.GetString("database.connections." + receiver.config.GetString("database.default") + ".driver") switch orm.Driver(driver) { - case orm.DriverPostgresql: + case orm.DriverPostgres: if create { - return migration.PostgresqlStubs{}.CreateUp(), migration.PostgresqlStubs{}.CreateDown() + return migration.PostgresStubs{}.CreateUp(), migration.PostgresStubs{}.CreateDown() } - return migration.PostgresqlStubs{}.UpdateUp(), migration.PostgresqlStubs{}.UpdateDown() + return migration.PostgresStubs{}.UpdateUp(), migration.PostgresStubs{}.UpdateDown() case orm.DriverSqlite: if create { return migration.SqliteStubs{}.CreateUp(), migration.SqliteStubs{}.CreateDown() diff --git a/database/console/migrate_fresh_command_test.go b/database/console/migrate_fresh_command_test.go index e2bd69634..32db7b9cf 100644 --- a/database/console/migrate_fresh_command_test.go +++ b/database/console/migrate_fresh_command_test.go @@ -54,14 +54,14 @@ func TestMigrateFreshCommand(t *testing.T) { }, }, { - name: "postgresql", + name: "postgres", setup: func() { var err error docker := gorm.NewPostgresDocker(docker.Postgres()) query, err = docker.New() assert.Nil(t, err) mockConfig = docker.MockConfig - createPostgresqlMigrations() + createPostgresMigrations() }, }, { diff --git a/database/console/migrate_refresh_command_test.go b/database/console/migrate_refresh_command_test.go index de9b0946b..7b2a59e40 100644 --- a/database/console/migrate_refresh_command_test.go +++ b/database/console/migrate_refresh_command_test.go @@ -54,14 +54,14 @@ func TestMigrateRefreshCommand(t *testing.T) { }, }, { - name: "postgresql", + name: "postgres", setup: func() { var err error docker := gorm.NewPostgresDocker(docker.Postgres()) query, err = docker.New() assert.Nil(t, err) mockConfig = docker.MockConfig - createPostgresqlMigrations() + createPostgresMigrations() }, }, { diff --git a/database/console/migrate_reset_command_test.go b/database/console/migrate_reset_command_test.go index 35b11133d..7510accd7 100644 --- a/database/console/migrate_reset_command_test.go +++ b/database/console/migrate_reset_command_test.go @@ -44,14 +44,14 @@ func TestMigrateResetCommand(t *testing.T) { }, }, { - name: "postgresql", + name: "postgres", setup: func() { var err error docker := gorm.NewPostgresDocker(docker.Postgres()) query, err = docker.New() assert.Nil(t, err) mockConfig = docker.MockConfig - createPostgresqlMigrations() + createPostgresMigrations() }, }, { diff --git a/database/console/migrate_rollback_command_test.go b/database/console/migrate_rollback_command_test.go index 21052214c..842d268fc 100644 --- a/database/console/migrate_rollback_command_test.go +++ b/database/console/migrate_rollback_command_test.go @@ -44,14 +44,14 @@ func TestMigrateRollbackCommand(t *testing.T) { }, }, { - name: "postgresql", + name: "postgres", setup: func() { var err error docker := gorm.NewPostgresDocker(docker.Postgres()) query, err = docker.New() assert.Nil(t, err) mockConfig = docker.MockConfig - createPostgresqlMigrations() + createPostgresMigrations() }, }, { diff --git a/database/console/migrate_status_command_test.go b/database/console/migrate_status_command_test.go index 6d9eed0c8..ff67dcb93 100644 --- a/database/console/migrate_status_command_test.go +++ b/database/console/migrate_status_command_test.go @@ -44,14 +44,14 @@ func TestMigrateStatusCommand(t *testing.T) { }, }, { - name: "postgresql", + name: "postgres", setup: func() { var err error docker := gorm.NewPostgresDocker(docker.Postgres()) query, err = docker.New() assert.Nil(t, err) mockConfig = docker.MockConfig - createPostgresqlMigrations() + createPostgresMigrations() }, }, { diff --git a/database/db/dsn.go b/database/db/dsn.go index c88c73951..47c0e1764 100644 --- a/database/db/dsn.go +++ b/database/db/dsn.go @@ -9,7 +9,7 @@ import ( type Dsn interface { Mysql(config databasecontract.Config) string - Postgresql(config databasecontract.Config) string + Postgres(config databasecontract.Config) string Sqlite(config databasecontract.Config) string Sqlserver(config databasecontract.Config) string } @@ -39,7 +39,7 @@ func (d *DsnImpl) Mysql(config databasecontract.Config) string { config.Username, config.Password, host, config.Port, config.Database, charset, true, loc) } -func (d *DsnImpl) Postgresql(config databasecontract.Config) string { +func (d *DsnImpl) Postgres(config databasecontract.Config) string { host := config.Host if host == "" { return "" diff --git a/database/db/dsn_test.go b/database/db/dsn_test.go index 50066a7b7..83dc5ddb5 100644 --- a/database/db/dsn_test.go +++ b/database/db/dsn_test.go @@ -52,8 +52,8 @@ func (s *DsnTestSuite) TestMysql() { testUsername, testPassword, testHost, testPort, testDatabase, charset, true, loc), dsn.Mysql(testConfig)) } -func (s *DsnTestSuite) TestPostgresql() { - connection := orm.DriverPostgresql.String() +func (s *DsnTestSuite) TestPostgres() { + connection := orm.DriverPostgres.String() dsn := NewDsnImpl(s.mockConfig, connection) sslmode := "disable" timezone := "UTC" @@ -61,7 +61,7 @@ func (s *DsnTestSuite) TestPostgresql() { s.mockConfig.On("GetString", fmt.Sprintf("database.connections.%s.timezone", connection)).Return(timezone).Once() s.Equal(fmt.Sprintf("postgres://%s:%s@%s:%d/%s?sslmode=%s&timezone=%s", - testUsername, testPassword, testHost, testPort, testDatabase, sslmode, timezone), dsn.Postgresql(testConfig)) + testUsername, testPassword, testHost, testPort, testDatabase, sslmode, timezone), dsn.Postgres(testConfig)) } func (s *DsnTestSuite) TestSqlite() { diff --git a/database/gorm/dialector.go b/database/gorm/dialector.go index 9355014f0..d8d34f3e6 100644 --- a/database/gorm/dialector.go +++ b/database/gorm/dialector.go @@ -47,14 +47,14 @@ func (d *DialectorImpl) Make(configs []databasecontract.Config) ([]gorm.Dialecto switch orm.Driver(driver) { case orm.DriverMysql: dialector = d.mysql(item) - case orm.DriverPostgresql: - dialector = d.postgresql(item) + case orm.DriverPostgres: + dialector = d.postgres(item) case orm.DriverSqlite: dialector = d.sqlite(item) case orm.DriverSqlserver: dialector = d.sqlserver(item) default: - err = fmt.Errorf("err database driver: %s, only support mysql, postgresql, sqlite and sqlserver", driver) + err = fmt.Errorf("err database driver: %s, only support mysql, postgres, sqlite and sqlserver", driver) } if err != nil { @@ -78,8 +78,8 @@ func (d *DialectorImpl) mysql(config databasecontract.Config) gorm.Dialector { }) } -func (d *DialectorImpl) postgresql(config databasecontract.Config) gorm.Dialector { - dsn := d.dsn.Postgresql(config) +func (d *DialectorImpl) postgres(config databasecontract.Config) gorm.Dialector { + dsn := d.dsn.Postgres(config) if dsn == "" { return nil } diff --git a/database/gorm/dialector_test.go b/database/gorm/dialector_test.go index 1435a61bb..87dc71a87 100644 --- a/database/gorm/dialector_test.go +++ b/database/gorm/dialector_test.go @@ -53,13 +53,13 @@ func (s *DialectorTestSuite) TestMysql() { s.Nil(err) } -func (s *DialectorTestSuite) TestPostgresql() { - dialector := NewDialectorImpl(s.mockConfig, orm.DriverPostgresql.String()) - s.mockConfig.On("GetString", "database.connections.postgresql.driver"). - Return(orm.DriverPostgresql.String()).Once() - s.mockConfig.On("GetString", "database.connections.postgresql.sslmode"). +func (s *DialectorTestSuite) TestPostgres() { + dialector := NewDialectorImpl(s.mockConfig, orm.DriverPostgres.String()) + s.mockConfig.On("GetString", "database.connections.postgres.driver"). + Return(orm.DriverPostgres.String()).Once() + s.mockConfig.On("GetString", "database.connections.postgres.sslmode"). Return("disable").Once() - s.mockConfig.On("GetString", "database.connections.postgresql.timezone"). + s.mockConfig.On("GetString", "database.connections.postgres.timezone"). Return("UTC").Once() dialectors, err := dialector.Make([]databasecontract.Config{s.config}) s.Equal(postgres.New(postgres.Config{ diff --git a/database/gorm/query.go b/database/gorm/query.go index 5b16e0712..fefe56b7b 100644 --- a/database/gorm/query.go +++ b/database/gorm/query.go @@ -936,10 +936,10 @@ func (r *QueryImpl) buildLockForUpdate(db *gormio.DB) *gormio.DB { driver := r.instance.Name() mysqlDialector := mysql.Dialector{} - postgresqlDialector := postgres.Dialector{} + postgresDialector := postgres.Dialector{} sqlserverDialector := sqlserver.Dialector{} - if driver == mysqlDialector.Name() || driver == postgresqlDialector.Name() { + if driver == mysqlDialector.Name() || driver == postgresDialector.Name() { return db.Clauses(clause.Locking{Strength: "UPDATE"}) } else if driver == sqlserverDialector.Name() { return db.Clauses(hints.With("rowlock", "updlock", "holdlock")) @@ -1041,10 +1041,10 @@ func (r *QueryImpl) buildSharedLock(db *gormio.DB) *gormio.DB { driver := r.instance.Name() mysqlDialector := mysql.Dialector{} - postgresqlDialector := postgres.Dialector{} + postgresDialector := postgres.Dialector{} sqlserverDialector := sqlserver.Dialector{} - if driver == mysqlDialector.Name() || driver == postgresqlDialector.Name() { + if driver == mysqlDialector.Name() || driver == postgresDialector.Name() { return db.Clauses(clause.Locking{Strength: "SHARE"}) } else if driver == sqlserverDialector.Name() { return db.Clauses(hints.With("rowlock", "holdlock")) diff --git a/database/gorm/query_test.go b/database/gorm/query_test.go index 9d6fffe50..b3bbd8072 100644 --- a/database/gorm/query_test.go +++ b/database/gorm/query_test.go @@ -24,13 +24,13 @@ import ( type QueryTestSuite struct { suite.Suite - queries map[contractsorm.Driver]contractsorm.Query - mysqlDocker *MysqlDocker - mysql1 contractstesting.DatabaseDriver - postgres contractstesting.DatabaseDriver - postgresqlDocker *PostgresqlDocker - sqliteDocker *SqliteDocker - sqlserverDocker *SqlserverDocker + queries map[contractsorm.Driver]contractsorm.Query + mysqlDocker *MysqlDocker + mysql1 contractstesting.DatabaseDriver + postgres contractstesting.DatabaseDriver + postgresDocker *PostgresDocker + sqliteDocker *SqliteDocker + sqlserverDocker *SqlserverDocker } func TestQueryTestSuite(t *testing.T) { @@ -56,10 +56,10 @@ func TestQueryTestSuite(t *testing.T) { } postgres := supportdocker.Postgres() - postgresqlDocker := NewPostgresDocker(postgres) - postgresqlQuery, err := postgresqlDocker.New() + postgresDocker := NewPostgresDocker(postgres) + postgresQuery, err := postgresDocker.New() if err != nil { - log.Fatalf("Init postgresql error: %s", err) + log.Fatalf("Init postgres error: %s", err) } sqliteDocker := NewSqliteDocker(supportdocker.Sqlite()) @@ -76,17 +76,17 @@ func TestQueryTestSuite(t *testing.T) { suite.Run(t, &QueryTestSuite{ queries: map[contractsorm.Driver]contractsorm.Query{ - contractsorm.DriverMysql: mysqlQuery, - contractsorm.DriverPostgresql: postgresqlQuery, - contractsorm.DriverSqlite: sqliteQuery, - contractsorm.DriverSqlserver: sqlserverQuery, + contractsorm.DriverMysql: mysqlQuery, + contractsorm.DriverPostgres: postgresQuery, + contractsorm.DriverSqlite: sqliteQuery, + contractsorm.DriverSqlserver: sqlserverQuery, }, - mysqlDocker: mysqlDocker, - mysql1: mysqls[1], - postgres: postgres, - postgresqlDocker: postgresqlDocker, - sqliteDocker: sqliteDocker, - sqlserverDocker: sqlserverDocker, + mysqlDocker: mysqlDocker, + mysql1: mysqls[1], + postgres: postgres, + postgresDocker: postgresDocker, + sqliteDocker: sqliteDocker, + sqlserverDocker: sqlserverDocker, }) } @@ -2277,9 +2277,9 @@ func (s *QueryTestSuite) TestRefreshConnection() { return product }(), setup: func() { - mockPostgresqlConnection(s.mysqlDocker.MockConfig, s.postgres.Config()) + mockPostgresConnection(s.mysqlDocker.MockConfig, s.postgres.Config()) }, - expectConnection: "postgresql", + expectConnection: "postgres", }, } @@ -2497,7 +2497,7 @@ func (s *QueryTestSuite) TestToSql() { for driver, query := range s.queries { s.Run(driver.String(), func() { switch driver { - case contractsorm.DriverPostgresql: + case contractsorm.DriverPostgres: s.Equal("SELECT * FROM \"users\" WHERE \"id\" = $1 AND \"users\".\"deleted_at\" IS NULL", query.Where("id", 1).ToSql().Find(User{})) case contractsorm.DriverSqlserver: s.Equal("SELECT * FROM \"users\" WHERE \"id\" = @p1 AND \"users\".\"deleted_at\" IS NULL", query.Where("id", 1).ToSql().Find(User{})) @@ -2512,7 +2512,7 @@ func (s *QueryTestSuite) TestToRawSql() { for driver, query := range s.queries { s.Run(driver.String(), func() { switch driver { - case contractsorm.DriverPostgresql: + case contractsorm.DriverPostgres: s.Equal("SELECT * FROM \"users\" WHERE \"id\" = 1 AND \"users\".\"deleted_at\" IS NULL", query.Where("id", 1).ToRawSql().Find(User{})) case contractsorm.DriverSqlserver: s.Equal("SELECT * FROM \"users\" WHERE \"id\" = $1$ AND \"users\".\"deleted_at\" IS NULL", query.Where("id", 1).ToRawSql().Find(User{})) @@ -3069,8 +3069,8 @@ func (s *QueryTestSuite) mockDummyConnection(driver contractsorm.Driver) { switch driver { case contractsorm.DriverMysql: mockDummyConnection(s.mysqlDocker.MockConfig, s.mysql1.Config()) - case contractsorm.DriverPostgresql: - mockDummyConnection(s.postgresqlDocker.MockConfig, s.mysql1.Config()) + case contractsorm.DriverPostgres: + mockDummyConnection(s.postgresDocker.MockConfig, s.mysql1.Config()) case contractsorm.DriverSqlite: mockDummyConnection(s.sqliteDocker.MockConfig, s.mysql1.Config()) case contractsorm.DriverSqlserver: @@ -3091,8 +3091,8 @@ func TestCustomConnection(t *testing.T) { } postgres := supportdocker.Postgres() - postgresqlDocker := NewPostgresDocker(postgres) - _, err = postgresqlDocker.New() + postgresDocker := NewPostgresDocker(postgres) + _, err = postgresDocker.New() if err != nil { log.Fatalf("Init mysql error: %s", err) } @@ -3105,7 +3105,7 @@ func TestCustomConnection(t *testing.T) { assert.Nil(t, query.Where("body", "create_review").First(&review1)) assert.True(t, review1.ID > 0) - mockPostgresqlConnection(mysqlDocker.MockConfig, postgres.Config()) + mockPostgresConnection(mysqlDocker.MockConfig, postgres.Config()) product := Product{Name: "create_product"} assert.Nil(t, query.Create(&product)) @@ -3198,7 +3198,7 @@ func TestGetModelConnection(t *testing.T) { var product Product return product }(), - expectConnection: "postgresql", + expectConnection: "postgres", }, { name: "the connection of model is not empty and model is slice", @@ -3206,7 +3206,7 @@ func TestGetModelConnection(t *testing.T) { var products []Product return products }(), - expectConnection: "postgresql", + expectConnection: "postgres", }, } @@ -3273,22 +3273,22 @@ func TestReadWriteSeparate(t *testing.T) { } postgreses := supportdocker.Postgreses(2) - readPostgresqlDocker := NewPostgresDocker(postgreses[0]) - readPostgresqlQuery, err := readPostgresqlDocker.New() + readPostgresDocker := NewPostgresDocker(postgreses[0]) + readPostgresQuery, err := readPostgresDocker.New() if err != nil { - log.Fatalf("Get read postgresql error: %s", err) + log.Fatalf("Get read postgres error: %s", err) } - writePostgresqlDocker := NewPostgresDocker(postgreses[1]) - writePostgresqlQuery, err := writePostgresqlDocker.New() + writePostgresDocker := NewPostgresDocker(postgreses[1]) + writePostgresQuery, err := writePostgresDocker.New() if err != nil { - log.Fatalf("Get write postgresql error: %s", err) + log.Fatalf("Get write postgres error: %s", err) } - writePostgresqlDocker.MockReadWrite(readPostgresqlDocker.Port, writePostgresqlDocker.Port) - postgresqlQuery, err := writePostgresqlDocker.Query(false) + writePostgresDocker.MockReadWrite(readPostgresDocker.Port, writePostgresDocker.Port) + postgresQuery, err := writePostgresDocker.Query(false) if err != nil { - log.Fatalf("Get postgresql gorm error: %s", err) + log.Fatalf("Get postgres gorm error: %s", err) } sqlites := supportdocker.Sqlites(2) @@ -3334,10 +3334,10 @@ func TestReadWriteSeparate(t *testing.T) { "read": readMysqlQuery, "write": writeMysqlQuery, }, - contractsorm.DriverPostgresql: { - "mix": postgresqlQuery, - "read": readPostgresqlQuery, - "write": writePostgresqlQuery, + contractsorm.DriverPostgres: { + "mix": postgresQuery, + "read": readPostgresQuery, + "write": writePostgresQuery, }, contractsorm.DriverSqlite: { "mix": sqliteDB, @@ -3383,10 +3383,10 @@ func TestTablePrefixAndSingular(t *testing.T) { log.Fatalf("Init mysql error: %s", err) } - postgresqlDocker := NewPostgresDocker(supportdocker.Postgres()) - postgresqlQuery, err := postgresqlDocker.NewWithPrefixAndSingular() + postgresDocker := NewPostgresDocker(supportdocker.Postgres()) + postgresQuery, err := postgresDocker.NewWithPrefixAndSingular() if err != nil { - log.Fatalf("Init postgresql error: %s", err) + log.Fatalf("Init postgres error: %s", err) } sqliteDocker := NewSqliteDocker(supportdocker.Sqlite()) @@ -3402,10 +3402,10 @@ func TestTablePrefixAndSingular(t *testing.T) { } dbs := map[contractsorm.Driver]contractsorm.Query{ - contractsorm.DriverMysql: mysqlQuery, - contractsorm.DriverPostgresql: postgresqlQuery, - contractsorm.DriverSqlite: sqliteDB, - contractsorm.DriverSqlserver: sqlserverDB, + contractsorm.DriverMysql: mysqlQuery, + contractsorm.DriverPostgres: postgresQuery, + contractsorm.DriverSqlite: sqliteDB, + contractsorm.DriverSqlserver: sqlserverDB, } for drive, db := range dbs { @@ -3446,19 +3446,19 @@ func mockDummyConnection(mockConfig *mocksconfig.Config, databaseConfig contract mockConfig.On("GetString", "database.connections.dummy.database").Return(databaseConfig.Database) } -func mockPostgresqlConnection(mockConfig *mocksconfig.Config, databaseConfig contractstesting.DatabaseConfig) { - mockConfig.On("GetString", "database.connections.postgresql.prefix").Return("") - mockConfig.On("GetBool", "database.connections.postgresql.singular").Return(false) - mockConfig.On("Get", "database.connections.postgresql.read").Return(nil) - mockConfig.On("Get", "database.connections.postgresql.write").Return(nil) - mockConfig.On("GetString", "database.connections.postgresql.host").Return("127.0.0.1") - mockConfig.On("GetString", "database.connections.postgresql.username").Return(databaseConfig.Username) - mockConfig.On("GetString", "database.connections.postgresql.password").Return(databaseConfig.Password) - mockConfig.On("GetInt", "database.connections.postgresql.port").Return(databaseConfig.Port) - mockConfig.On("GetString", "database.connections.postgresql.driver").Return(contractsorm.DriverPostgresql.String()) - mockConfig.On("GetString", "database.connections.postgresql.sslmode").Return("disable") - mockConfig.On("GetString", "database.connections.postgresql.timezone").Return("UTC") - mockConfig.On("GetString", "database.connections.postgresql.database").Return(databaseConfig.Database) +func mockPostgresConnection(mockConfig *mocksconfig.Config, databaseConfig contractstesting.DatabaseConfig) { + mockConfig.On("GetString", "database.connections.postgres.prefix").Return("") + mockConfig.On("GetBool", "database.connections.postgres.singular").Return(false) + mockConfig.On("Get", "database.connections.postgres.read").Return(nil) + mockConfig.On("Get", "database.connections.postgres.write").Return(nil) + mockConfig.On("GetString", "database.connections.postgres.host").Return("127.0.0.1") + mockConfig.On("GetString", "database.connections.postgres.username").Return(databaseConfig.Username) + mockConfig.On("GetString", "database.connections.postgres.password").Return(databaseConfig.Password) + mockConfig.On("GetInt", "database.connections.postgres.port").Return(databaseConfig.Port) + mockConfig.On("GetString", "database.connections.postgres.driver").Return(contractsorm.DriverPostgres.String()) + mockConfig.On("GetString", "database.connections.postgres.sslmode").Return("disable") + mockConfig.On("GetString", "database.connections.postgres.timezone").Return("UTC") + mockConfig.On("GetString", "database.connections.postgres.database").Return(databaseConfig.Database) } type UserObserver struct{} diff --git a/database/gorm/test_models.go b/database/gorm/test_models.go index ff40e9d8a..e6042218c 100644 --- a/database/gorm/test_models.go +++ b/database/gorm/test_models.go @@ -301,7 +301,7 @@ type Product struct { } func (p *Product) Connection() string { - return "postgresql" + return "postgres" } type Review struct { diff --git a/database/gorm/test_utils.go b/database/gorm/test_utils.go index 3dde80152..14bc6d5ad 100644 --- a/database/gorm/test_utils.go +++ b/database/gorm/test_utils.go @@ -127,7 +127,7 @@ func (r *MysqlDocker) mockOfCommon() { mockPool(r.MockConfig) } -type PostgresqlDocker struct { +type PostgresDocker struct { MockConfig *mocksconfig.Config Port int user string @@ -135,13 +135,13 @@ type PostgresqlDocker struct { password string } -func NewPostgresDocker(driver testing.DatabaseDriver) *PostgresqlDocker { +func NewPostgresDocker(driver testing.DatabaseDriver) *PostgresDocker { config := driver.Config() - return &PostgresqlDocker{MockConfig: &mocksconfig.Config{}, Port: config.Port, user: config.Username, password: config.Password, database: config.Database} + return &PostgresDocker{MockConfig: &mocksconfig.Config{}, Port: config.Port, user: config.Username, password: config.Password, database: config.Database} } -func (r *PostgresqlDocker) New() (orm.Query, error) { +func (r *PostgresDocker) New() (orm.Query, error) { r.mock() db, err := r.Query(true) @@ -152,7 +152,7 @@ func (r *PostgresqlDocker) New() (orm.Query, error) { return db, nil } -func (r *PostgresqlDocker) NewWithPrefixAndSingular() (orm.Query, error) { +func (r *PostgresDocker) NewWithPrefixAndSingular() (orm.Query, error) { r.mockWithPrefixAndSingular() db, err := r.QueryWithPrefixAndSingular() @@ -163,14 +163,14 @@ func (r *PostgresqlDocker) NewWithPrefixAndSingular() (orm.Query, error) { return db, nil } -func (r *PostgresqlDocker) Query(createTable bool) (orm.Query, error) { - query, err := InitializeQuery(testContext, r.MockConfig, orm.DriverPostgresql.String()) +func (r *PostgresDocker) Query(createTable bool) (orm.Query, error) { + query, err := InitializeQuery(testContext, r.MockConfig, orm.DriverPostgres.String()) if err != nil { - return nil, errors.New("connect to postgresql failed") + return nil, errors.New("connect to postgres failed") } if createTable { - err := Tables{}.Create(orm.DriverPostgresql, query) + err := Tables{}.Create(orm.DriverPostgres, query) if err != nil { return nil, err } @@ -179,13 +179,13 @@ func (r *PostgresqlDocker) Query(createTable bool) (orm.Query, error) { return query, nil } -func (r *PostgresqlDocker) QueryWithPrefixAndSingular() (orm.Query, error) { - query, err := InitializeQuery(testContext, r.MockConfig, orm.DriverPostgresql.String()) +func (r *PostgresDocker) QueryWithPrefixAndSingular() (orm.Query, error) { + query, err := InitializeQuery(testContext, r.MockConfig, orm.DriverPostgres.String()) if err != nil { - return nil, errors.New("connect to postgresql failed") + return nil, errors.New("connect to postgres failed") } - err = Tables{}.CreateWithPrefixAndSingular(orm.DriverPostgresql, query) + err = Tables{}.CreateWithPrefixAndSingular(orm.DriverPostgres, query) if err != nil { return nil, err } @@ -193,50 +193,50 @@ func (r *PostgresqlDocker) QueryWithPrefixAndSingular() (orm.Query, error) { return query, nil } -func (r *PostgresqlDocker) MockReadWrite(readPort, writePort int) { +func (r *PostgresDocker) MockReadWrite(readPort, writePort int) { r.MockConfig = &mocksconfig.Config{} - r.MockConfig.On("Get", "database.connections.postgresql.read").Return([]database.Config{ + r.MockConfig.On("Get", "database.connections.postgres.read").Return([]database.Config{ {Host: "127.0.0.1", Port: readPort, Username: r.user, Password: r.password}, }) - r.MockConfig.On("Get", "database.connections.postgresql.write").Return([]database.Config{ + r.MockConfig.On("Get", "database.connections.postgres.write").Return([]database.Config{ {Host: "127.0.0.1", Port: writePort, Username: r.user, Password: r.password}, }) - r.MockConfig.On("GetString", "database.connections.postgresql.prefix").Return("") - r.MockConfig.On("GetBool", "database.connections.postgresql.singular").Return(false) + r.MockConfig.On("GetString", "database.connections.postgres.prefix").Return("") + r.MockConfig.On("GetBool", "database.connections.postgres.singular").Return(false) r.mockOfCommon() } -func (r *PostgresqlDocker) mock() { - r.MockConfig.On("GetString", "database.default").Return("postgresql") +func (r *PostgresDocker) mock() { + r.MockConfig.On("GetString", "database.default").Return("postgres") r.MockConfig.On("GetString", "database.migrations").Return("migrations") - r.MockConfig.On("GetString", "database.connections.postgresql.prefix").Return("") - r.MockConfig.On("GetBool", "database.connections.postgresql.singular").Return(false) + r.MockConfig.On("GetString", "database.connections.postgres.prefix").Return("") + r.MockConfig.On("GetBool", "database.connections.postgres.singular").Return(false) r.mockSingleOfCommon() r.mockOfCommon() } -func (r *PostgresqlDocker) mockWithPrefixAndSingular() { - r.MockConfig.On("GetString", "database.connections.postgresql.prefix").Return("goravel_") - r.MockConfig.On("GetBool", "database.connections.postgresql.singular").Return(true) +func (r *PostgresDocker) mockWithPrefixAndSingular() { + r.MockConfig.On("GetString", "database.connections.postgres.prefix").Return("goravel_") + r.MockConfig.On("GetBool", "database.connections.postgres.singular").Return(true) r.mockSingleOfCommon() r.mockOfCommon() } -func (r *PostgresqlDocker) mockSingleOfCommon() { - r.MockConfig.On("Get", "database.connections.postgresql.read").Return(nil) - r.MockConfig.On("Get", "database.connections.postgresql.write").Return(nil) - r.MockConfig.On("GetString", "database.connections.postgresql.host").Return("127.0.0.1") - r.MockConfig.On("GetString", "database.connections.postgresql.username").Return(r.user) - r.MockConfig.On("GetString", "database.connections.postgresql.password").Return(r.password) - r.MockConfig.On("GetInt", "database.connections.postgresql.port").Return(r.Port) +func (r *PostgresDocker) mockSingleOfCommon() { + r.MockConfig.On("Get", "database.connections.postgres.read").Return(nil) + r.MockConfig.On("Get", "database.connections.postgres.write").Return(nil) + r.MockConfig.On("GetString", "database.connections.postgres.host").Return("127.0.0.1") + r.MockConfig.On("GetString", "database.connections.postgres.username").Return(r.user) + r.MockConfig.On("GetString", "database.connections.postgres.password").Return(r.password) + r.MockConfig.On("GetInt", "database.connections.postgres.port").Return(r.Port) } -func (r *PostgresqlDocker) mockOfCommon() { +func (r *PostgresDocker) mockOfCommon() { r.MockConfig.On("GetBool", "app.debug").Return(true) - r.MockConfig.On("GetString", "database.connections.postgresql.driver").Return(orm.DriverPostgresql.String()) - r.MockConfig.On("GetString", "database.connections.postgresql.sslmode").Return("disable") - r.MockConfig.On("GetString", "database.connections.postgresql.timezone").Return("UTC") - r.MockConfig.On("GetString", "database.connections.postgresql.database").Return(r.database) + r.MockConfig.On("GetString", "database.connections.postgres.driver").Return(orm.DriverPostgres.String()) + r.MockConfig.On("GetString", "database.connections.postgres.sslmode").Return("disable") + r.MockConfig.On("GetString", "database.connections.postgres.timezone").Return("UTC") + r.MockConfig.On("GetString", "database.connections.postgres.database").Return(r.database) mockPool(r.MockConfig) } @@ -531,7 +531,7 @@ CREATE TABLE peoples ( KEY idx_users_updated_at (updated_at) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; ` - case orm.DriverPostgresql: + case orm.DriverPostgres: return ` CREATE TABLE peoples ( id SERIAL PRIMARY KEY NOT NULL, @@ -582,7 +582,7 @@ CREATE TABLE reviews ( KEY idx_users_updated_at (updated_at) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; ` - case orm.DriverPostgresql: + case orm.DriverPostgres: return ` CREATE TABLE reviews ( id SERIAL PRIMARY KEY NOT NULL, @@ -633,7 +633,7 @@ CREATE TABLE products ( KEY idx_users_updated_at (updated_at) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; ` - case orm.DriverPostgresql: + case orm.DriverPostgres: return ` CREATE TABLE products ( id SERIAL PRIMARY KEY NOT NULL, @@ -686,7 +686,7 @@ CREATE TABLE users ( KEY idx_users_updated_at (updated_at) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; ` - case orm.DriverPostgresql: + case orm.DriverPostgres: return ` CREATE TABLE users ( id SERIAL PRIMARY KEY NOT NULL, @@ -745,7 +745,7 @@ CREATE TABLE goravel_user ( KEY idx_users_updated_at (updated_at) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; ` - case orm.DriverPostgresql: + case orm.DriverPostgres: return ` CREATE TABLE goravel_user ( id SERIAL PRIMARY KEY NOT NULL, @@ -803,7 +803,7 @@ CREATE TABLE addresses ( KEY idx_addresses_updated_at (updated_at) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; ` - case orm.DriverPostgresql: + case orm.DriverPostgres: return ` CREATE TABLE addresses ( id SERIAL PRIMARY KEY NOT NULL, @@ -857,7 +857,7 @@ CREATE TABLE books ( KEY idx_books_updated_at (updated_at) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; ` - case orm.DriverPostgresql: + case orm.DriverPostgres: return ` CREATE TABLE books ( id SERIAL PRIMARY KEY NOT NULL, @@ -908,7 +908,7 @@ CREATE TABLE authors ( KEY idx_books_updated_at (updated_at) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; ` - case orm.DriverPostgresql: + case orm.DriverPostgres: return ` CREATE TABLE authors ( id SERIAL PRIMARY KEY NOT NULL, @@ -958,7 +958,7 @@ CREATE TABLE roles ( KEY idx_roles_updated_at (updated_at) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; ` - case orm.DriverPostgresql: + case orm.DriverPostgres: return ` CREATE TABLE roles ( id SERIAL PRIMARY KEY NOT NULL, @@ -1007,7 +1007,7 @@ CREATE TABLE houses ( KEY idx_houses_updated_at (updated_at) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; ` - case orm.DriverPostgresql: + case orm.DriverPostgres: return ` CREATE TABLE houses ( id SERIAL PRIMARY KEY NOT NULL, @@ -1062,7 +1062,7 @@ CREATE TABLE phones ( KEY idx_phones_updated_at (updated_at) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; ` - case orm.DriverPostgresql: + case orm.DriverPostgres: return ` CREATE TABLE phones ( id SERIAL PRIMARY KEY NOT NULL, @@ -1112,7 +1112,7 @@ CREATE TABLE role_user ( PRIMARY KEY (id) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; ` - case orm.DriverPostgresql: + case orm.DriverPostgres: return ` CREATE TABLE role_user ( id SERIAL PRIMARY KEY NOT NULL, diff --git a/database/gorm/test_utils_test.go b/database/gorm/test_utils_test.go index 5f390b0ea..7e4158391 100644 --- a/database/gorm/test_utils_test.go +++ b/database/gorm/test_utils_test.go @@ -22,7 +22,7 @@ func TestMysqlDocker(t *testing.T) { assert.Nil(t, err) } -func TestPostgresqlDocker(t *testing.T) { +func TestPostgresDocker(t *testing.T) { if env.IsWindows() { t.Skip("Skipping tests of using docker") } diff --git a/database/migration/sql_driver.go b/database/migration/sql_driver.go index d5568bf2b..146e64f58 100644 --- a/database/migration/sql_driver.go +++ b/database/migration/sql_driver.go @@ -54,12 +54,12 @@ func (r *SqlDriver) getStub(table string, create bool) (string, string) { driver := r.config.GetString("database.connections." + r.config.GetString("database.default") + ".driver") switch orm.Driver(driver) { - case orm.DriverPostgresql: + case orm.DriverPostgres: if create { - return PostgresqlStubs{}.CreateUp(), PostgresqlStubs{}.CreateDown() + return PostgresStubs{}.CreateUp(), PostgresStubs{}.CreateDown() } - return PostgresqlStubs{}.UpdateUp(), PostgresqlStubs{}.UpdateDown() + return PostgresStubs{}.UpdateUp(), PostgresStubs{}.UpdateDown() case orm.DriverSqlite: if create { return SqliteStubs{}.CreateUp(), SqliteStubs{}.CreateDown() diff --git a/database/migration/sql_driver_test.go b/database/migration/sql_driver_test.go index c1812047c..ceb60eb53 100644 --- a/database/migration/sql_driver_test.go +++ b/database/migration/sql_driver_test.go @@ -80,8 +80,8 @@ func TestSqlDriverCreate(t *testing.T) { upContent: ``, downContent: ``, setup: func() { - mockConfig.EXPECT().GetString("database.default").Return("postgresql").Twice() - mockConfig.EXPECT().GetString("database.connections.postgresql.charset").Return("utf8mb4").Twice() + mockConfig.EXPECT().GetString("database.default").Return("postgres").Twice() + mockConfig.EXPECT().GetString("database.connections.postgres.charset").Return("utf8mb4").Twice() }, }, { @@ -95,9 +95,9 @@ func TestSqlDriverCreate(t *testing.T) { `, downContent: `DROP TABLE IF EXISTS users;`, setup: func() { - mockConfig.EXPECT().GetString("database.default").Return("postgresql").Times(3) - mockConfig.EXPECT().GetString("database.connections.postgresql.driver").Return("postgresql").Once() - mockConfig.EXPECT().GetString("database.connections.postgresql.charset").Return("utf8mb4").Twice() + mockConfig.EXPECT().GetString("database.default").Return("postgres").Times(3) + mockConfig.EXPECT().GetString("database.connections.postgres.driver").Return("postgres").Once() + mockConfig.EXPECT().GetString("database.connections.postgres.charset").Return("utf8mb4").Twice() }, }, { @@ -106,9 +106,9 @@ func TestSqlDriverCreate(t *testing.T) { upContent: `ALTER TABLE users ADD column varchar(255) NOT NULL;`, downContent: `ALTER TABLE users DROP COLUMN column;`, setup: func() { - mockConfig.EXPECT().GetString("database.default").Return("postgresql").Times(3) - mockConfig.EXPECT().GetString("database.connections.postgresql.driver").Return("postgresql").Once() - mockConfig.EXPECT().GetString("database.connections.postgresql.charset").Return("utf8mb4").Twice() + mockConfig.EXPECT().GetString("database.default").Return("postgres").Times(3) + mockConfig.EXPECT().GetString("database.connections.postgres.driver").Return("postgres").Once() + mockConfig.EXPECT().GetString("database.connections.postgres.charset").Return("utf8mb4").Twice() }, }, { diff --git a/database/migration/stubs.go b/database/migration/stubs.go index 19ec7b38d..91007d851 100644 --- a/database/migration/stubs.go +++ b/database/migration/stubs.go @@ -123,11 +123,11 @@ func (receiver MysqlStubs) UpdateDown() string { ` } -type PostgresqlStubs struct { +type PostgresStubs struct { } // CreateUp Create up migration content. -func (receiver PostgresqlStubs) CreateUp() string { +func (receiver PostgresStubs) CreateUp() string { return `CREATE TABLE DummyTable ( id SERIAL PRIMARY KEY NOT NULL, created_at timestamp NOT NULL, @@ -137,19 +137,19 @@ func (receiver PostgresqlStubs) CreateUp() string { } // CreateDown Create down migration content. -func (receiver PostgresqlStubs) CreateDown() string { +func (receiver PostgresStubs) CreateDown() string { return `DROP TABLE IF EXISTS DummyTable; ` } // UpdateUp Update up migration content. -func (receiver PostgresqlStubs) UpdateUp() string { +func (receiver PostgresStubs) UpdateUp() string { return `ALTER TABLE DummyTable ADD column varchar(255) NOT NULL; ` } // UpdateDown Update down migration content. -func (receiver PostgresqlStubs) UpdateDown() string { +func (receiver PostgresStubs) UpdateDown() string { return `ALTER TABLE DummyTable DROP COLUMN column; ` } diff --git a/database/orm_test.go b/database/orm_test.go index 403be6f0f..47cd8b834 100644 --- a/database/orm_test.go +++ b/database/orm_test.go @@ -19,7 +19,7 @@ import ( var connections = []contractsorm.Driver{ contractsorm.DriverMysql, - contractsorm.DriverPostgresql, + contractsorm.DriverPostgres, contractsorm.DriverSqlite, contractsorm.DriverSqlserver, } @@ -37,11 +37,11 @@ type User struct { type OrmSuite struct { suite.Suite - orm *OrmImpl - mysqlQuery contractsorm.Query - postgresqlQuery contractsorm.Query - sqliteQuery contractsorm.Query - sqlserverDB contractsorm.Query + orm *OrmImpl + mysqlQuery contractsorm.Query + postgresQuery contractsorm.Query + sqliteQuery contractsorm.Query + sqlserverDB contractsorm.Query } func TestOrmSuite(t *testing.T) { @@ -55,10 +55,10 @@ func TestOrmSuite(t *testing.T) { log.Fatalf("Init mysql docker error: %v", err) } - postgresqlDocker := gorm.NewPostgresDocker(docker.Postgres()) - postgresqlQuery, err := postgresqlDocker.New() + postgresDocker := gorm.NewPostgresDocker(docker.Postgres()) + postgresQuery, err := postgresDocker.New() if err != nil { - log.Fatalf("Init postgresql docker error: %v", err) + log.Fatalf("Init postgres docker error: %v", err) } sqliteDocker := gorm.NewSqliteDocker(docker.Sqlite()) @@ -74,10 +74,10 @@ func TestOrmSuite(t *testing.T) { } suite.Run(t, &OrmSuite{ - mysqlQuery: mysqlQuery, - postgresqlQuery: postgresqlQuery, - sqliteQuery: sqliteQuery, - sqlserverDB: sqlserverQuery, + mysqlQuery: mysqlQuery, + postgresQuery: postgresQuery, + sqliteQuery: sqliteQuery, + sqlserverDB: sqlserverQuery, }) assert.Nil(t, file.Remove("goravel")) @@ -89,10 +89,10 @@ func (s *OrmSuite) SetupTest() { ctx: context.Background(), query: s.mysqlQuery, queries: map[string]contractsorm.Query{ - contractsorm.DriverMysql.String(): s.mysqlQuery, - contractsorm.DriverPostgresql.String(): s.postgresqlQuery, - contractsorm.DriverSqlite.String(): s.sqliteQuery, - contractsorm.DriverSqlserver.String(): s.sqlserverDB, + contractsorm.DriverMysql.String(): s.mysqlQuery, + contractsorm.DriverPostgres.String(): s.postgresQuery, + contractsorm.DriverSqlite.String(): s.sqliteQuery, + contractsorm.DriverSqlserver.String(): s.sqlserverDB, }, } } diff --git a/foundation/application_test.go b/foundation/application_test.go index 5091817b2..a84972fce 100644 --- a/foundation/application_test.go +++ b/foundation/application_test.go @@ -401,6 +401,7 @@ func (s *ApplicationTestSuite) TestMakeSchedule() { func (s *ApplicationTestSuite) TestMakeSession() { mockConfig := &configmocks.Config{} mockConfig.On("GetInt", "session.lifetime").Return(120).Once() + mockConfig.On("GetInt", "session.gc_interval", 30).Return(30).Once() mockConfig.On("GetString", "session.files").Return("storage/framework/sessions").Once() s.app.Singleton(frameworkconfig.Binding, func(app foundation.Application) (any, error) { diff --git a/go.mod b/go.mod index 33bc2c41f..bae48c119 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/goravel/framework -go 1.21 +go 1.22 require ( github.com/RichardKnop/machinery/v2 v2.0.13 diff --git a/hash/application_test.go b/hash/application_test.go index 38882cca4..5a6909b61 100644 --- a/hash/application_test.go +++ b/hash/application_test.go @@ -11,25 +11,24 @@ import ( type ApplicationTestSuite struct { suite.Suite + config *configmock.Config hashers map[string]hash.Hash } func TestApplicationTestSuite(t *testing.T) { - mockConfig := &configmock.Config{} - argon2idHasher := getArgon2idHasher(mockConfig) - bcryptHasher := getBcryptHasher(mockConfig) - - suite.Run(t, &ApplicationTestSuite{ - hashers: map[string]hash.Hash{ - "argon2id": argon2idHasher, - "bcrypt": bcryptHasher, - }, - }) - mockConfig.AssertExpectations(t) + suite.Run(t, &ApplicationTestSuite{}) } func (s *ApplicationTestSuite) SetupTest() { + s.config = &configmock.Config{} + s.hashers = map[string]hash.Hash{ + "argon2id": getArgon2idHasher(s.config), + "bcrypt": getBcryptHasher(s.config), + } +} +func (s *ApplicationTestSuite) TearDownSuite() { + s.config.AssertExpectations(s.T()) } func (s *ApplicationTestSuite) TestMakeHash() { @@ -78,6 +77,67 @@ func (s *ApplicationTestSuite) TestNeedsRehash() { } } +func BenchmarkMakeHash(b *testing.B) { + s := new(ApplicationTestSuite) + s.SetT(&testing.T{}) + s.SetupTest() + b.StartTimer() + b.ResetTimer() + for name, hasher := range s.hashers { + b.Run(name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + _, err := hasher.Make("password") + if err != nil { + b.Fatal(err) + } + } + }) + } + b.StopTimer() +} + +func BenchmarkCheckHash(b *testing.B) { + s := new(ApplicationTestSuite) + s.SetT(&testing.T{}) + s.SetupTest() + b.StartTimer() + b.ResetTimer() + for name, hasher := range s.hashers { + b.Run(name, func(b *testing.B) { + value, err := hasher.Make("password") + if err != nil { + b.Fatal(err) + } + for i := 0; i < b.N; i++ { + if !hasher.Check("password", value) { + b.Fatal("hash check failed") + } + } + }) + } + b.StopTimer() +} + +func BenchmarkNeedsRehash(b *testing.B) { + s := new(ApplicationTestSuite) + s.SetT(&testing.T{}) + s.SetupTest() + b.StartTimer() + b.ResetTimer() + for name, hasher := range s.hashers { + b.Run(name, func(b *testing.B) { + value, err := hasher.Make("password") + if err != nil { + b.Fatal(err) + } + for i := 0; i < b.N; i++ { + hasher.NeedsRehash(value) + } + }) + } + b.StopTimer() +} + func getArgon2idHasher(mockConfig *configmock.Config) *Argon2id { mockConfig.On("GetInt", "hashing.argon2id.memory", 65536).Return(65536).Once() mockConfig.On("GetInt", "hashing.argon2id.time", 4).Return(4).Once() @@ -87,7 +147,7 @@ func getArgon2idHasher(mockConfig *configmock.Config) *Argon2id { } func getBcryptHasher(mockConfig *configmock.Config) *Bcrypt { - mockConfig.On("GetInt", "hashing.bcrypt.rounds", 10).Return(10).Once() + mockConfig.On("GetInt", "hashing.bcrypt.rounds", 12).Return(10).Once() return NewBcrypt(mockConfig) } diff --git a/hash/bcrypt.go b/hash/bcrypt.go index eb8423416..b7d6b33f2 100644 --- a/hash/bcrypt.go +++ b/hash/bcrypt.go @@ -13,7 +13,7 @@ type Bcrypt struct { // NewBcrypt returns a new Bcrypt hasher. func NewBcrypt(config config.Config) *Bcrypt { return &Bcrypt{ - rounds: config.GetInt("hashing.bcrypt.rounds", 10), + rounds: config.GetInt("hashing.bcrypt.rounds", 12), } } diff --git a/http/middleware/throttle_test.go b/http/middleware/throttle_test.go index adc0964f8..d2e8fb6ad 100644 --- a/http/middleware/throttle_test.go +++ b/http/middleware/throttle_test.go @@ -276,6 +276,88 @@ func TestThrottle(t *testing.T) { } } +func Benchmark_Throttle(b *testing.B) { + var ( + ctx *TestContext + mockRateLimiterFacade *httpmocks.RateLimiter + mockCache *cachemocks.Cache + ) + + now := carbon.Now() + carbon.SetTestNow(now) + defer carbon.UnsetTestNow() + + ctx = new(TestContext) + mockCache = &cachemocks.Cache{} + mockRateLimiterFacade = &httpmocks.RateLimiter{} + http.CacheFacade = mockCache + http.RateLimiterFacade = mockRateLimiterFacade + + b.Run("WithOneLimiter", func(b *testing.B) { + mockRateLimiterFacade.On("Limiter", "test").Return(func(ctx contractshttp.Context) []contractshttp.Limit { + return []contractshttp.Limit{ + limit.PerDay(10), + } + }).Times(b.N) + mockCache.On("Get", mock.MatchedBy(func(key string) bool { + return strings.HasPrefix(key, "throttle:test:0:") + })).Return(limit.NewBucket(1, time.Minute)).Times(b.N) + + for i := 0; i < b.N; i++ { + Throttle("test")(ctx) + } + + mockCache.AssertExpectations(b) + mockRateLimiterFacade.AssertExpectations(b) + }) + + b.Run("WithTwoLimiters", func(b *testing.B) { + mockRateLimiterFacade.On("Limiter", "test").Return(func(ctx contractshttp.Context) []contractshttp.Limit { + return []contractshttp.Limit{ + limit.PerDay(10), + limit.PerMinute(5), + } + }).Times(b.N) + mockCache.On("Get", mock.MatchedBy(func(key string) bool { + return strings.HasPrefix(key, "throttle:test:0:") + })).Return(limit.NewBucket(10, 24*time.Hour)) + mockCache.On("Get", mock.MatchedBy(func(key string) bool { + return strings.HasPrefix(key, "throttle:test:1:") + })).Return(limit.NewBucket(5, time.Minute)) + + for i := 0; i < b.N; i++ { + Throttle("test")(ctx) + } + + mockRateLimiterFacade.AssertExpectations(b) + }) + + b.Run("WithThreeLimiters", func(b *testing.B) { + mockRateLimiterFacade.On("Limiter", "test").Return(func(ctx contractshttp.Context) []contractshttp.Limit { + return []contractshttp.Limit{ + limit.PerMinute(5), + limit.PerHour(10), + limit.PerDay(100), + } + }).Times(b.N) + mockCache.On("Get", mock.MatchedBy(func(key string) bool { + return strings.HasPrefix(key, "throttle:test:0:") + })).Return(limit.NewBucket(10, 24*time.Hour)) + mockCache.On("Get", mock.MatchedBy(func(key string) bool { + return strings.HasPrefix(key, "throttle:test:1:") + })).Return(limit.NewBucket(5, time.Minute)) + mockCache.On("Get", mock.MatchedBy(func(key string) bool { + return strings.HasPrefix(key, "throttle:test:2:") + })).Return(limit.NewBucket(1, time.Second)) + + for i := 0; i < b.N; i++ { + Throttle("test")(ctx) + } + + mockRateLimiterFacade.AssertExpectations(b) + }) +} + type TestContext struct { response contractshttp.ContextResponse } diff --git a/log/logger/daily.go b/log/logger/daily.go index 64ba06ada..4c9c27bff 100644 --- a/log/logger/daily.go +++ b/log/logger/daily.go @@ -14,6 +14,7 @@ import ( "github.com/goravel/framework/contracts/foundation" "github.com/goravel/framework/log/formatter" "github.com/goravel/framework/support" + "github.com/goravel/framework/support/carbon" ) type Daily struct { @@ -43,6 +44,7 @@ func (daily *Daily) Handle(channel string) (logrus.Hook, error) { logPath+"-%Y-%m-%d"+ext, rotatelogs.WithRotationTime(time.Duration(24)*time.Hour), rotatelogs.WithRotationCount(uint(daily.config.GetInt(channel+".days"))), + rotatelogs.WithClock(rotatelogs.NewClock(carbon.Now().StdTime())), ) if err != nil { return hook, errors.New("Config local file system for logger error: " + err.Error()) diff --git a/log/logrus_writer_test.go b/log/logrus_writer_test.go index ba5088926..96ee5b5f1 100644 --- a/log/logrus_writer_test.go +++ b/log/logrus_writer_test.go @@ -387,7 +387,6 @@ func TestLogrus(t *testing.T) { mockConfig.AssertExpectations(t) }) } - _ = file.Remove("storage") } @@ -431,6 +430,73 @@ func TestLogrus_Fatalf(t *testing.T) { _ = file.Remove("storage") } +func Benchmark_Debug(b *testing.B) { + mockConfig := initMockConfig() + mockDriverConfig(mockConfig) + log := NewApplication(mockConfig, json.NewJson()) + + for i := 0; i < b.N; i++ { + log.Debug("Debug Goravel") + } + + _ = file.Remove("storage") +} + +func Benchmark_Info(b *testing.B) { + mockConfig := initMockConfig() + mockDriverConfig(mockConfig) + log := NewApplication(mockConfig, json.NewJson()) + + for i := 0; i < b.N; i++ { + log.Info("Goravel") + } + + _ = file.Remove("storage") +} + +func Benchmark_Warning(b *testing.B) { + mockConfig := initMockConfig() + mockDriverConfig(mockConfig) + log := NewApplication(mockConfig, json.NewJson()) + + for i := 0; i < b.N; i++ { + log.Warning("Goravel") + } + + _ = file.Remove("storage") +} + +func Benchmark_Error(b *testing.B) { + mockConfig := initMockConfig() + mockDriverConfig(mockConfig) + log := NewApplication(mockConfig, json.NewJson()) + + for i := 0; i < b.N; i++ { + log.Error("Goravel") + } + + _ = file.Remove("storage") +} + +func Benchmark_Fatal(b *testing.B) { + // This test is not suitable for benchmarking because it will exit the program +} + +func Benchmark_Panic(b *testing.B) { + mockConfig := initMockConfig() + mockDriverConfig(mockConfig) + log := NewApplication(mockConfig, json.NewJson()) + + for i := 0; i < b.N; i++ { + defer func() { + recover() //nolint:errcheck + }() + log.Panic("Goravel") + } + + _ = file.Remove("storage") +} + func initMockConfig() *configmock.Config { mockConfig := &configmock.Config{} diff --git a/mocks/session/Manager.go b/mocks/session/Manager.go index ed3adbec3..9215db392 100644 --- a/mocks/session/Manager.go +++ b/mocks/session/Manager.go @@ -155,20 +155,18 @@ func (_c *Manager_Driver_Call) RunAndReturn(run func(...string) (session.Driver, } // Extend provides a mock function with given fields: driver, handler -func (_m *Manager) Extend(driver string, handler func() session.Driver) session.Manager { +func (_m *Manager) Extend(driver string, handler func() session.Driver) error { ret := _m.Called(driver, handler) if len(ret) == 0 { panic("no return value specified for Extend") } - var r0 session.Manager - if rf, ok := ret.Get(0).(func(string, func() session.Driver) session.Manager); ok { + var r0 error + if rf, ok := ret.Get(0).(func(string, func() session.Driver) error); ok { r0 = rf(driver, handler) } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(session.Manager) - } + r0 = ret.Error(0) } return r0 @@ -193,12 +191,45 @@ func (_c *Manager_Extend_Call) Run(run func(driver string, handler func() sessio return _c } -func (_c *Manager_Extend_Call) Return(_a0 session.Manager) *Manager_Extend_Call { +func (_c *Manager_Extend_Call) Return(_a0 error) *Manager_Extend_Call { _c.Call.Return(_a0) return _c } -func (_c *Manager_Extend_Call) RunAndReturn(run func(string, func() session.Driver) session.Manager) *Manager_Extend_Call { +func (_c *Manager_Extend_Call) RunAndReturn(run func(string, func() session.Driver) error) *Manager_Extend_Call { + _c.Call.Return(run) + return _c +} + +// ReleaseSession provides a mock function with given fields: _a0 +func (_m *Manager) ReleaseSession(_a0 session.Session) { + _m.Called(_a0) +} + +// Manager_ReleaseSession_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ReleaseSession' +type Manager_ReleaseSession_Call struct { + *mock.Call +} + +// ReleaseSession is a helper method to define mock.On call +// - _a0 session.Session +func (_e *Manager_Expecter) ReleaseSession(_a0 interface{}) *Manager_ReleaseSession_Call { + return &Manager_ReleaseSession_Call{Call: _e.mock.On("ReleaseSession", _a0)} +} + +func (_c *Manager_ReleaseSession_Call) Run(run func(_a0 session.Session)) *Manager_ReleaseSession_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(session.Session)) + }) + return _c +} + +func (_c *Manager_ReleaseSession_Call) Return() *Manager_ReleaseSession_Call { + _c.Call.Return() + return _c +} + +func (_c *Manager_ReleaseSession_Call) RunAndReturn(run func(session.Session)) *Manager_ReleaseSession_Call { _c.Call.Return(run) return _c } diff --git a/session/driver/file_test.go b/session/driver/file_test.go index eeb697a55..1261e5cb7 100644 --- a/session/driver/file_test.go +++ b/session/driver/file_test.go @@ -1,7 +1,6 @@ package driver import ( - "sync" "testing" "github.com/stretchr/testify/suite" @@ -109,24 +108,24 @@ func (f *FileTestSuite) TestWrite() { f.Nil(file.Remove(f.getPath())) } -func (f *FileTestSuite) TestReadWriteWithConcurrent() { +func BenchmarkFile_ReadWrite(b *testing.B) { + f := new(FileTestSuite) + f.SetT(&testing.T{}) + driver := f.getDriver() + f.Nil(driver.Write("foo", "bar")) - var wg sync.WaitGroup - for i := 0; i < 1000; i++ { - wg.Add(1) - go func() { - f.Nil(driver.Write("foo", "bar")) - - value, err := driver.Read("foo") - f.Nil(err) - f.Equal("bar", value) - wg.Done() - }() + b.ResetTimer() + for i := 0; i < b.N; i++ { + f.Nil(driver.Write("foo", "bar")) + + value, err := driver.Read("foo") + f.Nil(err) + f.Equal("bar", value) } + b.StopTimer() - wg.Wait() - f.Nil(file.Remove(f.getPath())) + f.BeforeTest() } func (f *FileTestSuite) getDriver() *File { diff --git a/session/manager.go b/session/manager.go index ed3af0854..fba6436ef 100644 --- a/session/manager.go +++ b/session/manager.go @@ -2,33 +2,59 @@ package session import ( "fmt" + "sync" + "time" "github.com/goravel/framework/contracts/config" "github.com/goravel/framework/contracts/foundation" sessioncontract "github.com/goravel/framework/contracts/session" "github.com/goravel/framework/session/driver" + "github.com/goravel/framework/support/color" ) type Manager struct { - config config.Config - customDrivers map[string]sessioncontract.Driver - drivers map[string]sessioncontract.Driver - json foundation.Json + config config.Config + drivers map[string]sessioncontract.Driver + json foundation.Json + sessionPool sync.Pool } func NewManager(config config.Config, json foundation.Json) *Manager { manager := &Manager{ - config: config, - customDrivers: make(map[string]sessioncontract.Driver), - drivers: make(map[string]sessioncontract.Driver), - json: json, + config: config, + drivers: make(map[string]sessioncontract.Driver), + json: json, + sessionPool: sync.Pool{New: func() any { + return &Session{ + attributes: make(map[string]any), + } + }, + }, } - manager.registerDrivers() + manager.extendDefaultDrivers() return manager } +func (m *Manager) AcquireSession() *Session { + session := m.sessionPool.Get().(*Session) + return session +} + func (m *Manager) BuildSession(handler sessioncontract.Driver, sessionID ...string) sessioncontract.Session { - return NewSession(m.config.GetString("session.cookie"), handler, m.json, sessionID...) + if handler == nil { + panic("session driver cannot be nil") + } + session := m.AcquireSession() + session.setDriver(handler) + session.setJson(m.json) + session.SetName(m.config.GetString("session.cookie")) + if len(sessionID) > 0 { + session.SetID(sessionID[0]) + } else { + session.SetID("") + } + + return session } func (m *Manager) Driver(name ...string) (sessioncontract.Driver, error) { @@ -44,30 +70,58 @@ func (m *Manager) Driver(name ...string) (sessioncontract.Driver, error) { } if m.drivers[driverName] == nil { - if m.customDrivers[driverName] == nil { - return nil, fmt.Errorf("driver [%s] not supported", driverName) - } - - m.drivers[driverName] = m.customDrivers[driverName] + return nil, fmt.Errorf("driver [%s] not supported", driverName) } return m.drivers[driverName], nil } -func (m *Manager) Extend(driver string, handler func() sessioncontract.Driver) sessioncontract.Manager { - m.customDrivers[driver] = handler() - return m +func (m *Manager) Extend(driver string, handler func() sessioncontract.Driver) error { + if m.drivers[driver] != nil { + return fmt.Errorf("driver [%s] already exists", driver) + } + m.drivers[driver] = handler() + m.startGcTimer(m.drivers[driver]) + return nil +} + +func (m *Manager) ReleaseSession(session sessioncontract.Session) { + s := session.(*Session) + s.reset() + m.sessionPool.Put(s) } func (m *Manager) getDefaultDriver() string { return m.config.GetString("session.driver") } +func (m *Manager) extendDefaultDrivers() { + if err := m.Extend("file", m.createFileDriver); err != nil { + panic(fmt.Sprintf("failed to extend session file driver: %v", err)) + } +} + func (m *Manager) createFileDriver() sessioncontract.Driver { lifetime := m.config.GetInt("session.lifetime") return driver.NewFile(m.config.GetString("session.files"), lifetime) } -func (m *Manager) registerDrivers() { - m.drivers["file"] = m.createFileDriver() +// startGcTimer starts a garbage collection timer for the session driver. +func (m *Manager) startGcTimer(driver sessioncontract.Driver) { + interval := m.config.GetInt("session.gc_interval", 30) + if interval <= 0 { + // No need to start the timer if the interval is zero or negative + return + } + + ticker := time.NewTicker(time.Duration(interval) * time.Minute) + + go func() { + for range ticker.C { + lifetime := ConfigFacade.GetInt("session.lifetime") * 60 + if err := driver.Gc(lifetime); err != nil { + color.Red().Printf("Error performing garbage collection: %s\n", err) + } + } + }() } diff --git a/session/manager_test.go b/session/manager_test.go index 2c6f48e75..a45a5ffc1 100644 --- a/session/manager_test.go +++ b/session/manager_test.go @@ -2,7 +2,7 @@ package session import ( "fmt" - "sync" + "os" "testing" "github.com/stretchr/testify/suite" @@ -25,110 +25,123 @@ func TestManagerTestSuite(t *testing.T) { suite.Run(t, &ManagerTestSuite{}) } -func (m *ManagerTestSuite) SetupTest() { - m.mockConfig = mockconfig.NewConfig(m.T()) - m.mockConfig.On("GetInt", "session.lifetime").Return(120).Once() - m.mockConfig.On("GetString", "session.files").Return("storage/framework/sessions").Once() - m.manager = m.getManager() - m.json = json.NewJson() +func (s *ManagerTestSuite) SetupTest() { + s.mockConfig = mockconfig.NewConfig(s.T()) + s.mockConfig.On("GetInt", "session.lifetime").Return(120).Once() + s.mockConfig.On("GetInt", "session.gc_interval", 30).Return(30).Once() + s.mockConfig.On("GetString", "session.files").Return("storage/framework/sessions").Once() + s.manager = s.getManager() + s.json = json.NewJson() } -func (m *ManagerTestSuite) TestDriver() { +func (s *ManagerTestSuite) TearDownSuite() { + s.mockConfig.AssertExpectations(s.T()) +} + +func (s *ManagerTestSuite) TestDriver() { // provide driver name - driver, err := m.manager.Driver("file") - m.Nil(err) - m.NotNil(driver) - m.Equal("*driver.File", fmt.Sprintf("%T", driver)) + driver, err := s.manager.Driver("file") + s.Nil(err) + s.NotNil(driver) + s.Equal("*driver.File", fmt.Sprintf("%T", driver)) // provide no driver name - m.mockConfig.On("GetString", "session.driver").Return("file").Once() + s.mockConfig.On("GetString", "session.driver").Return("file").Once() - driver, err = m.manager.Driver() - m.Nil(err) - m.NotNil(driver) - m.Equal("*driver.File", fmt.Sprintf("%T", driver)) + driver, err = s.manager.Driver() + s.Nil(err) + s.NotNil(driver) + s.Equal("*driver.File", fmt.Sprintf("%T", driver)) // provide custom driver - m.manager.Extend("test", func() sessioncontract.Driver { - return NewCustomDriver() - }) - driver, err = m.manager.Driver("test") - m.Nil(err) - m.NotNil(driver) - m.Equal("*session.CustomDriver", fmt.Sprintf("%T", driver)) + s.mockConfig.On("GetInt", "session.gc_interval", 30).Return(30).Once() + err = s.manager.Extend("test", NewCustomDriver) + s.Nil(err) + driver, err = s.manager.Driver("test") + s.Nil(err) + s.NotNil(driver) + s.Equal("*session.CustomDriver", fmt.Sprintf("%T", driver)) // not supported a driver - m.mockConfig.On("GetString", "session.driver").Return("not_supported").Once() - driver, err = m.manager.Driver() - m.NotNil(err) - m.Equal("driver [not_supported] not supported", err.Error()) - m.Nil(driver) + s.mockConfig.On("GetString", "session.driver").Return("not_supported").Once() + driver, err = s.manager.Driver() + s.NotNil(err) + s.Equal("driver [not_supported] not supported", err.Error()) + s.Nil(driver) // driver is not set - m.mockConfig.On("GetString", "session.driver").Return("").Once() - driver, err = m.manager.Driver() - m.NotNil(err) - m.Equal("driver is not set", err.Error()) - m.Nil(driver) + s.mockConfig.On("GetString", "session.driver").Return("").Once() + driver, err = s.manager.Driver() + s.NotNil(err) + s.Equal("driver is not set", err.Error()) + s.Nil(driver) } -func (m *ManagerTestSuite) TestExtend() { - m.manager.Extend("test", func() sessioncontract.Driver { - return NewCustomDriver() - }) - driver, err := m.manager.Driver("test") - m.Nil(err) - m.NotNil(driver) - m.Equal("*session.CustomDriver", fmt.Sprintf("%T", driver)) +func (s *ManagerTestSuite) TestExtend() { + s.mockConfig.On("GetInt", "session.gc_interval", 30).Return(30).Once() + err := s.manager.Extend("test", NewCustomDriver) + s.Nil(err) + driver, err := s.manager.Driver("test") + s.Nil(err) + s.NotNil(driver) + s.Equal("*session.CustomDriver", fmt.Sprintf("%T", driver)) } -func (m *ManagerTestSuite) TestBuildSession() { - m.mockConfig.On("GetString", "session.cookie").Return("test_cookie").Once() - session := m.manager.BuildSession(nil) - m.NotNil(session) - m.Equal("test_cookie", session.GetName()) +func (s *ManagerTestSuite) TestBuildSession() { + driver, err := s.manager.Driver("file") + s.Nil(err) + s.NotNil(driver) + s.Equal("*driver.File", fmt.Sprintf("%T", driver)) + + s.mockConfig.On("GetString", "session.cookie").Return("test_cookie").Once() + session := s.manager.BuildSession(driver) + s.NotNil(session) + s.Equal("test_cookie", session.GetName()) } -func (m *ManagerTestSuite) TestGetDefaultDriver() { - m.mockConfig.On("GetString", "session.driver").Return("file") - m.Equal("file", m.manager.getDefaultDriver()) +func (s *ManagerTestSuite) TestGetDefaultDriver() { + s.mockConfig.On("GetString", "session.driver").Return("file") + s.Equal("file", s.manager.getDefaultDriver()) } -func (m *ManagerTestSuite) TestConcurrentReadWrite() { +func (s *ManagerTestSuite) getManager() *Manager { + return NewManager(s.mockConfig, s.json) +} + +func BenchmarkSession_ReadWrite(b *testing.B) { + s := new(ManagerTestSuite) + s.SetT(&testing.T{}) + s.SetupTest() + // provide driver name - driver, err := m.manager.Driver("file") - m.Nil(err) - m.NotNil(driver) - m.Equal("*driver.File", fmt.Sprintf("%T", driver)) + driver, err := s.manager.Driver("file") + s.Nil(err) + s.NotNil(driver) + s.Equal("*driver.File", fmt.Sprintf("%T", driver)) // provide no driver name - m.mockConfig.On("GetString", "session.driver").Return("file").Once() - - driver, err = m.manager.Driver() - m.Nil(err) - m.NotNil(driver) - m.Equal("*driver.File", fmt.Sprintf("%T", driver)) - - var wg sync.WaitGroup - for i := 0; i < 1000; i++ { - wg.Add(1) - go func() { - id := str.Random(32) - s := str.Random(32) - m.Nil(driver.Write(id, s)) - data, err := driver.Read(id) - m.Nil(err) - m.Equal(s, data) - wg.Done() - }() + s.mockConfig.On("GetString", "session.driver").Return("file").Once() + + driver, err = s.manager.Driver() + s.Nil(err) + s.NotNil(driver) + s.Equal("*driver.File", fmt.Sprintf("%T", driver)) + + b.StartTimer() + b.ResetTimer() + for i := 0; i < b.N; i++ { + id := str.Random(32) + s1 := str.Random(32) + s.Nil(driver.Write(id, s1)) + data, err := driver.Read(id) + s.Nil(err) + s.Equal(s, data) } + b.StopTimer() - wg.Wait() - m.Nil(driver.Destroy("test")) -} + s.Nil(driver.Destroy("test")) + s.Nil(os.RemoveAll("storage")) -func (m *ManagerTestSuite) getManager() *Manager { - return NewManager(m.mockConfig, m.json) } type CustomDriver struct{} diff --git a/session/middleware/start_session.go b/session/middleware/start_session.go index 35c86ea3a..9df9d46a0 100644 --- a/session/middleware/start_session.go +++ b/session/middleware/start_session.go @@ -50,8 +50,11 @@ func StartSession() http.Middleware { req.Next() // Save session - if err := s.Save(); err != nil { + if err = s.Save(); err != nil { color.Red().Printf("Error saving session: %s\n", err) } + + // Release session + session.SessionFacade.ReleaseSession(s) } } diff --git a/session/middleware/start_session_test.go b/session/middleware/start_session_test.go index 87a4dba5e..6d4c6fdb7 100644 --- a/session/middleware/start_session_test.go +++ b/session/middleware/start_session_test.go @@ -43,6 +43,7 @@ func TestStartSession(t *testing.T) { mockConfig := &configmocks.Config{} session.ConfigFacade = mockConfig mockConfig.On("GetInt", "session.lifetime").Return(120).Once() + mockConfig.On("GetInt", "session.gc_interval", 30).Return(30).Once() mockConfig.On("GetString", "session.files").Return("storage/framework/sessions").Once() session.SessionFacade = session.NewManager(mockConfig, json.NewJson()) server := httptest.NewServer(testHttpSessionMiddleware(nethttp.HandlerFunc(func(w nethttp.ResponseWriter, r *nethttp.Request) { diff --git a/session/service_provider.go b/session/service_provider.go index 1e4629787..a3c3d2c44 100644 --- a/session/service_provider.go +++ b/session/service_provider.go @@ -1,12 +1,9 @@ package session import ( - "time" - "github.com/goravel/framework/contracts/config" "github.com/goravel/framework/contracts/foundation" "github.com/goravel/framework/contracts/session" - "github.com/goravel/framework/support/color" ) var ( @@ -30,32 +27,4 @@ func (receiver *ServiceProvider) Register(app foundation.Application) { func (receiver *ServiceProvider) Boot(app foundation.Application) { SessionFacade = app.MakeSession() ConfigFacade = app.MakeConfig() - - driver, err := SessionFacade.Driver() - if err != nil { - color.Red().Println(err) - return - } - - startGcTimer(driver) -} - -// startGcTimer starts a garbage collection timer for the session driver. -func startGcTimer(driver session.Driver) { - interval := ConfigFacade.GetInt("session.gc_interval", 30) - if interval <= 0 { - // No need to start the timer if the interval is zero or negative - return - } - - ticker := time.NewTicker(time.Duration(interval) * time.Minute) - - go func() { - for range ticker.C { - lifetime := ConfigFacade.GetInt("session.lifetime") * 60 - if err := driver.Gc(lifetime); err != nil { - color.Red().Printf("Error performing garbage collection: %s\n", err) - } - } - }() } diff --git a/session/session.go b/session/session.go index decd16c98..7c796e09f 100644 --- a/session/session.go +++ b/session/session.go @@ -272,6 +272,22 @@ func (s *Session) removeFromOldFlashData(keys ...string) { s.Put("_flash.old", old) } +func (s *Session) reset() { + s.id = "" + s.name = "" + s.attributes = make(map[string]any) + s.driver = nil + s.started = false +} + +func (s *Session) setDriver(driver sessioncontract.Driver) { + s.driver = driver +} + +func (s *Session) setJson(json foundation.Json) { + s.json = json +} + // toStringSlice converts an interface slice to a string slice. func toStringSlice(anySlice []any) []string { strSlice := make([]string, len(anySlice)) diff --git a/support/docker/postgresql.go b/support/docker/postgres.go similarity index 92% rename from support/docker/postgresql.go rename to support/docker/postgres.go index d0e8dedf1..6390fd6f6 100644 --- a/support/docker/postgresql.go +++ b/support/docker/postgres.go @@ -44,17 +44,17 @@ func (receiver *PostgresImpl) Build() error { command, exposedPorts := imageToCommand(receiver.image) containerID, err := run(command) if err != nil { - return fmt.Errorf("init Postgresql error: %v", err) + return fmt.Errorf("init Postgres error: %v", err) } if containerID == "" { - return fmt.Errorf("no container id return when creating Postgresql docker") + return fmt.Errorf("no container id return when creating Postgres docker") } receiver.containerID = containerID receiver.port = getExposedPort(exposedPorts, 5432) if _, err := receiver.connect(); err != nil { - return fmt.Errorf("connect Postgresql error: %v", err) + return fmt.Errorf("connect Postgres error: %v", err) } return nil @@ -92,12 +92,12 @@ func (receiver *PostgresImpl) Image(image testing.Image) { } func (receiver *PostgresImpl) Name() orm.Driver { - return orm.DriverPostgresql + return orm.DriverPostgres } func (receiver *PostgresImpl) Stop() error { if _, err := run(fmt.Sprintf("docker stop %s", receiver.containerID)); err != nil { - return fmt.Errorf("stop Postgresql error: %v", err) + return fmt.Errorf("stop Postgres error: %v", err) } return nil diff --git a/support/docker/postgresql_test.go b/support/docker/postgres_test.go similarity index 57% rename from support/docker/postgresql_test.go rename to support/docker/postgres_test.go index 8db648859..4ce7331c0 100644 --- a/support/docker/postgresql_test.go +++ b/support/docker/postgres_test.go @@ -11,36 +11,36 @@ import ( "github.com/goravel/framework/support/env" ) -type PostgresqlTestSuite struct { +type PostgresTestSuite struct { suite.Suite mockConfig *configmocks.Config - postgresql *PostgresImpl + postgres *PostgresImpl } -func TestPostgresqlTestSuite(t *testing.T) { +func TestPostgresTestSuite(t *testing.T) { if env.IsWindows() { t.Skip("Skipping tests of using docker") } - suite.Run(t, new(PostgresqlTestSuite)) + suite.Run(t, new(PostgresTestSuite)) } -func (s *PostgresqlTestSuite) SetupTest() { +func (s *PostgresTestSuite) SetupTest() { s.mockConfig = &configmocks.Config{} - s.postgresql = NewPostgresImpl("goravel", "goravel", "goravel") + s.postgres = NewPostgresImpl("goravel", "goravel", "goravel") } -func (s *PostgresqlTestSuite) TestBuild() { - s.Nil(s.postgresql.Build()) - instance, err := s.postgresql.connect() +func (s *PostgresTestSuite) TestBuild() { + s.Nil(s.postgres.Build()) + instance, err := s.postgres.connect() s.Nil(err) s.NotNil(instance) - s.Equal("127.0.0.1", s.postgresql.Config().Host) - s.Equal("goravel", s.postgresql.Config().Database) - s.Equal("goravel", s.postgresql.Config().Username) - s.Equal("goravel", s.postgresql.Config().Password) - s.True(s.postgresql.Config().Port > 0) + s.Equal("127.0.0.1", s.postgres.Config().Host) + s.Equal("goravel", s.postgres.Config().Database) + s.Equal("goravel", s.postgres.Config().Username) + s.Equal("goravel", s.postgres.Config().Password) + s.True(s.postgres.Config().Port > 0) res := instance.Exec(` CREATE TABLE users ( @@ -63,7 +63,7 @@ func (s *PostgresqlTestSuite) TestBuild() { s.Nil(res.Error) s.Equal(int64(1), count) - s.Nil(s.postgresql.Fresh()) + s.Nil(s.postgres.Fresh()) res = instance.Raw(` SELECT count(*) FROM information_schema.tables WHERE table_schema = 'public' and table_name = 'users'; @@ -71,17 +71,17 @@ func (s *PostgresqlTestSuite) TestBuild() { s.Nil(res.Error) s.Equal(int64(0), count) - s.Nil(s.postgresql.Stop()) + s.Nil(s.postgres.Stop()) } -func (s *PostgresqlTestSuite) TestImage() { +func (s *PostgresTestSuite) TestImage() { image := contractstesting.Image{ - Repository: "postgresql", + Repository: "postgres", } - s.postgresql.Image(image) - s.Equal(&image, s.postgresql.image) + s.postgres.Image(image) + s.Equal(&image, s.postgres.image) } -func (s *PostgresqlTestSuite) TestName() { - s.Equal(orm.DriverPostgresql, s.postgresql.Name()) +func (s *PostgresTestSuite) TestName() { + s.Equal(orm.DriverPostgres, s.postgres.Name()) } diff --git a/support/file/file_test.go b/support/file/file_test.go index 40e8b3ebf..c442a0866 100644 --- a/support/file/file_test.go +++ b/support/file/file_test.go @@ -4,9 +4,9 @@ import ( "os" "testing" - "github.com/goravel/framework/testing/file" - "github.com/stretchr/testify/assert" + + "github.com/goravel/framework/testing/file" ) func TestClientOriginalExtension(t *testing.T) { diff --git a/testing/docker/database.go b/testing/docker/database.go index f90359105..b0327c92f 100644 --- a/testing/docker/database.go +++ b/testing/docker/database.go @@ -39,7 +39,7 @@ func NewDatabase(app foundation.Application, connection string, gormInitialize g switch contractsorm.Driver(driver) { case contractsorm.DriverMysql: databaseDriver = supportdocker.NewMysqlImpl(database, username, password) - case contractsorm.DriverPostgresql: + case contractsorm.DriverPostgres: databaseDriver = supportdocker.NewPostgresImpl(database, username, password) case contractsorm.DriverSqlserver: databaseDriver = supportdocker.NewSqlserverImpl(database, username, password) diff --git a/testing/docker/database_test.go b/testing/docker/database_test.go index 1baee82ba..daab119ee 100644 --- a/testing/docker/database_test.go +++ b/testing/docker/database_test.go @@ -90,19 +90,19 @@ func TestNewDatabase(t *testing.T) { }, }, { - name: "success when connection is postgresql", - connection: "postgresql", + name: "success when connection is postgres", + connection: "postgres", setup: func() { - mockConfig.On("GetString", "database.connections.postgresql.driver").Return(contractsorm.DriverPostgresql.String()).Once() - mockConfig.On("GetString", "database.connections.postgresql.database").Return(database).Once() - mockConfig.On("GetString", "database.connections.postgresql.username").Return(username).Once() - mockConfig.On("GetString", "database.connections.postgresql.password").Return(password).Once() + mockConfig.On("GetString", "database.connections.postgres.driver").Return(contractsorm.DriverPostgres.String()).Once() + mockConfig.On("GetString", "database.connections.postgres.database").Return(database).Once() + mockConfig.On("GetString", "database.connections.postgres.username").Return(username).Once() + mockConfig.On("GetString", "database.connections.postgres.password").Return(password).Once() }, wantDatabase: func() *Database { return &Database{ app: mockApp, config: mockConfig, - connection: "postgresql", + connection: "postgres", driver: supportdocker.NewPostgresImpl(database, username, password), gormInitialize: mockGormInitialize, } diff --git a/testing/docker/docker_test.go b/testing/docker/docker_test.go index ae8f46456..d6c35b13a 100644 --- a/testing/docker/docker_test.go +++ b/testing/docker/docker_test.go @@ -40,15 +40,15 @@ func (s *DockerTestSuite) TestDatabase() { s.Equal("mysql", databaseImpl.connection) mockConfig = &configmocks.Config{} - mockConfig.On("GetString", "database.connections.postgresql.driver").Return("postgresql").Once() - mockConfig.On("GetString", "database.connections.postgresql.database").Return("goravel").Once() - mockConfig.On("GetString", "database.connections.postgresql.username").Return("goravel").Once() - mockConfig.On("GetString", "database.connections.postgresql.password").Return("goravel").Once() + mockConfig.On("GetString", "database.connections.postgres.driver").Return("postgres").Once() + mockConfig.On("GetString", "database.connections.postgres.database").Return("goravel").Once() + mockConfig.On("GetString", "database.connections.postgres.username").Return("goravel").Once() + mockConfig.On("GetString", "database.connections.postgres.password").Return("goravel").Once() s.mockApp.On("MakeConfig").Return(mockConfig).Once() - database, err = s.docker.Database("postgresql") + database, err = s.docker.Database("postgres") s.Nil(err) s.NotNil(database) databaseImpl = database.(*Database) - s.Equal("postgresql", databaseImpl.connection) + s.Equal("postgres", databaseImpl.connection) } diff --git a/translation/file_loader_test.go b/translation/file_loader_test.go index 10ad4279b..12f01a595 100644 --- a/translation/file_loader_test.go +++ b/translation/file_loader_test.go @@ -19,17 +19,22 @@ type FileLoaderTestSuite struct { } func TestFileLoaderTestSuite(t *testing.T) { - assert.Nil(t, file.Create("lang/en/test.json", `{"foo": "bar", "baz": {"foo": "bar"}}`)) - assert.Nil(t, file.Create("lang/en/another/test.json", `{"foo": "backagebar", "baz": "backagesplash"}`)) - assert.Nil(t, file.Create("lang/another/en/test.json", `{"foo": "backagebar", "baz": "backagesplash"}`)) - assert.Nil(t, file.Create("lang/en/invalid/test.json", `{"foo": "bar",}`)) - assert.Nil(t, file.Create("lang/cn.json", `{"foo": "bar", "baz": {"foo": "bar"}}`)) + suite.Run(t, &FileLoaderTestSuite{}) +} + +func (f *FileLoaderTestSuite) SetupSuite() { + assert.Nil(f.T(), file.Create("lang/en/test.json", `{"foo": "bar", "baz": {"foo": "bar"}}`)) + assert.Nil(f.T(), file.Create("lang/en/another/test.json", `{"foo": "backagebar", "baz": "backagesplash"}`)) + assert.Nil(f.T(), file.Create("lang/another/en/test.json", `{"foo": "backagebar", "baz": "backagesplash"}`)) + assert.Nil(f.T(), file.Create("lang/en/invalid/test.json", `{"foo": "bar",}`)) + assert.Nil(f.T(), file.Create("lang/cn.json", `{"foo": "bar", "baz": {"foo": "bar"}}`)) restrictedFilePath := "lang/en/restricted/test.json" - assert.Nil(t, file.Create(restrictedFilePath, `{"foo": "restricted"}`)) - assert.Nil(t, os.Chmod(restrictedFilePath, 0000)) + assert.Nil(f.T(), file.Create(restrictedFilePath, `{"foo": "restricted"}`)) + assert.Nil(f.T(), os.Chmod(restrictedFilePath, 0000)) +} - suite.Run(t, &FileLoaderTestSuite{}) - assert.Nil(t, file.Remove("lang")) +func (f *FileLoaderTestSuite) TearDownSuite() { + f.Nil(file.Remove("lang")) } func (f *FileLoaderTestSuite) SetupTest() { @@ -96,3 +101,22 @@ func (f *FileLoaderTestSuite) TestLoadInvalidJSON() { f.Error(err) f.Nil(translations) } + +func Benchmark_Load(b *testing.B) { + s := new(FileLoaderTestSuite) + s.SetT(&testing.T{}) + s.SetupSuite() + s.SetupTest() + b.StartTimer() + b.ResetTimer() + + paths := []string{"./lang"} + loader := NewFileLoader(paths, s.json) + for i := 0; i < b.N; i++ { + _, err := loader.Load("en", "test") + s.NoError(err) + } + + b.StopTimer() + s.TearDownSuite() +} diff --git a/translation/translator_test.go b/translation/translator_test.go index b0eb4b5ac..44dad98f0 100644 --- a/translation/translator_test.go +++ b/translation/translator_test.go @@ -446,3 +446,66 @@ func TestGetValue(t *testing.T) { result = getValue(obj, "x.y.z") assert.Equal(t, nil, result) } + +func Benchmark_Choice(b *testing.B) { + s := new(TranslatorTestSuite) + s.SetT(&testing.T{}) + s.SetupTest() + b.StartTimer() + b.ResetTimer() + + translator := NewTranslator(s.ctx, s.mockLoader, "en", "en", s.mockLog) + s.mockLoader.On("Load", "en", "*").Return(map[string]any{ + "test": map[string]any{ + "foo": "{0} first|{1}second", + }, + }, nil) + + for i := 0; i < b.N; i++ { + translator.Choice("test.foo", 1) + } + + b.StopTimer() +} + +func Benchmark_Get(b *testing.B) { + s := new(TranslatorTestSuite) + s.SetT(&testing.T{}) + s.SetupTest() + b.StartTimer() + b.ResetTimer() + + translator := NewTranslator(s.ctx, s.mockLoader, "en", "en", s.mockLog) + s.mockLoader.On("Load", "en", "*").Return(map[string]any{ + "test": map[string]any{ + "foo": "bar", + }, + }, nil) + + for i := 0; i < b.N; i++ { + translator.Get("test.foo") + } + + b.StopTimer() +} + +func Benchmark_Has(b *testing.B) { + s := new(TranslatorTestSuite) + s.SetT(&testing.T{}) + s.SetupTest() + b.StartTimer() + b.ResetTimer() + + translator := NewTranslator(s.ctx, s.mockLoader, "en", "en", s.mockLog) + s.mockLoader.On("Load", "en", "*").Return(map[string]any{ + "test": map[string]any{ + "foo": "bar", + }, + }, nil) + + for i := 0; i < b.N; i++ { + translator.Has("test.foo") + } + + b.StopTimer() +} diff --git a/validation/errors_test.go b/validation/errors_test.go index afbee5feb..4cacb911e 100644 --- a/validation/errors_test.go +++ b/validation/errors_test.go @@ -3,9 +3,9 @@ package validation import ( "testing" - httpvalidate "github.com/goravel/framework/contracts/validation" - "github.com/stretchr/testify/assert" + + httpvalidate "github.com/goravel/framework/contracts/validation" ) func TestOne(t *testing.T) { From 9996f02235d012dc34e02e2c3c8e85207ffed688 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 12 Sep 2024 07:47:10 +0800 Subject: [PATCH 5/5] chore(deps): Update module google.golang.org/grpc to v1.66.2 (#641) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bae48c119..a67d145e3 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,7 @@ require ( go.uber.org/atomic v1.11.0 golang.org/x/crypto v0.27.0 golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e - google.golang.org/grpc v1.66.1 + google.golang.org/grpc v1.66.2 gorm.io/driver/mysql v1.5.7 gorm.io/driver/postgres v1.5.9 gorm.io/driver/sqlserver v1.5.3 diff --git a/go.sum b/go.sum index 9ff1f7b22..85c8e725b 100644 --- a/go.sum +++ b/go.sum @@ -1024,8 +1024,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.66.1 h1:hO5qAXR19+/Z44hmvIM4dQFMSYX9XcWsByfoxutBpAM= -google.golang.org/grpc v1.66.1/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= +google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=