github.com/diptanu/nomad@v0.5.7-0.20170516172507-d72e86cbe3d9/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 164 plans := make([]*structs.Plan, 100) 165 for i := 0; i < len(plans); i++ { 166 if i%5 == 0 { 167 time.Sleep(10 * time.Millisecond) 168 } 169 plans[i] = mock.Plan() 170 pq.Enqueue(plans[i]) 171 } 172 173 var prev *pendingPlan 174 for i := range plans { 175 out, err := pq.Dequeue(time.Second) 176 if err != nil { 177 t.Fatalf("failed to dequeue plan %d: %v", i, err) 178 } 179 if prev != nil && out.enqueueTime.Before(prev.enqueueTime) { 180 t.Fatalf("out of order dequeue at %d, prev=%v, got=%v", i, prev.enqueueTime, out.enqueueTime) 181 } 182 prev = out 183 } 184 }