OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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> |
| 6 |
5 #include "base/bind.h" | 7 #include "base/bind.h" |
6 #include "base/command_line.h" | 8 #include "base/command_line.h" |
7 #include "base/macros.h" | 9 #include "base/macros.h" |
| 10 #include "base/memory/ptr_util.h" |
8 #include "base/process/process.h" | 11 #include "base/process/process.h" |
9 #include "base/run_loop.h" | 12 #include "base/run_loop.h" |
10 #include "services/shell/public/cpp/identity.h" | 13 #include "services/shell/public/cpp/identity.h" |
11 #include "services/shell/public/cpp/shell_test.h" | 14 #include "services/shell/public/cpp/shell_test.h" |
12 #include "services/shell/public/interfaces/shell.mojom.h" | 15 #include "services/shell/public/interfaces/shell.mojom.h" |
13 #include "services/shell/tests/lifecycle/lifecycle_unittest.mojom.h" | 16 #include "services/shell/tests/lifecycle/lifecycle_unittest.mojom.h" |
14 #include "services/shell/tests/util.h" | 17 #include "services/shell/tests/util.h" |
15 | 18 |
16 namespace mojo { | |
17 namespace shell { | 19 namespace shell { |
| 20 |
18 namespace { | 21 namespace { |
19 | 22 |
20 const char kTestAppName[] = "mojo:lifecycle_unittest_app"; | 23 const char kTestAppName[] = "mojo:lifecycle_unittest_app"; |
21 const char kTestParentName[] = "mojo:lifecycle_unittest_parent"; | 24 const char kTestParentName[] = "mojo:lifecycle_unittest_parent"; |
22 const char kTestExeName[] = "exe:lifecycle_unittest_exe"; | 25 const char kTestExeName[] = "exe:lifecycle_unittest_exe"; |
23 const char kTestPackageName[] = "mojo:lifecycle_unittest_package"; | 26 const char kTestPackageName[] = "mojo:lifecycle_unittest_package"; |
24 const char kTestPackageAppNameA[] = "mojo:lifecycle_unittest_package_app_a"; | 27 const char kTestPackageAppNameA[] = "mojo:lifecycle_unittest_package_app_a"; |
25 const char kTestPackageAppNameB[] = "mojo:lifecycle_unittest_package_app_b"; | 28 const char kTestPackageAppNameB[] = "mojo:lifecycle_unittest_package_app_b"; |
26 const char kTestName[] = "mojo:lifecycle_unittest"; | 29 const char kTestName[] = "mojo:lifecycle_unittest"; |
27 | 30 |
28 void QuitLoop(base::RunLoop* loop) { | 31 void QuitLoop(base::RunLoop* loop) { |
29 loop->Quit(); | 32 loop->Quit(); |
30 } | 33 } |
31 | 34 |
32 void DecrementCountAndQuitWhenZero(base::RunLoop* loop, size_t* count) { | 35 void DecrementCountAndQuitWhenZero(base::RunLoop* loop, size_t* count) { |
33 if (!--(*count)) | 36 if (!--(*count)) |
34 loop->Quit(); | 37 loop->Quit(); |
35 } | 38 } |
36 | 39 |
37 struct Instance { | 40 struct Instance { |
38 Instance() : id(shell::mojom::kInvalidInstanceID), pid(0) {} | 41 Instance() : id(mojom::kInvalidInstanceID), pid(0) {} |
39 Instance(const Identity& identity, uint32_t id, uint32_t pid) | 42 Instance(const Identity& identity, uint32_t id, uint32_t pid) |
40 : identity(identity), id(id), pid(pid) {} | 43 : identity(identity), id(id), pid(pid) {} |
41 | 44 |
42 Identity identity; | 45 Identity identity; |
43 uint32_t id; | 46 uint32_t id; |
44 uint32_t pid; | 47 uint32_t pid; |
45 }; | 48 }; |
46 | 49 |
47 class InstanceState : public mojom::InstanceListener { | 50 class InstanceState : public mojom::InstanceListener { |
48 public: | 51 public: |
(...skipping 10 matching lines...) Expand all Loading... |
59 void WaitForInstanceDestruction(base::RunLoop* loop) { | 62 void WaitForInstanceDestruction(base::RunLoop* loop) { |
60 DCHECK(!destruction_loop_); | 63 DCHECK(!destruction_loop_); |
61 destruction_loop_ = loop; | 64 destruction_loop_ = loop; |
62 // First of all check to see if we should be spinning this loop at all - | 65 // First of all check to see if we should be spinning this loop at all - |
63 // the app(s) we're waiting on quitting may already have quit. | 66 // the app(s) we're waiting on quitting may already have quit. |
64 TryToQuitDestructionLoop(); | 67 TryToQuitDestructionLoop(); |
65 } | 68 } |
66 | 69 |
67 private: | 70 private: |
68 // mojom::InstanceListener: | 71 // mojom::InstanceListener: |
69 void SetExistingInstances(Array<mojom::InstanceInfoPtr> instances) override { | 72 void SetExistingInstances( |
| 73 mojo::Array<mojom::InstanceInfoPtr> instances) override { |
70 for (const auto& instance : instances) { | 74 for (const auto& instance : instances) { |
71 Instance i(instance->identity.To<Identity>(), instance->id, | 75 Instance i(instance->identity.To<Identity>(), instance->id, |
72 instance->pid); | 76 instance->pid); |
73 initial_instances_[i.identity.name()] = i; | 77 initial_instances_[i.identity.name()] = i; |
74 instances_[i.identity.name()] = i; | 78 instances_[i.identity.name()] = i; |
75 } | 79 } |
76 loop_->Quit(); | 80 loop_->Quit(); |
77 } | 81 } |
78 void InstanceCreated(mojom::InstanceInfoPtr instance) override { | 82 void InstanceCreated(mojom::InstanceInfoPtr instance) override { |
79 instances_[instance->identity->name] = | 83 instances_[instance->identity->name] = |
(...skipping 23 matching lines...) Expand all Loading... |
103 destruction_loop_->Quit(); | 107 destruction_loop_->Quit(); |
104 destruction_loop_ = nullptr; | 108 destruction_loop_ = nullptr; |
105 } | 109 } |
106 } | 110 } |
107 | 111 |
108 // All currently running instances. | 112 // All currently running instances. |
109 std::map<std::string, Instance> instances_; | 113 std::map<std::string, Instance> instances_; |
110 // The initial set of instances. | 114 // The initial set of instances. |
111 std::map<std::string, Instance> initial_instances_; | 115 std::map<std::string, Instance> initial_instances_; |
112 | 116 |
113 Binding<mojom::InstanceListener> binding_; | 117 mojo::Binding<mojom::InstanceListener> binding_; |
114 base::RunLoop* loop_; | 118 base::RunLoop* loop_; |
115 | 119 |
116 // Set when the client wants to wait for this object to track the destruction | 120 // Set when the client wants to wait for this object to track the destruction |
117 // of an instance before proceeding. | 121 // of an instance before proceeding. |
118 base::RunLoop* destruction_loop_ = nullptr; | 122 base::RunLoop* destruction_loop_ = nullptr; |
119 | 123 |
120 DISALLOW_COPY_AND_ASSIGN(InstanceState); | 124 DISALLOW_COPY_AND_ASSIGN(InstanceState); |
121 }; | 125 }; |
122 | 126 |
123 } | 127 } // namespace |
124 | 128 |
125 class LifecycleTest : public mojo::test::ShellTest { | 129 class LifecycleTest : public test::ShellTest { |
126 public: | 130 public: |
127 LifecycleTest() : ShellTest(kTestName) {} | 131 LifecycleTest() : ShellTest(kTestName) {} |
128 ~LifecycleTest() override {} | 132 ~LifecycleTest() override {} |
129 | 133 |
130 protected: | 134 protected: |
131 // mojo::test::ShellTest: | 135 // test::ShellTest: |
132 void SetUp() override { | 136 void SetUp() override { |
133 mojo::test::ShellTest::SetUp(); | 137 test::ShellTest::SetUp(); |
134 InitPackage(); | 138 InitPackage(); |
135 instances_ = TrackInstances(); | 139 instances_ = TrackInstances(); |
136 } | 140 } |
137 void TearDown() override { | 141 void TearDown() override { |
138 instances_.reset(); | 142 instances_.reset(); |
139 mojo::test::ShellTest::TearDown(); | 143 test::ShellTest::TearDown(); |
140 } | 144 } |
141 | 145 |
142 bool CanRunCrashTest() { | 146 bool CanRunCrashTest() { |
143 return !base::CommandLine::ForCurrentProcess()->HasSwitch("single-process"); | 147 return !base::CommandLine::ForCurrentProcess()->HasSwitch("single-process"); |
144 } | 148 } |
145 | 149 |
146 void InitPackage() { | 150 void InitPackage() { |
147 test::mojom::LifecycleControlPtr lifecycle = ConnectTo(kTestPackageName); | 151 test::mojom::LifecycleControlPtr lifecycle = ConnectTo(kTestPackageName); |
148 base::RunLoop loop; | 152 base::RunLoop loop; |
149 lifecycle.set_connection_error_handler(base::Bind(&QuitLoop, &loop)); | 153 lifecycle.set_connection_error_handler(base::Bind(&QuitLoop, &loop)); |
(...skipping 30 matching lines...) Expand all Loading... |
180 | 184 |
181 InstanceState* instances() { return instances_.get(); } | 185 InstanceState* instances() { return instances_.get(); } |
182 | 186 |
183 void WaitForInstanceDestruction() { | 187 void WaitForInstanceDestruction() { |
184 base::RunLoop loop; | 188 base::RunLoop loop; |
185 instances()->WaitForInstanceDestruction(&loop); | 189 instances()->WaitForInstanceDestruction(&loop); |
186 loop.Run(); | 190 loop.Run(); |
187 } | 191 } |
188 | 192 |
189 private: | 193 private: |
190 scoped_ptr<InstanceState> TrackInstances() { | 194 std::unique_ptr<InstanceState> TrackInstances() { |
191 mojom::ShellPtr shell; | 195 mojom::ShellPtr shell; |
192 connector()->ConnectToInterface("mojo:shell", &shell); | 196 connector()->ConnectToInterface("mojo:shell", &shell); |
193 mojom::InstanceListenerPtr listener; | 197 mojom::InstanceListenerPtr listener; |
194 base::RunLoop loop; | 198 base::RunLoop loop; |
195 InstanceState* state = new InstanceState(GetProxy(&listener), &loop); | 199 InstanceState* state = new InstanceState(GetProxy(&listener), &loop); |
196 shell->AddInstanceListener(std::move(listener)); | 200 shell->AddInstanceListener(std::move(listener)); |
197 loop.Run(); | 201 loop.Run(); |
198 return make_scoped_ptr(state); | 202 return base::WrapUnique(state); |
199 } | 203 } |
200 | 204 |
201 scoped_ptr<InstanceState> instances_; | 205 std::unique_ptr<InstanceState> instances_; |
202 | 206 |
203 DISALLOW_COPY_AND_ASSIGN(LifecycleTest); | 207 DISALLOW_COPY_AND_ASSIGN(LifecycleTest); |
204 }; | 208 }; |
205 | 209 |
206 TEST_F(LifecycleTest, Standalone_GracefulQuit) { | 210 TEST_F(LifecycleTest, Standalone_GracefulQuit) { |
207 test::mojom::LifecycleControlPtr lifecycle = ConnectTo(kTestAppName); | 211 test::mojom::LifecycleControlPtr lifecycle = ConnectTo(kTestAppName); |
208 | 212 |
209 EXPECT_TRUE(instances()->HasInstanceForName(kTestAppName)); | 213 EXPECT_TRUE(instances()->HasInstanceForName(kTestAppName)); |
210 EXPECT_EQ(1u, instances()->GetNewInstanceCount()); | 214 EXPECT_EQ(1u, instances()->GetNewInstanceCount()); |
211 | 215 |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 process.Terminate(9, true); | 438 process.Terminate(9, true); |
435 loop.Run(); | 439 loop.Run(); |
436 | 440 |
437 WaitForInstanceDestruction(); | 441 WaitForInstanceDestruction(); |
438 EXPECT_FALSE(instances()->HasInstanceForName(kTestExeName)); | 442 EXPECT_FALSE(instances()->HasInstanceForName(kTestExeName)); |
439 EXPECT_EQ(0u, instances()->GetNewInstanceCount()); | 443 EXPECT_EQ(0u, instances()->GetNewInstanceCount()); |
440 } | 444 } |
441 | 445 |
442 TEST_F(LifecycleTest, ShutdownTree) { | 446 TEST_F(LifecycleTest, ShutdownTree) { |
443 // Verifies that Instances are destroyed when their creator is. | 447 // Verifies that Instances are destroyed when their creator is. |
444 scoped_ptr<Connection> parent_connection = | 448 std::unique_ptr<Connection> parent_connection = |
445 connector()->Connect(kTestParentName); | 449 connector()->Connect(kTestParentName); |
446 test::mojom::ParentPtr parent; | 450 test::mojom::ParentPtr parent; |
447 parent_connection->GetInterface(&parent); | 451 parent_connection->GetInterface(&parent); |
448 | 452 |
449 // This asks kTestParentName to open a connection to kTestAppName and blocks | 453 // This asks kTestParentName to open a connection to kTestAppName and blocks |
450 // on a response from a Ping(). | 454 // on a response from a Ping(). |
451 { | 455 { |
452 base::RunLoop loop; | 456 base::RunLoop loop; |
453 parent->ConnectToChild(base::Bind(&QuitLoop, &loop)); | 457 parent->ConnectToChild(base::Bind(&QuitLoop, &loop)); |
454 loop.Run(); | 458 loop.Run(); |
455 } | 459 } |
456 | 460 |
457 // Should now have two new instances (parent and child). | 461 // Should now have two new instances (parent and child). |
458 EXPECT_EQ(2u, instances()->GetNewInstanceCount()); | 462 EXPECT_EQ(2u, instances()->GetNewInstanceCount()); |
459 EXPECT_TRUE(instances()->HasInstanceForName(kTestParentName)); | 463 EXPECT_TRUE(instances()->HasInstanceForName(kTestParentName)); |
460 EXPECT_TRUE(instances()->HasInstanceForName(kTestAppName)); | 464 EXPECT_TRUE(instances()->HasInstanceForName(kTestAppName)); |
461 | 465 |
462 parent->Quit(); | 466 parent->Quit(); |
463 | 467 |
464 // Quitting the parent should cascade-quit the child. | 468 // Quitting the parent should cascade-quit the child. |
465 WaitForInstanceDestruction(); | 469 WaitForInstanceDestruction(); |
466 EXPECT_EQ(0u, instances()->GetNewInstanceCount()); | 470 EXPECT_EQ(0u, instances()->GetNewInstanceCount()); |
467 EXPECT_FALSE(instances()->HasInstanceForName(kTestParentName)); | 471 EXPECT_FALSE(instances()->HasInstanceForName(kTestParentName)); |
468 EXPECT_FALSE(instances()->HasInstanceForName(kTestAppName)); | 472 EXPECT_FALSE(instances()->HasInstanceForName(kTestAppName)); |
469 } | 473 } |
470 | 474 |
471 } // namespace shell | 475 } // namespace shell |
472 } // namespace mojo | |
OLD | NEW |