OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "mojo/services/view_manager/view_manager_connection.h" | 5 #include "mojo/services/view_manager/view_manager_connection.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
12 #include "base/message_loop/message_loop.h" | 12 #include "base/message_loop/message_loop.h" |
13 #include "base/run_loop.h" | 13 #include "base/run_loop.h" |
14 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" |
15 #include "mojo/public/cpp/bindings/allocation_scope.h" | 15 #include "mojo/public/cpp/bindings/allocation_scope.h" |
16 #include "mojo/public/cpp/environment/environment.h" | 16 #include "mojo/public/cpp/environment/environment.h" |
17 #include "mojo/services/view_manager/root_node_manager.h" | 17 #include "mojo/services/public/interfaces/view_manager/view_manager.mojom.h" |
| 18 #include "mojo/shell/shell_test_helper.h" |
18 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
19 | 20 |
20 namespace mojo { | 21 namespace mojo { |
21 namespace services { | 22 namespace services { |
22 namespace view_manager { | 23 namespace view_manager { |
23 | 24 |
24 namespace { | 25 namespace { |
25 | 26 |
26 base::RunLoop* current_run_loop = NULL; | 27 base::RunLoop* current_run_loop = NULL; |
27 | 28 |
| 29 uint16_t FirstIdFromTransportId(uint32_t id) { |
| 30 return static_cast<uint16_t>((id >> 16) & 0xFFFF); |
| 31 } |
| 32 |
| 33 uint16_t SecondIdFromTransportId(uint32_t id) { |
| 34 return static_cast<uint16_t>(id & 0xFFFF); |
| 35 } |
| 36 |
28 // Sets |current_run_loop| and runs it. It is expected that someone else quits | 37 // Sets |current_run_loop| and runs it. It is expected that someone else quits |
29 // the loop. | 38 // the loop. |
30 void DoRunLoop() { | 39 void DoRunLoop() { |
31 base::RunLoop run_loop; | 40 base::RunLoop run_loop; |
32 current_run_loop = &run_loop; | 41 current_run_loop = &run_loop; |
33 current_run_loop->Run(); | 42 current_run_loop->Run(); |
34 current_run_loop = NULL; | 43 current_run_loop = NULL; |
35 } | 44 } |
36 | 45 |
37 // Converts |id| into a string. | 46 // Converts |id| into a string. |
38 std::string NodeIdToString(uint32_t id) { | 47 std::string NodeIdToString(uint32_t id) { |
39 return (id == 0) ? "null" : | 48 return (id == 0) ? "null" : |
40 base::StringPrintf("%d,%d", FirstIdFromTransportId(id), | 49 base::StringPrintf("%d,%d", FirstIdFromTransportId(id), |
41 SecondIdFromTransportId(id)); | 50 SecondIdFromTransportId(id)); |
42 } | 51 } |
43 | 52 |
44 // Boolean callback. Sets |result_cache| to the value of |result| and quits | 53 // Boolean callback. Sets |result_cache| to the value of |result| and quits |
45 // the run loop. | 54 // the run loop. |
46 void BooleanCallback(bool* result_cache, bool result) { | 55 void BooleanCallback(bool* result_cache, bool result) { |
47 *result_cache = result; | 56 *result_cache = result; |
48 current_run_loop->Quit(); | 57 current_run_loop->Quit(); |
49 } | 58 } |
50 | 59 |
51 // Creates an id used for transport from the specified parameters. | 60 // Creates an id used for transport from the specified parameters. |
52 uint32_t CreateNodeId(uint16_t connection_id, uint16_t node_id) { | 61 uint32_t CreateNodeId(uint16_t connection_id, uint16_t node_id) { |
53 return NodeIdToTransportId(NodeId(connection_id, node_id)); | 62 return (connection_id << 16) | node_id; |
54 } | 63 } |
55 | 64 |
56 // Creates an id used for transport from the specified parameters. | 65 // Creates an id used for transport from the specified parameters. |
57 uint32_t CreateViewId(uint16_t connection_id, uint16_t view_id) { | 66 uint32_t CreateViewId(uint16_t connection_id, uint16_t view_id) { |
58 return ViewIdToTransportId(ViewId(connection_id, view_id)); | 67 return (connection_id << 16) | view_id; |
59 } | 68 } |
60 | 69 |
61 // Creates a node with the specified id. Returns true on success. Blocks until | 70 // Creates a node with the specified id. Returns true on success. Blocks until |
62 // we get back result from server. | 71 // we get back result from server. |
63 bool CreateNode(ViewManager* view_manager, uint16_t id) { | 72 bool CreateNode(ViewManager* view_manager, uint16_t id) { |
64 bool result = false; | 73 bool result = false; |
65 view_manager->CreateNode(id, base::Bind(&BooleanCallback, &result)); | 74 view_manager->CreateNode(id, base::Bind(&BooleanCallback, &result)); |
66 DoRunLoop(); | 75 DoRunLoop(); |
67 return result; | 76 return result; |
68 } | 77 } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
126 } | 135 } |
127 | 136 |
128 } // namespace | 137 } // namespace |
129 | 138 |
130 typedef std::vector<std::string> Changes; | 139 typedef std::vector<std::string> Changes; |
131 | 140 |
132 class ViewManagerClientImpl : public ViewManagerClient { | 141 class ViewManagerClientImpl : public ViewManagerClient { |
133 public: | 142 public: |
134 ViewManagerClientImpl() : id_(0), quit_count_(0) {} | 143 ViewManagerClientImpl() : id_(0), quit_count_(0) {} |
135 | 144 |
136 void set_quit_count(int count) { quit_count_ = count; } | |
137 | |
138 uint16_t id() const { return id_; } | 145 uint16_t id() const { return id_; } |
139 | 146 |
140 Changes GetAndClearChanges() { | 147 Changes GetAndClearChanges() { |
141 Changes changes; | 148 Changes changes; |
142 changes.swap(changes_); | 149 changes.swap(changes_); |
143 return changes; | 150 return changes; |
144 } | 151 } |
145 | 152 |
| 153 void WaitForId() { |
| 154 if (id_ == 0) |
| 155 DoRunLoop(); |
| 156 } |
| 157 |
| 158 void DoRunLoopUntilChangesCount(size_t count) { |
| 159 if (changes_.size() >= count) |
| 160 return; |
| 161 quit_count_ = count - changes_.size(); |
| 162 DoRunLoop(); |
| 163 } |
| 164 |
146 private: | 165 private: |
147 // ViewManagerClient overrides: | 166 // ViewManagerClient overrides: |
148 virtual void OnConnectionEstablished(uint16_t connection_id) OVERRIDE { | 167 virtual void OnConnectionEstablished(uint16_t connection_id) OVERRIDE { |
149 id_ = connection_id; | 168 id_ = connection_id; |
150 current_run_loop->Quit(); | 169 if (current_run_loop) |
| 170 current_run_loop->Quit(); |
151 } | 171 } |
152 virtual void OnNodeHierarchyChanged(uint32_t node, | 172 virtual void OnNodeHierarchyChanged(uint32_t node, |
153 uint32_t new_parent, | 173 uint32_t new_parent, |
154 uint32_t old_parent, | 174 uint32_t old_parent, |
155 int32_t change_id) OVERRIDE { | 175 int32_t change_id) OVERRIDE { |
156 changes_.push_back( | 176 changes_.push_back( |
157 base::StringPrintf( | 177 base::StringPrintf( |
158 "change_id=%d node=%s new_parent=%s old_parent=%s", | 178 "change_id=%d node=%s new_parent=%s old_parent=%s", |
159 change_id, NodeIdToString(node).c_str(), | 179 change_id, NodeIdToString(node).c_str(), |
160 NodeIdToString(new_parent).c_str(), | 180 NodeIdToString(new_parent).c_str(), |
(...skipping 14 matching lines...) Expand all Loading... |
175 } | 195 } |
176 | 196 |
177 void QuitIfNecessary() { | 197 void QuitIfNecessary() { |
178 if (quit_count_ > 0 && --quit_count_ == 0) | 198 if (quit_count_ > 0 && --quit_count_ == 0) |
179 current_run_loop->Quit(); | 199 current_run_loop->Quit(); |
180 } | 200 } |
181 | 201 |
182 uint16_t id_; | 202 uint16_t id_; |
183 | 203 |
184 // Used to determine when/if to quit the run loop. | 204 // Used to determine when/if to quit the run loop. |
185 int quit_count_; | 205 size_t quit_count_; |
186 | 206 |
187 Changes changes_; | 207 Changes changes_; |
188 | 208 |
189 DISALLOW_COPY_AND_ASSIGN(ViewManagerClientImpl); | 209 DISALLOW_COPY_AND_ASSIGN(ViewManagerClientImpl); |
190 }; | 210 }; |
191 | 211 |
192 class ViewManagerConnectionTest : public testing::Test { | 212 class ViewManagerConnectionTest : public testing::Test { |
193 public: | 213 public: |
194 ViewManagerConnectionTest() : service_factory_(&root_node_manager_) {} | 214 ViewManagerConnectionTest() {} |
195 | 215 |
196 virtual void SetUp() OVERRIDE { | 216 virtual void SetUp() OVERRIDE { |
197 InterfacePipe<ViewManagerClient, ViewManager> pipe; | 217 AllocationScope allocation_scope; |
198 view_manager_.reset(pipe.handle_to_peer.Pass(), &client_); | 218 |
199 connection_.Initialize( | 219 test_helper_.Init(); |
200 &service_factory_, | 220 |
201 ScopedMessagePipeHandle::From(pipe.handle_to_self.Pass())); | 221 InterfacePipe<ViewManager, AnyInterface> pipe; |
202 // Wait for the id. | 222 test_helper_.shell()->Connect("mojo:mojo_view_manager", |
203 DoRunLoop(); | 223 pipe.handle_to_peer.Pass()); |
| 224 view_manager_.reset(pipe.handle_to_self.Pass(), &client_); |
| 225 |
| 226 client_.WaitForId(); |
204 } | 227 } |
205 | 228 |
206 protected: | 229 protected: |
207 // Creates a second connection to the viewmanager. | 230 // Creates a second connection to the viewmanager. |
208 void EstablishSecondConnection() { | 231 void EstablishSecondConnection() { |
209 connection2_.reset(new ViewManagerConnection); | 232 AllocationScope allocation_scope; |
210 InterfacePipe<ViewManagerClient, ViewManager> pipe; | 233 InterfacePipe<ViewManager, AnyInterface> pipe; |
211 view_manager2_.reset(pipe.handle_to_peer.Pass(), &client2_); | 234 test_helper_.shell()->Connect("mojo:mojo_view_manager", |
212 connection2_->Initialize( | 235 pipe.handle_to_peer.Pass()); |
213 &service_factory_, | 236 view_manager2_.reset(pipe.handle_to_self.Pass(), &client2_); |
214 ScopedMessagePipeHandle::From(pipe.handle_to_self.Pass())); | 237 |
215 // Wait for the id. | 238 client2_.WaitForId(); |
216 DoRunLoop(); | |
217 } | 239 } |
218 | 240 |
219 void DestroySecondConnection() { | 241 void DestroySecondConnection() { |
220 connection2_.reset(); | |
221 view_manager2_.reset(); | 242 view_manager2_.reset(); |
222 } | 243 } |
223 | 244 |
224 Environment env_; | |
225 base::MessageLoop loop_; | 245 base::MessageLoop loop_; |
226 RootNodeManager root_node_manager_; | 246 shell::ShellTestHelper test_helper_; |
227 ServiceConnector<ViewManagerConnection, RootNodeManager> service_factory_; | 247 |
228 ViewManagerConnection connection_; | |
229 ViewManagerClientImpl client_; | 248 ViewManagerClientImpl client_; |
230 RemotePtr<ViewManager> view_manager_; | 249 RemotePtr<ViewManager> view_manager_; |
231 | 250 |
232 ViewManagerClientImpl client2_; | 251 ViewManagerClientImpl client2_; |
233 RemotePtr<ViewManager> view_manager2_; | 252 RemotePtr<ViewManager> view_manager2_; |
234 scoped_ptr<ViewManagerConnection> connection2_; | |
235 | 253 |
236 DISALLOW_COPY_AND_ASSIGN(ViewManagerConnectionTest); | 254 DISALLOW_COPY_AND_ASSIGN(ViewManagerConnectionTest); |
237 }; | 255 }; |
238 | 256 |
239 // Verifies client gets a valid id. | 257 // Verifies client gets a valid id. |
240 TEST_F(ViewManagerConnectionTest, ValidId) { | 258 TEST_F(ViewManagerConnectionTest, ValidId) { |
241 // All these tests assume 1 for the client id. The only real assertion here is | 259 // All these tests assume 1 for the client id. The only real assertion here is |
242 // the client id is not zero, but adding this as rest of code here assumes 1. | 260 // the client id is not zero, but adding this as rest of code here assumes 1. |
243 EXPECT_EQ(1, client_.id()); | 261 EXPECT_EQ(1, client_.id()); |
244 } | 262 } |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 CreateNodeId(client_.id(), 2), | 328 CreateNodeId(client_.id(), 2), |
311 11)); | 329 11)); |
312 Changes changes(client_.GetAndClearChanges()); | 330 Changes changes(client_.GetAndClearChanges()); |
313 ASSERT_EQ(1u, changes.size()); | 331 ASSERT_EQ(1u, changes.size()); |
314 EXPECT_EQ("change_id=11 node=1,2 new_parent=1,1 old_parent=null", | 332 EXPECT_EQ("change_id=11 node=1,2 new_parent=1,1 old_parent=null", |
315 changes[0]); | 333 changes[0]); |
316 } | 334 } |
317 | 335 |
318 // Second client should also have received the change. | 336 // Second client should also have received the change. |
319 { | 337 { |
| 338 client2_.DoRunLoopUntilChangesCount(1); |
320 Changes changes(client2_.GetAndClearChanges()); | 339 Changes changes(client2_.GetAndClearChanges()); |
321 if (changes.empty()) { | |
322 client2_.set_quit_count(1); | |
323 DoRunLoop(); | |
324 changes = client2_.GetAndClearChanges(); | |
325 } | |
326 ASSERT_EQ(1u, changes.size()); | 340 ASSERT_EQ(1u, changes.size()); |
327 EXPECT_EQ("change_id=0 node=1,2 new_parent=1,1 old_parent=null", | 341 EXPECT_EQ("change_id=0 node=1,2 new_parent=1,1 old_parent=null", |
328 changes[0]); | 342 changes[0]); |
329 } | 343 } |
330 } | 344 } |
331 | 345 |
332 // Verifies adding to root sends right notifications. | 346 // Verifies adding to root sends right notifications. |
333 TEST_F(ViewManagerConnectionTest, AddToRoot) { | 347 TEST_F(ViewManagerConnectionTest, AddToRoot) { |
334 ASSERT_TRUE(CreateNode(view_manager_.get(), 21)); | 348 ASSERT_TRUE(CreateNode(view_manager_.get(), 21)); |
335 ASSERT_TRUE(CreateNode(view_manager_.get(), 3)); | 349 ASSERT_TRUE(CreateNode(view_manager_.get(), 3)); |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
493 | 507 |
494 // Create a view in the second connection. | 508 // Create a view in the second connection. |
495 ASSERT_TRUE(CreateView(view_manager2_.get(), 51)); | 509 ASSERT_TRUE(CreateView(view_manager2_.get(), 51)); |
496 | 510 |
497 // Attach view to node 1 in the first connection. | 511 // Attach view to node 1 in the first connection. |
498 { | 512 { |
499 ASSERT_TRUE(SetView(view_manager2_.get(), | 513 ASSERT_TRUE(SetView(view_manager2_.get(), |
500 CreateNodeId(client_.id(), 1), | 514 CreateNodeId(client_.id(), 1), |
501 CreateViewId(client2_.id(), 51), | 515 CreateViewId(client2_.id(), 51), |
502 22)); | 516 22)); |
| 517 client_.DoRunLoopUntilChangesCount(1); |
503 Changes changes(client_.GetAndClearChanges()); | 518 Changes changes(client_.GetAndClearChanges()); |
504 ASSERT_EQ(1u, changes.size()); | 519 ASSERT_EQ(1u, changes.size()); |
505 EXPECT_EQ("change_id=0 node=1,1 new_view=2,51 old_view=null", changes[0]); | 520 EXPECT_EQ("change_id=0 node=1,1 new_view=2,51 old_view=null", changes[0]); |
506 | 521 |
| 522 client2_.DoRunLoopUntilChangesCount(1); |
507 changes = client2_.GetAndClearChanges(); | 523 changes = client2_.GetAndClearChanges(); |
508 ASSERT_EQ(1u, changes.size()); | 524 ASSERT_EQ(1u, changes.size()); |
509 EXPECT_EQ("change_id=22 node=1,1 new_view=2,51 old_view=null", changes[0]); | 525 EXPECT_EQ("change_id=22 node=1,1 new_view=2,51 old_view=null", changes[0]); |
510 } | 526 } |
511 | 527 |
512 // Shutdown the second connection and verify view is removed. | 528 // Shutdown the second connection and verify view is removed. |
513 { | 529 { |
514 DestroySecondConnection(); | 530 DestroySecondConnection(); |
515 client_.set_quit_count(1); | 531 client_.DoRunLoopUntilChangesCount(1); |
516 DoRunLoop(); | |
517 | 532 |
518 Changes changes(client_.GetAndClearChanges()); | 533 Changes changes(client_.GetAndClearChanges()); |
519 ASSERT_EQ(1u, changes.size()); | 534 ASSERT_EQ(1u, changes.size()); |
520 EXPECT_EQ("change_id=0 node=1,1 new_view=null old_view=2,51", changes[0]); | 535 EXPECT_EQ("change_id=0 node=1,1 new_view=null old_view=2,51", changes[0]); |
521 } | 536 } |
522 } | 537 } |
523 | 538 |
524 } // namespace view_manager | 539 } // namespace view_manager |
525 } // namespace services | 540 } // namespace services |
526 } // namespace mojo | 541 } // namespace mojo |
OLD | NEW |