github.com/ryanslade/nomad@v0.2.4-0.20160128061903-fc95782f2089/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_UpdateAllocFromClient(t *testing.T) { 1385 state := testStateStore(t) 1386 alloc := mock.Alloc() 1387 1388 notify := setupNotifyTest( 1389 state, 1390 watch.Item{Table: "allocs"}, 1391 watch.Item{Alloc: alloc.ID}, 1392 watch.Item{AllocEval: alloc.EvalID}, 1393 watch.Item{AllocJob: alloc.JobID}, 1394 watch.Item{AllocNode: alloc.NodeID}) 1395 1396 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}) 1397 if err != nil { 1398 t.Fatalf("err: %v", err) 1399 } 1400 1401 update := new(structs.Allocation) 1402 *update = *alloc 1403 update.ClientStatus = structs.AllocClientStatusFailed 1404 1405 err = state.UpdateAllocFromClient(1001, update) 1406 if err != nil { 1407 t.Fatalf("err: %v", err) 1408 } 1409 1410 out, err := state.AllocByID(alloc.ID) 1411 if err != nil { 1412 t.Fatalf("err: %v", err) 1413 } 1414 1415 update.ModifyIndex = 1001 1416 if !reflect.DeepEqual(update, out) { 1417 t.Fatalf("bad: %#v %#v", update, out) 1418 } 1419 1420 index, err := state.Index("allocs") 1421 if err != nil { 1422 t.Fatalf("err: %v", err) 1423 } 1424 if index != 1001 { 1425 t.Fatalf("bad: %d", index) 1426 } 1427 1428 notify.verify(t) 1429 } 1430 1431 func TestStateStore_UpsertAlloc_Alloc(t *testing.T) { 1432 state := testStateStore(t) 1433 alloc := mock.Alloc() 1434 1435 notify := setupNotifyTest( 1436 state, 1437 watch.Item{Table: "allocs"}, 1438 watch.Item{Alloc: alloc.ID}, 1439 watch.Item{AllocEval: alloc.EvalID}, 1440 watch.Item{AllocJob: alloc.JobID}, 1441 watch.Item{AllocNode: alloc.NodeID}) 1442 1443 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}) 1444 if err != nil { 1445 t.Fatalf("err: %v", err) 1446 } 1447 1448 out, err := state.AllocByID(alloc.ID) 1449 if err != nil { 1450 t.Fatalf("err: %v", err) 1451 } 1452 1453 if !reflect.DeepEqual(alloc, out) { 1454 t.Fatalf("bad: %#v %#v", alloc, out) 1455 } 1456 1457 index, err := state.Index("allocs") 1458 if err != nil { 1459 t.Fatalf("err: %v", err) 1460 } 1461 if index != 1000 { 1462 t.Fatalf("bad: %d", index) 1463 } 1464 1465 notify.verify(t) 1466 } 1467 1468 func TestStateStore_UpdateAlloc_Alloc(t *testing.T) { 1469 state := testStateStore(t) 1470 alloc := mock.Alloc() 1471 1472 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}) 1473 if err != nil { 1474 t.Fatalf("err: %v", err) 1475 } 1476 1477 alloc2 := mock.Alloc() 1478 alloc2.ID = alloc.ID 1479 alloc2.NodeID = alloc.NodeID + ".new" 1480 1481 notify := setupNotifyTest( 1482 state, 1483 watch.Item{Table: "allocs"}, 1484 watch.Item{Alloc: alloc2.ID}, 1485 watch.Item{AllocEval: alloc2.EvalID}, 1486 watch.Item{AllocJob: alloc2.JobID}, 1487 watch.Item{AllocNode: alloc2.NodeID}) 1488 1489 err = state.UpsertAllocs(1001, []*structs.Allocation{alloc2}) 1490 if err != nil { 1491 t.Fatalf("err: %v", err) 1492 } 1493 1494 out, err := state.AllocByID(alloc.ID) 1495 if err != nil { 1496 t.Fatalf("err: %v", err) 1497 } 1498 1499 if !reflect.DeepEqual(alloc2, out) { 1500 t.Fatalf("bad: %#v %#v", alloc2, out) 1501 } 1502 1503 if out.CreateIndex != 1000 { 1504 t.Fatalf("bad: %#v", out) 1505 } 1506 if out.ModifyIndex != 1001 { 1507 t.Fatalf("bad: %#v", out) 1508 } 1509 1510 index, err := state.Index("allocs") 1511 if err != nil { 1512 t.Fatalf("err: %v", err) 1513 } 1514 if index != 1001 { 1515 t.Fatalf("bad: %d", index) 1516 } 1517 1518 notify.verify(t) 1519 } 1520 1521 func TestStateStore_EvictAlloc_Alloc(t *testing.T) { 1522 state := testStateStore(t) 1523 alloc := mock.Alloc() 1524 1525 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}) 1526 if err != nil { 1527 t.Fatalf("err: %v", err) 1528 } 1529 1530 alloc2 := new(structs.Allocation) 1531 *alloc2 = *alloc 1532 alloc2.DesiredStatus = structs.AllocDesiredStatusEvict 1533 err = state.UpsertAllocs(1001, []*structs.Allocation{alloc2}) 1534 if err != nil { 1535 t.Fatalf("err: %v", err) 1536 } 1537 1538 out, err := state.AllocByID(alloc.ID) 1539 if err != nil { 1540 t.Fatalf("err: %v", err) 1541 } 1542 1543 if out.DesiredStatus != structs.AllocDesiredStatusEvict { 1544 t.Fatalf("bad: %#v %#v", alloc, out) 1545 } 1546 1547 index, err := state.Index("allocs") 1548 if err != nil { 1549 t.Fatalf("err: %v", err) 1550 } 1551 if index != 1001 { 1552 t.Fatalf("bad: %d", index) 1553 } 1554 } 1555 1556 func TestStateStore_AllocsByNode(t *testing.T) { 1557 state := testStateStore(t) 1558 var allocs []*structs.Allocation 1559 1560 for i := 0; i < 10; i++ { 1561 alloc := mock.Alloc() 1562 alloc.NodeID = "foo" 1563 allocs = append(allocs, alloc) 1564 } 1565 1566 err := state.UpsertAllocs(1000, allocs) 1567 if err != nil { 1568 t.Fatalf("err: %v", err) 1569 } 1570 1571 out, err := state.AllocsByNode("foo") 1572 if err != nil { 1573 t.Fatalf("err: %v", err) 1574 } 1575 1576 sort.Sort(AllocIDSort(allocs)) 1577 sort.Sort(AllocIDSort(out)) 1578 1579 if !reflect.DeepEqual(allocs, out) { 1580 t.Fatalf("bad: %#v %#v", allocs, out) 1581 } 1582 } 1583 1584 func TestStateStore_AllocsByJob(t *testing.T) { 1585 state := testStateStore(t) 1586 var allocs []*structs.Allocation 1587 1588 for i := 0; i < 10; i++ { 1589 alloc := mock.Alloc() 1590 alloc.JobID = "foo" 1591 allocs = append(allocs, alloc) 1592 } 1593 1594 err := state.UpsertAllocs(1000, allocs) 1595 if err != nil { 1596 t.Fatalf("err: %v", err) 1597 } 1598 1599 out, err := state.AllocsByJob("foo") 1600 if err != nil { 1601 t.Fatalf("err: %v", err) 1602 } 1603 1604 sort.Sort(AllocIDSort(allocs)) 1605 sort.Sort(AllocIDSort(out)) 1606 1607 if !reflect.DeepEqual(allocs, out) { 1608 t.Fatalf("bad: %#v %#v", allocs, out) 1609 } 1610 } 1611 1612 func TestStateStore_AllocsByIDPrefix(t *testing.T) { 1613 state := testStateStore(t) 1614 var allocs []*structs.Allocation 1615 1616 ids := []string{ 1617 "aaaaaaaa-7bfb-395d-eb95-0685af2176b2", 1618 "aaaaaaab-7bfb-395d-eb95-0685af2176b2", 1619 "aaaaaabb-7bfb-395d-eb95-0685af2176b2", 1620 "aaaaabbb-7bfb-395d-eb95-0685af2176b2", 1621 "aaaabbbb-7bfb-395d-eb95-0685af2176b2", 1622 "aaabbbbb-7bfb-395d-eb95-0685af2176b2", 1623 "aabbbbbb-7bfb-395d-eb95-0685af2176b2", 1624 "abbbbbbb-7bfb-395d-eb95-0685af2176b2", 1625 "bbbbbbbb-7bfb-395d-eb95-0685af2176b2", 1626 } 1627 for i := 0; i < 9; i++ { 1628 alloc := mock.Alloc() 1629 alloc.ID = ids[i] 1630 allocs = append(allocs, alloc) 1631 } 1632 1633 err := state.UpsertAllocs(1000, allocs) 1634 if err != nil { 1635 t.Fatalf("err: %v", err) 1636 } 1637 1638 iter, err := state.AllocsByIDPrefix("aaaa") 1639 if err != nil { 1640 t.Fatalf("err: %v", err) 1641 } 1642 1643 gatherAllocs := func(iter memdb.ResultIterator) []*structs.Allocation { 1644 var allocs []*structs.Allocation 1645 for { 1646 raw := iter.Next() 1647 if raw == nil { 1648 break 1649 } 1650 allocs = append(allocs, raw.(*structs.Allocation)) 1651 } 1652 return allocs 1653 } 1654 1655 out := gatherAllocs(iter) 1656 if len(out) != 5 { 1657 t.Fatalf("bad: expected five allocations, got: %#v", out) 1658 } 1659 1660 sort.Sort(AllocIDSort(allocs)) 1661 1662 for index, alloc := range out { 1663 if ids[index] != alloc.ID { 1664 t.Fatalf("bad: got unexpected id: %s", alloc.ID) 1665 } 1666 } 1667 1668 iter, err = state.AllocsByIDPrefix("b-a7bfb") 1669 if err != nil { 1670 t.Fatalf("err: %v", err) 1671 } 1672 1673 out = gatherAllocs(iter) 1674 if len(out) != 0 { 1675 t.Fatalf("bad: unexpected zero allocations, got: %#v", out) 1676 } 1677 } 1678 1679 func TestStateStore_Allocs(t *testing.T) { 1680 state := testStateStore(t) 1681 var allocs []*structs.Allocation 1682 1683 for i := 0; i < 10; i++ { 1684 alloc := mock.Alloc() 1685 allocs = append(allocs, alloc) 1686 } 1687 1688 err := state.UpsertAllocs(1000, allocs) 1689 if err != nil { 1690 t.Fatalf("err: %v", err) 1691 } 1692 1693 iter, err := state.Allocs() 1694 if err != nil { 1695 t.Fatalf("err: %v", err) 1696 } 1697 1698 var out []*structs.Allocation 1699 for { 1700 raw := iter.Next() 1701 if raw == nil { 1702 break 1703 } 1704 out = append(out, raw.(*structs.Allocation)) 1705 } 1706 1707 sort.Sort(AllocIDSort(allocs)) 1708 sort.Sort(AllocIDSort(out)) 1709 1710 if !reflect.DeepEqual(allocs, out) { 1711 t.Fatalf("bad: %#v %#v", allocs, out) 1712 } 1713 } 1714 1715 func TestStateStore_RestoreAlloc(t *testing.T) { 1716 state := testStateStore(t) 1717 alloc := mock.Alloc() 1718 1719 notify := setupNotifyTest( 1720 state, 1721 watch.Item{Table: "allocs"}, 1722 watch.Item{Alloc: alloc.ID}, 1723 watch.Item{AllocEval: alloc.EvalID}, 1724 watch.Item{AllocJob: alloc.JobID}, 1725 watch.Item{AllocNode: alloc.NodeID}) 1726 1727 restore, err := state.Restore() 1728 if err != nil { 1729 t.Fatalf("err: %v", err) 1730 } 1731 1732 err = restore.AllocRestore(alloc) 1733 if err != nil { 1734 t.Fatalf("err: %v", err) 1735 } 1736 1737 restore.Commit() 1738 1739 out, err := state.AllocByID(alloc.ID) 1740 if err != nil { 1741 t.Fatalf("err: %v", err) 1742 } 1743 1744 if !reflect.DeepEqual(out, alloc) { 1745 t.Fatalf("Bad: %#v %#v", out, alloc) 1746 } 1747 1748 notify.verify(t) 1749 } 1750 1751 func TestStateStore_SetJobStatus_ForceStatus(t *testing.T) { 1752 state := testStateStore(t) 1753 watcher := watch.NewItems() 1754 txn := state.db.Txn(true) 1755 1756 // Create and insert a mock job. 1757 job := mock.Job() 1758 job.Status = "" 1759 job.ModifyIndex = 0 1760 if err := txn.Insert("jobs", job); err != nil { 1761 t.Fatalf("job insert failed: %v", err) 1762 } 1763 1764 exp := "foobar" 1765 index := uint64(1000) 1766 if err := state.setJobStatus(index, watcher, txn, job, false, exp); err != nil { 1767 t.Fatalf("setJobStatus() failed: %v", err) 1768 } 1769 1770 i, err := txn.First("jobs", "id", job.ID) 1771 if err != nil { 1772 t.Fatalf("job lookup failed: %v", err) 1773 } 1774 updated := i.(*structs.Job) 1775 1776 if updated.Status != exp { 1777 t.Fatalf("setJobStatus() set %v; expected %v", updated.Status, exp) 1778 } 1779 1780 if updated.ModifyIndex != index { 1781 t.Fatalf("setJobStatus() set %d; expected %d", updated.ModifyIndex, index) 1782 } 1783 } 1784 1785 func TestStateStore_SetJobStatus_NoOp(t *testing.T) { 1786 state := testStateStore(t) 1787 watcher := watch.NewItems() 1788 txn := state.db.Txn(true) 1789 1790 // Create and insert a mock job that should be pending. 1791 job := mock.Job() 1792 job.Status = structs.JobStatusPending 1793 job.ModifyIndex = 10 1794 if err := txn.Insert("jobs", job); err != nil { 1795 t.Fatalf("job insert failed: %v", err) 1796 } 1797 1798 index := uint64(1000) 1799 if err := state.setJobStatus(index, watcher, txn, job, false, ""); err != nil { 1800 t.Fatalf("setJobStatus() failed: %v", err) 1801 } 1802 1803 i, err := txn.First("jobs", "id", job.ID) 1804 if err != nil { 1805 t.Fatalf("job lookup failed: %v", err) 1806 } 1807 updated := i.(*structs.Job) 1808 1809 if updated.ModifyIndex == index { 1810 t.Fatalf("setJobStatus() should have been a no-op") 1811 } 1812 } 1813 1814 func TestStateStore_SetJobStatus(t *testing.T) { 1815 state := testStateStore(t) 1816 watcher := watch.NewItems() 1817 txn := state.db.Txn(true) 1818 1819 // Create and insert a mock job that should be pending but has an incorrect 1820 // status. 1821 job := mock.Job() 1822 job.Status = "foobar" 1823 job.ModifyIndex = 10 1824 if err := txn.Insert("jobs", job); err != nil { 1825 t.Fatalf("job insert failed: %v", err) 1826 } 1827 1828 index := uint64(1000) 1829 if err := state.setJobStatus(index, watcher, txn, job, false, ""); err != nil { 1830 t.Fatalf("setJobStatus() failed: %v", err) 1831 } 1832 1833 i, err := txn.First("jobs", "id", job.ID) 1834 if err != nil { 1835 t.Fatalf("job lookup failed: %v", err) 1836 } 1837 updated := i.(*structs.Job) 1838 1839 if updated.Status != structs.JobStatusPending { 1840 t.Fatalf("setJobStatus() set %v; expected %v", updated.Status, structs.JobStatusPending) 1841 } 1842 1843 if updated.ModifyIndex != index { 1844 t.Fatalf("setJobStatus() set %d; expected %d", updated.ModifyIndex, index) 1845 } 1846 } 1847 1848 func TestStateStore_GetJobStatus_NoEvalsOrAllocs(t *testing.T) { 1849 job := mock.Job() 1850 state := testStateStore(t) 1851 txn := state.db.Txn(false) 1852 status, err := state.getJobStatus(txn, job, false) 1853 if err != nil { 1854 t.Fatalf("getJobStatus() failed: %v", err) 1855 } 1856 1857 if status != structs.JobStatusPending { 1858 t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusPending) 1859 } 1860 } 1861 1862 func TestStateStore_GetJobStatus_NoEvalsOrAllocs_Periodic(t *testing.T) { 1863 job := mock.PeriodicJob() 1864 state := testStateStore(t) 1865 txn := state.db.Txn(false) 1866 status, err := state.getJobStatus(txn, job, false) 1867 if err != nil { 1868 t.Fatalf("getJobStatus() failed: %v", err) 1869 } 1870 1871 if status != structs.JobStatusRunning { 1872 t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusRunning) 1873 } 1874 } 1875 1876 func TestStateStore_GetJobStatus_NoEvalsOrAllocs_EvalDelete(t *testing.T) { 1877 job := mock.Job() 1878 state := testStateStore(t) 1879 txn := state.db.Txn(false) 1880 status, err := state.getJobStatus(txn, job, true) 1881 if err != nil { 1882 t.Fatalf("getJobStatus() failed: %v", err) 1883 } 1884 1885 if status != structs.JobStatusDead { 1886 t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusDead) 1887 } 1888 } 1889 1890 func TestStateStore_GetJobStatus_DeadEvalsAndAllocs(t *testing.T) { 1891 state := testStateStore(t) 1892 job := mock.Job() 1893 1894 // Create a mock alloc that is dead. 1895 alloc := mock.Alloc() 1896 alloc.JobID = job.ID 1897 alloc.DesiredStatus = structs.AllocDesiredStatusFailed 1898 if err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}); err != nil { 1899 t.Fatalf("err: %v", err) 1900 } 1901 1902 // Create a mock eval that is complete 1903 eval := mock.Eval() 1904 eval.JobID = job.ID 1905 eval.Status = structs.EvalStatusComplete 1906 if err := state.UpsertEvals(1001, []*structs.Evaluation{eval}); err != nil { 1907 t.Fatalf("err: %v", err) 1908 } 1909 1910 txn := state.db.Txn(false) 1911 status, err := state.getJobStatus(txn, job, false) 1912 if err != nil { 1913 t.Fatalf("getJobStatus() failed: %v", err) 1914 } 1915 1916 if status != structs.JobStatusDead { 1917 t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusDead) 1918 } 1919 } 1920 1921 func TestStateStore_GetJobStatus_RunningAlloc(t *testing.T) { 1922 state := testStateStore(t) 1923 job := mock.Job() 1924 1925 // Create a mock alloc that is running. 1926 alloc := mock.Alloc() 1927 alloc.JobID = job.ID 1928 alloc.DesiredStatus = structs.AllocDesiredStatusRun 1929 if err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}); err != nil { 1930 t.Fatalf("err: %v", err) 1931 } 1932 1933 txn := state.db.Txn(false) 1934 status, err := state.getJobStatus(txn, job, true) 1935 if err != nil { 1936 t.Fatalf("getJobStatus() failed: %v", err) 1937 } 1938 1939 if status != structs.JobStatusRunning { 1940 t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusRunning) 1941 } 1942 } 1943 1944 func TestStateStore_SetJobStatus_PendingEval(t *testing.T) { 1945 state := testStateStore(t) 1946 job := mock.Job() 1947 1948 // Create a mock eval that is pending. 1949 eval := mock.Eval() 1950 eval.JobID = job.ID 1951 eval.Status = structs.EvalStatusPending 1952 if err := state.UpsertEvals(1000, []*structs.Evaluation{eval}); err != nil { 1953 t.Fatalf("err: %v", err) 1954 } 1955 1956 txn := state.db.Txn(false) 1957 status, err := state.getJobStatus(txn, job, true) 1958 if err != nil { 1959 t.Fatalf("getJobStatus() failed: %v", err) 1960 } 1961 1962 if status != structs.JobStatusPending { 1963 t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusPending) 1964 } 1965 } 1966 1967 func TestStateWatch_watch(t *testing.T) { 1968 sw := newStateWatch() 1969 notify1 := make(chan struct{}, 1) 1970 notify2 := make(chan struct{}, 1) 1971 notify3 := make(chan struct{}, 1) 1972 1973 // Notifications trigger subscribed channels 1974 sw.watch(watch.NewItems(watch.Item{Table: "foo"}), notify1) 1975 sw.watch(watch.NewItems(watch.Item{Table: "bar"}), notify2) 1976 sw.watch(watch.NewItems(watch.Item{Table: "baz"}), notify3) 1977 1978 items := watch.NewItems() 1979 items.Add(watch.Item{Table: "foo"}) 1980 items.Add(watch.Item{Table: "bar"}) 1981 1982 sw.notify(items) 1983 if len(notify1) != 1 { 1984 t.Fatalf("should notify") 1985 } 1986 if len(notify2) != 1 { 1987 t.Fatalf("should notify") 1988 } 1989 if len(notify3) != 0 { 1990 t.Fatalf("should not notify") 1991 } 1992 } 1993 1994 func TestStateWatch_stopWatch(t *testing.T) { 1995 sw := newStateWatch() 1996 notify := make(chan struct{}) 1997 1998 // First subscribe 1999 sw.watch(watch.NewItems(watch.Item{Table: "foo"}), notify) 2000 2001 // Unsubscribe stop notifications 2002 sw.stopWatch(watch.NewItems(watch.Item{Table: "foo"}), notify) 2003 2004 // Check that the group was removed 2005 if _, ok := sw.items[watch.Item{Table: "foo"}]; ok { 2006 t.Fatalf("should remove group") 2007 } 2008 2009 // Check that we are not notified 2010 sw.notify(watch.NewItems(watch.Item{Table: "foo"})) 2011 if len(notify) != 0 { 2012 t.Fatalf("should not notify") 2013 } 2014 } 2015 2016 // setupNotifyTest takes a state store and a set of watch items, then creates 2017 // and subscribes a notification channel for each item. 2018 func setupNotifyTest(state *StateStore, items ...watch.Item) notifyTest { 2019 var n notifyTest 2020 for _, item := range items { 2021 ch := make(chan struct{}, 1) 2022 state.Watch(watch.NewItems(item), ch) 2023 n = append(n, ¬ifyTestCase{item, ch}) 2024 } 2025 return n 2026 } 2027 2028 // notifyTestCase is used to set up and verify watch triggers. 2029 type notifyTestCase struct { 2030 item watch.Item 2031 ch chan struct{} 2032 } 2033 2034 // notifyTest is a suite of notifyTestCases. 2035 type notifyTest []*notifyTestCase 2036 2037 // verify ensures that each channel received a notification. 2038 func (n notifyTest) verify(t *testing.T) { 2039 for _, tcase := range n { 2040 if len(tcase.ch) != 1 { 2041 t.Fatalf("should notify %#v", tcase.item) 2042 } 2043 } 2044 } 2045 2046 // NodeIDSort is used to sort nodes by ID 2047 type NodeIDSort []*structs.Node 2048 2049 func (n NodeIDSort) Len() int { 2050 return len(n) 2051 } 2052 2053 func (n NodeIDSort) Less(i, j int) bool { 2054 return n[i].ID < n[j].ID 2055 } 2056 2057 func (n NodeIDSort) Swap(i, j int) { 2058 n[i], n[j] = n[j], n[i] 2059 } 2060 2061 // JobIDis used to sort jobs by id 2062 type JobIDSort []*structs.Job 2063 2064 func (n JobIDSort) Len() int { 2065 return len(n) 2066 } 2067 2068 func (n JobIDSort) Less(i, j int) bool { 2069 return n[i].ID < n[j].ID 2070 } 2071 2072 func (n JobIDSort) Swap(i, j int) { 2073 n[i], n[j] = n[j], n[i] 2074 } 2075 2076 // EvalIDis used to sort evals by id 2077 type EvalIDSort []*structs.Evaluation 2078 2079 func (n EvalIDSort) Len() int { 2080 return len(n) 2081 } 2082 2083 func (n EvalIDSort) Less(i, j int) bool { 2084 return n[i].ID < n[j].ID 2085 } 2086 2087 func (n EvalIDSort) Swap(i, j int) { 2088 n[i], n[j] = n[j], n[i] 2089 } 2090 2091 // AllocIDsort used to sort allocations by id 2092 type AllocIDSort []*structs.Allocation 2093 2094 func (n AllocIDSort) Len() int { 2095 return len(n) 2096 } 2097 2098 func (n AllocIDSort) Less(i, j int) bool { 2099 return n[i].ID < n[j].ID 2100 } 2101 2102 func (n AllocIDSort) Swap(i, j int) { 2103 n[i], n[j] = n[j], n[i] 2104 }