github.com/etecs-ru/gnomock@v0.13.2/gnomock_test.go (about)

     1  package gnomock_test
     2  
     3  import (
     4  	"context"
     5  	"crypto/tls"
     6  	"errors"
     7  	"fmt"
     8  	"io"
     9  	"io/ioutil"
    10  	"net/http"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/etecs-ru/gnomock"
    15  	"github.com/etecs-ru/gnomock/internal/testutil"
    16  	"github.com/stretchr/testify/require"
    17  )
    18  
    19  func TestGnomock_happyFlow(t *testing.T) {
    20  	t.Parallel()
    21  
    22  	namedPorts := gnomock.NamedPorts{
    23  		"web80":   gnomock.TCP(testutil.GoodPort80),
    24  		"web8080": gnomock.TCP(testutil.GoodPort8080),
    25  	}
    26  	container, err := gnomock.StartCustom(
    27  		testutil.TestImage, namedPorts,
    28  		gnomock.WithHealthCheckInterval(time.Microsecond*500),
    29  		gnomock.WithHealthCheck(testutil.Healthcheck),
    30  		gnomock.WithInit(initf),
    31  		gnomock.WithContext(context.Background()),
    32  		gnomock.WithTimeout(time.Second*30),
    33  		gnomock.WithEnv("GNOMOCK_TEST_1=foo"),
    34  		gnomock.WithEnv("GNOMOCK_TEST_2=bar"),
    35  	)
    36  
    37  	require.NoError(t, err)
    38  	require.NotNil(t, container)
    39  
    40  	addr := fmt.Sprintf("http://%s/", container.Address("web80"))
    41  	requireResponse(t, addr, "80")
    42  
    43  	addr = fmt.Sprintf("http://%s/", container.Address("web8080"))
    44  	requireResponse(t, addr, "8080")
    45  
    46  	t.Run("default address is empty when no default port set", func(t *testing.T) {
    47  		require.Empty(t, container.DefaultAddress())
    48  	})
    49  
    50  	t.Run("wrong port not found", func(t *testing.T) {
    51  		_, err := container.Ports.Find("tcp", 1234)
    52  		require.True(t, errors.Is(err, gnomock.ErrPortNotFound))
    53  	})
    54  
    55  	t.Run("default port is zero when no default port set", func(t *testing.T) {
    56  		require.Zero(t, container.DefaultPort())
    57  	})
    58  
    59  	require.NoError(t, gnomock.Stop(container))
    60  }
    61  
    62  func TestGnomock_wrongPort(t *testing.T) {
    63  	t.Parallel()
    64  
    65  	container, err := gnomock.StartCustom(
    66  		testutil.TestImage, gnomock.DefaultTCP(testutil.BadPort),
    67  		gnomock.WithTimeout(time.Millisecond*50),
    68  	)
    69  	require.Error(t, err)
    70  	require.Nil(t, container)
    71  	require.NoError(t, gnomock.Stop(container))
    72  }
    73  
    74  func TestGnomock_cancellation(t *testing.T) {
    75  	t.Parallel()
    76  
    77  	ctx, cancel := context.WithCancel(context.Background())
    78  
    79  	go func() {
    80  		time.Sleep(time.Millisecond * 100)
    81  		cancel()
    82  	}()
    83  
    84  	container, err := gnomock.StartCustom(
    85  		testutil.TestImage, gnomock.DefaultTCP(testutil.BadPort),
    86  		gnomock.WithContext(ctx),
    87  	)
    88  	require.True(t, errors.Is(err, context.Canceled))
    89  	require.Nil(t, container)
    90  	require.NoError(t, gnomock.Stop(container))
    91  }
    92  
    93  func TestGnomock_customHealthcheck(t *testing.T) {
    94  	t.Parallel()
    95  
    96  	container, err := gnomock.StartCustom(
    97  		testutil.TestImage, gnomock.DefaultTCP(testutil.BadPort),
    98  		gnomock.WithTimeout(time.Second*10),
    99  		gnomock.WithHealthCheck(failingHealthcheck),
   100  	)
   101  
   102  	defer func() {
   103  		require.NoError(t, gnomock.Stop(container))
   104  	}()
   105  
   106  	require.Error(t, err)
   107  }
   108  
   109  func TestGnomock_initError(t *testing.T) {
   110  	t.Parallel()
   111  
   112  	errNope := fmt.Errorf("nope")
   113  	initWithErr := func(context.Context, *gnomock.Container) error {
   114  		return errNope
   115  	}
   116  
   117  	container, err := gnomock.StartCustom(
   118  		testutil.TestImage, gnomock.DefaultTCP(testutil.GoodPort80),
   119  		gnomock.WithInit(initWithErr),
   120  	)
   121  	require.True(t, errors.Is(err, errNope))
   122  	require.Nil(t, container)
   123  	require.NoError(t, gnomock.Stop(container))
   124  }
   125  
   126  func TestGnomock_cantStart(t *testing.T) {
   127  	t.Parallel()
   128  
   129  	container, err := gnomock.StartCustom(
   130  		"docker.io/orlangure/noimage",
   131  		gnomock.DefaultTCP(testutil.GoodPort80),
   132  	)
   133  	require.Error(t, err)
   134  	require.Nil(t, container)
   135  	require.NoError(t, gnomock.Stop(container))
   136  }
   137  
   138  func TestGnomock_withLogWriter(t *testing.T) {
   139  	t.Parallel()
   140  
   141  	r, w := io.Pipe()
   142  
   143  	container, err := gnomock.StartCustom(
   144  		testutil.TestImage, gnomock.DefaultTCP(testutil.GoodPort80),
   145  		gnomock.WithLogWriter(w),
   146  	)
   147  	require.NoError(t, err)
   148  
   149  	signal := make(chan struct{})
   150  
   151  	go func() {
   152  		defer close(signal)
   153  
   154  		log, err := ioutil.ReadAll(r)
   155  		require.NoError(t, err)
   156  		require.Contains(t, string(log), "starting with env1 = '', env2 = ''\n")
   157  	}()
   158  
   159  	require.NoError(t, gnomock.Stop(container))
   160  
   161  	require.NoError(t, w.Close())
   162  	<-signal
   163  	require.NoError(t, r.Close())
   164  }
   165  
   166  func TestGnomock_withCommand(t *testing.T) {
   167  	t.Parallel()
   168  
   169  	r, w := io.Pipe()
   170  
   171  	container, err := gnomock.StartCustom(
   172  		testutil.TestImage, gnomock.DefaultTCP(testutil.GoodPort80),
   173  		gnomock.WithLogWriter(w),
   174  		gnomock.WithCommand("foo", "bar"),
   175  	)
   176  	require.NoError(t, err)
   177  
   178  	signal := make(chan struct{})
   179  
   180  	go func() {
   181  		defer close(signal)
   182  
   183  		log, err := ioutil.ReadAll(r)
   184  		require.NoError(t, err)
   185  		require.Contains(t, string(log), "[foo bar]")
   186  	}()
   187  
   188  	require.NoError(t, gnomock.Stop(container))
   189  
   190  	require.NoError(t, w.Close())
   191  	<-signal
   192  	require.NoError(t, r.Close())
   193  }
   194  
   195  func initf(context.Context, *gnomock.Container) error {
   196  	return nil
   197  }
   198  
   199  func requireResponse(t *testing.T, url string, expected string) {
   200  	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
   201  	defer cancel()
   202  
   203  	client := &http.Client{
   204  		Transport: &http.Transport{
   205  			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
   206  		},
   207  	}
   208  
   209  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
   210  	require.NoError(t, err)
   211  
   212  	resp, err := client.Do(req)
   213  	require.NoError(t, err)
   214  
   215  	defer func() {
   216  		require.NoError(t, resp.Body.Close())
   217  	}()
   218  
   219  	require.Equal(t, http.StatusOK, resp.StatusCode)
   220  
   221  	body, err := io.ReadAll(resp.Body)
   222  
   223  	require.NoError(t, err)
   224  	require.Equal(t, expected, string(body))
   225  }
   226  
   227  func failingHealthcheck(ctx context.Context, c *gnomock.Container) error {
   228  	return fmt.Errorf("this container should not start")
   229  }