github.com/xyproto/u-root@v6.0.1-0.20200302025726-5528e0c77a3c+incompatible/cmds/core/id/id_test.go (about) 1 // Copyright 2017-2018 the u-root 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 package main 6 7 import ( 8 "bytes" 9 "fmt" 10 "os/exec" 11 "sort" 12 "testing" 13 14 "github.com/u-root/u-root/pkg/testutil" 15 ) 16 17 var ( 18 logPrefixLength = len("2009/11/10 23:00:00 ") 19 ) 20 21 type test struct { 22 opt []string 23 out string 24 } 25 26 // Run the command, with the optional args, and return a string 27 // for stdout, stderr, and an error. 28 func run(c *exec.Cmd) (string, string, error) { 29 var o, e bytes.Buffer 30 c.Stdout, c.Stderr = &o, &e 31 err := c.Run() 32 return o.String(), e.String(), err 33 } 34 35 // Test incorrect invocation of id 36 func TestInvocation(t *testing.T) { 37 var tests = []test{ 38 {opt: []string{"-n"}, out: "id: cannot print only names in default format\n"}, 39 {opt: []string{"-G", "-g"}, out: "id: cannot print \"only\" of more than one choice\n"}, 40 {opt: []string{"-G", "-u"}, out: "id: cannot print \"only\" of more than one choice\n"}, 41 {opt: []string{"-g", "-u"}, out: "id: cannot print \"only\" of more than one choice\n"}, 42 {opt: []string{"-g", "-u", "-G"}, out: "id: cannot print \"only\" of more than one choice\n"}, 43 } 44 45 for _, test := range tests { 46 c := testutil.Command(t, test.opt...) 47 _, e, _ := run(c) 48 49 // Ignore the date and time because we're using Log.Fatalf 50 if e[logPrefixLength:] != test.out { 51 t.Errorf("id for '%v' failed: got '%s', want '%s'", test.opt, e, test.out) 52 } 53 } 54 } 55 56 type passwd struct { 57 name string 58 uid int 59 gid int 60 } 61 62 var passwdShould = []passwd{ 63 {"root", 0, 0}, 64 {"bin", 1, 1}, 65 {"daemon", 2, 2}, 66 {"lary", 1000, 1000}, 67 {"curly", 1001, 1001}, 68 {"moe", 1002, 2002}, 69 } 70 71 var passwdShouldnt = []passwd{ 72 {"adm", 3, 4}, 73 } 74 75 var passwdFiles = []string{ 76 "testdata/passwd-simple.txt", 77 "testdata/passwd-comments.txt", 78 } 79 80 type group struct { 81 name string 82 gid int 83 } 84 85 var groupShould = []group{ 86 {"printadmin", 997}, 87 {"ssh_keys", 996}, 88 {"rpcuser", 29}, 89 {"nfsnobody", 65534}, 90 {"sshd", 74}, 91 {"wheel", 10}, 92 } 93 94 var groupShouldnt = []group{ 95 {"bad", 314}, 96 {"wrong", 996}, 97 {"wheel", 11}, 98 } 99 100 var groupFiles = []string{ 101 "testdata/group-simple.txt", 102 "testdata/group-comments.txt", 103 } 104 105 var groupMembers = map[string][]int{ 106 "larry": {10, 74}, 107 "curly": {10, 29}, 108 "moe": {10}, 109 "joe": {}, 110 } 111 112 func passwdSame(u *Users, us passwd) error { 113 var s string 114 var d int 115 var err error 116 d, err = u.GetUID(us.name) 117 if err != nil { 118 return fmt.Errorf("failed to GetUID expected user %s: %v", us.name, err) 119 } 120 if d != us.uid { 121 return fmt.Errorf("wrong UID for %s: got %d, expected %d", us.name, d, us.uid) 122 } 123 124 d, err = u.GetGID(us.uid) 125 if err != nil { 126 return fmt.Errorf("failed to GetGID expected uid %d: %v", us.uid, err) 127 } 128 if d != us.gid { 129 return fmt.Errorf("wrong GID for uid %d: got %d, expected %d", us.uid, d, us.gid) 130 } 131 132 s, err = u.GetUser(us.uid) 133 if err != nil { 134 return fmt.Errorf("failed to GetUser expected user %s: %v", us.name, err) 135 } 136 if s != us.name { 137 return fmt.Errorf("wrong username for %d: got %s, expected %s", us.uid, s, us.name) 138 } 139 return nil 140 } 141 142 func TestUsers(t *testing.T) { 143 t.Run("non-existent passwd file", func(t *testing.T) { 144 f := "testdata/does-not-exist" 145 u, e := NewUsers(f) 146 if e == nil { 147 t.Errorf("NewUser on non-existant file should return an error") 148 } 149 if u == nil { 150 t.Errorf("NewUser should return a valid Users object, even on error") 151 } 152 }) 153 t.Run("empty passwd file", func(t *testing.T) { 154 f := "testdata/passwd-empty.txt" 155 u, e := NewUsers(f) 156 if e != nil { 157 t.Errorf("NewUser should not report error for empty passwd file") 158 } 159 if u == nil { 160 t.Errorf("NewUser should return a valid Users object even if passwd file is empty") 161 } 162 }) 163 for _, f := range passwdFiles { 164 t.Run(f, func(t *testing.T) { 165 u, e := NewUsers(f) 166 if e != nil { 167 t.Errorf("NewUser should not return an error on valid file") 168 } 169 if u == nil { 170 t.Errorf("NewUser should return a valid Users object on valid file") 171 } 172 for _, us := range passwdShould { 173 if e := passwdSame(u, us); e != nil { 174 t.Errorf("%v", e) 175 } 176 } 177 for _, us := range passwdShouldnt { 178 if e := passwdSame(u, us); e == nil { 179 t.Errorf("user %s matched when it shouldn't", us.name) 180 } 181 } 182 }) 183 } 184 } 185 186 func groupSame(g *Groups, gs group) error { 187 var s string 188 var d int 189 var err error 190 191 d, err = g.GetGID(gs.name) 192 if err != nil { 193 return fmt.Errorf("failed to GetGID expected group %s: %v", gs.name, err) 194 } 195 if d != gs.gid { 196 return fmt.Errorf("wrong GID for %s: got %d, expected %d", gs.name, d, gs.gid) 197 } 198 199 s, err = g.GetGroup(gs.gid) 200 if err != nil { 201 return fmt.Errorf("failed to GetGroup expected group %s: %v", gs.name, err) 202 } 203 if s != gs.name { 204 return fmt.Errorf("wrong groupname for %d: got %s, expected %s", gs.gid, s, gs.name) 205 } 206 return nil 207 } 208 209 func TestGroups(t *testing.T) { 210 t.Run("non-existent group file", func(t *testing.T) { 211 f := "testdata/does-not-exist" 212 g, e := NewGroups(f) 213 if e == nil { 214 t.Errorf("NewGroups jnon-existant file should return an error") 215 } 216 if g == nil { 217 t.Errorf("NewGroups should return a valid Groups object, even on error") 218 } 219 }) 220 t.Run("empty passwd file", func(t *testing.T) { 221 f := "testdata/group-empty.txt" 222 g, e := NewGroups(f) 223 if e != nil { 224 t.Errorf("NewGroups should not report error for empty passwd file") 225 } 226 if g == nil { 227 t.Errorf("NewGroups should return a valid Users object even if passwd file is empty") 228 } 229 }) 230 for _, f := range groupFiles { 231 t.Run(f, func(t *testing.T) { 232 g, e := NewGroups(f) 233 if e != nil { 234 t.Errorf("NewGroups should not return an error on valid file") 235 } 236 if g == nil { 237 t.Errorf("NewGroups should return a valid Users object on valid file") 238 } 239 for _, gs := range groupShould { 240 if e := groupSame(g, gs); e != nil { 241 t.Errorf("%v", e) 242 } 243 } 244 for _, gs := range groupShouldnt { 245 if e := groupSame(g, gs); e == nil { 246 t.Errorf("group %s matched when it shouldn't", gs.name) 247 } 248 } 249 for u, is := range groupMembers { 250 js := g.UserGetGIDs(u) 251 if len(js) != len(is) { 252 t.Errorf("unequal gid lists for %s: %v vs %v", u, is, js) 253 } else { 254 sort.Ints(is) 255 sort.Ints(js) 256 for i := range is { 257 if is[i] != js[i] { 258 t.Errorf("unequal gid lists for %s: %v vs %v", u, is, js) 259 } 260 } 261 } 262 } 263 }) 264 } 265 } 266 267 func TestMain(m *testing.M) { 268 testutil.Run(m, main) 269 }