github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/libpod/networking_linux_test.go (about) 1 package libpod 2 3 import ( 4 "fmt" 5 "net" 6 "reflect" 7 "testing" 8 9 "github.com/stretchr/testify/assert" 10 11 "github.com/containers/common/libnetwork/types" 12 "github.com/hanks177/podman/v4/libpod/define" 13 ) 14 15 func Test_ocicniPortsToNetTypesPorts(t *testing.T) { 16 tests := []struct { 17 name string 18 arg []types.OCICNIPortMapping 19 want []types.PortMapping 20 }{ 21 { 22 name: "no ports", 23 arg: nil, 24 want: nil, 25 }, 26 { 27 name: "empty ports", 28 arg: []types.OCICNIPortMapping{}, 29 want: nil, 30 }, 31 { 32 name: "single port", 33 arg: []types.OCICNIPortMapping{ 34 { 35 HostPort: 8080, 36 ContainerPort: 80, 37 Protocol: "tcp", 38 }, 39 }, 40 want: []types.PortMapping{ 41 { 42 HostPort: 8080, 43 ContainerPort: 80, 44 Protocol: "tcp", 45 Range: 1, 46 }, 47 }, 48 }, 49 { 50 name: "two separate ports", 51 arg: []types.OCICNIPortMapping{ 52 { 53 HostPort: 8080, 54 ContainerPort: 80, 55 Protocol: "tcp", 56 }, 57 { 58 HostPort: 9000, 59 ContainerPort: 90, 60 Protocol: "tcp", 61 }, 62 }, 63 want: []types.PortMapping{ 64 { 65 HostPort: 8080, 66 ContainerPort: 80, 67 Protocol: "tcp", 68 Range: 1, 69 }, 70 { 71 HostPort: 9000, 72 ContainerPort: 90, 73 Protocol: "tcp", 74 Range: 1, 75 }, 76 }, 77 }, 78 { 79 name: "two ports joined", 80 arg: []types.OCICNIPortMapping{ 81 { 82 HostPort: 8080, 83 ContainerPort: 80, 84 Protocol: "tcp", 85 }, 86 { 87 HostPort: 8081, 88 ContainerPort: 81, 89 Protocol: "tcp", 90 }, 91 }, 92 want: []types.PortMapping{ 93 { 94 HostPort: 8080, 95 ContainerPort: 80, 96 Protocol: "tcp", 97 Range: 2, 98 }, 99 }, 100 }, 101 { 102 name: "three ports with different container port are not joined", 103 arg: []types.OCICNIPortMapping{ 104 { 105 HostPort: 8080, 106 ContainerPort: 80, 107 Protocol: "tcp", 108 }, 109 { 110 HostPort: 8081, 111 ContainerPort: 79, 112 Protocol: "tcp", 113 }, 114 { 115 HostPort: 8082, 116 ContainerPort: 82, 117 Protocol: "tcp", 118 }, 119 }, 120 want: []types.PortMapping{ 121 { 122 HostPort: 8080, 123 ContainerPort: 80, 124 Protocol: "tcp", 125 Range: 1, 126 }, 127 { 128 HostPort: 8081, 129 ContainerPort: 79, 130 Protocol: "tcp", 131 Range: 1, 132 }, 133 { 134 HostPort: 8082, 135 ContainerPort: 82, 136 Protocol: "tcp", 137 Range: 1, 138 }, 139 }, 140 }, 141 { 142 name: "three ports joined (not sorted)", 143 arg: []types.OCICNIPortMapping{ 144 { 145 HostPort: 8081, 146 ContainerPort: 81, 147 Protocol: "tcp", 148 }, 149 { 150 HostPort: 8080, 151 ContainerPort: 80, 152 Protocol: "tcp", 153 }, 154 { 155 HostPort: 8082, 156 ContainerPort: 82, 157 Protocol: "tcp", 158 }, 159 }, 160 want: []types.PortMapping{ 161 { 162 HostPort: 8080, 163 ContainerPort: 80, 164 Protocol: "tcp", 165 Range: 3, 166 }, 167 }, 168 }, 169 { 170 name: "different protocols ports are not joined", 171 arg: []types.OCICNIPortMapping{ 172 { 173 HostPort: 8080, 174 ContainerPort: 80, 175 Protocol: "tcp", 176 }, 177 { 178 HostPort: 8081, 179 ContainerPort: 81, 180 Protocol: "udp", 181 }, 182 }, 183 want: []types.PortMapping{ 184 { 185 HostPort: 8080, 186 ContainerPort: 80, 187 Protocol: "tcp", 188 Range: 1, 189 }, 190 { 191 HostPort: 8081, 192 ContainerPort: 81, 193 Protocol: "udp", 194 Range: 1, 195 }, 196 }, 197 }, 198 { 199 name: "different host ip ports are not joined", 200 arg: []types.OCICNIPortMapping{ 201 { 202 HostPort: 8080, 203 ContainerPort: 80, 204 Protocol: "tcp", 205 HostIP: "192.168.1.1", 206 }, 207 { 208 HostPort: 8081, 209 ContainerPort: 81, 210 Protocol: "tcp", 211 HostIP: "192.168.1.2", 212 }, 213 }, 214 want: []types.PortMapping{ 215 { 216 HostPort: 8080, 217 ContainerPort: 80, 218 Protocol: "tcp", 219 Range: 1, 220 HostIP: "192.168.1.1", 221 }, 222 { 223 HostPort: 8081, 224 ContainerPort: 81, 225 Protocol: "tcp", 226 Range: 1, 227 HostIP: "192.168.1.2", 228 }, 229 }, 230 }, 231 } 232 for _, tt := range tests { 233 tt := tt 234 t.Run(tt.name, func(t *testing.T) { 235 result := ocicniPortsToNetTypesPorts(tt.arg) 236 assert.Equal(t, tt.want, result, "ports do not match") 237 }) 238 } 239 } 240 241 func Test_resultToBasicNetworkConfig(t *testing.T) { 242 testCases := []struct { 243 description string 244 inputResult types.StatusBlock 245 expectedNetworkConfig define.InspectBasicNetworkConfig 246 }{ 247 { 248 description: "single secondary IPv4 address is shown as define.Address", 249 inputResult: types.StatusBlock{ 250 Interfaces: map[string]types.NetInterface{ 251 "eth1": { 252 Subnets: []types.NetAddress{ 253 { 254 Gateway: net.ParseIP("172.26.0.1"), 255 IPNet: types.IPNet{ 256 IPNet: net.IPNet{ 257 IP: net.ParseIP("172.26.0.2"), 258 Mask: net.CIDRMask(20, 32), 259 }, 260 }, 261 }, 262 { 263 IPNet: types.IPNet{ 264 IPNet: net.IPNet{ 265 IP: net.ParseIP("172.26.0.3"), 266 Mask: net.CIDRMask(10, 32), 267 }, 268 }, 269 }, 270 }, 271 }, 272 }, 273 }, 274 expectedNetworkConfig: define.InspectBasicNetworkConfig{ 275 IPAddress: "172.26.0.2", 276 IPPrefixLen: 20, 277 Gateway: "172.26.0.1", 278 SecondaryIPAddresses: []define.Address{ 279 { 280 Addr: "172.26.0.3", 281 PrefixLength: 10, 282 }, 283 }, 284 }, 285 }, 286 { 287 description: "multiple secondary IPv4 addresses are shown as define.Address", 288 inputResult: types.StatusBlock{ 289 Interfaces: map[string]types.NetInterface{ 290 "eth1": { 291 Subnets: []types.NetAddress{ 292 { 293 Gateway: net.ParseIP("172.26.0.1"), 294 IPNet: types.IPNet{ 295 IPNet: net.IPNet{ 296 IP: net.ParseIP("172.26.0.2"), 297 Mask: net.CIDRMask(20, 32), 298 }, 299 }, 300 }, 301 { 302 IPNet: types.IPNet{ 303 IPNet: net.IPNet{ 304 IP: net.ParseIP("172.26.0.3"), 305 Mask: net.CIDRMask(10, 32), 306 }, 307 }, 308 }, 309 { 310 IPNet: types.IPNet{ 311 IPNet: net.IPNet{ 312 IP: net.ParseIP("172.26.0.4"), 313 Mask: net.CIDRMask(24, 32), 314 }, 315 }, 316 }, 317 }, 318 }, 319 }, 320 }, 321 expectedNetworkConfig: define.InspectBasicNetworkConfig{ 322 IPAddress: "172.26.0.2", 323 IPPrefixLen: 20, 324 Gateway: "172.26.0.1", 325 SecondaryIPAddresses: []define.Address{ 326 { 327 Addr: "172.26.0.3", 328 PrefixLength: 10, 329 }, 330 { 331 Addr: "172.26.0.4", 332 PrefixLength: 24, 333 }, 334 }, 335 }, 336 }, 337 { 338 description: "single secondary IPv6 address is shown as define.Address", 339 inputResult: types.StatusBlock{ 340 Interfaces: map[string]types.NetInterface{ 341 "eth1": { 342 Subnets: []types.NetAddress{ 343 { 344 Gateway: net.ParseIP("ff02::fb"), 345 IPNet: types.IPNet{ 346 IPNet: net.IPNet{ 347 IP: net.ParseIP("ff02::fc"), 348 Mask: net.CIDRMask(20, 128), 349 }, 350 }, 351 }, 352 { 353 IPNet: types.IPNet{ 354 IPNet: net.IPNet{ 355 IP: net.ParseIP("ff02::fd"), 356 Mask: net.CIDRMask(10, 128), 357 }, 358 }, 359 }, 360 }, 361 }, 362 }, 363 }, 364 expectedNetworkConfig: define.InspectBasicNetworkConfig{ 365 GlobalIPv6Address: "ff02::fc", 366 GlobalIPv6PrefixLen: 20, 367 IPv6Gateway: "ff02::fb", 368 SecondaryIPv6Addresses: []define.Address{ 369 { 370 Addr: "ff02::fd", 371 PrefixLength: 10, 372 }, 373 }, 374 }, 375 }, 376 { 377 description: "multiple secondary IPv6 addresses are shown as define.Address", 378 inputResult: types.StatusBlock{ 379 Interfaces: map[string]types.NetInterface{ 380 "eth1": { 381 Subnets: []types.NetAddress{ 382 { 383 Gateway: net.ParseIP("ff02::fb"), 384 IPNet: types.IPNet{ 385 IPNet: net.IPNet{ 386 IP: net.ParseIP("ff02::fc"), 387 Mask: net.CIDRMask(20, 128), 388 }, 389 }, 390 }, 391 { 392 IPNet: types.IPNet{ 393 IPNet: net.IPNet{ 394 IP: net.ParseIP("ff02::fd"), 395 Mask: net.CIDRMask(10, 128), 396 }, 397 }, 398 }, 399 { 400 IPNet: types.IPNet{ 401 IPNet: net.IPNet{ 402 IP: net.ParseIP("ff02::fe"), 403 Mask: net.CIDRMask(24, 128), 404 }, 405 }, 406 }, 407 }, 408 }, 409 }, 410 }, 411 expectedNetworkConfig: define.InspectBasicNetworkConfig{ 412 GlobalIPv6Address: "ff02::fc", 413 GlobalIPv6PrefixLen: 20, 414 IPv6Gateway: "ff02::fb", 415 SecondaryIPv6Addresses: []define.Address{ 416 { 417 Addr: "ff02::fd", 418 PrefixLength: 10, 419 }, 420 { 421 Addr: "ff02::fe", 422 PrefixLength: 24, 423 }, 424 }, 425 }, 426 }, 427 } 428 429 for _, tcl := range testCases { 430 tc := tcl 431 t.Run(tc.description, func(t *testing.T) { 432 t.Parallel() 433 actualNetworkConfig := resultToBasicNetworkConfig(tc.inputResult) 434 435 if !reflect.DeepEqual(tc.expectedNetworkConfig, actualNetworkConfig) { 436 t.Fatalf( 437 "Expected networkConfig %+v didn't match actual value %+v", tc.expectedNetworkConfig, actualNetworkConfig) 438 } 439 }) 440 } 441 } 442 443 func benchmarkOCICNIPortsToNetTypesPorts(b *testing.B, ports []types.OCICNIPortMapping) { 444 for n := 0; n < b.N; n++ { 445 ocicniPortsToNetTypesPorts(ports) 446 } 447 } 448 449 func Benchmark_ocicniPortsToNetTypesPortsNoPorts(b *testing.B) { 450 benchmarkOCICNIPortsToNetTypesPorts(b, nil) 451 } 452 453 func Benchmark_ocicniPortsToNetTypesPorts1(b *testing.B) { 454 benchmarkOCICNIPortsToNetTypesPorts(b, []types.OCICNIPortMapping{ 455 { 456 HostPort: 8080, 457 ContainerPort: 80, 458 Protocol: "tcp", 459 }, 460 }) 461 } 462 463 func Benchmark_ocicniPortsToNetTypesPorts10(b *testing.B) { 464 ports := make([]types.OCICNIPortMapping, 0, 10) 465 for i := int32(8080); i < 8090; i++ { 466 ports = append(ports, types.OCICNIPortMapping{ 467 HostPort: i, 468 ContainerPort: i, 469 Protocol: "tcp", 470 }) 471 } 472 b.ResetTimer() 473 benchmarkOCICNIPortsToNetTypesPorts(b, ports) 474 } 475 476 func Benchmark_ocicniPortsToNetTypesPorts100(b *testing.B) { 477 ports := make([]types.OCICNIPortMapping, 0, 100) 478 for i := int32(8080); i < 8180; i++ { 479 ports = append(ports, types.OCICNIPortMapping{ 480 HostPort: i, 481 ContainerPort: i, 482 Protocol: "tcp", 483 }) 484 } 485 b.ResetTimer() 486 benchmarkOCICNIPortsToNetTypesPorts(b, ports) 487 } 488 489 func Benchmark_ocicniPortsToNetTypesPorts1k(b *testing.B) { 490 ports := make([]types.OCICNIPortMapping, 0, 1000) 491 for i := int32(8080); i < 9080; i++ { 492 ports = append(ports, types.OCICNIPortMapping{ 493 HostPort: i, 494 ContainerPort: i, 495 Protocol: "tcp", 496 }) 497 } 498 b.ResetTimer() 499 benchmarkOCICNIPortsToNetTypesPorts(b, ports) 500 } 501 502 func Benchmark_ocicniPortsToNetTypesPorts10k(b *testing.B) { 503 ports := make([]types.OCICNIPortMapping, 0, 30000) 504 for i := int32(8080); i < 18080; i++ { 505 ports = append(ports, types.OCICNIPortMapping{ 506 HostPort: i, 507 ContainerPort: i, 508 Protocol: "tcp", 509 }) 510 } 511 b.ResetTimer() 512 benchmarkOCICNIPortsToNetTypesPorts(b, ports) 513 } 514 515 func Benchmark_ocicniPortsToNetTypesPorts1m(b *testing.B) { 516 ports := make([]types.OCICNIPortMapping, 0, 1000000) 517 for j := 0; j < 20; j++ { 518 for i := int32(1); i <= 50000; i++ { 519 ports = append(ports, types.OCICNIPortMapping{ 520 HostPort: i, 521 ContainerPort: i, 522 Protocol: "tcp", 523 HostIP: fmt.Sprintf("192.168.1.%d", j), 524 }) 525 } 526 } 527 b.ResetTimer() 528 benchmarkOCICNIPortsToNetTypesPorts(b, ports) 529 }