From 68dc377996cd892667bc989a69e5d96f344fd45a Mon Sep 17 00:00:00 2001 From: Albert Skalt Date: Fri, 10 Nov 2023 15:57:59 +0300 Subject: [PATCH] draft: fix tests --- box_error_test.go | 12 +- connection_test.go | 32 -- crud/example_test.go | 10 +- crud/tarantool_test.go | 15 +- datetime/datetime_test.go | 29 +- datetime/example_test.go | 8 +- datetime/interval_test.go | 2 +- decimal/decimal_test.go | 19 +- decimal/example_test.go | 9 +- dial_test.go | 361 ++++++++++---- example_custom_unpacking_test.go | 12 +- example_test.go | 156 +++--- export_test.go | 19 +- pool/connection_pool_test.go | 467 +++++++++-------- pool/example_test.go | 85 ++-- pool/round_robin_test.go | 15 +- queue/example_connection_pool_test.go | 33 +- queue/example_msgpack_test.go | 9 +- queue/example_test.go | 9 +- queue/queue_test.go | 88 ++-- settings/example_test.go | 6 +- settings/tarantool_test.go | 33 +- shutdown_test.go | 66 +-- ssl_test.go | 694 +++++++++++--------------- tarantool_test.go | 380 +++++--------- test_helpers/main.go | 45 +- test_helpers/pool_helper.go | 55 +- test_helpers/utils.go | 4 +- uuid/example_test.go | 9 +- uuid/uuid_test.go | 15 +- 30 files changed, 1316 insertions(+), 1381 deletions(-) delete mode 100644 connection_test.go diff --git a/box_error_test.go b/box_error_test.go index 0d7d3f47b..b08b6cc52 100644 --- a/box_error_test.go +++ b/box_error_test.go @@ -299,7 +299,7 @@ func TestErrorTypeMPEncodeDecode(t *testing.T) { func TestErrorTypeEval(t *testing.T) { test_helpers.SkipIfErrorMessagePackTypeUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() for name, testcase := range tupleCases { @@ -318,7 +318,7 @@ func TestErrorTypeEval(t *testing.T) { func TestErrorTypeEvalTyped(t *testing.T) { test_helpers.SkipIfErrorMessagePackTypeUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() for name, testcase := range tupleCases { @@ -336,7 +336,7 @@ func TestErrorTypeEvalTyped(t *testing.T) { func TestErrorTypeInsert(t *testing.T) { test_helpers.SkipIfErrorMessagePackTypeUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() truncateEval := fmt.Sprintf("box.space[%q]:truncate()", space) @@ -374,7 +374,7 @@ func TestErrorTypeInsert(t *testing.T) { func TestErrorTypeInsertTyped(t *testing.T) { test_helpers.SkipIfErrorMessagePackTypeUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() truncateEval := fmt.Sprintf("box.space[%q]:truncate()", space) @@ -416,7 +416,7 @@ func TestErrorTypeInsertTyped(t *testing.T) { func TestErrorTypeSelect(t *testing.T) { test_helpers.SkipIfErrorMessagePackTypeUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() truncateEval := fmt.Sprintf("box.space[%q]:truncate()", space) @@ -461,7 +461,7 @@ func TestErrorTypeSelect(t *testing.T) { func TestErrorTypeSelectTyped(t *testing.T) { test_helpers.SkipIfErrorMessagePackTypeUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() truncateEval := fmt.Sprintf("box.space[%q]:truncate()", space) diff --git a/connection_test.go b/connection_test.go deleted file mode 100644 index 20d06b183..000000000 --- a/connection_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package tarantool_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - "github.com/tarantool/go-iproto" - - . "github.com/tarantool/go-tarantool/v2" -) - -func TestOptsClonePreservesRequiredProtocolFeatures(t *testing.T) { - original := Opts{ - RequiredProtocolInfo: ProtocolInfo{ - Version: ProtocolVersion(100), - Features: []iproto.Feature{iproto.Feature(99), iproto.Feature(100)}, - }, - } - - origCopy := original.Clone() - - original.RequiredProtocolInfo.Features[1] = iproto.Feature(98) - - require.Equal(t, - origCopy, - Opts{ - RequiredProtocolInfo: ProtocolInfo{ - Version: ProtocolVersion(100), - Features: []iproto.Feature{iproto.Feature(99), iproto.Feature(100)}, - }, - }) -} diff --git a/crud/example_test.go b/crud/example_test.go index 763ab5deb..e6820057f 100644 --- a/crud/example_test.go +++ b/crud/example_test.go @@ -17,14 +17,18 @@ const ( var exampleOpts = tarantool.Opts{ Timeout: 5 * time.Second, - User: "test", - Pass: "test", +} + +var exampleDialer = tarantool.TtDialer{ + Address: exampleServer, + User: "test", + Password: "test", } func exampleConnect() *tarantool.Connection { ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) defer cancel() - conn, err := tarantool.Connect(ctx, exampleServer, exampleOpts) + conn, err := tarantool.Connect(ctx, exampleDialer, exampleOpts) if err != nil { panic("Connection is not established: " + err.Error()) } diff --git a/crud/tarantool_test.go b/crud/tarantool_test.go index 511980bd9..1b24fcdac 100644 --- a/crud/tarantool_test.go +++ b/crud/tarantool_test.go @@ -21,17 +21,20 @@ var spaceName = "test" var invalidSpaceName = "invalid" var indexNo = uint32(0) var indexName = "primary_index" + +var dialer = tarantool.TtDialer{ + Address: server, + User: "test", + Password: "test", +} + var opts = tarantool.Opts{ Timeout: 5 * time.Second, - User: "test", - Pass: "test", } var startOpts test_helpers.StartOpts = test_helpers.StartOpts{ InitScript: "testdata/config.lua", Listen: server, - User: opts.User, - Pass: opts.Pass, WaitStart: 100 * time.Millisecond, ConnectRetry: 10, RetryTimeout: 500 * time.Millisecond, @@ -109,7 +112,7 @@ var object = crud.MapObject{ func connect(t testing.TB) *tarantool.Connection { for i := 0; i < 10; i++ { ctx, cancel := test_helpers.GetConnectContext() - conn, err := tarantool.Connect(ctx, server, opts) + conn, err := tarantool.Connect(ctx, dialer, opts) cancel() if err != nil { t.Fatalf("Failed to connect: %s", err) @@ -1339,7 +1342,7 @@ func TestUnitEmptySchema(t *testing.T) { // is a separate function, see // https://stackoverflow.com/questions/27629380/how-to-exit-a-go-program-honoring-deferred-calls func runTestMain(m *testing.M) int { - inst, err := test_helpers.StartTarantool(startOpts) + inst, err := test_helpers.StartTarantool(startOpts, dialer) defer test_helpers.StopTarantoolWithCleanup(inst) if err != nil { diff --git a/datetime/datetime_test.go b/datetime/datetime_test.go index 858c7b84a..7488fca10 100644 --- a/datetime/datetime_test.go +++ b/datetime/datetime_test.go @@ -40,8 +40,11 @@ var isDatetimeSupported = false var server = "127.0.0.1:3013" var opts = Opts{ Timeout: 5 * time.Second, - User: "test", - Pass: "test", +} +var dialer = TtDialer{ + Address: server, + User: "test", + Password: "test", } var spaceTuple1 = "testDatetime_1" @@ -364,7 +367,7 @@ func TestDatetimeInterval(t *testing.T) { func TestDatetimeTarantoolInterval(t *testing.T) { skipIfDatetimeUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() dates := []string{ @@ -504,7 +507,7 @@ func TestInvalidOffset(t *testing.T) { t.Fatalf("Unexpected success: %v", dt) } if testcase.ok && isDatetimeSupported { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() tupleInsertSelectDelete(t, conn, tm) @@ -516,7 +519,7 @@ func TestInvalidOffset(t *testing.T) { func TestCustomTimezone(t *testing.T) { skipIfDatetimeUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() customZone := "Europe/Moscow" @@ -676,7 +679,7 @@ var datetimeSample = []struct { func TestDatetimeInsertSelectDelete(t *testing.T) { skipIfDatetimeUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() for _, testcase := range datetimeSample { @@ -705,7 +708,7 @@ func TestDatetimeInsertSelectDelete(t *testing.T) { func TestDatetimeBoundaryRange(t *testing.T) { skipIfDatetimeUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() for _, tm := range append(lesserBoundaryTimes, boundaryTimes...) { @@ -731,7 +734,7 @@ func TestDatetimeOutOfRange(t *testing.T) { func TestDatetimeReplace(t *testing.T) { skipIfDatetimeUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() tm, err := time.Parse(time.RFC3339, "2007-01-02T15:04:05Z") @@ -896,7 +899,7 @@ func (c *Tuple2) DecodeMsgpack(d *msgpack.Decoder) error { func TestCustomEncodeDecodeTuple1(t *testing.T) { skipIfDatetimeUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() tm1, _ := time.Parse(time.RFC3339, "2010-05-24T17:51:56.000000009Z") @@ -966,7 +969,7 @@ func TestCustomEncodeDecodeTuple1(t *testing.T) { func TestCustomDecodeFunction(t *testing.T) { skipIfDatetimeUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() // Call function 'call_datetime_testdata' returning a custom tuples. @@ -1010,7 +1013,7 @@ func TestCustomDecodeFunction(t *testing.T) { func TestCustomEncodeDecodeTuple5(t *testing.T) { skipIfDatetimeUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() tm := time.Unix(500, 1000).In(time.FixedZone(NoTimezone, 0)) @@ -1168,12 +1171,10 @@ func runTestMain(m *testing.M) int { instance, err := test_helpers.StartTarantool(test_helpers.StartOpts{ InitScript: "config.lua", Listen: server, - User: opts.User, - Pass: opts.Pass, WaitStart: 100 * time.Millisecond, ConnectRetry: 10, RetryTimeout: 500 * time.Millisecond, - }) + }, dialer) defer test_helpers.StopTarantoolWithCleanup(instance) if err != nil { diff --git a/datetime/example_test.go b/datetime/example_test.go index 954f43548..682281154 100644 --- a/datetime/example_test.go +++ b/datetime/example_test.go @@ -20,13 +20,13 @@ import ( // Example demonstrates how to use tuples with datetime. To enable support of // datetime import tarantool/datetime package. func Example() { - opts := tarantool.Opts{ - User: "test", - Pass: "test", + dialer := tarantool.TtDialer{ + Address: "127.0.0.1:3013", } + opts := tarantool.Opts{} ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) defer cancel() - conn, err := tarantool.Connect(ctx, "127.0.0.1:3013", opts) + conn, err := tarantool.Connect(ctx, dialer, opts) if err != nil { fmt.Printf("Error in connect is %v", err) return diff --git a/datetime/interval_test.go b/datetime/interval_test.go index ae42e92c7..4e3cf5ab1 100644 --- a/datetime/interval_test.go +++ b/datetime/interval_test.go @@ -105,7 +105,7 @@ func TestIntervalSub(t *testing.T) { func TestIntervalTarantoolEncoding(t *testing.T) { skipIfDatetimeUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() cases := []Interval{ diff --git a/decimal/decimal_test.go b/decimal/decimal_test.go index 57c70d1d7..bab70b3ae 100644 --- a/decimal/decimal_test.go +++ b/decimal/decimal_test.go @@ -20,10 +20,13 @@ import ( var isDecimalSupported = false var server = "127.0.0.1:3013" +var dialer = TtDialer{ + Address: server, + User: "test", + Password: "test", +} var opts = Opts{ Timeout: 5 * time.Second, - User: "test", - Pass: "test", } func skipIfDecimalUnsupported(t *testing.T) { @@ -526,7 +529,7 @@ func BenchmarkDecodeStringFromBCD(b *testing.B) { func TestSelect(t *testing.T) { skipIfDecimalUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() number, err := decimal.NewFromString("-12.34") @@ -572,7 +575,7 @@ func TestSelect(t *testing.T) { func TestUnmarshal_from_decimal_new(t *testing.T) { skipIfDecimalUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() samples := correctnessSamples @@ -627,7 +630,7 @@ func assertInsert(t *testing.T, conn *Connection, numString string) { func TestInsert(t *testing.T) { skipIfDecimalUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() samples := correctnessSamples @@ -642,7 +645,7 @@ func TestInsert(t *testing.T) { func TestReplace(t *testing.T) { skipIfDecimalUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() number, err := decimal.NewFromString("-12.34") @@ -697,12 +700,10 @@ func runTestMain(m *testing.M) int { instance, err := test_helpers.StartTarantool(test_helpers.StartOpts{ InitScript: "config.lua", Listen: server, - User: opts.User, - Pass: opts.Pass, WaitStart: 100 * time.Millisecond, ConnectRetry: 10, RetryTimeout: 500 * time.Millisecond, - }) + }, dialer) defer test_helpers.StopTarantoolWithCleanup(instance) if err != nil { diff --git a/decimal/example_test.go b/decimal/example_test.go index f1984283c..873bbc77b 100644 --- a/decimal/example_test.go +++ b/decimal/example_test.go @@ -22,13 +22,16 @@ import ( // import tarantool/decimal submodule. func Example() { server := "127.0.0.1:3013" + dialer := tarantool.TtDialer{ + Address: server, + User: "test", + Password: "test", + } opts := tarantool.Opts{ Timeout: 5 * time.Second, - User: "test", - Pass: "test", } ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) - client, err := tarantool.Connect(ctx, server, opts) + client, err := tarantool.Connect(ctx, dialer, opts) cancel() if err != nil { log.Fatalf("Failed to connect: %s", err.Error()) diff --git a/dial_test.go b/dial_test.go index 209fc50cd..f55434c16 100644 --- a/dial_test.go +++ b/dial_test.go @@ -5,6 +5,7 @@ import ( "context" "errors" "fmt" + "io" "net" "strings" "sync" @@ -14,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tarantool/go-iproto" + "github.com/tarantool/go-openssl" "github.com/tarantool/go-tarantool/v2" "github.com/tarantool/go-tarantool/v2/test_helpers" @@ -23,7 +25,7 @@ type mockErrorDialer struct { err error } -func (m mockErrorDialer) Dial(ctx context.Context, address string, +func (m mockErrorDialer) Dial(ctx context.Context, opts tarantool.DialOpts) (tarantool.Conn, error) { return nil, m.err } @@ -36,22 +38,18 @@ func TestDialer_Dial_error(t *testing.T) { ctx, cancel := test_helpers.GetConnectContext() defer cancel() - conn, err := tarantool.Connect(ctx, "any", tarantool.Opts{ - Dialer: dialer, - }) + conn, err := tarantool.Connect(ctx, dialer, tarantool.Opts{}) assert.Nil(t, conn) assert.ErrorContains(t, err, errMsg) } type mockPassedDialer struct { - ctx context.Context - address string - opts tarantool.DialOpts + ctx context.Context + opts tarantool.DialOpts } -func (m *mockPassedDialer) Dial(ctx context.Context, address string, +func (m *mockPassedDialer) Dial(ctx context.Context, opts tarantool.DialOpts) (tarantool.Conn, error) { - m.address = address m.opts = opts if ctx != m.ctx { return nil, errors.New("wrong context") @@ -60,53 +58,30 @@ func (m *mockPassedDialer) Dial(ctx context.Context, address string, } func TestDialer_Dial_passedOpts(t *testing.T) { - const addr = "127.0.0.1:8080" - opts := tarantool.DialOpts{ - IoTimeout: 2, - Transport: "any", - Ssl: tarantool.SslOpts{ - KeyFile: "a", - CertFile: "b", - CaFile: "c", - Ciphers: "d", - }, - RequiredProtocol: tarantool.ProtocolInfo{ - Auth: tarantool.ChapSha1Auth, - Version: 33, - Features: []iproto.Feature{ - iproto.IPROTO_FEATURE_ERROR_EXTENSION, - }, - }, - Auth: tarantool.ChapSha1Auth, - User: "user", - Password: "password", - } - dialer := &mockPassedDialer{} + ctx, cancel := test_helpers.GetConnectContext() defer cancel() - dialer.ctx = ctx - conn, err := tarantool.Connect(ctx, addr, tarantool.Opts{ - Dialer: dialer, - Timeout: opts.IoTimeout, - Transport: opts.Transport, - Ssl: opts.Ssl, - Auth: opts.Auth, - User: opts.User, - Pass: opts.Password, - RequiredProtocolInfo: opts.RequiredProtocol, + dialOpts := tarantool.DialOpts{ + IoTimeout: opts.Timeout, + } + + conn, err := tarantool.Connect(ctx, dialer, tarantool.Opts{ + Timeout: opts.Timeout, }) assert.Nil(t, conn) assert.NotNil(t, err) assert.NotEqual(t, err.Error(), "wrong context") - assert.Equal(t, addr, dialer.address) - assert.Equal(t, opts, dialer.opts) + assert.Equal(t, dialOpts, dialer.opts) } type mockIoConn struct { + addr net.Addr + // Addr calls count. + addrCnt int // Sends an event on Read()/Write()/Flush(). read, written chan struct{} // Read()/Write() buffers. @@ -117,12 +92,8 @@ type mockIoConn struct { readWgDelay, writeWgDelay int // Write()/Read()/Flush()/Close() calls count. writeCnt, readCnt, flushCnt, closeCnt int - // LocalAddr()/RemoteAddr() calls count. - localCnt, remoteCnt int // Greeting()/ProtocolInfo() calls count. greetingCnt, infoCnt int - // Values for LocalAddr()/RemoteAddr(). - local, remote net.Addr // Value for Greeting(). greeting tarantool.Greeting // Value for ProtocolInfo(). @@ -171,16 +142,6 @@ func (m *mockIoConn) Close() error { return nil } -func (m *mockIoConn) LocalAddr() net.Addr { - m.localCnt++ - return m.local -} - -func (m *mockIoConn) RemoteAddr() net.Addr { - m.remoteCnt++ - return m.remote -} - func (m *mockIoConn) Greeting() tarantool.Greeting { m.greetingCnt++ return m.greeting @@ -191,6 +152,11 @@ func (m *mockIoConn) ProtocolInfo() tarantool.ProtocolInfo { return m.info } +func (m *mockIoConn) Addr() net.Addr { + m.addrCnt++ + return m.addr +} + type mockIoDialer struct { init func(conn *mockIoConn) conn *mockIoConn @@ -203,8 +169,7 @@ func newMockIoConn() *mockIoConn { return conn } -func (m *mockIoDialer) Dial(ctx context.Context, address string, - opts tarantool.DialOpts) (tarantool.Conn, error) { +func (m *mockIoDialer) Dial(ctx context.Context, opts tarantool.DialOpts) (tarantool.Conn, error) { m.conn = newMockIoConn() if m.init != nil { m.init(m.conn) @@ -221,9 +186,8 @@ func dialIo(t *testing.T, } ctx, cancel := test_helpers.GetConnectContext() defer cancel() - conn, err := tarantool.Connect(ctx, "any", + conn, err := tarantool.Connect(ctx, &dialer, tarantool.Opts{ - Dialer: &dialer, Timeout: 1000 * time.Second, // Avoid pings. SkipSchema: true, }) @@ -244,7 +208,6 @@ func TestConn_Close(t *testing.T) { } type stubAddr struct { - net.Addr str string } @@ -252,25 +215,14 @@ func (a stubAddr) String() string { return a.str } -func TestConn_LocalAddr(t *testing.T) { - const addr = "any" - conn, dialer := dialIo(t, func(conn *mockIoConn) { - conn.local = stubAddr{str: addr} - }) - defer func() { - dialer.conn.readWg.Done() - dialer.conn.writeWg.Done() - conn.Close() - }() - - assert.Equal(t, addr, conn.LocalAddr()) - assert.Equal(t, 1, dialer.conn.localCnt) +func (a stubAddr) Network() string { + return "stub" } -func TestConn_RemoteAddr(t *testing.T) { +func TestConn_Addr(t *testing.T) { const addr = "any" conn, dialer := dialIo(t, func(conn *mockIoConn) { - conn.remote = stubAddr{str: addr} + conn.addr = stubAddr{str: addr} }) defer func() { dialer.conn.readWg.Done() @@ -278,8 +230,8 @@ func TestConn_RemoteAddr(t *testing.T) { conn.Close() }() - assert.Equal(t, addr, conn.RemoteAddr()) - assert.Equal(t, 1, dialer.conn.remoteCnt) + assert.Equal(t, addr, conn.Addr().String()) + assert.Equal(t, 1, dialer.conn.addrCnt) } func TestConn_Greeting(t *testing.T) { @@ -316,7 +268,7 @@ func TestConn_ProtocolInfo(t *testing.T) { conn.Close() }() - assert.Equal(t, info, conn.ServerProtocolInfo()) + assert.Equal(t, info, conn.ProtocolInfo()) assert.Equal(t, 1, dialer.conn.infoCnt) } @@ -359,13 +311,11 @@ func TestConn_ReadWrite(t *testing.T) { } func TestConn_ContextCancel(t *testing.T) { - const addr = "127.0.0.1:8080" - - dialer := tarantool.TtDialer{} + dialer := tarantool.TtDialer{Address: "127.0.0.1:8080"} ctx, cancel := context.WithCancel(context.Background()) cancel() - conn, err := dialer.Dial(ctx, addr, tarantool.DialOpts{}) + conn, err := dialer.Dial(ctx, tarantool.DialOpts{}) assert.Nil(t, conn) assert.NotNil(t, err) @@ -373,3 +323,246 @@ func TestConn_ContextCancel(t *testing.T) { fmt.Sprintf("unexpected error, expected to contain %s, got %v", "operation was canceled", err)) } + +func genSalt() [64]byte { + salt := [64]byte{} + for i := 0; i < 44; i++ { + salt[i] = 'a' + } + return salt +} + +var ( + testDialUser = "test" + testDialPass = "test" + testDialVersion = [64]byte{'t', 'e', 's', 't'} + + // Salt with end zeros. + testDialSalt = genSalt() + + idRequestExpected = []byte{ + 0xce, 0x00, 0x00, 0x00, 28, // Length. + 0x82, // Header map. + 0x00, 0x49, + 0x01, 0xce, 0x00, 0x00, 0x00, 0x00, + + 0x82, // Data map. + 0x54, + 0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, // Version. + 0x55, + 0x96, 0x00, 0x01, 0x02, 0x03, 0x04, 0x06, // Features. + } + + idResponseTyped = tarantool.ProtocolInfo{ + Version: 6, + Features: []iproto.Feature{iproto.Feature(1), iproto.Feature(21)}, + Auth: tarantool.ChapSha1Auth, + } + + idResponse = []byte{ + 0xce, 0x00, 0x00, 0x00, 37, // Length. + 0x83, // Header map. + 0x00, 0xce, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xce, 0x00, 0x00, 0x00, 0x00, + 0x05, 0xce, 0x00, 0x00, 0x00, 0x61, + + 0x83, // Data map. + 0x54, + 0x06, // Version. + 0x55, + 0x92, 0x01, 0x15, // Features. + 0x5b, + 0xa9, 'c', 'h', 'a', 'p', '-', 's', 'h', 'a', '1', + } + + idResponseNotSupported = []byte{ + 0xce, 0x00, 0x00, 0x00, 25, // Length. + 0x83, // Header map. + 0x00, 0xce, 0x00, 0x00, 0x80, 0x30, + 0x01, 0xce, 0x00, 0x00, 0x00, 0x00, + 0x05, 0xce, 0x00, 0x00, 0x00, 0x61, + 0x81, + 0x31, + 0xa3, 'e', 'r', 'r', + } + + authRequestExpected = []byte{ + 0xce, 0x00, 0x00, 0x00, 57, // Length. + 0x82, // Header map. + 0x00, 0x07, + 0x01, 0xce, 0x00, 0x00, 0x00, 0x00, + + 0x82, // Data map. + 0xce, 0x00, 0x00, 0x00, 0x23, + 0xa4, 't', 'e', 's', 't', // Login. + 0xce, 0x00, 0x00, 0x00, 0x21, + 0x92, // Tuple. + 0xa9, 'c', 'h', 'a', 'p', '-', 's', 'h', 'a', '1', + + // Scramble. + 0xb4, 0x1b, 0xd4, 0x20, 0x45, 0x73, 0x22, + 0xcf, 0xab, 0x05, 0x03, 0xf3, 0x89, 0x4b, + 0xfe, 0xc7, 0x24, 0x5a, 0xe6, 0xe8, 0x31, + } + + okResponse = []byte{ + 0xce, 0x00, 0x00, 0x00, 19, // Length. + 0x83, // Header map. + 0x00, 0xce, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xce, 0x00, 0x00, 0x00, 0x00, + 0x05, 0xce, 0x00, 0x00, 0x00, 0x61, + } + + errResponse = []byte{0xce} +) + +func assertRequest(t *testing.T, r io.Reader, expected []byte) { + t.Helper() + actual := make([]byte, len(expected)) + _, err := r.Read(actual) + require.NoError(t, err) + require.Equal(t, expected, actual) +} + +type testDialOpts struct { + errGreeting bool + errId bool + errAuth bool + idUnsupported bool +} + +func testDialAccept(t *testing.T, ch chan struct{}, opts testDialOpts, l net.Listener) { + defer close(ch) + client, err := l.Accept() + if err != nil { + t.Errorf("server got unexpected error: %v", err) + return + } + if opts.errGreeting { + client.Write(errResponse) + return + } else { + // Write greeting. + client.Write(testDialVersion[:]) + client.Write(testDialSalt[:]) + } + + // Check Id request. + assertRequest(t, client, idRequestExpected) + if opts.errId { + client.Write(errResponse) + return + } else if opts.idUnsupported { + client.Write(idResponseNotSupported) + } else { + client.Write(idResponse) + } + + // Check Auth request. + assertRequest(t, client, authRequestExpected) + if opts.errAuth { + client.Write(errResponse) + return + } else { + client.Write(okResponse) + } +} + +var testDialCases = []struct { + name string + opts testDialOpts + wantErr bool + protocolInfo tarantool.ProtocolInfo + version []byte +}{ + { + name: "all is ok", + opts: testDialOpts{}, + protocolInfo: idResponseTyped.Clone(), + version: testDialVersion[:], + }, + { + name: "id request unsupported", + opts: testDialOpts{idUnsupported: true}, + protocolInfo: tarantool.ProtocolInfo{}, + version: testDialVersion[:], + }, + { + name: "greeting response error", + opts: testDialOpts{errGreeting: true}, + wantErr: true, + }, + { + name: "id response error", + opts: testDialOpts{errId: true}, + wantErr: true, + }, + { + name: "auth response error", + opts: testDialOpts{errAuth: true}, + wantErr: true, + }, +} + +func testDialer(t *testing.T, + l net.Listener, dialer tarantool.Dialer) { + for _, cs := range testDialCases { + t.Run(cs.name, func(t *testing.T) { + ch := make(chan struct{}) + go testDialAccept(t, ch, cs.opts, l) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + conn, err := dialer.Dial(ctx, tarantool.DialOpts{ + IoTimeout: time.Second * 2, + }) + <-ch + if cs.wantErr { + require.Error(t, err) + return + } + require.NoError(t, err) + require.Equal(t, cs.protocolInfo, conn.ProtocolInfo()) + require.Equal(t, cs.version, []byte(conn.Greeting().Version)) + conn.Close() + }) + } +} + +func TestTtDialer_Dial(t *testing.T) { + l, err := net.Listen("tcp", "127.0.0.1:0") + require.NoError(t, err) + dialer := tarantool.TtDialer{ + Address: l.Addr().String(), + User: testDialUser, + Password: testDialPass, + } + testDialer(t, l, dialer) +} + +func TestOpenSslDialer_Dial(t *testing.T) { + ctx, err := tarantool.SslCreateContext("testdata/localhost.key", + "testdata/localhost.crt", "", "", "", "") + require.NoError(t, err) + l, err := openssl.Listen("tcp", "127.0.0.1:0", ctx.(*openssl.Ctx)) + require.NoError(t, err) + addr := l.Addr().String() + + dialers := []tarantool.Dialer{ + tarantool.OpenSslDialer{ + Address: addr, + User: testDialUser, + Password: testDialPass, + }, + tarantool.OpenSslDialer{ + Address: addr, + User: testDialUser, + Password: testDialPass, + KeyFile: "testdata/localhost.key", + CertFile: "testdata/localhost.crt", + }, + } + + for _, dialer := range dialers { + testDialer(t, l, dialer) + } +} diff --git a/example_custom_unpacking_test.go b/example_custom_unpacking_test.go index 8fb243db0..44f0171d2 100644 --- a/example_custom_unpacking_test.go +++ b/example_custom_unpacking_test.go @@ -78,13 +78,15 @@ func (c *Tuple2) DecodeMsgpack(d *msgpack.Decoder) error { func Example_customUnpacking() { // Establish a connection. server := "127.0.0.1:3013" - opts := tarantool.Opts{ - Timeout: 500 * time.Millisecond, - User: "test", - Pass: "test", + + dialer := tarantool.TtDialer{ + Address: server, + User: "test", + Password: "test", } + opts := tarantool.Opts{} ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) - conn, err := tarantool.Connect(ctx, server, opts) + conn, err := tarantool.Connect(ctx, dialer, opts) cancel() if err != nil { log.Fatalf("Failed to connect: %s", err.Error()) diff --git a/example_test.go b/example_test.go index f85f532d0..840a7741d 100644 --- a/example_test.go +++ b/example_test.go @@ -20,10 +20,10 @@ type Tuple struct { Name string } -func exampleConnect(opts tarantool.Opts) *tarantool.Connection { +func exampleConnect(dialer tarantool.Dialer, opts tarantool.Opts) *tarantool.Connection { ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) defer cancel() - conn, err := tarantool.Connect(ctx, server, opts) + conn, err := tarantool.Connect(ctx, dialer, opts) if err != nil { panic("Connection is not established: " + err.Error()) } @@ -31,27 +31,25 @@ func exampleConnect(opts tarantool.Opts) *tarantool.Connection { } // Example demonstrates how to use SSL transport. -func ExampleSslOpts() { - var opts = tarantool.Opts{ - User: "test", - Pass: "test", - Transport: "ssl", - Ssl: tarantool.SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - }, +func ExampleOpenSslDialer() { + sslDialer := tarantool.OpenSslDialer{ + Address: "127.0.0.1:3013", + User: "test", + Password: "test", + KeyFile: "testdata/localhost.key", + CertFile: "testdata/localhost.crt", + CaFile: "testdata/ca.crt", } ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) defer cancel() - _, err := tarantool.Connect(ctx, "127.0.0.1:3013", opts) + _, err := tarantool.Connect(ctx, sslDialer, opts) if err != nil { panic("Connection is not established: " + err.Error()) } } func ExampleIntKey() { - conn := exampleConnect(opts) + conn := exampleConnect(dialer, opts) defer conn.Close() const space = "test" @@ -73,7 +71,7 @@ func ExampleIntKey() { } func ExampleUintKey() { - conn := exampleConnect(opts) + conn := exampleConnect(dialer, opts) defer conn.Close() const space = "test" @@ -95,7 +93,7 @@ func ExampleUintKey() { } func ExampleStringKey() { - conn := exampleConnect(opts) + conn := exampleConnect(dialer, opts) defer conn.Close() const space = "teststring" @@ -120,7 +118,7 @@ func ExampleStringKey() { } func ExampleIntIntKey() { - conn := exampleConnect(opts) + conn := exampleConnect(dialer, opts) defer conn.Close() const space = "testintint" @@ -146,7 +144,7 @@ func ExampleIntIntKey() { } func ExamplePingRequest() { - conn := exampleConnect(opts) + conn := exampleConnect(dialer, opts) defer conn.Close() // Ping a Tarantool instance to check connection. @@ -166,7 +164,7 @@ func ExamplePingRequest() { // of the request. For those purposes use context.WithTimeout() as // the root context. func ExamplePingRequest_Context() { - conn := exampleConnect(opts) + conn := exampleConnect(dialer, opts) defer conn.Close() timeout := time.Nanosecond @@ -191,7 +189,7 @@ func ExamplePingRequest_Context() { } func ExampleSelectRequest() { - conn := exampleConnect(opts) + conn := exampleConnect(dialer, opts) defer conn.Close() for i := 1111; i <= 1112; i++ { @@ -232,7 +230,7 @@ func ExampleSelectRequest() { } func ExampleInsertRequest() { - conn := exampleConnect(opts) + conn := exampleConnect(dialer, opts) defer conn.Close() // Insert a new tuple { 31, 1 }. @@ -274,7 +272,7 @@ func ExampleInsertRequest() { } func ExampleDeleteRequest() { - conn := exampleConnect(opts) + conn := exampleConnect(dialer, opts) defer conn.Close() // Insert a new tuple { 35, 1 }. @@ -317,7 +315,7 @@ func ExampleDeleteRequest() { } func ExampleReplaceRequest() { - conn := exampleConnect(opts) + conn := exampleConnect(dialer, opts) defer conn.Close() // Insert a new tuple { 13, 1 }. @@ -376,7 +374,7 @@ func ExampleReplaceRequest() { } func ExampleUpdateRequest() { - conn := exampleConnect(opts) + conn := exampleConnect(dialer, opts) defer conn.Close() for i := 1111; i <= 1112; i++ { @@ -412,7 +410,7 @@ func ExampleUpdateRequest() { } func ExampleUpsertRequest() { - conn := exampleConnect(opts) + conn := exampleConnect(dialer, opts) defer conn.Close() var req tarantool.Request @@ -453,7 +451,7 @@ func ExampleUpsertRequest() { } func ExampleCallRequest() { - conn := exampleConnect(opts) + conn := exampleConnect(dialer, opts) defer conn.Close() // Call a function 'simple_concat' with arguments. @@ -472,7 +470,7 @@ func ExampleCallRequest() { } func ExampleEvalRequest() { - conn := exampleConnect(opts) + conn := exampleConnect(dialer, opts) defer conn.Close() // Run raw Lua code. @@ -500,7 +498,7 @@ func ExampleExecuteRequest() { return } - conn := exampleConnect(opts) + conn := exampleConnect(dialer, opts) defer conn.Close() req := tarantool.NewExecuteRequest( @@ -618,30 +616,11 @@ func ExampleExecuteRequest() { fmt.Println("SQL Info", resp.SQLInfo) } -func ExampleProtocolVersion() { - conn := exampleConnect(opts) - defer conn.Close() - - clientProtocolInfo := conn.ClientProtocolInfo() - fmt.Println("Connector client protocol version:", clientProtocolInfo.Version) - for _, f := range clientProtocolInfo.Features { - fmt.Println("Connector client protocol feature:", f) - } - // Output: - // Connector client protocol version: 6 - // Connector client protocol feature: IPROTO_FEATURE_STREAMS - // Connector client protocol feature: IPROTO_FEATURE_TRANSACTIONS - // Connector client protocol feature: IPROTO_FEATURE_ERROR_EXTENSION - // Connector client protocol feature: IPROTO_FEATURE_WATCHERS - // Connector client protocol feature: IPROTO_FEATURE_PAGINATION - // Connector client protocol feature: IPROTO_FEATURE_WATCH_ONCE -} - -func getTestTxnOpts() tarantool.Opts { - txnOpts := opts.Clone() +func getTestTxnDialer() tarantool.Dialer { + txnDialer := dialer - // Assert that server supports expected protocol features - txnOpts.RequiredProtocolInfo = tarantool.ProtocolInfo{ + // Assert that server supports expected protocol features. + txnDialer.RequiredProtocolInfo = tarantool.ProtocolInfo{ Version: tarantool.ProtocolVersion(1), Features: []iproto.Feature{ iproto.IPROTO_FEATURE_STREAMS, @@ -649,7 +628,7 @@ func getTestTxnOpts() tarantool.Opts { }, } - return txnOpts + return txnDialer } func ExampleCommitRequest() { @@ -663,8 +642,8 @@ func ExampleCommitRequest() { return } - txnOpts := getTestTxnOpts() - conn := exampleConnect(txnOpts) + txnDialer := getTestTxnDialer() + conn := exampleConnect(txnDialer, opts) defer conn.Close() stream, _ := conn.NewStream() @@ -740,8 +719,8 @@ func ExampleRollbackRequest() { return } - txnOpts := getTestTxnOpts() - conn := exampleConnect(txnOpts) + txnDialer := getTestTxnDialer() + conn := exampleConnect(txnDialer, opts) defer conn.Close() stream, _ := conn.NewStream() @@ -817,8 +796,8 @@ func ExampleBeginRequest_TxnIsolation() { return } - txnOpts := getTestTxnOpts() - conn := exampleConnect(txnOpts) + txnDialer := getTestTxnDialer() + conn := exampleConnect(txnDialer, opts) defer conn.Close() stream, _ := conn.NewStream() @@ -886,7 +865,7 @@ func ExampleBeginRequest_TxnIsolation() { } func ExampleFuture_GetIterator() { - conn := exampleConnect(opts) + conn := exampleConnect(dialer, opts) defer conn.Close() const timeout = 3 * time.Second @@ -923,10 +902,14 @@ func ExampleConnect() { ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) defer cancel() - conn, err := tarantool.Connect(ctx, "127.0.0.1:3013", tarantool.Opts{ + dialer := tarantool.TtDialer{ + Address: server, + User: "test", + Password: "test", + } + + conn, err := tarantool.Connect(ctx, dialer, tarantool.Opts{ Timeout: 5 * time.Second, - User: "test", - Pass: "test", Concurrency: 32, }) if err != nil { @@ -942,10 +925,14 @@ func ExampleConnect() { } func ExampleConnect_reconnects() { + dialer := tarantool.TtDialer{ + Address: "127.0.0.1:3013", + User: "test", + Password: "test", + } + opts := tarantool.Opts{ Timeout: 5 * time.Second, - User: "test", - Pass: "test", Concurrency: 32, Reconnect: time.Second, MaxReconnects: 10, @@ -956,7 +943,7 @@ func ExampleConnect_reconnects() { for i := uint(0); i < opts.MaxReconnects; i++ { ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) - conn, err = tarantool.Connect(ctx, "127.0.0.1:3013", opts) + conn, err = tarantool.Connect(ctx, dialer, opts) cancel() if err == nil { break @@ -977,7 +964,7 @@ func ExampleConnect_reconnects() { // Example demonstrates how to retrieve information with space schema. func ExampleSchema() { - conn := exampleConnect(opts) + conn := exampleConnect(dialer, opts) defer conn.Close() schema := conn.Schema @@ -999,7 +986,7 @@ func ExampleSchema() { // Example demonstrates how to retrieve information with space schema. func ExampleSpace() { - conn := exampleConnect(opts) + conn := exampleConnect(dialer, opts) defer conn.Close() // Save Schema to a local variable to avoid races @@ -1045,7 +1032,7 @@ func ExampleSpace() { // ExampleConnection_Do demonstrates how to send a request and process // a response. func ExampleConnection_Do() { - conn := exampleConnect(opts) + conn := exampleConnect(dialer, opts) defer conn.Close() // It could be any request. @@ -1072,7 +1059,7 @@ func ExampleConnection_Do() { // ExampleConnection_Do_failure demonstrates how to send a request and process // failure. func ExampleConnection_Do_failure() { - conn := exampleConnect(opts) + conn := exampleConnect(dialer, opts) defer conn.Close() // It could be any request. @@ -1120,14 +1107,17 @@ func ExampleConnection_NewPrepared() { } server := "127.0.0.1:3013" + dialer := tarantool.TtDialer{ + Address: server, + User: "test", + Password: "test", + } opts := tarantool.Opts{ Timeout: 5 * time.Second, - User: "test", - Pass: "test", } ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) defer cancel() - conn, err := tarantool.Connect(ctx, server, opts) + conn, err := tarantool.Connect(ctx, dialer, opts) if err != nil { fmt.Printf("Failed to connect: %s", err.Error()) } @@ -1162,20 +1152,24 @@ func ExampleConnection_NewWatcher() { } server := "127.0.0.1:3013" + dialer := tarantool.TtDialer{ + Address: server, + User: "test", + Password: "test", + // You can require the feature explicitly. + RequiredProtocolInfo: tarantool.ProtocolInfo{ + Features: []iproto.Feature{iproto.IPROTO_FEATURE_WATCHERS}, + }, + } + opts := tarantool.Opts{ Timeout: 5 * time.Second, Reconnect: 5 * time.Second, MaxReconnects: 3, - User: "test", - Pass: "test", - // You need to require the feature to create a watcher. - RequiredProtocolInfo: tarantool.ProtocolInfo{ - Features: []iproto.Feature{iproto.IPROTO_FEATURE_WATCHERS}, - }, } ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) defer cancel() - conn, err := tarantool.Connect(ctx, server, opts) + conn, err := tarantool.Connect(ctx, dialer, opts) if err != nil { fmt.Printf("Failed to connect: %s\n", err) return @@ -1201,7 +1195,7 @@ func ExampleConnection_NewWatcher() { // ExampleConnection_CloseGraceful_force demonstrates how to force close // a connection with graceful close in progress after a while. func ExampleConnection_CloseGraceful_force() { - conn := exampleConnect(opts) + conn := exampleConnect(dialer, opts) eval := `local fiber = require('fiber') local time = ... @@ -1244,7 +1238,7 @@ func ExampleWatchOnceRequest() { return } - conn := exampleConnect(opts) + conn := exampleConnect(dialer, opts) defer conn.Close() conn.Do(tarantool.NewBroadcastRequest(key).Value(value)).Get() diff --git a/export_test.go b/export_test.go index 38211a4fc..555803923 100644 --- a/export_test.go +++ b/export_test.go @@ -1,20 +1,21 @@ package tarantool import ( - "context" - "net" "time" "github.com/vmihailenco/msgpack/v5" ) -func SslDialContext(ctx context.Context, network, address string, - opts SslOpts) (connection net.Conn, err error) { - return sslDialContext(ctx, network, address, opts) -} - -func SslCreateContext(opts SslOpts) (ctx interface{}, err error) { - return sslCreateContext(opts) +func SslCreateContext(keyFile, certFile, caFile, ciphers, password, + passwordFile string) (ctx interface{}, err error) { + return sslCreateContext(sslOpts{ + keyFile: keyFile, + certFile: certFile, + caFile: caFile, + ciphers: ciphers, + password: password, + passwordFile: passwordFile, + }) } // RefImplPingBody is reference implementation for filling of a ping diff --git a/pool/connection_pool_test.go b/pool/connection_pool_test.go index 27310be23..71c14158c 100644 --- a/pool/connection_pool_test.go +++ b/pool/connection_pool_test.go @@ -13,21 +13,25 @@ import ( "time" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/tarantool/go-iproto" "github.com/vmihailenco/msgpack/v5" + "github.com/stretchr/testify/require" "github.com/tarantool/go-tarantool/v2" "github.com/tarantool/go-tarantool/v2/pool" "github.com/tarantool/go-tarantool/v2/test_helpers" ) +var user = "test" +var pass = "test" var spaceNo = uint32(520) var spaceName = "testPool" var indexNo = uint32(0) var ports = []string{"3013", "3014", "3015", "3016", "3017"} var host = "127.0.0.1" + +type Dialers = map[string]tarantool.Dialer + var servers = []string{ strings.Join([]string{host, ports[0]}, ":"), strings.Join([]string{host, ports[1]}, ":"), @@ -36,10 +40,34 @@ var servers = []string{ strings.Join([]string{host, ports[4]}, ":"), } +func makeDialer(serv string) tarantool.Dialer { + return tarantool.TtDialer{ + Address: serv, + User: user, + Password: pass, + } +} + +func makeDialers(servers []string) Dialers { + dialers := Dialers{} + for _, serv := range servers { + dialers[serv] = makeDialer(serv) + } + return dialers +} + +func makeRoles(servers []string, roles []bool) map[string]bool { + res := map[string]bool{} + for i, serv := range servers { + res[serv] = roles[i] + } + return res +} + +var dialers = makeDialers(servers) + var connOpts = tarantool.Opts{ Timeout: 5 * time.Second, - User: "test", - Pass: "test", } var defaultCountRetry = 5 @@ -49,21 +77,24 @@ var instances []test_helpers.TarantoolInstance func TestConnError_IncorrectParams(t *testing.T) { ctx, cancel := test_helpers.GetPoolConnectContext() - connPool, err := pool.Connect(ctx, []string{}, tarantool.Opts{}) + connPool, err := pool.Connect(ctx, Dialers{}, tarantool.Opts{}) cancel() require.Nilf(t, connPool, "conn is not nil with incorrect param") require.NotNilf(t, err, "err is nil with incorrect params") - require.Equal(t, "addrs (first argument) should not be empty", err.Error()) + require.Equal(t, "dialers (second argument) should not be empty", err.Error()) ctx, cancel = test_helpers.GetPoolConnectContext() - connPool, err = pool.Connect(ctx, []string{"err1", "err2"}, connOpts) + connPool, err = pool.Connect(ctx, Dialers{ + "err1": tarantool.TtDialer{Address: "err1"}, + "err2": tarantool.TtDialer{Address: "err2"}, + }, connOpts) cancel() require.Nilf(t, connPool, "conn is not nil with incorrect param") require.NotNilf(t, err, "err is nil with incorrect params") require.Equal(t, "no active connections", err.Error()) ctx, cancel = test_helpers.GetPoolConnectContext() - connPool, err = pool.ConnectWithOpts(ctx, servers, tarantool.Opts{}, pool.Opts{}) + connPool, err = pool.ConnectWithOpts(ctx, dialers, tarantool.Opts{}, pool.Opts{}) cancel() require.Nilf(t, connPool, "conn is not nil with incorrect param") require.NotNilf(t, err, "err is nil with incorrect params") @@ -71,10 +102,11 @@ func TestConnError_IncorrectParams(t *testing.T) { } func TestConnSuccessfully(t *testing.T) { - server := servers[0] + healthyServ := servers[0] + ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, []string{"err", server}, connOpts) + connPool, err := pool.Connect(ctx, makeDialers([]string{healthyServ, "err"}), connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -83,10 +115,10 @@ func TestConnSuccessfully(t *testing.T) { args := test_helpers.CheckStatusesArgs{ ConnPool: connPool, Mode: pool.ANY, - Servers: []string{server}, + Servers: []string{healthyServ}, ExpectedPoolStatus: true, ExpectedStatuses: map[string]bool{ - server: true, + healthyServ: true, }, } @@ -97,8 +129,6 @@ func TestConnSuccessfully(t *testing.T) { func TestConnErrorAfterCtxCancel(t *testing.T) { var connLongReconnectOpts = tarantool.Opts{ Timeout: 5 * time.Second, - User: "test", - Pass: "test", Reconnect: time.Second, MaxReconnects: 100, } @@ -109,7 +139,7 @@ func TestConnErrorAfterCtxCancel(t *testing.T) { var err error cancel() - connPool, err = pool.Connect(ctx, servers, connLongReconnectOpts) + connPool, err = pool.Connect(ctx, dialers, connLongReconnectOpts) if connPool != nil || err == nil { t.Fatalf("ConnectionPool was created after cancel") @@ -121,24 +151,25 @@ func TestConnErrorAfterCtxCancel(t *testing.T) { } type mockClosingDialer struct { - cnt int + addr string + cnt *int ctx context.Context ctxCancel context.CancelFunc } -func (m *mockClosingDialer) Dial(ctx context.Context, address string, +func (m *mockClosingDialer) Dial(ctx context.Context, opts tarantool.DialOpts) (tarantool.Conn, error) { + dialer := tarantool.TtDialer{ + Address: m.addr, + User: user, + Password: pass, + } + conn, err := dialer.Dial(m.ctx, tarantool.DialOpts{}) - dialer := tarantool.TtDialer{} - conn, err := dialer.Dial(m.ctx, address, tarantool.DialOpts{ - User: "test", - Password: "test", - }) - - if m.cnt == 0 { + if *m.cnt == 0 { m.ctxCancel() } - m.cnt++ + *m.cnt++ return conn, err } @@ -147,11 +178,18 @@ func TestContextCancelInProgress(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - dialer := &mockClosingDialer{0, ctx, cancel} + cnt := new(int) + poolDialers := Dialers{} + for _, serv := range servers { + poolDialers[serv] = &mockClosingDialer{ + addr: serv, + cnt: cnt, + ctx: ctx, + ctxCancel: cancel, + } + } - connPool, err := pool.Connect(ctx, servers, tarantool.Opts{ - Dialer: dialer, - }) + connPool, err := pool.Connect(ctx, poolDialers, tarantool.Opts{}) require.NotNilf(t, err, "expected err after ctx cancel") assert.Truef(t, strings.Contains(err.Error(), "operation was canceled"), fmt.Sprintf("unexpected error, expected to contain %s, got %v", @@ -161,10 +199,19 @@ func TestContextCancelInProgress(t *testing.T) { func TestConnSuccessfullyDuplicates(t *testing.T) { server := servers[0] + + poolDialers := Dialers{} + for i := 0; i < 4; i++ { + poolDialers[fmt.Sprintf("c%d", i)] = tarantool.TtDialer{ + Address: server, + User: user, + Password: pass, + } + } + ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, []string{server, server, server, server}, - connOpts) + connPool, err := pool.Connect(ctx, poolDialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -173,18 +220,18 @@ func TestConnSuccessfullyDuplicates(t *testing.T) { args := test_helpers.CheckStatusesArgs{ ConnPool: connPool, Mode: pool.ANY, - Servers: []string{server}, + Servers: []string{"c0", "c1", "c2", "c3"}, ExpectedPoolStatus: true, ExpectedStatuses: map[string]bool{ - server: true, + "c0": true, + "c1": true, + "c2": true, + "c3": true, }, } err = test_helpers.CheckPoolStatuses(args) require.Nil(t, err) - - addrs := connPool.GetAddrs() - require.Equalf(t, []string{server}, addrs, "should be only one address") } func TestReconnect(t *testing.T) { @@ -192,7 +239,7 @@ func TestReconnect(t *testing.T) { ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, connOpts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -233,14 +280,15 @@ func TestReconnect(t *testing.T) { } func TestDisconnect_withReconnect(t *testing.T) { - const serverId = 0 + serverId := 0 + server := servers[serverId] opts := connOpts opts.Reconnect = 10 * time.Second ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, []string{servers[serverId]}, opts) + connPool, err := pool.Connect(ctx, makeDialers([]string{server}), opts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -286,7 +334,7 @@ func TestDisconnectAll(t *testing.T) { ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, []string{server1, server2}, connOpts) + connPool, err := pool.Connect(ctx, makeDialers([]string{server1, server2}), connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -335,7 +383,7 @@ func TestDisconnectAll(t *testing.T) { func TestAdd(t *testing.T) { ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, []string{servers[0]}, connOpts) + connPool, err := pool.Connect(ctx, makeDialers(servers[:1]), connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -343,7 +391,7 @@ func TestAdd(t *testing.T) { for _, server := range servers[1:] { ctx, cancel := test_helpers.GetConnectContext() - err = connPool.Add(ctx, server) + err = connPool.Add(ctx, server, dialers[server]) cancel() require.Nil(t, err) } @@ -368,8 +416,9 @@ func TestAdd(t *testing.T) { } func TestAdd_exist(t *testing.T) { + server := servers[0] ctx, cancel := test_helpers.GetPoolConnectContext() - connPool, err := pool.Connect(ctx, []string{servers[0]}, connOpts) + connPool, err := pool.Connect(ctx, makeDialers([]string{server}), connOpts) cancel() require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -377,7 +426,7 @@ func TestAdd_exist(t *testing.T) { defer connPool.Close() ctx, cancel = test_helpers.GetConnectContext() - err = connPool.Add(ctx, servers[0]) + err = connPool.Add(ctx, server, makeDialer(server)) cancel() require.Equal(t, pool.ErrExists, err) @@ -387,7 +436,7 @@ func TestAdd_exist(t *testing.T) { Servers: servers, ExpectedPoolStatus: true, ExpectedStatuses: map[string]bool{ - servers[0]: true, + server: true, }, } @@ -397,16 +446,21 @@ func TestAdd_exist(t *testing.T) { } func TestAdd_unreachable(t *testing.T) { + server := servers[0] + ctx, cancel := test_helpers.GetPoolConnectContext() - connPool, err := pool.Connect(ctx, []string{servers[0]}, connOpts) + connPool, err := pool.Connect(ctx, makeDialers([]string{server}), connOpts) cancel() require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") defer connPool.Close() + unhealthyServ := "127.0.0.2:6667" ctx, cancel = test_helpers.GetConnectContext() - err = connPool.Add(ctx, "127.0.0.2:6667") + err = connPool.Add(ctx, unhealthyServ, tarantool.TtDialer{ + Address: unhealthyServ, + }) cancel() // The OS-dependent error so we just check for existence. require.NotNil(t, err) @@ -417,7 +471,7 @@ func TestAdd_unreachable(t *testing.T) { Servers: servers, ExpectedPoolStatus: true, ExpectedStatuses: map[string]bool{ - servers[0]: true, + server: true, }, } @@ -427,22 +481,26 @@ func TestAdd_unreachable(t *testing.T) { } func TestAdd_afterClose(t *testing.T) { + server := servers[0] ctx, cancel := test_helpers.GetPoolConnectContext() - connPool, err := pool.Connect(ctx, []string{servers[0]}, connOpts) + connPool, err := pool.Connect(ctx, makeDialers([]string{server}), connOpts) cancel() require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") connPool.Close() ctx, cancel = test_helpers.GetConnectContext() - err = connPool.Add(ctx, servers[0]) + err = connPool.Add(ctx, server, dialers[server]) cancel() assert.Equal(t, err, pool.ErrClosed) } func TestAdd_Close_concurrent(t *testing.T) { + serv0 := servers[0] + serv1 := servers[1] + ctx, cancel := test_helpers.GetPoolConnectContext() - connPool, err := pool.Connect(ctx, []string{servers[0]}, connOpts) + connPool, err := pool.Connect(ctx, makeDialers([]string{serv0}), connOpts) cancel() require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -453,7 +511,7 @@ func TestAdd_Close_concurrent(t *testing.T) { defer wg.Done() ctx, cancel := test_helpers.GetConnectContext() - err = connPool.Add(ctx, servers[1]) + err = connPool.Add(ctx, serv1, makeDialer(serv1)) cancel() if err != nil { assert.Equal(t, pool.ErrClosed, err) @@ -466,8 +524,11 @@ func TestAdd_Close_concurrent(t *testing.T) { } func TestAdd_CloseGraceful_concurrent(t *testing.T) { + serv0 := servers[0] + serv1 := servers[1] + ctx, cancel := test_helpers.GetPoolConnectContext() - connPool, err := pool.Connect(ctx, []string{servers[0]}, connOpts) + connPool, err := pool.Connect(ctx, makeDialers([]string{serv0}), connOpts) cancel() require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -478,7 +539,7 @@ func TestAdd_CloseGraceful_concurrent(t *testing.T) { defer wg.Done() ctx, cancel := test_helpers.GetConnectContext() - err = connPool.Add(ctx, servers[1]) + err = connPool.Add(ctx, serv1, makeDialer(serv1)) cancel() if err != nil { assert.Equal(t, pool.ErrClosed, err) @@ -493,7 +554,7 @@ func TestAdd_CloseGraceful_concurrent(t *testing.T) { func TestRemove(t *testing.T) { ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, connOpts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -522,7 +583,7 @@ func TestRemove(t *testing.T) { func TestRemove_double(t *testing.T) { ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, []string{servers[0], servers[1]}, connOpts) + connPool, err := pool.Connect(ctx, makeDialers(servers[:2]), connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -551,7 +612,7 @@ func TestRemove_double(t *testing.T) { func TestRemove_unknown(t *testing.T) { ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, []string{servers[0], servers[1]}, connOpts) + connPool, err := pool.Connect(ctx, makeDialers(servers[:2]), connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -579,7 +640,7 @@ func TestRemove_unknown(t *testing.T) { func TestRemove_concurrent(t *testing.T) { ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, []string{servers[0], servers[1]}, connOpts) + connPool, err := pool.Connect(ctx, makeDialers(servers[:2]), connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -628,7 +689,7 @@ func TestRemove_concurrent(t *testing.T) { func TestRemove_Close_concurrent(t *testing.T) { ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, []string{servers[0], servers[1]}, connOpts) + connPool, err := pool.Connect(ctx, makeDialers(servers[:2]), connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -649,7 +710,7 @@ func TestRemove_Close_concurrent(t *testing.T) { func TestRemove_CloseGraceful_concurrent(t *testing.T) { ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, []string{servers[0], servers[1]}, connOpts) + connPool, err := pool.Connect(ctx, makeDialers(servers[:2]), connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -673,7 +734,7 @@ func TestClose(t *testing.T) { ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, []string{server1, server2}, connOpts) + connPool, err := pool.Connect(ctx, makeDialers([]string{server1, server2}), connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -715,7 +776,7 @@ func TestCloseGraceful(t *testing.T) { ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, []string{server1, server2}, connOpts) + connPool, err := pool.Connect(ctx, makeDialers([]string{server1, server2}), connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -734,9 +795,11 @@ func TestCloseGraceful(t *testing.T) { require.Nil(t, err) eval := `local fiber = require('fiber') - local time = ... - fiber.sleep(time) + local time = ... + fiber.sleep(time) + ` + evalSleep := 3 // In seconds. req := tarantool.NewEvalRequest(eval).Args([]interface{}{evalSleep}) fut := connPool.Do(req, pool.ANY) @@ -779,7 +842,8 @@ func (h *testHandler) addErr(err error) { h.errs = append(h.errs, err) } -func (h *testHandler) Discovered(conn *tarantool.Connection, +func (h *testHandler) Discovered(id string, conn *tarantool.Connection, + role pool.Role) error { discovered := atomic.AddUint32(&h.discovered, 1) @@ -790,29 +854,29 @@ func (h *testHandler) Discovered(conn *tarantool.Connection, // discovered < 3 - initial open of connections // discovered >= 3 - update a connection after a role update - addr := conn.Addr() - if addr == servers[0] { + if id == servers[0] { if discovered < 3 && role != pool.MasterRole { - h.addErr(fmt.Errorf("unexpected init role %d for addr %s", role, addr)) + h.addErr(fmt.Errorf("unexpected init role %d for id %s", role, id)) } if discovered >= 3 && role != pool.ReplicaRole { - h.addErr(fmt.Errorf("unexpected updated role %d for addr %s", role, addr)) + h.addErr(fmt.Errorf("unexpected updated role %d for id %s", role, id)) } - } else if addr == servers[1] { + } else if id == servers[1] { if discovered >= 3 { - h.addErr(fmt.Errorf("unexpected discovery for addr %s", addr)) + h.addErr(fmt.Errorf("unexpected discovery for id %s", id)) } if role != pool.ReplicaRole { - h.addErr(fmt.Errorf("unexpected role %d for addr %s", role, addr)) + h.addErr(fmt.Errorf("unexpected role %d for id %s", role, id)) } } else { - h.addErr(fmt.Errorf("unexpected discovered addr %s", addr)) + h.addErr(fmt.Errorf("unexpected discovered id %s", id)) } return nil } -func (h *testHandler) Deactivated(conn *tarantool.Connection, +func (h *testHandler) Deactivated(id string, conn *tarantool.Connection, + role pool.Role) error { deactivated := atomic.AddUint32(&h.deactivated, 1) @@ -821,22 +885,21 @@ func (h *testHandler) Deactivated(conn *tarantool.Connection, return nil } - addr := conn.Addr() - if deactivated == 1 && addr == servers[0] { + if deactivated == 1 && id == servers[0] { // A first close is a role update. if role != pool.MasterRole { - h.addErr(fmt.Errorf("unexpected removed role %d for addr %s", role, addr)) + h.addErr(fmt.Errorf("unexpected removed role %d for id %s", role, id)) } return nil } - if addr == servers[0] || addr == servers[1] { + if id == servers[0] || id == servers[1] { // Close. if role != pool.ReplicaRole { - h.addErr(fmt.Errorf("unexpected removed role %d for addr %s", role, addr)) + h.addErr(fmt.Errorf("unexpected removed role %d for id %s", role, id)) } } else { - h.addErr(fmt.Errorf("unexpected removed addr %s", addr)) + h.addErr(fmt.Errorf("unexpected removed id %s", id)) } return nil @@ -844,9 +907,10 @@ func (h *testHandler) Deactivated(conn *tarantool.Connection, func TestConnectionHandlerOpenUpdateClose(t *testing.T) { poolServers := []string{servers[0], servers[1]} + poolDialers := makeDialers(poolServers) roles := []bool{false, true} - err := test_helpers.SetClusterRO(poolServers, connOpts, roles) + err := test_helpers.SetClusterRO(poolDialers, connOpts, makeRoles(poolServers, roles)) require.Nilf(t, err, "fail to set roles for cluster") h := &testHandler{} @@ -856,7 +920,7 @@ func TestConnectionHandlerOpenUpdateClose(t *testing.T) { } ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.ConnectWithOpts(ctx, poolServers, connOpts, poolOpts) + connPool, err := pool.ConnectWithOpts(ctx, poolDialers, connOpts, poolOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -910,13 +974,15 @@ type testAddErrorHandler struct { discovered, deactivated int } -func (h *testAddErrorHandler) Discovered(conn *tarantool.Connection, +func (h *testAddErrorHandler) Discovered(id string, conn *tarantool.Connection, + role pool.Role) error { h.discovered++ return fmt.Errorf("any error") } -func (h *testAddErrorHandler) Deactivated(conn *tarantool.Connection, +func (h *testAddErrorHandler) Deactivated(id string, conn *tarantool.Connection, + role pool.Role) error { h.deactivated++ return nil @@ -932,7 +998,7 @@ func TestConnectionHandlerOpenError(t *testing.T) { } ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.ConnectWithOpts(ctx, poolServers, connOpts, poolOpts) + connPool, err := pool.ConnectWithOpts(ctx, makeDialers(poolServers), connOpts, poolOpts) if err == nil { defer connPool.Close() } @@ -945,7 +1011,8 @@ type testUpdateErrorHandler struct { discovered, deactivated uint32 } -func (h *testUpdateErrorHandler) Discovered(conn *tarantool.Connection, +func (h *testUpdateErrorHandler) Discovered(id string, conn *tarantool.Connection, + role pool.Role) error { atomic.AddUint32(&h.discovered, 1) @@ -956,7 +1023,8 @@ func (h *testUpdateErrorHandler) Discovered(conn *tarantool.Connection, return nil } -func (h *testUpdateErrorHandler) Deactivated(conn *tarantool.Connection, +func (h *testUpdateErrorHandler) Deactivated(id string, conn *tarantool.Connection, + role pool.Role) error { atomic.AddUint32(&h.deactivated, 1) return nil @@ -964,9 +1032,10 @@ func (h *testUpdateErrorHandler) Deactivated(conn *tarantool.Connection, func TestConnectionHandlerUpdateError(t *testing.T) { poolServers := []string{servers[0], servers[1]} + poolDialers := makeDialers(poolServers) roles := []bool{false, false} - err := test_helpers.SetClusterRO(poolServers, connOpts, roles) + err := test_helpers.SetClusterRO(poolDialers, connOpts, makeRoles(poolServers, roles)) require.Nilf(t, err, "fail to set roles for cluster") h := &testUpdateErrorHandler{} @@ -976,7 +1045,7 @@ func TestConnectionHandlerUpdateError(t *testing.T) { } ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.ConnectWithOpts(ctx, poolServers, connOpts, poolOpts) + connPool, err := pool.ConnectWithOpts(ctx, poolDialers, connOpts, poolOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") defer connPool.Close() @@ -1023,7 +1092,7 @@ func TestRequestOnClosed(t *testing.T) { ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, []string{server1, server2}, connOpts) + connPool, err := pool.Connect(ctx, makeDialers([]string{server1, server2}), connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -1056,35 +1125,15 @@ func TestRequestOnClosed(t *testing.T) { require.Nilf(t, err, "failed to restart tarantool") } -func TestGetPoolInfo(t *testing.T) { - server1 := servers[0] - server2 := servers[1] - - srvs := []string{server1, server2} - expected := []string{server1, server2} - ctx, cancel := test_helpers.GetPoolConnectContext() - defer cancel() - connPool, err := pool.Connect(ctx, srvs, connOpts) - require.Nilf(t, err, "failed to connect") - require.NotNilf(t, connPool, "conn is nil after Connect") - - defer connPool.Close() - - srvs[0] = "x" - connPool.GetAddrs()[1] = "y" - - require.ElementsMatch(t, expected, connPool.GetAddrs()) -} - func TestCall(t *testing.T) { roles := []bool{false, true, false, false, true} - err := test_helpers.SetClusterRO(servers, connOpts, roles) + err := test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, connOpts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -1138,12 +1187,12 @@ func TestCall(t *testing.T) { func TestCall16(t *testing.T) { roles := []bool{false, true, false, false, true} - err := test_helpers.SetClusterRO(servers, connOpts, roles) + err := test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, connOpts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -1197,12 +1246,12 @@ func TestCall16(t *testing.T) { func TestCall17(t *testing.T) { roles := []bool{false, true, false, false, true} - err := test_helpers.SetClusterRO(servers, connOpts, roles) + err := test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, connOpts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -1256,12 +1305,12 @@ func TestCall17(t *testing.T) { func TestEval(t *testing.T) { roles := []bool{false, true, false, false, true} - err := test_helpers.SetClusterRO(servers, connOpts, roles) + err := test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, connOpts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -1336,12 +1385,12 @@ func TestExecute(t *testing.T) { roles := []bool{false, true, false, false, true} - err := test_helpers.SetClusterRO(servers, connOpts, roles) + err := test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, connOpts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -1395,12 +1444,12 @@ func TestRoundRobinStrategy(t *testing.T) { serversNumber := len(servers) - err := test_helpers.SetClusterRO(servers, connOpts, roles) + err := test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, connOpts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -1474,12 +1523,12 @@ func TestRoundRobinStrategy_NoReplica(t *testing.T) { servers[4]: true, } - err := test_helpers.SetClusterRO(servers, connOpts, roles) + err := test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, connOpts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -1547,12 +1596,12 @@ func TestRoundRobinStrategy_NoMaster(t *testing.T) { servers[4]: true, } - err := test_helpers.SetClusterRO(servers, connOpts, roles) + err := test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, connOpts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -1632,12 +1681,12 @@ func TestUpdateInstancesRoles(t *testing.T) { serversNumber := len(servers) - err := test_helpers.SetClusterRO(servers, connOpts, roles) + err := test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, connOpts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -1711,7 +1760,7 @@ func TestUpdateInstancesRoles(t *testing.T) { servers[3]: true, } - err = test_helpers.SetClusterRO(servers, connOpts, roles) + err = test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") // ANY @@ -1778,12 +1827,12 @@ func TestUpdateInstancesRoles(t *testing.T) { func TestInsert(t *testing.T) { roles := []bool{true, true, false, true, true} - err := test_helpers.SetClusterRO(servers, connOpts, roles) + err := test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, connOpts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -1809,7 +1858,7 @@ func TestInsert(t *testing.T) { // Connect to servers[2] to check if tuple // was inserted on RW instance - conn := test_helpers.ConnectWithValidation(t, servers[2], connOpts) + conn := test_helpers.ConnectWithValidation(t, makeDialer(servers[2]), connOpts) defer conn.Close() sel := tarantool.NewSelectRequest(spaceNo). @@ -1879,12 +1928,12 @@ func TestInsert(t *testing.T) { func TestDelete(t *testing.T) { roles := []bool{true, true, false, true, true} - err := test_helpers.SetClusterRO(servers, connOpts, roles) + err := test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, connOpts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -1892,7 +1941,7 @@ func TestDelete(t *testing.T) { // Connect to servers[2] to check if tuple // was inserted on RW instance - conn := test_helpers.ConnectWithValidation(t, servers[2], connOpts) + conn := test_helpers.ConnectWithValidation(t, makeDialer(servers[2]), connOpts) defer conn.Close() ins := tarantool.NewInsertRequest(spaceNo).Tuple([]interface{}{"delete_key", "delete_value"}) @@ -1945,12 +1994,12 @@ func TestDelete(t *testing.T) { func TestUpsert(t *testing.T) { roles := []bool{true, true, false, true, true} - err := test_helpers.SetClusterRO(servers, connOpts, roles) + err := test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, connOpts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -1958,7 +2007,7 @@ func TestUpsert(t *testing.T) { // Connect to servers[2] to check if tuple // was inserted on RW instance - conn := test_helpers.ConnectWithValidation(t, servers[2], connOpts) + conn := test_helpers.ConnectWithValidation(t, makeDialer(servers[2]), connOpts) defer conn.Close() // Mode is `RW` by default, we have only one RW instance (servers[2]) @@ -2019,12 +2068,12 @@ func TestUpsert(t *testing.T) { func TestUpdate(t *testing.T) { roles := []bool{true, true, false, true, true} - err := test_helpers.SetClusterRO(servers, connOpts, roles) + err := test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, connOpts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -2032,7 +2081,7 @@ func TestUpdate(t *testing.T) { // Connect to servers[2] to check if tuple // was inserted on RW instance - conn := test_helpers.ConnectWithValidation(t, servers[2], connOpts) + conn := test_helpers.ConnectWithValidation(t, makeDialer(servers[2]), connOpts) defer conn.Close() ins := tarantool.NewInsertRequest(spaceNo). @@ -2111,12 +2160,12 @@ func TestUpdate(t *testing.T) { func TestReplace(t *testing.T) { roles := []bool{true, true, false, true, true} - err := test_helpers.SetClusterRO(servers, connOpts, roles) + err := test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, connOpts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -2124,7 +2173,7 @@ func TestReplace(t *testing.T) { // Connect to servers[2] to check if tuple // was inserted on RW instance - conn := test_helpers.ConnectWithValidation(t, servers[2], connOpts) + conn := test_helpers.ConnectWithValidation(t, makeDialer(servers[2]), connOpts) defer conn.Close() ins := tarantool.NewInsertRequest(spaceNo). @@ -2199,12 +2248,12 @@ func TestReplace(t *testing.T) { func TestSelect(t *testing.T) { roles := []bool{true, true, false, true, false} - err := test_helpers.SetClusterRO(servers, connOpts, roles) + err := test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, connOpts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -2222,13 +2271,13 @@ func TestSelect(t *testing.T) { rwKey := []interface{}{"rw_select_key"} anyKey := []interface{}{"any_select_key"} - err = test_helpers.InsertOnInstances(roServers, connOpts, spaceNo, roTpl) + err = test_helpers.InsertOnInstances(makeDialers(roServers), connOpts, spaceNo, roTpl) require.Nil(t, err) - err = test_helpers.InsertOnInstances(rwServers, connOpts, spaceNo, rwTpl) + err = test_helpers.InsertOnInstances(makeDialers(rwServers), connOpts, spaceNo, rwTpl) require.Nil(t, err) - err = test_helpers.InsertOnInstances(allServers, connOpts, spaceNo, anyTpl) + err = test_helpers.InsertOnInstances(makeDialers(allServers), connOpts, spaceNo, anyTpl) require.Nil(t, err) //default: ANY @@ -2321,12 +2370,12 @@ func TestSelect(t *testing.T) { func TestPing(t *testing.T) { roles := []bool{true, true, false, true, false} - err := test_helpers.SetClusterRO(servers, connOpts, roles) + err := test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, connOpts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -2361,12 +2410,12 @@ func TestPing(t *testing.T) { func TestDo(t *testing.T) { roles := []bool{true, true, false, true, false} - err := test_helpers.SetClusterRO(servers, connOpts, roles) + err := test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, connOpts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -2402,12 +2451,12 @@ func TestDo(t *testing.T) { func TestDo_concurrent(t *testing.T) { roles := []bool{true, true, false, true, false} - err := test_helpers.SetClusterRO(servers, connOpts, roles) + err := test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, connOpts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -2435,12 +2484,12 @@ func TestNewPrepared(t *testing.T) { roles := []bool{true, true, false, true, false} - err := test_helpers.SetClusterRO(servers, connOpts, roles) + err := test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, connOpts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -2450,10 +2499,6 @@ func TestNewPrepared(t *testing.T) { "SELECT NAME0, NAME1 FROM SQL_TEST WHERE NAME0=:id AND NAME1=:name;", pool.RO) require.Nilf(t, err, "fail to prepare statement: %v", err) - if connPool.GetPoolInfo()[stmt.Conn.Addr()].ConnRole != pool.ReplicaRole { - t.Errorf("wrong role for the statement's connection") - } - executeReq := tarantool.NewExecutePreparedRequest(stmt) unprepareReq := tarantool.NewUnprepareRequest(stmt) @@ -2505,12 +2550,12 @@ func TestDoWithStrangerConn(t *testing.T) { roles := []bool{true, true, false, true, false} - err := test_helpers.SetClusterRO(servers, connOpts, roles) + err := test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, connOpts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -2536,12 +2581,12 @@ func TestStream_Commit(t *testing.T) { roles := []bool{true, true, false, true, true} - err = test_helpers.SetClusterRO(servers, connOpts, roles) + err = test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, connOpts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") defer connPool.Close() @@ -2568,7 +2613,7 @@ func TestStream_Commit(t *testing.T) { // Connect to servers[2] to check if tuple // was inserted outside of stream on RW instance // before transaction commit - conn := test_helpers.ConnectWithValidation(t, servers[2], connOpts) + conn := test_helpers.ConnectWithValidation(t, makeDialer(servers[2]), connOpts) defer conn.Close() // Select not related to the transaction @@ -2637,12 +2682,12 @@ func TestStream_Rollback(t *testing.T) { roles := []bool{true, true, false, true, true} - err = test_helpers.SetClusterRO(servers, connOpts, roles) + err = test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, connOpts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") defer connPool.Close() @@ -2668,7 +2713,7 @@ func TestStream_Rollback(t *testing.T) { // Connect to servers[2] to check if tuple // was not inserted outside of stream on RW instance - conn := test_helpers.ConnectWithValidation(t, servers[2], connOpts) + conn := test_helpers.ConnectWithValidation(t, makeDialer(servers[2]), connOpts) defer conn.Close() // Select not related to the transaction @@ -2738,12 +2783,12 @@ func TestStream_TxnIsolationLevel(t *testing.T) { roles := []bool{true, true, false, true, true} - err = test_helpers.SetClusterRO(servers, connOpts, roles) + err = test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, connOpts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") defer connPool.Close() @@ -2754,7 +2799,7 @@ func TestStream_TxnIsolationLevel(t *testing.T) { // Connect to servers[2] to check if tuple // was not inserted outside of stream on RW instance - conn := test_helpers.ConnectWithValidation(t, servers[2], connOpts) + conn := test_helpers.ConnectWithValidation(t, makeDialer(servers[2]), connOpts) defer conn.Close() for _, level := range txnIsolationLevels { @@ -2827,32 +2872,6 @@ func TestStream_TxnIsolationLevel(t *testing.T) { } } -func TestConnectionPool_NewWatcher_noWatchersFeature(t *testing.T) { - const key = "TestConnectionPool_NewWatcher_noWatchersFeature" - - roles := []bool{true, false, false, true, true} - - opts := connOpts.Clone() - opts.RequiredProtocolInfo.Features = []iproto.Feature{} - err := test_helpers.SetClusterRO(servers, opts, roles) - require.Nilf(t, err, "fail to set roles for cluster") - - ctx, cancel := test_helpers.GetPoolConnectContext() - defer cancel() - connPool, err := pool.Connect(ctx, servers, opts) - require.Nilf(t, err, "failed to connect") - require.NotNilf(t, connPool, "conn is nil after Connect") - defer connPool.Close() - - watcher, err := connPool.NewWatcher(key, - func(event tarantool.WatchEvent) {}, pool.ANY) - require.Nilf(t, watcher, "watcher must not be created") - require.NotNilf(t, err, "an error is expected") - expected := "the feature IPROTO_FEATURE_WATCHERS must be required by " + - "connection options to create a watcher" - require.Equal(t, expected, err.Error()) -} - func TestConnectionPool_NewWatcher_modes(t *testing.T) { test_helpers.SkipIfWatchersUnsupported(t) @@ -2860,16 +2879,12 @@ func TestConnectionPool_NewWatcher_modes(t *testing.T) { roles := []bool{true, false, false, true, true} - opts := connOpts.Clone() - opts.RequiredProtocolInfo.Features = []iproto.Feature{ - iproto.IPROTO_FEATURE_WATCHERS, - } - err := test_helpers.SetClusterRO(servers, opts, roles) + err := test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, opts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") defer connPool.Close() @@ -2910,7 +2925,7 @@ func TestConnectionPool_NewWatcher_modes(t *testing.T) { select { case event := <-events: require.NotNil(t, event.Conn) - addr := event.Conn.Addr() + addr := event.Conn.Addr().String() if val, ok := testMap[addr]; ok { testMap[addr] = val + 1 } else { @@ -2941,11 +2956,7 @@ func TestConnectionPool_NewWatcher_update(t *testing.T) { const initCnt = 2 roles := []bool{true, false, false, true, true} - opts := connOpts.Clone() - opts.RequiredProtocolInfo.Features = []iproto.Feature{ - iproto.IPROTO_FEATURE_WATCHERS, - } - err := test_helpers.SetClusterRO(servers, opts, roles) + err := test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") poolOpts := pool.Opts{ @@ -2953,7 +2964,7 @@ func TestConnectionPool_NewWatcher_update(t *testing.T) { } ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - pool, err := pool.ConnectWithOpts(ctx, servers, opts, poolOpts) + pool, err := pool.ConnectWithOpts(ctx, dialers, connOpts, poolOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, pool, "conn is nil after Connect") @@ -2976,7 +2987,7 @@ func TestConnectionPool_NewWatcher_update(t *testing.T) { select { case event := <-events: require.NotNil(t, event.Conn) - addr := event.Conn.Addr() + addr := event.Conn.Addr().String() if val, ok := testMap[addr]; ok { testMap[addr] = val + 1 } else { @@ -2992,7 +3003,7 @@ func TestConnectionPool_NewWatcher_update(t *testing.T) { for i, role := range roles { roles[i] = !role } - err = test_helpers.SetClusterRO(servers, connOpts, roles) + err = test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") // Wait for all updated events. @@ -3000,7 +3011,7 @@ func TestConnectionPool_NewWatcher_update(t *testing.T) { select { case event := <-events: require.NotNil(t, event.Conn) - addr := event.Conn.Addr() + addr := event.Conn.Addr().String() if val, ok := testMap[addr]; ok { testMap[addr] = val + 1 } else { @@ -3030,16 +3041,12 @@ func TestWatcher_Unregister(t *testing.T) { const expectedCnt = 2 roles := []bool{true, false, false, true, true} - opts := connOpts.Clone() - opts.RequiredProtocolInfo.Features = []iproto.Feature{ - iproto.IPROTO_FEATURE_WATCHERS, - } - err := test_helpers.SetClusterRO(servers, opts, roles) + err := test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - pool, err := pool.Connect(ctx, servers, opts) + pool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, pool, "conn is nil after Connect") defer pool.Close() @@ -3091,16 +3098,12 @@ func TestConnectionPool_NewWatcher_concurrent(t *testing.T) { roles := []bool{true, false, false, true, true} - opts := connOpts.Clone() - opts.RequiredProtocolInfo.Features = []iproto.Feature{ - iproto.IPROTO_FEATURE_WATCHERS, - } - err := test_helpers.SetClusterRO(servers, opts, roles) + err := test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, opts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") defer connPool.Close() @@ -3133,16 +3136,12 @@ func TestWatcher_Unregister_concurrent(t *testing.T) { roles := []bool{true, false, false, true, true} - opts := connOpts.Clone() - opts.RequiredProtocolInfo.Features = []iproto.Feature{ - iproto.IPROTO_FEATURE_WATCHERS, - } - err := test_helpers.SetClusterRO(servers, opts, roles) + err := test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) require.Nilf(t, err, "fail to set roles for cluster") ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, opts) + connPool, err := pool.Connect(ctx, dialers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") defer connPool.Close() @@ -3183,13 +3182,11 @@ func runTestMain(m *testing.M) int { instances, err = test_helpers.StartTarantoolInstances(servers, nil, test_helpers.StartOpts{ InitScript: initScript, - User: connOpts.User, - Pass: connOpts.Pass, WaitStart: waitStart, ConnectRetry: connectRetry, RetryTimeout: retryTimeout, MemtxUseMvccEngine: !isStreamUnsupported, - }) + }, makeDialer) if err != nil { log.Fatalf("Failed to prepare test tarantool: %s", err) diff --git a/pool/example_test.go b/pool/example_test.go index a38ae2831..cc39256e5 100644 --- a/pool/example_test.go +++ b/pool/example_test.go @@ -2,7 +2,6 @@ package pool_test import ( "fmt" - "strings" "time" "github.com/tarantool/go-iproto" @@ -22,14 +21,40 @@ type Tuple struct { var testRoles = []bool{true, true, false, true, true} -func examplePool(roles []bool, connOpts tarantool.Opts) (*pool.ConnectionPool, error) { - err := test_helpers.SetClusterRO(servers, connOpts, roles) +func examplePool(roles []bool, + connOpts tarantool.Opts) (*pool.ConnectionPool, error) { + err := test_helpers.SetClusterRO(dialers, connOpts, makeRoles(servers, roles)) if err != nil { return nil, fmt.Errorf("ConnectionPool is not established") } ctx, cancel := test_helpers.GetPoolConnectContext() defer cancel() - connPool, err := pool.Connect(ctx, servers, connOpts) + connPool, err := pool.Connect(ctx, dialers, connOpts) + if err != nil || connPool == nil { + return nil, fmt.Errorf("ConnectionPool is not established") + } + + return connPool, nil +} + +func exampleFeaturesPool(roles []bool, connOpts tarantool.Opts, + requiredProtocol tarantool.ProtocolInfo) (*pool.ConnectionPool, error) { + poolDialers := Dialers{} + for _, serv := range servers { + poolDialers[serv] = tarantool.TtDialer{ + Address: serv, + User: user, + Password: pass, + RequiredProtocolInfo: requiredProtocol, + } + } + err := test_helpers.SetClusterRO(poolDialers, connOpts, makeRoles(servers, roles)) + if err != nil { + return nil, fmt.Errorf("ConnectionPool is not established") + } + ctx, cancel := test_helpers.GetPoolConnectContext() + defer cancel() + connPool, err := pool.Connect(ctx, poolDialers, connOpts) if err != nil || connPool == nil { return nil, fmt.Errorf("ConnectionPool is not established") } @@ -94,11 +119,6 @@ func ExampleConnectionPool_NewWatcher() { const key = "foo" const value = "bar" - opts := connOpts.Clone() - opts.RequiredProtocolInfo.Features = []iproto.Feature{ - iproto.IPROTO_FEATURE_WATCHERS, - } - connPool, err := examplePool(testRoles, connOpts) if err != nil { fmt.Println(err) @@ -122,49 +142,15 @@ func ExampleConnectionPool_NewWatcher() { time.Sleep(time.Second) } -func ExampleConnectionPool_NewWatcher_noWatchersFeature() { - const key = "foo" - - opts := connOpts.Clone() - opts.RequiredProtocolInfo.Features = []iproto.Feature{} - - connPool, err := examplePool(testRoles, connOpts) - if err != nil { - fmt.Println(err) - } - defer connPool.Close() - - callback := func(event tarantool.WatchEvent) {} - watcher, err := connPool.NewWatcher(key, callback, pool.ANY) - fmt.Println(watcher) - if err != nil { - // Need to split the error message into two lines to pass - // golangci-lint. - str := err.Error() - fmt.Println(strings.Trim(str[:56], " ")) - fmt.Println(str[56:]) - } else { - fmt.Println(err) - } - // Output: - // - // the feature IPROTO_FEATURE_WATCHERS must be required by - // connection options to create a watcher -} - -func getTestTxnOpts() tarantool.Opts { - txnOpts := connOpts.Clone() - +func getTestTxnProtocol() tarantool.ProtocolInfo { // Assert that server supports expected protocol features - txnOpts.RequiredProtocolInfo = tarantool.ProtocolInfo{ + return tarantool.ProtocolInfo{ Version: tarantool.ProtocolVersion(1), Features: []iproto.Feature{ iproto.IPROTO_FEATURE_STREAMS, iproto.IPROTO_FEATURE_TRANSACTIONS, }, } - - return txnOpts } func ExampleCommitRequest() { @@ -178,8 +164,7 @@ func ExampleCommitRequest() { return } - txnOpts := getTestTxnOpts() - connPool, err := examplePool(testRoles, txnOpts) + connPool, err := exampleFeaturesPool(testRoles, connOpts, getTestTxnProtocol()) if err != nil { fmt.Println(err) return @@ -265,9 +250,8 @@ func ExampleRollbackRequest() { return } - txnOpts := getTestTxnOpts() // example pool has only one rw instance - connPool, err := examplePool(testRoles, txnOpts) + connPool, err := exampleFeaturesPool(testRoles, connOpts, getTestTxnProtocol()) if err != nil { fmt.Println(err) return @@ -352,9 +336,8 @@ func ExampleBeginRequest_TxnIsolation() { return } - txnOpts := getTestTxnOpts() // example pool has only one rw instance - connPool, err := examplePool(testRoles, txnOpts) + connPool, err := exampleFeaturesPool(testRoles, connOpts, getTestTxnProtocol()) if err != nil { fmt.Println(err) return diff --git a/pool/round_robin_test.go b/pool/round_robin_test.go index 4aacb1a26..8a825a1d0 100644 --- a/pool/round_robin_test.go +++ b/pool/round_robin_test.go @@ -22,7 +22,7 @@ func TestRoundRobinAddDelete(t *testing.T) { } for i, addr := range addrs { - if conn := rr.DeleteConnByAddr(addr); conn != conns[i] { + if conn := rr.DeleteConnById(addr); conn != conns[i] { t.Errorf("Unexpected connection on address %s", addr) } } @@ -40,13 +40,13 @@ func TestRoundRobinAddDuplicateDelete(t *testing.T) { rr.AddConn(validAddr1, conn1) rr.AddConn(validAddr1, conn2) - if rr.DeleteConnByAddr(validAddr1) != conn2 { + if rr.DeleteConnById(validAddr1) != conn2 { t.Errorf("Unexpected deleted connection") } if !rr.IsEmpty() { t.Errorf("RoundRobin does not empty") } - if rr.DeleteConnByAddr(validAddr1) != nil { + if rr.DeleteConnById(validAddr1) != nil { t.Errorf("Unexpected value after second deletion") } } @@ -79,11 +79,12 @@ func TestRoundRobinStrategy_GetConnections(t *testing.T) { rr.AddConn(addr, conns[i]) } - rr.GetConnections()[1] = conns[0] // GetConnections() returns a copy. + rr.GetConnections()[validAddr1] = conns[0] // GetConnections() returns a copy. rrConns := rr.GetConnections() - for i, expected := range conns { - if expected != rrConns[i] { - t.Errorf("Unexpected connection on %d call", i) + + for i, addr := range addrs { + if conns[i] != rrConns[addr] { + t.Errorf("Unexpected connection on %s addr", addr) } } } diff --git a/queue/example_connection_pool_test.go b/queue/example_connection_pool_test.go index a3bfaf0a4..0cb9c07be 100644 --- a/queue/example_connection_pool_test.go +++ b/queue/example_connection_pool_test.go @@ -44,7 +44,7 @@ func NewQueueConnectionHandler(name string, cfg queue.Cfg) *QueueConnectionHandl // // NOTE: the Queue supports only a master-replica cluster configuration. It // does not support a master-master configuration. -func (h *QueueConnectionHandler) Discovered(conn *tarantool.Connection, +func (h *QueueConnectionHandler) Discovered(id string, conn *tarantool.Connection, role pool.Role) error { h.mutex.Lock() defer h.mutex.Unlock() @@ -106,14 +106,14 @@ func (h *QueueConnectionHandler) Discovered(conn *tarantool.Connection, return h.err } - fmt.Printf("Master %s is ready to work!\n", conn.Addr()) + fmt.Printf("Master %s is ready to work!\n", id) atomic.AddInt32(&h.masterCnt, 1) return nil } // Deactivated doesn't do anything useful for the example. -func (h *QueueConnectionHandler) Deactivated(conn *tarantool.Connection, +func (h *QueueConnectionHandler) Deactivated(id string, conn *tarantool.Connection, role pool.Role) error { if role == pool.MasterRole { atomic.AddInt32(&h.masterCnt, -1) @@ -152,14 +152,20 @@ func Example_connectionPool() { defer h.Close() // Create a ConnectionPool object. - servers := []string{ - "127.0.0.1:3014", - "127.0.0.1:3015", + poolDialers := map[string]tarantool.Dialer{ + "127.0.0.1:3014": tarantool.TtDialer{ + Address: "127.0.0.1:3014", + User: "test", + Password: "test", + }, + "127.0.0.1:3015": tarantool.TtDialer{ + Address: "127.0.0.1:3015", + User: "test", + Password: "test", + }, } connOpts := tarantool.Opts{ Timeout: 5 * time.Second, - User: "test", - Pass: "test", } poolOpts := pool.Opts{ CheckTimeout: 5 * time.Second, @@ -167,7 +173,7 @@ func Example_connectionPool() { } ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) defer cancel() - connPool, err := pool.ConnectWithOpts(ctx, servers, connOpts, poolOpts) + connPool, err := pool.ConnectWithOpts(ctx, poolDialers, connOpts, poolOpts) if err != nil { fmt.Printf("Unable to connect to the pool: %s", err) return @@ -197,12 +203,17 @@ func Example_connectionPool() { } // Switch a master instance in the pool. - roles := []bool{true, false} + roles := map[string]bool{ + "127.0.0.1:3014": true, + "127.0.0.1:3015": false, + } for { - err := test_helpers.SetClusterRO(servers, connOpts, roles) + err := test_helpers.SetClusterRO(poolDialers, connOpts, roles) if err == nil { break } + fmt.Println(err) + <-time.After(time.Second * 10) } // Wait for a replica instance connection and a new master instance diff --git a/queue/example_msgpack_test.go b/queue/example_msgpack_test.go index 6d3637417..ab4dcce9c 100644 --- a/queue/example_msgpack_test.go +++ b/queue/example_msgpack_test.go @@ -49,15 +49,18 @@ func (c *dummyData) EncodeMsgpack(e *msgpack.Encoder) error { // cannot take the task out of the queue within the time corresponding to the // connection timeout. func Example_simpleQueueCustomMsgPack() { + dialer := tarantool.TtDialer{ + Address: "127.0.0.1:3013", + User: "test", + Password: "test", + } opts := tarantool.Opts{ Reconnect: time.Second, Timeout: 5 * time.Second, MaxReconnects: 5, - User: "test", - Pass: "test", } ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) - conn, err := tarantool.Connect(ctx, "127.0.0.1:3013", opts) + conn, err := tarantool.Connect(ctx, dialer, opts) cancel() if err != nil { log.Fatalf("connection: %s", err) diff --git a/queue/example_test.go b/queue/example_test.go index e81acca40..b9a3efc00 100644 --- a/queue/example_test.go +++ b/queue/example_test.go @@ -28,13 +28,16 @@ func Example_simpleQueue() { } opts := tarantool.Opts{ Timeout: 2500 * time.Millisecond, - User: "test", - Pass: "test", + } + dialer := tarantool.TtDialer{ + Address: "127.0.0.1:3013", + User: "test", + Password: "test", } ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) defer cancel() - conn, err := tarantool.Connect(ctx, "127.0.0.1:3013", opts) + conn, err := tarantool.Connect(ctx, dialer, opts) if err != nil { fmt.Printf("error in prepare is %v", err) return diff --git a/queue/queue_test.go b/queue/queue_test.go index 575ce78a0..a006d0f27 100644 --- a/queue/queue_test.go +++ b/queue/queue_test.go @@ -15,18 +15,35 @@ import ( "github.com/tarantool/go-tarantool/v2/test_helpers" ) +const ( + user = "test" + pass = "test" +) + var server = "127.0.0.1:3013" -var serversPool = []string{ - "127.0.0.1:3014", - "127.0.0.1:3015", +var serversPool = map[string]Dialer{ + "127.0.0.1:3014": TtDialer{ + Address: "127.0.0.1:3014", + User: user, + Password: pass, + }, + "127.0.0.1:3015": TtDialer{ + Address: "127.0.0.1:3015", + User: user, + Password: pass, + }, } var instances []test_helpers.TarantoolInstance +var dialer = TtDialer{ + Address: server, + User: user, + Password: pass, +} + var opts = Opts{ Timeout: 5 * time.Second, - User: "test", - Pass: "test", //Concurrency: 32, //RateLimit: 4*1024, } @@ -53,7 +70,7 @@ func dropQueue(t *testing.T, q queue.Queue) { /////////QUEUE///////// func TestFifoQueue(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() name := "test_queue" @@ -62,7 +79,7 @@ func TestFifoQueue(t *testing.T) { } func TestQueue_Cfg(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() name := "test_queue" @@ -76,7 +93,7 @@ func TestQueue_Cfg(t *testing.T) { } func TestQueue_Identify(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() name := "test_queue" @@ -99,7 +116,7 @@ func TestQueue_Identify(t *testing.T) { } func TestQueue_ReIdentify(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer func() { if conn != nil { conn.Close() @@ -152,7 +169,7 @@ func TestQueue_ReIdentify(t *testing.T) { conn.Close() conn = nil - conn = test_helpers.ConnectWithValidation(t, server, opts) + conn = test_helpers.ConnectWithValidation(t, dialer, opts) q = queue.New(conn, name) // Identify in another connection. @@ -182,7 +199,7 @@ func TestQueue_ReIdentify(t *testing.T) { } func TestQueue_State(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() name := "test_queue" @@ -199,7 +216,7 @@ func TestQueue_State(t *testing.T) { } func TestFifoQueue_GetExist_Statistic(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() name := "test_queue" @@ -229,7 +246,7 @@ func TestFifoQueue_GetExist_Statistic(t *testing.T) { } func TestFifoQueue_Put(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() name := "test_queue" @@ -249,7 +266,7 @@ func TestFifoQueue_Put(t *testing.T) { } func TestFifoQueue_Take(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() name := "test_queue" @@ -322,7 +339,7 @@ func (c *customData) EncodeMsgpack(e *msgpack.Encoder) error { } func TestFifoQueue_TakeTyped(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() name := "test_queue" @@ -385,7 +402,7 @@ func TestFifoQueue_TakeTyped(t *testing.T) { } func TestFifoQueue_Peek(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() name := "test_queue" @@ -417,7 +434,7 @@ func TestFifoQueue_Peek(t *testing.T) { } func TestFifoQueue_Bury_Kick(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() name := "test_queue" @@ -478,7 +495,7 @@ func TestFifoQueue_Bury_Kick(t *testing.T) { func TestFifoQueue_Delete(t *testing.T) { var err error - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() name := "test_queue" @@ -530,7 +547,7 @@ func TestFifoQueue_Delete(t *testing.T) { } func TestFifoQueue_Release(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() name := "test_queue" @@ -590,7 +607,7 @@ func TestFifoQueue_Release(t *testing.T) { } func TestQueue_ReleaseAll(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() name := "test_queue" @@ -654,7 +671,7 @@ func TestQueue_ReleaseAll(t *testing.T) { } func TestTtlQueue(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() name := "test_queue" @@ -688,7 +705,7 @@ func TestTtlQueue(t *testing.T) { } func TestTtlQueue_Put(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() name := "test_queue" @@ -737,7 +754,7 @@ func TestTtlQueue_Put(t *testing.T) { } func TestUtube_Put(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() name := "test_utube" @@ -810,7 +827,7 @@ func TestUtube_Put(t *testing.T) { } func TestTask_Touch(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() tests := []struct { @@ -898,12 +915,10 @@ func runTestMain(m *testing.M) int { inst, err := test_helpers.StartTarantool(test_helpers.StartOpts{ InitScript: "testdata/config.lua", Listen: server, - User: opts.User, - Pass: opts.Pass, WaitStart: 100 * time.Millisecond, ConnectRetry: 10, RetryTimeout: 500 * time.Millisecond, - }) + }, dialer) if err != nil { log.Fatalf("Failed to prepare test tarantool: %s", err) @@ -913,12 +928,18 @@ func runTestMain(m *testing.M) int { poolOpts := test_helpers.StartOpts{ InitScript: "testdata/pool.lua", - User: opts.User, - Pass: opts.Pass, WaitStart: 3 * time.Second, // replication_timeout * 3 ConnectRetry: -1, } - instances, err = test_helpers.StartTarantoolInstances(serversPool, nil, poolOpts) + poolAddrs := make([]string, 0) + for addr := range serversPool { + poolAddrs = append(poolAddrs, addr) + } + instances, err = test_helpers.StartTarantoolInstances(poolAddrs, nil, poolOpts, + func(server string) Dialer { + return TtDialer{Address: server, User: user, Password: pass} + }, + ) if err != nil { log.Printf("Failed to prepare test tarantool pool: %s", err) @@ -930,11 +951,12 @@ func runTestMain(m *testing.M) int { for i := 0; i < 10; i++ { // We need to skip bootstrap errors and to make sure that cluster is // configured. - roles := []bool{false, true} + roles := map[string]bool{ + poolAddrs[0]: false, + poolAddrs[1]: true, + } connOpts := Opts{ Timeout: 500 * time.Millisecond, - User: "test", - Pass: "test", } err = test_helpers.SetClusterRO(serversPool, connOpts, roles) diff --git a/settings/example_test.go b/settings/example_test.go index 29be33bfe..e306a950e 100644 --- a/settings/example_test.go +++ b/settings/example_test.go @@ -10,10 +10,10 @@ import ( "github.com/tarantool/go-tarantool/v2/test_helpers" ) -func example_connect(opts tarantool.Opts) *tarantool.Connection { +func example_connect(dialer tarantool.Dialer, opts tarantool.Opts) *tarantool.Connection { ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) defer cancel() - conn, err := tarantool.Connect(ctx, server, opts) + conn, err := tarantool.Connect(ctx, dialer, opts) if err != nil { panic("Connection is not established: " + err.Error()) } @@ -25,7 +25,7 @@ func Example_sqlFullColumnNames() { var err error var isLess bool - conn := example_connect(opts) + conn := example_connect(dialer, opts) defer conn.Close() // Tarantool supports session settings since version 2.3.1 diff --git a/settings/tarantool_test.go b/settings/tarantool_test.go index 2f7e01442..dfc04afd1 100644 --- a/settings/tarantool_test.go +++ b/settings/tarantool_test.go @@ -18,10 +18,13 @@ import ( var isSettingsSupported = false var server = "127.0.0.1:3013" +var dialer = tarantool.TtDialer{ + Address: server, + User: "test", + Password: "test", +} var opts = tarantool.Opts{ Timeout: 5 * time.Second, - User: "test", - Pass: "test", } func skipIfSettingsUnsupported(t *testing.T) { @@ -52,7 +55,7 @@ func TestErrorMarshalingEnabledSetting(t *testing.T) { var resp *tarantool.Response var err error - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() // Disable receiving box.error as MP_EXT 3. @@ -101,7 +104,7 @@ func TestSQLDefaultEngineSetting(t *testing.T) { var resp *tarantool.Response var err error - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() // Set default SQL "CREATE TABLE" engine to "vinyl". @@ -164,7 +167,7 @@ func TestSQLDeferForeignKeysSetting(t *testing.T) { var resp *tarantool.Response var err error - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() // Create a parent space. @@ -237,7 +240,7 @@ func TestSQLFullColumnNamesSetting(t *testing.T) { var resp *tarantool.Response var err error - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() // Create a space. @@ -299,7 +302,7 @@ func TestSQLFullMetadataSetting(t *testing.T) { var resp *tarantool.Response var err error - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() // Create a space. @@ -360,7 +363,7 @@ func TestSQLParserDebugSetting(t *testing.T) { var resp *tarantool.Response var err error - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() // Disable parser debug mode. @@ -398,7 +401,7 @@ func TestSQLRecursiveTriggersSetting(t *testing.T) { var resp *tarantool.Response var err error - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() // Create a space. @@ -470,7 +473,7 @@ func TestSQLReverseUnorderedSelectsSetting(t *testing.T) { var resp *tarantool.Response var err error - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() // Create a space. @@ -549,7 +552,7 @@ func TestSQLSelectDebugSetting(t *testing.T) { var resp *tarantool.Response var err error - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() // Disable select debug mode. @@ -586,7 +589,7 @@ func TestSQLVDBEDebugSetting(t *testing.T) { var resp *tarantool.Response var err error - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() // Disable VDBE debug mode. @@ -623,7 +626,7 @@ func TestSessionSettings(t *testing.T) { var resp *tarantool.Response var err error - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() // Set some settings values. @@ -670,12 +673,10 @@ func runTestMain(m *testing.M) int { inst, err := test_helpers.StartTarantool(test_helpers.StartOpts{ InitScript: "testdata/config.lua", Listen: server, - User: opts.User, - Pass: opts.Pass, WaitStart: 100 * time.Millisecond, ConnectRetry: 10, RetryTimeout: 500 * time.Millisecond, - }) + }, dialer) if err != nil { log.Fatalf("Failed to prepare test tarantool: %s", err) diff --git a/shutdown_test.go b/shutdown_test.go index cf4894344..329c8a95c 100644 --- a/shutdown_test.go +++ b/shutdown_test.go @@ -2,7 +2,6 @@ // +build linux darwin,!cgo // Use OS build flags since signals are system-dependent. - package tarantool_test import ( @@ -20,19 +19,23 @@ import ( ) var shtdnServer = "127.0.0.1:3014" +var shtdnDialer = TtDialer{ + Address: shtdnServer, + User: dialer.User, + Password: dialer.Password, + RequiredProtocolInfo: ProtocolInfo{ + Features: []iproto.Feature{iproto.IPROTO_FEATURE_WATCHERS}, + }, +} + var shtdnClntOpts = Opts{ - User: opts.User, - Pass: opts.Pass, - Timeout: 20 * time.Second, - Reconnect: 500 * time.Millisecond, - MaxReconnects: 10, - RequiredProtocolInfo: ProtocolInfo{Features: []iproto.Feature{iproto.IPROTO_FEATURE_WATCHERS}}, + Timeout: 20 * time.Second, + Reconnect: 500 * time.Millisecond, + MaxReconnects: 10, } var shtdnSrvOpts = test_helpers.StartOpts{ InitScript: "config.lua", Listen: shtdnServer, - User: shtdnClntOpts.User, - Pass: shtdnClntOpts.Pass, WaitStart: 100 * time.Millisecond, ConnectRetry: 10, RetryTimeout: 500 * time.Millisecond, @@ -135,11 +138,11 @@ func TestGracefulShutdown(t *testing.T) { var conn *Connection var err error - inst, err = test_helpers.StartTarantool(shtdnSrvOpts) + inst, err = test_helpers.StartTarantool(shtdnSrvOpts, shtdnDialer) require.Nil(t, err) defer test_helpers.StopTarantoolWithCleanup(inst) - conn = test_helpers.ConnectWithValidation(t, shtdnServer, shtdnClntOpts) + conn = test_helpers.ConnectWithValidation(t, shtdnDialer, shtdnClntOpts) defer conn.Close() testGracefulShutdown(t, conn, &inst) @@ -147,16 +150,16 @@ func TestGracefulShutdown(t *testing.T) { func TestCloseGraceful(t *testing.T) { opts := Opts{ - User: shtdnClntOpts.User, - Pass: shtdnClntOpts.Pass, Timeout: shtdnClntOpts.Timeout, } + testDialer := shtdnDialer.Clone() + testDialer.RequiredProtocolInfo = ProtocolInfo{} - inst, err := test_helpers.StartTarantool(shtdnSrvOpts) + inst, err := test_helpers.StartTarantool(shtdnSrvOpts, testDialer) require.Nil(t, err) defer test_helpers.StopTarantoolWithCleanup(inst) - conn := test_helpers.ConnectWithValidation(t, shtdnServer, opts) + conn := test_helpers.ConnectWithValidation(t, testDialer, opts) defer conn.Close() // Send request with sleep. @@ -193,11 +196,11 @@ func TestGracefulShutdownWithReconnect(t *testing.T) { var inst test_helpers.TarantoolInstance var err error - inst, err = test_helpers.StartTarantool(shtdnSrvOpts) + inst, err = test_helpers.StartTarantool(shtdnSrvOpts, shtdnDialer) require.Nil(t, err) defer test_helpers.StopTarantoolWithCleanup(inst) - conn := test_helpers.ConnectWithValidation(t, shtdnServer, shtdnClntOpts) + conn := test_helpers.ConnectWithValidation(t, shtdnDialer, shtdnClntOpts) defer conn.Close() testGracefulShutdown(t, conn, &inst) @@ -214,19 +217,20 @@ func TestGracefulShutdownWithReconnect(t *testing.T) { func TestNoGracefulShutdown(t *testing.T) { // No watchers = no graceful shutdown. - noShtdnClntOpts := shtdnClntOpts.Clone() - noShtdnClntOpts.RequiredProtocolInfo = ProtocolInfo{} + noSthdClntOpts := opts + noShtdDialer := shtdnDialer.Clone() + noShtdDialer.RequiredProtocolInfo = ProtocolInfo{} test_helpers.SkipIfWatchersSupported(t) var inst test_helpers.TarantoolInstance var conn *Connection var err error - inst, err = test_helpers.StartTarantool(shtdnSrvOpts) + inst, err = test_helpers.StartTarantool(shtdnSrvOpts, noShtdDialer) require.Nil(t, err) defer test_helpers.StopTarantoolWithCleanup(inst) - conn = test_helpers.ConnectWithValidation(t, shtdnServer, noShtdnClntOpts) + conn = test_helpers.ConnectWithValidation(t, noShtdDialer, noSthdClntOpts) defer conn.Close() evalSleep := 10 // in seconds @@ -274,11 +278,11 @@ func TestGracefulShutdownRespectsClose(t *testing.T) { var conn *Connection var err error - inst, err = test_helpers.StartTarantool(shtdnSrvOpts) + inst, err = test_helpers.StartTarantool(shtdnSrvOpts, shtdnDialer) require.Nil(t, err) defer test_helpers.StopTarantoolWithCleanup(inst) - conn = test_helpers.ConnectWithValidation(t, shtdnServer, shtdnClntOpts) + conn = test_helpers.ConnectWithValidation(t, shtdnDialer, shtdnClntOpts) defer conn.Close() // Create a helper watcher to ensure that async @@ -354,11 +358,11 @@ func TestGracefulShutdownNotRacesWithRequestReconnect(t *testing.T) { var conn *Connection var err error - inst, err = test_helpers.StartTarantool(shtdnSrvOpts) + inst, err = test_helpers.StartTarantool(shtdnSrvOpts, shtdnDialer) require.Nil(t, err) defer test_helpers.StopTarantoolWithCleanup(inst) - conn = test_helpers.ConnectWithValidation(t, shtdnServer, shtdnClntOpts) + conn = test_helpers.ConnectWithValidation(t, shtdnDialer, shtdnClntOpts) defer conn.Close() // Create a helper watcher to ensure that async @@ -425,11 +429,11 @@ func TestGracefulShutdownCloseConcurrent(t *testing.T) { var err error var srvShtdnStart, srvShtdnFinish time.Time - inst, err = test_helpers.StartTarantool(shtdnSrvOpts) + inst, err = test_helpers.StartTarantool(shtdnSrvOpts, shtdnDialer) require.Nil(t, err) defer test_helpers.StopTarantoolWithCleanup(inst) - conn := test_helpers.ConnectWithValidation(t, shtdnServer, shtdnClntOpts) + conn := test_helpers.ConnectWithValidation(t, shtdnDialer, shtdnClntOpts) defer conn.Close() // Create a helper watcher to ensure that async @@ -466,7 +470,7 @@ func TestGracefulShutdownCloseConcurrent(t *testing.T) { // Do not wait till Tarantool register out watcher, // test everything is ok even on async. - conn, err := Connect(ctx, shtdnServer, shtdnClntOpts) + conn, err := Connect(ctx, shtdnDialer, shtdnClntOpts) if err != nil { t.Errorf("Failed to connect: %s", err) } else { @@ -515,11 +519,11 @@ func TestGracefulShutdownConcurrent(t *testing.T) { var err error var srvShtdnStart, srvShtdnFinish time.Time - inst, err = test_helpers.StartTarantool(shtdnSrvOpts) + inst, err = test_helpers.StartTarantool(shtdnSrvOpts, shtdnDialer) require.Nil(t, err) defer test_helpers.StopTarantoolWithCleanup(inst) - conn := test_helpers.ConnectWithValidation(t, shtdnServer, shtdnClntOpts) + conn := test_helpers.ConnectWithValidation(t, shtdnDialer, shtdnClntOpts) defer conn.Close() // Set a big timeout so it would be easy to differ @@ -542,7 +546,7 @@ func TestGracefulShutdownConcurrent(t *testing.T) { go func(i int) { defer caseWg.Done() - conn := test_helpers.ConnectWithValidation(t, shtdnServer, shtdnClntOpts) + conn := test_helpers.ConnectWithValidation(t, shtdnDialer, shtdnClntOpts) defer conn.Close() // Create a helper watcher to ensure that async diff --git a/ssl_test.go b/ssl_test.go index 65be85504..44f42a93e 100644 --- a/ssl_test.go +++ b/ssl_test.go @@ -4,163 +4,97 @@ package tarantool_test import ( - "context" - "errors" "fmt" - "io/ioutil" - "net" "os" - "strconv" "strings" "testing" "time" - "github.com/tarantool/go-openssl" . "github.com/tarantool/go-tarantool/v2" "github.com/tarantool/go-tarantool/v2/test_helpers" ) -const sslHost = "127.0.0.1" -const tntHost = "127.0.0.1:3014" - -func serverSsl(network, address string, opts SslOpts) (net.Listener, error) { - ctx, err := SslCreateContext(opts) - if err != nil { - return nil, errors.New("Unable to create SSL context: " + err.Error()) - } - - return openssl.Listen(network, address, ctx.(*openssl.Ctx)) +type sslOpts struct { + keyFile string + certFile string + caFile string + ciphers string + password string + passwordFile string } -func serverSslAccept(l net.Listener) (<-chan string, <-chan error) { - message := make(chan string, 1) - errors := make(chan error, 1) - - go func() { - conn, err := l.Accept() - if err != nil { - errors <- err - } else { - bytes, err := ioutil.ReadAll(conn) - if err != nil { - errors <- err - } else { - message <- string(bytes) - } - conn.Close() - } - - close(message) - close(errors) - }() - - return message, errors -} - -func serverSslRecv(msgs <-chan string, errs <-chan error) (string, error) { - return <-msgs, <-errs -} - -func clientSsl(ctx context.Context, network, address string, - opts SslOpts) (net.Conn, error) { - return SslDialContext(ctx, network, address, opts) -} - -func createClientServerSsl(ctx context.Context, t testing.TB, serverOpts, - clientOpts SslOpts) (net.Listener, net.Conn, <-chan string, <-chan error, error) { - t.Helper() - - l, err := serverSsl("tcp", sslHost+":0", serverOpts) - if err != nil { - t.Fatalf("Unable to create server, error %q", err.Error()) - } - - msgs, errs := serverSslAccept(l) - - port := l.Addr().(*net.TCPAddr).Port - c, err := clientSsl(ctx, "tcp", sslHost+":"+strconv.Itoa(port), clientOpts) - - return l, c, msgs, errs, err -} - -func createClientServerSslOk(ctx context.Context, t testing.TB, serverOpts, - clientOpts SslOpts) (net.Listener, net.Conn, <-chan string, <-chan error) { - t.Helper() - - l, c, msgs, errs, err := createClientServerSsl(ctx, t, serverOpts, clientOpts) - if err != nil { - t.Fatalf("Unable to create client, error %q", err.Error()) - } - - return l, c, msgs, errs -} +const tntHost = "127.0.0.1:3014" -func serverTnt(serverOpts SslOpts, auth Auth) (test_helpers.TarantoolInstance, error) { +func serverTnt(serverOpts sslOpts, auth Auth) (test_helpers.TarantoolInstance, error) { listen := tntHost + "?transport=ssl&" - key := serverOpts.KeyFile + key := serverOpts.keyFile if key != "" { listen += fmt.Sprintf("ssl_key_file=%s&", key) } - cert := serverOpts.CertFile + cert := serverOpts.certFile if cert != "" { listen += fmt.Sprintf("ssl_cert_file=%s&", cert) } - ca := serverOpts.CaFile + ca := serverOpts.caFile if ca != "" { listen += fmt.Sprintf("ssl_ca_file=%s&", ca) } - ciphers := serverOpts.Ciphers + ciphers := serverOpts.ciphers if ciphers != "" { listen += fmt.Sprintf("ssl_ciphers=%s&", ciphers) } - password := serverOpts.Password + password := serverOpts.password if password != "" { listen += fmt.Sprintf("ssl_password=%s&", password) } - passwordFile := serverOpts.PasswordFile + passwordFile := serverOpts.passwordFile if passwordFile != "" { listen += fmt.Sprintf("ssl_password_file=%s&", passwordFile) } listen = listen[:len(listen)-1] - return test_helpers.StartTarantool(test_helpers.StartOpts{ - Auth: auth, - InitScript: "config.lua", - Listen: listen, - SslCertsDir: "testdata", - ClientServer: tntHost, - ClientTransport: "ssl", - ClientSsl: serverOpts, - User: "test", - Pass: "test", - WaitStart: 100 * time.Millisecond, - ConnectRetry: 10, - RetryTimeout: 500 * time.Millisecond, - }) + return test_helpers.StartTarantool( + test_helpers.StartOpts{ + Auth: auth, + InitScript: "config.lua", + Listen: listen, + SslCertsDir: "testdata", + WaitStart: 100 * time.Millisecond, + ConnectRetry: 10, + RetryTimeout: 500 * time.Millisecond, + }, + OpenSslDialer{ + Address: tntHost, + Auth: auth, + User: "test", + Password: "test", + KeyFile: serverOpts.keyFile, + CertFile: serverOpts.certFile, + CaFile: serverOpts.caFile, + Ciphers: serverOpts.ciphers, + SslPassword: serverOpts.password, + PasswordFile: serverOpts.passwordFile, + }, + ) } func serverTntStop(inst test_helpers.TarantoolInstance) { test_helpers.StopTarantoolWithCleanup(inst) } -func checkTntConn(clientOpts SslOpts) error { +func checkTntConn(dialer Dialer) error { ctx, cancel := test_helpers.GetConnectContext() defer cancel() - conn, err := Connect(ctx, tntHost, Opts{ - Auth: AutoAuth, + conn, err := Connect(ctx, dialer, Opts{ Timeout: 500 * time.Millisecond, - User: "test", - Pass: "test", SkipSchema: true, - Transport: "ssl", - Ssl: clientOpts, }) if err != nil { return err @@ -169,38 +103,7 @@ func checkTntConn(clientOpts SslOpts) error { return nil } -func assertConnectionSslFail(ctx context.Context, t testing.TB, serverOpts, - clientOpts SslOpts) { - t.Helper() - - l, c, _, _, err := createClientServerSsl(ctx, t, serverOpts, clientOpts) - l.Close() - if err == nil { - c.Close() - t.Errorf("An unexpected connection to the server.") - } -} - -func assertConnectionSslOk(ctx context.Context, t testing.TB, serverOpts, - clientOpts SslOpts) { - t.Helper() - - l, c, msgs, errs := createClientServerSslOk(ctx, t, serverOpts, clientOpts) - const message = "any test string" - c.Write([]byte(message)) - c.Close() - - recv, err := serverSslRecv(msgs, errs) - l.Close() - - if err != nil { - t.Errorf("An unexpected server error: %q", err.Error()) - } else if recv != message { - t.Errorf("An unexpected server message: %q, expected %q", recv, message) - } -} - -func assertConnectionTntFail(t testing.TB, serverOpts, clientOpts SslOpts) { +func assertConnectionTntFail(t testing.TB, serverOpts sslOpts, dialer OpenSslDialer) { t.Helper() inst, err := serverTnt(serverOpts, AutoAuth) @@ -209,13 +112,13 @@ func assertConnectionTntFail(t testing.TB, serverOpts, clientOpts SslOpts) { t.Fatalf("An unexpected server error %q", err.Error()) } - err = checkTntConn(clientOpts) + err = checkTntConn(dialer) if err == nil { t.Errorf("An unexpected connection to the server") } } -func assertConnectionTntOk(t testing.TB, serverOpts, clientOpts SslOpts) { +func assertConnectionTntOk(t testing.TB, serverOpts sslOpts, dialer OpenSslDialer) { t.Helper() inst, err := serverTnt(serverOpts, AutoAuth) @@ -224,7 +127,7 @@ func assertConnectionTntOk(t testing.TB, serverOpts, clientOpts SslOpts) { t.Fatalf("An unexpected server error %q", err.Error()) } - err = checkTntConn(clientOpts) + err = checkTntConn(dialer) if err != nil { t.Errorf("An unexpected connection error %q", err.Error()) } @@ -233,8 +136,8 @@ func assertConnectionTntOk(t testing.TB, serverOpts, clientOpts SslOpts) { type test struct { name string ok bool - serverOpts SslOpts - clientOpts SslOpts + serverOpts sslOpts + clientOpts sslOpts } /* @@ -257,361 +160,361 @@ var tests = []test{ { "key_crt_server", true, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", }, - SslOpts{}, + sslOpts{}, }, { "key_crt_server_and_client", true, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", }, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", }, }, { "key_crt_ca_server", false, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", }, - SslOpts{}, + sslOpts{}, }, { "key_crt_ca_server_key_crt_client", true, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", }, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", }, }, { "key_crt_ca_server_and_client", true, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", }, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", }, }, { "key_crt_ca_server_and_client_invalid_path_key", false, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", }, - SslOpts{ - KeyFile: "any_invalid_path", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", + sslOpts{ + keyFile: "any_invalid_path", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", }, }, { "key_crt_ca_server_and_client_invalid_path_crt", false, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", }, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "any_invalid_path", - CaFile: "testdata/ca.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "any_invalid_path", + caFile: "testdata/ca.crt", }, }, { "key_crt_ca_server_and_client_invalid_path_ca", false, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", }, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "any_invalid_path", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "any_invalid_path", }, }, { "key_crt_ca_server_and_client_empty_key", false, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", }, - SslOpts{ - KeyFile: "testdata/empty", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", + sslOpts{ + keyFile: "testdata/empty", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", }, }, { "key_crt_ca_server_and_client_empty_crt", false, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", }, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/empty", - CaFile: "testdata/ca.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/empty", + caFile: "testdata/ca.crt", }, }, { "key_crt_ca_server_and_client_empty_ca", false, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", }, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/empty", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/empty", }, }, { "key_crt_server_and_key_crt_ca_client", true, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", }, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", }, }, { "key_crt_ca_ciphers_server_key_crt_ca_client", true, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - Ciphers: "ECDHE-RSA-AES256-GCM-SHA384", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", + ciphers: "ECDHE-RSA-AES256-GCM-SHA384", }, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", }, }, { "key_crt_ca_ciphers_server_and_client", true, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - Ciphers: "ECDHE-RSA-AES256-GCM-SHA384", - }, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - Ciphers: "ECDHE-RSA-AES256-GCM-SHA384", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", + ciphers: "ECDHE-RSA-AES256-GCM-SHA384", + }, + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", + ciphers: "ECDHE-RSA-AES256-GCM-SHA384", }, }, { "non_equal_ciphers_client", false, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - Ciphers: "ECDHE-RSA-AES256-GCM-SHA384", - }, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - Ciphers: "TLS_AES_128_GCM_SHA256", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", + ciphers: "ECDHE-RSA-AES256-GCM-SHA384", + }, + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", + ciphers: "TLS_AES_128_GCM_SHA256", }, }, { "pass_key_encrypt_client", true, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", }, - SslOpts{ - KeyFile: "testdata/localhost.enc.key", - CertFile: "testdata/localhost.crt", - Password: "mysslpassword", + sslOpts{ + keyFile: "testdata/localhost.enc.key", + certFile: "testdata/localhost.crt", + password: "mysslpassword", }, }, { "passfile_key_encrypt_client", true, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", }, - SslOpts{ - KeyFile: "testdata/localhost.enc.key", - CertFile: "testdata/localhost.crt", - PasswordFile: "testdata/passwords", + sslOpts{ + keyFile: "testdata/localhost.enc.key", + certFile: "testdata/localhost.crt", + passwordFile: "testdata/passwords", }, }, { "pass_and_passfile_key_encrypt_client", true, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", }, - SslOpts{ - KeyFile: "testdata/localhost.enc.key", - CertFile: "testdata/localhost.crt", - Password: "mysslpassword", - PasswordFile: "testdata/passwords", + sslOpts{ + keyFile: "testdata/localhost.enc.key", + certFile: "testdata/localhost.crt", + password: "mysslpassword", + passwordFile: "testdata/passwords", }, }, { "inv_pass_and_passfile_key_encrypt_client", true, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", }, - SslOpts{ - KeyFile: "testdata/localhost.enc.key", - CertFile: "testdata/localhost.crt", - Password: "invalidpassword", - PasswordFile: "testdata/passwords", + sslOpts{ + keyFile: "testdata/localhost.enc.key", + certFile: "testdata/localhost.crt", + password: "invalidpassword", + passwordFile: "testdata/passwords", }, }, { "pass_and_inv_passfile_key_encrypt_client", true, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", }, - SslOpts{ - KeyFile: "testdata/localhost.enc.key", - CertFile: "testdata/localhost.crt", - Password: "mysslpassword", - PasswordFile: "testdata/invalidpasswords", + sslOpts{ + keyFile: "testdata/localhost.enc.key", + certFile: "testdata/localhost.crt", + password: "mysslpassword", + passwordFile: "testdata/invalidpasswords", }, }, { "pass_and_not_existing_passfile_key_encrypt_client", true, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", }, - SslOpts{ - KeyFile: "testdata/localhost.enc.key", - CertFile: "testdata/localhost.crt", - Password: "mysslpassword", - PasswordFile: "testdata/notafile", + sslOpts{ + keyFile: "testdata/localhost.enc.key", + certFile: "testdata/localhost.crt", + password: "mysslpassword", + passwordFile: "testdata/notafile", }, }, { "inv_pass_and_inv_passfile_key_encrypt_client", false, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", }, - SslOpts{ - KeyFile: "testdata/localhost.enc.key", - CertFile: "testdata/localhost.crt", - Password: "invalidpassword", - PasswordFile: "testdata/invalidpasswords", + sslOpts{ + keyFile: "testdata/localhost.enc.key", + certFile: "testdata/localhost.crt", + password: "invalidpassword", + passwordFile: "testdata/invalidpasswords", }, }, { "not_existing_passfile_key_encrypt_client", false, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", }, - SslOpts{ - KeyFile: "testdata/localhost.enc.key", - CertFile: "testdata/localhost.crt", - PasswordFile: "testdata/notafile", + sslOpts{ + keyFile: "testdata/localhost.enc.key", + certFile: "testdata/localhost.crt", + passwordFile: "testdata/notafile", }, }, { "no_pass_key_encrypt_client", false, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", }, - SslOpts{ - KeyFile: "testdata/localhost.enc.key", - CertFile: "testdata/localhost.crt", + sslOpts{ + keyFile: "testdata/localhost.enc.key", + certFile: "testdata/localhost.crt", }, }, { "pass_key_non_encrypt_client", true, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", }, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - Password: "invalidpassword", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + password: "invalidpassword", }, }, { "passfile_key_non_encrypt_client", true, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + caFile: "testdata/ca.crt", }, - SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - PasswordFile: "testdata/invalidpasswords", + sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", + passwordFile: "testdata/invalidpasswords", }, }, } @@ -622,67 +525,40 @@ func isTestTntSsl() bool { (testTntSsl == "1" || strings.ToUpper(testTntSsl) == "TRUE") } +func makeOpenSslDialer(opts sslOpts) OpenSslDialer { + return OpenSslDialer{ + Address: tntHost, + User: "test", + Password: "test", + KeyFile: opts.keyFile, + CertFile: opts.certFile, + CaFile: opts.caFile, + Ciphers: opts.ciphers, + SslPassword: opts.password, + PasswordFile: opts.passwordFile, + } +} + func TestSslOpts(t *testing.T) { isTntSsl := isTestTntSsl() for _, test := range tests { - var ctx context.Context - var cancel context.CancelFunc - ctx, cancel = test_helpers.GetConnectContext() - if test.ok { - t.Run("ok_ssl_"+test.name, func(t *testing.T) { - assertConnectionSslOk(ctx, t, test.serverOpts, test.clientOpts) - }) - } else { - t.Run("fail_ssl_"+test.name, func(t *testing.T) { - assertConnectionSslFail(ctx, t, test.serverOpts, test.clientOpts) - }) - } - cancel() if !isTntSsl { continue } + dialer := makeOpenSslDialer(test.clientOpts) if test.ok { t.Run("ok_tnt_"+test.name, func(t *testing.T) { - assertConnectionTntOk(t, test.serverOpts, test.clientOpts) + assertConnectionTntOk(t, test.serverOpts, dialer) }) } else { t.Run("fail_tnt_"+test.name, func(t *testing.T) { - assertConnectionTntFail(t, test.serverOpts, test.clientOpts) + assertConnectionTntFail(t, test.serverOpts, dialer) }) } } } -func TestSslDialContextCancel(t *testing.T) { - serverOpts := SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - Ciphers: "ECDHE-RSA-AES256-GCM-SHA384", - } - clientOpts := SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - Ciphers: "ECDHE-RSA-AES256-GCM-SHA384", - } - ctx, cancel := context.WithCancel(context.Background()) - cancel() - - l, c, _, _, err := createClientServerSsl(ctx, t, serverOpts, clientOpts) - l.Close() - - if err == nil { - c.Close() - t.Fatalf("Expected error, dial was not canceled") - } - if !strings.Contains(err.Error(), "operation was canceled") { - t.Fatalf("Unexpected error, expected to contain %s, got %v", - "operation was canceled", err) - } -} - func TestOpts_PapSha256Auth(t *testing.T) { isTntSsl := isTestTntSsl() if !isTntSsl { @@ -694,12 +570,12 @@ func TestOpts_PapSha256Auth(t *testing.T) { t.Fatalf("Could not check Tarantool version.") } if isLess { - t.Skip("Skipping test for Tarantoo without pap-sha256 support") + t.Skip("Skipping test for Tarantool without pap-sha256 support") } - sslOpts := SslOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", + sslOpts := sslOpts{ + keyFile: "testdata/localhost.key", + certFile: "testdata/localhost.crt", } inst, err := serverTnt(sslOpts, PapSha256Auth) @@ -708,14 +584,20 @@ func TestOpts_PapSha256Auth(t *testing.T) { t.Fatalf("An unexpected server error %q", err.Error()) } - clientOpts := opts - clientOpts.Transport = "ssl" - clientOpts.Ssl = sslOpts - clientOpts.Auth = PapSha256Auth - conn := test_helpers.ConnectWithValidation(t, tntHost, clientOpts) + client := OpenSslDialer{ + Address: tntHost, + Auth: PapSha256Auth, + User: "test", + Password: "test", + RequiredProtocolInfo: ProtocolInfo{}, + KeyFile: sslOpts.keyFile, + CertFile: sslOpts.certFile, + } + + conn := test_helpers.ConnectWithValidation(t, client, opts) conn.Close() - clientOpts.Auth = AutoAuth - conn = test_helpers.ConnectWithValidation(t, tntHost, clientOpts) + client.Auth = AutoAuth + conn = test_helpers.ConnectWithValidation(t, client, opts) conn.Close() } diff --git a/tarantool_test.go b/tarantool_test.go index 0ad365286..3f8013677 100644 --- a/tarantool_test.go +++ b/tarantool_test.go @@ -27,13 +27,17 @@ import ( var startOpts test_helpers.StartOpts = test_helpers.StartOpts{ InitScript: "config.lua", Listen: server, - User: opts.User, - Pass: opts.Pass, WaitStart: 100 * time.Millisecond, ConnectRetry: 10, RetryTimeout: 500 * time.Millisecond, } +var dialer = TtDialer{ + Address: server, + User: "test", + Password: "test", +} + type Member struct { Name string Nonce string @@ -78,8 +82,6 @@ var indexNo = uint32(0) var indexName = "primary" var opts = Opts{ Timeout: 5 * time.Second, - User: "test", - Pass: "test", //Concurrency: 32, //RateLimit: 4*1024, } @@ -89,7 +91,7 @@ const N = 500 func BenchmarkClientSerial(b *testing.B) { var err error - conn := test_helpers.ConnectWithValidation(b, server, opts) + conn := test_helpers.ConnectWithValidation(b, dialer, opts) defer conn.Close() _, err = conn.Replace(spaceNo, []interface{}{uint(1111), "hello", "world"}) @@ -109,7 +111,7 @@ func BenchmarkClientSerial(b *testing.B) { func BenchmarkClientSerialRequestObject(b *testing.B) { var err error - conn := test_helpers.ConnectWithValidation(b, server, opts) + conn := test_helpers.ConnectWithValidation(b, dialer, opts) defer conn.Close() _, err = conn.Replace(spaceNo, []interface{}{uint(1111), "hello", "world"}) @@ -136,7 +138,7 @@ func BenchmarkClientSerialRequestObject(b *testing.B) { func BenchmarkClientSerialRequestObjectWithContext(b *testing.B) { var err error - conn := test_helpers.ConnectWithValidation(b, server, opts) + conn := test_helpers.ConnectWithValidation(b, dialer, opts) defer conn.Close() _, err = conn.Replace(spaceNo, []interface{}{uint(1111), "hello", "world"}) @@ -165,7 +167,7 @@ func BenchmarkClientSerialRequestObjectWithContext(b *testing.B) { func BenchmarkClientSerialTyped(b *testing.B) { var err error - conn := test_helpers.ConnectWithValidation(b, server, opts) + conn := test_helpers.ConnectWithValidation(b, dialer, opts) defer conn.Close() _, err = conn.Replace(spaceNo, []interface{}{uint(1111), "hello", "world"}) @@ -186,7 +188,7 @@ func BenchmarkClientSerialTyped(b *testing.B) { func BenchmarkClientSerialSQL(b *testing.B) { test_helpers.SkipIfSQLUnsupported(b) - conn := test_helpers.ConnectWithValidation(b, server, opts) + conn := test_helpers.ConnectWithValidation(b, dialer, opts) defer conn.Close() _, err := conn.Replace("SQL_TEST", []interface{}{uint(1111), "hello", "world"}) @@ -208,7 +210,7 @@ func BenchmarkClientSerialSQL(b *testing.B) { func BenchmarkClientSerialSQLPrepared(b *testing.B) { test_helpers.SkipIfSQLUnsupported(b) - conn := test_helpers.ConnectWithValidation(b, server, opts) + conn := test_helpers.ConnectWithValidation(b, dialer, opts) defer conn.Close() _, err := conn.Replace("SQL_TEST", []interface{}{uint(1111), "hello", "world"}) @@ -240,7 +242,7 @@ func BenchmarkClientSerialSQLPrepared(b *testing.B) { func BenchmarkClientFuture(b *testing.B) { var err error - conn := test_helpers.ConnectWithValidation(b, server, opts) + conn := test_helpers.ConnectWithValidation(b, dialer, opts) defer conn.Close() _, err = conn.Replace(spaceNo, []interface{}{uint(1111), "hello", "world"}) @@ -267,7 +269,7 @@ func BenchmarkClientFuture(b *testing.B) { func BenchmarkClientFutureTyped(b *testing.B) { var err error - conn := test_helpers.ConnectWithValidation(b, server, opts) + conn := test_helpers.ConnectWithValidation(b, dialer, opts) defer conn.Close() _, err = conn.Replace(spaceNo, []interface{}{uint(1111), "hello", "world"}) @@ -297,7 +299,7 @@ func BenchmarkClientFutureTyped(b *testing.B) { func BenchmarkClientFutureParallel(b *testing.B) { var err error - conn := test_helpers.ConnectWithValidation(b, server, opts) + conn := test_helpers.ConnectWithValidation(b, dialer, opts) defer conn.Close() _, err = conn.Replace(spaceNo, []interface{}{uint(1111), "hello", "world"}) @@ -330,7 +332,7 @@ func BenchmarkClientFutureParallel(b *testing.B) { func BenchmarkClientFutureParallelTyped(b *testing.B) { var err error - conn := test_helpers.ConnectWithValidation(b, server, opts) + conn := test_helpers.ConnectWithValidation(b, dialer, opts) defer conn.Close() _, err = conn.Replace(spaceNo, []interface{}{uint(1111), "hello", "world"}) @@ -366,7 +368,7 @@ func BenchmarkClientFutureParallelTyped(b *testing.B) { } func BenchmarkClientParallel(b *testing.B) { - conn := test_helpers.ConnectWithValidation(b, server, opts) + conn := test_helpers.ConnectWithValidation(b, dialer, opts) defer conn.Close() _, err := conn.Replace(spaceNo, []interface{}{uint(1111), "hello", "world"}) @@ -387,7 +389,7 @@ func BenchmarkClientParallel(b *testing.B) { } func benchmarkClientParallelRequestObject(multiplier int, b *testing.B) { - conn := test_helpers.ConnectWithValidation(b, server, opts) + conn := test_helpers.ConnectWithValidation(b, dialer, opts) defer conn.Close() _, err := conn.Replace(spaceNo, []interface{}{uint(1111), "hello", "world"}) @@ -415,7 +417,7 @@ func benchmarkClientParallelRequestObject(multiplier int, b *testing.B) { } func benchmarkClientParallelRequestObjectWithContext(multiplier int, b *testing.B) { - conn := test_helpers.ConnectWithValidation(b, server, opts) + conn := test_helpers.ConnectWithValidation(b, dialer, opts) defer conn.Close() _, err := conn.Replace(spaceNo, []interface{}{uint(1111), "hello", "world"}) @@ -447,7 +449,7 @@ func benchmarkClientParallelRequestObjectWithContext(multiplier int, b *testing. } func benchmarkClientParallelRequestObjectMixed(multiplier int, b *testing.B) { - conn := test_helpers.ConnectWithValidation(b, server, opts) + conn := test_helpers.ConnectWithValidation(b, dialer, opts) defer conn.Close() _, err := conn.Replace(spaceNo, []interface{}{uint(1111), "hello", "world"}) @@ -486,7 +488,7 @@ func benchmarkClientParallelRequestObjectMixed(multiplier int, b *testing.B) { func BenchmarkClientParallelRequestObject(b *testing.B) { multipliers := []int{10, 50, 500, 1000} - conn := test_helpers.ConnectWithValidation(b, server, opts) + conn := test_helpers.ConnectWithValidation(b, dialer, opts) defer conn.Close() _, err := conn.Replace(spaceNo, []interface{}{uint(1111), "hello", "world"}) @@ -512,7 +514,7 @@ func BenchmarkClientParallelRequestObject(b *testing.B) { } func BenchmarkClientParallelMassive(b *testing.B) { - conn := test_helpers.ConnectWithValidation(b, server, opts) + conn := test_helpers.ConnectWithValidation(b, dialer, opts) defer conn.Close() _, err := conn.Replace(spaceNo, []interface{}{uint(1111), "hello", "world"}) @@ -547,7 +549,7 @@ func BenchmarkClientParallelMassive(b *testing.B) { } func BenchmarkClientParallelMassiveUntyped(b *testing.B) { - conn := test_helpers.ConnectWithValidation(b, server, opts) + conn := test_helpers.ConnectWithValidation(b, dialer, opts) defer conn.Close() _, err := conn.Replace(spaceNo, []interface{}{uint(1111), "hello", "world"}) @@ -582,7 +584,7 @@ func BenchmarkClientParallelMassiveUntyped(b *testing.B) { } func BenchmarkClientReplaceParallel(b *testing.B) { - conn := test_helpers.ConnectWithValidation(b, server, opts) + conn := test_helpers.ConnectWithValidation(b, dialer, opts) defer conn.Close() rSpaceNo, _, err := conn.Schema.ResolveSpaceIndex("test_perf", "secondary") @@ -602,7 +604,7 @@ func BenchmarkClientReplaceParallel(b *testing.B) { } func BenchmarkClientLargeSelectParallel(b *testing.B) { - conn := test_helpers.ConnectWithValidation(b, server, opts) + conn := test_helpers.ConnectWithValidation(b, dialer, opts) defer conn.Close() schema := conn.Schema @@ -627,7 +629,7 @@ func BenchmarkClientLargeSelectParallel(b *testing.B) { func BenchmarkClientParallelSQL(b *testing.B) { test_helpers.SkipIfSQLUnsupported(b) - conn := test_helpers.ConnectWithValidation(b, server, opts) + conn := test_helpers.ConnectWithValidation(b, dialer, opts) defer conn.Close() _, err := conn.Replace("SQL_TEST", []interface{}{uint(1111), "hello", "world"}) @@ -651,7 +653,7 @@ func BenchmarkClientParallelSQL(b *testing.B) { func BenchmarkClientParallelSQLPrepared(b *testing.B) { test_helpers.SkipIfSQLUnsupported(b) - conn := test_helpers.ConnectWithValidation(b, server, opts) + conn := test_helpers.ConnectWithValidation(b, dialer, opts) defer conn.Close() _, err := conn.Replace("SQL_TEST", []interface{}{uint(1111), "hello", "world"}) @@ -685,7 +687,7 @@ func BenchmarkClientParallelSQLPrepared(b *testing.B) { func BenchmarkSQLSerial(b *testing.B) { test_helpers.SkipIfSQLUnsupported(b) - conn := test_helpers.ConnectWithValidation(b, server, opts) + conn := test_helpers.ConnectWithValidation(b, dialer, opts) defer conn.Close() _, err := conn.Replace("SQL_TEST", []interface{}{uint(1111), "hello", "world"}) @@ -710,13 +712,12 @@ func TestTtDialer(t *testing.T) { ctx, cancel := test_helpers.GetConnectContext() defer cancel() - conn, err := TtDialer{}.Dial(ctx, server, DialOpts{}) + conn, err := dialer.Dial(ctx, DialOpts{}) require.Nil(err) require.NotNil(conn) defer conn.Close() - assert.Contains(conn.LocalAddr().String(), "127.0.0.1") - assert.Equal(server, conn.RemoteAddr().String()) + assert.Equal(server, conn.Addr().String()) assert.NotEqual("", conn.Greeting().Version) // Write IPROTO_PING. @@ -749,53 +750,8 @@ func TestTtDialer(t *testing.T) { assert.Equal([]byte{0x83, 0x00, 0xce, 0x00, 0x00, 0x00, 0x00}, buf[:7]) } -func TestTtDialer_worksWithConnection(t *testing.T) { - defaultOpts := opts - defaultOpts.Dialer = TtDialer{} - - conn := test_helpers.ConnectWithValidation(t, server, defaultOpts) - defer conn.Close() - - _, err := conn.Do(NewPingRequest()).Get() - assert.Nil(t, err) -} - -func TestOptsAuth_Default(t *testing.T) { - defaultOpts := opts - defaultOpts.Auth = AutoAuth - - conn := test_helpers.ConnectWithValidation(t, server, defaultOpts) - defer conn.Close() -} - -func TestOptsAuth_ChapSha1Auth(t *testing.T) { - chapSha1Opts := opts - chapSha1Opts.Auth = ChapSha1Auth - - conn := test_helpers.ConnectWithValidation(t, server, chapSha1Opts) - defer conn.Close() -} - -func TestOptsAuth_PapSha256AuthForbit(t *testing.T) { - papSha256Opts := opts - papSha256Opts.Auth = PapSha256Auth - - ctx, cancel := test_helpers.GetConnectContext() - defer cancel() - conn, err := Connect(ctx, server, papSha256Opts) - if err == nil { - t.Error("An error expected.") - conn.Close() - } - - if err.Error() != "failed to authenticate: forbidden to use pap-sha256"+ - " unless SSL is enabled for the connection" { - t.Errorf("An unexpected error: %s", err) - } -} - func TestFutureMultipleGetGetTyped(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() fut := conn.Call17Async("simple_concat", []interface{}{"1"}) @@ -833,7 +789,7 @@ func TestFutureMultipleGetGetTyped(t *testing.T) { } func TestFutureMultipleGetWithError(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() fut := conn.Call17Async("non_exist", []interface{}{"1"}) @@ -846,7 +802,7 @@ func TestFutureMultipleGetWithError(t *testing.T) { } func TestFutureMultipleGetTypedWithError(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() fut := conn.Call17Async("simple_concat", []interface{}{"1"}) @@ -875,7 +831,7 @@ func TestClient(t *testing.T) { var resp *Response var err error - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() // Ping @@ -1215,7 +1171,7 @@ func TestClient(t *testing.T) { } func TestClientSessionPush(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() var it ResponseIterator @@ -1515,7 +1471,7 @@ func TestSQL(t *testing.T) { }, } - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() for i, test := range testCases { @@ -1546,7 +1502,7 @@ func TestSQL(t *testing.T) { func TestSQLTyped(t *testing.T) { test_helpers.SkipIfSQLUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() mem := []Member{} @@ -1575,7 +1531,7 @@ func TestSQLBindings(t *testing.T) { var resp *Response - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() // test all types of supported bindings @@ -1677,7 +1633,7 @@ func TestStressSQL(t *testing.T) { var resp *Response - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() resp, err := conn.Execute(createTableQuery, []interface{}{}) @@ -1774,7 +1730,7 @@ func TestStressSQL(t *testing.T) { func TestNewPrepared(t *testing.T) { test_helpers.SkipIfSQLUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() stmt, err := conn.NewPrepared(selectNamedQuery2) @@ -1891,7 +1847,7 @@ func TestNewPreparedFromResponse(t *testing.T) { func TestSchema(t *testing.T) { var err error - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() // Schema @@ -2064,7 +2020,7 @@ func TestSchema(t *testing.T) { } func TestSchema_IsNullable(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() schema := conn.Schema @@ -2100,7 +2056,7 @@ func TestClientNamed(t *testing.T) { var resp *Response var err error - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() // Insert @@ -2197,7 +2153,7 @@ func TestClientRequestObjects(t *testing.T) { err error ) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() // Ping @@ -2591,7 +2547,7 @@ func testConnectionDoSelectRequestCheck(t *testing.T, } func TestConnectionDoSelectRequest(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() testConnectionDoSelectRequestPrepare(t, conn) @@ -2609,7 +2565,7 @@ func TestConnectionDoSelectRequest(t *testing.T) { func TestConnectionDoWatchOnceRequest(t *testing.T) { test_helpers.SkipIfWatchOnceUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() _, err := conn.Do(NewBroadcastRequest("hello").Value("world")).Get() @@ -2638,7 +2594,7 @@ func TestConnectionDoWatchOnceOnEmptyKey(t *testing.T) { return } - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() resp, err := conn.Do(NewWatchOnceRequest("notexists!")).Get() @@ -2656,7 +2612,7 @@ func TestConnectionDoWatchOnceOnEmptyKey(t *testing.T) { func TestConnectionDoSelectRequest_fetch_pos(t *testing.T) { test_helpers.SkipIfPaginationUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() testConnectionDoSelectRequestPrepare(t, conn) @@ -2675,7 +2631,7 @@ func TestConnectionDoSelectRequest_fetch_pos(t *testing.T) { func TestConnectDoSelectRequest_after_tuple(t *testing.T) { test_helpers.SkipIfPaginationUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() testConnectionDoSelectRequestPrepare(t, conn) @@ -2695,7 +2651,7 @@ func TestConnectDoSelectRequest_after_tuple(t *testing.T) { func TestConnectionDoSelectRequest_pagination_pos(t *testing.T) { test_helpers.SkipIfPaginationUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() testConnectionDoSelectRequestPrepare(t, conn) @@ -2719,7 +2675,7 @@ func TestConnection_Call(t *testing.T) { var resp *Response var err error - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() resp, err = conn.Call("simple_concat", []interface{}{"1"}) @@ -2735,7 +2691,7 @@ func TestCallRequest(t *testing.T) { var resp *Response var err error - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() req := NewCallRequest("simple_concat").Args([]interface{}{"1"}) @@ -2749,7 +2705,7 @@ func TestCallRequest(t *testing.T) { } func TestClientRequestObjectsWithNilContext(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() req := NewPingRequest().Context(nil) //nolint resp, err := conn.Do(req).Get() @@ -2765,7 +2721,7 @@ func TestClientRequestObjectsWithNilContext(t *testing.T) { } func TestClientRequestObjectsWithPassedCanceledContext(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() ctx, cancel := context.WithCancel(context.Background()) @@ -2807,7 +2763,7 @@ func (req *waitCtxRequest) Async() bool { func TestClientRequestObjectsWithContext(t *testing.T) { var err error - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() ctx, cancel := context.WithCancel(context.Background()) @@ -2846,7 +2802,7 @@ func TestClientRequestObjectsWithContext(t *testing.T) { func TestComplexStructs(t *testing.T) { var err error - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() tuple := Tuple2{Cid: 777, Orig: "orig", Members: []Member{{"lol", "", 1}, {"wut", "", 3}}} @@ -2877,7 +2833,7 @@ func TestComplexStructs(t *testing.T) { func TestStream_IdValues(t *testing.T) { test_helpers.SkipIfStreamsUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() cases := []uint64{ @@ -2914,7 +2870,7 @@ func TestStream_Commit(t *testing.T) { test_helpers.SkipIfStreamsUnsupported(t) - conn = test_helpers.ConnectWithValidation(t, server, opts) + conn = test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() stream, _ := conn.NewStream() @@ -3029,7 +2985,7 @@ func TestStream_Rollback(t *testing.T) { test_helpers.SkipIfStreamsUnsupported(t) - conn = test_helpers.ConnectWithValidation(t, server, opts) + conn = test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() stream, _ := conn.NewStream() @@ -3150,7 +3106,7 @@ func TestStream_TxnIsolationLevel(t *testing.T) { test_helpers.SkipIfStreamsUnsupported(t) - conn = test_helpers.ConnectWithValidation(t, server, opts) + conn = test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() stream, _ := conn.NewStream() @@ -3251,7 +3207,7 @@ func TestStream_DoWithClosedConn(t *testing.T) { test_helpers.SkipIfStreamsUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) stream, _ := conn.NewStream() conn.Close() @@ -3270,7 +3226,7 @@ func TestStream_DoWithClosedConn(t *testing.T) { func TestConnectionProtocolInfoSupported(t *testing.T) { test_helpers.SkipIfIdUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() // First Tarantool protocol version (1, IPROTO_FEATURE_STREAMS and @@ -3291,22 +3247,7 @@ func TestConnectionProtocolInfoSupported(t *testing.T) { }, } - clientProtocolInfo := conn.ClientProtocolInfo() - require.Equal(t, - clientProtocolInfo, - ProtocolInfo{ - Version: ProtocolVersion(6), - Features: []iproto.Feature{ - iproto.IPROTO_FEATURE_STREAMS, - iproto.IPROTO_FEATURE_TRANSACTIONS, - iproto.IPROTO_FEATURE_ERROR_EXTENSION, - iproto.IPROTO_FEATURE_WATCHERS, - iproto.IPROTO_FEATURE_PAGINATION, - iproto.IPROTO_FEATURE_WATCH_ONCE, - }, - }) - - serverProtocolInfo := conn.ServerProtocolInfo() + serverProtocolInfo := conn.ProtocolInfo() require.GreaterOrEqual(t, serverProtocolInfo.Version, tarantool210ProtocolInfo.Version) @@ -3318,7 +3259,7 @@ func TestConnectionProtocolInfoSupported(t *testing.T) { func TestClientIdRequestObject(t *testing.T) { test_helpers.SkipIfIdUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() tarantool210ProtocolInfo := ProtocolInfo{ @@ -3354,7 +3295,7 @@ func TestClientIdRequestObject(t *testing.T) { func TestClientIdRequestObjectWithNilContext(t *testing.T) { test_helpers.SkipIfIdUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() tarantool210ProtocolInfo := ProtocolInfo{ @@ -3388,7 +3329,7 @@ func TestClientIdRequestObjectWithNilContext(t *testing.T) { } func TestClientIdRequestObjectWithPassedCanceledContext(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() ctx, cancel := context.WithCancel(context.Background()) @@ -3406,65 +3347,38 @@ func TestClientIdRequestObjectWithPassedCanceledContext(t *testing.T) { func TestConnectionProtocolInfoUnsupported(t *testing.T) { test_helpers.SkipIfIdSupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() - clientProtocolInfo := conn.ClientProtocolInfo() - require.Equal(t, - clientProtocolInfo, - ProtocolInfo{ - Version: ProtocolVersion(6), - Features: []iproto.Feature{ - iproto.IPROTO_FEATURE_STREAMS, - iproto.IPROTO_FEATURE_TRANSACTIONS, - iproto.IPROTO_FEATURE_ERROR_EXTENSION, - iproto.IPROTO_FEATURE_WATCHERS, - iproto.IPROTO_FEATURE_PAGINATION, - iproto.IPROTO_FEATURE_WATCH_ONCE, - }, - }) - - serverProtocolInfo := conn.ServerProtocolInfo() + serverProtocolInfo := conn.ProtocolInfo() require.Equal(t, serverProtocolInfo, ProtocolInfo{}) } -func TestConnectionClientFeaturesUmmutable(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) - defer conn.Close() - - info := conn.ClientProtocolInfo() - infoOrig := info.Clone() - info.Features[0] = iproto.Feature(15532) - - require.Equal(t, conn.ClientProtocolInfo(), infoOrig) - require.NotEqual(t, conn.ClientProtocolInfo(), info) -} - func TestConnectionServerFeaturesUmmutable(t *testing.T) { test_helpers.SkipIfIdUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() - info := conn.ServerProtocolInfo() + info := conn.ProtocolInfo() infoOrig := info.Clone() info.Features[0] = iproto.Feature(15532) - require.Equal(t, conn.ServerProtocolInfo(), infoOrig) - require.NotEqual(t, conn.ServerProtocolInfo(), info) + require.Equal(t, conn.ProtocolInfo(), infoOrig) + require.NotEqual(t, conn.ProtocolInfo(), info) } func TestConnectionProtocolVersionRequirementSuccess(t *testing.T) { test_helpers.SkipIfIdUnsupported(t) - connOpts := opts.Clone() - connOpts.RequiredProtocolInfo = ProtocolInfo{ + testDialer := dialer.Clone() + testDialer.RequiredProtocolInfo = ProtocolInfo{ Version: ProtocolVersion(3), } ctx, cancel := test_helpers.GetConnectContext() defer cancel() - conn, err := Connect(ctx, server, connOpts) + conn, err := Connect(ctx, testDialer, opts) require.Nilf(t, err, "No errors on connect") require.NotNilf(t, conn, "Connect success") @@ -3475,14 +3389,14 @@ func TestConnectionProtocolVersionRequirementSuccess(t *testing.T) { func TestConnectionProtocolVersionRequirementFail(t *testing.T) { test_helpers.SkipIfIdSupported(t) - connOpts := opts.Clone() - connOpts.RequiredProtocolInfo = ProtocolInfo{ + testDialer := dialer.Clone() + testDialer.RequiredProtocolInfo = ProtocolInfo{ Version: ProtocolVersion(3), } ctx, cancel := test_helpers.GetConnectContext() defer cancel() - conn, err := Connect(ctx, server, connOpts) + conn, err := Connect(ctx, testDialer, opts) require.Nilf(t, conn, "Connect fail") require.NotNilf(t, err, "Got error on connect") @@ -3492,14 +3406,14 @@ func TestConnectionProtocolVersionRequirementFail(t *testing.T) { func TestConnectionProtocolFeatureRequirementSuccess(t *testing.T) { test_helpers.SkipIfIdUnsupported(t) - connOpts := opts.Clone() - connOpts.RequiredProtocolInfo = ProtocolInfo{ + testDialer := dialer.Clone() + testDialer.RequiredProtocolInfo = ProtocolInfo{ Features: []iproto.Feature{iproto.IPROTO_FEATURE_TRANSACTIONS}, } ctx, cancel := test_helpers.GetConnectContext() defer cancel() - conn, err := Connect(ctx, server, connOpts) + conn, err := Connect(ctx, testDialer, opts) require.NotNilf(t, conn, "Connect success") require.Nilf(t, err, "No errors on connect") @@ -3510,14 +3424,14 @@ func TestConnectionProtocolFeatureRequirementSuccess(t *testing.T) { func TestConnectionProtocolFeatureRequirementFail(t *testing.T) { test_helpers.SkipIfIdSupported(t) - connOpts := opts.Clone() - connOpts.RequiredProtocolInfo = ProtocolInfo{ + testDialer := dialer.Clone() + testDialer.RequiredProtocolInfo = ProtocolInfo{ Features: []iproto.Feature{iproto.IPROTO_FEATURE_TRANSACTIONS}, } ctx, cancel := test_helpers.GetConnectContext() defer cancel() - conn, err := Connect(ctx, server, connOpts) + conn, err := Connect(ctx, testDialer, opts) require.Nilf(t, conn, "Connect fail") require.NotNilf(t, err, "Got error on connect") @@ -3529,15 +3443,15 @@ func TestConnectionProtocolFeatureRequirementFail(t *testing.T) { func TestConnectionProtocolFeatureRequirementManyFail(t *testing.T) { test_helpers.SkipIfIdSupported(t) - connOpts := opts.Clone() - connOpts.RequiredProtocolInfo = ProtocolInfo{ + testDialer := dialer.Clone() + testDialer.RequiredProtocolInfo = ProtocolInfo{ Features: []iproto.Feature{iproto.IPROTO_FEATURE_TRANSACTIONS, iproto.Feature(15532)}, } ctx, cancel := test_helpers.GetConnectContext() defer cancel() - conn, err := Connect(ctx, server, connOpts) + conn, err := Connect(ctx, testDialer, opts) require.Nilf(t, conn, "Connect fail") require.NotNilf(t, err, "Got error on connect") @@ -3547,49 +3461,10 @@ func TestConnectionProtocolFeatureRequirementManyFail(t *testing.T) { "Feature(15532) are not supported") } -func TestConnectionFeatureOptsImmutable(t *testing.T) { - test_helpers.SkipIfIdUnsupported(t) - - restartOpts := startOpts - restartOpts.Listen = "127.0.0.1:3014" - inst, err := test_helpers.StartTarantool(restartOpts) - defer test_helpers.StopTarantoolWithCleanup(inst) - - if err != nil { - log.Printf("Failed to prepare test tarantool: %s", err) - return - } - - retries := uint(10) - timeout := 100 * time.Millisecond - - connOpts := opts.Clone() - connOpts.Reconnect = timeout - connOpts.MaxReconnects = retries - connOpts.RequiredProtocolInfo = ProtocolInfo{ - Features: []iproto.Feature{iproto.IPROTO_FEATURE_TRANSACTIONS}, - } - - // Connect with valid opts - conn := test_helpers.ConnectWithValidation(t, server, connOpts) - defer conn.Close() - - // Change opts outside - connOpts.RequiredProtocolInfo.Features[0] = iproto.Feature(15532) - - // Trigger reconnect with opts re-check - test_helpers.StopTarantool(inst) - err = test_helpers.RestartTarantool(&inst) - require.Nilf(t, err, "Failed to restart tarantool") - - connected := test_helpers.WaitUntilReconnected(conn, retries, timeout) - require.True(t, connected, "Reconnect success") -} - func TestErrorExtendedInfoBasic(t *testing.T) { test_helpers.SkipIfErrorExtendedInfoUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() _, err := conn.Eval("not a Lua code", []interface{}{}) @@ -3617,7 +3492,7 @@ func TestErrorExtendedInfoBasic(t *testing.T) { func TestErrorExtendedInfoStack(t *testing.T) { test_helpers.SkipIfErrorExtendedInfoUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() _, err := conn.Eval("error(chained_error)", []interface{}{}) @@ -3653,7 +3528,7 @@ func TestErrorExtendedInfoStack(t *testing.T) { func TestErrorExtendedInfoFields(t *testing.T) { test_helpers.SkipIfErrorExtendedInfoUnsupported(t) - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() _, err := conn.Eval("error(access_denied_error)", []interface{}{}) @@ -3687,11 +3562,11 @@ func TestConnection_NewWatcher(t *testing.T) { test_helpers.SkipIfWatchersUnsupported(t) const key = "TestConnection_NewWatcher" - connOpts := opts.Clone() - connOpts.RequiredProtocolInfo.Features = []iproto.Feature{ + testDialer := dialer.Clone() + testDialer.RequiredProtocolInfo.Features = []iproto.Feature{ iproto.IPROTO_FEATURE_WATCHERS, } - conn := test_helpers.ConnectWithValidation(t, server, connOpts) + conn := test_helpers.ConnectWithValidation(t, testDialer, opts) defer conn.Close() events := make(chan WatchEvent) @@ -3722,17 +3597,19 @@ func TestConnection_NewWatcher(t *testing.T) { } func TestConnection_NewWatcher_noWatchersFeature(t *testing.T) { + test_helpers.SkipIfWatchersSupported(t) + const key = "TestConnection_NewWatcher_noWatchersFeature" - connOpts := opts.Clone() - connOpts.RequiredProtocolInfo.Features = []iproto.Feature{} - conn := test_helpers.ConnectWithValidation(t, server, connOpts) + testDialer := dialer.Clone() + testDialer.RequiredProtocolInfo.Features = []iproto.Feature{} + conn := test_helpers.ConnectWithValidation(t, testDialer, opts) defer conn.Close() watcher, err := conn.NewWatcher(key, func(event WatchEvent) {}) require.Nilf(t, watcher, "watcher must not be created") require.NotNilf(t, err, "an error is expected") - expected := "the feature IPROTO_FEATURE_WATCHERS must be required by " + - "connection options to create a watcher" + expected := "the feature IPROTO_FEATURE_WATCHERS must be supported by " + + "connection to create a watcher" require.Equal(t, expected, err.Error()) } @@ -3742,15 +3619,16 @@ func TestConnection_NewWatcher_reconnect(t *testing.T) { const key = "TestConnection_NewWatcher_reconnect" const server = "127.0.0.1:3014" + testDialer := dialer.Clone() + testDialer.Address = server + inst, err := test_helpers.StartTarantool(test_helpers.StartOpts{ InitScript: "config.lua", Listen: server, - User: opts.User, - Pass: opts.Pass, WaitStart: 100 * time.Millisecond, ConnectRetry: 10, RetryTimeout: 500 * time.Millisecond, - }) + }, testDialer) defer test_helpers.StopTarantoolWithCleanup(inst) if err != nil { t.Fatalf("Unable to start Tarantool: %s", err) @@ -3759,10 +3637,10 @@ func TestConnection_NewWatcher_reconnect(t *testing.T) { reconnectOpts := opts reconnectOpts.Reconnect = 100 * time.Millisecond reconnectOpts.MaxReconnects = 10 - reconnectOpts.RequiredProtocolInfo.Features = []iproto.Feature{ + testDialer.RequiredProtocolInfo.Features = []iproto.Feature{ iproto.IPROTO_FEATURE_WATCHERS, } - conn := test_helpers.ConnectWithValidation(t, server, reconnectOpts) + conn := test_helpers.ConnectWithValidation(t, testDialer, reconnectOpts) defer conn.Close() events := make(chan WatchEvent) @@ -3796,11 +3674,11 @@ func TestBroadcastRequest(t *testing.T) { const key = "TestBroadcastRequest" const value = "bar" - connOpts := opts.Clone() - connOpts.RequiredProtocolInfo.Features = []iproto.Feature{ + testDialer := dialer.Clone() + testDialer.RequiredProtocolInfo.Features = []iproto.Feature{ iproto.IPROTO_FEATURE_WATCHERS, } - conn := test_helpers.ConnectWithValidation(t, server, connOpts) + conn := test_helpers.ConnectWithValidation(t, testDialer, opts) defer conn.Close() resp, err := conn.Do(NewBroadcastRequest(key).Value(value)).Get() @@ -3846,11 +3724,11 @@ func TestBroadcastRequest_multi(t *testing.T) { const key = "TestBroadcastRequest_multi" - connOpts := opts.Clone() - connOpts.RequiredProtocolInfo.Features = []iproto.Feature{ + testDialer := dialer.Clone() + testDialer.RequiredProtocolInfo.Features = []iproto.Feature{ iproto.IPROTO_FEATURE_WATCHERS, } - conn := test_helpers.ConnectWithValidation(t, server, connOpts) + conn := test_helpers.ConnectWithValidation(t, testDialer, opts) defer conn.Close() events := make(chan WatchEvent) @@ -3894,11 +3772,11 @@ func TestConnection_NewWatcher_multiOnKey(t *testing.T) { const key = "TestConnection_NewWatcher_multiOnKey" const value = "bar" - connOpts := opts.Clone() - connOpts.RequiredProtocolInfo.Features = []iproto.Feature{ + testDialer := dialer.Clone() + testDialer.RequiredProtocolInfo.Features = []iproto.Feature{ iproto.IPROTO_FEATURE_WATCHERS, } - conn := test_helpers.ConnectWithValidation(t, server, connOpts) + conn := test_helpers.ConnectWithValidation(t, testDialer, opts) defer conn.Close() events := []chan WatchEvent{ @@ -3957,11 +3835,11 @@ func TestWatcher_Unregister(t *testing.T) { const key = "TestWatcher_Unregister" const value = "bar" - connOpts := opts.Clone() - connOpts.RequiredProtocolInfo.Features = []iproto.Feature{ + testDialer := dialer.Clone() + testDialer.RequiredProtocolInfo.Features = []iproto.Feature{ iproto.IPROTO_FEATURE_WATCHERS, } - conn := test_helpers.ConnectWithValidation(t, server, connOpts) + conn := test_helpers.ConnectWithValidation(t, testDialer, opts) defer conn.Close() events := make(chan WatchEvent) @@ -3993,11 +3871,11 @@ func TestConnection_NewWatcher_concurrent(t *testing.T) { const testConcurrency = 1000 const key = "TestConnection_NewWatcher_concurrent" - connOpts := opts.Clone() - connOpts.RequiredProtocolInfo.Features = []iproto.Feature{ + testDialer := dialer.Clone() + testDialer.RequiredProtocolInfo.Features = []iproto.Feature{ iproto.IPROTO_FEATURE_WATCHERS, } - conn := test_helpers.ConnectWithValidation(t, server, connOpts) + conn := test_helpers.ConnectWithValidation(t, testDialer, opts) defer conn.Close() var wg sync.WaitGroup @@ -4038,11 +3916,11 @@ func TestWatcher_Unregister_concurrent(t *testing.T) { const testConcurrency = 1000 const key = "TestWatcher_Unregister_concurrent" - connOpts := opts.Clone() - connOpts.RequiredProtocolInfo.Features = []iproto.Feature{ + testDialer := dialer.Clone() + testDialer.RequiredProtocolInfo.Features = []iproto.Feature{ iproto.IPROTO_FEATURE_WATCHERS, } - conn := test_helpers.ConnectWithValidation(t, server, connOpts) + conn := test_helpers.ConnectWithValidation(t, testDialer, opts) defer conn.Close() watcher, err := conn.NewWatcher(key, func(event WatchEvent) {}) @@ -4063,7 +3941,7 @@ func TestWatcher_Unregister_concurrent(t *testing.T) { } func TestConnect_schema_update(t *testing.T) { - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() for i := 0; i < 100; i++ { @@ -4071,7 +3949,7 @@ func TestConnect_schema_update(t *testing.T) { ctx, cancel := test_helpers.GetConnectContext() defer cancel() - if conn, err := Connect(ctx, server, opts); err != nil { + if conn, err := Connect(ctx, dialer, opts); err != nil { if err.Error() != "concurrent schema update" { t.Errorf("unexpected error: %s", err) } @@ -4090,8 +3968,6 @@ func TestConnect_schema_update(t *testing.T) { func TestConnect_context_cancel(t *testing.T) { var connLongReconnectOpts = Opts{ Timeout: 5 * time.Second, - User: "test", - Pass: "test", Reconnect: time.Second, MaxReconnects: 100, } @@ -4102,7 +3978,7 @@ func TestConnect_context_cancel(t *testing.T) { var err error cancel() - conn, err = Connect(ctx, server, connLongReconnectOpts) + conn, err = Connect(ctx, dialer, connLongReconnectOpts) if conn != nil || err == nil { t.Fatalf("Connection was created after cancel") @@ -4127,7 +4003,7 @@ func runTestMain(m *testing.M) int { startOpts.MemtxUseMvccEngine = !isStreamUnsupported - inst, err := test_helpers.StartTarantool(startOpts) + inst, err := test_helpers.StartTarantool(startOpts, dialer) defer test_helpers.StopTarantoolWithCleanup(inst) if err != nil { diff --git a/test_helpers/main.go b/test_helpers/main.go index cc806a7d2..bfa3af2e7 100644 --- a/test_helpers/main.go +++ b/test_helpers/main.go @@ -39,18 +39,6 @@ type StartOpts struct { // https://www.tarantool.io/en/doc/latest/reference/configuration/#cfg-basic-listen Listen string - // ClientServer changes a host to connect to test startup of a Tarantool - // instance. By default, it uses Listen value as the host for the connection. - ClientServer string - - // ClientTransport changes Opts.Transport for a connection that checks startup - // of a Tarantool instance. - ClientTransport string - - // ClientSsl changes Opts.Ssl for a connection that checks startup of - // a Tarantool instance. - ClientSsl tarantool.SslOpts - // WorkDir is box.cfg work_dir parameter for a Tarantool instance: // a folder to store data files. If not specified, helpers create a // new temporary directory. @@ -62,13 +50,6 @@ type StartOpts struct { // copied to the working directory. SslCertsDir string - // User is a username used to connect to tarantool. - // All required grants must be given in InitScript. - User string - - // Pass is a password for specified User. - Pass string - // WaitStart is a time to wait before starting to ping tarantool. WaitStart time.Duration @@ -91,16 +72,19 @@ type TarantoolInstance struct { // Options for restarting a tarantool instance. Opts StartOpts + + // Dialer to check that connection established. + Dialer tarantool.Dialer } -func isReady(server string, opts *tarantool.Opts) error { +func isReady(dialer tarantool.Dialer, opts *tarantool.Opts) error { var err error var conn *tarantool.Connection var resp *tarantool.Response ctx, cancel := GetConnectContext() defer cancel() - conn, err = tarantool.Connect(ctx, server, *opts) + conn, err = tarantool.Connect(ctx, dialer, *opts) if err != nil { return err } @@ -185,7 +169,7 @@ func IsTarantoolVersionLess(majorMin uint64, minorMin uint64, patchMin uint64) ( // instance with StopTarantool. // Process must be stopped with StopTarantool. func RestartTarantool(inst *TarantoolInstance) error { - startedInst, err := StartTarantool(inst.Opts) + startedInst, err := StartTarantool(inst.Opts, inst.Dialer) inst.Cmd.Process = startedInst.Cmd.Process return err } @@ -193,12 +177,14 @@ func RestartTarantool(inst *TarantoolInstance) error { // StartTarantool starts a tarantool instance for tests // with specifies parameters (refer to StartOpts). // Process must be stopped with StopTarantool. -func StartTarantool(startOpts StartOpts) (TarantoolInstance, error) { +func StartTarantool(startOpts StartOpts, dialer tarantool.Dialer) (TarantoolInstance, error) { // Prepare tarantool command. var inst TarantoolInstance var dir string var err error + inst.Dialer = dialer + if startOpts.WorkDir == "" { // Create work_dir for a new instance. // TO DO: replace with `os.MkdirTemp` when we drop support of @@ -255,24 +241,13 @@ func StartTarantool(startOpts StartOpts) (TarantoolInstance, error) { time.Sleep(startOpts.WaitStart) opts := tarantool.Opts{ - Auth: startOpts.Auth, Timeout: 500 * time.Millisecond, - User: startOpts.User, - Pass: startOpts.Pass, SkipSchema: true, - Transport: startOpts.ClientTransport, - Ssl: startOpts.ClientSsl, } var i int - var server string - if startOpts.ClientServer != "" { - server = startOpts.ClientServer - } else { - server = startOpts.Listen - } for i = 0; i <= startOpts.ConnectRetry; i++ { - err = isReady(server, &opts) + err = isReady(dialer, &opts) // Both connect and ping is ok. if err == nil { diff --git a/test_helpers/pool_helper.go b/test_helpers/pool_helper.go index b2340ccb8..75cb7bc09 100644 --- a/test_helpers/pool_helper.go +++ b/test_helpers/pool_helper.go @@ -52,9 +52,9 @@ func CheckPoolStatuses(args interface{}) error { checkArgs.ExpectedPoolStatus, connected) } - poolInfo := checkArgs.ConnPool.GetPoolInfo() + poolInfo := checkArgs.ConnPool.GetInfo() for _, server := range checkArgs.Servers { - status := poolInfo[server] != nil && poolInfo[server].ConnectedNow + status := poolInfo[server].ConnectedNow if checkArgs.ExpectedStatuses[server] != status { return fmt.Errorf( "incorrect conn status: addr %s expected status %t actual status %t", @@ -106,7 +106,7 @@ func ProcessListenOnInstance(args interface{}) error { equal := reflect.DeepEqual(actualPorts, listenArgs.ExpectedPorts) if !equal { return fmt.Errorf("expected ports: %v, actual ports: %v", - actualPorts, listenArgs.ExpectedPorts) + listenArgs.ExpectedPorts, actualPorts) } return nil @@ -131,11 +131,11 @@ func Retry(f func(interface{}) error, args interface{}, count int, timeout time. return err } -func InsertOnInstance(ctx context.Context, server string, connOpts tarantool.Opts, +func InsertOnInstance(ctx context.Context, dialer tarantool.Dialer, connOpts tarantool.Opts, space interface{}, tuple interface{}) error { - conn, err := tarantool.Connect(ctx, server, connOpts) + conn, err := tarantool.Connect(ctx, dialer, connOpts) if err != nil { - return fmt.Errorf("fail to connect to %s: %s", server, err.Error()) + return fmt.Errorf("fail to connect: %s", err.Error()) } if conn == nil { return fmt.Errorf("conn is nil after Connect") @@ -169,22 +169,23 @@ func InsertOnInstance(ctx context.Context, server string, connOpts tarantool.Opt return nil } -func InsertOnInstances(servers []string, connOpts tarantool.Opts, space interface{}, +func InsertOnInstances( + dialers map[string]tarantool.Dialer, + connOpts tarantool.Opts, + space interface{}, tuple interface{}) error { - serversNumber := len(servers) - roles := make([]bool, serversNumber) - for i := 0; i < serversNumber; i++ { - roles[i] = false + roles := map[string]bool{} + for id := range dialers { + roles[id] = false } - - err := SetClusterRO(servers, connOpts, roles) + err := SetClusterRO(dialers, connOpts, roles) if err != nil { return fmt.Errorf("fail to set roles for cluster: %s", err.Error()) } - for _, server := range servers { + for _, dialer := range dialers { ctx, cancel := GetConnectContext() - err := InsertOnInstance(ctx, server, connOpts, space, tuple) + err := InsertOnInstance(ctx, dialer, connOpts, space, tuple) cancel() if err != nil { return err @@ -194,9 +195,9 @@ func InsertOnInstances(servers []string, connOpts tarantool.Opts, space interfac return nil } -func SetInstanceRO(ctx context.Context, server string, connOpts tarantool.Opts, +func SetInstanceRO(ctx context.Context, dialer tarantool.Dialer, connOpts tarantool.Opts, isReplica bool) error { - conn, err := tarantool.Connect(ctx, server, connOpts) + conn, err := tarantool.Connect(ctx, dialer, connOpts) if err != nil { return err } @@ -212,14 +213,15 @@ func SetInstanceRO(ctx context.Context, server string, connOpts tarantool.Opts, return nil } -func SetClusterRO(servers []string, connOpts tarantool.Opts, roles []bool) error { - if len(servers) != len(roles) { - return fmt.Errorf("number of servers should be equal to number of roles") +func SetClusterRO(dialers map[string]tarantool.Dialer, connOpts tarantool.Opts, + roles map[string]bool) error { + if len(dialers) != len(roles) { + return fmt.Errorf("number of dialers should be equal to number of roles") } - for i, server := range servers { + for id, dialer := range dialers { ctx, cancel := GetConnectContext() - err := SetInstanceRO(ctx, server, connOpts, roles[i]) + err := SetInstanceRO(ctx, dialer, connOpts, roles[id]) cancel() if err != nil { return err @@ -229,8 +231,11 @@ func SetClusterRO(servers []string, connOpts tarantool.Opts, roles []bool) error return nil } -func StartTarantoolInstances(servers []string, workDirs []string, - opts StartOpts) ([]TarantoolInstance, error) { +func StartTarantoolInstances( + servers []string, + workDirs []string, + opts StartOpts, + makeDialer func(string) tarantool.Dialer) ([]TarantoolInstance, error) { isUserWorkDirs := (workDirs != nil) if isUserWorkDirs && (len(servers) != len(workDirs)) { return nil, fmt.Errorf("number of servers should be equal to number of workDirs") @@ -246,7 +251,7 @@ func StartTarantoolInstances(servers []string, workDirs []string, opts.WorkDir = "" } - instance, err := StartTarantool(opts) + instance, err := StartTarantool(opts, makeDialer(server)) if err != nil { StopTarantoolInstances(instances) return nil, err diff --git a/test_helpers/utils.go b/test_helpers/utils.go index d2a941775..a121da0b0 100644 --- a/test_helpers/utils.go +++ b/test_helpers/utils.go @@ -13,13 +13,13 @@ import ( // It returns a valid connection if it is successful, otherwise finishes a test // with an error. func ConnectWithValidation(t testing.TB, - server string, + dialer tarantool.Dialer, opts tarantool.Opts) *tarantool.Connection { t.Helper() ctx, cancel := GetConnectContext() defer cancel() - conn, err := tarantool.Connect(ctx, server, opts) + conn, err := tarantool.Connect(ctx, dialer, opts) if err != nil { t.Fatalf("Failed to connect: %s", err.Error()) } diff --git a/uuid/example_test.go b/uuid/example_test.go index 08bd64aae..26f0d5f0e 100644 --- a/uuid/example_test.go +++ b/uuid/example_test.go @@ -23,12 +23,13 @@ import ( // in msgpack with google/uuid (https://github.com/google/uuid), import // tarantool/uuid submodule. func Example() { - opts := tarantool.Opts{ - User: "test", - Pass: "test", + dialer := tarantool.TtDialer{ + Address: "127.0.0.1:3013", + User: "test", + Password: "test", } ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) - client, err := tarantool.Connect(ctx, "127.0.0.1:3013", opts) + client, err := tarantool.Connect(ctx, dialer, opts) cancel() if err != nil { log.Fatalf("Failed to connect: %s", err.Error()) diff --git a/uuid/uuid_test.go b/uuid/uuid_test.go index 94baaa6ea..378cae9ff 100644 --- a/uuid/uuid_test.go +++ b/uuid/uuid_test.go @@ -23,8 +23,11 @@ var isUUIDSupported = false var server = "127.0.0.1:3013" var opts = Opts{ Timeout: 5 * time.Second, - User: "test", - Pass: "test", +} +var dialer = TtDialer{ + Address: server, + User: "test", + Password: "test", } var space = "testUUID" @@ -73,7 +76,7 @@ func TestSelect(t *testing.T) { t.Skip("Skipping test for Tarantool without UUID support in msgpack") } - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() id, uuidErr := uuid.Parse("c8f0fa1f-da29-438c-a040-393f1126ad39") @@ -113,7 +116,7 @@ func TestReplace(t *testing.T) { t.Skip("Skipping test for Tarantool without UUID support in msgpack") } - conn := test_helpers.ConnectWithValidation(t, server, opts) + conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() id, uuidErr := uuid.Parse("64d22e4d-ac92-4a23-899a-e59f34af5479") @@ -168,12 +171,10 @@ func runTestMain(m *testing.M) int { inst, err := test_helpers.StartTarantool(test_helpers.StartOpts{ InitScript: "config.lua", Listen: server, - User: opts.User, - Pass: opts.Pass, WaitStart: 100 * time.Millisecond, ConnectRetry: 10, RetryTimeout: 500 * time.Millisecond, - }) + }, dialer) defer test_helpers.StopTarantoolWithCleanup(inst) if err != nil {