github.com/yandex/pandora@v0.5.32/lib/testutil/matchers.go (about)

     1  package testutil
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/mock"
     8  	"go.uber.org/atomic"
     9  )
    10  
    11  type TestingT interface {
    12  	mock.TestingT
    13  }
    14  
    15  type flakyT struct {
    16  	t      *testing.T
    17  	failed atomic.Bool
    18  }
    19  
    20  var _ TestingT = &flakyT{}
    21  
    22  func (ff *flakyT) Logf(format string, args ...interface{}) {
    23  	getHelper(ff.t).Helper()
    24  	ff.t.Logf(format, args...)
    25  }
    26  
    27  func (ff *flakyT) Errorf(format string, args ...interface{}) {
    28  	getHelper(ff.t).Helper()
    29  	ff.t.Logf(format, args...)
    30  	ff.failed.Store(true)
    31  }
    32  
    33  func (ff *flakyT) FailNow() {
    34  	// WARN: that may not work in complex case.
    35  	panic("Failing now!")
    36  }
    37  
    38  func RunFlaky(t *testing.T, test func(t TestingT)) {
    39  	const retries = 5
    40  	var passed bool
    41  	for i := 1; i <= retries && !passed; i++ {
    42  		t.Run(fmt.Sprintf("Retry_%v", i), func(t *testing.T) {
    43  			if i == retries {
    44  				t.Log("Last retry.")
    45  				test(t)
    46  				return
    47  			}
    48  			ff := &flakyT{t: t}
    49  
    50  			var hasPanic bool
    51  			func() {
    52  				defer func() {
    53  					hasPanic = recover() != nil
    54  				}()
    55  				test(ff)
    56  			}()
    57  
    58  			passed = !ff.failed.Load() && !hasPanic
    59  			if passed {
    60  				t.Log("Passed!")
    61  			} else {
    62  				t.Log("Failed! Retrying.")
    63  			}
    64  		})
    65  	}
    66  }
    67  
    68  // getHelper allows to call t.Helper() without breaking compatibility with go version < 1.9
    69  func getHelper(t TestingT) helper {
    70  	var tInterface interface{} = t
    71  	if h, ok := tInterface.(helper); ok {
    72  		return h
    73  	}
    74  	return nopHelper{}
    75  }
    76  
    77  type nopHelper struct{}
    78  
    79  func (nopHelper) Helper() {}
    80  
    81  type helper interface {
    82  	Helper()
    83  }