OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include <stddef.h> | |
6 #include <stdint.h> | |
7 | |
8 #include <utility> | |
9 | |
10 #include "base/bind.h" | |
11 #include "base/macros.h" | |
12 #include "base/message_loop/message_loop.h" | |
13 #include "base/process/process_handle.h" | |
14 #include "mojo/public/cpp/bindings/binding_set.h" | |
15 #include "mojo/shell/public/cpp/interface_factory.h" | |
16 #include "mojo/shell/public/cpp/shell_client.h" | |
17 #include "mojo/shell/public/cpp/shell_test.h" | |
18 #include "mojo/shell/public/interfaces/application_manager.mojom.h" | |
19 #include "mojo/shell/tests/application_manager/application_manager_unittest.mojo
m.h" | |
20 | |
21 namespace mojo { | |
22 namespace shell { | |
23 namespace { | |
24 | |
25 class ApplicationManagerTestClient | |
26 : public mojo::test::ShellTestClient, | |
27 public InterfaceFactory<test::mojom::CreateInstanceForHandleTest>, | |
28 public test::mojom::CreateInstanceForHandleTest { | |
29 public: | |
30 explicit ApplicationManagerTestClient(mojo::test::ShellTest* test) | |
31 : ShellTestClient(test), | |
32 target_id_(mojom::Connector::kInvalidApplicationID), | |
33 binding_(this) {} | |
34 ~ApplicationManagerTestClient() override {} | |
35 | |
36 uint32_t target_id() const { return target_id_; } | |
37 | |
38 private: | |
39 // mojo::ShellClient: | |
40 bool AcceptConnection(Connection* connection) override { | |
41 connection->AddInterface<test::mojom::CreateInstanceForHandleTest>(this); | |
42 return true; | |
43 } | |
44 | |
45 // InterfaceFactory<test::mojom::CreateInstanceForHandleTest>: | |
46 void Create( | |
47 Connection* connection, | |
48 test::mojom::CreateInstanceForHandleTestRequest request) override { | |
49 binding_.Bind(std::move(request)); | |
50 } | |
51 | |
52 // test::mojom::CreateInstanceForHandleTest: | |
53 void SetTargetID(uint32_t target_id) override { | |
54 target_id_ = target_id; | |
55 base::MessageLoop::current()->QuitWhenIdle(); | |
56 } | |
57 | |
58 uint32_t target_id_; | |
59 | |
60 Binding<test::mojom::CreateInstanceForHandleTest> binding_; | |
61 | |
62 DISALLOW_COPY_AND_ASSIGN(ApplicationManagerTestClient); | |
63 }; | |
64 | |
65 } // namespace | |
66 | |
67 class ApplicationManagerTest : public mojo::test::ShellTest, | |
68 public mojom::InstanceListener { | |
69 public: | |
70 ApplicationManagerTest() | |
71 : ShellTest("mojo:application_manager_unittest"), | |
72 shell_client_(nullptr), | |
73 binding_(this) {} | |
74 ~ApplicationManagerTest() override {} | |
75 | |
76 void OnDriverQuit() { | |
77 base::MessageLoop::current()->QuitNow(); | |
78 } | |
79 | |
80 protected: | |
81 struct InstanceInfo { | |
82 InstanceInfo(uint32_t id, const std::string& name) | |
83 : id(id), name(name), pid(base::kNullProcessId) {} | |
84 | |
85 uint32_t id; | |
86 std::string name; | |
87 base::ProcessId pid; | |
88 }; | |
89 | |
90 void AddListenerAndWaitForApplications() { | |
91 mojom::ApplicationManagerPtr application_manager; | |
92 connector()->ConnectToInterface("mojo:shell", &application_manager); | |
93 | |
94 application_manager->AddInstanceListener( | |
95 binding_.CreateInterfacePtrAndBind()); | |
96 binding_.WaitForIncomingMethodCall(); | |
97 } | |
98 | |
99 bool ContainsInstanceWithName(const std::string& name) const { | |
100 for (const auto& instance : initial_instances_) { | |
101 if (instance.name == name) | |
102 return true; | |
103 } | |
104 for (const auto& instance : instances_) { | |
105 if (instance.name == name) | |
106 return true; | |
107 } | |
108 return false; | |
109 } | |
110 | |
111 uint32_t target_id() const { | |
112 DCHECK(shell_client_); | |
113 return shell_client_->target_id(); | |
114 } | |
115 | |
116 const std::vector<InstanceInfo>& instances() const { | |
117 return instances_; | |
118 } | |
119 | |
120 private: | |
121 // test::ShellTest: | |
122 scoped_ptr<ShellClient> CreateShellClient() override { | |
123 shell_client_ = new ApplicationManagerTestClient(this); | |
124 return make_scoped_ptr(shell_client_); | |
125 } | |
126 | |
127 // mojom::InstanceListener: | |
128 void SetExistingInstances(Array<mojom::InstanceInfoPtr> instances) override { | |
129 for (size_t i = 0; i < instances.size(); ++i) { | |
130 initial_instances_.push_back(InstanceInfo(instances[i]->id, | |
131 instances[i]->name)); | |
132 } | |
133 } | |
134 void InstanceCreated(mojom::InstanceInfoPtr instance) override { | |
135 instances_.push_back(InstanceInfo(instance->id, instance->name)); | |
136 } | |
137 void InstanceDestroyed(uint32_t id) override { | |
138 for (auto it = instances_.begin(); it != instances_.end(); ++it) { | |
139 auto& instance = *it; | |
140 if (instance.id == id) { | |
141 instances_.erase(it); | |
142 break; | |
143 } | |
144 } | |
145 } | |
146 void InstancePIDAvailable(uint32_t id, uint32_t pid) override { | |
147 for (auto& instance : instances_) { | |
148 if (instance.id == id) { | |
149 instance.pid = pid; | |
150 break; | |
151 } | |
152 } | |
153 } | |
154 | |
155 ApplicationManagerTestClient* shell_client_; | |
156 Binding<mojom::InstanceListener> binding_; | |
157 std::vector<InstanceInfo> instances_; | |
158 std::vector<InstanceInfo> initial_instances_; | |
159 | |
160 DISALLOW_COPY_AND_ASSIGN(ApplicationManagerTest); | |
161 }; | |
162 | |
163 TEST_F(ApplicationManagerTest, CreateInstanceForHandle) { | |
164 AddListenerAndWaitForApplications(); | |
165 | |
166 // 1. Launch a process. (Actually, have the runner launch a process that | |
167 // launches a process.) | |
168 mojo::shell::test::mojom::DriverPtr driver; | |
169 scoped_ptr<Connection> connection = | |
170 connector()->Connect("exe:application_manager_unittest_driver"); | |
171 connection->GetInterface(&driver); | |
172 | |
173 // 2. Wait for the target to connect to us. (via | |
174 // mojo:application_manager_unittest) | |
175 base::MessageLoop::current()->Run(); | |
176 | |
177 uint32_t remote_id = mojom::Connector::kInvalidApplicationID; | |
178 EXPECT_TRUE(connection->GetRemoteApplicationID(&remote_id)); | |
179 EXPECT_NE(mojom::Connector::kInvalidApplicationID, remote_id); | |
180 | |
181 // 3. Validate that this test suite's name was received from the application | |
182 // manager. | |
183 EXPECT_TRUE(ContainsInstanceWithName("mojo:application_manager_unittest")); | |
184 | |
185 // 4. Validate that the right applications/processes were created. | |
186 // Note that the target process will be created even if the tests are | |
187 // run with --single-process. | |
188 EXPECT_EQ(2u, instances().size()); | |
189 { | |
190 auto& instance = instances().front(); | |
191 EXPECT_EQ(remote_id, instance.id); | |
192 EXPECT_EQ("exe:application_manager_unittest_driver", instance.name); | |
193 EXPECT_NE(base::kNullProcessId, instance.pid); | |
194 } | |
195 { | |
196 auto& instance = instances().back(); | |
197 // We learn about the target process id via a ping from it. | |
198 EXPECT_EQ(target_id(), instance.id); | |
199 EXPECT_EQ("exe:application_manager_unittest_target", instance.name); | |
200 EXPECT_NE(base::kNullProcessId, instance.pid); | |
201 } | |
202 | |
203 driver.set_connection_error_handler( | |
204 base::Bind(&ApplicationManagerTest::OnDriverQuit, | |
205 base::Unretained(this))); | |
206 driver->QuitDriver(); | |
207 base::MessageLoop::current()->Run(); | |
208 } | |
209 | |
210 } // namespace shell | |
211 } // namespace mojo | |
OLD | NEW |