Skip to content

Commit 537f38f

Browse files
committed
test: fix flaky test
Helper method that performs initial assigning of master/replica roles and is widely used in ConnectionPool tests was adjusted to wait for the roles to be applied successfully. Prior to this patch it doesn't, so sometimes subsequent test code might work unexpectedly (the problem was caught with TestConnectionHandlerOpenUpdateClose) Closes #452
1 parent 20dc742 commit 537f38f

File tree

1 file changed

+55
-7
lines changed

1 file changed

+55
-7
lines changed

test_helpers/pool_helper.go

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ package test_helpers
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
67
"reflect"
8+
"sync"
79
"time"
810

911
"github.com/tarantool/go-tarantool/v2"
@@ -206,6 +208,45 @@ func SetInstanceRO(ctx context.Context, dialer tarantool.Dialer, connOpts tarant
206208
return err
207209
}
208210

211+
checkRole := func(conn *tarantool.Connection, isReplica bool) string {
212+
data, err := conn.Do(tarantool.NewCallRequest("box.info")).Get()
213+
switch {
214+
case err != nil:
215+
return fmt.Sprintf("failed to get box.info: %s", err)
216+
case len(data) < 1:
217+
return "box.info is empty"
218+
}
219+
220+
status, statusFound := data[0].(map[interface{}]interface{})["status"]
221+
readonly, readonlyFound := data[0].(map[interface{}]interface{})["ro"]
222+
switch {
223+
case !statusFound:
224+
return "box.info.status is missing"
225+
case status != "running":
226+
return fmt.Sprintf("box.info.status='%s' (waiting for 'running')", status)
227+
case !readonlyFound:
228+
return "box.info.ro is missing"
229+
case readonly != isReplica:
230+
return fmt.Sprintf("box.info.ro='%v' (waiting for '%v')", readonly, isReplica)
231+
default:
232+
return ""
233+
}
234+
}
235+
236+
problem := "not checked yet"
237+
238+
// Wait for the role to be applied.
239+
for len(problem) != 0 {
240+
select {
241+
case <-time.After(10 * time.Millisecond):
242+
case <-ctx.Done():
243+
return fmt.Errorf("%w: failed to apply role, the last problem: %s",
244+
ctx.Err(), problem)
245+
}
246+
247+
problem = checkRole(conn, isReplica)
248+
}
249+
209250
return nil
210251
}
211252

@@ -215,16 +256,23 @@ func SetClusterRO(dialers []tarantool.Dialer, connOpts tarantool.Opts,
215256
return fmt.Errorf("number of servers should be equal to number of roles")
216257
}
217258

259+
ctx, cancel := GetConnectContext()
260+
defer cancel()
261+
262+
// Apply roles in parallel.
263+
errs := make([]error, len(dialers))
264+
var wg sync.WaitGroup
265+
wg.Add(len(dialers))
218266
for i, dialer := range dialers {
219-
ctx, cancel := GetConnectContext()
220-
err := SetInstanceRO(ctx, dialer, connOpts, roles[i])
221-
cancel()
222-
if err != nil {
223-
return err
224-
}
267+
// Pass loop variables to avoid its closure.
268+
go func(i int, dialer tarantool.Dialer) {
269+
defer wg.Done()
270+
errs[i] = SetInstanceRO(ctx, dialer, connOpts, roles[i])
271+
}(i, dialer)
225272
}
273+
wg.Wait()
226274

227-
return nil
275+
return errors.Join(errs...)
228276
}
229277

230278
func StartTarantoolInstances(instsOpts []StartOpts) ([]*TarantoolInstance, error) {

0 commit comments

Comments
 (0)