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 <string> | 5 #include <string> |
6 #include <vector> | 6 #include <vector> |
7 | 7 |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
11 #include "base/run_loop.h" | 11 #include "base/run_loop.h" |
12 #include "base/strings/stringprintf.h" | 12 #include "base/strings/stringprintf.h" |
| 13 #include "mojo/common/common_type_converters.h" |
13 #include "mojo/public/cpp/bindings/allocation_scope.h" | 14 #include "mojo/public/cpp/bindings/allocation_scope.h" |
14 #include "mojo/public/cpp/environment/environment.h" | 15 #include "mojo/public/cpp/environment/environment.h" |
15 #include "mojo/public/cpp/shell/connect.h" | 16 #include "mojo/public/cpp/shell/connect.h" |
16 #include "mojo/services/public/cpp/view_manager/util.h" | 17 #include "mojo/services/public/cpp/view_manager/util.h" |
17 #include "mojo/services/public/cpp/view_manager/view_manager_types.h" | 18 #include "mojo/services/public/cpp/view_manager/view_manager_types.h" |
18 #include "mojo/services/public/interfaces/view_manager/view_manager.mojom.h" | 19 #include "mojo/services/public/interfaces/view_manager/view_manager.mojom.h" |
19 #include "mojo/shell/shell_test_helper.h" | 20 #include "mojo/shell/shell_test_helper.h" |
20 #include "testing/gtest/include/gtest/gtest.h" | 21 #include "testing/gtest/include/gtest/gtest.h" |
21 | 22 |
22 namespace mojo { | 23 namespace mojo { |
| 24 |
| 25 // TODO(sky): remove this when Darin is done with cleanup. |
| 26 template <typename T> |
| 27 class MOJO_COMMON_EXPORT TypeConverter<T, T> { |
| 28 public: |
| 29 static T ConvertFrom(T input, Buffer* buf) { |
| 30 return input; |
| 31 } |
| 32 static T ConvertTo(T input) { |
| 33 return input; |
| 34 } |
| 35 |
| 36 MOJO_ALLOW_IMPLICIT_TYPE_CONVERSION(); |
| 37 }; |
| 38 |
23 namespace view_manager { | 39 namespace view_manager { |
24 namespace service { | 40 namespace service { |
25 | 41 |
26 namespace { | 42 namespace { |
27 | 43 |
28 base::RunLoop* current_run_loop = NULL; | 44 base::RunLoop* current_run_loop = NULL; |
29 | 45 |
30 // Sets |current_run_loop| and runs it. It is expected that someone else quits | 46 // Sets |current_run_loop| and runs it. It is expected that someone else quits |
31 // the loop. | 47 // the loop. |
32 void DoRunLoop() { | 48 void DoRunLoop() { |
| 49 DCHECK(!current_run_loop); |
| 50 |
33 base::RunLoop run_loop; | 51 base::RunLoop run_loop; |
34 current_run_loop = &run_loop; | 52 current_run_loop = &run_loop; |
35 current_run_loop->Run(); | 53 current_run_loop->Run(); |
36 current_run_loop = NULL; | 54 current_run_loop = NULL; |
37 } | 55 } |
38 | 56 |
39 // Converts |id| into a string. | 57 // Converts |id| into a string. |
40 std::string NodeIdToString(TransportNodeId id) { | 58 std::string NodeIdToString(TransportNodeId id) { |
41 return (id == 0) ? "null" : | 59 return (id == 0) ? "null" : |
42 base::StringPrintf("%d,%d", HiWord(id), LoWord(id)); | 60 base::StringPrintf("%d,%d", HiWord(id), LoWord(id)); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 bool SetView(IViewManager* view_manager, | 186 bool SetView(IViewManager* view_manager, |
169 TransportNodeId node_id, | 187 TransportNodeId node_id, |
170 TransportViewId view_id) { | 188 TransportViewId view_id) { |
171 bool result = false; | 189 bool result = false; |
172 view_manager->SetView(node_id, view_id, | 190 view_manager->SetView(node_id, view_id, |
173 base::Bind(&BooleanCallback, &result)); | 191 base::Bind(&BooleanCallback, &result)); |
174 DoRunLoop(); | 192 DoRunLoop(); |
175 return result; | 193 return result; |
176 } | 194 } |
177 | 195 |
| 196 bool SetRoots(IViewManager* view_manager, |
| 197 TransportConnectionId connection_id, |
| 198 const std::vector<uint32_t>& node_ids) { |
| 199 bool result = false; |
| 200 view_manager->SetRoots(connection_id, |
| 201 Array<uint32_t>::From(node_ids), |
| 202 base::Bind(&BooleanCallback, &result)); |
| 203 DoRunLoop(); |
| 204 return result; |
| 205 } |
| 206 |
178 } // namespace | 207 } // namespace |
179 | 208 |
180 typedef std::vector<std::string> Changes; | 209 typedef std::vector<std::string> Changes; |
181 | 210 |
182 class ViewManagerClientImpl : public IViewManagerClient { | 211 class ViewManagerClientImpl : public IViewManagerClient { |
183 public: | 212 public: |
184 ViewManagerClientImpl() | 213 ViewManagerClientImpl() |
185 : id_(0), | 214 : id_(0), |
186 next_server_change_id_(0), | 215 next_server_change_id_(0), |
187 quit_count_(0) {} | 216 quit_count_(0) {} |
188 | 217 |
189 TransportConnectionId id() const { return id_; } | 218 TransportConnectionId id() const { return id_; } |
190 | 219 |
191 TransportChangeId next_server_change_id() const { | 220 TransportChangeId next_server_change_id() const { |
192 return next_server_change_id_; | 221 return next_server_change_id_; |
193 } | 222 } |
194 const std::vector<TestNode>& initial_nodes() const { | 223 const std::vector<TestNode>& initial_nodes() const { |
195 return initial_nodes_; | 224 return initial_nodes_; |
196 } | 225 } |
197 const std::vector<TestNode>& hierarchy_changed_nodes() const { | 226 const std::vector<TestNode>& hierarchy_changed_nodes() const { |
198 return hierarchy_changed_nodes_; | 227 return hierarchy_changed_nodes_; |
199 } | 228 } |
200 | 229 |
201 Changes GetAndClearChanges() { | 230 Changes GetAndClearChanges() { |
202 Changes changes; | 231 Changes changes; |
203 changes.swap(changes_); | 232 changes.swap(changes_); |
204 return changes; | 233 return changes; |
205 } | 234 } |
206 | 235 |
| 236 void ClearId() { |
| 237 id_ = 0; |
| 238 } |
| 239 |
207 void WaitForId() { | 240 void WaitForId() { |
208 if (id_ == 0) | 241 DCHECK_EQ(0, id_); |
209 DoRunLoop(); | 242 DoRunLoopUntilChangesCount(1); |
210 } | 243 } |
211 | 244 |
212 void DoRunLoopUntilChangesCount(size_t count) { | 245 void DoRunLoopUntilChangesCount(size_t count) { |
213 if (changes_.size() >= count) | 246 if (changes_.size() >= count) |
214 return; | 247 return; |
215 quit_count_ = count - changes_.size(); | 248 quit_count_ = count - changes_.size(); |
216 DoRunLoop(); | 249 DoRunLoop(); |
217 } | 250 } |
218 | 251 |
219 private: | 252 private: |
220 // IViewManagerClient overrides: | 253 // IViewManagerClient overrides: |
221 virtual void OnConnectionEstablished( | 254 virtual void OnConnectionEstablished( |
222 TransportConnectionId connection_id, | 255 TransportConnectionId connection_id, |
223 TransportChangeId next_server_change_id, | 256 TransportChangeId next_server_change_id, |
224 const mojo::Array<INode>& nodes) OVERRIDE { | 257 const mojo::Array<INode>& nodes) OVERRIDE { |
225 id_ = connection_id; | 258 id_ = connection_id; |
226 next_server_change_id_ = next_server_change_id; | 259 next_server_change_id_ = next_server_change_id; |
| 260 initial_nodes_.clear(); |
227 INodesToTestNodes(nodes, &initial_nodes_); | 261 INodesToTestNodes(nodes, &initial_nodes_); |
228 if (current_run_loop) | 262 changes_.push_back("OnConnectionEstablished"); |
229 current_run_loop->Quit(); | 263 QuitIfNecessary(); |
230 } | 264 } |
231 virtual void OnServerChangeIdAdvanced( | 265 virtual void OnServerChangeIdAdvanced( |
232 uint32_t next_server_change_id) OVERRIDE { | 266 uint32_t next_server_change_id) OVERRIDE { |
233 changes_.push_back( | 267 changes_.push_back( |
234 base::StringPrintf( | 268 base::StringPrintf( |
235 "ServerChangeIdAdvanced %d", | 269 "ServerChangeIdAdvanced %d", |
236 static_cast<int>(next_server_change_id))); | 270 static_cast<int>(next_server_change_id))); |
237 QuitIfNecessary(); | 271 QuitIfNecessary(); |
238 } | 272 } |
239 virtual void OnNodeHierarchyChanged( | 273 virtual void OnNodeHierarchyChanged( |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 public: | 341 public: |
308 ViewManagerConnectionTest() {} | 342 ViewManagerConnectionTest() {} |
309 | 343 |
310 virtual void SetUp() OVERRIDE { | 344 virtual void SetUp() OVERRIDE { |
311 test_helper_.Init(); | 345 test_helper_.Init(); |
312 | 346 |
313 ConnectTo(test_helper_.shell(), "mojo:mojo_view_manager", &view_manager_); | 347 ConnectTo(test_helper_.shell(), "mojo:mojo_view_manager", &view_manager_); |
314 view_manager_->SetClient(&client_); | 348 view_manager_->SetClient(&client_); |
315 | 349 |
316 client_.WaitForId(); | 350 client_.WaitForId(); |
| 351 client_.GetAndClearChanges(); |
317 } | 352 } |
318 | 353 |
319 protected: | 354 protected: |
320 // Creates a second connection to the viewmanager. | 355 // Creates a second connection to the viewmanager. |
321 void EstablishSecondConnection() { | 356 void EstablishSecondConnection() { |
322 ConnectTo(test_helper_.shell(), "mojo:mojo_view_manager", &view_manager2_); | 357 ConnectTo(test_helper_.shell(), "mojo:mojo_view_manager", &view_manager2_); |
323 view_manager2_->SetClient(&client2_); | 358 view_manager2_->SetClient(&client2_); |
324 | 359 |
325 client2_.WaitForId(); | 360 client2_.WaitForId(); |
| 361 client2_.GetAndClearChanges(); |
326 } | 362 } |
327 | 363 |
328 void DestroySecondConnection() { | 364 void DestroySecondConnection() { |
329 view_manager2_.reset(); | 365 view_manager2_.reset(); |
330 } | 366 } |
331 | 367 |
332 base::MessageLoop loop_; | 368 base::MessageLoop loop_; |
333 shell::ShellTestHelper test_helper_; | 369 shell::ShellTestHelper test_helper_; |
334 | 370 |
335 ViewManagerClientImpl client_; | 371 ViewManagerClientImpl client_; |
(...skipping 749 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1085 { | 1121 { |
1086 AllocationScope scope; | 1122 AllocationScope scope; |
1087 std::vector<TestNode> nodes; | 1123 std::vector<TestNode> nodes; |
1088 GetNodeTree(view_manager2_.get(), CreateNodeId(1, 1), &nodes); | 1124 GetNodeTree(view_manager2_.get(), CreateNodeId(1, 1), &nodes); |
1089 ASSERT_EQ(2u, nodes.size()); | 1125 ASSERT_EQ(2u, nodes.size()); |
1090 EXPECT_EQ("node=1,1 parent=0,1 view=null", nodes[0].ToString()); | 1126 EXPECT_EQ("node=1,1 parent=0,1 view=null", nodes[0].ToString()); |
1091 EXPECT_EQ("node=1,11 parent=1,1 view=1,51", nodes[1].ToString()); | 1127 EXPECT_EQ("node=1,11 parent=1,1 view=1,51", nodes[1].ToString()); |
1092 } | 1128 } |
1093 } | 1129 } |
1094 | 1130 |
| 1131 TEST_F(ViewManagerConnectionTest, SetRoots) { |
| 1132 // Create 1, 2, and 3 in the first connection. |
| 1133 ASSERT_TRUE(CreateNode(view_manager_.get(), 1, 1)); |
| 1134 ASSERT_TRUE(CreateNode(view_manager_.get(), 1, 2)); |
| 1135 ASSERT_TRUE(CreateNode(view_manager_.get(), 1, 3)); |
| 1136 |
| 1137 // Parent 1 to the root. |
| 1138 ASSERT_TRUE(AddNode(view_manager_.get(), |
| 1139 CreateNodeId(0, 1), |
| 1140 CreateNodeId(client_.id(), 1), |
| 1141 1)); |
| 1142 |
| 1143 // Establish the second connection and give it the roots 1 and 3. |
| 1144 EstablishSecondConnection(); |
| 1145 client2_.ClearId(); |
| 1146 { |
| 1147 AllocationScope scope; |
| 1148 std::vector<uint32_t> roots; |
| 1149 roots.push_back(CreateNodeId(1, 1)); |
| 1150 roots.push_back(CreateNodeId(1, 3)); |
| 1151 ASSERT_TRUE(SetRoots(view_manager_.get(), 2, roots)); |
| 1152 client2_.DoRunLoopUntilChangesCount(1); |
| 1153 Changes changes(client2_.GetAndClearChanges()); |
| 1154 ASSERT_EQ(1u, changes.size()); |
| 1155 EXPECT_EQ("OnConnectionEstablished", changes[0]); |
| 1156 ASSERT_NE(0u, client2_.id()); |
| 1157 const std::vector<TestNode>& nodes(client2_.initial_nodes()); |
| 1158 ASSERT_EQ(2u, nodes.size()); |
| 1159 EXPECT_EQ("node=1,1 parent=null view=null", nodes[0].ToString()); |
| 1160 EXPECT_EQ("node=1,3 parent=null view=null", nodes[1].ToString()); |
| 1161 } |
| 1162 |
| 1163 // Create 4 and add it to the root, connection 2 should only get id advanced. |
| 1164 { |
| 1165 ASSERT_TRUE(CreateNode(view_manager_.get(), 1, 4)); |
| 1166 ASSERT_TRUE(AddNode(view_manager_.get(), |
| 1167 CreateNodeId(0, 1), |
| 1168 CreateNodeId(client_.id(), 4), |
| 1169 2)); |
| 1170 client2_.DoRunLoopUntilChangesCount(1); |
| 1171 Changes changes(client2_.GetAndClearChanges()); |
| 1172 ASSERT_EQ(1u, changes.size()); |
| 1173 EXPECT_EQ("ServerChangeIdAdvanced 3", changes[0]); |
| 1174 } |
| 1175 |
| 1176 // Move 4 under 3, this should expose 4 to the client. |
| 1177 { |
| 1178 ASSERT_TRUE(AddNode(view_manager_.get(), |
| 1179 CreateNodeId(1, 3), |
| 1180 CreateNodeId(1, 4), |
| 1181 3)); |
| 1182 client2_.DoRunLoopUntilChangesCount(1); |
| 1183 Changes changes(client2_.GetAndClearChanges()); |
| 1184 ASSERT_EQ(1u, changes.size()); |
| 1185 EXPECT_EQ( |
| 1186 "HierarchyChanged change_id=3 node=1,4 new_parent=1,3 " |
| 1187 "old_parent=null", changes[0]); |
| 1188 const std::vector<TestNode>& nodes(client2_.hierarchy_changed_nodes()); |
| 1189 ASSERT_EQ(1u, nodes.size()); |
| 1190 EXPECT_EQ("node=1,4 parent=1,3 view=null", nodes[0].ToString()); |
| 1191 } |
| 1192 |
| 1193 // Move 4 under 2, since 2 isn't a root client should get a delete. |
| 1194 { |
| 1195 ASSERT_TRUE(AddNode(view_manager_.get(), |
| 1196 CreateNodeId(1, 2), |
| 1197 CreateNodeId(1, 4), |
| 1198 4)); |
| 1199 client2_.DoRunLoopUntilChangesCount(1); |
| 1200 Changes changes(client2_.GetAndClearChanges()); |
| 1201 ASSERT_EQ(1u, changes.size()); |
| 1202 EXPECT_EQ("NodeDeleted change_id=4 node=1,4", changes[0]); |
| 1203 } |
| 1204 |
| 1205 // Delete 4, client shouldn't receive a delete since it should no longer know |
| 1206 // about 4. |
| 1207 { |
| 1208 ASSERT_TRUE(DeleteNode(view_manager_.get(), CreateNodeId(client_.id(), 4))); |
| 1209 ASSERT_TRUE(client_.GetAndClearChanges().empty()); |
| 1210 |
| 1211 client2_.DoRunLoopUntilChangesCount(1); |
| 1212 Changes changes(client2_.GetAndClearChanges()); |
| 1213 ASSERT_EQ(1u, changes.size()); |
| 1214 EXPECT_EQ("ServerChangeIdAdvanced 6", changes[0]); |
| 1215 } |
| 1216 } |
| 1217 |
| 1218 // TODO: add tests that verify can't manipulate trees of uknown nodes. |
| 1219 |
1095 } // namespace service | 1220 } // namespace service |
1096 } // namespace view_manager | 1221 } // namespace view_manager |
1097 } // namespace mojo | 1222 } // namespace mojo |
OLD | NEW |