github.com/stolowski/snapd@v0.0.0-20210407085831-115137ce5a22/osutil/group_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2019 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package osutil_test 21 22 import ( 23 "fmt" 24 "os/user" 25 26 "gopkg.in/check.v1" 27 28 "github.com/snapcore/snapd/osutil" 29 "github.com/snapcore/snapd/testutil" 30 ) 31 32 type findUserGroupSuite struct { 33 testutil.BaseTest 34 mockGetent *testutil.MockCmd 35 } 36 37 var _ = check.Suite(&findUserGroupSuite{}) 38 39 func (s *findUserGroupSuite) SetUpTest(c *check.C) { 40 // exit 2 is not found 41 s.mockGetent = testutil.MockCommand(c, "getent", "exit 2") 42 } 43 44 func (s *findUserGroupSuite) TearDownTest(c *check.C) { 45 s.mockGetent.Restore() 46 } 47 48 func (s *findUserGroupSuite) TestFindUidNoGetentFallback(c *check.C) { 49 uid, err := osutil.FindUidNoGetentFallback("root") 50 c.Assert(err, check.IsNil) 51 c.Assert(uid, check.Equals, uint64(0)) 52 // getent shouldn't have been called with FindUidNoGetentFallback() 53 c.Check(s.mockGetent.Calls(), check.DeepEquals, [][]string(nil)) 54 } 55 56 func (s *findUserGroupSuite) TestFindUidNonexistent(c *check.C) { 57 _, err := osutil.FindUidNoGetentFallback("lakatos") 58 c.Assert(err, check.ErrorMatches, "user: unknown user lakatos") 59 _, ok := err.(user.UnknownUserError) 60 c.Assert(ok, check.Equals, true) 61 // getent shouldn't have been called with FindUidNoGetentFallback() 62 c.Check(s.mockGetent.Calls(), check.DeepEquals, [][]string(nil)) 63 } 64 65 func (s *findUserGroupSuite) TestFindUidWithGetentFallback(c *check.C) { 66 uid, err := osutil.FindUidWithGetentFallback("root") 67 c.Assert(err, check.IsNil) 68 c.Assert(uid, check.Equals, uint64(0)) 69 // getent shouldn't have been called since 'root' is in /etc/passwd 70 c.Check(s.mockGetent.Calls(), check.DeepEquals, [][]string(nil)) 71 } 72 73 func (s *findUserGroupSuite) TestFindUidGetentNonexistent(c *check.C) { 74 _, err := osutil.FindUidWithGetentFallback("lakatos") 75 c.Assert(err, check.ErrorMatches, "user: unknown user lakatos") 76 _, ok := err.(user.UnknownUserError) 77 c.Assert(ok, check.Equals, true) 78 // getent should've have been called 79 c.Check(s.mockGetent.Calls(), check.DeepEquals, [][]string{ 80 {"getent", "passwd", "lakatos"}, 81 }) 82 } 83 84 func (s *findUserGroupSuite) TestFindUidGetentFoundFromGetent(c *check.C) { 85 restore := osutil.MockFindUidNoFallback(func(string) (uint64, error) { 86 return 1000, nil 87 }) 88 defer restore() 89 90 uid, err := osutil.FindUidWithGetentFallback("some-user") 91 c.Assert(err, check.IsNil) 92 c.Assert(uid, check.Equals, uint64(1000)) 93 // getent not called, "some-user" was available in the local db 94 c.Check(s.mockGetent.Calls(), check.HasLen, 0) 95 } 96 97 func (s *findUserGroupSuite) TestFindUidGetentOtherErrFromFindUid(c *check.C) { 98 restore := osutil.MockFindUidNoFallback(func(string) (uint64, error) { 99 return 0, fmt.Errorf("other-error") 100 }) 101 defer restore() 102 103 _, err := osutil.FindUidWithGetentFallback("root") 104 c.Assert(err, check.ErrorMatches, "other-error") 105 } 106 107 func (s *findUserGroupSuite) TestFindUidGetentMockedOtherError(c *check.C) { 108 s.mockGetent = testutil.MockCommand(c, "getent", "exit 3") 109 110 uid, err := osutil.FindUidWithGetentFallback("lakatos") 111 c.Assert(err, check.ErrorMatches, "getent failed with: exit status 3") 112 c.Check(uid, check.Equals, uint64(0)) 113 // getent should've have been called 114 c.Check(s.mockGetent.Calls(), check.DeepEquals, [][]string{ 115 {"getent", "passwd", "lakatos"}, 116 }) 117 } 118 119 func (s *findUserGroupSuite) TestFindUidGetentMocked(c *check.C) { 120 s.mockGetent = testutil.MockCommand(c, "getent", "echo lakatos:x:1234:5678:::") 121 122 uid, err := osutil.FindUidWithGetentFallback("lakatos") 123 c.Assert(err, check.IsNil) 124 c.Check(uid, check.Equals, uint64(1234)) 125 c.Check(s.mockGetent.Calls(), check.DeepEquals, [][]string{ 126 {"getent", "passwd", "lakatos"}, 127 }) 128 } 129 130 func (s *findUserGroupSuite) TestFindUidGetentMockedMalformated(c *check.C) { 131 s.mockGetent = testutil.MockCommand(c, "getent", "printf too:few:colons") 132 133 _, err := osutil.FindUidWithGetentFallback("lakatos") 134 c.Assert(err, check.ErrorMatches, `malformed entry: "too:few:colons"`) 135 } 136 137 func (s *findUserGroupSuite) TestFindGidNoGetentFallback(c *check.C) { 138 gid, err := osutil.FindGidNoGetentFallback("root") 139 c.Assert(err, check.IsNil) 140 c.Assert(gid, check.Equals, uint64(0)) 141 // getent shouldn't have been called with FindGidNoGetentFallback() 142 c.Check(s.mockGetent.Calls(), check.DeepEquals, [][]string(nil)) 143 } 144 145 func (s *findUserGroupSuite) TestFindGidNonexistent(c *check.C) { 146 _, err := osutil.FindGidNoGetentFallback("lakatos") 147 c.Assert(err, check.ErrorMatches, "group: unknown group lakatos") 148 _, ok := err.(user.UnknownGroupError) 149 c.Assert(ok, check.Equals, true) 150 } 151 152 func (s *findUserGroupSuite) TestFindGidGetentFoundFromGetent(c *check.C) { 153 restore := osutil.MockFindGidNoFallback(func(string) (uint64, error) { 154 return 1000, nil 155 }) 156 defer restore() 157 158 gid, err := osutil.FindGidWithGetentFallback("some-group") 159 c.Assert(err, check.IsNil) 160 c.Assert(gid, check.Equals, uint64(1000)) 161 // getent not called, "some-group" was available in the local db 162 c.Check(s.mockGetent.Calls(), check.HasLen, 0) 163 } 164 165 func (s *findUserGroupSuite) TestFindGidGetentOtherErrFromFindUid(c *check.C) { 166 restore := osutil.MockFindGidNoFallback(func(string) (uint64, error) { 167 return 0, fmt.Errorf("other-error") 168 }) 169 defer restore() 170 171 _, err := osutil.FindGidWithGetentFallback("root") 172 c.Assert(err, check.ErrorMatches, "other-error") 173 } 174 175 func (s *findUserGroupSuite) TestFindGidWithGetentFallback(c *check.C) { 176 gid, err := osutil.FindGidWithGetentFallback("root") 177 c.Assert(err, check.IsNil) 178 c.Assert(gid, check.Equals, uint64(0)) 179 // getent shouldn't have been called since 'root' is in /etc/group 180 c.Check(s.mockGetent.Calls(), check.DeepEquals, [][]string(nil)) 181 } 182 183 func (s *findUserGroupSuite) TestFindGidGetentNonexistent(c *check.C) { 184 _, err := osutil.FindGidWithGetentFallback("lakatos") 185 c.Assert(err, check.ErrorMatches, "group: unknown group lakatos") 186 _, ok := err.(user.UnknownGroupError) 187 c.Assert(ok, check.Equals, true) 188 // getent should've have been called 189 c.Check(s.mockGetent.Calls(), check.DeepEquals, [][]string{ 190 {"getent", "group", "lakatos"}, 191 }) 192 } 193 194 func (s *findUserGroupSuite) TestFindGidGetentMockedOtherError(c *check.C) { 195 s.mockGetent = testutil.MockCommand(c, "getent", "exit 3") 196 197 gid, err := osutil.FindGidWithGetentFallback("lakatos") 198 c.Assert(err, check.ErrorMatches, "getent failed with: exit status 3") 199 c.Check(gid, check.Equals, uint64(0)) 200 // getent should've have been called 201 c.Check(s.mockGetent.Calls(), check.DeepEquals, [][]string{ 202 {"getent", "group", "lakatos"}, 203 }) 204 } 205 206 func (s *findUserGroupSuite) TestFindGidGetentMocked(c *check.C) { 207 s.mockGetent = testutil.MockCommand(c, "getent", "echo lakatos:x:1234:") 208 209 gid, err := osutil.FindGidWithGetentFallback("lakatos") 210 c.Assert(err, check.IsNil) 211 c.Check(gid, check.Equals, uint64(1234)) 212 c.Check(s.mockGetent.Calls(), check.DeepEquals, [][]string{ 213 {"getent", "group", "lakatos"}, 214 }) 215 } 216 217 func (s *findUserGroupSuite) TestIsUnknownUser(c *check.C) { 218 c.Check(osutil.IsUnknownUser(nil), check.Equals, false) 219 c.Check(osutil.IsUnknownUser(fmt.Errorf("something else")), check.Equals, false) 220 c.Check(osutil.IsUnknownUser(user.UnknownUserError("lakatos")), check.Equals, true) 221 } 222 223 func (s *findUserGroupSuite) TestIsUnknownGroup(c *check.C) { 224 c.Check(osutil.IsUnknownGroup(nil), check.Equals, false) 225 c.Check(osutil.IsUnknownGroup(fmt.Errorf("something else")), check.Equals, false) 226 c.Check(osutil.IsUnknownGroup(user.UnknownGroupError("lakatos")), check.Equals, true) 227 }