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