Skip to content

Commit

Permalink
add tests for CreateDNSRecord
Browse files Browse the repository at this point in the history
  • Loading branch information
mircea-pavel-anton committed Oct 16, 2024
1 parent 08c714d commit ba03ce9
Showing 1 changed file with 262 additions and 0 deletions.
262 changes: 262 additions & 0 deletions internal/mikrotik/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"net/http"
"net/http/httptest"
"testing"

"sigs.k8s.io/external-dns/endpoint"
)

var (
Expand Down Expand Up @@ -153,6 +155,7 @@ func TestGetSystemInfo(t *testing.T) {
},
}

// Run test cases
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
config := &tc.config
Expand Down Expand Up @@ -186,3 +189,262 @@ func TestGetSystemInfo(t *testing.T) {
})
}
}
func TestCreateDNSRecord(t *testing.T) {
// Define test cases
testCases := []struct {
name string
initialRecords map[string]DNSRecord
endpoint *endpoint.Endpoint
expectedError bool
}{
{
name: "Valid A record creation",
initialRecords: map[string]DNSRecord{},
endpoint: &endpoint.Endpoint{
DNSName: "test-a.example.com",
RecordType: "A",
Targets: endpoint.Targets{"192.0.2.1"},
},
expectedError: false,
},
{
name: "Valid AAAA record creation",
initialRecords: map[string]DNSRecord{},
endpoint: &endpoint.Endpoint{
DNSName: "test-aaaa.example.com",
RecordType: "AAAA",
Targets: endpoint.Targets{"2001:db8::1"},
},
expectedError: false,
},
{
name: "Valid CNAME record creation",
initialRecords: map[string]DNSRecord{},
endpoint: &endpoint.Endpoint{
DNSName: "test-cname.example.com",
RecordType: "CNAME",
Targets: endpoint.Targets{"example.com"},
},
expectedError: false,
},
{
name: "Valid TXT record creation",
initialRecords: map[string]DNSRecord{},
endpoint: &endpoint.Endpoint{
DNSName: "test-txt.example.com",
RecordType: "TXT",
Targets: endpoint.Targets{"\"some text record value\""},
},
expectedError: false,
},
{
name: "Record already exists",
initialRecords: map[string]DNSRecord{
"exists.example.com|A": {
ID: "*EXISTING",
Name: "exists.example.com",
Type: "A",
Address: "192.0.2.1",
},
},
endpoint: &endpoint.Endpoint{
DNSName: "exists.example.com",
RecordType: "A",
Targets: endpoint.Targets{"192.0.2.1"},
},
expectedError: true,
},
{
name: "Invalid record (missing DNSName)",
initialRecords: map[string]DNSRecord{},
endpoint: &endpoint.Endpoint{
DNSName: "",
RecordType: "A",
Targets: endpoint.Targets{"192.0.2.1"},
},
expectedError: true,
},

{
name: "Empty target for A record",
initialRecords: map[string]DNSRecord{},
endpoint: &endpoint.Endpoint{
DNSName: "empty-target.example.com",
RecordType: "A",
Targets: endpoint.Targets{""}, // Empty target
},
expectedError: true,
},
{
name: "Malformed IP address for A record",
initialRecords: map[string]DNSRecord{},
endpoint: &endpoint.Endpoint{
DNSName: "malformed-ip.example.com",
RecordType: "A",
Targets: endpoint.Targets{"999.999.999.999"}, // Invalid IP
},
expectedError: true,
},
{
name: "Malformed IP address for AAAA record",
initialRecords: map[string]DNSRecord{},
endpoint: &endpoint.Endpoint{
DNSName: "malformed-ipv6.example.com",
RecordType: "AAAA",
Targets: endpoint.Targets{"gggg::1"}, // Invalid IPv6
},
expectedError: true,
},
{
name: "Empty target for CNAME record",
initialRecords: map[string]DNSRecord{},
endpoint: &endpoint.Endpoint{
DNSName: "empty-cname.example.com",
RecordType: "CNAME",
Targets: endpoint.Targets{""}, // Empty target
},
expectedError: true,
},
// { //! we dont have any kind of cname validation so this will always pass
// name: "Malformed domain name for CNAME record",
// initialRecords: map[string]DNSRecord{},
// endpoint: &endpoint.Endpoint{
// DNSName: "bad-cname.example.com",
// RecordType: "CNAME",
// Targets: endpoint.Targets{"1234!"},
// },
// expectedError: true,
// },
{
name: "Empty text for TXT record",
initialRecords: map[string]DNSRecord{},
endpoint: &endpoint.Endpoint{
DNSName: "empty-txt.example.com",
RecordType: "TXT",
Targets: endpoint.Targets{""}, // Empty text
},
expectedError: true,
},
{
name: "Invalid record type",
initialRecords: map[string]DNSRecord{},
endpoint: &endpoint.Endpoint{
DNSName: "invalid-type.example.com",
RecordType: "INVALID",
Targets: endpoint.Targets{"some target"},
},
expectedError: true,
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
// Initialize an in-memory store for DNS records for this test case
recordStore := make(map[string]DNSRecord)
// Pre-populate recordStore with initialRecords
for k, v := range tc.initialRecords {
recordStore[k] = v
}

// Set up your mock server
server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Validate the Basic Auth header
username, password, ok := r.BasicAuth()
if !ok || username != mockUsername || password != mockPassword {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}

// Handle DNS record creation
if r.URL.Path == "/rest/ip/dns/static" && r.Method == http.MethodPut {
var record DNSRecord
if err := json.NewDecoder(r.Body).Decode(&record); err != nil {
http.Error(w, "Bad Request", http.StatusBadRequest)
return
}

// Check if record already exists
key := record.Name + "|" + record.Type
if _, exists := recordStore[key]; exists {
http.Error(w, "Conflict: Record already exists", http.StatusConflict)
return
}

// Simulate assigning an ID and storing the record
record.ID = "*NEW"
recordStore[key] = record

// Return the created record
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(record); err != nil {
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
return
}

// Return 404 for any other path
http.NotFound(w, r)
}))
defer server.Close()

// Set up the client with correct credentials
config := &Config{
BaseUrl: server.URL,
Username: mockUsername,
Password: mockPassword,
SkipTLSVerify: true,
}

client, err := NewMikrotikClient(config)
if err != nil {
t.Fatalf("Failed to create client: %v", err)
}

// Call CreateDNSRecord
record, err := client.CreateDNSRecord(tc.endpoint)

if tc.expectedError {
if err == nil {
t.Fatalf("Expected error, got none")
}
// Optionally, check for specific error messages
return // Error was expected and occurred, test passes
}

if err != nil {
t.Fatalf("Expected no error, got %v", err)
}

// Verify that the record was stored in the mock server
key := tc.endpoint.DNSName + "|" + tc.endpoint.RecordType
storedRecord, exists := recordStore[key]
if !exists {
t.Fatalf("Expected record to be stored, but it was not found")
}

// Verify that the client received the correct record
if record.ID != storedRecord.ID {
t.Errorf("Expected ID '%s', got '%s'", storedRecord.ID, record.ID)
}

// Additional checks specific to record type
switch tc.endpoint.RecordType {
case "A", "AAAA":
if storedRecord.Address != tc.endpoint.Targets[0] {
t.Errorf("Expected Address '%s', got '%s'", tc.endpoint.Targets[0], storedRecord.Address)
}
case "CNAME":
if storedRecord.CName != tc.endpoint.Targets[0] {
t.Errorf("Expected CName '%s', got '%s'", tc.endpoint.Targets[0], storedRecord.CName)
}
case "TXT":
if storedRecord.Text != tc.endpoint.Targets[0] {
t.Errorf("Expected Text '%s', got '%s'", tc.endpoint.Targets[0], storedRecord.Text)
}
default:
t.Errorf("Unsupported RecordType '%s' in test case", tc.endpoint.RecordType)
}
})
}
}

0 comments on commit ba03ce9

Please sign in to comment.