github.com/ranjib/nomad@v0.1.1-0.20160225204057-97751b02f70b/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 < 10; i++ {
   685  		job := mock.Job()
   686  		nonGc = append(nonGc, job)
   687  
   688  		if err := state.UpsertJob(1000+uint64(i), job); err != nil {
   689  			t.Fatalf("err: %v", err)
   690  		}
   691  	}
   692  
   693  	for i := 0; i < 10; i++ {
   694  		job := mock.Job()
   695  		job.GC = true
   696  		gc = append(gc, job)
   697  
   698  		if err := state.UpsertJob(2000+uint64(i), job); err != nil {
   699  			t.Fatalf("err: %v", err)
   700  		}
   701  	}
   702  
   703  	iter, err := state.JobsByGC(true)
   704  	if err != nil {
   705  		t.Fatalf("err: %v", err)
   706  	}
   707  
   708  	var outGc []*structs.Job
   709  	for i := iter.Next(); i != nil; i = iter.Next() {
   710  		outGc = append(outGc, i.(*structs.Job))
   711  	}
   712  
   713  	iter, err = state.JobsByGC(false)
   714  	if err != nil {
   715  		t.Fatalf("err: %v", err)
   716  	}
   717  
   718  	var outNonGc []*structs.Job
   719  	for i := iter.Next(); i != nil; i = iter.Next() {
   720  		outNonGc = append(outNonGc, i.(*structs.Job))
   721  	}
   722  
   723  	sort.Sort(JobIDSort(gc))
   724  	sort.Sort(JobIDSort(nonGc))
   725  	sort.Sort(JobIDSort(outGc))
   726  	sort.Sort(JobIDSort(outNonGc))
   727  
   728  	if !reflect.DeepEqual(gc, outGc) {
   729  		t.Fatalf("bad: %#v %#v", gc, outGc)
   730  	}
   731  
   732  	if !reflect.DeepEqual(nonGc, outNonGc) {
   733  		t.Fatalf("bad: %#v %#v", nonGc, outNonGc)
   734  	}
   735  }
   736  
   737  func TestStateStore_RestoreJob(t *testing.T) {
   738  	state := testStateStore(t)
   739  	job := mock.Job()
   740  
   741  	notify := setupNotifyTest(
   742  		state,
   743  		watch.Item{Table: "jobs"},
   744  		watch.Item{Job: job.ID})
   745  
   746  	restore, err := state.Restore()
   747  	if err != nil {
   748  		t.Fatalf("err: %v", err)
   749  	}
   750  
   751  	err = restore.JobRestore(job)
   752  	if err != nil {
   753  		t.Fatalf("err: %v", err)
   754  	}
   755  	restore.Commit()
   756  
   757  	out, err := state.JobByID(job.ID)
   758  	if err != nil {
   759  		t.Fatalf("err: %v", err)
   760  	}
   761  
   762  	if !reflect.DeepEqual(out, job) {
   763  		t.Fatalf("Bad: %#v %#v", out, job)
   764  	}
   765  
   766  	notify.verify(t)
   767  }
   768  
   769  func TestStateStore_UpsertPeriodicLaunch(t *testing.T) {
   770  	state := testStateStore(t)
   771  	job := mock.Job()
   772  	launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()}
   773  
   774  	notify := setupNotifyTest(
   775  		state,
   776  		watch.Item{Table: "periodic_launch"},
   777  		watch.Item{Job: job.ID})
   778  
   779  	err := state.UpsertPeriodicLaunch(1000, launch)
   780  	if err != nil {
   781  		t.Fatalf("err: %v", err)
   782  	}
   783  
   784  	out, err := state.PeriodicLaunchByID(job.ID)
   785  	if err != nil {
   786  		t.Fatalf("err: %v", err)
   787  	}
   788  	if out.CreateIndex != 1000 {
   789  		t.Fatalf("bad: %#v", out)
   790  	}
   791  	if out.ModifyIndex != 1000 {
   792  		t.Fatalf("bad: %#v", out)
   793  	}
   794  
   795  	if !reflect.DeepEqual(launch, out) {
   796  		t.Fatalf("bad: %#v %#v", job, out)
   797  	}
   798  
   799  	index, err := state.Index("periodic_launch")
   800  	if err != nil {
   801  		t.Fatalf("err: %v", err)
   802  	}
   803  	if index != 1000 {
   804  		t.Fatalf("bad: %d", index)
   805  	}
   806  
   807  	notify.verify(t)
   808  }
   809  
   810  func TestStateStore_UpdateUpsertPeriodicLaunch(t *testing.T) {
   811  	state := testStateStore(t)
   812  	job := mock.Job()
   813  	launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()}
   814  
   815  	notify := setupNotifyTest(
   816  		state,
   817  		watch.Item{Table: "periodic_launch"},
   818  		watch.Item{Job: job.ID})
   819  
   820  	err := state.UpsertPeriodicLaunch(1000, launch)
   821  	if err != nil {
   822  		t.Fatalf("err: %v", err)
   823  	}
   824  
   825  	launch2 := &structs.PeriodicLaunch{
   826  		ID:     job.ID,
   827  		Launch: launch.Launch.Add(1 * time.Second),
   828  	}
   829  	err = state.UpsertPeriodicLaunch(1001, launch2)
   830  	if err != nil {
   831  		t.Fatalf("err: %v", err)
   832  	}
   833  
   834  	out, err := state.PeriodicLaunchByID(job.ID)
   835  	if err != nil {
   836  		t.Fatalf("err: %v", err)
   837  	}
   838  	if out.CreateIndex != 1000 {
   839  		t.Fatalf("bad: %#v", out)
   840  	}
   841  	if out.ModifyIndex != 1001 {
   842  		t.Fatalf("bad: %#v", out)
   843  	}
   844  
   845  	if !reflect.DeepEqual(launch2, out) {
   846  		t.Fatalf("bad: %#v %#v", launch2, out)
   847  	}
   848  
   849  	index, err := state.Index("periodic_launch")
   850  	if err != nil {
   851  		t.Fatalf("err: %v", err)
   852  	}
   853  	if index != 1001 {
   854  		t.Fatalf("bad: %d", index)
   855  	}
   856  
   857  	notify.verify(t)
   858  }
   859  
   860  func TestStateStore_DeletePeriodicLaunch(t *testing.T) {
   861  	state := testStateStore(t)
   862  	job := mock.Job()
   863  	launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()}
   864  
   865  	notify := setupNotifyTest(
   866  		state,
   867  		watch.Item{Table: "periodic_launch"},
   868  		watch.Item{Job: job.ID})
   869  
   870  	err := state.UpsertPeriodicLaunch(1000, launch)
   871  	if err != nil {
   872  		t.Fatalf("err: %v", err)
   873  	}
   874  
   875  	err = state.DeletePeriodicLaunch(1001, job.ID)
   876  	if err != nil {
   877  		t.Fatalf("err: %v", err)
   878  	}
   879  
   880  	out, err := state.PeriodicLaunchByID(job.ID)
   881  	if err != nil {
   882  		t.Fatalf("err: %v", err)
   883  	}
   884  
   885  	if out != nil {
   886  		t.Fatalf("bad: %#v %#v", job, out)
   887  	}
   888  
   889  	index, err := state.Index("periodic_launch")
   890  	if err != nil {
   891  		t.Fatalf("err: %v", err)
   892  	}
   893  	if index != 1001 {
   894  		t.Fatalf("bad: %d", index)
   895  	}
   896  
   897  	notify.verify(t)
   898  }
   899  
   900  func TestStateStore_PeriodicLaunches(t *testing.T) {
   901  	state := testStateStore(t)
   902  	var launches []*structs.PeriodicLaunch
   903  
   904  	for i := 0; i < 10; i++ {
   905  		job := mock.Job()
   906  		launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()}
   907  		launches = append(launches, launch)
   908  
   909  		err := state.UpsertPeriodicLaunch(1000+uint64(i), launch)
   910  		if err != nil {
   911  			t.Fatalf("err: %v", err)
   912  		}
   913  	}
   914  
   915  	iter, err := state.PeriodicLaunches()
   916  	if err != nil {
   917  		t.Fatalf("err: %v", err)
   918  	}
   919  
   920  	out := make(map[string]*structs.PeriodicLaunch, 10)
   921  	for {
   922  		raw := iter.Next()
   923  		if raw == nil {
   924  			break
   925  		}
   926  		launch := raw.(*structs.PeriodicLaunch)
   927  		if _, ok := out[launch.ID]; ok {
   928  			t.Fatalf("duplicate: %v", launch.ID)
   929  		}
   930  
   931  		out[launch.ID] = launch
   932  	}
   933  
   934  	for _, launch := range launches {
   935  		l, ok := out[launch.ID]
   936  		if !ok {
   937  			t.Fatalf("bad %v", launch.ID)
   938  		}
   939  
   940  		if !reflect.DeepEqual(launch, l) {
   941  			t.Fatalf("bad: %#v %#v", launch, l)
   942  		}
   943  
   944  		delete(out, launch.ID)
   945  	}
   946  
   947  	if len(out) != 0 {
   948  		t.Fatalf("leftover: %#v", out)
   949  	}
   950  }
   951  
   952  func TestStateStore_RestorePeriodicLaunch(t *testing.T) {
   953  	state := testStateStore(t)
   954  	job := mock.Job()
   955  	launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()}
   956  
   957  	notify := setupNotifyTest(
   958  		state,
   959  		watch.Item{Table: "periodic_launch"},
   960  		watch.Item{Job: job.ID})
   961  
   962  	restore, err := state.Restore()
   963  	if err != nil {
   964  		t.Fatalf("err: %v", err)
   965  	}
   966  
   967  	err = restore.PeriodicLaunchRestore(launch)
   968  	if err != nil {
   969  		t.Fatalf("err: %v", err)
   970  	}
   971  	restore.Commit()
   972  
   973  	out, err := state.PeriodicLaunchByID(job.ID)
   974  	if err != nil {
   975  		t.Fatalf("err: %v", err)
   976  	}
   977  
   978  	if !reflect.DeepEqual(out, launch) {
   979  		t.Fatalf("Bad: %#v %#v", out, job)
   980  	}
   981  
   982  	notify.verify(t)
   983  }
   984  
   985  func TestStateStore_Indexes(t *testing.T) {
   986  	state := testStateStore(t)
   987  	node := mock.Node()
   988  
   989  	err := state.UpsertNode(1000, node)
   990  	if err != nil {
   991  		t.Fatalf("err: %v", err)
   992  	}
   993  
   994  	iter, err := state.Indexes()
   995  	if err != nil {
   996  		t.Fatalf("err: %v", err)
   997  	}
   998  
   999  	var out []*IndexEntry
  1000  	for {
  1001  		raw := iter.Next()
  1002  		if raw == nil {
  1003  			break
  1004  		}
  1005  		out = append(out, raw.(*IndexEntry))
  1006  	}
  1007  
  1008  	expect := []*IndexEntry{
  1009  		&IndexEntry{"nodes", 1000},
  1010  	}
  1011  
  1012  	if !reflect.DeepEqual(expect, out) {
  1013  		t.Fatalf("bad: %#v %#v", expect, out)
  1014  	}
  1015  }
  1016  
  1017  func TestStateStore_RestoreIndex(t *testing.T) {
  1018  	state := testStateStore(t)
  1019  
  1020  	restore, err := state.Restore()
  1021  	if err != nil {
  1022  		t.Fatalf("err: %v", err)
  1023  	}
  1024  
  1025  	index := &IndexEntry{"jobs", 1000}
  1026  	err = restore.IndexRestore(index)
  1027  	if err != nil {
  1028  		t.Fatalf("err: %v", err)
  1029  	}
  1030  
  1031  	restore.Commit()
  1032  
  1033  	out, err := state.Index("jobs")
  1034  	if err != nil {
  1035  		t.Fatalf("err: %v", err)
  1036  	}
  1037  
  1038  	if out != 1000 {
  1039  		t.Fatalf("Bad: %#v %#v", out, 1000)
  1040  	}
  1041  }
  1042  
  1043  func TestStateStore_UpsertEvals_Eval(t *testing.T) {
  1044  	state := testStateStore(t)
  1045  	eval := mock.Eval()
  1046  
  1047  	notify := setupNotifyTest(
  1048  		state,
  1049  		watch.Item{Table: "evals"},
  1050  		watch.Item{Eval: eval.ID})
  1051  
  1052  	err := state.UpsertEvals(1000, []*structs.Evaluation{eval})
  1053  	if err != nil {
  1054  		t.Fatalf("err: %v", err)
  1055  	}
  1056  
  1057  	out, err := state.EvalByID(eval.ID)
  1058  	if err != nil {
  1059  		t.Fatalf("err: %v", err)
  1060  	}
  1061  
  1062  	if !reflect.DeepEqual(eval, out) {
  1063  		t.Fatalf("bad: %#v %#v", eval, out)
  1064  	}
  1065  
  1066  	index, err := state.Index("evals")
  1067  	if err != nil {
  1068  		t.Fatalf("err: %v", err)
  1069  	}
  1070  	if index != 1000 {
  1071  		t.Fatalf("bad: %d", index)
  1072  	}
  1073  
  1074  	notify.verify(t)
  1075  }
  1076  
  1077  func TestStateStore_Update_UpsertEvals_Eval(t *testing.T) {
  1078  	state := testStateStore(t)
  1079  	eval := mock.Eval()
  1080  
  1081  	err := state.UpsertEvals(1000, []*structs.Evaluation{eval})
  1082  	if err != nil {
  1083  		t.Fatalf("err: %v", err)
  1084  	}
  1085  
  1086  	notify := setupNotifyTest(
  1087  		state,
  1088  		watch.Item{Table: "evals"},
  1089  		watch.Item{Eval: eval.ID})
  1090  
  1091  	eval2 := mock.Eval()
  1092  	eval2.ID = eval.ID
  1093  	err = state.UpsertEvals(1001, []*structs.Evaluation{eval2})
  1094  	if err != nil {
  1095  		t.Fatalf("err: %v", err)
  1096  	}
  1097  
  1098  	out, err := state.EvalByID(eval.ID)
  1099  	if err != nil {
  1100  		t.Fatalf("err: %v", err)
  1101  	}
  1102  
  1103  	if !reflect.DeepEqual(eval2, out) {
  1104  		t.Fatalf("bad: %#v %#v", eval2, out)
  1105  	}
  1106  
  1107  	if out.CreateIndex != 1000 {
  1108  		t.Fatalf("bad: %#v", out)
  1109  	}
  1110  	if out.ModifyIndex != 1001 {
  1111  		t.Fatalf("bad: %#v", out)
  1112  	}
  1113  
  1114  	index, err := state.Index("evals")
  1115  	if err != nil {
  1116  		t.Fatalf("err: %v", err)
  1117  	}
  1118  	if index != 1001 {
  1119  		t.Fatalf("bad: %d", index)
  1120  	}
  1121  
  1122  	notify.verify(t)
  1123  }
  1124  
  1125  func TestStateStore_DeleteEval_Eval(t *testing.T) {
  1126  	state := testStateStore(t)
  1127  	eval1 := mock.Eval()
  1128  	eval2 := mock.Eval()
  1129  	alloc1 := mock.Alloc()
  1130  	alloc2 := mock.Alloc()
  1131  
  1132  	notify := setupNotifyTest(
  1133  		state,
  1134  		watch.Item{Table: "evals"},
  1135  		watch.Item{Table: "allocs"},
  1136  		watch.Item{Eval: eval1.ID},
  1137  		watch.Item{Eval: eval2.ID},
  1138  		watch.Item{Alloc: alloc1.ID},
  1139  		watch.Item{Alloc: alloc2.ID},
  1140  		watch.Item{AllocEval: alloc1.EvalID},
  1141  		watch.Item{AllocEval: alloc2.EvalID},
  1142  		watch.Item{AllocJob: alloc1.JobID},
  1143  		watch.Item{AllocJob: alloc2.JobID},
  1144  		watch.Item{AllocNode: alloc1.NodeID},
  1145  		watch.Item{AllocNode: alloc2.NodeID})
  1146  
  1147  	err := state.UpsertEvals(1000, []*structs.Evaluation{eval1, eval2})
  1148  	if err != nil {
  1149  		t.Fatalf("err: %v", err)
  1150  	}
  1151  
  1152  	err = state.UpsertAllocs(1001, []*structs.Allocation{alloc1, alloc2})
  1153  	if err != nil {
  1154  		t.Fatalf("err: %v", err)
  1155  	}
  1156  
  1157  	err = state.DeleteEval(1002, []string{eval1.ID, eval2.ID}, []string{alloc1.ID, alloc2.ID})
  1158  	if err != nil {
  1159  		t.Fatalf("err: %v", err)
  1160  	}
  1161  
  1162  	out, err := state.EvalByID(eval1.ID)
  1163  	if err != nil {
  1164  		t.Fatalf("err: %v", err)
  1165  	}
  1166  
  1167  	if out != nil {
  1168  		t.Fatalf("bad: %#v %#v", eval1, out)
  1169  	}
  1170  
  1171  	out, err = state.EvalByID(eval2.ID)
  1172  	if err != nil {
  1173  		t.Fatalf("err: %v", err)
  1174  	}
  1175  
  1176  	if out != nil {
  1177  		t.Fatalf("bad: %#v %#v", eval1, out)
  1178  	}
  1179  
  1180  	outA, err := state.AllocByID(alloc1.ID)
  1181  	if err != nil {
  1182  		t.Fatalf("err: %v", err)
  1183  	}
  1184  
  1185  	if out != nil {
  1186  		t.Fatalf("bad: %#v %#v", alloc1, outA)
  1187  	}
  1188  
  1189  	outA, err = state.AllocByID(alloc2.ID)
  1190  	if err != nil {
  1191  		t.Fatalf("err: %v", err)
  1192  	}
  1193  
  1194  	if out != nil {
  1195  		t.Fatalf("bad: %#v %#v", alloc1, outA)
  1196  	}
  1197  
  1198  	index, err := state.Index("evals")
  1199  	if err != nil {
  1200  		t.Fatalf("err: %v", err)
  1201  	}
  1202  	if index != 1002 {
  1203  		t.Fatalf("bad: %d", index)
  1204  	}
  1205  
  1206  	index, err = state.Index("allocs")
  1207  	if err != nil {
  1208  		t.Fatalf("err: %v", err)
  1209  	}
  1210  	if index != 1002 {
  1211  		t.Fatalf("bad: %d", index)
  1212  	}
  1213  
  1214  	notify.verify(t)
  1215  }
  1216  
  1217  func TestStateStore_EvalsByJob(t *testing.T) {
  1218  	state := testStateStore(t)
  1219  
  1220  	eval1 := mock.Eval()
  1221  	eval2 := mock.Eval()
  1222  	eval2.JobID = eval1.JobID
  1223  	eval3 := mock.Eval()
  1224  	evals := []*structs.Evaluation{eval1, eval2}
  1225  
  1226  	err := state.UpsertEvals(1000, evals)
  1227  	if err != nil {
  1228  		t.Fatalf("err: %v", err)
  1229  	}
  1230  	err = state.UpsertEvals(1001, []*structs.Evaluation{eval3})
  1231  	if err != nil {
  1232  		t.Fatalf("err: %v", err)
  1233  	}
  1234  
  1235  	out, err := state.EvalsByJob(eval1.JobID)
  1236  	if err != nil {
  1237  		t.Fatalf("err: %v", err)
  1238  	}
  1239  
  1240  	sort.Sort(EvalIDSort(evals))
  1241  	sort.Sort(EvalIDSort(out))
  1242  
  1243  	if !reflect.DeepEqual(evals, out) {
  1244  		t.Fatalf("bad: %#v %#v", evals, out)
  1245  	}
  1246  }
  1247  
  1248  func TestStateStore_Evals(t *testing.T) {
  1249  	state := testStateStore(t)
  1250  	var evals []*structs.Evaluation
  1251  
  1252  	for i := 0; i < 10; i++ {
  1253  		eval := mock.Eval()
  1254  		evals = append(evals, eval)
  1255  
  1256  		err := state.UpsertEvals(1000+uint64(i), []*structs.Evaluation{eval})
  1257  		if err != nil {
  1258  			t.Fatalf("err: %v", err)
  1259  		}
  1260  	}
  1261  
  1262  	iter, err := state.Evals()
  1263  	if err != nil {
  1264  		t.Fatalf("err: %v", err)
  1265  	}
  1266  
  1267  	var out []*structs.Evaluation
  1268  	for {
  1269  		raw := iter.Next()
  1270  		if raw == nil {
  1271  			break
  1272  		}
  1273  		out = append(out, raw.(*structs.Evaluation))
  1274  	}
  1275  
  1276  	sort.Sort(EvalIDSort(evals))
  1277  	sort.Sort(EvalIDSort(out))
  1278  
  1279  	if !reflect.DeepEqual(evals, out) {
  1280  		t.Fatalf("bad: %#v %#v", evals, out)
  1281  	}
  1282  }
  1283  
  1284  func TestStateStore_EvalsByIDPrefix(t *testing.T) {
  1285  	state := testStateStore(t)
  1286  	var evals []*structs.Evaluation
  1287  
  1288  	ids := []string{
  1289  		"aaaaaaaa-7bfb-395d-eb95-0685af2176b2",
  1290  		"aaaaaaab-7bfb-395d-eb95-0685af2176b2",
  1291  		"aaaaaabb-7bfb-395d-eb95-0685af2176b2",
  1292  		"aaaaabbb-7bfb-395d-eb95-0685af2176b2",
  1293  		"aaaabbbb-7bfb-395d-eb95-0685af2176b2",
  1294  		"aaabbbbb-7bfb-395d-eb95-0685af2176b2",
  1295  		"aabbbbbb-7bfb-395d-eb95-0685af2176b2",
  1296  		"abbbbbbb-7bfb-395d-eb95-0685af2176b2",
  1297  		"bbbbbbbb-7bfb-395d-eb95-0685af2176b2",
  1298  	}
  1299  	for i := 0; i < 9; i++ {
  1300  		eval := mock.Eval()
  1301  		eval.ID = ids[i]
  1302  		evals = append(evals, eval)
  1303  	}
  1304  
  1305  	err := state.UpsertEvals(1000, evals)
  1306  	if err != nil {
  1307  		t.Fatalf("err: %v", err)
  1308  	}
  1309  
  1310  	iter, err := state.EvalsByIDPrefix("aaaa")
  1311  	if err != nil {
  1312  		t.Fatalf("err: %v", err)
  1313  	}
  1314  
  1315  	gatherEvals := func(iter memdb.ResultIterator) []*structs.Evaluation {
  1316  		var evals []*structs.Evaluation
  1317  		for {
  1318  			raw := iter.Next()
  1319  			if raw == nil {
  1320  				break
  1321  			}
  1322  			evals = append(evals, raw.(*structs.Evaluation))
  1323  		}
  1324  		return evals
  1325  	}
  1326  
  1327  	out := gatherEvals(iter)
  1328  	if len(out) != 5 {
  1329  		t.Fatalf("bad: expected five evaluations, got: %#v", out)
  1330  	}
  1331  
  1332  	sort.Sort(EvalIDSort(evals))
  1333  
  1334  	for index, eval := range out {
  1335  		if ids[index] != eval.ID {
  1336  			t.Fatalf("bad: got unexpected id: %s", eval.ID)
  1337  		}
  1338  	}
  1339  
  1340  	iter, err = state.EvalsByIDPrefix("b-a7bfb")
  1341  	if err != nil {
  1342  		t.Fatalf("err: %v", err)
  1343  	}
  1344  
  1345  	out = gatherEvals(iter)
  1346  	if len(out) != 0 {
  1347  		t.Fatalf("bad: unexpected zero evaluations, got: %#v", out)
  1348  	}
  1349  
  1350  }
  1351  
  1352  func TestStateStore_RestoreEval(t *testing.T) {
  1353  	state := testStateStore(t)
  1354  	eval := mock.Eval()
  1355  
  1356  	notify := setupNotifyTest(
  1357  		state,
  1358  		watch.Item{Table: "evals"},
  1359  		watch.Item{Eval: eval.ID})
  1360  
  1361  	restore, err := state.Restore()
  1362  	if err != nil {
  1363  		t.Fatalf("err: %v", err)
  1364  	}
  1365  
  1366  	err = restore.EvalRestore(eval)
  1367  	if err != nil {
  1368  		t.Fatalf("err: %v", err)
  1369  	}
  1370  	restore.Commit()
  1371  
  1372  	out, err := state.EvalByID(eval.ID)
  1373  	if err != nil {
  1374  		t.Fatalf("err: %v", err)
  1375  	}
  1376  
  1377  	if !reflect.DeepEqual(out, eval) {
  1378  		t.Fatalf("Bad: %#v %#v", out, eval)
  1379  	}
  1380  
  1381  	notify.verify(t)
  1382  }
  1383  
  1384  func TestStateStore_UpdateAllocsFromClient(t *testing.T) {
  1385  	state := testStateStore(t)
  1386  	alloc := mock.Alloc()
  1387  	alloc2 := mock.Alloc()
  1388  
  1389  	notify := setupNotifyTest(
  1390  		state,
  1391  		watch.Item{Table: "allocs"},
  1392  		watch.Item{Alloc: alloc.ID},
  1393  		watch.Item{AllocEval: alloc.EvalID},
  1394  		watch.Item{AllocJob: alloc.JobID},
  1395  		watch.Item{AllocNode: alloc.NodeID},
  1396  		watch.Item{Alloc: alloc2.ID},
  1397  		watch.Item{AllocEval: alloc2.EvalID},
  1398  		watch.Item{AllocJob: alloc2.JobID},
  1399  		watch.Item{AllocNode: alloc2.NodeID})
  1400  
  1401  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc, alloc2})
  1402  	if err != nil {
  1403  		t.Fatalf("err: %v", err)
  1404  	}
  1405  
  1406  	// Create the delta updates
  1407  	update := &structs.Allocation{
  1408  		ID:           alloc.ID,
  1409  		ClientStatus: structs.AllocClientStatusFailed,
  1410  		TaskStates: map[string]*structs.TaskState{
  1411  			"web": &structs.TaskState{
  1412  				State: structs.TaskStatePending,
  1413  			},
  1414  		},
  1415  	}
  1416  	update2 := &structs.Allocation{
  1417  		ID:           alloc2.ID,
  1418  		ClientStatus: structs.AllocClientStatusRunning,
  1419  		TaskStates: map[string]*structs.TaskState{
  1420  			"web": &structs.TaskState{
  1421  				State: structs.TaskStatePending,
  1422  			},
  1423  		},
  1424  	}
  1425  
  1426  	err = state.UpdateAllocsFromClient(1001, []*structs.Allocation{update, update2})
  1427  	if err != nil {
  1428  		t.Fatalf("err: %v", err)
  1429  	}
  1430  
  1431  	out, err := state.AllocByID(alloc.ID)
  1432  	if err != nil {
  1433  		t.Fatalf("err: %v", err)
  1434  	}
  1435  
  1436  	alloc.CreateIndex = 1000
  1437  	alloc.ModifyIndex = 1001
  1438  	alloc.ClientStatus = structs.AllocClientStatusFailed
  1439  	if !reflect.DeepEqual(alloc, out) {
  1440  		t.Fatalf("bad: %#v %#v", alloc, out)
  1441  	}
  1442  
  1443  	out, err = state.AllocByID(alloc2.ID)
  1444  	if err != nil {
  1445  		t.Fatalf("err: %v", err)
  1446  	}
  1447  
  1448  	alloc2.ModifyIndex = 1000
  1449  	alloc2.ModifyIndex = 1001
  1450  	alloc2.ClientStatus = structs.AllocClientStatusRunning
  1451  	if !reflect.DeepEqual(alloc2, out) {
  1452  		t.Fatalf("bad: %#v %#v", alloc2, out)
  1453  	}
  1454  
  1455  	index, err := state.Index("allocs")
  1456  	if err != nil {
  1457  		t.Fatalf("err: %v", err)
  1458  	}
  1459  	if index != 1001 {
  1460  		t.Fatalf("bad: %d", index)
  1461  	}
  1462  
  1463  	notify.verify(t)
  1464  }
  1465  
  1466  func TestStateStore_UpsertAlloc_Alloc(t *testing.T) {
  1467  	state := testStateStore(t)
  1468  	alloc := mock.Alloc()
  1469  
  1470  	notify := setupNotifyTest(
  1471  		state,
  1472  		watch.Item{Table: "allocs"},
  1473  		watch.Item{Alloc: alloc.ID},
  1474  		watch.Item{AllocEval: alloc.EvalID},
  1475  		watch.Item{AllocJob: alloc.JobID},
  1476  		watch.Item{AllocNode: alloc.NodeID})
  1477  
  1478  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  1479  	if err != nil {
  1480  		t.Fatalf("err: %v", err)
  1481  	}
  1482  
  1483  	out, err := state.AllocByID(alloc.ID)
  1484  	if err != nil {
  1485  		t.Fatalf("err: %v", err)
  1486  	}
  1487  
  1488  	if !reflect.DeepEqual(alloc, out) {
  1489  		t.Fatalf("bad: %#v %#v", alloc, out)
  1490  	}
  1491  
  1492  	index, err := state.Index("allocs")
  1493  	if err != nil {
  1494  		t.Fatalf("err: %v", err)
  1495  	}
  1496  	if index != 1000 {
  1497  		t.Fatalf("bad: %d", index)
  1498  	}
  1499  
  1500  	notify.verify(t)
  1501  }
  1502  
  1503  func TestStateStore_UpdateAlloc_Alloc(t *testing.T) {
  1504  	state := testStateStore(t)
  1505  	alloc := mock.Alloc()
  1506  
  1507  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  1508  	if err != nil {
  1509  		t.Fatalf("err: %v", err)
  1510  	}
  1511  
  1512  	alloc2 := mock.Alloc()
  1513  	alloc2.ID = alloc.ID
  1514  	alloc2.NodeID = alloc.NodeID + ".new"
  1515  
  1516  	notify := setupNotifyTest(
  1517  		state,
  1518  		watch.Item{Table: "allocs"},
  1519  		watch.Item{Alloc: alloc2.ID},
  1520  		watch.Item{AllocEval: alloc2.EvalID},
  1521  		watch.Item{AllocJob: alloc2.JobID},
  1522  		watch.Item{AllocNode: alloc2.NodeID})
  1523  
  1524  	err = state.UpsertAllocs(1001, []*structs.Allocation{alloc2})
  1525  	if err != nil {
  1526  		t.Fatalf("err: %v", err)
  1527  	}
  1528  
  1529  	out, err := state.AllocByID(alloc.ID)
  1530  	if err != nil {
  1531  		t.Fatalf("err: %v", err)
  1532  	}
  1533  
  1534  	if !reflect.DeepEqual(alloc2, out) {
  1535  		t.Fatalf("bad: %#v %#v", alloc2, out)
  1536  	}
  1537  
  1538  	if out.CreateIndex != 1000 {
  1539  		t.Fatalf("bad: %#v", out)
  1540  	}
  1541  	if out.ModifyIndex != 1001 {
  1542  		t.Fatalf("bad: %#v", out)
  1543  	}
  1544  
  1545  	index, err := state.Index("allocs")
  1546  	if err != nil {
  1547  		t.Fatalf("err: %v", err)
  1548  	}
  1549  	if index != 1001 {
  1550  		t.Fatalf("bad: %d", index)
  1551  	}
  1552  
  1553  	notify.verify(t)
  1554  }
  1555  
  1556  func TestStateStore_EvictAlloc_Alloc(t *testing.T) {
  1557  	state := testStateStore(t)
  1558  	alloc := mock.Alloc()
  1559  
  1560  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  1561  	if err != nil {
  1562  		t.Fatalf("err: %v", err)
  1563  	}
  1564  
  1565  	alloc2 := new(structs.Allocation)
  1566  	*alloc2 = *alloc
  1567  	alloc2.DesiredStatus = structs.AllocDesiredStatusEvict
  1568  	err = state.UpsertAllocs(1001, []*structs.Allocation{alloc2})
  1569  	if err != nil {
  1570  		t.Fatalf("err: %v", err)
  1571  	}
  1572  
  1573  	out, err := state.AllocByID(alloc.ID)
  1574  	if err != nil {
  1575  		t.Fatalf("err: %v", err)
  1576  	}
  1577  
  1578  	if out.DesiredStatus != structs.AllocDesiredStatusEvict {
  1579  		t.Fatalf("bad: %#v %#v", alloc, out)
  1580  	}
  1581  
  1582  	index, err := state.Index("allocs")
  1583  	if err != nil {
  1584  		t.Fatalf("err: %v", err)
  1585  	}
  1586  	if index != 1001 {
  1587  		t.Fatalf("bad: %d", index)
  1588  	}
  1589  }
  1590  
  1591  func TestStateStore_AllocsByNode(t *testing.T) {
  1592  	state := testStateStore(t)
  1593  	var allocs []*structs.Allocation
  1594  
  1595  	for i := 0; i < 10; i++ {
  1596  		alloc := mock.Alloc()
  1597  		alloc.NodeID = "foo"
  1598  		allocs = append(allocs, alloc)
  1599  	}
  1600  
  1601  	err := state.UpsertAllocs(1000, allocs)
  1602  	if err != nil {
  1603  		t.Fatalf("err: %v", err)
  1604  	}
  1605  
  1606  	out, err := state.AllocsByNode("foo")
  1607  	if err != nil {
  1608  		t.Fatalf("err: %v", err)
  1609  	}
  1610  
  1611  	sort.Sort(AllocIDSort(allocs))
  1612  	sort.Sort(AllocIDSort(out))
  1613  
  1614  	if !reflect.DeepEqual(allocs, out) {
  1615  		t.Fatalf("bad: %#v %#v", allocs, out)
  1616  	}
  1617  }
  1618  
  1619  func TestStateStore_AllocsByNodeTerminal(t *testing.T) {
  1620  	state := testStateStore(t)
  1621  	var allocs, term, nonterm []*structs.Allocation
  1622  
  1623  	for i := 0; i < 10; i++ {
  1624  		alloc := mock.Alloc()
  1625  		alloc.NodeID = "foo"
  1626  		if i%2 == 0 {
  1627  			alloc.DesiredStatus = structs.AllocDesiredStatusStop
  1628  			term = append(term, alloc)
  1629  		} else {
  1630  			nonterm = append(nonterm, alloc)
  1631  		}
  1632  		allocs = append(allocs, alloc)
  1633  	}
  1634  
  1635  	err := state.UpsertAllocs(1000, allocs)
  1636  	if err != nil {
  1637  		t.Fatalf("err: %v", err)
  1638  	}
  1639  
  1640  	// Verify the terminal allocs
  1641  	out, err := state.AllocsByNodeTerminal("foo", true)
  1642  	if err != nil {
  1643  		t.Fatalf("err: %v", err)
  1644  	}
  1645  
  1646  	sort.Sort(AllocIDSort(term))
  1647  	sort.Sort(AllocIDSort(out))
  1648  
  1649  	if !reflect.DeepEqual(term, out) {
  1650  		t.Fatalf("bad: %#v %#v", term, out)
  1651  	}
  1652  
  1653  	// Verify the non-terminal allocs
  1654  	out, err = state.AllocsByNodeTerminal("foo", false)
  1655  	if err != nil {
  1656  		t.Fatalf("err: %v", err)
  1657  	}
  1658  
  1659  	sort.Sort(AllocIDSort(nonterm))
  1660  	sort.Sort(AllocIDSort(out))
  1661  
  1662  	if !reflect.DeepEqual(nonterm, out) {
  1663  		t.Fatalf("bad: %#v %#v", nonterm, out)
  1664  	}
  1665  }
  1666  
  1667  func TestStateStore_AllocsByJob(t *testing.T) {
  1668  	state := testStateStore(t)
  1669  	var allocs []*structs.Allocation
  1670  
  1671  	for i := 0; i < 10; i++ {
  1672  		alloc := mock.Alloc()
  1673  		alloc.JobID = "foo"
  1674  		allocs = append(allocs, alloc)
  1675  	}
  1676  
  1677  	err := state.UpsertAllocs(1000, allocs)
  1678  	if err != nil {
  1679  		t.Fatalf("err: %v", err)
  1680  	}
  1681  
  1682  	out, err := state.AllocsByJob("foo")
  1683  	if err != nil {
  1684  		t.Fatalf("err: %v", err)
  1685  	}
  1686  
  1687  	sort.Sort(AllocIDSort(allocs))
  1688  	sort.Sort(AllocIDSort(out))
  1689  
  1690  	if !reflect.DeepEqual(allocs, out) {
  1691  		t.Fatalf("bad: %#v %#v", allocs, out)
  1692  	}
  1693  }
  1694  
  1695  func TestStateStore_AllocsByIDPrefix(t *testing.T) {
  1696  	state := testStateStore(t)
  1697  	var allocs []*structs.Allocation
  1698  
  1699  	ids := []string{
  1700  		"aaaaaaaa-7bfb-395d-eb95-0685af2176b2",
  1701  		"aaaaaaab-7bfb-395d-eb95-0685af2176b2",
  1702  		"aaaaaabb-7bfb-395d-eb95-0685af2176b2",
  1703  		"aaaaabbb-7bfb-395d-eb95-0685af2176b2",
  1704  		"aaaabbbb-7bfb-395d-eb95-0685af2176b2",
  1705  		"aaabbbbb-7bfb-395d-eb95-0685af2176b2",
  1706  		"aabbbbbb-7bfb-395d-eb95-0685af2176b2",
  1707  		"abbbbbbb-7bfb-395d-eb95-0685af2176b2",
  1708  		"bbbbbbbb-7bfb-395d-eb95-0685af2176b2",
  1709  	}
  1710  	for i := 0; i < 9; i++ {
  1711  		alloc := mock.Alloc()
  1712  		alloc.ID = ids[i]
  1713  		allocs = append(allocs, alloc)
  1714  	}
  1715  
  1716  	err := state.UpsertAllocs(1000, allocs)
  1717  	if err != nil {
  1718  		t.Fatalf("err: %v", err)
  1719  	}
  1720  
  1721  	iter, err := state.AllocsByIDPrefix("aaaa")
  1722  	if err != nil {
  1723  		t.Fatalf("err: %v", err)
  1724  	}
  1725  
  1726  	gatherAllocs := func(iter memdb.ResultIterator) []*structs.Allocation {
  1727  		var allocs []*structs.Allocation
  1728  		for {
  1729  			raw := iter.Next()
  1730  			if raw == nil {
  1731  				break
  1732  			}
  1733  			allocs = append(allocs, raw.(*structs.Allocation))
  1734  		}
  1735  		return allocs
  1736  	}
  1737  
  1738  	out := gatherAllocs(iter)
  1739  	if len(out) != 5 {
  1740  		t.Fatalf("bad: expected five allocations, got: %#v", out)
  1741  	}
  1742  
  1743  	sort.Sort(AllocIDSort(allocs))
  1744  
  1745  	for index, alloc := range out {
  1746  		if ids[index] != alloc.ID {
  1747  			t.Fatalf("bad: got unexpected id: %s", alloc.ID)
  1748  		}
  1749  	}
  1750  
  1751  	iter, err = state.AllocsByIDPrefix("b-a7bfb")
  1752  	if err != nil {
  1753  		t.Fatalf("err: %v", err)
  1754  	}
  1755  
  1756  	out = gatherAllocs(iter)
  1757  	if len(out) != 0 {
  1758  		t.Fatalf("bad: unexpected zero allocations, got: %#v", out)
  1759  	}
  1760  }
  1761  
  1762  func TestStateStore_Allocs(t *testing.T) {
  1763  	state := testStateStore(t)
  1764  	var allocs []*structs.Allocation
  1765  
  1766  	for i := 0; i < 10; i++ {
  1767  		alloc := mock.Alloc()
  1768  		allocs = append(allocs, alloc)
  1769  	}
  1770  
  1771  	err := state.UpsertAllocs(1000, allocs)
  1772  	if err != nil {
  1773  		t.Fatalf("err: %v", err)
  1774  	}
  1775  
  1776  	iter, err := state.Allocs()
  1777  	if err != nil {
  1778  		t.Fatalf("err: %v", err)
  1779  	}
  1780  
  1781  	var out []*structs.Allocation
  1782  	for {
  1783  		raw := iter.Next()
  1784  		if raw == nil {
  1785  			break
  1786  		}
  1787  		out = append(out, raw.(*structs.Allocation))
  1788  	}
  1789  
  1790  	sort.Sort(AllocIDSort(allocs))
  1791  	sort.Sort(AllocIDSort(out))
  1792  
  1793  	if !reflect.DeepEqual(allocs, out) {
  1794  		t.Fatalf("bad: %#v %#v", allocs, out)
  1795  	}
  1796  }
  1797  
  1798  func TestStateStore_RestoreAlloc(t *testing.T) {
  1799  	state := testStateStore(t)
  1800  	alloc := mock.Alloc()
  1801  
  1802  	notify := setupNotifyTest(
  1803  		state,
  1804  		watch.Item{Table: "allocs"},
  1805  		watch.Item{Alloc: alloc.ID},
  1806  		watch.Item{AllocEval: alloc.EvalID},
  1807  		watch.Item{AllocJob: alloc.JobID},
  1808  		watch.Item{AllocNode: alloc.NodeID})
  1809  
  1810  	restore, err := state.Restore()
  1811  	if err != nil {
  1812  		t.Fatalf("err: %v", err)
  1813  	}
  1814  
  1815  	err = restore.AllocRestore(alloc)
  1816  	if err != nil {
  1817  		t.Fatalf("err: %v", err)
  1818  	}
  1819  
  1820  	restore.Commit()
  1821  
  1822  	out, err := state.AllocByID(alloc.ID)
  1823  	if err != nil {
  1824  		t.Fatalf("err: %v", err)
  1825  	}
  1826  
  1827  	if !reflect.DeepEqual(out, alloc) {
  1828  		t.Fatalf("Bad: %#v %#v", out, alloc)
  1829  	}
  1830  
  1831  	notify.verify(t)
  1832  }
  1833  
  1834  func TestStateStore_SetJobStatus_ForceStatus(t *testing.T) {
  1835  	state := testStateStore(t)
  1836  	watcher := watch.NewItems()
  1837  	txn := state.db.Txn(true)
  1838  
  1839  	// Create and insert a mock job.
  1840  	job := mock.Job()
  1841  	job.Status = ""
  1842  	job.ModifyIndex = 0
  1843  	if err := txn.Insert("jobs", job); err != nil {
  1844  		t.Fatalf("job insert failed: %v", err)
  1845  	}
  1846  
  1847  	exp := "foobar"
  1848  	index := uint64(1000)
  1849  	if err := state.setJobStatus(index, watcher, txn, job, false, exp); err != nil {
  1850  		t.Fatalf("setJobStatus() failed: %v", err)
  1851  	}
  1852  
  1853  	i, err := txn.First("jobs", "id", job.ID)
  1854  	if err != nil {
  1855  		t.Fatalf("job lookup failed: %v", err)
  1856  	}
  1857  	updated := i.(*structs.Job)
  1858  
  1859  	if updated.Status != exp {
  1860  		t.Fatalf("setJobStatus() set %v; expected %v", updated.Status, exp)
  1861  	}
  1862  
  1863  	if updated.ModifyIndex != index {
  1864  		t.Fatalf("setJobStatus() set %d; expected %d", updated.ModifyIndex, index)
  1865  	}
  1866  }
  1867  
  1868  func TestStateStore_SetJobStatus_NoOp(t *testing.T) {
  1869  	state := testStateStore(t)
  1870  	watcher := watch.NewItems()
  1871  	txn := state.db.Txn(true)
  1872  
  1873  	// Create and insert a mock job that should be pending.
  1874  	job := mock.Job()
  1875  	job.Status = structs.JobStatusPending
  1876  	job.ModifyIndex = 10
  1877  	if err := txn.Insert("jobs", job); err != nil {
  1878  		t.Fatalf("job insert failed: %v", err)
  1879  	}
  1880  
  1881  	index := uint64(1000)
  1882  	if err := state.setJobStatus(index, watcher, txn, job, false, ""); err != nil {
  1883  		t.Fatalf("setJobStatus() failed: %v", err)
  1884  	}
  1885  
  1886  	i, err := txn.First("jobs", "id", job.ID)
  1887  	if err != nil {
  1888  		t.Fatalf("job lookup failed: %v", err)
  1889  	}
  1890  	updated := i.(*structs.Job)
  1891  
  1892  	if updated.ModifyIndex == index {
  1893  		t.Fatalf("setJobStatus() should have been a no-op")
  1894  	}
  1895  }
  1896  
  1897  func TestStateStore_SetJobStatus(t *testing.T) {
  1898  	state := testStateStore(t)
  1899  	watcher := watch.NewItems()
  1900  	txn := state.db.Txn(true)
  1901  
  1902  	// Create and insert a mock job that should be pending but has an incorrect
  1903  	// status.
  1904  	job := mock.Job()
  1905  	job.Status = "foobar"
  1906  	job.ModifyIndex = 10
  1907  	if err := txn.Insert("jobs", job); err != nil {
  1908  		t.Fatalf("job insert failed: %v", err)
  1909  	}
  1910  
  1911  	index := uint64(1000)
  1912  	if err := state.setJobStatus(index, watcher, txn, job, false, ""); err != nil {
  1913  		t.Fatalf("setJobStatus() failed: %v", err)
  1914  	}
  1915  
  1916  	i, err := txn.First("jobs", "id", job.ID)
  1917  	if err != nil {
  1918  		t.Fatalf("job lookup failed: %v", err)
  1919  	}
  1920  	updated := i.(*structs.Job)
  1921  
  1922  	if updated.Status != structs.JobStatusPending {
  1923  		t.Fatalf("setJobStatus() set %v; expected %v", updated.Status, structs.JobStatusPending)
  1924  	}
  1925  
  1926  	if updated.ModifyIndex != index {
  1927  		t.Fatalf("setJobStatus() set %d; expected %d", updated.ModifyIndex, index)
  1928  	}
  1929  }
  1930  
  1931  func TestStateStore_GetJobStatus_NoEvalsOrAllocs(t *testing.T) {
  1932  	job := mock.Job()
  1933  	state := testStateStore(t)
  1934  	txn := state.db.Txn(false)
  1935  	status, err := state.getJobStatus(txn, job, false)
  1936  	if err != nil {
  1937  		t.Fatalf("getJobStatus() failed: %v", err)
  1938  	}
  1939  
  1940  	if status != structs.JobStatusPending {
  1941  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusPending)
  1942  	}
  1943  }
  1944  
  1945  func TestStateStore_GetJobStatus_NoEvalsOrAllocs_Periodic(t *testing.T) {
  1946  	job := mock.PeriodicJob()
  1947  	state := testStateStore(t)
  1948  	txn := state.db.Txn(false)
  1949  	status, err := state.getJobStatus(txn, job, false)
  1950  	if err != nil {
  1951  		t.Fatalf("getJobStatus() failed: %v", err)
  1952  	}
  1953  
  1954  	if status != structs.JobStatusRunning {
  1955  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusRunning)
  1956  	}
  1957  }
  1958  
  1959  func TestStateStore_GetJobStatus_NoEvalsOrAllocs_EvalDelete(t *testing.T) {
  1960  	job := mock.Job()
  1961  	state := testStateStore(t)
  1962  	txn := state.db.Txn(false)
  1963  	status, err := state.getJobStatus(txn, job, true)
  1964  	if err != nil {
  1965  		t.Fatalf("getJobStatus() failed: %v", err)
  1966  	}
  1967  
  1968  	if status != structs.JobStatusDead {
  1969  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusDead)
  1970  	}
  1971  }
  1972  
  1973  func TestStateStore_GetJobStatus_DeadEvalsAndAllocs(t *testing.T) {
  1974  	state := testStateStore(t)
  1975  	job := mock.Job()
  1976  
  1977  	// Create a mock alloc that is dead.
  1978  	alloc := mock.Alloc()
  1979  	alloc.JobID = job.ID
  1980  	alloc.DesiredStatus = structs.AllocDesiredStatusFailed
  1981  	if err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}); err != nil {
  1982  		t.Fatalf("err: %v", err)
  1983  	}
  1984  
  1985  	// Create a mock eval that is complete
  1986  	eval := mock.Eval()
  1987  	eval.JobID = job.ID
  1988  	eval.Status = structs.EvalStatusComplete
  1989  	if err := state.UpsertEvals(1001, []*structs.Evaluation{eval}); err != nil {
  1990  		t.Fatalf("err: %v", err)
  1991  	}
  1992  
  1993  	txn := state.db.Txn(false)
  1994  	status, err := state.getJobStatus(txn, job, false)
  1995  	if err != nil {
  1996  		t.Fatalf("getJobStatus() failed: %v", err)
  1997  	}
  1998  
  1999  	if status != structs.JobStatusDead {
  2000  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusDead)
  2001  	}
  2002  }
  2003  
  2004  func TestStateStore_GetJobStatus_RunningAlloc(t *testing.T) {
  2005  	state := testStateStore(t)
  2006  	job := mock.Job()
  2007  
  2008  	// Create a mock alloc that is running.
  2009  	alloc := mock.Alloc()
  2010  	alloc.JobID = job.ID
  2011  	alloc.DesiredStatus = structs.AllocDesiredStatusRun
  2012  	if err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}); err != nil {
  2013  		t.Fatalf("err: %v", err)
  2014  	}
  2015  
  2016  	txn := state.db.Txn(false)
  2017  	status, err := state.getJobStatus(txn, job, true)
  2018  	if err != nil {
  2019  		t.Fatalf("getJobStatus() failed: %v", err)
  2020  	}
  2021  
  2022  	if status != structs.JobStatusRunning {
  2023  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusRunning)
  2024  	}
  2025  }
  2026  
  2027  func TestStateStore_SetJobStatus_PendingEval(t *testing.T) {
  2028  	state := testStateStore(t)
  2029  	job := mock.Job()
  2030  
  2031  	// Create a mock eval that is pending.
  2032  	eval := mock.Eval()
  2033  	eval.JobID = job.ID
  2034  	eval.Status = structs.EvalStatusPending
  2035  	if err := state.UpsertEvals(1000, []*structs.Evaluation{eval}); err != nil {
  2036  		t.Fatalf("err: %v", err)
  2037  	}
  2038  
  2039  	txn := state.db.Txn(false)
  2040  	status, err := state.getJobStatus(txn, job, true)
  2041  	if err != nil {
  2042  		t.Fatalf("getJobStatus() failed: %v", err)
  2043  	}
  2044  
  2045  	if status != structs.JobStatusPending {
  2046  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusPending)
  2047  	}
  2048  }
  2049  
  2050  func TestStateWatch_watch(t *testing.T) {
  2051  	sw := newStateWatch()
  2052  	notify1 := make(chan struct{}, 1)
  2053  	notify2 := make(chan struct{}, 1)
  2054  	notify3 := make(chan struct{}, 1)
  2055  
  2056  	// Notifications trigger subscribed channels
  2057  	sw.watch(watch.NewItems(watch.Item{Table: "foo"}), notify1)
  2058  	sw.watch(watch.NewItems(watch.Item{Table: "bar"}), notify2)
  2059  	sw.watch(watch.NewItems(watch.Item{Table: "baz"}), notify3)
  2060  
  2061  	items := watch.NewItems()
  2062  	items.Add(watch.Item{Table: "foo"})
  2063  	items.Add(watch.Item{Table: "bar"})
  2064  
  2065  	sw.notify(items)
  2066  	if len(notify1) != 1 {
  2067  		t.Fatalf("should notify")
  2068  	}
  2069  	if len(notify2) != 1 {
  2070  		t.Fatalf("should notify")
  2071  	}
  2072  	if len(notify3) != 0 {
  2073  		t.Fatalf("should not notify")
  2074  	}
  2075  }
  2076  
  2077  func TestStateWatch_stopWatch(t *testing.T) {
  2078  	sw := newStateWatch()
  2079  	notify := make(chan struct{})
  2080  
  2081  	// First subscribe
  2082  	sw.watch(watch.NewItems(watch.Item{Table: "foo"}), notify)
  2083  
  2084  	// Unsubscribe stop notifications
  2085  	sw.stopWatch(watch.NewItems(watch.Item{Table: "foo"}), notify)
  2086  
  2087  	// Check that the group was removed
  2088  	if _, ok := sw.items[watch.Item{Table: "foo"}]; ok {
  2089  		t.Fatalf("should remove group")
  2090  	}
  2091  
  2092  	// Check that we are not notified
  2093  	sw.notify(watch.NewItems(watch.Item{Table: "foo"}))
  2094  	if len(notify) != 0 {
  2095  		t.Fatalf("should not notify")
  2096  	}
  2097  }
  2098  
  2099  // setupNotifyTest takes a state store and a set of watch items, then creates
  2100  // and subscribes a notification channel for each item.
  2101  func setupNotifyTest(state *StateStore, items ...watch.Item) notifyTest {
  2102  	var n notifyTest
  2103  	for _, item := range items {
  2104  		ch := make(chan struct{}, 1)
  2105  		state.Watch(watch.NewItems(item), ch)
  2106  		n = append(n, &notifyTestCase{item, ch})
  2107  	}
  2108  	return n
  2109  }
  2110  
  2111  // notifyTestCase is used to set up and verify watch triggers.
  2112  type notifyTestCase struct {
  2113  	item watch.Item
  2114  	ch   chan struct{}
  2115  }
  2116  
  2117  // notifyTest is a suite of notifyTestCases.
  2118  type notifyTest []*notifyTestCase
  2119  
  2120  // verify ensures that each channel received a notification.
  2121  func (n notifyTest) verify(t *testing.T) {
  2122  	for _, tcase := range n {
  2123  		if len(tcase.ch) != 1 {
  2124  			t.Fatalf("should notify %#v", tcase.item)
  2125  		}
  2126  	}
  2127  }
  2128  
  2129  // NodeIDSort is used to sort nodes by ID
  2130  type NodeIDSort []*structs.Node
  2131  
  2132  func (n NodeIDSort) Len() int {
  2133  	return len(n)
  2134  }
  2135  
  2136  func (n NodeIDSort) Less(i, j int) bool {
  2137  	return n[i].ID < n[j].ID
  2138  }
  2139  
  2140  func (n NodeIDSort) Swap(i, j int) {
  2141  	n[i], n[j] = n[j], n[i]
  2142  }
  2143  
  2144  // JobIDis used to sort jobs by id
  2145  type JobIDSort []*structs.Job
  2146  
  2147  func (n JobIDSort) Len() int {
  2148  	return len(n)
  2149  }
  2150  
  2151  func (n JobIDSort) Less(i, j int) bool {
  2152  	return n[i].ID < n[j].ID
  2153  }
  2154  
  2155  func (n JobIDSort) Swap(i, j int) {
  2156  	n[i], n[j] = n[j], n[i]
  2157  }
  2158  
  2159  // EvalIDis used to sort evals by id
  2160  type EvalIDSort []*structs.Evaluation
  2161  
  2162  func (n EvalIDSort) Len() int {
  2163  	return len(n)
  2164  }
  2165  
  2166  func (n EvalIDSort) Less(i, j int) bool {
  2167  	return n[i].ID < n[j].ID
  2168  }
  2169  
  2170  func (n EvalIDSort) Swap(i, j int) {
  2171  	n[i], n[j] = n[j], n[i]
  2172  }
  2173  
  2174  // AllocIDsort used to sort allocations by id
  2175  type AllocIDSort []*structs.Allocation
  2176  
  2177  func (n AllocIDSort) Len() int {
  2178  	return len(n)
  2179  }
  2180  
  2181  func (n AllocIDSort) Less(i, j int) bool {
  2182  	return n[i].ID < n[j].ID
  2183  }
  2184  
  2185  func (n AllocIDSort) Swap(i, j int) {
  2186  	n[i], n[j] = n[j], n[i]
  2187  }