@@ -254,17 +254,18 @@ func TestPrintLogs(t *testing.T) {
254254 createFileContent (t , dir , f .name , bytes .NewBuffer ([]byte (f .content )))
255255 }
256256 result := bytes .NewBuffer (nil )
257- err := printLogs (context . Background (), result , dir , tc .lines , false , nil , nil )
257+ err := printLogs (t . Context (), result , dir , tc .lines , false , nil , nil )
258258 require .NoError (t , err )
259259
260260 require .Equal (t , tc .expected , result .String ())
261261 })
262262 }
263263
264+ const waitUntilMatchTimeout = 5 * time .Second
264265 t .Run ("returns tail and then follows the logs" , func (t * testing.T ) {
265266 dir := t .TempDir ()
266267 createFileContent (t , dir , file1 , bytes .NewBuffer ([]byte (generateLines (line1 , 1 , 10 ))))
267- ctx , cancel := context .WithCancel (context . Background ())
268+ ctx , cancel := context .WithCancel (t . Context ())
268269 defer cancel ()
269270
270271 logResult := newChanWriter ()
@@ -276,7 +277,8 @@ func TestPrintLogs(t *testing.T) {
276277 var expected string
277278 t .Run ("tails the file" , func (t * testing.T ) {
278279 expected = generateLines (line1 , 6 , 10 )
279- logResult .waitUntilMatch (t , expected , time .Second )
280+ err := logResult .waitUntilMatch (t .Context (), expected , waitUntilMatchTimeout )
281+ require .NoError (t , err )
280282 })
281283
282284 t .Run ("detects new lines and prints them" , func (t * testing.T ) {
@@ -287,29 +289,32 @@ func TestPrintLogs(t *testing.T) {
287289 f .Close ()
288290
289291 expected += generateLines (line1 , 11 , 20 )
290- logResult .waitUntilMatch (t , expected , 3 * watchInterval )
292+ err = logResult .waitUntilMatch (t .Context (), expected , waitUntilMatchTimeout )
293+ require .NoError (t , err )
291294 })
292295
293296 t .Run ("detects a new file and switches to it" , func (t * testing.T ) {
294297 createFileContent (t , dir , file2 , bytes .NewBuffer ([]byte (generateLines (line2 , 1 , 20 ))))
295298
296299 expected += generateLines (line2 , 1 , 20 )
297- logResult .waitUntilMatch (t , expected , 3 * watchInterval )
300+ err := logResult .waitUntilMatch (t .Context (), expected , waitUntilMatchTimeout )
301+ require .NoError (t , err )
298302 })
299303
300304 t .Run ("detects another file and switches to it" , func (t * testing.T ) {
301305 createFileContent (t , dir , file3 , bytes .NewBuffer ([]byte (generateLines (line3 , 1 , 30 ))))
302306
303307 expected += generateLines (line3 , 1 , 30 )
304- logResult .waitUntilMatch (t , expected , 3 * watchInterval )
308+ err := logResult .waitUntilMatch (t .Context (), expected , waitUntilMatchTimeout )
309+ require .NoError (t , err )
305310 })
306311
307312 t .Run ("handles interruption correctly" , func (t * testing.T ) {
308313 cancel ()
309314 select {
310315 case err := <- errChan :
311316 require .ErrorIs (t , err , context .Canceled )
312- case <- time .After (time .Second ):
317+ case <- time .After (2 * time .Second ):
313318 require .FailNow (t , "context must stop logs following" )
314319 }
315320 })
@@ -326,7 +331,7 @@ func TestPrintLogs(t *testing.T) {
326331` )
327332
328333 createFileContent (t , dir , file1 , bytes .NewBuffer (content ))
329- ctx , cancel := context .WithCancel (context . Background ())
334+ ctx , cancel := context .WithCancel (t . Context ())
330335 defer cancel ()
331336 logResult := newChanWriter ()
332337 errChan := make (chan error )
@@ -341,7 +346,8 @@ func TestPrintLogs(t *testing.T) {
341346!{"component":{"id":"match"}, "message":"test4"}!
342347!{"component":{"id":"match"}, "message":"test6"}!
343348`
344- logResult .waitUntilMatch (t , expected , time .Second )
349+ err := logResult .waitUntilMatch (t .Context (), expected , waitUntilMatchTimeout )
350+ require .NoError (t , err )
345351 })
346352
347353 t .Run ("detects new lines and prints them with filter" , func (t * testing.T ) {
@@ -368,7 +374,8 @@ func TestPrintLogs(t *testing.T) {
368374!{"component":{"id":"match"}, "message":"test12"}!
369375`
370376
371- logResult .waitUntilMatch (t , expected , 2 * watchInterval )
377+ err = logResult .waitUntilMatch (t .Context (), expected , waitUntilMatchTimeout )
378+ require .NoError (t , err )
372379 })
373380
374381 t .Run ("detects a new file and switches to it with filter" , func (t * testing.T ) {
@@ -385,7 +392,8 @@ func TestPrintLogs(t *testing.T) {
385392!{"component":{"id":"match"}, "message":"test15"}!
386393`
387394
388- logResult .waitUntilMatch (t , expected , 2 * watchInterval )
395+ err := logResult .waitUntilMatch (t .Context (), expected , waitUntilMatchTimeout )
396+ require .NoError (t , err )
389397 })
390398
391399 t .Run ("handles interruption correctly" , func (t * testing.T ) {
@@ -657,24 +665,37 @@ func (cw *chanWriter) Write(p []byte) (int, error) {
657665 return len (p ), nil
658666}
659667
660- // Waits until the combined data written to this object matches the expected
661- // string (after conversion), or the timeout expires, whichever comes first.
662- // Reports a fatal test error if the match fails.
668+ // waitUntilMatch waits until the accumulated output matches the expected string.
669+ //
670+ // The timeout is based on data idleness and resets each time new data arrives.
671+ // Returns nil on match, or an error if the timeout expires or the context is canceled.
663672func (cw * chanWriter ) waitUntilMatch (
664- t * testing. T ,
673+ ctx context. Context ,
665674 expected string ,
666675 timeout time.Duration ,
667- ) {
668- t .Helper ()
669- timeoutChan := time .After (timeout )
670- for string (cw .result ) != expected {
676+ ) error {
677+ timeoutChan := time .NewTimer (timeout )
678+
679+ loop:
680+ for {
681+ if len (cw .result ) > len (expected ) && string (cw .result ) != expected {
682+ break loop
683+ }
671684 select {
685+ case <- ctx .Done ():
686+ return ctx .Err ()
672687 case data := <- cw .ch :
688+ timeoutChan .Stop ()
673689 cw .result = append (cw .result , data ... )
674- case <- timeoutChan :
675- require .FailNow (t , fmt .Sprintf ("output does not match. got:\n %v\n expected:\n %v" , string (cw .result ), expected ))
690+ if string (cw .result ) == expected {
691+ return nil
692+ }
693+ timeoutChan .Reset (timeout )
694+ case <- timeoutChan .C :
695+ break loop
676696 }
677697 }
698+ return fmt .Errorf ("timed out waiting for output to match. got:\n %v\n expected:\n %v" , string (cw .result ), expected )
678699}
679700
680701func TestCobraCmd (t * testing.T ) {
0 commit comments