proxy-pool/internal/controller/health/policy_test.go
youfak 65aee12d51
Some checks are pending
ci / proto (push) Waiting to run
ci / test (ubuntu-latest) (push) Waiting to run
ci / test (windows-latest) (push) Waiting to run
ci / race (push) Waiting to run
ci / integration (push) Waiting to run
feat: wire checker observations into controller
2026-07-31 18:25:07 +08:00

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
}