Source file src/os/user/lookup_unix_test.go

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

View as plain text