github.com/cilium/cilium@v1.16.2/pkg/health/client/client_test.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package client 5 6 import ( 7 "io" 8 "testing" 9 10 "github.com/stretchr/testify/require" 11 12 "github.com/cilium/cilium/api/v1/health/models" 13 ) 14 15 func TestConnectivityStatusType(t *testing.T) { 16 tests := []struct { 17 cst ConnectivityStatusType 18 expectedStr string 19 }{ 20 { 21 cst: ConnStatusReachable, 22 expectedStr: "reachable", 23 }, 24 { 25 cst: ConnStatusUnreachable, 26 expectedStr: "unreachable", 27 }, 28 { 29 cst: ConnStatusUnknown, 30 expectedStr: "unknown", 31 }, 32 { 33 cst: 10, 34 expectedStr: "unknown", 35 }, 36 } 37 for _, tc := range tests { 38 t.Run(tc.expectedStr, func(t *testing.T) { 39 require.Equal(t, tc.expectedStr, tc.cst.String()) 40 }) 41 } 42 } 43 44 func TestGetConnectivityStatusType(t *testing.T) { 45 tests := []struct { 46 cs *models.ConnectivityStatus 47 expectedStatusType ConnectivityStatusType 48 }{ 49 { 50 cs: &models.ConnectivityStatus{Status: ""}, 51 expectedStatusType: ConnStatusReachable, 52 }, 53 { 54 cs: &models.ConnectivityStatus{Status: "failed"}, 55 expectedStatusType: ConnStatusUnreachable, 56 }, 57 { 58 cs: nil, 59 expectedStatusType: ConnStatusUnknown, 60 }, 61 } 62 for _, tc := range tests { 63 t.Run(tc.expectedStatusType.String(), func(t *testing.T) { 64 require.Equal(t, tc.expectedStatusType, GetConnectivityStatusType(tc.cs)) 65 }) 66 } 67 } 68 69 func TestGetPathConnectivityStatusType(t *testing.T) { 70 tests := []struct { 71 cp *models.PathStatus 72 expectedStatusType ConnectivityStatusType 73 }{ 74 { 75 cp: &models.PathStatus{ 76 Icmp: &models.ConnectivityStatus{Status: ""}, 77 HTTP: &models.ConnectivityStatus{Status: ""}, 78 }, 79 expectedStatusType: ConnStatusReachable, 80 }, 81 { 82 cp: &models.PathStatus{ 83 Icmp: &models.ConnectivityStatus{Status: "failed"}, 84 HTTP: &models.ConnectivityStatus{Status: "failed"}, 85 }, 86 expectedStatusType: ConnStatusUnreachable, 87 }, 88 { 89 cp: &models.PathStatus{ 90 Icmp: &models.ConnectivityStatus{Status: ""}, 91 HTTP: &models.ConnectivityStatus{Status: "failed"}, 92 }, 93 expectedStatusType: ConnStatusUnreachable, 94 }, 95 { 96 cp: &models.PathStatus{ 97 Icmp: &models.ConnectivityStatus{Status: "failed"}, 98 HTTP: &models.ConnectivityStatus{Status: ""}, 99 }, 100 expectedStatusType: ConnStatusUnreachable, 101 }, 102 { 103 cp: &models.PathStatus{ 104 Icmp: &models.ConnectivityStatus{Status: "failed"}, 105 HTTP: nil, 106 }, 107 expectedStatusType: ConnStatusUnreachable, 108 }, 109 { 110 cp: &models.PathStatus{ 111 Icmp: nil, 112 HTTP: &models.ConnectivityStatus{Status: "failed"}, 113 }, 114 expectedStatusType: ConnStatusUnreachable, 115 }, 116 { 117 cp: &models.PathStatus{ 118 Icmp: nil, 119 HTTP: nil, 120 }, 121 expectedStatusType: ConnStatusUnknown, 122 }, 123 { 124 cp: &models.PathStatus{ 125 Icmp: &models.ConnectivityStatus{Status: ""}, 126 HTTP: nil, 127 }, 128 expectedStatusType: ConnStatusUnknown, 129 }, 130 { 131 cp: &models.PathStatus{ 132 Icmp: nil, 133 HTTP: &models.ConnectivityStatus{Status: ""}, 134 }, 135 expectedStatusType: ConnStatusUnknown, 136 }, 137 } 138 for _, tc := range tests { 139 t.Run(tc.expectedStatusType.String(), func(t *testing.T) { 140 require.Equal(t, tc.expectedStatusType, GetPathConnectivityStatusType(tc.cp)) 141 }) 142 } 143 } 144 145 func TestFormatNodeStatus(t *testing.T) { 146 // This test generates permutations of models.NodeStatus and sees whether 147 // the calls to formatNodeStatus panic; the result of this test being 148 // successful is whether the test does not panic. 149 150 // not testing output, just that permutations of NodeStatus don't cause 151 // panics. 152 w := io.Discard 153 154 connectivityStatusGood := &models.ConnectivityStatus{ 155 Latency: 1, 156 Status: "", 157 } 158 connectivityStatusBad := &models.ConnectivityStatus{ 159 Latency: 1, 160 Status: "bad status", 161 } 162 possibleConnectivityStatus := []*models.ConnectivityStatus{ 163 connectivityStatusBad, 164 connectivityStatusGood, 165 } 166 possibleIPs := []string{"192.168.1.1", ""} 167 168 possibleNames := []string{"node1", ""} 169 170 possiblePathStatuses := []*models.PathStatus{} 171 172 for _, connectivityStatusHTTP := range possibleConnectivityStatus { 173 for _, connectivityStatusICMP := range possibleConnectivityStatus { 174 for _, possibleIP := range possibleIPs { 175 pathStatus := &models.PathStatus{ 176 HTTP: connectivityStatusHTTP, 177 Icmp: connectivityStatusICMP, 178 IP: possibleIP, 179 } 180 possiblePathStatuses = append(possiblePathStatuses, pathStatus) 181 } 182 } 183 } 184 185 possibleSecondaryAddresses := make([]*models.PathStatus, 0, len(possiblePathStatuses)+1) 186 possibleSecondaryAddresses = append(possibleSecondaryAddresses, nil) 187 possibleSecondaryAddresses = append(possibleSecondaryAddresses, possiblePathStatuses...) 188 189 // Assemble possible host statuses. 190 possibleHostStatuses := []*models.HostStatus{ 191 nil, 192 } 193 194 for _, possiblePrimaryAddress := range possiblePathStatuses { 195 hostStatus := &models.HostStatus{ 196 PrimaryAddress: possiblePrimaryAddress, 197 SecondaryAddresses: possibleSecondaryAddresses, 198 } 199 possibleHostStatuses = append(possibleHostStatuses, hostStatus) 200 } 201 202 // Assemble possible health-endpoint statuses. 203 possibleEndpointStatuses := []*models.EndpointStatus{ 204 nil, 205 } 206 for _, possiblePrimaryAddress := range possiblePathStatuses { 207 hostStatus := &models.EndpointStatus{ 208 PrimaryAddress: possiblePrimaryAddress, 209 SecondaryAddresses: possibleSecondaryAddresses, 210 } 211 possibleEndpointStatuses = append(possibleEndpointStatuses, hostStatus) 212 } 213 214 printAllOptions := []bool{true, false} 215 succinctOptions := []bool{true, false} 216 verboseOptions := []bool{true, false} 217 localhostOptions := []bool{true, false} 218 219 for _, possibleEndpointStatus := range possibleEndpointStatuses { 220 for _, hostStatus := range possibleHostStatuses { 221 for _, name := range possibleNames { 222 ns := &models.NodeStatus{ 223 HealthEndpoint: possibleEndpointStatus, 224 Host: hostStatus, 225 Name: name, 226 } 227 for _, printAllOpt := range printAllOptions { 228 for _, succintOpt := range succinctOptions { 229 for _, verboseOpt := range verboseOptions { 230 for _, localhostOpt := range localhostOptions { 231 formatNodeStatus(w, ns, printAllOpt, succintOpt, verboseOpt, localhostOpt) 232 } 233 } 234 } 235 } 236 } 237 } 238 } 239 } 240 241 func TestGetHostPrimaryAddress(t *testing.T) { 242 nilHostNS := &models.NodeStatus{ 243 Host: nil, 244 } 245 246 pathStatus := GetHostPrimaryAddress(nilHostNS) 247 require.Nil(t, pathStatus) 248 249 nilPrimaryAddressNS := &models.NodeStatus{ 250 Host: &models.HostStatus{ 251 PrimaryAddress: nil, 252 }, 253 } 254 255 pathStatus = GetHostPrimaryAddress(nilPrimaryAddressNS) 256 require.Nil(t, pathStatus) 257 258 primaryAddressNS := &models.NodeStatus{ 259 Host: &models.HostStatus{ 260 PrimaryAddress: &models.PathStatus{}, 261 }, 262 } 263 264 pathStatus = GetHostPrimaryAddress(primaryAddressNS) 265 require.NotNil(t, pathStatus) 266 } 267 268 func TestGetPrimaryAddressIP(t *testing.T) { 269 nilHostNS := &models.NodeStatus{ 270 Host: nil, 271 } 272 273 pathStatus := getPrimaryAddressIP(nilHostNS) 274 require.Equal(t, ipUnavailable, pathStatus) 275 276 nilPrimaryAddressNS := &models.NodeStatus{ 277 Host: &models.HostStatus{ 278 PrimaryAddress: nil, 279 }, 280 } 281 282 pathStatus = getPrimaryAddressIP(nilPrimaryAddressNS) 283 require.Equal(t, ipUnavailable, pathStatus) 284 285 primaryAddressNS := &models.NodeStatus{ 286 Host: &models.HostStatus{ 287 PrimaryAddress: &models.PathStatus{}, 288 }, 289 } 290 291 pathStatus = getPrimaryAddressIP(primaryAddressNS) 292 require.Empty(t, pathStatus) 293 } 294 295 func TestGetAllEndpointAddresses(t *testing.T) { 296 var ( 297 primary = models.PathStatus{IP: "1.1.1.1"} 298 secondary1 = models.PathStatus{IP: "2.2.2.2"} 299 secondary2 = models.PathStatus{IP: "3.3.3.3"} 300 ) 301 302 tests := []struct { 303 node *models.NodeStatus 304 expected []*models.PathStatus 305 }{ 306 { 307 node: &models.NodeStatus{}, 308 expected: nil, 309 }, 310 { 311 node: &models.NodeStatus{ 312 HealthEndpoint: &models.EndpointStatus{ 313 PrimaryAddress: &primary, 314 }}, 315 expected: []*models.PathStatus{&primary}, 316 }, 317 { 318 node: &models.NodeStatus{ 319 HealthEndpoint: &models.EndpointStatus{ 320 PrimaryAddress: &primary, 321 SecondaryAddresses: []*models.PathStatus{&secondary1, &secondary2}, 322 }}, 323 expected: []*models.PathStatus{&primary, &secondary1, &secondary2}, 324 }, 325 } 326 for _, tc := range tests { 327 require.Equal(t, tc.expected, GetAllEndpointAddresses(tc.node)) 328 } 329 }