github.com/damirazo/docker@v1.9.0/pkg/graphdb/graphdb_test.go (about) 1 package graphdb 2 3 import ( 4 "database/sql" 5 "fmt" 6 "os" 7 "path" 8 "strconv" 9 "testing" 10 11 _ "github.com/mattn/go-sqlite3" 12 ) 13 14 func newTestDb(t *testing.T) (*Database, string) { 15 p := path.Join(os.TempDir(), "sqlite.db") 16 conn, err := sql.Open("sqlite3", p) 17 db, err := NewDatabase(conn) 18 if err != nil { 19 t.Fatal(err) 20 } 21 return db, p 22 } 23 24 func destroyTestDb(dbPath string) { 25 os.Remove(dbPath) 26 } 27 28 func TestNewDatabase(t *testing.T) { 29 db, dbpath := newTestDb(t) 30 if db == nil { 31 t.Fatal("Database should not be nil") 32 } 33 db.Close() 34 defer destroyTestDb(dbpath) 35 } 36 37 func TestCreateRootEntity(t *testing.T) { 38 db, dbpath := newTestDb(t) 39 defer destroyTestDb(dbpath) 40 root := db.RootEntity() 41 if root == nil { 42 t.Fatal("Root entity should not be nil") 43 } 44 } 45 46 func TestGetRootEntity(t *testing.T) { 47 db, dbpath := newTestDb(t) 48 defer destroyTestDb(dbpath) 49 50 e := db.Get("/") 51 if e == nil { 52 t.Fatal("Entity should not be nil") 53 } 54 if e.ID() != "0" { 55 t.Fatalf("Entity id should be 0, got %s", e.ID()) 56 } 57 } 58 59 func TestSetEntityWithDifferentName(t *testing.T) { 60 db, dbpath := newTestDb(t) 61 defer destroyTestDb(dbpath) 62 63 db.Set("/test", "1") 64 if _, err := db.Set("/other", "1"); err != nil { 65 t.Fatal(err) 66 } 67 } 68 69 func TestSetDuplicateEntity(t *testing.T) { 70 db, dbpath := newTestDb(t) 71 defer destroyTestDb(dbpath) 72 73 if _, err := db.Set("/foo", "42"); err != nil { 74 t.Fatal(err) 75 } 76 if _, err := db.Set("/foo", "43"); err == nil { 77 t.Fatalf("Creating an entry with a duplicate path did not cause an error") 78 } 79 } 80 81 func TestCreateChild(t *testing.T) { 82 db, dbpath := newTestDb(t) 83 defer destroyTestDb(dbpath) 84 85 child, err := db.Set("/db", "1") 86 if err != nil { 87 t.Fatal(err) 88 } 89 if child == nil { 90 t.Fatal("Child should not be nil") 91 } 92 if child.ID() != "1" { 93 t.Fail() 94 } 95 } 96 97 func TestParents(t *testing.T) { 98 db, dbpath := newTestDb(t) 99 defer destroyTestDb(dbpath) 100 101 for i := 1; i < 6; i++ { 102 a := strconv.Itoa(i) 103 if _, err := db.Set("/"+a, a); err != nil { 104 t.Fatal(err) 105 } 106 } 107 108 for i := 6; i < 11; i++ { 109 a := strconv.Itoa(i) 110 p := strconv.Itoa(i - 5) 111 112 key := fmt.Sprintf("/%s/%s", p, a) 113 114 if _, err := db.Set(key, a); err != nil { 115 t.Fatal(err) 116 } 117 118 parents, err := db.Parents(key) 119 if err != nil { 120 t.Fatal(err) 121 } 122 123 if len(parents) != 1 { 124 t.Fatalf("Expected 1 entry for %s got %d", key, len(parents)) 125 } 126 127 if parents[0] != p { 128 t.Fatalf("ID %s received, %s expected", parents[0], p) 129 } 130 } 131 } 132 133 func TestChildren(t *testing.T) { 134 db, dbpath := newTestDb(t) 135 defer destroyTestDb(dbpath) 136 137 str := "/" 138 for i := 1; i < 6; i++ { 139 a := strconv.Itoa(i) 140 if _, err := db.Set(str+a, a); err != nil { 141 t.Fatal(err) 142 } 143 144 str = str + a + "/" 145 } 146 147 str = "/" 148 for i := 10; i < 30; i++ { // 20 entities 149 a := strconv.Itoa(i) 150 if _, err := db.Set(str+a, a); err != nil { 151 t.Fatal(err) 152 } 153 154 str = str + a + "/" 155 } 156 entries, err := db.Children("/", 5) 157 if err != nil { 158 t.Fatal(err) 159 } 160 161 if len(entries) != 11 { 162 t.Fatalf("Expect 11 entries for / got %d", len(entries)) 163 } 164 165 entries, err = db.Children("/", 20) 166 if err != nil { 167 t.Fatal(err) 168 } 169 170 if len(entries) != 25 { 171 t.Fatalf("Expect 25 entries for / got %d", len(entries)) 172 } 173 } 174 175 func TestListAllRootChildren(t *testing.T) { 176 db, dbpath := newTestDb(t) 177 defer destroyTestDb(dbpath) 178 179 for i := 1; i < 6; i++ { 180 a := strconv.Itoa(i) 181 if _, err := db.Set("/"+a, a); err != nil { 182 t.Fatal(err) 183 } 184 } 185 entries := db.List("/", -1) 186 if len(entries) != 5 { 187 t.Fatalf("Expect 5 entries for / got %d", len(entries)) 188 } 189 } 190 191 func TestListAllSubChildren(t *testing.T) { 192 db, dbpath := newTestDb(t) 193 defer destroyTestDb(dbpath) 194 195 _, err := db.Set("/webapp", "1") 196 if err != nil { 197 t.Fatal(err) 198 } 199 child2, err := db.Set("/db", "2") 200 if err != nil { 201 t.Fatal(err) 202 } 203 child4, err := db.Set("/logs", "4") 204 if err != nil { 205 t.Fatal(err) 206 } 207 if _, err := db.Set("/db/logs", child4.ID()); err != nil { 208 t.Fatal(err) 209 } 210 211 child3, err := db.Set("/sentry", "3") 212 if err != nil { 213 t.Fatal(err) 214 } 215 if _, err := db.Set("/webapp/sentry", child3.ID()); err != nil { 216 t.Fatal(err) 217 } 218 if _, err := db.Set("/webapp/db", child2.ID()); err != nil { 219 t.Fatal(err) 220 } 221 222 entries := db.List("/webapp", 1) 223 if len(entries) != 3 { 224 t.Fatalf("Expect 3 entries for / got %d", len(entries)) 225 } 226 227 entries = db.List("/webapp", 0) 228 if len(entries) != 2 { 229 t.Fatalf("Expect 2 entries for / got %d", len(entries)) 230 } 231 } 232 233 func TestAddSelfAsChild(t *testing.T) { 234 db, dbpath := newTestDb(t) 235 defer destroyTestDb(dbpath) 236 237 child, err := db.Set("/test", "1") 238 if err != nil { 239 t.Fatal(err) 240 } 241 if _, err := db.Set("/test/other", child.ID()); err == nil { 242 t.Fatal("Error should not be nil") 243 } 244 } 245 246 func TestAddChildToNonExistentRoot(t *testing.T) { 247 db, dbpath := newTestDb(t) 248 defer destroyTestDb(dbpath) 249 250 if _, err := db.Set("/myapp", "1"); err != nil { 251 t.Fatal(err) 252 } 253 254 if _, err := db.Set("/myapp/proxy/db", "2"); err == nil { 255 t.Fatal("Error should not be nil") 256 } 257 } 258 259 func TestWalkAll(t *testing.T) { 260 db, dbpath := newTestDb(t) 261 defer destroyTestDb(dbpath) 262 _, err := db.Set("/webapp", "1") 263 if err != nil { 264 t.Fatal(err) 265 } 266 child2, err := db.Set("/db", "2") 267 if err != nil { 268 t.Fatal(err) 269 } 270 child4, err := db.Set("/db/logs", "4") 271 if err != nil { 272 t.Fatal(err) 273 } 274 if _, err := db.Set("/webapp/logs", child4.ID()); err != nil { 275 t.Fatal(err) 276 } 277 278 child3, err := db.Set("/sentry", "3") 279 if err != nil { 280 t.Fatal(err) 281 } 282 if _, err := db.Set("/webapp/sentry", child3.ID()); err != nil { 283 t.Fatal(err) 284 } 285 if _, err := db.Set("/webapp/db", child2.ID()); err != nil { 286 t.Fatal(err) 287 } 288 289 child5, err := db.Set("/gograph", "5") 290 if err != nil { 291 t.Fatal(err) 292 } 293 if _, err := db.Set("/webapp/same-ref-diff-name", child5.ID()); err != nil { 294 t.Fatal(err) 295 } 296 297 if err := db.Walk("/", func(p string, e *Entity) error { 298 t.Logf("Path: %s Entity: %s", p, e.ID()) 299 return nil 300 }, -1); err != nil { 301 t.Fatal(err) 302 } 303 } 304 305 func TestGetEntityByPath(t *testing.T) { 306 db, dbpath := newTestDb(t) 307 defer destroyTestDb(dbpath) 308 _, err := db.Set("/webapp", "1") 309 if err != nil { 310 t.Fatal(err) 311 } 312 child2, err := db.Set("/db", "2") 313 if err != nil { 314 t.Fatal(err) 315 } 316 child4, err := db.Set("/logs", "4") 317 if err != nil { 318 t.Fatal(err) 319 } 320 if _, err := db.Set("/db/logs", child4.ID()); err != nil { 321 t.Fatal(err) 322 } 323 324 child3, err := db.Set("/sentry", "3") 325 if err != nil { 326 t.Fatal(err) 327 } 328 if _, err := db.Set("/webapp/sentry", child3.ID()); err != nil { 329 t.Fatal(err) 330 } 331 if _, err := db.Set("/webapp/db", child2.ID()); err != nil { 332 t.Fatal(err) 333 } 334 335 child5, err := db.Set("/gograph", "5") 336 if err != nil { 337 t.Fatal(err) 338 } 339 if _, err := db.Set("/webapp/same-ref-diff-name", child5.ID()); err != nil { 340 t.Fatal(err) 341 } 342 343 entity := db.Get("/webapp/db/logs") 344 if entity == nil { 345 t.Fatal("Entity should not be nil") 346 } 347 if entity.ID() != "4" { 348 t.Fatalf("Expected to get entity with id 4, got %s", entity.ID()) 349 } 350 } 351 352 func TestEnitiesPaths(t *testing.T) { 353 db, dbpath := newTestDb(t) 354 defer destroyTestDb(dbpath) 355 _, err := db.Set("/webapp", "1") 356 if err != nil { 357 t.Fatal(err) 358 } 359 child2, err := db.Set("/db", "2") 360 if err != nil { 361 t.Fatal(err) 362 } 363 child4, err := db.Set("/logs", "4") 364 if err != nil { 365 t.Fatal(err) 366 } 367 if _, err := db.Set("/db/logs", child4.ID()); err != nil { 368 t.Fatal(err) 369 } 370 371 child3, err := db.Set("/sentry", "3") 372 if err != nil { 373 t.Fatal(err) 374 } 375 if _, err := db.Set("/webapp/sentry", child3.ID()); err != nil { 376 t.Fatal(err) 377 } 378 if _, err := db.Set("/webapp/db", child2.ID()); err != nil { 379 t.Fatal(err) 380 } 381 382 child5, err := db.Set("/gograph", "5") 383 if err != nil { 384 t.Fatal(err) 385 } 386 if _, err := db.Set("/webapp/same-ref-diff-name", child5.ID()); err != nil { 387 t.Fatal(err) 388 } 389 390 out := db.List("/", -1) 391 for _, p := range out.Paths() { 392 t.Log(p) 393 } 394 } 395 396 func TestDeleteRootEntity(t *testing.T) { 397 db, dbpath := newTestDb(t) 398 defer destroyTestDb(dbpath) 399 400 if err := db.Delete("/"); err == nil { 401 t.Fatal("Error should not be nil") 402 } 403 } 404 405 func TestDeleteEntity(t *testing.T) { 406 db, dbpath := newTestDb(t) 407 defer destroyTestDb(dbpath) 408 _, err := db.Set("/webapp", "1") 409 if err != nil { 410 t.Fatal(err) 411 } 412 child2, err := db.Set("/db", "2") 413 if err != nil { 414 t.Fatal(err) 415 } 416 child4, err := db.Set("/logs", "4") 417 if err != nil { 418 t.Fatal(err) 419 } 420 if _, err := db.Set("/db/logs", child4.ID()); err != nil { 421 t.Fatal(err) 422 } 423 424 child3, err := db.Set("/sentry", "3") 425 if err != nil { 426 t.Fatal(err) 427 } 428 if _, err := db.Set("/webapp/sentry", child3.ID()); err != nil { 429 t.Fatal(err) 430 } 431 if _, err := db.Set("/webapp/db", child2.ID()); err != nil { 432 t.Fatal(err) 433 } 434 435 child5, err := db.Set("/gograph", "5") 436 if err != nil { 437 t.Fatal(err) 438 } 439 if _, err := db.Set("/webapp/same-ref-diff-name", child5.ID()); err != nil { 440 t.Fatal(err) 441 } 442 443 if err := db.Delete("/webapp/sentry"); err != nil { 444 t.Fatal(err) 445 } 446 entity := db.Get("/webapp/sentry") 447 if entity != nil { 448 t.Fatal("Entity /webapp/sentry should be nil") 449 } 450 } 451 452 func TestCountRefs(t *testing.T) { 453 db, dbpath := newTestDb(t) 454 defer destroyTestDb(dbpath) 455 456 db.Set("/webapp", "1") 457 458 if db.Refs("1") != 1 { 459 t.Fatal("Expect reference count to be 1") 460 } 461 462 db.Set("/db", "2") 463 db.Set("/webapp/db", "2") 464 if db.Refs("2") != 2 { 465 t.Fatal("Expect reference count to be 2") 466 } 467 } 468 469 func TestPurgeId(t *testing.T) { 470 db, dbpath := newTestDb(t) 471 defer destroyTestDb(dbpath) 472 473 db.Set("/webapp", "1") 474 475 if c := db.Refs("1"); c != 1 { 476 t.Fatalf("Expect reference count to be 1, got %d", c) 477 } 478 479 db.Set("/db", "2") 480 db.Set("/webapp/db", "2") 481 482 count, err := db.Purge("2") 483 if err != nil { 484 t.Fatal(err) 485 } 486 if count != 2 { 487 t.Fatalf("Expected 2 references to be removed, got %d", count) 488 } 489 } 490 491 // Regression test https://github.com/docker/docker/issues/12334 492 func TestPurgeIdRefPaths(t *testing.T) { 493 db, dbpath := newTestDb(t) 494 defer destroyTestDb(dbpath) 495 496 db.Set("/webapp", "1") 497 db.Set("/db", "2") 498 499 db.Set("/db/webapp", "1") 500 501 if c := db.Refs("1"); c != 2 { 502 t.Fatalf("Expected 2 reference for webapp, got %d", c) 503 } 504 if c := db.Refs("2"); c != 1 { 505 t.Fatalf("Expected 1 reference for db, got %d", c) 506 } 507 508 if rp := db.RefPaths("2"); len(rp) != 1 { 509 t.Fatalf("Expected 1 reference path for db, got %d", len(rp)) 510 } 511 512 count, err := db.Purge("2") 513 if err != nil { 514 t.Fatal(err) 515 } 516 517 if count != 2 { 518 t.Fatalf("Expected 2 rows to be removed, got %d", count) 519 } 520 521 if c := db.Refs("2"); c != 0 { 522 t.Fatalf("Expected 0 reference for db, got %d", c) 523 } 524 if c := db.Refs("1"); c != 1 { 525 t.Fatalf("Expected 1 reference for webapp, got %d", c) 526 } 527 } 528 529 func TestRename(t *testing.T) { 530 db, dbpath := newTestDb(t) 531 defer destroyTestDb(dbpath) 532 533 db.Set("/webapp", "1") 534 535 if db.Refs("1") != 1 { 536 t.Fatal("Expect reference count to be 1") 537 } 538 539 db.Set("/db", "2") 540 db.Set("/webapp/db", "2") 541 542 if db.Get("/webapp/db") == nil { 543 t.Fatal("Cannot find entity at path /webapp/db") 544 } 545 546 if err := db.Rename("/webapp/db", "/webapp/newdb"); err != nil { 547 t.Fatal(err) 548 } 549 if db.Get("/webapp/db") != nil { 550 t.Fatal("Entity should not exist at /webapp/db") 551 } 552 if db.Get("/webapp/newdb") == nil { 553 t.Fatal("Cannot find entity at path /webapp/newdb") 554 } 555 556 } 557 558 func TestCreateMultipleNames(t *testing.T) { 559 db, dbpath := newTestDb(t) 560 defer destroyTestDb(dbpath) 561 562 db.Set("/db", "1") 563 if _, err := db.Set("/myapp", "1"); err != nil { 564 t.Fatal(err) 565 } 566 567 db.Walk("/", func(p string, e *Entity) error { 568 t.Logf("%s\n", p) 569 return nil 570 }, -1) 571 } 572 573 func TestRefPaths(t *testing.T) { 574 db, dbpath := newTestDb(t) 575 defer destroyTestDb(dbpath) 576 577 db.Set("/webapp", "1") 578 579 db.Set("/db", "2") 580 db.Set("/webapp/db", "2") 581 582 refs := db.RefPaths("2") 583 if len(refs) != 2 { 584 t.Fatalf("Expected reference count to be 2, got %d", len(refs)) 585 } 586 } 587 588 func TestExistsTrue(t *testing.T) { 589 db, dbpath := newTestDb(t) 590 defer destroyTestDb(dbpath) 591 592 db.Set("/testing", "1") 593 594 if !db.Exists("/testing") { 595 t.Fatalf("/tesing should exist") 596 } 597 } 598 599 func TestExistsFalse(t *testing.T) { 600 db, dbpath := newTestDb(t) 601 defer destroyTestDb(dbpath) 602 603 db.Set("/toerhe", "1") 604 605 if db.Exists("/testing") { 606 t.Fatalf("/tesing should not exist") 607 } 608 609 } 610 611 func TestGetNameWithTrailingSlash(t *testing.T) { 612 db, dbpath := newTestDb(t) 613 defer destroyTestDb(dbpath) 614 615 db.Set("/todo", "1") 616 617 e := db.Get("/todo/") 618 if e == nil { 619 t.Fatalf("Entity should not be nil") 620 } 621 } 622 623 func TestConcurrentWrites(t *testing.T) { 624 db, dbpath := newTestDb(t) 625 defer destroyTestDb(dbpath) 626 627 errs := make(chan error, 2) 628 629 save := func(name string, id string) { 630 if _, err := db.Set(fmt.Sprintf("/%s", name), id); err != nil { 631 errs <- err 632 } 633 errs <- nil 634 } 635 purge := func(id string) { 636 if _, err := db.Purge(id); err != nil { 637 errs <- err 638 } 639 errs <- nil 640 } 641 642 save("/1", "1") 643 644 go purge("1") 645 go save("/2", "2") 646 647 any := false 648 for i := 0; i < 2; i++ { 649 if err := <-errs; err != nil { 650 any = true 651 t.Log(err) 652 } 653 } 654 if any { 655 t.Fail() 656 } 657 }