github.com/bishtawi/migrate/v4@v4.8.11/testing/testing.go (about) 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 // Cassandra docker image can take ~30s to start 27 } 28 29 for i, version := range versions { 30 version := version // capture range variable, see https://goo.gl/60w3p2 31 32 // Only test against one version in short mode 33 // TODO: order is random, maybe always pick first version instead? 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 // create new container 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 // make sure to remove container once done 48 defer func() { 49 if err := container.Remove(); err != nil { 50 t.Error(err) 51 } 52 }() 53 // wait until database is ready 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 // we can now run the tests 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 }