// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build darwin dragonfly freebsd !android,linux nacl netbsd openbsd solaris
// +build !cgo

package user

import (
	"reflect"
	"strings"
	"testing"
)

const testGroupFile = `# See the opendirectoryd(8) man page for additional 
# information about Open Directory.
##
nobody:*:-2:
nogroup:*:-1:
wheel:*:0:root
emptyid:*::root
invalidgid:*:notanumber:root
+plussign:*:20:root
-minussign:*:21:root
      
daemon:*:1:root
    indented:*:7:
# comment:*:4:found
     # comment:*:4:found
kmem:*:2:root
`

var groupTests = []struct {
	in   string
	name string
	gid  string
}{
	{testGroupFile, "nobody", "-2"},
	{testGroupFile, "kmem", "2"},
	{testGroupFile, "notinthefile", ""},
	{testGroupFile, "comment", ""},
	{testGroupFile, "plussign", ""},
	{testGroupFile, "+plussign", ""},
	{testGroupFile, "-minussign", ""},
	{testGroupFile, "minussign", ""},
	{testGroupFile, "emptyid", ""},
	{testGroupFile, "invalidgid", ""},
	{testGroupFile, "indented", "7"},
	{testGroupFile, "# comment", ""},
	{"", "emptyfile", ""},
}

func TestFindGroupName(t *testing.T) {
	for _, tt := range groupTests {
		got, err := findGroupName(tt.name, strings.NewReader(tt.in))
		if tt.gid == "" {
			if err == nil {
				t.Errorf("findGroupName(%s): got nil error, expected err", tt.name)
				continue
			}
			switch terr := err.(type) {
			case UnknownGroupError:
				if terr.Error() != "group: unknown group "+tt.name {
					t.Errorf("findGroupName(%s): got %v, want %v", tt.name, terr, tt.name)
				}
			default:
				t.Errorf("findGroupName(%s): got unexpected error %v", tt.name, terr)
			}
		} else {
			if err != nil {
				t.Fatalf("findGroupName(%s): got unexpected error %v", tt.name, err)
			}
			if got.Gid != tt.gid {
				t.Errorf("findGroupName(%s): got gid %v, want %s", tt.name, got.Gid, tt.gid)
			}
			if got.Name != tt.name {
				t.Errorf("findGroupName(%s): got name %s, want %s", tt.name, got.Name, tt.name)
			}
		}
	}
}

var groupIdTests = []struct {
	in   string
	gid  string
	name string
}{
	{testGroupFile, "-2", "nobody"},
	{testGroupFile, "2", "kmem"},
	{testGroupFile, "notinthefile", ""},
	{testGroupFile, "comment", ""},
	{testGroupFile, "7", "indented"},
	{testGroupFile, "4", ""},
	{testGroupFile, "20", ""}, // row starts with a plus
	{testGroupFile, "21", ""}, // row starts with a minus
	{"", "emptyfile", ""},
}

func TestFindGroupId(t *testing.T) {
	for _, tt := range groupIdTests {
		got, err := findGroupId(tt.gid, strings.NewReader(tt.in))
		if tt.name == "" {
			if err == nil {
				t.Errorf("findGroupId(%s): got nil error, expected err", tt.gid)
				continue
			}
			switch terr := err.(type) {
			case UnknownGroupIdError:
				if terr.Error() != "group: unknown groupid "+tt.gid {
					t.Errorf("findGroupId(%s): got %v, want %v", tt.name, terr, tt.name)
				}
			default:
				t.Errorf("findGroupId(%s): got unexpected error %v", tt.name, terr)
			}
		} else {
			if err != nil {
				t.Fatalf("findGroupId(%s): got unexpected error %v", tt.name, err)
			}
			if got.Gid != tt.gid {
				t.Errorf("findGroupId(%s): got gid %v, want %s", tt.name, got.Gid, tt.gid)
			}
			if got.Name != tt.name {
				t.Errorf("findGroupId(%s): got name %s, want %s", tt.name, got.Name, tt.name)
			}
		}
	}
}

const testUserFile = `   # Example user file
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:3:bin:/bin:/usr/sbin/nologin
     indented:x:3:3:indented:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
negative:x:-5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
allfields:x:6:12:mansplit,man2,man3,man4:/home/allfields:/usr/sbin/nologin
+plussign:x:8:10:man:/var/cache/man:/usr/sbin/nologin
-minussign:x:9:10:man:/var/cache/man:/usr/sbin/nologin

malformed:x:27:12 # more:colons:after:comment

struid:x:notanumber:12 # more:colons:after:comment

# commented:x:28:12:commented:/var/cache/man:/usr/sbin/nologin
      # commentindented:x:29:12:commentindented:/var/cache/man:/usr/sbin/nologin

struid2:x:30:badgid:struid2name:/home/struid:/usr/sbin/nologin
`

