github.com/dkerwin/nomad@v0.3.3-0.20160525181927-74554135514b/nomad/state/state_store_test.go (about)

     1  package state
     2  
     3  import (
     4  	"os"
     5  	"reflect"
     6  	"sort"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/hashicorp/go-memdb"
    11  	"github.com/hashicorp/nomad/nomad/mock"
    12  	"github.com/hashicorp/nomad/nomad/structs"
    13  	"github.com/hashicorp/nomad/nomad/watch"
    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  	notify := setupNotifyTest(
    32  		state,
    33  		watch.Item{Table: "nodes"},
    34  		watch.Item{Node: node.ID})
    35  
    36  	err := state.UpsertNode(1000, node)
    37  	if err != nil {
    38  		t.Fatalf("err: %v", err)
    39  	}
    40  
    41  	out, err := state.NodeByID(node.ID)
    42  	if err != nil {
    43  		t.Fatalf("err: %v", err)
    44  	}
    45  
    46  	if !reflect.DeepEqual(node, out) {
    47  		t.Fatalf("bad: %#v %#v", node, out)
    48  	}
    49  
    50  	index, err := state.Index("nodes")
    51  	if err != nil {
    52  		t.Fatalf("err: %v", err)
    53  	}
    54  	if index != 1000 {
    55  		t.Fatalf("bad: %d", index)
    56  	}
    57  
    58  	notify.verify(t)
    59  }
    60  
    61  func TestStateStore_DeleteNode_Node(t *testing.T) {
    62  	state := testStateStore(t)
    63  	node := mock.Node()
    64  
    65  	notify := setupNotifyTest(
    66  		state,
    67  		watch.Item{Table: "nodes"},
    68  		watch.Item{Node: node.ID})
    69  
    70  	err := state.UpsertNode(1000, node)
    71  	if err != nil {
    72  		t.Fatalf("err: %v", err)
    73  	}
    74  
    75  	err = state.DeleteNode(1001, node.ID)
    76  	if err != nil {
    77  		t.Fatalf("err: %v", err)
    78  	}
    79  
    80  	out, err := state.NodeByID(node.ID)
    81  	if err != nil {
    82  		t.Fatalf("err: %v", err)
    83  	}
    84  
    85  	if out != nil {
    86  		t.Fatalf("bad: %#v %#v", node, out)
    87  	}
    88  
    89  	index, err := state.Index("nodes")
    90  	if err != nil {
    91  		t.Fatalf("err: %v", err)
    92  	}
    93  	if index != 1001 {
    94  		t.Fatalf("bad: %d", index)
    95  	}
    96  
    97  	notify.verify(t)
    98  }
    99  
   100  func TestStateStore_UpdateNodeStatus_Node(t *testing.T) {
   101  	state := testStateStore(t)
   102  	node := mock.Node()
   103  
   104  	notify := setupNotifyTest(
   105  		state,
   106  		watch.Item{Table: "nodes"},
   107  		watch.Item{Node: node.ID})
   108  
   109  	err := state.UpsertNode(1000, node)
   110  	if err != nil {
   111  		t.Fatalf("err: %v", err)
   112  	}
   113  
   114  	err = state.UpdateNodeStatus(1001, node.ID, structs.NodeStatusReady)
   115  	if err != nil {
   116  		t.Fatalf("err: %v", err)
   117  	}
   118  
   119  	out, err := state.NodeByID(node.ID)
   120  	if err != nil {
   121  		t.Fatalf("err: %v", err)
   122  	}
   123  
   124  	if out.Status != structs.NodeStatusReady {
   125  		t.Fatalf("bad: %#v", out)
   126  	}
   127  	if out.ModifyIndex != 1001 {
   128  		t.Fatalf("bad: %#v", out)
   129  	}
   130  
   131  	index, err := state.Index("nodes")
   132  	if err != nil {
   133  		t.Fatalf("err: %v", err)
   134  	}
   135  	if index != 1001 {
   136  		t.Fatalf("bad: %d", index)
   137  	}
   138  
   139  	notify.verify(t)
   140  }
   141  
   142  func TestStateStore_UpdateNodeDrain_Node(t *testing.T) {
   143  	state := testStateStore(t)
   144  	node := mock.Node()
   145  
   146  	notify := setupNotifyTest(
   147  		state,
   148  		watch.Item{Table: "nodes"},
   149  		watch.Item{Node: node.ID})
   150  
   151  	err := state.UpsertNode(1000, node)
   152  	if err != nil {
   153  		t.Fatalf("err: %v", err)
   154  	}
   155  
   156  	err = state.UpdateNodeDrain(1001, node.ID, true)
   157  	if err != nil {
   158  		t.Fatalf("err: %v", err)
   159  	}
   160  
   161  	out, err := state.NodeByID(node.ID)
   162  	if err != nil {
   163  		t.Fatalf("err: %v", err)
   164  	}
   165  
   166  	if !out.Drain {
   167  		t.Fatalf("bad: %#v", out)
   168  	}
   169  	if out.ModifyIndex != 1001 {
   170  		t.Fatalf("bad: %#v", out)
   171  	}
   172  
   173  	index, err := state.Index("nodes")
   174  	if err != nil {
   175  		t.Fatalf("err: %v", err)
   176  	}
   177  	if index != 1001 {
   178  		t.Fatalf("bad: %d", index)
   179  	}
   180  
   181  	notify.verify(t)
   182  }
   183  
   184  func TestStateStore_Nodes(t *testing.T) {
   185  	state := testStateStore(t)
   186  	var nodes []*structs.Node
   187  
   188  	for i := 0; i < 10; i++ {
   189  		node := mock.Node()
   190  		nodes = append(nodes, node)
   191  
   192  		err := state.UpsertNode(1000+uint64(i), node)
   193  		if err != nil {
   194  			t.Fatalf("err: %v", err)
   195  		}
   196  	}
   197  
   198  	iter, err := state.Nodes()
   199  	if err != nil {
   200  		t.Fatalf("err: %v", err)
   201  	}
   202  
   203  	var out []*structs.Node
   204  	for {
   205  		raw := iter.Next()
   206  		if raw == nil {
   207  			break
   208  		}
   209  		out = append(out, raw.(*structs.Node))
   210  	}
   211  
   212  	sort.Sort(NodeIDSort(nodes))
   213  	sort.Sort(NodeIDSort(out))
   214  
   215  	if !reflect.DeepEqual(nodes, out) {
   216  		t.Fatalf("bad: %#v %#v", nodes, out)
   217  	}
   218  }
   219  
   220  func TestStateStore_NodesByIDPrefix(t *testing.T) {
   221  	state := testStateStore(t)
   222  	node := mock.Node()
   223  
   224  	node.ID = "11111111-662e-d0ab-d1c9-3e434af7bdb4"
   225  	err := state.UpsertNode(1000, node)
   226  	if err != nil {
   227  		t.Fatalf("err: %v", err)
   228  	}
   229  
   230  	iter, err := state.NodesByIDPrefix(node.ID)
   231  	if err != nil {
   232  		t.Fatalf("err: %v", err)
   233  	}
   234  
   235  	gatherNodes := func(iter memdb.ResultIterator) []*structs.Node {
   236  		var nodes []*structs.Node
   237  		for {
   238  			raw := iter.Next()
   239  			if raw == nil {
   240  				break
   241  			}
   242  			node := raw.(*structs.Node)
   243  			nodes = append(nodes, node)
   244  		}
   245  		return nodes
   246  	}
   247  
   248  	nodes := gatherNodes(iter)
   249  	if len(nodes) != 1 {
   250  		t.Fatalf("err: %v", err)
   251  	}
   252  
   253  	iter, err = state.NodesByIDPrefix("11")
   254  	if err != nil {
   255  		t.Fatalf("err: %v", err)
   256  	}
   257  
   258  	nodes = gatherNodes(iter)
   259  	if len(nodes) != 1 {
   260  		t.Fatalf("err: %v", err)
   261  	}
   262  
   263  	node = mock.Node()
   264  	node.ID = "11222222-662e-d0ab-d1c9-3e434af7bdb4"
   265  	err = state.UpsertNode(1001, node)
   266  	if err != nil {
   267  		t.Fatalf("err: %v", err)
   268  	}
   269  
   270  	iter, err = state.NodesByIDPrefix("11")
   271  	if err != nil {
   272  		t.Fatalf("err: %v", err)
   273  	}
   274  
   275  	nodes = gatherNodes(iter)
   276  	if len(nodes) != 2 {
   277  		t.Fatalf("err: %v", err)
   278  	}
   279  
   280  	iter, err = state.NodesByIDPrefix("1111")
   281  	if err != nil {
   282  		t.Fatalf("err: %v", err)
   283  	}
   284  
   285  	nodes = gatherNodes(iter)
   286  	if len(nodes) != 1 {
   287  		t.Fatalf("err: %v", err)
   288  	}
   289  }
   290  
   291  func TestStateStore_RestoreNode(t *testing.T) {
   292  	state := testStateStore(t)
   293  	node := mock.Node()
   294  
   295  	notify := setupNotifyTest(
   296  		state,
   297  		watch.Item{Table: "nodes"},
   298  		watch.Item{Node: node.ID})
   299  
   300  	restore, err := state.Restore()
   301  	if err != nil {
   302  		t.Fatalf("err: %v", err)
   303  	}
   304  
   305  	err = restore.NodeRestore(node)
   306  	if err != nil {
   307  		t.Fatalf("err: %v", err)
   308  	}
   309  	restore.Commit()
   310  
   311  	out, err := state.NodeByID(node.ID)
   312  	if err != nil {
   313  		t.Fatalf("err: %v", err)
   314  	}
   315  
   316  	if !reflect.DeepEqual(out, node) {
   317  		t.Fatalf("Bad: %#v %#v", out, node)
   318  	}
   319  
   320  	notify.verify(t)
   321  }
   322  
   323  func TestStateStore_UpsertJob_Job(t *testing.T) {
   324  	state := testStateStore(t)
   325  	job := mock.Job()
   326  
   327  	notify := setupNotifyTest(
   328  		state,
   329  		watch.Item{Table: "jobs"},
   330  		watch.Item{Job: job.ID})
   331  
   332  	err := state.UpsertJob(1000, job)
   333  	if err != nil {
   334  		t.Fatalf("err: %v", err)
   335  	}
   336  
   337  	out, err := state.JobByID(job.ID)
   338  	if err != nil {
   339  		t.Fatalf("err: %v", err)
   340  	}
   341  
   342  	if !reflect.DeepEqual(job, out) {
   343  		t.Fatalf("bad: %#v %#v", job, out)
   344  	}
   345  
   346  	index, err := state.Index("jobs")
   347  	if err != nil {
   348  		t.Fatalf("err: %v", err)
   349  	}
   350  	if index != 1000 {
   351  		t.Fatalf("bad: %d", index)
   352  	}
   353  
   354  	notify.verify(t)
   355  }
   356  
   357  func TestStateStore_UpdateUpsertJob_Job(t *testing.T) {
   358  	state := testStateStore(t)
   359  	job := mock.Job()
   360  
   361  	notify := setupNotifyTest(
   362  		state,
   363  		watch.Item{Table: "jobs"},
   364  		watch.Item{Job: job.ID})
   365  
   366  	err := state.UpsertJob(1000, job)
   367  	if err != nil {
   368  		t.Fatalf("err: %v", err)
   369  	}
   370  
   371  	job2 := mock.Job()
   372  	job2.ID = job.ID
   373  	err = state.UpsertJob(1001, job2)
   374  	if err != nil {
   375  		t.Fatalf("err: %v", err)
   376  	}
   377  
   378  	out, err := state.JobByID(job.ID)
   379  	if err != nil {
   380  		t.Fatalf("err: %v", err)
   381  	}
   382  
   383  	if !reflect.DeepEqual(job2, out) {
   384  		t.Fatalf("bad: %#v %#v", job2, out)
   385  	}
   386  
   387  	if out.CreateIndex != 1000 {
   388  		t.Fatalf("bad: %#v", out)
   389  	}
   390  	if out.ModifyIndex != 1001 {
   391  		t.Fatalf("bad: %#v", out)
   392  	}
   393  
   394  	index, err := state.Index("jobs")
   395  	if err != nil {
   396  		t.Fatalf("err: %v", err)
   397  	}
   398  	if index != 1001 {
   399  		t.Fatalf("bad: %d", index)
   400  	}
   401  
   402  	notify.verify(t)
   403  }
   404  
   405  func TestStateStore_DeleteJob_Job(t *testing.T) {
   406  	state := testStateStore(t)
   407  	job := mock.Job()
   408  
   409  	notify := setupNotifyTest(
   410  		state,
   411  		watch.Item{Table: "jobs"},
   412  		watch.Item{Job: job.ID})
   413  
   414  	err := state.UpsertJob(1000, job)
   415  	if err != nil {
   416  		t.Fatalf("err: %v", err)
   417  	}
   418  
   419  	err = state.DeleteJob(1001, job.ID)
   420  	if err != nil {
   421  		t.Fatalf("err: %v", err)
   422  	}
   423  
   424  	out, err := state.JobByID(job.ID)
   425  	if err != nil {
   426  		t.Fatalf("err: %v", err)
   427  	}
   428  
   429  	if out != nil {
   430  		t.Fatalf("bad: %#v %#v", job, out)
   431  	}
   432  
   433  	index, err := state.Index("jobs")
   434  	if err != nil {
   435  		t.Fatalf("err: %v", err)
   436  	}
   437  	if index != 1001 {
   438  		t.Fatalf("bad: %d", index)
   439  	}
   440  
   441  	notify.verify(t)
   442  }
   443  
   444  func TestStateStore_Jobs(t *testing.T) {
   445  	state := testStateStore(t)
   446  	var jobs []*structs.Job
   447  
   448  	for i := 0; i < 10; i++ {
   449  		job := mock.Job()
   450  		jobs = append(jobs, job)
   451  
   452  		err := state.UpsertJob(1000+uint64(i), job)
   453  		if err != nil {
   454  			t.Fatalf("err: %v", err)
   455  		}
   456  	}
   457  
   458  	iter, err := state.Jobs()
   459  	if err != nil {
   460  		t.Fatalf("err: %v", err)
   461  	}
   462  
   463  	var out []*structs.Job
   464  	for {
   465  		raw := iter.Next()
   466  		if raw == nil {
   467  			break
   468  		}
   469  		out = append(out, raw.(*structs.Job))
   470  	}
   471  
   472  	sort.Sort(JobIDSort(jobs))
   473  	sort.Sort(JobIDSort(out))
   474  
   475  	if !reflect.DeepEqual(jobs, out) {
   476  		t.Fatalf("bad: %#v %#v", jobs, out)
   477  	}
   478  }
   479  
   480  func TestStateStore_JobsByIDPrefix(t *testing.T) {
   481  	state := testStateStore(t)
   482  	job := mock.Job()
   483  
   484  	job.ID = "redis"
   485  	err := state.UpsertJob(1000, job)
   486  	if err != nil {
   487  		t.Fatalf("err: %v", err)
   488  	}
   489  
   490  	iter, err := state.JobsByIDPrefix(job.ID)
   491  	if err != nil {
   492  		t.Fatalf("err: %v", err)
   493  	}
   494  
   495  	gatherJobs := func(iter memdb.ResultIterator) []*structs.Job {
   496  		var jobs []*structs.Job
   497  		for {
   498  			raw := iter.Next()
   499  			if raw == nil {
   500  				break
   501  			}
   502  			jobs = append(jobs, raw.(*structs.Job))
   503  		}
   504  		return jobs
   505  	}
   506  
   507  	jobs := gatherJobs(iter)
   508  	if len(jobs) != 1 {
   509  		t.Fatalf("err: %v", err)
   510  	}
   511  
   512  	iter, err = state.JobsByIDPrefix("re")
   513  	if err != nil {
   514  		t.Fatalf("err: %v", err)
   515  	}
   516  
   517  	jobs = gatherJobs(iter)
   518  	if len(jobs) != 1 {
   519  		t.Fatalf("err: %v", err)
   520  	}
   521  
   522  	job = mock.Job()
   523  	job.ID = "riak"
   524  	err = state.UpsertJob(1001, job)
   525  	if err != nil {
   526  		t.Fatalf("err: %v", err)
   527  	}
   528  
   529  	iter, err = state.JobsByIDPrefix("r")
   530  	if err != nil {
   531  		t.Fatalf("err: %v", err)
   532  	}
   533  
   534  	jobs = gatherJobs(iter)
   535  	if len(jobs) != 2 {
   536  		t.Fatalf("err: %v", err)
   537  	}
   538  
   539  	iter, err = state.JobsByIDPrefix("ri")
   540  	if err != nil {
   541  		t.Fatalf("err: %v", err)
   542  	}
   543  
   544  	jobs = gatherJobs(iter)
   545  	if len(jobs) != 1 {
   546  		t.Fatalf("err: %v", err)
   547  	}
   548  }
   549  
   550  func TestStateStore_JobsByPeriodic(t *testing.T) {
   551  	state := testStateStore(t)
   552  	var periodic, nonPeriodic []*structs.Job
   553  
   554  	for i := 0; i < 10; i++ {
   555  		job := mock.Job()
   556  		nonPeriodic = append(nonPeriodic, job)
   557  
   558  		err := state.UpsertJob(1000+uint64(i), job)
   559  		if err != nil {
   560  			t.Fatalf("err: %v", err)
   561  		}
   562  	}
   563  
   564  	for i := 0; i < 10; i++ {
   565  		job := mock.PeriodicJob()
   566  		periodic = append(periodic, job)
   567  
   568  		err := state.UpsertJob(2000+uint64(i), job)
   569  		if err != nil {
   570  			t.Fatalf("err: %v", err)
   571  		}
   572  	}
   573  
   574  	iter, err := state.JobsByPeriodic(true)
   575  	if err != nil {
   576  		t.Fatalf("err: %v", err)
   577  	}
   578  
   579  	var outPeriodic []*structs.Job
   580  	for {
   581  		raw := iter.Next()
   582  		if raw == nil {
   583  			break
   584  		}
   585  		outPeriodic = append(outPeriodic, raw.(*structs.Job))
   586  	}
   587  
   588  	iter, err = state.JobsByPeriodic(false)
   589  
   590  	var outNonPeriodic []*structs.Job
   591  	for {
   592  		raw := iter.Next()
   593  		if raw == nil {
   594  			break
   595  		}
   596  		outNonPeriodic = append(outNonPeriodic, raw.(*structs.Job))
   597  	}
   598  
   599  	sort.Sort(JobIDSort(periodic))
   600  	sort.Sort(JobIDSort(nonPeriodic))
   601  	sort.Sort(JobIDSort(outPeriodic))
   602  	sort.Sort(JobIDSort(outNonPeriodic))
   603  
   604  	if !reflect.DeepEqual(periodic, outPeriodic) {
   605  		t.Fatalf("bad: %#v %#v", periodic, outPeriodic)
   606  	}
   607  
   608  	if !reflect.DeepEqual(nonPeriodic, outNonPeriodic) {
   609  		t.Fatalf("bad: %#v %#v", nonPeriodic, outNonPeriodic)
   610  	}
   611  }
   612  
   613  func TestStateStore_JobsByScheduler(t *testing.T) {
   614  	state := testStateStore(t)
   615  	var serviceJobs []*structs.Job
   616  	var sysJobs []*structs.Job
   617  
   618  	for i := 0; i < 10; i++ {
   619  		job := mock.Job()
   620  		serviceJobs = append(serviceJobs, job)
   621  
   622  		err := state.UpsertJob(1000+uint64(i), job)
   623  		if err != nil {
   624  			t.Fatalf("err: %v", err)
   625  		}
   626  	}
   627  
   628  	for i := 0; i < 10; i++ {
   629  		job := mock.SystemJob()
   630  		sysJobs = append(sysJobs, job)
   631  
   632  		err := state.UpsertJob(2000+uint64(i), job)
   633  		if err != nil {
   634  			t.Fatalf("err: %v", err)
   635  		}
   636  	}
   637  
   638  	iter, err := state.JobsByScheduler("service")
   639  	if err != nil {
   640  		t.Fatalf("err: %v", err)
   641  	}
   642  
   643  	var outService []*structs.Job
   644  	for {
   645  		raw := iter.Next()
   646  		if raw == nil {
   647  			break
   648  		}
   649  		outService = append(outService, raw.(*structs.Job))
   650  	}
   651  
   652  	iter, err = state.JobsByScheduler("system")
   653  	if err != nil {
   654  		t.Fatalf("err: %v", err)
   655  	}
   656  
   657  	var outSystem []*structs.Job
   658  	for {
   659  		raw := iter.Next()
   660  		if raw == nil {
   661  			break
   662  		}
   663  		outSystem = append(outSystem, raw.(*structs.Job))
   664  	}
   665  
   666  	sort.Sort(JobIDSort(serviceJobs))
   667  	sort.Sort(JobIDSort(sysJobs))
   668  	sort.Sort(JobIDSort(outService))
   669  	sort.Sort(JobIDSort(outSystem))
   670  
   671  	if !reflect.DeepEqual(serviceJobs, outService) {
   672  		t.Fatalf("bad: %#v %#v", serviceJobs, outService)
   673  	}
   674  
   675  	if !reflect.DeepEqual(sysJobs, outSystem) {
   676  		t.Fatalf("bad: %#v %#v", sysJobs, outSystem)
   677  	}
   678  }
   679  
   680  func TestStateStore_JobsByGC(t *testing.T) {
   681  	state := testStateStore(t)
   682  	var gc, nonGc []*structs.Job
   683  
   684  	for i := 0; i < 20; i++ {
   685  		var job *structs.Job
   686  		if i%2 == 0 {
   687  			job = mock.Job()
   688  		} else {
   689  			job = mock.PeriodicJob()
   690  		}
   691  		nonGc = append(nonGc, job)
   692  
   693  		if err := state.UpsertJob(1000+uint64(i), job); err != nil {
   694  			t.Fatalf("err: %v", err)
   695  		}
   696  	}
   697  
   698  	for i := 0; i < 10; i++ {
   699  		job := mock.Job()
   700  		job.Type = structs.JobTypeBatch
   701  		gc = append(gc, job)
   702  
   703  		if err := state.UpsertJob(2000+uint64(i), job); err != nil {
   704  			t.Fatalf("err: %v", err)
   705  		}
   706  	}
   707  
   708  	iter, err := state.JobsByGC(true)
   709  	if err != nil {
   710  		t.Fatalf("err: %v", err)
   711  	}
   712  
   713  	var outGc []*structs.Job
   714  	for i := iter.Next(); i != nil; i = iter.Next() {
   715  		outGc = append(outGc, i.(*structs.Job))
   716  	}
   717  
   718  	iter, err = state.JobsByGC(false)
   719  	if err != nil {
   720  		t.Fatalf("err: %v", err)
   721  	}
   722  
   723  	var outNonGc []*structs.Job
   724  	for i := iter.Next(); i != nil; i = iter.Next() {
   725  		outNonGc = append(outNonGc, i.(*structs.Job))
   726  	}
   727  
   728  	sort.Sort(JobIDSort(gc))
   729  	sort.Sort(JobIDSort(nonGc))
   730  	sort.Sort(JobIDSort(outGc))
   731  	sort.Sort(JobIDSort(outNonGc))
   732  
   733  	if !reflect.DeepEqual(gc, outGc) {
   734  		t.Fatalf("bad: %#v %#v", gc, outGc)
   735  	}
   736  
   737  	if !reflect.DeepEqual(nonGc, outNonGc) {
   738  		t.Fatalf("bad: %#v %#v", nonGc, outNonGc)
   739  	}
   740  }
   741  
   742  func TestStateStore_RestoreJob(t *testing.T) {
   743  	state := testStateStore(t)
   744  	job := mock.Job()
   745  
   746  	notify := setupNotifyTest(
   747  		state,
   748  		watch.Item{Table: "jobs"},
   749  		watch.Item{Job: job.ID})
   750  
   751  	restore, err := state.Restore()
   752  	if err != nil {
   753  		t.Fatalf("err: %v", err)
   754  	}
   755  
   756  	err = restore.JobRestore(job)
   757  	if err != nil {
   758  		t.Fatalf("err: %v", err)
   759  	}
   760  	restore.Commit()
   761  
   762  	out, err := state.JobByID(job.ID)
   763  	if err != nil {
   764  		t.Fatalf("err: %v", err)
   765  	}
   766  
   767  	if !reflect.DeepEqual(out, job) {
   768  		t.Fatalf("Bad: %#v %#v", out, job)
   769  	}
   770  
   771  	notify.verify(t)
   772  }
   773  
   774  func TestStateStore_UpsertPeriodicLaunch(t *testing.T) {
   775  	state := testStateStore(t)
   776  	job := mock.Job()
   777  	launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()}
   778  
   779  	notify := setupNotifyTest(
   780  		state,
   781  		watch.Item{Table: "periodic_launch"},
   782  		watch.Item{Job: job.ID})
   783  
   784  	err := state.UpsertPeriodicLaunch(1000, launch)
   785  	if err != nil {
   786  		t.Fatalf("err: %v", err)
   787  	}
   788  
   789  	out, err := state.PeriodicLaunchByID(job.ID)
   790  	if err != nil {
   791  		t.Fatalf("err: %v", err)
   792  	}
   793  	if out.CreateIndex != 1000 {
   794  		t.Fatalf("bad: %#v", out)
   795  	}
   796  	if out.ModifyIndex != 1000 {
   797  		t.Fatalf("bad: %#v", out)
   798  	}
   799  
   800  	if !reflect.DeepEqual(launch, out) {
   801  		t.Fatalf("bad: %#v %#v", job, out)
   802  	}
   803  
   804  	index, err := state.Index("periodic_launch")
   805  	if err != nil {
   806  		t.Fatalf("err: %v", err)
   807  	}
   808  	if index != 1000 {
   809  		t.Fatalf("bad: %d", index)
   810  	}
   811  
   812  	notify.verify(t)
   813  }
   814  
   815  func TestStateStore_UpdateUpsertPeriodicLaunch(t *testing.T) {
   816  	state := testStateStore(t)
   817  	job := mock.Job()
   818  	launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()}
   819  
   820  	notify := setupNotifyTest(
   821  		state,
   822  		watch.Item{Table: "periodic_launch"},
   823  		watch.Item{Job: job.ID})
   824  
   825  	err := state.UpsertPeriodicLaunch(1000, launch)
   826  	if err != nil {
   827  		t.Fatalf("err: %v", err)
   828  	}
   829  
   830  	launch2 := &structs.PeriodicLaunch{
   831  		ID:     job.ID,
   832  		Launch: launch.Launch.Add(1 * time.Second),
   833  	}
   834  	err = state.UpsertPeriodicLaunch(1001, launch2)
   835  	if err != nil {
   836  		t.Fatalf("err: %v", err)
   837  	}
   838  
   839  	out, err := state.PeriodicLaunchByID(job.ID)
   840  	if err != nil {
   841  		t.Fatalf("err: %v", err)
   842  	}
   843  	if out.CreateIndex != 1000 {
   844  		t.Fatalf("bad: %#v", out)
   845  	}
   846  	if out.ModifyIndex != 1001 {
   847  		t.Fatalf("bad: %#v", out)
   848  	}
   849  
   850  	if !reflect.DeepEqual(launch2, out) {
   851  		t.Fatalf("bad: %#v %#v", launch2, out)
   852  	}
   853  
   854  	index, err := state.Index("periodic_launch")
   855  	if err != nil {
   856  		t.Fatalf("err: %v", err)
   857  	}
   858  	if index != 1001 {
   859  		t.Fatalf("bad: %d", index)
   860  	}
   861  
   862  	notify.verify(t)
   863  }
   864  
   865  func TestStateStore_DeletePeriodicLaunch(t *testing.T) {
   866  	state := testStateStore(t)
   867  	job := mock.Job()
   868  	launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()}
   869  
   870  	notify := setupNotifyTest(
   871  		state,
   872  		watch.Item{Table: "periodic_launch"},
   873  		watch.Item{Job: job.ID})
   874  
   875  	err := state.UpsertPeriodicLaunch(1000, launch)
   876  	if err != nil {
   877  		t.Fatalf("err: %v", err)
   878  	}
   879  
   880  	err = state.DeletePeriodicLaunch(1001, job.ID)
   881  	if err != nil {
   882  		t.Fatalf("err: %v", err)
   883  	}
   884  
   885  	out, err := state.PeriodicLaunchByID(job.ID)
   886  	if err != nil {
   887  		t.Fatalf("err: %v", err)
   888  	}
   889  
   890  	if out != nil {
   891  		t.Fatalf("bad: %#v %#v", job, out)
   892  	}
   893  
   894  	index, err := state.Index("periodic_launch")
   895  	if err != nil {
   896  		t.Fatalf("err: %v", err)
   897  	}
   898  	if index != 1001 {
   899  		t.Fatalf("bad: %d", index)
   900  	}
   901  
   902  	notify.verify(t)
   903  }
   904  
   905  func TestStateStore_PeriodicLaunches(t *testing.T) {
   906  	state := testStateStore(t)
   907  	var launches []*structs.PeriodicLaunch
   908  
   909  	for i := 0; i < 10; i++ {
   910  		job := mock.Job()
   911  		launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()}
   912  		launches = append(launches, launch)
   913  
   914  		err := state.UpsertPeriodicLaunch(1000+uint64(i), launch)
   915  		if err != nil {
   916  			t.Fatalf("err: %v", err)
   917  		}
   918  	}
   919  
   920  	iter, err := state.PeriodicLaunches()
   921  	if err != nil {
   922  		t.Fatalf("err: %v", err)
   923  	}
   924  
   925  	out := make(map[string]*structs.PeriodicLaunch, 10)
   926  	for {
   927  		raw := iter.Next()
   928  		if raw == nil {
   929  			break
   930  		}
   931  		launch := raw.(*structs.PeriodicLaunch)
   932  		if _, ok := out[launch.ID]; ok {
   933  			t.Fatalf("duplicate: %v", launch.ID)
   934  		}
   935  
   936  		out[launch.ID] = launch
   937  	}
   938  
   939  	for _, launch := range launches {
   940  		l, ok := out[launch.ID]
   941  		if !ok {
   942  			t.Fatalf("bad %v", launch.ID)
   943  		}
   944  
   945  		if !reflect.DeepEqual(launch, l) {
   946  			t.Fatalf("bad: %#v %#v", launch, l)
   947  		}
   948  
   949  		delete(out, launch.ID)
   950  	}
   951  
   952  	if len(out) != 0 {
   953  		t.Fatalf("leftover: %#v", out)
   954  	}
   955  }
   956  
   957  func TestStateStore_RestorePeriodicLaunch(t *testing.T) {
   958  	state := testStateStore(t)
   959  	job := mock.Job()
   960  	launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()}
   961  
   962  	notify := setupNotifyTest(
   963  		state,
   964  		watch.Item{Table: "periodic_launch"},
   965  		watch.Item{Job: job.ID})
   966  
   967  	restore, err := state.Restore()
   968  	if err != nil {
   969  		t.Fatalf("err: %v", err)
   970  	}
   971  
   972  	err = restore.PeriodicLaunchRestore(launch)
   973  	if err != nil {
   974  		t.Fatalf("err: %v", err)
   975  	}
   976  	restore.Commit()
   977  
   978  	out, err := state.PeriodicLaunchByID(job.ID)
   979  	if err != nil {
   980  		t.Fatalf("err: %v", err)
   981  	}
   982  
   983  	if !reflect.DeepEqual(out, launch) {
   984  		t.Fatalf("Bad: %#v %#v", out, job)
   985  	}
   986  
   987  	notify.verify(t)
   988  }
   989  
   990  func TestStateStore_Indexes(t *testing.T) {
   991  	state := testStateStore(t)
   992  	node := mock.Node()
   993  
   994  	err := state.UpsertNode(1000, node)
   995  	if err != nil {
   996  		t.Fatalf("err: %v", err)
   997  	}
   998  
   999  	iter, err := state.Indexes()
  1000  	if err != nil {
  1001  		t.Fatalf("err: %v", err)
  1002  	}
  1003  
  1004  	var out []*IndexEntry
  1005  	for {
  1006  		raw := iter.Next()
  1007  		if raw == nil {
  1008  			break
  1009  		}
  1010  		out = append(out, raw.(*IndexEntry))
  1011  	}
  1012  
  1013  	expect := []*IndexEntry{
  1014  		&IndexEntry{"nodes", 1000},
  1015  	}
  1016  
  1017  	if !reflect.DeepEqual(expect, out) {
  1018  		t.Fatalf("bad: %#v %#v", expect, out)
  1019  	}
  1020  }
  1021  
  1022  func TestStateStore_LatestIndex(t *testing.T) {
  1023  	state := testStateStore(t)
  1024  
  1025  	if err := state.UpsertNode(1000, mock.Node()); err != nil {
  1026  		t.Fatalf("err: %v", err)
  1027  	}
  1028  
  1029  	exp := uint64(2000)
  1030  	if err := state.UpsertJob(exp, mock.Job()); err != nil {
  1031  		t.Fatalf("err: %v", err)
  1032  	}
  1033  
  1034  	latest, err := state.LatestIndex()
  1035  	if err != nil {
  1036  		t.Fatalf("err: %v", err)
  1037  	}
  1038  
  1039  	if latest != exp {
  1040  		t.Fatalf("LatestIndex() returned %d; want %d", latest, exp)
  1041  	}
  1042  }
  1043  
  1044  func TestStateStore_RestoreIndex(t *testing.T) {
  1045  	state := testStateStore(t)
  1046  
  1047  	restore, err := state.Restore()
  1048  	if err != nil {
  1049  		t.Fatalf("err: %v", err)
  1050  	}
  1051  
  1052  	index := &IndexEntry{"jobs", 1000}
  1053  	err = restore.IndexRestore(index)
  1054  	if err != nil {
  1055  		t.Fatalf("err: %v", err)
  1056  	}
  1057  
  1058  	restore.Commit()
  1059  
  1060  	out, err := state.Index("jobs")
  1061  	if err != nil {
  1062  		t.Fatalf("err: %v", err)
  1063  	}
  1064  
  1065  	if out != 1000 {
  1066  		t.Fatalf("Bad: %#v %#v", out, 1000)
  1067  	}
  1068  }
  1069  
  1070  func TestStateStore_UpsertEvals_Eval(t *testing.T) {
  1071  	state := testStateStore(t)
  1072  	eval := mock.Eval()
  1073  
  1074  	notify := setupNotifyTest(
  1075  		state,
  1076  		watch.Item{Table: "evals"},
  1077  		watch.Item{Eval: eval.ID})
  1078  
  1079  	err := state.UpsertEvals(1000, []*structs.Evaluation{eval})
  1080  	if err != nil {
  1081  		t.Fatalf("err: %v", err)
  1082  	}
  1083  
  1084  	out, err := state.EvalByID(eval.ID)
  1085  	if err != nil {
  1086  		t.Fatalf("err: %v", err)
  1087  	}
  1088  
  1089  	if !reflect.DeepEqual(eval, out) {
  1090  		t.Fatalf("bad: %#v %#v", eval, out)
  1091  	}
  1092  
  1093  	index, err := state.Index("evals")
  1094  	if err != nil {
  1095  		t.Fatalf("err: %v", err)
  1096  	}
  1097  	if index != 1000 {
  1098  		t.Fatalf("bad: %d", index)
  1099  	}
  1100  
  1101  	notify.verify(t)
  1102  }
  1103  
  1104  func TestStateStore_Update_UpsertEvals_Eval(t *testing.T) {
  1105  	state := testStateStore(t)
  1106  	eval := mock.Eval()
  1107  
  1108  	err := state.UpsertEvals(1000, []*structs.Evaluation{eval})
  1109  	if err != nil {
  1110  		t.Fatalf("err: %v", err)
  1111  	}
  1112  
  1113  	notify := setupNotifyTest(
  1114  		state,
  1115  		watch.Item{Table: "evals"},
  1116  		watch.Item{Eval: eval.ID})
  1117  
  1118  	eval2 := mock.Eval()
  1119  	eval2.ID = eval.ID
  1120  	err = state.UpsertEvals(1001, []*structs.Evaluation{eval2})
  1121  	if err != nil {
  1122  		t.Fatalf("err: %v", err)
  1123  	}
  1124  
  1125  	out, err := state.EvalByID(eval.ID)
  1126  	if err != nil {
  1127  		t.Fatalf("err: %v", err)
  1128  	}
  1129  
  1130  	if !reflect.DeepEqual(eval2, out) {
  1131  		t.Fatalf("bad: %#v %#v", eval2, out)
  1132  	}
  1133  
  1134  	if out.CreateIndex != 1000 {
  1135  		t.Fatalf("bad: %#v", out)
  1136  	}
  1137  	if out.ModifyIndex != 1001 {
  1138  		t.Fatalf("bad: %#v", out)
  1139  	}
  1140  
  1141  	index, err := state.Index("evals")
  1142  	if err != nil {
  1143  		t.Fatalf("err: %v", err)
  1144  	}
  1145  	if index != 1001 {
  1146  		t.Fatalf("bad: %d", index)
  1147  	}
  1148  
  1149  	notify.verify(t)
  1150  }
  1151  
  1152  func TestStateStore_DeleteEval_Eval(t *testing.T) {
  1153  	state := testStateStore(t)
  1154  	eval1 := mock.Eval()
  1155  	eval2 := mock.Eval()
  1156  	alloc1 := mock.Alloc()
  1157  	alloc2 := mock.Alloc()
  1158  
  1159  	notify := setupNotifyTest(
  1160  		state,
  1161  		watch.Item{Table: "evals"},
  1162  		watch.Item{Table: "allocs"},
  1163  		watch.Item{Eval: eval1.ID},
  1164  		watch.Item{Eval: eval2.ID},
  1165  		watch.Item{Alloc: alloc1.ID},
  1166  		watch.Item{Alloc: alloc2.ID},
  1167  		watch.Item{AllocEval: alloc1.EvalID},
  1168  		watch.Item{AllocEval: alloc2.EvalID},
  1169  		watch.Item{AllocJob: alloc1.JobID},
  1170  		watch.Item{AllocJob: alloc2.JobID},
  1171  		watch.Item{AllocNode: alloc1.NodeID},
  1172  		watch.Item{AllocNode: alloc2.NodeID})
  1173  
  1174  	err := state.UpsertEvals(1000, []*structs.Evaluation{eval1, eval2})
  1175  	if err != nil {
  1176  		t.Fatalf("err: %v", err)
  1177  	}
  1178  
  1179  	err = state.UpsertAllocs(1001, []*structs.Allocation{alloc1, alloc2})
  1180  	if err != nil {
  1181  		t.Fatalf("err: %v", err)
  1182  	}
  1183  
  1184  	err = state.DeleteEval(1002, []string{eval1.ID, eval2.ID}, []string{alloc1.ID, alloc2.ID})
  1185  	if err != nil {
  1186  		t.Fatalf("err: %v", err)
  1187  	}
  1188  
  1189  	out, err := state.EvalByID(eval1.ID)
  1190  	if err != nil {
  1191  		t.Fatalf("err: %v", err)
  1192  	}
  1193  
  1194  	if out != nil {
  1195  		t.Fatalf("bad: %#v %#v", eval1, out)
  1196  	}
  1197  
  1198  	out, err = state.EvalByID(eval2.ID)
  1199  	if err != nil {
  1200  		t.Fatalf("err: %v", err)
  1201  	}
  1202  
  1203  	if out != nil {
  1204  		t.Fatalf("bad: %#v %#v", eval1, out)
  1205  	}
  1206  
  1207  	outA, err := state.AllocByID(alloc1.ID)
  1208  	if err != nil {
  1209  		t.Fatalf("err: %v", err)
  1210  	}
  1211  
  1212  	if out != nil {
  1213  		t.Fatalf("bad: %#v %#v", alloc1, outA)
  1214  	}
  1215  
  1216  	outA, err = state.AllocByID(alloc2.ID)
  1217  	if err != nil {
  1218  		t.Fatalf("err: %v", err)
  1219  	}
  1220  
  1221  	if out != nil {
  1222  		t.Fatalf("bad: %#v %#v", alloc1, outA)
  1223  	}
  1224  
  1225  	index, err := state.Index("evals")
  1226  	if err != nil {
  1227  		t.Fatalf("err: %v", err)
  1228  	}
  1229  	if index != 1002 {
  1230  		t.Fatalf("bad: %d", index)
  1231  	}
  1232  
  1233  	index, err = state.Index("allocs")
  1234  	if err != nil {
  1235  		t.Fatalf("err: %v", err)
  1236  	}
  1237  	if index != 1002 {
  1238  		t.Fatalf("bad: %d", index)
  1239  	}
  1240  
  1241  	notify.verify(t)
  1242  }
  1243  
  1244  func TestStateStore_EvalsByJob(t *testing.T) {
  1245  	state := testStateStore(t)
  1246  
  1247  	eval1 := mock.Eval()
  1248  	eval2 := mock.Eval()
  1249  	eval2.JobID = eval1.JobID
  1250  	eval3 := mock.Eval()
  1251  	evals := []*structs.Evaluation{eval1, eval2}
  1252  
  1253  	err := state.UpsertEvals(1000, evals)
  1254  	if err != nil {
  1255  		t.Fatalf("err: %v", err)
  1256  	}
  1257  	err = state.UpsertEvals(1001, []*structs.Evaluation{eval3})
  1258  	if err != nil {
  1259  		t.Fatalf("err: %v", err)
  1260  	}
  1261  
  1262  	out, err := state.EvalsByJob(eval1.JobID)
  1263  	if err != nil {
  1264  		t.Fatalf("err: %v", err)
  1265  	}
  1266  
  1267  	sort.Sort(EvalIDSort(evals))
  1268  	sort.Sort(EvalIDSort(out))
  1269  
  1270  	if !reflect.DeepEqual(evals, out) {
  1271  		t.Fatalf("bad: %#v %#v", evals, out)
  1272  	}
  1273  }
  1274  
  1275  func TestStateStore_Evals(t *testing.T) {
  1276  	state := testStateStore(t)
  1277  	var evals []*structs.Evaluation
  1278  
  1279  	for i := 0; i < 10; i++ {
  1280  		eval := mock.Eval()
  1281  		evals = append(evals, eval)
  1282  
  1283  		err := state.UpsertEvals(1000+uint64(i), []*structs.Evaluation{eval})
  1284  		if err != nil {
  1285  			t.Fatalf("err: %v", err)
  1286  		}
  1287  	}
  1288  
  1289  	iter, err := state.Evals()
  1290  	if err != nil {
  1291  		t.Fatalf("err: %v", err)
  1292  	}
  1293  
  1294  	var out []*structs.Evaluation
  1295  	for {
  1296  		raw := iter.Next()
  1297  		if raw == nil {
  1298  			break
  1299  		}
  1300  		out = append(out, raw.(*structs.Evaluation))
  1301  	}
  1302  
  1303  	sort.Sort(EvalIDSort(evals))
  1304  	sort.Sort(EvalIDSort(out))
  1305  
  1306  	if !reflect.DeepEqual(evals, out) {
  1307  		t.Fatalf("bad: %#v %#v", evals, out)
  1308  	}
  1309  }
  1310  
  1311  func TestStateStore_EvalsByIDPrefix(t *testing.T) {
  1312  	state := testStateStore(t)
  1313  	var evals []*structs.Evaluation
  1314  
  1315  	ids := []string{
  1316  		"aaaaaaaa-7bfb-395d-eb95-0685af2176b2",
  1317  		"aaaaaaab-7bfb-395d-eb95-0685af2176b2",
  1318  		"aaaaaabb-7bfb-395d-eb95-0685af2176b2",
  1319  		"aaaaabbb-7bfb-395d-eb95-0685af2176b2",
  1320  		"aaaabbbb-7bfb-395d-eb95-0685af2176b2",
  1321  		"aaabbbbb-7bfb-395d-eb95-0685af2176b2",
  1322  		"aabbbbbb-7bfb-395d-eb95-0685af2176b2",
  1323  		"abbbbbbb-7bfb-395d-eb95-0685af2176b2",
  1324  		"bbbbbbbb-7bfb-395d-eb95-0685af2176b2",
  1325  	}
  1326  	for i := 0; i < 9; i++ {
  1327  		eval := mock.Eval()
  1328  		eval.ID = ids[i]
  1329  		evals = append(evals, eval)
  1330  	}
  1331  
  1332  	err := state.UpsertEvals(1000, evals)
  1333  	if err != nil {
  1334  		t.Fatalf("err: %v", err)
  1335  	}
  1336  
  1337  	iter, err := state.EvalsByIDPrefix("aaaa")
  1338  	if err != nil {
  1339  		t.Fatalf("err: %v", err)
  1340  	}
  1341  
  1342  	gatherEvals := func(iter memdb.ResultIterator) []*structs.Evaluation {
  1343  		var evals []*structs.Evaluation
  1344  		for {
  1345  			raw := iter.Next()
  1346  			if raw == nil {
  1347  				break
  1348  			}
  1349  			evals = append(evals, raw.(*structs.Evaluation))
  1350  		}
  1351  		return evals
  1352  	}
  1353  
  1354  	out := gatherEvals(iter)
  1355  	if len(out) != 5 {
  1356  		t.Fatalf("bad: expected five evaluations, got: %#v", out)
  1357  	}
  1358  
  1359  	sort.Sort(EvalIDSort(evals))
  1360  
  1361  	for index, eval := range out {
  1362  		if ids[index] != eval.ID {
  1363  			t.Fatalf("bad: got unexpected id: %s", eval.ID)
  1364  		}
  1365  	}
  1366  
  1367  	iter, err = state.EvalsByIDPrefix("b-a7bfb")
  1368  	if err != nil {
  1369  		t.Fatalf("err: %v", err)
  1370  	}
  1371  
  1372  	out = gatherEvals(iter)
  1373  	if len(out) != 0 {
  1374  		t.Fatalf("bad: unexpected zero evaluations, got: %#v", out)
  1375  	}
  1376  
  1377  }
  1378  
  1379  func TestStateStore_RestoreEval(t *testing.T) {
  1380  	state := testStateStore(t)
  1381  	eval := mock.Eval()
  1382  
  1383  	notify := setupNotifyTest(
  1384  		state,
  1385  		watch.Item{Table: "evals"},
  1386  		watch.Item{Eval: eval.ID})
  1387  
  1388  	restore, err := state.Restore()
  1389  	if err != nil {
  1390  		t.Fatalf("err: %v", err)
  1391  	}
  1392  
  1393  	err = restore.EvalRestore(eval)
  1394  	if err != nil {
  1395  		t.Fatalf("err: %v", err)
  1396  	}
  1397  	restore.Commit()
  1398  
  1399  	out, err := state.EvalByID(eval.ID)
  1400  	if err != nil {
  1401  		t.Fatalf("err: %v", err)
  1402  	}
  1403  
  1404  	if !reflect.DeepEqual(out, eval) {
  1405  		t.Fatalf("Bad: %#v %#v", out, eval)
  1406  	}
  1407  
  1408  	notify.verify(t)
  1409  }
  1410  
  1411  func TestStateStore_UpdateAllocsFromClient(t *testing.T) {
  1412  	state := testStateStore(t)
  1413  	alloc := mock.Alloc()
  1414  	alloc2 := mock.Alloc()
  1415  
  1416  	notify := setupNotifyTest(
  1417  		state,
  1418  		watch.Item{Table: "allocs"},
  1419  		watch.Item{Alloc: alloc.ID},
  1420  		watch.Item{AllocEval: alloc.EvalID},
  1421  		watch.Item{AllocJob: alloc.JobID},
  1422  		watch.Item{AllocNode: alloc.NodeID},
  1423  		watch.Item{Alloc: alloc2.ID},
  1424  		watch.Item{AllocEval: alloc2.EvalID},
  1425  		watch.Item{AllocJob: alloc2.JobID},
  1426  		watch.Item{AllocNode: alloc2.NodeID})
  1427  
  1428  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc, alloc2})
  1429  	if err != nil {
  1430  		t.Fatalf("err: %v", err)
  1431  	}
  1432  
  1433  	// Create the delta updates
  1434  	ts := map[string]*structs.TaskState{"web": &structs.TaskState{State: structs.TaskStatePending}}
  1435  	update := &structs.Allocation{
  1436  		ID:           alloc.ID,
  1437  		ClientStatus: structs.AllocClientStatusFailed,
  1438  		TaskStates:   ts,
  1439  	}
  1440  	update2 := &structs.Allocation{
  1441  		ID:           alloc2.ID,
  1442  		ClientStatus: structs.AllocClientStatusRunning,
  1443  		TaskStates:   ts,
  1444  	}
  1445  
  1446  	err = state.UpdateAllocsFromClient(1001, []*structs.Allocation{update, update2})
  1447  	if err != nil {
  1448  		t.Fatalf("err: %v", err)
  1449  	}
  1450  
  1451  	out, err := state.AllocByID(alloc.ID)
  1452  	if err != nil {
  1453  		t.Fatalf("err: %v", err)
  1454  	}
  1455  
  1456  	alloc.CreateIndex = 1000
  1457  	alloc.ModifyIndex = 1001
  1458  	alloc.TaskStates = ts
  1459  	alloc.ClientStatus = structs.AllocClientStatusFailed
  1460  	if !reflect.DeepEqual(alloc, out) {
  1461  		t.Fatalf("bad: %#v %#v", alloc, out)
  1462  	}
  1463  
  1464  	out, err = state.AllocByID(alloc2.ID)
  1465  	if err != nil {
  1466  		t.Fatalf("err: %v", err)
  1467  	}
  1468  
  1469  	alloc2.ModifyIndex = 1000
  1470  	alloc2.ModifyIndex = 1001
  1471  	alloc2.ClientStatus = structs.AllocClientStatusRunning
  1472  	alloc2.TaskStates = ts
  1473  	if !reflect.DeepEqual(alloc2, out) {
  1474  		t.Fatalf("bad: %#v %#v", alloc2, out)
  1475  	}
  1476  
  1477  	index, err := state.Index("allocs")
  1478  	if err != nil {
  1479  		t.Fatalf("err: %v", err)
  1480  	}
  1481  	if index != 1001 {
  1482  		t.Fatalf("bad: %d", index)
  1483  	}
  1484  
  1485  	notify.verify(t)
  1486  }
  1487  
  1488  func TestStateStore_UpsertAlloc_Alloc(t *testing.T) {
  1489  	state := testStateStore(t)
  1490  	alloc := mock.Alloc()
  1491  
  1492  	notify := setupNotifyTest(
  1493  		state,
  1494  		watch.Item{Table: "allocs"},
  1495  		watch.Item{Alloc: alloc.ID},
  1496  		watch.Item{AllocEval: alloc.EvalID},
  1497  		watch.Item{AllocJob: alloc.JobID},
  1498  		watch.Item{AllocNode: alloc.NodeID})
  1499  
  1500  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  1501  	if err != nil {
  1502  		t.Fatalf("err: %v", err)
  1503  	}
  1504  
  1505  	out, err := state.AllocByID(alloc.ID)
  1506  	if err != nil {
  1507  		t.Fatalf("err: %v", err)
  1508  	}
  1509  
  1510  	if !reflect.DeepEqual(alloc, out) {
  1511  		t.Fatalf("bad: %#v %#v", alloc, out)
  1512  	}
  1513  
  1514  	index, err := state.Index("allocs")
  1515  	if err != nil {
  1516  		t.Fatalf("err: %v", err)
  1517  	}
  1518  	if index != 1000 {
  1519  		t.Fatalf("bad: %d", index)
  1520  	}
  1521  
  1522  	notify.verify(t)
  1523  }
  1524  
  1525  func TestStateStore_UpdateAlloc_Alloc(t *testing.T) {
  1526  	state := testStateStore(t)
  1527  	alloc := mock.Alloc()
  1528  
  1529  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  1530  	if err != nil {
  1531  		t.Fatalf("err: %v", err)
  1532  	}
  1533  
  1534  	alloc2 := mock.Alloc()
  1535  	alloc2.ID = alloc.ID
  1536  	alloc2.NodeID = alloc.NodeID + ".new"
  1537  
  1538  	notify := setupNotifyTest(
  1539  		state,
  1540  		watch.Item{Table: "allocs"},
  1541  		watch.Item{Alloc: alloc2.ID},
  1542  		watch.Item{AllocEval: alloc2.EvalID},
  1543  		watch.Item{AllocJob: alloc2.JobID},
  1544  		watch.Item{AllocNode: alloc2.NodeID})
  1545  
  1546  	err = state.UpsertAllocs(1001, []*structs.Allocation{alloc2})
  1547  	if err != nil {
  1548  		t.Fatalf("err: %v", err)
  1549  	}
  1550  
  1551  	out, err := state.AllocByID(alloc.ID)
  1552  	if err != nil {
  1553  		t.Fatalf("err: %v", err)
  1554  	}
  1555  
  1556  	if !reflect.DeepEqual(alloc2, out) {
  1557  		t.Fatalf("bad: %#v %#v", alloc2, out)
  1558  	}
  1559  
  1560  	if out.CreateIndex != 1000 {
  1561  		t.Fatalf("bad: %#v", out)
  1562  	}
  1563  	if out.ModifyIndex != 1001 {
  1564  		t.Fatalf("bad: %#v", out)
  1565  	}
  1566  
  1567  	index, err := state.Index("allocs")
  1568  	if err != nil {
  1569  		t.Fatalf("err: %v", err)
  1570  	}
  1571  	if index != 1001 {
  1572  		t.Fatalf("bad: %d", index)
  1573  	}
  1574  
  1575  	notify.verify(t)
  1576  }
  1577  
  1578  func TestStateStore_EvictAlloc_Alloc(t *testing.T) {
  1579  	state := testStateStore(t)
  1580  	alloc := mock.Alloc()
  1581  
  1582  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  1583  	if err != nil {
  1584  		t.Fatalf("err: %v", err)
  1585  	}
  1586  
  1587  	alloc2 := new(structs.Allocation)
  1588  	*alloc2 = *alloc
  1589  	alloc2.DesiredStatus = structs.AllocDesiredStatusEvict
  1590  	err = state.UpsertAllocs(1001, []*structs.Allocation{alloc2})
  1591  	if err != nil {
  1592  		t.Fatalf("err: %v", err)
  1593  	}
  1594  
  1595  	out, err := state.AllocByID(alloc.ID)
  1596  	if err != nil {
  1597  		t.Fatalf("err: %v", err)
  1598  	}
  1599  
  1600  	if out.DesiredStatus != structs.AllocDesiredStatusEvict {
  1601  		t.Fatalf("bad: %#v %#v", alloc, out)
  1602  	}
  1603  
  1604  	index, err := state.Index("allocs")
  1605  	if err != nil {
  1606  		t.Fatalf("err: %v", err)
  1607  	}
  1608  	if index != 1001 {
  1609  		t.Fatalf("bad: %d", index)
  1610  	}
  1611  }
  1612  
  1613  func TestStateStore_AllocsByNode(t *testing.T) {
  1614  	state := testStateStore(t)
  1615  	var allocs []*structs.Allocation
  1616  
  1617  	for i := 0; i < 10; i++ {
  1618  		alloc := mock.Alloc()
  1619  		alloc.NodeID = "foo"
  1620  		allocs = append(allocs, alloc)
  1621  	}
  1622  
  1623  	err := state.UpsertAllocs(1000, allocs)
  1624  	if err != nil {
  1625  		t.Fatalf("err: %v", err)
  1626  	}
  1627  
  1628  	out, err := state.AllocsByNode("foo")
  1629  	if err != nil {
  1630  		t.Fatalf("err: %v", err)
  1631  	}
  1632  
  1633  	sort.Sort(AllocIDSort(allocs))
  1634  	sort.Sort(AllocIDSort(out))
  1635  
  1636  	if !reflect.DeepEqual(allocs, out) {
  1637  		t.Fatalf("bad: %#v %#v", allocs, out)
  1638  	}
  1639  }
  1640  
  1641  func TestStateStore_AllocsByNodeTerminal(t *testing.T) {
  1642  	state := testStateStore(t)
  1643  	var allocs, term, nonterm []*structs.Allocation
  1644  
  1645  	for i := 0; i < 10; i++ {
  1646  		alloc := mock.Alloc()
  1647  		alloc.NodeID = "foo"
  1648  		if i%2 == 0 {
  1649  			alloc.DesiredStatus = structs.AllocDesiredStatusStop
  1650  			term = append(term, alloc)
  1651  		} else {
  1652  			nonterm = append(nonterm, alloc)
  1653  		}
  1654  		allocs = append(allocs, alloc)
  1655  	}
  1656  
  1657  	err := state.UpsertAllocs(1000, allocs)
  1658  	if err != nil {
  1659  		t.Fatalf("err: %v", err)
  1660  	}
  1661  
  1662  	// Verify the terminal allocs
  1663  	out, err := state.AllocsByNodeTerminal("foo", true)
  1664  	if err != nil {
  1665  		t.Fatalf("err: %v", err)
  1666  	}
  1667  
  1668  	sort.Sort(AllocIDSort(term))
  1669  	sort.Sort(AllocIDSort(out))
  1670  
  1671  	if !reflect.DeepEqual(term, out) {
  1672  		t.Fatalf("bad: %#v %#v", term, out)
  1673  	}
  1674  
  1675  	// Verify the non-terminal allocs
  1676  	out, err = state.AllocsByNodeTerminal("foo", false)
  1677  	if err != nil {
  1678  		t.Fatalf("err: %v", err)
  1679  	}
  1680  
  1681  	sort.Sort(AllocIDSort(nonterm))
  1682  	sort.Sort(AllocIDSort(out))
  1683  
  1684  	if !reflect.DeepEqual(nonterm, out) {
  1685  		t.Fatalf("bad: %#v %#v", nonterm, out)
  1686  	}
  1687  }
  1688  
  1689  func TestStateStore_AllocsByJob(t *testing.T) {
  1690  	state := testStateStore(t)
  1691  	var allocs []*structs.Allocation
  1692  
  1693  	for i := 0; i < 10; i++ {
  1694  		alloc := mock.Alloc()
  1695  		alloc.JobID = "foo"
  1696  		allocs = append(allocs, alloc)
  1697  	}
  1698  
  1699  	err := state.UpsertAllocs(1000, allocs)
  1700  	if err != nil {
  1701  		t.Fatalf("err: %v", err)
  1702  	}
  1703  
  1704  	out, err := state.AllocsByJob("foo")
  1705  	if err != nil {
  1706  		t.Fatalf("err: %v", err)
  1707  	}
  1708  
  1709  	sort.Sort(AllocIDSort(allocs))
  1710  	sort.Sort(AllocIDSort(out))
  1711  
  1712  	if !reflect.DeepEqual(allocs, out) {
  1713  		t.Fatalf("bad: %#v %#v", allocs, out)
  1714  	}
  1715  }
  1716  
  1717  func TestStateStore_AllocsByIDPrefix(t *testing.T) {
  1718  	state := testStateStore(t)
  1719  	var allocs []*structs.Allocation
  1720  
  1721  	ids := []string{
  1722  		"aaaaaaaa-7bfb-395d-eb95-0685af2176b2",
  1723  		"aaaaaaab-7bfb-395d-eb95-0685af2176b2",
  1724  		"aaaaaabb-7bfb-395d-eb95-0685af2176b2",
  1725  		"aaaaabbb-7bfb-395d-eb95-0685af2176b2",
  1726  		"aaaabbbb-7bfb-395d-eb95-0685af2176b2",
  1727  		"aaabbbbb-7bfb-395d-eb95-0685af2176b2",
  1728  		"aabbbbbb-7bfb-395d-eb95-0685af2176b2",
  1729  		"abbbbbbb-7bfb-395d-eb95-0685af2176b2",
  1730  		"bbbbbbbb-7bfb-395d-eb95-0685af2176b2",
  1731  	}
  1732  	for i := 0; i < 9; i++ {
  1733  		alloc := mock.Alloc()
  1734  		alloc.ID = ids[i]
  1735  		allocs = append(allocs, alloc)
  1736  	}
  1737  
  1738  	err := state.UpsertAllocs(1000, allocs)
  1739  	if err != nil {
  1740  		t.Fatalf("err: %v", err)
  1741  	}
  1742  
  1743  	iter, err := state.AllocsByIDPrefix("aaaa")
  1744  	if err != nil {
  1745  		t.Fatalf("err: %v", err)
  1746  	}
  1747  
  1748  	gatherAllocs := func(iter memdb.ResultIterator) []*structs.Allocation {
  1749  		var allocs []*structs.Allocation
  1750  		for {
  1751  			raw := iter.Next()
  1752  			if raw == nil {
  1753  				break
  1754  			}
  1755  			allocs = append(allocs, raw.(*structs.Allocation))
  1756  		}
  1757  		return allocs
  1758  	}
  1759  
  1760  	out := gatherAllocs(iter)
  1761  	if len(out) != 5 {
  1762  		t.Fatalf("bad: expected five allocations, got: %#v", out)
  1763  	}
  1764  
  1765  	sort.Sort(AllocIDSort(allocs))
  1766  
  1767  	for index, alloc := range out {
  1768  		if ids[index] != alloc.ID {
  1769  			t.Fatalf("bad: got unexpected id: %s", alloc.ID)
  1770  		}
  1771  	}
  1772  
  1773  	iter, err = state.AllocsByIDPrefix("b-a7bfb")
  1774  	if err != nil {
  1775  		t.Fatalf("err: %v", err)
  1776  	}
  1777  
  1778  	out = gatherAllocs(iter)
  1779  	if len(out) != 0 {
  1780  		t.Fatalf("bad: unexpected zero allocations, got: %#v", out)
  1781  	}
  1782  }
  1783  
  1784  func TestStateStore_Allocs(t *testing.T) {
  1785  	state := testStateStore(t)
  1786  	var allocs []*structs.Allocation
  1787  
  1788  	for i := 0; i < 10; i++ {
  1789  		alloc := mock.Alloc()
  1790  		allocs = append(allocs, alloc)
  1791  	}
  1792  
  1793  	err := state.UpsertAllocs(1000, allocs)
  1794  	if err != nil {
  1795  		t.Fatalf("err: %v", err)
  1796  	}
  1797  
  1798  	iter, err := state.Allocs()
  1799  	if err != nil {
  1800  		t.Fatalf("err: %v", err)
  1801  	}
  1802  
  1803  	var out []*structs.Allocation
  1804  	for {
  1805  		raw := iter.Next()
  1806  		if raw == nil {
  1807  			break
  1808  		}
  1809  		out = append(out, raw.(*structs.Allocation))
  1810  	}
  1811  
  1812  	sort.Sort(AllocIDSort(allocs))
  1813  	sort.Sort(AllocIDSort(out))
  1814  
  1815  	if !reflect.DeepEqual(allocs, out) {
  1816  		t.Fatalf("bad: %#v %#v", allocs, out)
  1817  	}
  1818  }
  1819  
  1820  func TestStateStore_RestoreAlloc(t *testing.T) {
  1821  	state := testStateStore(t)
  1822  	alloc := mock.Alloc()
  1823  
  1824  	notify := setupNotifyTest(
  1825  		state,
  1826  		watch.Item{Table: "allocs"},
  1827  		watch.Item{Alloc: alloc.ID},
  1828  		watch.Item{AllocEval: alloc.EvalID},
  1829  		watch.Item{AllocJob: alloc.JobID},
  1830  		watch.Item{AllocNode: alloc.NodeID})
  1831  
  1832  	restore, err := state.Restore()
  1833  	if err != nil {
  1834  		t.Fatalf("err: %v", err)
  1835  	}
  1836  
  1837  	err = restore.AllocRestore(alloc)
  1838  	if err != nil {
  1839  		t.Fatalf("err: %v", err)
  1840  	}
  1841  
  1842  	restore.Commit()
  1843  
  1844  	out, err := state.AllocByID(alloc.ID)
  1845  	if err != nil {
  1846  		t.Fatalf("err: %v", err)
  1847  	}
  1848  
  1849  	if !reflect.DeepEqual(out, alloc) {
  1850  		t.Fatalf("Bad: %#v %#v", out, alloc)
  1851  	}
  1852  
  1853  	notify.verify(t)
  1854  }
  1855  
  1856  func TestStateStore_SetJobStatus_ForceStatus(t *testing.T) {
  1857  	state := testStateStore(t)
  1858  	watcher := watch.NewItems()
  1859  	txn := state.db.Txn(true)
  1860  
  1861  	// Create and insert a mock job.
  1862  	job := mock.Job()
  1863  	job.Status = ""
  1864  	job.ModifyIndex = 0
  1865  	if err := txn.Insert("jobs", job); err != nil {
  1866  		t.Fatalf("job insert failed: %v", err)
  1867  	}
  1868  
  1869  	exp := "foobar"
  1870  	index := uint64(1000)
  1871  	if err := state.setJobStatus(index, watcher, txn, job, false, exp); err != nil {
  1872  		t.Fatalf("setJobStatus() failed: %v", err)
  1873  	}
  1874  
  1875  	i, err := txn.First("jobs", "id", job.ID)
  1876  	if err != nil {
  1877  		t.Fatalf("job lookup failed: %v", err)
  1878  	}
  1879  	updated := i.(*structs.Job)
  1880  
  1881  	if updated.Status != exp {
  1882  		t.Fatalf("setJobStatus() set %v; expected %v", updated.Status, exp)
  1883  	}
  1884  
  1885  	if updated.ModifyIndex != index {
  1886  		t.Fatalf("setJobStatus() set %d; expected %d", updated.ModifyIndex, index)
  1887  	}
  1888  }
  1889  
  1890  func TestStateStore_SetJobStatus_NoOp(t *testing.T) {
  1891  	state := testStateStore(t)
  1892  	watcher := watch.NewItems()
  1893  	txn := state.db.Txn(true)
  1894  
  1895  	// Create and insert a mock job that should be pending.
  1896  	job := mock.Job()
  1897  	job.Status = structs.JobStatusPending
  1898  	job.ModifyIndex = 10
  1899  	if err := txn.Insert("jobs", job); err != nil {
  1900  		t.Fatalf("job insert failed: %v", err)
  1901  	}
  1902  
  1903  	index := uint64(1000)
  1904  	if err := state.setJobStatus(index, watcher, txn, job, false, ""); err != nil {
  1905  		t.Fatalf("setJobStatus() failed: %v", err)
  1906  	}
  1907  
  1908  	i, err := txn.First("jobs", "id", job.ID)
  1909  	if err != nil {
  1910  		t.Fatalf("job lookup failed: %v", err)
  1911  	}
  1912  	updated := i.(*structs.Job)
  1913  
  1914  	if updated.ModifyIndex == index {
  1915  		t.Fatalf("setJobStatus() should have been a no-op")
  1916  	}
  1917  }
  1918  
  1919  func TestStateStore_SetJobStatus(t *testing.T) {
  1920  	state := testStateStore(t)
  1921  	watcher := watch.NewItems()
  1922  	txn := state.db.Txn(true)
  1923  
  1924  	// Create and insert a mock job that should be pending but has an incorrect
  1925  	// status.
  1926  	job := mock.Job()
  1927  	job.Status = "foobar"
  1928  	job.ModifyIndex = 10
  1929  	if err := txn.Insert("jobs", job); err != nil {
  1930  		t.Fatalf("job insert failed: %v", err)
  1931  	}
  1932  
  1933  	index := uint64(1000)
  1934  	if err := state.setJobStatus(index, watcher, txn, job, false, ""); err != nil {
  1935  		t.Fatalf("setJobStatus() failed: %v", err)
  1936  	}
  1937  
  1938  	i, err := txn.First("jobs", "id", job.ID)
  1939  	if err != nil {
  1940  		t.Fatalf("job lookup failed: %v", err)
  1941  	}
  1942  	updated := i.(*structs.Job)
  1943  
  1944  	if updated.Status != structs.JobStatusPending {
  1945  		t.Fatalf("setJobStatus() set %v; expected %v", updated.Status, structs.JobStatusPending)
  1946  	}
  1947  
  1948  	if updated.ModifyIndex != index {
  1949  		t.Fatalf("setJobStatus() set %d; expected %d", updated.ModifyIndex, index)
  1950  	}
  1951  }
  1952  
  1953  func TestStateStore_GetJobStatus_NoEvalsOrAllocs(t *testing.T) {
  1954  	job := mock.Job()
  1955  	state := testStateStore(t)
  1956  	txn := state.db.Txn(false)
  1957  	status, err := state.getJobStatus(txn, job, false)
  1958  	if err != nil {
  1959  		t.Fatalf("getJobStatus() failed: %v", err)
  1960  	}
  1961  
  1962  	if status != structs.JobStatusPending {
  1963  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusPending)
  1964  	}
  1965  }
  1966  
  1967  func TestStateStore_GetJobStatus_NoEvalsOrAllocs_Periodic(t *testing.T) {
  1968  	job := mock.PeriodicJob()
  1969  	state := testStateStore(t)
  1970  	txn := state.db.Txn(false)
  1971  	status, err := state.getJobStatus(txn, job, false)
  1972  	if err != nil {
  1973  		t.Fatalf("getJobStatus() failed: %v", err)
  1974  	}
  1975  
  1976  	if status != structs.JobStatusRunning {
  1977  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusRunning)
  1978  	}
  1979  }
  1980  
  1981  func TestStateStore_GetJobStatus_NoEvalsOrAllocs_EvalDelete(t *testing.T) {
  1982  	job := mock.Job()
  1983  	state := testStateStore(t)
  1984  	txn := state.db.Txn(false)
  1985  	status, err := state.getJobStatus(txn, job, true)
  1986  	if err != nil {
  1987  		t.Fatalf("getJobStatus() failed: %v", err)
  1988  	}
  1989  
  1990  	if status != structs.JobStatusDead {
  1991  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusDead)
  1992  	}
  1993  }
  1994  
  1995  func TestStateStore_GetJobStatus_DeadEvalsAndAllocs(t *testing.T) {
  1996  	state := testStateStore(t)
  1997  	job := mock.Job()
  1998  
  1999  	// Create a mock alloc that is dead.
  2000  	alloc := mock.Alloc()
  2001  	alloc.JobID = job.ID
  2002  	alloc.DesiredStatus = structs.AllocDesiredStatusFailed
  2003  	if err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}); err != nil {
  2004  		t.Fatalf("err: %v", err)
  2005  	}
  2006  
  2007  	// Create a mock eval that is complete
  2008  	eval := mock.Eval()
  2009  	eval.JobID = job.ID
  2010  	eval.Status = structs.EvalStatusComplete
  2011  	if err := state.UpsertEvals(1001, []*structs.Evaluation{eval}); err != nil {
  2012  		t.Fatalf("err: %v", err)
  2013  	}
  2014  
  2015  	txn := state.db.Txn(false)
  2016  	status, err := state.getJobStatus(txn, job, false)
  2017  	if err != nil {
  2018  		t.Fatalf("getJobStatus() failed: %v", err)
  2019  	}
  2020  
  2021  	if status != structs.JobStatusDead {
  2022  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusDead)
  2023  	}
  2024  }
  2025  
  2026  func TestStateStore_GetJobStatus_RunningAlloc(t *testing.T) {
  2027  	state := testStateStore(t)
  2028  	job := mock.Job()
  2029  
  2030  	// Create a mock alloc that is running.
  2031  	alloc := mock.Alloc()
  2032  	alloc.JobID = job.ID
  2033  	alloc.DesiredStatus = structs.AllocDesiredStatusRun
  2034  	if err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}); err != nil {
  2035  		t.Fatalf("err: %v", err)
  2036  	}
  2037  
  2038  	txn := state.db.Txn(false)
  2039  	status, err := state.getJobStatus(txn, job, true)
  2040  	if err != nil {
  2041  		t.Fatalf("getJobStatus() failed: %v", err)
  2042  	}
  2043  
  2044  	if status != structs.JobStatusRunning {
  2045  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusRunning)
  2046  	}
  2047  }
  2048  
  2049  func TestStateStore_SetJobStatus_PendingEval(t *testing.T) {
  2050  	state := testStateStore(t)
  2051  	job := mock.Job()
  2052  
  2053  	// Create a mock eval that is pending.
  2054  	eval := mock.Eval()
  2055  	eval.JobID = job.ID
  2056  	eval.Status = structs.EvalStatusPending
  2057  	if err := state.UpsertEvals(1000, []*structs.Evaluation{eval}); err != nil {
  2058  		t.Fatalf("err: %v", err)
  2059  	}
  2060  
  2061  	txn := state.db.Txn(false)
  2062  	status, err := state.getJobStatus(txn, job, true)
  2063  	if err != nil {
  2064  		t.Fatalf("getJobStatus() failed: %v", err)
  2065  	}
  2066  
  2067  	if status != structs.JobStatusPending {
  2068  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusPending)
  2069  	}
  2070  }
  2071  
  2072  func TestStateWatch_watch(t *testing.T) {
  2073  	sw := newStateWatch()
  2074  	notify1 := make(chan struct{}, 1)
  2075  	notify2 := make(chan struct{}, 1)
  2076  	notify3 := make(chan struct{}, 1)
  2077  
  2078  	// Notifications trigger subscribed channels
  2079  	sw.watch(watch.NewItems(watch.Item{Table: "foo"}), notify1)
  2080  	sw.watch(watch.NewItems(watch.Item{Table: "bar"}), notify2)
  2081  	sw.watch(watch.NewItems(watch.Item{Table: "baz"}), notify3)
  2082  
  2083  	items := watch.NewItems()
  2084  	items.Add(watch.Item{Table: "foo"})
  2085  	items.Add(watch.Item{Table: "bar"})
  2086  
  2087  	sw.notify(items)
  2088  	if len(notify1) != 1 {
  2089  		t.Fatalf("should notify")
  2090  	}
  2091  	if len(notify2) != 1 {
  2092  		t.Fatalf("should notify")
  2093  	}
  2094  	if len(notify3) != 0 {
  2095  		t.Fatalf("should not notify")
  2096  	}
  2097  }
  2098  
  2099  func TestStateWatch_stopWatch(t *testing.T) {
  2100  	sw := newStateWatch()
  2101  	notify := make(chan struct{})
  2102  
  2103  	// First subscribe
  2104  	sw.watch(watch.NewItems(watch.Item{Table: "foo"}), notify)
  2105  
  2106  	// Unsubscribe stop notifications
  2107  	sw.stopWatch(watch.NewItems(watch.Item{Table: "foo"}), notify)
  2108  
  2109  	// Check that the group was removed
  2110  	if _, ok := sw.items[watch.Item{Table: "foo"}]; ok {
  2111  		t.Fatalf("should remove group")
  2112  	}
  2113  
  2114  	// Check that we are not notified
  2115  	sw.notify(watch.NewItems(watch.Item{Table: "foo"}))
  2116  	if len(notify) != 0 {
  2117  		t.Fatalf("should not notify")
  2118  	}
  2119  }
  2120  
  2121  // setupNotifyTest takes a state store and a set of watch items, then creates
  2122  // and subscribes a notification channel for each item.
  2123  func setupNotifyTest(state *StateStore, items ...watch.Item) notifyTest {
  2124  	var n notifyTest
  2125  	for _, item := range items {
  2126  		ch := make(chan struct{}, 1)
  2127  		state.Watch(watch.NewItems(item), ch)
  2128  		n = append(n, &notifyTestCase{item, ch})
  2129  	}
  2130  	return n
  2131  }
  2132  
  2133  // notifyTestCase is used to set up and verify watch triggers.
  2134  type notifyTestCase struct {
  2135  	item watch.Item
  2136  	ch   chan struct{}
  2137  }
  2138  
  2139  // notifyTest is a suite of notifyTestCases.
  2140  type notifyTest []*notifyTestCase
  2141  
  2142  // verify ensures that each channel received a notification.
  2143  func (n notifyTest) verify(t *testing.T) {
  2144  	for _, tcase := range n {
  2145  		if len(tcase.ch) != 1 {
  2146  			t.Fatalf("should notify %#v", tcase.item)
  2147  		}
  2148  	}
  2149  }
  2150  
  2151  // NodeIDSort is used to sort nodes by ID
  2152  type NodeIDSort []*structs.Node
  2153  
  2154  func (n NodeIDSort) Len() int {
  2155  	return len(n)
  2156  }
  2157  
  2158  func (n NodeIDSort) Less(i, j int) bool {
  2159  	return n[i].ID < n[j].ID
  2160  }
  2161  
  2162  func (n NodeIDSort) Swap(i, j int) {
  2163  	n[i], n[j] = n[j], n[i]
  2164  }
  2165  
  2166  // JobIDis used to sort jobs by id
  2167  type JobIDSort []*structs.Job
  2168  
  2169  func (n JobIDSort) Len() int {
  2170  	return len(n)
  2171  }
  2172  
  2173  func (n JobIDSort) Less(i, j int) bool {
  2174  	return n[i].ID < n[j].ID
  2175  }
  2176  
  2177  func (n JobIDSort) Swap(i, j int) {
  2178  	n[i], n[j] = n[j], n[i]
  2179  }
  2180  
  2181  // EvalIDis used to sort evals by id
  2182  type EvalIDSort []*structs.Evaluation
  2183  
  2184  func (n EvalIDSort) Len() int {
  2185  	return len(n)
  2186  }
  2187  
  2188  func (n EvalIDSort) Less(i, j int) bool {
  2189  	return n[i].ID < n[j].ID
  2190  }
  2191  
  2192  func (n EvalIDSort) Swap(i, j int) {
  2193  	n[i], n[j] = n[j], n[i]
  2194  }
  2195  
  2196  // AllocIDsort used to sort allocations by id
  2197  type AllocIDSort []*structs.Allocation
  2198  
  2199  func (n AllocIDSort) Len() int {
  2200  	return len(n)
  2201  }
  2202  
  2203  func (n AllocIDSort) Less(i, j int) bool {
  2204  	return n[i].ID < n[j].ID
  2205  }
  2206  
  2207  func (n AllocIDSort) Swap(i, j int) {
  2208  	n[i], n[j] = n[j], n[i]
  2209  }