github.com/ranjib/nomad@v0.1.1-0.20160225204057-97751b02f70b/nomad/state/state_store_test.go (about) 1 package state 2 3 import ( 4 "os" 5 "reflect" 6 "sort" 7 "testing" 8 "time" 9 10 "github.com/hashicorp/go-memdb" 11 "github.com/hashicorp/nomad/nomad/mock" 12 "github.com/hashicorp/nomad/nomad/structs" 13 "github.com/hashicorp/nomad/nomad/watch" 14 ) 15 16 func testStateStore(t *testing.T) *StateStore { 17 state, err := NewStateStore(os.Stderr) 18 if err != nil { 19 t.Fatalf("err: %v", err) 20 } 21 if state == nil { 22 t.Fatalf("missing state") 23 } 24 return state 25 } 26 27 func TestStateStore_UpsertNode_Node(t *testing.T) { 28 state := testStateStore(t) 29 node := mock.Node() 30 31 notify := setupNotifyTest( 32 state, 33 watch.Item{Table: "nodes"}, 34 watch.Item{Node: node.ID}) 35 36 err := state.UpsertNode(1000, node) 37 if err != nil { 38 t.Fatalf("err: %v", err) 39 } 40 41 out, err := state.NodeByID(node.ID) 42 if err != nil { 43 t.Fatalf("err: %v", err) 44 } 45 46 if !reflect.DeepEqual(node, out) { 47 t.Fatalf("bad: %#v %#v", node, out) 48 } 49 50 index, err := state.Index("nodes") 51 if err != nil { 52 t.Fatalf("err: %v", err) 53 } 54 if index != 1000 { 55 t.Fatalf("bad: %d", index) 56 } 57 58 notify.verify(t) 59 } 60 61 func TestStateStore_DeleteNode_Node(t *testing.T) { 62 state := testStateStore(t) 63 node := mock.Node() 64 65 notify := setupNotifyTest( 66 state, 67 watch.Item{Table: "nodes"}, 68 watch.Item{Node: node.ID}) 69 70 err := state.UpsertNode(1000, node) 71 if err != nil { 72 t.Fatalf("err: %v", err) 73 } 74 75 err = state.DeleteNode(1001, node.ID) 76 if err != nil { 77 t.Fatalf("err: %v", err) 78 } 79 80 out, err := state.NodeByID(node.ID) 81 if err != nil { 82 t.Fatalf("err: %v", err) 83 } 84 85 if out != nil { 86 t.Fatalf("bad: %#v %#v", node, out) 87 } 88 89 index, err := state.Index("nodes") 90 if err != nil { 91 t.Fatalf("err: %v", err) 92 } 93 if index != 1001 { 94 t.Fatalf("bad: %d", index) 95 } 96 97 notify.verify(t) 98 } 99 100 func TestStateStore_UpdateNodeStatus_Node(t *testing.T) { 101 state := testStateStore(t) 102 node := mock.Node() 103 104 notify := setupNotifyTest( 105 state, 106 watch.Item{Table: "nodes"}, 107 watch.Item{Node: node.ID}) 108 109 err := state.UpsertNode(1000, node) 110 if err != nil { 111 t.Fatalf("err: %v", err) 112 } 113 114 err = state.UpdateNodeStatus(1001, node.ID, structs.NodeStatusReady) 115 if err != nil { 116 t.Fatalf("err: %v", err) 117 } 118 119 out, err := state.NodeByID(node.ID) 120 if err != nil { 121 t.Fatalf("err: %v", err) 122 } 123 124 if out.Status != structs.NodeStatusReady { 125 t.Fatalf("bad: %#v", out) 126 } 127 if out.ModifyIndex != 1001 { 128 t.Fatalf("bad: %#v", out) 129 } 130 131 index, err := state.Index("nodes") 132 if err != nil { 133 t.Fatalf("err: %v", err) 134 } 135 if index != 1001 { 136 t.Fatalf("bad: %d", index) 137 } 138 139 notify.verify(t) 140 } 141 142 func TestStateStore_UpdateNodeDrain_Node(t *testing.T) { 143 state := testStateStore(t) 144 node := mock.Node() 145 146 notify := setupNotifyTest( 147 state, 148 watch.Item{Table: "nodes"}, 149 watch.Item{Node: node.ID}) 150 151 err := state.UpsertNode(1000, node) 152 if err != nil { 153 t.Fatalf("err: %v", err) 154 } 155 156 err = state.UpdateNodeDrain(1001, node.ID, true) 157 if err != nil { 158 t.Fatalf("err: %v", err) 159 } 160 161 out, err := state.NodeByID(node.ID) 162 if err != nil { 163 t.Fatalf("err: %v", err) 164 } 165 166 if !out.Drain { 167 t.Fatalf("bad: %#v", out) 168 } 169 if out.ModifyIndex != 1001 { 170 t.Fatalf("bad: %#v", out) 171 } 172 173 index, err := state.Index("nodes") 174 if err != nil { 175 t.Fatalf("err: %v", err) 176 } 177 if index != 1001 { 178 t.Fatalf("bad: %d", index) 179 } 180 181 notify.verify(t) 182 } 183 184 func TestStateStore_Nodes(t *testing.T) { 185 state := testStateStore(t) 186 var nodes []*structs.Node 187 188 for i := 0; i < 10; i++ { 189 node := mock.Node() 190 nodes = append(nodes, node) 191 192 err := state.UpsertNode(1000+uint64(i), node) 193 if err != nil { 194 t.Fatalf("err: %v", err) 195 } 196 } 197 198 iter, err := state.Nodes() 199 if err != nil { 200 t.Fatalf("err: %v", err) 201 } 202 203 var out []*structs.Node 204 for { 205 raw := iter.Next() 206 if raw == nil { 207 break 208 } 209 out = append(out, raw.(*structs.Node)) 210 } 211 212 sort.Sort(NodeIDSort(nodes)) 213 sort.Sort(NodeIDSort(out)) 214 215 if !reflect.DeepEqual(nodes, out) { 216 t.Fatalf("bad: %#v %#v", nodes, out) 217 } 218 } 219 220 func TestStateStore_NodesByIDPrefix(t *testing.T) { 221 state := testStateStore(t) 222 node := mock.Node() 223 224 node.ID = "11111111-662e-d0ab-d1c9-3e434af7bdb4" 225 err := state.UpsertNode(1000, node) 226 if err != nil { 227 t.Fatalf("err: %v", err) 228 } 229 230 iter, err := state.NodesByIDPrefix(node.ID) 231 if err != nil { 232 t.Fatalf("err: %v", err) 233 } 234 235 gatherNodes := func(iter memdb.ResultIterator) []*structs.Node { 236 var nodes []*structs.Node 237 for { 238 raw := iter.Next() 239 if raw == nil { 240 break 241 } 242 node := raw.(*structs.Node) 243 nodes = append(nodes, node) 244 } 245 return nodes 246 } 247 248 nodes := gatherNodes(iter) 249 if len(nodes) != 1 { 250 t.Fatalf("err: %v", err) 251 } 252 253 iter, err = state.NodesByIDPrefix("11") 254 if err != nil { 255 t.Fatalf("err: %v", err) 256 } 257 258 nodes = gatherNodes(iter) 259 if len(nodes) != 1 { 260 t.Fatalf("err: %v", err) 261 } 262 263 node = mock.Node() 264 node.ID = "11222222-662e-d0ab-d1c9-3e434af7bdb4" 265 err = state.UpsertNode(1001, node) 266 if err != nil { 267 t.Fatalf("err: %v", err) 268 } 269 270 iter, err = state.NodesByIDPrefix("11") 271 if err != nil { 272 t.Fatalf("err: %v", err) 273 } 274 275 nodes = gatherNodes(iter) 276 if len(nodes) != 2 { 277 t.Fatalf("err: %v", err) 278 } 279 280 iter, err = state.NodesByIDPrefix("1111") 281 if err != nil { 282 t.Fatalf("err: %v", err) 283 } 284 285 nodes = gatherNodes(iter) 286 if len(nodes) != 1 { 287 t.Fatalf("err: %v", err) 288 } 289 } 290 291 func TestStateStore_RestoreNode(t *testing.T) { 292 state := testStateStore(t) 293 node := mock.Node() 294 295 notify := setupNotifyTest( 296 state, 297 watch.Item{Table: "nodes"}, 298 watch.Item{Node: node.ID}) 299 300 restore, err := state.Restore() 301 if err != nil { 302 t.Fatalf("err: %v", err) 303 } 304 305 err = restore.NodeRestore(node) 306 if err != nil { 307 t.Fatalf("err: %v", err) 308 } 309 restore.Commit() 310 311 out, err := state.NodeByID(node.ID) 312 if err != nil { 313 t.Fatalf("err: %v", err) 314 } 315 316 if !reflect.DeepEqual(out, node) { 317 t.Fatalf("Bad: %#v %#v", out, node) 318 } 319 320 notify.verify(t) 321 } 322 323 func TestStateStore_UpsertJob_Job(t *testing.T) { 324 state := testStateStore(t) 325 job := mock.Job() 326 327 notify := setupNotifyTest( 328 state, 329 watch.Item{Table: "jobs"}, 330 watch.Item{Job: job.ID}) 331 332 err := state.UpsertJob(1000, job) 333 if err != nil { 334 t.Fatalf("err: %v", err) 335 } 336 337 out, err := state.JobByID(job.ID) 338 if err != nil { 339 t.Fatalf("err: %v", err) 340 } 341 342 if !reflect.DeepEqual(job, out) { 343 t.Fatalf("bad: %#v %#v", job, out) 344 } 345 346 index, err := state.Index("jobs") 347 if err != nil { 348 t.Fatalf("err: %v", err) 349 } 350 if index != 1000 { 351 t.Fatalf("bad: %d", index) 352 } 353 354 notify.verify(t) 355 } 356 357 func TestStateStore_UpdateUpsertJob_Job(t *testing.T) { 358 state := testStateStore(t) 359 job := mock.Job() 360 361 notify := setupNotifyTest( 362 state, 363 watch.Item{Table: "jobs"}, 364 watch.Item{Job: job.ID}) 365 366 err := state.UpsertJob(1000, job) 367 if err != nil { 368 t.Fatalf("err: %v", err) 369 } 370 371 job2 := mock.Job() 372 job2.ID = job.ID 373 err = state.UpsertJob(1001, job2) 374 if err != nil { 375 t.Fatalf("err: %v", err) 376 } 377 378 out, err := state.JobByID(job.ID) 379 if err != nil { 380 t.Fatalf("err: %v", err) 381 } 382 383 if !reflect.DeepEqual(job2, out) { 384 t.Fatalf("bad: %#v %#v", job2, out) 385 } 386 387 if out.CreateIndex != 1000 { 388 t.Fatalf("bad: %#v", out) 389 } 390 if out.ModifyIndex != 1001 { 391 t.Fatalf("bad: %#v", out) 392 } 393 394 index, err := state.Index("jobs") 395 if err != nil { 396 t.Fatalf("err: %v", err) 397 } 398 if index != 1001 { 399 t.Fatalf("bad: %d", index) 400 } 401 402 notify.verify(t) 403 } 404 405 func TestStateStore_DeleteJob_Job(t *testing.T) { 406 state := testStateStore(t) 407 job := mock.Job() 408 409 notify := setupNotifyTest( 410 state, 411 watch.Item{Table: "jobs"}, 412 watch.Item{Job: job.ID}) 413 414 err := state.UpsertJob(1000, job) 415 if err != nil { 416 t.Fatalf("err: %v", err) 417 } 418 419 err = state.DeleteJob(1001, job.ID) 420 if err != nil { 421 t.Fatalf("err: %v", err) 422 } 423 424 out, err := state.JobByID(job.ID) 425 if err != nil { 426 t.Fatalf("err: %v", err) 427 } 428 429 if out != nil { 430 t.Fatalf("bad: %#v %#v", job, out) 431 } 432 433 index, err := state.Index("jobs") 434 if err != nil { 435 t.Fatalf("err: %v", err) 436 } 437 if index != 1001 { 438 t.Fatalf("bad: %d", index) 439 } 440 441 notify.verify(t) 442 } 443 444 func TestStateStore_Jobs(t *testing.T) { 445 state := testStateStore(t) 446 var jobs []*structs.Job 447 448 for i := 0; i < 10; i++ { 449 job := mock.Job() 450 jobs = append(jobs, job) 451 452 err := state.UpsertJob(1000+uint64(i), job) 453 if err != nil { 454 t.Fatalf("err: %v", err) 455 } 456 } 457 458 iter, err := state.Jobs() 459 if err != nil { 460 t.Fatalf("err: %v", err) 461 } 462 463 var out []*structs.Job 464 for { 465 raw := iter.Next() 466 if raw == nil { 467 break 468 } 469 out = append(out, raw.(*structs.Job)) 470 } 471 472 sort.Sort(JobIDSort(jobs)) 473 sort.Sort(JobIDSort(out)) 474 475 if !reflect.DeepEqual(jobs, out) { 476 t.Fatalf("bad: %#v %#v", jobs, out) 477 } 478 } 479 480 func TestStateStore_JobsByIDPrefix(t *testing.T) { 481 state := testStateStore(t) 482 job := mock.Job() 483 484 job.ID = "redis" 485 err := state.UpsertJob(1000, job) 486 if err != nil { 487 t.Fatalf("err: %v", err) 488 } 489 490 iter, err := state.JobsByIDPrefix(job.ID) 491 if err != nil { 492 t.Fatalf("err: %v", err) 493 } 494 495 gatherJobs := func(iter memdb.ResultIterator) []*structs.Job { 496 var jobs []*structs.Job 497 for { 498 raw := iter.Next() 499 if raw == nil { 500 break 501 } 502 jobs = append(jobs, raw.(*structs.Job)) 503 } 504 return jobs 505 } 506 507 jobs := gatherJobs(iter) 508 if len(jobs) != 1 { 509 t.Fatalf("err: %v", err) 510 } 511 512 iter, err = state.JobsByIDPrefix("re") 513 if err != nil { 514 t.Fatalf("err: %v", err) 515 } 516 517 jobs = gatherJobs(iter) 518 if len(jobs) != 1 { 519 t.Fatalf("err: %v", err) 520 } 521 522 job = mock.Job() 523 job.ID = "riak" 524 err = state.UpsertJob(1001, job) 525 if err != nil { 526 t.Fatalf("err: %v", err) 527 } 528 529 iter, err = state.JobsByIDPrefix("r") 530 if err != nil { 531 t.Fatalf("err: %v", err) 532 } 533 534 jobs = gatherJobs(iter) 535 if len(jobs) != 2 { 536 t.Fatalf("err: %v", err) 537 } 538 539 iter, err = state.JobsByIDPrefix("ri") 540 if err != nil { 541 t.Fatalf("err: %v", err) 542 } 543 544 jobs = gatherJobs(iter) 545 if len(jobs) != 1 { 546 t.Fatalf("err: %v", err) 547 } 548 } 549 550 func TestStateStore_JobsByPeriodic(t *testing.T) { 551 state := testStateStore(t) 552 var periodic, nonPeriodic []*structs.Job 553 554 for i := 0; i < 10; i++ { 555 job := mock.Job() 556 nonPeriodic = append(nonPeriodic, job) 557 558 err := state.UpsertJob(1000+uint64(i), job) 559 if err != nil { 560 t.Fatalf("err: %v", err) 561 } 562 } 563 564 for i := 0; i < 10; i++ { 565 job := mock.PeriodicJob() 566 periodic = append(periodic, job) 567 568 err := state.UpsertJob(2000+uint64(i), job) 569 if err != nil { 570 t.Fatalf("err: %v", err) 571 } 572 } 573 574 iter, err := state.JobsByPeriodic(true) 575 if err != nil { 576 t.Fatalf("err: %v", err) 577 } 578 579 var outPeriodic []*structs.Job 580 for { 581 raw := iter.Next() 582 if raw == nil { 583 break 584 } 585 outPeriodic = append(outPeriodic, raw.(*structs.Job)) 586 } 587 588 iter, err = state.JobsByPeriodic(false) 589 590 var outNonPeriodic []*structs.Job 591 for { 592 raw := iter.Next() 593 if raw == nil { 594 break 595 } 596 outNonPeriodic = append(outNonPeriodic, raw.(*structs.Job)) 597 } 598 599 sort.Sort(JobIDSort(periodic)) 600 sort.Sort(JobIDSort(nonPeriodic)) 601 sort.Sort(JobIDSort(outPeriodic)) 602 sort.Sort(JobIDSort(outNonPeriodic)) 603 604 if !reflect.DeepEqual(periodic, outPeriodic) { 605 t.Fatalf("bad: %#v %#v", periodic, outPeriodic) 606 } 607 608 if !reflect.DeepEqual(nonPeriodic, outNonPeriodic) { 609 t.Fatalf("bad: %#v %#v", nonPeriodic, outNonPeriodic) 610 } 611 } 612 613 func TestStateStore_JobsByScheduler(t *testing.T) { 614 state := testStateStore(t) 615 var serviceJobs []*structs.Job 616 var sysJobs []*structs.Job 617 618 for i := 0; i < 10; i++ { 619 job := mock.Job() 620 serviceJobs = append(serviceJobs, job) 621 622 err := state.UpsertJob(1000+uint64(i), job) 623 if err != nil { 624 t.Fatalf("err: %v", err) 625 } 626 } 627 628 for i := 0; i < 10; i++ { 629 job := mock.SystemJob() 630 sysJobs = append(sysJobs, job) 631 632 err := state.UpsertJob(2000+uint64(i), job) 633 if err != nil { 634 t.Fatalf("err: %v", err) 635 } 636 } 637 638 iter, err := state.JobsByScheduler("service") 639 if err != nil { 640 t.Fatalf("err: %v", err) 641 } 642 643 var outService []*structs.Job 644 for { 645 raw := iter.Next() 646 if raw == nil { 647 break 648 } 649 outService = append(outService, raw.(*structs.Job)) 650 } 651 652 iter, err = state.JobsByScheduler("system") 653 if err != nil { 654 t.Fatalf("err: %v", err) 655 } 656 657 var outSystem []*structs.Job 658 for { 659 raw := iter.Next() 660 if raw == nil { 661 break 662 } 663 outSystem = append(outSystem, raw.(*structs.Job)) 664 } 665 666 sort.Sort(JobIDSort(serviceJobs)) 667 sort.Sort(JobIDSort(sysJobs)) 668 sort.Sort(JobIDSort(outService)) 669 sort.Sort(JobIDSort(outSystem)) 670 671 if !reflect.DeepEqual(serviceJobs, outService) { 672 t.Fatalf("bad: %#v %#v", serviceJobs, outService) 673 } 674 675 if !reflect.DeepEqual(sysJobs, outSystem) { 676 t.Fatalf("bad: %#v %#v", sysJobs, outSystem) 677 } 678 } 679 680 func TestStateStore_JobsByGC(t *testing.T) { 681 state := testStateStore(t) 682 var gc, nonGc []*structs.Job 683 684 for i := 0; i < 10; i++ { 685 job := mock.Job() 686 nonGc = append(nonGc, job) 687 688 if err := state.UpsertJob(1000+uint64(i), job); err != nil { 689 t.Fatalf("err: %v", err) 690 } 691 } 692 693 for i := 0; i < 10; i++ { 694 job := mock.Job() 695 job.GC = true 696 gc = append(gc, job) 697 698 if err := state.UpsertJob(2000+uint64(i), job); err != nil { 699 t.Fatalf("err: %v", err) 700 } 701 } 702 703 iter, err := state.JobsByGC(true) 704 if err != nil { 705 t.Fatalf("err: %v", err) 706 } 707 708 var outGc []*structs.Job 709 for i := iter.Next(); i != nil; i = iter.Next() { 710 outGc = append(outGc, i.(*structs.Job)) 711 } 712 713 iter, err = state.JobsByGC(false) 714 if err != nil { 715 t.Fatalf("err: %v", err) 716 } 717 718 var outNonGc []*structs.Job 719 for i := iter.Next(); i != nil; i = iter.Next() { 720 outNonGc = append(outNonGc, i.(*structs.Job)) 721 } 722 723 sort.Sort(JobIDSort(gc)) 724 sort.Sort(JobIDSort(nonGc)) 725 sort.Sort(JobIDSort(outGc)) 726 sort.Sort(JobIDSort(outNonGc)) 727 728 if !reflect.DeepEqual(gc, outGc) { 729 t.Fatalf("bad: %#v %#v", gc, outGc) 730 } 731 732 if !reflect.DeepEqual(nonGc, outNonGc) { 733 t.Fatalf("bad: %#v %#v", nonGc, outNonGc) 734 } 735 } 736 737 func TestStateStore_RestoreJob(t *testing.T) { 738 state := testStateStore(t) 739 job := mock.Job() 740 741 notify := setupNotifyTest( 742 state, 743 watch.Item{Table: "jobs"}, 744 watch.Item{Job: job.ID}) 745 746 restore, err := state.Restore() 747 if err != nil { 748 t.Fatalf("err: %v", err) 749 } 750 751 err = restore.JobRestore(job) 752 if err != nil { 753 t.Fatalf("err: %v", err) 754 } 755 restore.Commit() 756 757 out, err := state.JobByID(job.ID) 758 if err != nil { 759 t.Fatalf("err: %v", err) 760 } 761 762 if !reflect.DeepEqual(out, job) { 763 t.Fatalf("Bad: %#v %#v", out, job) 764 } 765 766 notify.verify(t) 767 } 768 769 func TestStateStore_UpsertPeriodicLaunch(t *testing.T) { 770 state := testStateStore(t) 771 job := mock.Job() 772 launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()} 773 774 notify := setupNotifyTest( 775 state, 776 watch.Item{Table: "periodic_launch"}, 777 watch.Item{Job: job.ID}) 778 779 err := state.UpsertPeriodicLaunch(1000, launch) 780 if err != nil { 781 t.Fatalf("err: %v", err) 782 } 783 784 out, err := state.PeriodicLaunchByID(job.ID) 785 if err != nil { 786 t.Fatalf("err: %v", err) 787 } 788 if out.CreateIndex != 1000 { 789 t.Fatalf("bad: %#v", out) 790 } 791 if out.ModifyIndex != 1000 { 792 t.Fatalf("bad: %#v", out) 793 } 794 795 if !reflect.DeepEqual(launch, out) { 796 t.Fatalf("bad: %#v %#v", job, out) 797 } 798 799 index, err := state.Index("periodic_launch") 800 if err != nil { 801 t.Fatalf("err: %v", err) 802 } 803 if index != 1000 { 804 t.Fatalf("bad: %d", index) 805 } 806 807 notify.verify(t) 808 } 809 810 func TestStateStore_UpdateUpsertPeriodicLaunch(t *testing.T) { 811 state := testStateStore(t) 812 job := mock.Job() 813 launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()} 814 815 notify := setupNotifyTest( 816 state, 817 watch.Item{Table: "periodic_launch"}, 818 watch.Item{Job: job.ID}) 819 820 err := state.UpsertPeriodicLaunch(1000, launch) 821 if err != nil { 822 t.Fatalf("err: %v", err) 823 } 824 825 launch2 := &structs.PeriodicLaunch{ 826 ID: job.ID, 827 Launch: launch.Launch.Add(1 * time.Second), 828 } 829 err = state.UpsertPeriodicLaunch(1001, launch2) 830 if err != nil { 831 t.Fatalf("err: %v", err) 832 } 833 834 out, err := state.PeriodicLaunchByID(job.ID) 835 if err != nil { 836 t.Fatalf("err: %v", err) 837 } 838 if out.CreateIndex != 1000 { 839 t.Fatalf("bad: %#v", out) 840 } 841 if out.ModifyIndex != 1001 { 842 t.Fatalf("bad: %#v", out) 843 } 844 845 if !reflect.DeepEqual(launch2, out) { 846 t.Fatalf("bad: %#v %#v", launch2, out) 847 } 848 849 index, err := state.Index("periodic_launch") 850 if err != nil { 851 t.Fatalf("err: %v", err) 852 } 853 if index != 1001 { 854 t.Fatalf("bad: %d", index) 855 } 856 857 notify.verify(t) 858 } 859 860 func TestStateStore_DeletePeriodicLaunch(t *testing.T) { 861 state := testStateStore(t) 862 job := mock.Job() 863 launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()} 864 865 notify := setupNotifyTest( 866 state, 867 watch.Item{Table: "periodic_launch"}, 868 watch.Item{Job: job.ID}) 869 870 err := state.UpsertPeriodicLaunch(1000, launch) 871 if err != nil { 872 t.Fatalf("err: %v", err) 873 } 874 875 err = state.DeletePeriodicLaunch(1001, job.ID) 876 if err != nil { 877 t.Fatalf("err: %v", err) 878 } 879 880 out, err := state.PeriodicLaunchByID(job.ID) 881 if err != nil { 882 t.Fatalf("err: %v", err) 883 } 884 885 if out != nil { 886 t.Fatalf("bad: %#v %#v", job, out) 887 } 888 889 index, err := state.Index("periodic_launch") 890 if err != nil { 891 t.Fatalf("err: %v", err) 892 } 893 if index != 1001 { 894 t.Fatalf("bad: %d", index) 895 } 896 897 notify.verify(t) 898 } 899 900 func TestStateStore_PeriodicLaunches(t *testing.T) { 901 state := testStateStore(t) 902 var launches []*structs.PeriodicLaunch 903 904 for i := 0; i < 10; i++ { 905 job := mock.Job() 906 launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()} 907 launches = append(launches, launch) 908 909 err := state.UpsertPeriodicLaunch(1000+uint64(i), launch) 910 if err != nil { 911 t.Fatalf("err: %v", err) 912 } 913 } 914 915 iter, err := state.PeriodicLaunches() 916 if err != nil { 917 t.Fatalf("err: %v", err) 918 } 919 920 out := make(map[string]*structs.PeriodicLaunch, 10) 921 for { 922 raw := iter.Next() 923 if raw == nil { 924 break 925 } 926 launch := raw.(*structs.PeriodicLaunch) 927 if _, ok := out[launch.ID]; ok { 928 t.Fatalf("duplicate: %v", launch.ID) 929 } 930 931 out[launch.ID] = launch 932 } 933 934 for _, launch := range launches { 935 l, ok := out[launch.ID] 936 if !ok { 937 t.Fatalf("bad %v", launch.ID) 938 } 939 940 if !reflect.DeepEqual(launch, l) { 941 t.Fatalf("bad: %#v %#v", launch, l) 942 } 943 944 delete(out, launch.ID) 945 } 946 947 if len(out) != 0 { 948 t.Fatalf("leftover: %#v", out) 949 } 950 } 951 952 func TestStateStore_RestorePeriodicLaunch(t *testing.T) { 953 state := testStateStore(t) 954 job := mock.Job() 955 launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()} 956 957 notify := setupNotifyTest( 958 state, 959 watch.Item{Table: "periodic_launch"}, 960 watch.Item{Job: job.ID}) 961 962 restore, err := state.Restore() 963 if err != nil { 964 t.Fatalf("err: %v", err) 965 } 966 967 err = restore.PeriodicLaunchRestore(launch) 968 if err != nil { 969 t.Fatalf("err: %v", err) 970 } 971 restore.Commit() 972 973 out, err := state.PeriodicLaunchByID(job.ID) 974 if err != nil { 975 t.Fatalf("err: %v", err) 976 } 977 978 if !reflect.DeepEqual(out, launch) { 979 t.Fatalf("Bad: %#v %#v", out, job) 980 } 981 982 notify.verify(t) 983 } 984 985 func TestStateStore_Indexes(t *testing.T) { 986 state := testStateStore(t) 987 node := mock.Node() 988 989 err := state.UpsertNode(1000, node) 990 if err != nil { 991 t.Fatalf("err: %v", err) 992 } 993 994 iter, err := state.Indexes() 995 if err != nil { 996 t.Fatalf("err: %v", err) 997 } 998 999 var out []*IndexEntry 1000 for { 1001 raw := iter.Next() 1002 if raw == nil { 1003 break 1004 } 1005 out = append(out, raw.(*IndexEntry)) 1006 } 1007 1008 expect := []*IndexEntry{ 1009 &IndexEntry{"nodes", 1000}, 1010 } 1011 1012 if !reflect.DeepEqual(expect, out) { 1013 t.Fatalf("bad: %#v %#v", expect, out) 1014 } 1015 } 1016 1017 func TestStateStore_RestoreIndex(t *testing.T) { 1018 state := testStateStore(t) 1019 1020 restore, err := state.Restore() 1021 if err != nil { 1022 t.Fatalf("err: %v", err) 1023 } 1024 1025 index := &IndexEntry{"jobs", 1000} 1026 err = restore.IndexRestore(index) 1027 if err != nil { 1028 t.Fatalf("err: %v", err) 1029 } 1030 1031 restore.Commit() 1032 1033 out, err := state.Index("jobs") 1034 if err != nil { 1035 t.Fatalf("err: %v", err) 1036 } 1037 1038 if out != 1000 { 1039 t.Fatalf("Bad: %#v %#v", out, 1000) 1040 } 1041 } 1042 1043 func TestStateStore_UpsertEvals_Eval(t *testing.T) { 1044 state := testStateStore(t) 1045 eval := mock.Eval() 1046 1047 notify := setupNotifyTest( 1048 state, 1049 watch.Item{Table: "evals"}, 1050 watch.Item{Eval: eval.ID}) 1051 1052 err := state.UpsertEvals(1000, []*structs.Evaluation{eval}) 1053 if err != nil { 1054 t.Fatalf("err: %v", err) 1055 } 1056 1057 out, err := state.EvalByID(eval.ID) 1058 if err != nil { 1059 t.Fatalf("err: %v", err) 1060 } 1061 1062 if !reflect.DeepEqual(eval, out) { 1063 t.Fatalf("bad: %#v %#v", eval, out) 1064 } 1065 1066 index, err := state.Index("evals") 1067 if err != nil { 1068 t.Fatalf("err: %v", err) 1069 } 1070 if index != 1000 { 1071 t.Fatalf("bad: %d", index) 1072 } 1073 1074 notify.verify(t) 1075 } 1076 1077 func TestStateStore_Update_UpsertEvals_Eval(t *testing.T) { 1078 state := testStateStore(t) 1079 eval := mock.Eval() 1080 1081 err := state.UpsertEvals(1000, []*structs.Evaluation{eval}) 1082 if err != nil { 1083 t.Fatalf("err: %v", err) 1084 } 1085 1086 notify := setupNotifyTest( 1087 state, 1088 watch.Item{Table: "evals"}, 1089 watch.Item{Eval: eval.ID}) 1090 1091 eval2 := mock.Eval() 1092 eval2.ID = eval.ID 1093 err = state.UpsertEvals(1001, []*structs.Evaluation{eval2}) 1094 if err != nil { 1095 t.Fatalf("err: %v", err) 1096 } 1097 1098 out, err := state.EvalByID(eval.ID) 1099 if err != nil { 1100 t.Fatalf("err: %v", err) 1101 } 1102 1103 if !reflect.DeepEqual(eval2, out) { 1104 t.Fatalf("bad: %#v %#v", eval2, out) 1105 } 1106 1107 if out.CreateIndex != 1000 { 1108 t.Fatalf("bad: %#v", out) 1109 } 1110 if out.ModifyIndex != 1001 { 1111 t.Fatalf("bad: %#v", out) 1112 } 1113 1114 index, err := state.Index("evals") 1115 if err != nil { 1116 t.Fatalf("err: %v", err) 1117 } 1118 if index != 1001 { 1119 t.Fatalf("bad: %d", index) 1120 } 1121 1122 notify.verify(t) 1123 } 1124 1125 func TestStateStore_DeleteEval_Eval(t *testing.T) { 1126 state := testStateStore(t) 1127 eval1 := mock.Eval() 1128 eval2 := mock.Eval() 1129 alloc1 := mock.Alloc() 1130 alloc2 := mock.Alloc() 1131 1132 notify := setupNotifyTest( 1133 state, 1134 watch.Item{Table: "evals"}, 1135 watch.Item{Table: "allocs"}, 1136 watch.Item{Eval: eval1.ID}, 1137 watch.Item{Eval: eval2.ID}, 1138 watch.Item{Alloc: alloc1.ID}, 1139 watch.Item{Alloc: alloc2.ID}, 1140 watch.Item{AllocEval: alloc1.EvalID}, 1141 watch.Item{AllocEval: alloc2.EvalID}, 1142 watch.Item{AllocJob: alloc1.JobID}, 1143 watch.Item{AllocJob: alloc2.JobID}, 1144 watch.Item{AllocNode: alloc1.NodeID}, 1145 watch.Item{AllocNode: alloc2.NodeID}) 1146 1147 err := state.UpsertEvals(1000, []*structs.Evaluation{eval1, eval2}) 1148 if err != nil { 1149 t.Fatalf("err: %v", err) 1150 } 1151 1152 err = state.UpsertAllocs(1001, []*structs.Allocation{alloc1, alloc2}) 1153 if err != nil { 1154 t.Fatalf("err: %v", err) 1155 } 1156 1157 err = state.DeleteEval(1002, []string{eval1.ID, eval2.ID}, []string{alloc1.ID, alloc2.ID}) 1158 if err != nil { 1159 t.Fatalf("err: %v", err) 1160 } 1161 1162 out, err := state.EvalByID(eval1.ID) 1163 if err != nil { 1164 t.Fatalf("err: %v", err) 1165 } 1166 1167 if out != nil { 1168 t.Fatalf("bad: %#v %#v", eval1, out) 1169 } 1170 1171 out, err = state.EvalByID(eval2.ID) 1172 if err != nil { 1173 t.Fatalf("err: %v", err) 1174 } 1175 1176 if out != nil { 1177 t.Fatalf("bad: %#v %#v", eval1, out) 1178 } 1179 1180 outA, err := state.AllocByID(alloc1.ID) 1181 if err != nil { 1182 t.Fatalf("err: %v", err) 1183 } 1184 1185 if out != nil { 1186 t.Fatalf("bad: %#v %#v", alloc1, outA) 1187 } 1188 1189 outA, err = state.AllocByID(alloc2.ID) 1190 if err != nil { 1191 t.Fatalf("err: %v", err) 1192 } 1193 1194 if out != nil { 1195 t.Fatalf("bad: %#v %#v", alloc1, outA) 1196 } 1197 1198 index, err := state.Index("evals") 1199 if err != nil { 1200 t.Fatalf("err: %v", err) 1201 } 1202 if index != 1002 { 1203 t.Fatalf("bad: %d", index) 1204 } 1205 1206 index, err = state.Index("allocs") 1207 if err != nil { 1208 t.Fatalf("err: %v", err) 1209 } 1210 if index != 1002 { 1211 t.Fatalf("bad: %d", index) 1212 } 1213 1214 notify.verify(t) 1215 } 1216 1217 func TestStateStore_EvalsByJob(t *testing.T) { 1218 state := testStateStore(t) 1219 1220 eval1 := mock.Eval() 1221 eval2 := mock.Eval() 1222 eval2.JobID = eval1.JobID 1223 eval3 := mock.Eval() 1224 evals := []*structs.Evaluation{eval1, eval2} 1225 1226 err := state.UpsertEvals(1000, evals) 1227 if err != nil { 1228 t.Fatalf("err: %v", err) 1229 } 1230 err = state.UpsertEvals(1001, []*structs.Evaluation{eval3}) 1231 if err != nil { 1232 t.Fatalf("err: %v", err) 1233 } 1234 1235 out, err := state.EvalsByJob(eval1.JobID) 1236 if err != nil { 1237 t.Fatalf("err: %v", err) 1238 } 1239 1240 sort.Sort(EvalIDSort(evals)) 1241 sort.Sort(EvalIDSort(out)) 1242 1243 if !reflect.DeepEqual(evals, out) { 1244 t.Fatalf("bad: %#v %#v", evals, out) 1245 } 1246 } 1247 1248 func TestStateStore_Evals(t *testing.T) { 1249 state := testStateStore(t) 1250 var evals []*structs.Evaluation 1251 1252 for i := 0; i < 10; i++ { 1253 eval := mock.Eval() 1254 evals = append(evals, eval) 1255 1256 err := state.UpsertEvals(1000+uint64(i), []*structs.Evaluation{eval}) 1257 if err != nil { 1258 t.Fatalf("err: %v", err) 1259 } 1260 } 1261 1262 iter, err := state.Evals() 1263 if err != nil { 1264 t.Fatalf("err: %v", err) 1265 } 1266 1267 var out []*structs.Evaluation 1268 for { 1269 raw := iter.Next() 1270 if raw == nil { 1271 break 1272 } 1273 out = append(out, raw.(*structs.Evaluation)) 1274 } 1275 1276 sort.Sort(EvalIDSort(evals)) 1277 sort.Sort(EvalIDSort(out)) 1278 1279 if !reflect.DeepEqual(evals, out) { 1280 t.Fatalf("bad: %#v %#v", evals, out) 1281 } 1282 } 1283 1284 func TestStateStore_EvalsByIDPrefix(t *testing.T) { 1285 state := testStateStore(t) 1286 var evals []*structs.Evaluation 1287 1288 ids := []string{ 1289 "aaaaaaaa-7bfb-395d-eb95-0685af2176b2", 1290 "aaaaaaab-7bfb-395d-eb95-0685af2176b2", 1291 "aaaaaabb-7bfb-395d-eb95-0685af2176b2", 1292 "aaaaabbb-7bfb-395d-eb95-0685af2176b2", 1293 "aaaabbbb-7bfb-395d-eb95-0685af2176b2", 1294 "aaabbbbb-7bfb-395d-eb95-0685af2176b2", 1295 "aabbbbbb-7bfb-395d-eb95-0685af2176b2", 1296 "abbbbbbb-7bfb-395d-eb95-0685af2176b2", 1297 "bbbbbbbb-7bfb-395d-eb95-0685af2176b2", 1298 } 1299 for i := 0; i < 9; i++ { 1300 eval := mock.Eval() 1301 eval.ID = ids[i] 1302 evals = append(evals, eval) 1303 } 1304 1305 err := state.UpsertEvals(1000, evals) 1306 if err != nil { 1307 t.Fatalf("err: %v", err) 1308 } 1309 1310 iter, err := state.EvalsByIDPrefix("aaaa") 1311 if err != nil { 1312 t.Fatalf("err: %v", err) 1313 } 1314 1315 gatherEvals := func(iter memdb.ResultIterator) []*structs.Evaluation { 1316 var evals []*structs.Evaluation 1317 for { 1318 raw := iter.Next() 1319 if raw == nil { 1320 break 1321 } 1322 evals = append(evals, raw.(*structs.Evaluation)) 1323 } 1324 return evals 1325 } 1326 1327 out := gatherEvals(iter) 1328 if len(out) != 5 { 1329 t.Fatalf("bad: expected five evaluations, got: %#v", out) 1330 } 1331 1332 sort.Sort(EvalIDSort(evals)) 1333 1334 for index, eval := range out { 1335 if ids[index] != eval.ID { 1336 t.Fatalf("bad: got unexpected id: %s", eval.ID) 1337 } 1338 } 1339 1340 iter, err = state.EvalsByIDPrefix("b-a7bfb") 1341 if err != nil { 1342 t.Fatalf("err: %v", err) 1343 } 1344 1345 out = gatherEvals(iter) 1346 if len(out) != 0 { 1347 t.Fatalf("bad: unexpected zero evaluations, got: %#v", out) 1348 } 1349 1350 } 1351 1352 func TestStateStore_RestoreEval(t *testing.T) { 1353 state := testStateStore(t) 1354 eval := mock.Eval() 1355 1356 notify := setupNotifyTest( 1357 state, 1358 watch.Item{Table: "evals"}, 1359 watch.Item{Eval: eval.ID}) 1360 1361 restore, err := state.Restore() 1362 if err != nil { 1363 t.Fatalf("err: %v", err) 1364 } 1365 1366 err = restore.EvalRestore(eval) 1367 if err != nil { 1368 t.Fatalf("err: %v", err) 1369 } 1370 restore.Commit() 1371 1372 out, err := state.EvalByID(eval.ID) 1373 if err != nil { 1374 t.Fatalf("err: %v", err) 1375 } 1376 1377 if !reflect.DeepEqual(out, eval) { 1378 t.Fatalf("Bad: %#v %#v", out, eval) 1379 } 1380 1381 notify.verify(t) 1382 } 1383 1384 func TestStateStore_UpdateAllocsFromClient(t *testing.T) { 1385 state := testStateStore(t) 1386 alloc := mock.Alloc() 1387 alloc2 := mock.Alloc() 1388 1389 notify := setupNotifyTest( 1390 state, 1391 watch.Item{Table: "allocs"}, 1392 watch.Item{Alloc: alloc.ID}, 1393 watch.Item{AllocEval: alloc.EvalID}, 1394 watch.Item{AllocJob: alloc.JobID}, 1395 watch.Item{AllocNode: alloc.NodeID}, 1396 watch.Item{Alloc: alloc2.ID}, 1397 watch.Item{AllocEval: alloc2.EvalID}, 1398 watch.Item{AllocJob: alloc2.JobID}, 1399 watch.Item{AllocNode: alloc2.NodeID}) 1400 1401 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc, alloc2}) 1402 if err != nil { 1403 t.Fatalf("err: %v", err) 1404 } 1405 1406 // Create the delta updates 1407 update := &structs.Allocation{ 1408 ID: alloc.ID, 1409 ClientStatus: structs.AllocClientStatusFailed, 1410 TaskStates: map[string]*structs.TaskState{ 1411 "web": &structs.TaskState{ 1412 State: structs.TaskStatePending, 1413 }, 1414 }, 1415 } 1416 update2 := &structs.Allocation{ 1417 ID: alloc2.ID, 1418 ClientStatus: structs.AllocClientStatusRunning, 1419 TaskStates: map[string]*structs.TaskState{ 1420 "web": &structs.TaskState{ 1421 State: structs.TaskStatePending, 1422 }, 1423 }, 1424 } 1425 1426 err = state.UpdateAllocsFromClient(1001, []*structs.Allocation{update, update2}) 1427 if err != nil { 1428 t.Fatalf("err: %v", err) 1429 } 1430 1431 out, err := state.AllocByID(alloc.ID) 1432 if err != nil { 1433 t.Fatalf("err: %v", err) 1434 } 1435 1436 alloc.CreateIndex = 1000 1437 alloc.ModifyIndex = 1001 1438 alloc.ClientStatus = structs.AllocClientStatusFailed 1439 if !reflect.DeepEqual(alloc, out) { 1440 t.Fatalf("bad: %#v %#v", alloc, out) 1441 } 1442 1443 out, err = state.AllocByID(alloc2.ID) 1444 if err != nil { 1445 t.Fatalf("err: %v", err) 1446 } 1447 1448 alloc2.ModifyIndex = 1000 1449 alloc2.ModifyIndex = 1001 1450 alloc2.ClientStatus = structs.AllocClientStatusRunning 1451 if !reflect.DeepEqual(alloc2, out) { 1452 t.Fatalf("bad: %#v %#v", alloc2, out) 1453 } 1454 1455 index, err := state.Index("allocs") 1456 if err != nil { 1457 t.Fatalf("err: %v", err) 1458 } 1459 if index != 1001 { 1460 t.Fatalf("bad: %d", index) 1461 } 1462 1463 notify.verify(t) 1464 } 1465 1466 func TestStateStore_UpsertAlloc_Alloc(t *testing.T) { 1467 state := testStateStore(t) 1468 alloc := mock.Alloc() 1469 1470 notify := setupNotifyTest( 1471 state, 1472 watch.Item{Table: "allocs"}, 1473 watch.Item{Alloc: alloc.ID}, 1474 watch.Item{AllocEval: alloc.EvalID}, 1475 watch.Item{AllocJob: alloc.JobID}, 1476 watch.Item{AllocNode: alloc.NodeID}) 1477 1478 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}) 1479 if err != nil { 1480 t.Fatalf("err: %v", err) 1481 } 1482 1483 out, err := state.AllocByID(alloc.ID) 1484 if err != nil { 1485 t.Fatalf("err: %v", err) 1486 } 1487 1488 if !reflect.DeepEqual(alloc, out) { 1489 t.Fatalf("bad: %#v %#v", alloc, out) 1490 } 1491 1492 index, err := state.Index("allocs") 1493 if err != nil { 1494 t.Fatalf("err: %v", err) 1495 } 1496 if index != 1000 { 1497 t.Fatalf("bad: %d", index) 1498 } 1499 1500 notify.verify(t) 1501 } 1502 1503 func TestStateStore_UpdateAlloc_Alloc(t *testing.T) { 1504 state := testStateStore(t) 1505 alloc := mock.Alloc() 1506 1507 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}) 1508 if err != nil { 1509 t.Fatalf("err: %v", err) 1510 } 1511 1512 alloc2 := mock.Alloc() 1513 alloc2.ID = alloc.ID 1514 alloc2.NodeID = alloc.NodeID + ".new" 1515 1516 notify := setupNotifyTest( 1517 state, 1518 watch.Item{Table: "allocs"}, 1519 watch.Item{Alloc: alloc2.ID}, 1520 watch.Item{AllocEval: alloc2.EvalID}, 1521 watch.Item{AllocJob: alloc2.JobID}, 1522 watch.Item{AllocNode: alloc2.NodeID}) 1523 1524 err = state.UpsertAllocs(1001, []*structs.Allocation{alloc2}) 1525 if err != nil { 1526 t.Fatalf("err: %v", err) 1527 } 1528 1529 out, err := state.AllocByID(alloc.ID) 1530 if err != nil { 1531 t.Fatalf("err: %v", err) 1532 } 1533 1534 if !reflect.DeepEqual(alloc2, out) { 1535 t.Fatalf("bad: %#v %#v", alloc2, out) 1536 } 1537 1538 if out.CreateIndex != 1000 { 1539 t.Fatalf("bad: %#v", out) 1540 } 1541 if out.ModifyIndex != 1001 { 1542 t.Fatalf("bad: %#v", out) 1543 } 1544 1545 index, err := state.Index("allocs") 1546 if err != nil { 1547 t.Fatalf("err: %v", err) 1548 } 1549 if index != 1001 { 1550 t.Fatalf("bad: %d", index) 1551 } 1552 1553 notify.verify(t) 1554 } 1555 1556 func TestStateStore_EvictAlloc_Alloc(t *testing.T) { 1557 state := testStateStore(t) 1558 alloc := mock.Alloc() 1559 1560 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}) 1561 if err != nil { 1562 t.Fatalf("err: %v", err) 1563 } 1564 1565 alloc2 := new(structs.Allocation) 1566 *alloc2 = *alloc 1567 alloc2.DesiredStatus = structs.AllocDesiredStatusEvict 1568 err = state.UpsertAllocs(1001, []*structs.Allocation{alloc2}) 1569 if err != nil { 1570 t.Fatalf("err: %v", err) 1571 } 1572 1573 out, err := state.AllocByID(alloc.ID) 1574 if err != nil { 1575 t.Fatalf("err: %v", err) 1576 } 1577 1578 if out.DesiredStatus != structs.AllocDesiredStatusEvict { 1579 t.Fatalf("bad: %#v %#v", alloc, out) 1580 } 1581 1582 index, err := state.Index("allocs") 1583 if err != nil { 1584 t.Fatalf("err: %v", err) 1585 } 1586 if index != 1001 { 1587 t.Fatalf("bad: %d", index) 1588 } 1589 } 1590 1591 func TestStateStore_AllocsByNode(t *testing.T) { 1592 state := testStateStore(t) 1593 var allocs []*structs.Allocation 1594 1595 for i := 0; i < 10; i++ { 1596 alloc := mock.Alloc() 1597 alloc.NodeID = "foo" 1598 allocs = append(allocs, alloc) 1599 } 1600 1601 err := state.UpsertAllocs(1000, allocs) 1602 if err != nil { 1603 t.Fatalf("err: %v", err) 1604 } 1605 1606 out, err := state.AllocsByNode("foo") 1607 if err != nil { 1608 t.Fatalf("err: %v", err) 1609 } 1610 1611 sort.Sort(AllocIDSort(allocs)) 1612 sort.Sort(AllocIDSort(out)) 1613 1614 if !reflect.DeepEqual(allocs, out) { 1615 t.Fatalf("bad: %#v %#v", allocs, out) 1616 } 1617 } 1618 1619 func TestStateStore_AllocsByNodeTerminal(t *testing.T) { 1620 state := testStateStore(t) 1621 var allocs, term, nonterm []*structs.Allocation 1622 1623 for i := 0; i < 10; i++ { 1624 alloc := mock.Alloc() 1625 alloc.NodeID = "foo" 1626 if i%2 == 0 { 1627 alloc.DesiredStatus = structs.AllocDesiredStatusStop 1628 term = append(term, alloc) 1629 } else { 1630 nonterm = append(nonterm, alloc) 1631 } 1632 allocs = append(allocs, alloc) 1633 } 1634 1635 err := state.UpsertAllocs(1000, allocs) 1636 if err != nil { 1637 t.Fatalf("err: %v", err) 1638 } 1639 1640 // Verify the terminal allocs 1641 out, err := state.AllocsByNodeTerminal("foo", true) 1642 if err != nil { 1643 t.Fatalf("err: %v", err) 1644 } 1645 1646 sort.Sort(AllocIDSort(term)) 1647 sort.Sort(AllocIDSort(out)) 1648 1649 if !reflect.DeepEqual(term, out) { 1650 t.Fatalf("bad: %#v %#v", term, out) 1651 } 1652 1653 // Verify the non-terminal allocs 1654 out, err = state.AllocsByNodeTerminal("foo", false) 1655 if err != nil { 1656 t.Fatalf("err: %v", err) 1657 } 1658 1659 sort.Sort(AllocIDSort(nonterm)) 1660 sort.Sort(AllocIDSort(out)) 1661 1662 if !reflect.DeepEqual(nonterm, out) { 1663 t.Fatalf("bad: %#v %#v", nonterm, out) 1664 } 1665 } 1666 1667 func TestStateStore_AllocsByJob(t *testing.T) { 1668 state := testStateStore(t) 1669 var allocs []*structs.Allocation 1670 1671 for i := 0; i < 10; i++ { 1672 alloc := mock.Alloc() 1673 alloc.JobID = "foo" 1674 allocs = append(allocs, alloc) 1675 } 1676 1677 err := state.UpsertAllocs(1000, allocs) 1678 if err != nil { 1679 t.Fatalf("err: %v", err) 1680 } 1681 1682 out, err := state.AllocsByJob("foo") 1683 if err != nil { 1684 t.Fatalf("err: %v", err) 1685 } 1686 1687 sort.Sort(AllocIDSort(allocs)) 1688 sort.Sort(AllocIDSort(out)) 1689 1690 if !reflect.DeepEqual(allocs, out) { 1691 t.Fatalf("bad: %#v %#v", allocs, out) 1692 } 1693 } 1694 1695 func TestStateStore_AllocsByIDPrefix(t *testing.T) { 1696 state := testStateStore(t) 1697 var allocs []*structs.Allocation 1698 1699 ids := []string{ 1700 "aaaaaaaa-7bfb-395d-eb95-0685af2176b2", 1701 "aaaaaaab-7bfb-395d-eb95-0685af2176b2", 1702 "aaaaaabb-7bfb-395d-eb95-0685af2176b2", 1703 "aaaaabbb-7bfb-395d-eb95-0685af2176b2", 1704 "aaaabbbb-7bfb-395d-eb95-0685af2176b2", 1705 "aaabbbbb-7bfb-395d-eb95-0685af2176b2", 1706 "aabbbbbb-7bfb-395d-eb95-0685af2176b2", 1707 "abbbbbbb-7bfb-395d-eb95-0685af2176b2", 1708 "bbbbbbbb-7bfb-395d-eb95-0685af2176b2", 1709 } 1710 for i := 0; i < 9; i++ { 1711 alloc := mock.Alloc() 1712 alloc.ID = ids[i] 1713 allocs = append(allocs, alloc) 1714 } 1715 1716 err := state.UpsertAllocs(1000, allocs) 1717 if err != nil { 1718 t.Fatalf("err: %v", err) 1719 } 1720 1721 iter, err := state.AllocsByIDPrefix("aaaa") 1722 if err != nil { 1723 t.Fatalf("err: %v", err) 1724 } 1725 1726 gatherAllocs := func(iter memdb.ResultIterator) []*structs.Allocation { 1727 var allocs []*structs.Allocation 1728 for { 1729 raw := iter.Next() 1730 if raw == nil { 1731 break 1732 } 1733 allocs = append(allocs, raw.(*structs.Allocation)) 1734 } 1735 return allocs 1736 } 1737 1738 out := gatherAllocs(iter) 1739 if len(out) != 5 { 1740 t.Fatalf("bad: expected five allocations, got: %#v", out) 1741 } 1742 1743 sort.Sort(AllocIDSort(allocs)) 1744 1745 for index, alloc := range out { 1746 if ids[index] != alloc.ID { 1747 t.Fatalf("bad: got unexpected id: %s", alloc.ID) 1748 } 1749 } 1750 1751 iter, err = state.AllocsByIDPrefix("b-a7bfb") 1752 if err != nil { 1753 t.Fatalf("err: %v", err) 1754 } 1755 1756 out = gatherAllocs(iter) 1757 if len(out) != 0 { 1758 t.Fatalf("bad: unexpected zero allocations, got: %#v", out) 1759 } 1760 } 1761 1762 func TestStateStore_Allocs(t *testing.T) { 1763 state := testStateStore(t) 1764 var allocs []*structs.Allocation 1765 1766 for i := 0; i < 10; i++ { 1767 alloc := mock.Alloc() 1768 allocs = append(allocs, alloc) 1769 } 1770 1771 err := state.UpsertAllocs(1000, allocs) 1772 if err != nil { 1773 t.Fatalf("err: %v", err) 1774 } 1775 1776 iter, err := state.Allocs() 1777 if err != nil { 1778 t.Fatalf("err: %v", err) 1779 } 1780 1781 var out []*structs.Allocation 1782 for { 1783 raw := iter.Next() 1784 if raw == nil { 1785 break 1786 } 1787 out = append(out, raw.(*structs.Allocation)) 1788 } 1789 1790 sort.Sort(AllocIDSort(allocs)) 1791 sort.Sort(AllocIDSort(out)) 1792 1793 if !reflect.DeepEqual(allocs, out) { 1794 t.Fatalf("bad: %#v %#v", allocs, out) 1795 } 1796 } 1797 1798 func TestStateStore_RestoreAlloc(t *testing.T) { 1799 state := testStateStore(t) 1800 alloc := mock.Alloc() 1801 1802 notify := setupNotifyTest( 1803 state, 1804 watch.Item{Table: "allocs"}, 1805 watch.Item{Alloc: alloc.ID}, 1806 watch.Item{AllocEval: alloc.EvalID}, 1807 watch.Item{AllocJob: alloc.JobID}, 1808 watch.Item{AllocNode: alloc.NodeID}) 1809 1810 restore, err := state.Restore() 1811 if err != nil { 1812 t.Fatalf("err: %v", err) 1813 } 1814 1815 err = restore.AllocRestore(alloc) 1816 if err != nil { 1817 t.Fatalf("err: %v", err) 1818 } 1819 1820 restore.Commit() 1821 1822 out, err := state.AllocByID(alloc.ID) 1823 if err != nil { 1824 t.Fatalf("err: %v", err) 1825 } 1826 1827 if !reflect.DeepEqual(out, alloc) { 1828 t.Fatalf("Bad: %#v %#v", out, alloc) 1829 } 1830 1831 notify.verify(t) 1832 } 1833 1834 func TestStateStore_SetJobStatus_ForceStatus(t *testing.T) { 1835 state := testStateStore(t) 1836 watcher := watch.NewItems() 1837 txn := state.db.Txn(true) 1838 1839 // Create and insert a mock job. 1840 job := mock.Job() 1841 job.Status = "" 1842 job.ModifyIndex = 0 1843 if err := txn.Insert("jobs", job); err != nil { 1844 t.Fatalf("job insert failed: %v", err) 1845 } 1846 1847 exp := "foobar" 1848 index := uint64(1000) 1849 if err := state.setJobStatus(index, watcher, txn, job, false, exp); err != nil { 1850 t.Fatalf("setJobStatus() failed: %v", err) 1851 } 1852 1853 i, err := txn.First("jobs", "id", job.ID) 1854 if err != nil { 1855 t.Fatalf("job lookup failed: %v", err) 1856 } 1857 updated := i.(*structs.Job) 1858 1859 if updated.Status != exp { 1860 t.Fatalf("setJobStatus() set %v; expected %v", updated.Status, exp) 1861 } 1862 1863 if updated.ModifyIndex != index { 1864 t.Fatalf("setJobStatus() set %d; expected %d", updated.ModifyIndex, index) 1865 } 1866 } 1867 1868 func TestStateStore_SetJobStatus_NoOp(t *testing.T) { 1869 state := testStateStore(t) 1870 watcher := watch.NewItems() 1871 txn := state.db.Txn(true) 1872 1873 // Create and insert a mock job that should be pending. 1874 job := mock.Job() 1875 job.Status = structs.JobStatusPending 1876 job.ModifyIndex = 10 1877 if err := txn.Insert("jobs", job); err != nil { 1878 t.Fatalf("job insert failed: %v", err) 1879 } 1880 1881 index := uint64(1000) 1882 if err := state.setJobStatus(index, watcher, txn, job, false, ""); err != nil { 1883 t.Fatalf("setJobStatus() failed: %v", err) 1884 } 1885 1886 i, err := txn.First("jobs", "id", job.ID) 1887 if err != nil { 1888 t.Fatalf("job lookup failed: %v", err) 1889 } 1890 updated := i.(*structs.Job) 1891 1892 if updated.ModifyIndex == index { 1893 t.Fatalf("setJobStatus() should have been a no-op") 1894 } 1895 } 1896 1897 func TestStateStore_SetJobStatus(t *testing.T) { 1898 state := testStateStore(t) 1899 watcher := watch.NewItems() 1900 txn := state.db.Txn(true) 1901 1902 // Create and insert a mock job that should be pending but has an incorrect 1903 // status. 1904 job := mock.Job() 1905 job.Status = "foobar" 1906 job.ModifyIndex = 10 1907 if err := txn.Insert("jobs", job); err != nil { 1908 t.Fatalf("job insert failed: %v", err) 1909 } 1910 1911 index := uint64(1000) 1912 if err := state.setJobStatus(index, watcher, txn, job, false, ""); err != nil { 1913 t.Fatalf("setJobStatus() failed: %v", err) 1914 } 1915 1916 i, err := txn.First("jobs", "id", job.ID) 1917 if err != nil { 1918 t.Fatalf("job lookup failed: %v", err) 1919 } 1920 updated := i.(*structs.Job) 1921 1922 if updated.Status != structs.JobStatusPending { 1923 t.Fatalf("setJobStatus() set %v; expected %v", updated.Status, structs.JobStatusPending) 1924 } 1925 1926 if updated.ModifyIndex != index { 1927 t.Fatalf("setJobStatus() set %d; expected %d", updated.ModifyIndex, index) 1928 } 1929 } 1930 1931 func TestStateStore_GetJobStatus_NoEvalsOrAllocs(t *testing.T) { 1932 job := mock.Job() 1933 state := testStateStore(t) 1934 txn := state.db.Txn(false) 1935 status, err := state.getJobStatus(txn, job, false) 1936 if err != nil { 1937 t.Fatalf("getJobStatus() failed: %v", err) 1938 } 1939 1940 if status != structs.JobStatusPending { 1941 t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusPending) 1942 } 1943 } 1944 1945 func TestStateStore_GetJobStatus_NoEvalsOrAllocs_Periodic(t *testing.T) { 1946 job := mock.PeriodicJob() 1947 state := testStateStore(t) 1948 txn := state.db.Txn(false) 1949 status, err := state.getJobStatus(txn, job, false) 1950 if err != nil { 1951 t.Fatalf("getJobStatus() failed: %v", err) 1952 } 1953 1954 if status != structs.JobStatusRunning { 1955 t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusRunning) 1956 } 1957 } 1958 1959 func TestStateStore_GetJobStatus_NoEvalsOrAllocs_EvalDelete(t *testing.T) { 1960 job := mock.Job() 1961 state := testStateStore(t) 1962 txn := state.db.Txn(false) 1963 status, err := state.getJobStatus(txn, job, true) 1964 if err != nil { 1965 t.Fatalf("getJobStatus() failed: %v", err) 1966 } 1967 1968 if status != structs.JobStatusDead { 1969 t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusDead) 1970 } 1971 } 1972 1973 func TestStateStore_GetJobStatus_DeadEvalsAndAllocs(t *testing.T) { 1974 state := testStateStore(t) 1975 job := mock.Job() 1976 1977 // Create a mock alloc that is dead. 1978 alloc := mock.Alloc() 1979 alloc.JobID = job.ID 1980 alloc.DesiredStatus = structs.AllocDesiredStatusFailed 1981 if err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}); err != nil { 1982 t.Fatalf("err: %v", err) 1983 } 1984 1985 // Create a mock eval that is complete 1986 eval := mock.Eval() 1987 eval.JobID = job.ID 1988 eval.Status = structs.EvalStatusComplete 1989 if err := state.UpsertEvals(1001, []*structs.Evaluation{eval}); err != nil { 1990 t.Fatalf("err: %v", err) 1991 } 1992 1993 txn := state.db.Txn(false) 1994 status, err := state.getJobStatus(txn, job, false) 1995 if err != nil { 1996 t.Fatalf("getJobStatus() failed: %v", err) 1997 } 1998 1999 if status != structs.JobStatusDead { 2000 t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusDead) 2001 } 2002 } 2003 2004 func TestStateStore_GetJobStatus_RunningAlloc(t *testing.T) { 2005 state := testStateStore(t) 2006 job := mock.Job() 2007 2008 // Create a mock alloc that is running. 2009 alloc := mock.Alloc() 2010 alloc.JobID = job.ID 2011 alloc.DesiredStatus = structs.AllocDesiredStatusRun 2012 if err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}); err != nil { 2013 t.Fatalf("err: %v", err) 2014 } 2015 2016 txn := state.db.Txn(false) 2017 status, err := state.getJobStatus(txn, job, true) 2018 if err != nil { 2019 t.Fatalf("getJobStatus() failed: %v", err) 2020 } 2021 2022 if status != structs.JobStatusRunning { 2023 t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusRunning) 2024 } 2025 } 2026 2027 func TestStateStore_SetJobStatus_PendingEval(t *testing.T) { 2028 state := testStateStore(t) 2029 job := mock.Job() 2030 2031 // Create a mock eval that is pending. 2032 eval := mock.Eval() 2033 eval.JobID = job.ID 2034 eval.Status = structs.EvalStatusPending 2035 if err := state.UpsertEvals(1000, []*structs.Evaluation{eval}); err != nil { 2036 t.Fatalf("err: %v", err) 2037 } 2038 2039 txn := state.db.Txn(false) 2040 status, err := state.getJobStatus(txn, job, true) 2041 if err != nil { 2042 t.Fatalf("getJobStatus() failed: %v", err) 2043 } 2044 2045 if status != structs.JobStatusPending { 2046 t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusPending) 2047 } 2048 } 2049 2050 func TestStateWatch_watch(t *testing.T) { 2051 sw := newStateWatch() 2052 notify1 := make(chan struct{}, 1) 2053 notify2 := make(chan struct{}, 1) 2054 notify3 := make(chan struct{}, 1) 2055 2056 // Notifications trigger subscribed channels 2057 sw.watch(watch.NewItems(watch.Item{Table: "foo"}), notify1) 2058 sw.watch(watch.NewItems(watch.Item{Table: "bar"}), notify2) 2059 sw.watch(watch.NewItems(watch.Item{Table: "baz"}), notify3) 2060 2061 items := watch.NewItems() 2062 items.Add(watch.Item{Table: "foo"}) 2063 items.Add(watch.Item{Table: "bar"}) 2064 2065 sw.notify(items) 2066 if len(notify1) != 1 { 2067 t.Fatalf("should notify") 2068 } 2069 if len(notify2) != 1 { 2070 t.Fatalf("should notify") 2071 } 2072 if len(notify3) != 0 { 2073 t.Fatalf("should not notify") 2074 } 2075 } 2076 2077 func TestStateWatch_stopWatch(t *testing.T) { 2078 sw := newStateWatch() 2079 notify := make(chan struct{}) 2080 2081 // First subscribe 2082 sw.watch(watch.NewItems(watch.Item{Table: "foo"}), notify) 2083 2084 // Unsubscribe stop notifications 2085 sw.stopWatch(watch.NewItems(watch.Item{Table: "foo"}), notify) 2086 2087 // Check that the group was removed 2088 if _, ok := sw.items[watch.Item{Table: "foo"}]; ok { 2089 t.Fatalf("should remove group") 2090 } 2091 2092 // Check that we are not notified 2093 sw.notify(watch.NewItems(watch.Item{Table: "foo"})) 2094 if len(notify) != 0 { 2095 t.Fatalf("should not notify") 2096 } 2097 } 2098 2099 // setupNotifyTest takes a state store and a set of watch items, then creates 2100 // and subscribes a notification channel for each item. 2101 func setupNotifyTest(state *StateStore, items ...watch.Item) notifyTest { 2102 var n notifyTest 2103 for _, item := range items { 2104 ch := make(chan struct{}, 1) 2105 state.Watch(watch.NewItems(item), ch) 2106 n = append(n, ¬ifyTestCase{item, ch}) 2107 } 2108 return n 2109 } 2110 2111 // notifyTestCase is used to set up and verify watch triggers. 2112 type notifyTestCase struct { 2113 item watch.Item 2114 ch chan struct{} 2115 } 2116 2117 // notifyTest is a suite of notifyTestCases. 2118 type notifyTest []*notifyTestCase 2119 2120 // verify ensures that each channel received a notification. 2121 func (n notifyTest) verify(t *testing.T) { 2122 for _, tcase := range n { 2123 if len(tcase.ch) != 1 { 2124 t.Fatalf("should notify %#v", tcase.item) 2125 } 2126 } 2127 } 2128 2129 // NodeIDSort is used to sort nodes by ID 2130 type NodeIDSort []*structs.Node 2131 2132 func (n NodeIDSort) Len() int { 2133 return len(n) 2134 } 2135 2136 func (n NodeIDSort) Less(i, j int) bool { 2137 return n[i].ID < n[j].ID 2138 } 2139 2140 func (n NodeIDSort) Swap(i, j int) { 2141 n[i], n[j] = n[j], n[i] 2142 } 2143 2144 // JobIDis used to sort jobs by id 2145 type JobIDSort []*structs.Job 2146 2147 func (n JobIDSort) Len() int { 2148 return len(n) 2149 } 2150 2151 func (n JobIDSort) Less(i, j int) bool { 2152 return n[i].ID < n[j].ID 2153 } 2154 2155 func (n JobIDSort) Swap(i, j int) { 2156 n[i], n[j] = n[j], n[i] 2157 } 2158 2159 // EvalIDis used to sort evals by id 2160 type EvalIDSort []*structs.Evaluation 2161 2162 func (n EvalIDSort) Len() int { 2163 return len(n) 2164 } 2165 2166 func (n EvalIDSort) Less(i, j int) bool { 2167 return n[i].ID < n[j].ID 2168 } 2169 2170 func (n EvalIDSort) Swap(i, j int) { 2171 n[i], n[j] = n[j], n[i] 2172 } 2173 2174 // AllocIDsort used to sort allocations by id 2175 type AllocIDSort []*structs.Allocation 2176 2177 func (n AllocIDSort) Len() int { 2178 return len(n) 2179 } 2180 2181 func (n AllocIDSort) Less(i, j int) bool { 2182 return n[i].ID < n[j].ID 2183 } 2184 2185 func (n AllocIDSort) Swap(i, j int) { 2186 n[i], n[j] = n[j], n[i] 2187 }