github.com/smartcontractkit/chainlink-testing-framework/libs@v0.0.0-20240227141906-ec710b4eb1a3/docker/test_env/wait_strategies.go (about) 1 package test_env 2 3 import ( 4 "context" 5 "fmt" 6 "io" 7 "regexp" 8 "time" 9 10 tcwait "github.com/testcontainers/testcontainers-go/wait" 11 ) 12 13 type LogRegexStrategy struct { 14 timeout *time.Duration 15 Pattern *regexp.Regexp 16 Occurrence int 17 PollInterval time.Duration 18 } 19 20 func NewLogRegexStrategy(pattern *regexp.Regexp) *LogRegexStrategy { 21 return &LogRegexStrategy{ 22 Pattern: pattern, 23 Occurrence: 1, 24 PollInterval: defaultPollInterval(), 25 } 26 } 27 28 func (ws *LogRegexStrategy) WithStartupTimeout(timeout time.Duration) *LogRegexStrategy { 29 ws.timeout = &timeout 30 return ws 31 } 32 33 // WithPollInterval can be used to override the default polling interval of 100 milliseconds 34 func (ws *LogRegexStrategy) WithPollInterval(pollInterval time.Duration) *LogRegexStrategy { 35 ws.PollInterval = pollInterval 36 return ws 37 } 38 39 func (ws *LogRegexStrategy) WithOccurrence(o int) *LogRegexStrategy { 40 // the number of occurrence needs to be positive 41 if o <= 0 { 42 o = 1 43 } 44 ws.Occurrence = o 45 return ws 46 } 47 48 // WaitUntilReady implements Strategy.WaitUntilReady 49 func (ws *LogRegexStrategy) WaitUntilReady(ctx context.Context, target tcwait.StrategyTarget) (err error) { 50 timeout := defaultStartupTimeout() 51 if ws.timeout != nil { 52 timeout = *ws.timeout 53 } 54 55 ctx, cancel := context.WithTimeout(ctx, timeout) 56 defer cancel() 57 58 length := 0 59 60 LOOP: 61 for { 62 select { 63 case <-ctx.Done(): 64 return ctx.Err() 65 default: 66 state, err := target.State(ctx) 67 if err != nil { 68 return err 69 } 70 if !state.Running { 71 return fmt.Errorf("container is not running %s", state.Status) 72 } 73 74 reader, err := target.Logs(ctx) 75 if err != nil { 76 time.Sleep(ws.PollInterval) 77 continue 78 } 79 80 b, err := io.ReadAll(reader) 81 if err != nil { 82 time.Sleep(ws.PollInterval) 83 continue 84 } 85 86 logs := string(b) 87 if length == len(logs) && err != nil { 88 return err 89 } else if len(ws.Pattern.FindAllString(logs, -1)) >= ws.Occurrence { 90 break LOOP 91 } else { 92 length = len(logs) 93 time.Sleep(ws.PollInterval) 94 continue 95 } 96 } 97 } 98 99 return nil 100 } 101 102 func defaultStartupTimeout() time.Duration { 103 return 60 * time.Second 104 } 105 106 func defaultPollInterval() time.Duration { 107 return 100 * time.Millisecond 108 }