github.com/anuvu/nomad@v0.8.7-atom1/nomad/state/state_store_test.go (about)

     1  package state
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"reflect"
     7  	"sort"
     8  	"strings"
     9  	"testing"
    10  	"time"
    11  
    12  	memdb "github.com/hashicorp/go-memdb"
    13  	"github.com/hashicorp/nomad/helper"
    14  	"github.com/hashicorp/nomad/helper/uuid"
    15  	"github.com/hashicorp/nomad/nomad/mock"
    16  	"github.com/hashicorp/nomad/nomad/structs"
    17  	"github.com/stretchr/testify/assert"
    18  	"github.com/stretchr/testify/require"
    19  )
    20  
    21  func testStateStore(t *testing.T) *StateStore {
    22  	return TestStateStore(t)
    23  }
    24  
    25  func TestStateStore_Blocking_Error(t *testing.T) {
    26  	t.Parallel()
    27  	expected := fmt.Errorf("test error")
    28  	errFn := func(memdb.WatchSet, *StateStore) (interface{}, uint64, error) {
    29  		return nil, 0, expected
    30  	}
    31  
    32  	state := testStateStore(t)
    33  	_, idx, err := state.BlockingQuery(errFn, 10, context.Background())
    34  	assert.EqualError(t, err, expected.Error())
    35  	assert.Zero(t, idx)
    36  }
    37  
    38  func TestStateStore_Blocking_Timeout(t *testing.T) {
    39  	t.Parallel()
    40  	noopFn := func(memdb.WatchSet, *StateStore) (interface{}, uint64, error) {
    41  		return nil, 5, nil
    42  	}
    43  
    44  	state := testStateStore(t)
    45  	timeout := time.Now().Add(250 * time.Millisecond)
    46  	deadlineCtx, cancel := context.WithDeadline(context.Background(), timeout)
    47  	defer cancel()
    48  
    49  	_, idx, err := state.BlockingQuery(noopFn, 10, deadlineCtx)
    50  	assert.EqualError(t, err, context.DeadlineExceeded.Error())
    51  	assert.EqualValues(t, 5, idx)
    52  	assert.WithinDuration(t, timeout, time.Now(), 100*time.Millisecond)
    53  }
    54  
    55  func TestStateStore_Blocking_MinQuery(t *testing.T) {
    56  	node := mock.Node()
    57  	count := 0
    58  	queryFn := func(ws memdb.WatchSet, s *StateStore) (interface{}, uint64, error) {
    59  		_, err := s.NodeByID(ws, node.ID)
    60  		if err != nil {
    61  			return nil, 0, err
    62  		}
    63  
    64  		count++
    65  		if count == 1 {
    66  			return false, 5, nil
    67  		} else if count > 2 {
    68  			return false, 20, fmt.Errorf("called too many times")
    69  		}
    70  
    71  		return true, 11, nil
    72  	}
    73  
    74  	state := testStateStore(t)
    75  	timeout := time.Now().Add(100 * time.Millisecond)
    76  	deadlineCtx, cancel := context.WithDeadline(context.Background(), timeout)
    77  	defer cancel()
    78  
    79  	time.AfterFunc(5*time.Millisecond, func() {
    80  		state.UpsertNode(11, node)
    81  	})
    82  
    83  	resp, idx, err := state.BlockingQuery(queryFn, 10, deadlineCtx)
    84  	if assert.Nil(t, err) {
    85  		assert.Equal(t, 2, count)
    86  		assert.EqualValues(t, 11, idx)
    87  		assert.True(t, resp.(bool))
    88  	}
    89  }
    90  
    91  // This test checks that:
    92  // 1) The job is denormalized
    93  // 2) Allocations are created
    94  func TestStateStore_UpsertPlanResults_AllocationsCreated_Denormalized(t *testing.T) {
    95  	state := testStateStore(t)
    96  	alloc := mock.Alloc()
    97  	job := alloc.Job
    98  	alloc.Job = nil
    99  
   100  	if err := state.UpsertJob(999, job); err != nil {
   101  		t.Fatalf("err: %v", err)
   102  	}
   103  
   104  	eval := mock.Eval()
   105  	eval.JobID = job.ID
   106  
   107  	// Create an eval
   108  	if err := state.UpsertEvals(1, []*structs.Evaluation{eval}); err != nil {
   109  		t.Fatalf("err: %v", err)
   110  	}
   111  
   112  	// Create a plan result
   113  	res := structs.ApplyPlanResultsRequest{
   114  		AllocUpdateRequest: structs.AllocUpdateRequest{
   115  			Alloc: []*structs.Allocation{alloc},
   116  			Job:   job,
   117  		},
   118  		EvalID: eval.ID,
   119  	}
   120  	assert := assert.New(t)
   121  	err := state.UpsertPlanResults(1000, &res)
   122  	assert.Nil(err)
   123  
   124  	ws := memdb.NewWatchSet()
   125  	out, err := state.AllocByID(ws, alloc.ID)
   126  	assert.Nil(err)
   127  	assert.Equal(alloc, out)
   128  
   129  	index, err := state.Index("allocs")
   130  	assert.Nil(err)
   131  	assert.EqualValues(1000, index)
   132  
   133  	if watchFired(ws) {
   134  		t.Fatalf("bad")
   135  	}
   136  
   137  	evalOut, err := state.EvalByID(ws, eval.ID)
   138  	assert.Nil(err)
   139  	assert.NotNil(evalOut)
   140  	assert.EqualValues(1000, evalOut.ModifyIndex)
   141  }
   142  
   143  // This test checks that the deployment is created and allocations count towards
   144  // the deployment
   145  func TestStateStore_UpsertPlanResults_Deployment(t *testing.T) {
   146  	state := testStateStore(t)
   147  	alloc := mock.Alloc()
   148  	alloc2 := mock.Alloc()
   149  	job := alloc.Job
   150  	alloc.Job = nil
   151  	alloc2.Job = nil
   152  
   153  	d := mock.Deployment()
   154  	alloc.DeploymentID = d.ID
   155  	alloc2.DeploymentID = d.ID
   156  
   157  	if err := state.UpsertJob(999, job); err != nil {
   158  		t.Fatalf("err: %v", err)
   159  	}
   160  
   161  	eval := mock.Eval()
   162  	eval.JobID = job.ID
   163  
   164  	// Create an eval
   165  	if err := state.UpsertEvals(1, []*structs.Evaluation{eval}); err != nil {
   166  		t.Fatalf("err: %v", err)
   167  	}
   168  
   169  	// Create a plan result
   170  	res := structs.ApplyPlanResultsRequest{
   171  		AllocUpdateRequest: structs.AllocUpdateRequest{
   172  			Alloc: []*structs.Allocation{alloc, alloc2},
   173  			Job:   job,
   174  		},
   175  		Deployment: d,
   176  		EvalID:     eval.ID,
   177  	}
   178  
   179  	err := state.UpsertPlanResults(1000, &res)
   180  	if err != nil {
   181  		t.Fatalf("err: %v", err)
   182  	}
   183  
   184  	ws := memdb.NewWatchSet()
   185  	assert := assert.New(t)
   186  	out, err := state.AllocByID(ws, alloc.ID)
   187  	assert.Nil(err)
   188  	assert.Equal(alloc, out)
   189  
   190  	dout, err := state.DeploymentByID(ws, d.ID)
   191  	assert.Nil(err)
   192  	assert.NotNil(dout)
   193  
   194  	tg, ok := dout.TaskGroups[alloc.TaskGroup]
   195  	assert.True(ok)
   196  	assert.NotNil(tg)
   197  	assert.Equal(2, tg.PlacedAllocs)
   198  
   199  	evalOut, err := state.EvalByID(ws, eval.ID)
   200  	assert.Nil(err)
   201  	assert.NotNil(evalOut)
   202  	assert.EqualValues(1000, evalOut.ModifyIndex)
   203  
   204  	if watchFired(ws) {
   205  		t.Fatalf("bad")
   206  	}
   207  
   208  	// Update the allocs to be part of a new deployment
   209  	d2 := d.Copy()
   210  	d2.ID = uuid.Generate()
   211  
   212  	allocNew := alloc.Copy()
   213  	allocNew.DeploymentID = d2.ID
   214  	allocNew2 := alloc2.Copy()
   215  	allocNew2.DeploymentID = d2.ID
   216  
   217  	// Create another plan
   218  	res = structs.ApplyPlanResultsRequest{
   219  		AllocUpdateRequest: structs.AllocUpdateRequest{
   220  			Alloc: []*structs.Allocation{allocNew, allocNew2},
   221  			Job:   job,
   222  		},
   223  		Deployment: d2,
   224  		EvalID:     eval.ID,
   225  	}
   226  
   227  	err = state.UpsertPlanResults(1001, &res)
   228  	if err != nil {
   229  		t.Fatalf("err: %v", err)
   230  	}
   231  
   232  	dout, err = state.DeploymentByID(ws, d2.ID)
   233  	assert.Nil(err)
   234  	assert.NotNil(dout)
   235  
   236  	tg, ok = dout.TaskGroups[alloc.TaskGroup]
   237  	assert.True(ok)
   238  	assert.NotNil(tg)
   239  	assert.Equal(2, tg.PlacedAllocs)
   240  
   241  	evalOut, err = state.EvalByID(ws, eval.ID)
   242  	assert.Nil(err)
   243  	assert.NotNil(evalOut)
   244  	assert.EqualValues(1001, evalOut.ModifyIndex)
   245  }
   246  
   247  // This test checks that deployment updates are applied correctly
   248  func TestStateStore_UpsertPlanResults_DeploymentUpdates(t *testing.T) {
   249  	state := testStateStore(t)
   250  
   251  	// Create a job that applies to all
   252  	job := mock.Job()
   253  	if err := state.UpsertJob(998, job); err != nil {
   254  		t.Fatalf("err: %v", err)
   255  	}
   256  
   257  	// Create a deployment that we will update its status
   258  	doutstanding := mock.Deployment()
   259  	doutstanding.JobID = job.ID
   260  
   261  	if err := state.UpsertDeployment(1000, doutstanding); err != nil {
   262  		t.Fatalf("err: %v", err)
   263  	}
   264  
   265  	eval := mock.Eval()
   266  	eval.JobID = job.ID
   267  
   268  	// Create an eval
   269  	if err := state.UpsertEvals(1, []*structs.Evaluation{eval}); err != nil {
   270  		t.Fatalf("err: %v", err)
   271  	}
   272  	alloc := mock.Alloc()
   273  	alloc.Job = nil
   274  
   275  	dnew := mock.Deployment()
   276  	dnew.JobID = job.ID
   277  	alloc.DeploymentID = dnew.ID
   278  
   279  	// Update the old deployment
   280  	update := &structs.DeploymentStatusUpdate{
   281  		DeploymentID:      doutstanding.ID,
   282  		Status:            "foo",
   283  		StatusDescription: "bar",
   284  	}
   285  
   286  	// Create a plan result
   287  	res := structs.ApplyPlanResultsRequest{
   288  		AllocUpdateRequest: structs.AllocUpdateRequest{
   289  			Alloc: []*structs.Allocation{alloc},
   290  			Job:   job,
   291  		},
   292  		Deployment:        dnew,
   293  		DeploymentUpdates: []*structs.DeploymentStatusUpdate{update},
   294  		EvalID:            eval.ID,
   295  	}
   296  
   297  	err := state.UpsertPlanResults(1000, &res)
   298  	if err != nil {
   299  		t.Fatalf("err: %v", err)
   300  	}
   301  	assert := assert.New(t)
   302  	ws := memdb.NewWatchSet()
   303  
   304  	// Check the deployments are correctly updated.
   305  	dout, err := state.DeploymentByID(ws, dnew.ID)
   306  	assert.Nil(err)
   307  	assert.NotNil(dout)
   308  
   309  	tg, ok := dout.TaskGroups[alloc.TaskGroup]
   310  	assert.True(ok)
   311  	assert.NotNil(tg)
   312  	assert.Equal(1, tg.PlacedAllocs)
   313  
   314  	doutstandingout, err := state.DeploymentByID(ws, doutstanding.ID)
   315  	assert.Nil(err)
   316  	assert.NotNil(doutstandingout)
   317  	assert.Equal(update.Status, doutstandingout.Status)
   318  	assert.Equal(update.StatusDescription, doutstandingout.StatusDescription)
   319  	assert.EqualValues(1000, doutstandingout.ModifyIndex)
   320  
   321  	evalOut, err := state.EvalByID(ws, eval.ID)
   322  	assert.Nil(err)
   323  	assert.NotNil(evalOut)
   324  	assert.EqualValues(1000, evalOut.ModifyIndex)
   325  	if watchFired(ws) {
   326  		t.Fatalf("bad")
   327  	}
   328  }
   329  
   330  func TestStateStore_UpsertDeployment(t *testing.T) {
   331  	state := testStateStore(t)
   332  	deployment := mock.Deployment()
   333  
   334  	// Create a watchset so we can test that upsert fires the watch
   335  	ws := memdb.NewWatchSet()
   336  	_, err := state.DeploymentsByJobID(ws, deployment.Namespace, deployment.ID)
   337  	if err != nil {
   338  		t.Fatalf("bad: %v", err)
   339  	}
   340  
   341  	err = state.UpsertDeployment(1000, deployment)
   342  	if err != nil {
   343  		t.Fatalf("err: %v", err)
   344  	}
   345  	if !watchFired(ws) {
   346  		t.Fatalf("bad")
   347  	}
   348  
   349  	ws = memdb.NewWatchSet()
   350  	out, err := state.DeploymentByID(ws, deployment.ID)
   351  	if err != nil {
   352  		t.Fatalf("err: %v", err)
   353  	}
   354  
   355  	if !reflect.DeepEqual(deployment, out) {
   356  		t.Fatalf("bad: %#v %#v", deployment, out)
   357  	}
   358  
   359  	index, err := state.Index("deployment")
   360  	if err != nil {
   361  		t.Fatalf("err: %v", err)
   362  	}
   363  	if index != 1000 {
   364  		t.Fatalf("bad: %d", index)
   365  	}
   366  
   367  	if watchFired(ws) {
   368  		t.Fatalf("bad")
   369  	}
   370  }
   371  
   372  func TestStateStore_DeleteDeployment(t *testing.T) {
   373  	state := testStateStore(t)
   374  	d1 := mock.Deployment()
   375  	d2 := mock.Deployment()
   376  
   377  	err := state.UpsertDeployment(1000, d1)
   378  	if err != nil {
   379  		t.Fatalf("err: %v", err)
   380  	}
   381  	if err := state.UpsertDeployment(1001, d2); err != nil {
   382  		t.Fatalf("err: %v", err)
   383  	}
   384  
   385  	// Create a watchset so we can test that delete fires the watch
   386  	ws := memdb.NewWatchSet()
   387  	if _, err := state.DeploymentByID(ws, d1.ID); err != nil {
   388  		t.Fatalf("bad: %v", err)
   389  	}
   390  
   391  	err = state.DeleteDeployment(1002, []string{d1.ID, d2.ID})
   392  	if err != nil {
   393  		t.Fatalf("err: %v", err)
   394  	}
   395  
   396  	if !watchFired(ws) {
   397  		t.Fatalf("bad")
   398  	}
   399  
   400  	ws = memdb.NewWatchSet()
   401  	out, err := state.DeploymentByID(ws, d1.ID)
   402  	if err != nil {
   403  		t.Fatalf("err: %v", err)
   404  	}
   405  
   406  	if out != nil {
   407  		t.Fatalf("bad: %#v %#v", d1, out)
   408  	}
   409  
   410  	index, err := state.Index("deployment")
   411  	if err != nil {
   412  		t.Fatalf("err: %v", err)
   413  	}
   414  	if index != 1002 {
   415  		t.Fatalf("bad: %d", index)
   416  	}
   417  
   418  	if watchFired(ws) {
   419  		t.Fatalf("bad")
   420  	}
   421  }
   422  
   423  func TestStateStore_Deployments(t *testing.T) {
   424  	state := testStateStore(t)
   425  	var deployments []*structs.Deployment
   426  
   427  	for i := 0; i < 10; i++ {
   428  		deployment := mock.Deployment()
   429  		deployments = append(deployments, deployment)
   430  
   431  		err := state.UpsertDeployment(1000+uint64(i), deployment)
   432  		if err != nil {
   433  			t.Fatalf("err: %v", err)
   434  		}
   435  	}
   436  
   437  	ws := memdb.NewWatchSet()
   438  	iter, err := state.Deployments(ws)
   439  	if err != nil {
   440  		t.Fatalf("err: %v", err)
   441  	}
   442  
   443  	var out []*structs.Deployment
   444  	for {
   445  		raw := iter.Next()
   446  		if raw == nil {
   447  			break
   448  		}
   449  		out = append(out, raw.(*structs.Deployment))
   450  	}
   451  
   452  	lessThan := func(i, j int) bool {
   453  		return deployments[i].ID < deployments[j].ID
   454  	}
   455  	sort.Slice(deployments, lessThan)
   456  	sort.Slice(out, lessThan)
   457  
   458  	if !reflect.DeepEqual(deployments, out) {
   459  		t.Fatalf("bad: %#v %#v", deployments, out)
   460  	}
   461  
   462  	if watchFired(ws) {
   463  		t.Fatalf("bad")
   464  	}
   465  }
   466  
   467  func TestStateStore_DeploymentsByIDPrefix(t *testing.T) {
   468  	state := testStateStore(t)
   469  	deploy := mock.Deployment()
   470  
   471  	deploy.ID = "11111111-662e-d0ab-d1c9-3e434af7bdb4"
   472  	err := state.UpsertDeployment(1000, deploy)
   473  	if err != nil {
   474  		t.Fatalf("err: %v", err)
   475  	}
   476  
   477  	// Create a watchset so we can test that getters don't cause it to fire
   478  	ws := memdb.NewWatchSet()
   479  	iter, err := state.DeploymentsByIDPrefix(ws, deploy.Namespace, deploy.ID)
   480  	if err != nil {
   481  		t.Fatalf("err: %v", err)
   482  	}
   483  
   484  	gatherDeploys := func(iter memdb.ResultIterator) []*structs.Deployment {
   485  		var deploys []*structs.Deployment
   486  		for {
   487  			raw := iter.Next()
   488  			if raw == nil {
   489  				break
   490  			}
   491  			deploy := raw.(*structs.Deployment)
   492  			deploys = append(deploys, deploy)
   493  		}
   494  		return deploys
   495  	}
   496  
   497  	deploys := gatherDeploys(iter)
   498  	if len(deploys) != 1 {
   499  		t.Fatalf("err: %v", err)
   500  	}
   501  
   502  	if watchFired(ws) {
   503  		t.Fatalf("bad")
   504  	}
   505  
   506  	iter, err = state.DeploymentsByIDPrefix(ws, deploy.Namespace, "11")
   507  	if err != nil {
   508  		t.Fatalf("err: %v", err)
   509  	}
   510  
   511  	deploys = gatherDeploys(iter)
   512  	if len(deploys) != 1 {
   513  		t.Fatalf("err: %v", err)
   514  	}
   515  
   516  	deploy = mock.Deployment()
   517  	deploy.ID = "11222222-662e-d0ab-d1c9-3e434af7bdb4"
   518  	err = state.UpsertDeployment(1001, deploy)
   519  	if err != nil {
   520  		t.Fatalf("err: %v", err)
   521  	}
   522  
   523  	if !watchFired(ws) {
   524  		t.Fatalf("bad")
   525  	}
   526  
   527  	ws = memdb.NewWatchSet()
   528  	iter, err = state.DeploymentsByIDPrefix(ws, deploy.Namespace, "11")
   529  	if err != nil {
   530  		t.Fatalf("err: %v", err)
   531  	}
   532  
   533  	deploys = gatherDeploys(iter)
   534  	if len(deploys) != 2 {
   535  		t.Fatalf("err: %v", err)
   536  	}
   537  
   538  	iter, err = state.DeploymentsByIDPrefix(ws, deploy.Namespace, "1111")
   539  	if err != nil {
   540  		t.Fatalf("err: %v", err)
   541  	}
   542  
   543  	deploys = gatherDeploys(iter)
   544  	if len(deploys) != 1 {
   545  		t.Fatalf("err: %v", err)
   546  	}
   547  
   548  	if watchFired(ws) {
   549  		t.Fatalf("bad")
   550  	}
   551  }
   552  
   553  func TestStateStore_UpsertNode_Node(t *testing.T) {
   554  	require := require.New(t)
   555  	state := testStateStore(t)
   556  	node := mock.Node()
   557  
   558  	// Create a watchset so we can test that upsert fires the watch
   559  	ws := memdb.NewWatchSet()
   560  	_, err := state.NodeByID(ws, node.ID)
   561  	require.NoError(err)
   562  
   563  	require.NoError(state.UpsertNode(1000, node))
   564  	require.True(watchFired(ws))
   565  
   566  	ws = memdb.NewWatchSet()
   567  	out, err := state.NodeByID(ws, node.ID)
   568  	require.NoError(err)
   569  
   570  	out2, err := state.NodeBySecretID(ws, node.SecretID)
   571  	require.NoError(err)
   572  	require.EqualValues(node, out)
   573  	require.EqualValues(node, out2)
   574  	require.Len(out.Events, 1)
   575  	require.Equal(NodeRegisterEventRegistered, out.Events[0].Message)
   576  
   577  	index, err := state.Index("nodes")
   578  	require.NoError(err)
   579  	require.EqualValues(1000, index)
   580  	require.False(watchFired(ws))
   581  
   582  	// Transition the node to down and then up and ensure we get a re-register
   583  	// event
   584  	down := out.Copy()
   585  	down.Status = structs.NodeStatusDown
   586  	require.NoError(state.UpsertNode(1001, down))
   587  	require.NoError(state.UpsertNode(1002, out))
   588  
   589  	out, err = state.NodeByID(ws, node.ID)
   590  	require.NoError(err)
   591  	require.Len(out.Events, 2)
   592  	require.Equal(NodeRegisterEventReregistered, out.Events[1].Message)
   593  }
   594  
   595  func TestStateStore_DeleteNode_Node(t *testing.T) {
   596  	state := testStateStore(t)
   597  	node := mock.Node()
   598  
   599  	err := state.UpsertNode(1000, node)
   600  	if err != nil {
   601  		t.Fatalf("err: %v", err)
   602  	}
   603  
   604  	// Create a watchset so we can test that delete fires the watch
   605  	ws := memdb.NewWatchSet()
   606  	if _, err := state.NodeByID(ws, node.ID); err != nil {
   607  		t.Fatalf("bad: %v", err)
   608  	}
   609  
   610  	err = state.DeleteNode(1001, node.ID)
   611  	if err != nil {
   612  		t.Fatalf("err: %v", err)
   613  	}
   614  
   615  	if !watchFired(ws) {
   616  		t.Fatalf("bad")
   617  	}
   618  
   619  	ws = memdb.NewWatchSet()
   620  	out, err := state.NodeByID(ws, node.ID)
   621  	if err != nil {
   622  		t.Fatalf("err: %v", err)
   623  	}
   624  
   625  	if out != nil {
   626  		t.Fatalf("bad: %#v %#v", node, out)
   627  	}
   628  
   629  	index, err := state.Index("nodes")
   630  	if err != nil {
   631  		t.Fatalf("err: %v", err)
   632  	}
   633  	if index != 1001 {
   634  		t.Fatalf("bad: %d", index)
   635  	}
   636  
   637  	if watchFired(ws) {
   638  		t.Fatalf("bad")
   639  	}
   640  }
   641  
   642  func TestStateStore_UpdateNodeStatus_Node(t *testing.T) {
   643  	require := require.New(t)
   644  	state := testStateStore(t)
   645  	node := mock.Node()
   646  
   647  	require.NoError(state.UpsertNode(800, node))
   648  
   649  	// Create a watchset so we can test that update node status fires the watch
   650  	ws := memdb.NewWatchSet()
   651  	_, err := state.NodeByID(ws, node.ID)
   652  	require.NoError(err)
   653  
   654  	event := &structs.NodeEvent{
   655  		Message:   "Node ready foo",
   656  		Subsystem: structs.NodeEventSubsystemCluster,
   657  		Timestamp: time.Now(),
   658  	}
   659  
   660  	require.NoError(state.UpdateNodeStatus(801, node.ID, structs.NodeStatusReady, event))
   661  	require.True(watchFired(ws))
   662  
   663  	ws = memdb.NewWatchSet()
   664  	out, err := state.NodeByID(ws, node.ID)
   665  	require.NoError(err)
   666  	require.Equal(structs.NodeStatusReady, out.Status)
   667  	require.EqualValues(801, out.ModifyIndex)
   668  	require.Len(out.Events, 2)
   669  	require.Equal(event.Message, out.Events[1].Message)
   670  
   671  	index, err := state.Index("nodes")
   672  	require.NoError(err)
   673  	require.EqualValues(801, index)
   674  	require.False(watchFired(ws))
   675  }
   676  
   677  func TestStateStore_BatchUpdateNodeDrain(t *testing.T) {
   678  	require := require.New(t)
   679  	state := testStateStore(t)
   680  
   681  	n1, n2 := mock.Node(), mock.Node()
   682  	require.Nil(state.UpsertNode(1000, n1))
   683  	require.Nil(state.UpsertNode(1001, n2))
   684  
   685  	// Create a watchset so we can test that update node drain fires the watch
   686  	ws := memdb.NewWatchSet()
   687  	_, err := state.NodeByID(ws, n1.ID)
   688  	require.Nil(err)
   689  
   690  	expectedDrain := &structs.DrainStrategy{
   691  		DrainSpec: structs.DrainSpec{
   692  			Deadline: -1 * time.Second,
   693  		},
   694  	}
   695  
   696  	update := map[string]*structs.DrainUpdate{
   697  		n1.ID: {
   698  			DrainStrategy: expectedDrain,
   699  		},
   700  		n2.ID: {
   701  			DrainStrategy: expectedDrain,
   702  		},
   703  	}
   704  
   705  	event := &structs.NodeEvent{
   706  		Message:   "Drain strategy enabled",
   707  		Subsystem: structs.NodeEventSubsystemDrain,
   708  		Timestamp: time.Now(),
   709  	}
   710  	events := map[string]*structs.NodeEvent{
   711  		n1.ID: event,
   712  		n2.ID: event,
   713  	}
   714  
   715  	require.Nil(state.BatchUpdateNodeDrain(1002, update, events))
   716  	require.True(watchFired(ws))
   717  
   718  	ws = memdb.NewWatchSet()
   719  	for _, id := range []string{n1.ID, n2.ID} {
   720  		out, err := state.NodeByID(ws, id)
   721  		require.Nil(err)
   722  		require.True(out.Drain)
   723  		require.NotNil(out.DrainStrategy)
   724  		require.Equal(out.DrainStrategy, expectedDrain)
   725  		require.Len(out.Events, 2)
   726  		require.EqualValues(1002, out.ModifyIndex)
   727  	}
   728  
   729  	index, err := state.Index("nodes")
   730  	require.Nil(err)
   731  	require.EqualValues(1002, index)
   732  	require.False(watchFired(ws))
   733  }
   734  
   735  func TestStateStore_UpdateNodeDrain_Node(t *testing.T) {
   736  	require := require.New(t)
   737  	state := testStateStore(t)
   738  	node := mock.Node()
   739  
   740  	require.Nil(state.UpsertNode(1000, node))
   741  
   742  	// Create a watchset so we can test that update node drain fires the watch
   743  	ws := memdb.NewWatchSet()
   744  	_, err := state.NodeByID(ws, node.ID)
   745  	require.Nil(err)
   746  
   747  	expectedDrain := &structs.DrainStrategy{
   748  		DrainSpec: structs.DrainSpec{
   749  			Deadline: -1 * time.Second,
   750  		},
   751  	}
   752  
   753  	event := &structs.NodeEvent{
   754  		Message:   "Drain strategy enabled",
   755  		Subsystem: structs.NodeEventSubsystemDrain,
   756  		Timestamp: time.Now(),
   757  	}
   758  	require.Nil(state.UpdateNodeDrain(1001, node.ID, expectedDrain, false, event))
   759  	require.True(watchFired(ws))
   760  
   761  	ws = memdb.NewWatchSet()
   762  	out, err := state.NodeByID(ws, node.ID)
   763  	require.Nil(err)
   764  	require.True(out.Drain)
   765  	require.NotNil(out.DrainStrategy)
   766  	require.Equal(out.DrainStrategy, expectedDrain)
   767  	require.Len(out.Events, 2)
   768  	require.EqualValues(1001, out.ModifyIndex)
   769  
   770  	index, err := state.Index("nodes")
   771  	require.Nil(err)
   772  	require.EqualValues(1001, index)
   773  	require.False(watchFired(ws))
   774  }
   775  
   776  func TestStateStore_AddSingleNodeEvent(t *testing.T) {
   777  	require := require.New(t)
   778  	state := testStateStore(t)
   779  
   780  	node := mock.Node()
   781  
   782  	// We create a new node event every time we register a node
   783  	err := state.UpsertNode(1000, node)
   784  	require.Nil(err)
   785  
   786  	require.Equal(1, len(node.Events))
   787  	require.Equal(structs.NodeEventSubsystemCluster, node.Events[0].Subsystem)
   788  	require.Equal(NodeRegisterEventRegistered, node.Events[0].Message)
   789  
   790  	// Create a watchset so we can test that AddNodeEvent fires the watch
   791  	ws := memdb.NewWatchSet()
   792  	_, err = state.NodeByID(ws, node.ID)
   793  	require.Nil(err)
   794  
   795  	nodeEvent := &structs.NodeEvent{
   796  		Message:   "failed",
   797  		Subsystem: "Driver",
   798  		Timestamp: time.Now(),
   799  	}
   800  	nodeEvents := map[string][]*structs.NodeEvent{
   801  		node.ID: {nodeEvent},
   802  	}
   803  	err = state.UpsertNodeEvents(uint64(1001), nodeEvents)
   804  	require.Nil(err)
   805  
   806  	require.True(watchFired(ws))
   807  
   808  	ws = memdb.NewWatchSet()
   809  	out, err := state.NodeByID(ws, node.ID)
   810  	require.Nil(err)
   811  
   812  	require.Equal(2, len(out.Events))
   813  	require.Equal(nodeEvent, out.Events[1])
   814  }
   815  
   816  // To prevent stale node events from accumulating, we limit the number of
   817  // stored node events to 10.
   818  func TestStateStore_NodeEvents_RetentionWindow(t *testing.T) {
   819  	require := require.New(t)
   820  	state := testStateStore(t)
   821  
   822  	node := mock.Node()
   823  
   824  	err := state.UpsertNode(1000, node)
   825  	if err != nil {
   826  		t.Fatalf("err: %v", err)
   827  	}
   828  	require.Equal(1, len(node.Events))
   829  	require.Equal(structs.NodeEventSubsystemCluster, node.Events[0].Subsystem)
   830  	require.Equal(NodeRegisterEventRegistered, node.Events[0].Message)
   831  
   832  	var out *structs.Node
   833  	for i := 1; i <= 20; i++ {
   834  		ws := memdb.NewWatchSet()
   835  		out, err = state.NodeByID(ws, node.ID)
   836  		require.Nil(err)
   837  
   838  		nodeEvent := &structs.NodeEvent{
   839  			Message:   fmt.Sprintf("%dith failed", i),
   840  			Subsystem: "Driver",
   841  			Timestamp: time.Now(),
   842  		}
   843  
   844  		nodeEvents := map[string][]*structs.NodeEvent{
   845  			out.ID: {nodeEvent},
   846  		}
   847  		err := state.UpsertNodeEvents(uint64(i), nodeEvents)
   848  		require.Nil(err)
   849  
   850  		require.True(watchFired(ws))
   851  		ws = memdb.NewWatchSet()
   852  		out, err = state.NodeByID(ws, node.ID)
   853  		require.Nil(err)
   854  	}
   855  
   856  	ws := memdb.NewWatchSet()
   857  	out, err = state.NodeByID(ws, node.ID)
   858  	require.Nil(err)
   859  
   860  	require.Equal(10, len(out.Events))
   861  	require.Equal(uint64(11), out.Events[0].CreateIndex)
   862  	require.Equal(uint64(20), out.Events[len(out.Events)-1].CreateIndex)
   863  }
   864  
   865  func TestStateStore_UpdateNodeDrain_ResetEligiblity(t *testing.T) {
   866  	require := require.New(t)
   867  	state := testStateStore(t)
   868  	node := mock.Node()
   869  	require.Nil(state.UpsertNode(1000, node))
   870  
   871  	// Create a watchset so we can test that update node drain fires the watch
   872  	ws := memdb.NewWatchSet()
   873  	_, err := state.NodeByID(ws, node.ID)
   874  	require.Nil(err)
   875  
   876  	drain := &structs.DrainStrategy{
   877  		DrainSpec: structs.DrainSpec{
   878  			Deadline: -1 * time.Second,
   879  		},
   880  	}
   881  
   882  	event1 := &structs.NodeEvent{
   883  		Message:   "Drain strategy enabled",
   884  		Subsystem: structs.NodeEventSubsystemDrain,
   885  		Timestamp: time.Now(),
   886  	}
   887  	require.Nil(state.UpdateNodeDrain(1001, node.ID, drain, false, event1))
   888  	require.True(watchFired(ws))
   889  
   890  	// Remove the drain
   891  	event2 := &structs.NodeEvent{
   892  		Message:   "Drain strategy disabled",
   893  		Subsystem: structs.NodeEventSubsystemDrain,
   894  		Timestamp: time.Now(),
   895  	}
   896  	require.Nil(state.UpdateNodeDrain(1002, node.ID, nil, true, event2))
   897  
   898  	ws = memdb.NewWatchSet()
   899  	out, err := state.NodeByID(ws, node.ID)
   900  	require.Nil(err)
   901  	require.False(out.Drain)
   902  	require.Nil(out.DrainStrategy)
   903  	require.Equal(out.SchedulingEligibility, structs.NodeSchedulingEligible)
   904  	require.Len(out.Events, 3)
   905  	require.EqualValues(1002, out.ModifyIndex)
   906  
   907  	index, err := state.Index("nodes")
   908  	require.Nil(err)
   909  	require.EqualValues(1002, index)
   910  	require.False(watchFired(ws))
   911  }
   912  
   913  func TestStateStore_UpdateNodeEligibility(t *testing.T) {
   914  	require := require.New(t)
   915  	state := testStateStore(t)
   916  	node := mock.Node()
   917  
   918  	err := state.UpsertNode(1000, node)
   919  	if err != nil {
   920  		t.Fatalf("err: %v", err)
   921  	}
   922  
   923  	expectedEligibility := structs.NodeSchedulingIneligible
   924  
   925  	// Create a watchset so we can test that update node drain fires the watch
   926  	ws := memdb.NewWatchSet()
   927  	if _, err := state.NodeByID(ws, node.ID); err != nil {
   928  		t.Fatalf("bad: %v", err)
   929  	}
   930  
   931  	event := &structs.NodeEvent{
   932  		Message:   "Node marked as ineligible",
   933  		Subsystem: structs.NodeEventSubsystemCluster,
   934  		Timestamp: time.Now(),
   935  	}
   936  	require.Nil(state.UpdateNodeEligibility(1001, node.ID, expectedEligibility, event))
   937  	require.True(watchFired(ws))
   938  
   939  	ws = memdb.NewWatchSet()
   940  	out, err := state.NodeByID(ws, node.ID)
   941  	require.Nil(err)
   942  	require.Equal(out.SchedulingEligibility, expectedEligibility)
   943  	require.Len(out.Events, 2)
   944  	require.Equal(out.Events[1], event)
   945  	require.EqualValues(1001, out.ModifyIndex)
   946  
   947  	index, err := state.Index("nodes")
   948  	require.Nil(err)
   949  	require.EqualValues(1001, index)
   950  	require.False(watchFired(ws))
   951  
   952  	// Set a drain strategy
   953  	expectedDrain := &structs.DrainStrategy{
   954  		DrainSpec: structs.DrainSpec{
   955  			Deadline: -1 * time.Second,
   956  		},
   957  	}
   958  	require.Nil(state.UpdateNodeDrain(1002, node.ID, expectedDrain, false, nil))
   959  
   960  	// Try to set the node to eligible
   961  	err = state.UpdateNodeEligibility(1003, node.ID, structs.NodeSchedulingEligible, nil)
   962  	require.NotNil(err)
   963  	require.Contains(err.Error(), "while it is draining")
   964  }
   965  
   966  func TestStateStore_Nodes(t *testing.T) {
   967  	state := testStateStore(t)
   968  	var nodes []*structs.Node
   969  
   970  	for i := 0; i < 10; i++ {
   971  		node := mock.Node()
   972  		nodes = append(nodes, node)
   973  
   974  		err := state.UpsertNode(1000+uint64(i), node)
   975  		if err != nil {
   976  			t.Fatalf("err: %v", err)
   977  		}
   978  	}
   979  
   980  	// Create a watchset so we can test that getters don't cause it to fire
   981  	ws := memdb.NewWatchSet()
   982  	iter, err := state.Nodes(ws)
   983  	if err != nil {
   984  		t.Fatalf("bad: %v", err)
   985  	}
   986  
   987  	var out []*structs.Node
   988  	for {
   989  		raw := iter.Next()
   990  		if raw == nil {
   991  			break
   992  		}
   993  		out = append(out, raw.(*structs.Node))
   994  	}
   995  
   996  	sort.Sort(NodeIDSort(nodes))
   997  	sort.Sort(NodeIDSort(out))
   998  
   999  	if !reflect.DeepEqual(nodes, out) {
  1000  		t.Fatalf("bad: %#v %#v", nodes, out)
  1001  	}
  1002  
  1003  	if watchFired(ws) {
  1004  		t.Fatalf("bad")
  1005  	}
  1006  }
  1007  
  1008  func TestStateStore_NodesByIDPrefix(t *testing.T) {
  1009  	state := testStateStore(t)
  1010  	node := mock.Node()
  1011  
  1012  	node.ID = "11111111-662e-d0ab-d1c9-3e434af7bdb4"
  1013  	err := state.UpsertNode(1000, node)
  1014  	if err != nil {
  1015  		t.Fatalf("err: %v", err)
  1016  	}
  1017  
  1018  	// Create a watchset so we can test that getters don't cause it to fire
  1019  	ws := memdb.NewWatchSet()
  1020  	iter, err := state.NodesByIDPrefix(ws, node.ID)
  1021  	if err != nil {
  1022  		t.Fatalf("err: %v", err)
  1023  	}
  1024  
  1025  	gatherNodes := func(iter memdb.ResultIterator) []*structs.Node {
  1026  		var nodes []*structs.Node
  1027  		for {
  1028  			raw := iter.Next()
  1029  			if raw == nil {
  1030  				break
  1031  			}
  1032  			node := raw.(*structs.Node)
  1033  			nodes = append(nodes, node)
  1034  		}
  1035  		return nodes
  1036  	}
  1037  
  1038  	nodes := gatherNodes(iter)
  1039  	if len(nodes) != 1 {
  1040  		t.Fatalf("err: %v", err)
  1041  	}
  1042  
  1043  	if watchFired(ws) {
  1044  		t.Fatalf("bad")
  1045  	}
  1046  
  1047  	iter, err = state.NodesByIDPrefix(ws, "11")
  1048  	if err != nil {
  1049  		t.Fatalf("err: %v", err)
  1050  	}
  1051  
  1052  	nodes = gatherNodes(iter)
  1053  	if len(nodes) != 1 {
  1054  		t.Fatalf("err: %v", err)
  1055  	}
  1056  
  1057  	node = mock.Node()
  1058  	node.ID = "11222222-662e-d0ab-d1c9-3e434af7bdb4"
  1059  	err = state.UpsertNode(1001, node)
  1060  	if err != nil {
  1061  		t.Fatalf("err: %v", err)
  1062  	}
  1063  
  1064  	if !watchFired(ws) {
  1065  		t.Fatalf("bad")
  1066  	}
  1067  
  1068  	ws = memdb.NewWatchSet()
  1069  	iter, err = state.NodesByIDPrefix(ws, "11")
  1070  	if err != nil {
  1071  		t.Fatalf("err: %v", err)
  1072  	}
  1073  
  1074  	nodes = gatherNodes(iter)
  1075  	if len(nodes) != 2 {
  1076  		t.Fatalf("err: %v", err)
  1077  	}
  1078  
  1079  	iter, err = state.NodesByIDPrefix(ws, "1111")
  1080  	if err != nil {
  1081  		t.Fatalf("err: %v", err)
  1082  	}
  1083  
  1084  	nodes = gatherNodes(iter)
  1085  	if len(nodes) != 1 {
  1086  		t.Fatalf("err: %v", err)
  1087  	}
  1088  
  1089  	if watchFired(ws) {
  1090  		t.Fatalf("bad")
  1091  	}
  1092  }
  1093  
  1094  func TestStateStore_RestoreNode(t *testing.T) {
  1095  	state := testStateStore(t)
  1096  	node := mock.Node()
  1097  
  1098  	restore, err := state.Restore()
  1099  	if err != nil {
  1100  		t.Fatalf("err: %v", err)
  1101  	}
  1102  
  1103  	err = restore.NodeRestore(node)
  1104  	if err != nil {
  1105  		t.Fatalf("err: %v", err)
  1106  	}
  1107  	restore.Commit()
  1108  
  1109  	ws := memdb.NewWatchSet()
  1110  	out, err := state.NodeByID(ws, node.ID)
  1111  	if err != nil {
  1112  		t.Fatalf("err: %v", err)
  1113  	}
  1114  
  1115  	if !reflect.DeepEqual(out, node) {
  1116  		t.Fatalf("Bad: %#v %#v", out, node)
  1117  	}
  1118  }
  1119  
  1120  func TestStateStore_UpsertJob_Job(t *testing.T) {
  1121  	state := testStateStore(t)
  1122  	job := mock.Job()
  1123  
  1124  	// Create a watchset so we can test that upsert fires the watch
  1125  	ws := memdb.NewWatchSet()
  1126  	_, err := state.JobByID(ws, job.Namespace, job.ID)
  1127  	if err != nil {
  1128  		t.Fatalf("bad: %v", err)
  1129  	}
  1130  
  1131  	if err := state.UpsertJob(1000, job); err != nil {
  1132  		t.Fatalf("err: %v", err)
  1133  	}
  1134  	if !watchFired(ws) {
  1135  		t.Fatalf("bad")
  1136  	}
  1137  
  1138  	ws = memdb.NewWatchSet()
  1139  	out, err := state.JobByID(ws, job.Namespace, job.ID)
  1140  	if err != nil {
  1141  		t.Fatalf("err: %v", err)
  1142  	}
  1143  
  1144  	if !reflect.DeepEqual(job, out) {
  1145  		t.Fatalf("bad: %#v %#v", job, out)
  1146  	}
  1147  
  1148  	index, err := state.Index("jobs")
  1149  	if err != nil {
  1150  		t.Fatalf("err: %v", err)
  1151  	}
  1152  	if index != 1000 {
  1153  		t.Fatalf("bad: %d", index)
  1154  	}
  1155  
  1156  	summary, err := state.JobSummaryByID(ws, job.Namespace, job.ID)
  1157  	if err != nil {
  1158  		t.Fatalf("err: %v", err)
  1159  	}
  1160  	if summary == nil {
  1161  		t.Fatalf("nil summary")
  1162  	}
  1163  	if summary.JobID != job.ID {
  1164  		t.Fatalf("bad summary id: %v", summary.JobID)
  1165  	}
  1166  	_, ok := summary.Summary["web"]
  1167  	if !ok {
  1168  		t.Fatalf("nil summary for task group")
  1169  	}
  1170  	if watchFired(ws) {
  1171  		t.Fatalf("bad")
  1172  	}
  1173  
  1174  	// Check the job versions
  1175  	allVersions, err := state.JobVersionsByID(ws, job.Namespace, job.ID)
  1176  	if err != nil {
  1177  		t.Fatalf("err: %v", err)
  1178  	}
  1179  	if len(allVersions) != 1 {
  1180  		t.Fatalf("got %d; want 1", len(allVersions))
  1181  	}
  1182  
  1183  	if a := allVersions[0]; a.ID != job.ID || a.Version != 0 {
  1184  		t.Fatalf("bad: %v", a)
  1185  	}
  1186  
  1187  	// Test the looking up the job by version returns the same results
  1188  	vout, err := state.JobByIDAndVersion(ws, job.Namespace, job.ID, 0)
  1189  	if err != nil {
  1190  		t.Fatalf("err: %v", err)
  1191  	}
  1192  
  1193  	if !reflect.DeepEqual(out, vout) {
  1194  		t.Fatalf("bad: %#v %#v", out, vout)
  1195  	}
  1196  }
  1197  
  1198  func TestStateStore_UpdateUpsertJob_Job(t *testing.T) {
  1199  	state := testStateStore(t)
  1200  	job := mock.Job()
  1201  
  1202  	// Create a watchset so we can test that upsert fires the watch
  1203  	ws := memdb.NewWatchSet()
  1204  	_, err := state.JobByID(ws, job.Namespace, job.ID)
  1205  	if err != nil {
  1206  		t.Fatalf("bad: %v", err)
  1207  	}
  1208  
  1209  	if err := state.UpsertJob(1000, job); err != nil {
  1210  		t.Fatalf("err: %v", err)
  1211  	}
  1212  
  1213  	job2 := mock.Job()
  1214  	job2.ID = job.ID
  1215  	job2.AllAtOnce = true
  1216  	err = state.UpsertJob(1001, job2)
  1217  	if err != nil {
  1218  		t.Fatalf("err: %v", err)
  1219  	}
  1220  
  1221  	if !watchFired(ws) {
  1222  		t.Fatalf("bad")
  1223  	}
  1224  
  1225  	ws = memdb.NewWatchSet()
  1226  	out, err := state.JobByID(ws, job.Namespace, job.ID)
  1227  	if err != nil {
  1228  		t.Fatalf("err: %v", err)
  1229  	}
  1230  
  1231  	if !reflect.DeepEqual(job2, out) {
  1232  		t.Fatalf("bad: %#v %#v", job2, out)
  1233  	}
  1234  
  1235  	if out.CreateIndex != 1000 {
  1236  		t.Fatalf("bad: %#v", out)
  1237  	}
  1238  	if out.ModifyIndex != 1001 {
  1239  		t.Fatalf("bad: %#v", out)
  1240  	}
  1241  	if out.Version != 1 {
  1242  		t.Fatalf("bad: %#v", out)
  1243  	}
  1244  
  1245  	index, err := state.Index("jobs")
  1246  	if err != nil {
  1247  		t.Fatalf("err: %v", err)
  1248  	}
  1249  	if index != 1001 {
  1250  		t.Fatalf("bad: %d", index)
  1251  	}
  1252  
  1253  	// Test the looking up the job by version returns the same results
  1254  	vout, err := state.JobByIDAndVersion(ws, job.Namespace, job.ID, 1)
  1255  	if err != nil {
  1256  		t.Fatalf("err: %v", err)
  1257  	}
  1258  
  1259  	if !reflect.DeepEqual(out, vout) {
  1260  		t.Fatalf("bad: %#v %#v", out, vout)
  1261  	}
  1262  
  1263  	// Test that the job summary remains the same if the job is updated but
  1264  	// count remains same
  1265  	summary, err := state.JobSummaryByID(ws, job.Namespace, job.ID)
  1266  	if err != nil {
  1267  		t.Fatalf("err: %v", err)
  1268  	}
  1269  	if summary == nil {
  1270  		t.Fatalf("nil summary")
  1271  	}
  1272  	if summary.JobID != job.ID {
  1273  		t.Fatalf("bad summary id: %v", summary.JobID)
  1274  	}
  1275  	_, ok := summary.Summary["web"]
  1276  	if !ok {
  1277  		t.Fatalf("nil summary for task group")
  1278  	}
  1279  
  1280  	// Check the job versions
  1281  	allVersions, err := state.JobVersionsByID(ws, job.Namespace, job.ID)
  1282  	if err != nil {
  1283  		t.Fatalf("err: %v", err)
  1284  	}
  1285  	if len(allVersions) != 2 {
  1286  		t.Fatalf("got %d; want 1", len(allVersions))
  1287  	}
  1288  
  1289  	if a := allVersions[0]; a.ID != job.ID || a.Version != 1 || !a.AllAtOnce {
  1290  		t.Fatalf("bad: %+v", a)
  1291  	}
  1292  	if a := allVersions[1]; a.ID != job.ID || a.Version != 0 || a.AllAtOnce {
  1293  		t.Fatalf("bad: %+v", a)
  1294  	}
  1295  
  1296  	if watchFired(ws) {
  1297  		t.Fatalf("bad")
  1298  	}
  1299  }
  1300  
  1301  func TestStateStore_UpdateUpsertJob_PeriodicJob(t *testing.T) {
  1302  	state := testStateStore(t)
  1303  	job := mock.PeriodicJob()
  1304  
  1305  	// Create a watchset so we can test that upsert fires the watch
  1306  	ws := memdb.NewWatchSet()
  1307  	_, err := state.JobByID(ws, job.Namespace, job.ID)
  1308  	if err != nil {
  1309  		t.Fatalf("bad: %v", err)
  1310  	}
  1311  
  1312  	if err := state.UpsertJob(1000, job); err != nil {
  1313  		t.Fatalf("err: %v", err)
  1314  	}
  1315  
  1316  	// Create a child and an evaluation
  1317  	job2 := job.Copy()
  1318  	job2.Periodic = nil
  1319  	job2.ID = fmt.Sprintf("%v/%s-1490635020", job.ID, structs.PeriodicLaunchSuffix)
  1320  	err = state.UpsertJob(1001, job2)
  1321  	if err != nil {
  1322  		t.Fatalf("err: %v", err)
  1323  	}
  1324  
  1325  	eval := mock.Eval()
  1326  	eval.JobID = job2.ID
  1327  	err = state.UpsertEvals(1002, []*structs.Evaluation{eval})
  1328  	if err != nil {
  1329  		t.Fatalf("err: %v", err)
  1330  	}
  1331  
  1332  	job3 := job.Copy()
  1333  	job3.TaskGroups[0].Tasks[0].Name = "new name"
  1334  	err = state.UpsertJob(1003, job3)
  1335  	if err != nil {
  1336  		t.Fatalf("err: %v", err)
  1337  	}
  1338  
  1339  	if !watchFired(ws) {
  1340  		t.Fatalf("bad")
  1341  	}
  1342  
  1343  	ws = memdb.NewWatchSet()
  1344  	out, err := state.JobByID(ws, job.Namespace, job.ID)
  1345  	if err != nil {
  1346  		t.Fatalf("err: %v", err)
  1347  	}
  1348  
  1349  	if s, e := out.Status, structs.JobStatusRunning; s != e {
  1350  		t.Fatalf("got status %v; want %v", s, e)
  1351  	}
  1352  
  1353  }
  1354  
  1355  // This test ensures that UpsertJob creates the EphemeralDisk is a job doesn't have
  1356  // one and clear out the task's disk resource asks
  1357  // COMPAT 0.4.1 -> 0.5
  1358  func TestStateStore_UpsertJob_NoEphemeralDisk(t *testing.T) {
  1359  	state := testStateStore(t)
  1360  	job := mock.Job()
  1361  
  1362  	// Set the EphemeralDisk to nil and set the tasks's DiskMB to 150
  1363  	job.TaskGroups[0].EphemeralDisk = nil
  1364  	job.TaskGroups[0].Tasks[0].Resources.DiskMB = 150
  1365  
  1366  	err := state.UpsertJob(1000, job)
  1367  	if err != nil {
  1368  		t.Fatalf("err: %v", err)
  1369  	}
  1370  
  1371  	ws := memdb.NewWatchSet()
  1372  	out, err := state.JobByID(ws, job.Namespace, job.ID)
  1373  	if err != nil {
  1374  		t.Fatalf("err: %v", err)
  1375  	}
  1376  
  1377  	// Expect the state store to create the EphemeralDisk and clear out Tasks's
  1378  	// DiskMB
  1379  	expected := job.Copy()
  1380  	expected.TaskGroups[0].EphemeralDisk = &structs.EphemeralDisk{
  1381  		SizeMB: 150,
  1382  	}
  1383  	expected.TaskGroups[0].Tasks[0].Resources.DiskMB = 0
  1384  
  1385  	if !reflect.DeepEqual(expected, out) {
  1386  		t.Fatalf("bad: %#v %#v", expected, out)
  1387  	}
  1388  }
  1389  
  1390  func TestStateStore_UpsertJob_BadNamespace(t *testing.T) {
  1391  	assert := assert.New(t)
  1392  	state := testStateStore(t)
  1393  	job := mock.Job()
  1394  	job.Namespace = "foo"
  1395  
  1396  	err := state.UpsertJob(1000, job)
  1397  	assert.Contains(err.Error(), "nonexistent namespace")
  1398  
  1399  	ws := memdb.NewWatchSet()
  1400  	out, err := state.JobByID(ws, job.Namespace, job.ID)
  1401  	assert.Nil(err)
  1402  	assert.Nil(out)
  1403  }
  1404  
  1405  // Upsert a job that is the child of a parent job and ensures its summary gets
  1406  // updated.
  1407  func TestStateStore_UpsertJob_ChildJob(t *testing.T) {
  1408  	state := testStateStore(t)
  1409  
  1410  	// Create a watchset so we can test that upsert fires the watch
  1411  	parent := mock.Job()
  1412  	ws := memdb.NewWatchSet()
  1413  	_, err := state.JobByID(ws, parent.Namespace, parent.ID)
  1414  	if err != nil {
  1415  		t.Fatalf("bad: %v", err)
  1416  	}
  1417  
  1418  	if err := state.UpsertJob(1000, parent); err != nil {
  1419  		t.Fatalf("err: %v", err)
  1420  	}
  1421  
  1422  	child := mock.Job()
  1423  	child.ParentID = parent.ID
  1424  	if err := state.UpsertJob(1001, child); err != nil {
  1425  		t.Fatalf("err: %v", err)
  1426  	}
  1427  
  1428  	summary, err := state.JobSummaryByID(ws, parent.Namespace, parent.ID)
  1429  	if err != nil {
  1430  		t.Fatalf("err: %v", err)
  1431  	}
  1432  	if summary == nil {
  1433  		t.Fatalf("nil summary")
  1434  	}
  1435  	if summary.JobID != parent.ID {
  1436  		t.Fatalf("bad summary id: %v", parent.ID)
  1437  	}
  1438  	if summary.Children == nil {
  1439  		t.Fatalf("nil children summary")
  1440  	}
  1441  	if summary.Children.Pending != 1 || summary.Children.Running != 0 || summary.Children.Dead != 0 {
  1442  		t.Fatalf("bad children summary: %v", summary.Children)
  1443  	}
  1444  	if !watchFired(ws) {
  1445  		t.Fatalf("bad")
  1446  	}
  1447  }
  1448  
  1449  func TestStateStore_UpdateUpsertJob_JobVersion(t *testing.T) {
  1450  	state := testStateStore(t)
  1451  
  1452  	// Create a job and mark it as stable
  1453  	job := mock.Job()
  1454  	job.Stable = true
  1455  	job.Name = "0"
  1456  
  1457  	// Create a watchset so we can test that upsert fires the watch
  1458  	ws := memdb.NewWatchSet()
  1459  	_, err := state.JobVersionsByID(ws, job.Namespace, job.ID)
  1460  	if err != nil {
  1461  		t.Fatalf("bad: %v", err)
  1462  	}
  1463  
  1464  	if err := state.UpsertJob(1000, job); err != nil {
  1465  		t.Fatalf("err: %v", err)
  1466  	}
  1467  
  1468  	if !watchFired(ws) {
  1469  		t.Fatalf("bad")
  1470  	}
  1471  
  1472  	var finalJob *structs.Job
  1473  	for i := 1; i < 300; i++ {
  1474  		finalJob = mock.Job()
  1475  		finalJob.ID = job.ID
  1476  		finalJob.Name = fmt.Sprintf("%d", i)
  1477  		err = state.UpsertJob(uint64(1000+i), finalJob)
  1478  		if err != nil {
  1479  			t.Fatalf("err: %v", err)
  1480  		}
  1481  	}
  1482  
  1483  	ws = memdb.NewWatchSet()
  1484  	out, err := state.JobByID(ws, job.Namespace, job.ID)
  1485  	if err != nil {
  1486  		t.Fatalf("err: %v", err)
  1487  	}
  1488  
  1489  	if !reflect.DeepEqual(finalJob, out) {
  1490  		t.Fatalf("bad: %#v %#v", finalJob, out)
  1491  	}
  1492  
  1493  	if out.CreateIndex != 1000 {
  1494  		t.Fatalf("bad: %#v", out)
  1495  	}
  1496  	if out.ModifyIndex != 1299 {
  1497  		t.Fatalf("bad: %#v", out)
  1498  	}
  1499  	if out.Version != 299 {
  1500  		t.Fatalf("bad: %#v", out)
  1501  	}
  1502  
  1503  	index, err := state.Index("job_version")
  1504  	if err != nil {
  1505  		t.Fatalf("err: %v", err)
  1506  	}
  1507  	if index != 1299 {
  1508  		t.Fatalf("bad: %d", index)
  1509  	}
  1510  
  1511  	// Check the job versions
  1512  	allVersions, err := state.JobVersionsByID(ws, job.Namespace, job.ID)
  1513  	if err != nil {
  1514  		t.Fatalf("err: %v", err)
  1515  	}
  1516  	if len(allVersions) != structs.JobTrackedVersions {
  1517  		t.Fatalf("got %d; want %d", len(allVersions), structs.JobTrackedVersions)
  1518  	}
  1519  
  1520  	if a := allVersions[0]; a.ID != job.ID || a.Version != 299 || a.Name != "299" {
  1521  		t.Fatalf("bad: %+v", a)
  1522  	}
  1523  	if a := allVersions[1]; a.ID != job.ID || a.Version != 298 || a.Name != "298" {
  1524  		t.Fatalf("bad: %+v", a)
  1525  	}
  1526  
  1527  	// Ensure we didn't delete the stable job
  1528  	if a := allVersions[structs.JobTrackedVersions-1]; a.ID != job.ID ||
  1529  		a.Version != 0 || a.Name != "0" || !a.Stable {
  1530  		t.Fatalf("bad: %+v", a)
  1531  	}
  1532  
  1533  	if watchFired(ws) {
  1534  		t.Fatalf("bad")
  1535  	}
  1536  }
  1537  
  1538  func TestStateStore_DeleteJob_Job(t *testing.T) {
  1539  	state := testStateStore(t)
  1540  	job := mock.Job()
  1541  
  1542  	err := state.UpsertJob(1000, job)
  1543  	if err != nil {
  1544  		t.Fatalf("err: %v", err)
  1545  	}
  1546  
  1547  	// Create a watchset so we can test that delete fires the watch
  1548  	ws := memdb.NewWatchSet()
  1549  	if _, err := state.JobByID(ws, job.Namespace, job.ID); err != nil {
  1550  		t.Fatalf("bad: %v", err)
  1551  	}
  1552  
  1553  	err = state.DeleteJob(1001, job.Namespace, job.ID)
  1554  	if err != nil {
  1555  		t.Fatalf("err: %v", err)
  1556  	}
  1557  
  1558  	if !watchFired(ws) {
  1559  		t.Fatalf("bad")
  1560  	}
  1561  
  1562  	ws = memdb.NewWatchSet()
  1563  	out, err := state.JobByID(ws, job.Namespace, job.ID)
  1564  	if err != nil {
  1565  		t.Fatalf("err: %v", err)
  1566  	}
  1567  
  1568  	if out != nil {
  1569  		t.Fatalf("bad: %#v %#v", job, out)
  1570  	}
  1571  
  1572  	index, err := state.Index("jobs")
  1573  	if err != nil {
  1574  		t.Fatalf("err: %v", err)
  1575  	}
  1576  	if index != 1001 {
  1577  		t.Fatalf("bad: %d", index)
  1578  	}
  1579  
  1580  	summary, err := state.JobSummaryByID(ws, job.Namespace, job.ID)
  1581  	if err != nil {
  1582  		t.Fatalf("err: %v", err)
  1583  	}
  1584  	if summary != nil {
  1585  		t.Fatalf("expected summary to be nil, but got: %v", summary)
  1586  	}
  1587  
  1588  	index, err = state.Index("job_summary")
  1589  	if err != nil {
  1590  		t.Fatalf("err: %v", err)
  1591  	}
  1592  	if index != 1001 {
  1593  		t.Fatalf("bad: %d", index)
  1594  	}
  1595  
  1596  	versions, err := state.JobVersionsByID(ws, job.Namespace, job.ID)
  1597  	if err != nil {
  1598  		t.Fatalf("err: %v", err)
  1599  	}
  1600  	if len(versions) != 0 {
  1601  		t.Fatalf("expected no job versions")
  1602  	}
  1603  
  1604  	index, err = state.Index("job_summary")
  1605  	if err != nil {
  1606  		t.Fatalf("err: %v", err)
  1607  	}
  1608  	if index != 1001 {
  1609  		t.Fatalf("bad: %d", index)
  1610  	}
  1611  
  1612  	if watchFired(ws) {
  1613  		t.Fatalf("bad")
  1614  	}
  1615  }
  1616  
  1617  func TestStateStore_DeleteJobTxn_BatchDeletes(t *testing.T) {
  1618  	state := testStateStore(t)
  1619  
  1620  	const testJobCount = 10
  1621  	const jobVersionCount = 4
  1622  
  1623  	stateIndex := uint64(1000)
  1624  
  1625  	jobs := make([]*structs.Job, testJobCount)
  1626  	for i := 0; i < testJobCount; i++ {
  1627  		stateIndex++
  1628  		job := mock.BatchJob()
  1629  
  1630  		err := state.UpsertJob(stateIndex, job)
  1631  		require.NoError(t, err)
  1632  
  1633  		jobs[i] = job
  1634  
  1635  		// Create some versions
  1636  		for vi := 1; vi < jobVersionCount; vi++ {
  1637  			stateIndex++
  1638  
  1639  			job := job.Copy()
  1640  			job.TaskGroups[0].Tasks[0].Env = map[string]string{
  1641  				"Version": fmt.Sprintf("%d", vi),
  1642  			}
  1643  
  1644  			require.NoError(t, state.UpsertJob(stateIndex, job))
  1645  		}
  1646  	}
  1647  
  1648  	ws := memdb.NewWatchSet()
  1649  
  1650  	// Sanity check that jobs are present in DB
  1651  	job, err := state.JobByID(ws, jobs[0].Namespace, jobs[0].ID)
  1652  	require.NoError(t, err)
  1653  	require.Equal(t, jobs[0].ID, job.ID)
  1654  
  1655  	jobVersions, err := state.JobVersionsByID(ws, jobs[0].Namespace, jobs[0].ID)
  1656  	require.NoError(t, err)
  1657  	require.Equal(t, jobVersionCount, len(jobVersions))
  1658  
  1659  	// Actually delete
  1660  	const deletionIndex = uint64(10001)
  1661  	err = state.WithWriteTransaction(func(txn Txn) error {
  1662  		for i, job := range jobs {
  1663  			err := state.DeleteJobTxn(deletionIndex, job.Namespace, job.ID, txn)
  1664  			require.NoError(t, err, "failed at %d %e", i, err)
  1665  		}
  1666  		return nil
  1667  	})
  1668  	assert.NoError(t, err)
  1669  
  1670  	assert.True(t, watchFired(ws))
  1671  
  1672  	ws = memdb.NewWatchSet()
  1673  	out, err := state.JobByID(ws, jobs[0].Namespace, jobs[0].ID)
  1674  	require.NoError(t, err)
  1675  	require.Nil(t, out)
  1676  
  1677  	jobVersions, err = state.JobVersionsByID(ws, jobs[0].Namespace, jobs[0].ID)
  1678  	require.NoError(t, err)
  1679  	require.Empty(t, jobVersions)
  1680  
  1681  	index, err := state.Index("jobs")
  1682  	require.NoError(t, err)
  1683  	require.Equal(t, deletionIndex, index)
  1684  }
  1685  
  1686  func TestStateStore_DeleteJob_MultipleVersions(t *testing.T) {
  1687  	state := testStateStore(t)
  1688  	assert := assert.New(t)
  1689  
  1690  	// Create a job and mark it as stable
  1691  	job := mock.Job()
  1692  	job.Stable = true
  1693  	job.Priority = 0
  1694  
  1695  	// Create a watchset so we can test that upsert fires the watch
  1696  	ws := memdb.NewWatchSet()
  1697  	_, err := state.JobVersionsByID(ws, job.Namespace, job.ID)
  1698  	assert.Nil(err)
  1699  	assert.Nil(state.UpsertJob(1000, job))
  1700  	assert.True(watchFired(ws))
  1701  
  1702  	var finalJob *structs.Job
  1703  	for i := 1; i < 20; i++ {
  1704  		finalJob = mock.Job()
  1705  		finalJob.ID = job.ID
  1706  		finalJob.Priority = i
  1707  		assert.Nil(state.UpsertJob(uint64(1000+i), finalJob))
  1708  	}
  1709  
  1710  	assert.Nil(state.DeleteJob(1020, job.Namespace, job.ID))
  1711  	assert.True(watchFired(ws))
  1712  
  1713  	ws = memdb.NewWatchSet()
  1714  	out, err := state.JobByID(ws, job.Namespace, job.ID)
  1715  	assert.Nil(err)
  1716  	assert.Nil(out)
  1717  
  1718  	index, err := state.Index("jobs")
  1719  	assert.Nil(err)
  1720  	assert.EqualValues(1020, index)
  1721  
  1722  	summary, err := state.JobSummaryByID(ws, job.Namespace, job.ID)
  1723  	assert.Nil(err)
  1724  	assert.Nil(summary)
  1725  
  1726  	index, err = state.Index("job_version")
  1727  	assert.Nil(err)
  1728  	assert.EqualValues(1020, index)
  1729  
  1730  	versions, err := state.JobVersionsByID(ws, job.Namespace, job.ID)
  1731  	assert.Nil(err)
  1732  	assert.Len(versions, 0)
  1733  
  1734  	index, err = state.Index("job_summary")
  1735  	assert.Nil(err)
  1736  	assert.EqualValues(1020, index)
  1737  
  1738  	assert.False(watchFired(ws))
  1739  }
  1740  
  1741  func TestStateStore_DeleteJob_ChildJob(t *testing.T) {
  1742  	state := testStateStore(t)
  1743  
  1744  	parent := mock.Job()
  1745  	if err := state.UpsertJob(998, parent); err != nil {
  1746  		t.Fatalf("err: %v", err)
  1747  	}
  1748  
  1749  	child := mock.Job()
  1750  	child.ParentID = parent.ID
  1751  
  1752  	if err := state.UpsertJob(999, child); err != nil {
  1753  		t.Fatalf("err: %v", err)
  1754  	}
  1755  
  1756  	// Create a watchset so we can test that delete fires the watch
  1757  	ws := memdb.NewWatchSet()
  1758  	if _, err := state.JobSummaryByID(ws, parent.Namespace, parent.ID); err != nil {
  1759  		t.Fatalf("bad: %v", err)
  1760  	}
  1761  
  1762  	err := state.DeleteJob(1001, child.Namespace, child.ID)
  1763  	if err != nil {
  1764  		t.Fatalf("err: %v", err)
  1765  	}
  1766  	if !watchFired(ws) {
  1767  		t.Fatalf("bad")
  1768  	}
  1769  
  1770  	ws = memdb.NewWatchSet()
  1771  	summary, err := state.JobSummaryByID(ws, parent.Namespace, parent.ID)
  1772  	if err != nil {
  1773  		t.Fatalf("err: %v", err)
  1774  	}
  1775  	if summary == nil {
  1776  		t.Fatalf("nil summary")
  1777  	}
  1778  	if summary.JobID != parent.ID {
  1779  		t.Fatalf("bad summary id: %v", parent.ID)
  1780  	}
  1781  	if summary.Children == nil {
  1782  		t.Fatalf("nil children summary")
  1783  	}
  1784  	if summary.Children.Pending != 0 || summary.Children.Running != 0 || summary.Children.Dead != 1 {
  1785  		t.Fatalf("bad children summary: %v", summary.Children)
  1786  	}
  1787  	if watchFired(ws) {
  1788  		t.Fatalf("bad")
  1789  	}
  1790  }
  1791  
  1792  func TestStateStore_Jobs(t *testing.T) {
  1793  	state := testStateStore(t)
  1794  	var jobs []*structs.Job
  1795  
  1796  	for i := 0; i < 10; i++ {
  1797  		job := mock.Job()
  1798  		jobs = append(jobs, job)
  1799  
  1800  		err := state.UpsertJob(1000+uint64(i), job)
  1801  		if err != nil {
  1802  			t.Fatalf("err: %v", err)
  1803  		}
  1804  	}
  1805  
  1806  	ws := memdb.NewWatchSet()
  1807  	iter, err := state.Jobs(ws)
  1808  	if err != nil {
  1809  		t.Fatalf("err: %v", err)
  1810  	}
  1811  
  1812  	var out []*structs.Job
  1813  	for {
  1814  		raw := iter.Next()
  1815  		if raw == nil {
  1816  			break
  1817  		}
  1818  		out = append(out, raw.(*structs.Job))
  1819  	}
  1820  
  1821  	sort.Sort(JobIDSort(jobs))
  1822  	sort.Sort(JobIDSort(out))
  1823  
  1824  	if !reflect.DeepEqual(jobs, out) {
  1825  		t.Fatalf("bad: %#v %#v", jobs, out)
  1826  	}
  1827  	if watchFired(ws) {
  1828  		t.Fatalf("bad")
  1829  	}
  1830  }
  1831  
  1832  func TestStateStore_JobVersions(t *testing.T) {
  1833  	state := testStateStore(t)
  1834  	var jobs []*structs.Job
  1835  
  1836  	for i := 0; i < 10; i++ {
  1837  		job := mock.Job()
  1838  		jobs = append(jobs, job)
  1839  
  1840  		err := state.UpsertJob(1000+uint64(i), job)
  1841  		if err != nil {
  1842  			t.Fatalf("err: %v", err)
  1843  		}
  1844  	}
  1845  
  1846  	ws := memdb.NewWatchSet()
  1847  	iter, err := state.JobVersions(ws)
  1848  	if err != nil {
  1849  		t.Fatalf("err: %v", err)
  1850  	}
  1851  
  1852  	var out []*structs.Job
  1853  	for {
  1854  		raw := iter.Next()
  1855  		if raw == nil {
  1856  			break
  1857  		}
  1858  		out = append(out, raw.(*structs.Job))
  1859  	}
  1860  
  1861  	sort.Sort(JobIDSort(jobs))
  1862  	sort.Sort(JobIDSort(out))
  1863  
  1864  	if !reflect.DeepEqual(jobs, out) {
  1865  		t.Fatalf("bad: %#v %#v", jobs, out)
  1866  	}
  1867  	if watchFired(ws) {
  1868  		t.Fatalf("bad")
  1869  	}
  1870  }
  1871  
  1872  func TestStateStore_JobsByIDPrefix(t *testing.T) {
  1873  	state := testStateStore(t)
  1874  	job := mock.Job()
  1875  
  1876  	job.ID = "redis"
  1877  	err := state.UpsertJob(1000, job)
  1878  	if err != nil {
  1879  		t.Fatalf("err: %v", err)
  1880  	}
  1881  
  1882  	ws := memdb.NewWatchSet()
  1883  	iter, err := state.JobsByIDPrefix(ws, job.Namespace, job.ID)
  1884  	if err != nil {
  1885  		t.Fatalf("err: %v", err)
  1886  	}
  1887  
  1888  	gatherJobs := func(iter memdb.ResultIterator) []*structs.Job {
  1889  		var jobs []*structs.Job
  1890  		for {
  1891  			raw := iter.Next()
  1892  			if raw == nil {
  1893  				break
  1894  			}
  1895  			jobs = append(jobs, raw.(*structs.Job))
  1896  		}
  1897  		return jobs
  1898  	}
  1899  
  1900  	jobs := gatherJobs(iter)
  1901  	if len(jobs) != 1 {
  1902  		t.Fatalf("err: %v", err)
  1903  	}
  1904  
  1905  	iter, err = state.JobsByIDPrefix(ws, job.Namespace, "re")
  1906  	if err != nil {
  1907  		t.Fatalf("err: %v", err)
  1908  	}
  1909  
  1910  	jobs = gatherJobs(iter)
  1911  	if len(jobs) != 1 {
  1912  		t.Fatalf("err: %v", err)
  1913  	}
  1914  	if watchFired(ws) {
  1915  		t.Fatalf("bad")
  1916  	}
  1917  
  1918  	job = mock.Job()
  1919  	job.ID = "riak"
  1920  	err = state.UpsertJob(1001, job)
  1921  	if err != nil {
  1922  		t.Fatalf("err: %v", err)
  1923  	}
  1924  
  1925  	if !watchFired(ws) {
  1926  		t.Fatalf("bad")
  1927  	}
  1928  
  1929  	ws = memdb.NewWatchSet()
  1930  	iter, err = state.JobsByIDPrefix(ws, job.Namespace, "r")
  1931  	if err != nil {
  1932  		t.Fatalf("err: %v", err)
  1933  	}
  1934  
  1935  	jobs = gatherJobs(iter)
  1936  	if len(jobs) != 2 {
  1937  		t.Fatalf("err: %v", err)
  1938  	}
  1939  
  1940  	iter, err = state.JobsByIDPrefix(ws, job.Namespace, "ri")
  1941  	if err != nil {
  1942  		t.Fatalf("err: %v", err)
  1943  	}
  1944  
  1945  	jobs = gatherJobs(iter)
  1946  	if len(jobs) != 1 {
  1947  		t.Fatalf("err: %v", err)
  1948  	}
  1949  	if watchFired(ws) {
  1950  		t.Fatalf("bad")
  1951  	}
  1952  }
  1953  
  1954  func TestStateStore_JobsByPeriodic(t *testing.T) {
  1955  	state := testStateStore(t)
  1956  	var periodic, nonPeriodic []*structs.Job
  1957  
  1958  	for i := 0; i < 10; i++ {
  1959  		job := mock.Job()
  1960  		nonPeriodic = append(nonPeriodic, job)
  1961  
  1962  		err := state.UpsertJob(1000+uint64(i), job)
  1963  		if err != nil {
  1964  			t.Fatalf("err: %v", err)
  1965  		}
  1966  	}
  1967  
  1968  	for i := 0; i < 10; i++ {
  1969  		job := mock.PeriodicJob()
  1970  		periodic = append(periodic, job)
  1971  
  1972  		err := state.UpsertJob(2000+uint64(i), job)
  1973  		if err != nil {
  1974  			t.Fatalf("err: %v", err)
  1975  		}
  1976  	}
  1977  
  1978  	ws := memdb.NewWatchSet()
  1979  	iter, err := state.JobsByPeriodic(ws, true)
  1980  	if err != nil {
  1981  		t.Fatalf("err: %v", err)
  1982  	}
  1983  
  1984  	var outPeriodic []*structs.Job
  1985  	for {
  1986  		raw := iter.Next()
  1987  		if raw == nil {
  1988  			break
  1989  		}
  1990  		outPeriodic = append(outPeriodic, raw.(*structs.Job))
  1991  	}
  1992  
  1993  	iter, err = state.JobsByPeriodic(ws, false)
  1994  	if err != nil {
  1995  		t.Fatalf("err: %v", err)
  1996  	}
  1997  
  1998  	var outNonPeriodic []*structs.Job
  1999  	for {
  2000  		raw := iter.Next()
  2001  		if raw == nil {
  2002  			break
  2003  		}
  2004  		outNonPeriodic = append(outNonPeriodic, raw.(*structs.Job))
  2005  	}
  2006  
  2007  	sort.Sort(JobIDSort(periodic))
  2008  	sort.Sort(JobIDSort(nonPeriodic))
  2009  	sort.Sort(JobIDSort(outPeriodic))
  2010  	sort.Sort(JobIDSort(outNonPeriodic))
  2011  
  2012  	if !reflect.DeepEqual(periodic, outPeriodic) {
  2013  		t.Fatalf("bad: %#v %#v", periodic, outPeriodic)
  2014  	}
  2015  
  2016  	if !reflect.DeepEqual(nonPeriodic, outNonPeriodic) {
  2017  		t.Fatalf("bad: %#v %#v", nonPeriodic, outNonPeriodic)
  2018  	}
  2019  	if watchFired(ws) {
  2020  		t.Fatalf("bad")
  2021  	}
  2022  }
  2023  
  2024  func TestStateStore_JobsByScheduler(t *testing.T) {
  2025  	state := testStateStore(t)
  2026  	var serviceJobs []*structs.Job
  2027  	var sysJobs []*structs.Job
  2028  
  2029  	for i := 0; i < 10; i++ {
  2030  		job := mock.Job()
  2031  		serviceJobs = append(serviceJobs, job)
  2032  
  2033  		err := state.UpsertJob(1000+uint64(i), job)
  2034  		if err != nil {
  2035  			t.Fatalf("err: %v", err)
  2036  		}
  2037  	}
  2038  
  2039  	for i := 0; i < 10; i++ {
  2040  		job := mock.SystemJob()
  2041  		job.Status = structs.JobStatusRunning
  2042  		sysJobs = append(sysJobs, job)
  2043  
  2044  		err := state.UpsertJob(2000+uint64(i), job)
  2045  		if err != nil {
  2046  			t.Fatalf("err: %v", err)
  2047  		}
  2048  	}
  2049  
  2050  	ws := memdb.NewWatchSet()
  2051  	iter, err := state.JobsByScheduler(ws, "service")
  2052  	if err != nil {
  2053  		t.Fatalf("err: %v", err)
  2054  	}
  2055  
  2056  	var outService []*structs.Job
  2057  	for {
  2058  		raw := iter.Next()
  2059  		if raw == nil {
  2060  			break
  2061  		}
  2062  		outService = append(outService, raw.(*structs.Job))
  2063  	}
  2064  
  2065  	iter, err = state.JobsByScheduler(ws, "system")
  2066  	if err != nil {
  2067  		t.Fatalf("err: %v", err)
  2068  	}
  2069  
  2070  	var outSystem []*structs.Job
  2071  	for {
  2072  		raw := iter.Next()
  2073  		if raw == nil {
  2074  			break
  2075  		}
  2076  		outSystem = append(outSystem, raw.(*structs.Job))
  2077  	}
  2078  
  2079  	sort.Sort(JobIDSort(serviceJobs))
  2080  	sort.Sort(JobIDSort(sysJobs))
  2081  	sort.Sort(JobIDSort(outService))
  2082  	sort.Sort(JobIDSort(outSystem))
  2083  
  2084  	if !reflect.DeepEqual(serviceJobs, outService) {
  2085  		t.Fatalf("bad: %#v %#v", serviceJobs, outService)
  2086  	}
  2087  
  2088  	if !reflect.DeepEqual(sysJobs, outSystem) {
  2089  		t.Fatalf("bad: %#v %#v", sysJobs, outSystem)
  2090  	}
  2091  	if watchFired(ws) {
  2092  		t.Fatalf("bad")
  2093  	}
  2094  }
  2095  
  2096  func TestStateStore_JobsByGC(t *testing.T) {
  2097  	state := testStateStore(t)
  2098  	gc, nonGc := make(map[string]struct{}), make(map[string]struct{})
  2099  
  2100  	for i := 0; i < 20; i++ {
  2101  		var job *structs.Job
  2102  		if i%2 == 0 {
  2103  			job = mock.Job()
  2104  		} else {
  2105  			job = mock.PeriodicJob()
  2106  		}
  2107  		nonGc[job.ID] = struct{}{}
  2108  
  2109  		if err := state.UpsertJob(1000+uint64(i), job); err != nil {
  2110  			t.Fatalf("err: %v", err)
  2111  		}
  2112  	}
  2113  
  2114  	for i := 0; i < 20; i += 2 {
  2115  		job := mock.Job()
  2116  		job.Type = structs.JobTypeBatch
  2117  		gc[job.ID] = struct{}{}
  2118  
  2119  		if err := state.UpsertJob(2000+uint64(i), job); err != nil {
  2120  			t.Fatalf("err: %v", err)
  2121  		}
  2122  
  2123  		// Create an eval for it
  2124  		eval := mock.Eval()
  2125  		eval.JobID = job.ID
  2126  		eval.Status = structs.EvalStatusComplete
  2127  		if err := state.UpsertEvals(2000+uint64(i+1), []*structs.Evaluation{eval}); err != nil {
  2128  			t.Fatalf("err: %v", err)
  2129  		}
  2130  
  2131  	}
  2132  
  2133  	ws := memdb.NewWatchSet()
  2134  	iter, err := state.JobsByGC(ws, true)
  2135  	if err != nil {
  2136  		t.Fatalf("err: %v", err)
  2137  	}
  2138  
  2139  	outGc := make(map[string]struct{})
  2140  	for i := iter.Next(); i != nil; i = iter.Next() {
  2141  		j := i.(*structs.Job)
  2142  		outGc[j.ID] = struct{}{}
  2143  	}
  2144  
  2145  	iter, err = state.JobsByGC(ws, false)
  2146  	if err != nil {
  2147  		t.Fatalf("err: %v", err)
  2148  	}
  2149  
  2150  	outNonGc := make(map[string]struct{})
  2151  	for i := iter.Next(); i != nil; i = iter.Next() {
  2152  		j := i.(*structs.Job)
  2153  		outNonGc[j.ID] = struct{}{}
  2154  	}
  2155  
  2156  	if !reflect.DeepEqual(gc, outGc) {
  2157  		t.Fatalf("bad: %#v %#v", gc, outGc)
  2158  	}
  2159  
  2160  	if !reflect.DeepEqual(nonGc, outNonGc) {
  2161  		t.Fatalf("bad: %#v %#v", nonGc, outNonGc)
  2162  	}
  2163  	if watchFired(ws) {
  2164  		t.Fatalf("bad")
  2165  	}
  2166  }
  2167  
  2168  func TestStateStore_RestoreJob(t *testing.T) {
  2169  	state := testStateStore(t)
  2170  	job := mock.Job()
  2171  
  2172  	restore, err := state.Restore()
  2173  	if err != nil {
  2174  		t.Fatalf("err: %v", err)
  2175  	}
  2176  
  2177  	err = restore.JobRestore(job)
  2178  	if err != nil {
  2179  		t.Fatalf("err: %v", err)
  2180  	}
  2181  	restore.Commit()
  2182  
  2183  	ws := memdb.NewWatchSet()
  2184  	out, err := state.JobByID(ws, job.Namespace, job.ID)
  2185  	if err != nil {
  2186  		t.Fatalf("err: %v", err)
  2187  	}
  2188  
  2189  	if !reflect.DeepEqual(out, job) {
  2190  		t.Fatalf("Bad: %#v %#v", out, job)
  2191  	}
  2192  }
  2193  
  2194  // This test ensures that the state restore creates the EphemeralDisk for a job if
  2195  // it doesn't have one
  2196  // COMPAT 0.4.1 -> 0.5
  2197  func TestStateStore_Jobs_NoEphemeralDisk(t *testing.T) {
  2198  	state := testStateStore(t)
  2199  	job := mock.Job()
  2200  
  2201  	// Set EphemeralDisk to nil and set the DiskMB to 150
  2202  	job.TaskGroups[0].EphemeralDisk = nil
  2203  	job.TaskGroups[0].Tasks[0].Resources.DiskMB = 150
  2204  
  2205  	restore, err := state.Restore()
  2206  	if err != nil {
  2207  		t.Fatalf("err: %v", err)
  2208  	}
  2209  
  2210  	err = restore.JobRestore(job)
  2211  	if err != nil {
  2212  		t.Fatalf("err: %v", err)
  2213  	}
  2214  	restore.Commit()
  2215  
  2216  	ws := memdb.NewWatchSet()
  2217  	out, err := state.JobByID(ws, job.Namespace, job.ID)
  2218  	if err != nil {
  2219  		t.Fatalf("err: %v", err)
  2220  	}
  2221  
  2222  	// Expect job to have local disk and clear out the task's disk resource ask
  2223  	expected := job.Copy()
  2224  	expected.TaskGroups[0].EphemeralDisk = &structs.EphemeralDisk{
  2225  		SizeMB: 150,
  2226  	}
  2227  	expected.TaskGroups[0].Tasks[0].Resources.DiskMB = 0
  2228  	if !reflect.DeepEqual(out, expected) {
  2229  		t.Fatalf("Bad: %#v %#v", out, job)
  2230  	}
  2231  }
  2232  
  2233  func TestStateStore_UpsertPeriodicLaunch(t *testing.T) {
  2234  	state := testStateStore(t)
  2235  	job := mock.Job()
  2236  	launch := &structs.PeriodicLaunch{
  2237  		ID:        job.ID,
  2238  		Namespace: job.Namespace,
  2239  		Launch:    time.Now(),
  2240  	}
  2241  
  2242  	// Create a watchset so we can test that upsert fires the watch
  2243  	ws := memdb.NewWatchSet()
  2244  	if _, err := state.PeriodicLaunchByID(ws, job.Namespace, launch.ID); err != nil {
  2245  		t.Fatalf("bad: %v", err)
  2246  	}
  2247  
  2248  	err := state.UpsertPeriodicLaunch(1000, launch)
  2249  	if err != nil {
  2250  		t.Fatalf("err: %v", err)
  2251  	}
  2252  
  2253  	if !watchFired(ws) {
  2254  		t.Fatalf("bad")
  2255  	}
  2256  
  2257  	ws = memdb.NewWatchSet()
  2258  	out, err := state.PeriodicLaunchByID(ws, job.Namespace, job.ID)
  2259  	if err != nil {
  2260  		t.Fatalf("err: %v", err)
  2261  	}
  2262  	if out.CreateIndex != 1000 {
  2263  		t.Fatalf("bad: %#v", out)
  2264  	}
  2265  	if out.ModifyIndex != 1000 {
  2266  		t.Fatalf("bad: %#v", out)
  2267  	}
  2268  
  2269  	if !reflect.DeepEqual(launch, out) {
  2270  		t.Fatalf("bad: %#v %#v", job, out)
  2271  	}
  2272  
  2273  	index, err := state.Index("periodic_launch")
  2274  	if err != nil {
  2275  		t.Fatalf("err: %v", err)
  2276  	}
  2277  	if index != 1000 {
  2278  		t.Fatalf("bad: %d", index)
  2279  	}
  2280  
  2281  	if watchFired(ws) {
  2282  		t.Fatalf("bad")
  2283  	}
  2284  }
  2285  
  2286  func TestStateStore_UpdateUpsertPeriodicLaunch(t *testing.T) {
  2287  	state := testStateStore(t)
  2288  	job := mock.Job()
  2289  	launch := &structs.PeriodicLaunch{
  2290  		ID:        job.ID,
  2291  		Namespace: job.Namespace,
  2292  		Launch:    time.Now(),
  2293  	}
  2294  
  2295  	err := state.UpsertPeriodicLaunch(1000, launch)
  2296  	if err != nil {
  2297  		t.Fatalf("err: %v", err)
  2298  	}
  2299  
  2300  	// Create a watchset so we can test that upsert fires the watch
  2301  	ws := memdb.NewWatchSet()
  2302  	if _, err := state.PeriodicLaunchByID(ws, job.Namespace, launch.ID); err != nil {
  2303  		t.Fatalf("bad: %v", err)
  2304  	}
  2305  
  2306  	launch2 := &structs.PeriodicLaunch{
  2307  		ID:        job.ID,
  2308  		Namespace: job.Namespace,
  2309  		Launch:    launch.Launch.Add(1 * time.Second),
  2310  	}
  2311  	err = state.UpsertPeriodicLaunch(1001, launch2)
  2312  	if err != nil {
  2313  		t.Fatalf("err: %v", err)
  2314  	}
  2315  
  2316  	if !watchFired(ws) {
  2317  		t.Fatalf("bad")
  2318  	}
  2319  
  2320  	ws = memdb.NewWatchSet()
  2321  	out, err := state.PeriodicLaunchByID(ws, job.Namespace, job.ID)
  2322  	if err != nil {
  2323  		t.Fatalf("err: %v", err)
  2324  	}
  2325  	if out.CreateIndex != 1000 {
  2326  		t.Fatalf("bad: %#v", out)
  2327  	}
  2328  	if out.ModifyIndex != 1001 {
  2329  		t.Fatalf("bad: %#v", out)
  2330  	}
  2331  
  2332  	if !reflect.DeepEqual(launch2, out) {
  2333  		t.Fatalf("bad: %#v %#v", launch2, out)
  2334  	}
  2335  
  2336  	index, err := state.Index("periodic_launch")
  2337  	if err != nil {
  2338  		t.Fatalf("err: %v", err)
  2339  	}
  2340  	if index != 1001 {
  2341  		t.Fatalf("bad: %d", index)
  2342  	}
  2343  
  2344  	if watchFired(ws) {
  2345  		t.Fatalf("bad")
  2346  	}
  2347  }
  2348  
  2349  func TestStateStore_DeletePeriodicLaunch(t *testing.T) {
  2350  	state := testStateStore(t)
  2351  	job := mock.Job()
  2352  	launch := &structs.PeriodicLaunch{
  2353  		ID:        job.ID,
  2354  		Namespace: job.Namespace,
  2355  		Launch:    time.Now(),
  2356  	}
  2357  
  2358  	err := state.UpsertPeriodicLaunch(1000, launch)
  2359  	if err != nil {
  2360  		t.Fatalf("err: %v", err)
  2361  	}
  2362  
  2363  	// Create a watchset so we can test that delete fires the watch
  2364  	ws := memdb.NewWatchSet()
  2365  	if _, err := state.PeriodicLaunchByID(ws, job.Namespace, launch.ID); err != nil {
  2366  		t.Fatalf("bad: %v", err)
  2367  	}
  2368  
  2369  	err = state.DeletePeriodicLaunch(1001, launch.Namespace, launch.ID)
  2370  	if err != nil {
  2371  		t.Fatalf("err: %v", err)
  2372  	}
  2373  
  2374  	if !watchFired(ws) {
  2375  		t.Fatalf("bad")
  2376  	}
  2377  
  2378  	ws = memdb.NewWatchSet()
  2379  	out, err := state.PeriodicLaunchByID(ws, job.Namespace, job.ID)
  2380  	if err != nil {
  2381  		t.Fatalf("err: %v", err)
  2382  	}
  2383  
  2384  	if out != nil {
  2385  		t.Fatalf("bad: %#v %#v", job, out)
  2386  	}
  2387  
  2388  	index, err := state.Index("periodic_launch")
  2389  	if err != nil {
  2390  		t.Fatalf("err: %v", err)
  2391  	}
  2392  	if index != 1001 {
  2393  		t.Fatalf("bad: %d", index)
  2394  	}
  2395  
  2396  	if watchFired(ws) {
  2397  		t.Fatalf("bad")
  2398  	}
  2399  }
  2400  
  2401  func TestStateStore_PeriodicLaunches(t *testing.T) {
  2402  	state := testStateStore(t)
  2403  	var launches []*structs.PeriodicLaunch
  2404  
  2405  	for i := 0; i < 10; i++ {
  2406  		job := mock.Job()
  2407  		launch := &structs.PeriodicLaunch{
  2408  			ID:        job.ID,
  2409  			Namespace: job.Namespace,
  2410  			Launch:    time.Now(),
  2411  		}
  2412  		launches = append(launches, launch)
  2413  
  2414  		err := state.UpsertPeriodicLaunch(1000+uint64(i), launch)
  2415  		if err != nil {
  2416  			t.Fatalf("err: %v", err)
  2417  		}
  2418  	}
  2419  
  2420  	ws := memdb.NewWatchSet()
  2421  	iter, err := state.PeriodicLaunches(ws)
  2422  	if err != nil {
  2423  		t.Fatalf("err: %v", err)
  2424  	}
  2425  
  2426  	out := make(map[string]*structs.PeriodicLaunch, 10)
  2427  	for {
  2428  		raw := iter.Next()
  2429  		if raw == nil {
  2430  			break
  2431  		}
  2432  		launch := raw.(*structs.PeriodicLaunch)
  2433  		if _, ok := out[launch.ID]; ok {
  2434  			t.Fatalf("duplicate: %v", launch.ID)
  2435  		}
  2436  
  2437  		out[launch.ID] = launch
  2438  	}
  2439  
  2440  	for _, launch := range launches {
  2441  		l, ok := out[launch.ID]
  2442  		if !ok {
  2443  			t.Fatalf("bad %v", launch.ID)
  2444  		}
  2445  
  2446  		if !reflect.DeepEqual(launch, l) {
  2447  			t.Fatalf("bad: %#v %#v", launch, l)
  2448  		}
  2449  
  2450  		delete(out, launch.ID)
  2451  	}
  2452  
  2453  	if len(out) != 0 {
  2454  		t.Fatalf("leftover: %#v", out)
  2455  	}
  2456  
  2457  	if watchFired(ws) {
  2458  		t.Fatalf("bad")
  2459  	}
  2460  }
  2461  
  2462  func TestStateStore_RestorePeriodicLaunch(t *testing.T) {
  2463  	state := testStateStore(t)
  2464  	job := mock.Job()
  2465  	launch := &structs.PeriodicLaunch{
  2466  		ID:        job.ID,
  2467  		Namespace: job.Namespace,
  2468  		Launch:    time.Now(),
  2469  	}
  2470  
  2471  	restore, err := state.Restore()
  2472  	if err != nil {
  2473  		t.Fatalf("err: %v", err)
  2474  	}
  2475  
  2476  	err = restore.PeriodicLaunchRestore(launch)
  2477  	if err != nil {
  2478  		t.Fatalf("err: %v", err)
  2479  	}
  2480  	restore.Commit()
  2481  
  2482  	ws := memdb.NewWatchSet()
  2483  	out, err := state.PeriodicLaunchByID(ws, job.Namespace, job.ID)
  2484  	if err != nil {
  2485  		t.Fatalf("err: %v", err)
  2486  	}
  2487  
  2488  	if !reflect.DeepEqual(out, launch) {
  2489  		t.Fatalf("Bad: %#v %#v", out, job)
  2490  	}
  2491  
  2492  	if watchFired(ws) {
  2493  		t.Fatalf("bad")
  2494  	}
  2495  }
  2496  
  2497  func TestStateStore_RestoreJobVersion(t *testing.T) {
  2498  	state := testStateStore(t)
  2499  	job := mock.Job()
  2500  
  2501  	restore, err := state.Restore()
  2502  	if err != nil {
  2503  		t.Fatalf("err: %v", err)
  2504  	}
  2505  
  2506  	err = restore.JobVersionRestore(job)
  2507  	if err != nil {
  2508  		t.Fatalf("err: %v", err)
  2509  	}
  2510  	restore.Commit()
  2511  
  2512  	ws := memdb.NewWatchSet()
  2513  	out, err := state.JobByIDAndVersion(ws, job.Namespace, job.ID, job.Version)
  2514  	if err != nil {
  2515  		t.Fatalf("err: %v", err)
  2516  	}
  2517  
  2518  	if !reflect.DeepEqual(out, job) {
  2519  		t.Fatalf("Bad: %#v %#v", out, job)
  2520  	}
  2521  
  2522  	if watchFired(ws) {
  2523  		t.Fatalf("bad")
  2524  	}
  2525  }
  2526  
  2527  func TestStateStore_RestoreDeployment(t *testing.T) {
  2528  	state := testStateStore(t)
  2529  	d := mock.Deployment()
  2530  
  2531  	restore, err := state.Restore()
  2532  	if err != nil {
  2533  		t.Fatalf("err: %v", err)
  2534  	}
  2535  
  2536  	err = restore.DeploymentRestore(d)
  2537  	if err != nil {
  2538  		t.Fatalf("err: %v", err)
  2539  	}
  2540  	restore.Commit()
  2541  
  2542  	ws := memdb.NewWatchSet()
  2543  	out, err := state.DeploymentByID(ws, d.ID)
  2544  	if err != nil {
  2545  		t.Fatalf("err: %v", err)
  2546  	}
  2547  
  2548  	if !reflect.DeepEqual(out, d) {
  2549  		t.Fatalf("Bad: %#v %#v", out, d)
  2550  	}
  2551  
  2552  	if watchFired(ws) {
  2553  		t.Fatalf("bad")
  2554  	}
  2555  }
  2556  
  2557  func TestStateStore_RestoreJobSummary(t *testing.T) {
  2558  	state := testStateStore(t)
  2559  	job := mock.Job()
  2560  	jobSummary := &structs.JobSummary{
  2561  		JobID:     job.ID,
  2562  		Namespace: job.Namespace,
  2563  		Summary: map[string]structs.TaskGroupSummary{
  2564  			"web": {
  2565  				Starting: 10,
  2566  			},
  2567  		},
  2568  	}
  2569  	restore, err := state.Restore()
  2570  	if err != nil {
  2571  		t.Fatalf("err: %v", err)
  2572  	}
  2573  
  2574  	err = restore.JobSummaryRestore(jobSummary)
  2575  	if err != nil {
  2576  		t.Fatalf("err: %v", err)
  2577  	}
  2578  	restore.Commit()
  2579  
  2580  	ws := memdb.NewWatchSet()
  2581  	out, err := state.JobSummaryByID(ws, job.Namespace, job.ID)
  2582  	if err != nil {
  2583  		t.Fatalf("err: %v", err)
  2584  	}
  2585  
  2586  	if !reflect.DeepEqual(out, jobSummary) {
  2587  		t.Fatalf("Bad: %#v %#v", out, jobSummary)
  2588  	}
  2589  }
  2590  
  2591  func TestStateStore_Indexes(t *testing.T) {
  2592  	state := testStateStore(t)
  2593  	node := mock.Node()
  2594  
  2595  	err := state.UpsertNode(1000, node)
  2596  	if err != nil {
  2597  		t.Fatalf("err: %v", err)
  2598  	}
  2599  
  2600  	iter, err := state.Indexes()
  2601  	if err != nil {
  2602  		t.Fatalf("err: %v", err)
  2603  	}
  2604  
  2605  	var out []*IndexEntry
  2606  	for {
  2607  		raw := iter.Next()
  2608  		if raw == nil {
  2609  			break
  2610  		}
  2611  		out = append(out, raw.(*IndexEntry))
  2612  	}
  2613  
  2614  	expect := &IndexEntry{"nodes", 1000}
  2615  	if l := len(out); l != 1 && l != 2 {
  2616  		t.Fatalf("unexpected number of index entries: %v", out)
  2617  	}
  2618  
  2619  	for _, index := range out {
  2620  		if index.Key != expect.Key {
  2621  			continue
  2622  		}
  2623  		if index.Value != expect.Value {
  2624  			t.Fatalf("bad index; got %d; want %d", index.Value, expect.Value)
  2625  		}
  2626  
  2627  		// We matched
  2628  		return
  2629  	}
  2630  
  2631  	t.Fatal("did not find expected index entry")
  2632  }
  2633  
  2634  func TestStateStore_LatestIndex(t *testing.T) {
  2635  	state := testStateStore(t)
  2636  
  2637  	if err := state.UpsertNode(1000, mock.Node()); err != nil {
  2638  		t.Fatalf("err: %v", err)
  2639  	}
  2640  
  2641  	exp := uint64(2000)
  2642  	if err := state.UpsertJob(exp, mock.Job()); err != nil {
  2643  		t.Fatalf("err: %v", err)
  2644  	}
  2645  
  2646  	latest, err := state.LatestIndex()
  2647  	if err != nil {
  2648  		t.Fatalf("err: %v", err)
  2649  	}
  2650  
  2651  	if latest != exp {
  2652  		t.Fatalf("LatestIndex() returned %d; want %d", latest, exp)
  2653  	}
  2654  }
  2655  
  2656  func TestStateStore_RestoreIndex(t *testing.T) {
  2657  	state := testStateStore(t)
  2658  
  2659  	restore, err := state.Restore()
  2660  	if err != nil {
  2661  		t.Fatalf("err: %v", err)
  2662  	}
  2663  
  2664  	index := &IndexEntry{"jobs", 1000}
  2665  	err = restore.IndexRestore(index)
  2666  	if err != nil {
  2667  		t.Fatalf("err: %v", err)
  2668  	}
  2669  
  2670  	restore.Commit()
  2671  
  2672  	out, err := state.Index("jobs")
  2673  	if err != nil {
  2674  		t.Fatalf("err: %v", err)
  2675  	}
  2676  
  2677  	if out != 1000 {
  2678  		t.Fatalf("Bad: %#v %#v", out, 1000)
  2679  	}
  2680  }
  2681  
  2682  func TestStateStore_UpsertEvals_Eval(t *testing.T) {
  2683  	state := testStateStore(t)
  2684  	eval := mock.Eval()
  2685  
  2686  	// Create a watchset so we can test that upsert fires the watch
  2687  	ws := memdb.NewWatchSet()
  2688  	if _, err := state.EvalByID(ws, eval.ID); err != nil {
  2689  		t.Fatalf("bad: %v", err)
  2690  	}
  2691  
  2692  	err := state.UpsertEvals(1000, []*structs.Evaluation{eval})
  2693  	if err != nil {
  2694  		t.Fatalf("err: %v", err)
  2695  	}
  2696  
  2697  	if !watchFired(ws) {
  2698  		t.Fatalf("bad")
  2699  	}
  2700  
  2701  	ws = memdb.NewWatchSet()
  2702  	out, err := state.EvalByID(ws, eval.ID)
  2703  	if err != nil {
  2704  		t.Fatalf("err: %v", err)
  2705  	}
  2706  
  2707  	if !reflect.DeepEqual(eval, out) {
  2708  		t.Fatalf("bad: %#v %#v", eval, out)
  2709  	}
  2710  
  2711  	index, err := state.Index("evals")
  2712  	if err != nil {
  2713  		t.Fatalf("err: %v", err)
  2714  	}
  2715  	if index != 1000 {
  2716  		t.Fatalf("bad: %d", index)
  2717  	}
  2718  
  2719  	if watchFired(ws) {
  2720  		t.Fatalf("bad")
  2721  	}
  2722  }
  2723  
  2724  func TestStateStore_UpsertEvals_CancelBlocked(t *testing.T) {
  2725  	state := testStateStore(t)
  2726  
  2727  	// Create two blocked evals for the same job
  2728  	j := "test-job"
  2729  	b1, b2 := mock.Eval(), mock.Eval()
  2730  	b1.JobID = j
  2731  	b1.Status = structs.EvalStatusBlocked
  2732  	b2.JobID = j
  2733  	b2.Status = structs.EvalStatusBlocked
  2734  
  2735  	err := state.UpsertEvals(999, []*structs.Evaluation{b1, b2})
  2736  	if err != nil {
  2737  		t.Fatalf("err: %v", err)
  2738  	}
  2739  
  2740  	// Create one complete and successful eval for the job
  2741  	eval := mock.Eval()
  2742  	eval.JobID = j
  2743  	eval.Status = structs.EvalStatusComplete
  2744  
  2745  	// Create a watchset so we can test that the upsert of the complete eval
  2746  	// fires the watch
  2747  	ws := memdb.NewWatchSet()
  2748  	if _, err := state.EvalByID(ws, b1.ID); err != nil {
  2749  		t.Fatalf("bad: %v", err)
  2750  	}
  2751  	if _, err := state.EvalByID(ws, b2.ID); err != nil {
  2752  		t.Fatalf("bad: %v", err)
  2753  	}
  2754  
  2755  	if err := state.UpsertEvals(1000, []*structs.Evaluation{eval}); err != nil {
  2756  		t.Fatalf("err: %v", err)
  2757  	}
  2758  
  2759  	if !watchFired(ws) {
  2760  		t.Fatalf("bad")
  2761  	}
  2762  
  2763  	ws = memdb.NewWatchSet()
  2764  	out, err := state.EvalByID(ws, eval.ID)
  2765  	if err != nil {
  2766  		t.Fatalf("err: %v", err)
  2767  	}
  2768  
  2769  	if !reflect.DeepEqual(eval, out) {
  2770  		t.Fatalf("bad: %#v %#v", eval, out)
  2771  	}
  2772  
  2773  	index, err := state.Index("evals")
  2774  	if err != nil {
  2775  		t.Fatalf("err: %v", err)
  2776  	}
  2777  	if index != 1000 {
  2778  		t.Fatalf("bad: %d", index)
  2779  	}
  2780  
  2781  	// Get b1/b2 and check they are cancelled
  2782  	out1, err := state.EvalByID(ws, b1.ID)
  2783  	if err != nil {
  2784  		t.Fatalf("err: %v", err)
  2785  	}
  2786  
  2787  	out2, err := state.EvalByID(ws, b2.ID)
  2788  	if err != nil {
  2789  		t.Fatalf("err: %v", err)
  2790  	}
  2791  
  2792  	if out1.Status != structs.EvalStatusCancelled || out2.Status != structs.EvalStatusCancelled {
  2793  		t.Fatalf("bad: %#v %#v", out1, out2)
  2794  	}
  2795  
  2796  	if watchFired(ws) {
  2797  		t.Fatalf("bad")
  2798  	}
  2799  }
  2800  
  2801  func TestStateStore_Update_UpsertEvals_Eval(t *testing.T) {
  2802  	state := testStateStore(t)
  2803  	eval := mock.Eval()
  2804  
  2805  	err := state.UpsertEvals(1000, []*structs.Evaluation{eval})
  2806  	if err != nil {
  2807  		t.Fatalf("err: %v", err)
  2808  	}
  2809  
  2810  	// Create a watchset so we can test that delete fires the watch
  2811  	ws := memdb.NewWatchSet()
  2812  	ws2 := memdb.NewWatchSet()
  2813  	if _, err := state.EvalByID(ws, eval.ID); err != nil {
  2814  		t.Fatalf("bad: %v", err)
  2815  	}
  2816  
  2817  	if _, err := state.EvalsByJob(ws2, eval.Namespace, eval.JobID); err != nil {
  2818  		t.Fatalf("bad: %v", err)
  2819  	}
  2820  
  2821  	eval2 := mock.Eval()
  2822  	eval2.ID = eval.ID
  2823  	eval2.JobID = eval.JobID
  2824  	err = state.UpsertEvals(1001, []*structs.Evaluation{eval2})
  2825  	if err != nil {
  2826  		t.Fatalf("err: %v", err)
  2827  	}
  2828  
  2829  	if !watchFired(ws) {
  2830  		t.Fatalf("bad")
  2831  	}
  2832  	if !watchFired(ws2) {
  2833  		t.Fatalf("bad")
  2834  	}
  2835  
  2836  	ws = memdb.NewWatchSet()
  2837  	out, err := state.EvalByID(ws, eval.ID)
  2838  	if err != nil {
  2839  		t.Fatalf("err: %v", err)
  2840  	}
  2841  
  2842  	if !reflect.DeepEqual(eval2, out) {
  2843  		t.Fatalf("bad: %#v %#v", eval2, out)
  2844  	}
  2845  
  2846  	if out.CreateIndex != 1000 {
  2847  		t.Fatalf("bad: %#v", out)
  2848  	}
  2849  	if out.ModifyIndex != 1001 {
  2850  		t.Fatalf("bad: %#v", out)
  2851  	}
  2852  
  2853  	index, err := state.Index("evals")
  2854  	if err != nil {
  2855  		t.Fatalf("err: %v", err)
  2856  	}
  2857  	if index != 1001 {
  2858  		t.Fatalf("bad: %d", index)
  2859  	}
  2860  
  2861  	if watchFired(ws) {
  2862  		t.Fatalf("bad")
  2863  	}
  2864  }
  2865  
  2866  func TestStateStore_UpsertEvals_Eval_ChildJob(t *testing.T) {
  2867  	state := testStateStore(t)
  2868  
  2869  	parent := mock.Job()
  2870  	if err := state.UpsertJob(998, parent); err != nil {
  2871  		t.Fatalf("err: %v", err)
  2872  	}
  2873  
  2874  	child := mock.Job()
  2875  	child.ParentID = parent.ID
  2876  
  2877  	if err := state.UpsertJob(999, child); err != nil {
  2878  		t.Fatalf("err: %v", err)
  2879  	}
  2880  
  2881  	eval := mock.Eval()
  2882  	eval.Status = structs.EvalStatusComplete
  2883  	eval.JobID = child.ID
  2884  
  2885  	// Create watchsets so we can test that upsert fires the watch
  2886  	ws := memdb.NewWatchSet()
  2887  	ws2 := memdb.NewWatchSet()
  2888  	ws3 := memdb.NewWatchSet()
  2889  	if _, err := state.JobSummaryByID(ws, parent.Namespace, parent.ID); err != nil {
  2890  		t.Fatalf("bad: %v", err)
  2891  	}
  2892  	if _, err := state.EvalByID(ws2, eval.ID); err != nil {
  2893  		t.Fatalf("bad: %v", err)
  2894  	}
  2895  	if _, err := state.EvalsByJob(ws3, eval.Namespace, eval.JobID); err != nil {
  2896  		t.Fatalf("bad: %v", err)
  2897  	}
  2898  
  2899  	err := state.UpsertEvals(1000, []*structs.Evaluation{eval})
  2900  	if err != nil {
  2901  		t.Fatalf("err: %v", err)
  2902  	}
  2903  
  2904  	if !watchFired(ws) {
  2905  		t.Fatalf("bad")
  2906  	}
  2907  	if !watchFired(ws2) {
  2908  		t.Fatalf("bad")
  2909  	}
  2910  	if !watchFired(ws3) {
  2911  		t.Fatalf("bad")
  2912  	}
  2913  
  2914  	ws = memdb.NewWatchSet()
  2915  	out, err := state.EvalByID(ws, eval.ID)
  2916  	if err != nil {
  2917  		t.Fatalf("err: %v", err)
  2918  	}
  2919  
  2920  	if !reflect.DeepEqual(eval, out) {
  2921  		t.Fatalf("bad: %#v %#v", eval, out)
  2922  	}
  2923  
  2924  	index, err := state.Index("evals")
  2925  	if err != nil {
  2926  		t.Fatalf("err: %v", err)
  2927  	}
  2928  	if index != 1000 {
  2929  		t.Fatalf("bad: %d", index)
  2930  	}
  2931  
  2932  	summary, err := state.JobSummaryByID(ws, parent.Namespace, parent.ID)
  2933  	if err != nil {
  2934  		t.Fatalf("err: %v", err)
  2935  	}
  2936  	if summary == nil {
  2937  		t.Fatalf("nil summary")
  2938  	}
  2939  	if summary.JobID != parent.ID {
  2940  		t.Fatalf("bad summary id: %v", parent.ID)
  2941  	}
  2942  	if summary.Children == nil {
  2943  		t.Fatalf("nil children summary")
  2944  	}
  2945  	if summary.Children.Pending != 0 || summary.Children.Running != 0 || summary.Children.Dead != 1 {
  2946  		t.Fatalf("bad children summary: %v", summary.Children)
  2947  	}
  2948  
  2949  	if watchFired(ws) {
  2950  		t.Fatalf("bad")
  2951  	}
  2952  }
  2953  
  2954  func TestStateStore_DeleteEval_Eval(t *testing.T) {
  2955  	state := testStateStore(t)
  2956  	eval1 := mock.Eval()
  2957  	eval2 := mock.Eval()
  2958  	alloc1 := mock.Alloc()
  2959  	alloc2 := mock.Alloc()
  2960  
  2961  	// Create watchsets so we can test that upsert fires the watch
  2962  	watches := make([]memdb.WatchSet, 12)
  2963  	for i := 0; i < 12; i++ {
  2964  		watches[i] = memdb.NewWatchSet()
  2965  	}
  2966  	if _, err := state.EvalByID(watches[0], eval1.ID); err != nil {
  2967  		t.Fatalf("bad: %v", err)
  2968  	}
  2969  	if _, err := state.EvalByID(watches[1], eval2.ID); err != nil {
  2970  		t.Fatalf("bad: %v", err)
  2971  	}
  2972  	if _, err := state.EvalsByJob(watches[2], eval1.Namespace, eval1.JobID); err != nil {
  2973  		t.Fatalf("bad: %v", err)
  2974  	}
  2975  	if _, err := state.EvalsByJob(watches[3], eval2.Namespace, eval2.JobID); err != nil {
  2976  		t.Fatalf("bad: %v", err)
  2977  	}
  2978  	if _, err := state.AllocByID(watches[4], alloc1.ID); err != nil {
  2979  		t.Fatalf("bad: %v", err)
  2980  	}
  2981  	if _, err := state.AllocByID(watches[5], alloc2.ID); err != nil {
  2982  		t.Fatalf("bad: %v", err)
  2983  	}
  2984  	if _, err := state.AllocsByEval(watches[6], alloc1.EvalID); err != nil {
  2985  		t.Fatalf("bad: %v", err)
  2986  	}
  2987  	if _, err := state.AllocsByEval(watches[7], alloc2.EvalID); err != nil {
  2988  		t.Fatalf("bad: %v", err)
  2989  	}
  2990  	if _, err := state.AllocsByJob(watches[8], alloc1.Namespace, alloc1.JobID, false); err != nil {
  2991  		t.Fatalf("bad: %v", err)
  2992  	}
  2993  	if _, err := state.AllocsByJob(watches[9], alloc2.Namespace, alloc2.JobID, false); err != nil {
  2994  		t.Fatalf("bad: %v", err)
  2995  	}
  2996  	if _, err := state.AllocsByNode(watches[10], alloc1.NodeID); err != nil {
  2997  		t.Fatalf("bad: %v", err)
  2998  	}
  2999  	if _, err := state.AllocsByNode(watches[11], alloc2.NodeID); err != nil {
  3000  		t.Fatalf("bad: %v", err)
  3001  	}
  3002  
  3003  	state.UpsertJobSummary(900, mock.JobSummary(eval1.JobID))
  3004  	state.UpsertJobSummary(901, mock.JobSummary(eval2.JobID))
  3005  	state.UpsertJobSummary(902, mock.JobSummary(alloc1.JobID))
  3006  	state.UpsertJobSummary(903, mock.JobSummary(alloc2.JobID))
  3007  	err := state.UpsertEvals(1000, []*structs.Evaluation{eval1, eval2})
  3008  	if err != nil {
  3009  		t.Fatalf("err: %v", err)
  3010  	}
  3011  
  3012  	err = state.UpsertAllocs(1001, []*structs.Allocation{alloc1, alloc2})
  3013  	if err != nil {
  3014  		t.Fatalf("err: %v", err)
  3015  	}
  3016  
  3017  	err = state.DeleteEval(1002, []string{eval1.ID, eval2.ID}, []string{alloc1.ID, alloc2.ID})
  3018  	if err != nil {
  3019  		t.Fatalf("err: %v", err)
  3020  	}
  3021  
  3022  	for i, ws := range watches {
  3023  		if !watchFired(ws) {
  3024  			t.Fatalf("bad %d", i)
  3025  		}
  3026  	}
  3027  
  3028  	ws := memdb.NewWatchSet()
  3029  	out, err := state.EvalByID(ws, eval1.ID)
  3030  	if err != nil {
  3031  		t.Fatalf("err: %v", err)
  3032  	}
  3033  
  3034  	if out != nil {
  3035  		t.Fatalf("bad: %#v %#v", eval1, out)
  3036  	}
  3037  
  3038  	out, err = state.EvalByID(ws, eval2.ID)
  3039  	if err != nil {
  3040  		t.Fatalf("err: %v", err)
  3041  	}
  3042  
  3043  	if out != nil {
  3044  		t.Fatalf("bad: %#v %#v", eval1, out)
  3045  	}
  3046  
  3047  	outA, err := state.AllocByID(ws, alloc1.ID)
  3048  	if err != nil {
  3049  		t.Fatalf("err: %v", err)
  3050  	}
  3051  
  3052  	if out != nil {
  3053  		t.Fatalf("bad: %#v %#v", alloc1, outA)
  3054  	}
  3055  
  3056  	outA, err = state.AllocByID(ws, alloc2.ID)
  3057  	if err != nil {
  3058  		t.Fatalf("err: %v", err)
  3059  	}
  3060  
  3061  	if out != nil {
  3062  		t.Fatalf("bad: %#v %#v", alloc1, outA)
  3063  	}
  3064  
  3065  	index, err := state.Index("evals")
  3066  	if err != nil {
  3067  		t.Fatalf("err: %v", err)
  3068  	}
  3069  	if index != 1002 {
  3070  		t.Fatalf("bad: %d", index)
  3071  	}
  3072  
  3073  	index, err = state.Index("allocs")
  3074  	if err != nil {
  3075  		t.Fatalf("err: %v", err)
  3076  	}
  3077  	if index != 1002 {
  3078  		t.Fatalf("bad: %d", index)
  3079  	}
  3080  
  3081  	if watchFired(ws) {
  3082  		t.Fatalf("bad")
  3083  	}
  3084  }
  3085  
  3086  func TestStateStore_DeleteEval_ChildJob(t *testing.T) {
  3087  	state := testStateStore(t)
  3088  
  3089  	parent := mock.Job()
  3090  	if err := state.UpsertJob(998, parent); err != nil {
  3091  		t.Fatalf("err: %v", err)
  3092  	}
  3093  
  3094  	child := mock.Job()
  3095  	child.ParentID = parent.ID
  3096  
  3097  	if err := state.UpsertJob(999, child); err != nil {
  3098  		t.Fatalf("err: %v", err)
  3099  	}
  3100  
  3101  	eval1 := mock.Eval()
  3102  	eval1.JobID = child.ID
  3103  	alloc1 := mock.Alloc()
  3104  	alloc1.JobID = child.ID
  3105  
  3106  	err := state.UpsertEvals(1000, []*structs.Evaluation{eval1})
  3107  	if err != nil {
  3108  		t.Fatalf("err: %v", err)
  3109  	}
  3110  
  3111  	err = state.UpsertAllocs(1001, []*structs.Allocation{alloc1})
  3112  	if err != nil {
  3113  		t.Fatalf("err: %v", err)
  3114  	}
  3115  
  3116  	// Create watchsets so we can test that delete fires the watch
  3117  	ws := memdb.NewWatchSet()
  3118  	if _, err := state.JobSummaryByID(ws, parent.Namespace, parent.ID); err != nil {
  3119  		t.Fatalf("bad: %v", err)
  3120  	}
  3121  
  3122  	err = state.DeleteEval(1002, []string{eval1.ID}, []string{alloc1.ID})
  3123  	if err != nil {
  3124  		t.Fatalf("err: %v", err)
  3125  	}
  3126  
  3127  	if !watchFired(ws) {
  3128  		t.Fatalf("bad")
  3129  	}
  3130  
  3131  	ws = memdb.NewWatchSet()
  3132  	summary, err := state.JobSummaryByID(ws, parent.Namespace, parent.ID)
  3133  	if err != nil {
  3134  		t.Fatalf("err: %v", err)
  3135  	}
  3136  	if summary == nil {
  3137  		t.Fatalf("nil summary")
  3138  	}
  3139  	if summary.JobID != parent.ID {
  3140  		t.Fatalf("bad summary id: %v", parent.ID)
  3141  	}
  3142  	if summary.Children == nil {
  3143  		t.Fatalf("nil children summary")
  3144  	}
  3145  	if summary.Children.Pending != 0 || summary.Children.Running != 0 || summary.Children.Dead != 1 {
  3146  		t.Fatalf("bad children summary: %v", summary.Children)
  3147  	}
  3148  
  3149  	if watchFired(ws) {
  3150  		t.Fatalf("bad")
  3151  	}
  3152  }
  3153  
  3154  func TestStateStore_EvalsByJob(t *testing.T) {
  3155  	state := testStateStore(t)
  3156  
  3157  	eval1 := mock.Eval()
  3158  	eval2 := mock.Eval()
  3159  	eval2.JobID = eval1.JobID
  3160  	eval3 := mock.Eval()
  3161  	evals := []*structs.Evaluation{eval1, eval2}
  3162  
  3163  	err := state.UpsertEvals(1000, evals)
  3164  	if err != nil {
  3165  		t.Fatalf("err: %v", err)
  3166  	}
  3167  	err = state.UpsertEvals(1001, []*structs.Evaluation{eval3})
  3168  	if err != nil {
  3169  		t.Fatalf("err: %v", err)
  3170  	}
  3171  
  3172  	ws := memdb.NewWatchSet()
  3173  	out, err := state.EvalsByJob(ws, eval1.Namespace, eval1.JobID)
  3174  	if err != nil {
  3175  		t.Fatalf("err: %v", err)
  3176  	}
  3177  
  3178  	sort.Sort(EvalIDSort(evals))
  3179  	sort.Sort(EvalIDSort(out))
  3180  
  3181  	if !reflect.DeepEqual(evals, out) {
  3182  		t.Fatalf("bad: %#v %#v", evals, out)
  3183  	}
  3184  
  3185  	if watchFired(ws) {
  3186  		t.Fatalf("bad")
  3187  	}
  3188  }
  3189  
  3190  func TestStateStore_Evals(t *testing.T) {
  3191  	state := testStateStore(t)
  3192  	var evals []*structs.Evaluation
  3193  
  3194  	for i := 0; i < 10; i++ {
  3195  		eval := mock.Eval()
  3196  		evals = append(evals, eval)
  3197  
  3198  		err := state.UpsertEvals(1000+uint64(i), []*structs.Evaluation{eval})
  3199  		if err != nil {
  3200  			t.Fatalf("err: %v", err)
  3201  		}
  3202  	}
  3203  
  3204  	ws := memdb.NewWatchSet()
  3205  	iter, err := state.Evals(ws)
  3206  	if err != nil {
  3207  		t.Fatalf("err: %v", err)
  3208  	}
  3209  
  3210  	var out []*structs.Evaluation
  3211  	for {
  3212  		raw := iter.Next()
  3213  		if raw == nil {
  3214  			break
  3215  		}
  3216  		out = append(out, raw.(*structs.Evaluation))
  3217  	}
  3218  
  3219  	sort.Sort(EvalIDSort(evals))
  3220  	sort.Sort(EvalIDSort(out))
  3221  
  3222  	if !reflect.DeepEqual(evals, out) {
  3223  		t.Fatalf("bad: %#v %#v", evals, out)
  3224  	}
  3225  
  3226  	if watchFired(ws) {
  3227  		t.Fatalf("bad")
  3228  	}
  3229  }
  3230  
  3231  func TestStateStore_EvalsByIDPrefix(t *testing.T) {
  3232  	state := testStateStore(t)
  3233  	var evals []*structs.Evaluation
  3234  
  3235  	ids := []string{
  3236  		"aaaaaaaa-7bfb-395d-eb95-0685af2176b2",
  3237  		"aaaaaaab-7bfb-395d-eb95-0685af2176b2",
  3238  		"aaaaaabb-7bfb-395d-eb95-0685af2176b2",
  3239  		"aaaaabbb-7bfb-395d-eb95-0685af2176b2",
  3240  		"aaaabbbb-7bfb-395d-eb95-0685af2176b2",
  3241  		"aaabbbbb-7bfb-395d-eb95-0685af2176b2",
  3242  		"aabbbbbb-7bfb-395d-eb95-0685af2176b2",
  3243  		"abbbbbbb-7bfb-395d-eb95-0685af2176b2",
  3244  		"bbbbbbbb-7bfb-395d-eb95-0685af2176b2",
  3245  	}
  3246  	for i := 0; i < 9; i++ {
  3247  		eval := mock.Eval()
  3248  		eval.ID = ids[i]
  3249  		evals = append(evals, eval)
  3250  	}
  3251  
  3252  	err := state.UpsertEvals(1000, evals)
  3253  	if err != nil {
  3254  		t.Fatalf("err: %v", err)
  3255  	}
  3256  
  3257  	ws := memdb.NewWatchSet()
  3258  	iter, err := state.EvalsByIDPrefix(ws, structs.DefaultNamespace, "aaaa")
  3259  	if err != nil {
  3260  		t.Fatalf("err: %v", err)
  3261  	}
  3262  
  3263  	gatherEvals := func(iter memdb.ResultIterator) []*structs.Evaluation {
  3264  		var evals []*structs.Evaluation
  3265  		for {
  3266  			raw := iter.Next()
  3267  			if raw == nil {
  3268  				break
  3269  			}
  3270  			evals = append(evals, raw.(*structs.Evaluation))
  3271  		}
  3272  		return evals
  3273  	}
  3274  
  3275  	out := gatherEvals(iter)
  3276  	if len(out) != 5 {
  3277  		t.Fatalf("bad: expected five evaluations, got: %#v", out)
  3278  	}
  3279  
  3280  	sort.Sort(EvalIDSort(evals))
  3281  
  3282  	for index, eval := range out {
  3283  		if ids[index] != eval.ID {
  3284  			t.Fatalf("bad: got unexpected id: %s", eval.ID)
  3285  		}
  3286  	}
  3287  
  3288  	iter, err = state.EvalsByIDPrefix(ws, structs.DefaultNamespace, "b-a7bfb")
  3289  	if err != nil {
  3290  		t.Fatalf("err: %v", err)
  3291  	}
  3292  
  3293  	out = gatherEvals(iter)
  3294  	if len(out) != 0 {
  3295  		t.Fatalf("bad: unexpected zero evaluations, got: %#v", out)
  3296  	}
  3297  
  3298  	if watchFired(ws) {
  3299  		t.Fatalf("bad")
  3300  	}
  3301  }
  3302  
  3303  func TestStateStore_RestoreEval(t *testing.T) {
  3304  	state := testStateStore(t)
  3305  	eval := mock.Eval()
  3306  
  3307  	restore, err := state.Restore()
  3308  	if err != nil {
  3309  		t.Fatalf("err: %v", err)
  3310  	}
  3311  
  3312  	err = restore.EvalRestore(eval)
  3313  	if err != nil {
  3314  		t.Fatalf("err: %v", err)
  3315  	}
  3316  	restore.Commit()
  3317  
  3318  	ws := memdb.NewWatchSet()
  3319  	out, err := state.EvalByID(ws, eval.ID)
  3320  	if err != nil {
  3321  		t.Fatalf("err: %v", err)
  3322  	}
  3323  
  3324  	if !reflect.DeepEqual(out, eval) {
  3325  		t.Fatalf("Bad: %#v %#v", out, eval)
  3326  	}
  3327  }
  3328  
  3329  func TestStateStore_UpdateAllocsFromClient(t *testing.T) {
  3330  	state := testStateStore(t)
  3331  	parent := mock.Job()
  3332  	if err := state.UpsertJob(998, parent); err != nil {
  3333  		t.Fatalf("err: %v", err)
  3334  	}
  3335  
  3336  	child := mock.Job()
  3337  	child.ParentID = parent.ID
  3338  	if err := state.UpsertJob(999, child); err != nil {
  3339  		t.Fatalf("err: %v", err)
  3340  	}
  3341  
  3342  	alloc := mock.Alloc()
  3343  	alloc.JobID = child.ID
  3344  	alloc.Job = child
  3345  
  3346  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  3347  	if err != nil {
  3348  		t.Fatalf("err: %v", err)
  3349  	}
  3350  
  3351  	ws := memdb.NewWatchSet()
  3352  	summary, err := state.JobSummaryByID(ws, parent.Namespace, parent.ID)
  3353  	if err != nil {
  3354  		t.Fatalf("err: %v", err)
  3355  	}
  3356  	if summary == nil {
  3357  		t.Fatalf("nil summary")
  3358  	}
  3359  	if summary.JobID != parent.ID {
  3360  		t.Fatalf("bad summary id: %v", parent.ID)
  3361  	}
  3362  	if summary.Children == nil {
  3363  		t.Fatalf("nil children summary")
  3364  	}
  3365  	if summary.Children.Pending != 0 || summary.Children.Running != 1 || summary.Children.Dead != 0 {
  3366  		t.Fatalf("bad children summary: %v", summary.Children)
  3367  	}
  3368  
  3369  	// Create watchsets so we can test that update fires the watch
  3370  	ws = memdb.NewWatchSet()
  3371  	if _, err := state.JobSummaryByID(ws, parent.Namespace, parent.ID); err != nil {
  3372  		t.Fatalf("bad: %v", err)
  3373  	}
  3374  
  3375  	// Create the delta updates
  3376  	ts := map[string]*structs.TaskState{"web": {State: structs.TaskStateRunning}}
  3377  	update := &structs.Allocation{
  3378  		ID:           alloc.ID,
  3379  		ClientStatus: structs.AllocClientStatusComplete,
  3380  		TaskStates:   ts,
  3381  		JobID:        alloc.JobID,
  3382  		TaskGroup:    alloc.TaskGroup,
  3383  	}
  3384  	err = state.UpdateAllocsFromClient(1001, []*structs.Allocation{update})
  3385  	if err != nil {
  3386  		t.Fatalf("err: %v", err)
  3387  	}
  3388  
  3389  	if !watchFired(ws) {
  3390  		t.Fatalf("bad")
  3391  	}
  3392  
  3393  	ws = memdb.NewWatchSet()
  3394  	summary, err = state.JobSummaryByID(ws, parent.Namespace, parent.ID)
  3395  	if err != nil {
  3396  		t.Fatalf("err: %v", err)
  3397  	}
  3398  	if summary == nil {
  3399  		t.Fatalf("nil summary")
  3400  	}
  3401  	if summary.JobID != parent.ID {
  3402  		t.Fatalf("bad summary id: %v", parent.ID)
  3403  	}
  3404  	if summary.Children == nil {
  3405  		t.Fatalf("nil children summary")
  3406  	}
  3407  	if summary.Children.Pending != 0 || summary.Children.Running != 0 || summary.Children.Dead != 1 {
  3408  		t.Fatalf("bad children summary: %v", summary.Children)
  3409  	}
  3410  
  3411  	if watchFired(ws) {
  3412  		t.Fatalf("bad")
  3413  	}
  3414  }
  3415  
  3416  func TestStateStore_UpdateAllocsFromClient_ChildJob(t *testing.T) {
  3417  	state := testStateStore(t)
  3418  	alloc1 := mock.Alloc()
  3419  	alloc2 := mock.Alloc()
  3420  
  3421  	if err := state.UpsertJob(999, alloc1.Job); err != nil {
  3422  		t.Fatalf("err: %v", err)
  3423  	}
  3424  	if err := state.UpsertJob(999, alloc2.Job); err != nil {
  3425  		t.Fatalf("err: %v", err)
  3426  	}
  3427  
  3428  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc1, alloc2})
  3429  	if err != nil {
  3430  		t.Fatalf("err: %v", err)
  3431  	}
  3432  
  3433  	// Create watchsets so we can test that update fires the watch
  3434  	watches := make([]memdb.WatchSet, 8)
  3435  	for i := 0; i < 8; i++ {
  3436  		watches[i] = memdb.NewWatchSet()
  3437  	}
  3438  	if _, err := state.AllocByID(watches[0], alloc1.ID); err != nil {
  3439  		t.Fatalf("bad: %v", err)
  3440  	}
  3441  	if _, err := state.AllocByID(watches[1], alloc2.ID); err != nil {
  3442  		t.Fatalf("bad: %v", err)
  3443  	}
  3444  	if _, err := state.AllocsByEval(watches[2], alloc1.EvalID); err != nil {
  3445  		t.Fatalf("bad: %v", err)
  3446  	}
  3447  	if _, err := state.AllocsByEval(watches[3], alloc2.EvalID); err != nil {
  3448  		t.Fatalf("bad: %v", err)
  3449  	}
  3450  	if _, err := state.AllocsByJob(watches[4], alloc1.Namespace, alloc1.JobID, false); err != nil {
  3451  		t.Fatalf("bad: %v", err)
  3452  	}
  3453  	if _, err := state.AllocsByJob(watches[5], alloc2.Namespace, alloc2.JobID, false); err != nil {
  3454  		t.Fatalf("bad: %v", err)
  3455  	}
  3456  	if _, err := state.AllocsByNode(watches[6], alloc1.NodeID); err != nil {
  3457  		t.Fatalf("bad: %v", err)
  3458  	}
  3459  	if _, err := state.AllocsByNode(watches[7], alloc2.NodeID); err != nil {
  3460  		t.Fatalf("bad: %v", err)
  3461  	}
  3462  
  3463  	// Create the delta updates
  3464  	ts := map[string]*structs.TaskState{"web": {State: structs.TaskStatePending}}
  3465  	update := &structs.Allocation{
  3466  		ID:           alloc1.ID,
  3467  		ClientStatus: structs.AllocClientStatusFailed,
  3468  		TaskStates:   ts,
  3469  		JobID:        alloc1.JobID,
  3470  		TaskGroup:    alloc1.TaskGroup,
  3471  	}
  3472  	update2 := &structs.Allocation{
  3473  		ID:           alloc2.ID,
  3474  		ClientStatus: structs.AllocClientStatusRunning,
  3475  		TaskStates:   ts,
  3476  		JobID:        alloc2.JobID,
  3477  		TaskGroup:    alloc2.TaskGroup,
  3478  	}
  3479  
  3480  	err = state.UpdateAllocsFromClient(1001, []*structs.Allocation{update, update2})
  3481  	if err != nil {
  3482  		t.Fatalf("err: %v", err)
  3483  	}
  3484  
  3485  	for i, ws := range watches {
  3486  		if !watchFired(ws) {
  3487  			t.Fatalf("bad %d", i)
  3488  		}
  3489  	}
  3490  
  3491  	ws := memdb.NewWatchSet()
  3492  	out, err := state.AllocByID(ws, alloc1.ID)
  3493  	if err != nil {
  3494  		t.Fatalf("err: %v", err)
  3495  	}
  3496  
  3497  	alloc1.CreateIndex = 1000
  3498  	alloc1.ModifyIndex = 1001
  3499  	alloc1.TaskStates = ts
  3500  	alloc1.ClientStatus = structs.AllocClientStatusFailed
  3501  	if !reflect.DeepEqual(alloc1, out) {
  3502  		t.Fatalf("bad: %#v %#v", alloc1, out)
  3503  	}
  3504  
  3505  	out, err = state.AllocByID(ws, alloc2.ID)
  3506  	if err != nil {
  3507  		t.Fatalf("err: %v", err)
  3508  	}
  3509  
  3510  	alloc2.ModifyIndex = 1000
  3511  	alloc2.ModifyIndex = 1001
  3512  	alloc2.ClientStatus = structs.AllocClientStatusRunning
  3513  	alloc2.TaskStates = ts
  3514  	if !reflect.DeepEqual(alloc2, out) {
  3515  		t.Fatalf("bad: %#v %#v", alloc2, out)
  3516  	}
  3517  
  3518  	index, err := state.Index("allocs")
  3519  	if err != nil {
  3520  		t.Fatalf("err: %v", err)
  3521  	}
  3522  	if index != 1001 {
  3523  		t.Fatalf("bad: %d", index)
  3524  	}
  3525  
  3526  	// Ensure summaries have been updated
  3527  	summary, err := state.JobSummaryByID(ws, alloc1.Namespace, alloc1.JobID)
  3528  	if err != nil {
  3529  		t.Fatalf("err: %v", err)
  3530  	}
  3531  	tgSummary := summary.Summary["web"]
  3532  	if tgSummary.Failed != 1 {
  3533  		t.Fatalf("expected failed: %v, actual: %v, summary: %#v", 1, tgSummary.Failed, tgSummary)
  3534  	}
  3535  
  3536  	summary2, err := state.JobSummaryByID(ws, alloc2.Namespace, alloc2.JobID)
  3537  	if err != nil {
  3538  		t.Fatalf("err: %v", err)
  3539  	}
  3540  	tgSummary2 := summary2.Summary["web"]
  3541  	if tgSummary2.Running != 1 {
  3542  		t.Fatalf("expected running: %v, actual: %v", 1, tgSummary2.Running)
  3543  	}
  3544  
  3545  	if watchFired(ws) {
  3546  		t.Fatalf("bad")
  3547  	}
  3548  }
  3549  
  3550  func TestStateStore_UpdateMultipleAllocsFromClient(t *testing.T) {
  3551  	state := testStateStore(t)
  3552  	alloc := mock.Alloc()
  3553  
  3554  	if err := state.UpsertJob(999, alloc.Job); err != nil {
  3555  		t.Fatalf("err: %v", err)
  3556  	}
  3557  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  3558  	if err != nil {
  3559  		t.Fatalf("err: %v", err)
  3560  	}
  3561  
  3562  	// Create the delta updates
  3563  	ts := map[string]*structs.TaskState{"web": {State: structs.TaskStatePending}}
  3564  	update := &structs.Allocation{
  3565  		ID:           alloc.ID,
  3566  		ClientStatus: structs.AllocClientStatusRunning,
  3567  		TaskStates:   ts,
  3568  		JobID:        alloc.JobID,
  3569  		TaskGroup:    alloc.TaskGroup,
  3570  	}
  3571  	update2 := &structs.Allocation{
  3572  		ID:           alloc.ID,
  3573  		ClientStatus: structs.AllocClientStatusPending,
  3574  		TaskStates:   ts,
  3575  		JobID:        alloc.JobID,
  3576  		TaskGroup:    alloc.TaskGroup,
  3577  	}
  3578  
  3579  	err = state.UpdateAllocsFromClient(1001, []*structs.Allocation{update, update2})
  3580  	if err != nil {
  3581  		t.Fatalf("err: %v", err)
  3582  	}
  3583  
  3584  	ws := memdb.NewWatchSet()
  3585  	out, err := state.AllocByID(ws, alloc.ID)
  3586  	if err != nil {
  3587  		t.Fatalf("err: %v", err)
  3588  	}
  3589  
  3590  	alloc.CreateIndex = 1000
  3591  	alloc.ModifyIndex = 1001
  3592  	alloc.TaskStates = ts
  3593  	alloc.ClientStatus = structs.AllocClientStatusPending
  3594  	if !reflect.DeepEqual(alloc, out) {
  3595  		t.Fatalf("bad: %#v , actual:%#v", alloc, out)
  3596  	}
  3597  
  3598  	summary, err := state.JobSummaryByID(ws, alloc.Namespace, alloc.JobID)
  3599  	expectedSummary := &structs.JobSummary{
  3600  		JobID:     alloc.JobID,
  3601  		Namespace: alloc.Namespace,
  3602  		Summary: map[string]structs.TaskGroupSummary{
  3603  			"web": {
  3604  				Starting: 1,
  3605  			},
  3606  		},
  3607  		Children:    new(structs.JobChildrenSummary),
  3608  		CreateIndex: 999,
  3609  		ModifyIndex: 1001,
  3610  	}
  3611  	if err != nil {
  3612  		t.Fatalf("err: %v", err)
  3613  	}
  3614  	if !reflect.DeepEqual(summary, expectedSummary) {
  3615  		t.Fatalf("expected: %#v, actual: %#v", expectedSummary, summary)
  3616  	}
  3617  }
  3618  
  3619  func TestStateStore_UpdateAllocsFromClient_Deployment(t *testing.T) {
  3620  	require := require.New(t)
  3621  	state := testStateStore(t)
  3622  
  3623  	alloc := mock.Alloc()
  3624  	now := time.Now()
  3625  	alloc.CreateTime = now.UnixNano()
  3626  	pdeadline := 5 * time.Minute
  3627  	deployment := mock.Deployment()
  3628  	deployment.TaskGroups[alloc.TaskGroup].ProgressDeadline = pdeadline
  3629  	alloc.DeploymentID = deployment.ID
  3630  
  3631  	require.Nil(state.UpsertJob(999, alloc.Job))
  3632  	require.Nil(state.UpsertDeployment(1000, deployment))
  3633  	require.Nil(state.UpsertAllocs(1001, []*structs.Allocation{alloc}))
  3634  
  3635  	healthy := now.Add(time.Second)
  3636  	update := &structs.Allocation{
  3637  		ID:           alloc.ID,
  3638  		ClientStatus: structs.AllocClientStatusRunning,
  3639  		JobID:        alloc.JobID,
  3640  		TaskGroup:    alloc.TaskGroup,
  3641  		DeploymentStatus: &structs.AllocDeploymentStatus{
  3642  			Healthy:   helper.BoolToPtr(true),
  3643  			Timestamp: healthy,
  3644  		},
  3645  	}
  3646  	require.Nil(state.UpdateAllocsFromClient(1001, []*structs.Allocation{update}))
  3647  
  3648  	// Check that the deployment state was updated because the healthy
  3649  	// deployment
  3650  	dout, err := state.DeploymentByID(nil, deployment.ID)
  3651  	require.Nil(err)
  3652  	require.NotNil(dout)
  3653  	require.Len(dout.TaskGroups, 1)
  3654  	dstate := dout.TaskGroups[alloc.TaskGroup]
  3655  	require.NotNil(dstate)
  3656  	require.Equal(1, dstate.PlacedAllocs)
  3657  	require.True(healthy.Add(pdeadline).Equal(dstate.RequireProgressBy))
  3658  }
  3659  
  3660  // This tests that the deployment state is merged correctly
  3661  func TestStateStore_UpdateAllocsFromClient_DeploymentStateMerges(t *testing.T) {
  3662  	require := require.New(t)
  3663  	state := testStateStore(t)
  3664  
  3665  	alloc := mock.Alloc()
  3666  	now := time.Now()
  3667  	alloc.CreateTime = now.UnixNano()
  3668  	pdeadline := 5 * time.Minute
  3669  	deployment := mock.Deployment()
  3670  	deployment.TaskGroups[alloc.TaskGroup].ProgressDeadline = pdeadline
  3671  	alloc.DeploymentID = deployment.ID
  3672  	alloc.DeploymentStatus = &structs.AllocDeploymentStatus{
  3673  		Canary: true,
  3674  	}
  3675  
  3676  	require.Nil(state.UpsertJob(999, alloc.Job))
  3677  	require.Nil(state.UpsertDeployment(1000, deployment))
  3678  	require.Nil(state.UpsertAllocs(1001, []*structs.Allocation{alloc}))
  3679  
  3680  	update := &structs.Allocation{
  3681  		ID:           alloc.ID,
  3682  		ClientStatus: structs.AllocClientStatusRunning,
  3683  		JobID:        alloc.JobID,
  3684  		TaskGroup:    alloc.TaskGroup,
  3685  		DeploymentStatus: &structs.AllocDeploymentStatus{
  3686  			Healthy: helper.BoolToPtr(true),
  3687  			Canary:  false,
  3688  		},
  3689  	}
  3690  	require.Nil(state.UpdateAllocsFromClient(1001, []*structs.Allocation{update}))
  3691  
  3692  	// Check that the merging of the deployment status was correct
  3693  	out, err := state.AllocByID(nil, alloc.ID)
  3694  	require.Nil(err)
  3695  	require.NotNil(out)
  3696  	require.True(out.DeploymentStatus.Canary)
  3697  	require.NotNil(out.DeploymentStatus.Healthy)
  3698  	require.True(*out.DeploymentStatus.Healthy)
  3699  }
  3700  
  3701  func TestStateStore_UpsertAlloc_Alloc(t *testing.T) {
  3702  	state := testStateStore(t)
  3703  	alloc := mock.Alloc()
  3704  
  3705  	if err := state.UpsertJob(999, alloc.Job); err != nil {
  3706  		t.Fatalf("err: %v", err)
  3707  	}
  3708  
  3709  	// Create watchsets so we can test that update fires the watch
  3710  	watches := make([]memdb.WatchSet, 4)
  3711  	for i := 0; i < 4; i++ {
  3712  		watches[i] = memdb.NewWatchSet()
  3713  	}
  3714  	if _, err := state.AllocByID(watches[0], alloc.ID); err != nil {
  3715  		t.Fatalf("bad: %v", err)
  3716  	}
  3717  	if _, err := state.AllocsByEval(watches[1], alloc.EvalID); err != nil {
  3718  		t.Fatalf("bad: %v", err)
  3719  	}
  3720  	if _, err := state.AllocsByJob(watches[2], alloc.Namespace, alloc.JobID, false); err != nil {
  3721  		t.Fatalf("bad: %v", err)
  3722  	}
  3723  	if _, err := state.AllocsByNode(watches[3], alloc.NodeID); err != nil {
  3724  		t.Fatalf("bad: %v", err)
  3725  	}
  3726  
  3727  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  3728  	if err != nil {
  3729  		t.Fatalf("err: %v", err)
  3730  	}
  3731  
  3732  	for i, ws := range watches {
  3733  		if !watchFired(ws) {
  3734  			t.Fatalf("bad %d", i)
  3735  		}
  3736  	}
  3737  
  3738  	ws := memdb.NewWatchSet()
  3739  	out, err := state.AllocByID(ws, alloc.ID)
  3740  	if err != nil {
  3741  		t.Fatalf("err: %v", err)
  3742  	}
  3743  
  3744  	if !reflect.DeepEqual(alloc, out) {
  3745  		t.Fatalf("bad: %#v %#v", alloc, out)
  3746  	}
  3747  
  3748  	index, err := state.Index("allocs")
  3749  	if err != nil {
  3750  		t.Fatalf("err: %v", err)
  3751  	}
  3752  	if index != 1000 {
  3753  		t.Fatalf("bad: %d", index)
  3754  	}
  3755  
  3756  	summary, err := state.JobSummaryByID(ws, alloc.Namespace, alloc.JobID)
  3757  	if err != nil {
  3758  		t.Fatalf("err: %v", err)
  3759  	}
  3760  
  3761  	tgSummary, ok := summary.Summary["web"]
  3762  	if !ok {
  3763  		t.Fatalf("no summary for task group web")
  3764  	}
  3765  	if tgSummary.Starting != 1 {
  3766  		t.Fatalf("expected queued: %v, actual: %v", 1, tgSummary.Starting)
  3767  	}
  3768  
  3769  	if watchFired(ws) {
  3770  		t.Fatalf("bad")
  3771  	}
  3772  }
  3773  
  3774  func TestStateStore_UpsertAlloc_Deployment(t *testing.T) {
  3775  	require := require.New(t)
  3776  	state := testStateStore(t)
  3777  	alloc := mock.Alloc()
  3778  	now := time.Now()
  3779  	alloc.CreateTime = now.UnixNano()
  3780  	alloc.ModifyTime = now.UnixNano()
  3781  	pdeadline := 5 * time.Minute
  3782  	deployment := mock.Deployment()
  3783  	deployment.TaskGroups[alloc.TaskGroup].ProgressDeadline = pdeadline
  3784  	alloc.DeploymentID = deployment.ID
  3785  
  3786  	require.Nil(state.UpsertJob(999, alloc.Job))
  3787  	require.Nil(state.UpsertDeployment(1000, deployment))
  3788  
  3789  	// Create a watch set so we can test that update fires the watch
  3790  	ws := memdb.NewWatchSet()
  3791  	require.Nil(state.AllocsByDeployment(ws, alloc.DeploymentID))
  3792  
  3793  	err := state.UpsertAllocs(1001, []*structs.Allocation{alloc})
  3794  	require.Nil(err)
  3795  
  3796  	if !watchFired(ws) {
  3797  		t.Fatalf("watch not fired")
  3798  	}
  3799  
  3800  	ws = memdb.NewWatchSet()
  3801  	allocs, err := state.AllocsByDeployment(ws, alloc.DeploymentID)
  3802  	require.Nil(err)
  3803  	require.Len(allocs, 1)
  3804  	require.EqualValues(alloc, allocs[0])
  3805  
  3806  	index, err := state.Index("allocs")
  3807  	require.Nil(err)
  3808  	require.EqualValues(1001, index)
  3809  	if watchFired(ws) {
  3810  		t.Fatalf("bad")
  3811  	}
  3812  
  3813  	// Check that the deployment state was updated
  3814  	dout, err := state.DeploymentByID(nil, deployment.ID)
  3815  	require.Nil(err)
  3816  	require.NotNil(dout)
  3817  	require.Len(dout.TaskGroups, 1)
  3818  	dstate := dout.TaskGroups[alloc.TaskGroup]
  3819  	require.NotNil(dstate)
  3820  	require.Equal(1, dstate.PlacedAllocs)
  3821  	require.True(now.Add(pdeadline).Equal(dstate.RequireProgressBy))
  3822  }
  3823  
  3824  // Testing to ensure we keep issue
  3825  // https://github.com/hashicorp/nomad/issues/2583 fixed
  3826  func TestStateStore_UpsertAlloc_No_Job(t *testing.T) {
  3827  	state := testStateStore(t)
  3828  	alloc := mock.Alloc()
  3829  	alloc.Job = nil
  3830  
  3831  	err := state.UpsertAllocs(999, []*structs.Allocation{alloc})
  3832  	if err == nil || !strings.Contains(err.Error(), "without a job") {
  3833  		t.Fatalf("expect err: %v", err)
  3834  	}
  3835  }
  3836  
  3837  func TestStateStore_UpsertAlloc_NoEphemeralDisk(t *testing.T) {
  3838  	state := testStateStore(t)
  3839  	alloc := mock.Alloc()
  3840  	alloc.Job.TaskGroups[0].EphemeralDisk = nil
  3841  	alloc.Job.TaskGroups[0].Tasks[0].Resources.DiskMB = 120
  3842  
  3843  	if err := state.UpsertJob(999, alloc.Job); err != nil {
  3844  		t.Fatalf("err: %v", err)
  3845  	}
  3846  
  3847  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  3848  	if err != nil {
  3849  		t.Fatalf("err: %v", err)
  3850  	}
  3851  
  3852  	ws := memdb.NewWatchSet()
  3853  	out, err := state.AllocByID(ws, alloc.ID)
  3854  	if err != nil {
  3855  		t.Fatalf("err: %v", err)
  3856  	}
  3857  
  3858  	expected := alloc.Copy()
  3859  	expected.Job.TaskGroups[0].EphemeralDisk = &structs.EphemeralDisk{SizeMB: 120}
  3860  	if !reflect.DeepEqual(expected, out) {
  3861  		t.Fatalf("bad: %#v %#v", expected, out)
  3862  	}
  3863  }
  3864  
  3865  func TestStateStore_UpsertAlloc_ChildJob(t *testing.T) {
  3866  	state := testStateStore(t)
  3867  
  3868  	parent := mock.Job()
  3869  	if err := state.UpsertJob(998, parent); err != nil {
  3870  		t.Fatalf("err: %v", err)
  3871  	}
  3872  
  3873  	child := mock.Job()
  3874  	child.ParentID = parent.ID
  3875  
  3876  	if err := state.UpsertJob(999, child); err != nil {
  3877  		t.Fatalf("err: %v", err)
  3878  	}
  3879  
  3880  	alloc := mock.Alloc()
  3881  	alloc.JobID = child.ID
  3882  	alloc.Job = child
  3883  
  3884  	// Create watchsets so we can test that delete fires the watch
  3885  	ws := memdb.NewWatchSet()
  3886  	if _, err := state.JobSummaryByID(ws, parent.Namespace, parent.ID); err != nil {
  3887  		t.Fatalf("bad: %v", err)
  3888  	}
  3889  
  3890  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  3891  	if err != nil {
  3892  		t.Fatalf("err: %v", err)
  3893  	}
  3894  
  3895  	if !watchFired(ws) {
  3896  		t.Fatalf("bad")
  3897  	}
  3898  
  3899  	ws = memdb.NewWatchSet()
  3900  	summary, err := state.JobSummaryByID(ws, parent.Namespace, parent.ID)
  3901  	if err != nil {
  3902  		t.Fatalf("err: %v", err)
  3903  	}
  3904  	if summary == nil {
  3905  		t.Fatalf("nil summary")
  3906  	}
  3907  	if summary.JobID != parent.ID {
  3908  		t.Fatalf("bad summary id: %v", parent.ID)
  3909  	}
  3910  	if summary.Children == nil {
  3911  		t.Fatalf("nil children summary")
  3912  	}
  3913  	if summary.Children.Pending != 0 || summary.Children.Running != 1 || summary.Children.Dead != 0 {
  3914  		t.Fatalf("bad children summary: %v", summary.Children)
  3915  	}
  3916  
  3917  	if watchFired(ws) {
  3918  		t.Fatalf("bad")
  3919  	}
  3920  }
  3921  
  3922  func TestStateStore_UpdateAlloc_Alloc(t *testing.T) {
  3923  	state := testStateStore(t)
  3924  	alloc := mock.Alloc()
  3925  
  3926  	if err := state.UpsertJob(999, alloc.Job); err != nil {
  3927  		t.Fatalf("err: %v", err)
  3928  	}
  3929  
  3930  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  3931  	if err != nil {
  3932  		t.Fatalf("err: %v", err)
  3933  	}
  3934  
  3935  	ws := memdb.NewWatchSet()
  3936  	summary, err := state.JobSummaryByID(ws, alloc.Namespace, alloc.JobID)
  3937  	if err != nil {
  3938  		t.Fatalf("err: %v", err)
  3939  	}
  3940  	tgSummary := summary.Summary["web"]
  3941  	if tgSummary.Starting != 1 {
  3942  		t.Fatalf("expected starting: %v, actual: %v", 1, tgSummary.Starting)
  3943  	}
  3944  
  3945  	alloc2 := mock.Alloc()
  3946  	alloc2.ID = alloc.ID
  3947  	alloc2.NodeID = alloc.NodeID + ".new"
  3948  	state.UpsertJobSummary(1001, mock.JobSummary(alloc2.JobID))
  3949  
  3950  	// Create watchsets so we can test that update fires the watch
  3951  	watches := make([]memdb.WatchSet, 4)
  3952  	for i := 0; i < 4; i++ {
  3953  		watches[i] = memdb.NewWatchSet()
  3954  	}
  3955  	if _, err := state.AllocByID(watches[0], alloc2.ID); err != nil {
  3956  		t.Fatalf("bad: %v", err)
  3957  	}
  3958  	if _, err := state.AllocsByEval(watches[1], alloc2.EvalID); err != nil {
  3959  		t.Fatalf("bad: %v", err)
  3960  	}
  3961  	if _, err := state.AllocsByJob(watches[2], alloc2.Namespace, alloc2.JobID, false); err != nil {
  3962  		t.Fatalf("bad: %v", err)
  3963  	}
  3964  	if _, err := state.AllocsByNode(watches[3], alloc2.NodeID); err != nil {
  3965  		t.Fatalf("bad: %v", err)
  3966  	}
  3967  
  3968  	err = state.UpsertAllocs(1002, []*structs.Allocation{alloc2})
  3969  	if err != nil {
  3970  		t.Fatalf("err: %v", err)
  3971  	}
  3972  
  3973  	for i, ws := range watches {
  3974  		if !watchFired(ws) {
  3975  			t.Fatalf("bad %d", i)
  3976  		}
  3977  	}
  3978  
  3979  	ws = memdb.NewWatchSet()
  3980  	out, err := state.AllocByID(ws, alloc.ID)
  3981  	if err != nil {
  3982  		t.Fatalf("err: %v", err)
  3983  	}
  3984  
  3985  	if !reflect.DeepEqual(alloc2, out) {
  3986  		t.Fatalf("bad: %#v %#v", alloc2, out)
  3987  	}
  3988  
  3989  	if out.CreateIndex != 1000 {
  3990  		t.Fatalf("bad: %#v", out)
  3991  	}
  3992  	if out.ModifyIndex != 1002 {
  3993  		t.Fatalf("bad: %#v", out)
  3994  	}
  3995  
  3996  	index, err := state.Index("allocs")
  3997  	if err != nil {
  3998  		t.Fatalf("err: %v", err)
  3999  	}
  4000  	if index != 1002 {
  4001  		t.Fatalf("bad: %d", index)
  4002  	}
  4003  
  4004  	// Ensure that summary hasb't changed
  4005  	summary, err = state.JobSummaryByID(ws, alloc.Namespace, alloc.JobID)
  4006  	if err != nil {
  4007  		t.Fatalf("err: %v", err)
  4008  	}
  4009  	tgSummary = summary.Summary["web"]
  4010  	if tgSummary.Starting != 1 {
  4011  		t.Fatalf("expected starting: %v, actual: %v", 1, tgSummary.Starting)
  4012  	}
  4013  
  4014  	if watchFired(ws) {
  4015  		t.Fatalf("bad")
  4016  	}
  4017  }
  4018  
  4019  // This test ensures that the state store will mark the clients status as lost
  4020  // when set rather than preferring the existing status.
  4021  func TestStateStore_UpdateAlloc_Lost(t *testing.T) {
  4022  	state := testStateStore(t)
  4023  	alloc := mock.Alloc()
  4024  	alloc.ClientStatus = "foo"
  4025  
  4026  	if err := state.UpsertJob(999, alloc.Job); err != nil {
  4027  		t.Fatalf("err: %v", err)
  4028  	}
  4029  
  4030  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  4031  	if err != nil {
  4032  		t.Fatalf("err: %v", err)
  4033  	}
  4034  
  4035  	alloc2 := new(structs.Allocation)
  4036  	*alloc2 = *alloc
  4037  	alloc2.ClientStatus = structs.AllocClientStatusLost
  4038  	if err := state.UpsertAllocs(1001, []*structs.Allocation{alloc2}); err != nil {
  4039  		t.Fatalf("err: %v", err)
  4040  	}
  4041  
  4042  	ws := memdb.NewWatchSet()
  4043  	out, err := state.AllocByID(ws, alloc2.ID)
  4044  	if err != nil {
  4045  		t.Fatalf("err: %v", err)
  4046  	}
  4047  
  4048  	if out.ClientStatus != structs.AllocClientStatusLost {
  4049  		t.Fatalf("bad: %#v", out)
  4050  	}
  4051  }
  4052  
  4053  // This test ensures an allocation can be updated when there is no job
  4054  // associated with it. This will happen when a job is stopped by an user which
  4055  // has non-terminal allocations on clients
  4056  func TestStateStore_UpdateAlloc_NoJob(t *testing.T) {
  4057  	state := testStateStore(t)
  4058  	alloc := mock.Alloc()
  4059  
  4060  	// Upsert a job
  4061  	state.UpsertJobSummary(998, mock.JobSummary(alloc.JobID))
  4062  	if err := state.UpsertJob(999, alloc.Job); err != nil {
  4063  		t.Fatalf("err: %v", err)
  4064  	}
  4065  
  4066  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  4067  	if err != nil {
  4068  		t.Fatalf("err: %v", err)
  4069  	}
  4070  
  4071  	if err := state.DeleteJob(1001, alloc.Namespace, alloc.JobID); err != nil {
  4072  		t.Fatalf("err: %v", err)
  4073  	}
  4074  
  4075  	// Update the desired state of the allocation to stop
  4076  	allocCopy := alloc.Copy()
  4077  	allocCopy.DesiredStatus = structs.AllocDesiredStatusStop
  4078  	if err := state.UpsertAllocs(1002, []*structs.Allocation{allocCopy}); err != nil {
  4079  		t.Fatalf("err: %v", err)
  4080  	}
  4081  
  4082  	// Update the client state of the allocation to complete
  4083  	allocCopy1 := allocCopy.Copy()
  4084  	allocCopy1.ClientStatus = structs.AllocClientStatusComplete
  4085  	if err := state.UpdateAllocsFromClient(1003, []*structs.Allocation{allocCopy1}); err != nil {
  4086  		t.Fatalf("err: %v", err)
  4087  	}
  4088  
  4089  	ws := memdb.NewWatchSet()
  4090  	out, _ := state.AllocByID(ws, alloc.ID)
  4091  	// Update the modify index of the alloc before comparing
  4092  	allocCopy1.ModifyIndex = 1003
  4093  	if !reflect.DeepEqual(out, allocCopy1) {
  4094  		t.Fatalf("expected: %#v \n actual: %#v", allocCopy1, out)
  4095  	}
  4096  }
  4097  
  4098  func TestStateStore_UpdateAllocDesiredTransition(t *testing.T) {
  4099  	t.Parallel()
  4100  	require := require.New(t)
  4101  
  4102  	state := testStateStore(t)
  4103  	alloc := mock.Alloc()
  4104  
  4105  	require.Nil(state.UpsertJob(999, alloc.Job))
  4106  	require.Nil(state.UpsertAllocs(1000, []*structs.Allocation{alloc}))
  4107  
  4108  	t1 := &structs.DesiredTransition{
  4109  		Migrate: helper.BoolToPtr(true),
  4110  	}
  4111  	t2 := &structs.DesiredTransition{
  4112  		Migrate: helper.BoolToPtr(false),
  4113  	}
  4114  	eval := &structs.Evaluation{
  4115  		ID:             uuid.Generate(),
  4116  		Namespace:      alloc.Namespace,
  4117  		Priority:       alloc.Job.Priority,
  4118  		Type:           alloc.Job.Type,
  4119  		TriggeredBy:    structs.EvalTriggerNodeDrain,
  4120  		JobID:          alloc.Job.ID,
  4121  		JobModifyIndex: alloc.Job.ModifyIndex,
  4122  		Status:         structs.EvalStatusPending,
  4123  	}
  4124  	evals := []*structs.Evaluation{eval}
  4125  
  4126  	m := map[string]*structs.DesiredTransition{alloc.ID: t1}
  4127  	require.Nil(state.UpdateAllocsDesiredTransitions(1001, m, evals))
  4128  
  4129  	ws := memdb.NewWatchSet()
  4130  	out, err := state.AllocByID(ws, alloc.ID)
  4131  	require.Nil(err)
  4132  	require.NotNil(out.DesiredTransition.Migrate)
  4133  	require.True(*out.DesiredTransition.Migrate)
  4134  	require.EqualValues(1000, out.CreateIndex)
  4135  	require.EqualValues(1001, out.ModifyIndex)
  4136  
  4137  	index, err := state.Index("allocs")
  4138  	require.Nil(err)
  4139  	require.EqualValues(1001, index)
  4140  
  4141  	// Check the eval is created
  4142  	eout, err := state.EvalByID(nil, eval.ID)
  4143  	require.Nil(err)
  4144  	require.NotNil(eout)
  4145  
  4146  	m = map[string]*structs.DesiredTransition{alloc.ID: t2}
  4147  	require.Nil(state.UpdateAllocsDesiredTransitions(1002, m, evals))
  4148  
  4149  	ws = memdb.NewWatchSet()
  4150  	out, err = state.AllocByID(ws, alloc.ID)
  4151  	require.Nil(err)
  4152  	require.NotNil(out.DesiredTransition.Migrate)
  4153  	require.False(*out.DesiredTransition.Migrate)
  4154  	require.EqualValues(1000, out.CreateIndex)
  4155  	require.EqualValues(1002, out.ModifyIndex)
  4156  
  4157  	index, err = state.Index("allocs")
  4158  	require.Nil(err)
  4159  	require.EqualValues(1002, index)
  4160  
  4161  	// Try with a bogus alloc id
  4162  	m = map[string]*structs.DesiredTransition{uuid.Generate(): t2}
  4163  	require.Nil(state.UpdateAllocsDesiredTransitions(1003, m, evals))
  4164  }
  4165  
  4166  func TestStateStore_JobSummary(t *testing.T) {
  4167  	state := testStateStore(t)
  4168  
  4169  	// Add a job
  4170  	job := mock.Job()
  4171  	state.UpsertJob(900, job)
  4172  
  4173  	// Get the job back
  4174  	ws := memdb.NewWatchSet()
  4175  	outJob, _ := state.JobByID(ws, job.Namespace, job.ID)
  4176  	if outJob.CreateIndex != 900 {
  4177  		t.Fatalf("bad create index: %v", outJob.CreateIndex)
  4178  	}
  4179  	summary, _ := state.JobSummaryByID(ws, job.Namespace, job.ID)
  4180  	if summary.CreateIndex != 900 {
  4181  		t.Fatalf("bad create index: %v", summary.CreateIndex)
  4182  	}
  4183  
  4184  	// Upsert an allocation
  4185  	alloc := mock.Alloc()
  4186  	alloc.JobID = job.ID
  4187  	alloc.Job = job
  4188  	state.UpsertAllocs(910, []*structs.Allocation{alloc})
  4189  
  4190  	// Update the alloc from client
  4191  	alloc1 := alloc.Copy()
  4192  	alloc1.ClientStatus = structs.AllocClientStatusPending
  4193  	alloc1.DesiredStatus = ""
  4194  	state.UpdateAllocsFromClient(920, []*structs.Allocation{alloc})
  4195  
  4196  	alloc3 := alloc.Copy()
  4197  	alloc3.ClientStatus = structs.AllocClientStatusRunning
  4198  	alloc3.DesiredStatus = ""
  4199  	state.UpdateAllocsFromClient(930, []*structs.Allocation{alloc3})
  4200  
  4201  	// Upsert the alloc
  4202  	alloc4 := alloc.Copy()
  4203  	alloc4.ClientStatus = structs.AllocClientStatusPending
  4204  	alloc4.DesiredStatus = structs.AllocDesiredStatusRun
  4205  	state.UpsertAllocs(950, []*structs.Allocation{alloc4})
  4206  
  4207  	// Again upsert the alloc
  4208  	alloc5 := alloc.Copy()
  4209  	alloc5.ClientStatus = structs.AllocClientStatusPending
  4210  	alloc5.DesiredStatus = structs.AllocDesiredStatusRun
  4211  	state.UpsertAllocs(970, []*structs.Allocation{alloc5})
  4212  
  4213  	if !watchFired(ws) {
  4214  		t.Fatalf("bad")
  4215  	}
  4216  
  4217  	expectedSummary := structs.JobSummary{
  4218  		JobID:     job.ID,
  4219  		Namespace: job.Namespace,
  4220  		Summary: map[string]structs.TaskGroupSummary{
  4221  			"web": {
  4222  				Running: 1,
  4223  			},
  4224  		},
  4225  		Children:    new(structs.JobChildrenSummary),
  4226  		CreateIndex: 900,
  4227  		ModifyIndex: 930,
  4228  	}
  4229  
  4230  	summary, _ = state.JobSummaryByID(ws, job.Namespace, job.ID)
  4231  	if !reflect.DeepEqual(&expectedSummary, summary) {
  4232  		t.Fatalf("expected: %#v, actual: %v", expectedSummary, summary)
  4233  	}
  4234  
  4235  	// De-register the job.
  4236  	state.DeleteJob(980, job.Namespace, job.ID)
  4237  
  4238  	// Shouldn't have any effect on the summary
  4239  	alloc6 := alloc.Copy()
  4240  	alloc6.ClientStatus = structs.AllocClientStatusRunning
  4241  	alloc6.DesiredStatus = ""
  4242  	state.UpdateAllocsFromClient(990, []*structs.Allocation{alloc6})
  4243  
  4244  	// We shouldn't have any summary at this point
  4245  	summary, _ = state.JobSummaryByID(ws, job.Namespace, job.ID)
  4246  	if summary != nil {
  4247  		t.Fatalf("expected nil, actual: %#v", summary)
  4248  	}
  4249  
  4250  	// Re-register the same job
  4251  	job1 := mock.Job()
  4252  	job1.ID = job.ID
  4253  	state.UpsertJob(1000, job1)
  4254  	outJob2, _ := state.JobByID(ws, job1.Namespace, job1.ID)
  4255  	if outJob2.CreateIndex != 1000 {
  4256  		t.Fatalf("bad create index: %v", outJob2.CreateIndex)
  4257  	}
  4258  	summary, _ = state.JobSummaryByID(ws, job1.Namespace, job1.ID)
  4259  	if summary.CreateIndex != 1000 {
  4260  		t.Fatalf("bad create index: %v", summary.CreateIndex)
  4261  	}
  4262  
  4263  	// Upsert an allocation
  4264  	alloc7 := alloc.Copy()
  4265  	alloc7.JobID = outJob.ID
  4266  	alloc7.Job = outJob
  4267  	alloc7.ClientStatus = structs.AllocClientStatusComplete
  4268  	alloc7.DesiredStatus = structs.AllocDesiredStatusRun
  4269  	state.UpdateAllocsFromClient(1020, []*structs.Allocation{alloc7})
  4270  
  4271  	expectedSummary = structs.JobSummary{
  4272  		JobID:     job.ID,
  4273  		Namespace: job.Namespace,
  4274  		Summary: map[string]structs.TaskGroupSummary{
  4275  			"web": {},
  4276  		},
  4277  		Children:    new(structs.JobChildrenSummary),
  4278  		CreateIndex: 1000,
  4279  		ModifyIndex: 1000,
  4280  	}
  4281  
  4282  	summary, _ = state.JobSummaryByID(ws, job1.Namespace, job1.ID)
  4283  	if !reflect.DeepEqual(&expectedSummary, summary) {
  4284  		t.Fatalf("expected: %#v, actual: %#v", expectedSummary, summary)
  4285  	}
  4286  }
  4287  
  4288  func TestStateStore_ReconcileJobSummary(t *testing.T) {
  4289  	state := testStateStore(t)
  4290  
  4291  	// Create an alloc
  4292  	alloc := mock.Alloc()
  4293  
  4294  	// Add another task group to the job
  4295  	tg2 := alloc.Job.TaskGroups[0].Copy()
  4296  	tg2.Name = "db"
  4297  	alloc.Job.TaskGroups = append(alloc.Job.TaskGroups, tg2)
  4298  	state.UpsertJob(100, alloc.Job)
  4299  
  4300  	// Create one more alloc for the db task group
  4301  	alloc2 := mock.Alloc()
  4302  	alloc2.TaskGroup = "db"
  4303  	alloc2.JobID = alloc.JobID
  4304  	alloc2.Job = alloc.Job
  4305  
  4306  	// Upserts the alloc
  4307  	state.UpsertAllocs(110, []*structs.Allocation{alloc, alloc2})
  4308  
  4309  	// Change the state of the first alloc to running
  4310  	alloc3 := alloc.Copy()
  4311  	alloc3.ClientStatus = structs.AllocClientStatusRunning
  4312  	state.UpdateAllocsFromClient(120, []*structs.Allocation{alloc3})
  4313  
  4314  	//Add some more allocs to the second tg
  4315  	alloc4 := mock.Alloc()
  4316  	alloc4.JobID = alloc.JobID
  4317  	alloc4.Job = alloc.Job
  4318  	alloc4.TaskGroup = "db"
  4319  	alloc5 := alloc4.Copy()
  4320  	alloc5.ClientStatus = structs.AllocClientStatusRunning
  4321  
  4322  	alloc6 := mock.Alloc()
  4323  	alloc6.JobID = alloc.JobID
  4324  	alloc6.Job = alloc.Job
  4325  	alloc6.TaskGroup = "db"
  4326  	alloc7 := alloc6.Copy()
  4327  	alloc7.ClientStatus = structs.AllocClientStatusComplete
  4328  
  4329  	alloc8 := mock.Alloc()
  4330  	alloc8.JobID = alloc.JobID
  4331  	alloc8.Job = alloc.Job
  4332  	alloc8.TaskGroup = "db"
  4333  	alloc9 := alloc8.Copy()
  4334  	alloc9.ClientStatus = structs.AllocClientStatusFailed
  4335  
  4336  	alloc10 := mock.Alloc()
  4337  	alloc10.JobID = alloc.JobID
  4338  	alloc10.Job = alloc.Job
  4339  	alloc10.TaskGroup = "db"
  4340  	alloc11 := alloc10.Copy()
  4341  	alloc11.ClientStatus = structs.AllocClientStatusLost
  4342  
  4343  	state.UpsertAllocs(130, []*structs.Allocation{alloc4, alloc6, alloc8, alloc10})
  4344  
  4345  	state.UpdateAllocsFromClient(150, []*structs.Allocation{alloc5, alloc7, alloc9, alloc11})
  4346  
  4347  	// DeleteJobSummary is a helper method and doesn't modify the indexes table
  4348  	state.DeleteJobSummary(130, alloc.Namespace, alloc.Job.ID)
  4349  
  4350  	state.ReconcileJobSummaries(120)
  4351  
  4352  	ws := memdb.NewWatchSet()
  4353  	summary, _ := state.JobSummaryByID(ws, alloc.Namespace, alloc.Job.ID)
  4354  	expectedSummary := structs.JobSummary{
  4355  		JobID:     alloc.Job.ID,
  4356  		Namespace: alloc.Namespace,
  4357  		Summary: map[string]structs.TaskGroupSummary{
  4358  			"web": {
  4359  				Running: 1,
  4360  			},
  4361  			"db": {
  4362  				Starting: 1,
  4363  				Running:  1,
  4364  				Failed:   1,
  4365  				Complete: 1,
  4366  				Lost:     1,
  4367  			},
  4368  		},
  4369  		CreateIndex: 100,
  4370  		ModifyIndex: 120,
  4371  	}
  4372  	if !reflect.DeepEqual(&expectedSummary, summary) {
  4373  		t.Fatalf("expected: %v, actual: %v", expectedSummary, summary)
  4374  	}
  4375  }
  4376  
  4377  func TestStateStore_UpdateAlloc_JobNotPresent(t *testing.T) {
  4378  	state := testStateStore(t)
  4379  
  4380  	alloc := mock.Alloc()
  4381  	state.UpsertJob(100, alloc.Job)
  4382  	state.UpsertAllocs(200, []*structs.Allocation{alloc})
  4383  
  4384  	// Delete the job
  4385  	state.DeleteJob(300, alloc.Namespace, alloc.Job.ID)
  4386  
  4387  	// Update the alloc
  4388  	alloc1 := alloc.Copy()
  4389  	alloc1.ClientStatus = structs.AllocClientStatusRunning
  4390  
  4391  	// Updating allocation should not throw any error
  4392  	if err := state.UpdateAllocsFromClient(400, []*structs.Allocation{alloc1}); err != nil {
  4393  		t.Fatalf("expect err: %v", err)
  4394  	}
  4395  
  4396  	// Re-Register the job
  4397  	state.UpsertJob(500, alloc.Job)
  4398  
  4399  	// Update the alloc again
  4400  	alloc2 := alloc.Copy()
  4401  	alloc2.ClientStatus = structs.AllocClientStatusComplete
  4402  	if err := state.UpdateAllocsFromClient(400, []*structs.Allocation{alloc1}); err != nil {
  4403  		t.Fatalf("expect err: %v", err)
  4404  	}
  4405  
  4406  	// Job Summary of the newly registered job shouldn't account for the
  4407  	// allocation update for the older job
  4408  	expectedSummary := structs.JobSummary{
  4409  		JobID:     alloc1.JobID,
  4410  		Namespace: alloc1.Namespace,
  4411  		Summary: map[string]structs.TaskGroupSummary{
  4412  			"web": {},
  4413  		},
  4414  		Children:    new(structs.JobChildrenSummary),
  4415  		CreateIndex: 500,
  4416  		ModifyIndex: 500,
  4417  	}
  4418  
  4419  	ws := memdb.NewWatchSet()
  4420  	summary, _ := state.JobSummaryByID(ws, alloc.Namespace, alloc.Job.ID)
  4421  	if !reflect.DeepEqual(&expectedSummary, summary) {
  4422  		t.Fatalf("expected: %v, actual: %v", expectedSummary, summary)
  4423  	}
  4424  }
  4425  
  4426  func TestStateStore_EvictAlloc_Alloc(t *testing.T) {
  4427  	state := testStateStore(t)
  4428  	alloc := mock.Alloc()
  4429  
  4430  	state.UpsertJobSummary(999, mock.JobSummary(alloc.JobID))
  4431  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  4432  	if err != nil {
  4433  		t.Fatalf("err: %v", err)
  4434  	}
  4435  
  4436  	alloc2 := new(structs.Allocation)
  4437  	*alloc2 = *alloc
  4438  	alloc2.DesiredStatus = structs.AllocDesiredStatusEvict
  4439  	err = state.UpsertAllocs(1001, []*structs.Allocation{alloc2})
  4440  	if err != nil {
  4441  		t.Fatalf("err: %v", err)
  4442  	}
  4443  
  4444  	ws := memdb.NewWatchSet()
  4445  	out, err := state.AllocByID(ws, alloc.ID)
  4446  	if err != nil {
  4447  		t.Fatalf("err: %v", err)
  4448  	}
  4449  
  4450  	if out.DesiredStatus != structs.AllocDesiredStatusEvict {
  4451  		t.Fatalf("bad: %#v %#v", alloc, out)
  4452  	}
  4453  
  4454  	index, err := state.Index("allocs")
  4455  	if err != nil {
  4456  		t.Fatalf("err: %v", err)
  4457  	}
  4458  	if index != 1001 {
  4459  		t.Fatalf("bad: %d", index)
  4460  	}
  4461  }
  4462  
  4463  func TestStateStore_AllocsByNode(t *testing.T) {
  4464  	state := testStateStore(t)
  4465  	var allocs []*structs.Allocation
  4466  
  4467  	for i := 0; i < 10; i++ {
  4468  		alloc := mock.Alloc()
  4469  		alloc.NodeID = "foo"
  4470  		allocs = append(allocs, alloc)
  4471  	}
  4472  
  4473  	for idx, alloc := range allocs {
  4474  		state.UpsertJobSummary(uint64(900+idx), mock.JobSummary(alloc.JobID))
  4475  	}
  4476  
  4477  	err := state.UpsertAllocs(1000, allocs)
  4478  	if err != nil {
  4479  		t.Fatalf("err: %v", err)
  4480  	}
  4481  
  4482  	ws := memdb.NewWatchSet()
  4483  	out, err := state.AllocsByNode(ws, "foo")
  4484  	if err != nil {
  4485  		t.Fatalf("err: %v", err)
  4486  	}
  4487  
  4488  	sort.Sort(AllocIDSort(allocs))
  4489  	sort.Sort(AllocIDSort(out))
  4490  
  4491  	if !reflect.DeepEqual(allocs, out) {
  4492  		t.Fatalf("bad: %#v %#v", allocs, out)
  4493  	}
  4494  
  4495  	if watchFired(ws) {
  4496  		t.Fatalf("bad")
  4497  	}
  4498  }
  4499  
  4500  func TestStateStore_AllocsByNodeTerminal(t *testing.T) {
  4501  	state := testStateStore(t)
  4502  	var allocs, term, nonterm []*structs.Allocation
  4503  
  4504  	for i := 0; i < 10; i++ {
  4505  		alloc := mock.Alloc()
  4506  		alloc.NodeID = "foo"
  4507  		if i%2 == 0 {
  4508  			alloc.DesiredStatus = structs.AllocDesiredStatusStop
  4509  			term = append(term, alloc)
  4510  		} else {
  4511  			nonterm = append(nonterm, alloc)
  4512  		}
  4513  		allocs = append(allocs, alloc)
  4514  	}
  4515  
  4516  	for idx, alloc := range allocs {
  4517  		state.UpsertJobSummary(uint64(900+idx), mock.JobSummary(alloc.JobID))
  4518  	}
  4519  
  4520  	err := state.UpsertAllocs(1000, allocs)
  4521  	if err != nil {
  4522  		t.Fatalf("err: %v", err)
  4523  	}
  4524  
  4525  	// Verify the terminal allocs
  4526  	ws := memdb.NewWatchSet()
  4527  	out, err := state.AllocsByNodeTerminal(ws, "foo", true)
  4528  	if err != nil {
  4529  		t.Fatalf("err: %v", err)
  4530  	}
  4531  
  4532  	sort.Sort(AllocIDSort(term))
  4533  	sort.Sort(AllocIDSort(out))
  4534  
  4535  	if !reflect.DeepEqual(term, out) {
  4536  		t.Fatalf("bad: %#v %#v", term, out)
  4537  	}
  4538  
  4539  	// Verify the non-terminal allocs
  4540  	out, err = state.AllocsByNodeTerminal(ws, "foo", false)
  4541  	if err != nil {
  4542  		t.Fatalf("err: %v", err)
  4543  	}
  4544  
  4545  	sort.Sort(AllocIDSort(nonterm))
  4546  	sort.Sort(AllocIDSort(out))
  4547  
  4548  	if !reflect.DeepEqual(nonterm, out) {
  4549  		t.Fatalf("bad: %#v %#v", nonterm, out)
  4550  	}
  4551  
  4552  	if watchFired(ws) {
  4553  		t.Fatalf("bad")
  4554  	}
  4555  }
  4556  
  4557  func TestStateStore_AllocsByJob(t *testing.T) {
  4558  	state := testStateStore(t)
  4559  	var allocs []*structs.Allocation
  4560  
  4561  	for i := 0; i < 10; i++ {
  4562  		alloc := mock.Alloc()
  4563  		alloc.JobID = "foo"
  4564  		allocs = append(allocs, alloc)
  4565  	}
  4566  
  4567  	for i, alloc := range allocs {
  4568  		state.UpsertJobSummary(uint64(900+i), mock.JobSummary(alloc.JobID))
  4569  	}
  4570  
  4571  	err := state.UpsertAllocs(1000, allocs)
  4572  	if err != nil {
  4573  		t.Fatalf("err: %v", err)
  4574  	}
  4575  
  4576  	ws := memdb.NewWatchSet()
  4577  	out, err := state.AllocsByJob(ws, mock.Alloc().Namespace, "foo", false)
  4578  	if err != nil {
  4579  		t.Fatalf("err: %v", err)
  4580  	}
  4581  
  4582  	sort.Sort(AllocIDSort(allocs))
  4583  	sort.Sort(AllocIDSort(out))
  4584  
  4585  	if !reflect.DeepEqual(allocs, out) {
  4586  		t.Fatalf("bad: %#v %#v", allocs, out)
  4587  	}
  4588  
  4589  	if watchFired(ws) {
  4590  		t.Fatalf("bad")
  4591  	}
  4592  }
  4593  
  4594  func TestStateStore_AllocsForRegisteredJob(t *testing.T) {
  4595  	state := testStateStore(t)
  4596  	var allocs []*structs.Allocation
  4597  	var allocs1 []*structs.Allocation
  4598  
  4599  	job := mock.Job()
  4600  	job.ID = "foo"
  4601  	state.UpsertJob(100, job)
  4602  	for i := 0; i < 3; i++ {
  4603  		alloc := mock.Alloc()
  4604  		alloc.Job = job
  4605  		alloc.JobID = job.ID
  4606  		allocs = append(allocs, alloc)
  4607  	}
  4608  	if err := state.UpsertAllocs(200, allocs); err != nil {
  4609  		t.Fatalf("err: %v", err)
  4610  	}
  4611  
  4612  	if err := state.DeleteJob(250, job.Namespace, job.ID); err != nil {
  4613  		t.Fatalf("err: %v", err)
  4614  	}
  4615  
  4616  	job1 := mock.Job()
  4617  	job1.ID = "foo"
  4618  	job1.CreateIndex = 50
  4619  	state.UpsertJob(300, job1)
  4620  	for i := 0; i < 4; i++ {
  4621  		alloc := mock.Alloc()
  4622  		alloc.Job = job1
  4623  		alloc.JobID = job1.ID
  4624  		allocs1 = append(allocs1, alloc)
  4625  	}
  4626  
  4627  	if err := state.UpsertAllocs(1000, allocs1); err != nil {
  4628  		t.Fatalf("err: %v", err)
  4629  	}
  4630  
  4631  	ws := memdb.NewWatchSet()
  4632  	out, err := state.AllocsByJob(ws, job1.Namespace, job1.ID, true)
  4633  	if err != nil {
  4634  		t.Fatalf("err: %v", err)
  4635  	}
  4636  
  4637  	expected := len(allocs) + len(allocs1)
  4638  	if len(out) != expected {
  4639  		t.Fatalf("expected: %v, actual: %v", expected, len(out))
  4640  	}
  4641  
  4642  	out1, err := state.AllocsByJob(ws, job1.Namespace, job1.ID, false)
  4643  	if err != nil {
  4644  		t.Fatalf("bad: %v", err)
  4645  	}
  4646  
  4647  	expected = len(allocs1)
  4648  	if len(out1) != expected {
  4649  		t.Fatalf("expected: %v, actual: %v", expected, len(out1))
  4650  	}
  4651  
  4652  	if watchFired(ws) {
  4653  		t.Fatalf("bad")
  4654  	}
  4655  }
  4656  
  4657  func TestStateStore_AllocsByIDPrefix(t *testing.T) {
  4658  	state := testStateStore(t)
  4659  	var allocs []*structs.Allocation
  4660  
  4661  	ids := []string{
  4662  		"aaaaaaaa-7bfb-395d-eb95-0685af2176b2",
  4663  		"aaaaaaab-7bfb-395d-eb95-0685af2176b2",
  4664  		"aaaaaabb-7bfb-395d-eb95-0685af2176b2",
  4665  		"aaaaabbb-7bfb-395d-eb95-0685af2176b2",
  4666  		"aaaabbbb-7bfb-395d-eb95-0685af2176b2",
  4667  		"aaabbbbb-7bfb-395d-eb95-0685af2176b2",
  4668  		"aabbbbbb-7bfb-395d-eb95-0685af2176b2",
  4669  		"abbbbbbb-7bfb-395d-eb95-0685af2176b2",
  4670  		"bbbbbbbb-7bfb-395d-eb95-0685af2176b2",
  4671  	}
  4672  	for i := 0; i < 9; i++ {
  4673  		alloc := mock.Alloc()
  4674  		alloc.ID = ids[i]
  4675  		allocs = append(allocs, alloc)
  4676  	}
  4677  
  4678  	for i, alloc := range allocs {
  4679  		state.UpsertJobSummary(uint64(900+i), mock.JobSummary(alloc.JobID))
  4680  	}
  4681  
  4682  	err := state.UpsertAllocs(1000, allocs)
  4683  	if err != nil {
  4684  		t.Fatalf("err: %v", err)
  4685  	}
  4686  
  4687  	ws := memdb.NewWatchSet()
  4688  	iter, err := state.AllocsByIDPrefix(ws, structs.DefaultNamespace, "aaaa")
  4689  	if err != nil {
  4690  		t.Fatalf("err: %v", err)
  4691  	}
  4692  
  4693  	gatherAllocs := func(iter memdb.ResultIterator) []*structs.Allocation {
  4694  		var allocs []*structs.Allocation
  4695  		for {
  4696  			raw := iter.Next()
  4697  			if raw == nil {
  4698  				break
  4699  			}
  4700  			allocs = append(allocs, raw.(*structs.Allocation))
  4701  		}
  4702  		return allocs
  4703  	}
  4704  
  4705  	out := gatherAllocs(iter)
  4706  	if len(out) != 5 {
  4707  		t.Fatalf("bad: expected five allocations, got: %#v", out)
  4708  	}
  4709  
  4710  	sort.Sort(AllocIDSort(allocs))
  4711  
  4712  	for index, alloc := range out {
  4713  		if ids[index] != alloc.ID {
  4714  			t.Fatalf("bad: got unexpected id: %s", alloc.ID)
  4715  		}
  4716  	}
  4717  
  4718  	iter, err = state.AllocsByIDPrefix(ws, structs.DefaultNamespace, "b-a7bfb")
  4719  	if err != nil {
  4720  		t.Fatalf("err: %v", err)
  4721  	}
  4722  
  4723  	out = gatherAllocs(iter)
  4724  	if len(out) != 0 {
  4725  		t.Fatalf("bad: unexpected zero allocations, got: %#v", out)
  4726  	}
  4727  
  4728  	if watchFired(ws) {
  4729  		t.Fatalf("bad")
  4730  	}
  4731  }
  4732  
  4733  func TestStateStore_Allocs(t *testing.T) {
  4734  	state := testStateStore(t)
  4735  	var allocs []*structs.Allocation
  4736  
  4737  	for i := 0; i < 10; i++ {
  4738  		alloc := mock.Alloc()
  4739  		allocs = append(allocs, alloc)
  4740  	}
  4741  	for i, alloc := range allocs {
  4742  		state.UpsertJobSummary(uint64(900+i), mock.JobSummary(alloc.JobID))
  4743  	}
  4744  
  4745  	err := state.UpsertAllocs(1000, allocs)
  4746  	if err != nil {
  4747  		t.Fatalf("err: %v", err)
  4748  	}
  4749  
  4750  	ws := memdb.NewWatchSet()
  4751  	iter, err := state.Allocs(ws)
  4752  	if err != nil {
  4753  		t.Fatalf("err: %v", err)
  4754  	}
  4755  
  4756  	var out []*structs.Allocation
  4757  	for {
  4758  		raw := iter.Next()
  4759  		if raw == nil {
  4760  			break
  4761  		}
  4762  		out = append(out, raw.(*structs.Allocation))
  4763  	}
  4764  
  4765  	sort.Sort(AllocIDSort(allocs))
  4766  	sort.Sort(AllocIDSort(out))
  4767  
  4768  	if !reflect.DeepEqual(allocs, out) {
  4769  		t.Fatalf("bad: %#v %#v", allocs, out)
  4770  	}
  4771  
  4772  	if watchFired(ws) {
  4773  		t.Fatalf("bad")
  4774  	}
  4775  }
  4776  
  4777  func TestStateStore_Allocs_PrevAlloc(t *testing.T) {
  4778  	state := testStateStore(t)
  4779  	var allocs []*structs.Allocation
  4780  
  4781  	require := require.New(t)
  4782  	for i := 0; i < 5; i++ {
  4783  		alloc := mock.Alloc()
  4784  		allocs = append(allocs, alloc)
  4785  	}
  4786  	for i, alloc := range allocs {
  4787  		state.UpsertJobSummary(uint64(900+i), mock.JobSummary(alloc.JobID))
  4788  	}
  4789  	// Set some previous alloc ids
  4790  	allocs[1].PreviousAllocation = allocs[0].ID
  4791  	allocs[2].PreviousAllocation = allocs[1].ID
  4792  
  4793  	err := state.UpsertAllocs(1000, allocs)
  4794  	require.Nil(err)
  4795  
  4796  	ws := memdb.NewWatchSet()
  4797  	iter, err := state.Allocs(ws)
  4798  	require.Nil(err)
  4799  
  4800  	var out []*structs.Allocation
  4801  	for {
  4802  		raw := iter.Next()
  4803  		if raw == nil {
  4804  			break
  4805  		}
  4806  		out = append(out, raw.(*structs.Allocation))
  4807  	}
  4808  
  4809  	// Set expected NextAllocation fields
  4810  	allocs[0].NextAllocation = allocs[1].ID
  4811  	allocs[1].NextAllocation = allocs[2].ID
  4812  
  4813  	sort.Sort(AllocIDSort(allocs))
  4814  	sort.Sort(AllocIDSort(out))
  4815  
  4816  	require.Equal(allocs, out)
  4817  	require.False(watchFired(ws))
  4818  
  4819  	// Insert another alloc, verify index of previous alloc also got updated
  4820  	alloc := mock.Alloc()
  4821  	alloc.PreviousAllocation = allocs[0].ID
  4822  	err = state.UpsertAllocs(1001, []*structs.Allocation{alloc})
  4823  	require.Nil(err)
  4824  	alloc0, err := state.AllocByID(nil, allocs[0].ID)
  4825  	require.Nil(err)
  4826  	require.Equal(alloc0.ModifyIndex, uint64(1001))
  4827  }
  4828  
  4829  func TestStateStore_RestoreAlloc(t *testing.T) {
  4830  	state := testStateStore(t)
  4831  	alloc := mock.Alloc()
  4832  
  4833  	restore, err := state.Restore()
  4834  	if err != nil {
  4835  		t.Fatalf("err: %v", err)
  4836  	}
  4837  
  4838  	err = restore.AllocRestore(alloc)
  4839  	if err != nil {
  4840  		t.Fatalf("err: %v", err)
  4841  	}
  4842  
  4843  	restore.Commit()
  4844  
  4845  	ws := memdb.NewWatchSet()
  4846  	out, err := state.AllocByID(ws, alloc.ID)
  4847  	if err != nil {
  4848  		t.Fatalf("err: %v", err)
  4849  	}
  4850  
  4851  	if !reflect.DeepEqual(out, alloc) {
  4852  		t.Fatalf("Bad: %#v %#v", out, alloc)
  4853  	}
  4854  
  4855  	if watchFired(ws) {
  4856  		t.Fatalf("bad")
  4857  	}
  4858  }
  4859  
  4860  func TestStateStore_RestoreAlloc_NoEphemeralDisk(t *testing.T) {
  4861  	state := testStateStore(t)
  4862  	alloc := mock.Alloc()
  4863  	alloc.Job.TaskGroups[0].EphemeralDisk = nil
  4864  	alloc.Job.TaskGroups[0].Tasks[0].Resources.DiskMB = 120
  4865  
  4866  	restore, err := state.Restore()
  4867  	if err != nil {
  4868  		t.Fatalf("err: %v", err)
  4869  	}
  4870  
  4871  	err = restore.AllocRestore(alloc)
  4872  	if err != nil {
  4873  		t.Fatalf("err: %v", err)
  4874  	}
  4875  
  4876  	restore.Commit()
  4877  
  4878  	ws := memdb.NewWatchSet()
  4879  	out, err := state.AllocByID(ws, alloc.ID)
  4880  	if err != nil {
  4881  		t.Fatalf("err: %v", err)
  4882  	}
  4883  
  4884  	expected := alloc.Copy()
  4885  	expected.Job.TaskGroups[0].EphemeralDisk = &structs.EphemeralDisk{SizeMB: 120}
  4886  	expected.Job.TaskGroups[0].Tasks[0].Resources.DiskMB = 0
  4887  
  4888  	if !reflect.DeepEqual(out, expected) {
  4889  		t.Fatalf("Bad: %#v %#v", out, expected)
  4890  	}
  4891  
  4892  	if watchFired(ws) {
  4893  		t.Fatalf("bad")
  4894  	}
  4895  }
  4896  
  4897  func TestStateStore_SetJobStatus_ForceStatus(t *testing.T) {
  4898  	state := testStateStore(t)
  4899  	txn := state.db.Txn(true)
  4900  
  4901  	// Create and insert a mock job.
  4902  	job := mock.Job()
  4903  	job.Status = ""
  4904  	job.ModifyIndex = 0
  4905  	if err := txn.Insert("jobs", job); err != nil {
  4906  		t.Fatalf("job insert failed: %v", err)
  4907  	}
  4908  
  4909  	exp := "foobar"
  4910  	index := uint64(1000)
  4911  	if err := state.setJobStatus(index, txn, job, false, exp); err != nil {
  4912  		t.Fatalf("setJobStatus() failed: %v", err)
  4913  	}
  4914  
  4915  	i, err := txn.First("jobs", "id", job.Namespace, job.ID)
  4916  	if err != nil {
  4917  		t.Fatalf("job lookup failed: %v", err)
  4918  	}
  4919  	updated := i.(*structs.Job)
  4920  
  4921  	if updated.Status != exp {
  4922  		t.Fatalf("setJobStatus() set %v; expected %v", updated.Status, exp)
  4923  	}
  4924  
  4925  	if updated.ModifyIndex != index {
  4926  		t.Fatalf("setJobStatus() set %d; expected %d", updated.ModifyIndex, index)
  4927  	}
  4928  }
  4929  
  4930  func TestStateStore_SetJobStatus_NoOp(t *testing.T) {
  4931  	state := testStateStore(t)
  4932  	txn := state.db.Txn(true)
  4933  
  4934  	// Create and insert a mock job that should be pending.
  4935  	job := mock.Job()
  4936  	job.Status = structs.JobStatusPending
  4937  	job.ModifyIndex = 10
  4938  	if err := txn.Insert("jobs", job); err != nil {
  4939  		t.Fatalf("job insert failed: %v", err)
  4940  	}
  4941  
  4942  	index := uint64(1000)
  4943  	if err := state.setJobStatus(index, txn, job, false, ""); err != nil {
  4944  		t.Fatalf("setJobStatus() failed: %v", err)
  4945  	}
  4946  
  4947  	i, err := txn.First("jobs", "id", job.Namespace, job.ID)
  4948  	if err != nil {
  4949  		t.Fatalf("job lookup failed: %v", err)
  4950  	}
  4951  	updated := i.(*structs.Job)
  4952  
  4953  	if updated.ModifyIndex == index {
  4954  		t.Fatalf("setJobStatus() should have been a no-op")
  4955  	}
  4956  }
  4957  
  4958  func TestStateStore_SetJobStatus(t *testing.T) {
  4959  	state := testStateStore(t)
  4960  	txn := state.db.Txn(true)
  4961  
  4962  	// Create and insert a mock job that should be pending but has an incorrect
  4963  	// status.
  4964  	job := mock.Job()
  4965  	job.Status = "foobar"
  4966  	job.ModifyIndex = 10
  4967  	if err := txn.Insert("jobs", job); err != nil {
  4968  		t.Fatalf("job insert failed: %v", err)
  4969  	}
  4970  
  4971  	index := uint64(1000)
  4972  	if err := state.setJobStatus(index, txn, job, false, ""); err != nil {
  4973  		t.Fatalf("setJobStatus() failed: %v", err)
  4974  	}
  4975  
  4976  	i, err := txn.First("jobs", "id", job.Namespace, job.ID)
  4977  	if err != nil {
  4978  		t.Fatalf("job lookup failed: %v", err)
  4979  	}
  4980  	updated := i.(*structs.Job)
  4981  
  4982  	if updated.Status != structs.JobStatusPending {
  4983  		t.Fatalf("setJobStatus() set %v; expected %v", updated.Status, structs.JobStatusPending)
  4984  	}
  4985  
  4986  	if updated.ModifyIndex != index {
  4987  		t.Fatalf("setJobStatus() set %d; expected %d", updated.ModifyIndex, index)
  4988  	}
  4989  }
  4990  
  4991  func TestStateStore_GetJobStatus_NoEvalsOrAllocs(t *testing.T) {
  4992  	job := mock.Job()
  4993  	state := testStateStore(t)
  4994  	txn := state.db.Txn(false)
  4995  	status, err := state.getJobStatus(txn, job, false)
  4996  	if err != nil {
  4997  		t.Fatalf("getJobStatus() failed: %v", err)
  4998  	}
  4999  
  5000  	if status != structs.JobStatusPending {
  5001  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusPending)
  5002  	}
  5003  }
  5004  
  5005  func TestStateStore_GetJobStatus_NoEvalsOrAllocs_Periodic(t *testing.T) {
  5006  	job := mock.PeriodicJob()
  5007  	state := testStateStore(t)
  5008  	txn := state.db.Txn(false)
  5009  	status, err := state.getJobStatus(txn, job, false)
  5010  	if err != nil {
  5011  		t.Fatalf("getJobStatus() failed: %v", err)
  5012  	}
  5013  
  5014  	if status != structs.JobStatusRunning {
  5015  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusRunning)
  5016  	}
  5017  }
  5018  
  5019  func TestStateStore_GetJobStatus_NoEvalsOrAllocs_EvalDelete(t *testing.T) {
  5020  	job := mock.Job()
  5021  	state := testStateStore(t)
  5022  	txn := state.db.Txn(false)
  5023  	status, err := state.getJobStatus(txn, job, true)
  5024  	if err != nil {
  5025  		t.Fatalf("getJobStatus() failed: %v", err)
  5026  	}
  5027  
  5028  	if status != structs.JobStatusDead {
  5029  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusDead)
  5030  	}
  5031  }
  5032  
  5033  func TestStateStore_GetJobStatus_DeadEvalsAndAllocs(t *testing.T) {
  5034  	state := testStateStore(t)
  5035  	job := mock.Job()
  5036  
  5037  	// Create a mock alloc that is dead.
  5038  	alloc := mock.Alloc()
  5039  	alloc.JobID = job.ID
  5040  	alloc.DesiredStatus = structs.AllocDesiredStatusStop
  5041  	state.UpsertJobSummary(999, mock.JobSummary(alloc.JobID))
  5042  	if err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}); err != nil {
  5043  		t.Fatalf("err: %v", err)
  5044  	}
  5045  
  5046  	// Create a mock eval that is complete
  5047  	eval := mock.Eval()
  5048  	eval.JobID = job.ID
  5049  	eval.Status = structs.EvalStatusComplete
  5050  	if err := state.UpsertEvals(1001, []*structs.Evaluation{eval}); err != nil {
  5051  		t.Fatalf("err: %v", err)
  5052  	}
  5053  
  5054  	txn := state.db.Txn(false)
  5055  	status, err := state.getJobStatus(txn, job, false)
  5056  	if err != nil {
  5057  		t.Fatalf("getJobStatus() failed: %v", err)
  5058  	}
  5059  
  5060  	if status != structs.JobStatusDead {
  5061  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusDead)
  5062  	}
  5063  }
  5064  
  5065  func TestStateStore_GetJobStatus_RunningAlloc(t *testing.T) {
  5066  	state := testStateStore(t)
  5067  	job := mock.Job()
  5068  
  5069  	// Create a mock alloc that is running.
  5070  	alloc := mock.Alloc()
  5071  	alloc.JobID = job.ID
  5072  	alloc.DesiredStatus = structs.AllocDesiredStatusRun
  5073  	state.UpsertJobSummary(999, mock.JobSummary(alloc.JobID))
  5074  	if err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}); err != nil {
  5075  		t.Fatalf("err: %v", err)
  5076  	}
  5077  
  5078  	txn := state.db.Txn(false)
  5079  	status, err := state.getJobStatus(txn, job, true)
  5080  	if err != nil {
  5081  		t.Fatalf("getJobStatus() failed: %v", err)
  5082  	}
  5083  
  5084  	if status != structs.JobStatusRunning {
  5085  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusRunning)
  5086  	}
  5087  }
  5088  
  5089  func TestStateStore_GetJobStatus_PeriodicJob(t *testing.T) {
  5090  	state := testStateStore(t)
  5091  	job := mock.PeriodicJob()
  5092  
  5093  	txn := state.db.Txn(false)
  5094  	status, err := state.getJobStatus(txn, job, false)
  5095  	if err != nil {
  5096  		t.Fatalf("getJobStatus() failed: %v", err)
  5097  	}
  5098  
  5099  	if status != structs.JobStatusRunning {
  5100  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusRunning)
  5101  	}
  5102  
  5103  	// Mark it as stopped
  5104  	job.Stop = true
  5105  	status, err = state.getJobStatus(txn, job, false)
  5106  	if err != nil {
  5107  		t.Fatalf("getJobStatus() failed: %v", err)
  5108  	}
  5109  
  5110  	if status != structs.JobStatusDead {
  5111  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusDead)
  5112  	}
  5113  }
  5114  
  5115  func TestStateStore_GetJobStatus_ParameterizedJob(t *testing.T) {
  5116  	state := testStateStore(t)
  5117  	job := mock.Job()
  5118  	job.ParameterizedJob = &structs.ParameterizedJobConfig{}
  5119  
  5120  	txn := state.db.Txn(false)
  5121  	status, err := state.getJobStatus(txn, job, false)
  5122  	if err != nil {
  5123  		t.Fatalf("getJobStatus() failed: %v", err)
  5124  	}
  5125  
  5126  	if status != structs.JobStatusRunning {
  5127  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusRunning)
  5128  	}
  5129  
  5130  	// Mark it as stopped
  5131  	job.Stop = true
  5132  	status, err = state.getJobStatus(txn, job, false)
  5133  	if err != nil {
  5134  		t.Fatalf("getJobStatus() failed: %v", err)
  5135  	}
  5136  
  5137  	if status != structs.JobStatusDead {
  5138  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusDead)
  5139  	}
  5140  }
  5141  
  5142  func TestStateStore_SetJobStatus_PendingEval(t *testing.T) {
  5143  	state := testStateStore(t)
  5144  	job := mock.Job()
  5145  
  5146  	// Create a mock eval that is pending.
  5147  	eval := mock.Eval()
  5148  	eval.JobID = job.ID
  5149  	eval.Status = structs.EvalStatusPending
  5150  	if err := state.UpsertEvals(1000, []*structs.Evaluation{eval}); err != nil {
  5151  		t.Fatalf("err: %v", err)
  5152  	}
  5153  
  5154  	txn := state.db.Txn(false)
  5155  	status, err := state.getJobStatus(txn, job, true)
  5156  	if err != nil {
  5157  		t.Fatalf("getJobStatus() failed: %v", err)
  5158  	}
  5159  
  5160  	if status != structs.JobStatusPending {
  5161  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusPending)
  5162  	}
  5163  }
  5164  
  5165  // TestStateStore_SetJobStatus_SystemJob asserts that system jobs are still
  5166  // considered running until explicitly stopped.
  5167  func TestStateStore_SetJobStatus_SystemJob(t *testing.T) {
  5168  	state := testStateStore(t)
  5169  	job := mock.SystemJob()
  5170  
  5171  	// Create a mock eval that is pending.
  5172  	eval := mock.Eval()
  5173  	eval.JobID = job.ID
  5174  	eval.Type = job.Type
  5175  	eval.Status = structs.EvalStatusComplete
  5176  	if err := state.UpsertEvals(1000, []*structs.Evaluation{eval}); err != nil {
  5177  		t.Fatalf("err: %v", err)
  5178  	}
  5179  
  5180  	txn := state.db.Txn(false)
  5181  	status, err := state.getJobStatus(txn, job, true)
  5182  	if err != nil {
  5183  		t.Fatalf("getJobStatus() failed: %v", err)
  5184  	}
  5185  
  5186  	if expected := structs.JobStatusRunning; status != expected {
  5187  		t.Fatalf("getJobStatus() returned %v; expected %v", status, expected)
  5188  	}
  5189  
  5190  	// Stop the job
  5191  	job.Stop = true
  5192  	status, err = state.getJobStatus(txn, job, true)
  5193  	if err != nil {
  5194  		t.Fatalf("getJobStatus() failed: %v", err)
  5195  	}
  5196  
  5197  	if expected := structs.JobStatusDead; status != expected {
  5198  		t.Fatalf("getJobStatus() returned %v; expected %v", status, expected)
  5199  	}
  5200  }
  5201  
  5202  func TestStateJobSummary_UpdateJobCount(t *testing.T) {
  5203  	state := testStateStore(t)
  5204  	alloc := mock.Alloc()
  5205  	job := alloc.Job
  5206  	job.TaskGroups[0].Count = 3
  5207  
  5208  	// Create watchsets so we can test that upsert fires the watch
  5209  	ws := memdb.NewWatchSet()
  5210  	if _, err := state.JobSummaryByID(ws, job.Namespace, job.ID); err != nil {
  5211  		t.Fatalf("bad: %v", err)
  5212  	}
  5213  
  5214  	if err := state.UpsertJob(1000, job); err != nil {
  5215  		t.Fatalf("err: %v", err)
  5216  	}
  5217  
  5218  	if err := state.UpsertAllocs(1001, []*structs.Allocation{alloc}); err != nil {
  5219  		t.Fatalf("err: %v", err)
  5220  	}
  5221  
  5222  	if !watchFired(ws) {
  5223  		t.Fatalf("bad")
  5224  	}
  5225  
  5226  	ws = memdb.NewWatchSet()
  5227  	summary, _ := state.JobSummaryByID(ws, job.Namespace, job.ID)
  5228  	expectedSummary := structs.JobSummary{
  5229  		JobID:     job.ID,
  5230  		Namespace: job.Namespace,
  5231  		Summary: map[string]structs.TaskGroupSummary{
  5232  			"web": {
  5233  				Starting: 1,
  5234  			},
  5235  		},
  5236  		Children:    new(structs.JobChildrenSummary),
  5237  		CreateIndex: 1000,
  5238  		ModifyIndex: 1001,
  5239  	}
  5240  	if !reflect.DeepEqual(summary, &expectedSummary) {
  5241  		t.Fatalf("expected: %v, actual: %v", expectedSummary, summary)
  5242  	}
  5243  
  5244  	// Create watchsets so we can test that upsert fires the watch
  5245  	ws2 := memdb.NewWatchSet()
  5246  	if _, err := state.JobSummaryByID(ws2, job.Namespace, job.ID); err != nil {
  5247  		t.Fatalf("bad: %v", err)
  5248  	}
  5249  
  5250  	alloc2 := mock.Alloc()
  5251  	alloc2.Job = job
  5252  	alloc2.JobID = job.ID
  5253  
  5254  	alloc3 := mock.Alloc()
  5255  	alloc3.Job = job
  5256  	alloc3.JobID = job.ID
  5257  
  5258  	if err := state.UpsertAllocs(1002, []*structs.Allocation{alloc2, alloc3}); err != nil {
  5259  		t.Fatalf("err: %v", err)
  5260  	}
  5261  
  5262  	if !watchFired(ws2) {
  5263  		t.Fatalf("bad")
  5264  	}
  5265  
  5266  	outA, _ := state.AllocByID(ws, alloc3.ID)
  5267  
  5268  	summary, _ = state.JobSummaryByID(ws, job.Namespace, job.ID)
  5269  	expectedSummary = structs.JobSummary{
  5270  		JobID:     job.ID,
  5271  		Namespace: job.Namespace,
  5272  		Summary: map[string]structs.TaskGroupSummary{
  5273  			"web": {
  5274  				Starting: 3,
  5275  			},
  5276  		},
  5277  		Children:    new(structs.JobChildrenSummary),
  5278  		CreateIndex: job.CreateIndex,
  5279  		ModifyIndex: outA.ModifyIndex,
  5280  	}
  5281  	if !reflect.DeepEqual(summary, &expectedSummary) {
  5282  		t.Fatalf("expected summary: %v, actual: %v", expectedSummary, summary)
  5283  	}
  5284  
  5285  	// Create watchsets so we can test that upsert fires the watch
  5286  	ws3 := memdb.NewWatchSet()
  5287  	if _, err := state.JobSummaryByID(ws3, job.Namespace, job.ID); err != nil {
  5288  		t.Fatalf("bad: %v", err)
  5289  	}
  5290  
  5291  	alloc4 := mock.Alloc()
  5292  	alloc4.ID = alloc2.ID
  5293  	alloc4.Job = alloc2.Job
  5294  	alloc4.JobID = alloc2.JobID
  5295  	alloc4.ClientStatus = structs.AllocClientStatusComplete
  5296  
  5297  	alloc5 := mock.Alloc()
  5298  	alloc5.ID = alloc3.ID
  5299  	alloc5.Job = alloc3.Job
  5300  	alloc5.JobID = alloc3.JobID
  5301  	alloc5.ClientStatus = structs.AllocClientStatusComplete
  5302  
  5303  	if err := state.UpdateAllocsFromClient(1004, []*structs.Allocation{alloc4, alloc5}); err != nil {
  5304  		t.Fatalf("err: %v", err)
  5305  	}
  5306  
  5307  	if !watchFired(ws2) {
  5308  		t.Fatalf("bad")
  5309  	}
  5310  
  5311  	outA, _ = state.AllocByID(ws, alloc5.ID)
  5312  	summary, _ = state.JobSummaryByID(ws, job.Namespace, job.ID)
  5313  	expectedSummary = structs.JobSummary{
  5314  		JobID:     job.ID,
  5315  		Namespace: job.Namespace,
  5316  		Summary: map[string]structs.TaskGroupSummary{
  5317  			"web": {
  5318  				Complete: 2,
  5319  				Starting: 1,
  5320  			},
  5321  		},
  5322  		Children:    new(structs.JobChildrenSummary),
  5323  		CreateIndex: job.CreateIndex,
  5324  		ModifyIndex: outA.ModifyIndex,
  5325  	}
  5326  	if !reflect.DeepEqual(summary, &expectedSummary) {
  5327  		t.Fatalf("expected: %v, actual: %v", expectedSummary, summary)
  5328  	}
  5329  }
  5330  
  5331  func TestJobSummary_UpdateClientStatus(t *testing.T) {
  5332  	state := testStateStore(t)
  5333  	alloc := mock.Alloc()
  5334  	job := alloc.Job
  5335  	job.TaskGroups[0].Count = 3
  5336  
  5337  	alloc2 := mock.Alloc()
  5338  	alloc2.Job = job
  5339  	alloc2.JobID = job.ID
  5340  
  5341  	alloc3 := mock.Alloc()
  5342  	alloc3.Job = job
  5343  	alloc3.JobID = job.ID
  5344  
  5345  	err := state.UpsertJob(1000, job)
  5346  	if err != nil {
  5347  		t.Fatalf("err: %v", err)
  5348  	}
  5349  
  5350  	if err := state.UpsertAllocs(1001, []*structs.Allocation{alloc, alloc2, alloc3}); err != nil {
  5351  		t.Fatalf("err: %v", err)
  5352  	}
  5353  
  5354  	ws := memdb.NewWatchSet()
  5355  	summary, _ := state.JobSummaryByID(ws, job.Namespace, job.ID)
  5356  	if summary.Summary["web"].Starting != 3 {
  5357  		t.Fatalf("bad job summary: %v", summary)
  5358  	}
  5359  
  5360  	alloc4 := mock.Alloc()
  5361  	alloc4.ID = alloc2.ID
  5362  	alloc4.Job = alloc2.Job
  5363  	alloc4.JobID = alloc2.JobID
  5364  	alloc4.ClientStatus = structs.AllocClientStatusComplete
  5365  
  5366  	alloc5 := mock.Alloc()
  5367  	alloc5.ID = alloc3.ID
  5368  	alloc5.Job = alloc3.Job
  5369  	alloc5.JobID = alloc3.JobID
  5370  	alloc5.ClientStatus = structs.AllocClientStatusFailed
  5371  
  5372  	alloc6 := mock.Alloc()
  5373  	alloc6.ID = alloc.ID
  5374  	alloc6.Job = alloc.Job
  5375  	alloc6.JobID = alloc.JobID
  5376  	alloc6.ClientStatus = structs.AllocClientStatusRunning
  5377  
  5378  	if err := state.UpdateAllocsFromClient(1002, []*structs.Allocation{alloc4, alloc5, alloc6}); err != nil {
  5379  		t.Fatalf("err: %v", err)
  5380  	}
  5381  
  5382  	if !watchFired(ws) {
  5383  		t.Fatalf("bad")
  5384  	}
  5385  
  5386  	summary, _ = state.JobSummaryByID(ws, job.Namespace, job.ID)
  5387  	if summary.Summary["web"].Running != 1 || summary.Summary["web"].Failed != 1 || summary.Summary["web"].Complete != 1 {
  5388  		t.Fatalf("bad job summary: %v", summary)
  5389  	}
  5390  
  5391  	alloc7 := mock.Alloc()
  5392  	alloc7.Job = alloc.Job
  5393  	alloc7.JobID = alloc.JobID
  5394  
  5395  	if err := state.UpsertAllocs(1003, []*structs.Allocation{alloc7}); err != nil {
  5396  		t.Fatalf("err: %v", err)
  5397  	}
  5398  	summary, _ = state.JobSummaryByID(ws, job.Namespace, job.ID)
  5399  	if summary.Summary["web"].Starting != 1 || summary.Summary["web"].Running != 1 || summary.Summary["web"].Failed != 1 || summary.Summary["web"].Complete != 1 {
  5400  		t.Fatalf("bad job summary: %v", summary)
  5401  	}
  5402  }
  5403  
  5404  // Test that nonexistent deployment can't be updated
  5405  func TestStateStore_UpsertDeploymentStatusUpdate_Nonexistent(t *testing.T) {
  5406  	state := testStateStore(t)
  5407  
  5408  	// Update the nonexistent deployment
  5409  	req := &structs.DeploymentStatusUpdateRequest{
  5410  		DeploymentUpdate: &structs.DeploymentStatusUpdate{
  5411  			DeploymentID: uuid.Generate(),
  5412  			Status:       structs.DeploymentStatusRunning,
  5413  		},
  5414  	}
  5415  	err := state.UpdateDeploymentStatus(2, req)
  5416  	if err == nil || !strings.Contains(err.Error(), "does not exist") {
  5417  		t.Fatalf("expected error updating the status because the deployment doesn't exist")
  5418  	}
  5419  }
  5420  
  5421  // Test that terminal deployment can't be updated
  5422  func TestStateStore_UpsertDeploymentStatusUpdate_Terminal(t *testing.T) {
  5423  	state := testStateStore(t)
  5424  
  5425  	// Insert a terminal deployment
  5426  	d := mock.Deployment()
  5427  	d.Status = structs.DeploymentStatusFailed
  5428  
  5429  	if err := state.UpsertDeployment(1, d); err != nil {
  5430  		t.Fatalf("bad: %v", err)
  5431  	}
  5432  
  5433  	// Update the deployment
  5434  	req := &structs.DeploymentStatusUpdateRequest{
  5435  		DeploymentUpdate: &structs.DeploymentStatusUpdate{
  5436  			DeploymentID: d.ID,
  5437  			Status:       structs.DeploymentStatusRunning,
  5438  		},
  5439  	}
  5440  	err := state.UpdateDeploymentStatus(2, req)
  5441  	if err == nil || !strings.Contains(err.Error(), "has terminal status") {
  5442  		t.Fatalf("expected error updating the status because the deployment is terminal")
  5443  	}
  5444  }
  5445  
  5446  // Test that a non terminal deployment is updated and that a job and eval are
  5447  // created.
  5448  func TestStateStore_UpsertDeploymentStatusUpdate_NonTerminal(t *testing.T) {
  5449  	state := testStateStore(t)
  5450  
  5451  	// Insert a deployment
  5452  	d := mock.Deployment()
  5453  	if err := state.UpsertDeployment(1, d); err != nil {
  5454  		t.Fatalf("bad: %v", err)
  5455  	}
  5456  
  5457  	// Create an eval and a job
  5458  	e := mock.Eval()
  5459  	j := mock.Job()
  5460  
  5461  	// Update the deployment
  5462  	status, desc := structs.DeploymentStatusFailed, "foo"
  5463  	req := &structs.DeploymentStatusUpdateRequest{
  5464  		DeploymentUpdate: &structs.DeploymentStatusUpdate{
  5465  			DeploymentID:      d.ID,
  5466  			Status:            status,
  5467  			StatusDescription: desc,
  5468  		},
  5469  		Job:  j,
  5470  		Eval: e,
  5471  	}
  5472  	err := state.UpdateDeploymentStatus(2, req)
  5473  	if err != nil {
  5474  		t.Fatalf("bad: %v", err)
  5475  	}
  5476  
  5477  	// Check that the status was updated properly
  5478  	ws := memdb.NewWatchSet()
  5479  	dout, err := state.DeploymentByID(ws, d.ID)
  5480  	if err != nil {
  5481  		t.Fatalf("bad: %v", err)
  5482  	}
  5483  	if dout.Status != status || dout.StatusDescription != desc {
  5484  		t.Fatalf("bad: %#v", dout)
  5485  	}
  5486  
  5487  	// Check that the evaluation was created
  5488  	eout, _ := state.EvalByID(ws, e.ID)
  5489  	if err != nil {
  5490  		t.Fatalf("bad: %v", err)
  5491  	}
  5492  	if eout == nil {
  5493  		t.Fatalf("bad: %#v", eout)
  5494  	}
  5495  
  5496  	// Check that the job was created
  5497  	jout, _ := state.JobByID(ws, j.Namespace, j.ID)
  5498  	if err != nil {
  5499  		t.Fatalf("bad: %v", err)
  5500  	}
  5501  	if jout == nil {
  5502  		t.Fatalf("bad: %#v", jout)
  5503  	}
  5504  }
  5505  
  5506  // Test that when a deployment is updated to successful the job is updated to
  5507  // stable
  5508  func TestStateStore_UpsertDeploymentStatusUpdate_Successful(t *testing.T) {
  5509  	state := testStateStore(t)
  5510  
  5511  	// Insert a job
  5512  	job := mock.Job()
  5513  	if err := state.UpsertJob(1, job); err != nil {
  5514  		t.Fatalf("bad: %v", err)
  5515  	}
  5516  
  5517  	// Insert a deployment
  5518  	d := structs.NewDeployment(job)
  5519  	if err := state.UpsertDeployment(2, d); err != nil {
  5520  		t.Fatalf("bad: %v", err)
  5521  	}
  5522  
  5523  	// Update the deployment
  5524  	req := &structs.DeploymentStatusUpdateRequest{
  5525  		DeploymentUpdate: &structs.DeploymentStatusUpdate{
  5526  			DeploymentID:      d.ID,
  5527  			Status:            structs.DeploymentStatusSuccessful,
  5528  			StatusDescription: structs.DeploymentStatusDescriptionSuccessful,
  5529  		},
  5530  	}
  5531  	err := state.UpdateDeploymentStatus(3, req)
  5532  	if err != nil {
  5533  		t.Fatalf("bad: %v", err)
  5534  	}
  5535  
  5536  	// Check that the status was updated properly
  5537  	ws := memdb.NewWatchSet()
  5538  	dout, err := state.DeploymentByID(ws, d.ID)
  5539  	if err != nil {
  5540  		t.Fatalf("bad: %v", err)
  5541  	}
  5542  	if dout.Status != structs.DeploymentStatusSuccessful ||
  5543  		dout.StatusDescription != structs.DeploymentStatusDescriptionSuccessful {
  5544  		t.Fatalf("bad: %#v", dout)
  5545  	}
  5546  
  5547  	// Check that the job was created
  5548  	jout, _ := state.JobByID(ws, job.Namespace, job.ID)
  5549  	if err != nil {
  5550  		t.Fatalf("bad: %v", err)
  5551  	}
  5552  	if jout == nil {
  5553  		t.Fatalf("bad: %#v", jout)
  5554  	}
  5555  	if !jout.Stable {
  5556  		t.Fatalf("job not marked stable %#v", jout)
  5557  	}
  5558  	if jout.Version != d.JobVersion {
  5559  		t.Fatalf("job version changed; got %d; want %d", jout.Version, d.JobVersion)
  5560  	}
  5561  }
  5562  
  5563  func TestStateStore_UpdateJobStability(t *testing.T) {
  5564  	state := testStateStore(t)
  5565  
  5566  	// Insert a job twice to get two versions
  5567  	job := mock.Job()
  5568  	if err := state.UpsertJob(1, job); err != nil {
  5569  		t.Fatalf("bad: %v", err)
  5570  	}
  5571  
  5572  	if err := state.UpsertJob(2, job); err != nil {
  5573  		t.Fatalf("bad: %v", err)
  5574  	}
  5575  
  5576  	// Update the stability to true
  5577  	err := state.UpdateJobStability(3, job.Namespace, job.ID, 0, true)
  5578  	if err != nil {
  5579  		t.Fatalf("bad: %v", err)
  5580  	}
  5581  
  5582  	// Check that the job was updated properly
  5583  	ws := memdb.NewWatchSet()
  5584  	jout, _ := state.JobByIDAndVersion(ws, job.Namespace, job.ID, 0)
  5585  	if err != nil {
  5586  		t.Fatalf("bad: %v", err)
  5587  	}
  5588  	if jout == nil {
  5589  		t.Fatalf("bad: %#v", jout)
  5590  	}
  5591  	if !jout.Stable {
  5592  		t.Fatalf("job not marked stable %#v", jout)
  5593  	}
  5594  
  5595  	// Update the stability to false
  5596  	err = state.UpdateJobStability(3, job.Namespace, job.ID, 0, false)
  5597  	if err != nil {
  5598  		t.Fatalf("bad: %v", err)
  5599  	}
  5600  
  5601  	// Check that the job was updated properly
  5602  	jout, _ = state.JobByIDAndVersion(ws, job.Namespace, job.ID, 0)
  5603  	if err != nil {
  5604  		t.Fatalf("bad: %v", err)
  5605  	}
  5606  	if jout == nil {
  5607  		t.Fatalf("bad: %#v", jout)
  5608  	}
  5609  	if jout.Stable {
  5610  		t.Fatalf("job marked stable %#v", jout)
  5611  	}
  5612  }
  5613  
  5614  // Test that nonexistent deployment can't be promoted
  5615  func TestStateStore_UpsertDeploymentPromotion_Nonexistent(t *testing.T) {
  5616  	state := testStateStore(t)
  5617  
  5618  	// Promote the nonexistent deployment
  5619  	req := &structs.ApplyDeploymentPromoteRequest{
  5620  		DeploymentPromoteRequest: structs.DeploymentPromoteRequest{
  5621  			DeploymentID: uuid.Generate(),
  5622  			All:          true,
  5623  		},
  5624  	}
  5625  	err := state.UpdateDeploymentPromotion(2, req)
  5626  	if err == nil || !strings.Contains(err.Error(), "does not exist") {
  5627  		t.Fatalf("expected error promoting because the deployment doesn't exist")
  5628  	}
  5629  }
  5630  
  5631  // Test that terminal deployment can't be updated
  5632  func TestStateStore_UpsertDeploymentPromotion_Terminal(t *testing.T) {
  5633  	state := testStateStore(t)
  5634  
  5635  	// Insert a terminal deployment
  5636  	d := mock.Deployment()
  5637  	d.Status = structs.DeploymentStatusFailed
  5638  
  5639  	if err := state.UpsertDeployment(1, d); err != nil {
  5640  		t.Fatalf("bad: %v", err)
  5641  	}
  5642  
  5643  	// Promote the deployment
  5644  	req := &structs.ApplyDeploymentPromoteRequest{
  5645  		DeploymentPromoteRequest: structs.DeploymentPromoteRequest{
  5646  			DeploymentID: d.ID,
  5647  			All:          true,
  5648  		},
  5649  	}
  5650  	err := state.UpdateDeploymentPromotion(2, req)
  5651  	if err == nil || !strings.Contains(err.Error(), "has terminal status") {
  5652  		t.Fatalf("expected error updating the status because the deployment is terminal: %v", err)
  5653  	}
  5654  }
  5655  
  5656  // Test promoting unhealthy canaries in a deployment.
  5657  func TestStateStore_UpsertDeploymentPromotion_Unhealthy(t *testing.T) {
  5658  	state := testStateStore(t)
  5659  	require := require.New(t)
  5660  
  5661  	// Create a job
  5662  	j := mock.Job()
  5663  	require.Nil(state.UpsertJob(1, j))
  5664  
  5665  	// Create a deployment
  5666  	d := mock.Deployment()
  5667  	d.JobID = j.ID
  5668  	d.TaskGroups["web"].DesiredCanaries = 2
  5669  	require.Nil(state.UpsertDeployment(2, d))
  5670  
  5671  	// Create a set of allocations
  5672  	c1 := mock.Alloc()
  5673  	c1.JobID = j.ID
  5674  	c1.DeploymentID = d.ID
  5675  	d.TaskGroups[c1.TaskGroup].PlacedCanaries = append(d.TaskGroups[c1.TaskGroup].PlacedCanaries, c1.ID)
  5676  	c2 := mock.Alloc()
  5677  	c2.JobID = j.ID
  5678  	c2.DeploymentID = d.ID
  5679  	d.TaskGroups[c2.TaskGroup].PlacedCanaries = append(d.TaskGroups[c2.TaskGroup].PlacedCanaries, c2.ID)
  5680  
  5681  	// Create a healthy but terminal alloc
  5682  	c3 := mock.Alloc()
  5683  	c3.JobID = j.ID
  5684  	c3.DeploymentID = d.ID
  5685  	c3.DesiredStatus = structs.AllocDesiredStatusStop
  5686  	c3.DeploymentStatus = &structs.AllocDeploymentStatus{Healthy: helper.BoolToPtr(true)}
  5687  	d.TaskGroups[c3.TaskGroup].PlacedCanaries = append(d.TaskGroups[c3.TaskGroup].PlacedCanaries, c3.ID)
  5688  
  5689  	require.Nil(state.UpsertAllocs(3, []*structs.Allocation{c1, c2, c3}))
  5690  
  5691  	// Promote the canaries
  5692  	req := &structs.ApplyDeploymentPromoteRequest{
  5693  		DeploymentPromoteRequest: structs.DeploymentPromoteRequest{
  5694  			DeploymentID: d.ID,
  5695  			All:          true,
  5696  		},
  5697  	}
  5698  	err := state.UpdateDeploymentPromotion(4, req)
  5699  	require.NotNil(err)
  5700  	require.Contains(err.Error(), `Task group "web" has 0/2 healthy allocations`)
  5701  }
  5702  
  5703  // Test promoting a deployment with no canaries
  5704  func TestStateStore_UpsertDeploymentPromotion_NoCanaries(t *testing.T) {
  5705  	state := testStateStore(t)
  5706  	require := require.New(t)
  5707  
  5708  	// Create a job
  5709  	j := mock.Job()
  5710  	require.Nil(state.UpsertJob(1, j))
  5711  
  5712  	// Create a deployment
  5713  	d := mock.Deployment()
  5714  	d.TaskGroups["web"].DesiredCanaries = 2
  5715  	d.JobID = j.ID
  5716  	require.Nil(state.UpsertDeployment(2, d))
  5717  
  5718  	// Promote the canaries
  5719  	req := &structs.ApplyDeploymentPromoteRequest{
  5720  		DeploymentPromoteRequest: structs.DeploymentPromoteRequest{
  5721  			DeploymentID: d.ID,
  5722  			All:          true,
  5723  		},
  5724  	}
  5725  	err := state.UpdateDeploymentPromotion(4, req)
  5726  	require.NotNil(err)
  5727  	require.Contains(err.Error(), `Task group "web" has 0/2 healthy allocations`)
  5728  }
  5729  
  5730  // Test promoting all canaries in a deployment.
  5731  func TestStateStore_UpsertDeploymentPromotion_All(t *testing.T) {
  5732  	state := testStateStore(t)
  5733  
  5734  	// Create a job with two task groups
  5735  	j := mock.Job()
  5736  	tg1 := j.TaskGroups[0]
  5737  	tg2 := tg1.Copy()
  5738  	tg2.Name = "foo"
  5739  	j.TaskGroups = append(j.TaskGroups, tg2)
  5740  	if err := state.UpsertJob(1, j); err != nil {
  5741  		t.Fatalf("bad: %v", err)
  5742  	}
  5743  
  5744  	// Create a deployment
  5745  	d := mock.Deployment()
  5746  	d.StatusDescription = structs.DeploymentStatusDescriptionRunningNeedsPromotion
  5747  	d.JobID = j.ID
  5748  	d.TaskGroups = map[string]*structs.DeploymentState{
  5749  		"web": {
  5750  			DesiredTotal:    10,
  5751  			DesiredCanaries: 1,
  5752  		},
  5753  		"foo": {
  5754  			DesiredTotal:    10,
  5755  			DesiredCanaries: 1,
  5756  		},
  5757  	}
  5758  	if err := state.UpsertDeployment(2, d); err != nil {
  5759  		t.Fatalf("bad: %v", err)
  5760  	}
  5761  
  5762  	// Create a set of allocations
  5763  	c1 := mock.Alloc()
  5764  	c1.JobID = j.ID
  5765  	c1.DeploymentID = d.ID
  5766  	d.TaskGroups[c1.TaskGroup].PlacedCanaries = append(d.TaskGroups[c1.TaskGroup].PlacedCanaries, c1.ID)
  5767  	c1.DeploymentStatus = &structs.AllocDeploymentStatus{
  5768  		Healthy: helper.BoolToPtr(true),
  5769  	}
  5770  	c2 := mock.Alloc()
  5771  	c2.JobID = j.ID
  5772  	c2.DeploymentID = d.ID
  5773  	d.TaskGroups[c2.TaskGroup].PlacedCanaries = append(d.TaskGroups[c2.TaskGroup].PlacedCanaries, c2.ID)
  5774  	c2.TaskGroup = tg2.Name
  5775  	c2.DeploymentStatus = &structs.AllocDeploymentStatus{
  5776  		Healthy: helper.BoolToPtr(true),
  5777  	}
  5778  
  5779  	if err := state.UpsertAllocs(3, []*structs.Allocation{c1, c2}); err != nil {
  5780  		t.Fatalf("err: %v", err)
  5781  	}
  5782  
  5783  	// Create an eval
  5784  	e := mock.Eval()
  5785  
  5786  	// Promote the canaries
  5787  	req := &structs.ApplyDeploymentPromoteRequest{
  5788  		DeploymentPromoteRequest: structs.DeploymentPromoteRequest{
  5789  			DeploymentID: d.ID,
  5790  			All:          true,
  5791  		},
  5792  		Eval: e,
  5793  	}
  5794  	err := state.UpdateDeploymentPromotion(4, req)
  5795  	if err != nil {
  5796  		t.Fatalf("bad: %v", err)
  5797  	}
  5798  
  5799  	// Check that the status per task group was updated properly
  5800  	ws := memdb.NewWatchSet()
  5801  	dout, err := state.DeploymentByID(ws, d.ID)
  5802  	if err != nil {
  5803  		t.Fatalf("bad: %v", err)
  5804  	}
  5805  	if dout.StatusDescription != structs.DeploymentStatusDescriptionRunning {
  5806  		t.Fatalf("status description not updated: got %v; want %v", dout.StatusDescription, structs.DeploymentStatusDescriptionRunning)
  5807  	}
  5808  	if len(dout.TaskGroups) != 2 {
  5809  		t.Fatalf("bad: %#v", dout.TaskGroups)
  5810  	}
  5811  	for tg, state := range dout.TaskGroups {
  5812  		if !state.Promoted {
  5813  			t.Fatalf("bad: group %q not promoted %#v", tg, state)
  5814  		}
  5815  	}
  5816  
  5817  	// Check that the evaluation was created
  5818  	eout, _ := state.EvalByID(ws, e.ID)
  5819  	if err != nil {
  5820  		t.Fatalf("bad: %v", err)
  5821  	}
  5822  	if eout == nil {
  5823  		t.Fatalf("bad: %#v", eout)
  5824  	}
  5825  }
  5826  
  5827  // Test promoting a subset of canaries in a deployment.
  5828  func TestStateStore_UpsertDeploymentPromotion_Subset(t *testing.T) {
  5829  	state := testStateStore(t)
  5830  	require := require.New(t)
  5831  
  5832  	// Create a job with two task groups
  5833  	j := mock.Job()
  5834  	tg1 := j.TaskGroups[0]
  5835  	tg2 := tg1.Copy()
  5836  	tg2.Name = "foo"
  5837  	j.TaskGroups = append(j.TaskGroups, tg2)
  5838  	require.Nil(state.UpsertJob(1, j))
  5839  
  5840  	// Create a deployment
  5841  	d := mock.Deployment()
  5842  	d.JobID = j.ID
  5843  	d.TaskGroups = map[string]*structs.DeploymentState{
  5844  		"web": {
  5845  			DesiredTotal:    10,
  5846  			DesiredCanaries: 1,
  5847  		},
  5848  		"foo": {
  5849  			DesiredTotal:    10,
  5850  			DesiredCanaries: 1,
  5851  		},
  5852  	}
  5853  	require.Nil(state.UpsertDeployment(2, d))
  5854  
  5855  	// Create a set of allocations for both groups, including an unhealthy one
  5856  	c1 := mock.Alloc()
  5857  	c1.JobID = j.ID
  5858  	c1.DeploymentID = d.ID
  5859  	d.TaskGroups[c1.TaskGroup].PlacedCanaries = append(d.TaskGroups[c1.TaskGroup].PlacedCanaries, c1.ID)
  5860  	c1.DeploymentStatus = &structs.AllocDeploymentStatus{
  5861  		Healthy: helper.BoolToPtr(true),
  5862  		Canary:  true,
  5863  	}
  5864  
  5865  	// Should still be a canary
  5866  	c2 := mock.Alloc()
  5867  	c2.JobID = j.ID
  5868  	c2.DeploymentID = d.ID
  5869  	d.TaskGroups[c2.TaskGroup].PlacedCanaries = append(d.TaskGroups[c2.TaskGroup].PlacedCanaries, c2.ID)
  5870  	c2.TaskGroup = tg2.Name
  5871  	c2.DeploymentStatus = &structs.AllocDeploymentStatus{
  5872  		Healthy: helper.BoolToPtr(true),
  5873  		Canary:  true,
  5874  	}
  5875  
  5876  	c3 := mock.Alloc()
  5877  	c3.JobID = j.ID
  5878  	c3.DeploymentID = d.ID
  5879  	d.TaskGroups[c3.TaskGroup].PlacedCanaries = append(d.TaskGroups[c3.TaskGroup].PlacedCanaries, c3.ID)
  5880  	c3.DeploymentStatus = &structs.AllocDeploymentStatus{
  5881  		Healthy: helper.BoolToPtr(false),
  5882  		Canary:  true,
  5883  	}
  5884  
  5885  	require.Nil(state.UpsertAllocs(3, []*structs.Allocation{c1, c2, c3}))
  5886  
  5887  	// Create an eval
  5888  	e := mock.Eval()
  5889  
  5890  	// Promote the canaries
  5891  	req := &structs.ApplyDeploymentPromoteRequest{
  5892  		DeploymentPromoteRequest: structs.DeploymentPromoteRequest{
  5893  			DeploymentID: d.ID,
  5894  			Groups:       []string{"web"},
  5895  		},
  5896  		Eval: e,
  5897  	}
  5898  	require.Nil(state.UpdateDeploymentPromotion(4, req))
  5899  
  5900  	// Check that the status per task group was updated properly
  5901  	ws := memdb.NewWatchSet()
  5902  	dout, err := state.DeploymentByID(ws, d.ID)
  5903  	require.Nil(err)
  5904  	require.Len(dout.TaskGroups, 2)
  5905  	require.Contains(dout.TaskGroups, "web")
  5906  	require.True(dout.TaskGroups["web"].Promoted)
  5907  
  5908  	// Check that the evaluation was created
  5909  	eout, err := state.EvalByID(ws, e.ID)
  5910  	require.Nil(err)
  5911  	require.NotNil(eout)
  5912  
  5913  	// Check the canary field was set properly
  5914  	aout1, err1 := state.AllocByID(ws, c1.ID)
  5915  	aout2, err2 := state.AllocByID(ws, c2.ID)
  5916  	aout3, err3 := state.AllocByID(ws, c3.ID)
  5917  	require.Nil(err1)
  5918  	require.Nil(err2)
  5919  	require.Nil(err3)
  5920  	require.NotNil(aout1)
  5921  	require.NotNil(aout2)
  5922  	require.NotNil(aout3)
  5923  	require.False(aout1.DeploymentStatus.Canary)
  5924  	require.True(aout2.DeploymentStatus.Canary)
  5925  	require.True(aout3.DeploymentStatus.Canary)
  5926  }
  5927  
  5928  // Test that allocation health can't be set against a nonexistent deployment
  5929  func TestStateStore_UpsertDeploymentAllocHealth_Nonexistent(t *testing.T) {
  5930  	state := testStateStore(t)
  5931  
  5932  	// Set health against the nonexistent deployment
  5933  	req := &structs.ApplyDeploymentAllocHealthRequest{
  5934  		DeploymentAllocHealthRequest: structs.DeploymentAllocHealthRequest{
  5935  			DeploymentID:         uuid.Generate(),
  5936  			HealthyAllocationIDs: []string{uuid.Generate()},
  5937  		},
  5938  	}
  5939  	err := state.UpdateDeploymentAllocHealth(2, req)
  5940  	if err == nil || !strings.Contains(err.Error(), "does not exist") {
  5941  		t.Fatalf("expected error because the deployment doesn't exist: %v", err)
  5942  	}
  5943  }
  5944  
  5945  // Test that allocation health can't be set against a terminal deployment
  5946  func TestStateStore_UpsertDeploymentAllocHealth_Terminal(t *testing.T) {
  5947  	state := testStateStore(t)
  5948  
  5949  	// Insert a terminal deployment
  5950  	d := mock.Deployment()
  5951  	d.Status = structs.DeploymentStatusFailed
  5952  
  5953  	if err := state.UpsertDeployment(1, d); err != nil {
  5954  		t.Fatalf("bad: %v", err)
  5955  	}
  5956  
  5957  	// Set health against the terminal deployment
  5958  	req := &structs.ApplyDeploymentAllocHealthRequest{
  5959  		DeploymentAllocHealthRequest: structs.DeploymentAllocHealthRequest{
  5960  			DeploymentID:         d.ID,
  5961  			HealthyAllocationIDs: []string{uuid.Generate()},
  5962  		},
  5963  	}
  5964  	err := state.UpdateDeploymentAllocHealth(2, req)
  5965  	if err == nil || !strings.Contains(err.Error(), "has terminal status") {
  5966  		t.Fatalf("expected error because the deployment is terminal: %v", err)
  5967  	}
  5968  }
  5969  
  5970  // Test that allocation health can't be set against a nonexistent alloc
  5971  func TestStateStore_UpsertDeploymentAllocHealth_BadAlloc_Nonexistent(t *testing.T) {
  5972  	state := testStateStore(t)
  5973  
  5974  	// Insert a deployment
  5975  	d := mock.Deployment()
  5976  	if err := state.UpsertDeployment(1, d); err != nil {
  5977  		t.Fatalf("bad: %v", err)
  5978  	}
  5979  
  5980  	// Set health against the terminal deployment
  5981  	req := &structs.ApplyDeploymentAllocHealthRequest{
  5982  		DeploymentAllocHealthRequest: structs.DeploymentAllocHealthRequest{
  5983  			DeploymentID:         d.ID,
  5984  			HealthyAllocationIDs: []string{uuid.Generate()},
  5985  		},
  5986  	}
  5987  	err := state.UpdateDeploymentAllocHealth(2, req)
  5988  	if err == nil || !strings.Contains(err.Error(), "unknown alloc") {
  5989  		t.Fatalf("expected error because the alloc doesn't exist: %v", err)
  5990  	}
  5991  }
  5992  
  5993  // Test that allocation health can't be set for an alloc with mismatched
  5994  // deployment ids
  5995  func TestStateStore_UpsertDeploymentAllocHealth_BadAlloc_MismatchDeployment(t *testing.T) {
  5996  	state := testStateStore(t)
  5997  
  5998  	// Insert two  deployment
  5999  	d1 := mock.Deployment()
  6000  	d2 := mock.Deployment()
  6001  	if err := state.UpsertDeployment(1, d1); err != nil {
  6002  		t.Fatalf("bad: %v", err)
  6003  	}
  6004  	if err := state.UpsertDeployment(2, d2); err != nil {
  6005  		t.Fatalf("bad: %v", err)
  6006  	}
  6007  
  6008  	// Insert an alloc for a random deployment
  6009  	a := mock.Alloc()
  6010  	a.DeploymentID = d1.ID
  6011  	if err := state.UpsertAllocs(3, []*structs.Allocation{a}); err != nil {
  6012  		t.Fatalf("bad: %v", err)
  6013  	}
  6014  
  6015  	// Set health against the terminal deployment
  6016  	req := &structs.ApplyDeploymentAllocHealthRequest{
  6017  		DeploymentAllocHealthRequest: structs.DeploymentAllocHealthRequest{
  6018  			DeploymentID:         d2.ID,
  6019  			HealthyAllocationIDs: []string{a.ID},
  6020  		},
  6021  	}
  6022  	err := state.UpdateDeploymentAllocHealth(4, req)
  6023  	if err == nil || !strings.Contains(err.Error(), "not part of deployment") {
  6024  		t.Fatalf("expected error because the alloc isn't part of the deployment: %v", err)
  6025  	}
  6026  }
  6027  
  6028  // Test that allocation health is properly set
  6029  func TestStateStore_UpsertDeploymentAllocHealth(t *testing.T) {
  6030  	state := testStateStore(t)
  6031  
  6032  	// Insert a deployment
  6033  	d := mock.Deployment()
  6034  	d.TaskGroups["web"].ProgressDeadline = 5 * time.Minute
  6035  	if err := state.UpsertDeployment(1, d); err != nil {
  6036  		t.Fatalf("bad: %v", err)
  6037  	}
  6038  
  6039  	// Insert two allocations
  6040  	a1 := mock.Alloc()
  6041  	a1.DeploymentID = d.ID
  6042  	a2 := mock.Alloc()
  6043  	a2.DeploymentID = d.ID
  6044  	if err := state.UpsertAllocs(2, []*structs.Allocation{a1, a2}); err != nil {
  6045  		t.Fatalf("bad: %v", err)
  6046  	}
  6047  
  6048  	// Create a job to roll back to
  6049  	j := mock.Job()
  6050  
  6051  	// Create an eval that should be upserted
  6052  	e := mock.Eval()
  6053  
  6054  	// Create a status update for the deployment
  6055  	status, desc := structs.DeploymentStatusFailed, "foo"
  6056  	u := &structs.DeploymentStatusUpdate{
  6057  		DeploymentID:      d.ID,
  6058  		Status:            status,
  6059  		StatusDescription: desc,
  6060  	}
  6061  
  6062  	// Capture the time for the update
  6063  	ts := time.Now()
  6064  
  6065  	// Set health against the deployment
  6066  	req := &structs.ApplyDeploymentAllocHealthRequest{
  6067  		DeploymentAllocHealthRequest: structs.DeploymentAllocHealthRequest{
  6068  			DeploymentID:           d.ID,
  6069  			HealthyAllocationIDs:   []string{a1.ID},
  6070  			UnhealthyAllocationIDs: []string{a2.ID},
  6071  		},
  6072  		Job:              j,
  6073  		Eval:             e,
  6074  		DeploymentUpdate: u,
  6075  		Timestamp:        ts,
  6076  	}
  6077  	err := state.UpdateDeploymentAllocHealth(3, req)
  6078  	if err != nil {
  6079  		t.Fatalf("bad: %v", err)
  6080  	}
  6081  
  6082  	// Check that the status was updated properly
  6083  	ws := memdb.NewWatchSet()
  6084  	dout, err := state.DeploymentByID(ws, d.ID)
  6085  	if err != nil {
  6086  		t.Fatalf("bad: %v", err)
  6087  	}
  6088  	if dout.Status != status || dout.StatusDescription != desc {
  6089  		t.Fatalf("bad: %#v", dout)
  6090  	}
  6091  
  6092  	// Check that the evaluation was created
  6093  	eout, _ := state.EvalByID(ws, e.ID)
  6094  	if err != nil {
  6095  		t.Fatalf("bad: %v", err)
  6096  	}
  6097  	if eout == nil {
  6098  		t.Fatalf("bad: %#v", eout)
  6099  	}
  6100  
  6101  	// Check that the job was created
  6102  	jout, _ := state.JobByID(ws, j.Namespace, j.ID)
  6103  	if err != nil {
  6104  		t.Fatalf("bad: %v", err)
  6105  	}
  6106  	if jout == nil {
  6107  		t.Fatalf("bad: %#v", jout)
  6108  	}
  6109  
  6110  	// Check the status of the allocs
  6111  	out1, err := state.AllocByID(ws, a1.ID)
  6112  	if err != nil {
  6113  		t.Fatalf("err: %v", err)
  6114  	}
  6115  	out2, err := state.AllocByID(ws, a2.ID)
  6116  	if err != nil {
  6117  		t.Fatalf("err: %v", err)
  6118  	}
  6119  
  6120  	if !out1.DeploymentStatus.IsHealthy() {
  6121  		t.Fatalf("bad: alloc %q not healthy", out1.ID)
  6122  	}
  6123  	if !out2.DeploymentStatus.IsUnhealthy() {
  6124  		t.Fatalf("bad: alloc %q not unhealthy", out2.ID)
  6125  	}
  6126  
  6127  	if !out1.DeploymentStatus.Timestamp.Equal(ts) {
  6128  		t.Fatalf("bad: alloc %q had timestamp %v; want %v", out1.ID, out1.DeploymentStatus.Timestamp, ts)
  6129  	}
  6130  	if !out2.DeploymentStatus.Timestamp.Equal(ts) {
  6131  		t.Fatalf("bad: alloc %q had timestamp %v; want %v", out2.ID, out2.DeploymentStatus.Timestamp, ts)
  6132  	}
  6133  }
  6134  
  6135  func TestStateStore_UpsertVaultAccessors(t *testing.T) {
  6136  	state := testStateStore(t)
  6137  	a := mock.VaultAccessor()
  6138  	a2 := mock.VaultAccessor()
  6139  
  6140  	ws := memdb.NewWatchSet()
  6141  	if _, err := state.VaultAccessor(ws, a.Accessor); err != nil {
  6142  		t.Fatalf("err: %v", err)
  6143  	}
  6144  
  6145  	if _, err := state.VaultAccessor(ws, a2.Accessor); err != nil {
  6146  		t.Fatalf("err: %v", err)
  6147  	}
  6148  
  6149  	err := state.UpsertVaultAccessor(1000, []*structs.VaultAccessor{a, a2})
  6150  	if err != nil {
  6151  		t.Fatalf("err: %v", err)
  6152  	}
  6153  
  6154  	if !watchFired(ws) {
  6155  		t.Fatalf("bad")
  6156  	}
  6157  
  6158  	ws = memdb.NewWatchSet()
  6159  	out, err := state.VaultAccessor(ws, a.Accessor)
  6160  	if err != nil {
  6161  		t.Fatalf("err: %v", err)
  6162  	}
  6163  
  6164  	if !reflect.DeepEqual(a, out) {
  6165  		t.Fatalf("bad: %#v %#v", a, out)
  6166  	}
  6167  
  6168  	out, err = state.VaultAccessor(ws, a2.Accessor)
  6169  	if err != nil {
  6170  		t.Fatalf("err: %v", err)
  6171  	}
  6172  
  6173  	if !reflect.DeepEqual(a2, out) {
  6174  		t.Fatalf("bad: %#v %#v", a2, out)
  6175  	}
  6176  
  6177  	iter, err := state.VaultAccessors(ws)
  6178  	if err != nil {
  6179  		t.Fatalf("err: %v", err)
  6180  	}
  6181  
  6182  	count := 0
  6183  	for {
  6184  		raw := iter.Next()
  6185  		if raw == nil {
  6186  			break
  6187  		}
  6188  
  6189  		count++
  6190  		accessor := raw.(*structs.VaultAccessor)
  6191  
  6192  		if !reflect.DeepEqual(accessor, a) && !reflect.DeepEqual(accessor, a2) {
  6193  			t.Fatalf("bad: %#v", accessor)
  6194  		}
  6195  	}
  6196  
  6197  	if count != 2 {
  6198  		t.Fatalf("bad: %d", count)
  6199  	}
  6200  
  6201  	index, err := state.Index("vault_accessors")
  6202  	if err != nil {
  6203  		t.Fatalf("err: %v", err)
  6204  	}
  6205  	if index != 1000 {
  6206  		t.Fatalf("bad: %d", index)
  6207  	}
  6208  
  6209  	if watchFired(ws) {
  6210  		t.Fatalf("bad")
  6211  	}
  6212  }
  6213  
  6214  func TestStateStore_DeleteVaultAccessors(t *testing.T) {
  6215  	state := testStateStore(t)
  6216  	a1 := mock.VaultAccessor()
  6217  	a2 := mock.VaultAccessor()
  6218  	accessors := []*structs.VaultAccessor{a1, a2}
  6219  
  6220  	err := state.UpsertVaultAccessor(1000, accessors)
  6221  	if err != nil {
  6222  		t.Fatalf("err: %v", err)
  6223  	}
  6224  
  6225  	ws := memdb.NewWatchSet()
  6226  	if _, err := state.VaultAccessor(ws, a1.Accessor); err != nil {
  6227  		t.Fatalf("err: %v", err)
  6228  	}
  6229  
  6230  	err = state.DeleteVaultAccessors(1001, accessors)
  6231  	if err != nil {
  6232  		t.Fatalf("err: %v", err)
  6233  	}
  6234  
  6235  	if !watchFired(ws) {
  6236  		t.Fatalf("bad")
  6237  	}
  6238  
  6239  	ws = memdb.NewWatchSet()
  6240  	out, err := state.VaultAccessor(ws, a1.Accessor)
  6241  	if err != nil {
  6242  		t.Fatalf("err: %v", err)
  6243  	}
  6244  	if out != nil {
  6245  		t.Fatalf("bad: %#v %#v", a1, out)
  6246  	}
  6247  	out, err = state.VaultAccessor(ws, a2.Accessor)
  6248  	if err != nil {
  6249  		t.Fatalf("err: %v", err)
  6250  	}
  6251  	if out != nil {
  6252  		t.Fatalf("bad: %#v %#v", a2, out)
  6253  	}
  6254  
  6255  	index, err := state.Index("vault_accessors")
  6256  	if err != nil {
  6257  		t.Fatalf("err: %v", err)
  6258  	}
  6259  	if index != 1001 {
  6260  		t.Fatalf("bad: %d", index)
  6261  	}
  6262  
  6263  	if watchFired(ws) {
  6264  		t.Fatalf("bad")
  6265  	}
  6266  }
  6267  
  6268  func TestStateStore_VaultAccessorsByAlloc(t *testing.T) {
  6269  	state := testStateStore(t)
  6270  	alloc := mock.Alloc()
  6271  	var accessors []*structs.VaultAccessor
  6272  	var expected []*structs.VaultAccessor
  6273  
  6274  	for i := 0; i < 5; i++ {
  6275  		accessor := mock.VaultAccessor()
  6276  		accessor.AllocID = alloc.ID
  6277  		expected = append(expected, accessor)
  6278  		accessors = append(accessors, accessor)
  6279  	}
  6280  
  6281  	for i := 0; i < 10; i++ {
  6282  		accessor := mock.VaultAccessor()
  6283  		accessors = append(accessors, accessor)
  6284  	}
  6285  
  6286  	err := state.UpsertVaultAccessor(1000, accessors)
  6287  	if err != nil {
  6288  		t.Fatalf("err: %v", err)
  6289  	}
  6290  
  6291  	ws := memdb.NewWatchSet()
  6292  	out, err := state.VaultAccessorsByAlloc(ws, alloc.ID)
  6293  	if err != nil {
  6294  		t.Fatalf("err: %v", err)
  6295  	}
  6296  
  6297  	if len(expected) != len(out) {
  6298  		t.Fatalf("bad: %#v %#v", len(expected), len(out))
  6299  	}
  6300  
  6301  	index, err := state.Index("vault_accessors")
  6302  	if err != nil {
  6303  		t.Fatalf("err: %v", err)
  6304  	}
  6305  	if index != 1000 {
  6306  		t.Fatalf("bad: %d", index)
  6307  	}
  6308  
  6309  	if watchFired(ws) {
  6310  		t.Fatalf("bad")
  6311  	}
  6312  }
  6313  
  6314  func TestStateStore_VaultAccessorsByNode(t *testing.T) {
  6315  	state := testStateStore(t)
  6316  	node := mock.Node()
  6317  	var accessors []*structs.VaultAccessor
  6318  	var expected []*structs.VaultAccessor
  6319  
  6320  	for i := 0; i < 5; i++ {
  6321  		accessor := mock.VaultAccessor()
  6322  		accessor.NodeID = node.ID
  6323  		expected = append(expected, accessor)
  6324  		accessors = append(accessors, accessor)
  6325  	}
  6326  
  6327  	for i := 0; i < 10; i++ {
  6328  		accessor := mock.VaultAccessor()
  6329  		accessors = append(accessors, accessor)
  6330  	}
  6331  
  6332  	err := state.UpsertVaultAccessor(1000, accessors)
  6333  	if err != nil {
  6334  		t.Fatalf("err: %v", err)
  6335  	}
  6336  
  6337  	ws := memdb.NewWatchSet()
  6338  	out, err := state.VaultAccessorsByNode(ws, node.ID)
  6339  	if err != nil {
  6340  		t.Fatalf("err: %v", err)
  6341  	}
  6342  
  6343  	if len(expected) != len(out) {
  6344  		t.Fatalf("bad: %#v %#v", len(expected), len(out))
  6345  	}
  6346  
  6347  	index, err := state.Index("vault_accessors")
  6348  	if err != nil {
  6349  		t.Fatalf("err: %v", err)
  6350  	}
  6351  	if index != 1000 {
  6352  		t.Fatalf("bad: %d", index)
  6353  	}
  6354  
  6355  	if watchFired(ws) {
  6356  		t.Fatalf("bad")
  6357  	}
  6358  }
  6359  
  6360  func TestStateStore_RestoreVaultAccessor(t *testing.T) {
  6361  	state := testStateStore(t)
  6362  	a := mock.VaultAccessor()
  6363  
  6364  	restore, err := state.Restore()
  6365  	if err != nil {
  6366  		t.Fatalf("err: %v", err)
  6367  	}
  6368  
  6369  	err = restore.VaultAccessorRestore(a)
  6370  	if err != nil {
  6371  		t.Fatalf("err: %v", err)
  6372  	}
  6373  	restore.Commit()
  6374  
  6375  	ws := memdb.NewWatchSet()
  6376  	out, err := state.VaultAccessor(ws, a.Accessor)
  6377  	if err != nil {
  6378  		t.Fatalf("err: %v", err)
  6379  	}
  6380  
  6381  	if !reflect.DeepEqual(out, a) {
  6382  		t.Fatalf("Bad: %#v %#v", out, a)
  6383  	}
  6384  
  6385  	if watchFired(ws) {
  6386  		t.Fatalf("bad")
  6387  	}
  6388  }
  6389  
  6390  func TestStateStore_UpsertACLPolicy(t *testing.T) {
  6391  	state := testStateStore(t)
  6392  	policy := mock.ACLPolicy()
  6393  	policy2 := mock.ACLPolicy()
  6394  
  6395  	ws := memdb.NewWatchSet()
  6396  	if _, err := state.ACLPolicyByName(ws, policy.Name); err != nil {
  6397  		t.Fatalf("err: %v", err)
  6398  	}
  6399  	if _, err := state.ACLPolicyByName(ws, policy2.Name); err != nil {
  6400  		t.Fatalf("err: %v", err)
  6401  	}
  6402  
  6403  	if err := state.UpsertACLPolicies(1000,
  6404  		[]*structs.ACLPolicy{policy, policy2}); err != nil {
  6405  		t.Fatalf("err: %v", err)
  6406  	}
  6407  	if !watchFired(ws) {
  6408  		t.Fatalf("bad")
  6409  	}
  6410  
  6411  	ws = memdb.NewWatchSet()
  6412  	out, err := state.ACLPolicyByName(ws, policy.Name)
  6413  	assert.Equal(t, nil, err)
  6414  	assert.Equal(t, policy, out)
  6415  
  6416  	out, err = state.ACLPolicyByName(ws, policy2.Name)
  6417  	assert.Equal(t, nil, err)
  6418  	assert.Equal(t, policy2, out)
  6419  
  6420  	iter, err := state.ACLPolicies(ws)
  6421  	if err != nil {
  6422  		t.Fatalf("err: %v", err)
  6423  	}
  6424  
  6425  	// Ensure we see both policies
  6426  	count := 0
  6427  	for {
  6428  		raw := iter.Next()
  6429  		if raw == nil {
  6430  			break
  6431  		}
  6432  		count++
  6433  	}
  6434  	if count != 2 {
  6435  		t.Fatalf("bad: %d", count)
  6436  	}
  6437  
  6438  	index, err := state.Index("acl_policy")
  6439  	if err != nil {
  6440  		t.Fatalf("err: %v", err)
  6441  	}
  6442  	if index != 1000 {
  6443  		t.Fatalf("bad: %d", index)
  6444  	}
  6445  
  6446  	if watchFired(ws) {
  6447  		t.Fatalf("bad")
  6448  	}
  6449  }
  6450  
  6451  func TestStateStore_DeleteACLPolicy(t *testing.T) {
  6452  	state := testStateStore(t)
  6453  	policy := mock.ACLPolicy()
  6454  	policy2 := mock.ACLPolicy()
  6455  
  6456  	// Create the policy
  6457  	if err := state.UpsertACLPolicies(1000,
  6458  		[]*structs.ACLPolicy{policy, policy2}); err != nil {
  6459  		t.Fatalf("err: %v", err)
  6460  	}
  6461  
  6462  	// Create a watcher
  6463  	ws := memdb.NewWatchSet()
  6464  	if _, err := state.ACLPolicyByName(ws, policy.Name); err != nil {
  6465  		t.Fatalf("err: %v", err)
  6466  	}
  6467  
  6468  	// Delete the policy
  6469  	if err := state.DeleteACLPolicies(1001,
  6470  		[]string{policy.Name, policy2.Name}); err != nil {
  6471  		t.Fatalf("err: %v", err)
  6472  	}
  6473  
  6474  	// Ensure watching triggered
  6475  	if !watchFired(ws) {
  6476  		t.Fatalf("bad")
  6477  	}
  6478  
  6479  	// Ensure we don't get the object back
  6480  	ws = memdb.NewWatchSet()
  6481  	out, err := state.ACLPolicyByName(ws, policy.Name)
  6482  	assert.Equal(t, nil, err)
  6483  	if out != nil {
  6484  		t.Fatalf("bad: %#v", out)
  6485  	}
  6486  
  6487  	iter, err := state.ACLPolicies(ws)
  6488  	if err != nil {
  6489  		t.Fatalf("err: %v", err)
  6490  	}
  6491  
  6492  	// Ensure we see both policies
  6493  	count := 0
  6494  	for {
  6495  		raw := iter.Next()
  6496  		if raw == nil {
  6497  			break
  6498  		}
  6499  		count++
  6500  	}
  6501  	if count != 0 {
  6502  		t.Fatalf("bad: %d", count)
  6503  	}
  6504  
  6505  	index, err := state.Index("acl_policy")
  6506  	if err != nil {
  6507  		t.Fatalf("err: %v", err)
  6508  	}
  6509  	if index != 1001 {
  6510  		t.Fatalf("bad: %d", index)
  6511  	}
  6512  
  6513  	if watchFired(ws) {
  6514  		t.Fatalf("bad")
  6515  	}
  6516  }
  6517  
  6518  func TestStateStore_ACLPolicyByNamePrefix(t *testing.T) {
  6519  	state := testStateStore(t)
  6520  	names := []string{
  6521  		"foo",
  6522  		"bar",
  6523  		"foobar",
  6524  		"foozip",
  6525  		"zip",
  6526  	}
  6527  
  6528  	// Create the policies
  6529  	var baseIndex uint64 = 1000
  6530  	for _, name := range names {
  6531  		p := mock.ACLPolicy()
  6532  		p.Name = name
  6533  		if err := state.UpsertACLPolicies(baseIndex, []*structs.ACLPolicy{p}); err != nil {
  6534  			t.Fatalf("err: %v", err)
  6535  		}
  6536  		baseIndex++
  6537  	}
  6538  
  6539  	// Scan by prefix
  6540  	iter, err := state.ACLPolicyByNamePrefix(nil, "foo")
  6541  	if err != nil {
  6542  		t.Fatalf("err: %v", err)
  6543  	}
  6544  
  6545  	// Ensure we see both policies
  6546  	count := 0
  6547  	out := []string{}
  6548  	for {
  6549  		raw := iter.Next()
  6550  		if raw == nil {
  6551  			break
  6552  		}
  6553  		count++
  6554  		out = append(out, raw.(*structs.ACLPolicy).Name)
  6555  	}
  6556  	if count != 3 {
  6557  		t.Fatalf("bad: %d %v", count, out)
  6558  	}
  6559  	sort.Strings(out)
  6560  
  6561  	expect := []string{"foo", "foobar", "foozip"}
  6562  	assert.Equal(t, expect, out)
  6563  }
  6564  
  6565  func TestStateStore_BootstrapACLTokens(t *testing.T) {
  6566  	state := testStateStore(t)
  6567  	tk1 := mock.ACLToken()
  6568  	tk2 := mock.ACLToken()
  6569  
  6570  	ok, resetIdx, err := state.CanBootstrapACLToken()
  6571  	assert.Nil(t, err)
  6572  	assert.Equal(t, true, ok)
  6573  	assert.EqualValues(t, 0, resetIdx)
  6574  
  6575  	if err := state.BootstrapACLTokens(1000, 0, tk1); err != nil {
  6576  		t.Fatalf("err: %v", err)
  6577  	}
  6578  
  6579  	out, err := state.ACLTokenByAccessorID(nil, tk1.AccessorID)
  6580  	assert.Equal(t, nil, err)
  6581  	assert.Equal(t, tk1, out)
  6582  
  6583  	ok, resetIdx, err = state.CanBootstrapACLToken()
  6584  	assert.Nil(t, err)
  6585  	assert.Equal(t, false, ok)
  6586  	assert.EqualValues(t, 1000, resetIdx)
  6587  
  6588  	if err := state.BootstrapACLTokens(1001, 0, tk2); err == nil {
  6589  		t.Fatalf("expected error")
  6590  	}
  6591  
  6592  	iter, err := state.ACLTokens(nil)
  6593  	if err != nil {
  6594  		t.Fatalf("err: %v", err)
  6595  	}
  6596  
  6597  	// Ensure we see both policies
  6598  	count := 0
  6599  	for {
  6600  		raw := iter.Next()
  6601  		if raw == nil {
  6602  			break
  6603  		}
  6604  		count++
  6605  	}
  6606  	if count != 1 {
  6607  		t.Fatalf("bad: %d", count)
  6608  	}
  6609  
  6610  	index, err := state.Index("acl_token")
  6611  	if err != nil {
  6612  		t.Fatalf("err: %v", err)
  6613  	}
  6614  	if index != 1000 {
  6615  		t.Fatalf("bad: %d", index)
  6616  	}
  6617  	index, err = state.Index("acl_token_bootstrap")
  6618  	if err != nil {
  6619  		t.Fatalf("err: %v", err)
  6620  	}
  6621  	if index != 1000 {
  6622  		t.Fatalf("bad: %d", index)
  6623  	}
  6624  
  6625  	// Should allow bootstrap with reset index
  6626  	if err := state.BootstrapACLTokens(1001, 1000, tk2); err != nil {
  6627  		t.Fatalf("err %v", err)
  6628  	}
  6629  
  6630  	// Check we've modified the index
  6631  	index, err = state.Index("acl_token")
  6632  	if err != nil {
  6633  		t.Fatalf("err: %v", err)
  6634  	}
  6635  	if index != 1001 {
  6636  		t.Fatalf("bad: %d", index)
  6637  	}
  6638  	index, err = state.Index("acl_token_bootstrap")
  6639  	if err != nil {
  6640  		t.Fatalf("err: %v", err)
  6641  	}
  6642  	if index != 1001 {
  6643  		t.Fatalf("bad: %d", index)
  6644  	}
  6645  }
  6646  
  6647  func TestStateStore_UpsertACLTokens(t *testing.T) {
  6648  	state := testStateStore(t)
  6649  	tk1 := mock.ACLToken()
  6650  	tk2 := mock.ACLToken()
  6651  
  6652  	ws := memdb.NewWatchSet()
  6653  	if _, err := state.ACLTokenByAccessorID(ws, tk1.AccessorID); err != nil {
  6654  		t.Fatalf("err: %v", err)
  6655  	}
  6656  	if _, err := state.ACLTokenByAccessorID(ws, tk2.AccessorID); err != nil {
  6657  		t.Fatalf("err: %v", err)
  6658  	}
  6659  
  6660  	if err := state.UpsertACLTokens(1000,
  6661  		[]*structs.ACLToken{tk1, tk2}); err != nil {
  6662  		t.Fatalf("err: %v", err)
  6663  	}
  6664  	if !watchFired(ws) {
  6665  		t.Fatalf("bad")
  6666  	}
  6667  
  6668  	ws = memdb.NewWatchSet()
  6669  	out, err := state.ACLTokenByAccessorID(ws, tk1.AccessorID)
  6670  	assert.Equal(t, nil, err)
  6671  	assert.Equal(t, tk1, out)
  6672  
  6673  	out, err = state.ACLTokenByAccessorID(ws, tk2.AccessorID)
  6674  	assert.Equal(t, nil, err)
  6675  	assert.Equal(t, tk2, out)
  6676  
  6677  	out, err = state.ACLTokenBySecretID(ws, tk1.SecretID)
  6678  	assert.Equal(t, nil, err)
  6679  	assert.Equal(t, tk1, out)
  6680  
  6681  	out, err = state.ACLTokenBySecretID(ws, tk2.SecretID)
  6682  	assert.Equal(t, nil, err)
  6683  	assert.Equal(t, tk2, out)
  6684  
  6685  	iter, err := state.ACLTokens(ws)
  6686  	if err != nil {
  6687  		t.Fatalf("err: %v", err)
  6688  	}
  6689  
  6690  	// Ensure we see both policies
  6691  	count := 0
  6692  	for {
  6693  		raw := iter.Next()
  6694  		if raw == nil {
  6695  			break
  6696  		}
  6697  		count++
  6698  	}
  6699  	if count != 2 {
  6700  		t.Fatalf("bad: %d", count)
  6701  	}
  6702  
  6703  	index, err := state.Index("acl_token")
  6704  	if err != nil {
  6705  		t.Fatalf("err: %v", err)
  6706  	}
  6707  	if index != 1000 {
  6708  		t.Fatalf("bad: %d", index)
  6709  	}
  6710  
  6711  	if watchFired(ws) {
  6712  		t.Fatalf("bad")
  6713  	}
  6714  }
  6715  
  6716  func TestStateStore_DeleteACLTokens(t *testing.T) {
  6717  	state := testStateStore(t)
  6718  	tk1 := mock.ACLToken()
  6719  	tk2 := mock.ACLToken()
  6720  
  6721  	// Create the tokens
  6722  	if err := state.UpsertACLTokens(1000,
  6723  		[]*structs.ACLToken{tk1, tk2}); err != nil {
  6724  		t.Fatalf("err: %v", err)
  6725  	}
  6726  
  6727  	// Create a watcher
  6728  	ws := memdb.NewWatchSet()
  6729  	if _, err := state.ACLTokenByAccessorID(ws, tk1.AccessorID); err != nil {
  6730  		t.Fatalf("err: %v", err)
  6731  	}
  6732  
  6733  	// Delete the token
  6734  	if err := state.DeleteACLTokens(1001,
  6735  		[]string{tk1.AccessorID, tk2.AccessorID}); err != nil {
  6736  		t.Fatalf("err: %v", err)
  6737  	}
  6738  
  6739  	// Ensure watching triggered
  6740  	if !watchFired(ws) {
  6741  		t.Fatalf("bad")
  6742  	}
  6743  
  6744  	// Ensure we don't get the object back
  6745  	ws = memdb.NewWatchSet()
  6746  	out, err := state.ACLTokenByAccessorID(ws, tk1.AccessorID)
  6747  	assert.Equal(t, nil, err)
  6748  	if out != nil {
  6749  		t.Fatalf("bad: %#v", out)
  6750  	}
  6751  
  6752  	iter, err := state.ACLTokens(ws)
  6753  	if err != nil {
  6754  		t.Fatalf("err: %v", err)
  6755  	}
  6756  
  6757  	// Ensure we see both policies
  6758  	count := 0
  6759  	for {
  6760  		raw := iter.Next()
  6761  		if raw == nil {
  6762  			break
  6763  		}
  6764  		count++
  6765  	}
  6766  	if count != 0 {
  6767  		t.Fatalf("bad: %d", count)
  6768  	}
  6769  
  6770  	index, err := state.Index("acl_token")
  6771  	if err != nil {
  6772  		t.Fatalf("err: %v", err)
  6773  	}
  6774  	if index != 1001 {
  6775  		t.Fatalf("bad: %d", index)
  6776  	}
  6777  
  6778  	if watchFired(ws) {
  6779  		t.Fatalf("bad")
  6780  	}
  6781  }
  6782  
  6783  func TestStateStore_ACLTokenByAccessorIDPrefix(t *testing.T) {
  6784  	state := testStateStore(t)
  6785  	prefixes := []string{
  6786  		"aaaa",
  6787  		"aabb",
  6788  		"bbbb",
  6789  		"bbcc",
  6790  		"ffff",
  6791  	}
  6792  
  6793  	// Create the tokens
  6794  	var baseIndex uint64 = 1000
  6795  	for _, prefix := range prefixes {
  6796  		tk := mock.ACLToken()
  6797  		tk.AccessorID = prefix + tk.AccessorID[4:]
  6798  		if err := state.UpsertACLTokens(baseIndex, []*structs.ACLToken{tk}); err != nil {
  6799  			t.Fatalf("err: %v", err)
  6800  		}
  6801  		baseIndex++
  6802  	}
  6803  
  6804  	// Scan by prefix
  6805  	iter, err := state.ACLTokenByAccessorIDPrefix(nil, "aa")
  6806  	if err != nil {
  6807  		t.Fatalf("err: %v", err)
  6808  	}
  6809  
  6810  	// Ensure we see both tokens
  6811  	count := 0
  6812  	out := []string{}
  6813  	for {
  6814  		raw := iter.Next()
  6815  		if raw == nil {
  6816  			break
  6817  		}
  6818  		count++
  6819  		out = append(out, raw.(*structs.ACLToken).AccessorID[:4])
  6820  	}
  6821  	if count != 2 {
  6822  		t.Fatalf("bad: %d %v", count, out)
  6823  	}
  6824  	sort.Strings(out)
  6825  
  6826  	expect := []string{"aaaa", "aabb"}
  6827  	assert.Equal(t, expect, out)
  6828  }
  6829  
  6830  func TestStateStore_RestoreACLPolicy(t *testing.T) {
  6831  	state := testStateStore(t)
  6832  	policy := mock.ACLPolicy()
  6833  
  6834  	restore, err := state.Restore()
  6835  	if err != nil {
  6836  		t.Fatalf("err: %v", err)
  6837  	}
  6838  
  6839  	err = restore.ACLPolicyRestore(policy)
  6840  	if err != nil {
  6841  		t.Fatalf("err: %v", err)
  6842  	}
  6843  	restore.Commit()
  6844  
  6845  	ws := memdb.NewWatchSet()
  6846  	out, err := state.ACLPolicyByName(ws, policy.Name)
  6847  	if err != nil {
  6848  		t.Fatalf("err: %v", err)
  6849  	}
  6850  	assert.Equal(t, policy, out)
  6851  }
  6852  
  6853  func TestStateStore_ACLTokensByGlobal(t *testing.T) {
  6854  	state := testStateStore(t)
  6855  	tk1 := mock.ACLToken()
  6856  	tk2 := mock.ACLToken()
  6857  	tk3 := mock.ACLToken()
  6858  	tk4 := mock.ACLToken()
  6859  	tk3.Global = true
  6860  
  6861  	if err := state.UpsertACLTokens(1000,
  6862  		[]*structs.ACLToken{tk1, tk2, tk3, tk4}); err != nil {
  6863  		t.Fatalf("err: %v", err)
  6864  	}
  6865  
  6866  	iter, err := state.ACLTokensByGlobal(nil, true)
  6867  	if err != nil {
  6868  		t.Fatalf("err: %v", err)
  6869  	}
  6870  
  6871  	// Ensure we see the one global policies
  6872  	count := 0
  6873  	for {
  6874  		raw := iter.Next()
  6875  		if raw == nil {
  6876  			break
  6877  		}
  6878  		count++
  6879  	}
  6880  	if count != 1 {
  6881  		t.Fatalf("bad: %d", count)
  6882  	}
  6883  }
  6884  
  6885  func TestStateStore_RestoreACLToken(t *testing.T) {
  6886  	state := testStateStore(t)
  6887  	token := mock.ACLToken()
  6888  
  6889  	restore, err := state.Restore()
  6890  	if err != nil {
  6891  		t.Fatalf("err: %v", err)
  6892  	}
  6893  
  6894  	err = restore.ACLTokenRestore(token)
  6895  	if err != nil {
  6896  		t.Fatalf("err: %v", err)
  6897  	}
  6898  	restore.Commit()
  6899  
  6900  	ws := memdb.NewWatchSet()
  6901  	out, err := state.ACLTokenByAccessorID(ws, token.AccessorID)
  6902  	if err != nil {
  6903  		t.Fatalf("err: %v", err)
  6904  	}
  6905  	assert.Equal(t, token, out)
  6906  }
  6907  
  6908  func TestStateStore_Abandon(t *testing.T) {
  6909  	s := testStateStore(t)
  6910  	abandonCh := s.AbandonCh()
  6911  	s.Abandon()
  6912  	select {
  6913  	case <-abandonCh:
  6914  	default:
  6915  		t.Fatalf("bad")
  6916  	}
  6917  }
  6918  
  6919  // watchFired is a helper for unit tests that returns if the given watch set
  6920  // fired (it doesn't care which watch actually fired). This uses a fixed
  6921  // timeout since we already expect the event happened before calling this and
  6922  // just need to distinguish a fire from a timeout. We do need a little time to
  6923  // allow the watch to set up any goroutines, though.
  6924  func watchFired(ws memdb.WatchSet) bool {
  6925  	timedOut := ws.Watch(time.After(50 * time.Millisecond))
  6926  	return !timedOut
  6927  }
  6928  
  6929  // NodeIDSort is used to sort nodes by ID
  6930  type NodeIDSort []*structs.Node
  6931  
  6932  func (n NodeIDSort) Len() int {
  6933  	return len(n)
  6934  }
  6935  
  6936  func (n NodeIDSort) Less(i, j int) bool {
  6937  	return n[i].ID < n[j].ID
  6938  }
  6939  
  6940  func (n NodeIDSort) Swap(i, j int) {
  6941  	n[i], n[j] = n[j], n[i]
  6942  }
  6943  
  6944  // JobIDis used to sort jobs by id
  6945  type JobIDSort []*structs.Job
  6946  
  6947  func (n JobIDSort) Len() int {
  6948  	return len(n)
  6949  }
  6950  
  6951  func (n JobIDSort) Less(i, j int) bool {
  6952  	return n[i].ID < n[j].ID
  6953  }
  6954  
  6955  func (n JobIDSort) Swap(i, j int) {
  6956  	n[i], n[j] = n[j], n[i]
  6957  }
  6958  
  6959  // EvalIDis used to sort evals by id
  6960  type EvalIDSort []*structs.Evaluation
  6961  
  6962  func (n EvalIDSort) Len() int {
  6963  	return len(n)
  6964  }
  6965  
  6966  func (n EvalIDSort) Less(i, j int) bool {
  6967  	return n[i].ID < n[j].ID
  6968  }
  6969  
  6970  func (n EvalIDSort) Swap(i, j int) {
  6971  	n[i], n[j] = n[j], n[i]
  6972  }
  6973  
  6974  // AllocIDsort used to sort allocations by id
  6975  type AllocIDSort []*structs.Allocation
  6976  
  6977  func (n AllocIDSort) Len() int {
  6978  	return len(n)
  6979  }
  6980  
  6981  func (n AllocIDSort) Less(i, j int) bool {
  6982  	return n[i].ID < n[j].ID
  6983  }
  6984  
  6985  func (n AllocIDSort) Swap(i, j int) {
  6986  	n[i], n[j] = n[j], n[i]
  6987  }