github.com/mailgun/holster/v4@v4.20.0/testutil/until_test.go (about)

     1  package testutil_test
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"math/rand"
     7  	"net/http"
     8  	"net/http/httptest"
     9  	"net/url"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/mailgun/holster/v4/testutil"
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/require"
    16  	"golang.org/x/net/nettest"
    17  )
    18  
    19  func TestUntilConnect(t *testing.T) {
    20  	ln, err := nettest.NewLocalListener("tcp")
    21  	require.NoError(t, err)
    22  
    23  	go func() {
    24  		cn, err := ln.Accept()
    25  		require.NoError(t, err)
    26  		cn.Close()
    27  	}()
    28  	// Wait until we can connect, then continue with the test
    29  	testutil.UntilConnect(t, 10, time.Millisecond*100, ln.Addr().String())
    30  }
    31  
    32  func TestUntilPass(t *testing.T) {
    33  	rand.Seed(time.Now().UnixNano())
    34  	var value string
    35  
    36  	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    37  		if r.Method == http.MethodPost {
    38  			// Sleep some rand amount to time to simulate some
    39  			// async process happening on the server
    40  			time.Sleep(time.Duration(rand.Intn(10)) * time.Millisecond)
    41  			// Set the value
    42  			value = r.FormValue("value")
    43  		} else {
    44  			fmt.Fprintln(w, value)
    45  		}
    46  	}))
    47  	defer ts.Close()
    48  
    49  	// Start the async process that produces a value on the server
    50  	res, err := http.PostForm(ts.URL, url.Values{"value": []string{"batch job completed"}})
    51  	require.NoError(t, err)
    52  	defer func() {
    53  		err := res.Body.Close()
    54  		require.NoError(t, err)
    55  	}()
    56  
    57  	// Keep running this until the batch job completes or attempts are exhausted
    58  	testutil.UntilPass(t, 10, time.Millisecond*100, func(t testutil.TestingT) {
    59  		r, err := http.Get(ts.URL)
    60  
    61  		// use of `require` will abort the current test here and tell UntilPass() to
    62  		// run again after 100 milliseconds
    63  		require.NoError(t, err)
    64  
    65  		defer func() {
    66  			err = r.Body.Close()
    67  			require.NoError(t, err)
    68  		}()
    69  
    70  		// Or you can check if the assert returned true or not
    71  		if !assert.Equal(t, 200, r.StatusCode) {
    72  			return
    73  		}
    74  
    75  		b, err := io.ReadAll(r.Body)
    76  		require.NoError(t, err)
    77  
    78  		assert.Equal(t, "batch job completed\n", string(b))
    79  	})
    80  }