blob: 7f9db236b9835bad071f70fc1610c5ddddd91179 [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/liveness_checker_impl.h"
#include <base/basictypes.h>
#include <base/memory/ref_counted.h>
#include <base/memory/scoped_ptr.h>
#include <base/message_loop.h>
#include <base/message_loop_proxy.h>
#include <base/run_loop.h>
#include <base/time.h>
#include <chromeos/dbus/service_constants.h>
#include <dbus/dbus.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "login_manager/mock_process_manager_service.h"
#include "login_manager/mock_system_utils.h"
#include "login_manager/scoped_dbus_pending_call.h"
using ::base::TimeDelta;
using ::testing::AtLeast;
using ::testing::DoAll;
using ::testing::InvokeWithoutArgs;
using ::testing::Return;
using ::testing::StrEq;
using ::testing::StrictMock;
using ::testing::_;
namespace login_manager {
class LivenessCheckerImplTest : public ::testing::Test {
public:
LivenessCheckerImplTest() {}
virtual ~LivenessCheckerImplTest() {
// NB: checker_ must be destroyed before system_.
}
virtual void SetUp() {
manager_.reset(new StrictMock<MockProcessManagerService>);
loop_proxy_ = base::MessageLoopProxy::current();
checker_.reset(new LivenessCheckerImpl(manager_.get(),
&system_,
loop_proxy_,
true,
TimeDelta::FromSeconds(0)));
}
void ExpectUnAckedLivenessPing() {
scoped_ptr<ScopedDBusPendingCall> call =
ScopedDBusPendingCall::CreateForTesting();
EXPECT_CALL(system_, CheckAsyncMethodSuccess(call->Get()))
.WillOnce(Return(false));
EXPECT_CALL(system_, CancelAsyncMethodCall(call->Get()))
.Times(1);
system_.EnqueueFakePendingCall(call.Pass());
}
// Expect two pings, the first with a response.
void ExpectLivenessPingResponsePing() {
scoped_ptr<ScopedDBusPendingCall> call1 =
ScopedDBusPendingCall::CreateForTesting();
scoped_ptr<ScopedDBusPendingCall> call2 =
ScopedDBusPendingCall::CreateForTesting();
EXPECT_CALL(system_, CheckAsyncMethodSuccess(call1->Get()))
.WillOnce(Return(true));
EXPECT_CALL(system_, CheckAsyncMethodSuccess(call2->Get()))
.WillOnce(Return(false));
EXPECT_CALL(system_, CancelAsyncMethodCall(call2->Get()))
.Times(1);
system_.EnqueueFakePendingCall(call1.Pass());
system_.EnqueueFakePendingCall(call2.Pass());
}
// Expect three runs through CheckAndSendLivenessPing():
// 1) No ping has been sent before, so expect initial ping and ACK it.
// 2) Last ping was ACK'd, so expect a no-op during this run.
// 3) Caller should expect action during this run; Quit after it.
void ExpectPingResponsePingCheckPingAndQuit() {
scoped_ptr<ScopedDBusPendingCall> call1 =
ScopedDBusPendingCall::CreateForTesting();
scoped_ptr<ScopedDBusPendingCall> call2 =
ScopedDBusPendingCall::CreateForTesting();
scoped_ptr<ScopedDBusPendingCall> call3 =
ScopedDBusPendingCall::CreateForTesting();
EXPECT_CALL(system_, CheckAsyncMethodSuccess(call1->Get()))
.WillOnce(Return(true));
EXPECT_CALL(system_, CheckAsyncMethodSuccess(call2->Get()))
.WillOnce(DoAll(InvokeWithoutArgs(MessageLoop::current(),
&MessageLoop::QuitNow),
Return(false)));
EXPECT_CALL(system_, CancelAsyncMethodCall(call3->Get()))
.Times(1);
system_.EnqueueFakePendingCall(call1.Pass());
system_.EnqueueFakePendingCall(call2.Pass());
system_.EnqueueFakePendingCall(call3.Pass());
}
MessageLoop loop_;
scoped_refptr<base::MessageLoopProxy> loop_proxy_;
StrictMock<MockSystemUtils> system_;
scoped_ptr<StrictMock<MockProcessManagerService> > manager_;
scoped_ptr<LivenessCheckerImpl> checker_;
private:
DISALLOW_COPY_AND_ASSIGN(LivenessCheckerImplTest);
};
TEST_F(LivenessCheckerImplTest, CheckAndSendOutstandingPing) {
ExpectUnAckedLivenessPing();
EXPECT_CALL(*manager_.get(), AbortBrowser(SIGFPE, _)).Times(1);
checker_->CheckAndSendLivenessPing(TimeDelta());
base::RunLoop().RunUntilIdle();
}
TEST_F(LivenessCheckerImplTest, CheckAndSendAckedThenOutstandingPing) {
ExpectLivenessPingResponsePing();
EXPECT_CALL(*manager_.get(), AbortBrowser(SIGFPE, _)).Times(1);
checker_->CheckAndSendLivenessPing(TimeDelta());
base::RunLoop().RunUntilIdle();
}
TEST_F(LivenessCheckerImplTest, CheckAndSendAckedThenOutstandingPingNeutered) {
checker_.reset(new LivenessCheckerImpl(manager_.get(),
&system_,
loop_proxy_,
false /* Disable aborting */,
TimeDelta()));
ExpectPingResponsePingCheckPingAndQuit();
// Expect _no_ browser abort!
checker_->CheckAndSendLivenessPing(TimeDelta());
base::RunLoop().RunUntilIdle();
}
TEST_F(LivenessCheckerImplTest, StartStop) {
checker_->Start();
EXPECT_TRUE(checker_->IsRunning());
checker_->Stop(); // Should cancel ping, so...
EXPECT_FALSE(checker_->IsRunning());
}
} // namespace login_manager