Source file
src/os/user/lookup_unix_test.go
Documentation: os/user
1
2
3
4
5
6
7
8
9 package user
10
11 import (
12 "fmt"
13 "reflect"
14 "strings"
15 "testing"
16 )
17
18 var testGroupFile = `# See the opendirectoryd(8) man page for additional
19 # information about Open Directory.
20 ##
21 nobody:*:-2:
22 nogroup:*:-1:
23 wheel:*:0:root
24 emptyid:*::root
25 invalidgid:*:notanumber:root
26 +plussign:*:20:root
27 -minussign:*:21:root
28
29 daemon:*:1:root
30 indented:*:7:
31 # comment:*:4:found
32 # comment:*:4:found
33 kmem:*:2:root
34 ` + largeGroup()
35
36 var groupTests = []struct {
37 in string
38 name string
39 gid string
40 }{
41 {testGroupFile, "nobody", "-2"},
42 {testGroupFile, "kmem", "2"},
43 {testGroupFile, "notinthefile", ""},
44 {testGroupFile, "comment", ""},
45 {testGroupFile, "plussign", ""},
46 {testGroupFile, "+plussign", ""},
47 {testGroupFile, "-minussign", ""},
48 {testGroupFile, "minussign", ""},
49 {testGroupFile, "emptyid", ""},
50 {testGroupFile, "invalidgid", ""},
51 {testGroupFile, "indented", "7"},
52 {testGroupFile, "# comment", ""},
53 {testGroupFile, "largegroup", "1000"},
54 {"", "emptyfile", ""},
55 }
56
57
58 func largeGroup() (res string) {
59 var b strings.Builder
60 b.WriteString("largegroup:x:1000:user1")
61 for i := 2; i <= 7500; i++ {
62 fmt.Fprintf(&b, ",user%d", i)
63 }
64 return b.String()
65 }
66
67 func TestFindGroupName(t *testing.T) {
68 for _, tt := range groupTests {
69 got, err := findGroupName(tt.name, strings.NewReader(tt.in))
70 if tt.gid == "" {
71 if err == nil {
72 t.Errorf("findGroupName(%s): got nil error, expected err", tt.name)
73 continue
74 }
75 switch terr := err.(type) {
76 case UnknownGroupError:
77 if terr.Error() != "group: unknown group "+tt.name {
78 t.Errorf("findGroupName(%s): got %v, want %v", tt.name, terr, tt.name)
79 }
80 default:
81 t.Errorf("findGroupName(%s): got unexpected error %v", tt.name, terr)
82 }
83 } else {
84 if err != nil {
85 t.Fatalf("findGroupName(%s): got unexpected error %v", tt.name, err)
86 }
87 if got.Gid != tt.gid {
88 t.Errorf("findGroupName(%s): got gid %v, want %s", tt.name, got.Gid, tt.gid)
89 }
90 if got.Name != tt.name {
91 t.Errorf("findGroupName(%s): got name %s, want %s", tt.name, got.Name, tt.name)
92 }
93 }
94 }
95 }
96
97 var groupIdTests = []struct {
98 in string
99 gid string
100 name string
101 }{
102 {testGroupFile, "-2", "nobody"},
103 {testGroupFile, "2", "kmem"},
104 {testGroupFile, "notinthefile", ""},
105 {testGroupFile, "comment", ""},
106 {testGroupFile, "7", "indented"},
107 {testGroupFile, "4", ""},
108 {testGroupFile, "20", ""},
109 {testGroupFile, "21", ""},
110 {"", "emptyfile", ""},
111 }
112
113 func TestFindGroupId(t *testing.T) {
114 for _, tt := range groupIdTests {
115 got, err := findGroupId(tt.gid, strings.NewReader(tt.in))
116 if tt.name == "" {
117 if err == nil {
118 t.Errorf("findGroupId(%s): got nil error, expected err", tt.gid)
119 continue
120 }
121 switch terr := err.(type) {
122 case UnknownGroupIdError:
123 if terr.Error() != "group: unknown groupid "+tt.gid {
124 t.Errorf("findGroupId(%s): got %v, want %v", tt.name, terr, tt.name)
125 }
126 default:
127 t.Errorf("findGroupId(%s): got unexpected error %v", tt.name, terr)
128 }
129 } else {
130 if err != nil {
131 t.Fatalf("findGroupId(%s): got unexpected error %v", tt.name, err)
132 }
133 if got.Gid != tt.gid {
134 t.Errorf("findGroupId(%s): got gid %v, want %s", tt.name, got.Gid, tt.gid)
135 }
136 if got.Name != tt.name {
137 t.Errorf("findGroupId(%s): got name %s, want %s", tt.name, got.Name, tt.name)
138 }
139 }
140 }
141 }
142
143 const testUserFile = ` # Example user file
144 root:x:0:0:root:/root:/bin/bash
145 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
146 bin:x:2:3:bin:/bin:/usr/sbin/nologin
147 indented:x:3:3:indented:/dev:/usr/sbin/nologin
148 sync:x:4:65534:sync:/bin:/bin/sync
149 negative:x:-5:60:games:/usr/games:/usr/sbin/nologin
150 man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
151 allfields:x:6:12:mansplit,man2,man3,man4:/home/allfields:/usr/sbin/nologin
152 +plussign:x:8:10:man:/var/cache/man:/usr/sbin/nologin
153 -minussign:x:9:10:man:/var/cache/man:/usr/sbin/nologin
154
155 malformed:x:27:12 # more:colons:after:comment
156
157 struid:x:notanumber:12 # more:colons:after:comment
158
159 # commented:x:28:12:commented:/var/cache/man:/usr/sbin/nologin
160 # commentindented:x:29:12:commentindented:/var/cache/man:/usr/sbin/nologin
161
162 struid2:x:30:badgid:struid2name:/home/struid:/usr/sbin/nologin
163 `
164
165 var userIdTests = []struct {
166 in string
167 uid string
168 name string
169 }{
170 {testUserFile, "-5", "negative"},
171 {testUserFile, "2", "bin"},
172 {testUserFile, "100", ""},
173 {testUserFile, "8", ""},
174 {testUserFile, "9", ""},
175 {testUserFile, "27", ""},
176 {testUserFile, "28", ""},
177 {testUserFile, "29", ""},
178 {testUserFile, "3", "indented"},
179 {testUserFile, "30", ""},
180 {"", "1", ""},
181 }
182
183 func TestInvalidUserId(t *testing.T) {
184 _, err := findUserId("notanumber", strings.NewReader(""))
185 if err == nil {
186 t.Fatalf("findUserId('notanumber'): got nil error")
187 }
188 if want := "user: invalid userid notanumber"; err.Error() != want {
189 t.Errorf("findUserId('notanumber'): got %v, want %s", err, want)
190 }
191 }
192
193 func TestLookupUserId(t *testing.T) {
194 for _, tt := range userIdTests {
195 got, err := findUserId(tt.uid, strings.NewReader(tt.in))
196 if tt.name == "" {
197 if err == nil {
198 t.Errorf("findUserId(%s): got nil error, expected err", tt.uid)
199 continue
200 }
201 switch terr := err.(type) {
202 case UnknownUserIdError:
203 if want := "user: unknown userid " + tt.uid; terr.Error() != want {
204 t.Errorf("findUserId(%s): got %v, want %v", tt.name, terr, want)
205 }
206 default:
207 t.Errorf("findUserId(%s): got unexpected error %v", tt.name, terr)
208 }
209 } else {
210 if err != nil {
211 t.Fatalf("findUserId(%s): got unexpected error %v", tt.name, err)
212 }
213 if got.Uid != tt.uid {
214 t.Errorf("findUserId(%s): got uid %v, want %s", tt.name, got.Uid, tt.uid)
215 }
216 if got.Username != tt.name {
217 t.Errorf("findUserId(%s): got name %s, want %s", tt.name, got.Username, tt.name)
218 }
219 }
220 }
221 }
222
223 func TestLookupUserPopulatesAllFields(t *testing.T) {
224 u, err := findUsername("allfields", strings.NewReader(testUserFile))
225 if err != nil {
226 t.Fatal(err)
227 }
228 want := &User{
229 Username: "allfields",
230 Uid: "6",
231 Gid: "12",
232 Name: "mansplit",
233 HomeDir: "/home/allfields",
234 }
235 if !reflect.DeepEqual(u, want) {
236 t.Errorf("findUsername: got %#v, want %#v", u, want)
237 }
238 }
239
240 var userTests = []struct {
241 in string
242 name string
243 uid string
244 }{
245 {testUserFile, "negative", "-5"},
246 {testUserFile, "bin", "2"},
247 {testUserFile, "notinthefile", ""},
248 {testUserFile, "indented", "3"},
249 {testUserFile, "plussign", ""},
250 {testUserFile, "+plussign", ""},
251 {testUserFile, "minussign", ""},
252 {testUserFile, "-minussign", ""},
253 {testUserFile, " indented", ""},
254 {testUserFile, "commented", ""},
255 {testUserFile, "commentindented", ""},
256 {testUserFile, "malformed", ""},
257 {testUserFile, "# commented", ""},
258 {"", "emptyfile", ""},
259 }
260
261 func TestLookupUser(t *testing.T) {
262 for _, tt := range userTests {
263 got, err := findUsername(tt.name, strings.NewReader(tt.in))
264 if tt.uid == "" {
265 if err == nil {
266 t.Errorf("lookupUser(%s): got nil error, expected err", tt.uid)
267 continue
268 }
269 switch terr := err.(type) {
270 case UnknownUserError:
271 if want := "user: unknown user " + tt.name; terr.Error() != want {
272 t.Errorf("lookupUser(%s): got %v, want %v", tt.name, terr, want)
273 }
274 default:
275 t.Errorf("lookupUser(%s): got unexpected error %v", tt.name, terr)
276 }
277 } else {
278 if err != nil {
279 t.Fatalf("lookupUser(%s): got unexpected error %v", tt.name, err)
280 }
281 if got.Uid != tt.uid {
282 t.Errorf("lookupUser(%s): got uid %v, want %s", tt.name, got.Uid, tt.uid)
283 }
284 if got.Username != tt.name {
285 t.Errorf("lookupUser(%s): got name %s, want %s", tt.name, got.Username, tt.name)
286 }
287 }
288 }
289 }
290
View as plain text