github.com/taylorchu/nomad@v0.5.3-rc1.0.20170407200202-db11e7dd7b55/nomad/eval_endpoint_test.go (about)

     1  package nomad
     2  
     3  import (
     4  	"reflect"
     5  	"strings"
     6  	"testing"
     7  	"time"
     8  
     9  	memdb "github.com/hashicorp/go-memdb"
    10  	"github.com/hashicorp/net-rpc-msgpackrpc"
    11  	"github.com/hashicorp/nomad/nomad/mock"
    12  	"github.com/hashicorp/nomad/nomad/structs"
    13  	"github.com/hashicorp/nomad/scheduler"
    14  	"github.com/hashicorp/nomad/testutil"
    15  )
    16  
    17  func TestEvalEndpoint_GetEval(t *testing.T) {
    18  	s1 := testServer(t, nil)
    19  	defer s1.Shutdown()
    20  	codec := rpcClient(t, s1)
    21  	testutil.WaitForLeader(t, s1.RPC)
    22  
    23  	// Create the register request
    24  	eval1 := mock.Eval()
    25  	s1.fsm.State().UpsertEvals(1000, []*structs.Evaluation{eval1})
    26  
    27  	// Lookup the eval
    28  	get := &structs.EvalSpecificRequest{
    29  		EvalID:       eval1.ID,
    30  		QueryOptions: structs.QueryOptions{Region: "global"},
    31  	}
    32  	var resp structs.SingleEvalResponse
    33  	if err := msgpackrpc.CallWithCodec(codec, "Eval.GetEval", get, &resp); err != nil {
    34  		t.Fatalf("err: %v", err)
    35  	}
    36  	if resp.Index != 1000 {
    37  		t.Fatalf("Bad index: %d %d", resp.Index, 1000)
    38  	}
    39  
    40  	if !reflect.DeepEqual(eval1, resp.Eval) {
    41  		t.Fatalf("bad: %#v %#v", eval1, resp.Eval)
    42  	}
    43  
    44  	// Lookup non-existing node
    45  	get.EvalID = structs.GenerateUUID()
    46  	if err := msgpackrpc.CallWithCodec(codec, "Eval.GetEval", get, &resp); err != nil {
    47  		t.Fatalf("err: %v", err)
    48  	}
    49  	if resp.Index != 1000 {
    50  		t.Fatalf("Bad index: %d %d", resp.Index, 1000)
    51  	}
    52  	if resp.Eval != nil {
    53  		t.Fatalf("unexpected eval")
    54  	}
    55  }
    56  
    57  func TestEvalEndpoint_GetEval_Blocking(t *testing.T) {
    58  	s1 := testServer(t, nil)
    59  	defer s1.Shutdown()
    60  	state := s1.fsm.State()
    61  	codec := rpcClient(t, s1)
    62  	testutil.WaitForLeader(t, s1.RPC)
    63  
    64  	// Create the evals
    65  	eval1 := mock.Eval()
    66  	eval2 := mock.Eval()
    67  
    68  	// First create an unrelated eval
    69  	time.AfterFunc(100*time.Millisecond, func() {
    70  		err := state.UpsertEvals(100, []*structs.Evaluation{eval1})
    71  		if err != nil {
    72  			t.Fatalf("err: %v", err)
    73  		}
    74  	})
    75  
    76  	// Upsert the eval we are watching later
    77  	time.AfterFunc(200*time.Millisecond, func() {
    78  		err := state.UpsertEvals(200, []*structs.Evaluation{eval2})
    79  		if err != nil {
    80  			t.Fatalf("err: %v", err)
    81  		}
    82  	})
    83  
    84  	// Lookup the eval
    85  	req := &structs.EvalSpecificRequest{
    86  		EvalID: eval2.ID,
    87  		QueryOptions: structs.QueryOptions{
    88  			Region:        "global",
    89  			MinQueryIndex: 150,
    90  		},
    91  	}
    92  	var resp structs.SingleEvalResponse
    93  	start := time.Now()
    94  	if err := msgpackrpc.CallWithCodec(codec, "Eval.GetEval", req, &resp); err != nil {
    95  		t.Fatalf("err: %v", err)
    96  	}
    97  
    98  	if elapsed := time.Since(start); elapsed < 200*time.Millisecond {
    99  		t.Fatalf("should block (returned in %s) %#v", elapsed, resp)
   100  	}
   101  	if resp.Index != 200 {
   102  		t.Fatalf("Bad index: %d %d", resp.Index, 200)
   103  	}
   104  	if resp.Eval == nil || resp.Eval.ID != eval2.ID {
   105  		t.Fatalf("bad: %#v", resp.Eval)
   106  	}
   107  
   108  	// Eval delete triggers watches
   109  	time.AfterFunc(100*time.Millisecond, func() {
   110  		err := state.DeleteEval(300, []string{eval2.ID}, []string{})
   111  		if err != nil {
   112  			t.Fatalf("err: %v", err)
   113  		}
   114  	})
   115  
   116  	req.QueryOptions.MinQueryIndex = 250
   117  	var resp2 structs.SingleEvalResponse
   118  	start = time.Now()
   119  	if err := msgpackrpc.CallWithCodec(codec, "Eval.GetEval", req, &resp2); err != nil {
   120  		t.Fatalf("err: %v", err)
   121  	}
   122  
   123  	if elapsed := time.Since(start); elapsed < 100*time.Millisecond {
   124  		t.Fatalf("should block (returned in %s) %#v", elapsed, resp2)
   125  	}
   126  	if resp2.Index != 300 {
   127  		t.Fatalf("Bad index: %d %d", resp2.Index, 300)
   128  	}
   129  	if resp2.Eval != nil {
   130  		t.Fatalf("bad: %#v", resp2.Eval)
   131  	}
   132  }
   133  
   134  func TestEvalEndpoint_Dequeue(t *testing.T) {
   135  	s1 := testServer(t, func(c *Config) {
   136  		c.NumSchedulers = 0 // Prevent automatic dequeue
   137  	})
   138  	defer s1.Shutdown()
   139  	codec := rpcClient(t, s1)
   140  	testutil.WaitForLeader(t, s1.RPC)
   141  
   142  	// Create the register request
   143  	eval1 := mock.Eval()
   144  	s1.evalBroker.Enqueue(eval1)
   145  
   146  	// Dequeue the eval
   147  	get := &structs.EvalDequeueRequest{
   148  		Schedulers:       defaultSched,
   149  		SchedulerVersion: scheduler.SchedulerVersion,
   150  		WriteRequest:     structs.WriteRequest{Region: "global"},
   151  	}
   152  	var resp structs.EvalDequeueResponse
   153  	if err := msgpackrpc.CallWithCodec(codec, "Eval.Dequeue", get, &resp); err != nil {
   154  		t.Fatalf("err: %v", err)
   155  	}
   156  
   157  	if !reflect.DeepEqual(eval1, resp.Eval) {
   158  		t.Fatalf("bad: %v %v", eval1, resp.Eval)
   159  	}
   160  
   161  	// Ensure outstanding
   162  	token, ok := s1.evalBroker.Outstanding(eval1.ID)
   163  	if !ok {
   164  		t.Fatalf("should be outstanding")
   165  	}
   166  	if token != resp.Token {
   167  		t.Fatalf("bad token: %#v %#v", token, resp.Token)
   168  	}
   169  }
   170  
   171  func TestEvalEndpoint_Dequeue_Version_Mismatch(t *testing.T) {
   172  	s1 := testServer(t, func(c *Config) {
   173  		c.NumSchedulers = 0 // Prevent automatic dequeue
   174  	})
   175  	defer s1.Shutdown()
   176  	codec := rpcClient(t, s1)
   177  	testutil.WaitForLeader(t, s1.RPC)
   178  
   179  	// Create the register request
   180  	eval1 := mock.Eval()
   181  	s1.evalBroker.Enqueue(eval1)
   182  
   183  	// Dequeue the eval
   184  	get := &structs.EvalDequeueRequest{
   185  		Schedulers:       defaultSched,
   186  		SchedulerVersion: 0,
   187  		WriteRequest:     structs.WriteRequest{Region: "global"},
   188  	}
   189  	var resp structs.EvalDequeueResponse
   190  	err := msgpackrpc.CallWithCodec(codec, "Eval.Dequeue", get, &resp)
   191  	if err == nil || !strings.Contains(err.Error(), "scheduler version is 0") {
   192  		t.Fatalf("err: %v", err)
   193  	}
   194  }
   195  
   196  func TestEvalEndpoint_Ack(t *testing.T) {
   197  	s1 := testServer(t, nil)
   198  	defer s1.Shutdown()
   199  	codec := rpcClient(t, s1)
   200  
   201  	testutil.WaitForResult(func() (bool, error) {
   202  		return s1.evalBroker.Enabled(), nil
   203  	}, func(err error) {
   204  		t.Fatalf("should enable eval broker")
   205  	})
   206  
   207  	// Create the register request
   208  	eval1 := mock.Eval()
   209  	s1.evalBroker.Enqueue(eval1)
   210  	out, token, err := s1.evalBroker.Dequeue(defaultSched, time.Second)
   211  	if err != nil {
   212  		t.Fatalf("err: %v", err)
   213  	}
   214  	if out == nil {
   215  		t.Fatalf("missing eval")
   216  	}
   217  
   218  	// Ack the eval
   219  	get := &structs.EvalAckRequest{
   220  		EvalID:       out.ID,
   221  		Token:        token,
   222  		WriteRequest: structs.WriteRequest{Region: "global"},
   223  	}
   224  	var resp structs.GenericResponse
   225  	if err := msgpackrpc.CallWithCodec(codec, "Eval.Ack", get, &resp); err != nil {
   226  		t.Fatalf("err: %v", err)
   227  	}
   228  
   229  	// Ensure outstanding
   230  	if _, ok := s1.evalBroker.Outstanding(eval1.ID); ok {
   231  		t.Fatalf("should not be outstanding")
   232  	}
   233  }
   234  
   235  func TestEvalEndpoint_Nack(t *testing.T) {
   236  	s1 := testServer(t, func(c *Config) {
   237  		// Disable all of the schedulers so we can manually dequeue
   238  		// evals and check the queue status
   239  		c.NumSchedulers = 0
   240  	})
   241  	defer s1.Shutdown()
   242  	codec := rpcClient(t, s1)
   243  
   244  	testutil.WaitForResult(func() (bool, error) {
   245  		return s1.evalBroker.Enabled(), nil
   246  	}, func(err error) {
   247  		t.Fatalf("should enable eval broker")
   248  	})
   249  
   250  	// Create the register request
   251  	eval1 := mock.Eval()
   252  	s1.evalBroker.Enqueue(eval1)
   253  	out, token, _ := s1.evalBroker.Dequeue(defaultSched, time.Second)
   254  	if out == nil {
   255  		t.Fatalf("missing eval")
   256  	}
   257  
   258  	// Nack the eval
   259  	get := &structs.EvalAckRequest{
   260  		EvalID:       out.ID,
   261  		Token:        token,
   262  		WriteRequest: structs.WriteRequest{Region: "global"},
   263  	}
   264  	var resp structs.GenericResponse
   265  	if err := msgpackrpc.CallWithCodec(codec, "Eval.Nack", get, &resp); err != nil {
   266  		t.Fatalf("err: %v", err)
   267  	}
   268  
   269  	// Ensure outstanding
   270  	if _, ok := s1.evalBroker.Outstanding(eval1.ID); ok {
   271  		t.Fatalf("should not be outstanding")
   272  	}
   273  
   274  	// Should get it back
   275  	out2, _, _ := s1.evalBroker.Dequeue(defaultSched, time.Second)
   276  	if out2 != out {
   277  		t.Fatalf("nack failed")
   278  	}
   279  }
   280  
   281  func TestEvalEndpoint_Update(t *testing.T) {
   282  	s1 := testServer(t, nil)
   283  	defer s1.Shutdown()
   284  	codec := rpcClient(t, s1)
   285  
   286  	testutil.WaitForResult(func() (bool, error) {
   287  		return s1.evalBroker.Enabled(), nil
   288  	}, func(err error) {
   289  		t.Fatalf("should enable eval broker")
   290  	})
   291  
   292  	// Create the register request
   293  	eval1 := mock.Eval()
   294  	s1.evalBroker.Enqueue(eval1)
   295  	out, token, err := s1.evalBroker.Dequeue(defaultSched, time.Second)
   296  	if err != nil {
   297  		t.Fatalf("err: %v", err)
   298  	}
   299  	if out == nil {
   300  		t.Fatalf("missing eval")
   301  	}
   302  
   303  	// Update the eval
   304  	eval2 := eval1.Copy()
   305  	eval2.Status = structs.EvalStatusComplete
   306  
   307  	get := &structs.EvalUpdateRequest{
   308  		Evals:        []*structs.Evaluation{eval2},
   309  		EvalToken:    token,
   310  		WriteRequest: structs.WriteRequest{Region: "global"},
   311  	}
   312  	var resp structs.GenericResponse
   313  	if err := msgpackrpc.CallWithCodec(codec, "Eval.Update", get, &resp); err != nil {
   314  		t.Fatalf("err: %v", err)
   315  	}
   316  
   317  	// Ensure updated
   318  	ws := memdb.NewWatchSet()
   319  	outE, err := s1.fsm.State().EvalByID(ws, eval2.ID)
   320  	if err != nil {
   321  		t.Fatalf("err: %v", err)
   322  	}
   323  	if outE.Status != structs.EvalStatusComplete {
   324  		t.Fatalf("Bad: %#v", out)
   325  	}
   326  }
   327  
   328  func TestEvalEndpoint_Create(t *testing.T) {
   329  	s1 := testServer(t, func(c *Config) {
   330  		c.NumSchedulers = 0 // Prevent automatic dequeue
   331  	})
   332  	defer s1.Shutdown()
   333  	codec := rpcClient(t, s1)
   334  
   335  	testutil.WaitForResult(func() (bool, error) {
   336  		return s1.evalBroker.Enabled(), nil
   337  	}, func(err error) {
   338  		t.Fatalf("should enable eval broker")
   339  	})
   340  
   341  	// Create the register request
   342  	prev := mock.Eval()
   343  	s1.evalBroker.Enqueue(prev)
   344  	out, token, err := s1.evalBroker.Dequeue(defaultSched, time.Second)
   345  	if err != nil {
   346  		t.Fatalf("err: %v", err)
   347  	}
   348  	if out == nil {
   349  		t.Fatalf("missing eval")
   350  	}
   351  
   352  	// Create the register request
   353  	eval1 := mock.Eval()
   354  	eval1.PreviousEval = prev.ID
   355  	get := &structs.EvalUpdateRequest{
   356  		Evals:        []*structs.Evaluation{eval1},
   357  		EvalToken:    token,
   358  		WriteRequest: structs.WriteRequest{Region: "global"},
   359  	}
   360  	var resp structs.GenericResponse
   361  	if err := msgpackrpc.CallWithCodec(codec, "Eval.Create", get, &resp); err != nil {
   362  		t.Fatalf("err: %v", err)
   363  	}
   364  
   365  	// Ensure created
   366  	ws := memdb.NewWatchSet()
   367  	outE, err := s1.fsm.State().EvalByID(ws, eval1.ID)
   368  	if err != nil {
   369  		t.Fatalf("err: %v", err)
   370  	}
   371  
   372  	eval1.CreateIndex = resp.Index
   373  	eval1.ModifyIndex = resp.Index
   374  	if !reflect.DeepEqual(eval1, outE) {
   375  		t.Fatalf("Bad: %#v %#v", outE, eval1)
   376  	}
   377  }
   378  
   379  func TestEvalEndpoint_Reap(t *testing.T) {
   380  	s1 := testServer(t, nil)
   381  	defer s1.Shutdown()
   382  	codec := rpcClient(t, s1)
   383  	testutil.WaitForLeader(t, s1.RPC)
   384  
   385  	// Create the register request
   386  	eval1 := mock.Eval()
   387  	s1.fsm.State().UpsertEvals(1000, []*structs.Evaluation{eval1})
   388  
   389  	// Reap the eval
   390  	get := &structs.EvalDeleteRequest{
   391  		Evals:        []string{eval1.ID},
   392  		WriteRequest: structs.WriteRequest{Region: "global"},
   393  	}
   394  	var resp structs.GenericResponse
   395  	if err := msgpackrpc.CallWithCodec(codec, "Eval.Reap", get, &resp); err != nil {
   396  		t.Fatalf("err: %v", err)
   397  	}
   398  	if resp.Index == 0 {
   399  		t.Fatalf("Bad index: %d", resp.Index)
   400  	}
   401  
   402  	// Ensure deleted
   403  	ws := memdb.NewWatchSet()
   404  	outE, err := s1.fsm.State().EvalByID(ws, eval1.ID)
   405  	if err != nil {
   406  		t.Fatalf("err: %v", err)
   407  	}
   408  	if outE != nil {
   409  		t.Fatalf("Bad: %#v", outE)
   410  	}
   411  }
   412  
   413  func TestEvalEndpoint_List(t *testing.T) {
   414  	s1 := testServer(t, nil)
   415  	defer s1.Shutdown()
   416  	codec := rpcClient(t, s1)
   417  	testutil.WaitForLeader(t, s1.RPC)
   418  
   419  	// Create the register request
   420  	eval1 := mock.Eval()
   421  	eval1.ID = "aaaaaaaa-3350-4b4b-d185-0e1992ed43e9"
   422  	eval2 := mock.Eval()
   423  	eval2.ID = "aaaabbbb-3350-4b4b-d185-0e1992ed43e9"
   424  	s1.fsm.State().UpsertEvals(1000, []*structs.Evaluation{eval1, eval2})
   425  
   426  	// Lookup the eval
   427  	get := &structs.EvalListRequest{
   428  		QueryOptions: structs.QueryOptions{Region: "global"},
   429  	}
   430  	var resp structs.EvalListResponse
   431  	if err := msgpackrpc.CallWithCodec(codec, "Eval.List", get, &resp); err != nil {
   432  		t.Fatalf("err: %v", err)
   433  	}
   434  	if resp.Index != 1000 {
   435  		t.Fatalf("Bad index: %d %d", resp.Index, 1000)
   436  	}
   437  
   438  	if len(resp.Evaluations) != 2 {
   439  		t.Fatalf("bad: %#v", resp.Evaluations)
   440  	}
   441  
   442  	// Lookup the eval by prefix
   443  	get = &structs.EvalListRequest{
   444  		QueryOptions: structs.QueryOptions{Region: "global", Prefix: "aaaabb"},
   445  	}
   446  	var resp2 structs.EvalListResponse
   447  	if err := msgpackrpc.CallWithCodec(codec, "Eval.List", get, &resp2); err != nil {
   448  		t.Fatalf("err: %v", err)
   449  	}
   450  	if resp2.Index != 1000 {
   451  		t.Fatalf("Bad index: %d %d", resp2.Index, 1000)
   452  	}
   453  
   454  	if len(resp2.Evaluations) != 1 {
   455  		t.Fatalf("bad: %#v", resp2.Evaluations)
   456  	}
   457  
   458  }
   459  
   460  func TestEvalEndpoint_List_Blocking(t *testing.T) {
   461  	s1 := testServer(t, nil)
   462  	defer s1.Shutdown()
   463  	state := s1.fsm.State()
   464  	codec := rpcClient(t, s1)
   465  	testutil.WaitForLeader(t, s1.RPC)
   466  
   467  	// Create the ieval
   468  	eval := mock.Eval()
   469  
   470  	// Upsert eval triggers watches
   471  	time.AfterFunc(100*time.Millisecond, func() {
   472  		if err := state.UpsertEvals(2, []*structs.Evaluation{eval}); err != nil {
   473  			t.Fatalf("err: %v", err)
   474  		}
   475  	})
   476  
   477  	req := &structs.EvalListRequest{
   478  		QueryOptions: structs.QueryOptions{
   479  			Region:        "global",
   480  			MinQueryIndex: 1,
   481  		},
   482  	}
   483  	start := time.Now()
   484  	var resp structs.EvalListResponse
   485  	if err := msgpackrpc.CallWithCodec(codec, "Eval.List", req, &resp); err != nil {
   486  		t.Fatalf("err: %v", err)
   487  	}
   488  
   489  	if elapsed := time.Since(start); elapsed < 100*time.Millisecond {
   490  		t.Fatalf("should block (returned in %s) %#v", elapsed, resp)
   491  	}
   492  	if resp.Index != 2 {
   493  		t.Fatalf("Bad index: %d %d", resp.Index, 2)
   494  	}
   495  	if len(resp.Evaluations) != 1 || resp.Evaluations[0].ID != eval.ID {
   496  		t.Fatalf("bad: %#v", resp.Evaluations)
   497  	}
   498  
   499  	// Eval deletion triggers watches
   500  	time.AfterFunc(100*time.Millisecond, func() {
   501  		if err := state.DeleteEval(3, []string{eval.ID}, nil); err != nil {
   502  			t.Fatalf("err: %v", err)
   503  		}
   504  	})
   505  
   506  	req.MinQueryIndex = 2
   507  	start = time.Now()
   508  	var resp2 structs.EvalListResponse
   509  	if err := msgpackrpc.CallWithCodec(codec, "Eval.List", req, &resp2); err != nil {
   510  		t.Fatalf("err: %v", err)
   511  	}
   512  
   513  	if elapsed := time.Since(start); elapsed < 100*time.Millisecond {
   514  		t.Fatalf("should block (returned in %s) %#v", elapsed, resp2)
   515  	}
   516  	if resp2.Index != 3 {
   517  		t.Fatalf("Bad index: %d %d", resp2.Index, 3)
   518  	}
   519  	if len(resp2.Evaluations) != 0 {
   520  		t.Fatalf("bad: %#v", resp2.Evaluations)
   521  	}
   522  }
   523  
   524  func TestEvalEndpoint_Allocations(t *testing.T) {
   525  	s1 := testServer(t, nil)
   526  	defer s1.Shutdown()
   527  	codec := rpcClient(t, s1)
   528  	testutil.WaitForLeader(t, s1.RPC)
   529  
   530  	// Create the register request
   531  	alloc1 := mock.Alloc()
   532  	alloc2 := mock.Alloc()
   533  	alloc2.EvalID = alloc1.EvalID
   534  	state := s1.fsm.State()
   535  	state.UpsertJobSummary(998, mock.JobSummary(alloc1.JobID))
   536  	state.UpsertJobSummary(999, mock.JobSummary(alloc2.JobID))
   537  	err := state.UpsertAllocs(1000,
   538  		[]*structs.Allocation{alloc1, alloc2})
   539  	if err != nil {
   540  		t.Fatalf("err: %v", err)
   541  	}
   542  
   543  	// Lookup the eval
   544  	get := &structs.EvalSpecificRequest{
   545  		EvalID:       alloc1.EvalID,
   546  		QueryOptions: structs.QueryOptions{Region: "global"},
   547  	}
   548  	var resp structs.EvalAllocationsResponse
   549  	if err := msgpackrpc.CallWithCodec(codec, "Eval.Allocations", get, &resp); err != nil {
   550  		t.Fatalf("err: %v", err)
   551  	}
   552  	if resp.Index != 1000 {
   553  		t.Fatalf("Bad index: %d %d", resp.Index, 1000)
   554  	}
   555  
   556  	if len(resp.Allocations) != 2 {
   557  		t.Fatalf("bad: %#v", resp.Allocations)
   558  	}
   559  }
   560  
   561  func TestEvalEndpoint_Allocations_Blocking(t *testing.T) {
   562  	s1 := testServer(t, nil)
   563  	defer s1.Shutdown()
   564  	state := s1.fsm.State()
   565  	codec := rpcClient(t, s1)
   566  	testutil.WaitForLeader(t, s1.RPC)
   567  
   568  	// Create the allocs
   569  	alloc1 := mock.Alloc()
   570  	alloc2 := mock.Alloc()
   571  
   572  	// Upsert an unrelated alloc first
   573  	time.AfterFunc(100*time.Millisecond, func() {
   574  		state.UpsertJobSummary(99, mock.JobSummary(alloc1.JobID))
   575  		err := state.UpsertAllocs(100, []*structs.Allocation{alloc1})
   576  		if err != nil {
   577  			t.Fatalf("err: %v", err)
   578  		}
   579  	})
   580  
   581  	// Upsert an alloc which will trigger the watch later
   582  	time.AfterFunc(200*time.Millisecond, func() {
   583  		state.UpsertJobSummary(199, mock.JobSummary(alloc2.JobID))
   584  		err := state.UpsertAllocs(200, []*structs.Allocation{alloc2})
   585  		if err != nil {
   586  			t.Fatalf("err: %v", err)
   587  		}
   588  	})
   589  
   590  	// Lookup the eval
   591  	get := &structs.EvalSpecificRequest{
   592  		EvalID: alloc2.EvalID,
   593  		QueryOptions: structs.QueryOptions{
   594  			Region:        "global",
   595  			MinQueryIndex: 150,
   596  		},
   597  	}
   598  	var resp structs.EvalAllocationsResponse
   599  	start := time.Now()
   600  	if err := msgpackrpc.CallWithCodec(codec, "Eval.Allocations", get, &resp); err != nil {
   601  		t.Fatalf("err: %v", err)
   602  	}
   603  
   604  	if elapsed := time.Since(start); elapsed < 200*time.Millisecond {
   605  		t.Fatalf("should block (returned in %s) %#v", elapsed, resp)
   606  	}
   607  	if resp.Index != 200 {
   608  		t.Fatalf("Bad index: %d %d", resp.Index, 200)
   609  	}
   610  	if len(resp.Allocations) != 1 || resp.Allocations[0].ID != alloc2.ID {
   611  		t.Fatalf("bad: %#v", resp.Allocations)
   612  	}
   613  }
   614  
   615  func TestEvalEndpoint_Reblock_NonExistent(t *testing.T) {
   616  	s1 := testServer(t, func(c *Config) {
   617  		c.NumSchedulers = 0 // Prevent automatic dequeue
   618  	})
   619  	defer s1.Shutdown()
   620  	codec := rpcClient(t, s1)
   621  
   622  	testutil.WaitForResult(func() (bool, error) {
   623  		return s1.evalBroker.Enabled(), nil
   624  	}, func(err error) {
   625  		t.Fatalf("should enable eval broker")
   626  	})
   627  
   628  	// Create the register request
   629  	eval1 := mock.Eval()
   630  	s1.evalBroker.Enqueue(eval1)
   631  	out, token, err := s1.evalBroker.Dequeue(defaultSched, time.Second)
   632  	if err != nil {
   633  		t.Fatalf("err: %v", err)
   634  	}
   635  	if out == nil {
   636  		t.Fatalf("missing eval")
   637  	}
   638  
   639  	get := &structs.EvalUpdateRequest{
   640  		Evals:        []*structs.Evaluation{eval1},
   641  		EvalToken:    token,
   642  		WriteRequest: structs.WriteRequest{Region: "global"},
   643  	}
   644  	var resp structs.GenericResponse
   645  	if err := msgpackrpc.CallWithCodec(codec, "Eval.Reblock", get, &resp); err == nil {
   646  		t.Fatalf("expect error since eval does not exist")
   647  	}
   648  }
   649  
   650  func TestEvalEndpoint_Reblock_NonBlocked(t *testing.T) {
   651  	s1 := testServer(t, func(c *Config) {
   652  		c.NumSchedulers = 0 // Prevent automatic dequeue
   653  	})
   654  	defer s1.Shutdown()
   655  	codec := rpcClient(t, s1)
   656  
   657  	testutil.WaitForResult(func() (bool, error) {
   658  		return s1.evalBroker.Enabled(), nil
   659  	}, func(err error) {
   660  		t.Fatalf("should enable eval broker")
   661  	})
   662  
   663  	// Create the eval
   664  	eval1 := mock.Eval()
   665  	s1.evalBroker.Enqueue(eval1)
   666  
   667  	// Insert it into the state store
   668  	if err := s1.fsm.State().UpsertEvals(1000, []*structs.Evaluation{eval1}); err != nil {
   669  		t.Fatal(err)
   670  	}
   671  
   672  	out, token, err := s1.evalBroker.Dequeue(defaultSched, 2*time.Second)
   673  	if err != nil {
   674  		t.Fatalf("err: %v", err)
   675  	}
   676  	if out == nil {
   677  		t.Fatalf("missing eval")
   678  	}
   679  
   680  	get := &structs.EvalUpdateRequest{
   681  		Evals:        []*structs.Evaluation{eval1},
   682  		EvalToken:    token,
   683  		WriteRequest: structs.WriteRequest{Region: "global"},
   684  	}
   685  	var resp structs.GenericResponse
   686  	if err := msgpackrpc.CallWithCodec(codec, "Eval.Reblock", get, &resp); err == nil {
   687  		t.Fatalf("should error since eval was not in blocked state: %v", err)
   688  	}
   689  }
   690  
   691  func TestEvalEndpoint_Reblock(t *testing.T) {
   692  	s1 := testServer(t, func(c *Config) {
   693  		c.NumSchedulers = 0 // Prevent automatic dequeue
   694  	})
   695  	defer s1.Shutdown()
   696  	codec := rpcClient(t, s1)
   697  
   698  	testutil.WaitForResult(func() (bool, error) {
   699  		return s1.evalBroker.Enabled(), nil
   700  	}, func(err error) {
   701  		t.Fatalf("should enable eval broker")
   702  	})
   703  
   704  	// Create the eval
   705  	eval1 := mock.Eval()
   706  	eval1.Status = structs.EvalStatusBlocked
   707  	s1.evalBroker.Enqueue(eval1)
   708  
   709  	// Insert it into the state store
   710  	if err := s1.fsm.State().UpsertEvals(1000, []*structs.Evaluation{eval1}); err != nil {
   711  		t.Fatal(err)
   712  	}
   713  
   714  	out, token, err := s1.evalBroker.Dequeue(defaultSched, 7*time.Second)
   715  	if err != nil {
   716  		t.Fatalf("err: %v", err)
   717  	}
   718  	if out == nil {
   719  		t.Fatalf("bad: %v", out)
   720  	}
   721  
   722  	get := &structs.EvalUpdateRequest{
   723  		Evals:        []*structs.Evaluation{eval1},
   724  		EvalToken:    token,
   725  		WriteRequest: structs.WriteRequest{Region: "global"},
   726  	}
   727  	var resp structs.GenericResponse
   728  	if err := msgpackrpc.CallWithCodec(codec, "Eval.Reblock", get, &resp); err != nil {
   729  		t.Fatalf("err: %v", err)
   730  	}
   731  
   732  	// Check that it is blocked
   733  	bStats := s1.blockedEvals.Stats()
   734  	if bStats.TotalBlocked+bStats.TotalEscaped == 0 {
   735  		t.Fatalf("ReblockEval didn't insert eval into the blocked eval tracker")
   736  	}
   737  }