blob: 4190e5a41f592f2c8166db0290a550fc147e6652 [file] [log] [blame]
Philip Zeyliger5f26a342025-07-04 01:30:29 +00001package loop
2
3import (
4 "context"
5 "fmt"
6 "net"
7 "net/http"
8 "sync"
9 "testing"
10 "time"
11)
12
13// TestPortMonitor_IntegrationDemo demonstrates the full integration of PortMonitor with an Agent.
14// This test shows how the PortMonitor detects port changes and sends notifications to an Agent.
15func TestPortMonitor_IntegrationDemo(t *testing.T) {
16 // Create a test agent
17 agent := createTestAgent(t)
18
19 // Create and start the port monitor
20 pm := NewPortMonitor(agent, 100*time.Millisecond) // Fast polling for demo
21 ctx := context.Background()
22 err := pm.Start(ctx)
23 if err != nil {
24 t.Fatalf("Failed to start port monitor: %v", err)
25 }
26 defer pm.Stop()
27
28 // Wait for initial scan
29 time.Sleep(200 * time.Millisecond)
30
31 // Show current ports
32 currentPorts := pm.GetPorts()
33 t.Logf("Initial TCP ports detected: %d", len(currentPorts))
34 for _, port := range currentPorts {
35 t.Logf(" - Port %d (process: %s, pid: %d)", port.Port, port.Process, port.Pid)
36 }
37
38 // Start multiple test servers to demonstrate detection
39 var listeners []net.Listener
40 var wg sync.WaitGroup
41
42 // Start 3 test HTTP servers
43 for i := 0; i < 3; i++ {
44 listener, err := net.Listen("tcp", "127.0.0.1:0")
45 if err != nil {
46 t.Fatalf("Failed to start test listener %d: %v", i, err)
47 }
48 listeners = append(listeners, listener)
49
50 addr := listener.Addr().(*net.TCPAddr)
51 port := addr.Port
52 t.Logf("Started test HTTP server %d on port %d", i+1, port)
53
54 // Start a simple HTTP server
55 wg.Add(1)
56 go func(l net.Listener, serverID int) {
57 defer wg.Done()
58 mux := http.NewServeMux()
59 mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
60 fmt.Fprintf(w, "Hello from test server %d!\n", serverID)
61 })
62 server := &http.Server{Handler: mux}
63 server.Serve(l)
64 }(listener, i+1)
65 }
66
67 // Wait for ports to be detected
68 time.Sleep(500 * time.Millisecond)
69
70 // Check that the new ports were detected
71 updatedPorts := pm.GetPorts()
72 t.Logf("Updated TCP ports detected: %d", len(updatedPorts))
73
74 // Verify that we have at least 3 more ports than initially
75 if len(updatedPorts) < len(currentPorts)+3 {
76 t.Errorf("Expected at least %d ports, got %d", len(currentPorts)+3, len(updatedPorts))
77 }
78
79 // Find the new test server ports
80 var testPorts []uint16
81 for _, listener := range listeners {
82 addr := listener.Addr().(*net.TCPAddr)
83 testPorts = append(testPorts, uint16(addr.Port))
84 }
85
86 // Verify all test ports are detected
87 portMap := make(map[uint16]bool)
88 for _, port := range updatedPorts {
89 portMap[port.Port] = true
90 }
91
92 allPortsDetected := true
93 for _, testPort := range testPorts {
94 if !portMap[testPort] {
95 allPortsDetected = false
96 t.Errorf("Test port %d was not detected", testPort)
97 }
98 }
99
100 if allPortsDetected {
101 t.Logf("All test ports successfully detected!")
102 }
103
104 // Close all listeners
105 for i, listener := range listeners {
106 t.Logf("Closing test server %d", i+1)
107 listener.Close()
108 }
109
110 // Wait for servers to stop
111 wg.Wait()
112
113 // Wait for ports to be removed
114 time.Sleep(500 * time.Millisecond)
115
116 // Check that ports were removed
117 finalPorts := pm.GetPorts()
118 t.Logf("Final TCP ports detected: %d", len(finalPorts))
119
120 // Verify the final port count is back to near the original
121 if len(finalPorts) > len(currentPorts)+1 {
122 t.Errorf("Expected final port count to be close to initial (%d), got %d", len(currentPorts), len(finalPorts))
123 }
124
125 // Verify test ports are no longer detected
126 portMap = make(map[uint16]bool)
127 for _, port := range finalPorts {
128 portMap[port.Port] = true
129 }
130
131 allPortsRemoved := true
132 for _, testPort := range testPorts {
133 if portMap[testPort] {
134 allPortsRemoved = false
135 t.Errorf("Test port %d was not removed", testPort)
136 }
137 }
138
139 if allPortsRemoved {
140 t.Logf("All test ports successfully removed!")
141 }
142
143 t.Logf("Integration test completed successfully!")
144 t.Logf("- Initial ports: %d", len(currentPorts))
145 t.Logf("- Peak ports: %d", len(updatedPorts))
146 t.Logf("- Final ports: %d", len(finalPorts))
147 t.Logf("- Test ports added and removed: %d", len(testPorts))
148}
149
150// contains checks if a string contains a substring.
151func contains(s, substr string) bool {
152 return len(s) >= len(substr) && (s == substr ||
153 (len(s) > len(substr) &&
154 (s[:len(substr)] == substr ||
155 s[len(s)-len(substr):] == substr ||
156 indexOfSubstring(s, substr) >= 0)))
157}
158
159// indexOfSubstring finds the index of substring in string.
160func indexOfSubstring(s, substr string) int {
161 if len(substr) == 0 {
162 return 0
163 }
164 for i := 0; i <= len(s)-len(substr); i++ {
165 if s[i:i+len(substr)] == substr {
166 return i
167 }
168 }
169 return -1
170}