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

Side by Side 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, 4 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 unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <memory> 5 #include <memory>
6 6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/macros.h" 7 #include "base/macros.h"
10 #include "base/memory/ptr_util.h" 8 #include "base/memory/ptr_util.h"
11 #include "base/run_loop.h"
12 #include "chromeos/dbus/dbus_thread_manager.h"
13 #include "components/arc/arc_bridge_service_impl.h" 9 #include "components/arc/arc_bridge_service_impl.h"
14 #include "components/arc/test/fake_arc_bridge_bootstrap.h" 10 #include "components/arc/test/fake_arc_bridge_bootstrap.h"
15 #include "components/arc/test/fake_arc_bridge_instance.h"
16 #include "mojo/public/cpp/system/message_pipe.h"
17 #include "testing/gtest/include/gtest/gtest.h" 11 #include "testing/gtest/include/gtest/gtest.h"
18 12
19 namespace arc { 13 namespace arc {
20 14
21 namespace { 15 namespace {
22 16
23 class DummyObserver : public ArcBridgeService::Observer {}; 17 class DummyObserver : public ArcBridgeService::Observer {};
24 18
25 } // namespace 19 } // namespace
26 20
27 class ArcBridgeTest : public testing::Test, public ArcBridgeService::Observer { 21 class ArcBridgeTest : public testing::Test,
22 public ArcBridgeService::Observer,
23 public ArcBridgeServiceImpl::Delegate {
28 public: 24 public:
29 ArcBridgeTest() : ready_(false) {} 25 ArcBridgeTest() = default;
30 ~ArcBridgeTest() override {} 26 ~ArcBridgeTest() override = default;
31 27
32 void OnBridgeReady() override { 28 void OnBridgeStopped(ArcBridgeService::StopReason stop_reason) override {
33 state_ = ArcBridgeService::State::READY; 29 // The instance is already destructed in ArcBridgeServiceImpl::OnStopped().
34 ready_ = true; 30 bootstrap_ = nullptr;
31
32 stop_reason_ = stop_reason;
35 } 33 }
36 34
37 void OnBridgeStopped(ArcBridgeService::StopReason stop_reason) override { 35 FakeArcBridgeBootstrap* bootstrap() const { return bootstrap_; }
38 state_ = ArcBridgeService::State::STOPPED;
39 stop_reason_ = stop_reason;
40 message_loop_.PostTask(FROM_HERE, message_loop_.QuitWhenIdleClosure());
41 }
42
43 bool ready() const { return ready_; }
44 ArcBridgeService::State state() const { return state_; }
45 36
46 protected: 37 protected:
47 std::unique_ptr<ArcBridgeServiceImpl> service_; 38 std::unique_ptr<ArcBridgeServiceImpl> service_;
48 std::unique_ptr<FakeArcBridgeInstance> instance_;
49 ArcBridgeService::StopReason stop_reason_; 39 ArcBridgeService::StopReason stop_reason_;
50 40
41 void EnableBootFailureEmulation(ArcBridgeService::StopReason reason) {
42 boot_failure_emulation_enabled_ = true;
43 boot_failure_reason_ = reason;
44 }
45
46 void SuspendBoot() { boot_suspended_ = true; }
47
51 private: 48 private:
52 void SetUp() override { 49 void SetUp() override {
53 chromeos::DBusThreadManager::Initialize();
54
55 ready_ = false;
56 state_ = ArcBridgeService::State::STOPPED;
57 stop_reason_ = ArcBridgeService::StopReason::SHUTDOWN; 50 stop_reason_ = ArcBridgeService::StopReason::SHUTDOWN;
58 51
59 instance_.reset(new FakeArcBridgeInstance()); 52 boot_failure_emulation_enabled_ = false;
60 service_.reset(new ArcBridgeServiceImpl( 53 boot_suspended_ = false;
61 base::MakeUnique<FakeArcBridgeBootstrap>(instance_.get())));
62 54
55 service_.reset(new ArcBridgeServiceImpl);
56 service_->SetDelegateForTesting(this);
63 service_->AddObserver(this); 57 service_->AddObserver(this);
64 } 58 }
65 59
66 void TearDown() override { 60 void TearDown() override {
67 service_->RemoveObserver(this); 61 service_->RemoveObserver(this);
68 instance_.reset();
69 service_.reset(); 62 service_.reset();
70
71 chromeos::DBusThreadManager::Shutdown();
72 } 63 }
73 64
74 bool ready_; 65 // ArcBridgeServiceImpl::Delegate.
75 ArcBridgeService::State state_; 66 std::unique_ptr<ArcBridgeBootstrap> CreateBootstrap() override {
76 base::MessageLoopForUI message_loop_; 67 // The testee ArcBridgeServiceImpl instance has the ownership. So, keep
68 // the raw pointer only here.
69 bootstrap_ = new FakeArcBridgeBootstrap;
70 if (boot_failure_emulation_enabled_) {
71 bootstrap_->EnableBootFailureEmulation(boot_failure_reason_);
72 }
73 if (boot_suspended_) {
74 bootstrap_->SuspendBoot();
75 }
76
77 return base::WrapUnique(bootstrap_);
78 }
79
80 // Tracks the current bootstrap instance. This depends on the implementation
81 // details of ArcBridgeServiceImpl.
82 FakeArcBridgeBootstrap* bootstrap_ = nullptr;
83 bool boot_failure_emulation_enabled_ = false;
84 ArcBridgeService::StopReason boot_failure_reason_;
85 bool boot_suspended_ = false;
77 86
78 DISALLOW_COPY_AND_ASSIGN(ArcBridgeTest); 87 DISALLOW_COPY_AND_ASSIGN(ArcBridgeTest);
79 }; 88 };
80 89
81 // Exercises the basic functionality of the ARC Bridge Service. A message from 90 // Exercises the basic functionality of the ARC Bridge Service. A message from
82 // within the instance should cause the observer to be notified. 91 // within the instance should cause the observer to be notified.
83 TEST_F(ArcBridgeTest, Basic) { 92 TEST_F(ArcBridgeTest, Basic) {
84 ASSERT_FALSE(ready()); 93 ASSERT_TRUE(service_->stopped());
85 ASSERT_EQ(ArcBridgeService::State::STOPPED, state());
86 94
87 service_->HandleStartup(); 95 service_->HandleStartup();
88 instance_->WaitForInitCall(); 96 ASSERT_TRUE(service_->ready());
89 ASSERT_EQ(ArcBridgeService::State::READY, state());
90 97
91 service_->Shutdown(); 98 service_->Shutdown();
92 ASSERT_EQ(ArcBridgeService::State::STOPPED, state()); 99 ASSERT_TRUE(service_->stopped());
93 } 100 }
94 101
95 // If the ArcBridgeService is shut down, it should be stopped, even 102 // If the ArcBridgeService is shut down, it should be stopped, even
96 // mid-startup. 103 // mid-startup.
97 TEST_F(ArcBridgeTest, ShutdownMidStartup) { 104 TEST_F(ArcBridgeTest, ShutdownMidStartup) {
98 ASSERT_FALSE(ready()); 105 ASSERT_TRUE(service_->stopped());
99 106
107 SuspendBoot();
100 service_->HandleStartup(); 108 service_->HandleStartup();
101 // WaitForInitCall() omitted. 109 ASSERT_FALSE(service_->stopped());
102 ASSERT_EQ(ArcBridgeService::State::READY, state()); 110 ASSERT_FALSE(service_->ready());
103 111
104 service_->Shutdown(); 112 service_->Shutdown();
105 ASSERT_EQ(ArcBridgeService::State::STOPPED, state()); 113 ASSERT_TRUE(service_->stopped());
114 }
115
116 // If the boot procedure is failed, then restarting mechanism should not
117 // triggered.
118 TEST_F(ArcBridgeTest, BootFailure) {
119 ASSERT_TRUE(service_->stopped());
120
121 EnableBootFailureEmulation(
122 ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE);
123 service_->HandleStartup();
124 EXPECT_EQ(ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE, stop_reason_);
125 ASSERT_TRUE(service_->stopped());
106 } 126 }
107 127
108 // If the instance is stopped, it should be re-started. 128 // If the instance is stopped, it should be re-started.
109 TEST_F(ArcBridgeTest, Restart) { 129 TEST_F(ArcBridgeTest, Restart) {
110 ASSERT_FALSE(ready()); 130 ASSERT_TRUE(service_->stopped());
111 ASSERT_EQ(0, instance_->init_calls());
112 131
113 service_->HandleStartup(); 132 service_->HandleStartup();
114 instance_->WaitForInitCall(); 133 ASSERT_TRUE(service_->ready());
115 ASSERT_EQ(ArcBridgeService::State::READY, state());
116 ASSERT_EQ(1, instance_->init_calls());
117 134
118 // Simulate a connection loss. 135 // Simulate a connection loss.
119 service_->DisableReconnectDelayForTesting(); 136 service_->DisableReconnectDelayForTesting();
120 instance_->Stop(ArcBridgeService::StopReason::CRASH); 137 ASSERT_TRUE(bootstrap());
121 instance_->WaitForInitCall(); 138 bootstrap()->StopWithReason(ArcBridgeService::StopReason::CRASH);
122 ASSERT_EQ(ArcBridgeService::State::READY, state()); 139 ASSERT_TRUE(service_->ready());
123 ASSERT_EQ(2, instance_->init_calls());
124 140
125 service_->Shutdown(); 141 service_->Shutdown();
126 ASSERT_EQ(ArcBridgeService::State::STOPPED, state()); 142 ASSERT_TRUE(service_->stopped());
127 } 143 }
128 144
129 // Makes sure OnBridgeStopped is called on stop. 145 // Makes sure OnBridgeStopped is called on stop.
130 TEST_F(ArcBridgeTest, OnBridgeStopped) { 146 TEST_F(ArcBridgeTest, OnBridgeStopped) {
131 ASSERT_FALSE(ready()); 147 ASSERT_TRUE(service_->stopped());
132 148
133 service_->DisableReconnectDelayForTesting(); 149 service_->DisableReconnectDelayForTesting();
134 service_->HandleStartup(); 150 service_->HandleStartup();
135 instance_->WaitForInitCall(); 151 ASSERT_TRUE(service_->ready());
136 ASSERT_EQ(ArcBridgeService::State::READY, state());
137 152
138 // Simulate boot failure. 153 // Simulate boot failure.
139 instance_->Stop(ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE); 154 ASSERT_TRUE(bootstrap());
140 instance_->WaitForInitCall(); 155 bootstrap()->StopWithReason(
141 ASSERT_EQ(ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE, stop_reason_); 156 ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE);
142 ASSERT_EQ(ArcBridgeService::State::READY, state()); 157 EXPECT_EQ(ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE, stop_reason_);
158 ASSERT_TRUE(service_->ready());
143 159
144 // Simulate crash. 160 // Simulate crash.
145 instance_->Stop(ArcBridgeService::StopReason::CRASH); 161 ASSERT_TRUE(bootstrap());
146 instance_->WaitForInitCall(); 162 bootstrap()->StopWithReason(ArcBridgeService::StopReason::CRASH);
147 ASSERT_EQ(ArcBridgeService::StopReason::CRASH, stop_reason_); 163 EXPECT_EQ(ArcBridgeService::StopReason::CRASH, stop_reason_);
148 ASSERT_EQ(ArcBridgeService::State::READY, state()); 164 ASSERT_TRUE(service_->ready());
149 165
150 // Graceful shutdown. 166 // Graceful shutdown.
151 service_->Shutdown(); 167 service_->Shutdown();
152 ASSERT_EQ(ArcBridgeService::StopReason::SHUTDOWN, stop_reason_); 168 EXPECT_EQ(ArcBridgeService::StopReason::SHUTDOWN, stop_reason_);
153 ASSERT_EQ(ArcBridgeService::State::STOPPED, state()); 169 ASSERT_TRUE(service_->stopped());
154 } 170 }
155 171
156 // Removing the same observer more than once should be okay. 172 // Removing the same observer more than once should be okay.
157 TEST_F(ArcBridgeTest, RemoveObserverTwice) { 173 TEST_F(ArcBridgeTest, RemoveObserverTwice) {
158 ASSERT_FALSE(ready()); 174 ASSERT_TRUE(service_->stopped());
159 service_->RemoveObserver(this); 175 auto dummy_observer = base::MakeUnique<DummyObserver>();
160 // The teardown method will also remove |this|. 176 service_->AddObserver(dummy_observer.get());
177 // Call RemoveObserver() twice.
178 service_->RemoveObserver(dummy_observer.get());
179 service_->RemoveObserver(dummy_observer.get());
161 } 180 }
162 181
163 // Removing an unknown observer should be allowed. 182 // Removing an unknown observer should be allowed.
164 TEST_F(ArcBridgeTest, RemoveUnknownObserver) { 183 TEST_F(ArcBridgeTest, RemoveUnknownObserver) {
165 ASSERT_FALSE(ready()); 184 ASSERT_TRUE(service_->stopped());
166 auto dummy_observer = base::MakeUnique<DummyObserver>(); 185 auto dummy_observer = base::MakeUnique<DummyObserver>();
167 service_->RemoveObserver(dummy_observer.get()); 186 service_->RemoveObserver(dummy_observer.get());
168 } 187 }
169 188
170 } // namespace arc 189 } // namespace arc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698