github.com/karrick/go@v0.0.0-20170817181416-d5b0ec858b37/src/os/user/lookup_unix_test.go (about)

     1  // Copyright 2016 The Go 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 darwin dragonfly freebsd !android,linux nacl netbsd openbsd solaris
     6  // +build !cgo
     7  
     8  package user
     9  
    10  import (
    11  	"reflect"
    12  	"strings"
    13  	"testing"
    14  )
    15  
    16  const testGroupFile = `# See the opendirectoryd(8) man page for additional 
    17  # information about Open Directory.
    18  ##
    19  nobody:*:-2:
    20  nogroup:*:-1:
    21  wheel:*:0:root
    22  emptyid:*::root
    23  invalidgid:*:notanumber:root
    24  +plussign:*:20:root
    25  -minussign:*:21:root
    26        
    27  daemon:*:1:root
    28      indented:*:7:
    29  # comment:*:4:found
    30       # comment:*:4:found
    31  kmem:*:2:root
    32  `
    33  
    34  var groupTests = []struct {
    35  	in   string
    36  	name string
    37  	gid  string
    38  }{
    39  	{testGroupFile, "nobody", "-2"},
    40  	{testGroupFile, "kmem", "2"},
    41  	{testGroupFile, "notinthefile", ""},
    42  	{testGroupFile, "comment", ""},
    43  	{testGroupFile, "plussign", ""},
    44  	{testGroupFile, "+plussign", ""},
    45  	{testGroupFile, "-minussign", ""},
    46  	{testGroupFile, "minussign", ""},
    47  	{testGroupFile, "emptyid", ""},
    48  	{testGroupFile, "invalidgid", ""},
    49  	{testGroupFile, "indented", "7"},
    50  	{testGroupFile, "# comment", ""},
    51  	{"", "emptyfile", ""},
    52  }
    53  
    54  func TestFindGroupName(t *testing.T) {
    55  	for _, tt := range groupTests {
    56  		got, err := findGroupName(tt.name, strings.NewReader(tt.in))
    57  		if tt.gid == "" {
    58  			if err == nil {
    59  				t.Errorf("findGroupName(%s): got nil error, expected err", tt.name)
    60  				continue
    61  			}
    62  			switch terr := err.(type) {
    63  			case UnknownGroupError:
    64  				if terr.Error() != "group: unknown group "+tt.name {
    65  					t.Errorf("findGroupName(%s): got %v, want %v", tt.name, terr, tt.name)
    66  				}
    67  			default:
    68  				t.Errorf("findGroupName(%s): got unexpected error %v", tt.name, terr)
    69  			}
    70  		} else {
    71  			if err != nil {
    72  				t.Fatalf("findGroupName(%s): got unexpected error %v", tt.name, err)
    73  			}
    74  			if got.Gid != tt.gid {
    75  				t.Errorf("findGroupName(%s): got gid %v, want %s", tt.name, got.Gid, tt.gid)
    76  			}
    77  			if got.Name != tt.name {
    78  				t.Errorf("findGroupName(%s): got name %s, want %s", tt.name, got.Name, tt.name)
    79  			}
    80  		}
    81  	}
    82  }
    83  
    84  var groupIdTests = []struct {
    85  	in   string
    86  	gid  string
    87  	name string
    88  }{
    89  	{testGroupFile, "-2", "nobody"},
    90  	{testGroupFile, "2", "kmem"},
    91  	{testGroupFile, "notinthefile", ""},
    92  	{testGroupFile, "comment", ""},
    93  	{testGroupFile, "7", "indented"},
    94  	{testGroupFile, "4", ""},
    95  	{testGroupFile, "20", ""}, // row starts with a plus
    96  	{testGroupFile, "21", ""}, // row starts with a minus
    97  	{"", "emptyfile", ""},
    98  }
    99  
   100  func TestFindGroupId(t *testing.T) {
   101  	for _, tt := range groupIdTests {
   102  		got, err := findGroupId(tt.gid, strings.NewReader(tt.in))
   103  		if tt.name == "" {
   104  			if err == nil {
   105  				t.Errorf("findGroupId(%s): got nil error, expected err", tt.gid)
   106  				continue
   107  			}
   108  			switch terr := err.(type) {
   109  			case UnknownGroupIdError:
   110  				if terr.Error() != "group: unknown groupid "+tt.gid {
   111  					t.Errorf("findGroupId(%s): got %v, want %v", tt.name, terr, tt.name)
   112  				}
   113  			default:
   114  				t.Errorf("findGroupId(%s): got unexpected error %v", tt.name, terr)
   115  			}
   116  		} else {
   117  			if err != nil {
   118  				t.Fatalf("findGroupId(%s): got unexpected error %v", tt.name, err)
   119  			}
   120  			if got.Gid != tt.gid {
   121  				t.Errorf("findGroupId(%s): got gid %v, want %s", tt.name, got.Gid, tt.gid)
   122  			}
   123  			if got.Name != tt.name {
   124  				t.Errorf("findGroupId(%s): got name %s, want %s", tt.name, got.Name, tt.name)
   125  			}
   126  		}
   127  	}
   128  }
   129  
   130  const testUserFile = `   # Example user file
   131  root:x:0:0:root:/root:/bin/bash
   132  daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
   133  bin:x:2:3:bin:/bin:/usr/sbin/nologin
   134       indented:x:3:3:indented:/dev:/usr/sbin/nologin
   135  sync:x:4:65534:sync:/bin:/bin/sync
   136  negative:x:-5:60:games:/usr/games:/usr/sbin/nologin
   137  man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
   138  allfields:x:6:12:mansplit,man2,man3,man4:/home/allfields:/usr/sbin/nologin
   139  +plussign:x:8:10:man:/var/cache/man:/usr/sbin/nologin
   140  -minussign:x:9:10:man:/var/cache/man:/usr/sbin/nologin
   141  
   142  malformed:x:27:12 # more:colons:after:comment
   143  
   144  struid:x:notanumber:12 # more:colons:after:comment
   145  
   146  # commented:x:28:12:commented:/var/cache/man:/usr/sbin/nologin
   147        # commentindented:x:29:12:commentindented:/var/cache/man:/usr/sbin/nologin
   148  
   149  struid2:x:30:badgid:struid2name:/home/struid:/usr/sbin/nologin
   150  `
   151  
   152  var userIdTests = []struct {
   153  	in   string
   154  	uid  string
   155  	name string
   156  }{
   157  	{testUserFile, "-5", "negative"},
   158  	{testUserFile, "2", "bin"},
   159  	{testUserFile, "100", ""}, // not in the file
   160  	{testUserFile, "8", ""},   // plus sign, glibc doesn't find it
   161  	{testUserFile, "9", ""},   // minus sign, glibc doesn't find it
   162  	{testUserFile, "27", ""},  // malformed
   163  	{testUserFile, "28", ""},  // commented out
   164  	{testUserFile, "29", ""},  // commented out, indented
   165  	{testUserFile, "3", "indented"},
   166  	{testUserFile, "30", ""}, // the Gid is not valid, shouldn't match
   167  	{"", "1", ""},
   168  }
   169  
   170  func TestInvalidUserId(t *testing.T) {
   171  	_, err := findUserId("notanumber", strings.NewReader(""))
   172  	if err == nil {
   173  		t.Fatalf("findUserId('notanumber'): got nil error")
   174  	}
   175  	if want := "user: invalid userid notanumber"; err.Error() != want {
   176  		t.Errorf("findUserId('notanumber'): got %v, want %s", err, want)
   177  	}
   178  }
   179  
   180  func TestLookupUserId(t *testing.T) {
   181  	for _, tt := range userIdTests {
   182  		got, err := findUserId(tt.uid, strings.NewReader(tt.in))
   183  		if tt.name == "" {
   184  			if err == nil {
   185  				t.Errorf("findUserId(%s): got nil error, expected err", tt.uid)
   186  				continue
   187  			}
   188  			switch terr := err.(type) {
   189  			case UnknownUserIdError:
   190  				if want := "user: unknown userid " + tt.uid; terr.Error() != want {
   191  					t.Errorf("findUserId(%s): got %v, want %v", tt.name, terr, want)
   192  				}
   193  			default:
   194  				t.Errorf("findUserId(%s): got unexpected error %v", tt.name, terr)
   195  			}
   196  		} else {
   197  			if err != nil {
   198  				t.Fatalf("findUserId(%s): got unexpected error %v", tt.name, err)
   199  			}
   200  			if got.Uid != tt.uid {
   201  				t.Errorf("findUserId(%s): got uid %v, want %s", tt.name, got.Uid, tt.uid)
   202  			}
   203  			if got.Username != tt.name {
   204  				t.Errorf("findUserId(%s): got name %s, want %s", tt.name, got.Username, tt.name)
   205  			}
   206  		}
   207  	}
   208  }
   209  
   210  func TestLookupUserPopulatesAllFields(t *testing.T) {
   211  	u, err := findUsername("allfields", strings.NewReader(testUserFile))
   212  	if err != nil {
   213  		t.Fatal(err)
   214  	}
   215  	want := &User{
   216  		Username: "allfields",
   217  		Uid:      "6",
   218  		Gid:      "12",
   219  		Name:     "mansplit",
   220  		HomeDir:  "/home/allfields",
   221  	}
   222  	if !reflect.DeepEqual(u, want) {
   223  		t.Errorf("findUsername: got %#v, want %#v", u, want)
   224  	}
   225  }
   226  
   227  var userTests = []struct {
   228  	in   string
   229  	name string
   230  	uid  string
   231  }{
   232  	{testUserFile, "negative", "-5"},
   233  	{testUserFile, "bin", "2"},
   234  	{testUserFile, "notinthefile", ""},
   235  	{testUserFile, "indented", "3"},
   236  	{testUserFile, "plussign", ""},
   237  	{testUserFile, "+plussign", ""},
   238  	{testUserFile, "minussign", ""},
   239  	{testUserFile, "-minussign", ""},
   240  	{testUserFile, "   indented", ""},
   241  	{testUserFile, "commented", ""},
   242  	{testUserFile, "commentindented", ""},
   243  	{testUserFile, "malformed", ""},
   244  	{testUserFile, "# commented", ""},
   245  	{"", "emptyfile", ""},
   246  }
   247  
   248  func TestLookupUser(t *testing.T) {
   249  	for _, tt := range userTests {
   250  		got, err := findUsername(tt.name, strings.NewReader(tt.in))
   251  		if tt.uid == "" {
   252  			if err == nil {
   253  				t.Errorf("lookupUser(%s): got nil error, expected err", tt.uid)
   254  				continue
   255  			}
   256  			switch terr := err.(type) {
   257  			case UnknownUserError:
   258  				if want := "user: unknown user " + tt.name; terr.Error() != want {
   259  					t.Errorf("lookupUser(%s): got %v, want %v", tt.name, terr, want)
   260  				}
   261  			default:
   262  				t.Errorf("lookupUser(%s): got unexpected error %v", tt.name, terr)
   263  			}
   264  		} else {
   265  			if err != nil {
   266  				t.Fatalf("lookupUser(%s): got unexpected error %v", tt.name, err)
   267  			}
   268  			if got.Uid != tt.uid {
   269  				t.Errorf("lookupUser(%s): got uid %v, want %s", tt.name, got.Uid, tt.uid)
   270  			}
   271  			if got.Username != tt.name {
   272  				t.Errorf("lookupUser(%s): got name %s, want %s", tt.name, got.Username, tt.name)
   273  			}
   274  		}
   275  	}
   276  }