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  }