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