| 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 |