github.com/ydb-platform/ydb-go-sdk/v3@v3.57.0/internal/repeater/repeater_test.go (about)

     1  package repeater
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"runtime"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/jonboulle/clockwork"
    11  )
    12  
    13  func TestRepeaterNoWakeUpsAfterStop(t *testing.T) {
    14  	var (
    15  		interval    = time.Millisecond
    16  		wakeUpStart = make(chan struct{})
    17  		wakeUpDone  = make(chan struct{})
    18  	)
    19  	fakeClock := clockwork.NewFakeClock()
    20  	r := New(context.Background(), interval, func(ctx context.Context) (err error) {
    21  		wakeUpStart <- struct{}{}
    22  		<-wakeUpDone
    23  
    24  		return nil
    25  	}, WithClock(fakeClock))
    26  
    27  	fakeClock.Advance(interval)
    28  	<-wakeUpStart            // wait first wake up
    29  	wakeUpDone <- struct{}{} // unlock exit from first wake up
    30  
    31  	fakeClock.Advance(interval)
    32  	<-wakeUpStart   // wait second wake up
    33  	r.stop(func() { // call stop
    34  		wakeUpDone <- struct{}{} // unlock exit from second wake up
    35  	})
    36  
    37  	noWakeup := make(chan struct{})
    38  	go func() {
    39  		<-fakeClock.After(interval * 2)
    40  		noWakeup <- struct{}{}
    41  	}()
    42  
    43  waitNoWakeup:
    44  	for {
    45  		fakeClock.Advance(interval)
    46  		select {
    47  		case <-wakeUpStart:
    48  			t.Fatalf("unexpected wake up after stop")
    49  		case <-noWakeup:
    50  			break waitNoWakeup
    51  		default:
    52  			runtime.Gosched()
    53  		}
    54  	}
    55  }
    56  
    57  func TestRepeaterForceLogBackoff(t *testing.T) {
    58  	delays := []time.Duration{
    59  		0 * time.Second,
    60  		1 * time.Second,  // 1 sec
    61  		2 * time.Second,  // 3 sec
    62  		4 * time.Second,  // 7 sec
    63  		8 * time.Second,  // 15 sec
    64  		16 * time.Second, // 31 sec
    65  		32 * time.Second, // 63 sec
    66  	}
    67  
    68  	fakeClock := clockwork.NewFakeClock()
    69  	var (
    70  		wakeUps    = 0
    71  		lastWakeUp = fakeClock.Now()
    72  	)
    73  
    74  	repeaterDone := make(chan struct{})
    75  	r := New(context.Background(), 10*time.Minute, func(ctx context.Context) (err error) {
    76  		defer func() {
    77  			repeaterDone <- struct{}{}
    78  		}()
    79  
    80  		sinceLastWakeUp := fakeClock.Since(lastWakeUp)
    81  		d := delays[wakeUps]
    82  		if sinceLastWakeUp != d {
    83  			t.Fatalf("unexpected wake up delay: %v, exp: %v", sinceLastWakeUp, d)
    84  		}
    85  		lastWakeUp = fakeClock.Now()
    86  		wakeUps++
    87  
    88  		return fmt.Errorf("special error for force with log backoff")
    89  	}, WithClock(fakeClock))
    90  	defer r.Stop()
    91  
    92  	r.Force()
    93  	<-repeaterDone
    94  
    95  	for _, delay := range delays[1:] {
    96  		// ensure right listeners attached
    97  		fakeClock.BlockUntil(2)
    98  
    99  		// release trash timer listeners
   100  		fakeClock.Advance(delay - 1)
   101  
   102  		// fire estimated time
   103  		fakeClock.Advance(1)
   104  		<-repeaterDone
   105  	}
   106  }