Test Cases
Comprehensive test case documentation for dnsweaver integration testing. This document defines the test matrix for every provider, source, and end-to-end scenario that must pass before release.
For test templates and patterns, see the templates/ directory.
Overview
Category
Test Cases
Description
Provider Tests
6 providers × record types
CRUD operations, orphan cleanup
Source Tests
3 sources × modes
Service discovery, watch/poll
Scenario Tests
9 scenarios
End-to-end behavior, recovery
Reconciler Tests
Edge cases
Multi-provider, conflict resolution
Provider Tests
Each provider must pass the full test matrix for every record type it supports.
Record Type Support Matrix
Provider
A
AAAA
CNAME
SRV
TXT
Ownership
Technitium
✅
✅
✅
✅
✅
TXT record
Cloudflare
✅
✅
✅
✅
✅
TXT record
RFC 2136
✅
✅
✅
✅
✅
TXT record
Pi-hole v5
✅
✅
✅
❌
❌
Custom list
Pi-hole v6
✅
✅
✅
❌
❌
Custom list
dnsmasq
✅
✅
✅
❌
❌
Config file
Webhook
✅
✅
✅
✅
✅
Callback
Per-Provider Test Cases
For each supported record type, every provider must pass these operations:
TC-P-001: Create Record
Step
Action
Expected Result
1
Discover a new service with matching domain
Record appears in desired state
2
Reconciler creates the record
Provider API confirms creation
3
Verify DNS resolution
Record resolves to expected target
TC-P-002: Update Record (Target Change)
Step
Action
Expected Result
1
Change service target (e.g., new IP address)
Desired state updates
2
Reconciler detects drift
Record updated in provider
3
Verify DNS resolution
Record resolves to new target
TC-P-003: Delete Record
Step
Action
Expected Result
1
Remove the source service
Service disappears from desired state
2
Reconciler identifies orphan
Record deleted from provider
3
Verify DNS resolution
Record no longer resolves
TC-P-004: Orphan Cleanup
Step
Action
Expected Result
1
Start dnsweaver with pre-existing managed records
Provider has stale records
2
Reconciler runs with current desired state
Orphaned records cleaned up
3
Only valid records remain
No stale entries in provider
TC-P-005: Ownership Verification
Step
Action
Expected Result
1
Manually create a record outside dnsweaver
Record exists without ownership marker
2
Reconciler encounters unowned record
Record is NOT modified or deleted
3
Create same hostname via dnsweaver
Ownership marker is set on creation
TC-P-006: Idempotent Apply
Step
Action
Expected Result
1
Reconciler creates a record
Record exists in provider
2
Run reconciler again with same state
No errors, no duplicate records
3
Provider state unchanged
API calls are minimal (no-op)
Provider-Specific Tests
Technitium (TC-TECH-xxx)
ID
Test Case
Notes
TC-TECH-001
Zone creation when zone doesn't exist
Auto-create primary zone
TC-TECH-002
SRV record with port and weight
Full SRV fields
TC-TECH-003
Multiple zones in single instance
Zone isolation
TC-TECH-004
Token-based authentication
_FILE suffix support
TC-TECH-005
API error handling (429, 500)
Retry and backoff
Cloudflare (TC-CF-xxx)
ID
Test Case
Notes
TC-CF-001
Proxied vs DNS-only records
Proxy flag handling
TC-CF-002
Zone ID auto-discovery
From zone name
TC-CF-003
Rate limit handling
Cloudflare API limits
TC-CF-004
API token authentication
Bearer token
TC-CF-005
TTL management
Custom vs auto TTL
RFC 2136 (TC-RFC-xxx)
ID
Test Case
Notes
TC-RFC-001
TSIG authentication (HMAC-SHA256)
Key-based auth
TC-RFC-002
TSIG authentication (HMAC-SHA512)
Key-based auth
TC-RFC-003
Unauthenticated updates
No TSIG key
TC-RFC-004
Multiple record updates in single message
Batch efficiency
TC-RFC-005
SOA serial increment verification
After update
Pi-hole v5 (TC-PH5-xxx)
ID
Test Case
Notes
TC-PH5-001
Custom DNS entry via API
Admin API
TC-PH5-002
CNAME via local DNS records
File-based CNAME
TC-PH5-003
Auth token handling
_FILE suffix support
TC-PH5-004
Gravity database interaction
Verify no interference
Pi-hole v6 (TC-PH6-xxx)
ID
Test Case
Notes
TC-PH6-001
New v6 API endpoint usage
/api/dns/
TC-PH6-002
Session-based authentication
Login/session flow
TC-PH6-003
Migration from v5 to v6
Config continuity
TC-PH6-004
Custom DNS entry via v6 API
New API format
dnsmasq (TC-DM-xxx)
ID
Test Case
Notes
TC-DM-001
Config file creation
New file in config dir
TC-DM-002
Config file update (add record)
Append to existing
TC-DM-003
Config file update (remove record)
Remove line from file
TC-DM-004
Reload via SIGHUP
Kill -HUP command
TC-DM-005
Reload via systemctl
systemctl reload
TC-DM-006
SSH remote management
SFTP write + SSH reload
TC-DM-007
File permission handling
Write access validation
Webhook (TC-WH-xxx)
ID
Test Case
Notes
TC-WH-001
POST on record create
Custom URL + payload
TC-WH-002
POST on record update
Updated payload
TC-WH-003
POST on record delete
Delete notification
TC-WH-004
Custom headers
Auth headers
TC-WH-005
Webhook failure retry
Transient error handling
TC-WH-006
Template rendering
Go template in payload
Source Tests
Each source must pass discovery and mode-specific tests.
Per-Source Test Cases
TC-S-001: Service Discovery
Step
Action
Expected Result
1
Deploy a service with DNS labels/annotations
Source discovers the service
2
Verify hostname extraction
Correct FQDN(s) parsed
3
Verify target extraction
Correct IP/hostname parsed
4
Verify record type assignment
Matches configured type
TC-S-002: Service Removal
Step
Action
Expected Result
1
Remove a previously discovered service
Source detects removal
2
Service removed from desired state
Reconciler notified
TC-S-003: Service Update (Hostname Change)
Step
Action
Expected Result
1
Change a service's DNS label/annotation
Source detects change
2
Old hostname removed, new hostname added
Desired state updated
TC-S-004: Service Update (Target Change)
Step
Action
Expected Result
1
Service target changes (new IP, new backend)
Source detects change
2
Existing record updated with new target
Desired state updated
TC-S-005: Multi-Hostname Service
Step
Action
Expected Result
1
Service has multiple hostnames (comma-separated)
All hostnames discovered
2
Each hostname creates a separate record
Correct count in desired state
TC-S-006: Domain Filtering
Step
Action
Expected Result
1
Service hostname matches DOMAINS glob
Service is included
2
Service hostname matches EXCLUDE_DOMAINS glob
Service is excluded
3
Service hostname matches neither
Service is excluded
Source-Specific Tests
Traefik (TC-TRK-xxx)
ID
Test Case
Mode
Notes
TC-TRK-001
Label-based discovery
Docker labels
traefik.http.routers.*.rule
TC-TRK-002
File provider discovery
File config
Static routes from YAML/TOML
TC-TRK-003
Watch mode (real-time)
Watch
Event-driven updates
TC-TRK-004
Poll mode (interval)
Poll
Timer-based refresh
TC-TRK-005
Router rule parsing (Host)
Both
Host(\example.com`)`
TC-TRK-006
Router rule parsing (HostSNI)
Both
TLS routes
TC-TRK-007
Router rule parsing (multiple hosts)
Both
Host(\a.com`) || Host(`b.com`)`
TC-TRK-008
EntryPoint filtering
Both
Only specific entrypoints
TC-TRK-009
Service target from loadbalancer
Both
IP extraction
Kubernetes (TC-K8S-xxx)
ID
Test Case
Mode
Notes
TC-K8S-001
Ingress discovery
Watch
Standard Ingress resources
TC-K8S-002
Service annotation discovery
Watch
dnsweaver.dev/hostname
TC-K8S-003
Namespace filtering
Both
Include/exclude namespaces
TC-K8S-004
Watch mode reconnection
Watch
After API server restart
TC-K8S-005
Poll mode fallback
Poll
Timer-based refresh
TC-K8S-006
LoadBalancer IP extraction
Both
From service status
TC-K8S-007
NodePort target resolution
Both
Node IP + port
dnsweaver Native (TC-DWN-xxx)
ID
Test Case
Mode
Notes
TC-DWN-001
Label-based discovery
Docker
dnsweaver.hostname label
TC-DWN-002
Multi-hostname labels
Docker
Comma-separated hostnames
TC-DWN-003
Container IP extraction
Docker
Bridge/overlay network
TC-DWN-004
Watch mode (Docker events)
Watch
Real-time container events
TC-DWN-005
Poll mode (Docker API)
Poll
Timer-based container list
TC-DWN-006
Container start/stop lifecycle
Watch
Full lifecycle tracking
Scenario Tests
End-to-end scenarios testing system behavior across sources and providers.
TC-E2E-001: Service Lifecycle (Start → Stop)
Step
Action
Expected Result
1
Start a service with DNS labels
Record created in provider
2
Verify DNS resolution
Name resolves correctly
3
Stop the service
Record removed from provider
4
Verify DNS resolution
Name no longer resolves
TC-E2E-002: Service Hostname Change
Step
Action
Expected Result
1
Service running with hostname old.example.com
Record exists
2
Update service with hostname new.example.com
Old record removed, new record created
3
Verify both DNS states
Old gone, new resolves
TC-E2E-003: Service Target Change
Step
Action
Expected Result
1
Service running with target 192.0.2.1
A record points to 192.0.2.1
2
Service target changes to 192.0.2.2
Record updated to 192.0.2.2
3
Verify DNS resolution
Resolves to new target
TC-E2E-004: Multi-Service Conflict Resolution
Step
Action
Expected Result
1
Two services claim same hostname
Conflict detected
2
Reconciler applies conflict policy
One record wins (deterministic)
3
Remove winning service
Remaining service takes over
TC-E2E-005: Multi-Hostname Service
Step
Action
Expected Result
1
Service declares 3 hostnames
3 DNS records created
2
All records point to same target
Correct target for all
3
Remove service
All 3 records cleaned up
TC-E2E-006: Provider Outage Recovery
Step
Action
Expected Result
1
Provider becomes unreachable
Reconciler logs error
2
Source changes accumulate
Desired state updated
3
Provider recovers
All pending changes applied
4
Verify final state
Provider matches desired state
TC-E2E-007: dnsweaver Restart Recovery
Step
Action
Expected Result
1
dnsweaver managing records, then restart
Process stops cleanly
2
dnsweaver starts with same config
Sources re-discovered
3
Reconciler runs full sync
Provider state matches desired
4
No duplicate or orphaned records
Clean state
TC-E2E-008: Rolling Update (Zero-Downtime)
Step
Action
Expected Result
1
Service running with DNS record
Record exists
2
Deploy new version of service (rolling)
Old and new containers overlap
3
Rollout completes
Record points to new container
4
Verify no DNS gaps
Resolution always succeeds
TC-E2E-009: Multi-Provider Same Hostname
Step
Action
Expected Result
1
Two providers configured for same domain
Both active
2
Service discovered with matching hostname
Both providers create records
3
Service removed
Both providers clean up
Reconciler Tests
Tests for the reconciler's edge case handling and correctness.
TC-R-001: Empty Desired State
Step
Action
Expected Result
1
No services discovered
Desired state is empty
2
Reconciler runs
All owned records cleaned up
3
Unowned records untouched
No accidental deletions
TC-R-002: Empty Provider State
Step
Action
Expected Result
1
Fresh provider with no records
Provider state is empty
2
Reconciler runs with desired state
All records created
TC-R-003: Concurrent Reconciliation
Step
Action
Expected Result
1
Multiple reconcile triggers arrive simultaneously
Only one runs at a time
2
Subsequent triggers queued or deduplicated
No race conditions
3
Final state is consistent
Matches latest desired state
TC-R-004: Provider Rate Limiting
Step
Action
Expected Result
1
Large batch of record changes
Many API calls needed
2
Provider returns rate limit error
Reconciler backs off
3
Retries after backoff period
All changes eventually applied
TC-R-005: Partial Failure Recovery
Step
Action
Expected Result
1
Batch of 10 record creates
Reconciler processes batch
2
Record 5 fails, others succeed
Failure logged, 9 records created
3
Next reconcile cycle
Failed record retried and created
Running Tests
Unit Tests
Integration Tests
Integration tests require a running test environment with real provider backends.
# All integration tests
make test-integration
# Specific provider
go test -tags= integration ./providers/technitium/... -v
# Specific source
go test -tags= integration ./sources/traefik/... -v
Test Environment
See README.md for test environment setup and the templates/ directory for writing new tests.