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  }