github.com/dctrud/umoci@v0.4.3-0.20191016193643-05a1d37de015/third_party/user/user_test.go (about)

     1  package user
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"reflect"
     7  	"sort"
     8  	"strings"
     9  	"testing"
    10  	"unsafe"
    11  )
    12  
    13  func TestUserParseLine(t *testing.T) {
    14  	var (
    15  		a, b string
    16  		c    []string
    17  		d    int
    18  	)
    19  
    20  	parseLine("", &a, &b)
    21  	if a != "" || b != "" {
    22  		t.Fatalf("a and b should be empty ('%v', '%v')", a, b)
    23  	}
    24  
    25  	parseLine("a", &a, &b)
    26  	if a != "a" || b != "" {
    27  		t.Fatalf("a should be 'a' and b should be empty ('%v', '%v')", a, b)
    28  	}
    29  
    30  	parseLine("bad boys:corny cows", &a, &b)
    31  	if a != "bad boys" || b != "corny cows" {
    32  		t.Fatalf("a should be 'bad boys' and b should be 'corny cows' ('%v', '%v')", a, b)
    33  	}
    34  
    35  	parseLine("", &c)
    36  	if len(c) != 0 {
    37  		t.Fatalf("c should be empty (%#v)", c)
    38  	}
    39  
    40  	parseLine("d,e,f:g:h:i,j,k", &c, &a, &b, &c)
    41  	if a != "g" || b != "h" || len(c) != 3 || c[0] != "i" || c[1] != "j" || c[2] != "k" {
    42  		t.Fatalf("a should be 'g', b should be 'h', and c should be ['i','j','k'] ('%v', '%v', '%#v')", a, b, c)
    43  	}
    44  
    45  	parseLine("::::::::::", &a, &b, &c)
    46  	if a != "" || b != "" || len(c) != 0 {
    47  		t.Fatalf("a, b, and c should all be empty ('%v', '%v', '%#v')", a, b, c)
    48  	}
    49  
    50  	parseLine("not a number", &d)
    51  	if d != 0 {
    52  		t.Fatalf("d should be 0 (%v)", d)
    53  	}
    54  
    55  	parseLine("b:12:c", &a, &d, &b)
    56  	if a != "b" || b != "c" || d != 12 {
    57  		t.Fatalf("a should be 'b' and b should be 'c', and d should be 12 ('%v', '%v', %v)", a, b, d)
    58  	}
    59  }
    60  
    61  func TestUserParsePasswd(t *testing.T) {
    62  	users, err := ParsePasswdFilter(strings.NewReader(`
    63  root:x:0:0:root:/root:/bin/bash
    64  adm:x:3:4:adm:/var/adm:/bin/false
    65  this is just some garbage data
    66  `), nil)
    67  	if err != nil {
    68  		t.Fatalf("Unexpected error: %v", err)
    69  	}
    70  	if len(users) != 3 {
    71  		t.Fatalf("Expected 3 users, got %v", len(users))
    72  	}
    73  	if users[0].Uid != 0 || users[0].Name != "root" {
    74  		t.Fatalf("Expected users[0] to be 0 - root, got %v - %v", users[0].Uid, users[0].Name)
    75  	}
    76  	if users[1].Uid != 3 || users[1].Name != "adm" {
    77  		t.Fatalf("Expected users[1] to be 3 - adm, got %v - %v", users[1].Uid, users[1].Name)
    78  	}
    79  }
    80  
    81  func TestUserParseGroup(t *testing.T) {
    82  	groups, err := ParseGroupFilter(strings.NewReader(`
    83  root:x:0:root
    84  adm:x:4:root,adm,daemon
    85  this is just some garbage data
    86  `), nil)
    87  	if err != nil {
    88  		t.Fatalf("Unexpected error: %v", err)
    89  	}
    90  	if len(groups) != 3 {
    91  		t.Fatalf("Expected 3 groups, got %v", len(groups))
    92  	}
    93  	if groups[0].Gid != 0 || groups[0].Name != "root" || len(groups[0].List) != 1 {
    94  		t.Fatalf("Expected groups[0] to be 0 - root - 1 member, got %v - %v - %v", groups[0].Gid, groups[0].Name, len(groups[0].List))
    95  	}
    96  	if groups[1].Gid != 4 || groups[1].Name != "adm" || len(groups[1].List) != 3 {
    97  		t.Fatalf("Expected groups[1] to be 4 - adm - 3 members, got %v - %v - %v", groups[1].Gid, groups[1].Name, len(groups[1].List))
    98  	}
    99  }
   100  
   101  func TestValidGetExecUser(t *testing.T) {
   102  	const passwdContent = `
   103  root:x:0:0:root user:/root:/bin/bash
   104  adm:x:42:43:adm:/var/adm:/bin/false
   105  111:x:222:333::/var/garbage
   106  odd:x:111:112::/home/odd:::::
   107  this is just some garbage data
   108  `
   109  	const groupContent = `
   110  root:x:0:root
   111  adm:x:43:
   112  grp:x:1234:root,adm
   113  444:x:555:111
   114  odd:x:444:
   115  this is just some garbage data
   116  `
   117  	defaultExecUser := ExecUser{
   118  		Uid:   8888,
   119  		Gid:   8888,
   120  		Sgids: []int{8888},
   121  		Home:  "/8888",
   122  	}
   123  
   124  	tests := []struct {
   125  		ref      string
   126  		expected ExecUser
   127  	}{
   128  		{
   129  			ref: "root",
   130  			expected: ExecUser{
   131  				Uid:   0,
   132  				Gid:   0,
   133  				Sgids: []int{0, 1234},
   134  				Home:  "/root",
   135  			},
   136  		},
   137  		{
   138  			ref: "adm",
   139  			expected: ExecUser{
   140  				Uid:   42,
   141  				Gid:   43,
   142  				Sgids: []int{1234},
   143  				Home:  "/var/adm",
   144  			},
   145  		},
   146  		{
   147  			ref: "root:adm",
   148  			expected: ExecUser{
   149  				Uid:   0,
   150  				Gid:   43,
   151  				Sgids: defaultExecUser.Sgids,
   152  				Home:  "/root",
   153  			},
   154  		},
   155  		{
   156  			ref: "adm:1234",
   157  			expected: ExecUser{
   158  				Uid:   42,
   159  				Gid:   1234,
   160  				Sgids: defaultExecUser.Sgids,
   161  				Home:  "/var/adm",
   162  			},
   163  		},
   164  		{
   165  			ref: "42:1234",
   166  			expected: ExecUser{
   167  				Uid:   42,
   168  				Gid:   1234,
   169  				Sgids: defaultExecUser.Sgids,
   170  				Home:  "/var/adm",
   171  			},
   172  		},
   173  		{
   174  			ref: "1337:1234",
   175  			expected: ExecUser{
   176  				Uid:   1337,
   177  				Gid:   1234,
   178  				Sgids: defaultExecUser.Sgids,
   179  				Home:  defaultExecUser.Home,
   180  			},
   181  		},
   182  		{
   183  			ref: "1337",
   184  			expected: ExecUser{
   185  				Uid:   1337,
   186  				Gid:   defaultExecUser.Gid,
   187  				Sgids: defaultExecUser.Sgids,
   188  				Home:  defaultExecUser.Home,
   189  			},
   190  		},
   191  		{
   192  			ref: "",
   193  			expected: ExecUser{
   194  				Uid:   defaultExecUser.Uid,
   195  				Gid:   defaultExecUser.Gid,
   196  				Sgids: defaultExecUser.Sgids,
   197  				Home:  defaultExecUser.Home,
   198  			},
   199  		},
   200  
   201  		// Regression tests for #695.
   202  		{
   203  			ref: "111",
   204  			expected: ExecUser{
   205  				Uid:   111,
   206  				Gid:   112,
   207  				Sgids: defaultExecUser.Sgids,
   208  				Home:  "/home/odd",
   209  			},
   210  		},
   211  		{
   212  			ref: "111:444",
   213  			expected: ExecUser{
   214  				Uid:   111,
   215  				Gid:   444,
   216  				Sgids: defaultExecUser.Sgids,
   217  				Home:  "/home/odd",
   218  			},
   219  		},
   220  	}
   221  
   222  	for _, test := range tests {
   223  		passwd := strings.NewReader(passwdContent)
   224  		group := strings.NewReader(groupContent)
   225  
   226  		execUser, err := GetExecUser(test.ref, &defaultExecUser, passwd, group)
   227  		if err != nil {
   228  			t.Logf("got unexpected error when parsing '%s': %s", test.ref, err.Error())
   229  			t.Fail()
   230  			continue
   231  		}
   232  
   233  		if !reflect.DeepEqual(test.expected, *execUser) {
   234  			t.Logf("ref:      %v", test.ref)
   235  			t.Logf("got:      %#v", execUser)
   236  			t.Logf("expected: %#v", test.expected)
   237  			t.Fail()
   238  			continue
   239  		}
   240  	}
   241  }
   242  
   243  func TestInvalidGetExecUser(t *testing.T) {
   244  	const passwdContent = `
   245  root:x:0:0:root user:/root:/bin/bash
   246  adm:x:42:43:adm:/var/adm:/bin/false
   247  -42:x:12:13:broken:/very/broken
   248  this is just some garbage data
   249  `
   250  	const groupContent = `
   251  root:x:0:root
   252  adm:x:43:
   253  grp:x:1234:root,adm
   254  this is just some garbage data
   255  `
   256  
   257  	tests := []string{
   258  		// No such user/group.
   259  		"notuser",
   260  		"notuser:notgroup",
   261  		"root:notgroup",
   262  		"notuser:adm",
   263  		"8888:notgroup",
   264  		"notuser:8888",
   265  
   266  		// Invalid user/group values.
   267  		"-1:0",
   268  		"0:-3",
   269  		"-5:-2",
   270  		"-42",
   271  		"-43",
   272  	}
   273  
   274  	for _, test := range tests {
   275  		passwd := strings.NewReader(passwdContent)
   276  		group := strings.NewReader(groupContent)
   277  
   278  		execUser, err := GetExecUser(test, nil, passwd, group)
   279  		if err == nil {
   280  			t.Logf("got unexpected success when parsing '%s': %#v", test, execUser)
   281  			t.Fail()
   282  			continue
   283  		}
   284  	}
   285  }
   286  
   287  func TestGetExecUserNilSources(t *testing.T) {
   288  	const passwdContent = `
   289  root:x:0:0:root user:/root:/bin/bash
   290  adm:x:42:43:adm:/var/adm:/bin/false
   291  this is just some garbage data
   292  `
   293  	const groupContent = `
   294  root:x:0:root
   295  adm:x:43:
   296  grp:x:1234:root,adm
   297  this is just some garbage data
   298  `
   299  
   300  	defaultExecUser := ExecUser{
   301  		Uid:   8888,
   302  		Gid:   8888,
   303  		Sgids: []int{8888},
   304  		Home:  "/8888",
   305  	}
   306  
   307  	tests := []struct {
   308  		ref           string
   309  		passwd, group bool
   310  		expected      ExecUser
   311  	}{
   312  		{
   313  			ref:    "",
   314  			passwd: false,
   315  			group:  false,
   316  			expected: ExecUser{
   317  				Uid:   8888,
   318  				Gid:   8888,
   319  				Sgids: []int{8888},
   320  				Home:  "/8888",
   321  			},
   322  		},
   323  		{
   324  			ref:    "root",
   325  			passwd: true,
   326  			group:  false,
   327  			expected: ExecUser{
   328  				Uid:   0,
   329  				Gid:   0,
   330  				Sgids: []int{8888},
   331  				Home:  "/root",
   332  			},
   333  		},
   334  		{
   335  			ref:    "0",
   336  			passwd: false,
   337  			group:  false,
   338  			expected: ExecUser{
   339  				Uid:   0,
   340  				Gid:   8888,
   341  				Sgids: []int{8888},
   342  				Home:  "/8888",
   343  			},
   344  		},
   345  		{
   346  			ref:    "0:0",
   347  			passwd: false,
   348  			group:  false,
   349  			expected: ExecUser{
   350  				Uid:   0,
   351  				Gid:   0,
   352  				Sgids: []int{8888},
   353  				Home:  "/8888",
   354  			},
   355  		},
   356  	}
   357  
   358  	for _, test := range tests {
   359  		var passwd, group io.Reader
   360  
   361  		if test.passwd {
   362  			passwd = strings.NewReader(passwdContent)
   363  		}
   364  
   365  		if test.group {
   366  			group = strings.NewReader(groupContent)
   367  		}
   368  
   369  		execUser, err := GetExecUser(test.ref, &defaultExecUser, passwd, group)
   370  		if err != nil {
   371  			t.Logf("got unexpected error when parsing '%s': %s", test.ref, err.Error())
   372  			t.Fail()
   373  			continue
   374  		}
   375  
   376  		if !reflect.DeepEqual(test.expected, *execUser) {
   377  			t.Logf("got:      %#v", execUser)
   378  			t.Logf("expected: %#v", test.expected)
   379  			t.Fail()
   380  			continue
   381  		}
   382  	}
   383  }
   384  
   385  func TestGetAdditionalGroups(t *testing.T) {
   386  	type foo struct {
   387  		groups   []string
   388  		expected []int
   389  		hasError bool
   390  	}
   391  
   392  	const groupContent = `
   393  root:x:0:root
   394  adm:x:43:
   395  grp:x:1234:root,adm
   396  adm:x:4343:root,adm-duplicate
   397  this is just some garbage data
   398  `
   399  	tests := []foo{
   400  		{
   401  			// empty group
   402  			groups:   []string{},
   403  			expected: []int{},
   404  		},
   405  		{
   406  			// single group
   407  			groups:   []string{"adm"},
   408  			expected: []int{43},
   409  		},
   410  		{
   411  			// multiple groups
   412  			groups:   []string{"adm", "grp"},
   413  			expected: []int{43, 1234},
   414  		},
   415  		{
   416  			// invalid group
   417  			groups:   []string{"adm", "grp", "not-exist"},
   418  			expected: nil,
   419  			hasError: true,
   420  		},
   421  		{
   422  			// group with numeric id
   423  			groups:   []string{"43"},
   424  			expected: []int{43},
   425  		},
   426  		{
   427  			// group with unknown numeric id
   428  			groups:   []string{"adm", "10001"},
   429  			expected: []int{43, 10001},
   430  		},
   431  		{
   432  			// groups specified twice with numeric and name
   433  			groups:   []string{"adm", "43"},
   434  			expected: []int{43},
   435  		},
   436  		{
   437  			// groups with too small id
   438  			groups:   []string{"-1"},
   439  			expected: nil,
   440  			hasError: true,
   441  		},
   442  	}
   443  
   444  	if int(unsafe.Sizeof(1)) > 4 {
   445  		tests = append(tests, foo{
   446  			// groups with too large id
   447  			groups:   []string{fmt.Sprintf("%d", int64(1<<31))},
   448  			expected: nil,
   449  			hasError: true,
   450  		})
   451  	}
   452  
   453  	for _, test := range tests {
   454  		group := strings.NewReader(groupContent)
   455  
   456  		gids, err := GetAdditionalGroups(test.groups, group)
   457  		if test.hasError && err == nil {
   458  			t.Errorf("Parse(%#v) expects error but has none", test)
   459  			continue
   460  		}
   461  		if !test.hasError && err != nil {
   462  			t.Errorf("Parse(%#v) has error %v", test, err)
   463  			continue
   464  		}
   465  		sort.Sort(sort.IntSlice(gids))
   466  		if !reflect.DeepEqual(gids, test.expected) {
   467  			t.Errorf("Gids(%v), expect %v from groups %v", gids, test.expected, test.groups)
   468  		}
   469  	}
   470  }
   471  
   472  func TestGetAdditionalGroupsNumeric(t *testing.T) {
   473  	tests := []struct {
   474  		groups   []string
   475  		expected []int
   476  		hasError bool
   477  	}{
   478  		{
   479  			// numeric groups only
   480  			groups:   []string{"1234", "5678"},
   481  			expected: []int{1234, 5678},
   482  		},
   483  		{
   484  			// numeric and alphabetic
   485  			groups:   []string{"1234", "fake"},
   486  			expected: nil,
   487  			hasError: true,
   488  		},
   489  	}
   490  
   491  	for _, test := range tests {
   492  		gids, err := GetAdditionalGroups(test.groups, nil)
   493  		if test.hasError && err == nil {
   494  			t.Errorf("Parse(%#v) expects error but has none", test)
   495  			continue
   496  		}
   497  		if !test.hasError && err != nil {
   498  			t.Errorf("Parse(%#v) has error %v", test, err)
   499  			continue
   500  		}
   501  		sort.Sort(sort.IntSlice(gids))
   502  		if !reflect.DeepEqual(gids, test.expected) {
   503  			t.Errorf("Gids(%v), expect %v from groups %v", gids, test.expected, test.groups)
   504  		}
   505  	}
   506  }