var userIdTests = []struct {
	in   string
	uid  string
	name string
}{
	{testUserFile, "-5", "negative"},
	{testUserFile, "2", "bin"},
	{testUserFile, "100", ""}, // not in the file
	{testUserFile, "8", ""},   // plus sign, glibc doesn't find it
	{testUserFile, "9", ""},   // minus sign, glibc doesn't find it
	{testUserFile, "27", ""},  // malformed
	{testUserFile, "28", ""},  // commented out
	{testUserFile, "29", ""},  // commented out, indented
	{testUserFile, "3", "indented"},
	{testUserFile, "30", ""}, // the Gid is not valid, shouldn't match
	{"", "1", ""},
}

func TestInvalidUserId(t *testing.T) {
	_, err := findUserId("notanumber", strings.NewReader(""))
	if err == nil {
		t.Fatalf("findUserId('notanumber'): got nil error")
	}
	if want := "user: invalid userid notanumber"; err.Error() != want {
		t.Errorf("findUserId('notanumber'): got %v, want %s", err, want)
	}
}

func TestLookupUserId(t *testing.T) {
	for _, tt := range userIdTests {
		got, err := findUserId(tt.uid, strings.NewReader(tt.in))
		if tt.name == "" {
			if err == nil {
				t.Errorf("findUserId(%s): got nil error, expected err", tt.uid)
				continue
			}
			switch terr := err.(type) {
			case UnknownUserIdError:
				if want := "user: unknown userid " + tt.uid; terr.Error() != want {
					t.Errorf("findUserId(%s): got %v, want %v", tt.name, terr, want)
				}
			default:
				t.Errorf("findUserId(%s): got unexpected error %v", tt.name, terr)
			}
		} else {
			if err != nil {
				t.Fatalf("findUserId(%s): got unexpected error %v", tt.name, err)
			}
			if got.Uid != tt.uid {
				t.Errorf("findUserId(%s): got uid %v, want %s", tt.name, got.Uid, tt.uid)
			}
			if got.Username != tt.name {
				t.Errorf("findUserId(%s): got name %s, want %s", tt.name, got.Username, tt.name)
			}
		}
	}
}

func TestLookupUserPopulatesAllFields(t *testing.T) {
	u, err := findUsername("allfields", strings.NewReader(testUserFile))
	if err != nil {
		t.Fatal(err)
	}
	want := &User{
		Username: "allfields",
		Uid:      "6",
		Gid:      "12",
		Name:     "mansplit",
		HomeDir:  "/home/allfields",
	}
	if !reflect.DeepEqual(u, want) {
		t.Errorf("findUsername: got %#v, want %#v", u, want)
	}
}

var userTests = []struct {
	in   string
	name string
	uid  string
}{
	{testUserFile, "negative", "-5"},
	{testUserFile, "bin", "2"},
	{testUserFile, "notinthefile", ""},
	{testUserFile, "indented", "3"},
	{testUserFile, "plussign", ""},
	{testUserFile, "+plussign", ""},
	{testUserFile, "minussign", ""},
	{testUserFile, "-minussign", ""},
	{testUserFile, "   indented", ""},
	{testUserFile, "commented", ""},
	{testUserFile, "commentindented", ""},
	{testUserFile, "malformed", ""},
	{testUserFile, "# commented", ""},
	{"", "emptyfile", ""},
}

func TestLookupUser(t *testing.T) {
	for _, tt := range userTests {
		got, err := findUsername(tt.name, strings.NewReader(tt.in))
		if tt.uid == "" {
			if err == nil {
				t.Errorf("lookupUser(%s): got nil error, expected err", tt.uid)
				continue
			}
			switch terr := err.(type) {
			case UnknownUserError:
				if want := "user: unknown user " + tt.name; terr.Error() != want {
					t.Errorf("lookupUser(%s): got %v, want %v", tt.name, terr, want)
				}
			default:
				t.Errorf("lookupUser(%s): got unexpected error %v", tt.name, terr)
			}
		} else {
			if err != nil {
				t.Fatalf("lookupUser(%s): got unexpected error %v", tt.name, err)
			}
			if got.Uid != tt.uid {
				t.Errorf("lookupUser(%s): got uid %v, want %s", tt.name, got.Uid, tt.uid)
			}
			if got.Username != tt.name {
				t.Errorf("lookupUser(%s): got name %s, want %s", tt.name, got.Username, tt.name)
			}
		}
	}
}
