summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-06-12 21:07:31 +0300
committerPaul Buetow <paul@buetow.org>2025-06-12 21:07:31 +0300
commit6352e8c33c1c22af382093d406d477d1530950db (patch)
tree427a59a0c917cf2351e514032c6c50890c65eb54 /internal
parent49fe110a6263c64d34c95024fd1ffa7352c63006 (diff)
Add comprehensive unit tests for federated feature
- Tests successful federation from remote endpoints - Tests error handling (server errors, invalid JSON, timeouts) - Tests multiple endpoint federation - Tests duplicate check name conflict resolution - Uses httptest.NewServer for realistic HTTP simulation - Validates federated check marking and status reporting 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Diffstat (limited to 'internal')
-rw-r--r--internal/federated_test.go280
1 files changed, 280 insertions, 0 deletions
diff --git a/internal/federated_test.go b/internal/federated_test.go
new file mode 100644
index 0000000..bfca309
--- /dev/null
+++ b/internal/federated_test.go
@@ -0,0 +1,280 @@
+package internal
+
+import (
+ "context"
+ "encoding/json"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+ "time"
+)
+
+func TestMergeFederated(t *testing.T) {
+ tests := []struct {
+ name string
+ serverResponse map[string]checkState
+ serverStatus int
+ expectedChecks []string
+ expectError bool
+ }{
+ {
+ name: "successful federation",
+ serverResponse: map[string]checkState{
+ "Remote Check 1": {
+ Status: nagiosOk,
+ Epoch: time.Now().Unix(),
+ },
+ "Remote Check 2": {
+ Status: nagiosCritical,
+ Epoch: time.Now().Unix(),
+ },
+ },
+ serverStatus: 200,
+ expectedChecks: []string{"Remote Check 1", "Remote Check 2"},
+ expectError: false,
+ },
+ {
+ name: "server error",
+ serverResponse: nil,
+ serverStatus: 500,
+ expectedChecks: []string{},
+ expectError: true,
+ },
+ {
+ name: "invalid json",
+ serverResponse: nil,
+ serverStatus: 200,
+ expectedChecks: []string{},
+ expectError: true,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ // Create mock server
+ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if tt.serverStatus != 200 {
+ w.WriteHeader(tt.serverStatus)
+ return
+ }
+
+ if tt.serverResponse == nil && tt.name == "invalid json" {
+ w.Write([]byte("invalid json"))
+ return
+ }
+
+ if tt.serverResponse != nil {
+ jsonData, _ := json.Marshal(tt.serverResponse)
+ w.Header().Set("Content-Type", "application/json")
+ w.Write(jsonData)
+ }
+ }))
+ defer server.Close()
+
+ // Create initial state
+ state := state{
+ checks: make(map[string]checkState),
+ staleEpoch: time.Now().Unix() - 3600,
+ }
+
+ // Create config with federated endpoint
+ conf := config{
+ Federated: []string{server.URL},
+ }
+
+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+ defer cancel()
+
+ // Execute federation
+ resultState := mergeFederated(ctx, state, conf)
+
+ // Verify results
+ if tt.expectError {
+ // Should have a federated endpoint check that failed
+ federatedCheckName := "Federated endpoint " + server.URL
+ if check, exists := resultState.checks[federatedCheckName]; !exists {
+ t.Errorf("Expected federated endpoint check to exist")
+ } else if check.Status != nagiosCritical {
+ t.Errorf("Expected federated endpoint check to be CRITICAL, got %v", check.Status)
+ }
+ } else {
+ // Should have merged the remote checks
+ for _, checkName := range tt.expectedChecks {
+ if _, exists := resultState.checks[checkName]; !exists {
+ t.Errorf("Expected check '%s' to be merged", checkName)
+ }
+ }
+
+ // Should have successful federated endpoint check
+ federatedCheckName := "Federated endpoint " + server.URL
+ if check, exists := resultState.checks[federatedCheckName]; !exists {
+ t.Errorf("Expected federated endpoint check to exist")
+ } else if check.Status != nagiosOk {
+ t.Errorf("Expected federated endpoint check to be OK, got %v", check.Status)
+ }
+ }
+ })
+ }
+}
+
+func TestMergeFederatedMultipleEndpoints(t *testing.T) {
+ // Create two mock servers
+ server1Response := map[string]checkState{
+ "Server1 Check": {
+ Status: nagiosOk,
+ Epoch: time.Now().Unix(),
+ },
+ }
+
+ server2Response := map[string]checkState{
+ "Server2 Check": {
+ Status: nagiosWarning,
+ Epoch: time.Now().Unix(),
+ },
+ }
+
+ server1 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ jsonData, _ := json.Marshal(server1Response)
+ w.Header().Set("Content-Type", "application/json")
+ w.Write(jsonData)
+ }))
+ defer server1.Close()
+
+ server2 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ jsonData, _ := json.Marshal(server2Response)
+ w.Header().Set("Content-Type", "application/json")
+ w.Write(jsonData)
+ }))
+ defer server2.Close()
+
+ // Create initial state
+ state := state{
+ checks: make(map[string]checkState),
+ staleEpoch: time.Now().Unix() - 3600,
+ }
+
+ // Create config with multiple federated endpoints
+ conf := config{
+ Federated: []string{server1.URL, server2.URL},
+ }
+
+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+ defer cancel()
+
+ // Execute federation
+ resultState := mergeFederated(ctx, state, conf)
+
+ // Verify both servers' checks were merged
+ if _, exists := resultState.checks["Server1 Check"]; !exists {
+ t.Errorf("Expected Server1 Check to be merged")
+ }
+
+ if _, exists := resultState.checks["Server2 Check"]; !exists {
+ t.Errorf("Expected Server2 Check to be merged")
+ }
+
+ // Verify both federated endpoint checks exist and are OK
+ federatedCheck1 := "Federated endpoint " + server1.URL
+ federatedCheck2 := "Federated endpoint " + server2.URL
+
+ if check, exists := resultState.checks[federatedCheck1]; !exists {
+ t.Errorf("Expected federated endpoint check 1 to exist")
+ } else if check.Status != nagiosOk {
+ t.Errorf("Expected federated endpoint check 1 to be OK, got %v", check.Status)
+ }
+
+ if check, exists := resultState.checks[federatedCheck2]; !exists {
+ t.Errorf("Expected federated endpoint check 2 to exist")
+ } else if check.Status != nagiosOk {
+ t.Errorf("Expected federated endpoint check 2 to be OK, got %v", check.Status)
+ }
+}
+
+func TestMergeFederatedTimeout(t *testing.T) {
+ // Create a server that delays response
+ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ time.Sleep(2 * time.Second)
+ w.WriteHeader(200)
+ }))
+ defer server.Close()
+
+ // Create initial state
+ state := state{
+ checks: make(map[string]checkState),
+ staleEpoch: time.Now().Unix() - 3600,
+ }
+
+ // Create config with federated endpoint
+ conf := config{
+ Federated: []string{server.URL},
+ }
+
+ // Create context with short timeout
+ ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
+ defer cancel()
+
+ // Execute federation
+ resultState := mergeFederated(ctx, state, conf)
+
+ // Should have a failed federated endpoint check
+ federatedCheckName := "Federated endpoint " + server.URL
+ if check, exists := resultState.checks[federatedCheckName]; !exists {
+ t.Errorf("Expected federated endpoint check to exist")
+ } else if check.Status != nagiosCritical {
+ t.Errorf("Expected federated endpoint check to be CRITICAL due to timeout, got %v", check.Status)
+ }
+}
+
+func TestMergeFederatedDuplicateCheckNames(t *testing.T) {
+ // Create server with check name that conflicts with local state
+ serverResponse := map[string]checkState{
+ "Duplicate Check": {
+ Status: nagiosOk,
+ Epoch: time.Now().Unix(),
+ },
+ }
+
+ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ jsonData, _ := json.Marshal(serverResponse)
+ w.Header().Set("Content-Type", "application/json")
+ w.Write(jsonData)
+ }))
+ defer server.Close()
+
+ // Create initial state with existing check
+ state := state{
+ checks: map[string]checkState{
+ "Duplicate Check": {
+ Status: nagiosCritical,
+ Epoch: time.Now().Unix(),
+ },
+ },
+ staleEpoch: time.Now().Unix() - 3600,
+ }
+
+ // Create config with federated endpoint
+ conf := config{
+ Federated: []string{server.URL},
+ }
+
+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+ defer cancel()
+
+ // Execute federation
+ resultState := mergeFederated(ctx, state, conf)
+
+ // Should have a failed federated endpoint check due to duplicate name
+ federatedCheckName := "Federated endpoint " + server.URL
+ if check, exists := resultState.checks[federatedCheckName]; !exists {
+ t.Errorf("Expected federated endpoint check to exist")
+ } else if check.Status != nagiosCritical {
+ t.Errorf("Expected federated endpoint check to be CRITICAL due to duplicate name, got %v", check.Status)
+ }
+
+ // Original check should remain unchanged
+ if check, exists := resultState.checks["Duplicate Check"]; !exists {
+ t.Errorf("Expected original check to remain")
+ } else if check.Status != nagiosCritical {
+ t.Errorf("Expected original check status to remain CRITICAL, got %v", check.Status)
+ }
+} \ No newline at end of file