github.com/kardianos/nomad@v0.1.3-0.20151022182107-b13df73ee850/nomad/structs/structs_test.go (about) 1 package structs 2 3 import ( 4 "reflect" 5 "strings" 6 "testing" 7 8 "github.com/hashicorp/go-multierror" 9 ) 10 11 func TestJob_Validate(t *testing.T) { 12 j := &Job{} 13 err := j.Validate() 14 mErr := err.(*multierror.Error) 15 if !strings.Contains(mErr.Errors[0].Error(), "job region") { 16 t.Fatalf("err: %s", err) 17 } 18 if !strings.Contains(mErr.Errors[1].Error(), "job ID") { 19 t.Fatalf("err: %s", err) 20 } 21 if !strings.Contains(mErr.Errors[2].Error(), "job name") { 22 t.Fatalf("err: %s", err) 23 } 24 if !strings.Contains(mErr.Errors[3].Error(), "job type") { 25 t.Fatalf("err: %s", err) 26 } 27 if !strings.Contains(mErr.Errors[4].Error(), "priority") { 28 t.Fatalf("err: %s", err) 29 } 30 if !strings.Contains(mErr.Errors[5].Error(), "datacenters") { 31 t.Fatalf("err: %s", err) 32 } 33 if !strings.Contains(mErr.Errors[6].Error(), "task groups") { 34 t.Fatalf("err: %s", err) 35 } 36 37 j = &Job{ 38 Region: "global", 39 ID: GenerateUUID(), 40 Name: "my-job", 41 Type: JobTypeService, 42 Priority: 50, 43 Datacenters: []string{"dc1"}, 44 TaskGroups: []*TaskGroup{ 45 &TaskGroup{ 46 Name: "web", 47 }, 48 &TaskGroup{ 49 Name: "web", 50 }, 51 &TaskGroup{}, 52 }, 53 } 54 err = j.Validate() 55 mErr = err.(*multierror.Error) 56 if !strings.Contains(mErr.Errors[0].Error(), "2 redefines 'web' from group 1") { 57 t.Fatalf("err: %s", err) 58 } 59 if !strings.Contains(mErr.Errors[1].Error(), "group 3 missing name") { 60 t.Fatalf("err: %s", err) 61 } 62 if !strings.Contains(mErr.Errors[2].Error(), "Task group 1 validation failed") { 63 t.Fatalf("err: %s", err) 64 } 65 } 66 67 func TestTaskGroup_Validate(t *testing.T) { 68 tg := &TaskGroup{} 69 err := tg.Validate() 70 mErr := err.(*multierror.Error) 71 if !strings.Contains(mErr.Errors[0].Error(), "group name") { 72 t.Fatalf("err: %s", err) 73 } 74 if !strings.Contains(mErr.Errors[1].Error(), "count must be positive") { 75 t.Fatalf("err: %s", err) 76 } 77 if !strings.Contains(mErr.Errors[2].Error(), "Missing tasks") { 78 t.Fatalf("err: %s", err) 79 } 80 81 tg = &TaskGroup{ 82 Name: "web", 83 Count: 1, 84 Tasks: []*Task{ 85 &Task{Name: "web"}, 86 &Task{Name: "web"}, 87 &Task{}, 88 }, 89 } 90 err = tg.Validate() 91 mErr = err.(*multierror.Error) 92 if !strings.Contains(mErr.Errors[0].Error(), "2 redefines 'web' from task 1") { 93 t.Fatalf("err: %s", err) 94 } 95 if !strings.Contains(mErr.Errors[1].Error(), "Task 3 missing name") { 96 t.Fatalf("err: %s", err) 97 } 98 if !strings.Contains(mErr.Errors[2].Error(), "Task 1 validation failed") { 99 t.Fatalf("err: %s", err) 100 } 101 } 102 103 func TestTask_Validate(t *testing.T) { 104 task := &Task{} 105 err := task.Validate() 106 mErr := err.(*multierror.Error) 107 if !strings.Contains(mErr.Errors[0].Error(), "task name") { 108 t.Fatalf("err: %s", err) 109 } 110 if !strings.Contains(mErr.Errors[1].Error(), "task driver") { 111 t.Fatalf("err: %s", err) 112 } 113 if !strings.Contains(mErr.Errors[2].Error(), "task resources") { 114 t.Fatalf("err: %s", err) 115 } 116 117 task = &Task{ 118 Name: "web", 119 Driver: "docker", 120 Resources: &Resources{}, 121 } 122 err = task.Validate() 123 if err != nil { 124 t.Fatalf("err: %s", err) 125 } 126 } 127 128 func TestConstraint_Validate(t *testing.T) { 129 c := &Constraint{} 130 err := c.Validate() 131 mErr := err.(*multierror.Error) 132 if !strings.Contains(mErr.Errors[0].Error(), "Missing constraint operand") { 133 t.Fatalf("err: %s", err) 134 } 135 136 c = &Constraint{ 137 LTarget: "$attr.kernel.name", 138 RTarget: "linux", 139 Operand: "=", 140 } 141 err = c.Validate() 142 if err != nil { 143 t.Fatalf("err: %v", err) 144 } 145 146 // Perform additional regexp validation 147 c.Operand = "regexp" 148 c.RTarget = "(foo" 149 err = c.Validate() 150 mErr = err.(*multierror.Error) 151 if !strings.Contains(mErr.Errors[0].Error(), "missing closing") { 152 t.Fatalf("err: %s", err) 153 } 154 155 // Perform version validation 156 c.Operand = "version" 157 c.RTarget = "~> foo" 158 err = c.Validate() 159 mErr = err.(*multierror.Error) 160 if !strings.Contains(mErr.Errors[0].Error(), "Malformed constraint") { 161 t.Fatalf("err: %s", err) 162 } 163 } 164 165 func TestResource_NetIndex(t *testing.T) { 166 r := &Resources{ 167 Networks: []*NetworkResource{ 168 &NetworkResource{Device: "eth0"}, 169 &NetworkResource{Device: "lo0"}, 170 &NetworkResource{Device: ""}, 171 }, 172 } 173 if idx := r.NetIndex(&NetworkResource{Device: "eth0"}); idx != 0 { 174 t.Fatalf("Bad: %d", idx) 175 } 176 if idx := r.NetIndex(&NetworkResource{Device: "lo0"}); idx != 1 { 177 t.Fatalf("Bad: %d", idx) 178 } 179 if idx := r.NetIndex(&NetworkResource{Device: "eth1"}); idx != -1 { 180 t.Fatalf("Bad: %d", idx) 181 } 182 } 183 184 func TestResource_Superset(t *testing.T) { 185 r1 := &Resources{ 186 CPU: 2000, 187 MemoryMB: 2048, 188 DiskMB: 10000, 189 IOPS: 100, 190 } 191 r2 := &Resources{ 192 CPU: 2000, 193 MemoryMB: 1024, 194 DiskMB: 5000, 195 IOPS: 50, 196 } 197 198 if s, _ := r1.Superset(r1); !s { 199 t.Fatalf("bad") 200 } 201 if s, _ := r1.Superset(r2); !s { 202 t.Fatalf("bad") 203 } 204 if s, _ := r2.Superset(r1); s { 205 t.Fatalf("bad") 206 } 207 if s, _ := r2.Superset(r2); !s { 208 t.Fatalf("bad") 209 } 210 } 211 212 func TestResource_Add(t *testing.T) { 213 r1 := &Resources{ 214 CPU: 2000, 215 MemoryMB: 2048, 216 DiskMB: 10000, 217 IOPS: 100, 218 Networks: []*NetworkResource{ 219 &NetworkResource{ 220 CIDR: "10.0.0.0/8", 221 MBits: 100, 222 ReservedPorts: []int{22}, 223 }, 224 }, 225 } 226 r2 := &Resources{ 227 CPU: 2000, 228 MemoryMB: 1024, 229 DiskMB: 5000, 230 IOPS: 50, 231 Networks: []*NetworkResource{ 232 &NetworkResource{ 233 IP: "10.0.0.1", 234 MBits: 50, 235 ReservedPorts: []int{80}, 236 }, 237 }, 238 } 239 240 err := r1.Add(r2) 241 if err != nil { 242 t.Fatalf("Err: %v", err) 243 } 244 245 expect := &Resources{ 246 CPU: 3000, 247 MemoryMB: 3072, 248 DiskMB: 15000, 249 IOPS: 150, 250 Networks: []*NetworkResource{ 251 &NetworkResource{ 252 CIDR: "10.0.0.0/8", 253 MBits: 150, 254 ReservedPorts: []int{22, 80}, 255 }, 256 }, 257 } 258 259 if !reflect.DeepEqual(expect.Networks, r1.Networks) { 260 t.Fatalf("bad: %#v %#v", expect, r1) 261 } 262 } 263 264 func TestResource_Add_Network(t *testing.T) { 265 r1 := &Resources{} 266 r2 := &Resources{ 267 Networks: []*NetworkResource{ 268 &NetworkResource{ 269 MBits: 50, 270 DynamicPorts: []string{"http", "https"}, 271 }, 272 }, 273 } 274 r3 := &Resources{ 275 Networks: []*NetworkResource{ 276 &NetworkResource{ 277 MBits: 25, 278 DynamicPorts: []string{"admin"}, 279 }, 280 }, 281 } 282 283 err := r1.Add(r2) 284 if err != nil { 285 t.Fatalf("Err: %v", err) 286 } 287 err = r1.Add(r3) 288 if err != nil { 289 t.Fatalf("Err: %v", err) 290 } 291 292 expect := &Resources{ 293 Networks: []*NetworkResource{ 294 &NetworkResource{ 295 MBits: 75, 296 DynamicPorts: []string{"http", "https", "admin"}, 297 }, 298 }, 299 } 300 301 if !reflect.DeepEqual(expect.Networks, r1.Networks) { 302 t.Fatalf("bad: %#v %#v", expect.Networks[0], r1.Networks[0]) 303 } 304 } 305 306 func TestMapDynamicPorts(t *testing.T) { 307 resources := &NetworkResource{ 308 ReservedPorts: []int{80, 443, 3306, 8080}, 309 DynamicPorts: []string{"mysql", "admin"}, 310 } 311 312 expected := map[string]int{ 313 "mysql": 3306, 314 "admin": 8080, 315 } 316 actual := resources.MapDynamicPorts() 317 318 if !reflect.DeepEqual(expected, actual) { 319 t.Fatalf("Expected %#v; found %#v", expected, actual) 320 } 321 } 322 323 func TestMapDynamicPortsEmpty(t *testing.T) { 324 resources := &NetworkResource{ 325 ReservedPorts: []int{}, 326 DynamicPorts: []string{}, 327 } 328 329 expected := map[string]int{} 330 actual := resources.MapDynamicPorts() 331 332 if !reflect.DeepEqual(expected, actual) { 333 t.Fatalf("Expected %#v; found %#v", expected, actual) 334 } 335 } 336 337 func TestMapDynamicPortsStaticOnly(t *testing.T) { 338 resources := &NetworkResource{ 339 ReservedPorts: []int{80, 443}, 340 DynamicPorts: []string{}, 341 } 342 343 expected := map[string]int{} 344 actual := resources.MapDynamicPorts() 345 346 if !reflect.DeepEqual(expected, actual) { 347 t.Fatalf("Expected %#v; found %#v", expected, actual) 348 } 349 } 350 351 func TestMapDynamicPortsOnly(t *testing.T) { 352 resources := &NetworkResource{ 353 ReservedPorts: []int{3306, 8080}, 354 DynamicPorts: []string{"mysql", "admin"}, 355 } 356 357 expected := map[string]int{ 358 "mysql": 3306, 359 "admin": 8080, 360 } 361 actual := resources.MapDynamicPorts() 362 363 if !reflect.DeepEqual(expected, actual) { 364 t.Fatalf("Expected %#v; found %#v", expected, actual) 365 } 366 } 367 368 func TestListStaticPorts(t *testing.T) { 369 resources := &NetworkResource{ 370 ReservedPorts: []int{80, 443, 3306, 8080}, 371 DynamicPorts: []string{"mysql", "admin"}, 372 } 373 374 expected := []int{80, 443} 375 actual := resources.ListStaticPorts() 376 377 if !reflect.DeepEqual(expected, actual) { 378 t.Fatalf("Expected %#v; found %#v", expected, actual) 379 } 380 } 381 382 func TestListStaticPortsEmpty(t *testing.T) { 383 resources := &NetworkResource{ 384 ReservedPorts: []int{}, 385 DynamicPorts: []string{}, 386 } 387 388 expected := []int{} 389 actual := resources.ListStaticPorts() 390 391 if !reflect.DeepEqual(expected, actual) { 392 t.Fatalf("Expected %#v; found %#v", expected, actual) 393 } 394 } 395 396 func TestListStaticPortsOnly(t *testing.T) { 397 resources := &NetworkResource{ 398 ReservedPorts: []int{80, 443}, 399 DynamicPorts: []string{}, 400 } 401 402 expected := []int{80, 443} 403 actual := resources.ListStaticPorts() 404 405 if !reflect.DeepEqual(expected, actual) { 406 t.Fatalf("Expected %#v; found %#v", expected, actual) 407 } 408 } 409 410 func TestListStaticPortsDynamicOnly(t *testing.T) { 411 resources := &NetworkResource{ 412 ReservedPorts: []int{3306, 8080}, 413 DynamicPorts: []string{"mysql", "admin"}, 414 } 415 416 expected := []int{} 417 actual := resources.ListStaticPorts() 418 419 if !reflect.DeepEqual(expected, actual) { 420 t.Fatalf("Expected %#v; found %#v", expected, actual) 421 } 422 } 423 424 func TestEncodeDecode(t *testing.T) { 425 type FooRequest struct { 426 Foo string 427 Bar int 428 Baz bool 429 } 430 arg := &FooRequest{ 431 Foo: "test", 432 Bar: 42, 433 Baz: true, 434 } 435 buf, err := Encode(1, arg) 436 if err != nil { 437 t.Fatalf("err: %v", err) 438 } 439 440 var out FooRequest 441 err = Decode(buf[1:], &out) 442 if err != nil { 443 t.Fatalf("err: %v", err) 444 } 445 446 if !reflect.DeepEqual(arg, &out) { 447 t.Fatalf("bad: %#v %#v", arg, out) 448 } 449 }