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