Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(38)

Unified Diff: components/arc/arc_bridge_service_unittest.cc

Issue 2194193002: Fix ArcBridgeBootstrap race issues. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix ArcBridgeBootstrap race issues. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 d85b5562ee269be85d82263430393505c03e46da..6656012f76269216d9d26609a99e84ff3d987786 100644
--- a/components/arc/arc_bridge_service_unittest.cc
+++ b/components/arc/arc_bridge_service_unittest.cc
@@ -4,16 +4,10 @@
#include <memory>
-#include "base/bind.h"
-#include "base/bind_helpers.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
-#include "base/run_loop.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
#include "components/arc/arc_bridge_service_impl.h"
#include "components/arc/test/fake_arc_bridge_bootstrap.h"
-#include "components/arc/test/fake_arc_bridge_instance.h"
-#include "mojo/public/cpp/system/message_pipe.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace arc {
@@ -24,56 +18,71 @@ class DummyObserver : public ArcBridgeService::Observer {};
} // namespace
-class ArcBridgeTest : public testing::Test, public ArcBridgeService::Observer {
+class ArcBridgeTest : public testing::Test,
+ public ArcBridgeService::Observer,
+ public ArcBridgeServiceImpl::Delegate {
public:
- ArcBridgeTest() : ready_(false) {}
- ~ArcBridgeTest() override {}
-
- void OnBridgeReady() override {
- state_ = ArcBridgeService::State::READY;
- ready_ = true;
- }
+ ArcBridgeTest() = default;
+ ~ArcBridgeTest() override = default;
void OnBridgeStopped(ArcBridgeService::StopReason stop_reason) override {
- state_ = ArcBridgeService::State::STOPPED;
+ // The instance is already destructed in ArcBridgeServiceImpl::OnStopped().
+ bootstrap_ = nullptr;
+
stop_reason_ = stop_reason;
- message_loop_.PostTask(FROM_HERE, message_loop_.QuitWhenIdleClosure());
}
- 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();
-
- ready_ = false;
- 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);
+ 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.
+ 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);
};
@@ -81,88 +90,98 @@ class ArcBridgeTest : public testing::Test, public ArcBridgeService::Observer {
// Exercises the basic functionality of the ARC Bridge Service. A message from
// within the instance should cause the observer to be notified.
TEST_F(ArcBridgeTest, Basic) {
- ASSERT_FALSE(ready());
- ASSERT_EQ(ArcBridgeService::State::STOPPED, state());
+ ASSERT_TRUE(service_->stopped());
service_->HandleStartup();
- instance_->WaitForInitCall();
- ASSERT_EQ(ArcBridgeService::State::READY, state());
+ ASSERT_TRUE(service_->ready());
service_->Shutdown();
- ASSERT_EQ(ArcBridgeService::State::STOPPED, state());
+ ASSERT_TRUE(service_->stopped());
}
// If the ArcBridgeService is shut down, it should be stopped, even
// mid-startup.
TEST_F(ArcBridgeTest, ShutdownMidStartup) {
- ASSERT_FALSE(ready());
+ ASSERT_TRUE(service_->stopped());
+ 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());
+ ASSERT_TRUE(service_->stopped());
+}
+
+// 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());
+ ASSERT_TRUE(service_->stopped());
service_->HandleStartup();
- instance_->WaitForInitCall();
- ASSERT_EQ(ArcBridgeService::State::READY, state());
- ASSERT_EQ(1, instance_->init_calls());
+ ASSERT_TRUE(service_->ready());
// 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());
+ ASSERT_TRUE(service_->stopped());
}
// Makes sure OnBridgeStopped is called on stop.
TEST_F(ArcBridgeTest, OnBridgeStopped) {
- ASSERT_FALSE(ready());
+ ASSERT_TRUE(service_->stopped());
service_->DisableReconnectDelayForTesting();
service_->HandleStartup();
- instance_->WaitForInitCall();
- ASSERT_EQ(ArcBridgeService::State::READY, state());
+ ASSERT_TRUE(service_->ready());
// 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();
- ASSERT_EQ(ArcBridgeService::StopReason::SHUTDOWN, stop_reason_);
- ASSERT_EQ(ArcBridgeService::State::STOPPED, state());
+ EXPECT_EQ(ArcBridgeService::StopReason::SHUTDOWN, stop_reason_);
+ ASSERT_TRUE(service_->stopped());
}
// 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|.
+ ASSERT_TRUE(service_->stopped());
+ 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.
TEST_F(ArcBridgeTest, RemoveUnknownObserver) {
- ASSERT_FALSE(ready());
+ ASSERT_TRUE(service_->stopped());
auto dummy_observer = base::MakeUnique<DummyObserver>();
service_->RemoveObserver(dummy_observer.get());
}

Powered by Google App Engine
This is Rietveld 408576698