Chromium Code Reviews| Index: components/arc/arc_bridge_service_unittest.cc |
| diff --git a/components/arc/arc_bridge_service_unittest.cc b/components/arc/arc_bridge_service_unittest.cc |
| index cff48893c182a1a056df97f970f13aea4287b4b7..d0f2d997423cc5ac60d6956b8bdd3abf864cbb2b 100644 |
| --- a/components/arc/arc_bridge_service_unittest.cc |
| +++ b/components/arc/arc_bridge_service_unittest.cc |
| @@ -25,10 +25,14 @@ class DummyObserver : public ArcBridgeService::Observer {}; |
| } // namespace |
| -class ArcBridgeTest : public testing::Test, public ArcBridgeService::Observer { |
| +// TODO(hidehiko): ArcBridgeTest gets complicated and has stale code. |
| +// Simplify the code. |
| +class ArcBridgeTest : public testing::Test, |
| + public ArcBridgeService::Observer, |
| + public ArcBridgeServiceImpl::Delegate { |
| public: |
| ArcBridgeTest() : ready_(false) {} |
| - ~ArcBridgeTest() override {} |
| + ~ArcBridgeTest() override {}; |
|
Luis Héctor Chávez
2016/09/07 23:38:32
remove the ;? (also, = default?)
hidehiko
2016/09/08 16:53:41
Oops. Fixed.
|
| void OnBridgeReady() override { |
| state_ = ArcBridgeService::State::READY; |
| @@ -36,7 +40,9 @@ class ArcBridgeTest : public testing::Test, public ArcBridgeService::Observer { |
| } |
| void OnBridgeStopped(ArcBridgeService::StopReason stop_reason) override { |
| + // The instance is already destructed in ArcBridgeServiceImpl::OnStopped(). |
| state_ = ArcBridgeService::State::STOPPED; |
| + bootstrap_ = nullptr; |
| stop_reason_ = stop_reason; |
| message_loop_.task_runner()->PostTask(FROM_HERE, |
| message_loop_.QuitWhenIdleClosure()); |
| @@ -44,12 +50,19 @@ class ArcBridgeTest : public testing::Test, public ArcBridgeService::Observer { |
| bool ready() const { return ready_; } |
| ArcBridgeService::State state() const { return state_; } |
| + FakeArcBridgeBootstrap* bootstrap() const { return bootstrap_; } |
| protected: |
| std::unique_ptr<ArcBridgeServiceImpl> service_; |
| - std::unique_ptr<FakeArcBridgeInstance> instance_; |
| ArcBridgeService::StopReason stop_reason_; |
| + void EnableBootFailureEmulation(ArcBridgeService::StopReason reason) { |
| + boot_failure_emulation_enabled_ = true; |
| + boot_failure_reason_ = reason; |
| + } |
| + |
| + void SuspendBoot() { boot_suspended_ = true; } |
| + |
| private: |
| void SetUp() override { |
| chromeos::DBusThreadManager::Initialize(); |
| @@ -58,25 +71,47 @@ class ArcBridgeTest : public testing::Test, public ArcBridgeService::Observer { |
| state_ = ArcBridgeService::State::STOPPED; |
| stop_reason_ = ArcBridgeService::StopReason::SHUTDOWN; |
| - instance_.reset(new FakeArcBridgeInstance()); |
| - service_.reset(new ArcBridgeServiceImpl( |
| - base::MakeUnique<FakeArcBridgeBootstrap>(instance_.get()))); |
| + boot_failure_emulation_enabled_ = false; |
| + boot_suspended_ = false; |
| + service_.reset(new ArcBridgeServiceImpl); |
|
Luis Héctor Chávez
2016/09/07 23:38:32
Any reason why you're not using parentheses? I've
hidehiko
2016/09/08 16:53:41
For consistency, with variables on stack. As you m
Luis Héctor Chávez
2016/09/15 23:08:49
There was a recent discussion about this in chromi
hidehiko
2016/09/20 13:35:19
I see. Thank you for explanation and references.
I
|
| + service_->SetDelegateForTesting(this); |
| service_->AddObserver(this); |
| } |
| void TearDown() override { |
| service_->RemoveObserver(this); |
| - instance_.reset(); |
| service_.reset(); |
| chromeos::DBusThreadManager::Shutdown(); |
| } |
| + // ArcBridgeServiceImpl::Delegate. |
| + std::unique_ptr<ArcBridgeBootstrap> CreateBootstrap() override { |
| + // The testee ArcBridgeServiceImpl instance has the ownership. So, keep |
| + // the raw pointer only here. |
|
Luis Héctor Chávez
2016/09/07 23:38:32
This looks dangerous :S
Anyways, is there any cha
hidehiko
2016/09/08 16:53:41
Ok, now I rewrote it under Factory redesign.
|
| + bootstrap_ = new FakeArcBridgeBootstrap; |
| + if (boot_failure_emulation_enabled_) { |
| + bootstrap_->EnableBootFailureEmulation(boot_failure_reason_); |
| + } |
| + if (boot_suspended_) { |
| + bootstrap_->SuspendBoot(); |
| + } |
| + |
| + return base::WrapUnique(bootstrap_); |
| + } |
| + |
| bool ready_; |
| ArcBridgeService::State state_; |
| base::MessageLoopForUI message_loop_; |
| + // Tracks the current bootstrap instance. This depends on the implementation |
| + // details of ArcBridgeServiceImpl. |
| + FakeArcBridgeBootstrap* bootstrap_ = nullptr; |
| + bool boot_failure_emulation_enabled_ = false; |
| + ArcBridgeService::StopReason boot_failure_reason_; |
| + bool boot_suspended_ = false; |
| + |
| DISALLOW_COPY_AND_ASSIGN(ArcBridgeTest); |
| }; |
| @@ -87,7 +122,6 @@ TEST_F(ArcBridgeTest, Basic) { |
| ASSERT_EQ(ArcBridgeService::State::STOPPED, state()); |
| service_->HandleStartup(); |
| - instance_->WaitForInitCall(); |
| ASSERT_EQ(ArcBridgeService::State::READY, state()); |
| service_->Shutdown(); |
| @@ -99,30 +133,39 @@ TEST_F(ArcBridgeTest, Basic) { |
| TEST_F(ArcBridgeTest, ShutdownMidStartup) { |
| ASSERT_FALSE(ready()); |
| + SuspendBoot(); |
| service_->HandleStartup(); |
| - // WaitForInitCall() omitted. |
| - ASSERT_EQ(ArcBridgeService::State::READY, state()); |
| + ASSERT_FALSE(service_->stopped()); |
| + ASSERT_FALSE(service_->ready()); |
| service_->Shutdown(); |
| ASSERT_EQ(ArcBridgeService::State::STOPPED, state()); |
| } |
| +// If the boot procedure is failed, then restarting mechanism should not |
| +// triggered. |
| +TEST_F(ArcBridgeTest, BootFailure) { |
| + ASSERT_TRUE(service_->stopped()); |
| + |
| + EnableBootFailureEmulation( |
| + ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE); |
| + service_->HandleStartup(); |
| + EXPECT_EQ(ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE, stop_reason_); |
| + ASSERT_TRUE(service_->stopped()); |
| +} |
| + |
| // If the instance is stopped, it should be re-started. |
| TEST_F(ArcBridgeTest, Restart) { |
| ASSERT_FALSE(ready()); |
| - ASSERT_EQ(0, instance_->init_calls()); |
| service_->HandleStartup(); |
| - instance_->WaitForInitCall(); |
| ASSERT_EQ(ArcBridgeService::State::READY, state()); |
| - ASSERT_EQ(1, instance_->init_calls()); |
| // Simulate a connection loss. |
| service_->DisableReconnectDelayForTesting(); |
| - instance_->Stop(ArcBridgeService::StopReason::CRASH); |
| - instance_->WaitForInitCall(); |
| - ASSERT_EQ(ArcBridgeService::State::READY, state()); |
| - ASSERT_EQ(2, instance_->init_calls()); |
| + ASSERT_TRUE(bootstrap()); |
| + bootstrap()->StopWithReason(ArcBridgeService::StopReason::CRASH); |
| + ASSERT_TRUE(service_->ready()); |
| service_->Shutdown(); |
| ASSERT_EQ(ArcBridgeService::State::STOPPED, state()); |
| @@ -134,20 +177,20 @@ TEST_F(ArcBridgeTest, OnBridgeStopped) { |
| service_->DisableReconnectDelayForTesting(); |
| service_->HandleStartup(); |
| - instance_->WaitForInitCall(); |
| ASSERT_EQ(ArcBridgeService::State::READY, state()); |
| // Simulate boot failure. |
| - instance_->Stop(ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE); |
| - instance_->WaitForInitCall(); |
| - ASSERT_EQ(ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE, stop_reason_); |
| - ASSERT_EQ(ArcBridgeService::State::READY, state()); |
| + ASSERT_TRUE(bootstrap()); |
| + bootstrap()->StopWithReason( |
| + ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE); |
| + EXPECT_EQ(ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE, stop_reason_); |
| + ASSERT_TRUE(service_->ready()); |
| // Simulate crash. |
| - instance_->Stop(ArcBridgeService::StopReason::CRASH); |
| - instance_->WaitForInitCall(); |
| - ASSERT_EQ(ArcBridgeService::StopReason::CRASH, stop_reason_); |
| - ASSERT_EQ(ArcBridgeService::State::READY, state()); |
| + ASSERT_TRUE(bootstrap()); |
| + bootstrap()->StopWithReason(ArcBridgeService::StopReason::CRASH); |
| + EXPECT_EQ(ArcBridgeService::StopReason::CRASH, stop_reason_); |
| + ASSERT_TRUE(service_->ready()); |
| // Graceful shutdown. |
| service_->Shutdown(); |
| @@ -158,8 +201,11 @@ TEST_F(ArcBridgeTest, OnBridgeStopped) { |
| // Removing the same observer more than once should be okay. |
| TEST_F(ArcBridgeTest, RemoveObserverTwice) { |
| ASSERT_FALSE(ready()); |
| - service_->RemoveObserver(this); |
| - // The teardown method will also remove |this|. |
| + auto dummy_observer = base::MakeUnique<DummyObserver>(); |
| + service_->AddObserver(dummy_observer.get()); |
| + // Call RemoveObserver() twice. |
| + service_->RemoveObserver(dummy_observer.get()); |
| + service_->RemoveObserver(dummy_observer.get()); |
| } |
| // Removing an unknown observer should be allowed. |