blob: 16a7b29e789f133e1b6b7b2961ba845eacecab1b [file] [log] [blame]
// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "login_manager/session_manager_impl.h"
#include <unistd.h>
#include <algorithm>
#include <map>
#include <string>
#include <vector>
#include <base/basictypes.h>
#include <base/bind.h>
#include <base/callback.h>
#include <base/command_line.h>
#include <base/file_util.h>
#include <base/files/file_path.h>
#include <base/files/scoped_temp_dir.h>
#include <base/memory/ref_counted.h>
#include <base/message_loop/message_loop.h>
#include <base/message_loop/message_loop_proxy.h>
#include <base/strings/string_util.h>
#include <chromeos/cryptohome.h>
#include <chromeos/dbus/service_constants.h>
#include <crypto/scoped_nss_types.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "login_manager/dbus_error_types.h"
#include "login_manager/device_local_account_policy_service.h"
#include "login_manager/device_management_backend.pb.h"
#include "login_manager/file_checker.h"
#include "login_manager/matchers.h"
#include "login_manager/mock_dbus_signal_emitter.h"
#include "login_manager/mock_device_policy_service.h"
#include "login_manager/mock_file_checker.h"
#include "login_manager/mock_key_generator.h"
#include "login_manager/mock_metrics.h"
#include "login_manager/mock_nss_util.h"
#include "login_manager/mock_policy_service.h"
#include "login_manager/mock_process_manager_service.h"
#include "login_manager/mock_system_utils.h"
#include "login_manager/mock_user_policy_service_factory.h"
#include "login_manager/server_backed_state_key_generator.h"
#include "login_manager/stub_upstart_signal_emitter.h"
using ::testing::AnyNumber;
using ::testing::AtMost;
using ::testing::DoAll;
using ::testing::ElementsAre;
using ::testing::ElementsAreArray;
using ::testing::HasSubstr;
using ::testing::InvokeWithoutArgs;
using ::testing::Mock;
using ::testing::Return;
using ::testing::SetArgumentPointee;
using ::testing::StrEq;
using ::testing::_;
using chromeos::cryptohome::home::SanitizeUserName;
using chromeos::cryptohome::home::SetSystemSalt;
using chromeos::cryptohome::home::kGuestUserName;
using std::map;
using std::string;
using std::vector;
namespace login_manager {
class SessionManagerImplTest : public ::testing::Test {
public:
SessionManagerImplTest()
: device_policy_service_(new MockDevicePolicyService),
state_key_generator_(&utils_),
impl_(scoped_ptr<UpstartSignalEmitter>(new StubUpstartSignalEmitter),
&dbus_emitter_,
base::Bind(&SessionManagerImplTest::FakeLockScreen,
base::Unretained(this)),
base::Bind(&SessionManagerImplTest::FakeRestartDevice,
base::Unretained(this)),
&key_gen_,
&state_key_generator_,
&manager_,
&metrics_,
&nss_,
&utils_),
fake_salt_("fake salt"),
actual_locks_(0),
expected_locks_(0),
actual_restarts_(0),
expected_restarts_(0) {}
virtual ~SessionManagerImplTest() {}
virtual void SetUp() OVERRIDE {
ASSERT_TRUE(tmpdir_.CreateUniqueTempDir());
SetSystemSalt(&fake_salt_);
MockUserPolicyServiceFactory* factory = new MockUserPolicyServiceFactory;
EXPECT_CALL(*factory, Create(_))
.WillRepeatedly(
Invoke(this, &SessionManagerImplTest::CreateUserPolicyService));
scoped_ptr<DeviceLocalAccountPolicyService> device_local_account_policy(
new DeviceLocalAccountPolicyService(tmpdir_.path(), NULL, NULL));
impl_.InjectPolicyServices(
scoped_ptr<DevicePolicyService>(device_policy_service_),
scoped_ptr<UserPolicyServiceFactory>(factory),
device_local_account_policy.Pass());
}
virtual void TearDown() OVERRIDE {
SetSystemSalt(NULL);
EXPECT_EQ(actual_locks_, expected_locks_);
EXPECT_EQ(actual_restarts_, expected_restarts_);
}
protected:
void ExpectStartSession(const string& email_string) {
ExpectSessionBoilerplate(email_string, false, false);
}
void ExpectGuestSession() {
ExpectSessionBoilerplate(kGuestUserName, true, false);
}
void ExpectStartOwnerSession(const string& email_string) {
ExpectSessionBoilerplate(email_string, false, true);
}
void ExpectStartSessionUnowned(const string& email_string) {
ExpectStartSessionUnownedBoilerplate(email_string, false, false);
}
void ExpectStartSessionOwningInProcess(const string& email_string) {
ExpectStartSessionUnownedBoilerplate(email_string, false, true);
}
void ExpectStartSessionOwnerLost(const string& email_string) {
ExpectStartSessionUnownedBoilerplate(email_string, true, false);
}
void ExpectLockScreen() {
expected_locks_ = 1;
}
void ExpectDeviceRestart() {
expected_restarts_ = 1;
}
void ExpectStorePolicy(MockDevicePolicyService* service,
const string& policy,
int flags) {
EXPECT_CALL(*service, Store(CastEq(policy), policy.size(), _, flags))
.WillOnce(Return(true));
}
void ExpectAndRunStartSession(const string& email) {
ExpectStartSession(email);
EXPECT_TRUE(impl_.StartSession(email, kNothing, NULL));
}
void ExpectAndRunGuestSession() {
ExpectGuestSession();
EXPECT_TRUE(impl_.StartSession(kGuestUserName, kNothing, NULL));
}
PolicyService* CreateUserPolicyService(const string& username) {
user_policy_services_[username] = new MockPolicyService();
return user_policy_services_[username];
}
void VerifyAndClearExpectations() {
Mock::VerifyAndClearExpectations(device_policy_service_);
for (map<string, MockPolicyService*>::iterator it =
user_policy_services_.begin();
it != user_policy_services_.end();
++it) {
Mock::VerifyAndClearExpectations(it->second);
}
Mock::VerifyAndClearExpectations(&manager_);
Mock::VerifyAndClearExpectations(&metrics_);
Mock::VerifyAndClearExpectations(&nss_);
Mock::VerifyAndClearExpectations(&utils_);
}
// These are bare pointers, not scoped_ptrs, because we need to give them
// to a SessionManagerImpl instance, but also be able to set expectations
// on them after we hand them off.
MockDevicePolicyService* device_policy_service_;
map<string, MockPolicyService*> user_policy_services_;
MockDBusSignalEmitter dbus_emitter_;
MockKeyGenerator key_gen_;
ServerBackedStateKeyGenerator state_key_generator_;
MockProcessManagerService manager_;
MockMetrics metrics_;
MockNssUtil nss_;
MockSystemUtils utils_;
SessionManagerImpl impl_;
SessionManagerImpl::Error error_;
base::ScopedTempDir tmpdir_;
static const pid_t kDummyPid;
static const char kNothing[];
static const char kSaneEmail[];
private:
void ExpectSessionBoilerplate(const string& email_string,
bool guest,
bool for_owner) {
EXPECT_CALL(manager_,
SetBrowserSessionForUser(StrEq(email_string),
StrEq(SanitizeUserName(email_string))))
.Times(1);
// Expect initialization of the device policy service, return success.
EXPECT_CALL(*device_policy_service_,
CheckAndHandleOwnerLogin(StrEq(email_string), _, _, _))
.WillOnce(DoAll(SetArgumentPointee<2>(for_owner),
Return(true)));
// Confirm that the key is present.
EXPECT_CALL(*device_policy_service_, KeyMissing())
.WillOnce(Return(false));
EXPECT_CALL(metrics_, SendLoginUserType(false, guest, for_owner))
.Times(1);
EXPECT_CALL(dbus_emitter_,
EmitSignalWithString(
StrEq(login_manager::kSessionStateChangedSignal),
StrEq(SessionManagerImpl::kStarted)))
.Times(1);
EXPECT_CALL(utils_, IsDevMode())
.WillOnce(Return(false));
}
void ExpectStartSessionUnownedBoilerplate(const string& email_string,
bool mitigating,
bool owning_in_progress) {
EXPECT_CALL(manager_,
SetBrowserSessionForUser(StrEq(email_string),
StrEq(SanitizeUserName(email_string))))
.Times(1);
// Expect initialization of the device policy service, return success.
EXPECT_CALL(*device_policy_service_,
CheckAndHandleOwnerLogin(StrEq(email_string), _, _, _))
.WillOnce(DoAll(SetArgumentPointee<2>(false),
Return(true)));
// Indicate that there is no owner key in order to trigger a new one to be
// generated.
EXPECT_CALL(*device_policy_service_, KeyMissing())
.WillOnce(Return(true));
EXPECT_CALL(*device_policy_service_, Mitigating())
.WillRepeatedly(Return(mitigating));
if (!mitigating && !owning_in_progress)
EXPECT_CALL(key_gen_, Start(StrEq(email_string))).Times(1);
else
EXPECT_CALL(key_gen_, Start(_)).Times(0);
EXPECT_CALL(dbus_emitter_,
EmitSignalWithString(
StrEq(login_manager::kSessionStateChangedSignal),
StrEq(SessionManagerImpl::kStarted)))
.Times(1);
EXPECT_CALL(utils_, IsDevMode())
.WillOnce(Return(false));
}
void FakeLockScreen() {
actual_locks_++;
}
void FakeRestartDevice() {
actual_restarts_++;
}
string fake_salt_;
// Used by fake closures that simulate calling chrome and powerd to lock
// the screen and restart the device.
uint actual_locks_;
uint expected_locks_;
uint actual_restarts_;
uint expected_restarts_;
DISALLOW_COPY_AND_ASSIGN(SessionManagerImplTest);
};
const pid_t SessionManagerImplTest::kDummyPid = 4;
const char SessionManagerImplTest::kNothing[] = "";
const char SessionManagerImplTest::kSaneEmail[] = "user@somewhere.com";
TEST_F(SessionManagerImplTest, EmitLoginPromptVisible) {
const char event_name[] = "login-prompt-visible";
EXPECT_CALL(metrics_, RecordStats(StrEq(event_name))).Times(1);
EXPECT_CALL(dbus_emitter_,
EmitSignal(StrEq(login_manager::kLoginPromptVisibleSignal)))
.Times(1);
impl_.EmitLoginPromptVisible(&error_);
}
TEST_F(SessionManagerImplTest, EnableChromeTesting) {
std::vector<std::string> args;
args.push_back("--repeat-arg");
args.push_back("--one-time-arg");
base::FilePath expected = utils_.GetUniqueFilename();
ASSERT_FALSE(expected.empty());
string expected_testing_path = expected.value();
EXPECT_CALL(manager_,
RestartBrowserWithArgs(
ElementsAre(args[0], args[1],
HasSubstr(expected_testing_path)),
true))
.Times(1);
string testing_path = impl_.EnableChromeTesting(false, args, NULL);
EXPECT_TRUE(EndsWith(testing_path, expected_testing_path, false));
// Calling again, without forcing relaunch, should not do anything.
testing_path.clear();
testing_path = impl_.EnableChromeTesting(false, args, NULL);
EXPECT_TRUE(EndsWith(testing_path, expected_testing_path, false));
// Force relaunch. Should go through the whole path again.
args[0] = "--dummy";
args[1] = "--repeat-arg";
testing_path.empty();
EXPECT_CALL(manager_,
RestartBrowserWithArgs(
ElementsAre(args[0], args[1],
HasSubstr(expected_testing_path)),
true))
.Times(1);
testing_path = impl_.EnableChromeTesting(true, args, NULL);
EXPECT_TRUE(EndsWith(testing_path, expected_testing_path, false));
}
TEST_F(SessionManagerImplTest, StartSession) {
ExpectStartSession(kSaneEmail);
EXPECT_TRUE(impl_.StartSession(kSaneEmail, kNothing, &error_));
}
TEST_F(SessionManagerImplTest, StartSession_New) {
ExpectStartSessionUnowned(kSaneEmail);
EXPECT_TRUE(impl_.StartSession(kSaneEmail, kNothing, &error_));
}
TEST_F(SessionManagerImplTest, StartSession_InvalidUser) {
const char bad_email[] = "user";
EXPECT_FALSE(impl_.StartSession(bad_email, kNothing, &error_));
EXPECT_EQ(dbus_error::kInvalidAccount, error_.name());
}
TEST_F(SessionManagerImplTest, StartSession_Twice) {
ExpectStartSession(kSaneEmail);
EXPECT_TRUE(impl_.StartSession(kSaneEmail, kNothing, NULL));
EXPECT_FALSE(impl_.StartSession(kSaneEmail, kNothing, &error_));
EXPECT_EQ(dbus_error::kSessionExists, error_.name());
}
TEST_F(SessionManagerImplTest, StartSession_TwoUsers) {
ExpectStartSession(kSaneEmail);
EXPECT_TRUE(impl_.StartSession(kSaneEmail, kNothing, NULL));
VerifyAndClearExpectations();
const char email2[] = "user2@somewhere";
ExpectStartSession(email2);
EXPECT_TRUE(impl_.StartSession(email2, kNothing, NULL));
}
TEST_F(SessionManagerImplTest, StartSession_OwnerAndOther) {
ExpectStartSessionUnowned(kSaneEmail);
EXPECT_TRUE(impl_.StartSession(kSaneEmail, kNothing, NULL));
VerifyAndClearExpectations();
const char email2[] = "user2@somewhere";
ExpectStartSession(email2);
EXPECT_TRUE(impl_.StartSession(email2, kNothing, NULL));
}
TEST_F(SessionManagerImplTest, StartSession_OwnerRace) {
ExpectStartSessionUnowned(kSaneEmail);
EXPECT_TRUE(impl_.StartSession(kSaneEmail, kNothing, NULL));
VerifyAndClearExpectations();
const char email2[] = "user2@somewhere";
ExpectStartSessionOwningInProcess(email2);
EXPECT_TRUE(impl_.StartSession(email2, kNothing, NULL));
}
TEST_F(SessionManagerImplTest, StartSession_BadNssDB) {
nss_.MakeBadDB();
EXPECT_FALSE(impl_.StartSession(kSaneEmail, kNothing, &error_));
EXPECT_EQ(dbus_error::kNoUserNssDb, error_.name());
}
TEST_F(SessionManagerImplTest, StartSession_DevicePolicyFailure) {
// Upon the owner login check, return an error.
EXPECT_CALL(*device_policy_service_,
CheckAndHandleOwnerLogin(StrEq(kSaneEmail), _, _, _))
.WillOnce(Return(false));
EXPECT_FALSE(impl_.StartSession(kSaneEmail, kNothing, &error_));
}
TEST_F(SessionManagerImplTest, StartSession_Owner) {
ExpectStartOwnerSession(kSaneEmail);
EXPECT_TRUE(impl_.StartSession(kSaneEmail, kNothing, NULL));
}
TEST_F(SessionManagerImplTest, StartSession_KeyMitigation) {
ExpectStartSessionOwnerLost(kSaneEmail);
EXPECT_TRUE(impl_.StartSession(kSaneEmail, kNothing, NULL));
}
TEST_F(SessionManagerImplTest, StopSession) {
EXPECT_CALL(manager_, ScheduleShutdown()).Times(1);
EXPECT_TRUE(impl_.StopSession());
}
TEST_F(SessionManagerImplTest, StorePolicy_NoSession) {
const string fake_policy("fake policy");
const vector<uint8> policy_blob(fake_policy.begin(), fake_policy.end());
ExpectStorePolicy(device_policy_service_,
fake_policy,
PolicyService::KEY_ROTATE |
PolicyService::KEY_INSTALL_NEW |
PolicyService::KEY_CLOBBER);
impl_.StorePolicy(policy_blob.data(), policy_blob.size(), NULL);
}
TEST_F(SessionManagerImplTest, StorePolicy_SessionStarted) {
ExpectAndRunStartSession(kSaneEmail);
const string fake_policy("fake policy");
const vector<uint8> policy_blob(fake_policy.begin(), fake_policy.end());
ExpectStorePolicy(device_policy_service_,
fake_policy,
PolicyService::KEY_ROTATE);
impl_.StorePolicy(policy_blob.data(), policy_blob.size(), NULL);
}
TEST_F(SessionManagerImplTest, RetrievePolicy) {
const string fake_policy("fake policy");
const vector<uint8> policy_data(fake_policy.begin(), fake_policy.end());
EXPECT_CALL(*device_policy_service_, Retrieve(_))
.WillOnce(DoAll(SetArgumentPointee<0>(policy_data),
Return(true)));
vector<uint8> out_blob;
impl_.RetrievePolicy(&out_blob, NULL);
EXPECT_EQ(fake_policy.size(), out_blob.size());
EXPECT_TRUE(
std::equal(fake_policy.begin(), fake_policy.end(), out_blob.begin()));
}
TEST_F(SessionManagerImplTest, StoreUserPolicy_NoSession) {
const string fake_policy("fake policy");
const vector<uint8> policy_blob(fake_policy.begin(), fake_policy.end());
MockPolicyServiceCompletion completion;
EXPECT_CALL(completion,
ReportFailure(PolicyErrorEq(dbus_error::kSessionDoesNotExist)))
.Times(1);
impl_.StorePolicyForUser(kSaneEmail,
policy_blob.data(), policy_blob.size(),
&completion);
}
TEST_F(SessionManagerImplTest, StoreUserPolicy_SessionStarted) {
ExpectAndRunStartSession(kSaneEmail);
const string fake_policy("fake policy");
const vector<uint8> policy_blob(fake_policy.begin(), fake_policy.end());
EXPECT_CALL(*user_policy_services_[kSaneEmail],
Store(CastEq(fake_policy),
fake_policy.size(),
_,
PolicyService::KEY_ROTATE | PolicyService::KEY_INSTALL_NEW))
.WillOnce(Return(true));
impl_.StorePolicyForUser(kSaneEmail,
policy_blob.data(), policy_blob.size(),
NULL);
}
TEST_F(SessionManagerImplTest, StoreUserPolicy_SecondSession) {
ExpectAndRunStartSession(kSaneEmail);
ASSERT_TRUE(user_policy_services_[kSaneEmail]);
// Store policy for the signed-in user.
const std::string fake_policy("fake policy");
const vector<uint8> policy_blob(fake_policy.begin(), fake_policy.end());
EXPECT_CALL(*user_policy_services_[kSaneEmail],
Store(CastEq(fake_policy),
fake_policy.size(),
_,
PolicyService::KEY_ROTATE | PolicyService::KEY_INSTALL_NEW))
.WillOnce(Return(true));
impl_.StorePolicyForUser(kSaneEmail,
policy_blob.data(), policy_blob.size(),
NULL);
Mock::VerifyAndClearExpectations(user_policy_services_[kSaneEmail]);
// Storing policy for another username fails before his session starts.
const char user2[] = "user2@somewhere.com";
MockPolicyServiceCompletion completion;
EXPECT_CALL(completion,
ReportFailure(PolicyErrorEq(dbus_error::kSessionDoesNotExist)))
.Times(1);
impl_.StorePolicyForUser(user2,
policy_blob.data(), policy_blob.size(),
&completion);
// Now start another session for the 2nd user.
ExpectAndRunStartSession(user2);
ASSERT_TRUE(user_policy_services_[user2]);
// Storing policy for that user now succeeds.
EXPECT_CALL(*user_policy_services_[user2],
Store(CastEq(fake_policy),
fake_policy.size(),
_,
PolicyService::KEY_ROTATE | PolicyService::KEY_INSTALL_NEW))
.WillOnce(Return(true));
impl_.StorePolicyForUser(user2,
policy_blob.data(), policy_blob.size(),
NULL);
Mock::VerifyAndClearExpectations(user_policy_services_[user2]);
}
TEST_F(SessionManagerImplTest, RetrieveUserPolicy_NoSession) {
vector<uint8> out_blob;
impl_.RetrievePolicyForUser(kSaneEmail, &out_blob, &error_);
EXPECT_EQ(out_blob.size(), 0);
EXPECT_EQ(dbus_error::kSessionDoesNotExist, error_.name());
}
TEST_F(SessionManagerImplTest, RetrieveUserPolicy_SessionStarted) {
ExpectAndRunStartSession(kSaneEmail);
const string fake_policy("fake policy");
const vector<uint8> policy_data(fake_policy.begin(), fake_policy.end());
EXPECT_CALL(*user_policy_services_[kSaneEmail], Retrieve(_))
.WillOnce(DoAll(SetArgumentPointee<0>(policy_data),
Return(true)));
vector<uint8> out_blob;
impl_.RetrievePolicyForUser(kSaneEmail, &out_blob, &error_);
EXPECT_EQ(fake_policy.size(), out_blob.size());
EXPECT_TRUE(
std::equal(fake_policy.begin(), fake_policy.end(), out_blob.begin()));
}
TEST_F(SessionManagerImplTest, RetrieveUserPolicy_SecondSession) {
ExpectAndRunStartSession(kSaneEmail);
ASSERT_TRUE(user_policy_services_[kSaneEmail]);
// Retrieve policy for the signed-in user.
const std::string fake_policy("fake policy");
const std::vector<uint8> policy_data(fake_policy.begin(), fake_policy.end());
EXPECT_CALL(*user_policy_services_[kSaneEmail], Retrieve(_))
.WillOnce(DoAll(SetArgumentPointee<0>(policy_data),
Return(true)));
std::vector<uint8> out_blob;
impl_.RetrievePolicyForUser(kSaneEmail, &out_blob, NULL);
Mock::VerifyAndClearExpectations(user_policy_services_[kSaneEmail]);
EXPECT_EQ(fake_policy.size(), out_blob.size());
EXPECT_TRUE(
std::equal(fake_policy.begin(), fake_policy.end(), out_blob.begin()));
// Retrieving policy for another username fails before his session starts.
const char user2[] = "user2@somewhere.com";
out_blob.clear();
impl_.RetrievePolicyForUser(user2, &out_blob, &error_);
EXPECT_EQ(error_.name(), dbus_error::kSessionDoesNotExist);
// Now start another session for the 2nd user.
ExpectAndRunStartSession(user2);
ASSERT_TRUE(user_policy_services_[user2]);
// Retrieving policy for that user now succeeds.
EXPECT_CALL(*user_policy_services_[user2], Retrieve(_))
.WillOnce(DoAll(SetArgumentPointee<0>(policy_data),
Return(true)));
out_blob.clear();
impl_.RetrievePolicyForUser(user2, &out_blob, NULL);
Mock::VerifyAndClearExpectations(user_policy_services_[user2]);
EXPECT_EQ(fake_policy.size(), out_blob.size());
EXPECT_TRUE(
std::equal(fake_policy.begin(), fake_policy.end(), out_blob.begin()));
}
TEST_F(SessionManagerImplTest, RetrieveActiveSessions) {
ExpectStartSession(kSaneEmail);
EXPECT_TRUE(impl_.StartSession(kSaneEmail, kNothing, NULL));
std::map<std::string, std::string> active_users;
impl_.RetrieveActiveSessions(&active_users);
EXPECT_EQ(active_users.size(), 1);
EXPECT_EQ(active_users[kSaneEmail], SanitizeUserName(kSaneEmail));
VerifyAndClearExpectations();
const char email2[] = "user2@somewhere";
ExpectStartSession(email2);
EXPECT_TRUE(impl_.StartSession(email2, kNothing, NULL));
active_users.clear();
impl_.RetrieveActiveSessions(&active_users);
EXPECT_EQ(active_users.size(), 2);
EXPECT_EQ(active_users[kSaneEmail], SanitizeUserName(kSaneEmail));
EXPECT_EQ(active_users[email2], SanitizeUserName(email2));
}
TEST_F(SessionManagerImplTest, RestartJob_UnknownPid) {
EXPECT_CALL(manager_, IsBrowser(kDummyPid)).WillOnce(Return(false));
EXPECT_FALSE(impl_.RestartJob(kDummyPid, "", &error_));
EXPECT_EQ(dbus_error::kUnknownPid, error_.name());
}
TEST_F(SessionManagerImplTest, RestartJob) {
const char arguments[] = "dummy";
EXPECT_CALL(manager_, IsBrowser(kDummyPid)).WillOnce(Return(true));
EXPECT_CALL(manager_, RestartBrowserWithArgs(ElementsAre(arguments), false))
.Times(1);
ExpectGuestSession();
EXPECT_EQ(TRUE, impl_.RestartJob(kDummyPid, arguments, NULL));
}
TEST_F(SessionManagerImplTest, LockScreen) {
ExpectAndRunStartSession(kSaneEmail);
ExpectLockScreen();
impl_.LockScreen(NULL);
EXPECT_TRUE(impl_.ScreenIsLocked());
}
TEST_F(SessionManagerImplTest, LockScreen_MultiSession) {
ExpectAndRunStartSession("user@somewhere");
ExpectAndRunStartSession("user2@somewhere");
ExpectLockScreen();
impl_.LockScreen(NULL);
EXPECT_EQ(TRUE, impl_.ScreenIsLocked());
}
TEST_F(SessionManagerImplTest, LockScreen_NoSession) {
impl_.LockScreen(&error_);
EXPECT_EQ(dbus_error::kSessionDoesNotExist, error_.name());
}
TEST_F(SessionManagerImplTest, LockScreen_Guest) {
ExpectAndRunGuestSession();
impl_.LockScreen(&error_);
EXPECT_EQ(dbus_error::kSessionExists, error_.name());
}
TEST_F(SessionManagerImplTest, LockScreen_UserAndGuest) {
ExpectAndRunStartSession(kSaneEmail);
ExpectAndRunGuestSession();
ExpectLockScreen();
impl_.LockScreen(&error_);
EXPECT_EQ(TRUE, impl_.ScreenIsLocked());
}
TEST_F(SessionManagerImplTest, LockUnlockScreen) {
ExpectAndRunStartSession(kSaneEmail);
ExpectLockScreen();
impl_.LockScreen(&error_);
EXPECT_EQ(TRUE, impl_.ScreenIsLocked());
EXPECT_CALL(dbus_emitter_,
EmitSignal(StrEq(login_manager::kScreenIsLockedSignal)))
.Times(1);
impl_.HandleLockScreenShown();
EXPECT_EQ(TRUE, impl_.ScreenIsLocked());
EXPECT_CALL(dbus_emitter_,
EmitSignal(StrEq(login_manager::kScreenIsUnlockedSignal)))
.Times(1);
impl_.HandleLockScreenDismissed();
EXPECT_EQ(FALSE, impl_.ScreenIsLocked());
}
TEST_F(SessionManagerImplTest, StartDeviceWipe_AlreadyLoggedIn) {
base::FilePath logged_in_path(SessionManagerImpl::kLoggedInFlag);
ASSERT_FALSE(utils_.Exists(logged_in_path));
ASSERT_TRUE(utils_.AtomicFileWrite(logged_in_path, "1"));
impl_.StartDeviceWipe(&error_);
EXPECT_EQ(error_.name(), dbus_error::kSessionExists);
}
TEST_F(SessionManagerImplTest, StartDeviceWipe) {
base::FilePath logged_in_path(SessionManagerImpl::kLoggedInFlag);
base::FilePath reset_path(SessionManagerImpl::kResetFile);
ASSERT_TRUE(utils_.RemoveFile(logged_in_path));
ExpectDeviceRestart();
impl_.StartDeviceWipe(NULL);
}
TEST_F(SessionManagerImplTest, ImportValidateAndStoreGeneratedKey) {
base::FilePath key_file_path;
string key("key_contents");
ASSERT_TRUE(base::CreateTemporaryFileInDir(tmpdir_.path(),
&key_file_path));
ASSERT_EQ(file_util::WriteFile(key_file_path, key.c_str(), key.size()),
key.size());
// Start a session, to set up NSSDB for the user.
ExpectStartOwnerSession(kSaneEmail);
ASSERT_TRUE(impl_.StartSession(kSaneEmail, kNothing, NULL));
EXPECT_CALL(*device_policy_service_,
ValidateAndStoreOwnerKey(StrEq(kSaneEmail),
StrEq(key),
nss_.GetSlot()))
.WillOnce(Return(true));
impl_.OnKeyGenerated(kSaneEmail, key_file_path);
EXPECT_FALSE(base::PathExists(key_file_path));
}
class SessionManagerImplStaticTest : public ::testing::Test {
public:
SessionManagerImplStaticTest() {}
virtual ~SessionManagerImplStaticTest() {}
bool ValidateEmail(const string& email_address) {
return SessionManagerImpl::ValidateEmail(email_address);
}
};
TEST_F(SessionManagerImplStaticTest, EmailAddressTest) {
const char valid[] = "user_who+we.like@some-where.com";
EXPECT_TRUE(ValidateEmail(valid));
}
TEST_F(SessionManagerImplStaticTest, EmailAddressNonAsciiTest) {
char invalid[4] = "a@m";
invalid[2] = 254;
EXPECT_FALSE(ValidateEmail(invalid));
}
TEST_F(SessionManagerImplStaticTest, EmailAddressNoAtTest) {
const char no_at[] = "user";
EXPECT_FALSE(ValidateEmail(no_at));
}
TEST_F(SessionManagerImplStaticTest, EmailAddressTooMuchAtTest) {
const char extra_at[] = "user@what@where";
EXPECT_FALSE(ValidateEmail(extra_at));
}
} // namespace login_manager