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