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

     1  package state
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"reflect"
     7  	"sort"
     8  	"testing"
     9  	"time"
    10  
    11  	memdb "github.com/hashicorp/go-memdb"
    12  	"github.com/hashicorp/nomad/nomad/mock"
    13  	"github.com/hashicorp/nomad/nomad/structs"
    14  )
    15  
    16  func testStateStore(t *testing.T) *StateStore {
    17  	state, err := NewStateStore(os.Stderr)
    18  	if err != nil {
    19  		t.Fatalf("err: %v", err)
    20  	}
    21  	if state == nil {
    22  		t.Fatalf("missing state")
    23  	}
    24  	return state
    25  }
    26  
    27  func TestStateStore_UpsertNode_Node(t *testing.T) {
    28  	state := testStateStore(t)
    29  	node := mock.Node()
    30  
    31  	// Create a watchset so we can test that upsert fires the watch
    32  	ws := memdb.NewWatchSet()
    33  	_, err := state.NodeByID(ws, node.ID)
    34  	if err != nil {
    35  		t.Fatalf("bad: %v", err)
    36  	}
    37  
    38  	err = state.UpsertNode(1000, node)
    39  	if err != nil {
    40  		t.Fatalf("err: %v", err)
    41  	}
    42  	if !watchFired(ws) {
    43  		t.Fatalf("bad")
    44  	}
    45  
    46  	ws = memdb.NewWatchSet()
    47  	out, err := state.NodeByID(ws, node.ID)
    48  	if err != nil {
    49  		t.Fatalf("err: %v", err)
    50  	}
    51  
    52  	if !reflect.DeepEqual(node, out) {
    53  		t.Fatalf("bad: %#v %#v", node, out)
    54  	}
    55  
    56  	index, err := state.Index("nodes")
    57  	if err != nil {
    58  		t.Fatalf("err: %v", err)
    59  	}
    60  	if index != 1000 {
    61  		t.Fatalf("bad: %d", index)
    62  	}
    63  
    64  	if watchFired(ws) {
    65  		t.Fatalf("bad")
    66  	}
    67  }
    68  
    69  func TestStateStore_DeleteNode_Node(t *testing.T) {
    70  	state := testStateStore(t)
    71  	node := mock.Node()
    72  
    73  	err := state.UpsertNode(1000, node)
    74  	if err != nil {
    75  		t.Fatalf("err: %v", err)
    76  	}
    77  
    78  	// Create a watchset so we can test that delete fires the watch
    79  	ws := memdb.NewWatchSet()
    80  	if _, err := state.NodeByID(ws, node.ID); err != nil {
    81  		t.Fatalf("bad: %v", err)
    82  	}
    83  
    84  	err = state.DeleteNode(1001, node.ID)
    85  	if err != nil {
    86  		t.Fatalf("err: %v", err)
    87  	}
    88  
    89  	if !watchFired(ws) {
    90  		t.Fatalf("bad")
    91  	}
    92  
    93  	ws = memdb.NewWatchSet()
    94  	out, err := state.NodeByID(ws, node.ID)
    95  	if err != nil {
    96  		t.Fatalf("err: %v", err)
    97  	}
    98  
    99  	if out != nil {
   100  		t.Fatalf("bad: %#v %#v", node, out)
   101  	}
   102  
   103  	index, err := state.Index("nodes")
   104  	if err != nil {
   105  		t.Fatalf("err: %v", err)
   106  	}
   107  	if index != 1001 {
   108  		t.Fatalf("bad: %d", index)
   109  	}
   110  
   111  	if watchFired(ws) {
   112  		t.Fatalf("bad")
   113  	}
   114  }
   115  
   116  func TestStateStore_UpdateNodeStatus_Node(t *testing.T) {
   117  	state := testStateStore(t)
   118  	node := mock.Node()
   119  
   120  	err := state.UpsertNode(800, node)
   121  	if err != nil {
   122  		t.Fatalf("err: %v", err)
   123  	}
   124  
   125  	// Create a watchset so we can test that update node status fires the watch
   126  	ws := memdb.NewWatchSet()
   127  	if _, err := state.NodeByID(ws, node.ID); err != nil {
   128  		t.Fatalf("bad: %v", err)
   129  	}
   130  
   131  	err = state.UpdateNodeStatus(801, node.ID, structs.NodeStatusReady)
   132  	if err != nil {
   133  		t.Fatalf("err: %v", err)
   134  	}
   135  
   136  	if !watchFired(ws) {
   137  		t.Fatalf("bad")
   138  	}
   139  
   140  	ws = memdb.NewWatchSet()
   141  	out, err := state.NodeByID(ws, node.ID)
   142  	if err != nil {
   143  		t.Fatalf("err: %v", err)
   144  	}
   145  
   146  	if out.Status != structs.NodeStatusReady {
   147  		t.Fatalf("bad: %#v", out)
   148  	}
   149  	if out.ModifyIndex != 801 {
   150  		t.Fatalf("bad: %#v", out)
   151  	}
   152  
   153  	index, err := state.Index("nodes")
   154  	if err != nil {
   155  		t.Fatalf("err: %v", err)
   156  	}
   157  	if index != 801 {
   158  		t.Fatalf("bad: %d", index)
   159  	}
   160  
   161  	if watchFired(ws) {
   162  		t.Fatalf("bad")
   163  	}
   164  }
   165  
   166  func TestStateStore_UpdateNodeDrain_Node(t *testing.T) {
   167  	state := testStateStore(t)
   168  	node := mock.Node()
   169  
   170  	err := state.UpsertNode(1000, node)
   171  	if err != nil {
   172  		t.Fatalf("err: %v", err)
   173  	}
   174  
   175  	// Create a watchset so we can test that update node drain fires the watch
   176  	ws := memdb.NewWatchSet()
   177  	if _, err := state.NodeByID(ws, node.ID); err != nil {
   178  		t.Fatalf("bad: %v", err)
   179  	}
   180  
   181  	err = state.UpdateNodeDrain(1001, node.ID, true)
   182  	if err != nil {
   183  		t.Fatalf("err: %v", err)
   184  	}
   185  
   186  	if !watchFired(ws) {
   187  		t.Fatalf("bad")
   188  	}
   189  
   190  	ws = memdb.NewWatchSet()
   191  	out, err := state.NodeByID(ws, node.ID)
   192  	if err != nil {
   193  		t.Fatalf("err: %v", err)
   194  	}
   195  
   196  	if !out.Drain {
   197  		t.Fatalf("bad: %#v", out)
   198  	}
   199  	if out.ModifyIndex != 1001 {
   200  		t.Fatalf("bad: %#v", out)
   201  	}
   202  
   203  	index, err := state.Index("nodes")
   204  	if err != nil {
   205  		t.Fatalf("err: %v", err)
   206  	}
   207  	if index != 1001 {
   208  		t.Fatalf("bad: %d", index)
   209  	}
   210  
   211  	if watchFired(ws) {
   212  		t.Fatalf("bad")
   213  	}
   214  }
   215  
   216  func TestStateStore_Nodes(t *testing.T) {
   217  	state := testStateStore(t)
   218  	var nodes []*structs.Node
   219  
   220  	for i := 0; i < 10; i++ {
   221  		node := mock.Node()
   222  		nodes = append(nodes, node)
   223  
   224  		err := state.UpsertNode(1000+uint64(i), node)
   225  		if err != nil {
   226  			t.Fatalf("err: %v", err)
   227  		}
   228  	}
   229  
   230  	// Create a watchset so we can test that getters don't cause it to fire
   231  	ws := memdb.NewWatchSet()
   232  	iter, err := state.Nodes(ws)
   233  	if err != nil {
   234  		t.Fatalf("bad: %v", err)
   235  	}
   236  
   237  	var out []*structs.Node
   238  	for {
   239  		raw := iter.Next()
   240  		if raw == nil {
   241  			break
   242  		}
   243  		out = append(out, raw.(*structs.Node))
   244  	}
   245  
   246  	sort.Sort(NodeIDSort(nodes))
   247  	sort.Sort(NodeIDSort(out))
   248  
   249  	if !reflect.DeepEqual(nodes, out) {
   250  		t.Fatalf("bad: %#v %#v", nodes, out)
   251  	}
   252  
   253  	if watchFired(ws) {
   254  		t.Fatalf("bad")
   255  	}
   256  }
   257  
   258  func TestStateStore_NodesByIDPrefix(t *testing.T) {
   259  	state := testStateStore(t)
   260  	node := mock.Node()
   261  
   262  	node.ID = "11111111-662e-d0ab-d1c9-3e434af7bdb4"
   263  	err := state.UpsertNode(1000, node)
   264  	if err != nil {
   265  		t.Fatalf("err: %v", err)
   266  	}
   267  
   268  	// Create a watchset so we can test that getters don't cause it to fire
   269  	ws := memdb.NewWatchSet()
   270  	iter, err := state.NodesByIDPrefix(ws, node.ID)
   271  	if err != nil {
   272  		t.Fatalf("err: %v", err)
   273  	}
   274  
   275  	gatherNodes := func(iter memdb.ResultIterator) []*structs.Node {
   276  		var nodes []*structs.Node
   277  		for {
   278  			raw := iter.Next()
   279  			if raw == nil {
   280  				break
   281  			}
   282  			node := raw.(*structs.Node)
   283  			nodes = append(nodes, node)
   284  		}
   285  		return nodes
   286  	}
   287  
   288  	nodes := gatherNodes(iter)
   289  	if len(nodes) != 1 {
   290  		t.Fatalf("err: %v", err)
   291  	}
   292  
   293  	if watchFired(ws) {
   294  		t.Fatalf("bad")
   295  	}
   296  
   297  	iter, err = state.NodesByIDPrefix(ws, "11")
   298  	if err != nil {
   299  		t.Fatalf("err: %v", err)
   300  	}
   301  
   302  	nodes = gatherNodes(iter)
   303  	if len(nodes) != 1 {
   304  		t.Fatalf("err: %v", err)
   305  	}
   306  
   307  	node = mock.Node()
   308  	node.ID = "11222222-662e-d0ab-d1c9-3e434af7bdb4"
   309  	err = state.UpsertNode(1001, node)
   310  	if err != nil {
   311  		t.Fatalf("err: %v", err)
   312  	}
   313  
   314  	if !watchFired(ws) {
   315  		t.Fatalf("bad")
   316  	}
   317  
   318  	ws = memdb.NewWatchSet()
   319  	iter, err = state.NodesByIDPrefix(ws, "11")
   320  	if err != nil {
   321  		t.Fatalf("err: %v", err)
   322  	}
   323  
   324  	nodes = gatherNodes(iter)
   325  	if len(nodes) != 2 {
   326  		t.Fatalf("err: %v", err)
   327  	}
   328  
   329  	iter, err = state.NodesByIDPrefix(ws, "1111")
   330  	if err != nil {
   331  		t.Fatalf("err: %v", err)
   332  	}
   333  
   334  	nodes = gatherNodes(iter)
   335  	if len(nodes) != 1 {
   336  		t.Fatalf("err: %v", err)
   337  	}
   338  
   339  	if watchFired(ws) {
   340  		t.Fatalf("bad")
   341  	}
   342  }
   343  
   344  func TestStateStore_RestoreNode(t *testing.T) {
   345  	state := testStateStore(t)
   346  	node := mock.Node()
   347  
   348  	restore, err := state.Restore()
   349  	if err != nil {
   350  		t.Fatalf("err: %v", err)
   351  	}
   352  
   353  	err = restore.NodeRestore(node)
   354  	if err != nil {
   355  		t.Fatalf("err: %v", err)
   356  	}
   357  	restore.Commit()
   358  
   359  	ws := memdb.NewWatchSet()
   360  	out, err := state.NodeByID(ws, node.ID)
   361  	if err != nil {
   362  		t.Fatalf("err: %v", err)
   363  	}
   364  
   365  	if !reflect.DeepEqual(out, node) {
   366  		t.Fatalf("Bad: %#v %#v", out, node)
   367  	}
   368  }
   369  
   370  func TestStateStore_UpsertJob_Job(t *testing.T) {
   371  	state := testStateStore(t)
   372  	job := mock.Job()
   373  
   374  	// Create a watchset so we can test that upsert fires the watch
   375  	ws := memdb.NewWatchSet()
   376  	_, err := state.JobByID(ws, job.ID)
   377  	if err != nil {
   378  		t.Fatalf("bad: %v", err)
   379  	}
   380  
   381  	if err := state.UpsertJob(1000, job); err != nil {
   382  		t.Fatalf("err: %v", err)
   383  	}
   384  	if !watchFired(ws) {
   385  		t.Fatalf("bad")
   386  	}
   387  
   388  	ws = memdb.NewWatchSet()
   389  	out, err := state.JobByID(ws, job.ID)
   390  	if err != nil {
   391  		t.Fatalf("err: %v", err)
   392  	}
   393  
   394  	if !reflect.DeepEqual(job, out) {
   395  		t.Fatalf("bad: %#v %#v", job, out)
   396  	}
   397  
   398  	index, err := state.Index("jobs")
   399  	if err != nil {
   400  		t.Fatalf("err: %v", err)
   401  	}
   402  	if index != 1000 {
   403  		t.Fatalf("bad: %d", index)
   404  	}
   405  
   406  	summary, err := state.JobSummaryByID(ws, job.ID)
   407  	if err != nil {
   408  		t.Fatalf("err: %v", err)
   409  	}
   410  	if summary == nil {
   411  		t.Fatalf("nil summary")
   412  	}
   413  	if summary.JobID != job.ID {
   414  		t.Fatalf("bad summary id: %v", summary.JobID)
   415  	}
   416  	_, ok := summary.Summary["web"]
   417  	if !ok {
   418  		t.Fatalf("nil summary for task group")
   419  	}
   420  	if watchFired(ws) {
   421  		t.Fatalf("bad")
   422  	}
   423  }
   424  
   425  func TestStateStore_UpdateUpsertJob_Job(t *testing.T) {
   426  	state := testStateStore(t)
   427  	job := mock.Job()
   428  
   429  	// Create a watchset so we can test that upsert fires the watch
   430  	ws := memdb.NewWatchSet()
   431  	_, err := state.JobByID(ws, job.ID)
   432  	if err != nil {
   433  		t.Fatalf("bad: %v", err)
   434  	}
   435  
   436  	if err := state.UpsertJob(1000, job); err != nil {
   437  		t.Fatalf("err: %v", err)
   438  	}
   439  
   440  	job2 := mock.Job()
   441  	job2.ID = job.ID
   442  	err = state.UpsertJob(1001, job2)
   443  	if err != nil {
   444  		t.Fatalf("err: %v", err)
   445  	}
   446  
   447  	if !watchFired(ws) {
   448  		t.Fatalf("bad")
   449  	}
   450  
   451  	ws = memdb.NewWatchSet()
   452  	out, err := state.JobByID(ws, job.ID)
   453  	if err != nil {
   454  		t.Fatalf("err: %v", err)
   455  	}
   456  
   457  	if !reflect.DeepEqual(job2, out) {
   458  		t.Fatalf("bad: %#v %#v", job2, out)
   459  	}
   460  
   461  	if out.CreateIndex != 1000 {
   462  		t.Fatalf("bad: %#v", out)
   463  	}
   464  	if out.ModifyIndex != 1001 {
   465  		t.Fatalf("bad: %#v", out)
   466  	}
   467  
   468  	index, err := state.Index("jobs")
   469  	if err != nil {
   470  		t.Fatalf("err: %v", err)
   471  	}
   472  	if index != 1001 {
   473  		t.Fatalf("bad: %d", index)
   474  	}
   475  
   476  	// Test that the job summary remains the same if the job is updated but
   477  	// count remains same
   478  	summary, err := state.JobSummaryByID(ws, job.ID)
   479  	if err != nil {
   480  		t.Fatalf("err: %v", err)
   481  	}
   482  	if summary == nil {
   483  		t.Fatalf("nil summary")
   484  	}
   485  	if summary.JobID != job.ID {
   486  		t.Fatalf("bad summary id: %v", summary.JobID)
   487  	}
   488  	_, ok := summary.Summary["web"]
   489  	if !ok {
   490  		t.Fatalf("nil summary for task group")
   491  	}
   492  
   493  	if watchFired(ws) {
   494  		t.Fatalf("bad")
   495  	}
   496  }
   497  
   498  func TestStateStore_UpdateUpsertJob_PeriodicJob(t *testing.T) {
   499  	state := testStateStore(t)
   500  	job := mock.PeriodicJob()
   501  
   502  	// Create a watchset so we can test that upsert fires the watch
   503  	ws := memdb.NewWatchSet()
   504  	_, err := state.JobByID(ws, job.ID)
   505  	if err != nil {
   506  		t.Fatalf("bad: %v", err)
   507  	}
   508  
   509  	if err := state.UpsertJob(1000, job); err != nil {
   510  		t.Fatalf("err: %v", err)
   511  	}
   512  
   513  	// Create a child and an evaluation
   514  	job2 := job.Copy()
   515  	job2.Periodic = nil
   516  	job2.ID = fmt.Sprintf("%v/%s-1490635020", job.ID, structs.PeriodicLaunchSuffix)
   517  	err = state.UpsertJob(1001, job2)
   518  	if err != nil {
   519  		t.Fatalf("err: %v", err)
   520  	}
   521  
   522  	eval := mock.Eval()
   523  	eval.JobID = job2.ID
   524  	err = state.UpsertEvals(1002, []*structs.Evaluation{eval})
   525  	if err != nil {
   526  		t.Fatalf("err: %v", err)
   527  	}
   528  
   529  	job3 := job.Copy()
   530  	job3.TaskGroups[0].Tasks[0].Name = "new name"
   531  	err = state.UpsertJob(1003, job3)
   532  	if err != nil {
   533  		t.Fatalf("err: %v", err)
   534  	}
   535  
   536  	if !watchFired(ws) {
   537  		t.Fatalf("bad")
   538  	}
   539  
   540  	ws = memdb.NewWatchSet()
   541  	out, err := state.JobByID(ws, job.ID)
   542  	if err != nil {
   543  		t.Fatalf("err: %v", err)
   544  	}
   545  
   546  	if s, e := out.Status, structs.JobStatusRunning; s != e {
   547  		t.Fatalf("got status %v; want %v", s, e)
   548  	}
   549  
   550  }
   551  
   552  // This test ensures that UpsertJob creates the EphemeralDisk is a job doesn't have
   553  // one and clear out the task's disk resource asks
   554  // COMPAT 0.4.1 -> 0.5
   555  func TestStateStore_UpsertJob_NoEphemeralDisk(t *testing.T) {
   556  	state := testStateStore(t)
   557  	job := mock.Job()
   558  
   559  	// Set the EphemeralDisk to nil and set the tasks's DiskMB to 150
   560  	job.TaskGroups[0].EphemeralDisk = nil
   561  	job.TaskGroups[0].Tasks[0].Resources.DiskMB = 150
   562  
   563  	err := state.UpsertJob(1000, job)
   564  	if err != nil {
   565  		t.Fatalf("err: %v", err)
   566  	}
   567  
   568  	ws := memdb.NewWatchSet()
   569  	out, err := state.JobByID(ws, job.ID)
   570  	if err != nil {
   571  		t.Fatalf("err: %v", err)
   572  	}
   573  
   574  	// Expect the state store to create the EphemeralDisk and clear out Tasks's
   575  	// DiskMB
   576  	expected := job.Copy()
   577  	expected.TaskGroups[0].EphemeralDisk = &structs.EphemeralDisk{
   578  		SizeMB: 150,
   579  	}
   580  	expected.TaskGroups[0].Tasks[0].Resources.DiskMB = 0
   581  
   582  	if !reflect.DeepEqual(expected, out) {
   583  		t.Fatalf("bad: %#v %#v", expected, out)
   584  	}
   585  }
   586  
   587  // Upsert a job that is the child of a parent job and ensures its summary gets
   588  // updated.
   589  func TestStateStore_UpsertJob_ChildJob(t *testing.T) {
   590  	state := testStateStore(t)
   591  
   592  	// Create a watchset so we can test that upsert fires the watch
   593  	parent := mock.Job()
   594  	ws := memdb.NewWatchSet()
   595  	_, err := state.JobByID(ws, parent.ID)
   596  	if err != nil {
   597  		t.Fatalf("bad: %v", err)
   598  	}
   599  
   600  	if err := state.UpsertJob(1000, parent); err != nil {
   601  		t.Fatalf("err: %v", err)
   602  	}
   603  
   604  	child := mock.Job()
   605  	child.ParentID = parent.ID
   606  	if err := state.UpsertJob(1001, child); err != nil {
   607  		t.Fatalf("err: %v", err)
   608  	}
   609  
   610  	summary, err := state.JobSummaryByID(ws, parent.ID)
   611  	if err != nil {
   612  		t.Fatalf("err: %v", err)
   613  	}
   614  	if summary == nil {
   615  		t.Fatalf("nil summary")
   616  	}
   617  	if summary.JobID != parent.ID {
   618  		t.Fatalf("bad summary id: %v", parent.ID)
   619  	}
   620  	if summary.Children == nil {
   621  		t.Fatalf("nil children summary")
   622  	}
   623  	if summary.Children.Pending != 1 || summary.Children.Running != 0 || summary.Children.Dead != 0 {
   624  		t.Fatalf("bad children summary: %v", summary.Children)
   625  	}
   626  	if !watchFired(ws) {
   627  		t.Fatalf("bad")
   628  	}
   629  }
   630  
   631  func TestStateStore_DeleteJob_Job(t *testing.T) {
   632  	state := testStateStore(t)
   633  	job := mock.Job()
   634  
   635  	err := state.UpsertJob(1000, job)
   636  	if err != nil {
   637  		t.Fatalf("err: %v", err)
   638  	}
   639  
   640  	// Create a watchset so we can test that delete fires the watch
   641  	ws := memdb.NewWatchSet()
   642  	if _, err := state.JobByID(ws, job.ID); err != nil {
   643  		t.Fatalf("bad: %v", err)
   644  	}
   645  
   646  	err = state.DeleteJob(1001, job.ID)
   647  	if err != nil {
   648  		t.Fatalf("err: %v", err)
   649  	}
   650  
   651  	if !watchFired(ws) {
   652  		t.Fatalf("bad")
   653  	}
   654  
   655  	ws = memdb.NewWatchSet()
   656  	out, err := state.JobByID(ws, job.ID)
   657  	if err != nil {
   658  		t.Fatalf("err: %v", err)
   659  	}
   660  
   661  	if out != nil {
   662  		t.Fatalf("bad: %#v %#v", job, out)
   663  	}
   664  
   665  	index, err := state.Index("jobs")
   666  	if err != nil {
   667  		t.Fatalf("err: %v", err)
   668  	}
   669  	if index != 1001 {
   670  		t.Fatalf("bad: %d", index)
   671  	}
   672  
   673  	summary, err := state.JobSummaryByID(ws, job.ID)
   674  	if err != nil {
   675  		t.Fatalf("err: %v", err)
   676  	}
   677  	if summary != nil {
   678  		t.Fatalf("expected summary to be nil, but got: %v", summary)
   679  	}
   680  
   681  	if watchFired(ws) {
   682  		t.Fatalf("bad")
   683  	}
   684  }
   685  
   686  func TestStateStore_DeleteJob_ChildJob(t *testing.T) {
   687  	state := testStateStore(t)
   688  
   689  	parent := mock.Job()
   690  	if err := state.UpsertJob(998, parent); err != nil {
   691  		t.Fatalf("err: %v", err)
   692  	}
   693  
   694  	child := mock.Job()
   695  	child.ParentID = parent.ID
   696  
   697  	if err := state.UpsertJob(999, child); err != nil {
   698  		t.Fatalf("err: %v", err)
   699  	}
   700  
   701  	// Create a watchset so we can test that delete fires the watch
   702  	ws := memdb.NewWatchSet()
   703  	if _, err := state.JobSummaryByID(ws, parent.ID); err != nil {
   704  		t.Fatalf("bad: %v", err)
   705  	}
   706  
   707  	err := state.DeleteJob(1001, child.ID)
   708  	if err != nil {
   709  		t.Fatalf("err: %v", err)
   710  	}
   711  	if !watchFired(ws) {
   712  		t.Fatalf("bad")
   713  	}
   714  
   715  	ws = memdb.NewWatchSet()
   716  	summary, err := state.JobSummaryByID(ws, parent.ID)
   717  	if err != nil {
   718  		t.Fatalf("err: %v", err)
   719  	}
   720  	if summary == nil {
   721  		t.Fatalf("nil summary")
   722  	}
   723  	if summary.JobID != parent.ID {
   724  		t.Fatalf("bad summary id: %v", parent.ID)
   725  	}
   726  	if summary.Children == nil {
   727  		t.Fatalf("nil children summary")
   728  	}
   729  	if summary.Children.Pending != 0 || summary.Children.Running != 0 || summary.Children.Dead != 1 {
   730  		t.Fatalf("bad children summary: %v", summary.Children)
   731  	}
   732  	if watchFired(ws) {
   733  		t.Fatalf("bad")
   734  	}
   735  }
   736  
   737  func TestStateStore_Jobs(t *testing.T) {
   738  	state := testStateStore(t)
   739  	var jobs []*structs.Job
   740  
   741  	for i := 0; i < 10; i++ {
   742  		job := mock.Job()
   743  		jobs = append(jobs, job)
   744  
   745  		err := state.UpsertJob(1000+uint64(i), job)
   746  		if err != nil {
   747  			t.Fatalf("err: %v", err)
   748  		}
   749  	}
   750  
   751  	ws := memdb.NewWatchSet()
   752  	iter, err := state.Jobs(ws)
   753  	if err != nil {
   754  		t.Fatalf("err: %v", err)
   755  	}
   756  
   757  	var out []*structs.Job
   758  	for {
   759  		raw := iter.Next()
   760  		if raw == nil {
   761  			break
   762  		}
   763  		out = append(out, raw.(*structs.Job))
   764  	}
   765  
   766  	sort.Sort(JobIDSort(jobs))
   767  	sort.Sort(JobIDSort(out))
   768  
   769  	if !reflect.DeepEqual(jobs, out) {
   770  		t.Fatalf("bad: %#v %#v", jobs, out)
   771  	}
   772  	if watchFired(ws) {
   773  		t.Fatalf("bad")
   774  	}
   775  }
   776  
   777  func TestStateStore_JobsByIDPrefix(t *testing.T) {
   778  	state := testStateStore(t)
   779  	job := mock.Job()
   780  
   781  	job.ID = "redis"
   782  	err := state.UpsertJob(1000, job)
   783  	if err != nil {
   784  		t.Fatalf("err: %v", err)
   785  	}
   786  
   787  	ws := memdb.NewWatchSet()
   788  	iter, err := state.JobsByIDPrefix(ws, job.ID)
   789  	if err != nil {
   790  		t.Fatalf("err: %v", err)
   791  	}
   792  
   793  	gatherJobs := func(iter memdb.ResultIterator) []*structs.Job {
   794  		var jobs []*structs.Job
   795  		for {
   796  			raw := iter.Next()
   797  			if raw == nil {
   798  				break
   799  			}
   800  			jobs = append(jobs, raw.(*structs.Job))
   801  		}
   802  		return jobs
   803  	}
   804  
   805  	jobs := gatherJobs(iter)
   806  	if len(jobs) != 1 {
   807  		t.Fatalf("err: %v", err)
   808  	}
   809  
   810  	iter, err = state.JobsByIDPrefix(ws, "re")
   811  	if err != nil {
   812  		t.Fatalf("err: %v", err)
   813  	}
   814  
   815  	jobs = gatherJobs(iter)
   816  	if len(jobs) != 1 {
   817  		t.Fatalf("err: %v", err)
   818  	}
   819  	if watchFired(ws) {
   820  		t.Fatalf("bad")
   821  	}
   822  
   823  	job = mock.Job()
   824  	job.ID = "riak"
   825  	err = state.UpsertJob(1001, job)
   826  	if err != nil {
   827  		t.Fatalf("err: %v", err)
   828  	}
   829  
   830  	if !watchFired(ws) {
   831  		t.Fatalf("bad")
   832  	}
   833  
   834  	ws = memdb.NewWatchSet()
   835  	iter, err = state.JobsByIDPrefix(ws, "r")
   836  	if err != nil {
   837  		t.Fatalf("err: %v", err)
   838  	}
   839  
   840  	jobs = gatherJobs(iter)
   841  	if len(jobs) != 2 {
   842  		t.Fatalf("err: %v", err)
   843  	}
   844  
   845  	iter, err = state.JobsByIDPrefix(ws, "ri")
   846  	if err != nil {
   847  		t.Fatalf("err: %v", err)
   848  	}
   849  
   850  	jobs = gatherJobs(iter)
   851  	if len(jobs) != 1 {
   852  		t.Fatalf("err: %v", err)
   853  	}
   854  	if watchFired(ws) {
   855  		t.Fatalf("bad")
   856  	}
   857  }
   858  
   859  func TestStateStore_JobsByPeriodic(t *testing.T) {
   860  	state := testStateStore(t)
   861  	var periodic, nonPeriodic []*structs.Job
   862  
   863  	for i := 0; i < 10; i++ {
   864  		job := mock.Job()
   865  		nonPeriodic = append(nonPeriodic, job)
   866  
   867  		err := state.UpsertJob(1000+uint64(i), job)
   868  		if err != nil {
   869  			t.Fatalf("err: %v", err)
   870  		}
   871  	}
   872  
   873  	for i := 0; i < 10; i++ {
   874  		job := mock.PeriodicJob()
   875  		periodic = append(periodic, job)
   876  
   877  		err := state.UpsertJob(2000+uint64(i), job)
   878  		if err != nil {
   879  			t.Fatalf("err: %v", err)
   880  		}
   881  	}
   882  
   883  	ws := memdb.NewWatchSet()
   884  	iter, err := state.JobsByPeriodic(ws, true)
   885  	if err != nil {
   886  		t.Fatalf("err: %v", err)
   887  	}
   888  
   889  	var outPeriodic []*structs.Job
   890  	for {
   891  		raw := iter.Next()
   892  		if raw == nil {
   893  			break
   894  		}
   895  		outPeriodic = append(outPeriodic, raw.(*structs.Job))
   896  	}
   897  
   898  	iter, err = state.JobsByPeriodic(ws, false)
   899  	if err != nil {
   900  		t.Fatalf("err: %v", err)
   901  	}
   902  
   903  	var outNonPeriodic []*structs.Job
   904  	for {
   905  		raw := iter.Next()
   906  		if raw == nil {
   907  			break
   908  		}
   909  		outNonPeriodic = append(outNonPeriodic, raw.(*structs.Job))
   910  	}
   911  
   912  	sort.Sort(JobIDSort(periodic))
   913  	sort.Sort(JobIDSort(nonPeriodic))
   914  	sort.Sort(JobIDSort(outPeriodic))
   915  	sort.Sort(JobIDSort(outNonPeriodic))
   916  
   917  	if !reflect.DeepEqual(periodic, outPeriodic) {
   918  		t.Fatalf("bad: %#v %#v", periodic, outPeriodic)
   919  	}
   920  
   921  	if !reflect.DeepEqual(nonPeriodic, outNonPeriodic) {
   922  		t.Fatalf("bad: %#v %#v", nonPeriodic, outNonPeriodic)
   923  	}
   924  	if watchFired(ws) {
   925  		t.Fatalf("bad")
   926  	}
   927  }
   928  
   929  func TestStateStore_JobsByScheduler(t *testing.T) {
   930  	state := testStateStore(t)
   931  	var serviceJobs []*structs.Job
   932  	var sysJobs []*structs.Job
   933  
   934  	for i := 0; i < 10; i++ {
   935  		job := mock.Job()
   936  		serviceJobs = append(serviceJobs, job)
   937  
   938  		err := state.UpsertJob(1000+uint64(i), job)
   939  		if err != nil {
   940  			t.Fatalf("err: %v", err)
   941  		}
   942  	}
   943  
   944  	for i := 0; i < 10; i++ {
   945  		job := mock.SystemJob()
   946  		sysJobs = append(sysJobs, job)
   947  
   948  		err := state.UpsertJob(2000+uint64(i), job)
   949  		if err != nil {
   950  			t.Fatalf("err: %v", err)
   951  		}
   952  	}
   953  
   954  	ws := memdb.NewWatchSet()
   955  	iter, err := state.JobsByScheduler(ws, "service")
   956  	if err != nil {
   957  		t.Fatalf("err: %v", err)
   958  	}
   959  
   960  	var outService []*structs.Job
   961  	for {
   962  		raw := iter.Next()
   963  		if raw == nil {
   964  			break
   965  		}
   966  		outService = append(outService, raw.(*structs.Job))
   967  	}
   968  
   969  	iter, err = state.JobsByScheduler(ws, "system")
   970  	if err != nil {
   971  		t.Fatalf("err: %v", err)
   972  	}
   973  
   974  	var outSystem []*structs.Job
   975  	for {
   976  		raw := iter.Next()
   977  		if raw == nil {
   978  			break
   979  		}
   980  		outSystem = append(outSystem, raw.(*structs.Job))
   981  	}
   982  
   983  	sort.Sort(JobIDSort(serviceJobs))
   984  	sort.Sort(JobIDSort(sysJobs))
   985  	sort.Sort(JobIDSort(outService))
   986  	sort.Sort(JobIDSort(outSystem))
   987  
   988  	if !reflect.DeepEqual(serviceJobs, outService) {
   989  		t.Fatalf("bad: %#v %#v", serviceJobs, outService)
   990  	}
   991  
   992  	if !reflect.DeepEqual(sysJobs, outSystem) {
   993  		t.Fatalf("bad: %#v %#v", sysJobs, outSystem)
   994  	}
   995  	if watchFired(ws) {
   996  		t.Fatalf("bad")
   997  	}
   998  }
   999  
  1000  func TestStateStore_JobsByGC(t *testing.T) {
  1001  	state := testStateStore(t)
  1002  	var gc, nonGc []*structs.Job
  1003  
  1004  	for i := 0; i < 20; i++ {
  1005  		var job *structs.Job
  1006  		if i%2 == 0 {
  1007  			job = mock.Job()
  1008  		} else {
  1009  			job = mock.PeriodicJob()
  1010  		}
  1011  		nonGc = append(nonGc, job)
  1012  
  1013  		if err := state.UpsertJob(1000+uint64(i), job); err != nil {
  1014  			t.Fatalf("err: %v", err)
  1015  		}
  1016  	}
  1017  
  1018  	for i := 0; i < 10; i++ {
  1019  		job := mock.Job()
  1020  		job.Type = structs.JobTypeBatch
  1021  		gc = append(gc, job)
  1022  
  1023  		if err := state.UpsertJob(2000+uint64(i), job); err != nil {
  1024  			t.Fatalf("err: %v", err)
  1025  		}
  1026  	}
  1027  
  1028  	ws := memdb.NewWatchSet()
  1029  	iter, err := state.JobsByGC(ws, true)
  1030  	if err != nil {
  1031  		t.Fatalf("err: %v", err)
  1032  	}
  1033  
  1034  	var outGc []*structs.Job
  1035  	for i := iter.Next(); i != nil; i = iter.Next() {
  1036  		outGc = append(outGc, i.(*structs.Job))
  1037  	}
  1038  
  1039  	iter, err = state.JobsByGC(ws, false)
  1040  	if err != nil {
  1041  		t.Fatalf("err: %v", err)
  1042  	}
  1043  
  1044  	var outNonGc []*structs.Job
  1045  	for i := iter.Next(); i != nil; i = iter.Next() {
  1046  		outNonGc = append(outNonGc, i.(*structs.Job))
  1047  	}
  1048  
  1049  	sort.Sort(JobIDSort(gc))
  1050  	sort.Sort(JobIDSort(nonGc))
  1051  	sort.Sort(JobIDSort(outGc))
  1052  	sort.Sort(JobIDSort(outNonGc))
  1053  
  1054  	if !reflect.DeepEqual(gc, outGc) {
  1055  		t.Fatalf("bad: %#v %#v", gc, outGc)
  1056  	}
  1057  
  1058  	if !reflect.DeepEqual(nonGc, outNonGc) {
  1059  		t.Fatalf("bad: %#v %#v", nonGc, outNonGc)
  1060  	}
  1061  	if watchFired(ws) {
  1062  		t.Fatalf("bad")
  1063  	}
  1064  }
  1065  
  1066  func TestStateStore_RestoreJob(t *testing.T) {
  1067  	state := testStateStore(t)
  1068  	job := mock.Job()
  1069  
  1070  	restore, err := state.Restore()
  1071  	if err != nil {
  1072  		t.Fatalf("err: %v", err)
  1073  	}
  1074  
  1075  	err = restore.JobRestore(job)
  1076  	if err != nil {
  1077  		t.Fatalf("err: %v", err)
  1078  	}
  1079  	restore.Commit()
  1080  
  1081  	ws := memdb.NewWatchSet()
  1082  	out, err := state.JobByID(ws, job.ID)
  1083  	if err != nil {
  1084  		t.Fatalf("err: %v", err)
  1085  	}
  1086  
  1087  	if !reflect.DeepEqual(out, job) {
  1088  		t.Fatalf("Bad: %#v %#v", out, job)
  1089  	}
  1090  }
  1091  
  1092  // This test ensures that the state restore creates the EphemeralDisk for a job if
  1093  // it doesn't have one
  1094  // COMPAT 0.4.1 -> 0.5
  1095  func TestStateStore_Jobs_NoEphemeralDisk(t *testing.T) {
  1096  	state := testStateStore(t)
  1097  	job := mock.Job()
  1098  
  1099  	// Set EphemeralDisk to nil and set the DiskMB to 150
  1100  	job.TaskGroups[0].EphemeralDisk = nil
  1101  	job.TaskGroups[0].Tasks[0].Resources.DiskMB = 150
  1102  
  1103  	restore, err := state.Restore()
  1104  	if err != nil {
  1105  		t.Fatalf("err: %v", err)
  1106  	}
  1107  
  1108  	err = restore.JobRestore(job)
  1109  	if err != nil {
  1110  		t.Fatalf("err: %v", err)
  1111  	}
  1112  	restore.Commit()
  1113  
  1114  	ws := memdb.NewWatchSet()
  1115  	out, err := state.JobByID(ws, job.ID)
  1116  	if err != nil {
  1117  		t.Fatalf("err: %v", err)
  1118  	}
  1119  
  1120  	// Expect job to have local disk and clear out the task's disk resource ask
  1121  	expected := job.Copy()
  1122  	expected.TaskGroups[0].EphemeralDisk = &structs.EphemeralDisk{
  1123  		SizeMB: 150,
  1124  	}
  1125  	expected.TaskGroups[0].Tasks[0].Resources.DiskMB = 0
  1126  	if !reflect.DeepEqual(out, expected) {
  1127  		t.Fatalf("Bad: %#v %#v", out, job)
  1128  	}
  1129  }
  1130  
  1131  func TestStateStore_UpsertPeriodicLaunch(t *testing.T) {
  1132  	state := testStateStore(t)
  1133  	job := mock.Job()
  1134  	launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()}
  1135  
  1136  	// Create a watchset so we can test that upsert fires the watch
  1137  	ws := memdb.NewWatchSet()
  1138  	if _, err := state.PeriodicLaunchByID(ws, launch.ID); err != nil {
  1139  		t.Fatalf("bad: %v", err)
  1140  	}
  1141  
  1142  	err := state.UpsertPeriodicLaunch(1000, launch)
  1143  	if err != nil {
  1144  		t.Fatalf("err: %v", err)
  1145  	}
  1146  
  1147  	if !watchFired(ws) {
  1148  		t.Fatalf("bad")
  1149  	}
  1150  
  1151  	ws = memdb.NewWatchSet()
  1152  	out, err := state.PeriodicLaunchByID(ws, job.ID)
  1153  	if err != nil {
  1154  		t.Fatalf("err: %v", err)
  1155  	}
  1156  	if out.CreateIndex != 1000 {
  1157  		t.Fatalf("bad: %#v", out)
  1158  	}
  1159  	if out.ModifyIndex != 1000 {
  1160  		t.Fatalf("bad: %#v", out)
  1161  	}
  1162  
  1163  	if !reflect.DeepEqual(launch, out) {
  1164  		t.Fatalf("bad: %#v %#v", job, out)
  1165  	}
  1166  
  1167  	index, err := state.Index("periodic_launch")
  1168  	if err != nil {
  1169  		t.Fatalf("err: %v", err)
  1170  	}
  1171  	if index != 1000 {
  1172  		t.Fatalf("bad: %d", index)
  1173  	}
  1174  
  1175  	if watchFired(ws) {
  1176  		t.Fatalf("bad")
  1177  	}
  1178  }
  1179  
  1180  func TestStateStore_UpdateUpsertPeriodicLaunch(t *testing.T) {
  1181  	state := testStateStore(t)
  1182  	job := mock.Job()
  1183  	launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()}
  1184  
  1185  	err := state.UpsertPeriodicLaunch(1000, launch)
  1186  	if err != nil {
  1187  		t.Fatalf("err: %v", err)
  1188  	}
  1189  
  1190  	// Create a watchset so we can test that upsert fires the watch
  1191  	ws := memdb.NewWatchSet()
  1192  	if _, err := state.PeriodicLaunchByID(ws, launch.ID); err != nil {
  1193  		t.Fatalf("bad: %v", err)
  1194  	}
  1195  
  1196  	launch2 := &structs.PeriodicLaunch{
  1197  		ID:     job.ID,
  1198  		Launch: launch.Launch.Add(1 * time.Second),
  1199  	}
  1200  	err = state.UpsertPeriodicLaunch(1001, launch2)
  1201  	if err != nil {
  1202  		t.Fatalf("err: %v", err)
  1203  	}
  1204  
  1205  	if !watchFired(ws) {
  1206  		t.Fatalf("bad")
  1207  	}
  1208  
  1209  	ws = memdb.NewWatchSet()
  1210  	out, err := state.PeriodicLaunchByID(ws, job.ID)
  1211  	if err != nil {
  1212  		t.Fatalf("err: %v", err)
  1213  	}
  1214  	if out.CreateIndex != 1000 {
  1215  		t.Fatalf("bad: %#v", out)
  1216  	}
  1217  	if out.ModifyIndex != 1001 {
  1218  		t.Fatalf("bad: %#v", out)
  1219  	}
  1220  
  1221  	if !reflect.DeepEqual(launch2, out) {
  1222  		t.Fatalf("bad: %#v %#v", launch2, out)
  1223  	}
  1224  
  1225  	index, err := state.Index("periodic_launch")
  1226  	if err != nil {
  1227  		t.Fatalf("err: %v", err)
  1228  	}
  1229  	if index != 1001 {
  1230  		t.Fatalf("bad: %d", index)
  1231  	}
  1232  
  1233  	if watchFired(ws) {
  1234  		t.Fatalf("bad")
  1235  	}
  1236  }
  1237  
  1238  func TestStateStore_DeletePeriodicLaunch(t *testing.T) {
  1239  	state := testStateStore(t)
  1240  	job := mock.Job()
  1241  	launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()}
  1242  
  1243  	err := state.UpsertPeriodicLaunch(1000, launch)
  1244  	if err != nil {
  1245  		t.Fatalf("err: %v", err)
  1246  	}
  1247  
  1248  	// Create a watchset so we can test that delete fires the watch
  1249  	ws := memdb.NewWatchSet()
  1250  	if _, err := state.PeriodicLaunchByID(ws, launch.ID); err != nil {
  1251  		t.Fatalf("bad: %v", err)
  1252  	}
  1253  
  1254  	err = state.DeletePeriodicLaunch(1001, launch.ID)
  1255  	if err != nil {
  1256  		t.Fatalf("err: %v", err)
  1257  	}
  1258  
  1259  	if !watchFired(ws) {
  1260  		t.Fatalf("bad")
  1261  	}
  1262  
  1263  	ws = memdb.NewWatchSet()
  1264  	out, err := state.PeriodicLaunchByID(ws, job.ID)
  1265  	if err != nil {
  1266  		t.Fatalf("err: %v", err)
  1267  	}
  1268  
  1269  	if out != nil {
  1270  		t.Fatalf("bad: %#v %#v", job, out)
  1271  	}
  1272  
  1273  	index, err := state.Index("periodic_launch")
  1274  	if err != nil {
  1275  		t.Fatalf("err: %v", err)
  1276  	}
  1277  	if index != 1001 {
  1278  		t.Fatalf("bad: %d", index)
  1279  	}
  1280  
  1281  	if watchFired(ws) {
  1282  		t.Fatalf("bad")
  1283  	}
  1284  }
  1285  
  1286  func TestStateStore_PeriodicLaunches(t *testing.T) {
  1287  	state := testStateStore(t)
  1288  	var launches []*structs.PeriodicLaunch
  1289  
  1290  	for i := 0; i < 10; i++ {
  1291  		job := mock.Job()
  1292  		launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()}
  1293  		launches = append(launches, launch)
  1294  
  1295  		err := state.UpsertPeriodicLaunch(1000+uint64(i), launch)
  1296  		if err != nil {
  1297  			t.Fatalf("err: %v", err)
  1298  		}
  1299  	}
  1300  
  1301  	ws := memdb.NewWatchSet()
  1302  	iter, err := state.PeriodicLaunches(ws)
  1303  	if err != nil {
  1304  		t.Fatalf("err: %v", err)
  1305  	}
  1306  
  1307  	out := make(map[string]*structs.PeriodicLaunch, 10)
  1308  	for {
  1309  		raw := iter.Next()
  1310  		if raw == nil {
  1311  			break
  1312  		}
  1313  		launch := raw.(*structs.PeriodicLaunch)
  1314  		if _, ok := out[launch.ID]; ok {
  1315  			t.Fatalf("duplicate: %v", launch.ID)
  1316  		}
  1317  
  1318  		out[launch.ID] = launch
  1319  	}
  1320  
  1321  	for _, launch := range launches {
  1322  		l, ok := out[launch.ID]
  1323  		if !ok {
  1324  			t.Fatalf("bad %v", launch.ID)
  1325  		}
  1326  
  1327  		if !reflect.DeepEqual(launch, l) {
  1328  			t.Fatalf("bad: %#v %#v", launch, l)
  1329  		}
  1330  
  1331  		delete(out, launch.ID)
  1332  	}
  1333  
  1334  	if len(out) != 0 {
  1335  		t.Fatalf("leftover: %#v", out)
  1336  	}
  1337  
  1338  	if watchFired(ws) {
  1339  		t.Fatalf("bad")
  1340  	}
  1341  }
  1342  
  1343  func TestStateStore_RestorePeriodicLaunch(t *testing.T) {
  1344  	state := testStateStore(t)
  1345  	job := mock.Job()
  1346  	launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()}
  1347  
  1348  	restore, err := state.Restore()
  1349  	if err != nil {
  1350  		t.Fatalf("err: %v", err)
  1351  	}
  1352  
  1353  	err = restore.PeriodicLaunchRestore(launch)
  1354  	if err != nil {
  1355  		t.Fatalf("err: %v", err)
  1356  	}
  1357  	restore.Commit()
  1358  
  1359  	ws := memdb.NewWatchSet()
  1360  	out, err := state.PeriodicLaunchByID(ws, job.ID)
  1361  	if err != nil {
  1362  		t.Fatalf("err: %v", err)
  1363  	}
  1364  
  1365  	if !reflect.DeepEqual(out, launch) {
  1366  		t.Fatalf("Bad: %#v %#v", out, job)
  1367  	}
  1368  
  1369  	if watchFired(ws) {
  1370  		t.Fatalf("bad")
  1371  	}
  1372  }
  1373  
  1374  func TestStateStore_RestoreJobSummary(t *testing.T) {
  1375  	state := testStateStore(t)
  1376  	job := mock.Job()
  1377  	jobSummary := &structs.JobSummary{
  1378  		JobID: job.ID,
  1379  		Summary: map[string]structs.TaskGroupSummary{
  1380  			"web": structs.TaskGroupSummary{
  1381  				Starting: 10,
  1382  			},
  1383  		},
  1384  	}
  1385  	restore, err := state.Restore()
  1386  	if err != nil {
  1387  		t.Fatalf("err: %v", err)
  1388  	}
  1389  
  1390  	err = restore.JobSummaryRestore(jobSummary)
  1391  	if err != nil {
  1392  		t.Fatalf("err: %v", err)
  1393  	}
  1394  	restore.Commit()
  1395  
  1396  	ws := memdb.NewWatchSet()
  1397  	out, err := state.JobSummaryByID(ws, job.ID)
  1398  	if err != nil {
  1399  		t.Fatalf("err: %v", err)
  1400  	}
  1401  
  1402  	if !reflect.DeepEqual(out, jobSummary) {
  1403  		t.Fatalf("Bad: %#v %#v", out, jobSummary)
  1404  	}
  1405  }
  1406  
  1407  func TestStateStore_Indexes(t *testing.T) {
  1408  	state := testStateStore(t)
  1409  	node := mock.Node()
  1410  
  1411  	err := state.UpsertNode(1000, node)
  1412  	if err != nil {
  1413  		t.Fatalf("err: %v", err)
  1414  	}
  1415  
  1416  	iter, err := state.Indexes()
  1417  	if err != nil {
  1418  		t.Fatalf("err: %v", err)
  1419  	}
  1420  
  1421  	var out []*IndexEntry
  1422  	for {
  1423  		raw := iter.Next()
  1424  		if raw == nil {
  1425  			break
  1426  		}
  1427  		out = append(out, raw.(*IndexEntry))
  1428  	}
  1429  
  1430  	expect := []*IndexEntry{
  1431  		&IndexEntry{"nodes", 1000},
  1432  	}
  1433  
  1434  	if !reflect.DeepEqual(expect, out) {
  1435  		t.Fatalf("bad: %#v %#v", expect, out)
  1436  	}
  1437  }
  1438  
  1439  func TestStateStore_LatestIndex(t *testing.T) {
  1440  	state := testStateStore(t)
  1441  
  1442  	if err := state.UpsertNode(1000, mock.Node()); err != nil {
  1443  		t.Fatalf("err: %v", err)
  1444  	}
  1445  
  1446  	exp := uint64(2000)
  1447  	if err := state.UpsertJob(exp, mock.Job()); err != nil {
  1448  		t.Fatalf("err: %v", err)
  1449  	}
  1450  
  1451  	latest, err := state.LatestIndex()
  1452  	if err != nil {
  1453  		t.Fatalf("err: %v", err)
  1454  	}
  1455  
  1456  	if latest != exp {
  1457  		t.Fatalf("LatestIndex() returned %d; want %d", latest, exp)
  1458  	}
  1459  }
  1460  
  1461  func TestStateStore_RestoreIndex(t *testing.T) {
  1462  	state := testStateStore(t)
  1463  
  1464  	restore, err := state.Restore()
  1465  	if err != nil {
  1466  		t.Fatalf("err: %v", err)
  1467  	}
  1468  
  1469  	index := &IndexEntry{"jobs", 1000}
  1470  	err = restore.IndexRestore(index)
  1471  	if err != nil {
  1472  		t.Fatalf("err: %v", err)
  1473  	}
  1474  
  1475  	restore.Commit()
  1476  
  1477  	out, err := state.Index("jobs")
  1478  	if err != nil {
  1479  		t.Fatalf("err: %v", err)
  1480  	}
  1481  
  1482  	if out != 1000 {
  1483  		t.Fatalf("Bad: %#v %#v", out, 1000)
  1484  	}
  1485  }
  1486  
  1487  func TestStateStore_UpsertEvals_Eval(t *testing.T) {
  1488  	state := testStateStore(t)
  1489  	eval := mock.Eval()
  1490  
  1491  	// Create a watchset so we can test that upsert fires the watch
  1492  	ws := memdb.NewWatchSet()
  1493  	if _, err := state.EvalByID(ws, eval.ID); err != nil {
  1494  		t.Fatalf("bad: %v", err)
  1495  	}
  1496  
  1497  	err := state.UpsertEvals(1000, []*structs.Evaluation{eval})
  1498  	if err != nil {
  1499  		t.Fatalf("err: %v", err)
  1500  	}
  1501  
  1502  	if !watchFired(ws) {
  1503  		t.Fatalf("bad")
  1504  	}
  1505  
  1506  	ws = memdb.NewWatchSet()
  1507  	out, err := state.EvalByID(ws, eval.ID)
  1508  	if err != nil {
  1509  		t.Fatalf("err: %v", err)
  1510  	}
  1511  
  1512  	if !reflect.DeepEqual(eval, out) {
  1513  		t.Fatalf("bad: %#v %#v", eval, out)
  1514  	}
  1515  
  1516  	index, err := state.Index("evals")
  1517  	if err != nil {
  1518  		t.Fatalf("err: %v", err)
  1519  	}
  1520  	if index != 1000 {
  1521  		t.Fatalf("bad: %d", index)
  1522  	}
  1523  
  1524  	if watchFired(ws) {
  1525  		t.Fatalf("bad")
  1526  	}
  1527  }
  1528  
  1529  func TestStateStore_UpsertEvals_CancelBlocked(t *testing.T) {
  1530  	state := testStateStore(t)
  1531  
  1532  	// Create two blocked evals for the same job
  1533  	j := "test-job"
  1534  	b1, b2 := mock.Eval(), mock.Eval()
  1535  	b1.JobID = j
  1536  	b1.Status = structs.EvalStatusBlocked
  1537  	b2.JobID = j
  1538  	b2.Status = structs.EvalStatusBlocked
  1539  
  1540  	err := state.UpsertEvals(999, []*structs.Evaluation{b1, b2})
  1541  	if err != nil {
  1542  		t.Fatalf("err: %v", err)
  1543  	}
  1544  
  1545  	// Create one complete and successful eval for the job
  1546  	eval := mock.Eval()
  1547  	eval.JobID = j
  1548  	eval.Status = structs.EvalStatusComplete
  1549  
  1550  	// Create a watchset so we can test that the upsert of the complete eval
  1551  	// fires the watch
  1552  	ws := memdb.NewWatchSet()
  1553  	if _, err := state.EvalByID(ws, b1.ID); err != nil {
  1554  		t.Fatalf("bad: %v", err)
  1555  	}
  1556  	if _, err := state.EvalByID(ws, b2.ID); err != nil {
  1557  		t.Fatalf("bad: %v", err)
  1558  	}
  1559  
  1560  	if err := state.UpsertEvals(1000, []*structs.Evaluation{eval}); err != nil {
  1561  		t.Fatalf("err: %v", err)
  1562  	}
  1563  
  1564  	if !watchFired(ws) {
  1565  		t.Fatalf("bad")
  1566  	}
  1567  
  1568  	ws = memdb.NewWatchSet()
  1569  	out, err := state.EvalByID(ws, eval.ID)
  1570  	if err != nil {
  1571  		t.Fatalf("err: %v", err)
  1572  	}
  1573  
  1574  	if !reflect.DeepEqual(eval, out) {
  1575  		t.Fatalf("bad: %#v %#v", eval, out)
  1576  	}
  1577  
  1578  	index, err := state.Index("evals")
  1579  	if err != nil {
  1580  		t.Fatalf("err: %v", err)
  1581  	}
  1582  	if index != 1000 {
  1583  		t.Fatalf("bad: %d", index)
  1584  	}
  1585  
  1586  	// Get b1/b2 and check they are cancelled
  1587  	out1, err := state.EvalByID(ws, b1.ID)
  1588  	if err != nil {
  1589  		t.Fatalf("err: %v", err)
  1590  	}
  1591  
  1592  	out2, err := state.EvalByID(ws, b2.ID)
  1593  	if err != nil {
  1594  		t.Fatalf("err: %v", err)
  1595  	}
  1596  
  1597  	if out1.Status != structs.EvalStatusCancelled || out2.Status != structs.EvalStatusCancelled {
  1598  		t.Fatalf("bad: %#v %#v", out1, out2)
  1599  	}
  1600  
  1601  	if watchFired(ws) {
  1602  		t.Fatalf("bad")
  1603  	}
  1604  }
  1605  
  1606  func TestStateStore_Update_UpsertEvals_Eval(t *testing.T) {
  1607  	state := testStateStore(t)
  1608  	eval := mock.Eval()
  1609  
  1610  	err := state.UpsertEvals(1000, []*structs.Evaluation{eval})
  1611  	if err != nil {
  1612  		t.Fatalf("err: %v", err)
  1613  	}
  1614  
  1615  	// Create a watchset so we can test that delete fires the watch
  1616  	ws := memdb.NewWatchSet()
  1617  	ws2 := memdb.NewWatchSet()
  1618  	if _, err := state.EvalByID(ws, eval.ID); err != nil {
  1619  		t.Fatalf("bad: %v", err)
  1620  	}
  1621  
  1622  	if _, err := state.EvalsByJob(ws2, eval.JobID); err != nil {
  1623  		t.Fatalf("bad: %v", err)
  1624  	}
  1625  
  1626  	eval2 := mock.Eval()
  1627  	eval2.ID = eval.ID
  1628  	eval2.JobID = eval.JobID
  1629  	err = state.UpsertEvals(1001, []*structs.Evaluation{eval2})
  1630  	if err != nil {
  1631  		t.Fatalf("err: %v", err)
  1632  	}
  1633  
  1634  	if !watchFired(ws) {
  1635  		t.Fatalf("bad")
  1636  	}
  1637  	if !watchFired(ws2) {
  1638  		t.Fatalf("bad")
  1639  	}
  1640  
  1641  	ws = memdb.NewWatchSet()
  1642  	out, err := state.EvalByID(ws, eval.ID)
  1643  	if err != nil {
  1644  		t.Fatalf("err: %v", err)
  1645  	}
  1646  
  1647  	if !reflect.DeepEqual(eval2, out) {
  1648  		t.Fatalf("bad: %#v %#v", eval2, out)
  1649  	}
  1650  
  1651  	if out.CreateIndex != 1000 {
  1652  		t.Fatalf("bad: %#v", out)
  1653  	}
  1654  	if out.ModifyIndex != 1001 {
  1655  		t.Fatalf("bad: %#v", out)
  1656  	}
  1657  
  1658  	index, err := state.Index("evals")
  1659  	if err != nil {
  1660  		t.Fatalf("err: %v", err)
  1661  	}
  1662  	if index != 1001 {
  1663  		t.Fatalf("bad: %d", index)
  1664  	}
  1665  
  1666  	if watchFired(ws) {
  1667  		t.Fatalf("bad")
  1668  	}
  1669  }
  1670  
  1671  func TestStateStore_UpsertEvals_Eval_ChildJob(t *testing.T) {
  1672  	state := testStateStore(t)
  1673  
  1674  	parent := mock.Job()
  1675  	if err := state.UpsertJob(998, parent); err != nil {
  1676  		t.Fatalf("err: %v", err)
  1677  	}
  1678  
  1679  	child := mock.Job()
  1680  	child.ParentID = parent.ID
  1681  
  1682  	if err := state.UpsertJob(999, child); err != nil {
  1683  		t.Fatalf("err: %v", err)
  1684  	}
  1685  
  1686  	eval := mock.Eval()
  1687  	eval.Status = structs.EvalStatusComplete
  1688  	eval.JobID = child.ID
  1689  
  1690  	// Create watchsets so we can test that upsert fires the watch
  1691  	ws := memdb.NewWatchSet()
  1692  	ws2 := memdb.NewWatchSet()
  1693  	ws3 := memdb.NewWatchSet()
  1694  	if _, err := state.JobSummaryByID(ws, parent.ID); err != nil {
  1695  		t.Fatalf("bad: %v", err)
  1696  	}
  1697  	if _, err := state.EvalByID(ws2, eval.ID); err != nil {
  1698  		t.Fatalf("bad: %v", err)
  1699  	}
  1700  	if _, err := state.EvalsByJob(ws3, eval.JobID); err != nil {
  1701  		t.Fatalf("bad: %v", err)
  1702  	}
  1703  
  1704  	err := state.UpsertEvals(1000, []*structs.Evaluation{eval})
  1705  	if err != nil {
  1706  		t.Fatalf("err: %v", err)
  1707  	}
  1708  
  1709  	if !watchFired(ws) {
  1710  		t.Fatalf("bad")
  1711  	}
  1712  	if !watchFired(ws2) {
  1713  		t.Fatalf("bad")
  1714  	}
  1715  	if !watchFired(ws3) {
  1716  		t.Fatalf("bad")
  1717  	}
  1718  
  1719  	ws = memdb.NewWatchSet()
  1720  	out, err := state.EvalByID(ws, eval.ID)
  1721  	if err != nil {
  1722  		t.Fatalf("err: %v", err)
  1723  	}
  1724  
  1725  	if !reflect.DeepEqual(eval, out) {
  1726  		t.Fatalf("bad: %#v %#v", eval, out)
  1727  	}
  1728  
  1729  	index, err := state.Index("evals")
  1730  	if err != nil {
  1731  		t.Fatalf("err: %v", err)
  1732  	}
  1733  	if index != 1000 {
  1734  		t.Fatalf("bad: %d", index)
  1735  	}
  1736  
  1737  	summary, err := state.JobSummaryByID(ws, parent.ID)
  1738  	if err != nil {
  1739  		t.Fatalf("err: %v", err)
  1740  	}
  1741  	if summary == nil {
  1742  		t.Fatalf("nil summary")
  1743  	}
  1744  	if summary.JobID != parent.ID {
  1745  		t.Fatalf("bad summary id: %v", parent.ID)
  1746  	}
  1747  	if summary.Children == nil {
  1748  		t.Fatalf("nil children summary")
  1749  	}
  1750  	if summary.Children.Pending != 0 || summary.Children.Running != 0 || summary.Children.Dead != 1 {
  1751  		t.Fatalf("bad children summary: %v", summary.Children)
  1752  	}
  1753  
  1754  	if watchFired(ws) {
  1755  		t.Fatalf("bad")
  1756  	}
  1757  }
  1758  
  1759  func TestStateStore_DeleteEval_Eval(t *testing.T) {
  1760  	state := testStateStore(t)
  1761  	eval1 := mock.Eval()
  1762  	eval2 := mock.Eval()
  1763  	alloc1 := mock.Alloc()
  1764  	alloc2 := mock.Alloc()
  1765  
  1766  	// Create watchsets so we can test that upsert fires the watch
  1767  	watches := make([]memdb.WatchSet, 12)
  1768  	for i := 0; i < 12; i++ {
  1769  		watches[i] = memdb.NewWatchSet()
  1770  	}
  1771  	if _, err := state.EvalByID(watches[0], eval1.ID); err != nil {
  1772  		t.Fatalf("bad: %v", err)
  1773  	}
  1774  	if _, err := state.EvalByID(watches[1], eval2.ID); err != nil {
  1775  		t.Fatalf("bad: %v", err)
  1776  	}
  1777  	if _, err := state.EvalsByJob(watches[2], eval1.JobID); err != nil {
  1778  		t.Fatalf("bad: %v", err)
  1779  	}
  1780  	if _, err := state.EvalsByJob(watches[3], eval2.JobID); err != nil {
  1781  		t.Fatalf("bad: %v", err)
  1782  	}
  1783  	if _, err := state.AllocByID(watches[4], alloc1.ID); err != nil {
  1784  		t.Fatalf("bad: %v", err)
  1785  	}
  1786  	if _, err := state.AllocByID(watches[5], alloc2.ID); err != nil {
  1787  		t.Fatalf("bad: %v", err)
  1788  	}
  1789  	if _, err := state.AllocsByEval(watches[6], alloc1.EvalID); err != nil {
  1790  		t.Fatalf("bad: %v", err)
  1791  	}
  1792  	if _, err := state.AllocsByEval(watches[7], alloc2.EvalID); err != nil {
  1793  		t.Fatalf("bad: %v", err)
  1794  	}
  1795  	if _, err := state.AllocsByJob(watches[8], alloc1.JobID, false); err != nil {
  1796  		t.Fatalf("bad: %v", err)
  1797  	}
  1798  	if _, err := state.AllocsByJob(watches[9], alloc2.JobID, false); err != nil {
  1799  		t.Fatalf("bad: %v", err)
  1800  	}
  1801  	if _, err := state.AllocsByNode(watches[10], alloc1.NodeID); err != nil {
  1802  		t.Fatalf("bad: %v", err)
  1803  	}
  1804  	if _, err := state.AllocsByNode(watches[11], alloc2.NodeID); err != nil {
  1805  		t.Fatalf("bad: %v", err)
  1806  	}
  1807  
  1808  	state.UpsertJobSummary(900, mock.JobSummary(eval1.JobID))
  1809  	state.UpsertJobSummary(901, mock.JobSummary(eval2.JobID))
  1810  	state.UpsertJobSummary(902, mock.JobSummary(alloc1.JobID))
  1811  	state.UpsertJobSummary(903, mock.JobSummary(alloc2.JobID))
  1812  	err := state.UpsertEvals(1000, []*structs.Evaluation{eval1, eval2})
  1813  	if err != nil {
  1814  		t.Fatalf("err: %v", err)
  1815  	}
  1816  
  1817  	err = state.UpsertAllocs(1001, []*structs.Allocation{alloc1, alloc2})
  1818  	if err != nil {
  1819  		t.Fatalf("err: %v", err)
  1820  	}
  1821  
  1822  	err = state.DeleteEval(1002, []string{eval1.ID, eval2.ID}, []string{alloc1.ID, alloc2.ID})
  1823  	if err != nil {
  1824  		t.Fatalf("err: %v", err)
  1825  	}
  1826  
  1827  	for i, ws := range watches {
  1828  		if !watchFired(ws) {
  1829  			t.Fatalf("bad %d", i)
  1830  		}
  1831  	}
  1832  
  1833  	ws := memdb.NewWatchSet()
  1834  	out, err := state.EvalByID(ws, eval1.ID)
  1835  	if err != nil {
  1836  		t.Fatalf("err: %v", err)
  1837  	}
  1838  
  1839  	if out != nil {
  1840  		t.Fatalf("bad: %#v %#v", eval1, out)
  1841  	}
  1842  
  1843  	out, err = state.EvalByID(ws, eval2.ID)
  1844  	if err != nil {
  1845  		t.Fatalf("err: %v", err)
  1846  	}
  1847  
  1848  	if out != nil {
  1849  		t.Fatalf("bad: %#v %#v", eval1, out)
  1850  	}
  1851  
  1852  	outA, err := state.AllocByID(ws, alloc1.ID)
  1853  	if err != nil {
  1854  		t.Fatalf("err: %v", err)
  1855  	}
  1856  
  1857  	if out != nil {
  1858  		t.Fatalf("bad: %#v %#v", alloc1, outA)
  1859  	}
  1860  
  1861  	outA, err = state.AllocByID(ws, alloc2.ID)
  1862  	if err != nil {
  1863  		t.Fatalf("err: %v", err)
  1864  	}
  1865  
  1866  	if out != nil {
  1867  		t.Fatalf("bad: %#v %#v", alloc1, outA)
  1868  	}
  1869  
  1870  	index, err := state.Index("evals")
  1871  	if err != nil {
  1872  		t.Fatalf("err: %v", err)
  1873  	}
  1874  	if index != 1002 {
  1875  		t.Fatalf("bad: %d", index)
  1876  	}
  1877  
  1878  	index, err = state.Index("allocs")
  1879  	if err != nil {
  1880  		t.Fatalf("err: %v", err)
  1881  	}
  1882  	if index != 1002 {
  1883  		t.Fatalf("bad: %d", index)
  1884  	}
  1885  
  1886  	if watchFired(ws) {
  1887  		t.Fatalf("bad")
  1888  	}
  1889  }
  1890  
  1891  func TestStateStore_DeleteEval_ChildJob(t *testing.T) {
  1892  	state := testStateStore(t)
  1893  
  1894  	parent := mock.Job()
  1895  	if err := state.UpsertJob(998, parent); err != nil {
  1896  		t.Fatalf("err: %v", err)
  1897  	}
  1898  
  1899  	child := mock.Job()
  1900  	child.ParentID = parent.ID
  1901  
  1902  	if err := state.UpsertJob(999, child); err != nil {
  1903  		t.Fatalf("err: %v", err)
  1904  	}
  1905  
  1906  	eval1 := mock.Eval()
  1907  	eval1.JobID = child.ID
  1908  	alloc1 := mock.Alloc()
  1909  	alloc1.JobID = child.ID
  1910  
  1911  	err := state.UpsertEvals(1000, []*structs.Evaluation{eval1})
  1912  	if err != nil {
  1913  		t.Fatalf("err: %v", err)
  1914  	}
  1915  
  1916  	err = state.UpsertAllocs(1001, []*structs.Allocation{alloc1})
  1917  	if err != nil {
  1918  		t.Fatalf("err: %v", err)
  1919  	}
  1920  
  1921  	// Create watchsets so we can test that delete fires the watch
  1922  	ws := memdb.NewWatchSet()
  1923  	if _, err := state.JobSummaryByID(ws, parent.ID); err != nil {
  1924  		t.Fatalf("bad: %v", err)
  1925  	}
  1926  
  1927  	err = state.DeleteEval(1002, []string{eval1.ID}, []string{alloc1.ID})
  1928  	if err != nil {
  1929  		t.Fatalf("err: %v", err)
  1930  	}
  1931  
  1932  	if !watchFired(ws) {
  1933  		t.Fatalf("bad")
  1934  	}
  1935  
  1936  	ws = memdb.NewWatchSet()
  1937  	summary, err := state.JobSummaryByID(ws, parent.ID)
  1938  	if err != nil {
  1939  		t.Fatalf("err: %v", err)
  1940  	}
  1941  	if summary == nil {
  1942  		t.Fatalf("nil summary")
  1943  	}
  1944  	if summary.JobID != parent.ID {
  1945  		t.Fatalf("bad summary id: %v", parent.ID)
  1946  	}
  1947  	if summary.Children == nil {
  1948  		t.Fatalf("nil children summary")
  1949  	}
  1950  	if summary.Children.Pending != 0 || summary.Children.Running != 0 || summary.Children.Dead != 1 {
  1951  		t.Fatalf("bad children summary: %v", summary.Children)
  1952  	}
  1953  
  1954  	if watchFired(ws) {
  1955  		t.Fatalf("bad")
  1956  	}
  1957  }
  1958  
  1959  func TestStateStore_EvalsByJob(t *testing.T) {
  1960  	state := testStateStore(t)
  1961  
  1962  	eval1 := mock.Eval()
  1963  	eval2 := mock.Eval()
  1964  	eval2.JobID = eval1.JobID
  1965  	eval3 := mock.Eval()
  1966  	evals := []*structs.Evaluation{eval1, eval2}
  1967  
  1968  	err := state.UpsertEvals(1000, evals)
  1969  	if err != nil {
  1970  		t.Fatalf("err: %v", err)
  1971  	}
  1972  	err = state.UpsertEvals(1001, []*structs.Evaluation{eval3})
  1973  	if err != nil {
  1974  		t.Fatalf("err: %v", err)
  1975  	}
  1976  
  1977  	ws := memdb.NewWatchSet()
  1978  	out, err := state.EvalsByJob(ws, eval1.JobID)
  1979  	if err != nil {
  1980  		t.Fatalf("err: %v", err)
  1981  	}
  1982  
  1983  	sort.Sort(EvalIDSort(evals))
  1984  	sort.Sort(EvalIDSort(out))
  1985  
  1986  	if !reflect.DeepEqual(evals, out) {
  1987  		t.Fatalf("bad: %#v %#v", evals, out)
  1988  	}
  1989  
  1990  	if watchFired(ws) {
  1991  		t.Fatalf("bad")
  1992  	}
  1993  }
  1994  
  1995  func TestStateStore_Evals(t *testing.T) {
  1996  	state := testStateStore(t)
  1997  	var evals []*structs.Evaluation
  1998  
  1999  	for i := 0; i < 10; i++ {
  2000  		eval := mock.Eval()
  2001  		evals = append(evals, eval)
  2002  
  2003  		err := state.UpsertEvals(1000+uint64(i), []*structs.Evaluation{eval})
  2004  		if err != nil {
  2005  			t.Fatalf("err: %v", err)
  2006  		}
  2007  	}
  2008  
  2009  	ws := memdb.NewWatchSet()
  2010  	iter, err := state.Evals(ws)
  2011  	if err != nil {
  2012  		t.Fatalf("err: %v", err)
  2013  	}
  2014  
  2015  	var out []*structs.Evaluation
  2016  	for {
  2017  		raw := iter.Next()
  2018  		if raw == nil {
  2019  			break
  2020  		}
  2021  		out = append(out, raw.(*structs.Evaluation))
  2022  	}
  2023  
  2024  	sort.Sort(EvalIDSort(evals))
  2025  	sort.Sort(EvalIDSort(out))
  2026  
  2027  	if !reflect.DeepEqual(evals, out) {
  2028  		t.Fatalf("bad: %#v %#v", evals, out)
  2029  	}
  2030  
  2031  	if watchFired(ws) {
  2032  		t.Fatalf("bad")
  2033  	}
  2034  }
  2035  
  2036  func TestStateStore_EvalsByIDPrefix(t *testing.T) {
  2037  	state := testStateStore(t)
  2038  	var evals []*structs.Evaluation
  2039  
  2040  	ids := []string{
  2041  		"aaaaaaaa-7bfb-395d-eb95-0685af2176b2",
  2042  		"aaaaaaab-7bfb-395d-eb95-0685af2176b2",
  2043  		"aaaaaabb-7bfb-395d-eb95-0685af2176b2",
  2044  		"aaaaabbb-7bfb-395d-eb95-0685af2176b2",
  2045  		"aaaabbbb-7bfb-395d-eb95-0685af2176b2",
  2046  		"aaabbbbb-7bfb-395d-eb95-0685af2176b2",
  2047  		"aabbbbbb-7bfb-395d-eb95-0685af2176b2",
  2048  		"abbbbbbb-7bfb-395d-eb95-0685af2176b2",
  2049  		"bbbbbbbb-7bfb-395d-eb95-0685af2176b2",
  2050  	}
  2051  	for i := 0; i < 9; i++ {
  2052  		eval := mock.Eval()
  2053  		eval.ID = ids[i]
  2054  		evals = append(evals, eval)
  2055  	}
  2056  
  2057  	err := state.UpsertEvals(1000, evals)
  2058  	if err != nil {
  2059  		t.Fatalf("err: %v", err)
  2060  	}
  2061  
  2062  	ws := memdb.NewWatchSet()
  2063  	iter, err := state.EvalsByIDPrefix(ws, "aaaa")
  2064  	if err != nil {
  2065  		t.Fatalf("err: %v", err)
  2066  	}
  2067  
  2068  	gatherEvals := func(iter memdb.ResultIterator) []*structs.Evaluation {
  2069  		var evals []*structs.Evaluation
  2070  		for {
  2071  			raw := iter.Next()
  2072  			if raw == nil {
  2073  				break
  2074  			}
  2075  			evals = append(evals, raw.(*structs.Evaluation))
  2076  		}
  2077  		return evals
  2078  	}
  2079  
  2080  	out := gatherEvals(iter)
  2081  	if len(out) != 5 {
  2082  		t.Fatalf("bad: expected five evaluations, got: %#v", out)
  2083  	}
  2084  
  2085  	sort.Sort(EvalIDSort(evals))
  2086  
  2087  	for index, eval := range out {
  2088  		if ids[index] != eval.ID {
  2089  			t.Fatalf("bad: got unexpected id: %s", eval.ID)
  2090  		}
  2091  	}
  2092  
  2093  	iter, err = state.EvalsByIDPrefix(ws, "b-a7bfb")
  2094  	if err != nil {
  2095  		t.Fatalf("err: %v", err)
  2096  	}
  2097  
  2098  	out = gatherEvals(iter)
  2099  	if len(out) != 0 {
  2100  		t.Fatalf("bad: unexpected zero evaluations, got: %#v", out)
  2101  	}
  2102  
  2103  	if watchFired(ws) {
  2104  		t.Fatalf("bad")
  2105  	}
  2106  }
  2107  
  2108  func TestStateStore_RestoreEval(t *testing.T) {
  2109  	state := testStateStore(t)
  2110  	eval := mock.Eval()
  2111  
  2112  	restore, err := state.Restore()
  2113  	if err != nil {
  2114  		t.Fatalf("err: %v", err)
  2115  	}
  2116  
  2117  	err = restore.EvalRestore(eval)
  2118  	if err != nil {
  2119  		t.Fatalf("err: %v", err)
  2120  	}
  2121  	restore.Commit()
  2122  
  2123  	ws := memdb.NewWatchSet()
  2124  	out, err := state.EvalByID(ws, eval.ID)
  2125  	if err != nil {
  2126  		t.Fatalf("err: %v", err)
  2127  	}
  2128  
  2129  	if !reflect.DeepEqual(out, eval) {
  2130  		t.Fatalf("Bad: %#v %#v", out, eval)
  2131  	}
  2132  }
  2133  
  2134  func TestStateStore_UpdateAllocsFromClient(t *testing.T) {
  2135  	state := testStateStore(t)
  2136  	parent := mock.Job()
  2137  	if err := state.UpsertJob(998, parent); err != nil {
  2138  		t.Fatalf("err: %v", err)
  2139  	}
  2140  
  2141  	child := mock.Job()
  2142  	child.ParentID = parent.ID
  2143  	if err := state.UpsertJob(999, child); err != nil {
  2144  		t.Fatalf("err: %v", err)
  2145  	}
  2146  
  2147  	alloc := mock.Alloc()
  2148  	alloc.JobID = child.ID
  2149  	alloc.Job = child
  2150  
  2151  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  2152  	if err != nil {
  2153  		t.Fatalf("err: %v", err)
  2154  	}
  2155  
  2156  	ws := memdb.NewWatchSet()
  2157  	summary, err := state.JobSummaryByID(ws, parent.ID)
  2158  	if err != nil {
  2159  		t.Fatalf("err: %v", err)
  2160  	}
  2161  	if summary == nil {
  2162  		t.Fatalf("nil summary")
  2163  	}
  2164  	if summary.JobID != parent.ID {
  2165  		t.Fatalf("bad summary id: %v", parent.ID)
  2166  	}
  2167  	if summary.Children == nil {
  2168  		t.Fatalf("nil children summary")
  2169  	}
  2170  	if summary.Children.Pending != 0 || summary.Children.Running != 1 || summary.Children.Dead != 0 {
  2171  		t.Fatalf("bad children summary: %v", summary.Children)
  2172  	}
  2173  
  2174  	// Create watchsets so we can test that update fires the watch
  2175  	ws = memdb.NewWatchSet()
  2176  	if _, err := state.JobSummaryByID(ws, parent.ID); err != nil {
  2177  		t.Fatalf("bad: %v", err)
  2178  	}
  2179  
  2180  	// Create the delta updates
  2181  	ts := map[string]*structs.TaskState{"web": &structs.TaskState{State: structs.TaskStateRunning}}
  2182  	update := &structs.Allocation{
  2183  		ID:           alloc.ID,
  2184  		ClientStatus: structs.AllocClientStatusComplete,
  2185  		TaskStates:   ts,
  2186  		JobID:        alloc.JobID,
  2187  		TaskGroup:    alloc.TaskGroup,
  2188  	}
  2189  	err = state.UpdateAllocsFromClient(1001, []*structs.Allocation{update})
  2190  	if err != nil {
  2191  		t.Fatalf("err: %v", err)
  2192  	}
  2193  
  2194  	if !watchFired(ws) {
  2195  		t.Fatalf("bad")
  2196  	}
  2197  
  2198  	ws = memdb.NewWatchSet()
  2199  	summary, err = state.JobSummaryByID(ws, parent.ID)
  2200  	if err != nil {
  2201  		t.Fatalf("err: %v", err)
  2202  	}
  2203  	if summary == nil {
  2204  		t.Fatalf("nil summary")
  2205  	}
  2206  	if summary.JobID != parent.ID {
  2207  		t.Fatalf("bad summary id: %v", parent.ID)
  2208  	}
  2209  	if summary.Children == nil {
  2210  		t.Fatalf("nil children summary")
  2211  	}
  2212  	if summary.Children.Pending != 0 || summary.Children.Running != 0 || summary.Children.Dead != 1 {
  2213  		t.Fatalf("bad children summary: %v", summary.Children)
  2214  	}
  2215  
  2216  	if watchFired(ws) {
  2217  		t.Fatalf("bad")
  2218  	}
  2219  }
  2220  
  2221  func TestStateStore_UpdateAllocsFromClient_ChildJob(t *testing.T) {
  2222  	state := testStateStore(t)
  2223  	alloc1 := mock.Alloc()
  2224  	alloc2 := mock.Alloc()
  2225  
  2226  	if err := state.UpsertJob(999, alloc1.Job); err != nil {
  2227  		t.Fatalf("err: %v", err)
  2228  	}
  2229  	if err := state.UpsertJob(999, alloc2.Job); err != nil {
  2230  		t.Fatalf("err: %v", err)
  2231  	}
  2232  
  2233  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc1, alloc2})
  2234  	if err != nil {
  2235  		t.Fatalf("err: %v", err)
  2236  	}
  2237  
  2238  	// Create watchsets so we can test that update fires the watch
  2239  	watches := make([]memdb.WatchSet, 8)
  2240  	for i := 0; i < 8; i++ {
  2241  		watches[i] = memdb.NewWatchSet()
  2242  	}
  2243  	if _, err := state.AllocByID(watches[0], alloc1.ID); err != nil {
  2244  		t.Fatalf("bad: %v", err)
  2245  	}
  2246  	if _, err := state.AllocByID(watches[1], alloc2.ID); err != nil {
  2247  		t.Fatalf("bad: %v", err)
  2248  	}
  2249  	if _, err := state.AllocsByEval(watches[2], alloc1.EvalID); err != nil {
  2250  		t.Fatalf("bad: %v", err)
  2251  	}
  2252  	if _, err := state.AllocsByEval(watches[3], alloc2.EvalID); err != nil {
  2253  		t.Fatalf("bad: %v", err)
  2254  	}
  2255  	if _, err := state.AllocsByJob(watches[4], alloc1.JobID, false); err != nil {
  2256  		t.Fatalf("bad: %v", err)
  2257  	}
  2258  	if _, err := state.AllocsByJob(watches[5], alloc2.JobID, false); err != nil {
  2259  		t.Fatalf("bad: %v", err)
  2260  	}
  2261  	if _, err := state.AllocsByNode(watches[6], alloc1.NodeID); err != nil {
  2262  		t.Fatalf("bad: %v", err)
  2263  	}
  2264  	if _, err := state.AllocsByNode(watches[7], alloc2.NodeID); err != nil {
  2265  		t.Fatalf("bad: %v", err)
  2266  	}
  2267  
  2268  	// Create the delta updates
  2269  	ts := map[string]*structs.TaskState{"web": &structs.TaskState{State: structs.TaskStatePending}}
  2270  	update := &structs.Allocation{
  2271  		ID:           alloc1.ID,
  2272  		ClientStatus: structs.AllocClientStatusFailed,
  2273  		TaskStates:   ts,
  2274  		JobID:        alloc1.JobID,
  2275  		TaskGroup:    alloc1.TaskGroup,
  2276  	}
  2277  	update2 := &structs.Allocation{
  2278  		ID:           alloc2.ID,
  2279  		ClientStatus: structs.AllocClientStatusRunning,
  2280  		TaskStates:   ts,
  2281  		JobID:        alloc2.JobID,
  2282  		TaskGroup:    alloc2.TaskGroup,
  2283  	}
  2284  
  2285  	err = state.UpdateAllocsFromClient(1001, []*structs.Allocation{update, update2})
  2286  	if err != nil {
  2287  		t.Fatalf("err: %v", err)
  2288  	}
  2289  
  2290  	for i, ws := range watches {
  2291  		if !watchFired(ws) {
  2292  			t.Fatalf("bad %d", i)
  2293  		}
  2294  	}
  2295  
  2296  	ws := memdb.NewWatchSet()
  2297  	out, err := state.AllocByID(ws, alloc1.ID)
  2298  	if err != nil {
  2299  		t.Fatalf("err: %v", err)
  2300  	}
  2301  
  2302  	alloc1.CreateIndex = 1000
  2303  	alloc1.ModifyIndex = 1001
  2304  	alloc1.TaskStates = ts
  2305  	alloc1.ClientStatus = structs.AllocClientStatusFailed
  2306  	if !reflect.DeepEqual(alloc1, out) {
  2307  		t.Fatalf("bad: %#v %#v", alloc1, out)
  2308  	}
  2309  
  2310  	out, err = state.AllocByID(ws, alloc2.ID)
  2311  	if err != nil {
  2312  		t.Fatalf("err: %v", err)
  2313  	}
  2314  
  2315  	alloc2.ModifyIndex = 1000
  2316  	alloc2.ModifyIndex = 1001
  2317  	alloc2.ClientStatus = structs.AllocClientStatusRunning
  2318  	alloc2.TaskStates = ts
  2319  	if !reflect.DeepEqual(alloc2, out) {
  2320  		t.Fatalf("bad: %#v %#v", alloc2, out)
  2321  	}
  2322  
  2323  	index, err := state.Index("allocs")
  2324  	if err != nil {
  2325  		t.Fatalf("err: %v", err)
  2326  	}
  2327  	if index != 1001 {
  2328  		t.Fatalf("bad: %d", index)
  2329  	}
  2330  
  2331  	// Ensure summaries have been updated
  2332  	summary, err := state.JobSummaryByID(ws, alloc1.JobID)
  2333  	if err != nil {
  2334  		t.Fatalf("err: %v", err)
  2335  	}
  2336  	tgSummary := summary.Summary["web"]
  2337  	if tgSummary.Failed != 1 {
  2338  		t.Fatalf("expected failed: %v, actual: %v, summary: %#v", 1, tgSummary.Failed, tgSummary)
  2339  	}
  2340  
  2341  	summary2, err := state.JobSummaryByID(ws, alloc2.JobID)
  2342  	if err != nil {
  2343  		t.Fatalf("err: %v", err)
  2344  	}
  2345  	tgSummary2 := summary2.Summary["web"]
  2346  	if tgSummary2.Running != 1 {
  2347  		t.Fatalf("expected running: %v, actual: %v", 1, tgSummary2.Running)
  2348  	}
  2349  
  2350  	if watchFired(ws) {
  2351  		t.Fatalf("bad")
  2352  	}
  2353  }
  2354  
  2355  func TestStateStore_UpdateMultipleAllocsFromClient(t *testing.T) {
  2356  	state := testStateStore(t)
  2357  	alloc := mock.Alloc()
  2358  
  2359  	if err := state.UpsertJob(999, alloc.Job); err != nil {
  2360  		t.Fatalf("err: %v", err)
  2361  	}
  2362  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  2363  	if err != nil {
  2364  		t.Fatalf("err: %v", err)
  2365  	}
  2366  
  2367  	// Create the delta updates
  2368  	ts := map[string]*structs.TaskState{"web": &structs.TaskState{State: structs.TaskStatePending}}
  2369  	update := &structs.Allocation{
  2370  		ID:           alloc.ID,
  2371  		ClientStatus: structs.AllocClientStatusRunning,
  2372  		TaskStates:   ts,
  2373  		JobID:        alloc.JobID,
  2374  		TaskGroup:    alloc.TaskGroup,
  2375  	}
  2376  	update2 := &structs.Allocation{
  2377  		ID:           alloc.ID,
  2378  		ClientStatus: structs.AllocClientStatusPending,
  2379  		TaskStates:   ts,
  2380  		JobID:        alloc.JobID,
  2381  		TaskGroup:    alloc.TaskGroup,
  2382  	}
  2383  
  2384  	err = state.UpdateAllocsFromClient(1001, []*structs.Allocation{update, update2})
  2385  	if err != nil {
  2386  		t.Fatalf("err: %v", err)
  2387  	}
  2388  
  2389  	ws := memdb.NewWatchSet()
  2390  	out, err := state.AllocByID(ws, alloc.ID)
  2391  	if err != nil {
  2392  		t.Fatalf("err: %v", err)
  2393  	}
  2394  
  2395  	alloc.CreateIndex = 1000
  2396  	alloc.ModifyIndex = 1001
  2397  	alloc.TaskStates = ts
  2398  	alloc.ClientStatus = structs.AllocClientStatusPending
  2399  	if !reflect.DeepEqual(alloc, out) {
  2400  		t.Fatalf("bad: %#v , actual:%#v", alloc, out)
  2401  	}
  2402  
  2403  	summary, err := state.JobSummaryByID(ws, alloc.JobID)
  2404  	expectedSummary := &structs.JobSummary{
  2405  		JobID: alloc.JobID,
  2406  		Summary: map[string]structs.TaskGroupSummary{
  2407  			"web": structs.TaskGroupSummary{
  2408  				Starting: 1,
  2409  			},
  2410  		},
  2411  		Children:    new(structs.JobChildrenSummary),
  2412  		CreateIndex: 999,
  2413  		ModifyIndex: 1001,
  2414  	}
  2415  	if err != nil {
  2416  		t.Fatalf("err: %v", err)
  2417  	}
  2418  	if !reflect.DeepEqual(summary, expectedSummary) {
  2419  		t.Fatalf("expected: %#v, actual: %#v", expectedSummary, summary)
  2420  	}
  2421  }
  2422  
  2423  func TestStateStore_UpsertAlloc_Alloc(t *testing.T) {
  2424  	state := testStateStore(t)
  2425  	alloc := mock.Alloc()
  2426  
  2427  	if err := state.UpsertJob(999, alloc.Job); err != nil {
  2428  		t.Fatalf("err: %v", err)
  2429  	}
  2430  
  2431  	// Create watchsets so we can test that update fires the watch
  2432  	watches := make([]memdb.WatchSet, 4)
  2433  	for i := 0; i < 4; i++ {
  2434  		watches[i] = memdb.NewWatchSet()
  2435  	}
  2436  	if _, err := state.AllocByID(watches[0], alloc.ID); err != nil {
  2437  		t.Fatalf("bad: %v", err)
  2438  	}
  2439  	if _, err := state.AllocsByEval(watches[1], alloc.EvalID); err != nil {
  2440  		t.Fatalf("bad: %v", err)
  2441  	}
  2442  	if _, err := state.AllocsByJob(watches[2], alloc.JobID, false); err != nil {
  2443  		t.Fatalf("bad: %v", err)
  2444  	}
  2445  	if _, err := state.AllocsByNode(watches[3], alloc.NodeID); err != nil {
  2446  		t.Fatalf("bad: %v", err)
  2447  	}
  2448  
  2449  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  2450  	if err != nil {
  2451  		t.Fatalf("err: %v", err)
  2452  	}
  2453  
  2454  	for i, ws := range watches {
  2455  		if !watchFired(ws) {
  2456  			t.Fatalf("bad %d", i)
  2457  		}
  2458  	}
  2459  
  2460  	ws := memdb.NewWatchSet()
  2461  	out, err := state.AllocByID(ws, alloc.ID)
  2462  	if err != nil {
  2463  		t.Fatalf("err: %v", err)
  2464  	}
  2465  
  2466  	if !reflect.DeepEqual(alloc, out) {
  2467  		t.Fatalf("bad: %#v %#v", alloc, out)
  2468  	}
  2469  
  2470  	index, err := state.Index("allocs")
  2471  	if err != nil {
  2472  		t.Fatalf("err: %v", err)
  2473  	}
  2474  	if index != 1000 {
  2475  		t.Fatalf("bad: %d", index)
  2476  	}
  2477  
  2478  	summary, err := state.JobSummaryByID(ws, alloc.JobID)
  2479  	if err != nil {
  2480  		t.Fatalf("err: %v", err)
  2481  	}
  2482  
  2483  	tgSummary, ok := summary.Summary["web"]
  2484  	if !ok {
  2485  		t.Fatalf("no summary for task group web")
  2486  	}
  2487  	if tgSummary.Starting != 1 {
  2488  		t.Fatalf("expected queued: %v, actual: %v", 1, tgSummary.Starting)
  2489  	}
  2490  
  2491  	if watchFired(ws) {
  2492  		t.Fatalf("bad")
  2493  	}
  2494  }
  2495  
  2496  func TestStateStore_UpsertAlloc_NoEphemeralDisk(t *testing.T) {
  2497  	state := testStateStore(t)
  2498  	alloc := mock.Alloc()
  2499  	alloc.Job.TaskGroups[0].EphemeralDisk = nil
  2500  	alloc.Job.TaskGroups[0].Tasks[0].Resources.DiskMB = 120
  2501  
  2502  	if err := state.UpsertJob(999, alloc.Job); err != nil {
  2503  		t.Fatalf("err: %v", err)
  2504  	}
  2505  
  2506  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  2507  	if err != nil {
  2508  		t.Fatalf("err: %v", err)
  2509  	}
  2510  
  2511  	ws := memdb.NewWatchSet()
  2512  	out, err := state.AllocByID(ws, alloc.ID)
  2513  	if err != nil {
  2514  		t.Fatalf("err: %v", err)
  2515  	}
  2516  
  2517  	expected := alloc.Copy()
  2518  	expected.Job.TaskGroups[0].EphemeralDisk = &structs.EphemeralDisk{SizeMB: 120}
  2519  	if !reflect.DeepEqual(expected, out) {
  2520  		t.Fatalf("bad: %#v %#v", expected, out)
  2521  	}
  2522  }
  2523  
  2524  func TestStateStore_UpsertAlloc_ChildJob(t *testing.T) {
  2525  	state := testStateStore(t)
  2526  
  2527  	parent := mock.Job()
  2528  	if err := state.UpsertJob(998, parent); err != nil {
  2529  		t.Fatalf("err: %v", err)
  2530  	}
  2531  
  2532  	child := mock.Job()
  2533  	child.ParentID = parent.ID
  2534  
  2535  	if err := state.UpsertJob(999, child); err != nil {
  2536  		t.Fatalf("err: %v", err)
  2537  	}
  2538  
  2539  	alloc := mock.Alloc()
  2540  	alloc.JobID = child.ID
  2541  	alloc.Job = child
  2542  
  2543  	// Create watchsets so we can test that delete fires the watch
  2544  	ws := memdb.NewWatchSet()
  2545  	if _, err := state.JobSummaryByID(ws, parent.ID); err != nil {
  2546  		t.Fatalf("bad: %v", err)
  2547  	}
  2548  
  2549  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  2550  	if err != nil {
  2551  		t.Fatalf("err: %v", err)
  2552  	}
  2553  
  2554  	if !watchFired(ws) {
  2555  		t.Fatalf("bad")
  2556  	}
  2557  
  2558  	ws = memdb.NewWatchSet()
  2559  	summary, err := state.JobSummaryByID(ws, parent.ID)
  2560  	if err != nil {
  2561  		t.Fatalf("err: %v", err)
  2562  	}
  2563  	if summary == nil {
  2564  		t.Fatalf("nil summary")
  2565  	}
  2566  	if summary.JobID != parent.ID {
  2567  		t.Fatalf("bad summary id: %v", parent.ID)
  2568  	}
  2569  	if summary.Children == nil {
  2570  		t.Fatalf("nil children summary")
  2571  	}
  2572  	if summary.Children.Pending != 0 || summary.Children.Running != 1 || summary.Children.Dead != 0 {
  2573  		t.Fatalf("bad children summary: %v", summary.Children)
  2574  	}
  2575  
  2576  	if watchFired(ws) {
  2577  		t.Fatalf("bad")
  2578  	}
  2579  }
  2580  
  2581  func TestStateStore_UpdateAlloc_Alloc(t *testing.T) {
  2582  	state := testStateStore(t)
  2583  	alloc := mock.Alloc()
  2584  
  2585  	if err := state.UpsertJob(999, alloc.Job); err != nil {
  2586  		t.Fatalf("err: %v", err)
  2587  	}
  2588  
  2589  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  2590  	if err != nil {
  2591  		t.Fatalf("err: %v", err)
  2592  	}
  2593  
  2594  	ws := memdb.NewWatchSet()
  2595  	summary, err := state.JobSummaryByID(ws, alloc.JobID)
  2596  	if err != nil {
  2597  		t.Fatalf("err: %v", err)
  2598  	}
  2599  	tgSummary := summary.Summary["web"]
  2600  	if tgSummary.Starting != 1 {
  2601  		t.Fatalf("expected starting: %v, actual: %v", 1, tgSummary.Starting)
  2602  	}
  2603  
  2604  	alloc2 := mock.Alloc()
  2605  	alloc2.ID = alloc.ID
  2606  	alloc2.NodeID = alloc.NodeID + ".new"
  2607  	state.UpsertJobSummary(1001, mock.JobSummary(alloc2.JobID))
  2608  
  2609  	// Create watchsets so we can test that update fires the watch
  2610  	watches := make([]memdb.WatchSet, 4)
  2611  	for i := 0; i < 4; i++ {
  2612  		watches[i] = memdb.NewWatchSet()
  2613  	}
  2614  	if _, err := state.AllocByID(watches[0], alloc2.ID); err != nil {
  2615  		t.Fatalf("bad: %v", err)
  2616  	}
  2617  	if _, err := state.AllocsByEval(watches[1], alloc2.EvalID); err != nil {
  2618  		t.Fatalf("bad: %v", err)
  2619  	}
  2620  	if _, err := state.AllocsByJob(watches[2], alloc2.JobID, false); err != nil {
  2621  		t.Fatalf("bad: %v", err)
  2622  	}
  2623  	if _, err := state.AllocsByNode(watches[3], alloc2.NodeID); err != nil {
  2624  		t.Fatalf("bad: %v", err)
  2625  	}
  2626  
  2627  	err = state.UpsertAllocs(1002, []*structs.Allocation{alloc2})
  2628  	if err != nil {
  2629  		t.Fatalf("err: %v", err)
  2630  	}
  2631  
  2632  	for i, ws := range watches {
  2633  		if !watchFired(ws) {
  2634  			t.Fatalf("bad %d", i)
  2635  		}
  2636  	}
  2637  
  2638  	ws = memdb.NewWatchSet()
  2639  	out, err := state.AllocByID(ws, alloc.ID)
  2640  	if err != nil {
  2641  		t.Fatalf("err: %v", err)
  2642  	}
  2643  
  2644  	if !reflect.DeepEqual(alloc2, out) {
  2645  		t.Fatalf("bad: %#v %#v", alloc2, out)
  2646  	}
  2647  
  2648  	if out.CreateIndex != 1000 {
  2649  		t.Fatalf("bad: %#v", out)
  2650  	}
  2651  	if out.ModifyIndex != 1002 {
  2652  		t.Fatalf("bad: %#v", out)
  2653  	}
  2654  
  2655  	index, err := state.Index("allocs")
  2656  	if err != nil {
  2657  		t.Fatalf("err: %v", err)
  2658  	}
  2659  	if index != 1002 {
  2660  		t.Fatalf("bad: %d", index)
  2661  	}
  2662  
  2663  	// Ensure that summary hasb't changed
  2664  	summary, err = state.JobSummaryByID(ws, alloc.JobID)
  2665  	if err != nil {
  2666  		t.Fatalf("err: %v", err)
  2667  	}
  2668  	tgSummary = summary.Summary["web"]
  2669  	if tgSummary.Starting != 1 {
  2670  		t.Fatalf("expected starting: %v, actual: %v", 1, tgSummary.Starting)
  2671  	}
  2672  
  2673  	if watchFired(ws) {
  2674  		t.Fatalf("bad")
  2675  	}
  2676  }
  2677  
  2678  // This test ensures that the state store will mark the clients status as lost
  2679  // when set rather than preferring the existing status.
  2680  func TestStateStore_UpdateAlloc_Lost(t *testing.T) {
  2681  	state := testStateStore(t)
  2682  	alloc := mock.Alloc()
  2683  	alloc.ClientStatus = "foo"
  2684  
  2685  	if err := state.UpsertJob(999, alloc.Job); err != nil {
  2686  		t.Fatalf("err: %v", err)
  2687  	}
  2688  
  2689  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  2690  	if err != nil {
  2691  		t.Fatalf("err: %v", err)
  2692  	}
  2693  
  2694  	alloc2 := new(structs.Allocation)
  2695  	*alloc2 = *alloc
  2696  	alloc2.ClientStatus = structs.AllocClientStatusLost
  2697  	if err := state.UpsertAllocs(1001, []*structs.Allocation{alloc2}); err != nil {
  2698  		t.Fatalf("err: %v", err)
  2699  	}
  2700  
  2701  	ws := memdb.NewWatchSet()
  2702  	out, err := state.AllocByID(ws, alloc2.ID)
  2703  	if err != nil {
  2704  		t.Fatalf("err: %v", err)
  2705  	}
  2706  
  2707  	if out.ClientStatus != structs.AllocClientStatusLost {
  2708  		t.Fatalf("bad: %#v", out)
  2709  	}
  2710  }
  2711  
  2712  // This test ensures an allocation can be updated when there is no job
  2713  // associated with it. This will happen when a job is stopped by an user which
  2714  // has non-terminal allocations on clients
  2715  func TestStateStore_UpdateAlloc_NoJob(t *testing.T) {
  2716  	state := testStateStore(t)
  2717  	alloc := mock.Alloc()
  2718  
  2719  	// Upsert a job
  2720  	state.UpsertJobSummary(998, mock.JobSummary(alloc.JobID))
  2721  	if err := state.UpsertJob(999, alloc.Job); err != nil {
  2722  		t.Fatalf("err: %v", err)
  2723  	}
  2724  
  2725  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  2726  	if err != nil {
  2727  		t.Fatalf("err: %v", err)
  2728  	}
  2729  
  2730  	if err := state.DeleteJob(1001, alloc.JobID); err != nil {
  2731  		t.Fatalf("err: %v", err)
  2732  	}
  2733  
  2734  	// Update the desired state of the allocation to stop
  2735  	allocCopy := alloc.Copy()
  2736  	allocCopy.DesiredStatus = structs.AllocDesiredStatusStop
  2737  	if err := state.UpsertAllocs(1002, []*structs.Allocation{allocCopy}); err != nil {
  2738  		t.Fatalf("err: %v", err)
  2739  	}
  2740  
  2741  	// Update the client state of the allocation to complete
  2742  	allocCopy1 := allocCopy.Copy()
  2743  	allocCopy1.ClientStatus = structs.AllocClientStatusComplete
  2744  	if err := state.UpdateAllocsFromClient(1003, []*structs.Allocation{allocCopy1}); err != nil {
  2745  		t.Fatalf("err: %v", err)
  2746  	}
  2747  
  2748  	ws := memdb.NewWatchSet()
  2749  	out, _ := state.AllocByID(ws, alloc.ID)
  2750  	// Update the modify index of the alloc before comparing
  2751  	allocCopy1.ModifyIndex = 1003
  2752  	if !reflect.DeepEqual(out, allocCopy1) {
  2753  		t.Fatalf("expected: %#v \n actual: %#v", allocCopy1, out)
  2754  	}
  2755  }
  2756  
  2757  func TestStateStore_JobSummary(t *testing.T) {
  2758  	state := testStateStore(t)
  2759  
  2760  	// Add a job
  2761  	job := mock.Job()
  2762  	state.UpsertJob(900, job)
  2763  
  2764  	// Get the job back
  2765  	ws := memdb.NewWatchSet()
  2766  	outJob, _ := state.JobByID(ws, job.ID)
  2767  	if outJob.CreateIndex != 900 {
  2768  		t.Fatalf("bad create index: %v", outJob.CreateIndex)
  2769  	}
  2770  	summary, _ := state.JobSummaryByID(ws, job.ID)
  2771  	if summary.CreateIndex != 900 {
  2772  		t.Fatalf("bad create index: %v", summary.CreateIndex)
  2773  	}
  2774  
  2775  	// Upsert an allocation
  2776  	alloc := mock.Alloc()
  2777  	alloc.JobID = job.ID
  2778  	alloc.Job = job
  2779  	state.UpsertAllocs(910, []*structs.Allocation{alloc})
  2780  
  2781  	// Update the alloc from client
  2782  	alloc1 := alloc.Copy()
  2783  	alloc1.ClientStatus = structs.AllocClientStatusPending
  2784  	alloc1.DesiredStatus = ""
  2785  	state.UpdateAllocsFromClient(920, []*structs.Allocation{alloc})
  2786  
  2787  	alloc3 := alloc.Copy()
  2788  	alloc3.ClientStatus = structs.AllocClientStatusRunning
  2789  	alloc3.DesiredStatus = ""
  2790  	state.UpdateAllocsFromClient(930, []*structs.Allocation{alloc3})
  2791  
  2792  	// Upsert the alloc
  2793  	alloc4 := alloc.Copy()
  2794  	alloc4.ClientStatus = structs.AllocClientStatusPending
  2795  	alloc4.DesiredStatus = structs.AllocDesiredStatusRun
  2796  	state.UpsertAllocs(950, []*structs.Allocation{alloc4})
  2797  
  2798  	// Again upsert the alloc
  2799  	alloc5 := alloc.Copy()
  2800  	alloc5.ClientStatus = structs.AllocClientStatusPending
  2801  	alloc5.DesiredStatus = structs.AllocDesiredStatusRun
  2802  	state.UpsertAllocs(970, []*structs.Allocation{alloc5})
  2803  
  2804  	if !watchFired(ws) {
  2805  		t.Fatalf("bad")
  2806  	}
  2807  
  2808  	expectedSummary := structs.JobSummary{
  2809  		JobID: job.ID,
  2810  		Summary: map[string]structs.TaskGroupSummary{
  2811  			"web": structs.TaskGroupSummary{
  2812  				Running: 1,
  2813  			},
  2814  		},
  2815  		Children:    new(structs.JobChildrenSummary),
  2816  		CreateIndex: 900,
  2817  		ModifyIndex: 930,
  2818  	}
  2819  
  2820  	summary, _ = state.JobSummaryByID(ws, job.ID)
  2821  	if !reflect.DeepEqual(&expectedSummary, summary) {
  2822  		t.Fatalf("expected: %#v, actual: %v", expectedSummary, summary)
  2823  	}
  2824  
  2825  	// De-register the job.
  2826  	state.DeleteJob(980, job.ID)
  2827  
  2828  	// Shouldn't have any effect on the summary
  2829  	alloc6 := alloc.Copy()
  2830  	alloc6.ClientStatus = structs.AllocClientStatusRunning
  2831  	alloc6.DesiredStatus = ""
  2832  	state.UpdateAllocsFromClient(990, []*structs.Allocation{alloc6})
  2833  
  2834  	// We shouldn't have any summary at this point
  2835  	summary, _ = state.JobSummaryByID(ws, job.ID)
  2836  	if summary != nil {
  2837  		t.Fatalf("expected nil, actual: %#v", summary)
  2838  	}
  2839  
  2840  	// Re-register the same job
  2841  	job1 := mock.Job()
  2842  	job1.ID = job.ID
  2843  	state.UpsertJob(1000, job1)
  2844  	outJob2, _ := state.JobByID(ws, job1.ID)
  2845  	if outJob2.CreateIndex != 1000 {
  2846  		t.Fatalf("bad create index: %v", outJob2.CreateIndex)
  2847  	}
  2848  	summary, _ = state.JobSummaryByID(ws, job1.ID)
  2849  	if summary.CreateIndex != 1000 {
  2850  		t.Fatalf("bad create index: %v", summary.CreateIndex)
  2851  	}
  2852  
  2853  	// Upsert an allocation
  2854  	alloc7 := alloc.Copy()
  2855  	alloc7.JobID = outJob.ID
  2856  	alloc7.Job = outJob
  2857  	alloc7.ClientStatus = structs.AllocClientStatusComplete
  2858  	alloc7.DesiredStatus = structs.AllocDesiredStatusRun
  2859  	state.UpdateAllocsFromClient(1020, []*structs.Allocation{alloc7})
  2860  
  2861  	expectedSummary = structs.JobSummary{
  2862  		JobID: job.ID,
  2863  		Summary: map[string]structs.TaskGroupSummary{
  2864  			"web": structs.TaskGroupSummary{},
  2865  		},
  2866  		Children:    new(structs.JobChildrenSummary),
  2867  		CreateIndex: 1000,
  2868  		ModifyIndex: 1000,
  2869  	}
  2870  
  2871  	summary, _ = state.JobSummaryByID(ws, job1.ID)
  2872  	if !reflect.DeepEqual(&expectedSummary, summary) {
  2873  		t.Fatalf("expected: %#v, actual: %#v", expectedSummary, summary)
  2874  	}
  2875  }
  2876  
  2877  func TestStateStore_ReconcileJobSummary(t *testing.T) {
  2878  	state := testStateStore(t)
  2879  
  2880  	// Create an alloc
  2881  	alloc := mock.Alloc()
  2882  
  2883  	// Add another task group to the job
  2884  	tg2 := alloc.Job.TaskGroups[0].Copy()
  2885  	tg2.Name = "db"
  2886  	alloc.Job.TaskGroups = append(alloc.Job.TaskGroups, tg2)
  2887  	state.UpsertJob(100, alloc.Job)
  2888  
  2889  	// Create one more alloc for the db task group
  2890  	alloc2 := mock.Alloc()
  2891  	alloc2.TaskGroup = "db"
  2892  	alloc2.JobID = alloc.JobID
  2893  	alloc2.Job = alloc.Job
  2894  
  2895  	// Upserts the alloc
  2896  	state.UpsertAllocs(110, []*structs.Allocation{alloc, alloc2})
  2897  
  2898  	// Change the state of the first alloc to running
  2899  	alloc3 := alloc.Copy()
  2900  	alloc3.ClientStatus = structs.AllocClientStatusRunning
  2901  	state.UpdateAllocsFromClient(120, []*structs.Allocation{alloc3})
  2902  
  2903  	//Add some more allocs to the second tg
  2904  	alloc4 := mock.Alloc()
  2905  	alloc4.JobID = alloc.JobID
  2906  	alloc4.Job = alloc.Job
  2907  	alloc4.TaskGroup = "db"
  2908  	alloc5 := alloc4.Copy()
  2909  	alloc5.ClientStatus = structs.AllocClientStatusRunning
  2910  
  2911  	alloc6 := mock.Alloc()
  2912  	alloc6.JobID = alloc.JobID
  2913  	alloc6.Job = alloc.Job
  2914  	alloc6.TaskGroup = "db"
  2915  	alloc7 := alloc6.Copy()
  2916  	alloc7.ClientStatus = structs.AllocClientStatusComplete
  2917  
  2918  	alloc8 := mock.Alloc()
  2919  	alloc8.JobID = alloc.JobID
  2920  	alloc8.Job = alloc.Job
  2921  	alloc8.TaskGroup = "db"
  2922  	alloc9 := alloc8.Copy()
  2923  	alloc9.ClientStatus = structs.AllocClientStatusFailed
  2924  
  2925  	alloc10 := mock.Alloc()
  2926  	alloc10.JobID = alloc.JobID
  2927  	alloc10.Job = alloc.Job
  2928  	alloc10.TaskGroup = "db"
  2929  	alloc11 := alloc10.Copy()
  2930  	alloc11.ClientStatus = structs.AllocClientStatusLost
  2931  
  2932  	state.UpsertAllocs(130, []*structs.Allocation{alloc4, alloc6, alloc8, alloc10})
  2933  
  2934  	state.UpdateAllocsFromClient(150, []*structs.Allocation{alloc5, alloc7, alloc9, alloc11})
  2935  
  2936  	// DeleteJobSummary is a helper method and doesn't modify the indexes table
  2937  	state.DeleteJobSummary(130, alloc.Job.ID)
  2938  
  2939  	state.ReconcileJobSummaries(120)
  2940  
  2941  	ws := memdb.NewWatchSet()
  2942  	summary, _ := state.JobSummaryByID(ws, alloc.Job.ID)
  2943  	expectedSummary := structs.JobSummary{
  2944  		JobID: alloc.Job.ID,
  2945  		Summary: map[string]structs.TaskGroupSummary{
  2946  			"web": structs.TaskGroupSummary{
  2947  				Running: 1,
  2948  			},
  2949  			"db": structs.TaskGroupSummary{
  2950  				Starting: 1,
  2951  				Running:  1,
  2952  				Failed:   1,
  2953  				Complete: 1,
  2954  				Lost:     1,
  2955  			},
  2956  		},
  2957  		CreateIndex: 100,
  2958  		ModifyIndex: 120,
  2959  	}
  2960  	if !reflect.DeepEqual(&expectedSummary, summary) {
  2961  		t.Fatalf("expected: %v, actual: %v", expectedSummary, summary)
  2962  	}
  2963  }
  2964  
  2965  func TestStateStore_UpdateAlloc_JobNotPresent(t *testing.T) {
  2966  	state := testStateStore(t)
  2967  
  2968  	alloc := mock.Alloc()
  2969  	state.UpsertJob(100, alloc.Job)
  2970  	state.UpsertAllocs(200, []*structs.Allocation{alloc})
  2971  
  2972  	// Delete the job
  2973  	state.DeleteJob(300, alloc.Job.ID)
  2974  
  2975  	// Update the alloc
  2976  	alloc1 := alloc.Copy()
  2977  	alloc1.ClientStatus = structs.AllocClientStatusRunning
  2978  
  2979  	// Updating allocation should not throw any error
  2980  	if err := state.UpdateAllocsFromClient(400, []*structs.Allocation{alloc1}); err != nil {
  2981  		t.Fatalf("expect err: %v", err)
  2982  	}
  2983  
  2984  	// Re-Register the job
  2985  	state.UpsertJob(500, alloc.Job)
  2986  
  2987  	// Update the alloc again
  2988  	alloc2 := alloc.Copy()
  2989  	alloc2.ClientStatus = structs.AllocClientStatusComplete
  2990  	if err := state.UpdateAllocsFromClient(400, []*structs.Allocation{alloc1}); err != nil {
  2991  		t.Fatalf("expect err: %v", err)
  2992  	}
  2993  
  2994  	// Job Summary of the newly registered job shouldn't account for the
  2995  	// allocation update for the older job
  2996  	expectedSummary := structs.JobSummary{
  2997  		JobID: alloc1.JobID,
  2998  		Summary: map[string]structs.TaskGroupSummary{
  2999  			"web": structs.TaskGroupSummary{},
  3000  		},
  3001  		Children:    new(structs.JobChildrenSummary),
  3002  		CreateIndex: 500,
  3003  		ModifyIndex: 500,
  3004  	}
  3005  
  3006  	ws := memdb.NewWatchSet()
  3007  	summary, _ := state.JobSummaryByID(ws, alloc.Job.ID)
  3008  	if !reflect.DeepEqual(&expectedSummary, summary) {
  3009  		t.Fatalf("expected: %v, actual: %v", expectedSummary, summary)
  3010  	}
  3011  }
  3012  
  3013  func TestStateStore_EvictAlloc_Alloc(t *testing.T) {
  3014  	state := testStateStore(t)
  3015  	alloc := mock.Alloc()
  3016  
  3017  	state.UpsertJobSummary(999, mock.JobSummary(alloc.JobID))
  3018  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  3019  	if err != nil {
  3020  		t.Fatalf("err: %v", err)
  3021  	}
  3022  
  3023  	alloc2 := new(structs.Allocation)
  3024  	*alloc2 = *alloc
  3025  	alloc2.DesiredStatus = structs.AllocDesiredStatusEvict
  3026  	err = state.UpsertAllocs(1001, []*structs.Allocation{alloc2})
  3027  	if err != nil {
  3028  		t.Fatalf("err: %v", err)
  3029  	}
  3030  
  3031  	ws := memdb.NewWatchSet()
  3032  	out, err := state.AllocByID(ws, alloc.ID)
  3033  	if err != nil {
  3034  		t.Fatalf("err: %v", err)
  3035  	}
  3036  
  3037  	if out.DesiredStatus != structs.AllocDesiredStatusEvict {
  3038  		t.Fatalf("bad: %#v %#v", alloc, out)
  3039  	}
  3040  
  3041  	index, err := state.Index("allocs")
  3042  	if err != nil {
  3043  		t.Fatalf("err: %v", err)
  3044  	}
  3045  	if index != 1001 {
  3046  		t.Fatalf("bad: %d", index)
  3047  	}
  3048  }
  3049  
  3050  func TestStateStore_AllocsByNode(t *testing.T) {
  3051  	state := testStateStore(t)
  3052  	var allocs []*structs.Allocation
  3053  
  3054  	for i := 0; i < 10; i++ {
  3055  		alloc := mock.Alloc()
  3056  		alloc.NodeID = "foo"
  3057  		allocs = append(allocs, alloc)
  3058  	}
  3059  
  3060  	for idx, alloc := range allocs {
  3061  		state.UpsertJobSummary(uint64(900+idx), mock.JobSummary(alloc.JobID))
  3062  	}
  3063  
  3064  	err := state.UpsertAllocs(1000, allocs)
  3065  	if err != nil {
  3066  		t.Fatalf("err: %v", err)
  3067  	}
  3068  
  3069  	ws := memdb.NewWatchSet()
  3070  	out, err := state.AllocsByNode(ws, "foo")
  3071  	if err != nil {
  3072  		t.Fatalf("err: %v", err)
  3073  	}
  3074  
  3075  	sort.Sort(AllocIDSort(allocs))
  3076  	sort.Sort(AllocIDSort(out))
  3077  
  3078  	if !reflect.DeepEqual(allocs, out) {
  3079  		t.Fatalf("bad: %#v %#v", allocs, out)
  3080  	}
  3081  
  3082  	if watchFired(ws) {
  3083  		t.Fatalf("bad")
  3084  	}
  3085  }
  3086  
  3087  func TestStateStore_AllocsByNodeTerminal(t *testing.T) {
  3088  	state := testStateStore(t)
  3089  	var allocs, term, nonterm []*structs.Allocation
  3090  
  3091  	for i := 0; i < 10; i++ {
  3092  		alloc := mock.Alloc()
  3093  		alloc.NodeID = "foo"
  3094  		if i%2 == 0 {
  3095  			alloc.DesiredStatus = structs.AllocDesiredStatusStop
  3096  			term = append(term, alloc)
  3097  		} else {
  3098  			nonterm = append(nonterm, alloc)
  3099  		}
  3100  		allocs = append(allocs, alloc)
  3101  	}
  3102  
  3103  	for idx, alloc := range allocs {
  3104  		state.UpsertJobSummary(uint64(900+idx), mock.JobSummary(alloc.JobID))
  3105  	}
  3106  
  3107  	err := state.UpsertAllocs(1000, allocs)
  3108  	if err != nil {
  3109  		t.Fatalf("err: %v", err)
  3110  	}
  3111  
  3112  	// Verify the terminal allocs
  3113  	ws := memdb.NewWatchSet()
  3114  	out, err := state.AllocsByNodeTerminal(ws, "foo", true)
  3115  	if err != nil {
  3116  		t.Fatalf("err: %v", err)
  3117  	}
  3118  
  3119  	sort.Sort(AllocIDSort(term))
  3120  	sort.Sort(AllocIDSort(out))
  3121  
  3122  	if !reflect.DeepEqual(term, out) {
  3123  		t.Fatalf("bad: %#v %#v", term, out)
  3124  	}
  3125  
  3126  	// Verify the non-terminal allocs
  3127  	out, err = state.AllocsByNodeTerminal(ws, "foo", false)
  3128  	if err != nil {
  3129  		t.Fatalf("err: %v", err)
  3130  	}
  3131  
  3132  	sort.Sort(AllocIDSort(nonterm))
  3133  	sort.Sort(AllocIDSort(out))
  3134  
  3135  	if !reflect.DeepEqual(nonterm, out) {
  3136  		t.Fatalf("bad: %#v %#v", nonterm, out)
  3137  	}
  3138  
  3139  	if watchFired(ws) {
  3140  		t.Fatalf("bad")
  3141  	}
  3142  }
  3143  
  3144  func TestStateStore_AllocsByJob(t *testing.T) {
  3145  	state := testStateStore(t)
  3146  	var allocs []*structs.Allocation
  3147  
  3148  	for i := 0; i < 10; i++ {
  3149  		alloc := mock.Alloc()
  3150  		alloc.JobID = "foo"
  3151  		allocs = append(allocs, alloc)
  3152  	}
  3153  
  3154  	for i, alloc := range allocs {
  3155  		state.UpsertJobSummary(uint64(900+i), mock.JobSummary(alloc.JobID))
  3156  	}
  3157  
  3158  	err := state.UpsertAllocs(1000, allocs)
  3159  	if err != nil {
  3160  		t.Fatalf("err: %v", err)
  3161  	}
  3162  
  3163  	ws := memdb.NewWatchSet()
  3164  	out, err := state.AllocsByJob(ws, "foo", false)
  3165  	if err != nil {
  3166  		t.Fatalf("err: %v", err)
  3167  	}
  3168  
  3169  	sort.Sort(AllocIDSort(allocs))
  3170  	sort.Sort(AllocIDSort(out))
  3171  
  3172  	if !reflect.DeepEqual(allocs, out) {
  3173  		t.Fatalf("bad: %#v %#v", allocs, out)
  3174  	}
  3175  
  3176  	if watchFired(ws) {
  3177  		t.Fatalf("bad")
  3178  	}
  3179  }
  3180  
  3181  func TestStateStore_AllocsForRegisteredJob(t *testing.T) {
  3182  	state := testStateStore(t)
  3183  	var allocs []*structs.Allocation
  3184  	var allocs1 []*structs.Allocation
  3185  
  3186  	job := mock.Job()
  3187  	job.ID = "foo"
  3188  	state.UpsertJob(100, job)
  3189  	for i := 0; i < 3; i++ {
  3190  		alloc := mock.Alloc()
  3191  		alloc.Job = job
  3192  		alloc.JobID = job.ID
  3193  		allocs = append(allocs, alloc)
  3194  	}
  3195  	if err := state.UpsertAllocs(200, allocs); err != nil {
  3196  		t.Fatalf("err: %v", err)
  3197  	}
  3198  
  3199  	if err := state.DeleteJob(250, job.ID); err != nil {
  3200  		t.Fatalf("err: %v", err)
  3201  	}
  3202  
  3203  	job1 := mock.Job()
  3204  	job1.ID = "foo"
  3205  	job1.CreateIndex = 50
  3206  	state.UpsertJob(300, job1)
  3207  	for i := 0; i < 4; i++ {
  3208  		alloc := mock.Alloc()
  3209  		alloc.Job = job1
  3210  		alloc.JobID = job1.ID
  3211  		allocs1 = append(allocs1, alloc)
  3212  	}
  3213  
  3214  	if err := state.UpsertAllocs(1000, allocs1); err != nil {
  3215  		t.Fatalf("err: %v", err)
  3216  	}
  3217  
  3218  	ws := memdb.NewWatchSet()
  3219  	out, err := state.AllocsByJob(ws, job1.ID, true)
  3220  	if err != nil {
  3221  		t.Fatalf("err: %v", err)
  3222  	}
  3223  
  3224  	expected := len(allocs) + len(allocs1)
  3225  	if len(out) != expected {
  3226  		t.Fatalf("expected: %v, actual: %v", expected, len(out))
  3227  	}
  3228  
  3229  	out1, err := state.AllocsByJob(ws, job1.ID, false)
  3230  	expected = len(allocs1)
  3231  	if len(out1) != expected {
  3232  		t.Fatalf("expected: %v, actual: %v", expected, len(out1))
  3233  	}
  3234  
  3235  	if watchFired(ws) {
  3236  		t.Fatalf("bad")
  3237  	}
  3238  }
  3239  
  3240  func TestStateStore_AllocsByIDPrefix(t *testing.T) {
  3241  	state := testStateStore(t)
  3242  	var allocs []*structs.Allocation
  3243  
  3244  	ids := []string{
  3245  		"aaaaaaaa-7bfb-395d-eb95-0685af2176b2",
  3246  		"aaaaaaab-7bfb-395d-eb95-0685af2176b2",
  3247  		"aaaaaabb-7bfb-395d-eb95-0685af2176b2",
  3248  		"aaaaabbb-7bfb-395d-eb95-0685af2176b2",
  3249  		"aaaabbbb-7bfb-395d-eb95-0685af2176b2",
  3250  		"aaabbbbb-7bfb-395d-eb95-0685af2176b2",
  3251  		"aabbbbbb-7bfb-395d-eb95-0685af2176b2",
  3252  		"abbbbbbb-7bfb-395d-eb95-0685af2176b2",
  3253  		"bbbbbbbb-7bfb-395d-eb95-0685af2176b2",
  3254  	}
  3255  	for i := 0; i < 9; i++ {
  3256  		alloc := mock.Alloc()
  3257  		alloc.ID = ids[i]
  3258  		allocs = append(allocs, alloc)
  3259  	}
  3260  
  3261  	for i, alloc := range allocs {
  3262  		state.UpsertJobSummary(uint64(900+i), mock.JobSummary(alloc.JobID))
  3263  	}
  3264  
  3265  	err := state.UpsertAllocs(1000, allocs)
  3266  	if err != nil {
  3267  		t.Fatalf("err: %v", err)
  3268  	}
  3269  
  3270  	ws := memdb.NewWatchSet()
  3271  	iter, err := state.AllocsByIDPrefix(ws, "aaaa")
  3272  	if err != nil {
  3273  		t.Fatalf("err: %v", err)
  3274  	}
  3275  
  3276  	gatherAllocs := func(iter memdb.ResultIterator) []*structs.Allocation {
  3277  		var allocs []*structs.Allocation
  3278  		for {
  3279  			raw := iter.Next()
  3280  			if raw == nil {
  3281  				break
  3282  			}
  3283  			allocs = append(allocs, raw.(*structs.Allocation))
  3284  		}
  3285  		return allocs
  3286  	}
  3287  
  3288  	out := gatherAllocs(iter)
  3289  	if len(out) != 5 {
  3290  		t.Fatalf("bad: expected five allocations, got: %#v", out)
  3291  	}
  3292  
  3293  	sort.Sort(AllocIDSort(allocs))
  3294  
  3295  	for index, alloc := range out {
  3296  		if ids[index] != alloc.ID {
  3297  			t.Fatalf("bad: got unexpected id: %s", alloc.ID)
  3298  		}
  3299  	}
  3300  
  3301  	iter, err = state.AllocsByIDPrefix(ws, "b-a7bfb")
  3302  	if err != nil {
  3303  		t.Fatalf("err: %v", err)
  3304  	}
  3305  
  3306  	out = gatherAllocs(iter)
  3307  	if len(out) != 0 {
  3308  		t.Fatalf("bad: unexpected zero allocations, got: %#v", out)
  3309  	}
  3310  
  3311  	if watchFired(ws) {
  3312  		t.Fatalf("bad")
  3313  	}
  3314  }
  3315  
  3316  func TestStateStore_Allocs(t *testing.T) {
  3317  	state := testStateStore(t)
  3318  	var allocs []*structs.Allocation
  3319  
  3320  	for i := 0; i < 10; i++ {
  3321  		alloc := mock.Alloc()
  3322  		allocs = append(allocs, alloc)
  3323  	}
  3324  	for i, alloc := range allocs {
  3325  		state.UpsertJobSummary(uint64(900+i), mock.JobSummary(alloc.JobID))
  3326  	}
  3327  
  3328  	err := state.UpsertAllocs(1000, allocs)
  3329  	if err != nil {
  3330  		t.Fatalf("err: %v", err)
  3331  	}
  3332  
  3333  	ws := memdb.NewWatchSet()
  3334  	iter, err := state.Allocs(ws)
  3335  	if err != nil {
  3336  		t.Fatalf("err: %v", err)
  3337  	}
  3338  
  3339  	var out []*structs.Allocation
  3340  	for {
  3341  		raw := iter.Next()
  3342  		if raw == nil {
  3343  			break
  3344  		}
  3345  		out = append(out, raw.(*structs.Allocation))
  3346  	}
  3347  
  3348  	sort.Sort(AllocIDSort(allocs))
  3349  	sort.Sort(AllocIDSort(out))
  3350  
  3351  	if !reflect.DeepEqual(allocs, out) {
  3352  		t.Fatalf("bad: %#v %#v", allocs, out)
  3353  	}
  3354  
  3355  	if watchFired(ws) {
  3356  		t.Fatalf("bad")
  3357  	}
  3358  }
  3359  
  3360  func TestStateStore_RestoreAlloc(t *testing.T) {
  3361  	state := testStateStore(t)
  3362  	alloc := mock.Alloc()
  3363  
  3364  	restore, err := state.Restore()
  3365  	if err != nil {
  3366  		t.Fatalf("err: %v", err)
  3367  	}
  3368  
  3369  	err = restore.AllocRestore(alloc)
  3370  	if err != nil {
  3371  		t.Fatalf("err: %v", err)
  3372  	}
  3373  
  3374  	restore.Commit()
  3375  
  3376  	ws := memdb.NewWatchSet()
  3377  	out, err := state.AllocByID(ws, alloc.ID)
  3378  	if err != nil {
  3379  		t.Fatalf("err: %v", err)
  3380  	}
  3381  
  3382  	if !reflect.DeepEqual(out, alloc) {
  3383  		t.Fatalf("Bad: %#v %#v", out, alloc)
  3384  	}
  3385  
  3386  	if watchFired(ws) {
  3387  		t.Fatalf("bad")
  3388  	}
  3389  }
  3390  
  3391  func TestStateStore_RestoreAlloc_NoEphemeralDisk(t *testing.T) {
  3392  	state := testStateStore(t)
  3393  	alloc := mock.Alloc()
  3394  	alloc.Job.TaskGroups[0].EphemeralDisk = nil
  3395  	alloc.Job.TaskGroups[0].Tasks[0].Resources.DiskMB = 120
  3396  
  3397  	restore, err := state.Restore()
  3398  	if err != nil {
  3399  		t.Fatalf("err: %v", err)
  3400  	}
  3401  
  3402  	err = restore.AllocRestore(alloc)
  3403  	if err != nil {
  3404  		t.Fatalf("err: %v", err)
  3405  	}
  3406  
  3407  	restore.Commit()
  3408  
  3409  	ws := memdb.NewWatchSet()
  3410  	out, err := state.AllocByID(ws, alloc.ID)
  3411  	if err != nil {
  3412  		t.Fatalf("err: %v", err)
  3413  	}
  3414  
  3415  	expected := alloc.Copy()
  3416  	expected.Job.TaskGroups[0].EphemeralDisk = &structs.EphemeralDisk{SizeMB: 120}
  3417  	expected.Job.TaskGroups[0].Tasks[0].Resources.DiskMB = 0
  3418  
  3419  	if !reflect.DeepEqual(out, expected) {
  3420  		t.Fatalf("Bad: %#v %#v", out, expected)
  3421  	}
  3422  
  3423  	if watchFired(ws) {
  3424  		t.Fatalf("bad")
  3425  	}
  3426  }
  3427  
  3428  func TestStateStore_SetJobStatus_ForceStatus(t *testing.T) {
  3429  	state := testStateStore(t)
  3430  	txn := state.db.Txn(true)
  3431  
  3432  	// Create and insert a mock job.
  3433  	job := mock.Job()
  3434  	job.Status = ""
  3435  	job.ModifyIndex = 0
  3436  	if err := txn.Insert("jobs", job); err != nil {
  3437  		t.Fatalf("job insert failed: %v", err)
  3438  	}
  3439  
  3440  	exp := "foobar"
  3441  	index := uint64(1000)
  3442  	if err := state.setJobStatus(index, txn, job, false, exp); err != nil {
  3443  		t.Fatalf("setJobStatus() failed: %v", err)
  3444  	}
  3445  
  3446  	i, err := txn.First("jobs", "id", job.ID)
  3447  	if err != nil {
  3448  		t.Fatalf("job lookup failed: %v", err)
  3449  	}
  3450  	updated := i.(*structs.Job)
  3451  
  3452  	if updated.Status != exp {
  3453  		t.Fatalf("setJobStatus() set %v; expected %v", updated.Status, exp)
  3454  	}
  3455  
  3456  	if updated.ModifyIndex != index {
  3457  		t.Fatalf("setJobStatus() set %d; expected %d", updated.ModifyIndex, index)
  3458  	}
  3459  }
  3460  
  3461  func TestStateStore_SetJobStatus_NoOp(t *testing.T) {
  3462  	state := testStateStore(t)
  3463  	txn := state.db.Txn(true)
  3464  
  3465  	// Create and insert a mock job that should be pending.
  3466  	job := mock.Job()
  3467  	job.Status = structs.JobStatusPending
  3468  	job.ModifyIndex = 10
  3469  	if err := txn.Insert("jobs", job); err != nil {
  3470  		t.Fatalf("job insert failed: %v", err)
  3471  	}
  3472  
  3473  	index := uint64(1000)
  3474  	if err := state.setJobStatus(index, txn, job, false, ""); err != nil {
  3475  		t.Fatalf("setJobStatus() failed: %v", err)
  3476  	}
  3477  
  3478  	i, err := txn.First("jobs", "id", job.ID)
  3479  	if err != nil {
  3480  		t.Fatalf("job lookup failed: %v", err)
  3481  	}
  3482  	updated := i.(*structs.Job)
  3483  
  3484  	if updated.ModifyIndex == index {
  3485  		t.Fatalf("setJobStatus() should have been a no-op")
  3486  	}
  3487  }
  3488  
  3489  func TestStateStore_SetJobStatus(t *testing.T) {
  3490  	state := testStateStore(t)
  3491  	txn := state.db.Txn(true)
  3492  
  3493  	// Create and insert a mock job that should be pending but has an incorrect
  3494  	// status.
  3495  	job := mock.Job()
  3496  	job.Status = "foobar"
  3497  	job.ModifyIndex = 10
  3498  	if err := txn.Insert("jobs", job); err != nil {
  3499  		t.Fatalf("job insert failed: %v", err)
  3500  	}
  3501  
  3502  	index := uint64(1000)
  3503  	if err := state.setJobStatus(index, txn, job, false, ""); err != nil {
  3504  		t.Fatalf("setJobStatus() failed: %v", err)
  3505  	}
  3506  
  3507  	i, err := txn.First("jobs", "id", job.ID)
  3508  	if err != nil {
  3509  		t.Fatalf("job lookup failed: %v", err)
  3510  	}
  3511  	updated := i.(*structs.Job)
  3512  
  3513  	if updated.Status != structs.JobStatusPending {
  3514  		t.Fatalf("setJobStatus() set %v; expected %v", updated.Status, structs.JobStatusPending)
  3515  	}
  3516  
  3517  	if updated.ModifyIndex != index {
  3518  		t.Fatalf("setJobStatus() set %d; expected %d", updated.ModifyIndex, index)
  3519  	}
  3520  }
  3521  
  3522  func TestStateStore_GetJobStatus_NoEvalsOrAllocs(t *testing.T) {
  3523  	job := mock.Job()
  3524  	state := testStateStore(t)
  3525  	txn := state.db.Txn(false)
  3526  	status, err := state.getJobStatus(txn, job, false)
  3527  	if err != nil {
  3528  		t.Fatalf("getJobStatus() failed: %v", err)
  3529  	}
  3530  
  3531  	if status != structs.JobStatusPending {
  3532  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusPending)
  3533  	}
  3534  }
  3535  
  3536  func TestStateStore_GetJobStatus_NoEvalsOrAllocs_Periodic(t *testing.T) {
  3537  	job := mock.PeriodicJob()
  3538  	state := testStateStore(t)
  3539  	txn := state.db.Txn(false)
  3540  	status, err := state.getJobStatus(txn, job, false)
  3541  	if err != nil {
  3542  		t.Fatalf("getJobStatus() failed: %v", err)
  3543  	}
  3544  
  3545  	if status != structs.JobStatusRunning {
  3546  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusRunning)
  3547  	}
  3548  }
  3549  
  3550  func TestStateStore_GetJobStatus_NoEvalsOrAllocs_EvalDelete(t *testing.T) {
  3551  	job := mock.Job()
  3552  	state := testStateStore(t)
  3553  	txn := state.db.Txn(false)
  3554  	status, err := state.getJobStatus(txn, job, true)
  3555  	if err != nil {
  3556  		t.Fatalf("getJobStatus() failed: %v", err)
  3557  	}
  3558  
  3559  	if status != structs.JobStatusDead {
  3560  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusDead)
  3561  	}
  3562  }
  3563  
  3564  func TestStateStore_GetJobStatus_DeadEvalsAndAllocs(t *testing.T) {
  3565  	state := testStateStore(t)
  3566  	job := mock.Job()
  3567  
  3568  	// Create a mock alloc that is dead.
  3569  	alloc := mock.Alloc()
  3570  	alloc.JobID = job.ID
  3571  	alloc.DesiredStatus = structs.AllocDesiredStatusStop
  3572  	state.UpsertJobSummary(999, mock.JobSummary(alloc.JobID))
  3573  	if err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}); err != nil {
  3574  		t.Fatalf("err: %v", err)
  3575  	}
  3576  
  3577  	// Create a mock eval that is complete
  3578  	eval := mock.Eval()
  3579  	eval.JobID = job.ID
  3580  	eval.Status = structs.EvalStatusComplete
  3581  	if err := state.UpsertEvals(1001, []*structs.Evaluation{eval}); err != nil {
  3582  		t.Fatalf("err: %v", err)
  3583  	}
  3584  
  3585  	txn := state.db.Txn(false)
  3586  	status, err := state.getJobStatus(txn, job, false)
  3587  	if err != nil {
  3588  		t.Fatalf("getJobStatus() failed: %v", err)
  3589  	}
  3590  
  3591  	if status != structs.JobStatusDead {
  3592  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusDead)
  3593  	}
  3594  }
  3595  
  3596  func TestStateStore_GetJobStatus_RunningAlloc(t *testing.T) {
  3597  	state := testStateStore(t)
  3598  	job := mock.Job()
  3599  
  3600  	// Create a mock alloc that is running.
  3601  	alloc := mock.Alloc()
  3602  	alloc.JobID = job.ID
  3603  	alloc.DesiredStatus = structs.AllocDesiredStatusRun
  3604  	state.UpsertJobSummary(999, mock.JobSummary(alloc.JobID))
  3605  	if err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}); err != nil {
  3606  		t.Fatalf("err: %v", err)
  3607  	}
  3608  
  3609  	txn := state.db.Txn(false)
  3610  	status, err := state.getJobStatus(txn, job, true)
  3611  	if err != nil {
  3612  		t.Fatalf("getJobStatus() failed: %v", err)
  3613  	}
  3614  
  3615  	if status != structs.JobStatusRunning {
  3616  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusRunning)
  3617  	}
  3618  }
  3619  
  3620  func TestStateStore_SetJobStatus_PendingEval(t *testing.T) {
  3621  	state := testStateStore(t)
  3622  	job := mock.Job()
  3623  
  3624  	// Create a mock eval that is pending.
  3625  	eval := mock.Eval()
  3626  	eval.JobID = job.ID
  3627  	eval.Status = structs.EvalStatusPending
  3628  	if err := state.UpsertEvals(1000, []*structs.Evaluation{eval}); err != nil {
  3629  		t.Fatalf("err: %v", err)
  3630  	}
  3631  
  3632  	txn := state.db.Txn(false)
  3633  	status, err := state.getJobStatus(txn, job, true)
  3634  	if err != nil {
  3635  		t.Fatalf("getJobStatus() failed: %v", err)
  3636  	}
  3637  
  3638  	if status != structs.JobStatusPending {
  3639  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusPending)
  3640  	}
  3641  }
  3642  
  3643  func TestStateJobSummary_UpdateJobCount(t *testing.T) {
  3644  	state := testStateStore(t)
  3645  	alloc := mock.Alloc()
  3646  	job := alloc.Job
  3647  	job.TaskGroups[0].Count = 3
  3648  
  3649  	// Create watchsets so we can test that upsert fires the watch
  3650  	ws := memdb.NewWatchSet()
  3651  	if _, err := state.JobSummaryByID(ws, job.ID); err != nil {
  3652  		t.Fatalf("bad: %v", err)
  3653  	}
  3654  
  3655  	if err := state.UpsertJob(1000, job); err != nil {
  3656  		t.Fatalf("err: %v", err)
  3657  	}
  3658  
  3659  	if err := state.UpsertAllocs(1001, []*structs.Allocation{alloc}); err != nil {
  3660  		t.Fatalf("err: %v", err)
  3661  	}
  3662  
  3663  	if !watchFired(ws) {
  3664  		t.Fatalf("bad")
  3665  	}
  3666  
  3667  	ws = memdb.NewWatchSet()
  3668  	summary, _ := state.JobSummaryByID(ws, job.ID)
  3669  	expectedSummary := structs.JobSummary{
  3670  		JobID: job.ID,
  3671  		Summary: map[string]structs.TaskGroupSummary{
  3672  			"web": {
  3673  				Starting: 1,
  3674  			},
  3675  		},
  3676  		Children:    new(structs.JobChildrenSummary),
  3677  		CreateIndex: 1000,
  3678  		ModifyIndex: 1001,
  3679  	}
  3680  	if !reflect.DeepEqual(summary, &expectedSummary) {
  3681  		t.Fatalf("expected: %v, actual: %v", expectedSummary, summary)
  3682  	}
  3683  
  3684  	// Create watchsets so we can test that upsert fires the watch
  3685  	ws2 := memdb.NewWatchSet()
  3686  	if _, err := state.JobSummaryByID(ws2, job.ID); err != nil {
  3687  		t.Fatalf("bad: %v", err)
  3688  	}
  3689  
  3690  	alloc2 := mock.Alloc()
  3691  	alloc2.Job = job
  3692  	alloc2.JobID = job.ID
  3693  
  3694  	alloc3 := mock.Alloc()
  3695  	alloc3.Job = job
  3696  	alloc3.JobID = job.ID
  3697  
  3698  	if err := state.UpsertAllocs(1002, []*structs.Allocation{alloc2, alloc3}); err != nil {
  3699  		t.Fatalf("err: %v", err)
  3700  	}
  3701  
  3702  	if !watchFired(ws2) {
  3703  		t.Fatalf("bad")
  3704  	}
  3705  
  3706  	outA, _ := state.AllocByID(ws, alloc3.ID)
  3707  
  3708  	summary, _ = state.JobSummaryByID(ws, job.ID)
  3709  	expectedSummary = structs.JobSummary{
  3710  		JobID: job.ID,
  3711  		Summary: map[string]structs.TaskGroupSummary{
  3712  			"web": {
  3713  				Starting: 3,
  3714  			},
  3715  		},
  3716  		Children:    new(structs.JobChildrenSummary),
  3717  		CreateIndex: job.CreateIndex,
  3718  		ModifyIndex: outA.ModifyIndex,
  3719  	}
  3720  	if !reflect.DeepEqual(summary, &expectedSummary) {
  3721  		t.Fatalf("expected summary: %v, actual: %v", expectedSummary, summary)
  3722  	}
  3723  
  3724  	// Create watchsets so we can test that upsert fires the watch
  3725  	ws3 := memdb.NewWatchSet()
  3726  	if _, err := state.JobSummaryByID(ws3, job.ID); err != nil {
  3727  		t.Fatalf("bad: %v", err)
  3728  	}
  3729  
  3730  	alloc4 := mock.Alloc()
  3731  	alloc4.ID = alloc2.ID
  3732  	alloc4.Job = alloc2.Job
  3733  	alloc4.JobID = alloc2.JobID
  3734  	alloc4.ClientStatus = structs.AllocClientStatusComplete
  3735  
  3736  	alloc5 := mock.Alloc()
  3737  	alloc5.ID = alloc3.ID
  3738  	alloc5.Job = alloc3.Job
  3739  	alloc5.JobID = alloc3.JobID
  3740  	alloc5.ClientStatus = structs.AllocClientStatusComplete
  3741  
  3742  	if err := state.UpdateAllocsFromClient(1004, []*structs.Allocation{alloc4, alloc5}); err != nil {
  3743  		t.Fatalf("err: %v", err)
  3744  	}
  3745  
  3746  	if !watchFired(ws2) {
  3747  		t.Fatalf("bad")
  3748  	}
  3749  
  3750  	outA, _ = state.AllocByID(ws, alloc5.ID)
  3751  	summary, _ = state.JobSummaryByID(ws, job.ID)
  3752  	expectedSummary = structs.JobSummary{
  3753  		JobID: job.ID,
  3754  		Summary: map[string]structs.TaskGroupSummary{
  3755  			"web": {
  3756  				Complete: 2,
  3757  				Starting: 1,
  3758  			},
  3759  		},
  3760  		Children:    new(structs.JobChildrenSummary),
  3761  		CreateIndex: job.CreateIndex,
  3762  		ModifyIndex: outA.ModifyIndex,
  3763  	}
  3764  	if !reflect.DeepEqual(summary, &expectedSummary) {
  3765  		t.Fatalf("expected: %v, actual: %v", expectedSummary, summary)
  3766  	}
  3767  }
  3768  
  3769  func TestJobSummary_UpdateClientStatus(t *testing.T) {
  3770  	state := testStateStore(t)
  3771  	alloc := mock.Alloc()
  3772  	job := alloc.Job
  3773  	job.TaskGroups[0].Count = 3
  3774  
  3775  	alloc2 := mock.Alloc()
  3776  	alloc2.Job = job
  3777  	alloc2.JobID = job.ID
  3778  
  3779  	alloc3 := mock.Alloc()
  3780  	alloc3.Job = job
  3781  	alloc3.JobID = job.ID
  3782  
  3783  	err := state.UpsertJob(1000, job)
  3784  	if err != nil {
  3785  		t.Fatalf("err: %v", err)
  3786  	}
  3787  
  3788  	if err := state.UpsertAllocs(1001, []*structs.Allocation{alloc, alloc2, alloc3}); err != nil {
  3789  		t.Fatalf("err: %v", err)
  3790  	}
  3791  
  3792  	ws := memdb.NewWatchSet()
  3793  	summary, _ := state.JobSummaryByID(ws, job.ID)
  3794  	if summary.Summary["web"].Starting != 3 {
  3795  		t.Fatalf("bad job summary: %v", summary)
  3796  	}
  3797  
  3798  	alloc4 := mock.Alloc()
  3799  	alloc4.ID = alloc2.ID
  3800  	alloc4.Job = alloc2.Job
  3801  	alloc4.JobID = alloc2.JobID
  3802  	alloc4.ClientStatus = structs.AllocClientStatusComplete
  3803  
  3804  	alloc5 := mock.Alloc()
  3805  	alloc5.ID = alloc3.ID
  3806  	alloc5.Job = alloc3.Job
  3807  	alloc5.JobID = alloc3.JobID
  3808  	alloc5.ClientStatus = structs.AllocClientStatusFailed
  3809  
  3810  	alloc6 := mock.Alloc()
  3811  	alloc6.ID = alloc.ID
  3812  	alloc6.Job = alloc.Job
  3813  	alloc6.JobID = alloc.JobID
  3814  	alloc6.ClientStatus = structs.AllocClientStatusRunning
  3815  
  3816  	if err := state.UpdateAllocsFromClient(1002, []*structs.Allocation{alloc4, alloc5, alloc6}); err != nil {
  3817  		t.Fatalf("err: %v", err)
  3818  	}
  3819  
  3820  	if !watchFired(ws) {
  3821  		t.Fatalf("bad")
  3822  	}
  3823  
  3824  	summary, _ = state.JobSummaryByID(ws, job.ID)
  3825  	if summary.Summary["web"].Running != 1 || summary.Summary["web"].Failed != 1 || summary.Summary["web"].Complete != 1 {
  3826  		t.Fatalf("bad job summary: %v", summary)
  3827  	}
  3828  
  3829  	alloc7 := mock.Alloc()
  3830  	alloc7.Job = alloc.Job
  3831  	alloc7.JobID = alloc.JobID
  3832  
  3833  	if err := state.UpsertAllocs(1003, []*structs.Allocation{alloc7}); err != nil {
  3834  		t.Fatalf("err: %v", err)
  3835  	}
  3836  	summary, _ = state.JobSummaryByID(ws, job.ID)
  3837  	if summary.Summary["web"].Starting != 1 || summary.Summary["web"].Running != 1 || summary.Summary["web"].Failed != 1 || summary.Summary["web"].Complete != 1 {
  3838  		t.Fatalf("bad job summary: %v", summary)
  3839  	}
  3840  }
  3841  
  3842  func TestStateStore_UpsertVaultAccessors(t *testing.T) {
  3843  	state := testStateStore(t)
  3844  	a := mock.VaultAccessor()
  3845  	a2 := mock.VaultAccessor()
  3846  
  3847  	ws := memdb.NewWatchSet()
  3848  	if _, err := state.VaultAccessor(ws, a.Accessor); err != nil {
  3849  		t.Fatalf("err: %v", err)
  3850  	}
  3851  
  3852  	if _, err := state.VaultAccessor(ws, a2.Accessor); err != nil {
  3853  		t.Fatalf("err: %v", err)
  3854  	}
  3855  
  3856  	err := state.UpsertVaultAccessor(1000, []*structs.VaultAccessor{a, a2})
  3857  	if err != nil {
  3858  		t.Fatalf("err: %v", err)
  3859  	}
  3860  
  3861  	if !watchFired(ws) {
  3862  		t.Fatalf("bad")
  3863  	}
  3864  
  3865  	ws = memdb.NewWatchSet()
  3866  	out, err := state.VaultAccessor(ws, a.Accessor)
  3867  	if err != nil {
  3868  		t.Fatalf("err: %v", err)
  3869  	}
  3870  
  3871  	if !reflect.DeepEqual(a, out) {
  3872  		t.Fatalf("bad: %#v %#v", a, out)
  3873  	}
  3874  
  3875  	out, err = state.VaultAccessor(ws, a2.Accessor)
  3876  	if err != nil {
  3877  		t.Fatalf("err: %v", err)
  3878  	}
  3879  
  3880  	if !reflect.DeepEqual(a2, out) {
  3881  		t.Fatalf("bad: %#v %#v", a2, out)
  3882  	}
  3883  
  3884  	iter, err := state.VaultAccessors(ws)
  3885  	if err != nil {
  3886  		t.Fatalf("err: %v", err)
  3887  	}
  3888  
  3889  	count := 0
  3890  	for {
  3891  		raw := iter.Next()
  3892  		if raw == nil {
  3893  			break
  3894  		}
  3895  
  3896  		count++
  3897  		accessor := raw.(*structs.VaultAccessor)
  3898  
  3899  		if !reflect.DeepEqual(accessor, a) && !reflect.DeepEqual(accessor, a2) {
  3900  			t.Fatalf("bad: %#v", accessor)
  3901  		}
  3902  	}
  3903  
  3904  	if count != 2 {
  3905  		t.Fatalf("bad: %d", count)
  3906  	}
  3907  
  3908  	index, err := state.Index("vault_accessors")
  3909  	if err != nil {
  3910  		t.Fatalf("err: %v", err)
  3911  	}
  3912  	if index != 1000 {
  3913  		t.Fatalf("bad: %d", index)
  3914  	}
  3915  
  3916  	if watchFired(ws) {
  3917  		t.Fatalf("bad")
  3918  	}
  3919  }
  3920  
  3921  func TestStateStore_DeleteVaultAccessors(t *testing.T) {
  3922  	state := testStateStore(t)
  3923  	a1 := mock.VaultAccessor()
  3924  	a2 := mock.VaultAccessor()
  3925  	accessors := []*structs.VaultAccessor{a1, a2}
  3926  
  3927  	err := state.UpsertVaultAccessor(1000, accessors)
  3928  	if err != nil {
  3929  		t.Fatalf("err: %v", err)
  3930  	}
  3931  
  3932  	ws := memdb.NewWatchSet()
  3933  	if _, err := state.VaultAccessor(ws, a1.Accessor); err != nil {
  3934  		t.Fatalf("err: %v", err)
  3935  	}
  3936  
  3937  	err = state.DeleteVaultAccessors(1001, accessors)
  3938  	if err != nil {
  3939  		t.Fatalf("err: %v", err)
  3940  	}
  3941  
  3942  	if !watchFired(ws) {
  3943  		t.Fatalf("bad")
  3944  	}
  3945  
  3946  	ws = memdb.NewWatchSet()
  3947  	out, err := state.VaultAccessor(ws, a1.Accessor)
  3948  	if err != nil {
  3949  		t.Fatalf("err: %v", err)
  3950  	}
  3951  	if out != nil {
  3952  		t.Fatalf("bad: %#v %#v", a1, out)
  3953  	}
  3954  	out, err = state.VaultAccessor(ws, a2.Accessor)
  3955  	if err != nil {
  3956  		t.Fatalf("err: %v", err)
  3957  	}
  3958  	if out != nil {
  3959  		t.Fatalf("bad: %#v %#v", a2, out)
  3960  	}
  3961  
  3962  	index, err := state.Index("vault_accessors")
  3963  	if err != nil {
  3964  		t.Fatalf("err: %v", err)
  3965  	}
  3966  	if index != 1001 {
  3967  		t.Fatalf("bad: %d", index)
  3968  	}
  3969  
  3970  	if watchFired(ws) {
  3971  		t.Fatalf("bad")
  3972  	}
  3973  }
  3974  
  3975  func TestStateStore_VaultAccessorsByAlloc(t *testing.T) {
  3976  	state := testStateStore(t)
  3977  	alloc := mock.Alloc()
  3978  	var accessors []*structs.VaultAccessor
  3979  	var expected []*structs.VaultAccessor
  3980  
  3981  	for i := 0; i < 5; i++ {
  3982  		accessor := mock.VaultAccessor()
  3983  		accessor.AllocID = alloc.ID
  3984  		expected = append(expected, accessor)
  3985  		accessors = append(accessors, accessor)
  3986  	}
  3987  
  3988  	for i := 0; i < 10; i++ {
  3989  		accessor := mock.VaultAccessor()
  3990  		accessors = append(accessors, accessor)
  3991  	}
  3992  
  3993  	err := state.UpsertVaultAccessor(1000, accessors)
  3994  	if err != nil {
  3995  		t.Fatalf("err: %v", err)
  3996  	}
  3997  
  3998  	ws := memdb.NewWatchSet()
  3999  	out, err := state.VaultAccessorsByAlloc(ws, alloc.ID)
  4000  	if err != nil {
  4001  		t.Fatalf("err: %v", err)
  4002  	}
  4003  
  4004  	if len(expected) != len(out) {
  4005  		t.Fatalf("bad: %#v %#v", len(expected), len(out))
  4006  	}
  4007  
  4008  	index, err := state.Index("vault_accessors")
  4009  	if err != nil {
  4010  		t.Fatalf("err: %v", err)
  4011  	}
  4012  	if index != 1000 {
  4013  		t.Fatalf("bad: %d", index)
  4014  	}
  4015  
  4016  	if watchFired(ws) {
  4017  		t.Fatalf("bad")
  4018  	}
  4019  }
  4020  
  4021  func TestStateStore_VaultAccessorsByNode(t *testing.T) {
  4022  	state := testStateStore(t)
  4023  	node := mock.Node()
  4024  	var accessors []*structs.VaultAccessor
  4025  	var expected []*structs.VaultAccessor
  4026  
  4027  	for i := 0; i < 5; i++ {
  4028  		accessor := mock.VaultAccessor()
  4029  		accessor.NodeID = node.ID
  4030  		expected = append(expected, accessor)
  4031  		accessors = append(accessors, accessor)
  4032  	}
  4033  
  4034  	for i := 0; i < 10; i++ {
  4035  		accessor := mock.VaultAccessor()
  4036  		accessors = append(accessors, accessor)
  4037  	}
  4038  
  4039  	err := state.UpsertVaultAccessor(1000, accessors)
  4040  	if err != nil {
  4041  		t.Fatalf("err: %v", err)
  4042  	}
  4043  
  4044  	ws := memdb.NewWatchSet()
  4045  	out, err := state.VaultAccessorsByNode(ws, node.ID)
  4046  	if err != nil {
  4047  		t.Fatalf("err: %v", err)
  4048  	}
  4049  
  4050  	if len(expected) != len(out) {
  4051  		t.Fatalf("bad: %#v %#v", len(expected), len(out))
  4052  	}
  4053  
  4054  	index, err := state.Index("vault_accessors")
  4055  	if err != nil {
  4056  		t.Fatalf("err: %v", err)
  4057  	}
  4058  	if index != 1000 {
  4059  		t.Fatalf("bad: %d", index)
  4060  	}
  4061  
  4062  	if watchFired(ws) {
  4063  		t.Fatalf("bad")
  4064  	}
  4065  }
  4066  
  4067  func TestStateStore_RestoreVaultAccessor(t *testing.T) {
  4068  	state := testStateStore(t)
  4069  	a := mock.VaultAccessor()
  4070  
  4071  	restore, err := state.Restore()
  4072  	if err != nil {
  4073  		t.Fatalf("err: %v", err)
  4074  	}
  4075  
  4076  	err = restore.VaultAccessorRestore(a)
  4077  	if err != nil {
  4078  		t.Fatalf("err: %v", err)
  4079  	}
  4080  	restore.Commit()
  4081  
  4082  	ws := memdb.NewWatchSet()
  4083  	out, err := state.VaultAccessor(ws, a.Accessor)
  4084  	if err != nil {
  4085  		t.Fatalf("err: %v", err)
  4086  	}
  4087  
  4088  	if !reflect.DeepEqual(out, a) {
  4089  		t.Fatalf("Bad: %#v %#v", out, a)
  4090  	}
  4091  
  4092  	if watchFired(ws) {
  4093  		t.Fatalf("bad")
  4094  	}
  4095  }
  4096  
  4097  func TestStateStore_Abandon(t *testing.T) {
  4098  	s := testStateStore(t)
  4099  	abandonCh := s.AbandonCh()
  4100  	s.Abandon()
  4101  	select {
  4102  	case <-abandonCh:
  4103  	default:
  4104  		t.Fatalf("bad")
  4105  	}
  4106  }
  4107  
  4108  // watchFired is a helper for unit tests that returns if the given watch set
  4109  // fired (it doesn't care which watch actually fired). This uses a fixed
  4110  // timeout since we already expect the event happened before calling this and
  4111  // just need to distinguish a fire from a timeout. We do need a little time to
  4112  // allow the watch to set up any goroutines, though.
  4113  func watchFired(ws memdb.WatchSet) bool {
  4114  	timedOut := ws.Watch(time.After(50 * time.Millisecond))
  4115  	return !timedOut
  4116  }
  4117  
  4118  // NodeIDSort is used to sort nodes by ID
  4119  type NodeIDSort []*structs.Node
  4120  
  4121  func (n NodeIDSort) Len() int {
  4122  	return len(n)
  4123  }
  4124  
  4125  func (n NodeIDSort) Less(i, j int) bool {
  4126  	return n[i].ID < n[j].ID
  4127  }
  4128  
  4129  func (n NodeIDSort) Swap(i, j int) {
  4130  	n[i], n[j] = n[j], n[i]
  4131  }
  4132  
  4133  // JobIDis used to sort jobs by id
  4134  type JobIDSort []*structs.Job
  4135  
  4136  func (n JobIDSort) Len() int {
  4137  	return len(n)
  4138  }
  4139  
  4140  func (n JobIDSort) Less(i, j int) bool {
  4141  	return n[i].ID < n[j].ID
  4142  }
  4143  
  4144  func (n JobIDSort) Swap(i, j int) {
  4145  	n[i], n[j] = n[j], n[i]
  4146  }
  4147  
  4148  // EvalIDis used to sort evals by id
  4149  type EvalIDSort []*structs.Evaluation
  4150  
  4151  func (n EvalIDSort) Len() int {
  4152  	return len(n)
  4153  }
  4154  
  4155  func (n EvalIDSort) Less(i, j int) bool {
  4156  	return n[i].ID < n[j].ID
  4157  }
  4158  
  4159  func (n EvalIDSort) Swap(i, j int) {
  4160  	n[i], n[j] = n[j], n[i]
  4161  }
  4162  
  4163  // AllocIDsort used to sort allocations by id
  4164  type AllocIDSort []*structs.Allocation
  4165  
  4166  func (n AllocIDSort) Len() int {
  4167  	return len(n)
  4168  }
  4169  
  4170  func (n AllocIDSort) Less(i, j int) bool {
  4171  	return n[i].ID < n[j].ID
  4172  }
  4173  
  4174  func (n AllocIDSort) Swap(i, j int) {
  4175  	n[i], n[j] = n[j], n[i]
  4176  }