blob: eac59f021e2bf4b6c912bdb2bae3d152dccac50f [file] [log] [blame]
// Copyright (c) 2009-2010 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_service.h"
#include <errno.h>
#include <gtest/gtest.h>
#include <signal.h>
#include <unistd.h>
#include <base/basictypes.h>
#include <base/command_line.h>
#include <base/logging.h>
#include <base/scoped_ptr.h>
#include <base/string_util.h>
#include <chromeos/dbus/dbus.h>
#include <chromeos/dbus/service_constants.h>
#include "login_manager/bindings/client.h"
#include "login_manager/child_job.h"
#include "login_manager/file_checker.h"
#include "login_manager/mock_child_job.h"
#include "login_manager/mock_system_utils.h"
#include "login_manager/system_utils.h"
namespace login_manager {
using ::testing::Invoke;
using ::testing::InSequence;
using ::testing::Return;
using ::testing::_;
class SessionManagerTest : public ::testing::Test { };
TEST(SessionManagerTest, NoLoopTest) {
MockChildJob *job = new MockChildJob;
login_manager::SessionManagerService manager(job); // manager takes ownership
manager.set_exit_on_child_done(true);
EXPECT_CALL(*job, ShouldRun())
.Times(1)
.WillRepeatedly(Return(false));
manager.Run();
}
static void BadExit() { _exit(1); } // compatible with void Run()
TEST(SessionManagerTest, BadExitChild) {
MockChildJob *job = new MockChildJob;
login_manager::SessionManagerService manager(job); // manager takes ownership
manager.set_exit_on_child_done(true);
EXPECT_CALL(*job, ShouldRun())
.Times(2)
.WillOnce(Return(true))
.WillRepeatedly(Return(false));
EXPECT_CALL(*job, RecordTime())
.Times(1);
EXPECT_CALL(*job, ShouldStop())
.Times(1)
.WillOnce(Return(false));
ON_CALL(*job, Run())
.WillByDefault(Invoke(BadExit));
manager.Run();
}
static void CleanExit() { _exit(0); }
TEST(SessionManagerTest, CleanExitChild) {
MockChildJob* job = new MockChildJob;
login_manager::SessionManagerService manager(job); // manager takes ownership
manager.set_exit_on_child_done(true);
EXPECT_CALL(*job, ShouldRun())
.Times(1)
.WillOnce(Return(true));
EXPECT_CALL(*job, RecordTime())
.Times(1);
ON_CALL(*job, Run())
.WillByDefault(Invoke(CleanExit));
manager.Run();
}
TEST(SessionManagerTest, MustStopChild) {
MockChildJob *job = new MockChildJob;
login_manager::SessionManagerService manager(job); // manager takes ownership
EXPECT_CALL(*job, ShouldRun())
.WillOnce(Return(true));
EXPECT_CALL(*job, RecordTime())
.Times(1);
EXPECT_CALL(*job, ShouldStop())
.Times(1)
.WillOnce(Return(true));
ON_CALL(*job, Run())
.WillByDefault(Invoke(BadExit));
manager.Run();
}
TEST(SessionManagerTest, MultiRunTest) {
MockChildJob* job = new MockChildJob;
login_manager::SessionManagerService manager(job); // manager takes ownership
manager.set_exit_on_child_done(true);
EXPECT_CALL(*job, ShouldRun())
.Times(3)
.WillOnce(Return(true))
.WillOnce(Return(true))
.WillRepeatedly(Return(false));
EXPECT_CALL(*job, RecordTime())
.Times(2);
EXPECT_CALL(*job, ShouldStop())
.Times(2)
.WillRepeatedly(Return(false));
ON_CALL(*job, Run())
.WillByDefault(Invoke(BadExit));
manager.Run();
}
static const pid_t kDummyPid = 4;
TEST(SessionManagerTest, SessionNotStartedCleanupTest) {
MockChildJob* job = new MockChildJob;
MockSystemUtils* utils = new MockSystemUtils;
login_manager::SessionManagerService manager(job); // manager takes ownership
manager.set_exit_on_child_done(true);
manager.set_child_pid(kDummyPid);
manager.set_systemutils(utils);
int timeout = 3;
EXPECT_CALL(*utils, kill(kDummyPid, SIGKILL))
.WillOnce(Return(0));
EXPECT_CALL(*utils, child_is_gone(kDummyPid, timeout))
.WillOnce(Return(true));
manager.CleanupChildren(timeout);
}
TEST(SessionManagerTest, SessionNotStartedSlowKillCleanupTest) {
MockChildJob* job = new MockChildJob;
MockSystemUtils* utils = new MockSystemUtils;
login_manager::SessionManagerService manager(job); // manager takes ownership
manager.set_exit_on_child_done(true);
manager.set_child_pid(kDummyPid);
manager.set_systemutils(utils);
int timeout = 3;
EXPECT_CALL(*utils, kill(kDummyPid, SIGKILL))
.Times(2)
.WillRepeatedly(Return(0));
EXPECT_CALL(*utils, child_is_gone(kDummyPid, timeout))
.WillOnce(Return(false));
manager.CleanupChildren(timeout);
}
MockChildJob* CreateTrivialMockJob() {
MockChildJob* job = new MockChildJob;
EXPECT_CALL(*job, ShouldRun())
.WillRepeatedly(Return(true));
return job;
}
TEST(SessionManagerTest, SessionStartedCleanupTest) {
MockChildJob* job = CreateTrivialMockJob();
MockSystemUtils* utils = new MockSystemUtils;
login_manager::SessionManagerService manager(job); // manager takes ownership
manager.set_exit_on_child_done(true);
manager.set_child_pid(kDummyPid);
manager.set_systemutils(utils);
gboolean out;
gchar email[] = "user@somewhere";
gchar nothing[] = "";
int timeout = 3;
EXPECT_CALL(*utils, kill(kDummyPid, SIGTERM))
.WillOnce(Return(0));
EXPECT_CALL(*utils, child_is_gone(kDummyPid, timeout))
.WillOnce(Return(true));
std::string email_string(email);
EXPECT_CALL(*job, SetState(email_string))
.Times(1);
manager.StartSession(email, nothing, &out, NULL);
manager.CleanupChildren(timeout);
}
TEST(SessionManagerTest, SessionStartedSlowKillCleanupTest) {
MockChildJob* job = CreateTrivialMockJob();
MockSystemUtils* utils = new MockSystemUtils;
login_manager::SessionManagerService manager(job); // manager takes ownership
manager.set_exit_on_child_done(true);
manager.set_child_pid(kDummyPid);
manager.set_systemutils(utils);
int timeout = 3;
EXPECT_CALL(*utils, kill(kDummyPid, SIGTERM))
.WillOnce(Return(0));
EXPECT_CALL(*utils, child_is_gone(kDummyPid, timeout))
.WillOnce(Return(false));
EXPECT_CALL(*utils, kill(kDummyPid, SIGKILL))
.WillOnce(Return(0));
gboolean out;
gchar email[] = "user@somewhere";
gchar nothing[] = "";
std::string email_string(email);
EXPECT_CALL(*job, SetState(email_string))
.Times(1);
manager.StartSession(email, nothing, &out, NULL);
manager.CleanupChildren(timeout);
}
static void Sleep() { execl("/bin/sleep", "sleep", "10000", NULL); }
TEST(SessionManagerTest, SessionStartedSigTermTest) {
int pid = fork();
if (pid == 0) {
MockChildJob* job = CreateTrivialMockJob();
login_manager::SessionManagerService* manager =
new login_manager::SessionManagerService(job);
gboolean out;
gchar email[] = "user@somewhere";
gchar nothing[] = "";
std::string email_string(email);
EXPECT_CALL(*job, RecordTime())
.Times(1);
ON_CALL(*job, Run())
.WillByDefault(Invoke(Sleep));
EXPECT_CALL(*job, SetState(email_string))
.Times(1);
manager->StartSession(email, nothing, &out, NULL);
manager->Run();
delete manager;
exit(0);
}
sleep(1);
kill(pid, SIGTERM);
int status;
while (waitpid(pid, &status, 0) == -1 && errno == EINTR)
;
DLOG(INFO) << "exited waitpid. " << pid << "\n"
<< " WIFSIGNALED is " << WIFSIGNALED(status) << "\n"
<< " WTERMSIG is " << WTERMSIG(status) << "\n"
<< " WIFEXITED is " << WIFEXITED(status) << "\n"
<< " WEXITSTATUS is " << WEXITSTATUS(status);
EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0);
}
TEST(SessionManagerTest, StartSessionTest) {
MockChildJob* job = CreateTrivialMockJob();
login_manager::SessionManagerService manager(job); // manager takes ownership
manager.set_exit_on_child_done(true);
gboolean out;
gchar email[] = "user@somewhere";
gchar nothing[] = "";
std::string email_string(email);
EXPECT_CALL(*job, SetState(email_string))
.Times(1);
manager.StartSession(email, nothing, &out, NULL);
}
TEST(SessionManagerTest, StartSessionErrorTest) {
MockChildJob* job = new MockChildJob;
login_manager::SessionManagerService manager(job); // manager takes ownership
manager.set_exit_on_child_done(true);
EXPECT_CALL(*job, ShouldRun())
.WillRepeatedly(Return(true));
gboolean out;
gchar email[] = "user";
gchar nothing[] = "";
GError* error = NULL;
manager.StartSession(email, nothing, &out, &error);
EXPECT_EQ(CHROMEOS_LOGIN_ERROR_INVALID_EMAIL, error->code);
g_error_free(error);
}
TEST(SessionManagerTest, StopSessionTest) {
MockChildJob* job = new MockChildJob;
login_manager::SessionManagerService manager(job); // manager takes ownership
manager.set_exit_on_child_done(true);
EXPECT_CALL(*job, ShouldRun())
.WillRepeatedly(Return(true));
gboolean out;
gchar nothing[] = "";
manager.StopSession(nothing, &out, NULL);
}
TEST(SessionManagerTest, EmailAddressTest) {
const char valid[] = "user@somewhere";
EXPECT_TRUE(login_manager::SessionManagerService::ValidateEmail(valid));
}
TEST(SessionManagerTest, EmailAddressNonAsciiTest) {
char invalid[4] = "a@m";
invalid[2] = 254;
EXPECT_FALSE(login_manager::SessionManagerService::ValidateEmail(invalid));
}
TEST(SessionManagerTest, EmailAddressNoAtTest) {
const char no_at[] = "user";
EXPECT_FALSE(login_manager::SessionManagerService::ValidateEmail(no_at));
}
TEST(SessionManagerTest, EmailAddressTooMuchAtTest) {
const char extra_at[] = "user@what@where";
EXPECT_FALSE(login_manager::SessionManagerService::ValidateEmail(extra_at));
}
} // namespace login_manager