diff --git a/.github/workflows/reusable_testing.yml b/.github/workflows/reusable_testing.yml index f0897a8d9..b84b95f17 100644 --- a/.github/workflows/reusable_testing.yml +++ b/.github/workflows/reusable_testing.yml @@ -40,35 +40,21 @@ jobs: - name: Run base tests run: | - mkdir snap xlog - TNT_PID=$(tarantool ./config.lua > tarantool.log 2>&1 & echo $!) go clean -testcache && go test -v - kill $TNT_PID # TODO(ylobankov): Uncomment this when tarantool/go-tarantool#115 is resolved. # - name: Run queue tests # working-directory: ./queue # run: | -# mkdir snap xlog -# tarantoolctl rocks install queue 1.1.0 -# TNT_PID=$(tarantool ./config.lua > tarantool.log 2>&1 & echo $!) # go clean -testcache && go test -v -# kill $TNT_PID - name: Run uuid tests working-directory: ./uuid run: | - mkdir snap xlog - TNT_PID=$(tarantool ./config.lua > tarantool.log 2>&1 & echo $!) go clean -testcache && go test -v - kill $TNT_PID if: ${{ !startsWith(env.TNT_VERSION, 'Tarantool 1.10') }} - name: Run multi tests working-directory: ./multi run: | - mkdir -p m1/{snap,xlog} m2/{snap,xlog} - TNT_PID_1=$(tarantool ./config_m1.lua > tarantool_m1.log 2>&1 & echo $!) - TNT_PID_2=$(tarantool ./config_m2.lua > tarantool_m2.log 2>&1 & echo $!) go clean -testcache && go test -v - kill $TNT_PID_1 $TNT_PID_2 diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 8b894210a..0083d43bf 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -41,35 +41,21 @@ jobs: - name: Run base tests run: | - mkdir snap xlog - TNT_PID=$(tarantool ./config.lua > tarantool.log 2>&1 & echo $!) go clean -testcache && go test -v - kill $TNT_PID # TODO(ylobankov): Uncomment this when tarantool/go-tarantool#115 is resolved. # - name: Run queue tests # working-directory: ./queue # run: | -# mkdir snap xlog -# tarantoolctl rocks install queue 1.1.0 -# TNT_PID=$(tarantool ./config.lua > tarantool.log 2>&1 & echo $!) # go clean -testcache && go test -v -# kill $TNT_PID - name: Run uuid tests working-directory: ./uuid run: | - mkdir snap xlog - TNT_PID=$(tarantool ./config.lua > tarantool.log 2>&1 & echo $!) go clean -testcache && go test -v - kill $TNT_PID if: ${{ matrix.tarantool != 1.10 }} - name: Run multi tests working-directory: ./multi run: | - mkdir -p m1/{snap,xlog} m2/{snap,xlog} - TNT_PID_1=$(tarantool ./config_m1.lua > tarantool_m1.log 2>&1 & echo $!) - TNT_PID_2=$(tarantool ./config_m2.lua > tarantool_m2.log 2>&1 & echo $!) go clean -testcache && go test -v - kill $TNT_PID_1 $TNT_PID_2 diff --git a/.gitignore b/.gitignore index 8fcb790f1..8958050e9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ *.DS_Store *.swp .idea/ -snap -xlog +work_dir* +.rocks diff --git a/config.lua b/config.lua index c2a9ae966..8ce372cc9 100644 --- a/config.lua +++ b/config.lua @@ -1,7 +1,7 @@ +-- Do not set listen for now so connector won't be +-- able to send requests until everything is configured. box.cfg{ - listen = 3013, - wal_dir='xlog', - snap_dir='snap', + work_dir = os.getenv("TARANTOOL_WORK_DIR"), } box.once("init", function() @@ -56,7 +56,10 @@ function simple_incr(a) end box.space.test:truncate() -local console = require 'console' -console.listen '0.0.0.0:33015' --box.schema.user.revoke('guest', 'read,write,execute', 'universe') + +-- Set listen only when every other thing is configured. +box.cfg{ + listen = os.getenv("TARANTOOL_LISTEN"), +} diff --git a/multi/config.lua b/multi/config.lua new file mode 100644 index 000000000..7913886cd --- /dev/null +++ b/multi/config.lua @@ -0,0 +1,19 @@ +local nodes_load = require("config_load_nodes") + +-- Do not set listen for now so connector won't be +-- able to send requests until everything is configured. +box.cfg{ + work_dir = os.getenv("TARANTOOL_WORK_DIR"), +} + +get_cluster_nodes = nodes_load.get_cluster_nodes + +box.once("init", function() + box.schema.user.create('test', { password = 'test' }) + box.schema.user.grant('test', 'read,write,execute', 'universe') +end) + +-- Set listen only when every other thing is configured. +box.cfg{ + listen = os.getenv("TARANTOOL_LISTEN"), +} diff --git a/multi/config_m1.lua b/multi/config_m1.lua deleted file mode 100644 index 5e364b5cc..000000000 --- a/multi/config_m1.lua +++ /dev/null @@ -1,14 +0,0 @@ -local nodes_load = require("config_load_nodes") - -box.cfg { - listen = 3013, - wal_dir = 'm1/xlog', - snap_dir = 'm1/snap', -} - -get_cluster_nodes = nodes_load.get_cluster_nodes - -box.once("init", function() - box.schema.user.create('test', { password = 'test' }) - box.schema.user.grant('test', 'read,write,execute', 'universe') -end) diff --git a/multi/config_m2.lua b/multi/config_m2.lua deleted file mode 100644 index cf73da319..000000000 --- a/multi/config_m2.lua +++ /dev/null @@ -1,14 +0,0 @@ -local nodes_load = require("config_load_nodes") - -box.cfg { - listen = 3014, - wal_dir = 'm2/xlog', - snap_dir = 'm2/snap', -} - -get_cluster_nodes = nodes_load.get_cluster_nodes - -box.once("init", function() - box.schema.user.create('test', { password = 'test' }) - box.schema.user.grant('test', 'read,write,execute', 'universe') -end) diff --git a/multi/multi_test.go b/multi/multi_test.go index 4515c6232..4741bbdf6 100644 --- a/multi/multi_test.go +++ b/multi/multi_test.go @@ -1,10 +1,14 @@ package multi import ( + "log" + "os" + "os/exec" "testing" "time" "github.com/tarantool/go-tarantool" + "github.com/tarantool/go-tarantool/test_helpers" ) var server1 = "127.0.0.1:3013" @@ -204,3 +208,49 @@ func TestRefresh(t *testing.T) { t.Error("Expect to get data after reconnect") } } + +// See https://stackoverflow.com/questions/27629380/how-to-exit-a-go-program-honoring-deferred-calls +// on issue with defer + os.Exit. +func runTestMain(m *testing.M) int { + var err error + var cmd1, cmd2 *exec.Cmd + + cmd1, err = test_helpers.StartTarantool(test_helpers.StartOpts{ + Command: "config.lua", + Server: server1, + WorkDir: "work_dir1", + User: connOpts.User, + Pass: connOpts.Pass, + WaitStart: 100 * time.Millisecond, + ConnectRetry: 3, + RetryTimeout: 200 * time.Millisecond, + }) + defer test_helpers.StopTarantool(cmd1) + + if err != nil { + log.Panic("Failed to prepare test tarantool: ", err) + } + + cmd2, err = test_helpers.StartTarantool(test_helpers.StartOpts{ + Command: "config.lua", + Server: server2, + WorkDir: "work_dir2", + User: connOpts.User, + Pass: connOpts.Pass, + WaitStart: 100 * time.Millisecond, + ConnectRetry: 3, + RetryTimeout: 200 * time.Millisecond, + }) + defer test_helpers.StopTarantool(cmd2) + + if err != nil { + log.Panic("Failed to prepare test tarantool: ", err) + } + + return m.Run() +} + +func TestMain(m *testing.M) { + code := runTestMain(m) + os.Exit(code) +} diff --git a/queue/config.lua b/queue/config.lua index 2488ff300..981e148c5 100644 --- a/queue/config.lua +++ b/queue/config.lua @@ -1,9 +1,9 @@ -queue = require 'queue' +queue = require('queue') +-- Do not set listen for now so connector won't be +-- able to send requests until everything is configured. box.cfg{ - listen = 3013, - wal_dir='xlog', - snap_dir='snap', + work_dir = os.getenv("TARANTOOL_WORK_DIR"), } box.once("init", function() @@ -27,3 +27,8 @@ box.schema.user.grant('test', 'read,write', 'space', '_queue_consumers') box.schema.user.grant('test', 'read,write', 'space', '_priv') box.schema.user.grant('test', 'read,write', 'space', '_queue_taken') end) + +-- Set listen only when every other thing is configured. +box.cfg{ + listen = os.getenv("TARANTOOL_LISTEN"), +} diff --git a/queue/queue_test.go b/queue/queue_test.go index d1a909120..03bd05083 100644 --- a/queue/queue_test.go +++ b/queue/queue_test.go @@ -2,12 +2,15 @@ package queue_test import ( "fmt" + "log" "math" + "os" "testing" "time" . "github.com/tarantool/go-tarantool" "github.com/tarantool/go-tarantool/queue" + "github.com/tarantool/go-tarantool/test_helpers" "gopkg.in/vmihailenco/msgpack.v2" ) @@ -818,3 +821,38 @@ func TestUtube_Put(t *testing.T) { t.Fatalf("Blocking time is less than expected: actual = %.2fs, expected = 1s", end.Sub(start).Seconds()) } } + +// See https://stackoverflow.com/questions/27629380/how-to-exit-a-go-program-honoring-deferred-calls +// on issue with defer + os.Exit. +func runTestMain(m *testing.M) int { + if err := os.RemoveAll(".rocks"); err != nil { + log.Panic(err) + } + + if err := test_helpers.InstallRock("queue", "1.1.0"); err != nil { + log.Panic(err) + } + + cmd, err := test_helpers.StartTarantool(test_helpers.StartOpts{ + Command: "config.lua", + Server: server, + WorkDir: "work_dir", + User: opts.User, + Pass: opts.Pass, + WaitStart: 100 * time.Millisecond, + ConnectRetry: 3, + RetryTimeout: 200 * time.Millisecond, + }) + defer test_helpers.StopTarantool(cmd) + + if err != nil { + log.Panic("Failed to prepare test tarantool: ", err) + } + + return m.Run() +} + +func TestMain(m *testing.M) { + code := runTestMain(m) + os.Exit(code) +} diff --git a/tarantool_test.go b/tarantool_test.go index ae725fdc7..504d9a76c 100644 --- a/tarantool_test.go +++ b/tarantool_test.go @@ -2,12 +2,15 @@ package tarantool_test import ( "fmt" + "log" + "os" "strings" "sync" "testing" "time" . "github.com/tarantool/go-tarantool" + "github.com/tarantool/go-tarantool/test_helpers" "gopkg.in/vmihailenco/msgpack.v2" ) @@ -1005,3 +1008,30 @@ func TestComplexStructs(t *testing.T) { return } } + +// See https://stackoverflow.com/questions/27629380/how-to-exit-a-go-program-honoring-deferred-calls +// on issue with defer + os.Exit. +func runTestMain(m *testing.M) int { + cmd, err := test_helpers.StartTarantool(test_helpers.StartOpts{ + Command: "config.lua", + Server: server, + WorkDir: "work_dir", + User: opts.User, + Pass: opts.Pass, + WaitStart: 100 * time.Millisecond, + ConnectRetry: 3, + RetryTimeout: 200 * time.Millisecond, + }) + defer test_helpers.StopTarantool(cmd) + + if err != nil { + log.Panic("Failed to prepare test tarantool: ", err) + } + + return m.Run() +} + +func TestMain(m *testing.M) { + code := runTestMain(m) + os.Exit(code) +} diff --git a/test_helpers/main.go b/test_helpers/main.go new file mode 100644 index 000000000..605a2b876 --- /dev/null +++ b/test_helpers/main.go @@ -0,0 +1,126 @@ +package test_helpers + +import ( + "errors" + "fmt" + "os" + "os/exec" + "time" + + "github.com/tarantool/go-tarantool" +) + +type StartOpts struct { + Command string + Server string + WorkDir string + User string + Pass string + WaitStart time.Duration + ConnectRetry uint + RetryTimeout time.Duration +} + +func InstallRock(rock string, version string) error { + cmd := exec.Command("tarantoolctl", "rocks", "install", rock, version) + + err := cmd.Run() + if err != nil { + return err + } + + return nil +} + +func isReady(server string, opts *tarantool.Opts) error { + var err error + var conn *tarantool.Connection + var resp *tarantool.Response + + conn, err = tarantool.Connect(server, *opts) + if err != nil { + return err + } + if conn == nil { + return errors.New("Conn is nil after connect") + } + defer conn.Close() + + resp, err = conn.Ping() + if err != nil { + return err + } + if resp == nil { + return errors.New("Response is nil after ping") + } + + return nil +} + +func StartTarantool(startOpts StartOpts) (*exec.Cmd, error) { + var err error + var cmd *exec.Cmd + + // Prepare tarantool command + cmd = exec.Command("tarantool", "config.lua") + + cmd.Env = append( + os.Environ(), + fmt.Sprintf("TARANTOOL_WORK_DIR=%s", startOpts.WorkDir), + fmt.Sprintf("TARANTOOL_LISTEN=%s", startOpts.Server), + ) + + // Clean up existing work_dir. + err = os.RemoveAll(startOpts.WorkDir) + if err != nil { + return cmd, err + } + + // Create work_dir. + err = os.Mkdir(startOpts.WorkDir, 0755) + if err != nil { + return cmd, err + } + + // Start tarantool. + err = cmd.Start() + if err != nil { + return cmd, err + } + + // Try to connect and ping tarantool. + // Using reconnect opts do not help on Connect, + // see https://github.com/tarantool/go-tarantool/issues/136 + time.Sleep(startOpts.WaitStart) + + opts := tarantool.Opts{ + Timeout: 500 * time.Millisecond, + User: startOpts.User, + Pass: startOpts.Pass, + SkipSchema: true, + } + + var i uint + for i = 0; i <= startOpts.ConnectRetry; i++ { + err = isReady(startOpts.Server, &opts) + + // Both connect and ping is ok. + if err == nil { + break + } + + if i != startOpts.ConnectRetry { + time.Sleep(startOpts.RetryTimeout) + } + } + + return cmd, err +} + +func StopTarantool(cmd *exec.Cmd) { + if cmd == nil || cmd.Process == nil { + return + } + + cmd.Process.Kill() +} diff --git a/uuid/config.lua b/uuid/config.lua index 34b5d26c4..f1826dca1 100644 --- a/uuid/config.lua +++ b/uuid/config.lua @@ -1,10 +1,10 @@ local uuid = require('uuid') local msgpack = require('msgpack') +-- Do not set listen for now so connector won't be +-- able to send requests until everything is configured. box.cfg{ - listen = 3013, - wal_dir = 'xlog', - snap_dir = 'snap', + work_dir = os.getenv("TARANTOOL_WORK_DIR"), } box.schema.user.create('test', { password = 'test' , if_not_exists = true }) @@ -29,3 +29,8 @@ s:truncate() box.schema.user.grant('test', 'read,write', 'space', 'testUUID', { if_not_exists = true }) s:insert({ uuid.fromstr("c8f0fa1f-da29-438c-a040-393f1126ad39") }) + +-- Set listen only when every other thing is configured. +box.cfg{ + listen = os.getenv("TARANTOOL_LISTEN"), +} diff --git a/uuid/uuid_test.go b/uuid/uuid_test.go index 61eb632d2..00db471ad 100644 --- a/uuid/uuid_test.go +++ b/uuid/uuid_test.go @@ -2,13 +2,16 @@ package uuid_test import ( "fmt" + "log" + "os" "testing" "time" + "github.com/google/uuid" . "github.com/tarantool/go-tarantool" - _ "github.com/tarantool/go-tarantool/uuid" + "github.com/tarantool/go-tarantool/test_helpers" + _ "github.com/tarantool/go-tarantool/uuid" "gopkg.in/vmihailenco/msgpack.v2" - "github.com/google/uuid" ) var server = "127.0.0.1:3013" @@ -98,7 +101,7 @@ func TestSelect(t *testing.T) { t.Errorf("Failed to prepare test uuid: %s", uuidErr) } - resp, errSel := conn.Select(space, index, 0, 1, IterEq, []interface{}{ id }) + resp, errSel := conn.Select(space, index, 0, 1, IterEq, []interface{}{id}) if errSel != nil { t.Errorf("UUID select failed: %s", errSel.Error()) } @@ -108,7 +111,7 @@ func TestSelect(t *testing.T) { tupleValueIsId(t, resp.Data, id) var tuples []TupleUUID - errTyp := conn.SelectTyped(space, index, 0, 1, IterEq, []interface{}{ id }, &tuples) + errTyp := conn.SelectTyped(space, index, 0, 1, IterEq, []interface{}{id}, &tuples) if errTyp != nil { t.Errorf("Failed to SelectTyped: %s", errTyp.Error()) } @@ -131,7 +134,7 @@ func TestReplace(t *testing.T) { t.Errorf("Failed to prepare test uuid: %s", uuidErr) } - respRep, errRep := conn.Replace(space, []interface{}{ id }) + respRep, errRep := conn.Replace(space, []interface{}{id}) if errRep != nil { t.Errorf("UUID replace failed: %s", errRep) } @@ -140,7 +143,7 @@ func TestReplace(t *testing.T) { } tupleValueIsId(t, respRep.Data, id) - respSel, errSel := conn.Select(space, index, 0, 1, IterEq, []interface{}{ id }) + respSel, errSel := conn.Select(space, index, 0, 1, IterEq, []interface{}{id}) if errSel != nil { t.Errorf("UUID select failed: %s", errSel) } @@ -149,3 +152,30 @@ func TestReplace(t *testing.T) { } tupleValueIsId(t, respSel.Data, id) } + +// See https://stackoverflow.com/questions/27629380/how-to-exit-a-go-program-honoring-deferred-calls +// on issue with defer + os.Exit. +func runTestMain(m *testing.M) int { + cmd, err := test_helpers.StartTarantool(test_helpers.StartOpts{ + Command: "config.lua", + Server: server, + WorkDir: "work_dir", + User: opts.User, + Pass: opts.Pass, + WaitStart: 100 * time.Millisecond, + ConnectRetry: 3, + RetryTimeout: 200 * time.Millisecond, + }) + defer test_helpers.StopTarantool(cmd) + + if err != nil { + log.Panic("Failed to prepare test tarantool: ", err) + } + + return m.Run() +} + +func TestMain(m *testing.M) { + code := runTestMain(m) + os.Exit(code) +}