86 lines
3.3 KiB
Go
86 lines
3.3 KiB
Go
package health
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
|
|
"proxy-pool/internal/config"
|
|
"proxy-pool/internal/domain/activitypool"
|
|
healthDomain "proxy-pool/internal/domain/health"
|
|
)
|
|
|
|
func TestConfiguredFailureThresholdResolverUsesCurrentProxyUpstream(t *testing.T) {
|
|
now := time.Date(2026, 7, 31, 16, 0, 0, 0, time.UTC)
|
|
source := &configurationSourceStub{configuration: &config.Config{
|
|
Defaults: config.Defaults{Check: config.Check{MaxConsecutiveFailures: 2}},
|
|
Upstreams: map[string]config.Upstream{
|
|
"provider-a": {Enabled: true, Check: config.Check{MaxConsecutiveFailures: 4}},
|
|
"provider-b": {Enabled: true},
|
|
},
|
|
}}
|
|
proxies := &proxyUpstreamReaderStub{upstreams: map[string]string{"proxy-a": "provider-a", "proxy-b": "provider-b"}}
|
|
resolver, err := NewConfiguredFailureThresholdResolver(source, proxies, func() time.Time { return now })
|
|
if err != nil {
|
|
t.Fatalf("NewConfiguredFailureThresholdResolver(): %v", err)
|
|
}
|
|
if threshold, err := resolver(context.Background(), reducerObservation(healthDomain.LevelBasic, now)); err != nil || threshold != 4 {
|
|
t.Fatalf("resolver(provider-a) = (%d, %v)", threshold, err)
|
|
}
|
|
fact := reducerObservation(healthDomain.LevelTarget, now)
|
|
fact.ProxyID = "proxy-b"
|
|
if threshold, err := resolver(context.Background(), fact); err != nil || threshold != 2 {
|
|
t.Fatalf("resolver(provider-b default) = (%d, %v)", threshold, err)
|
|
}
|
|
if proxies.now != now {
|
|
t.Fatalf("lookup time = %v, want %v", proxies.now, now)
|
|
}
|
|
}
|
|
|
|
func TestConfiguredFailureThresholdResolverRejectsUnknownAndInvalidInputs(t *testing.T) {
|
|
now := time.Date(2026, 7, 31, 16, 0, 0, 0, time.UTC)
|
|
source := &configurationSourceStub{configuration: &config.Config{Upstreams: map[string]config.Upstream{}}}
|
|
proxies := &proxyUpstreamReaderStub{upstreams: map[string]string{"proxy-a": "missing"}}
|
|
resolver, err := NewConfiguredFailureThresholdResolver(source, proxies, func() time.Time { return now })
|
|
if err != nil {
|
|
t.Fatalf("NewConfiguredFailureThresholdResolver(): %v", err)
|
|
}
|
|
if _, err := resolver(context.Background(), reducerObservation(healthDomain.LevelBasic, now)); !errors.Is(err, ErrUnconfiguredUpstream) {
|
|
t.Fatalf("resolver(unknown) error = %v, want ErrUnconfiguredUpstream", err)
|
|
}
|
|
if resolver, err := NewConfiguredFailureThresholdResolver(nil, proxies, func() time.Time { return now }); err == nil || resolver != nil {
|
|
t.Fatalf("NewConfiguredFailureThresholdResolver(nil configuration) = (%v, %v)", resolver, err)
|
|
}
|
|
var typedNilReader *proxyUpstreamReaderStub
|
|
if resolver, err := NewConfiguredFailureThresholdResolver(source, typedNilReader, func() time.Time { return now }); err == nil || resolver != nil {
|
|
t.Fatalf("NewConfiguredFailureThresholdResolver(typed nil reader) = (%v, %v)", resolver, err)
|
|
}
|
|
}
|
|
|
|
type configurationSourceStub struct {
|
|
configuration *config.Config
|
|
}
|
|
|
|
func (source *configurationSourceStub) Current() *config.Config {
|
|
return source.configuration
|
|
}
|
|
|
|
type proxyUpstreamReaderStub struct {
|
|
upstreams map[string]string
|
|
now time.Time
|
|
err error
|
|
}
|
|
|
|
func (reader *proxyUpstreamReaderStub) UpstreamForProxy(_ context.Context, proxyID string, now time.Time) (string, error) {
|
|
reader.now = now
|
|
if reader.err != nil {
|
|
return "", reader.err
|
|
}
|
|
upstream, exists := reader.upstreams[proxyID]
|
|
if !exists {
|
|
return "", activitypool.ErrActivityNotFound
|
|
}
|
|
return upstream, nil
|
|
}
|