110 lines
4.5 KiB
Go
110 lines
4.5 KiB
Go
// Package targettest provides the common behavioral contract for real Target adapters.
|
|
package targettest
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
|
|
"proxyctl/internal/profile"
|
|
"proxyctl/internal/target"
|
|
)
|
|
|
|
// Fixture supplies adapter-specific host setup while assertions stay at the Target seam.
|
|
type Fixture struct {
|
|
Target target.Target
|
|
Active *profile.Profile
|
|
MakeExternal func(*testing.T)
|
|
MakeDrifted func(*testing.T)
|
|
PermissionFailure func(*testing.T) target.OperationResult
|
|
PartialFailure func(*testing.T) target.OperationResult
|
|
RedactionFailure func(*testing.T) target.OperationResult
|
|
RecoveryRetry func(*testing.T) (target.OperationResult, target.OperationResult, target.OperationResult)
|
|
Secret string
|
|
}
|
|
|
|
type Factory func(*testing.T) Fixture
|
|
|
|
// Run verifies the state and desired-state behavior shared by every adapter.
|
|
// Adapter suites add injected permission and partial-effect failures because their
|
|
// failure injection mechanisms necessarily differ.
|
|
func Run(t *testing.T, factory Factory) {
|
|
t.Helper()
|
|
t.Run("common Target contract", func(t *testing.T) {
|
|
fixture := factory(t)
|
|
ctx := context.Background()
|
|
if !fixture.Target.Availability(ctx).Available {
|
|
t.Fatal("Target fixture must be available")
|
|
}
|
|
if got := fixture.Target.Inspect(ctx, fixture.Active).State; got != target.Disabled {
|
|
t.Fatalf("initial state = %s, want Disabled", got)
|
|
}
|
|
if got := fixture.Target.SetDesired(ctx, true, nil); got.Err == nil || !strings.Contains(got.Err.Error(), "Profile management") {
|
|
t.Fatalf("nil Active Profile = %#v", got)
|
|
}
|
|
invalid := &profile.Profile{Name: "invalid", Mode: profile.SingleMode, SingleURL: "ftp://proxy.example:21"}
|
|
if got := fixture.Target.SetDesired(ctx, true, invalid); got.Err == nil || got.Inspection.State != target.Disabled {
|
|
t.Fatalf("validation failure = %#v", got)
|
|
}
|
|
if got := fixture.Target.SetDesired(ctx, true, fixture.Active); got.Err != nil || got.Inspection.State != target.Enabled {
|
|
t.Fatalf("enable = %#v", got)
|
|
}
|
|
if got := fixture.Target.SetDesired(ctx, true, fixture.Active); got.Err != nil || got.Inspection.State != target.Enabled {
|
|
t.Fatalf("idempotent enable = %#v", got)
|
|
}
|
|
fixture.MakeDrifted(t)
|
|
if got := fixture.Target.Inspect(ctx, fixture.Active).State; got != target.Drifted {
|
|
t.Fatalf("drift state = %s", got)
|
|
}
|
|
if got := fixture.Target.SetDesired(ctx, true, fixture.Active); got.Err != nil || got.Inspection.State != target.Enabled {
|
|
t.Fatalf("repair = %#v", got)
|
|
}
|
|
if got := fixture.Target.SetDesired(ctx, false, nil); got.Err != nil {
|
|
t.Fatalf("disable = %#v", got)
|
|
}
|
|
if got := fixture.Target.SetDesired(ctx, false, nil); got.Err != nil {
|
|
t.Fatalf("idempotent disable = %#v", got)
|
|
}
|
|
|
|
external := factory(t)
|
|
external.MakeExternal(t)
|
|
if got := external.Target.Inspect(ctx, external.Active).State; got != target.External {
|
|
t.Fatalf("external state = %s", got)
|
|
}
|
|
if got := external.Target.SetDesired(ctx, true, external.Active); got.Err != nil {
|
|
t.Fatalf("enable over External = %#v", got)
|
|
}
|
|
if got := external.Target.SetDesired(ctx, false, nil); got.Err != nil || got.Inspection.State != target.External {
|
|
t.Fatalf("restore External = %#v", got)
|
|
}
|
|
|
|
permission := fixture.PermissionFailure(t)
|
|
if permission.Err == nil || !errors.Is(permission.Err, os.ErrPermission) || permission.Inspection.State != target.Disabled {
|
|
t.Fatalf("permission failure = %#v", permission)
|
|
}
|
|
partial := fixture.PartialFailure(t)
|
|
if partial.Err == nil || partial.Inspection.State != target.Drifted {
|
|
t.Fatalf("partial failure = %#v", partial)
|
|
}
|
|
first, retry, disabled := fixture.RecoveryRetry(t)
|
|
if first.Err == nil || first.Inspection.State != target.External || retry.Err != nil || retry.Inspection.State != target.Enabled || disabled.Err != nil || disabled.Inspection.State != target.External {
|
|
t.Fatalf("recovery retry transaction = first %#v, retry %#v, disable %#v", first, retry, disabled)
|
|
}
|
|
|
|
redacted := fixture.RedactionFailure(t)
|
|
if redacted.Err == nil || fixture.Secret == "" {
|
|
t.Fatalf("redaction failure = %#v", redacted)
|
|
}
|
|
for current := redacted.Err; current != nil; current = errors.Unwrap(current) {
|
|
for _, rendered := range []string{current.Error(), fmt.Sprintf("%v", current), fmt.Sprintf("%+v", current), fmt.Sprintf("%#v", current)} {
|
|
if strings.Contains(rendered, fixture.Secret) {
|
|
t.Fatalf("secret in error chain representation %q", rendered)
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|