ax(mining): rename circuit_breaker_test.go to TestFilename_Function_{Good,Bad,Ugly} convention

All test functions in circuit_breaker_test.go now follow the AX-required
naming pattern. Added missing _Bad and _Ugly variants and usage-example
comments on each test function.

Co-Authored-By: Charon <charon@lethean.io>
This commit is contained in:
Claude 2026-04-02 12:20:58 +01:00
parent ee3fb3d6b7
commit 99f37ed1bc
No known key found for this signature in database
GPG key ID: AF404715446AEB41

View file

@ -7,7 +7,10 @@ import (
"time"
)
func TestCircuitBreakerDefaultConfig(t *testing.T) {
// TestCircuitBreaker_DefaultConfig_Good verifies that DefaultCircuitBreakerConfig() returns sane defaults.
// configuration := DefaultCircuitBreakerConfig()
// configuration.FailureThreshold == 3
func TestCircuitBreaker_DefaultConfig_Good(t *testing.T) {
configuration := DefaultCircuitBreakerConfig()
if configuration.FailureThreshold != 3 {
@ -21,7 +24,9 @@ func TestCircuitBreakerDefaultConfig(t *testing.T) {
}
}
func TestCircuitBreakerStateString(t *testing.T) {
// TestCircuitBreaker_StateString_Good verifies all known CircuitState values stringify correctly.
// CircuitClosed.String() == "closed"
func TestCircuitBreaker_StateString_Good(t *testing.T) {
tests := []struct {
state CircuitState
expected string
@ -29,7 +34,6 @@ func TestCircuitBreakerStateString(t *testing.T) {
{CircuitClosed, "closed"},
{CircuitOpen, "open"},
{CircuitHalfOpen, "half-open"},
{CircuitState(99), "unknown"},
}
for _, tt := range tests {
@ -39,14 +43,24 @@ func TestCircuitBreakerStateString(t *testing.T) {
}
}
func TestCircuitBreakerClosed(t *testing.T) {
// TestCircuitBreaker_StateString_Ugly verifies unknown CircuitState values stringify to "unknown".
// CircuitState(99).String() == "unknown"
func TestCircuitBreaker_StateString_Ugly(t *testing.T) {
if got := CircuitState(99).String(); got != "unknown" {
t.Errorf("expected 'unknown' for unknown state, got %s", got)
}
}
// TestCircuitBreaker_Execute_Good verifies a closed circuit allows execution and returns results.
// cb := NewCircuitBreaker("test", DefaultCircuitBreakerConfig())
// result, err := cb.Execute(func() (interface{}, error) { return "success", nil })
func TestCircuitBreaker_Execute_Good(t *testing.T) {
cb := NewCircuitBreaker("test", DefaultCircuitBreakerConfig())
if cb.State() != CircuitClosed {
t.Error("expected initial state to be closed")
}
// Successful execution
result, err := cb.Execute(func() (interface{}, error) {
return "success", nil
})
@ -62,7 +76,9 @@ func TestCircuitBreakerClosed(t *testing.T) {
}
}
func TestCircuitBreakerOpensAfterFailures(t *testing.T) {
// TestCircuitBreaker_Execute_Bad verifies that exceeding FailureThreshold opens the circuit.
// cb.Execute(failingFn) × FailureThreshold → cb.State() == CircuitOpen
func TestCircuitBreaker_Execute_Bad(t *testing.T) {
configuration := CircuitBreakerConfig{
FailureThreshold: 2,
ResetTimeout: time.Minute,
@ -72,7 +88,6 @@ func TestCircuitBreakerOpensAfterFailures(t *testing.T) {
testErr := errors.New("test error")
// First failure
_, err := cb.Execute(func() (interface{}, error) {
return nil, testErr
})
@ -83,7 +98,6 @@ func TestCircuitBreakerOpensAfterFailures(t *testing.T) {
t.Error("should still be closed after 1 failure")
}
// Second failure - should open circuit
_, err = cb.Execute(func() (interface{}, error) {
return nil, testErr
})
@ -95,16 +109,17 @@ func TestCircuitBreakerOpensAfterFailures(t *testing.T) {
}
}
func TestCircuitBreakerRejectsWhenOpen(t *testing.T) {
// TestCircuitBreaker_Execute_Ugly verifies that an open circuit rejects calls with ErrCircuitOpen.
// cb (open) → cb.Execute(fn) returns ErrCircuitOpen without calling fn
func TestCircuitBreaker_Execute_Ugly(t *testing.T) {
configuration := CircuitBreakerConfig{
FailureThreshold: 1,
ResetTimeout: time.Hour, // Long timeout to keep circuit open
ResetTimeout: time.Hour,
SuccessThreshold: 1,
}
cb := NewCircuitBreaker("test", configuration)
// Open the circuit
cb.Execute(func() (interface{}, error) {
cb.Execute(func() (interface{}, error) { //nolint:errcheck
return nil, errors.New("fail")
})
@ -112,7 +127,6 @@ func TestCircuitBreakerRejectsWhenOpen(t *testing.T) {
t.Fatal("circuit should be open")
}
// Next request should be rejected
called := false
_, err := cb.Execute(func() (interface{}, error) {
called = true
@ -127,7 +141,10 @@ func TestCircuitBreakerRejectsWhenOpen(t *testing.T) {
}
}
func TestCircuitBreakerTransitionsToHalfOpen(t *testing.T) {
// TestCircuitBreaker_HalfOpen_Good verifies that the circuit transitions from open to half-open after ResetTimeout,
// and closes again on a successful probe.
// cb (open) → sleep(ResetTimeout) → cb.Execute(successFn) → cb.State() == CircuitClosed
func TestCircuitBreaker_HalfOpen_Good(t *testing.T) {
configuration := CircuitBreakerConfig{
FailureThreshold: 1,
ResetTimeout: 50 * time.Millisecond,
@ -135,8 +152,7 @@ func TestCircuitBreakerTransitionsToHalfOpen(t *testing.T) {
}
cb := NewCircuitBreaker("test", configuration)
// Open the circuit
cb.Execute(func() (interface{}, error) {
cb.Execute(func() (interface{}, error) { //nolint:errcheck
return nil, errors.New("fail")
})
@ -144,10 +160,8 @@ func TestCircuitBreakerTransitionsToHalfOpen(t *testing.T) {
t.Fatal("circuit should be open")
}
// Wait for reset timeout
time.Sleep(100 * time.Millisecond)
// Next request should transition to half-open and execute
result, err := cb.Execute(func() (interface{}, error) {
return "probe success", nil
})
@ -163,7 +177,9 @@ func TestCircuitBreakerTransitionsToHalfOpen(t *testing.T) {
}
}
func TestCircuitBreakerHalfOpenFailureReopens(t *testing.T) {
// TestCircuitBreaker_HalfOpen_Bad verifies that a failed probe in half-open state reopens the circuit.
// cb (half-open) → cb.Execute(failFn) → cb.State() == CircuitOpen
func TestCircuitBreaker_HalfOpen_Bad(t *testing.T) {
configuration := CircuitBreakerConfig{
FailureThreshold: 1,
ResetTimeout: 50 * time.Millisecond,
@ -171,16 +187,13 @@ func TestCircuitBreakerHalfOpenFailureReopens(t *testing.T) {
}
cb := NewCircuitBreaker("test", configuration)
// Open the circuit
cb.Execute(func() (interface{}, error) {
cb.Execute(func() (interface{}, error) { //nolint:errcheck
return nil, errors.New("fail")
})
// Wait for reset timeout
time.Sleep(100 * time.Millisecond)
// Probe fails
cb.Execute(func() (interface{}, error) {
cb.Execute(func() (interface{}, error) { //nolint:errcheck
return nil, errors.New("probe failed")
})
@ -189,7 +202,9 @@ func TestCircuitBreakerHalfOpenFailureReopens(t *testing.T) {
}
}
func TestCircuitBreakerCaching(t *testing.T) {
// TestCircuitBreaker_Caching_Good verifies that a successful result is cached and returned when the circuit is open.
// cb.Execute(successFn) → opens circuit → cb.Execute(anyFn) returns cached value
func TestCircuitBreaker_Caching_Good(t *testing.T) {
configuration := CircuitBreakerConfig{
FailureThreshold: 1,
ResetTimeout: time.Hour,
@ -197,7 +212,6 @@ func TestCircuitBreakerCaching(t *testing.T) {
}
cb := NewCircuitBreaker("test", configuration)
// Successful call - caches result
result, err := cb.Execute(func() (interface{}, error) {
return "cached value", nil
})
@ -208,12 +222,10 @@ func TestCircuitBreakerCaching(t *testing.T) {
t.Fatalf("expected 'cached value', got %v", result)
}
// Open the circuit
cb.Execute(func() (interface{}, error) {
cb.Execute(func() (interface{}, error) { //nolint:errcheck
return nil, errors.New("fail")
})
// Should return cached value when circuit is open
result, err = cb.Execute(func() (interface{}, error) {
return "should not run", nil
})
@ -226,17 +238,17 @@ func TestCircuitBreakerCaching(t *testing.T) {
}
}
func TestCircuitBreakerGetCached(t *testing.T) {
// TestCircuitBreaker_GetCached_Good verifies that GetCached returns the last successful result.
// cb.Execute(successFn) → result, ok := cb.GetCached() → ok == true
func TestCircuitBreaker_GetCached_Good(t *testing.T) {
cb := NewCircuitBreaker("test", DefaultCircuitBreakerConfig())
// No cache initially
_, ok := cb.GetCached()
if ok {
t.Error("expected no cached value initially")
}
// Cache a value
cb.Execute(func() (interface{}, error) {
cb.Execute(func() (interface{}, error) { //nolint:errcheck
return "test value", nil
})
@ -249,7 +261,20 @@ func TestCircuitBreakerGetCached(t *testing.T) {
}
}
func TestCircuitBreakerReset(t *testing.T) {
// TestCircuitBreaker_GetCached_Bad verifies that GetCached returns false when no execution has occurred.
// cb := NewCircuitBreaker(...) → _, ok := cb.GetCached() → ok == false
func TestCircuitBreaker_GetCached_Bad(t *testing.T) {
cb := NewCircuitBreaker("test", DefaultCircuitBreakerConfig())
_, ok := cb.GetCached()
if ok {
t.Error("expected no cached value on fresh circuit breaker")
}
}
// TestCircuitBreaker_Reset_Good verifies that Reset forces the circuit back to closed state.
// cb (open) → cb.Reset() → cb.State() == CircuitClosed
func TestCircuitBreaker_Reset_Good(t *testing.T) {
configuration := CircuitBreakerConfig{
FailureThreshold: 1,
ResetTimeout: time.Hour,
@ -257,8 +282,7 @@ func TestCircuitBreakerReset(t *testing.T) {
}
cb := NewCircuitBreaker("test", configuration)
// Open the circuit
cb.Execute(func() (interface{}, error) {
cb.Execute(func() (interface{}, error) { //nolint:errcheck
return nil, errors.New("fail")
})
@ -266,7 +290,6 @@ func TestCircuitBreakerReset(t *testing.T) {
t.Fatal("circuit should be open")
}
// Manual reset
cb.Reset()
if cb.State() != CircuitClosed {
@ -274,7 +297,9 @@ func TestCircuitBreakerReset(t *testing.T) {
}
}
func TestCircuitBreakerConcurrency(t *testing.T) {
// TestCircuitBreaker_Concurrency_Ugly verifies no panics occur under concurrent execution with mixed success/failure.
// 100 goroutines concurrently call cb.Execute — no race condition or panic should occur.
func TestCircuitBreaker_Concurrency_Ugly(t *testing.T) {
cb := NewCircuitBreaker("test", DefaultCircuitBreakerConfig())
var wg sync.WaitGroup
@ -282,7 +307,7 @@ func TestCircuitBreakerConcurrency(t *testing.T) {
wg.Add(1)
go func(n int) {
defer wg.Done()
cb.Execute(func() (interface{}, error) {
cb.Execute(func() (interface{}, error) { //nolint:errcheck
if n%3 == 0 {
return nil, errors.New("fail")
}
@ -292,11 +317,12 @@ func TestCircuitBreakerConcurrency(t *testing.T) {
}
wg.Wait()
// Just verify no panics occurred
_ = cb.State()
}
func TestGetGitHubCircuitBreaker(t *testing.T) {
// TestCircuitBreaker_GitHubSingleton_Good verifies that getGitHubCircuitBreaker returns the same instance each call.
// cb1 := getGitHubCircuitBreaker(); cb2 := getGitHubCircuitBreaker(); cb1 == cb2
func TestCircuitBreaker_GitHubSingleton_Good(t *testing.T) {
cb1 := getGitHubCircuitBreaker()
cb2 := getGitHubCircuitBreaker()
@ -310,12 +336,13 @@ func TestGetGitHubCircuitBreaker(t *testing.T) {
}
// Benchmark tests
func BenchmarkCircuitBreakerExecute(b *testing.B) {
cb := NewCircuitBreaker("bench", DefaultCircuitBreakerConfig())
b.ResetTimer()
for i := 0; i < b.N; i++ {
cb.Execute(func() (interface{}, error) {
cb.Execute(func() (interface{}, error) { //nolint:errcheck
return "result", nil
})
}
@ -326,7 +353,7 @@ func BenchmarkCircuitBreakerConcurrent(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
cb.Execute(func() (interface{}, error) {
cb.Execute(func() (interface{}, error) { //nolint:errcheck
return "result", nil
})
}