github.com/blixtra/nomad@v0.7.2-0.20171221000451-da9a1d7bb050/nomad/structs/funcs_test.go (about) 1 package structs 2 3 import ( 4 "fmt" 5 "testing" 6 7 lru "github.com/hashicorp/golang-lru" 8 "github.com/hashicorp/nomad/helper/uuid" 9 "github.com/stretchr/testify/assert" 10 ) 11 12 func TestRemoveAllocs(t *testing.T) { 13 l := []*Allocation{ 14 {ID: "foo"}, 15 {ID: "bar"}, 16 {ID: "baz"}, 17 {ID: "zip"}, 18 } 19 20 out := RemoveAllocs(l, []*Allocation{l[1], l[3]}) 21 if len(out) != 2 { 22 t.Fatalf("bad: %#v", out) 23 } 24 if out[0].ID != "foo" && out[1].ID != "baz" { 25 t.Fatalf("bad: %#v", out) 26 } 27 } 28 29 func TestFilterTerminalAllocs(t *testing.T) { 30 l := []*Allocation{ 31 { 32 ID: "bar", 33 Name: "myname1", 34 DesiredStatus: AllocDesiredStatusEvict, 35 }, 36 {ID: "baz", DesiredStatus: AllocDesiredStatusStop}, 37 { 38 ID: "foo", 39 DesiredStatus: AllocDesiredStatusRun, 40 ClientStatus: AllocClientStatusPending, 41 }, 42 { 43 ID: "bam", 44 Name: "myname", 45 DesiredStatus: AllocDesiredStatusRun, 46 ClientStatus: AllocClientStatusComplete, 47 CreateIndex: 5, 48 }, 49 { 50 ID: "lol", 51 Name: "myname", 52 DesiredStatus: AllocDesiredStatusRun, 53 ClientStatus: AllocClientStatusComplete, 54 CreateIndex: 2, 55 }, 56 } 57 58 out, terminalAllocs := FilterTerminalAllocs(l) 59 if len(out) != 1 { 60 t.Fatalf("bad: %#v", out) 61 } 62 if out[0].ID != "foo" { 63 t.Fatalf("bad: %#v", out) 64 } 65 66 if len(terminalAllocs) != 3 { 67 for _, o := range terminalAllocs { 68 fmt.Printf("%#v \n", o) 69 } 70 71 t.Fatalf("bad: %#v", terminalAllocs) 72 } 73 74 if terminalAllocs["myname"].ID != "bam" { 75 t.Fatalf("bad: %#v", terminalAllocs["myname"]) 76 } 77 } 78 79 func TestAllocsFit_PortsOvercommitted(t *testing.T) { 80 n := &Node{ 81 Resources: &Resources{ 82 Networks: []*NetworkResource{ 83 { 84 Device: "eth0", 85 CIDR: "10.0.0.0/8", 86 MBits: 100, 87 }, 88 }, 89 }, 90 } 91 92 a1 := &Allocation{ 93 Job: &Job{ 94 TaskGroups: []*TaskGroup{ 95 { 96 Name: "web", 97 EphemeralDisk: DefaultEphemeralDisk(), 98 }, 99 }, 100 }, 101 TaskResources: map[string]*Resources{ 102 "web": { 103 Networks: []*NetworkResource{ 104 { 105 Device: "eth0", 106 IP: "10.0.0.1", 107 MBits: 50, 108 ReservedPorts: []Port{{"main", 8000}}, 109 }, 110 }, 111 }, 112 }, 113 } 114 115 // Should fit one allocation 116 fit, dim, _, err := AllocsFit(n, []*Allocation{a1}, nil) 117 if err != nil { 118 t.Fatalf("err: %v", err) 119 } 120 if !fit { 121 t.Fatalf("Bad: %s", dim) 122 } 123 124 // Should not fit second allocation 125 fit, _, _, err = AllocsFit(n, []*Allocation{a1, a1}, nil) 126 if err != nil { 127 t.Fatalf("err: %v", err) 128 } 129 if fit { 130 t.Fatalf("Bad") 131 } 132 } 133 134 func TestAllocsFit(t *testing.T) { 135 n := &Node{ 136 Resources: &Resources{ 137 CPU: 2000, 138 MemoryMB: 2048, 139 DiskMB: 10000, 140 IOPS: 100, 141 Networks: []*NetworkResource{ 142 { 143 Device: "eth0", 144 CIDR: "10.0.0.0/8", 145 MBits: 100, 146 }, 147 }, 148 }, 149 Reserved: &Resources{ 150 CPU: 1000, 151 MemoryMB: 1024, 152 DiskMB: 5000, 153 IOPS: 50, 154 Networks: []*NetworkResource{ 155 { 156 Device: "eth0", 157 IP: "10.0.0.1", 158 MBits: 50, 159 ReservedPorts: []Port{{"main", 80}}, 160 }, 161 }, 162 }, 163 } 164 165 a1 := &Allocation{ 166 Resources: &Resources{ 167 CPU: 1000, 168 MemoryMB: 1024, 169 DiskMB: 5000, 170 IOPS: 50, 171 Networks: []*NetworkResource{ 172 { 173 Device: "eth0", 174 IP: "10.0.0.1", 175 MBits: 50, 176 ReservedPorts: []Port{{"main", 8000}}, 177 }, 178 }, 179 }, 180 } 181 182 // Should fit one allocation 183 fit, _, used, err := AllocsFit(n, []*Allocation{a1}, nil) 184 if err != nil { 185 t.Fatalf("err: %v", err) 186 } 187 if !fit { 188 t.Fatalf("Bad") 189 } 190 191 // Sanity check the used resources 192 if used.CPU != 2000 { 193 t.Fatalf("bad: %#v", used) 194 } 195 if used.MemoryMB != 2048 { 196 t.Fatalf("bad: %#v", used) 197 } 198 199 // Should not fit second allocation 200 fit, _, used, err = AllocsFit(n, []*Allocation{a1, a1}, nil) 201 if err != nil { 202 t.Fatalf("err: %v", err) 203 } 204 if fit { 205 t.Fatalf("Bad") 206 } 207 208 // Sanity check the used resources 209 if used.CPU != 3000 { 210 t.Fatalf("bad: %#v", used) 211 } 212 if used.MemoryMB != 3072 { 213 t.Fatalf("bad: %#v", used) 214 } 215 216 } 217 218 func TestScoreFit(t *testing.T) { 219 node := &Node{} 220 node.Resources = &Resources{ 221 CPU: 4096, 222 MemoryMB: 8192, 223 } 224 node.Reserved = &Resources{ 225 CPU: 2048, 226 MemoryMB: 4096, 227 } 228 229 // Test a perfect fit 230 util := &Resources{ 231 CPU: 2048, 232 MemoryMB: 4096, 233 } 234 score := ScoreFit(node, util) 235 if score != 18.0 { 236 t.Fatalf("bad: %v", score) 237 } 238 239 // Test the worst fit 240 util = &Resources{ 241 CPU: 0, 242 MemoryMB: 0, 243 } 244 score = ScoreFit(node, util) 245 if score != 0.0 { 246 t.Fatalf("bad: %v", score) 247 } 248 249 // Test a mid-case scenario 250 util = &Resources{ 251 CPU: 1024, 252 MemoryMB: 2048, 253 } 254 score = ScoreFit(node, util) 255 if score < 10.0 || score > 16.0 { 256 t.Fatalf("bad: %v", score) 257 } 258 } 259 260 func TestACLPolicyListHash(t *testing.T) { 261 h1 := ACLPolicyListHash(nil) 262 assert.NotEqual(t, "", h1) 263 264 p1 := &ACLPolicy{ 265 Name: fmt.Sprintf("policy-%s", uuid.Generate()), 266 Description: "Super cool policy!", 267 Rules: ` 268 namespace "default" { 269 policy = "write" 270 } 271 node { 272 policy = "read" 273 } 274 agent { 275 policy = "read" 276 } 277 `, 278 CreateIndex: 10, 279 ModifyIndex: 20, 280 } 281 282 h2 := ACLPolicyListHash([]*ACLPolicy{p1}) 283 assert.NotEqual(t, "", h2) 284 assert.NotEqual(t, h1, h2) 285 286 // Create P2 as copy of P1 with new name 287 p2 := &ACLPolicy{} 288 *p2 = *p1 289 p2.Name = fmt.Sprintf("policy-%s", uuid.Generate()) 290 291 h3 := ACLPolicyListHash([]*ACLPolicy{p1, p2}) 292 assert.NotEqual(t, "", h3) 293 assert.NotEqual(t, h2, h3) 294 295 h4 := ACLPolicyListHash([]*ACLPolicy{p2}) 296 assert.NotEqual(t, "", h4) 297 assert.NotEqual(t, h3, h4) 298 299 // ModifyIndex should change the hash 300 p2.ModifyIndex++ 301 h5 := ACLPolicyListHash([]*ACLPolicy{p2}) 302 assert.NotEqual(t, "", h5) 303 assert.NotEqual(t, h4, h5) 304 } 305 306 func TestCompileACLObject(t *testing.T) { 307 p1 := &ACLPolicy{ 308 Name: fmt.Sprintf("policy-%s", uuid.Generate()), 309 Description: "Super cool policy!", 310 Rules: ` 311 namespace "default" { 312 policy = "write" 313 } 314 node { 315 policy = "read" 316 } 317 agent { 318 policy = "read" 319 } 320 `, 321 CreateIndex: 10, 322 ModifyIndex: 20, 323 } 324 325 // Create P2 as copy of P1 with new name 326 p2 := &ACLPolicy{} 327 *p2 = *p1 328 p2.Name = fmt.Sprintf("policy-%s", uuid.Generate()) 329 330 // Create a small cache 331 cache, err := lru.New2Q(16) 332 assert.Nil(t, err) 333 334 // Test compilation 335 aclObj, err := CompileACLObject(cache, []*ACLPolicy{p1}) 336 assert.Nil(t, err) 337 assert.NotNil(t, aclObj) 338 339 // Should get the same object 340 aclObj2, err := CompileACLObject(cache, []*ACLPolicy{p1}) 341 assert.Nil(t, err) 342 if aclObj != aclObj2 { 343 t.Fatalf("expected the same object") 344 } 345 346 // Should get another object 347 aclObj3, err := CompileACLObject(cache, []*ACLPolicy{p1, p2}) 348 assert.Nil(t, err) 349 assert.NotNil(t, aclObj3) 350 if aclObj == aclObj3 { 351 t.Fatalf("unexpected same object") 352 } 353 354 // Should be order independent 355 aclObj4, err := CompileACLObject(cache, []*ACLPolicy{p2, p1}) 356 assert.Nil(t, err) 357 assert.NotNil(t, aclObj4) 358 if aclObj3 != aclObj4 { 359 t.Fatalf("expected same object") 360 } 361 }