Files
owncast/activitypub/workerpool/outbound_test.go

128 lines
3.4 KiB
Go

package workerpool
import (
"testing"
"time"
)
// resetCircuitBreakerForTesting clears all failed domain state for testing purposes.
// This function provides test isolation by resetting the global circuit breaker state.
func resetCircuitBreakerForTesting() {
failedDomainsMutex.Lock()
defer failedDomainsMutex.Unlock()
failedDomains = make(map[string]*domainFailure)
}
func TestCircuitBreaker(t *testing.T) {
// Ensure clean state before test
resetCircuitBreakerForTesting()
defer resetCircuitBreakerForTesting() // Clean up after test
testDomain := "failing.example.com"
// Initially, domain should not be skipped
if shouldSkipDomain(testDomain) {
t.Error("Domain should not be skipped initially")
}
// Record failures
recordDomainFailure(testDomain)
recordDomainFailure(testDomain)
recordDomainFailure(testDomain)
// Domain should now be skipped
if !shouldSkipDomain(testDomain) {
t.Error("Domain should be skipped after failures")
}
// After successful delivery, domain should be reset
resetDomainFailure(testDomain)
if shouldSkipDomain(testDomain) {
t.Error("Domain should not be skipped after reset")
}
}
func TestHTTPTimeouts(t *testing.T) {
// Ensure clean state before test
resetCircuitBreakerForTesting()
defer resetCircuitBreakerForTesting() // Clean up after test
// Initialize HTTP client
InitOutboundWorkerPool(1)
if httpClient == nil {
t.Error("HTTP client should be initialized")
}
if httpClient.Timeout != 15*time.Second {
t.Error("HTTP client should have 15 second timeout")
}
}
func TestWorkerPoolSizing(t *testing.T) {
// Ensure clean state before test
resetCircuitBreakerForTesting()
defer resetCircuitBreakerForTesting() // Clean up after test
// Test the queue sizing
InitOutboundWorkerPool(5)
if cap(queue) != 5 {
t.Errorf("Queue capacity should be 5, got %d", cap(queue))
}
}
func TestBackoffDurations(t *testing.T) {
// Test that backoff durations are properly configured
expectedDurations := []time.Duration{
1 * time.Minute,
5 * time.Minute,
15 * time.Minute,
30 * time.Minute,
60 * time.Minute,
}
if len(circuitBreakerBackoffDurations) != len(expectedDurations) {
t.Errorf("Expected %d backoff durations, got %d", len(expectedDurations), len(circuitBreakerBackoffDurations))
}
for i, expected := range expectedDurations {
if circuitBreakerBackoffDurations[i] != expected {
t.Errorf("Backoff duration at index %d: expected %v, got %v", i, expected, circuitBreakerBackoffDurations[i])
}
}
}
func TestCircuitBreakerIsolation(t *testing.T) {
// Test that multiple tests don't interfere with each other
resetCircuitBreakerForTesting()
defer resetCircuitBreakerForTesting()
domain1 := "test1.example.com"
domain2 := "test2.example.com"
// Neither domain should be blocked initially
if shouldSkipDomain(domain1) || shouldSkipDomain(domain2) {
t.Error("Domains should not be blocked initially")
}
// Record failures for domain1 only
recordDomainFailure(domain1)
recordDomainFailure(domain1)
recordDomainFailure(domain1)
// Only domain1 should be blocked
if !shouldSkipDomain(domain1) {
t.Error("Domain1 should be blocked after failures")
}
if shouldSkipDomain(domain2) {
t.Error("Domain2 should not be blocked")
}
// Reset and verify clean state
resetCircuitBreakerForTesting()
if shouldSkipDomain(domain1) || shouldSkipDomain(domain2) {
t.Error("Both domains should be unblocked after reset")
}
}