github.com/docker/engine@v22.0.0-20211208180946-d456264580cf+incompatible/libnetwork/portallocator/portallocator_test.go (about) 1 package portallocator 2 3 import ( 4 "fmt" 5 "net" 6 "testing" 7 ) 8 9 func resetPortAllocator() { 10 instance = newInstance() 11 } 12 13 func TestRequestNewPort(t *testing.T) { 14 p := Get() 15 defer resetPortAllocator() 16 17 port, err := p.RequestPort(defaultIP, "tcp", 0) 18 if err != nil { 19 t.Fatal(err) 20 } 21 22 if expected := p.Begin; port != expected { 23 t.Fatalf("Expected port %d got %d", expected, port) 24 } 25 } 26 27 func TestRequestSpecificPort(t *testing.T) { 28 p := Get() 29 defer resetPortAllocator() 30 31 port, err := p.RequestPort(defaultIP, "tcp", 5000) 32 if err != nil { 33 t.Fatal(err) 34 } 35 36 if port != 5000 { 37 t.Fatalf("Expected port 5000 got %d", port) 38 } 39 } 40 41 func TestReleasePort(t *testing.T) { 42 p := Get() 43 44 port, err := p.RequestPort(defaultIP, "tcp", 5000) 45 if err != nil { 46 t.Fatal(err) 47 } 48 if port != 5000 { 49 t.Fatalf("Expected port 5000 got %d", port) 50 } 51 52 if err := p.ReleasePort(defaultIP, "tcp", 5000); err != nil { 53 t.Fatal(err) 54 } 55 } 56 57 func TestReuseReleasedPort(t *testing.T) { 58 p := Get() 59 defer resetPortAllocator() 60 61 port, err := p.RequestPort(defaultIP, "tcp", 5000) 62 if err != nil { 63 t.Fatal(err) 64 } 65 if port != 5000 { 66 t.Fatalf("Expected port 5000 got %d", port) 67 } 68 69 if err := p.ReleasePort(defaultIP, "tcp", 5000); err != nil { 70 t.Fatal(err) 71 } 72 73 port, err = p.RequestPort(defaultIP, "tcp", 5000) 74 if err != nil { 75 t.Fatal(err) 76 } 77 if port != 5000 { 78 t.Fatalf("Expected port 5000 got %d", port) 79 } 80 } 81 82 func TestReleaseUnreadledPort(t *testing.T) { 83 p := Get() 84 defer resetPortAllocator() 85 86 port, err := p.RequestPort(defaultIP, "tcp", 5000) 87 if err != nil { 88 t.Fatal(err) 89 } 90 if port != 5000 { 91 t.Fatalf("Expected port 5000 got %d", port) 92 } 93 94 _, err = p.RequestPort(defaultIP, "tcp", 5000) 95 96 switch err.(type) { 97 case ErrPortAlreadyAllocated: 98 default: 99 t.Fatalf("Expected port allocation error got %s", err) 100 } 101 } 102 103 func TestUnknowProtocol(t *testing.T) { 104 if _, err := Get().RequestPort(defaultIP, "tcpp", 0); err != ErrUnknownProtocol { 105 t.Fatalf("Expected error %s got %s", ErrUnknownProtocol, err) 106 } 107 } 108 109 func TestAllocateAllPorts(t *testing.T) { 110 p := Get() 111 defer resetPortAllocator() 112 113 for i := 0; i <= p.End-p.Begin; i++ { 114 port, err := p.RequestPort(defaultIP, "tcp", 0) 115 if err != nil { 116 t.Fatal(err) 117 } 118 119 if expected := p.Begin + i; port != expected { 120 t.Fatalf("Expected port %d got %d", expected, port) 121 } 122 } 123 124 if _, err := p.RequestPort(defaultIP, "tcp", 0); err != ErrAllPortsAllocated { 125 t.Fatalf("Expected error %s got %s", ErrAllPortsAllocated, err) 126 } 127 128 _, err := p.RequestPort(defaultIP, "udp", 0) 129 if err != nil { 130 t.Fatal(err) 131 } 132 133 // release a port in the middle and ensure we get another tcp port 134 port := p.Begin + 5 135 if err := p.ReleasePort(defaultIP, "tcp", port); err != nil { 136 t.Fatal(err) 137 } 138 newPort, err := p.RequestPort(defaultIP, "tcp", 0) 139 if err != nil { 140 t.Fatal(err) 141 } 142 if newPort != port { 143 t.Fatalf("Expected port %d got %d", port, newPort) 144 } 145 146 // now pm.last == newPort, release it so that it's the only free port of 147 // the range, and ensure we get it back 148 if err := p.ReleasePort(defaultIP, "tcp", newPort); err != nil { 149 t.Fatal(err) 150 } 151 port, err = p.RequestPort(defaultIP, "tcp", 0) 152 if err != nil { 153 t.Fatal(err) 154 } 155 if newPort != port { 156 t.Fatalf("Expected port %d got %d", newPort, port) 157 } 158 } 159 160 func BenchmarkAllocatePorts(b *testing.B) { 161 p := Get() 162 defer resetPortAllocator() 163 164 for i := 0; i < b.N; i++ { 165 for i := 0; i <= p.End-p.Begin; i++ { 166 port, err := p.RequestPort(defaultIP, "tcp", 0) 167 if err != nil { 168 b.Fatal(err) 169 } 170 171 if expected := p.Begin + i; port != expected { 172 b.Fatalf("Expected port %d got %d", expected, port) 173 } 174 } 175 if err := p.ReleaseAll(); err != nil { 176 b.Fatal(err) 177 } 178 } 179 } 180 181 func TestPortAllocation(t *testing.T) { 182 p := Get() 183 defer resetPortAllocator() 184 185 ip := net.ParseIP("192.168.0.1") 186 ip2 := net.ParseIP("192.168.0.2") 187 if port, err := p.RequestPort(ip, "tcp", 80); err != nil { 188 t.Fatal(err) 189 } else if port != 80 { 190 t.Fatalf("Acquire(80) should return 80, not %d", port) 191 } 192 port, err := p.RequestPort(ip, "tcp", 0) 193 if err != nil { 194 t.Fatal(err) 195 } 196 if port <= 0 { 197 t.Fatalf("Acquire(0) should return a non-zero port") 198 } 199 200 if _, err := p.RequestPort(ip, "tcp", port); err == nil { 201 t.Fatalf("Acquiring a port already in use should return an error") 202 } 203 204 if newPort, err := p.RequestPort(ip, "tcp", 0); err != nil { 205 t.Fatal(err) 206 } else if newPort == port { 207 t.Fatalf("Acquire(0) allocated the same port twice: %d", port) 208 } 209 210 if _, err := p.RequestPort(ip, "tcp", 80); err == nil { 211 t.Fatalf("Acquiring a port already in use should return an error") 212 } 213 if _, err := p.RequestPort(ip2, "tcp", 80); err != nil { 214 t.Fatalf("It should be possible to allocate the same port on a different interface") 215 } 216 if _, err := p.RequestPort(ip2, "tcp", 80); err == nil { 217 t.Fatalf("Acquiring a port already in use should return an error") 218 } 219 if err := p.ReleasePort(ip, "tcp", 80); err != nil { 220 t.Fatal(err) 221 } 222 if _, err := p.RequestPort(ip, "tcp", 80); err != nil { 223 t.Fatal(err) 224 } 225 226 port, err = p.RequestPort(ip, "tcp", 0) 227 if err != nil { 228 t.Fatal(err) 229 } 230 port2, err := p.RequestPort(ip, "tcp", port+1) 231 if err != nil { 232 t.Fatal(err) 233 } 234 port3, err := p.RequestPort(ip, "tcp", 0) 235 if err != nil { 236 t.Fatal(err) 237 } 238 if port3 == port2 { 239 t.Fatal("Requesting a dynamic port should never allocate a used port") 240 } 241 } 242 243 func TestPortAllocationWithCustomRange(t *testing.T) { 244 p := Get() 245 defer resetPortAllocator() 246 247 start, end := 8081, 8082 248 specificPort := 8000 249 250 //get an ephemeral port. 251 port1, err := p.RequestPortInRange(defaultIP, "tcp", 0, 0) 252 if err != nil { 253 t.Fatal(err) 254 } 255 256 //request invalid ranges 257 if _, err := p.RequestPortInRange(defaultIP, "tcp", 0, end); err == nil { 258 t.Fatalf("Expected error for invalid range %d-%d", 0, end) 259 } 260 if _, err := p.RequestPortInRange(defaultIP, "tcp", start, 0); err == nil { 261 t.Fatalf("Expected error for invalid range %d-%d", 0, end) 262 } 263 if _, err := p.RequestPortInRange(defaultIP, "tcp", 8081, 8080); err == nil { 264 t.Fatalf("Expected error for invalid range %d-%d", 0, end) 265 } 266 267 //request a single port 268 port, err := p.RequestPortInRange(defaultIP, "tcp", specificPort, specificPort) 269 if err != nil { 270 t.Fatal(err) 271 } 272 if port != specificPort { 273 t.Fatalf("Expected port %d, got %d", specificPort, port) 274 } 275 276 //get a port from the range 277 port2, err := p.RequestPortInRange(defaultIP, "tcp", start, end) 278 if err != nil { 279 t.Fatal(err) 280 } 281 if port2 < start || port2 > end { 282 t.Fatalf("Expected a port between %d and %d, got %d", start, end, port2) 283 } 284 //get another ephemeral port (should be > port1) 285 port3, err := p.RequestPortInRange(defaultIP, "tcp", 0, 0) 286 if err != nil { 287 t.Fatal(err) 288 } 289 if port3 < port1 { 290 t.Fatalf("Expected new port > %d in the ephemeral range, got %d", port1, port3) 291 } 292 //get another (and in this case the only other) port from the range 293 port4, err := p.RequestPortInRange(defaultIP, "tcp", start, end) 294 if err != nil { 295 t.Fatal(err) 296 } 297 if port4 < start || port4 > end { 298 t.Fatalf("Expected a port between %d and %d, got %d", start, end, port4) 299 } 300 if port4 == port2 { 301 t.Fatal("Allocated the same port from a custom range") 302 } 303 //request 3rd port from the range of 2 304 if _, err := p.RequestPortInRange(defaultIP, "tcp", start, end); err != ErrAllPortsAllocated { 305 t.Fatalf("Expected error %s got %s", ErrAllPortsAllocated, err) 306 } 307 } 308 309 func TestNoDuplicateBPR(t *testing.T) { 310 p := Get() 311 defer resetPortAllocator() 312 313 if port, err := p.RequestPort(defaultIP, "tcp", p.Begin); err != nil { 314 t.Fatal(err) 315 } else if port != p.Begin { 316 t.Fatalf("Expected port %d got %d", p.Begin, port) 317 } 318 319 if port, err := p.RequestPort(defaultIP, "tcp", 0); err != nil { 320 t.Fatal(err) 321 } else if port == p.Begin { 322 t.Fatalf("Acquire(0) allocated the same port twice: %d", port) 323 } 324 } 325 326 func TestChangePortRange(t *testing.T) { 327 var tests = []struct { 328 begin int 329 end int 330 setErr error 331 reqRlt int 332 }{ 333 {defaultPortRangeEnd + 1, defaultPortRangeEnd + 10, fmt.Errorf("begin out of range"), 0}, 334 {defaultPortRangeStart - 10, defaultPortRangeStart - 1, fmt.Errorf("end out of range"), 0}, 335 {defaultPortRangeEnd, defaultPortRangeStart, fmt.Errorf("out of order"), 0}, 336 {defaultPortRangeStart + 100, defaultPortRangeEnd + 10, nil, defaultPortRangeStart + 100}, 337 {0, 0, nil, defaultPortRangeStart}, // revert to default if no value given 338 {defaultPortRangeStart - 100, defaultPortRangeEnd, nil, defaultPortRangeStart + 1}, 339 } 340 p := Get() 341 port := 0 342 for _, c := range tests { 343 t.Logf("test: port allocate range %v-%v, setErr=%v, reqPort=%v", 344 c.begin, c.end, c.setErr, c.reqRlt) 345 err := p.SetPortRange(c.begin, c.end) 346 if (c.setErr == nil && c.setErr != err) || 347 (c.setErr != nil && err == nil) { 348 t.Fatalf("Unexpected set range result, expected=%v, actual=%v", c.setErr, err) 349 } 350 if err != nil { 351 continue 352 } 353 if port > 0 { 354 err := p.ReleasePort(defaultIP, "tcp", port) 355 if err != nil { 356 t.Fatalf("Releasing port %v failed, err=%v", port, err) 357 } 358 } 359 360 port, err = p.RequestPort(defaultIP, "tcp", 0) 361 if err != nil { 362 t.Fatalf("Request failed, err %v", err) 363 } 364 if port != c.reqRlt { 365 t.Fatalf("Incorrect port returned, expected=%v, actual=%v", c.reqRlt, port) 366 } 367 } 368 }