277 lines
7.6 KiB
Go
277 lines
7.6 KiB
Go
// Copyright 2016 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// +build aix darwin dragonfly freebsd !android,linux netbsd openbsd solaris
|
|
// +build !cgo
|
|
|
|
package user
|
|
|
|
import (
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
const testGroupFile = `# See the opendirectoryd(8) man page for additional
|
|
# information about Open Directory.
|
|
##
|
|
nobody:*:-2:
|
|
nogroup:*:-1:
|
|
wheel:*:0:root
|
|
emptyid:*::root
|
|
invalidgid:*:notanumber:root
|
|
+plussign:*:20:root
|
|
-minussign:*:21:root
|
|
|
|
daemon:*:1:root
|
|
indented:*:7:
|
|
# comment:*:4:found
|
|
# comment:*:4:found
|
|
kmem:*:2:root
|
|
`
|
|
|
|
var groupTests = []struct {
|
|
in string
|
|
name string
|
|
gid string
|
|
}{
|
|
{testGroupFile, "nobody", "-2"},
|
|
{testGroupFile, "kmem", "2"},
|
|
{testGroupFile, "notinthefile", ""},
|
|
{testGroupFile, "comment", ""},
|
|
{testGroupFile, "plussign", ""},
|
|
{testGroupFile, "+plussign", ""},
|
|
{testGroupFile, "-minussign", ""},
|
|
{testGroupFile, "minussign", ""},
|
|
{testGroupFile, "emptyid", ""},
|
|
{testGroupFile, "invalidgid", ""},
|
|
{testGroupFile, "indented", "7"},
|
|
{testGroupFile, "# comment", ""},
|
|
{"", "emptyfile", ""},
|
|
}
|
|
|
|
func TestFindGroupName(t *testing.T) {
|
|
for _, tt := range groupTests {
|
|
got, err := findGroupName(tt.name, strings.NewReader(tt.in))
|
|
if tt.gid == "" {
|
|
if err == nil {
|
|
t.Errorf("findGroupName(%s): got nil error, expected err", tt.name)
|
|
continue
|
|
}
|
|
switch terr := err.(type) {
|
|
case UnknownGroupError:
|
|
if terr.Error() != "group: unknown group "+tt.name {
|
|
t.Errorf("findGroupName(%s): got %v, want %v", tt.name, terr, tt.name)
|
|
}
|
|
default:
|
|
t.Errorf("findGroupName(%s): got unexpected error %v", tt.name, terr)
|
|
}
|
|
} else {
|
|
if err != nil {
|
|
t.Fatalf("findGroupName(%s): got unexpected error %v", tt.name, err)
|
|
}
|
|
if got.Gid != tt.gid {
|
|
t.Errorf("findGroupName(%s): got gid %v, want %s", tt.name, got.Gid, tt.gid)
|
|
}
|
|
if got.Name != tt.name {
|
|
t.Errorf("findGroupName(%s): got name %s, want %s", tt.name, got.Name, tt.name)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
var groupIdTests = []struct {
|
|
in string
|
|
gid string
|
|
name string
|
|
}{
|
|
{testGroupFile, "-2", "nobody"},
|
|
{testGroupFile, "2", "kmem"},
|
|
{testGroupFile, "notinthefile", ""},
|
|
{testGroupFile, "comment", ""},
|
|
{testGroupFile, "7", "indented"},
|
|
{testGroupFile, "4", ""},
|
|
{testGroupFile, "20", ""}, // row starts with a plus
|
|
{testGroupFile, "21", ""}, // row starts with a minus
|
|
{"", "emptyfile", ""},
|
|
}
|
|
|
|
func TestFindGroupId(t *testing.T) {
|
|
for _, tt := range groupIdTests {
|
|
got, err := findGroupId(tt.gid, strings.NewReader(tt.in))
|
|
if tt.name == "" {
|
|
if err == nil {
|
|
t.Errorf("findGroupId(%s): got nil error, expected err", tt.gid)
|
|
continue
|
|
}
|
|
switch terr := err.(type) {
|
|
case UnknownGroupIdError:
|
|
if terr.Error() != "group: unknown groupid "+tt.gid {
|
|
t.Errorf("findGroupId(%s): got %v, want %v", tt.name, terr, tt.name)
|
|
}
|
|
default:
|
|
t.Errorf("findGroupId(%s): got unexpected error %v", tt.name, terr)
|
|
}
|
|
} else {
|
|
if err != nil {
|
|
t.Fatalf("findGroupId(%s): got unexpected error %v", tt.name, err)
|
|
}
|
|
if got.Gid != tt.gid {
|
|
t.Errorf("findGroupId(%s): got gid %v, want %s", tt.name, got.Gid, tt.gid)
|
|
}
|
|
if got.Name != tt.name {
|
|
t.Errorf("findGroupId(%s): got name %s, want %s", tt.name, got.Name, tt.name)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const testUserFile = ` # Example user file
|
|
root:x:0:0:root:/root:/bin/bash
|
|
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
|
|
bin:x:2:3:bin:/bin:/usr/sbin/nologin
|
|
indented:x:3:3:indented:/dev:/usr/sbin/nologin
|
|
sync:x:4:65534:sync:/bin:/bin/sync
|
|
negative:x:-5:60:games:/usr/games:/usr/sbin/nologin
|
|
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
|
|
allfields:x:6:12:mansplit,man2,man3,man4:/home/allfields:/usr/sbin/nologin
|
|
+plussign:x:8:10:man:/var/cache/man:/usr/sbin/nologin
|
|
-minussign:x:9:10:man:/var/cache/man:/usr/sbin/nologin
|
|
|
|
malformed:x:27:12 # more:colons:after:comment
|
|
|
|
struid:x:notanumber:12 # more:colons:after:comment
|
|
|
|
# commented:x:28:12:commented:/var/cache/man:/usr/sbin/nologin
|
|
# commentindented:x:29:12:commentindented:/var/cache/man:/usr/sbin/nologin
|
|
|
|
struid2:x:30:badgid:struid2name:/home/struid:/usr/sbin/nologin
|
|
`
|
|
|
|
var userIdTests = []struct {
|
|
in string
|
|
uid string
|
|
name string
|
|
}{
|
|
{testUserFile, "-5", "negative"},
|
|
{testUserFile, "2", "bin"},
|
|
{testUserFile, "100", ""}, // not in the file
|
|
{testUserFile, "8", ""}, // plus sign, glibc doesn't find it
|
|
{testUserFile, "9", ""}, // minus sign, glibc doesn't find it
|
|
{testUserFile, "27", ""}, // malformed
|
|
{testUserFile, "28", ""}, // commented out
|
|
{testUserFile, "29", ""}, // commented out, indented
|
|
{testUserFile, "3", "indented"},
|
|
{testUserFile, "30", ""}, // the Gid is not valid, shouldn't match
|
|
{"", "1", ""},
|
|
}
|
|
|
|
func TestInvalidUserId(t *testing.T) {
|
|
_, err := findUserId("notanumber", strings.NewReader(""))
|
|
if err == nil {
|
|
t.Fatalf("findUserId('notanumber'): got nil error")
|
|
}
|
|
if want := "user: invalid userid notanumber"; err.Error() != want {
|
|
t.Errorf("findUserId('notanumber'): got %v, want %s", err, want)
|
|
}
|
|
}
|
|
|
|
func TestLookupUserId(t *testing.T) {
|
|
for _, tt := range userIdTests {
|
|
got, err := findUserId(tt.uid, strings.NewReader(tt.in))
|
|
if tt.name == "" {
|
|
if err == nil {
|
|
t.Errorf("findUserId(%s): got nil error, expected err", tt.uid)
|
|
continue
|
|
}
|
|
switch terr := err.(type) {
|
|
case UnknownUserIdError:
|
|
if want := "user: unknown userid " + tt.uid; terr.Error() != want {
|
|
t.Errorf("findUserId(%s): got %v, want %v", tt.name, terr, want)
|
|
}
|
|
default:
|
|
t.Errorf("findUserId(%s): got unexpected error %v", tt.name, terr)
|
|
}
|
|
} else {
|
|
if err != nil {
|
|
t.Fatalf("findUserId(%s): got unexpected error %v", tt.name, err)
|
|
}
|
|
if got.Uid != tt.uid {
|
|
t.Errorf("findUserId(%s): got uid %v, want %s", tt.name, got.Uid, tt.uid)
|
|
}
|
|
if got.Username != tt.name {
|
|
t.Errorf("findUserId(%s): got name %s, want %s", tt.name, got.Username, tt.name)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLookupUserPopulatesAllFields(t *testing.T) {
|
|
u, err := findUsername("allfields", strings.NewReader(testUserFile))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
want := &User{
|
|
Username: "allfields",
|
|
Uid: "6",
|
|
Gid: "12",
|
|
Name: "mansplit",
|
|
HomeDir: "/home/allfields",
|
|
}
|
|
if !reflect.DeepEqual(u, want) {
|
|
t.Errorf("findUsername: got %#v, want %#v", u, want)
|
|
}
|
|
}
|
|
|
|
var userTests = []struct {
|
|
in string
|
|
name string
|
|
uid string
|
|
}{
|
|
{testUserFile, "negative", "-5"},
|
|
{testUserFile, "bin", "2"},
|
|
{testUserFile, "notinthefile", ""},
|
|
{testUserFile, "indented", "3"},
|
|
{testUserFile, "plussign", ""},
|
|
{testUserFile, "+plussign", ""},
|
|
{testUserFile, "minussign", ""},
|
|
{testUserFile, "-minussign", ""},
|
|
{testUserFile, " indented", ""},
|
|
{testUserFile, "commented", ""},
|
|
{testUserFile, "commentindented", ""},
|
|
{testUserFile, "malformed", ""},
|
|
{testUserFile, "# commented", ""},
|
|
{"", "emptyfile", ""},
|
|
}
|
|
|
|
func TestLookupUser(t *testing.T) {
|
|
for _, tt := range userTests {
|
|
got, err := findUsername(tt.name, strings.NewReader(tt.in))
|
|
if tt.uid == "" {
|
|
if err == nil {
|
|
t.Errorf("lookupUser(%s): got nil error, expected err", tt.uid)
|
|
continue
|
|
}
|
|
switch terr := err.(type) {
|
|
case UnknownUserError:
|
|
if want := "user: unknown user " + tt.name; terr.Error() != want {
|
|
t.Errorf("lookupUser(%s): got %v, want %v", tt.name, terr, want)
|
|
}
|
|
default:
|
|
t.Errorf("lookupUser(%s): got unexpected error %v", tt.name, terr)
|
|
}
|
|
} else {
|
|
if err != nil {
|
|
t.Fatalf("lookupUser(%s): got unexpected error %v", tt.name, err)
|
|
}
|
|
if got.Uid != tt.uid {
|
|
t.Errorf("lookupUser(%s): got uid %v, want %s", tt.name, got.Uid, tt.uid)
|
|
}
|
|
if got.Username != tt.name {
|
|
t.Errorf("lookupUser(%s): got name %s, want %s", tt.name, got.Username, tt.name)
|
|
}
|
|
}
|
|
}
|
|
}
|