diff --git a/CHANGELOG.md b/CHANGELOG.md index ab3c73982..c2dc4fc19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,10 +11,12 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release. ### Added * New types for MessagePack extensions compatible with go-option (#459). +* Added `box.MustNew` wrapper for `box.New` without an error (#448). ### Changed * Required Go version is `1.24` now (#456). +* `box.New` returns an error instead of panic (#448). ### Fixed diff --git a/MIGRATION.md b/MIGRATION.md index 54f4e3034..ea82c8815 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -9,6 +9,8 @@ TODO ### Major changes * Required Go version is `1.24` now. +* `box.New` returns an error instead of panic +* Added `box.MustNew` wrapper for `box.New` without an error ## Migration from v1.x.x to v2.x.x diff --git a/box/box.go b/box/box.go index a4cc1780e..4341768cf 100644 --- a/box/box.go +++ b/box/box.go @@ -1,6 +1,8 @@ package box import ( + "errors" + "github.com/tarantool/go-tarantool/v3" ) @@ -11,16 +13,24 @@ type Box struct { } // New returns a new instance of the box structure, which implements the Box interface. -func New(conn tarantool.Doer) *Box { +func New(conn tarantool.Doer) (*Box, error) { if conn == nil { - // Check if the provided Tarantool connection is nil, and if it is, panic with an error - // message. panic early helps to catch and fix nil pointer issues in the code. - panic("tarantool connection cannot be nil") + return nil, errors.New("tarantool connection cannot be nil") } return &Box{ conn: conn, // Assigns the provided Tarantool connection. + }, nil +} + +// MustNew returns a new instance of the box structure, which implements the Box interface. +// It panics if conn == nil. +func MustNew(conn tarantool.Doer) *Box { + b, err := New(conn) + if err != nil { + panic(err) } + return b } // Schema returns a new Schema instance, providing access to schema-related operations. diff --git a/box/box_test.go b/box/box_test.go index 59ceaf6e3..57d0d5526 100644 --- a/box/box_test.go +++ b/box/box_test.go @@ -15,8 +15,31 @@ import ( func TestNew(t *testing.T) { t.Parallel() + _, err := box.New(nil) + require.Error(t, err) +} + +func TestMustNew(t *testing.T) { + t.Parallel() + // Create a box instance with a nil connection. This should lead to a panic. - require.Panics(t, func() { box.New(nil) }) + require.Panics(t, func() { box.MustNew(nil) }) +} + +func TestMocked_BoxNew(t *testing.T) { + t.Parallel() + + mock := test_helpers.NewMockDoer(t, + test_helpers.NewMockResponse(t, "valid"), + ) + + b, err := box.New(&mock) + require.NoError(t, err) + require.NotNil(t, b) + + assert.Len(t, mock.Requests, 0) + b.Schema().User().Exists(box.NewInfoRequest().Ctx(), "") + require.Len(t, mock.Requests, 1) } func TestMocked_BoxInfo(t *testing.T) { @@ -37,7 +60,7 @@ func TestMocked_BoxInfo(t *testing.T) { mock := test_helpers.NewMockDoer(t, test_helpers.NewMockResponse(t, data), ) - b := box.New(&mock) + b := box.MustNew(&mock) info, err := b.Info() require.NoError(t, err) @@ -57,7 +80,7 @@ func TestMocked_BoxSchemaUserInfo(t *testing.T) { mock := test_helpers.NewMockDoer(t, test_helpers.NewMockResponse(t, data), ) - b := box.New(&mock) + b := box.MustNew(&mock) privs, err := b.Schema().User().Info(context.Background(), "username") require.NoError(t, err) @@ -82,7 +105,7 @@ func TestMocked_BoxSessionSu(t *testing.T) { test_helpers.NewMockResponse(t, []interface{}{}), errors.New("user not found or supplied credentials are invalid"), ) - b := box.New(&mock) + b := box.MustNew(&mock) err := b.Session().Su(context.Background(), "admin") require.NoError(t, err) diff --git a/box/example_test.go b/box/example_test.go index fa65189a8..39474d8aa 100644 --- a/box/example_test.go +++ b/box/example_test.go @@ -45,7 +45,7 @@ func ExampleBox_Info() { // Or use simple Box implementation. - b := box.New(client) + b := box.MustNew(client) info, err := b.Info() if err != nil { @@ -88,7 +88,8 @@ func ExampleSchemaUser_Exists() { } // Or use simple User implementation. - b := box.New(client) + b := box.MustNew(client) + exists, err := b.Schema().User().Exists(ctx, "user") if err != nil { log.Fatalf("Failed get box schema user exists with error: %s", err) @@ -120,7 +121,7 @@ func ExampleSchemaUser_Create() { } // Create SchemaUser. - schemaUser := box.New(client).Schema().User() + schemaUser := box.MustNew(client).Schema().User() // Create a new user. username := "new_user" @@ -153,7 +154,7 @@ func ExampleSchemaUser_Drop() { } // Create SchemaUser. - schemaUser := box.New(client).Schema().User() + schemaUser := box.MustNew(client).Schema().User() // Drop an existing user. username := "new_user" @@ -192,7 +193,7 @@ func ExampleSchemaUser_Password() { } // Create SchemaUser. - schemaUser := box.New(client).Schema().User() + schemaUser := box.MustNew(client).Schema().User() // Get the password hash. password := "my-password" @@ -221,7 +222,7 @@ func ExampleSchemaUser_Info() { } // Create SchemaUser. - schemaUser := box.New(client).Schema().User() + schemaUser := box.MustNew(client).Schema().User() info, err := schemaUser.Info(ctx, "test") if err != nil { diff --git a/box/session_test.go b/box/session_test.go index 39b80d1d4..188360251 100644 --- a/box/session_test.go +++ b/box/session_test.go @@ -10,7 +10,7 @@ import ( ) func TestBox_Session(t *testing.T) { - b := box.New(th.Ptr(th.NewMockDoer(t))) + b := box.MustNew(th.Ptr(th.NewMockDoer(t))) require.NotNil(t, b.Session()) } diff --git a/box/tarantool_test.go b/box/tarantool_test.go index 4244a98e9..ae47932d8 100644 --- a/box/tarantool_test.go +++ b/box/tarantool_test.go @@ -48,7 +48,9 @@ func TestBox_Sugar_Info(t *testing.T) { conn, err := tarantool.Connect(ctx, dialer, tarantool.Opts{}) require.NoError(t, err) - info, err := box.New(conn).Info() + b := box.MustNew(conn) + + info, err := b.Info() require.NoError(t, err) validateInfo(t, info) @@ -83,7 +85,7 @@ func TestBox_Sugar_Schema_UserCreate_NoError(t *testing.T) { conn, err := tarantool.Connect(ctx, dialer, tarantool.Opts{}) require.NoError(t, err) - b := box.New(conn) + b := box.MustNew(conn) // Create new user. err = b.Schema().User().Create(ctx, username, box.UserCreateOptions{Password: password}) @@ -103,7 +105,7 @@ func TestBox_Sugar_Schema_UserCreate_CanConnectWithNewCred(t *testing.T) { conn, err := tarantool.Connect(ctx, dialer, tarantool.Opts{}) require.NoError(t, err) - b := box.New(conn) + b := box.MustNew(conn) // Create new user. err = b.Schema().User().Create(ctx, username, box.UserCreateOptions{Password: password}) @@ -137,7 +139,7 @@ func TestBox_Sugar_Schema_UserCreate_AlreadyExists(t *testing.T) { conn, err := tarantool.Connect(ctx, dialer, tarantool.Opts{}) require.NoError(t, err) - b := box.New(conn) + b := box.MustNew(conn) // Create new user. err = b.Schema().User().Create(ctx, username, box.UserCreateOptions{Password: password}) @@ -167,7 +169,7 @@ func TestBox_Sugar_Schema_UserCreate_ExistsTrue(t *testing.T) { conn, err := tarantool.Connect(ctx, dialer, tarantool.Opts{}) require.NoError(t, err) - b := box.New(conn) + b := box.MustNew(conn) // Create new user. err = b.Schema().User().Create(ctx, username, box.UserCreateOptions{Password: password}) @@ -193,7 +195,7 @@ func TestBox_Sugar_Schema_UserCreate_IfNotExistsNoErr(t *testing.T) { conn, err := tarantool.Connect(ctx, dialer, tarantool.Opts{}) require.NoError(t, err) - b := box.New(conn) + b := box.MustNew(conn) // Create new user. err = b.Schema().User().Create(ctx, username, box.UserCreateOptions{Password: password}) @@ -217,7 +219,7 @@ func TestBox_Sugar_Schema_UserPassword(t *testing.T) { conn, err := tarantool.Connect(ctx, dialer, tarantool.Opts{}) require.NoError(t, err) - b := box.New(conn) + b := box.MustNew(conn) // Require password hash. hash, err := b.Schema().User().Password(ctx, password) @@ -236,7 +238,7 @@ func TestBox_Sugar_Schema_UserDrop_AfterCreate(t *testing.T) { conn, err := tarantool.Connect(ctx, dialer, tarantool.Opts{}) require.NoError(t, err) - b := box.New(conn) + b := box.MustNew(conn) // Create new user err = b.Schema().User().Create(ctx, username, box.UserCreateOptions{Password: password}) @@ -258,7 +260,7 @@ func TestBox_Sugar_Schema_UserDrop_DoubleDrop(t *testing.T) { conn, err := tarantool.Connect(ctx, dialer, tarantool.Opts{}) require.NoError(t, err) - b := box.New(conn) + b := box.MustNew(conn) // Create new user err = b.Schema().User().Create(ctx, username, box.UserCreateOptions{Password: password}) @@ -286,7 +288,7 @@ func TestBox_Sugar_Schema_UserDrop_UnknownUser(t *testing.T) { conn, err := tarantool.Connect(ctx, dialer, tarantool.Opts{}) require.NoError(t, err) - b := box.New(conn) + b := box.MustNew(conn) // Require error cause user not exists err = b.Schema().User().Drop(ctx, "some_strange_not_existing_name", box.UserDropOptions{}) @@ -305,7 +307,7 @@ func TestSchemaUser_Passwd_NotFound(t *testing.T) { conn, err := tarantool.Connect(ctx, dialer, tarantool.Opts{}) require.NoError(t, err) - b := box.New(conn) + b := box.MustNew(conn) err = b.Schema().User().Passwd(ctx, "not-exists-passwd", "new_password") require.Error(t, err) @@ -329,7 +331,7 @@ func TestSchemaUser_Passwd_Ok(t *testing.T) { conn, err := tarantool.Connect(ctx, dialer, tarantool.Opts{}) require.NoError(t, err) - b := box.New(conn) + b := box.MustNew(conn) // New user change password and connect @@ -367,7 +369,7 @@ func TestSchemaUser_Passwd_WithoutGrants(t *testing.T) { conn, err := tarantool.Connect(ctx, dialer, tarantool.Opts{}) require.NoError(t, err) - b := box.New(conn) + b := box.MustNew(conn) err = b.Schema().User().Create(ctx, username, box.UserCreateOptions{Password: startPassword, IfNotExists: true}) @@ -381,7 +383,8 @@ func TestSchemaUser_Passwd_WithoutGrants(t *testing.T) { require.NoError(t, err) require.NotNil(t, conn2Fail) - bFail := box.New(conn2Fail) + bFail := box.MustNew(conn2Fail) + // can't change self user password without grants err = bFail.Schema().User().Passwd(ctx, endPassword) require.Error(t, err) @@ -401,7 +404,7 @@ func TestSchemaUser_Info_TestUserCorrect(t *testing.T) { conn, err := tarantool.Connect(ctx, dialer, tarantool.Opts{}) require.NoError(t, err) - b := box.New(conn) + b := box.MustNew(conn) privileges, err := b.Schema().User().Info(ctx, dialer.User) require.NoError(t, err) @@ -418,7 +421,7 @@ func TestSchemaUser_Info_NonExistsUser(t *testing.T) { conn, err := tarantool.Connect(ctx, dialer, tarantool.Opts{}) require.NoError(t, err) - b := box.New(conn) + b := box.MustNew(conn) privileges, err := b.Schema().User().Info(ctx, "non-existing") require.Error(t, err) @@ -438,7 +441,7 @@ func TestBox_Sugar_Schema_UserGrant_NoSu(t *testing.T) { conn, err := tarantool.Connect(ctx, dialer, tarantool.Opts{}) require.NoError(t, err) - b := box.New(conn) + b := box.MustNew(conn) err = b.Schema().User().Create(ctx, username, box.UserCreateOptions{Password: password}) require.NoError(t, err) @@ -471,7 +474,7 @@ func TestBox_Sugar_Schema_UserGrant_WithSu(t *testing.T) { conn, err := tarantool.Connect(ctx, dialer, tarantool.Opts{}) require.NoError(t, err) - b := box.New(conn) + b := box.MustNew(conn) err = b.Schema().User().Create(ctx, username, box.UserCreateOptions{Password: password}) require.NoError(t, err) @@ -521,7 +524,7 @@ func TestSchemaUser_Revoke_WithoutSu(t *testing.T) { conn, err := tarantool.Connect(ctx, dialer, tarantool.Opts{}) require.NoError(t, err) - b := box.New(conn) + b := box.MustNew(conn) err = b.Schema().User().Create(ctx, username, box.UserCreateOptions{Password: password}) require.NoError(t, err) @@ -555,7 +558,7 @@ func TestSchemaUser_Revoke_WithSu(t *testing.T) { conn, err := tarantool.Connect(ctx, dialer, tarantool.Opts{}) require.NoError(t, err) - b := box.New(conn) + b := box.MustNew(conn) err = b.Schema().User().Create(ctx, username, box.UserCreateOptions{Password: password}) require.NoError(t, err) @@ -603,7 +606,7 @@ func TestSchemaUser_Revoke_NonExistsPermission(t *testing.T) { conn, err := tarantool.Connect(ctx, dialer, tarantool.Opts{}) require.NoError(t, err) - b := box.New(conn) + b := box.MustNew(conn) err = b.Schema().User().Create(ctx, username, box.UserCreateOptions{Password: password}) require.NoError(t, err) @@ -639,7 +642,7 @@ func TestSession_Su_AdminPermissions(t *testing.T) { conn, err := tarantool.Connect(ctx, dialer, tarantool.Opts{}) require.NoError(t, err) - b := box.New(conn) + b := box.MustNew(conn) err = b.Session().Su(ctx, "admin") require.NoError(t, err) @@ -652,7 +655,8 @@ func cleanupUser(username string) { log.Fatal(err) } - b := box.New(conn) + b := box.MustNew(conn) + err = b.Schema().User().Drop(ctx, username, box.UserDropOptions{}) if err != nil { log.Fatal(err)