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