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  }