github.com/dkerwin/nomad@v0.3.3-0.20160525181927-74554135514b/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 < 20; i++ { 685 var job *structs.Job 686 if i%2 == 0 { 687 job = mock.Job() 688 } else { 689 job = mock.PeriodicJob() 690 } 691 nonGc = append(nonGc, job) 692 693 if err := state.UpsertJob(1000+uint64(i), job); err != nil { 694 t.Fatalf("err: %v", err) 695 } 696 } 697 698 for i := 0; i < 10; i++ { 699 job := mock.Job() 700 job.Type = structs.JobTypeBatch 701 gc = append(gc, job) 702 703 if err := state.UpsertJob(2000+uint64(i), job); err != nil { 704 t.Fatalf("err: %v", err) 705 } 706 } 707 708 iter, err := state.JobsByGC(true) 709 if err != nil { 710 t.Fatalf("err: %v", err) 711 } 712 713 var outGc []*structs.Job 714 for i := iter.Next(); i != nil; i = iter.Next() { 715 outGc = append(outGc, i.(*structs.Job)) 716 } 717 718 iter, err = state.JobsByGC(false) 719 if err != nil { 720 t.Fatalf("err: %v", err) 721 } 722 723 var outNonGc []*structs.Job 724 for i := iter.Next(); i != nil; i = iter.Next() { 725 outNonGc = append(outNonGc, i.(*structs.Job)) 726 } 727 728 sort.Sort(JobIDSort(gc)) 729 sort.Sort(JobIDSort(nonGc)) 730 sort.Sort(JobIDSort(outGc)) 731 sort.Sort(JobIDSort(outNonGc)) 732 733 if !reflect.DeepEqual(gc, outGc) { 734 t.Fatalf("bad: %#v %#v", gc, outGc) 735 } 736 737 if !reflect.DeepEqual(nonGc, outNonGc) { 738 t.Fatalf("bad: %#v %#v", nonGc, outNonGc) 739 } 740 } 741 742 func TestStateStore_RestoreJob(t *testing.T) { 743 state := testStateStore(t) 744 job := mock.Job() 745 746 notify := setupNotifyTest( 747 state, 748 watch.Item{Table: "jobs"}, 749 watch.Item{Job: job.ID}) 750 751 restore, err := state.Restore() 752 if err != nil { 753 t.Fatalf("err: %v", err) 754 } 755 756 err = restore.JobRestore(job) 757 if err != nil { 758 t.Fatalf("err: %v", err) 759 } 760 restore.Commit() 761 762 out, err := state.JobByID(job.ID) 763 if err != nil { 764 t.Fatalf("err: %v", err) 765 } 766 767 if !reflect.DeepEqual(out, job) { 768 t.Fatalf("Bad: %#v %#v", out, job) 769 } 770 771 notify.verify(t) 772 } 773 774 func TestStateStore_UpsertPeriodicLaunch(t *testing.T) { 775 state := testStateStore(t) 776 job := mock.Job() 777 launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()} 778 779 notify := setupNotifyTest( 780 state, 781 watch.Item{Table: "periodic_launch"}, 782 watch.Item{Job: job.ID}) 783 784 err := state.UpsertPeriodicLaunch(1000, launch) 785 if err != nil { 786 t.Fatalf("err: %v", err) 787 } 788 789 out, err := state.PeriodicLaunchByID(job.ID) 790 if err != nil { 791 t.Fatalf("err: %v", err) 792 } 793 if out.CreateIndex != 1000 { 794 t.Fatalf("bad: %#v", out) 795 } 796 if out.ModifyIndex != 1000 { 797 t.Fatalf("bad: %#v", out) 798 } 799 800 if !reflect.DeepEqual(launch, out) { 801 t.Fatalf("bad: %#v %#v", job, out) 802 } 803 804 index, err := state.Index("periodic_launch") 805 if err != nil { 806 t.Fatalf("err: %v", err) 807 } 808 if index != 1000 { 809 t.Fatalf("bad: %d", index) 810 } 811 812 notify.verify(t) 813 } 814 815 func TestStateStore_UpdateUpsertPeriodicLaunch(t *testing.T) { 816 state := testStateStore(t) 817 job := mock.Job() 818 launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()} 819 820 notify := setupNotifyTest( 821 state, 822 watch.Item{Table: "periodic_launch"}, 823 watch.Item{Job: job.ID}) 824 825 err := state.UpsertPeriodicLaunch(1000, launch) 826 if err != nil { 827 t.Fatalf("err: %v", err) 828 } 829 830 launch2 := &structs.PeriodicLaunch{ 831 ID: job.ID, 832 Launch: launch.Launch.Add(1 * time.Second), 833 } 834 err = state.UpsertPeriodicLaunch(1001, launch2) 835 if err != nil { 836 t.Fatalf("err: %v", err) 837 } 838 839 out, err := state.PeriodicLaunchByID(job.ID) 840 if err != nil { 841 t.Fatalf("err: %v", err) 842 } 843 if out.CreateIndex != 1000 { 844 t.Fatalf("bad: %#v", out) 845 } 846 if out.ModifyIndex != 1001 { 847 t.Fatalf("bad: %#v", out) 848 } 849 850 if !reflect.DeepEqual(launch2, out) { 851 t.Fatalf("bad: %#v %#v", launch2, out) 852 } 853 854 index, err := state.Index("periodic_launch") 855 if err != nil { 856 t.Fatalf("err: %v", err) 857 } 858 if index != 1001 { 859 t.Fatalf("bad: %d", index) 860 } 861 862 notify.verify(t) 863 } 864 865 func TestStateStore_DeletePeriodicLaunch(t *testing.T) { 866 state := testStateStore(t) 867 job := mock.Job() 868 launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()} 869 870 notify := setupNotifyTest( 871 state, 872 watch.Item{Table: "periodic_launch"}, 873 watch.Item{Job: job.ID}) 874 875 err := state.UpsertPeriodicLaunch(1000, launch) 876 if err != nil { 877 t.Fatalf("err: %v", err) 878 } 879 880 err = state.DeletePeriodicLaunch(1001, job.ID) 881 if err != nil { 882 t.Fatalf("err: %v", err) 883 } 884 885 out, err := state.PeriodicLaunchByID(job.ID) 886 if err != nil { 887 t.Fatalf("err: %v", err) 888 } 889 890 if out != nil { 891 t.Fatalf("bad: %#v %#v", job, out) 892 } 893 894 index, err := state.Index("periodic_launch") 895 if err != nil { 896 t.Fatalf("err: %v", err) 897 } 898 if index != 1001 { 899 t.Fatalf("bad: %d", index) 900 } 901 902 notify.verify(t) 903 } 904 905 func TestStateStore_PeriodicLaunches(t *testing.T) { 906 state := testStateStore(t) 907 var launches []*structs.PeriodicLaunch 908 909 for i := 0; i < 10; i++ { 910 job := mock.Job() 911 launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()} 912 launches = append(launches, launch) 913 914 err := state.UpsertPeriodicLaunch(1000+uint64(i), launch) 915 if err != nil { 916 t.Fatalf("err: %v", err) 917 } 918 } 919 920 iter, err := state.PeriodicLaunches() 921 if err != nil { 922 t.Fatalf("err: %v", err) 923 } 924 925 out := make(map[string]*structs.PeriodicLaunch, 10) 926 for { 927 raw := iter.Next() 928 if raw == nil { 929 break 930 } 931 launch := raw.(*structs.PeriodicLaunch) 932 if _, ok := out[launch.ID]; ok { 933 t.Fatalf("duplicate: %v", launch.ID) 934 } 935 936 out[launch.ID] = launch 937 } 938 939 for _, launch := range launches { 940 l, ok := out[launch.ID] 941 if !ok { 942 t.Fatalf("bad %v", launch.ID) 943 } 944 945 if !reflect.DeepEqual(launch, l) { 946 t.Fatalf("bad: %#v %#v", launch, l) 947 } 948 949 delete(out, launch.ID) 950 } 951 952 if len(out) != 0 { 953 t.Fatalf("leftover: %#v", out) 954 } 955 } 956 957 func TestStateStore_RestorePeriodicLaunch(t *testing.T) { 958 state := testStateStore(t) 959 job := mock.Job() 960 launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()} 961 962 notify := setupNotifyTest( 963 state, 964 watch.Item{Table: "periodic_launch"}, 965 watch.Item{Job: job.ID}) 966 967 restore, err := state.Restore() 968 if err != nil { 969 t.Fatalf("err: %v", err) 970 } 971 972 err = restore.PeriodicLaunchRestore(launch) 973 if err != nil { 974 t.Fatalf("err: %v", err) 975 } 976 restore.Commit() 977 978 out, err := state.PeriodicLaunchByID(job.ID) 979 if err != nil { 980 t.Fatalf("err: %v", err) 981 } 982 983 if !reflect.DeepEqual(out, launch) { 984 t.Fatalf("Bad: %#v %#v", out, job) 985 } 986 987 notify.verify(t) 988 } 989 990 func TestStateStore_Indexes(t *testing.T) { 991 state := testStateStore(t) 992 node := mock.Node() 993 994 err := state.UpsertNode(1000, node) 995 if err != nil { 996 t.Fatalf("err: %v", err) 997 } 998 999 iter, err := state.Indexes() 1000 if err != nil { 1001 t.Fatalf("err: %v", err) 1002 } 1003 1004 var out []*IndexEntry 1005 for { 1006 raw := iter.Next() 1007 if raw == nil { 1008 break 1009 } 1010 out = append(out, raw.(*IndexEntry)) 1011 } 1012 1013 expect := []*IndexEntry{ 1014 &IndexEntry{"nodes", 1000}, 1015 } 1016 1017 if !reflect.DeepEqual(expect, out) { 1018 t.Fatalf("bad: %#v %#v", expect, out) 1019 } 1020 } 1021 1022 func TestStateStore_LatestIndex(t *testing.T) { 1023 state := testStateStore(t) 1024 1025 if err := state.UpsertNode(1000, mock.Node()); err != nil { 1026 t.Fatalf("err: %v", err) 1027 } 1028 1029 exp := uint64(2000) 1030 if err := state.UpsertJob(exp, mock.Job()); err != nil { 1031 t.Fatalf("err: %v", err) 1032 } 1033 1034 latest, err := state.LatestIndex() 1035 if err != nil { 1036 t.Fatalf("err: %v", err) 1037 } 1038 1039 if latest != exp { 1040 t.Fatalf("LatestIndex() returned %d; want %d", latest, exp) 1041 } 1042 } 1043 1044 func TestStateStore_RestoreIndex(t *testing.T) { 1045 state := testStateStore(t) 1046 1047 restore, err := state.Restore() 1048 if err != nil { 1049 t.Fatalf("err: %v", err) 1050 } 1051 1052 index := &IndexEntry{"jobs", 1000} 1053 err = restore.IndexRestore(index) 1054 if err != nil { 1055 t.Fatalf("err: %v", err) 1056 } 1057 1058 restore.Commit() 1059 1060 out, err := state.Index("jobs") 1061 if err != nil { 1062 t.Fatalf("err: %v", err) 1063 } 1064 1065 if out != 1000 { 1066 t.Fatalf("Bad: %#v %#v", out, 1000) 1067 } 1068 } 1069 1070 func TestStateStore_UpsertEvals_Eval(t *testing.T) { 1071 state := testStateStore(t) 1072 eval := mock.Eval() 1073 1074 notify := setupNotifyTest( 1075 state, 1076 watch.Item{Table: "evals"}, 1077 watch.Item{Eval: eval.ID}) 1078 1079 err := state.UpsertEvals(1000, []*structs.Evaluation{eval}) 1080 if err != nil { 1081 t.Fatalf("err: %v", err) 1082 } 1083 1084 out, err := state.EvalByID(eval.ID) 1085 if err != nil { 1086 t.Fatalf("err: %v", err) 1087 } 1088 1089 if !reflect.DeepEqual(eval, out) { 1090 t.Fatalf("bad: %#v %#v", eval, out) 1091 } 1092 1093 index, err := state.Index("evals") 1094 if err != nil { 1095 t.Fatalf("err: %v", err) 1096 } 1097 if index != 1000 { 1098 t.Fatalf("bad: %d", index) 1099 } 1100 1101 notify.verify(t) 1102 } 1103 1104 func TestStateStore_Update_UpsertEvals_Eval(t *testing.T) { 1105 state := testStateStore(t) 1106 eval := mock.Eval() 1107 1108 err := state.UpsertEvals(1000, []*structs.Evaluation{eval}) 1109 if err != nil { 1110 t.Fatalf("err: %v", err) 1111 } 1112 1113 notify := setupNotifyTest( 1114 state, 1115 watch.Item{Table: "evals"}, 1116 watch.Item{Eval: eval.ID}) 1117 1118 eval2 := mock.Eval() 1119 eval2.ID = eval.ID 1120 err = state.UpsertEvals(1001, []*structs.Evaluation{eval2}) 1121 if err != nil { 1122 t.Fatalf("err: %v", err) 1123 } 1124 1125 out, err := state.EvalByID(eval.ID) 1126 if err != nil { 1127 t.Fatalf("err: %v", err) 1128 } 1129 1130 if !reflect.DeepEqual(eval2, out) { 1131 t.Fatalf("bad: %#v %#v", eval2, out) 1132 } 1133 1134 if out.CreateIndex != 1000 { 1135 t.Fatalf("bad: %#v", out) 1136 } 1137 if out.ModifyIndex != 1001 { 1138 t.Fatalf("bad: %#v", out) 1139 } 1140 1141 index, err := state.Index("evals") 1142 if err != nil { 1143 t.Fatalf("err: %v", err) 1144 } 1145 if index != 1001 { 1146 t.Fatalf("bad: %d", index) 1147 } 1148 1149 notify.verify(t) 1150 } 1151 1152 func TestStateStore_DeleteEval_Eval(t *testing.T) { 1153 state := testStateStore(t) 1154 eval1 := mock.Eval() 1155 eval2 := mock.Eval() 1156 alloc1 := mock.Alloc() 1157 alloc2 := mock.Alloc() 1158 1159 notify := setupNotifyTest( 1160 state, 1161 watch.Item{Table: "evals"}, 1162 watch.Item{Table: "allocs"}, 1163 watch.Item{Eval: eval1.ID}, 1164 watch.Item{Eval: eval2.ID}, 1165 watch.Item{Alloc: alloc1.ID}, 1166 watch.Item{Alloc: alloc2.ID}, 1167 watch.Item{AllocEval: alloc1.EvalID}, 1168 watch.Item{AllocEval: alloc2.EvalID}, 1169 watch.Item{AllocJob: alloc1.JobID}, 1170 watch.Item{AllocJob: alloc2.JobID}, 1171 watch.Item{AllocNode: alloc1.NodeID}, 1172 watch.Item{AllocNode: alloc2.NodeID}) 1173 1174 err := state.UpsertEvals(1000, []*structs.Evaluation{eval1, eval2}) 1175 if err != nil { 1176 t.Fatalf("err: %v", err) 1177 } 1178 1179 err = state.UpsertAllocs(1001, []*structs.Allocation{alloc1, alloc2}) 1180 if err != nil { 1181 t.Fatalf("err: %v", err) 1182 } 1183 1184 err = state.DeleteEval(1002, []string{eval1.ID, eval2.ID}, []string{alloc1.ID, alloc2.ID}) 1185 if err != nil { 1186 t.Fatalf("err: %v", err) 1187 } 1188 1189 out, err := state.EvalByID(eval1.ID) 1190 if err != nil { 1191 t.Fatalf("err: %v", err) 1192 } 1193 1194 if out != nil { 1195 t.Fatalf("bad: %#v %#v", eval1, out) 1196 } 1197 1198 out, err = state.EvalByID(eval2.ID) 1199 if err != nil { 1200 t.Fatalf("err: %v", err) 1201 } 1202 1203 if out != nil { 1204 t.Fatalf("bad: %#v %#v", eval1, out) 1205 } 1206 1207 outA, err := state.AllocByID(alloc1.ID) 1208 if err != nil { 1209 t.Fatalf("err: %v", err) 1210 } 1211 1212 if out != nil { 1213 t.Fatalf("bad: %#v %#v", alloc1, outA) 1214 } 1215 1216 outA, err = state.AllocByID(alloc2.ID) 1217 if err != nil { 1218 t.Fatalf("err: %v", err) 1219 } 1220 1221 if out != nil { 1222 t.Fatalf("bad: %#v %#v", alloc1, outA) 1223 } 1224 1225 index, err := state.Index("evals") 1226 if err != nil { 1227 t.Fatalf("err: %v", err) 1228 } 1229 if index != 1002 { 1230 t.Fatalf("bad: %d", index) 1231 } 1232 1233 index, err = state.Index("allocs") 1234 if err != nil { 1235 t.Fatalf("err: %v", err) 1236 } 1237 if index != 1002 { 1238 t.Fatalf("bad: %d", index) 1239 } 1240 1241 notify.verify(t) 1242 } 1243 1244 func TestStateStore_EvalsByJob(t *testing.T) { 1245 state := testStateStore(t) 1246 1247 eval1 := mock.Eval() 1248 eval2 := mock.Eval() 1249 eval2.JobID = eval1.JobID 1250 eval3 := mock.Eval() 1251 evals := []*structs.Evaluation{eval1, eval2} 1252 1253 err := state.UpsertEvals(1000, evals) 1254 if err != nil { 1255 t.Fatalf("err: %v", err) 1256 } 1257 err = state.UpsertEvals(1001, []*structs.Evaluation{eval3}) 1258 if err != nil { 1259 t.Fatalf("err: %v", err) 1260 } 1261 1262 out, err := state.EvalsByJob(eval1.JobID) 1263 if err != nil { 1264 t.Fatalf("err: %v", err) 1265 } 1266 1267 sort.Sort(EvalIDSort(evals)) 1268 sort.Sort(EvalIDSort(out)) 1269 1270 if !reflect.DeepEqual(evals, out) { 1271 t.Fatalf("bad: %#v %#v", evals, out) 1272 } 1273 } 1274 1275 func TestStateStore_Evals(t *testing.T) { 1276 state := testStateStore(t) 1277 var evals []*structs.Evaluation 1278 1279 for i := 0; i < 10; i++ { 1280 eval := mock.Eval() 1281 evals = append(evals, eval) 1282 1283 err := state.UpsertEvals(1000+uint64(i), []*structs.Evaluation{eval}) 1284 if err != nil { 1285 t.Fatalf("err: %v", err) 1286 } 1287 } 1288 1289 iter, err := state.Evals() 1290 if err != nil { 1291 t.Fatalf("err: %v", err) 1292 } 1293 1294 var out []*structs.Evaluation 1295 for { 1296 raw := iter.Next() 1297 if raw == nil { 1298 break 1299 } 1300 out = append(out, raw.(*structs.Evaluation)) 1301 } 1302 1303 sort.Sort(EvalIDSort(evals)) 1304 sort.Sort(EvalIDSort(out)) 1305 1306 if !reflect.DeepEqual(evals, out) { 1307 t.Fatalf("bad: %#v %#v", evals, out) 1308 } 1309 } 1310 1311 func TestStateStore_EvalsByIDPrefix(t *testing.T) { 1312 state := testStateStore(t) 1313 var evals []*structs.Evaluation 1314 1315 ids := []string{ 1316 "aaaaaaaa-7bfb-395d-eb95-0685af2176b2", 1317 "aaaaaaab-7bfb-395d-eb95-0685af2176b2", 1318 "aaaaaabb-7bfb-395d-eb95-0685af2176b2", 1319 "aaaaabbb-7bfb-395d-eb95-0685af2176b2", 1320 "aaaabbbb-7bfb-395d-eb95-0685af2176b2", 1321 "aaabbbbb-7bfb-395d-eb95-0685af2176b2", 1322 "aabbbbbb-7bfb-395d-eb95-0685af2176b2", 1323 "abbbbbbb-7bfb-395d-eb95-0685af2176b2", 1324 "bbbbbbbb-7bfb-395d-eb95-0685af2176b2", 1325 } 1326 for i := 0; i < 9; i++ { 1327 eval := mock.Eval() 1328 eval.ID = ids[i] 1329 evals = append(evals, eval) 1330 } 1331 1332 err := state.UpsertEvals(1000, evals) 1333 if err != nil { 1334 t.Fatalf("err: %v", err) 1335 } 1336 1337 iter, err := state.EvalsByIDPrefix("aaaa") 1338 if err != nil { 1339 t.Fatalf("err: %v", err) 1340 } 1341 1342 gatherEvals := func(iter memdb.ResultIterator) []*structs.Evaluation { 1343 var evals []*structs.Evaluation 1344 for { 1345 raw := iter.Next() 1346 if raw == nil { 1347 break 1348 } 1349 evals = append(evals, raw.(*structs.Evaluation)) 1350 } 1351 return evals 1352 } 1353 1354 out := gatherEvals(iter) 1355 if len(out) != 5 { 1356 t.Fatalf("bad: expected five evaluations, got: %#v", out) 1357 } 1358 1359 sort.Sort(EvalIDSort(evals)) 1360 1361 for index, eval := range out { 1362 if ids[index] != eval.ID { 1363 t.Fatalf("bad: got unexpected id: %s", eval.ID) 1364 } 1365 } 1366 1367 iter, err = state.EvalsByIDPrefix("b-a7bfb") 1368 if err != nil { 1369 t.Fatalf("err: %v", err) 1370 } 1371 1372 out = gatherEvals(iter) 1373 if len(out) != 0 { 1374 t.Fatalf("bad: unexpected zero evaluations, got: %#v", out) 1375 } 1376 1377 } 1378 1379 func TestStateStore_RestoreEval(t *testing.T) { 1380 state := testStateStore(t) 1381 eval := mock.Eval() 1382 1383 notify := setupNotifyTest( 1384 state, 1385 watch.Item{Table: "evals"}, 1386 watch.Item{Eval: eval.ID}) 1387 1388 restore, err := state.Restore() 1389 if err != nil { 1390 t.Fatalf("err: %v", err) 1391 } 1392 1393 err = restore.EvalRestore(eval) 1394 if err != nil { 1395 t.Fatalf("err: %v", err) 1396 } 1397 restore.Commit() 1398 1399 out, err := state.EvalByID(eval.ID) 1400 if err != nil { 1401 t.Fatalf("err: %v", err) 1402 } 1403 1404 if !reflect.DeepEqual(out, eval) { 1405 t.Fatalf("Bad: %#v %#v", out, eval) 1406 } 1407 1408 notify.verify(t) 1409 } 1410 1411 func TestStateStore_UpdateAllocsFromClient(t *testing.T) { 1412 state := testStateStore(t) 1413 alloc := mock.Alloc() 1414 alloc2 := mock.Alloc() 1415 1416 notify := setupNotifyTest( 1417 state, 1418 watch.Item{Table: "allocs"}, 1419 watch.Item{Alloc: alloc.ID}, 1420 watch.Item{AllocEval: alloc.EvalID}, 1421 watch.Item{AllocJob: alloc.JobID}, 1422 watch.Item{AllocNode: alloc.NodeID}, 1423 watch.Item{Alloc: alloc2.ID}, 1424 watch.Item{AllocEval: alloc2.EvalID}, 1425 watch.Item{AllocJob: alloc2.JobID}, 1426 watch.Item{AllocNode: alloc2.NodeID}) 1427 1428 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc, alloc2}) 1429 if err != nil { 1430 t.Fatalf("err: %v", err) 1431 } 1432 1433 // Create the delta updates 1434 ts := map[string]*structs.TaskState{"web": &structs.TaskState{State: structs.TaskStatePending}} 1435 update := &structs.Allocation{ 1436 ID: alloc.ID, 1437 ClientStatus: structs.AllocClientStatusFailed, 1438 TaskStates: ts, 1439 } 1440 update2 := &structs.Allocation{ 1441 ID: alloc2.ID, 1442 ClientStatus: structs.AllocClientStatusRunning, 1443 TaskStates: ts, 1444 } 1445 1446 err = state.UpdateAllocsFromClient(1001, []*structs.Allocation{update, update2}) 1447 if err != nil { 1448 t.Fatalf("err: %v", err) 1449 } 1450 1451 out, err := state.AllocByID(alloc.ID) 1452 if err != nil { 1453 t.Fatalf("err: %v", err) 1454 } 1455 1456 alloc.CreateIndex = 1000 1457 alloc.ModifyIndex = 1001 1458 alloc.TaskStates = ts 1459 alloc.ClientStatus = structs.AllocClientStatusFailed 1460 if !reflect.DeepEqual(alloc, out) { 1461 t.Fatalf("bad: %#v %#v", alloc, out) 1462 } 1463 1464 out, err = state.AllocByID(alloc2.ID) 1465 if err != nil { 1466 t.Fatalf("err: %v", err) 1467 } 1468 1469 alloc2.ModifyIndex = 1000 1470 alloc2.ModifyIndex = 1001 1471 alloc2.ClientStatus = structs.AllocClientStatusRunning 1472 alloc2.TaskStates = ts 1473 if !reflect.DeepEqual(alloc2, out) { 1474 t.Fatalf("bad: %#v %#v", alloc2, out) 1475 } 1476 1477 index, err := state.Index("allocs") 1478 if err != nil { 1479 t.Fatalf("err: %v", err) 1480 } 1481 if index != 1001 { 1482 t.Fatalf("bad: %d", index) 1483 } 1484 1485 notify.verify(t) 1486 } 1487 1488 func TestStateStore_UpsertAlloc_Alloc(t *testing.T) { 1489 state := testStateStore(t) 1490 alloc := mock.Alloc() 1491 1492 notify := setupNotifyTest( 1493 state, 1494 watch.Item{Table: "allocs"}, 1495 watch.Item{Alloc: alloc.ID}, 1496 watch.Item{AllocEval: alloc.EvalID}, 1497 watch.Item{AllocJob: alloc.JobID}, 1498 watch.Item{AllocNode: alloc.NodeID}) 1499 1500 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}) 1501 if err != nil { 1502 t.Fatalf("err: %v", err) 1503 } 1504 1505 out, err := state.AllocByID(alloc.ID) 1506 if err != nil { 1507 t.Fatalf("err: %v", err) 1508 } 1509 1510 if !reflect.DeepEqual(alloc, out) { 1511 t.Fatalf("bad: %#v %#v", alloc, out) 1512 } 1513 1514 index, err := state.Index("allocs") 1515 if err != nil { 1516 t.Fatalf("err: %v", err) 1517 } 1518 if index != 1000 { 1519 t.Fatalf("bad: %d", index) 1520 } 1521 1522 notify.verify(t) 1523 } 1524 1525 func TestStateStore_UpdateAlloc_Alloc(t *testing.T) { 1526 state := testStateStore(t) 1527 alloc := mock.Alloc() 1528 1529 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}) 1530 if err != nil { 1531 t.Fatalf("err: %v", err) 1532 } 1533 1534 alloc2 := mock.Alloc() 1535 alloc2.ID = alloc.ID 1536 alloc2.NodeID = alloc.NodeID + ".new" 1537 1538 notify := setupNotifyTest( 1539 state, 1540 watch.Item{Table: "allocs"}, 1541 watch.Item{Alloc: alloc2.ID}, 1542 watch.Item{AllocEval: alloc2.EvalID}, 1543 watch.Item{AllocJob: alloc2.JobID}, 1544 watch.Item{AllocNode: alloc2.NodeID}) 1545 1546 err = state.UpsertAllocs(1001, []*structs.Allocation{alloc2}) 1547 if err != nil { 1548 t.Fatalf("err: %v", err) 1549 } 1550 1551 out, err := state.AllocByID(alloc.ID) 1552 if err != nil { 1553 t.Fatalf("err: %v", err) 1554 } 1555 1556 if !reflect.DeepEqual(alloc2, out) { 1557 t.Fatalf("bad: %#v %#v", alloc2, out) 1558 } 1559 1560 if out.CreateIndex != 1000 { 1561 t.Fatalf("bad: %#v", out) 1562 } 1563 if out.ModifyIndex != 1001 { 1564 t.Fatalf("bad: %#v", out) 1565 } 1566 1567 index, err := state.Index("allocs") 1568 if err != nil { 1569 t.Fatalf("err: %v", err) 1570 } 1571 if index != 1001 { 1572 t.Fatalf("bad: %d", index) 1573 } 1574 1575 notify.verify(t) 1576 } 1577 1578 func TestStateStore_EvictAlloc_Alloc(t *testing.T) { 1579 state := testStateStore(t) 1580 alloc := mock.Alloc() 1581 1582 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}) 1583 if err != nil { 1584 t.Fatalf("err: %v", err) 1585 } 1586 1587 alloc2 := new(structs.Allocation) 1588 *alloc2 = *alloc 1589 alloc2.DesiredStatus = structs.AllocDesiredStatusEvict 1590 err = state.UpsertAllocs(1001, []*structs.Allocation{alloc2}) 1591 if err != nil { 1592 t.Fatalf("err: %v", err) 1593 } 1594 1595 out, err := state.AllocByID(alloc.ID) 1596 if err != nil { 1597 t.Fatalf("err: %v", err) 1598 } 1599 1600 if out.DesiredStatus != structs.AllocDesiredStatusEvict { 1601 t.Fatalf("bad: %#v %#v", alloc, out) 1602 } 1603 1604 index, err := state.Index("allocs") 1605 if err != nil { 1606 t.Fatalf("err: %v", err) 1607 } 1608 if index != 1001 { 1609 t.Fatalf("bad: %d", index) 1610 } 1611 } 1612 1613 func TestStateStore_AllocsByNode(t *testing.T) { 1614 state := testStateStore(t) 1615 var allocs []*structs.Allocation 1616 1617 for i := 0; i < 10; i++ { 1618 alloc := mock.Alloc() 1619 alloc.NodeID = "foo" 1620 allocs = append(allocs, alloc) 1621 } 1622 1623 err := state.UpsertAllocs(1000, allocs) 1624 if err != nil { 1625 t.Fatalf("err: %v", err) 1626 } 1627 1628 out, err := state.AllocsByNode("foo") 1629 if err != nil { 1630 t.Fatalf("err: %v", err) 1631 } 1632 1633 sort.Sort(AllocIDSort(allocs)) 1634 sort.Sort(AllocIDSort(out)) 1635 1636 if !reflect.DeepEqual(allocs, out) { 1637 t.Fatalf("bad: %#v %#v", allocs, out) 1638 } 1639 } 1640 1641 func TestStateStore_AllocsByNodeTerminal(t *testing.T) { 1642 state := testStateStore(t) 1643 var allocs, term, nonterm []*structs.Allocation 1644 1645 for i := 0; i < 10; i++ { 1646 alloc := mock.Alloc() 1647 alloc.NodeID = "foo" 1648 if i%2 == 0 { 1649 alloc.DesiredStatus = structs.AllocDesiredStatusStop 1650 term = append(term, alloc) 1651 } else { 1652 nonterm = append(nonterm, alloc) 1653 } 1654 allocs = append(allocs, alloc) 1655 } 1656 1657 err := state.UpsertAllocs(1000, allocs) 1658 if err != nil { 1659 t.Fatalf("err: %v", err) 1660 } 1661 1662 // Verify the terminal allocs 1663 out, err := state.AllocsByNodeTerminal("foo", true) 1664 if err != nil { 1665 t.Fatalf("err: %v", err) 1666 } 1667 1668 sort.Sort(AllocIDSort(term)) 1669 sort.Sort(AllocIDSort(out)) 1670 1671 if !reflect.DeepEqual(term, out) { 1672 t.Fatalf("bad: %#v %#v", term, out) 1673 } 1674 1675 // Verify the non-terminal allocs 1676 out, err = state.AllocsByNodeTerminal("foo", false) 1677 if err != nil { 1678 t.Fatalf("err: %v", err) 1679 } 1680 1681 sort.Sort(AllocIDSort(nonterm)) 1682 sort.Sort(AllocIDSort(out)) 1683 1684 if !reflect.DeepEqual(nonterm, out) { 1685 t.Fatalf("bad: %#v %#v", nonterm, out) 1686 } 1687 } 1688 1689 func TestStateStore_AllocsByJob(t *testing.T) { 1690 state := testStateStore(t) 1691 var allocs []*structs.Allocation 1692 1693 for i := 0; i < 10; i++ { 1694 alloc := mock.Alloc() 1695 alloc.JobID = "foo" 1696 allocs = append(allocs, alloc) 1697 } 1698 1699 err := state.UpsertAllocs(1000, allocs) 1700 if err != nil { 1701 t.Fatalf("err: %v", err) 1702 } 1703 1704 out, err := state.AllocsByJob("foo") 1705 if err != nil { 1706 t.Fatalf("err: %v", err) 1707 } 1708 1709 sort.Sort(AllocIDSort(allocs)) 1710 sort.Sort(AllocIDSort(out)) 1711 1712 if !reflect.DeepEqual(allocs, out) { 1713 t.Fatalf("bad: %#v %#v", allocs, out) 1714 } 1715 } 1716 1717 func TestStateStore_AllocsByIDPrefix(t *testing.T) { 1718 state := testStateStore(t) 1719 var allocs []*structs.Allocation 1720 1721 ids := []string{ 1722 "aaaaaaaa-7bfb-395d-eb95-0685af2176b2", 1723 "aaaaaaab-7bfb-395d-eb95-0685af2176b2", 1724 "aaaaaabb-7bfb-395d-eb95-0685af2176b2", 1725 "aaaaabbb-7bfb-395d-eb95-0685af2176b2", 1726 "aaaabbbb-7bfb-395d-eb95-0685af2176b2", 1727 "aaabbbbb-7bfb-395d-eb95-0685af2176b2", 1728 "aabbbbbb-7bfb-395d-eb95-0685af2176b2", 1729 "abbbbbbb-7bfb-395d-eb95-0685af2176b2", 1730 "bbbbbbbb-7bfb-395d-eb95-0685af2176b2", 1731 } 1732 for i := 0; i < 9; i++ { 1733 alloc := mock.Alloc() 1734 alloc.ID = ids[i] 1735 allocs = append(allocs, alloc) 1736 } 1737 1738 err := state.UpsertAllocs(1000, allocs) 1739 if err != nil { 1740 t.Fatalf("err: %v", err) 1741 } 1742 1743 iter, err := state.AllocsByIDPrefix("aaaa") 1744 if err != nil { 1745 t.Fatalf("err: %v", err) 1746 } 1747 1748 gatherAllocs := func(iter memdb.ResultIterator) []*structs.Allocation { 1749 var allocs []*structs.Allocation 1750 for { 1751 raw := iter.Next() 1752 if raw == nil { 1753 break 1754 } 1755 allocs = append(allocs, raw.(*structs.Allocation)) 1756 } 1757 return allocs 1758 } 1759 1760 out := gatherAllocs(iter) 1761 if len(out) != 5 { 1762 t.Fatalf("bad: expected five allocations, got: %#v", out) 1763 } 1764 1765 sort.Sort(AllocIDSort(allocs)) 1766 1767 for index, alloc := range out { 1768 if ids[index] != alloc.ID { 1769 t.Fatalf("bad: got unexpected id: %s", alloc.ID) 1770 } 1771 } 1772 1773 iter, err = state.AllocsByIDPrefix("b-a7bfb") 1774 if err != nil { 1775 t.Fatalf("err: %v", err) 1776 } 1777 1778 out = gatherAllocs(iter) 1779 if len(out) != 0 { 1780 t.Fatalf("bad: unexpected zero allocations, got: %#v", out) 1781 } 1782 } 1783 1784 func TestStateStore_Allocs(t *testing.T) { 1785 state := testStateStore(t) 1786 var allocs []*structs.Allocation 1787 1788 for i := 0; i < 10; i++ { 1789 alloc := mock.Alloc() 1790 allocs = append(allocs, alloc) 1791 } 1792 1793 err := state.UpsertAllocs(1000, allocs) 1794 if err != nil { 1795 t.Fatalf("err: %v", err) 1796 } 1797 1798 iter, err := state.Allocs() 1799 if err != nil { 1800 t.Fatalf("err: %v", err) 1801 } 1802 1803 var out []*structs.Allocation 1804 for { 1805 raw := iter.Next() 1806 if raw == nil { 1807 break 1808 } 1809 out = append(out, raw.(*structs.Allocation)) 1810 } 1811 1812 sort.Sort(AllocIDSort(allocs)) 1813 sort.Sort(AllocIDSort(out)) 1814 1815 if !reflect.DeepEqual(allocs, out) { 1816 t.Fatalf("bad: %#v %#v", allocs, out) 1817 } 1818 } 1819 1820 func TestStateStore_RestoreAlloc(t *testing.T) { 1821 state := testStateStore(t) 1822 alloc := mock.Alloc() 1823 1824 notify := setupNotifyTest( 1825 state, 1826 watch.Item{Table: "allocs"}, 1827 watch.Item{Alloc: alloc.ID}, 1828 watch.Item{AllocEval: alloc.EvalID}, 1829 watch.Item{AllocJob: alloc.JobID}, 1830 watch.Item{AllocNode: alloc.NodeID}) 1831 1832 restore, err := state.Restore() 1833 if err != nil { 1834 t.Fatalf("err: %v", err) 1835 } 1836 1837 err = restore.AllocRestore(alloc) 1838 if err != nil { 1839 t.Fatalf("err: %v", err) 1840 } 1841 1842 restore.Commit() 1843 1844 out, err := state.AllocByID(alloc.ID) 1845 if err != nil { 1846 t.Fatalf("err: %v", err) 1847 } 1848 1849 if !reflect.DeepEqual(out, alloc) { 1850 t.Fatalf("Bad: %#v %#v", out, alloc) 1851 } 1852 1853 notify.verify(t) 1854 } 1855 1856 func TestStateStore_SetJobStatus_ForceStatus(t *testing.T) { 1857 state := testStateStore(t) 1858 watcher := watch.NewItems() 1859 txn := state.db.Txn(true) 1860 1861 // Create and insert a mock job. 1862 job := mock.Job() 1863 job.Status = "" 1864 job.ModifyIndex = 0 1865 if err := txn.Insert("jobs", job); err != nil { 1866 t.Fatalf("job insert failed: %v", err) 1867 } 1868 1869 exp := "foobar" 1870 index := uint64(1000) 1871 if err := state.setJobStatus(index, watcher, txn, job, false, exp); err != nil { 1872 t.Fatalf("setJobStatus() failed: %v", err) 1873 } 1874 1875 i, err := txn.First("jobs", "id", job.ID) 1876 if err != nil { 1877 t.Fatalf("job lookup failed: %v", err) 1878 } 1879 updated := i.(*structs.Job) 1880 1881 if updated.Status != exp { 1882 t.Fatalf("setJobStatus() set %v; expected %v", updated.Status, exp) 1883 } 1884 1885 if updated.ModifyIndex != index { 1886 t.Fatalf("setJobStatus() set %d; expected %d", updated.ModifyIndex, index) 1887 } 1888 } 1889 1890 func TestStateStore_SetJobStatus_NoOp(t *testing.T) { 1891 state := testStateStore(t) 1892 watcher := watch.NewItems() 1893 txn := state.db.Txn(true) 1894 1895 // Create and insert a mock job that should be pending. 1896 job := mock.Job() 1897 job.Status = structs.JobStatusPending 1898 job.ModifyIndex = 10 1899 if err := txn.Insert("jobs", job); err != nil { 1900 t.Fatalf("job insert failed: %v", err) 1901 } 1902 1903 index := uint64(1000) 1904 if err := state.setJobStatus(index, watcher, txn, job, false, ""); err != nil { 1905 t.Fatalf("setJobStatus() failed: %v", err) 1906 } 1907 1908 i, err := txn.First("jobs", "id", job.ID) 1909 if err != nil { 1910 t.Fatalf("job lookup failed: %v", err) 1911 } 1912 updated := i.(*structs.Job) 1913 1914 if updated.ModifyIndex == index { 1915 t.Fatalf("setJobStatus() should have been a no-op") 1916 } 1917 } 1918 1919 func TestStateStore_SetJobStatus(t *testing.T) { 1920 state := testStateStore(t) 1921 watcher := watch.NewItems() 1922 txn := state.db.Txn(true) 1923 1924 // Create and insert a mock job that should be pending but has an incorrect 1925 // status. 1926 job := mock.Job() 1927 job.Status = "foobar" 1928 job.ModifyIndex = 10 1929 if err := txn.Insert("jobs", job); err != nil { 1930 t.Fatalf("job insert failed: %v", err) 1931 } 1932 1933 index := uint64(1000) 1934 if err := state.setJobStatus(index, watcher, txn, job, false, ""); err != nil { 1935 t.Fatalf("setJobStatus() failed: %v", err) 1936 } 1937 1938 i, err := txn.First("jobs", "id", job.ID) 1939 if err != nil { 1940 t.Fatalf("job lookup failed: %v", err) 1941 } 1942 updated := i.(*structs.Job) 1943 1944 if updated.Status != structs.JobStatusPending { 1945 t.Fatalf("setJobStatus() set %v; expected %v", updated.Status, structs.JobStatusPending) 1946 } 1947 1948 if updated.ModifyIndex != index { 1949 t.Fatalf("setJobStatus() set %d; expected %d", updated.ModifyIndex, index) 1950 } 1951 } 1952 1953 func TestStateStore_GetJobStatus_NoEvalsOrAllocs(t *testing.T) { 1954 job := mock.Job() 1955 state := testStateStore(t) 1956 txn := state.db.Txn(false) 1957 status, err := state.getJobStatus(txn, job, false) 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 TestStateStore_GetJobStatus_NoEvalsOrAllocs_Periodic(t *testing.T) { 1968 job := mock.PeriodicJob() 1969 state := testStateStore(t) 1970 txn := state.db.Txn(false) 1971 status, err := state.getJobStatus(txn, job, false) 1972 if err != nil { 1973 t.Fatalf("getJobStatus() failed: %v", err) 1974 } 1975 1976 if status != structs.JobStatusRunning { 1977 t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusRunning) 1978 } 1979 } 1980 1981 func TestStateStore_GetJobStatus_NoEvalsOrAllocs_EvalDelete(t *testing.T) { 1982 job := mock.Job() 1983 state := testStateStore(t) 1984 txn := state.db.Txn(false) 1985 status, err := state.getJobStatus(txn, job, true) 1986 if err != nil { 1987 t.Fatalf("getJobStatus() failed: %v", err) 1988 } 1989 1990 if status != structs.JobStatusDead { 1991 t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusDead) 1992 } 1993 } 1994 1995 func TestStateStore_GetJobStatus_DeadEvalsAndAllocs(t *testing.T) { 1996 state := testStateStore(t) 1997 job := mock.Job() 1998 1999 // Create a mock alloc that is dead. 2000 alloc := mock.Alloc() 2001 alloc.JobID = job.ID 2002 alloc.DesiredStatus = structs.AllocDesiredStatusFailed 2003 if err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}); err != nil { 2004 t.Fatalf("err: %v", err) 2005 } 2006 2007 // Create a mock eval that is complete 2008 eval := mock.Eval() 2009 eval.JobID = job.ID 2010 eval.Status = structs.EvalStatusComplete 2011 if err := state.UpsertEvals(1001, []*structs.Evaluation{eval}); err != nil { 2012 t.Fatalf("err: %v", err) 2013 } 2014 2015 txn := state.db.Txn(false) 2016 status, err := state.getJobStatus(txn, job, false) 2017 if err != nil { 2018 t.Fatalf("getJobStatus() failed: %v", err) 2019 } 2020 2021 if status != structs.JobStatusDead { 2022 t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusDead) 2023 } 2024 } 2025 2026 func TestStateStore_GetJobStatus_RunningAlloc(t *testing.T) { 2027 state := testStateStore(t) 2028 job := mock.Job() 2029 2030 // Create a mock alloc that is running. 2031 alloc := mock.Alloc() 2032 alloc.JobID = job.ID 2033 alloc.DesiredStatus = structs.AllocDesiredStatusRun 2034 if err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}); err != nil { 2035 t.Fatalf("err: %v", err) 2036 } 2037 2038 txn := state.db.Txn(false) 2039 status, err := state.getJobStatus(txn, job, true) 2040 if err != nil { 2041 t.Fatalf("getJobStatus() failed: %v", err) 2042 } 2043 2044 if status != structs.JobStatusRunning { 2045 t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusRunning) 2046 } 2047 } 2048 2049 func TestStateStore_SetJobStatus_PendingEval(t *testing.T) { 2050 state := testStateStore(t) 2051 job := mock.Job() 2052 2053 // Create a mock eval that is pending. 2054 eval := mock.Eval() 2055 eval.JobID = job.ID 2056 eval.Status = structs.EvalStatusPending 2057 if err := state.UpsertEvals(1000, []*structs.Evaluation{eval}); err != nil { 2058 t.Fatalf("err: %v", err) 2059 } 2060 2061 txn := state.db.Txn(false) 2062 status, err := state.getJobStatus(txn, job, true) 2063 if err != nil { 2064 t.Fatalf("getJobStatus() failed: %v", err) 2065 } 2066 2067 if status != structs.JobStatusPending { 2068 t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusPending) 2069 } 2070 } 2071 2072 func TestStateWatch_watch(t *testing.T) { 2073 sw := newStateWatch() 2074 notify1 := make(chan struct{}, 1) 2075 notify2 := make(chan struct{}, 1) 2076 notify3 := make(chan struct{}, 1) 2077 2078 // Notifications trigger subscribed channels 2079 sw.watch(watch.NewItems(watch.Item{Table: "foo"}), notify1) 2080 sw.watch(watch.NewItems(watch.Item{Table: "bar"}), notify2) 2081 sw.watch(watch.NewItems(watch.Item{Table: "baz"}), notify3) 2082 2083 items := watch.NewItems() 2084 items.Add(watch.Item{Table: "foo"}) 2085 items.Add(watch.Item{Table: "bar"}) 2086 2087 sw.notify(items) 2088 if len(notify1) != 1 { 2089 t.Fatalf("should notify") 2090 } 2091 if len(notify2) != 1 { 2092 t.Fatalf("should notify") 2093 } 2094 if len(notify3) != 0 { 2095 t.Fatalf("should not notify") 2096 } 2097 } 2098 2099 func TestStateWatch_stopWatch(t *testing.T) { 2100 sw := newStateWatch() 2101 notify := make(chan struct{}) 2102 2103 // First subscribe 2104 sw.watch(watch.NewItems(watch.Item{Table: "foo"}), notify) 2105 2106 // Unsubscribe stop notifications 2107 sw.stopWatch(watch.NewItems(watch.Item{Table: "foo"}), notify) 2108 2109 // Check that the group was removed 2110 if _, ok := sw.items[watch.Item{Table: "foo"}]; ok { 2111 t.Fatalf("should remove group") 2112 } 2113 2114 // Check that we are not notified 2115 sw.notify(watch.NewItems(watch.Item{Table: "foo"})) 2116 if len(notify) != 0 { 2117 t.Fatalf("should not notify") 2118 } 2119 } 2120 2121 // setupNotifyTest takes a state store and a set of watch items, then creates 2122 // and subscribes a notification channel for each item. 2123 func setupNotifyTest(state *StateStore, items ...watch.Item) notifyTest { 2124 var n notifyTest 2125 for _, item := range items { 2126 ch := make(chan struct{}, 1) 2127 state.Watch(watch.NewItems(item), ch) 2128 n = append(n, ¬ifyTestCase{item, ch}) 2129 } 2130 return n 2131 } 2132 2133 // notifyTestCase is used to set up and verify watch triggers. 2134 type notifyTestCase struct { 2135 item watch.Item 2136 ch chan struct{} 2137 } 2138 2139 // notifyTest is a suite of notifyTestCases. 2140 type notifyTest []*notifyTestCase 2141 2142 // verify ensures that each channel received a notification. 2143 func (n notifyTest) verify(t *testing.T) { 2144 for _, tcase := range n { 2145 if len(tcase.ch) != 1 { 2146 t.Fatalf("should notify %#v", tcase.item) 2147 } 2148 } 2149 } 2150 2151 // NodeIDSort is used to sort nodes by ID 2152 type NodeIDSort []*structs.Node 2153 2154 func (n NodeIDSort) Len() int { 2155 return len(n) 2156 } 2157 2158 func (n NodeIDSort) Less(i, j int) bool { 2159 return n[i].ID < n[j].ID 2160 } 2161 2162 func (n NodeIDSort) Swap(i, j int) { 2163 n[i], n[j] = n[j], n[i] 2164 } 2165 2166 // JobIDis used to sort jobs by id 2167 type JobIDSort []*structs.Job 2168 2169 func (n JobIDSort) Len() int { 2170 return len(n) 2171 } 2172 2173 func (n JobIDSort) Less(i, j int) bool { 2174 return n[i].ID < n[j].ID 2175 } 2176 2177 func (n JobIDSort) Swap(i, j int) { 2178 n[i], n[j] = n[j], n[i] 2179 } 2180 2181 // EvalIDis used to sort evals by id 2182 type EvalIDSort []*structs.Evaluation 2183 2184 func (n EvalIDSort) Len() int { 2185 return len(n) 2186 } 2187 2188 func (n EvalIDSort) Less(i, j int) bool { 2189 return n[i].ID < n[j].ID 2190 } 2191 2192 func (n EvalIDSort) Swap(i, j int) { 2193 n[i], n[j] = n[j], n[i] 2194 } 2195 2196 // AllocIDsort used to sort allocations by id 2197 type AllocIDSort []*structs.Allocation 2198 2199 func (n AllocIDSort) Len() int { 2200 return len(n) 2201 } 2202 2203 func (n AllocIDSort) Less(i, j int) bool { 2204 return n[i].ID < n[j].ID 2205 } 2206 2207 func (n AllocIDSort) Swap(i, j int) { 2208 n[i], n[j] = n[j], n[i] 2209 }