@@ -33,6 +33,14 @@ type StartOpts struct {
3333 // InitScript is a Lua script for tarantool to run on start.
3434 InitScript string
3535
36+ // ConfigFile is a path to a configuration file for a Tarantool instance.
37+ // Required in pair with InstanceName.
38+ ConfigFile string
39+
40+ // InstanceName is a name of an instance to run.
41+ // Required in pair with ConfigFile.
42+ InstanceName string
43+
3644 // Listen is box.cfg listen parameter for tarantool.
3745 // Use this address to connect to tarantool after configuration.
3846 // https://www.tarantool.io/en/doc/latest/reference/configuration/#cfg-basic-listen
@@ -77,6 +85,38 @@ type TarantoolInstance struct {
7785
7886 // Dialer to check that connection established.
7987 Dialer tarantool.Dialer
88+
89+ done chan error
90+ is_done bool
91+ result error
92+ is_stopping bool
93+ }
94+
95+ // Status checks if Tarantool instance is still running.
96+ // Return true if it is running, false if it is not.
97+ // If instance was exit and error is nil - process completed success with zero status code.
98+ func (t * TarantoolInstance ) Status () (bool , error ) {
99+ if t .is_done {
100+ return false , t .result
101+ }
102+
103+ select {
104+ case t .result = <- t .done :
105+ t .is_done = true
106+ return false , t .result
107+ default :
108+ return true , nil
109+ }
110+ }
111+
112+ func (t * TarantoolInstance ) checkDone () {
113+ t .is_stopping = false
114+ t .done = make (chan error , 1 )
115+ t .done <- t .Cmd .Wait ()
116+ if ! t .is_stopping {
117+ _ , err := t .Status ()
118+ log .Printf ("Tarantool was unexpected terminated: %s" , err )
119+ }
80120}
81121
82122func isReady (dialer tarantool.Dialer , opts * tarantool.Opts ) error {
@@ -108,7 +148,7 @@ var (
108148)
109149
110150func init () {
111- tarantoolVersionRegexp = regexp .MustCompile (`Tarantool (?: Enterprise )?(\d+)\.(\d+)\.(\d+).*` )
151+ tarantoolVersionRegexp = regexp .MustCompile (`Tarantool (Enterprise )?(\d+)\.(\d+)\.(\d+).*` )
112152}
113153
114154// atoiUint64 parses string to uint64.
@@ -145,15 +185,15 @@ func IsTarantoolVersionLess(majorMin uint64, minorMin uint64, patchMin uint64) (
145185 return true , fmt .Errorf ("failed to parse output %q" , out )
146186 }
147187
148- if major , err = atoiUint64 (parsed [1 ]); err != nil {
188+ if major , err = atoiUint64 (parsed [2 ]); err != nil {
149189 return true , fmt .Errorf ("failed to parse major from output %q: %w" , out , err )
150190 }
151191
152- if minor , err = atoiUint64 (parsed [2 ]); err != nil {
192+ if minor , err = atoiUint64 (parsed [3 ]); err != nil {
153193 return true , fmt .Errorf ("failed to parse minor from output %q: %w" , out , err )
154194 }
155195
156- if patch , err = atoiUint64 (parsed [3 ]); err != nil {
196+ if patch , err = atoiUint64 (parsed [4 ]); err != nil {
157197 return true , fmt .Errorf ("failed to parse patch from output %q: %w" , out , err )
158198 }
159199
@@ -166,6 +206,21 @@ func IsTarantoolVersionLess(majorMin uint64, minorMin uint64, patchMin uint64) (
166206 }
167207}
168208
209+ // IsTarantoolEE checks if Tarantool is Enterprise edition.
210+ func IsTarantoolEE () (bool , error ) {
211+ out , err := exec .Command (getTarantoolExec (), "--version" ).Output ()
212+ if err != nil {
213+ return true , err
214+ }
215+
216+ parsed := tarantoolVersionRegexp .FindStringSubmatch (string (out ))
217+ if parsed == nil {
218+ return true , fmt .Errorf ("failed to parse output %q" , out )
219+ }
220+
221+ return parsed [1 ] != "" , nil
222+ }
223+
169224// RestartTarantool restarts a tarantool instance for tests
170225// with specifies parameters (refer to StartOpts)
171226// which were specified in inst parameter.
@@ -211,6 +266,7 @@ func StartTarantool(startOpts StartOpts) (TarantoolInstance, error) {
211266 }
212267
213268 inst .Cmd = exec .Command (getTarantoolExec (), startOpts .InitScript )
269+ inst .Cmd .Dir = startOpts .WorkDir
214270
215271 inst .Cmd .Env = append (
216272 os .Environ (),
@@ -219,6 +275,11 @@ func StartTarantool(startOpts StartOpts) (TarantoolInstance, error) {
219275 fmt .Sprintf ("TEST_TNT_MEMTX_USE_MVCC_ENGINE=%t" , startOpts .MemtxUseMvccEngine ),
220276 fmt .Sprintf ("TEST_TNT_AUTH_TYPE=%s" , startOpts .Auth ),
221277 )
278+ if startOpts .ConfigFile != "" && startOpts .InstanceName != "" {
279+ inst .Cmd .Env = append (inst .Cmd .Env , fmt .Sprintf ("TT_CONFIG=%s" , startOpts .ConfigFile ))
280+ inst .Cmd .Env = append (inst .Cmd .Env ,
281+ fmt .Sprintf ("TT_INSTANCE_NAME=%s" , startOpts .InstanceName ))
282+ }
222283
223284 // Copy SSL certificates.
224285 if startOpts .SslCertsDir != "" {
@@ -242,6 +303,8 @@ func StartTarantool(startOpts StartOpts) (TarantoolInstance, error) {
242303 // see https://github.com/tarantool/go-tarantool/issues/136
243304 time .Sleep (startOpts .WaitStart )
244305
306+ go inst .checkDone ()
307+
245308 opts := tarantool.Opts {
246309 Timeout : 500 * time .Millisecond ,
247310 SkipSchema : true ,
@@ -261,21 +324,39 @@ func StartTarantool(startOpts StartOpts) (TarantoolInstance, error) {
261324 }
262325 }
263326
264- return inst , err
327+ working , err_st := inst .Status ()
328+ if ! working || err_st != nil {
329+ StopTarantool (inst )
330+ return TarantoolInstance {}, fmt .Errorf ("unexpected terminated Tarantool: %w" , err_st )
331+ }
332+
333+ if err != nil {
334+ StopTarantool (inst )
335+ return TarantoolInstance {}, fmt .Errorf ("failed to connect Tarantool: %w" , err )
336+ }
337+
338+ return inst , nil
265339}
266340
267341// StopTarantool stops a tarantool instance started
268342// with StartTarantool. Waits until any resources
269343// associated with the process is released. If something went wrong, fails.
270344func StopTarantool (inst TarantoolInstance ) {
345+ inst .is_stopping = true
271346 if inst .Cmd != nil && inst .Cmd .Process != nil {
272347 if err := inst .Cmd .Process .Kill (); err != nil {
273- log .Fatalf ("Failed to kill tarantool (pid %d), got %s" , inst .Cmd .Process .Pid , err )
348+ is_running , _ := inst .Status ()
349+ if is_running {
350+ log .Fatalf ("Failed to kill tarantool (pid %d), got %s" , inst .Cmd .Process .Pid , err )
351+ }
274352 }
275353
276354 // Wait releases any resources associated with the Process.
277355 if _ , err := inst .Cmd .Process .Wait (); err != nil {
278- log .Fatalf ("Failed to wait for Tarantool process to exit, got %s" , err )
356+ is_running , _ := inst .Status ()
357+ if is_running {
358+ log .Fatalf ("Failed to wait for Tarantool process to exit, got %s" , err )
359+ }
279360 }
280361
281362 inst .Cmd .Process = nil
0 commit comments