github.com/postmates/migrate@v3.0.2-0.20200730201548-1a6ead3e680d+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  }
    21  
    22  func ParallelTest(t *testing.T, versions []Version, readyFn IsReadyFunc, testFn TestFunc) {
    23  	delay, err := strconv.Atoi(os.Getenv("MIGRATE_TEST_CONTAINER_BOOT_DELAY"))
    24  	if err != nil {
    25  		delay = 0
    26  	}
    27  
    28  	for i, version := range versions {
    29  		version := version // capture range variable, see https://goo.gl/60w3p2
    30  
    31  		// Only test against one version in short mode
    32  		// TODO: order is random, maybe always pick first version instead?
    33  		if i > 0 && testing.Short() {
    34  			t.Logf("Skipping %v in short mode", version)
    35  
    36  		} else {
    37  			t.Run(version.Image, func(t *testing.T) {
    38  				t.Parallel()
    39  
    40  				// create new container
    41  				container, err := NewDockerContainer(t, version.Image, version.ENV)
    42  				if err != nil {
    43  					t.Fatalf("%v\n%s", err, containerLogs(t, container))
    44  				}
    45  
    46  				// make sure to remove container once done
    47  				defer container.Remove()
    48  
    49  				// wait until database is ready
    50  				tick := time.Tick(1000 * time.Millisecond)
    51  				timeout := time.After(time.Duration(delay + 60) * time.Second)
    52  				outer:
    53  				for {
    54  					select {
    55  					case <-tick:
    56  						if readyFn(container) {
    57  							break outer
    58  						}
    59  
    60  					case <-timeout:
    61  						t.Fatalf("Docker: Container not ready, timeout for %v.\n%s", version, containerLogs(t, container))
    62  					}
    63  				}
    64  
    65  				time.Sleep(time.Duration(int64(delay)) * time.Second)
    66  
    67  				// we can now run the tests
    68  				testFn(t, container)
    69  			})
    70  		}
    71  	}
    72  }
    73  
    74  func containerLogs(t *testing.T, c *DockerContainer) []byte {
    75  	r, err := c.Logs()
    76  	if err != nil {
    77  		t.Error("%v", err)
    78  		return nil
    79  	}
    80  	defer r.Close()
    81  	b, err := ioutil.ReadAll(r)
    82  	if err != nil {
    83  		t.Error("%v", err)
    84  		return nil
    85  	}
    86  	return b
    87  }
    88  
    89  type Instance interface {
    90  	Host() string
    91  	Port() uint
    92  	NetworkSettings() dockertypes.NetworkSettings
    93  	KeepForDebugging()
    94  }