github.com/maier/nomad@v0.4.1-0.20161110003312-a9e3d0b8549d/nomad/structs/funcs_test.go (about) 1 package structs 2 3 import ( 4 "fmt" 5 "reflect" 6 "regexp" 7 "sort" 8 "testing" 9 ) 10 11 func TestRemoveAllocs(t *testing.T) { 12 l := []*Allocation{ 13 &Allocation{ID: "foo"}, 14 &Allocation{ID: "bar"}, 15 &Allocation{ID: "baz"}, 16 &Allocation{ID: "zip"}, 17 } 18 19 out := RemoveAllocs(l, []*Allocation{l[1], l[3]}) 20 if len(out) != 2 { 21 t.Fatalf("bad: %#v", out) 22 } 23 if out[0].ID != "foo" && out[1].ID != "baz" { 24 t.Fatalf("bad: %#v", out) 25 } 26 } 27 28 func TestFilterTerminalAllocs(t *testing.T) { 29 l := []*Allocation{ 30 &Allocation{ 31 ID: "bar", 32 Name: "myname1", 33 DesiredStatus: AllocDesiredStatusEvict, 34 }, 35 &Allocation{ID: "baz", DesiredStatus: AllocDesiredStatusStop}, 36 &Allocation{ 37 ID: "foo", 38 DesiredStatus: AllocDesiredStatusRun, 39 ClientStatus: AllocClientStatusPending, 40 }, 41 &Allocation{ 42 ID: "bam", 43 Name: "myname", 44 DesiredStatus: AllocDesiredStatusRun, 45 ClientStatus: AllocClientStatusComplete, 46 CreateIndex: 5, 47 }, 48 &Allocation{ 49 ID: "lol", 50 Name: "myname", 51 DesiredStatus: AllocDesiredStatusRun, 52 ClientStatus: AllocClientStatusComplete, 53 CreateIndex: 2, 54 }, 55 } 56 57 out, terminalAllocs := FilterTerminalAllocs(l) 58 if len(out) != 1 { 59 t.Fatalf("bad: %#v", out) 60 } 61 if out[0].ID != "foo" { 62 t.Fatalf("bad: %#v", out) 63 } 64 65 if len(terminalAllocs) != 3 { 66 for _, o := range terminalAllocs { 67 fmt.Printf("%#v \n", o) 68 } 69 70 t.Fatalf("bad: %#v", terminalAllocs) 71 } 72 73 if terminalAllocs["myname"].ID != "bam" { 74 t.Fatalf("bad: %#v", terminalAllocs["myname"]) 75 } 76 } 77 78 func TestAllocsFit_PortsOvercommitted(t *testing.T) { 79 n := &Node{ 80 Resources: &Resources{ 81 Networks: []*NetworkResource{ 82 &NetworkResource{ 83 Device: "eth0", 84 CIDR: "10.0.0.0/8", 85 MBits: 100, 86 }, 87 }, 88 }, 89 } 90 91 a1 := &Allocation{ 92 Job: &Job{ 93 TaskGroups: []*TaskGroup{ 94 { 95 Name: "web", 96 EphemeralDisk: DefaultEphemeralDisk(), 97 }, 98 }, 99 }, 100 TaskResources: map[string]*Resources{ 101 "web": &Resources{ 102 Networks: []*NetworkResource{ 103 &NetworkResource{ 104 Device: "eth0", 105 IP: "10.0.0.1", 106 MBits: 50, 107 ReservedPorts: []Port{{"main", 8000}}, 108 }, 109 }, 110 }, 111 }, 112 } 113 114 // Should fit one allocation 115 fit, dim, _, err := AllocsFit(n, []*Allocation{a1}, nil) 116 if err != nil { 117 t.Fatalf("err: %v", err) 118 } 119 if !fit { 120 t.Fatalf("Bad: %s", dim) 121 } 122 123 // Should not fit second allocation 124 fit, _, _, err = AllocsFit(n, []*Allocation{a1, a1}, nil) 125 if err != nil { 126 t.Fatalf("err: %v", err) 127 } 128 if fit { 129 t.Fatalf("Bad") 130 } 131 } 132 133 func TestAllocsFit(t *testing.T) { 134 n := &Node{ 135 Resources: &Resources{ 136 CPU: 2000, 137 MemoryMB: 2048, 138 DiskMB: 10000, 139 IOPS: 100, 140 Networks: []*NetworkResource{ 141 &NetworkResource{ 142 Device: "eth0", 143 CIDR: "10.0.0.0/8", 144 MBits: 100, 145 }, 146 }, 147 }, 148 Reserved: &Resources{ 149 CPU: 1000, 150 MemoryMB: 1024, 151 DiskMB: 5000, 152 IOPS: 50, 153 Networks: []*NetworkResource{ 154 &NetworkResource{ 155 Device: "eth0", 156 IP: "10.0.0.1", 157 MBits: 50, 158 ReservedPorts: []Port{{"main", 80}}, 159 }, 160 }, 161 }, 162 } 163 164 a1 := &Allocation{ 165 Resources: &Resources{ 166 CPU: 1000, 167 MemoryMB: 1024, 168 DiskMB: 5000, 169 IOPS: 50, 170 Networks: []*NetworkResource{ 171 &NetworkResource{ 172 Device: "eth0", 173 IP: "10.0.0.1", 174 MBits: 50, 175 ReservedPorts: []Port{{"main", 8000}}, 176 }, 177 }, 178 }, 179 } 180 181 // Should fit one allocation 182 fit, _, used, err := AllocsFit(n, []*Allocation{a1}, nil) 183 if err != nil { 184 t.Fatalf("err: %v", err) 185 } 186 if !fit { 187 t.Fatalf("Bad") 188 } 189 190 // Sanity check the used resources 191 if used.CPU != 2000 { 192 t.Fatalf("bad: %#v", used) 193 } 194 if used.MemoryMB != 2048 { 195 t.Fatalf("bad: %#v", used) 196 } 197 198 // Should not fit second allocation 199 fit, _, used, err = AllocsFit(n, []*Allocation{a1, a1}, nil) 200 if err != nil { 201 t.Fatalf("err: %v", err) 202 } 203 if fit { 204 t.Fatalf("Bad") 205 } 206 207 // Sanity check the used resources 208 if used.CPU != 3000 { 209 t.Fatalf("bad: %#v", used) 210 } 211 if used.MemoryMB != 3072 { 212 t.Fatalf("bad: %#v", used) 213 } 214 215 } 216 217 func TestScoreFit(t *testing.T) { 218 node := &Node{} 219 node.Resources = &Resources{ 220 CPU: 4096, 221 MemoryMB: 8192, 222 } 223 node.Reserved = &Resources{ 224 CPU: 2048, 225 MemoryMB: 4096, 226 } 227 228 // Test a perfect fit 229 util := &Resources{ 230 CPU: 2048, 231 MemoryMB: 4096, 232 } 233 score := ScoreFit(node, util) 234 if score != 18.0 { 235 t.Fatalf("bad: %v", score) 236 } 237 238 // Test the worst fit 239 util = &Resources{ 240 CPU: 0, 241 MemoryMB: 0, 242 } 243 score = ScoreFit(node, util) 244 if score != 0.0 { 245 t.Fatalf("bad: %v", score) 246 } 247 248 // Test a mid-case scenario 249 util = &Resources{ 250 CPU: 1024, 251 MemoryMB: 2048, 252 } 253 score = ScoreFit(node, util) 254 if score < 10.0 || score > 16.0 { 255 t.Fatalf("bad: %v", score) 256 } 257 } 258 259 func TestGenerateUUID(t *testing.T) { 260 prev := GenerateUUID() 261 for i := 0; i < 100; i++ { 262 id := GenerateUUID() 263 if prev == id { 264 t.Fatalf("Should get a new ID!") 265 } 266 267 matched, err := regexp.MatchString( 268 "[\\da-f]{8}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{12}", id) 269 if !matched || err != nil { 270 t.Fatalf("expected match %s %v %s", id, matched, err) 271 } 272 } 273 } 274 275 func TestSliceStringIsSubset(t *testing.T) { 276 l := []string{"a", "b", "c"} 277 s := []string{"d"} 278 279 sub, offending := SliceStringIsSubset(l, l[:1]) 280 if !sub || len(offending) != 0 { 281 t.Fatalf("bad %v %v", sub, offending) 282 } 283 284 sub, offending = SliceStringIsSubset(l, s) 285 if sub || len(offending) == 0 || offending[0] != "d" { 286 t.Fatalf("bad %v %v", sub, offending) 287 } 288 } 289 290 func TestMapStringStringSliceValueSet(t *testing.T) { 291 m := map[string][]string{ 292 "foo": []string{"1", "2"}, 293 "bar": []string{"3"}, 294 "baz": nil, 295 } 296 297 act := MapStringStringSliceValueSet(m) 298 exp := []string{"1", "2", "3"} 299 sort.Strings(act) 300 if !reflect.DeepEqual(act, exp) { 301 t.Fatalf("Bad; got %v; want %v", act, exp) 302 } 303 }