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

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

Powered by Google App Engine
This is Rietveld 408576698