2015-07-27 21:59:16 +00:00
|
|
|
package nomad
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2015-08-11 21:27:14 +00:00
|
|
|
"github.com/hashicorp/nomad/nomad/mock"
|
2015-07-27 21:59:16 +00:00
|
|
|
"github.com/hashicorp/nomad/nomad/structs"
|
|
|
|
)
|
|
|
|
|
|
|
|
func testPlanQueue(t *testing.T) *PlanQueue {
|
|
|
|
pq, err := NewPlanQueue()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
return pq
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestPlanQueue_Enqueue_Dequeue(t *testing.T) {
|
|
|
|
pq := testPlanQueue(t)
|
2015-08-05 23:30:57 +00:00
|
|
|
if pq.Enabled() {
|
|
|
|
t.Fatalf("should not be enabled")
|
|
|
|
}
|
2015-07-27 21:59:16 +00:00
|
|
|
pq.SetEnabled(true)
|
2015-08-05 23:30:57 +00:00
|
|
|
if !pq.Enabled() {
|
|
|
|
t.Fatalf("should be enabled")
|
|
|
|
}
|
2015-07-27 21:59:16 +00:00
|
|
|
|
2015-08-11 21:27:14 +00:00
|
|
|
plan := mock.Plan()
|
2015-07-27 21:59:16 +00:00
|
|
|
future, err := pq.Enqueue(plan)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
stats := pq.Stats()
|
|
|
|
if stats.Depth != 1 {
|
|
|
|
t.Fatalf("bad: %#v", stats)
|
|
|
|
}
|
|
|
|
|
|
|
|
resCh := make(chan *structs.PlanResult, 1)
|
|
|
|
go func() {
|
|
|
|
res, err := future.Wait()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
resCh <- res
|
|
|
|
}()
|
|
|
|
|
|
|
|
pending, err := pq.Dequeue(time.Second)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
stats = pq.Stats()
|
|
|
|
if stats.Depth != 0 {
|
|
|
|
t.Fatalf("bad: %#v", stats)
|
|
|
|
}
|
|
|
|
|
|
|
|
if pending == nil || pending.plan != plan {
|
|
|
|
t.Fatalf("bad: %#v", pending)
|
|
|
|
}
|
|
|
|
|
2015-08-11 21:27:14 +00:00
|
|
|
result := mock.PlanResult()
|
2015-07-27 21:59:16 +00:00
|
|
|
pending.respond(result, nil)
|
|
|
|
|
|
|
|
select {
|
|
|
|
case r := <-resCh:
|
|
|
|
if r != result {
|
|
|
|
t.Fatalf("Bad: %#v", r)
|
|
|
|
}
|
|
|
|
case <-time.After(time.Second):
|
|
|
|
t.Fatalf("timeout")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestPlanQueue_Enqueue_Disable(t *testing.T) {
|
|
|
|
pq := testPlanQueue(t)
|
|
|
|
|
|
|
|
// Enqueue
|
2015-08-11 21:27:14 +00:00
|
|
|
plan := mock.Plan()
|
2015-07-27 21:59:16 +00:00
|
|
|
pq.SetEnabled(true)
|
|
|
|
future, err := pq.Enqueue(plan)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Flush via SetEnabled
|
|
|
|
pq.SetEnabled(false)
|
|
|
|
|
|
|
|
// Check the stats
|
|
|
|
stats := pq.Stats()
|
|
|
|
if stats.Depth != 0 {
|
|
|
|
t.Fatalf("bad: %#v", stats)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Future should be canceled
|
|
|
|
res, err := future.Wait()
|
|
|
|
if err != planQueueFlushed {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if res != nil {
|
|
|
|
t.Fatalf("bad: %#v", res)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestPlanQueue_Dequeue_Timeout(t *testing.T) {
|
|
|
|
pq := testPlanQueue(t)
|
|
|
|
pq.SetEnabled(true)
|
|
|
|
|
|
|
|
start := time.Now()
|
|
|
|
out, err := pq.Dequeue(5 * time.Millisecond)
|
|
|
|
end := time.Now()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if out != nil {
|
|
|
|
t.Fatalf("unexpected: %#v", out)
|
|
|
|
}
|
|
|
|
|
|
|
|
if diff := end.Sub(start); diff < 5*time.Millisecond {
|
|
|
|
t.Fatalf("bad: %#v", diff)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure higher priority dequeued first
|
|
|
|
func TestPlanQueue_Dequeue_Priority(t *testing.T) {
|
|
|
|
pq := testPlanQueue(t)
|
|
|
|
pq.SetEnabled(true)
|
|
|
|
|
2015-08-11 21:27:14 +00:00
|
|
|
plan1 := mock.Plan()
|
2015-07-27 21:59:16 +00:00
|
|
|
plan1.Priority = 10
|
|
|
|
pq.Enqueue(plan1)
|
|
|
|
|
2015-08-11 21:27:14 +00:00
|
|
|
plan2 := mock.Plan()
|
2015-07-27 21:59:16 +00:00
|
|
|
plan2.Priority = 30
|
|
|
|
pq.Enqueue(plan2)
|
|
|
|
|
2015-08-11 21:27:14 +00:00
|
|
|
plan3 := mock.Plan()
|
2015-07-27 21:59:16 +00:00
|
|
|
plan3.Priority = 20
|
|
|
|
pq.Enqueue(plan3)
|
|
|
|
|
|
|
|
out1, _ := pq.Dequeue(time.Second)
|
|
|
|
if out1.plan != plan2 {
|
|
|
|
t.Fatalf("bad: %#v", out1)
|
|
|
|
}
|
|
|
|
|
|
|
|
out2, _ := pq.Dequeue(time.Second)
|
|
|
|
if out2.plan != plan3 {
|
|
|
|
t.Fatalf("bad: %#v", out2)
|
|
|
|
}
|
|
|
|
|
|
|
|
out3, _ := pq.Dequeue(time.Second)
|
|
|
|
if out3.plan != plan1 {
|
|
|
|
t.Fatalf("bad: %#v", out3)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure FIFO at fixed priority
|
|
|
|
func TestPlanQueue_Dequeue_FIFO(t *testing.T) {
|
|
|
|
pq := testPlanQueue(t)
|
|
|
|
pq.SetEnabled(true)
|
|
|
|
NUM := 100
|
|
|
|
|
2015-07-29 00:49:27 +00:00
|
|
|
plans := make([]*structs.Plan, NUM)
|
2015-07-27 21:59:16 +00:00
|
|
|
for i := 0; i < NUM; i++ {
|
2015-08-11 21:27:14 +00:00
|
|
|
plan := mock.Plan()
|
2015-07-27 21:59:16 +00:00
|
|
|
pq.Enqueue(plan)
|
2015-07-29 00:49:27 +00:00
|
|
|
plans[i] = plan
|
2015-07-27 21:59:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for i := 0; i < NUM; i++ {
|
|
|
|
out1, _ := pq.Dequeue(time.Second)
|
2015-07-29 00:49:27 +00:00
|
|
|
if out1.plan != plans[i] {
|
2015-07-27 21:59:16 +00:00
|
|
|
t.Fatalf("bad: %d %#v", i, out1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|