Source file src/os/user/user_test.go

     1  // Copyright 2011 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  package user
     6  
     7  import (
     8  	"os"
     9  	"slices"
    10  	"testing"
    11  )
    12  
    13  var (
    14  	hasCgo  = false
    15  	hasUSER = os.Getenv("USER") != ""
    16  	hasHOME = os.Getenv("HOME") != ""
    17  )
    18  
    19  func checkUser(t *testing.T) {
    20  	t.Helper()
    21  	if !userImplemented {
    22  		t.Skip("user: not implemented; skipping tests")
    23  	}
    24  }
    25  
    26  func TestCurrent(t *testing.T) {
    27  	old := userBuffer
    28  	defer func() {
    29  		userBuffer = old
    30  	}()
    31  	userBuffer = 1 // force use of retry code
    32  	u, err := Current()
    33  	if err != nil {
    34  		if hasCgo || (hasUSER && hasHOME) {
    35  			t.Fatalf("Current: %v (got %#v)", err, u)
    36  		} else {
    37  			t.Skipf("skipping: %v", err)
    38  		}
    39  	}
    40  	if u.HomeDir == "" {
    41  		t.Errorf("didn't get a HomeDir")
    42  	}
    43  	if u.Username == "" {
    44  		t.Errorf("didn't get a username")
    45  	}
    46  }
    47  
    48  func BenchmarkCurrent(b *testing.B) {
    49  	// Benchmark current instead of Current because Current caches the result.
    50  	for i := 0; i < b.N; i++ {
    51  		current()
    52  	}
    53  }
    54  
    55  func compare(t *testing.T, want, got *User) {
    56  	if want.Uid != got.Uid {
    57  		t.Errorf("got Uid=%q; want %q", got.Uid, want.Uid)
    58  	}
    59  	if want.Username != got.Username {
    60  		t.Errorf("got Username=%q; want %q", got.Username, want.Username)
    61  	}
    62  	if want.Name != got.Name {
    63  		t.Errorf("got Name=%q; want %q", got.Name, want.Name)
    64  	}
    65  	if want.HomeDir != got.HomeDir {
    66  		t.Errorf("got HomeDir=%q; want %q", got.HomeDir, want.HomeDir)
    67  	}
    68  	if want.Gid != got.Gid {
    69  		t.Errorf("got Gid=%q; want %q", got.Gid, want.Gid)
    70  	}
    71  }
    72  
    73  func TestLookup(t *testing.T) {
    74  	checkUser(t)
    75  
    76  	want, err := Current()
    77  	if err != nil {
    78  		if hasCgo || (hasUSER && hasHOME) {
    79  			t.Fatalf("Current: %v", err)
    80  		} else {
    81  			t.Skipf("skipping: %v", err)
    82  		}
    83  	}
    84  
    85  	// TODO: Lookup() has a fast path that calls Current() and returns if the
    86  	// usernames match, so this test does not exercise very much. It would be
    87  	// good to try and test finding a different user than the current user.
    88  	got, err := Lookup(want.Username)
    89  	if err != nil {
    90  		t.Fatalf("Lookup: %v", err)
    91  	}
    92  	compare(t, want, got)
    93  }
    94  
    95  func TestLookupId(t *testing.T) {
    96  	checkUser(t)
    97  
    98  	want, err := Current()
    99  	if err != nil {
   100  		if hasCgo || (hasUSER && hasHOME) {
   101  			t.Fatalf("Current: %v", err)
   102  		} else {
   103  			t.Skipf("skipping: %v", err)
   104  		}
   105  	}
   106  
   107  	got, err := LookupId(want.Uid)
   108  	if err != nil {
   109  		t.Fatalf("LookupId: %v", err)
   110  	}
   111  	compare(t, want, got)
   112  }
   113  
   114  func checkGroup(t *testing.T) {
   115  	t.Helper()
   116  	if !groupImplemented {
   117  		t.Skip("user: group not implemented; skipping test")
   118  	}
   119  }
   120  
   121  func TestLookupGroup(t *testing.T) {
   122  	old := groupBuffer
   123  	defer func() {
   124  		groupBuffer = old
   125  	}()
   126  	groupBuffer = 1 // force use of retry code
   127  	checkGroup(t)
   128  
   129  	user, err := Current()
   130  	if err != nil {
   131  		if hasCgo || (hasUSER && hasHOME) {
   132  			t.Fatalf("Current: %v", err)
   133  		} else {
   134  			t.Skipf("skipping: %v", err)
   135  		}
   136  	}
   137  
   138  	g1, err := LookupGroupId(user.Gid)
   139  	if err != nil {
   140  		// NOTE(rsc): Maybe the group isn't defined. That's fine.
   141  		// On my OS X laptop, rsc logs in with group 5000 even
   142  		// though there's no name for group 5000. Such is Unix.
   143  		t.Logf("LookupGroupId(%q): %v", user.Gid, err)
   144  		return
   145  	}
   146  	if g1.Gid != user.Gid {
   147  		t.Errorf("LookupGroupId(%q).Gid = %s; want %s", user.Gid, g1.Gid, user.Gid)
   148  	}
   149  
   150  	g2, err := LookupGroup(g1.Name)
   151  	if err != nil {
   152  		t.Fatalf("LookupGroup(%q): %v", g1.Name, err)
   153  	}
   154  	if g1.Gid != g2.Gid || g1.Name != g2.Name {
   155  		t.Errorf("LookupGroup(%q) = %+v; want %+v", g1.Name, g2, g1)
   156  	}
   157  }
   158  
   159  func checkGroupList(t *testing.T) {
   160  	t.Helper()
   161  	if !groupListImplemented {
   162  		t.Skip("user: group list not implemented; skipping test")
   163  	}
   164  }
   165  
   166  func TestGroupIds(t *testing.T) {
   167  	checkGroupList(t)
   168  
   169  	user, err := Current()
   170  	if err != nil {
   171  		if hasCgo || (hasUSER && hasHOME) {
   172  			t.Fatalf("Current: %v", err)
   173  		} else {
   174  			t.Skipf("skipping: %v", err)
   175  		}
   176  	}
   177  
   178  	gids, err := user.GroupIds()
   179  	if err != nil {
   180  		t.Fatalf("%+v.GroupIds(): %v", user, err)
   181  	}
   182  	if !slices.Contains(gids, user.Gid) {
   183  		t.Errorf("%+v.GroupIds() = %v; does not contain user GID %s", user, gids, user.Gid)
   184  	}
   185  }
   186  

View as plain text