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 }