func TestMaxExponentialWithContext_New(t *testing.T) {
	cases := map[string]struct {
		cfg         Exponential
		ctxDuration time.Duration
		expected    []time.Duration
	}{
		"linear": {
			cfg: Exponential{
				Base:    0,
				YOffset: 10 * time.Microsecond,
			},
			ctxDuration: 31 * time.Microsecond,
			expected:    []time.Duration{10 * time.Microsecond, 10 * time.Microsecond, 10 * time.Microsecond},
		},
		"exponential: 10us*2^x + 10us (limit 50 with max exec context of 205ms)": {
			cfg: Exponential{
				Base:               2,
				Scaling:            10 * time.Microsecond,
				YOffset:            10 * time.Microsecond,
				MaxAttemptWaitTime: 50 * time.Microsecond,
			},
			ctxDuration: 205 * time.Microsecond,
			expected:    []time.Duration{20 * time.Microsecond, 30 * time.Microsecond, 50 * time.Microsecond, 50 * time.Microsecond},
		},
		"exponential: 10us*2^x + 10us (limit 50 with max exec context of 105ms)": {
			cfg: Exponential{
				Base:               2,
				Scaling:            10 * time.Microsecond,
				YOffset:            10 * time.Microsecond,
				MaxAttemptWaitTime: 50 * time.Microsecond,
			},
			ctxDuration: 105 * time.Microsecond,
			expected:    []time.Duration{20 * time.Microsecond, 30 * time.Microsecond, 50 * time.Microsecond},
		},
	}

	for caseName, c := range cases {
		t.Run(caseName, func(t *testing.T) {
			ctx, cancel := context.WithTimeout(context.Background(), c.ctxDuration)
			svcInterface := c.cfg.NewWithContext(ctx)
			svc := svcInterface.(*maxExponentialContextService)
			startAt := time.Now()
			for i := 0; i < len(c.expected); i++ {
				svc.Yield()
			}
			cancel()
			endAt := time.Now()
			expectedEndAt := startAt.Add(c.ctxDuration)
			if expectedEndAt.Add(1 * time.Microsecond).After(endAt) {
				t.Errorf(`exceeded context timeout, over by %v`, endAt.Sub(expectedEndAt))
			}
		})
	}
}
// TestMaxExponentialWithContext_New ensures that the context governs the maximum run time of a retry
TestMaxExponentialWithContext_New ensures that the context governs the maximum run time of a retry
// TestMaxExponentialWithContext_New ensures that the context governs the maximum run time of a retry
func TestMaxExponentialWithContext_New(t *testing.T) {
	cases := map[string]struct {
		cfg         Exponential
		ctxDuration time.Duration
		expected    []time.Duration
	}{
		"linear": {
			cfg: Exponential{
				Base:    0,
				YOffset: 10 * time.Microsecond,
			},
			ctxDuration: 31 * time.Microsecond,
			expected:    []time.Duration{10 * time.Microsecond, 10 * time.Microsecond, 10 * time.Microsecond},
		},
		"exponential: 10us*2^x + 10us (limit 50 with max exec context of 205ms)": {
			cfg: Exponential{
				Base:               2,
				Scaling:            10 * time.Microsecond,
				YOffset:            10 * time.Microsecond,
				MaxAttemptWaitTime: 50 * time.Microsecond,
			},
			ctxDuration: 205 * time.Microsecond,
			expected:    []time.Duration{20 * time.Microsecond, 30 * time.Microsecond, 50 * time.Microsecond, 50 * time.Microsecond},
		},
		"exponential: 10us*2^x + 10us (limit 50 with max exec context of 105ms)": {
			cfg: Exponential{
				Base:               2,
				Scaling:            10 * time.Microsecond,
				YOffset:            10 * time.Microsecond,
				MaxAttemptWaitTime: 50 * time.Microsecond,
			},
			ctxDuration: 105 * time.Microsecond,
			expected:    []time.Duration{20 * time.Microsecond, 30 * time.Microsecond, 50 * time.Microsecond},
		},
	}
	for caseName, c := range cases {
		t.Run(caseName, func(t *testing.T) {
			ctx, cancel := context.WithTimeout(context.Background(), c.ctxDuration)
			svcInterface := c.cfg.NewWithContext(ctx)
			svc := svcInterface.(*maxExponentialContextService)
			startAt := time.Now()
			for i := 0; i < len(c.expected); i++ {
				svc.Yield()
			}
			cancel()
			endAt := time.Now()
			expectedEndAt := startAt.Add(c.ctxDuration)
			if expectedEndAt.Add(1 * time.Microsecond).After(endAt) {
				t.Errorf(`exceeded context timeout, over by %v`, endAt.Sub(expectedEndAt))
			}
		})
	}
}
func TestMaxExponentialWithContext_New ( t * testing . T ) { cases := map [ string ] struct { cfg Exponential ctxDuration time . Duration expected [ ] time . Duration } { " " : { cfg : Exponential { Base : 0 , YOffset : 10 * time . Microsecond , } , ctxDuration : 31 * time . Microsecond , expected : [ ] time . Duration { 10 * time . Microsecond , 10 * time . Microsecond , 10 * time . Microsecond } , } , " " : { cfg : Exponential { Base : 2 , Scaling : 10 * time . Microsecond , YOffset : 10 * time . Microsecond , MaxAttemptWaitTime : 50 * time . Microsecond , } , ctxDuration : 205 * time . Microsecond , expected : [ ] time . Duration { 20 * time . Microsecond , 30 * time . Microsecond , 50 * time . Microsecond , 50 * time . Microsecond } , } , " " : { cfg : Exponential { Base : 2 , Scaling : 10 * time . Microsecond , YOffset : 10 * time . Microsecond , MaxAttemptWaitTime : 50 * time . Microsecond , } , ctxDuration : 105 * time . Microsecond , expected : [ ] time . Duration { 20 * time . Microsecond , 30 * time . Microsecond , 50 * time . Microsecond } , } , } for caseName , c := range cases { t . Run ( caseName , func ( t * testing . T ) { ctx , cancel := context . WithTimeout ( context . Background ( ) , c . ctxDuration ) svcInterface := c . cfg . NewWithContext ( ctx ) svc := svcInterface . ( * maxExponentialContextService ) startAt := time . Now ( ) for i := 0 ; i < len ( c . expected ) ; i ++ { svc . Yield ( ) } cancel ( ) endAt := time . Now ( ) expectedEndAt := startAt . Add ( c . ctxDuration ) if expectedEndAt . Add ( 1 * time . Microsecond ) . After ( endAt ) { t . Errorf ( `exceeded context timeout, over by %v` , endAt . Sub ( expectedEndAt ) ) } } ) } }
TestMaxExponentialWithContext_New ensures that the context governs the maximum run time of a retry
TestMaxExponentialWithContext_New ensures that the context governs the maximum run time of a retry