github.com/ryanslade/nomad@v0.2.4-0.20160128061903-fc95782f2089/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_UpdateAllocFromClient(t *testing.T) {
  1385  	state := testStateStore(t)
  1386  	alloc := mock.Alloc()
  1387  
  1388  	notify := setupNotifyTest(
  1389  		state,
  1390  		watch.Item{Table: "allocs"},
  1391  		watch.Item{Alloc: alloc.ID},
  1392  		watch.Item{AllocEval: alloc.EvalID},
  1393  		watch.Item{AllocJob: alloc.JobID},
  1394  		watch.Item{AllocNode: alloc.NodeID})
  1395  
  1396  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  1397  	if err != nil {
  1398  		t.Fatalf("err: %v", err)
  1399  	}
  1400  
  1401  	update := new(structs.Allocation)
  1402  	*update = *alloc
  1403  	update.ClientStatus = structs.AllocClientStatusFailed
  1404  
  1405  	err = state.UpdateAllocFromClient(1001, update)
  1406  	if err != nil {
  1407  		t.Fatalf("err: %v", err)
  1408  	}
  1409  
  1410  	out, err := state.AllocByID(alloc.ID)
  1411  	if err != nil {
  1412  		t.Fatalf("err: %v", err)
  1413  	}
  1414  
  1415  	update.ModifyIndex = 1001
  1416  	if !reflect.DeepEqual(update, out) {
  1417  		t.Fatalf("bad: %#v %#v", update, out)
  1418  	}
  1419  
  1420  	index, err := state.Index("allocs")
  1421  	if err != nil {
  1422  		t.Fatalf("err: %v", err)
  1423  	}
  1424  	if index != 1001 {
  1425  		t.Fatalf("bad: %d", index)
  1426  	}
  1427  
  1428  	notify.verify(t)
  1429  }
  1430  
  1431  func TestStateStore_UpsertAlloc_Alloc(t *testing.T) {
  1432  	state := testStateStore(t)
  1433  	alloc := mock.Alloc()
  1434  
  1435  	notify := setupNotifyTest(
  1436  		state,
  1437  		watch.Item{Table: "allocs"},
  1438  		watch.Item{Alloc: alloc.ID},
  1439  		watch.Item{AllocEval: alloc.EvalID},
  1440  		watch.Item{AllocJob: alloc.JobID},
  1441  		watch.Item{AllocNode: alloc.NodeID})
  1442  
  1443  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  1444  	if err != nil {
  1445  		t.Fatalf("err: %v", err)
  1446  	}
  1447  
  1448  	out, err := state.AllocByID(alloc.ID)
  1449  	if err != nil {
  1450  		t.Fatalf("err: %v", err)
  1451  	}
  1452  
  1453  	if !reflect.DeepEqual(alloc, out) {
  1454  		t.Fatalf("bad: %#v %#v", alloc, out)
  1455  	}
  1456  
  1457  	index, err := state.Index("allocs")
  1458  	if err != nil {
  1459  		t.Fatalf("err: %v", err)
  1460  	}
  1461  	if index != 1000 {
  1462  		t.Fatalf("bad: %d", index)
  1463  	}
  1464  
  1465  	notify.verify(t)
  1466  }
  1467  
  1468  func TestStateStore_UpdateAlloc_Alloc(t *testing.T) {
  1469  	state := testStateStore(t)
  1470  	alloc := mock.Alloc()
  1471  
  1472  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  1473  	if err != nil {
  1474  		t.Fatalf("err: %v", err)
  1475  	}
  1476  
  1477  	alloc2 := mock.Alloc()
  1478  	alloc2.ID = alloc.ID
  1479  	alloc2.NodeID = alloc.NodeID + ".new"
  1480  
  1481  	notify := setupNotifyTest(
  1482  		state,
  1483  		watch.Item{Table: "allocs"},
  1484  		watch.Item{Alloc: alloc2.ID},
  1485  		watch.Item{AllocEval: alloc2.EvalID},
  1486  		watch.Item{AllocJob: alloc2.JobID},
  1487  		watch.Item{AllocNode: alloc2.NodeID})
  1488  
  1489  	err = state.UpsertAllocs(1001, []*structs.Allocation{alloc2})
  1490  	if err != nil {
  1491  		t.Fatalf("err: %v", err)
  1492  	}
  1493  
  1494  	out, err := state.AllocByID(alloc.ID)
  1495  	if err != nil {
  1496  		t.Fatalf("err: %v", err)
  1497  	}
  1498  
  1499  	if !reflect.DeepEqual(alloc2, out) {
  1500  		t.Fatalf("bad: %#v %#v", alloc2, out)
  1501  	}
  1502  
  1503  	if out.CreateIndex != 1000 {
  1504  		t.Fatalf("bad: %#v", out)
  1505  	}
  1506  	if out.ModifyIndex != 1001 {
  1507  		t.Fatalf("bad: %#v", out)
  1508  	}
  1509  
  1510  	index, err := state.Index("allocs")
  1511  	if err != nil {
  1512  		t.Fatalf("err: %v", err)
  1513  	}
  1514  	if index != 1001 {
  1515  		t.Fatalf("bad: %d", index)
  1516  	}
  1517  
  1518  	notify.verify(t)
  1519  }
  1520  
  1521  func TestStateStore_EvictAlloc_Alloc(t *testing.T) {
  1522  	state := testStateStore(t)
  1523  	alloc := mock.Alloc()
  1524  
  1525  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  1526  	if err != nil {
  1527  		t.Fatalf("err: %v", err)
  1528  	}
  1529  
  1530  	alloc2 := new(structs.Allocation)
  1531  	*alloc2 = *alloc
  1532  	alloc2.DesiredStatus = structs.AllocDesiredStatusEvict
  1533  	err = state.UpsertAllocs(1001, []*structs.Allocation{alloc2})
  1534  	if err != nil {
  1535  		t.Fatalf("err: %v", err)
  1536  	}
  1537  
  1538  	out, err := state.AllocByID(alloc.ID)
  1539  	if err != nil {
  1540  		t.Fatalf("err: %v", err)
  1541  	}
  1542  
  1543  	if out.DesiredStatus != structs.AllocDesiredStatusEvict {
  1544  		t.Fatalf("bad: %#v %#v", alloc, out)
  1545  	}
  1546  
  1547  	index, err := state.Index("allocs")
  1548  	if err != nil {
  1549  		t.Fatalf("err: %v", err)
  1550  	}
  1551  	if index != 1001 {
  1552  		t.Fatalf("bad: %d", index)
  1553  	}
  1554  }
  1555  
  1556  func TestStateStore_AllocsByNode(t *testing.T) {
  1557  	state := testStateStore(t)
  1558  	var allocs []*structs.Allocation
  1559  
  1560  	for i := 0; i < 10; i++ {
  1561  		alloc := mock.Alloc()
  1562  		alloc.NodeID = "foo"
  1563  		allocs = append(allocs, alloc)
  1564  	}
  1565  
  1566  	err := state.UpsertAllocs(1000, allocs)
  1567  	if err != nil {
  1568  		t.Fatalf("err: %v", err)
  1569  	}
  1570  
  1571  	out, err := state.AllocsByNode("foo")
  1572  	if err != nil {
  1573  		t.Fatalf("err: %v", err)
  1574  	}
  1575  
  1576  	sort.Sort(AllocIDSort(allocs))
  1577  	sort.Sort(AllocIDSort(out))
  1578  
  1579  	if !reflect.DeepEqual(allocs, out) {
  1580  		t.Fatalf("bad: %#v %#v", allocs, out)
  1581  	}
  1582  }
  1583  
  1584  func TestStateStore_AllocsByJob(t *testing.T) {
  1585  	state := testStateStore(t)
  1586  	var allocs []*structs.Allocation
  1587  
  1588  	for i := 0; i < 10; i++ {
  1589  		alloc := mock.Alloc()
  1590  		alloc.JobID = "foo"
  1591  		allocs = append(allocs, alloc)
  1592  	}
  1593  
  1594  	err := state.UpsertAllocs(1000, allocs)
  1595  	if err != nil {
  1596  		t.Fatalf("err: %v", err)
  1597  	}
  1598  
  1599  	out, err := state.AllocsByJob("foo")
  1600  	if err != nil {
  1601  		t.Fatalf("err: %v", err)
  1602  	}
  1603  
  1604  	sort.Sort(AllocIDSort(allocs))
  1605  	sort.Sort(AllocIDSort(out))
  1606  
  1607  	if !reflect.DeepEqual(allocs, out) {
  1608  		t.Fatalf("bad: %#v %#v", allocs, out)
  1609  	}
  1610  }
  1611  
  1612  func TestStateStore_AllocsByIDPrefix(t *testing.T) {
  1613  	state := testStateStore(t)
  1614  	var allocs []*structs.Allocation
  1615  
  1616  	ids := []string{
  1617  		"aaaaaaaa-7bfb-395d-eb95-0685af2176b2",
  1618  		"aaaaaaab-7bfb-395d-eb95-0685af2176b2",
  1619  		"aaaaaabb-7bfb-395d-eb95-0685af2176b2",
  1620  		"aaaaabbb-7bfb-395d-eb95-0685af2176b2",
  1621  		"aaaabbbb-7bfb-395d-eb95-0685af2176b2",
  1622  		"aaabbbbb-7bfb-395d-eb95-0685af2176b2",
  1623  		"aabbbbbb-7bfb-395d-eb95-0685af2176b2",
  1624  		"abbbbbbb-7bfb-395d-eb95-0685af2176b2",
  1625  		"bbbbbbbb-7bfb-395d-eb95-0685af2176b2",
  1626  	}
  1627  	for i := 0; i < 9; i++ {
  1628  		alloc := mock.Alloc()
  1629  		alloc.ID = ids[i]
  1630  		allocs = append(allocs, alloc)
  1631  	}
  1632  
  1633  	err := state.UpsertAllocs(1000, allocs)
  1634  	if err != nil {
  1635  		t.Fatalf("err: %v", err)
  1636  	}
  1637  
  1638  	iter, err := state.AllocsByIDPrefix("aaaa")
  1639  	if err != nil {
  1640  		t.Fatalf("err: %v", err)
  1641  	}
  1642  
  1643  	gatherAllocs := func(iter memdb.ResultIterator) []*structs.Allocation {
  1644  		var allocs []*structs.Allocation
  1645  		for {
  1646  			raw := iter.Next()
  1647  			if raw == nil {
  1648  				break
  1649  			}
  1650  			allocs = append(allocs, raw.(*structs.Allocation))
  1651  		}
  1652  		return allocs
  1653  	}
  1654  
  1655  	out := gatherAllocs(iter)
  1656  	if len(out) != 5 {
  1657  		t.Fatalf("bad: expected five allocations, got: %#v", out)
  1658  	}
  1659  
  1660  	sort.Sort(AllocIDSort(allocs))
  1661  
  1662  	for index, alloc := range out {
  1663  		if ids[index] != alloc.ID {
  1664  			t.Fatalf("bad: got unexpected id: %s", alloc.ID)
  1665  		}
  1666  	}
  1667  
  1668  	iter, err = state.AllocsByIDPrefix("b-a7bfb")
  1669  	if err != nil {
  1670  		t.Fatalf("err: %v", err)
  1671  	}
  1672  
  1673  	out = gatherAllocs(iter)
  1674  	if len(out) != 0 {
  1675  		t.Fatalf("bad: unexpected zero allocations, got: %#v", out)
  1676  	}
  1677  }
  1678  
  1679  func TestStateStore_Allocs(t *testing.T) {
  1680  	state := testStateStore(t)
  1681  	var allocs []*structs.Allocation
  1682  
  1683  	for i := 0; i < 10; i++ {
  1684  		alloc := mock.Alloc()
  1685  		allocs = append(allocs, alloc)
  1686  	}
  1687  
  1688  	err := state.UpsertAllocs(1000, allocs)
  1689  	if err != nil {
  1690  		t.Fatalf("err: %v", err)
  1691  	}
  1692  
  1693  	iter, err := state.Allocs()
  1694  	if err != nil {
  1695  		t.Fatalf("err: %v", err)
  1696  	}
  1697  
  1698  	var out []*structs.Allocation
  1699  	for {
  1700  		raw := iter.Next()
  1701  		if raw == nil {
  1702  			break
  1703  		}
  1704  		out = append(out, raw.(*structs.Allocation))
  1705  	}
  1706  
  1707  	sort.Sort(AllocIDSort(allocs))
  1708  	sort.Sort(AllocIDSort(out))
  1709  
  1710  	if !reflect.DeepEqual(allocs, out) {
  1711  		t.Fatalf("bad: %#v %#v", allocs, out)
  1712  	}
  1713  }
  1714  
  1715  func TestStateStore_RestoreAlloc(t *testing.T) {
  1716  	state := testStateStore(t)
  1717  	alloc := mock.Alloc()
  1718  
  1719  	notify := setupNotifyTest(
  1720  		state,
  1721  		watch.Item{Table: "allocs"},
  1722  		watch.Item{Alloc: alloc.ID},
  1723  		watch.Item{AllocEval: alloc.EvalID},
  1724  		watch.Item{AllocJob: alloc.JobID},
  1725  		watch.Item{AllocNode: alloc.NodeID})
  1726  
  1727  	restore, err := state.Restore()
  1728  	if err != nil {
  1729  		t.Fatalf("err: %v", err)
  1730  	}
  1731  
  1732  	err = restore.AllocRestore(alloc)
  1733  	if err != nil {
  1734  		t.Fatalf("err: %v", err)
  1735  	}
  1736  
  1737  	restore.Commit()
  1738  
  1739  	out, err := state.AllocByID(alloc.ID)
  1740  	if err != nil {
  1741  		t.Fatalf("err: %v", err)
  1742  	}
  1743  
  1744  	if !reflect.DeepEqual(out, alloc) {
  1745  		t.Fatalf("Bad: %#v %#v", out, alloc)
  1746  	}
  1747  
  1748  	notify.verify(t)
  1749  }
  1750  
  1751  func TestStateStore_SetJobStatus_ForceStatus(t *testing.T) {
  1752  	state := testStateStore(t)
  1753  	watcher := watch.NewItems()
  1754  	txn := state.db.Txn(true)
  1755  
  1756  	// Create and insert a mock job.
  1757  	job := mock.Job()
  1758  	job.Status = ""
  1759  	job.ModifyIndex = 0
  1760  	if err := txn.Insert("jobs", job); err != nil {
  1761  		t.Fatalf("job insert failed: %v", err)
  1762  	}
  1763  
  1764  	exp := "foobar"
  1765  	index := uint64(1000)
  1766  	if err := state.setJobStatus(index, watcher, txn, job, false, exp); err != nil {
  1767  		t.Fatalf("setJobStatus() failed: %v", err)
  1768  	}
  1769  
  1770  	i, err := txn.First("jobs", "id", job.ID)
  1771  	if err != nil {
  1772  		t.Fatalf("job lookup failed: %v", err)
  1773  	}
  1774  	updated := i.(*structs.Job)
  1775  
  1776  	if updated.Status != exp {
  1777  		t.Fatalf("setJobStatus() set %v; expected %v", updated.Status, exp)
  1778  	}
  1779  
  1780  	if updated.ModifyIndex != index {
  1781  		t.Fatalf("setJobStatus() set %d; expected %d", updated.ModifyIndex, index)
  1782  	}
  1783  }
  1784  
  1785  func TestStateStore_SetJobStatus_NoOp(t *testing.T) {
  1786  	state := testStateStore(t)
  1787  	watcher := watch.NewItems()
  1788  	txn := state.db.Txn(true)
  1789  
  1790  	// Create and insert a mock job that should be pending.
  1791  	job := mock.Job()
  1792  	job.Status = structs.JobStatusPending
  1793  	job.ModifyIndex = 10
  1794  	if err := txn.Insert("jobs", job); err != nil {
  1795  		t.Fatalf("job insert failed: %v", err)
  1796  	}
  1797  
  1798  	index := uint64(1000)
  1799  	if err := state.setJobStatus(index, watcher, txn, job, false, ""); err != nil {
  1800  		t.Fatalf("setJobStatus() failed: %v", err)
  1801  	}
  1802  
  1803  	i, err := txn.First("jobs", "id", job.ID)
  1804  	if err != nil {
  1805  		t.Fatalf("job lookup failed: %v", err)
  1806  	}
  1807  	updated := i.(*structs.Job)
  1808  
  1809  	if updated.ModifyIndex == index {
  1810  		t.Fatalf("setJobStatus() should have been a no-op")
  1811  	}
  1812  }
  1813  
  1814  func TestStateStore_SetJobStatus(t *testing.T) {
  1815  	state := testStateStore(t)
  1816  	watcher := watch.NewItems()
  1817  	txn := state.db.Txn(true)
  1818  
  1819  	// Create and insert a mock job that should be pending but has an incorrect
  1820  	// status.
  1821  	job := mock.Job()
  1822  	job.Status = "foobar"
  1823  	job.ModifyIndex = 10
  1824  	if err := txn.Insert("jobs", job); err != nil {
  1825  		t.Fatalf("job insert failed: %v", err)
  1826  	}
  1827  
  1828  	index := uint64(1000)
  1829  	if err := state.setJobStatus(index, watcher, txn, job, false, ""); err != nil {
  1830  		t.Fatalf("setJobStatus() failed: %v", err)
  1831  	}
  1832  
  1833  	i, err := txn.First("jobs", "id", job.ID)
  1834  	if err != nil {
  1835  		t.Fatalf("job lookup failed: %v", err)
  1836  	}
  1837  	updated := i.(*structs.Job)
  1838  
  1839  	if updated.Status != structs.JobStatusPending {
  1840  		t.Fatalf("setJobStatus() set %v; expected %v", updated.Status, structs.JobStatusPending)
  1841  	}
  1842  
  1843  	if updated.ModifyIndex != index {
  1844  		t.Fatalf("setJobStatus() set %d; expected %d", updated.ModifyIndex, index)
  1845  	}
  1846  }
  1847  
  1848  func TestStateStore_GetJobStatus_NoEvalsOrAllocs(t *testing.T) {
  1849  	job := mock.Job()
  1850  	state := testStateStore(t)
  1851  	txn := state.db.Txn(false)
  1852  	status, err := state.getJobStatus(txn, job, false)
  1853  	if err != nil {
  1854  		t.Fatalf("getJobStatus() failed: %v", err)
  1855  	}
  1856  
  1857  	if status != structs.JobStatusPending {
  1858  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusPending)
  1859  	}
  1860  }
  1861  
  1862  func TestStateStore_GetJobStatus_NoEvalsOrAllocs_Periodic(t *testing.T) {
  1863  	job := mock.PeriodicJob()
  1864  	state := testStateStore(t)
  1865  	txn := state.db.Txn(false)
  1866  	status, err := state.getJobStatus(txn, job, false)
  1867  	if err != nil {
  1868  		t.Fatalf("getJobStatus() failed: %v", err)
  1869  	}
  1870  
  1871  	if status != structs.JobStatusRunning {
  1872  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusRunning)
  1873  	}
  1874  }
  1875  
  1876  func TestStateStore_GetJobStatus_NoEvalsOrAllocs_EvalDelete(t *testing.T) {
  1877  	job := mock.Job()
  1878  	state := testStateStore(t)
  1879  	txn := state.db.Txn(false)
  1880  	status, err := state.getJobStatus(txn, job, true)
  1881  	if err != nil {
  1882  		t.Fatalf("getJobStatus() failed: %v", err)
  1883  	}
  1884  
  1885  	if status != structs.JobStatusDead {
  1886  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusDead)
  1887  	}
  1888  }
  1889  
  1890  func TestStateStore_GetJobStatus_DeadEvalsAndAllocs(t *testing.T) {
  1891  	state := testStateStore(t)
  1892  	job := mock.Job()
  1893  
  1894  	// Create a mock alloc that is dead.
  1895  	alloc := mock.Alloc()
  1896  	alloc.JobID = job.ID
  1897  	alloc.DesiredStatus = structs.AllocDesiredStatusFailed
  1898  	if err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}); err != nil {
  1899  		t.Fatalf("err: %v", err)
  1900  	}
  1901  
  1902  	// Create a mock eval that is complete
  1903  	eval := mock.Eval()
  1904  	eval.JobID = job.ID
  1905  	eval.Status = structs.EvalStatusComplete
  1906  	if err := state.UpsertEvals(1001, []*structs.Evaluation{eval}); err != nil {
  1907  		t.Fatalf("err: %v", err)
  1908  	}
  1909  
  1910  	txn := state.db.Txn(false)
  1911  	status, err := state.getJobStatus(txn, job, false)
  1912  	if err != nil {
  1913  		t.Fatalf("getJobStatus() failed: %v", err)
  1914  	}
  1915  
  1916  	if status != structs.JobStatusDead {
  1917  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusDead)
  1918  	}
  1919  }
  1920  
  1921  func TestStateStore_GetJobStatus_RunningAlloc(t *testing.T) {
  1922  	state := testStateStore(t)
  1923  	job := mock.Job()
  1924  
  1925  	// Create a mock alloc that is running.
  1926  	alloc := mock.Alloc()
  1927  	alloc.JobID = job.ID
  1928  	alloc.DesiredStatus = structs.AllocDesiredStatusRun
  1929  	if err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}); err != nil {
  1930  		t.Fatalf("err: %v", err)
  1931  	}
  1932  
  1933  	txn := state.db.Txn(false)
  1934  	status, err := state.getJobStatus(txn, job, true)
  1935  	if err != nil {
  1936  		t.Fatalf("getJobStatus() failed: %v", err)
  1937  	}
  1938  
  1939  	if status != structs.JobStatusRunning {
  1940  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusRunning)
  1941  	}
  1942  }
  1943  
  1944  func TestStateStore_SetJobStatus_PendingEval(t *testing.T) {
  1945  	state := testStateStore(t)
  1946  	job := mock.Job()
  1947  
  1948  	// Create a mock eval that is pending.
  1949  	eval := mock.Eval()
  1950  	eval.JobID = job.ID
  1951  	eval.Status = structs.EvalStatusPending
  1952  	if err := state.UpsertEvals(1000, []*structs.Evaluation{eval}); err != nil {
  1953  		t.Fatalf("err: %v", err)
  1954  	}
  1955  
  1956  	txn := state.db.Txn(false)
  1957  	status, err := state.getJobStatus(txn, job, true)
  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 TestStateWatch_watch(t *testing.T) {
  1968  	sw := newStateWatch()
  1969  	notify1 := make(chan struct{}, 1)
  1970  	notify2 := make(chan struct{}, 1)
  1971  	notify3 := make(chan struct{}, 1)
  1972  
  1973  	// Notifications trigger subscribed channels
  1974  	sw.watch(watch.NewItems(watch.Item{Table: "foo"}), notify1)
  1975  	sw.watch(watch.NewItems(watch.Item{Table: "bar"}), notify2)
  1976  	sw.watch(watch.NewItems(watch.Item{Table: "baz"}), notify3)
  1977  
  1978  	items := watch.NewItems()
  1979  	items.Add(watch.Item{Table: "foo"})
  1980  	items.Add(watch.Item{Table: "bar"})
  1981  
  1982  	sw.notify(items)
  1983  	if len(notify1) != 1 {
  1984  		t.Fatalf("should notify")
  1985  	}
  1986  	if len(notify2) != 1 {
  1987  		t.Fatalf("should notify")
  1988  	}
  1989  	if len(notify3) != 0 {
  1990  		t.Fatalf("should not notify")
  1991  	}
  1992  }
  1993  
  1994  func TestStateWatch_stopWatch(t *testing.T) {
  1995  	sw := newStateWatch()
  1996  	notify := make(chan struct{})
  1997  
  1998  	// First subscribe
  1999  	sw.watch(watch.NewItems(watch.Item{Table: "foo"}), notify)
  2000  
  2001  	// Unsubscribe stop notifications
  2002  	sw.stopWatch(watch.NewItems(watch.Item{Table: "foo"}), notify)
  2003  
  2004  	// Check that the group was removed
  2005  	if _, ok := sw.items[watch.Item{Table: "foo"}]; ok {
  2006  		t.Fatalf("should remove group")
  2007  	}
  2008  
  2009  	// Check that we are not notified
  2010  	sw.notify(watch.NewItems(watch.Item{Table: "foo"}))
  2011  	if len(notify) != 0 {
  2012  		t.Fatalf("should not notify")
  2013  	}
  2014  }
  2015  
  2016  // setupNotifyTest takes a state store and a set of watch items, then creates
  2017  // and subscribes a notification channel for each item.
  2018  func setupNotifyTest(state *StateStore, items ...watch.Item) notifyTest {
  2019  	var n notifyTest
  2020  	for _, item := range items {
  2021  		ch := make(chan struct{}, 1)
  2022  		state.Watch(watch.NewItems(item), ch)
  2023  		n = append(n, &notifyTestCase{item, ch})
  2024  	}
  2025  	return n
  2026  }
  2027  
  2028  // notifyTestCase is used to set up and verify watch triggers.
  2029  type notifyTestCase struct {
  2030  	item watch.Item
  2031  	ch   chan struct{}
  2032  }
  2033  
  2034  // notifyTest is a suite of notifyTestCases.
  2035  type notifyTest []*notifyTestCase
  2036  
  2037  // verify ensures that each channel received a notification.
  2038  func (n notifyTest) verify(t *testing.T) {
  2039  	for _, tcase := range n {
  2040  		if len(tcase.ch) != 1 {
  2041  			t.Fatalf("should notify %#v", tcase.item)
  2042  		}
  2043  	}
  2044  }
  2045  
  2046  // NodeIDSort is used to sort nodes by ID
  2047  type NodeIDSort []*structs.Node
  2048  
  2049  func (n NodeIDSort) Len() int {
  2050  	return len(n)
  2051  }
  2052  
  2053  func (n NodeIDSort) Less(i, j int) bool {
  2054  	return n[i].ID < n[j].ID
  2055  }
  2056  
  2057  func (n NodeIDSort) Swap(i, j int) {
  2058  	n[i], n[j] = n[j], n[i]
  2059  }
  2060  
  2061  // JobIDis used to sort jobs by id
  2062  type JobIDSort []*structs.Job
  2063  
  2064  func (n JobIDSort) Len() int {
  2065  	return len(n)
  2066  }
  2067  
  2068  func (n JobIDSort) Less(i, j int) bool {
  2069  	return n[i].ID < n[j].ID
  2070  }
  2071  
  2072  func (n JobIDSort) Swap(i, j int) {
  2073  	n[i], n[j] = n[j], n[i]
  2074  }
  2075  
  2076  // EvalIDis used to sort evals by id
  2077  type EvalIDSort []*structs.Evaluation
  2078  
  2079  func (n EvalIDSort) Len() int {
  2080  	return len(n)
  2081  }
  2082  
  2083  func (n EvalIDSort) Less(i, j int) bool {
  2084  	return n[i].ID < n[j].ID
  2085  }
  2086  
  2087  func (n EvalIDSort) Swap(i, j int) {
  2088  	n[i], n[j] = n[j], n[i]
  2089  }
  2090  
  2091  // AllocIDsort used to sort allocations by id
  2092  type AllocIDSort []*structs.Allocation
  2093  
  2094  func (n AllocIDSort) Len() int {
  2095  	return len(n)
  2096  }
  2097  
  2098  func (n AllocIDSort) Less(i, j int) bool {
  2099  	return n[i].ID < n[j].ID
  2100  }
  2101  
  2102  func (n AllocIDSort) Swap(i, j int) {
  2103  	n[i], n[j] = n[j], n[i]
  2104  }