chore: clean .gitignore cache
This commit is contained in:
@@ -1,553 +0,0 @@
|
||||
package dnsprovider
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// mockProvider is a test implementation of ProviderPlugin
|
||||
type mockProvider struct {
|
||||
providerType string
|
||||
}
|
||||
|
||||
func (m *mockProvider) Type() string {
|
||||
return m.providerType
|
||||
}
|
||||
|
||||
func (m *mockProvider) Metadata() ProviderMetadata {
|
||||
return ProviderMetadata{
|
||||
Type: m.providerType,
|
||||
Name: "Mock Provider",
|
||||
Version: "1.0.0",
|
||||
IsBuiltIn: false,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *mockProvider) Init() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockProvider) Cleanup() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockProvider) ValidateCredentials(creds map[string]string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockProvider) TestCredentials(creds map[string]string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockProvider) RequiredCredentialFields() []CredentialFieldSpec {
|
||||
return []CredentialFieldSpec{}
|
||||
}
|
||||
|
||||
func (m *mockProvider) OptionalCredentialFields() []CredentialFieldSpec {
|
||||
return []CredentialFieldSpec{}
|
||||
}
|
||||
|
||||
func (m *mockProvider) SupportsMultiCredential() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *mockProvider) BuildCaddyConfig(creds map[string]string) map[string]any {
|
||||
return map[string]any{}
|
||||
}
|
||||
|
||||
func (m *mockProvider) BuildCaddyConfigForZone(baseDomain string, creds map[string]string) map[string]any {
|
||||
return map[string]any{}
|
||||
}
|
||||
|
||||
func (m *mockProvider) PropagationTimeout() time.Duration {
|
||||
return time.Minute
|
||||
}
|
||||
|
||||
func (m *mockProvider) PollingInterval() time.Duration {
|
||||
return 2 * time.Second
|
||||
}
|
||||
|
||||
// TestNewRegistry tests creating a new registry instance
|
||||
func TestNewRegistry(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
if r == nil {
|
||||
t.Fatal("NewRegistry returned nil")
|
||||
}
|
||||
|
||||
if r.Count() != 0 {
|
||||
t.Errorf("expected empty registry, got %d providers", r.Count())
|
||||
}
|
||||
}
|
||||
|
||||
// TestGlobal tests the global registry singleton
|
||||
func TestGlobal(t *testing.T) {
|
||||
r1 := Global()
|
||||
r2 := Global()
|
||||
|
||||
if r1 != r2 {
|
||||
t.Error("Global() should return the same instance")
|
||||
}
|
||||
|
||||
if r1 == nil {
|
||||
t.Fatal("Global() returned nil")
|
||||
}
|
||||
}
|
||||
|
||||
// TestRegister tests registering providers
|
||||
func TestRegister(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
provider ProviderPlugin
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
name: "successful registration",
|
||||
provider: &mockProvider{providerType: "test-provider"},
|
||||
wantErr: nil,
|
||||
},
|
||||
{
|
||||
name: "nil provider",
|
||||
provider: nil,
|
||||
wantErr: ErrInvalidPlugin,
|
||||
},
|
||||
{
|
||||
name: "empty provider type",
|
||||
provider: &mockProvider{providerType: ""},
|
||||
wantErr: ErrInvalidPlugin,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
err := r.Register(tt.provider)
|
||||
|
||||
if err != tt.wantErr {
|
||||
t.Errorf("Register() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
|
||||
// If successful, verify provider was registered
|
||||
if err == nil && tt.provider != nil {
|
||||
if !r.IsSupported(tt.provider.Type()) {
|
||||
t.Errorf("provider %s was not registered", tt.provider.Type())
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestRegister_Duplicate tests duplicate registration
|
||||
func TestRegister_Duplicate(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
|
||||
provider := &mockProvider{providerType: "duplicate-test"}
|
||||
|
||||
// First registration should succeed
|
||||
err := r.Register(provider)
|
||||
if err != nil {
|
||||
t.Fatalf("first registration failed: %v", err)
|
||||
}
|
||||
|
||||
// Second registration should fail
|
||||
err = r.Register(provider)
|
||||
if err != ErrProviderAlreadyRegistered {
|
||||
t.Errorf("expected ErrProviderAlreadyRegistered, got %v", err)
|
||||
}
|
||||
|
||||
// Count should still be 1
|
||||
if r.Count() != 1 {
|
||||
t.Errorf("expected count 1, got %d", r.Count())
|
||||
}
|
||||
}
|
||||
|
||||
// TestGet tests retrieving providers
|
||||
func TestGet(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
|
||||
provider := &mockProvider{providerType: "test-get"}
|
||||
if err := r.Register(provider); err != nil {
|
||||
t.Fatalf("failed to register provider: %v", err)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
providerType string
|
||||
wantOK bool
|
||||
}{
|
||||
{
|
||||
name: "existing provider",
|
||||
providerType: "test-get",
|
||||
wantOK: true,
|
||||
},
|
||||
{
|
||||
name: "non-existent provider",
|
||||
providerType: "does-not-exist",
|
||||
wantOK: false,
|
||||
},
|
||||
{
|
||||
name: "empty provider type",
|
||||
providerType: "",
|
||||
wantOK: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
gotProvider, gotOK := r.Get(tt.providerType)
|
||||
|
||||
if gotOK != tt.wantOK {
|
||||
t.Errorf("Get() ok = %v, want %v", gotOK, tt.wantOK)
|
||||
}
|
||||
|
||||
if tt.wantOK {
|
||||
if gotProvider == nil {
|
||||
t.Error("expected non-nil provider for existing type")
|
||||
}
|
||||
if gotProvider.Type() != tt.providerType {
|
||||
t.Errorf("got provider type %s, want %s", gotProvider.Type(), tt.providerType)
|
||||
}
|
||||
} else {
|
||||
if gotProvider != nil {
|
||||
t.Error("expected nil provider for non-existent type")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestList tests listing all providers
|
||||
func TestList(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
|
||||
// Test empty registry
|
||||
list := r.List()
|
||||
if len(list) != 0 {
|
||||
t.Errorf("expected empty list, got %d providers", len(list))
|
||||
}
|
||||
|
||||
// Register multiple providers
|
||||
providers := []*mockProvider{
|
||||
{providerType: "provider-c"},
|
||||
{providerType: "provider-a"},
|
||||
{providerType: "provider-b"},
|
||||
}
|
||||
|
||||
for _, p := range providers {
|
||||
if err := r.Register(p); err != nil {
|
||||
t.Fatalf("failed to register provider %s: %v", p.Type(), err)
|
||||
}
|
||||
}
|
||||
|
||||
// Get list (should be sorted)
|
||||
list = r.List()
|
||||
|
||||
if len(list) != 3 {
|
||||
t.Fatalf("expected 3 providers, got %d", len(list))
|
||||
}
|
||||
|
||||
// Verify alphabetical ordering
|
||||
expectedOrder := []string{"provider-a", "provider-b", "provider-c"}
|
||||
for i, p := range list {
|
||||
if p.Type() != expectedOrder[i] {
|
||||
t.Errorf("list[%d] = %s, want %s", i, p.Type(), expectedOrder[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestTypes tests listing provider types
|
||||
func TestTypes(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
|
||||
// Test empty registry
|
||||
types := r.Types()
|
||||
if len(types) != 0 {
|
||||
t.Errorf("expected empty types, got %d", len(types))
|
||||
}
|
||||
|
||||
// Register multiple providers
|
||||
providers := []*mockProvider{
|
||||
{providerType: "zebra"},
|
||||
{providerType: "alpha"},
|
||||
{providerType: "beta"},
|
||||
}
|
||||
|
||||
for _, p := range providers {
|
||||
if err := r.Register(p); err != nil {
|
||||
t.Fatalf("failed to register provider %s: %v", p.Type(), err)
|
||||
}
|
||||
}
|
||||
|
||||
// Get types (should be sorted)
|
||||
types = r.Types()
|
||||
|
||||
if len(types) != 3 {
|
||||
t.Fatalf("expected 3 types, got %d", len(types))
|
||||
}
|
||||
|
||||
// Verify alphabetical ordering
|
||||
expectedOrder := []string{"alpha", "beta", "zebra"}
|
||||
for i, typ := range types {
|
||||
if typ != expectedOrder[i] {
|
||||
t.Errorf("types[%d] = %s, want %s", i, typ, expectedOrder[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestIsSupported tests checking provider support
|
||||
func TestIsSupported(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
|
||||
// Register a provider
|
||||
provider := &mockProvider{providerType: "supported-test"}
|
||||
if err := r.Register(provider); err != nil {
|
||||
t.Fatalf("failed to register provider: %v", err)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
providerType string
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "supported provider",
|
||||
providerType: "supported-test",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "unsupported provider",
|
||||
providerType: "unsupported",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "empty string",
|
||||
providerType: "",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "case sensitivity",
|
||||
providerType: "SUPPORTED-TEST",
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := r.IsSupported(tt.providerType)
|
||||
if got != tt.want {
|
||||
t.Errorf("IsSupported(%q) = %v, want %v", tt.providerType, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestUnregister tests removing providers
|
||||
func TestUnregister(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
|
||||
// Register a provider
|
||||
provider := &mockProvider{providerType: "unregister-test"}
|
||||
if err := r.Register(provider); err != nil {
|
||||
t.Fatalf("failed to register provider: %v", err)
|
||||
}
|
||||
|
||||
// Verify it's registered
|
||||
if !r.IsSupported("unregister-test") {
|
||||
t.Fatal("provider not registered")
|
||||
}
|
||||
|
||||
// Unregister it
|
||||
r.Unregister("unregister-test")
|
||||
|
||||
// Verify it's gone
|
||||
if r.IsSupported("unregister-test") {
|
||||
t.Error("provider still registered after unregister")
|
||||
}
|
||||
|
||||
// Unregister non-existent (should not panic)
|
||||
r.Unregister("does-not-exist")
|
||||
|
||||
// Count should be 0
|
||||
if r.Count() != 0 {
|
||||
t.Errorf("expected count 0, got %d", r.Count())
|
||||
}
|
||||
}
|
||||
|
||||
// TestCount tests counting registered providers
|
||||
func TestCount(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
|
||||
// Initial count should be 0
|
||||
if r.Count() != 0 {
|
||||
t.Errorf("expected count 0, got %d", r.Count())
|
||||
}
|
||||
|
||||
// Register providers
|
||||
for i := 1; i <= 5; i++ {
|
||||
provider := &mockProvider{providerType: "test-" + string(rune('a'+i-1))}
|
||||
if err := r.Register(provider); err != nil {
|
||||
t.Fatalf("failed to register provider: %v", err)
|
||||
}
|
||||
|
||||
if r.Count() != i {
|
||||
t.Errorf("after registering %d providers, count = %d", i, r.Count())
|
||||
}
|
||||
}
|
||||
|
||||
// Unregister one
|
||||
r.Unregister("test-a")
|
||||
if r.Count() != 4 {
|
||||
t.Errorf("after unregistering, count = %d, want 4", r.Count())
|
||||
}
|
||||
}
|
||||
|
||||
// TestClear tests clearing all providers
|
||||
func TestClear(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
|
||||
// Register multiple providers
|
||||
for i := 0; i < 3; i++ {
|
||||
provider := &mockProvider{providerType: "clear-test-" + string(rune('a'+i))}
|
||||
if err := r.Register(provider); err != nil {
|
||||
t.Fatalf("failed to register provider: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Verify count
|
||||
if r.Count() != 3 {
|
||||
t.Fatalf("expected count 3, got %d", r.Count())
|
||||
}
|
||||
|
||||
// Clear registry
|
||||
r.Clear()
|
||||
|
||||
// Verify empty
|
||||
if r.Count() != 0 {
|
||||
t.Errorf("after clear, count = %d, want 0", r.Count())
|
||||
}
|
||||
|
||||
// Verify no providers are supported
|
||||
if r.IsSupported("clear-test-a") {
|
||||
t.Error("provider still supported after clear")
|
||||
}
|
||||
|
||||
// List should be empty
|
||||
if len(r.List()) != 0 {
|
||||
t.Errorf("list not empty after clear, got %d providers", len(r.List()))
|
||||
}
|
||||
}
|
||||
|
||||
// TestConcurrency tests thread-safe operations
|
||||
func TestConcurrency(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
// Concurrent registrations
|
||||
for i := 0; i < 10; i++ {
|
||||
wg.Add(1)
|
||||
go func(n int) {
|
||||
defer wg.Done()
|
||||
provider := &mockProvider{providerType: "concurrent-" + string(rune('a'+n))}
|
||||
_ = r.Register(provider)
|
||||
}(i)
|
||||
}
|
||||
|
||||
// Concurrent reads
|
||||
for i := 0; i < 10; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
_ = r.List()
|
||||
_ = r.Types()
|
||||
_ = r.IsSupported("concurrent-a")
|
||||
_, _ = r.Get("concurrent-a")
|
||||
}()
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
// Verify final state
|
||||
if r.Count() != 10 {
|
||||
t.Errorf("expected 10 providers after concurrent registration, got %d", r.Count())
|
||||
}
|
||||
}
|
||||
|
||||
// TestRegistry_Operations tests combined operations
|
||||
func TestRegistry_Operations(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
|
||||
// Start with empty registry
|
||||
if r.Count() != 0 {
|
||||
t.Errorf("new registry should be empty")
|
||||
}
|
||||
|
||||
// Register providers
|
||||
p1 := &mockProvider{providerType: "provider1"}
|
||||
p2 := &mockProvider{providerType: "provider2"}
|
||||
p3 := &mockProvider{providerType: "provider3"}
|
||||
|
||||
if err := r.Register(p1); err != nil {
|
||||
t.Fatalf("failed to register p1: %v", err)
|
||||
}
|
||||
if err := r.Register(p2); err != nil {
|
||||
t.Fatalf("failed to register p2: %v", err)
|
||||
}
|
||||
if err := r.Register(p3); err != nil {
|
||||
t.Fatalf("failed to register p3: %v", err)
|
||||
}
|
||||
|
||||
// Verify all are registered
|
||||
for _, p := range []ProviderPlugin{p1, p2, p3} {
|
||||
if !r.IsSupported(p.Type()) {
|
||||
t.Errorf("provider %s not registered", p.Type())
|
||||
}
|
||||
|
||||
retrieved, ok := r.Get(p.Type())
|
||||
if !ok {
|
||||
t.Errorf("failed to get provider %s", p.Type())
|
||||
}
|
||||
if retrieved.Type() != p.Type() {
|
||||
t.Errorf("retrieved wrong provider: got %s, want %s", retrieved.Type(), p.Type())
|
||||
}
|
||||
}
|
||||
|
||||
// List should contain all 3
|
||||
list := r.List()
|
||||
if len(list) != 3 {
|
||||
t.Errorf("list length = %d, want 3", len(list))
|
||||
}
|
||||
|
||||
// Types should contain all 3
|
||||
types := r.Types()
|
||||
if len(types) != 3 {
|
||||
t.Errorf("types length = %d, want 3", len(types))
|
||||
}
|
||||
|
||||
// Unregister one
|
||||
r.Unregister("provider2")
|
||||
|
||||
// Verify count decreased
|
||||
if r.Count() != 2 {
|
||||
t.Errorf("after unregister, count = %d, want 2", r.Count())
|
||||
}
|
||||
|
||||
// Verify p2 is gone
|
||||
if r.IsSupported("provider2") {
|
||||
t.Error("provider2 still supported after unregister")
|
||||
}
|
||||
|
||||
// Clear all
|
||||
r.Clear()
|
||||
|
||||
// Verify empty
|
||||
if r.Count() != 0 {
|
||||
t.Errorf("after clear, count = %d, want 0", r.Count())
|
||||
}
|
||||
if len(r.List()) != 0 {
|
||||
t.Error("list not empty after clear")
|
||||
}
|
||||
if len(r.Types()) != 0 {
|
||||
t.Error("types not empty after clear")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user