github.com/ghosta3/migrate/v4@v4.15.10/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  }