package circuitbreaker import ( "errors" "testing" "time" "github.com/stretchr/testify/require" ) const success = "Success" func TestCircuitBreaker_ExecuteSuccessSingle(t *testing.T) { cb := NewCircuitBreaker(Config{ CommandName: "SuccessSingle", // unique name to avoid conflicts with go tests `-count` option Timeout: 1000, MaxConcurrentRequests: 100, RequestVolumeThreshold: 10, SleepWindow: 10, ErrorPercentThreshold: 10, }) expectedResult := success cmd := Command{ functors: []*Functor{ NewFunctor(func() ([]interface{}, error) { return []any{expectedResult}, nil }), }, } result := cb.Execute(cmd) require.NoError(t, result.Error()) require.Equal(t, expectedResult, result.Result()[0].(string)) } func TestCircuitBreaker_ExecuteMultipleFallbacksFail(t *testing.T) { cb := NewCircuitBreaker(Config{ CommandName: "MultipleFail", // unique name to avoid conflicts with go tests `-count` option Timeout: 10, MaxConcurrentRequests: 100, RequestVolumeThreshold: 10, SleepWindow: 10, ErrorPercentThreshold: 10, }) cmd := Command{ functors: []*Functor{ NewFunctor(func() ([]interface{}, error) { time.Sleep(100 * time.Millisecond) // will cause hystrix: timeout return []any{success}, nil }), NewFunctor(func() ([]interface{}, error) { return nil, errors.New("provider 2 failed") }), NewFunctor(func() ([]interface{}, error) { return nil, errors.New("provider 3 failed") }), }, } result := cb.Execute(cmd) require.Error(t, result.Error()) } func TestCircuitBreaker_ExecuteMultipleFallbacksFailButLastSuccessStress(t *testing.T) { cb := NewCircuitBreaker(Config{ CommandName: "LastSuccessStress", // unique name to avoid conflicts with go tests `-count` option Timeout: 10, MaxConcurrentRequests: 100, RequestVolumeThreshold: 10, SleepWindow: 10, ErrorPercentThreshold: 10, }) expectedResult := success // These are executed sequentially, but I had an issue with the test failing // because of the open circuit for i := 0; i < 1000; i++ { cmd := Command{ functors: []*Functor{ NewFunctor(func() ([]interface{}, error) { return nil, errors.New("provider 1 failed") }), NewFunctor(func() ([]interface{}, error) { return nil, errors.New("provider 2 failed") }), NewFunctor(func() ([]interface{}, error) { return []any{expectedResult}, nil }), }, } result := cb.Execute(cmd) require.NoError(t, result.Error()) require.Equal(t, expectedResult, result.Result()[0].(string)) } }