github.com/dctrud/umoci@v0.4.3-0.20191016193643-05a1d37de015/third_party/user/user_test.go (about) 1 package user 2 3 import ( 4 "fmt" 5 "io" 6 "reflect" 7 "sort" 8 "strings" 9 "testing" 10 "unsafe" 11 ) 12 13 func TestUserParseLine(t *testing.T) { 14 var ( 15 a, b string 16 c []string 17 d int 18 ) 19 20 parseLine("", &a, &b) 21 if a != "" || b != "" { 22 t.Fatalf("a and b should be empty ('%v', '%v')", a, b) 23 } 24 25 parseLine("a", &a, &b) 26 if a != "a" || b != "" { 27 t.Fatalf("a should be 'a' and b should be empty ('%v', '%v')", a, b) 28 } 29 30 parseLine("bad boys:corny cows", &a, &b) 31 if a != "bad boys" || b != "corny cows" { 32 t.Fatalf("a should be 'bad boys' and b should be 'corny cows' ('%v', '%v')", a, b) 33 } 34 35 parseLine("", &c) 36 if len(c) != 0 { 37 t.Fatalf("c should be empty (%#v)", c) 38 } 39 40 parseLine("d,e,f:g:h:i,j,k", &c, &a, &b, &c) 41 if a != "g" || b != "h" || len(c) != 3 || c[0] != "i" || c[1] != "j" || c[2] != "k" { 42 t.Fatalf("a should be 'g', b should be 'h', and c should be ['i','j','k'] ('%v', '%v', '%#v')", a, b, c) 43 } 44 45 parseLine("::::::::::", &a, &b, &c) 46 if a != "" || b != "" || len(c) != 0 { 47 t.Fatalf("a, b, and c should all be empty ('%v', '%v', '%#v')", a, b, c) 48 } 49 50 parseLine("not a number", &d) 51 if d != 0 { 52 t.Fatalf("d should be 0 (%v)", d) 53 } 54 55 parseLine("b:12:c", &a, &d, &b) 56 if a != "b" || b != "c" || d != 12 { 57 t.Fatalf("a should be 'b' and b should be 'c', and d should be 12 ('%v', '%v', %v)", a, b, d) 58 } 59 } 60 61 func TestUserParsePasswd(t *testing.T) { 62 users, err := ParsePasswdFilter(strings.NewReader(` 63 root:x:0:0:root:/root:/bin/bash 64 adm:x:3:4:adm:/var/adm:/bin/false 65 this is just some garbage data 66 `), nil) 67 if err != nil { 68 t.Fatalf("Unexpected error: %v", err) 69 } 70 if len(users) != 3 { 71 t.Fatalf("Expected 3 users, got %v", len(users)) 72 } 73 if users[0].Uid != 0 || users[0].Name != "root" { 74 t.Fatalf("Expected users[0] to be 0 - root, got %v - %v", users[0].Uid, users[0].Name) 75 } 76 if users[1].Uid != 3 || users[1].Name != "adm" { 77 t.Fatalf("Expected users[1] to be 3 - adm, got %v - %v", users[1].Uid, users[1].Name) 78 } 79 } 80 81 func TestUserParseGroup(t *testing.T) { 82 groups, err := ParseGroupFilter(strings.NewReader(` 83 root:x:0:root 84 adm:x:4:root,adm,daemon 85 this is just some garbage data 86 `), nil) 87 if err != nil { 88 t.Fatalf("Unexpected error: %v", err) 89 } 90 if len(groups) != 3 { 91 t.Fatalf("Expected 3 groups, got %v", len(groups)) 92 } 93 if groups[0].Gid != 0 || groups[0].Name != "root" || len(groups[0].List) != 1 { 94 t.Fatalf("Expected groups[0] to be 0 - root - 1 member, got %v - %v - %v", groups[0].Gid, groups[0].Name, len(groups[0].List)) 95 } 96 if groups[1].Gid != 4 || groups[1].Name != "adm" || len(groups[1].List) != 3 { 97 t.Fatalf("Expected groups[1] to be 4 - adm - 3 members, got %v - %v - %v", groups[1].Gid, groups[1].Name, len(groups[1].List)) 98 } 99 } 100 101 func TestValidGetExecUser(t *testing.T) { 102 const passwdContent = ` 103 root:x:0:0:root user:/root:/bin/bash 104 adm:x:42:43:adm:/var/adm:/bin/false 105 111:x:222:333::/var/garbage 106 odd:x:111:112::/home/odd::::: 107 this is just some garbage data 108 ` 109 const groupContent = ` 110 root:x:0:root 111 adm:x:43: 112 grp:x:1234:root,adm 113 444:x:555:111 114 odd:x:444: 115 this is just some garbage data 116 ` 117 defaultExecUser := ExecUser{ 118 Uid: 8888, 119 Gid: 8888, 120 Sgids: []int{8888}, 121 Home: "/8888", 122 } 123 124 tests := []struct { 125 ref string 126 expected ExecUser 127 }{ 128 { 129 ref: "root", 130 expected: ExecUser{ 131 Uid: 0, 132 Gid: 0, 133 Sgids: []int{0, 1234}, 134 Home: "/root", 135 }, 136 }, 137 { 138 ref: "adm", 139 expected: ExecUser{ 140 Uid: 42, 141 Gid: 43, 142 Sgids: []int{1234}, 143 Home: "/var/adm", 144 }, 145 }, 146 { 147 ref: "root:adm", 148 expected: ExecUser{ 149 Uid: 0, 150 Gid: 43, 151 Sgids: defaultExecUser.Sgids, 152 Home: "/root", 153 }, 154 }, 155 { 156 ref: "adm:1234", 157 expected: ExecUser{ 158 Uid: 42, 159 Gid: 1234, 160 Sgids: defaultExecUser.Sgids, 161 Home: "/var/adm", 162 }, 163 }, 164 { 165 ref: "42:1234", 166 expected: ExecUser{ 167 Uid: 42, 168 Gid: 1234, 169 Sgids: defaultExecUser.Sgids, 170 Home: "/var/adm", 171 }, 172 }, 173 { 174 ref: "1337:1234", 175 expected: ExecUser{ 176 Uid: 1337, 177 Gid: 1234, 178 Sgids: defaultExecUser.Sgids, 179 Home: defaultExecUser.Home, 180 }, 181 }, 182 { 183 ref: "1337", 184 expected: ExecUser{ 185 Uid: 1337, 186 Gid: defaultExecUser.Gid, 187 Sgids: defaultExecUser.Sgids, 188 Home: defaultExecUser.Home, 189 }, 190 }, 191 { 192 ref: "", 193 expected: ExecUser{ 194 Uid: defaultExecUser.Uid, 195 Gid: defaultExecUser.Gid, 196 Sgids: defaultExecUser.Sgids, 197 Home: defaultExecUser.Home, 198 }, 199 }, 200 201 // Regression tests for #695. 202 { 203 ref: "111", 204 expected: ExecUser{ 205 Uid: 111, 206 Gid: 112, 207 Sgids: defaultExecUser.Sgids, 208 Home: "/home/odd", 209 }, 210 }, 211 { 212 ref: "111:444", 213 expected: ExecUser{ 214 Uid: 111, 215 Gid: 444, 216 Sgids: defaultExecUser.Sgids, 217 Home: "/home/odd", 218 }, 219 }, 220 } 221 222 for _, test := range tests { 223 passwd := strings.NewReader(passwdContent) 224 group := strings.NewReader(groupContent) 225 226 execUser, err := GetExecUser(test.ref, &defaultExecUser, passwd, group) 227 if err != nil { 228 t.Logf("got unexpected error when parsing '%s': %s", test.ref, err.Error()) 229 t.Fail() 230 continue 231 } 232 233 if !reflect.DeepEqual(test.expected, *execUser) { 234 t.Logf("ref: %v", test.ref) 235 t.Logf("got: %#v", execUser) 236 t.Logf("expected: %#v", test.expected) 237 t.Fail() 238 continue 239 } 240 } 241 } 242 243 func TestInvalidGetExecUser(t *testing.T) { 244 const passwdContent = ` 245 root:x:0:0:root user:/root:/bin/bash 246 adm:x:42:43:adm:/var/adm:/bin/false 247 -42:x:12:13:broken:/very/broken 248 this is just some garbage data 249 ` 250 const groupContent = ` 251 root:x:0:root 252 adm:x:43: 253 grp:x:1234:root,adm 254 this is just some garbage data 255 ` 256 257 tests := []string{ 258 // No such user/group. 259 "notuser", 260 "notuser:notgroup", 261 "root:notgroup", 262 "notuser:adm", 263 "8888:notgroup", 264 "notuser:8888", 265 266 // Invalid user/group values. 267 "-1:0", 268 "0:-3", 269 "-5:-2", 270 "-42", 271 "-43", 272 } 273 274 for _, test := range tests { 275 passwd := strings.NewReader(passwdContent) 276 group := strings.NewReader(groupContent) 277 278 execUser, err := GetExecUser(test, nil, passwd, group) 279 if err == nil { 280 t.Logf("got unexpected success when parsing '%s': %#v", test, execUser) 281 t.Fail() 282 continue 283 } 284 } 285 } 286 287 func TestGetExecUserNilSources(t *testing.T) { 288 const passwdContent = ` 289 root:x:0:0:root user:/root:/bin/bash 290 adm:x:42:43:adm:/var/adm:/bin/false 291 this is just some garbage data 292 ` 293 const groupContent = ` 294 root:x:0:root 295 adm:x:43: 296 grp:x:1234:root,adm 297 this is just some garbage data 298 ` 299 300 defaultExecUser := ExecUser{ 301 Uid: 8888, 302 Gid: 8888, 303 Sgids: []int{8888}, 304 Home: "/8888", 305 } 306 307 tests := []struct { 308 ref string 309 passwd, group bool 310 expected ExecUser 311 }{ 312 { 313 ref: "", 314 passwd: false, 315 group: false, 316 expected: ExecUser{ 317 Uid: 8888, 318 Gid: 8888, 319 Sgids: []int{8888}, 320 Home: "/8888", 321 }, 322 }, 323 { 324 ref: "root", 325 passwd: true, 326 group: false, 327 expected: ExecUser{ 328 Uid: 0, 329 Gid: 0, 330 Sgids: []int{8888}, 331 Home: "/root", 332 }, 333 }, 334 { 335 ref: "0", 336 passwd: false, 337 group: false, 338 expected: ExecUser{ 339 Uid: 0, 340 Gid: 8888, 341 Sgids: []int{8888}, 342 Home: "/8888", 343 }, 344 }, 345 { 346 ref: "0:0", 347 passwd: false, 348 group: false, 349 expected: ExecUser{ 350 Uid: 0, 351 Gid: 0, 352 Sgids: []int{8888}, 353 Home: "/8888", 354 }, 355 }, 356 } 357 358 for _, test := range tests { 359 var passwd, group io.Reader 360 361 if test.passwd { 362 passwd = strings.NewReader(passwdContent) 363 } 364 365 if test.group { 366 group = strings.NewReader(groupContent) 367 } 368 369 execUser, err := GetExecUser(test.ref, &defaultExecUser, passwd, group) 370 if err != nil { 371 t.Logf("got unexpected error when parsing '%s': %s", test.ref, err.Error()) 372 t.Fail() 373 continue 374 } 375 376 if !reflect.DeepEqual(test.expected, *execUser) { 377 t.Logf("got: %#v", execUser) 378 t.Logf("expected: %#v", test.expected) 379 t.Fail() 380 continue 381 } 382 } 383 } 384 385 func TestGetAdditionalGroups(t *testing.T) { 386 type foo struct { 387 groups []string 388 expected []int 389 hasError bool 390 } 391 392 const groupContent = ` 393 root:x:0:root 394 adm:x:43: 395 grp:x:1234:root,adm 396 adm:x:4343:root,adm-duplicate 397 this is just some garbage data 398 ` 399 tests := []foo{ 400 { 401 // empty group 402 groups: []string{}, 403 expected: []int{}, 404 }, 405 { 406 // single group 407 groups: []string{"adm"}, 408 expected: []int{43}, 409 }, 410 { 411 // multiple groups 412 groups: []string{"adm", "grp"}, 413 expected: []int{43, 1234}, 414 }, 415 { 416 // invalid group 417 groups: []string{"adm", "grp", "not-exist"}, 418 expected: nil, 419 hasError: true, 420 }, 421 { 422 // group with numeric id 423 groups: []string{"43"}, 424 expected: []int{43}, 425 }, 426 { 427 // group with unknown numeric id 428 groups: []string{"adm", "10001"}, 429 expected: []int{43, 10001}, 430 }, 431 { 432 // groups specified twice with numeric and name 433 groups: []string{"adm", "43"}, 434 expected: []int{43}, 435 }, 436 { 437 // groups with too small id 438 groups: []string{"-1"}, 439 expected: nil, 440 hasError: true, 441 }, 442 } 443 444 if int(unsafe.Sizeof(1)) > 4 { 445 tests = append(tests, foo{ 446 // groups with too large id 447 groups: []string{fmt.Sprintf("%d", int64(1<<31))}, 448 expected: nil, 449 hasError: true, 450 }) 451 } 452 453 for _, test := range tests { 454 group := strings.NewReader(groupContent) 455 456 gids, err := GetAdditionalGroups(test.groups, group) 457 if test.hasError && err == nil { 458 t.Errorf("Parse(%#v) expects error but has none", test) 459 continue 460 } 461 if !test.hasError && err != nil { 462 t.Errorf("Parse(%#v) has error %v", test, err) 463 continue 464 } 465 sort.Sort(sort.IntSlice(gids)) 466 if !reflect.DeepEqual(gids, test.expected) { 467 t.Errorf("Gids(%v), expect %v from groups %v", gids, test.expected, test.groups) 468 } 469 } 470 } 471 472 func TestGetAdditionalGroupsNumeric(t *testing.T) { 473 tests := []struct { 474 groups []string 475 expected []int 476 hasError bool 477 }{ 478 { 479 // numeric groups only 480 groups: []string{"1234", "5678"}, 481 expected: []int{1234, 5678}, 482 }, 483 { 484 // numeric and alphabetic 485 groups: []string{"1234", "fake"}, 486 expected: nil, 487 hasError: true, 488 }, 489 } 490 491 for _, test := range tests { 492 gids, err := GetAdditionalGroups(test.groups, nil) 493 if test.hasError && err == nil { 494 t.Errorf("Parse(%#v) expects error but has none", test) 495 continue 496 } 497 if !test.hasError && err != nil { 498 t.Errorf("Parse(%#v) has error %v", test, err) 499 continue 500 } 501 sort.Sort(sort.IntSlice(gids)) 502 if !reflect.DeepEqual(gids, test.expected) { 503 t.Errorf("Gids(%v), expect %v from groups %v", gids, test.expected, test.groups) 504 } 505 } 506 }