github.com/pwn-term/docker@v0.0.0-20210616085119-6e977cce2565/libnetwork/etchosts/etchosts_test.go (about) 1 package etchosts 2 3 import ( 4 "bytes" 5 "fmt" 6 "io/ioutil" 7 "os" 8 "sync" 9 "testing" 10 11 _ "github.com/docker/libnetwork/testutils" 12 ) 13 14 func TestBuildDefault(t *testing.T) { 15 file, err := ioutil.TempFile("", "") 16 if err != nil { 17 t.Fatal(err) 18 } 19 defer os.Remove(file.Name()) 20 21 // check that /data/data/hilled.pwnterm/files/usr/etc/hosts has consistent ordering 22 for i := 0; i <= 5; i++ { 23 err = Build(file.Name(), "", "", "", nil) 24 if err != nil { 25 t.Fatal(err) 26 } 27 28 content, err := ioutil.ReadFile(file.Name()) 29 if err != nil { 30 t.Fatal(err) 31 } 32 expected := "127.0.0.1\tlocalhost\n::1\tlocalhost ip6-localhost ip6-loopback\nfe00::0\tip6-localnet\nff00::0\tip6-mcastprefix\nff02::1\tip6-allnodes\nff02::2\tip6-allrouters\n" 33 34 if expected != string(content) { 35 t.Fatalf("Expected to find '%s' got '%s'", expected, content) 36 } 37 } 38 } 39 40 func TestBuildHostnameDomainname(t *testing.T) { 41 file, err := ioutil.TempFile("", "") 42 if err != nil { 43 t.Fatal(err) 44 } 45 defer os.Remove(file.Name()) 46 47 err = Build(file.Name(), "10.11.12.13", "testhostname", "testdomainname", nil) 48 if err != nil { 49 t.Fatal(err) 50 } 51 52 content, err := ioutil.ReadFile(file.Name()) 53 if err != nil { 54 t.Fatal(err) 55 } 56 57 if expected := "10.11.12.13\ttesthostname.testdomainname testhostname\n"; !bytes.Contains(content, []byte(expected)) { 58 t.Fatalf("Expected to find '%s' got '%s'", expected, content) 59 } 60 } 61 62 func TestBuildHostname(t *testing.T) { 63 file, err := ioutil.TempFile("", "") 64 if err != nil { 65 t.Fatal(err) 66 } 67 defer os.Remove(file.Name()) 68 69 err = Build(file.Name(), "10.11.12.13", "testhostname", "", nil) 70 if err != nil { 71 t.Fatal(err) 72 } 73 74 content, err := ioutil.ReadFile(file.Name()) 75 if err != nil { 76 t.Fatal(err) 77 } 78 79 if expected := "10.11.12.13\ttesthostname\n"; !bytes.Contains(content, []byte(expected)) { 80 t.Fatalf("Expected to find '%s' got '%s'", expected, content) 81 } 82 } 83 84 func TestBuildHostnameFQDN(t *testing.T) { 85 file, err := ioutil.TempFile("", "") 86 if err != nil { 87 t.Fatal(err) 88 } 89 defer os.Remove(file.Name()) 90 91 err = Build(file.Name(), "10.11.12.13", "testhostname.testdomainname.com", "", nil) 92 if err != nil { 93 t.Fatal(err) 94 } 95 96 content, err := ioutil.ReadFile(file.Name()) 97 if err != nil { 98 t.Fatal(err) 99 } 100 101 if expected := "10.11.12.13\ttesthostname.testdomainname.com testhostname\n"; !bytes.Contains(content, []byte(expected)) { 102 t.Fatalf("Expected to find '%s' got '%s'", expected, content) 103 } 104 } 105 106 func TestBuildNoIP(t *testing.T) { 107 file, err := ioutil.TempFile("", "") 108 if err != nil { 109 t.Fatal(err) 110 } 111 defer os.Remove(file.Name()) 112 113 err = Build(file.Name(), "", "testhostname", "", nil) 114 if err != nil { 115 t.Fatal(err) 116 } 117 118 content, err := ioutil.ReadFile(file.Name()) 119 if err != nil { 120 t.Fatal(err) 121 } 122 123 if expected := ""; !bytes.Contains(content, []byte(expected)) { 124 t.Fatalf("Expected to find '%s' got '%s'", expected, content) 125 } 126 } 127 128 func TestUpdate(t *testing.T) { 129 file, err := ioutil.TempFile("", "") 130 if err != nil { 131 t.Fatal(err) 132 } 133 defer os.Remove(file.Name()) 134 135 if err := Build(file.Name(), "10.11.12.13", "testhostname", "testdomainname", nil); err != nil { 136 t.Fatal(err) 137 } 138 139 content, err := ioutil.ReadFile(file.Name()) 140 if err != nil { 141 t.Fatal(err) 142 } 143 144 if expected := "10.11.12.13\ttesthostname.testdomainname testhostname\n"; !bytes.Contains(content, []byte(expected)) { 145 t.Fatalf("Expected to find '%s' got '%s'", expected, content) 146 } 147 148 if err := Update(file.Name(), "1.1.1.1", "testhostname"); err != nil { 149 t.Fatal(err) 150 } 151 152 content, err = ioutil.ReadFile(file.Name()) 153 if err != nil { 154 t.Fatal(err) 155 } 156 157 if expected := "1.1.1.1\ttesthostname.testdomainname testhostname\n"; !bytes.Contains(content, []byte(expected)) { 158 t.Fatalf("Expected to find '%s' got '%s'", expected, content) 159 } 160 } 161 162 // This regression test ensures that when a host is given a new IP 163 // via the Update function that other hosts which start with the 164 // same name as the targeted host are not erroneously updated as well. 165 // In the test example, if updating a host called "prefix", unrelated 166 // hosts named "prefixAndMore" or "prefix2" or anything else starting 167 // with "prefix" should not be changed. For more information see 168 // GitHub issue #603. 169 func TestUpdateIgnoresPrefixedHostname(t *testing.T) { 170 file, err := ioutil.TempFile("", "") 171 if err != nil { 172 t.Fatal(err) 173 } 174 defer os.Remove(file.Name()) 175 176 if err := Build(file.Name(), "10.11.12.13", "testhostname", "testdomainname", []Record{ 177 { 178 Hosts: "prefix", 179 IP: "2.2.2.2", 180 }, 181 { 182 Hosts: "prefixAndMore", 183 IP: "3.3.3.3", 184 }, 185 { 186 Hosts: "unaffectedHost", 187 IP: "4.4.4.4", 188 }, 189 }); err != nil { 190 t.Fatal(err) 191 } 192 193 content, err := ioutil.ReadFile(file.Name()) 194 if err != nil { 195 t.Fatal(err) 196 } 197 198 if expected := "2.2.2.2\tprefix\n3.3.3.3\tprefixAndMore\n4.4.4.4\tunaffectedHost\n"; !bytes.Contains(content, []byte(expected)) { 199 t.Fatalf("Expected to find '%s' got '%s'", expected, content) 200 } 201 202 if err := Update(file.Name(), "5.5.5.5", "prefix"); err != nil { 203 t.Fatal(err) 204 } 205 206 content, err = ioutil.ReadFile(file.Name()) 207 if err != nil { 208 t.Fatal(err) 209 } 210 211 if expected := "5.5.5.5\tprefix\n3.3.3.3\tprefixAndMore\n4.4.4.4\tunaffectedHost\n"; !bytes.Contains(content, []byte(expected)) { 212 t.Fatalf("Expected to find '%s' got '%s'", expected, content) 213 } 214 215 } 216 217 // This regression test covers the host prefix issue for the 218 // Delete function. In the test example, if deleting a host called 219 // "prefix", an unrelated host called "prefixAndMore" should not 220 // be deleted. For more information see GitHub issue #603. 221 func TestDeleteIgnoresPrefixedHostname(t *testing.T) { 222 file, err := ioutil.TempFile("", "") 223 if err != nil { 224 t.Fatal(err) 225 } 226 defer os.Remove(file.Name()) 227 228 err = Build(file.Name(), "", "", "", nil) 229 if err != nil { 230 t.Fatal(err) 231 } 232 233 if err := Add(file.Name(), []Record{ 234 { 235 Hosts: "prefix", 236 IP: "1.1.1.1", 237 }, 238 { 239 Hosts: "prefixAndMore", 240 IP: "2.2.2.2", 241 }, 242 }); err != nil { 243 t.Fatal(err) 244 } 245 246 if err := Delete(file.Name(), []Record{ 247 { 248 Hosts: "prefix", 249 IP: "1.1.1.1", 250 }, 251 }); err != nil { 252 t.Fatal(err) 253 } 254 255 content, err := ioutil.ReadFile(file.Name()) 256 if err != nil { 257 t.Fatal(err) 258 } 259 260 if expected := "2.2.2.2\tprefixAndMore\n"; !bytes.Contains(content, []byte(expected)) { 261 t.Fatalf("Expected to find '%s' got '%s'", expected, content) 262 } 263 264 if expected := "1.1.1.1\tprefix\n"; bytes.Contains(content, []byte(expected)) { 265 t.Fatalf("Did not expect to find '%s' got '%s'", expected, content) 266 } 267 } 268 269 func TestAddEmpty(t *testing.T) { 270 file, err := ioutil.TempFile("", "") 271 if err != nil { 272 t.Fatal(err) 273 } 274 defer os.Remove(file.Name()) 275 276 err = Build(file.Name(), "", "", "", nil) 277 if err != nil { 278 t.Fatal(err) 279 } 280 281 if err := Add(file.Name(), []Record{}); err != nil { 282 t.Fatal(err) 283 } 284 } 285 286 func TestAdd(t *testing.T) { 287 file, err := ioutil.TempFile("", "") 288 if err != nil { 289 t.Fatal(err) 290 } 291 defer os.Remove(file.Name()) 292 293 err = Build(file.Name(), "", "", "", nil) 294 if err != nil { 295 t.Fatal(err) 296 } 297 298 if err := Add(file.Name(), []Record{ 299 { 300 Hosts: "testhostname", 301 IP: "2.2.2.2", 302 }, 303 }); err != nil { 304 t.Fatal(err) 305 } 306 307 content, err := ioutil.ReadFile(file.Name()) 308 if err != nil { 309 t.Fatal(err) 310 } 311 312 if expected := "2.2.2.2\ttesthostname\n"; !bytes.Contains(content, []byte(expected)) { 313 t.Fatalf("Expected to find '%s' got '%s'", expected, content) 314 } 315 } 316 317 func TestDeleteEmpty(t *testing.T) { 318 file, err := ioutil.TempFile("", "") 319 if err != nil { 320 t.Fatal(err) 321 } 322 defer os.Remove(file.Name()) 323 324 err = Build(file.Name(), "", "", "", nil) 325 if err != nil { 326 t.Fatal(err) 327 } 328 329 if err := Delete(file.Name(), []Record{}); err != nil { 330 t.Fatal(err) 331 } 332 } 333 334 func TestDeleteNewline(t *testing.T) { 335 file, err := ioutil.TempFile("", "") 336 if err != nil { 337 t.Fatal(err) 338 } 339 defer os.Remove(file.Name()) 340 341 b := []byte("\n") 342 if _, err := file.Write(b); err != nil { 343 t.Fatal(err) 344 } 345 346 rec := []Record{ 347 { 348 Hosts: "prefix", 349 IP: "2.2.2.2", 350 }, 351 } 352 if err := Delete(file.Name(), rec); err != nil { 353 t.Fatal(err) 354 } 355 } 356 357 func TestDelete(t *testing.T) { 358 file, err := ioutil.TempFile("", "") 359 if err != nil { 360 t.Fatal(err) 361 } 362 defer os.Remove(file.Name()) 363 364 err = Build(file.Name(), "", "", "", nil) 365 if err != nil { 366 t.Fatal(err) 367 } 368 369 if err := Add(file.Name(), []Record{ 370 { 371 Hosts: "testhostname1", 372 IP: "1.1.1.1", 373 }, 374 { 375 Hosts: "testhostname2", 376 IP: "2.2.2.2", 377 }, 378 { 379 Hosts: "testhostname3", 380 IP: "3.3.3.3", 381 }, 382 }); err != nil { 383 t.Fatal(err) 384 } 385 386 if err := Delete(file.Name(), []Record{ 387 { 388 Hosts: "testhostname1", 389 IP: "1.1.1.1", 390 }, 391 { 392 Hosts: "testhostname3", 393 IP: "3.3.3.3", 394 }, 395 }); err != nil { 396 t.Fatal(err) 397 } 398 399 content, err := ioutil.ReadFile(file.Name()) 400 if err != nil { 401 t.Fatal(err) 402 } 403 404 if expected := "2.2.2.2\ttesthostname2\n"; !bytes.Contains(content, []byte(expected)) { 405 t.Fatalf("Expected to find '%s' got '%s'", expected, content) 406 } 407 408 if expected := "1.1.1.1\ttesthostname1\n"; bytes.Contains(content, []byte(expected)) { 409 t.Fatalf("Did not expect to find '%s' got '%s'", expected, content) 410 } 411 } 412 413 func TestConcurrentWrites(t *testing.T) { 414 file, err := ioutil.TempFile("", "") 415 if err != nil { 416 t.Fatal(err) 417 } 418 defer os.Remove(file.Name()) 419 420 err = Build(file.Name(), "", "", "", nil) 421 if err != nil { 422 t.Fatal(err) 423 } 424 425 if err := Add(file.Name(), []Record{ 426 { 427 Hosts: "inithostname", 428 IP: "172.17.0.1", 429 }, 430 }); err != nil { 431 t.Fatal(err) 432 } 433 434 var wg sync.WaitGroup 435 for i := 0; i < 10; i++ { 436 wg.Add(1) 437 go func(i int) { 438 defer wg.Done() 439 440 rec := []Record{ 441 { 442 IP: fmt.Sprintf("%d.%d.%d.%d", i, i, i, i), 443 Hosts: fmt.Sprintf("testhostname%d", i), 444 }, 445 } 446 447 for j := 0; j < 25; j++ { 448 if err := Add(file.Name(), rec); err != nil { 449 t.Fatal(err) 450 } 451 452 if err := Delete(file.Name(), rec); err != nil { 453 t.Fatal(err) 454 } 455 } 456 }(i) 457 } 458 459 wg.Wait() 460 461 content, err := ioutil.ReadFile(file.Name()) 462 if err != nil { 463 t.Fatal(err) 464 } 465 466 if expected := "172.17.0.1\tinithostname\n"; !bytes.Contains(content, []byte(expected)) { 467 t.Fatalf("Expected to find '%s' got '%s'", expected, content) 468 } 469 } 470 471 func benchDelete(b *testing.B) { 472 b.StopTimer() 473 file, err := ioutil.TempFile("", "") 474 if err != nil { 475 b.Fatal(err) 476 } 477 defer func() { 478 b.StopTimer() 479 file.Close() 480 os.Remove(file.Name()) 481 b.StartTimer() 482 }() 483 484 err = Build(file.Name(), "", "", "", nil) 485 if err != nil { 486 b.Fatal(err) 487 } 488 489 var records []Record 490 var toDelete []Record 491 for i := 0; i < 255; i++ { 492 record := Record{ 493 Hosts: fmt.Sprintf("testhostname%d", i), 494 IP: fmt.Sprintf("%d.%d.%d.%d", i, i, i, i), 495 } 496 records = append(records, record) 497 if i%2 == 0 { 498 toDelete = append(records, record) 499 } 500 } 501 502 if err := Add(file.Name(), records); err != nil { 503 b.Fatal(err) 504 } 505 506 b.StartTimer() 507 if err := Delete(file.Name(), toDelete); err != nil { 508 b.Fatal(err) 509 } 510 } 511 512 func BenchmarkDelete(b *testing.B) { 513 for i := 0; i < b.N; i++ { 514 benchDelete(b) 515 } 516 }