func TestGroupOnDemandRefresh(t *testing.T) {
	mock := newMock()
	mock.usersGroupsError = errors.New("")
	config := &Config{
		AccountRefreshFrequency: time.Hour,
		AccountRefreshCooldown:  0,
		KeyRefreshFrequency:     time.Hour,
		KeyRefreshCooldown:      0,
	}
	store := testStore(mock, config)
	mock.usersGroupsError = nil

	ch := registerCallback(config)
	testbase.RunCases(t, []testbase.TestCase{
		&testbase.FailureCase{
			`GroupByName("group1")`,
			func() (interface{}, error) { return store.GroupByName("group1") },
			`unable to find group with name "group1"`,
		},
	})
	<-ch
	removeCallback()
	testbase.RunCases(t, []testbase.TestCase{
		&testbase.SuccessCase{
			`GroupByName("group1")`,
			func() (interface{}, error) { return store.GroupByName("group1") },
			testbase.ExpGroups[0],
		},
	})
}
func TestGroupOnDemandRefresh(t *testing.T) {
	mock.Clear()
	mock.usersGroupsError = errors.New("")
	// No cooldown.
	config := &Config{time.Hour, 0, time.Hour, 0}
	store := testStore(mock, config)
	mock.usersGroupsError = nil

	ch := make(chan struct{})
	accountRefreshCallback = func() { close(ch) }
	testbase.RunCases(t, []testbase.TestCase{
		&testbase.FailureCase{
			`GroupByName("group1")`,
			func() (interface{}, error) { return store.GroupByName("group1") },
			`unable to find group with name "group1"`,
		},
	})
	<-ch
	accountRefreshCallback = func() {}
	ch = make(chan struct{})
	// Ensure keys are refreshed.
	keyRefreshCallback = func() { close(ch) }
	testbase.RunCases(t, []testbase.TestCase{
		&testbase.SuccessCase{
			`GroupByName("group1")`,
			func() (interface{}, error) { return store.GroupByName("group1") },
			testbase.ExpGroups[0],
		},
	})
	<-ch
	keyRefreshCallback = func() {}
	// First update and once for missing username.
	mock.AssertCalls(t, 2, 2)
}
func TestHugeData(t *testing.T) {
	// 1000 keys ranging from 1000 bytes to ~11 Kb.
	keys := make([]string, 1000)
	for x := range keys {
		key := make([]byte, 1000+(x*10))
		var b byte
		for y := range key {
			if rune(b) == '\n' {
				continue
			}
			key[y] = b
			b++
		}
		keys[x] = string(key)
	}
	socketPath = tempFile()
	mock := &testbase.MockProvider{Usrs: testbase.ExpUsers, Keys: map[string][]string{"user1": keys}}
	client := &Client{}
	startServer(mock)
	defer os.Remove(socketPath)
	testbase.RunCases(t, []testbase.TestCase{
		&testbase.SuccessCase{
			`AuthorizedKeys("user1")`,
			func() (interface{}, error) { return client.AuthorizedKeys("user1") },
			keys,
		},
	})
}
func TestKeysBasicCase(t *testing.T) {
	mock := newMock()
	config := &Config{
		AccountRefreshFrequency: time.Hour,
		AccountRefreshCooldown:  0,
		KeyRefreshFrequency:     time.Hour,
		KeyRefreshCooldown:      0,
	}
	store := testStore(mock, config)
	testbase.RunCases(t, []testbase.TestCase{
		&testbase.SuccessCase{
			`AuthorizedKeys("user1")`,
			func() (interface{}, error) { return store.AuthorizedKeys("user1") },
			testbase.ExpKeys["user1"],
		},
		&testbase.SuccessCase{
			`AuthorizedKeys("user2")`,
			func() (interface{}, error) { return store.AuthorizedKeys("user2") },
			[]string(nil),
		},
		&testbase.FailureCase{
			`AuthorizedKeys("user3")`,
			func() (interface{}, error) { return store.AuthorizedKeys("user3") },
			`unable to find user with name "user3"`,
		},
	})
}
func TestEmptyUsersGroups(t *testing.T) {
	emptyMock := &mockAPIClient{}
	config := &Config{time.Hour, time.Hour, time.Hour, 0}
	store := testStore(emptyMock, config)
	testbase.RunCases(t, []testbase.TestCase{
		&testbase.SuccessCase{
			"Names()",
			func() (interface{}, error) { return store.Names() },
			[]string{"gce-sudoers"},
		},
	})
}
func TestKeyCooldownAndRefresh(t *testing.T) {
	mTime := time.Now().UTC()
	// Mock time.
	timeNow = func() time.Time { return mTime }
	pulse := make(chan time.Time)
	timeAfter = func(time.Duration) <-chan time.Time { return pulse }
	mock := newMock()
	config := &Config{
		AccountRefreshFrequency: time.Hour,
		AccountRefreshCooldown:  0,
		KeyRefreshFrequency:     time.Second,
		KeyRefreshCooldown:      0,
	}
	store := testStore(mock, config)
	testbase.RunCases(t, []testbase.TestCase{
		&testbase.SuccessCase{
			`AuthorizedKeys("user1")`,
			func() (interface{}, error) { return store.AuthorizedKeys("user1") },
			testbase.ExpKeys["user1"],
		},
	})
	mock.keys["user1"] = []string{"key1"}

	mTime = mTime.Add(time.Second + time.Nanosecond)
	ch := registerCallback(config)
	// Trigger refresh.
	pulse <- mTime
	<-ch
	removeCallback()
	mock.keys["user1"] = []string{"key2"}
	testbase.RunCases(t, []testbase.TestCase{
		&testbase.SuccessCase{
			`AuthorizedKeys("user1")`,
			func() (interface{}, error) { return store.AuthorizedKeys("user1") },
			[]string{"key1"},
		},
	})
	timeAfter = time.After
	timeNow = time.Now
}
func TestEmptyKeys(t *testing.T) {
	emptyMock := &mockAPIClient{users: mock.users}
	config := &Config{time.Hour, time.Hour, time.Hour, 0}
	store := testStore(emptyMock, config)
	testbase.RunCases(t, []testbase.TestCase{
		&testbase.SuccessCase{
			`AuthorizedKeys("user1")`,
			func() (interface{}, error) { return store.AuthorizedKeys("user1") },
			[]string(nil),
		},
	})
	emptyMock.AssertCalls(t, 1, 3)
}
func TestKeyPrewarmingAndCaching(t *testing.T) {
	mock.Clear()
	// Background key refreshes happen every second.
	config := &Config{time.Hour, time.Hour, time.Hour, 0}
	store := testStore(mock, config)
	mock.keysError = errors.New("API error")
	testbase.RunCases(t, []testbase.TestCase{
		&testbase.SuccessCase{
			`AuthorizedKeys("user1")`,
			func() (interface{}, error) { return store.AuthorizedKeys("user1") },
			testbase.ExpKeys["user1"],
		},
		&testbase.SuccessCase{
			`AuthorizedKeys("user2")`,
			func() (interface{}, error) { return store.AuthorizedKeys("user2") },
			[]string(nil),
		},
	})
	mock.AssertCalls(t, 1, 4)
}
func TestKeyCooldownAndRefresh(t *testing.T) {
	mTime := time.Now().UTC()
	// Mock time.
	timeNow = func() time.Time { return mTime }
	pulse := make(chan time.Time)
	timeAfter = func(time.Duration) <-chan time.Time { return pulse }
	mock.Clear()
	// Background key refreshes happen every second.
	config := &Config{time.Hour, 0, time.Second, 0}
	store := testStore(mock, config)
	testbase.RunCases(t, []testbase.TestCase{
		&testbase.SuccessCase{
			`AuthorizedKeys("user1")`,
			func() (interface{}, error) { return store.AuthorizedKeys("user1") },
			testbase.ExpKeys["user1"],
		},
		&testbase.SuccessCase{
			`AuthorizedKeys("user2")`,
			func() (interface{}, error) { return store.AuthorizedKeys("user2") },
			[]string(nil),
		},
	})
	mock.AssertCalls(t, 1, 2)

	mTime = mTime.Add(time.Second + time.Nanosecond)
	ch := make(chan struct{})
	keyRefreshCallback = func() { close(ch) }
	// Trigger refresh.
	pulse <- mTime
	<-ch
	keyRefreshCallback = func() {}
	mock.AssertCalls(t, 2, 4)

	timeAfter = time.After
	timeNow = time.Now
}
func TestKeysBasicCase(t *testing.T) {
	mock.Clear()
	config := &Config{time.Hour, time.Hour, time.Hour, 0}
	store := testStore(mock, config)
	testbase.RunCases(t, []testbase.TestCase{
		&testbase.SuccessCase{
			`AuthorizedKeys("user1")`,
			func() (interface{}, error) { return store.AuthorizedKeys("user1") },
			testbase.ExpKeys["user1"],
		},
		&testbase.SuccessCase{
			`AuthorizedKeys("user2")`,
			func() (interface{}, error) { return store.AuthorizedKeys("user2") },
			[]string(nil),
		},
		&testbase.FailureCase{
			`AuthorizedKeys("user3")`,
			func() (interface{}, error) { return store.AuthorizedKeys("user3") },
			`unable to find user with name "user3"`,
		},
	})
	// Prewarm and on-demand key fetches.
	mock.AssertCalls(t, 1, 4)
}
func TestKeyPrewarmingAndCaching(t *testing.T) {
	mock := newMock()
	// Background key refreshes happen every second.
	config := &Config{
		AccountRefreshFrequency: time.Hour,
		AccountRefreshCooldown:  0,
		KeyRefreshFrequency:     time.Hour,
		KeyRefreshCooldown:      0,
	}
	store := testStore(mock, config)
	mock.keysError = errors.New("API error")
	testbase.RunCases(t, []testbase.TestCase{
		&testbase.SuccessCase{
			`AuthorizedKeys("user1")`,
			func() (interface{}, error) { return store.AuthorizedKeys("user1") },
			testbase.ExpKeys["user1"],
		},
		&testbase.SuccessCase{
			`AuthorizedKeys("user2")`,
			func() (interface{}, error) { return store.AuthorizedKeys("user2") },
			[]string(nil),
		},
	})
}
func TestAll(t *testing.T) {
	socketPath = tempFile()
	mock := &testbase.MockProvider{Usrs: testbase.ExpUsers, Grps: testbase.ExpGroups, Nams: testbase.ExpNames, Keys: testbase.ExpKeys}
	client := &Client{}
	startServer(mock)
	defer os.Remove(socketPath)
	testbase.RunCases(t, []testbase.TestCase{
		&testbase.SuccessCase{
			`UserByName("user1")`,
			func() (interface{}, error) { return client.UserByName("user1") },
			testbase.ExpUsers[0],
		},
		&testbase.SuccessCase{
			"UserByUID(1002)",
			func() (interface{}, error) { return client.UserByUID(1002) },
			testbase.ExpUsers[1],
		},
		&testbase.SuccessCase{
			`GroupByName("group1")`,
			func() (interface{}, error) { return client.GroupByName("group1") },
			testbase.ExpGroups[0],
		},
		&testbase.SuccessCase{
			"GroupByGID(1001)",
			func() (interface{}, error) { return client.GroupByGID(1001) },
			testbase.ExpGroups[1],
		},
		&testbase.SuccessCase{
			"Users()",
			func() (interface{}, error) { return client.Users() },
			testbase.ExpUsers,
		},
		&testbase.SuccessCase{
			"Groups()",
			func() (interface{}, error) { return client.Groups() },
			testbase.ExpGroups,
		},
		&testbase.SuccessCase{
			"Names()",
			func() (interface{}, error) { return client.Names() },
			testbase.ExpNames,
		},
		&testbase.SuccessCase{
			`IsName("user1")`,
			func() (interface{}, error) { return client.IsName("user1") },
			true,
		},
		&testbase.SuccessCase{
			`IsName("group1")`,
			func() (interface{}, error) { return client.IsName("group1") },
			true,
		},
		&testbase.SuccessCase{
			`IsName("nil")`,
			func() (interface{}, error) { return client.IsName("nil") },
			false,
		},
		&testbase.SuccessCase{
			`AuthorizedKeys("user1")`,
			func() (interface{}, error) { return client.AuthorizedKeys("user1") },
			testbase.ExpKeys["user1"],
		},
		&testbase.SuccessCase{
			`AuthorizedKeys("user2")`,
			func() (interface{}, error) { return client.AuthorizedKeys("user2") },
			[]string{},
		},
		&testbase.FailureCase{
			`UserByName("nil")`,
			func() (interface{}, error) { return client.UserByName("nil") },
			"unable to find user or group",
		},
		&testbase.FailureCase{
			"UserByUID(2)",
			func() (interface{}, error) { return client.UserByUID(2) },
			"unable to find user or group",
		},
		&testbase.FailureCase{
			`GroupByName("nil")`,
			func() (interface{}, error) { return client.GroupByName("nil") },
			"unable to find user or group",
		},
		&testbase.FailureCase{
			"GroupByGID(1)",
			func() (interface{}, error) { return client.GroupByGID(1) },
			"unable to find user or group",
		},
	})
	mock.Err = errors.New("")
	testbase.RunCases(t, []testbase.TestCase{
		&testbase.FailureCase{
			`UserByName("user1")`,
			func() (interface{}, error) { return client.UserByName("user1") },
			"request failed",
		},
		&testbase.FailureCase{
			"UserByUID(1002)",
			func() (interface{}, error) { return client.UserByUID(1002) },
			"request failed",
		},
		&testbase.FailureCase{
			`GroupByName("group1")`,
			func() (interface{}, error) { return client.GroupByName("group1") },
			"request failed",
		},
		&testbase.FailureCase{
			"GroupByGID(1001)",
			func() (interface{}, error) { return client.GroupByGID(1001) },
			"request failed",
		},
		&testbase.FailureCase{
			"Users()",
			func() (interface{}, error) { return client.Users() },
			"request failed",
		},
		&testbase.FailureCase{
			"Groups()",
			func() (interface{}, error) { return client.Groups() },
			"request failed",
		},
		&testbase.FailureCase{
			"Names()",
			func() (interface{}, error) { return client.Names() },
			"request failed",
		},
		&testbase.FailureCase{
			`IsName("user1")`,
			func() (interface{}, error) { return client.IsName("user1") },
			"request failed",
		},
		&testbase.FailureCase{
			`IsName("group1")`,
			func() (interface{}, error) { return client.IsName("group1") },
			"request failed",
		},
		&testbase.FailureCase{
			`IsName("nil")`,
			func() (interface{}, error) { return client.IsName("nil") },
			"request failed",
		},
		&testbase.FailureCase{
			`AuthorizedKeys("user1")`,
			func() (interface{}, error) { return client.AuthorizedKeys("user1") },
			"request failed",
		},
	})
}
func TestUsersGroups(t *testing.T) {
	mock.Clear()
	config := &Config{time.Hour, time.Hour, time.Hour, 0}
	store := testStore(mock, config)
	testbase.RunCases(t, []testbase.TestCase{
		&testbase.SuccessCase{
			`UserByName("user1")`,
			func() (interface{}, error) { return store.UserByName("user1") },
			testbase.ExpUsers[0],
		},
		&testbase.SuccessCase{
			"UserByUID(4002)",
			func() (interface{}, error) { return store.UserByUID(4002) },
			testbase.ExpUsers[1],
		},
		&testbase.SuccessCase{
			`GroupByName("group1")`,
			func() (interface{}, error) { return store.GroupByName("group1") },
			testbase.ExpGroups[0],
		},
		&testbase.SuccessCase{
			"GroupByGID(4001)",
			func() (interface{}, error) { return store.GroupByGID(4001) },
			testbase.ExpGroups[1],
		},
		&testbase.SuccessCase{
			"Users()",
			func() (interface{}, error) { r, e := store.Users(); sort.Sort(userSlice(r)); return r, e },
			testbase.ExpUsers,
		},
		&testbase.SuccessCase{
			"Groups()",
			func() (interface{}, error) { r, e := store.Groups(); sort.Sort(groupSlice(r)); return r, e },
			testbase.ExpGroups,
		},
		&testbase.SuccessCase{
			"Names()",
			func() (interface{}, error) { r, e := store.Names(); sort.Sort(sort.StringSlice(r)); return r, e },
			testbase.ExpNames,
		},
		&testbase.SuccessCase{
			`IsName("user1")`,
			func() (interface{}, error) { return store.IsName("user1") },
			true,
		},
		&testbase.SuccessCase{
			`IsName("group1")`,
			func() (interface{}, error) { return store.IsName("group1") },
			true,
		},
		&testbase.SuccessCase{
			`IsName("nil")`,
			func() (interface{}, error) { return store.IsName("nil") },
			false,
		},
		&testbase.FailureCase{
			`UserByName("nil")`,
			func() (interface{}, error) { return store.UserByName("nil") },
			`unable to find user with name "nil"`,
		},
		&testbase.FailureCase{
			"UserByUID(2)",
			func() (interface{}, error) { return store.UserByUID(2) },
			"unable to find user with UID 2",
		},
		&testbase.FailureCase{
			`GroupByName("nil")`,
			func() (interface{}, error) { return store.GroupByName("nil") },
			`unable to find group with name "nil"`,
		},
		&testbase.FailureCase{
			"GroupByGID(1)",
			func() (interface{}, error) { return store.GroupByGID(1) },
			"unable to find group with GID 1",
		},
	})
	// First refresh and key prewarm.
	mock.AssertCalls(t, 1, 2)
}
func TestUsersGroups(t *testing.T) {
	mock := newMock()
	config := &Config{
		AccountRefreshFrequency: time.Hour,
		AccountRefreshCooldown:  0,
		KeyRefreshFrequency:     time.Hour,
		KeyRefreshCooldown:      0,
	}
	store := testStore(mock, config)
	testbase.RunCases(t, []testbase.TestCase{
		&testbase.SuccessCase{
			`UserByName("user1")`,
			func() (interface{}, error) { return store.UserByName("user1") },
			testbase.ExpUsers[0],
		},
		&testbase.SuccessCase{
			"UserByUID(1002)",
			func() (interface{}, error) { return store.UserByUID(1002) },
			testbase.ExpUsers[1],
		},
		&testbase.SuccessCase{
			`GroupByName("group1")`,
			func() (interface{}, error) { return store.GroupByName("group1") },
			testbase.ExpGroups[0],
		},
		&testbase.SuccessCase{
			`GroupByName("gce-sudoers")`,
			func() (interface{}, error) { return store.GroupByName("gce-sudoers") },
			expSudoers,
		},
		&testbase.SuccessCase{
			"GroupByGID(1001)",
			func() (interface{}, error) { return store.GroupByGID(1001) },
			testbase.ExpGroups[1],
		},
		&testbase.SuccessCase{
			"GroupByGID(4001)",
			func() (interface{}, error) { return store.GroupByGID(4001) },
			expSudoers,
		},
		&testbase.SuccessCase{
			"Users()",
			func() (interface{}, error) { r, e := store.Users(); sort.Sort(userSlice(r)); return r, e },
			testbase.ExpUsers,
		},
		&testbase.SuccessCase{
			"Groups()",
			func() (interface{}, error) { r, e := store.Groups(); sort.Sort(groupSlice(r)); return r, e },
			append([]*accounts.Group{expSudoers}, testbase.ExpGroups...),
		},
		&testbase.SuccessCase{
			"Names()",
			func() (interface{}, error) { r, e := store.Names(); sort.Sort(sort.StringSlice(r)); return r, e },
			append([]string{"gce-sudoers"}, testbase.ExpNames...),
		},
		&testbase.SuccessCase{
			`IsName("user1")`,
			func() (interface{}, error) { return store.IsName("user1") },
			true,
		},
		&testbase.SuccessCase{
			`IsName("group1")`,
			func() (interface{}, error) { return store.IsName("group1") },
			true,
		},
		&testbase.SuccessCase{
			`IsName("gce-sudoers")`,
			func() (interface{}, error) { return store.IsName("gce-sudoers") },
			true,
		},
		&testbase.SuccessCase{
			`IsName("nil")`,
			func() (interface{}, error) { return store.IsName("nil") },
			false,
		},
		&testbase.FailureCase{
			`UserByName("nil")`,
			func() (interface{}, error) { return store.UserByName("nil") },
			`unable to find user with name "nil"`,
		},
		&testbase.FailureCase{
			"UserByUID(2)",
			func() (interface{}, error) { return store.UserByUID(2) },
			"unable to find user with UID 2",
		},
		&testbase.FailureCase{
			`GroupByName("nil")`,
			func() (interface{}, error) { return store.GroupByName("nil") },
			`unable to find group with name "nil"`,
		},
		&testbase.FailureCase{
			"GroupByGID(1)",
			func() (interface{}, error) { return store.GroupByGID(1) },
			"unable to find group with GID 1",
		},
	})
}