github.com/huiliang/nomad@v0.2.1-0.20151124023127-7a8b664699ff/nomad/state/state_store_test.go (about) 1 package state 2 3 import ( 4 "os" 5 "reflect" 6 "sort" 7 "testing" 8 9 "github.com/hashicorp/nomad/nomad/mock" 10 "github.com/hashicorp/nomad/nomad/structs" 11 "github.com/hashicorp/nomad/nomad/watch" 12 ) 13 14 func testStateStore(t *testing.T) *StateStore { 15 state, err := NewStateStore(os.Stderr) 16 if err != nil { 17 t.Fatalf("err: %v", err) 18 } 19 if state == nil { 20 t.Fatalf("missing state") 21 } 22 return state 23 } 24 25 func TestStateStore_UpsertNode_Node(t *testing.T) { 26 state := testStateStore(t) 27 node := mock.Node() 28 29 notify := setupNotifyTest( 30 state, 31 watch.Item{Table: "nodes"}, 32 watch.Item{Node: node.ID}) 33 34 err := state.UpsertNode(1000, node) 35 if err != nil { 36 t.Fatalf("err: %v", err) 37 } 38 39 out, err := state.NodeByID(node.ID) 40 if err != nil { 41 t.Fatalf("err: %v", err) 42 } 43 44 if !reflect.DeepEqual(node, out) { 45 t.Fatalf("bad: %#v %#v", node, out) 46 } 47 48 index, err := state.Index("nodes") 49 if err != nil { 50 t.Fatalf("err: %v", err) 51 } 52 if index != 1000 { 53 t.Fatalf("bad: %d", index) 54 } 55 56 notify.verify(t) 57 } 58 59 func TestStateStore_DeleteNode_Node(t *testing.T) { 60 state := testStateStore(t) 61 node := mock.Node() 62 63 notify := setupNotifyTest( 64 state, 65 watch.Item{Table: "nodes"}, 66 watch.Item{Node: node.ID}) 67 68 err := state.UpsertNode(1000, node) 69 if err != nil { 70 t.Fatalf("err: %v", err) 71 } 72 73 err = state.DeleteNode(1001, node.ID) 74 if err != nil { 75 t.Fatalf("err: %v", err) 76 } 77 78 out, err := state.NodeByID(node.ID) 79 if err != nil { 80 t.Fatalf("err: %v", err) 81 } 82 83 if out != nil { 84 t.Fatalf("bad: %#v %#v", node, out) 85 } 86 87 index, err := state.Index("nodes") 88 if err != nil { 89 t.Fatalf("err: %v", err) 90 } 91 if index != 1001 { 92 t.Fatalf("bad: %d", index) 93 } 94 95 notify.verify(t) 96 } 97 98 func TestStateStore_UpdateNodeStatus_Node(t *testing.T) { 99 state := testStateStore(t) 100 node := mock.Node() 101 102 notify := setupNotifyTest( 103 state, 104 watch.Item{Table: "nodes"}, 105 watch.Item{Node: node.ID}) 106 107 err := state.UpsertNode(1000, node) 108 if err != nil { 109 t.Fatalf("err: %v", err) 110 } 111 112 err = state.UpdateNodeStatus(1001, node.ID, structs.NodeStatusReady) 113 if err != nil { 114 t.Fatalf("err: %v", err) 115 } 116 117 out, err := state.NodeByID(node.ID) 118 if err != nil { 119 t.Fatalf("err: %v", err) 120 } 121 122 if out.Status != structs.NodeStatusReady { 123 t.Fatalf("bad: %#v", out) 124 } 125 if out.ModifyIndex != 1001 { 126 t.Fatalf("bad: %#v", out) 127 } 128 129 index, err := state.Index("nodes") 130 if err != nil { 131 t.Fatalf("err: %v", err) 132 } 133 if index != 1001 { 134 t.Fatalf("bad: %d", index) 135 } 136 137 notify.verify(t) 138 } 139 140 func TestStateStore_UpdateNodeDrain_Node(t *testing.T) { 141 state := testStateStore(t) 142 node := mock.Node() 143 144 notify := setupNotifyTest( 145 state, 146 watch.Item{Table: "nodes"}, 147 watch.Item{Node: node.ID}) 148 149 err := state.UpsertNode(1000, node) 150 if err != nil { 151 t.Fatalf("err: %v", err) 152 } 153 154 err = state.UpdateNodeDrain(1001, node.ID, true) 155 if err != nil { 156 t.Fatalf("err: %v", err) 157 } 158 159 out, err := state.NodeByID(node.ID) 160 if err != nil { 161 t.Fatalf("err: %v", err) 162 } 163 164 if !out.Drain { 165 t.Fatalf("bad: %#v", out) 166 } 167 if out.ModifyIndex != 1001 { 168 t.Fatalf("bad: %#v", out) 169 } 170 171 index, err := state.Index("nodes") 172 if err != nil { 173 t.Fatalf("err: %v", err) 174 } 175 if index != 1001 { 176 t.Fatalf("bad: %d", index) 177 } 178 179 notify.verify(t) 180 } 181 182 func TestStateStore_Nodes(t *testing.T) { 183 state := testStateStore(t) 184 var nodes []*structs.Node 185 186 for i := 0; i < 10; i++ { 187 node := mock.Node() 188 nodes = append(nodes, node) 189 190 err := state.UpsertNode(1000+uint64(i), node) 191 if err != nil { 192 t.Fatalf("err: %v", err) 193 } 194 } 195 196 iter, err := state.Nodes() 197 if err != nil { 198 t.Fatalf("err: %v", err) 199 } 200 201 var out []*structs.Node 202 for { 203 raw := iter.Next() 204 if raw == nil { 205 break 206 } 207 out = append(out, raw.(*structs.Node)) 208 } 209 210 sort.Sort(NodeIDSort(nodes)) 211 sort.Sort(NodeIDSort(out)) 212 213 if !reflect.DeepEqual(nodes, out) { 214 t.Fatalf("bad: %#v %#v", nodes, out) 215 } 216 } 217 218 func TestStateStore_RestoreNode(t *testing.T) { 219 state := testStateStore(t) 220 node := mock.Node() 221 222 notify := setupNotifyTest( 223 state, 224 watch.Item{Table: "nodes"}, 225 watch.Item{Node: node.ID}) 226 227 restore, err := state.Restore() 228 if err != nil { 229 t.Fatalf("err: %v", err) 230 } 231 232 err = restore.NodeRestore(node) 233 if err != nil { 234 t.Fatalf("err: %v", err) 235 } 236 restore.Commit() 237 238 out, err := state.NodeByID(node.ID) 239 if err != nil { 240 t.Fatalf("err: %v", err) 241 } 242 243 if !reflect.DeepEqual(out, node) { 244 t.Fatalf("Bad: %#v %#v", out, node) 245 } 246 247 notify.verify(t) 248 } 249 250 func TestStateStore_UpsertJob_Job(t *testing.T) { 251 state := testStateStore(t) 252 job := mock.Job() 253 254 notify := setupNotifyTest( 255 state, 256 watch.Item{Table: "jobs"}, 257 watch.Item{Job: job.ID}) 258 259 err := state.UpsertJob(1000, job) 260 if err != nil { 261 t.Fatalf("err: %v", err) 262 } 263 264 out, err := state.JobByID(job.ID) 265 if err != nil { 266 t.Fatalf("err: %v", err) 267 } 268 269 if !reflect.DeepEqual(job, out) { 270 t.Fatalf("bad: %#v %#v", job, out) 271 } 272 273 index, err := state.Index("jobs") 274 if err != nil { 275 t.Fatalf("err: %v", err) 276 } 277 if index != 1000 { 278 t.Fatalf("bad: %d", index) 279 } 280 281 notify.verify(t) 282 } 283 284 func TestStateStore_UpdateUpsertJob_Job(t *testing.T) { 285 state := testStateStore(t) 286 job := mock.Job() 287 288 notify := setupNotifyTest( 289 state, 290 watch.Item{Table: "jobs"}, 291 watch.Item{Job: job.ID}) 292 293 err := state.UpsertJob(1000, job) 294 if err != nil { 295 t.Fatalf("err: %v", err) 296 } 297 298 job2 := mock.Job() 299 job2.ID = job.ID 300 err = state.UpsertJob(1001, job2) 301 if err != nil { 302 t.Fatalf("err: %v", err) 303 } 304 305 out, err := state.JobByID(job.ID) 306 if err != nil { 307 t.Fatalf("err: %v", err) 308 } 309 310 if !reflect.DeepEqual(job2, out) { 311 t.Fatalf("bad: %#v %#v", job2, out) 312 } 313 314 if out.CreateIndex != 1000 { 315 t.Fatalf("bad: %#v", out) 316 } 317 if out.ModifyIndex != 1001 { 318 t.Fatalf("bad: %#v", out) 319 } 320 321 index, err := state.Index("jobs") 322 if err != nil { 323 t.Fatalf("err: %v", err) 324 } 325 if index != 1001 { 326 t.Fatalf("bad: %d", index) 327 } 328 329 notify.verify(t) 330 } 331 332 func TestStateStore_DeleteJob_Job(t *testing.T) { 333 state := testStateStore(t) 334 job := mock.Job() 335 336 notify := setupNotifyTest( 337 state, 338 watch.Item{Table: "jobs"}, 339 watch.Item{Job: job.ID}) 340 341 err := state.UpsertJob(1000, job) 342 if err != nil { 343 t.Fatalf("err: %v", err) 344 } 345 346 err = state.DeleteJob(1001, job.ID) 347 if err != nil { 348 t.Fatalf("err: %v", err) 349 } 350 351 out, err := state.JobByID(job.ID) 352 if err != nil { 353 t.Fatalf("err: %v", err) 354 } 355 356 if out != nil { 357 t.Fatalf("bad: %#v %#v", job, out) 358 } 359 360 index, err := state.Index("jobs") 361 if err != nil { 362 t.Fatalf("err: %v", err) 363 } 364 if index != 1001 { 365 t.Fatalf("bad: %d", index) 366 } 367 368 notify.verify(t) 369 } 370 371 func TestStateStore_Jobs(t *testing.T) { 372 state := testStateStore(t) 373 var jobs []*structs.Job 374 375 for i := 0; i < 10; i++ { 376 job := mock.Job() 377 jobs = append(jobs, job) 378 379 err := state.UpsertJob(1000+uint64(i), job) 380 if err != nil { 381 t.Fatalf("err: %v", err) 382 } 383 } 384 385 iter, err := state.Jobs() 386 if err != nil { 387 t.Fatalf("err: %v", err) 388 } 389 390 var out []*structs.Job 391 for { 392 raw := iter.Next() 393 if raw == nil { 394 break 395 } 396 out = append(out, raw.(*structs.Job)) 397 } 398 399 sort.Sort(JobIDSort(jobs)) 400 sort.Sort(JobIDSort(out)) 401 402 if !reflect.DeepEqual(jobs, out) { 403 t.Fatalf("bad: %#v %#v", jobs, out) 404 } 405 } 406 407 func TestStateStore_JobsByScheduler(t *testing.T) { 408 state := testStateStore(t) 409 var serviceJobs []*structs.Job 410 var sysJobs []*structs.Job 411 412 for i := 0; i < 10; i++ { 413 job := mock.Job() 414 serviceJobs = append(serviceJobs, job) 415 416 err := state.UpsertJob(1000+uint64(i), job) 417 if err != nil { 418 t.Fatalf("err: %v", err) 419 } 420 } 421 422 for i := 0; i < 10; i++ { 423 job := mock.SystemJob() 424 sysJobs = append(sysJobs, job) 425 426 err := state.UpsertJob(2000+uint64(i), job) 427 if err != nil { 428 t.Fatalf("err: %v", err) 429 } 430 } 431 432 iter, err := state.JobsByScheduler("service") 433 if err != nil { 434 t.Fatalf("err: %v", err) 435 } 436 437 var outService []*structs.Job 438 for { 439 raw := iter.Next() 440 if raw == nil { 441 break 442 } 443 outService = append(outService, raw.(*structs.Job)) 444 } 445 446 iter, err = state.JobsByScheduler("system") 447 if err != nil { 448 t.Fatalf("err: %v", err) 449 } 450 451 var outSystem []*structs.Job 452 for { 453 raw := iter.Next() 454 if raw == nil { 455 break 456 } 457 outSystem = append(outSystem, raw.(*structs.Job)) 458 } 459 460 sort.Sort(JobIDSort(serviceJobs)) 461 sort.Sort(JobIDSort(sysJobs)) 462 sort.Sort(JobIDSort(outService)) 463 sort.Sort(JobIDSort(outSystem)) 464 465 if !reflect.DeepEqual(serviceJobs, outService) { 466 t.Fatalf("bad: %#v %#v", serviceJobs, outService) 467 } 468 469 if !reflect.DeepEqual(sysJobs, outSystem) { 470 t.Fatalf("bad: %#v %#v", sysJobs, outSystem) 471 } 472 } 473 474 func TestStateStore_RestoreJob(t *testing.T) { 475 state := testStateStore(t) 476 job := mock.Job() 477 478 notify := setupNotifyTest( 479 state, 480 watch.Item{Table: "jobs"}, 481 watch.Item{Job: job.ID}) 482 483 restore, err := state.Restore() 484 if err != nil { 485 t.Fatalf("err: %v", err) 486 } 487 488 err = restore.JobRestore(job) 489 if err != nil { 490 t.Fatalf("err: %v", err) 491 } 492 restore.Commit() 493 494 out, err := state.JobByID(job.ID) 495 if err != nil { 496 t.Fatalf("err: %v", err) 497 } 498 499 if !reflect.DeepEqual(out, job) { 500 t.Fatalf("Bad: %#v %#v", out, job) 501 } 502 503 notify.verify(t) 504 } 505 506 func TestStateStore_Indexes(t *testing.T) { 507 state := testStateStore(t) 508 node := mock.Node() 509 510 err := state.UpsertNode(1000, node) 511 if err != nil { 512 t.Fatalf("err: %v", err) 513 } 514 515 iter, err := state.Indexes() 516 if err != nil { 517 t.Fatalf("err: %v", err) 518 } 519 520 var out []*IndexEntry 521 for { 522 raw := iter.Next() 523 if raw == nil { 524 break 525 } 526 out = append(out, raw.(*IndexEntry)) 527 } 528 529 expect := []*IndexEntry{ 530 &IndexEntry{"nodes", 1000}, 531 } 532 533 if !reflect.DeepEqual(expect, out) { 534 t.Fatalf("bad: %#v %#v", expect, out) 535 } 536 } 537 538 func TestStateStore_RestoreIndex(t *testing.T) { 539 state := testStateStore(t) 540 541 restore, err := state.Restore() 542 if err != nil { 543 t.Fatalf("err: %v", err) 544 } 545 546 index := &IndexEntry{"jobs", 1000} 547 err = restore.IndexRestore(index) 548 if err != nil { 549 t.Fatalf("err: %v", err) 550 } 551 552 restore.Commit() 553 554 out, err := state.Index("jobs") 555 if err != nil { 556 t.Fatalf("err: %v", err) 557 } 558 559 if out != 1000 { 560 t.Fatalf("Bad: %#v %#v", out, 1000) 561 } 562 } 563 564 func TestStateStore_UpsertEvals_Eval(t *testing.T) { 565 state := testStateStore(t) 566 eval := mock.Eval() 567 568 notify := setupNotifyTest( 569 state, 570 watch.Item{Table: "evals"}, 571 watch.Item{Eval: eval.ID}) 572 573 err := state.UpsertEvals(1000, []*structs.Evaluation{eval}) 574 if err != nil { 575 t.Fatalf("err: %v", err) 576 } 577 578 out, err := state.EvalByID(eval.ID) 579 if err != nil { 580 t.Fatalf("err: %v", err) 581 } 582 583 if !reflect.DeepEqual(eval, out) { 584 t.Fatalf("bad: %#v %#v", eval, out) 585 } 586 587 index, err := state.Index("evals") 588 if err != nil { 589 t.Fatalf("err: %v", err) 590 } 591 if index != 1000 { 592 t.Fatalf("bad: %d", index) 593 } 594 595 notify.verify(t) 596 } 597 598 func TestStateStore_Update_UpsertEvals_Eval(t *testing.T) { 599 state := testStateStore(t) 600 eval := mock.Eval() 601 602 err := state.UpsertEvals(1000, []*structs.Evaluation{eval}) 603 if err != nil { 604 t.Fatalf("err: %v", err) 605 } 606 607 notify := setupNotifyTest( 608 state, 609 watch.Item{Table: "evals"}, 610 watch.Item{Eval: eval.ID}) 611 612 eval2 := mock.Eval() 613 eval2.ID = eval.ID 614 err = state.UpsertEvals(1001, []*structs.Evaluation{eval2}) 615 if err != nil { 616 t.Fatalf("err: %v", err) 617 } 618 619 out, err := state.EvalByID(eval.ID) 620 if err != nil { 621 t.Fatalf("err: %v", err) 622 } 623 624 if !reflect.DeepEqual(eval2, out) { 625 t.Fatalf("bad: %#v %#v", eval2, out) 626 } 627 628 if out.CreateIndex != 1000 { 629 t.Fatalf("bad: %#v", out) 630 } 631 if out.ModifyIndex != 1001 { 632 t.Fatalf("bad: %#v", out) 633 } 634 635 index, err := state.Index("evals") 636 if err != nil { 637 t.Fatalf("err: %v", err) 638 } 639 if index != 1001 { 640 t.Fatalf("bad: %d", index) 641 } 642 643 notify.verify(t) 644 } 645 646 func TestStateStore_DeleteEval_Eval(t *testing.T) { 647 state := testStateStore(t) 648 eval1 := mock.Eval() 649 eval2 := mock.Eval() 650 alloc1 := mock.Alloc() 651 alloc2 := mock.Alloc() 652 653 notify := setupNotifyTest( 654 state, 655 watch.Item{Table: "evals"}, 656 watch.Item{Table: "allocs"}, 657 watch.Item{Eval: eval1.ID}, 658 watch.Item{Eval: eval2.ID}, 659 watch.Item{Alloc: alloc1.ID}, 660 watch.Item{Alloc: alloc2.ID}, 661 watch.Item{AllocEval: alloc1.EvalID}, 662 watch.Item{AllocEval: alloc2.EvalID}, 663 watch.Item{AllocJob: alloc1.JobID}, 664 watch.Item{AllocJob: alloc2.JobID}, 665 watch.Item{AllocNode: alloc1.NodeID}, 666 watch.Item{AllocNode: alloc2.NodeID}) 667 668 err := state.UpsertEvals(1000, []*structs.Evaluation{eval1, eval2}) 669 if err != nil { 670 t.Fatalf("err: %v", err) 671 } 672 673 err = state.UpsertAllocs(1001, []*structs.Allocation{alloc1, alloc2}) 674 if err != nil { 675 t.Fatalf("err: %v", err) 676 } 677 678 err = state.DeleteEval(1002, []string{eval1.ID, eval2.ID}, []string{alloc1.ID, alloc2.ID}) 679 if err != nil { 680 t.Fatalf("err: %v", err) 681 } 682 683 out, err := state.EvalByID(eval1.ID) 684 if err != nil { 685 t.Fatalf("err: %v", err) 686 } 687 688 if out != nil { 689 t.Fatalf("bad: %#v %#v", eval1, out) 690 } 691 692 out, err = state.EvalByID(eval2.ID) 693 if err != nil { 694 t.Fatalf("err: %v", err) 695 } 696 697 if out != nil { 698 t.Fatalf("bad: %#v %#v", eval1, out) 699 } 700 701 outA, err := state.AllocByID(alloc1.ID) 702 if err != nil { 703 t.Fatalf("err: %v", err) 704 } 705 706 if out != nil { 707 t.Fatalf("bad: %#v %#v", alloc1, outA) 708 } 709 710 outA, err = state.AllocByID(alloc2.ID) 711 if err != nil { 712 t.Fatalf("err: %v", err) 713 } 714 715 if out != nil { 716 t.Fatalf("bad: %#v %#v", alloc1, outA) 717 } 718 719 index, err := state.Index("evals") 720 if err != nil { 721 t.Fatalf("err: %v", err) 722 } 723 if index != 1002 { 724 t.Fatalf("bad: %d", index) 725 } 726 727 index, err = state.Index("allocs") 728 if err != nil { 729 t.Fatalf("err: %v", err) 730 } 731 if index != 1002 { 732 t.Fatalf("bad: %d", index) 733 } 734 735 notify.verify(t) 736 } 737 738 func TestStateStore_EvalsByJob(t *testing.T) { 739 state := testStateStore(t) 740 741 eval1 := mock.Eval() 742 eval2 := mock.Eval() 743 eval2.JobID = eval1.JobID 744 eval3 := mock.Eval() 745 evals := []*structs.Evaluation{eval1, eval2} 746 747 err := state.UpsertEvals(1000, evals) 748 if err != nil { 749 t.Fatalf("err: %v", err) 750 } 751 err = state.UpsertEvals(1001, []*structs.Evaluation{eval3}) 752 if err != nil { 753 t.Fatalf("err: %v", err) 754 } 755 756 out, err := state.EvalsByJob(eval1.JobID) 757 if err != nil { 758 t.Fatalf("err: %v", err) 759 } 760 761 sort.Sort(EvalIDSort(evals)) 762 sort.Sort(EvalIDSort(out)) 763 764 if !reflect.DeepEqual(evals, out) { 765 t.Fatalf("bad: %#v %#v", evals, out) 766 } 767 } 768 769 func TestStateStore_Evals(t *testing.T) { 770 state := testStateStore(t) 771 var evals []*structs.Evaluation 772 773 for i := 0; i < 10; i++ { 774 eval := mock.Eval() 775 evals = append(evals, eval) 776 777 err := state.UpsertEvals(1000+uint64(i), []*structs.Evaluation{eval}) 778 if err != nil { 779 t.Fatalf("err: %v", err) 780 } 781 } 782 783 iter, err := state.Evals() 784 if err != nil { 785 t.Fatalf("err: %v", err) 786 } 787 788 var out []*structs.Evaluation 789 for { 790 raw := iter.Next() 791 if raw == nil { 792 break 793 } 794 out = append(out, raw.(*structs.Evaluation)) 795 } 796 797 sort.Sort(EvalIDSort(evals)) 798 sort.Sort(EvalIDSort(out)) 799 800 if !reflect.DeepEqual(evals, out) { 801 t.Fatalf("bad: %#v %#v", evals, out) 802 } 803 } 804 805 func TestStateStore_RestoreEval(t *testing.T) { 806 state := testStateStore(t) 807 eval := mock.Eval() 808 809 notify := setupNotifyTest( 810 state, 811 watch.Item{Table: "evals"}, 812 watch.Item{Eval: eval.ID}) 813 814 restore, err := state.Restore() 815 if err != nil { 816 t.Fatalf("err: %v", err) 817 } 818 819 err = restore.EvalRestore(eval) 820 if err != nil { 821 t.Fatalf("err: %v", err) 822 } 823 restore.Commit() 824 825 out, err := state.EvalByID(eval.ID) 826 if err != nil { 827 t.Fatalf("err: %v", err) 828 } 829 830 if !reflect.DeepEqual(out, eval) { 831 t.Fatalf("Bad: %#v %#v", out, eval) 832 } 833 834 notify.verify(t) 835 } 836 837 func TestStateStore_UpdateAllocFromClient(t *testing.T) { 838 state := testStateStore(t) 839 alloc := mock.Alloc() 840 841 notify := setupNotifyTest( 842 state, 843 watch.Item{Table: "allocs"}, 844 watch.Item{Alloc: alloc.ID}, 845 watch.Item{AllocEval: alloc.EvalID}, 846 watch.Item{AllocJob: alloc.JobID}, 847 watch.Item{AllocNode: alloc.NodeID}) 848 849 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}) 850 if err != nil { 851 t.Fatalf("err: %v", err) 852 } 853 854 update := new(structs.Allocation) 855 *update = *alloc 856 update.ClientStatus = structs.AllocClientStatusFailed 857 858 err = state.UpdateAllocFromClient(1001, update) 859 if err != nil { 860 t.Fatalf("err: %v", err) 861 } 862 863 out, err := state.AllocByID(alloc.ID) 864 if err != nil { 865 t.Fatalf("err: %v", err) 866 } 867 868 update.ModifyIndex = 1001 869 if !reflect.DeepEqual(update, out) { 870 t.Fatalf("bad: %#v %#v", update, out) 871 } 872 873 index, err := state.Index("allocs") 874 if err != nil { 875 t.Fatalf("err: %v", err) 876 } 877 if index != 1001 { 878 t.Fatalf("bad: %d", index) 879 } 880 881 notify.verify(t) 882 } 883 884 func TestStateStore_UpsertAlloc_Alloc(t *testing.T) { 885 state := testStateStore(t) 886 alloc := mock.Alloc() 887 888 notify := setupNotifyTest( 889 state, 890 watch.Item{Table: "allocs"}, 891 watch.Item{Alloc: alloc.ID}, 892 watch.Item{AllocEval: alloc.EvalID}, 893 watch.Item{AllocJob: alloc.JobID}, 894 watch.Item{AllocNode: alloc.NodeID}) 895 896 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}) 897 if err != nil { 898 t.Fatalf("err: %v", err) 899 } 900 901 out, err := state.AllocByID(alloc.ID) 902 if err != nil { 903 t.Fatalf("err: %v", err) 904 } 905 906 if !reflect.DeepEqual(alloc, out) { 907 t.Fatalf("bad: %#v %#v", alloc, out) 908 } 909 910 index, err := state.Index("allocs") 911 if err != nil { 912 t.Fatalf("err: %v", err) 913 } 914 if index != 1000 { 915 t.Fatalf("bad: %d", index) 916 } 917 918 notify.verify(t) 919 } 920 921 func TestStateStore_UpdateAlloc_Alloc(t *testing.T) { 922 state := testStateStore(t) 923 alloc := mock.Alloc() 924 925 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}) 926 if err != nil { 927 t.Fatalf("err: %v", err) 928 } 929 930 alloc2 := mock.Alloc() 931 alloc2.ID = alloc.ID 932 alloc2.NodeID = alloc.NodeID + ".new" 933 934 notify := setupNotifyTest( 935 state, 936 watch.Item{Table: "allocs"}, 937 watch.Item{Alloc: alloc2.ID}, 938 watch.Item{AllocEval: alloc2.EvalID}, 939 watch.Item{AllocJob: alloc2.JobID}, 940 watch.Item{AllocNode: alloc2.NodeID}) 941 942 err = state.UpsertAllocs(1001, []*structs.Allocation{alloc2}) 943 if err != nil { 944 t.Fatalf("err: %v", err) 945 } 946 947 out, err := state.AllocByID(alloc.ID) 948 if err != nil { 949 t.Fatalf("err: %v", err) 950 } 951 952 if !reflect.DeepEqual(alloc2, out) { 953 t.Fatalf("bad: %#v %#v", alloc2, out) 954 } 955 956 if out.CreateIndex != 1000 { 957 t.Fatalf("bad: %#v", out) 958 } 959 if out.ModifyIndex != 1001 { 960 t.Fatalf("bad: %#v", out) 961 } 962 963 index, err := state.Index("allocs") 964 if err != nil { 965 t.Fatalf("err: %v", err) 966 } 967 if index != 1001 { 968 t.Fatalf("bad: %d", index) 969 } 970 971 notify.verify(t) 972 } 973 974 func TestStateStore_EvictAlloc_Alloc(t *testing.T) { 975 state := testStateStore(t) 976 alloc := mock.Alloc() 977 978 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}) 979 if err != nil { 980 t.Fatalf("err: %v", err) 981 } 982 983 alloc2 := new(structs.Allocation) 984 *alloc2 = *alloc 985 alloc2.DesiredStatus = structs.AllocDesiredStatusEvict 986 err = state.UpsertAllocs(1001, []*structs.Allocation{alloc2}) 987 if err != nil { 988 t.Fatalf("err: %v", err) 989 } 990 991 out, err := state.AllocByID(alloc.ID) 992 if err != nil { 993 t.Fatalf("err: %v", err) 994 } 995 996 if out.DesiredStatus != structs.AllocDesiredStatusEvict { 997 t.Fatalf("bad: %#v %#v", alloc, out) 998 } 999 1000 index, err := state.Index("allocs") 1001 if err != nil { 1002 t.Fatalf("err: %v", err) 1003 } 1004 if index != 1001 { 1005 t.Fatalf("bad: %d", index) 1006 } 1007 } 1008 1009 func TestStateStore_AllocsByNode(t *testing.T) { 1010 state := testStateStore(t) 1011 var allocs []*structs.Allocation 1012 1013 for i := 0; i < 10; i++ { 1014 alloc := mock.Alloc() 1015 alloc.NodeID = "foo" 1016 allocs = append(allocs, alloc) 1017 } 1018 1019 err := state.UpsertAllocs(1000, allocs) 1020 if err != nil { 1021 t.Fatalf("err: %v", err) 1022 } 1023 1024 out, err := state.AllocsByNode("foo") 1025 if err != nil { 1026 t.Fatalf("err: %v", err) 1027 } 1028 1029 sort.Sort(AllocIDSort(allocs)) 1030 sort.Sort(AllocIDSort(out)) 1031 1032 if !reflect.DeepEqual(allocs, out) { 1033 t.Fatalf("bad: %#v %#v", allocs, out) 1034 } 1035 } 1036 1037 func TestStateStore_AllocsByJob(t *testing.T) { 1038 state := testStateStore(t) 1039 var allocs []*structs.Allocation 1040 1041 for i := 0; i < 10; i++ { 1042 alloc := mock.Alloc() 1043 alloc.JobID = "foo" 1044 allocs = append(allocs, alloc) 1045 } 1046 1047 err := state.UpsertAllocs(1000, allocs) 1048 if err != nil { 1049 t.Fatalf("err: %v", err) 1050 } 1051 1052 out, err := state.AllocsByJob("foo") 1053 if err != nil { 1054 t.Fatalf("err: %v", err) 1055 } 1056 1057 sort.Sort(AllocIDSort(allocs)) 1058 sort.Sort(AllocIDSort(out)) 1059 1060 if !reflect.DeepEqual(allocs, out) { 1061 t.Fatalf("bad: %#v %#v", allocs, out) 1062 } 1063 } 1064 1065 func TestStateStore_Allocs(t *testing.T) { 1066 state := testStateStore(t) 1067 var allocs []*structs.Allocation 1068 1069 for i := 0; i < 10; i++ { 1070 alloc := mock.Alloc() 1071 allocs = append(allocs, alloc) 1072 } 1073 1074 err := state.UpsertAllocs(1000, allocs) 1075 if err != nil { 1076 t.Fatalf("err: %v", err) 1077 } 1078 1079 iter, err := state.Allocs() 1080 if err != nil { 1081 t.Fatalf("err: %v", err) 1082 } 1083 1084 var out []*structs.Allocation 1085 for { 1086 raw := iter.Next() 1087 if raw == nil { 1088 break 1089 } 1090 out = append(out, raw.(*structs.Allocation)) 1091 } 1092 1093 sort.Sort(AllocIDSort(allocs)) 1094 sort.Sort(AllocIDSort(out)) 1095 1096 if !reflect.DeepEqual(allocs, out) { 1097 t.Fatalf("bad: %#v %#v", allocs, out) 1098 } 1099 } 1100 1101 func TestStateStore_RestoreAlloc(t *testing.T) { 1102 state := testStateStore(t) 1103 alloc := mock.Alloc() 1104 1105 notify := setupNotifyTest( 1106 state, 1107 watch.Item{Table: "allocs"}, 1108 watch.Item{Alloc: alloc.ID}, 1109 watch.Item{AllocEval: alloc.EvalID}, 1110 watch.Item{AllocJob: alloc.JobID}, 1111 watch.Item{AllocNode: alloc.NodeID}) 1112 1113 restore, err := state.Restore() 1114 if err != nil { 1115 t.Fatalf("err: %v", err) 1116 } 1117 1118 err = restore.AllocRestore(alloc) 1119 if err != nil { 1120 t.Fatalf("err: %v", err) 1121 } 1122 1123 restore.Commit() 1124 1125 out, err := state.AllocByID(alloc.ID) 1126 if err != nil { 1127 t.Fatalf("err: %v", err) 1128 } 1129 1130 if !reflect.DeepEqual(out, alloc) { 1131 t.Fatalf("Bad: %#v %#v", out, alloc) 1132 } 1133 1134 notify.verify(t) 1135 } 1136 1137 func TestStateWatch_watch(t *testing.T) { 1138 sw := newStateWatch() 1139 notify1 := make(chan struct{}, 1) 1140 notify2 := make(chan struct{}, 1) 1141 notify3 := make(chan struct{}, 1) 1142 1143 // Notifications trigger subscribed channels 1144 sw.watch(watch.NewItems(watch.Item{Table: "foo"}), notify1) 1145 sw.watch(watch.NewItems(watch.Item{Table: "bar"}), notify2) 1146 sw.watch(watch.NewItems(watch.Item{Table: "baz"}), notify3) 1147 1148 items := watch.NewItems() 1149 items.Add(watch.Item{Table: "foo"}) 1150 items.Add(watch.Item{Table: "bar"}) 1151 1152 sw.notify(items) 1153 if len(notify1) != 1 { 1154 t.Fatalf("should notify") 1155 } 1156 if len(notify2) != 1 { 1157 t.Fatalf("should notify") 1158 } 1159 if len(notify3) != 0 { 1160 t.Fatalf("should not notify") 1161 } 1162 } 1163 1164 func TestStateWatch_stopWatch(t *testing.T) { 1165 sw := newStateWatch() 1166 notify := make(chan struct{}) 1167 1168 // First subscribe 1169 sw.watch(watch.NewItems(watch.Item{Table: "foo"}), notify) 1170 1171 // Unsubscribe stop notifications 1172 sw.stopWatch(watch.NewItems(watch.Item{Table: "foo"}), notify) 1173 1174 // Check that the group was removed 1175 if _, ok := sw.items[watch.Item{Table: "foo"}]; ok { 1176 t.Fatalf("should remove group") 1177 } 1178 1179 // Check that we are not notified 1180 sw.notify(watch.NewItems(watch.Item{Table: "foo"})) 1181 if len(notify) != 0 { 1182 t.Fatalf("should not notify") 1183 } 1184 } 1185 1186 // setupNotifyTest takes a state store and a set of watch items, then creates 1187 // and subscribes a notification channel for each item. 1188 func setupNotifyTest(state *StateStore, items ...watch.Item) notifyTest { 1189 var n notifyTest 1190 for _, item := range items { 1191 ch := make(chan struct{}, 1) 1192 state.Watch(watch.NewItems(item), ch) 1193 n = append(n, ¬ifyTestCase{item, ch}) 1194 } 1195 return n 1196 } 1197 1198 // notifyTestCase is used to set up and verify watch triggers. 1199 type notifyTestCase struct { 1200 item watch.Item 1201 ch chan struct{} 1202 } 1203 1204 // notifyTest is a suite of notifyTestCases. 1205 type notifyTest []*notifyTestCase 1206 1207 // verify ensures that each channel received a notification. 1208 func (n notifyTest) verify(t *testing.T) { 1209 for _, tcase := range n { 1210 if len(tcase.ch) != 1 { 1211 t.Fatalf("should notify %#v", tcase.item) 1212 } 1213 } 1214 } 1215 1216 // NodeIDSort is used to sort nodes by ID 1217 type NodeIDSort []*structs.Node 1218 1219 func (n NodeIDSort) Len() int { 1220 return len(n) 1221 } 1222 1223 func (n NodeIDSort) Less(i, j int) bool { 1224 return n[i].ID < n[j].ID 1225 } 1226 1227 func (n NodeIDSort) Swap(i, j int) { 1228 n[i], n[j] = n[j], n[i] 1229 } 1230 1231 // JobIDis used to sort jobs by id 1232 type JobIDSort []*structs.Job 1233 1234 func (n JobIDSort) Len() int { 1235 return len(n) 1236 } 1237 1238 func (n JobIDSort) Less(i, j int) bool { 1239 return n[i].ID < n[j].ID 1240 } 1241 1242 func (n JobIDSort) Swap(i, j int) { 1243 n[i], n[j] = n[j], n[i] 1244 } 1245 1246 // EvalIDis used to sort evals by id 1247 type EvalIDSort []*structs.Evaluation 1248 1249 func (n EvalIDSort) Len() int { 1250 return len(n) 1251 } 1252 1253 func (n EvalIDSort) Less(i, j int) bool { 1254 return n[i].ID < n[j].ID 1255 } 1256 1257 func (n EvalIDSort) Swap(i, j int) { 1258 n[i], n[j] = n[j], n[i] 1259 } 1260 1261 // AllocIDsort used to sort allocations by id 1262 type AllocIDSort []*structs.Allocation 1263 1264 func (n AllocIDSort) Len() int { 1265 return len(n) 1266 } 1267 1268 func (n AllocIDSort) Less(i, j int) bool { 1269 return n[i].ID < n[j].ID 1270 } 1271 1272 func (n AllocIDSort) Swap(i, j int) { 1273 n[i], n[j] = n[j], n[i] 1274 }