github.com/kardianos/nomad@v0.1.3-0.20151022182107-b13df73ee850/nomad/plan_queue_test.go (about) 1 package nomad 2 3 import ( 4 "testing" 5 "time" 6 7 "github.com/hashicorp/nomad/nomad/mock" 8 "github.com/hashicorp/nomad/nomad/structs" 9 ) 10 11 func testPlanQueue(t *testing.T) *PlanQueue { 12 pq, err := NewPlanQueue() 13 if err != nil { 14 t.Fatalf("err: %v", err) 15 } 16 return pq 17 } 18 19 func TestPlanQueue_Enqueue_Dequeue(t *testing.T) { 20 pq := testPlanQueue(t) 21 if pq.Enabled() { 22 t.Fatalf("should not be enabled") 23 } 24 pq.SetEnabled(true) 25 if !pq.Enabled() { 26 t.Fatalf("should be enabled") 27 } 28 29 plan := mock.Plan() 30 future, err := pq.Enqueue(plan) 31 if err != nil { 32 t.Fatalf("err: %v", err) 33 } 34 35 stats := pq.Stats() 36 if stats.Depth != 1 { 37 t.Fatalf("bad: %#v", stats) 38 } 39 40 resCh := make(chan *structs.PlanResult, 1) 41 go func() { 42 res, err := future.Wait() 43 if err != nil { 44 t.Fatalf("err: %v", err) 45 } 46 resCh <- res 47 }() 48 49 pending, err := pq.Dequeue(time.Second) 50 if err != nil { 51 t.Fatalf("err: %v", err) 52 } 53 54 stats = pq.Stats() 55 if stats.Depth != 0 { 56 t.Fatalf("bad: %#v", stats) 57 } 58 59 if pending == nil || pending.plan != plan { 60 t.Fatalf("bad: %#v", pending) 61 } 62 63 result := mock.PlanResult() 64 pending.respond(result, nil) 65 66 select { 67 case r := <-resCh: 68 if r != result { 69 t.Fatalf("Bad: %#v", r) 70 } 71 case <-time.After(time.Second): 72 t.Fatalf("timeout") 73 } 74 } 75 76 func TestPlanQueue_Enqueue_Disable(t *testing.T) { 77 pq := testPlanQueue(t) 78 79 // Enqueue 80 plan := mock.Plan() 81 pq.SetEnabled(true) 82 future, err := pq.Enqueue(plan) 83 if err != nil { 84 t.Fatalf("err: %v", err) 85 } 86 87 // Flush via SetEnabled 88 pq.SetEnabled(false) 89 90 // Check the stats 91 stats := pq.Stats() 92 if stats.Depth != 0 { 93 t.Fatalf("bad: %#v", stats) 94 } 95 96 // Future should be canceled 97 res, err := future.Wait() 98 if err != planQueueFlushed { 99 t.Fatalf("err: %v", err) 100 } 101 if res != nil { 102 t.Fatalf("bad: %#v", res) 103 } 104 } 105 106 func TestPlanQueue_Dequeue_Timeout(t *testing.T) { 107 pq := testPlanQueue(t) 108 pq.SetEnabled(true) 109 110 start := time.Now() 111 out, err := pq.Dequeue(5 * time.Millisecond) 112 end := time.Now() 113 114 if err != nil { 115 t.Fatalf("err: %v", err) 116 } 117 if out != nil { 118 t.Fatalf("unexpected: %#v", out) 119 } 120 121 if diff := end.Sub(start); diff < 5*time.Millisecond { 122 t.Fatalf("bad: %#v", diff) 123 } 124 } 125 126 // Ensure higher priority dequeued first 127 func TestPlanQueue_Dequeue_Priority(t *testing.T) { 128 pq := testPlanQueue(t) 129 pq.SetEnabled(true) 130 131 plan1 := mock.Plan() 132 plan1.Priority = 10 133 pq.Enqueue(plan1) 134 135 plan2 := mock.Plan() 136 plan2.Priority = 30 137 pq.Enqueue(plan2) 138 139 plan3 := mock.Plan() 140 plan3.Priority = 20 141 pq.Enqueue(plan3) 142 143 out1, _ := pq.Dequeue(time.Second) 144 if out1.plan != plan2 { 145 t.Fatalf("bad: %#v", out1) 146 } 147 148 out2, _ := pq.Dequeue(time.Second) 149 if out2.plan != plan3 { 150 t.Fatalf("bad: %#v", out2) 151 } 152 153 out3, _ := pq.Dequeue(time.Second) 154 if out3.plan != plan1 { 155 t.Fatalf("bad: %#v", out3) 156 } 157 } 158 159 // Ensure FIFO at fixed priority 160 func TestPlanQueue_Dequeue_FIFO(t *testing.T) { 161 pq := testPlanQueue(t) 162 pq.SetEnabled(true) 163 NUM := 100 164 165 plans := make([]*structs.Plan, NUM) 166 for i := 0; i < NUM; i++ { 167 plan := mock.Plan() 168 pq.Enqueue(plan) 169 plans[i] = plan 170 } 171 172 for i := 0; i < NUM; i++ { 173 out1, _ := pq.Dequeue(time.Second) 174 if out1.plan != plans[i] { 175 t.Fatalf("bad: %d %#v", i, out1) 176 } 177 } 178 }