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