github.com/kardianos/nomad@v0.1.3-0.20151022182107-b13df73ee850/scheduler/stack_test.go (about)

     1  package scheduler
     2  
     3  import (
     4  	"reflect"
     5  	"testing"
     6  
     7  	"github.com/hashicorp/nomad/nomad/mock"
     8  	"github.com/hashicorp/nomad/nomad/structs"
     9  )
    10  
    11  func TestServiceStack_SetNodes(t *testing.T) {
    12  	_, ctx := testContext(t)
    13  	stack := NewGenericStack(false, ctx)
    14  
    15  	nodes := []*structs.Node{
    16  		mock.Node(),
    17  		mock.Node(),
    18  		mock.Node(),
    19  		mock.Node(),
    20  		mock.Node(),
    21  		mock.Node(),
    22  		mock.Node(),
    23  		mock.Node(),
    24  	}
    25  	stack.SetNodes(nodes)
    26  
    27  	// Check that our scan limit is updated
    28  	if stack.limit.limit != 3 {
    29  		t.Fatalf("bad limit %d", stack.limit.limit)
    30  	}
    31  
    32  	out := collectFeasible(stack.source)
    33  	if !reflect.DeepEqual(out, nodes) {
    34  		t.Fatalf("bad: %#v", out)
    35  	}
    36  }
    37  
    38  func TestServiceStack_SetJob(t *testing.T) {
    39  	_, ctx := testContext(t)
    40  	stack := NewGenericStack(false, ctx)
    41  
    42  	job := mock.Job()
    43  	stack.SetJob(job)
    44  
    45  	if stack.binPack.priority != job.Priority {
    46  		t.Fatalf("bad")
    47  	}
    48  	if !reflect.DeepEqual(stack.jobConstraint.constraints, job.Constraints) {
    49  		t.Fatalf("bad")
    50  	}
    51  }
    52  
    53  func TestServiceStack_Select_Size(t *testing.T) {
    54  	_, ctx := testContext(t)
    55  	nodes := []*structs.Node{
    56  		mock.Node(),
    57  	}
    58  	stack := NewGenericStack(false, ctx)
    59  	stack.SetNodes(nodes)
    60  
    61  	job := mock.Job()
    62  	stack.SetJob(job)
    63  	node, size := stack.Select(job.TaskGroups[0])
    64  	if node == nil {
    65  		t.Fatalf("missing node %#v", ctx.Metrics())
    66  	}
    67  	if size == nil {
    68  		t.Fatalf("missing size")
    69  	}
    70  
    71  	if size.CPU != 500 || size.MemoryMB != 256 {
    72  		t.Fatalf("bad: %#v", size)
    73  	}
    74  
    75  	met := ctx.Metrics()
    76  	if met.AllocationTime == 0 {
    77  		t.Fatalf("missing time")
    78  	}
    79  }
    80  
    81  func TestServiceStack_Select_MetricsReset(t *testing.T) {
    82  	_, ctx := testContext(t)
    83  	nodes := []*structs.Node{
    84  		mock.Node(),
    85  		mock.Node(),
    86  		mock.Node(),
    87  		mock.Node(),
    88  	}
    89  	stack := NewGenericStack(false, ctx)
    90  	stack.SetNodes(nodes)
    91  
    92  	job := mock.Job()
    93  	stack.SetJob(job)
    94  	n1, _ := stack.Select(job.TaskGroups[0])
    95  	m1 := ctx.Metrics()
    96  	if n1 == nil {
    97  		t.Fatalf("missing node %#v", m1)
    98  	}
    99  
   100  	if m1.NodesEvaluated != 2 {
   101  		t.Fatalf("should only be 2")
   102  	}
   103  
   104  	n2, _ := stack.Select(job.TaskGroups[0])
   105  	m2 := ctx.Metrics()
   106  	if n2 == nil {
   107  		t.Fatalf("missing node %#v", m2)
   108  	}
   109  
   110  	// If we don't reset, this would be 4
   111  	if m2.NodesEvaluated != 2 {
   112  		t.Fatalf("should only be 2")
   113  	}
   114  }
   115  
   116  func TestServiceStack_Select_DriverFilter(t *testing.T) {
   117  	_, ctx := testContext(t)
   118  	nodes := []*structs.Node{
   119  		mock.Node(),
   120  		mock.Node(),
   121  	}
   122  	zero := nodes[0]
   123  	zero.Attributes["driver.foo"] = "1"
   124  
   125  	stack := NewGenericStack(false, ctx)
   126  	stack.SetNodes(nodes)
   127  
   128  	job := mock.Job()
   129  	job.TaskGroups[0].Tasks[0].Driver = "foo"
   130  	stack.SetJob(job)
   131  
   132  	node, _ := stack.Select(job.TaskGroups[0])
   133  	if node == nil {
   134  		t.Fatalf("missing node %#v", ctx.Metrics())
   135  	}
   136  
   137  	if node.Node != zero {
   138  		t.Fatalf("bad")
   139  	}
   140  }
   141  
   142  func TestServiceStack_Select_ConstraintFilter(t *testing.T) {
   143  	_, ctx := testContext(t)
   144  	nodes := []*structs.Node{
   145  		mock.Node(),
   146  		mock.Node(),
   147  	}
   148  	zero := nodes[0]
   149  	zero.Attributes["kernel.name"] = "freebsd"
   150  
   151  	stack := NewGenericStack(false, ctx)
   152  	stack.SetNodes(nodes)
   153  
   154  	job := mock.Job()
   155  	job.Constraints[0].RTarget = "freebsd"
   156  	stack.SetJob(job)
   157  
   158  	node, _ := stack.Select(job.TaskGroups[0])
   159  	if node == nil {
   160  		t.Fatalf("missing node %#v", ctx.Metrics())
   161  	}
   162  
   163  	if node.Node != zero {
   164  		t.Fatalf("bad")
   165  	}
   166  
   167  	met := ctx.Metrics()
   168  	if met.NodesFiltered != 1 {
   169  		t.Fatalf("bad: %#v", met)
   170  	}
   171  	if met.ClassFiltered["linux-medium-pci"] != 1 {
   172  		t.Fatalf("bad: %#v", met)
   173  	}
   174  	if met.ConstraintFiltered["$attr.kernel.name = freebsd"] != 1 {
   175  		t.Fatalf("bad: %#v", met)
   176  	}
   177  }
   178  
   179  func TestServiceStack_Select_BinPack_Overflow(t *testing.T) {
   180  	_, ctx := testContext(t)
   181  	nodes := []*structs.Node{
   182  		mock.Node(),
   183  		mock.Node(),
   184  	}
   185  	zero := nodes[0]
   186  	one := nodes[1]
   187  	one.Reserved = one.Resources
   188  
   189  	stack := NewGenericStack(false, ctx)
   190  	stack.SetNodes(nodes)
   191  
   192  	job := mock.Job()
   193  	stack.SetJob(job)
   194  
   195  	node, _ := stack.Select(job.TaskGroups[0])
   196  	if node == nil {
   197  		t.Fatalf("missing node %#v", ctx.Metrics())
   198  	}
   199  
   200  	if node.Node != zero {
   201  		t.Fatalf("bad")
   202  	}
   203  
   204  	met := ctx.Metrics()
   205  	if met.NodesExhausted != 1 {
   206  		t.Fatalf("bad: %#v", met)
   207  	}
   208  	if met.ClassExhausted["linux-medium-pci"] != 1 {
   209  		t.Fatalf("bad: %#v", met)
   210  	}
   211  	if len(met.Scores) != 1 {
   212  		t.Fatalf("bad: %#v", met)
   213  	}
   214  }
   215  
   216  func TestSystemStack_SetNodes(t *testing.T) {
   217  	_, ctx := testContext(t)
   218  	stack := NewSystemStack(ctx)
   219  
   220  	nodes := []*structs.Node{
   221  		mock.Node(),
   222  		mock.Node(),
   223  		mock.Node(),
   224  		mock.Node(),
   225  		mock.Node(),
   226  		mock.Node(),
   227  		mock.Node(),
   228  		mock.Node(),
   229  	}
   230  	stack.SetNodes(nodes)
   231  
   232  	out := collectFeasible(stack.source)
   233  	if !reflect.DeepEqual(out, nodes) {
   234  		t.Fatalf("bad: %#v", out)
   235  	}
   236  }
   237  
   238  func TestSystemStack_SetJob(t *testing.T) {
   239  	_, ctx := testContext(t)
   240  	stack := NewSystemStack(ctx)
   241  
   242  	job := mock.Job()
   243  	stack.SetJob(job)
   244  
   245  	if stack.binPack.priority != job.Priority {
   246  		t.Fatalf("bad")
   247  	}
   248  	if !reflect.DeepEqual(stack.jobConstraint.constraints, job.Constraints) {
   249  		t.Fatalf("bad")
   250  	}
   251  }
   252  
   253  func TestSystemStack_Select_Size(t *testing.T) {
   254  	_, ctx := testContext(t)
   255  	nodes := []*structs.Node{mock.Node()}
   256  	stack := NewSystemStack(ctx)
   257  	stack.SetNodes(nodes)
   258  
   259  	job := mock.Job()
   260  	stack.SetJob(job)
   261  	node, size := stack.Select(job.TaskGroups[0])
   262  	if node == nil {
   263  		t.Fatalf("missing node %#v", ctx.Metrics())
   264  	}
   265  	if size == nil {
   266  		t.Fatalf("missing size")
   267  	}
   268  
   269  	if size.CPU != 500 || size.MemoryMB != 256 {
   270  		t.Fatalf("bad: %#v", size)
   271  	}
   272  
   273  	met := ctx.Metrics()
   274  	if met.AllocationTime == 0 {
   275  		t.Fatalf("missing time")
   276  	}
   277  }
   278  
   279  func TestSystemStack_Select_MetricsReset(t *testing.T) {
   280  	_, ctx := testContext(t)
   281  	nodes := []*structs.Node{
   282  		mock.Node(),
   283  		mock.Node(),
   284  		mock.Node(),
   285  		mock.Node(),
   286  	}
   287  	stack := NewSystemStack(ctx)
   288  	stack.SetNodes(nodes)
   289  
   290  	job := mock.Job()
   291  	stack.SetJob(job)
   292  	n1, _ := stack.Select(job.TaskGroups[0])
   293  	m1 := ctx.Metrics()
   294  	if n1 == nil {
   295  		t.Fatalf("missing node %#v", m1)
   296  	}
   297  
   298  	if m1.NodesEvaluated != 1 {
   299  		t.Fatalf("should only be 1")
   300  	}
   301  
   302  	n2, _ := stack.Select(job.TaskGroups[0])
   303  	m2 := ctx.Metrics()
   304  	if n2 == nil {
   305  		t.Fatalf("missing node %#v", m2)
   306  	}
   307  
   308  	// If we don't reset, this would be 2
   309  	if m2.NodesEvaluated != 1 {
   310  		t.Fatalf("should only be 2")
   311  	}
   312  }
   313  
   314  func TestSystemStack_Select_DriverFilter(t *testing.T) {
   315  	_, ctx := testContext(t)
   316  	nodes := []*structs.Node{
   317  		mock.Node(),
   318  	}
   319  	zero := nodes[0]
   320  	zero.Attributes["driver.foo"] = "1"
   321  
   322  	stack := NewSystemStack(ctx)
   323  	stack.SetNodes(nodes)
   324  
   325  	job := mock.Job()
   326  	job.TaskGroups[0].Tasks[0].Driver = "foo"
   327  	stack.SetJob(job)
   328  
   329  	node, _ := stack.Select(job.TaskGroups[0])
   330  	if node == nil {
   331  		t.Fatalf("missing node %#v", ctx.Metrics())
   332  	}
   333  
   334  	if node.Node != zero {
   335  		t.Fatalf("bad")
   336  	}
   337  
   338  	zero.Attributes["driver.foo"] = "0"
   339  	stack = NewSystemStack(ctx)
   340  	stack.SetNodes(nodes)
   341  	stack.SetJob(job)
   342  	node, _ = stack.Select(job.TaskGroups[0])
   343  	if node != nil {
   344  		t.Fatalf("node not filtered %#v", node)
   345  	}
   346  }
   347  
   348  func TestSystemStack_Select_ConstraintFilter(t *testing.T) {
   349  	_, ctx := testContext(t)
   350  	nodes := []*structs.Node{
   351  		mock.Node(),
   352  		mock.Node(),
   353  	}
   354  	zero := nodes[1]
   355  	zero.Attributes["kernel.name"] = "freebsd"
   356  
   357  	stack := NewSystemStack(ctx)
   358  	stack.SetNodes(nodes)
   359  
   360  	job := mock.Job()
   361  	job.Constraints[0].RTarget = "freebsd"
   362  	stack.SetJob(job)
   363  
   364  	node, _ := stack.Select(job.TaskGroups[0])
   365  	if node == nil {
   366  		t.Fatalf("missing node %#v", ctx.Metrics())
   367  	}
   368  
   369  	if node.Node != zero {
   370  		t.Fatalf("bad")
   371  	}
   372  
   373  	met := ctx.Metrics()
   374  	if met.NodesFiltered != 1 {
   375  		t.Fatalf("bad: %#v", met)
   376  	}
   377  	if met.ClassFiltered["linux-medium-pci"] != 1 {
   378  		t.Fatalf("bad: %#v", met)
   379  	}
   380  	if met.ConstraintFiltered["$attr.kernel.name = freebsd"] != 1 {
   381  		t.Fatalf("bad: %#v", met)
   382  	}
   383  }
   384  
   385  func TestSystemStack_Select_BinPack_Overflow(t *testing.T) {
   386  	_, ctx := testContext(t)
   387  	nodes := []*structs.Node{
   388  		mock.Node(),
   389  		mock.Node(),
   390  	}
   391  	zero := nodes[0]
   392  	zero.Reserved = zero.Resources
   393  	one := nodes[1]
   394  
   395  	stack := NewSystemStack(ctx)
   396  	stack.SetNodes(nodes)
   397  
   398  	job := mock.Job()
   399  	stack.SetJob(job)
   400  
   401  	node, _ := stack.Select(job.TaskGroups[0])
   402  	if node == nil {
   403  		t.Fatalf("missing node %#v", ctx.Metrics())
   404  	}
   405  
   406  	if node.Node != one {
   407  		t.Fatalf("bad")
   408  	}
   409  
   410  	met := ctx.Metrics()
   411  	if met.NodesExhausted != 1 {
   412  		t.Fatalf("bad: %#v", met)
   413  	}
   414  	if met.ClassExhausted["linux-medium-pci"] != 1 {
   415  		t.Fatalf("bad: %#v", met)
   416  	}
   417  	if len(met.Scores) != 1 {
   418  		t.Fatalf("bad: %#v", met)
   419  	}
   420  }