...
1 package testing
2
3 import (
4 "io/ioutil"
5 "os"
6 "strconv"
7 "testing"
8 "time"
9
10 dockertypes "github.com/docker/docker/api/types"
11 )
12
13 type IsReadyFunc func(Instance) bool
14
15 type TestFunc func(*testing.T, Instance)
16
17 type Version struct {
18 Image string
19 ENV []string
20 Cmd []string
21 }
22
23 func ParallelTest(t *testing.T, versions []Version, readyFn IsReadyFunc, testFn TestFunc) {
24 timeout, err := strconv.Atoi(os.Getenv("MIGRATE_TEST_CONTAINER_BOOT_TIMEOUT"))
25 if err != nil {
26 timeout = 60
27 }
28
29 for i, version := range versions {
30 version := version
31
32
33
34 if i > 0 && testing.Short() {
35 t.Logf("Skipping %v in short mode", version)
36
37 } else {
38 t.Run(version.Image, func(t *testing.T) {
39 t.Parallel()
40
41
42 container, err := NewDockerContainer(t, version.Image, version.ENV, version.Cmd)
43 if err != nil {
44 t.Fatalf("%v\n%s", err, containerLogs(t, container))
45 }
46
47
48 defer func() {
49 if err := container.Remove(); err != nil {
50 t.Error(err)
51 }
52 }()
53
54 tick := time.NewTicker(1000 * time.Millisecond)
55 defer tick.Stop()
56 timeout := time.NewTimer(time.Duration(timeout) * time.Second)
57 defer timeout.Stop()
58 outer:
59 for {
60 select {
61 case <-tick.C:
62 if readyFn(container) {
63 break outer
64 }
65
66 case <-timeout.C:
67 t.Fatalf("Docker: Container not ready, timeout for %v.\n%s", version, containerLogs(t, container))
68 }
69 }
70
71
72 testFn(t, container)
73 })
74 }
75 }
76 }
77
78 func containerLogs(t *testing.T, c *DockerContainer) []byte {
79 r, err := c.Logs()
80 if err != nil {
81 t.Error(err)
82 return nil
83 }
84 defer func() {
85 if err := r.Close(); err != nil {
86 t.Error(err)
87 }
88 }()
89 b, err := ioutil.ReadAll(r)
90 if err != nil {
91 t.Error(err)
92 return nil
93 }
94 return b
95 }
96
97 type Instance interface {
98 Host() string
99 Port() uint
100 PortFor(int) uint
101 NetworkSettings() dockertypes.NetworkSettings
102 KeepForDebugging()
103 }
104
View as plain text