github.com/mrqzzz/migrate@v5.1.7+incompatible/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 container.Remove()
    49  
    50  				// wait until database is ready
    51  				tick := time.NewTicker(1000 * time.Millisecond)
    52  				defer tick.Stop()
    53  				timeout := time.NewTimer(time.Duration(timeout) * time.Second)
    54  				defer timeout.Stop()
    55  			outer:
    56  				for {
    57  					select {
    58  					case <-tick.C:
    59  						if readyFn(container) {
    60  							break outer
    61  						}
    62  
    63  					case <-timeout.C:
    64  						t.Fatalf("Docker: Container not ready, timeout for %v.\n%s", version, containerLogs(t, container))
    65  					}
    66  				}
    67  
    68  				// we can now run the tests
    69  				testFn(t, container)
    70  			})
    71  		}
    72  	}
    73  }
    74  
    75  func containerLogs(t *testing.T, c *DockerContainer) []byte {
    76  	r, err := c.Logs()
    77  	if err != nil {
    78  		t.Error(err)
    79  		return nil
    80  	}
    81  	defer r.Close()
    82  	b, err := ioutil.ReadAll(r)
    83  	if err != nil {
    84  		t.Error(err)
    85  		return nil
    86  	}
    87  	return b
    88  }
    89  
    90  type Instance interface {
    91  	Host() string
    92  	Port() uint
    93  	PortFor(int) uint
    94  	NetworkSettings() dockertypes.NetworkSettings
    95  	KeepForDebugging()
    96  }