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