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
3// found in the LICENSE file.
4
5#include "mojo/services/public/cpp/view_manager/node.h"
6
7#include "base/logging.h"
8#include "base/strings/stringprintf.h"
9#include "mojo/services/public/cpp/view_manager/lib/node_private.h"
10#include "mojo/services/public/cpp/view_manager/node_observer.h"
11#include "mojo/services/public/cpp/view_manager/util.h"
12#include "testing/gtest/include/gtest/gtest.h"
13
14namespace mojo {
15namespace view_manager {
16
17// Node ------------------------------------------------------------------------
18
19typedef testing::Test NodeTest;
20
21// Subclass with public ctor/dtor.
22class TestNode : public Node {
23 public:
24  TestNode() {
25    NodePrivate(this).set_id(1);
26  }
27  ~TestNode() {}
28
29 private:
30  DISALLOW_COPY_AND_ASSIGN(TestNode);
31};
32
33TEST_F(NodeTest, AddChild) {
34  TestNode v1;
35  TestNode v11;
36  v1.AddChild(&v11);
37  EXPECT_EQ(1U, v1.children().size());
38}
39
40TEST_F(NodeTest, RemoveChild) {
41  TestNode v1;
42  TestNode v11;
43  v1.AddChild(&v11);
44  EXPECT_EQ(1U, v1.children().size());
45  v1.RemoveChild(&v11);
46  EXPECT_EQ(0U, v1.children().size());
47}
48
49TEST_F(NodeTest, Reparent) {
50  TestNode v1;
51  TestNode v2;
52  TestNode v11;
53  v1.AddChild(&v11);
54  EXPECT_EQ(1U, v1.children().size());
55  v2.AddChild(&v11);
56  EXPECT_EQ(1U, v2.children().size());
57  EXPECT_EQ(0U, v1.children().size());
58}
59
60TEST_F(NodeTest, Contains) {
61  TestNode v1;
62
63  // Direct descendant.
64  TestNode v11;
65  v1.AddChild(&v11);
66  EXPECT_TRUE(v1.Contains(&v11));
67
68  // Indirect descendant.
69  TestNode v111;
70  v11.AddChild(&v111);
71  EXPECT_TRUE(v1.Contains(&v111));
72}
73
74TEST_F(NodeTest, GetChildById) {
75  TestNode v1;
76  NodePrivate(&v1).set_id(1);
77  TestNode v11;
78  NodePrivate(&v11).set_id(11);
79  v1.AddChild(&v11);
80  TestNode v111;
81  NodePrivate(&v111).set_id(111);
82  v11.AddChild(&v111);
83
84  // Find direct & indirect descendents.
85  EXPECT_EQ(&v11, v1.GetChildById(v11.id()));
86  EXPECT_EQ(&v111, v1.GetChildById(v111.id()));
87}
88
89// NodeObserver --------------------------------------------------------
90
91typedef testing::Test NodeObserverTest;
92
93bool TreeChangeParamsMatch(const NodeObserver::TreeChangeParams& lhs,
94                           const NodeObserver::TreeChangeParams& rhs) {
95  return lhs.target == rhs.target &&  lhs.old_parent == rhs.old_parent &&
96      lhs.new_parent == rhs.new_parent && lhs.receiver == rhs.receiver &&
97      lhs.phase == rhs.phase;
98}
99
100class TreeChangeObserver : public NodeObserver {
101 public:
102  explicit TreeChangeObserver(Node* observee) : observee_(observee) {
103    observee_->AddObserver(this);
104  }
105  virtual ~TreeChangeObserver() {
106    observee_->RemoveObserver(this);
107  }
108
109  void Reset() {
110    received_params_.clear();
111  }
112
113  const std::vector<TreeChangeParams>& received_params() {
114    return received_params_;
115  }
116
117 private:
118  // Overridden from NodeObserver:
119  virtual void OnTreeChange(const TreeChangeParams& params) OVERRIDE {
120    received_params_.push_back(params);
121  }
122
123  Node* observee_;
124  std::vector<TreeChangeParams> received_params_;
125
126  DISALLOW_COPY_AND_ASSIGN(TreeChangeObserver);
127};
128
129// Adds/Removes v11 to v1.
130TEST_F(NodeObserverTest, TreeChange_SimpleAddRemove) {
131  TestNode v1;
132  TreeChangeObserver o1(&v1);
133  EXPECT_TRUE(o1.received_params().empty());
134
135  TestNode v11;
136  TreeChangeObserver o11(&v11);
137  EXPECT_TRUE(o11.received_params().empty());
138
139  // Add.
140
141  v1.AddChild(&v11);
142
143  EXPECT_EQ(2U, o1.received_params().size());
144  NodeObserver::TreeChangeParams p1;
145  p1.target = &v11;
146  p1.receiver = &v1;
147  p1.old_parent = NULL;
148  p1.new_parent = &v1;
149  p1.phase = NodeObserver::DISPOSITION_CHANGED;
150  EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back()));
151
152  EXPECT_EQ(2U, o11.received_params().size());
153  NodeObserver::TreeChangeParams p11 = p1;
154  p11.receiver = &v11;
155  p11.phase = NodeObserver::DISPOSITION_CHANGING;
156  EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front()));
157  p11.phase = NodeObserver::DISPOSITION_CHANGED;
158  EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back()));
159
160  o1.Reset();
161  o11.Reset();
162  EXPECT_TRUE(o1.received_params().empty());
163  EXPECT_TRUE(o11.received_params().empty());
164
165  // Remove.
166
167  v1.RemoveChild(&v11);
168
169  EXPECT_EQ(2U, o1.received_params().size());
170  p1.target = &v11;
171  p1.receiver = &v1;
172  p1.old_parent = &v1;
173  p1.new_parent = NULL;
174  p1.phase = NodeObserver::DISPOSITION_CHANGING;
175  EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().front()));
176
177  EXPECT_EQ(2U, o11.received_params().size());
178  p11 = p1;
179  p11.receiver = &v11;
180  EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front()));
181  p11.phase = NodeObserver::DISPOSITION_CHANGED;
182  EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back()));
183}
184
185// Creates these two trees:
186// v1
187//  +- v11
188// v111
189//  +- v1111
190//  +- v1112
191// Then adds/removes v111 from v11.
192TEST_F(NodeObserverTest, TreeChange_NestedAddRemove) {
193  TestNode v1, v11, v111, v1111, v1112;
194
195  // Root tree.
196  v1.AddChild(&v11);
197
198  // Tree to be attached.
199  v111.AddChild(&v1111);
200  v111.AddChild(&v1112);
201
202  TreeChangeObserver o1(&v1), o11(&v11), o111(&v111), o1111(&v1111),
203      o1112(&v1112);
204  NodeObserver::TreeChangeParams p1, p11, p111, p1111, p1112;
205
206  // Add.
207
208  v11.AddChild(&v111);
209
210  EXPECT_EQ(2U, o1.received_params().size());
211  p1.target = &v111;
212  p1.receiver = &v1;
213  p1.old_parent = NULL;
214  p1.new_parent = &v11;
215  p1.phase = NodeObserver::DISPOSITION_CHANGED;
216  EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back()));
217
218  EXPECT_EQ(2U, o11.received_params().size());
219  p11 = p1;
220  p11.receiver = &v11;
221  EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back()));
222
223  EXPECT_EQ(2U, o111.received_params().size());
224  p111 = p11;
225  p111.receiver = &v111;
226  p111.phase = NodeObserver::DISPOSITION_CHANGING;
227  EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front()));
228  p111.phase = NodeObserver::DISPOSITION_CHANGED;
229  EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back()));
230
231  EXPECT_EQ(2U, o1111.received_params().size());
232  p1111 = p111;
233  p1111.receiver = &v1111;
234  p1111.phase = NodeObserver::DISPOSITION_CHANGING;
235  EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().front()));
236  p1111.phase = NodeObserver::DISPOSITION_CHANGED;
237  EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().back()));
238
239  EXPECT_EQ(2U, o1112.received_params().size());
240  p1112 = p111;
241  p1112.receiver = &v1112;
242  p1112.phase = NodeObserver::DISPOSITION_CHANGING;
243  EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().front()));
244  p1112.phase = NodeObserver::DISPOSITION_CHANGED;
245  EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().back()));
246
247  // Remove.
248  o1.Reset();
249  o11.Reset();
250  o111.Reset();
251  o1111.Reset();
252  o1112.Reset();
253  EXPECT_TRUE(o1.received_params().empty());
254  EXPECT_TRUE(o11.received_params().empty());
255  EXPECT_TRUE(o111.received_params().empty());
256  EXPECT_TRUE(o1111.received_params().empty());
257  EXPECT_TRUE(o1112.received_params().empty());
258
259  v11.RemoveChild(&v111);
260
261  EXPECT_EQ(2U, o1.received_params().size());
262  p1.target = &v111;
263  p1.receiver = &v1;
264  p1.old_parent = &v11;
265  p1.new_parent = NULL;
266  p1.phase = NodeObserver::DISPOSITION_CHANGING;
267  EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().front()));
268
269  EXPECT_EQ(2U, o11.received_params().size());
270  p11 = p1;
271  p11.receiver = &v11;
272  EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front()));
273
274  EXPECT_EQ(2U, o111.received_params().size());
275  p111 = p11;
276  p111.receiver = &v111;
277  p111.phase = NodeObserver::DISPOSITION_CHANGING;
278  EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front()));
279  p111.phase = NodeObserver::DISPOSITION_CHANGED;
280  EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back()));
281
282  EXPECT_EQ(2U, o1111.received_params().size());
283  p1111 = p111;
284  p1111.receiver = &v1111;
285  p1111.phase = NodeObserver::DISPOSITION_CHANGING;
286  EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().front()));
287  p1111.phase = NodeObserver::DISPOSITION_CHANGED;
288  EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().back()));
289
290  EXPECT_EQ(2U, o1112.received_params().size());
291  p1112 = p111;
292  p1112.receiver = &v1112;
293  p1112.phase = NodeObserver::DISPOSITION_CHANGING;
294  EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().front()));
295  p1112.phase = NodeObserver::DISPOSITION_CHANGED;
296  EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().back()));
297}
298
299TEST_F(NodeObserverTest, TreeChange_Reparent) {
300  TestNode v1, v11, v12, v111;
301  v1.AddChild(&v11);
302  v1.AddChild(&v12);
303  v11.AddChild(&v111);
304
305  TreeChangeObserver o1(&v1), o11(&v11), o12(&v12), o111(&v111);
306
307  // Reparent.
308  v12.AddChild(&v111);
309
310  // v1 (root) should see both changing and changed notifications.
311  EXPECT_EQ(4U, o1.received_params().size());
312  NodeObserver::TreeChangeParams p1;
313  p1.target = &v111;
314  p1.receiver = &v1;
315  p1.old_parent = &v11;
316  p1.new_parent = &v12;
317  p1.phase = NodeObserver::DISPOSITION_CHANGING;
318  EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().front()));
319  p1.phase = NodeObserver::DISPOSITION_CHANGED;
320  EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back()));
321
322  // v11 should see changing notifications.
323  EXPECT_EQ(2U, o11.received_params().size());
324  NodeObserver::TreeChangeParams p11;
325  p11 = p1;
326  p11.receiver = &v11;
327  p11.phase = NodeObserver::DISPOSITION_CHANGING;
328  EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front()));
329
330  // v12 should see changed notifications.
331  EXPECT_EQ(2U, o12.received_params().size());
332  NodeObserver::TreeChangeParams p12;
333  p12 = p1;
334  p12.receiver = &v12;
335  p12.phase = NodeObserver::DISPOSITION_CHANGED;
336  EXPECT_TRUE(TreeChangeParamsMatch(p12, o12.received_params().back()));
337
338  // v111 should see both changing and changed notifications.
339  EXPECT_EQ(2U, o111.received_params().size());
340  NodeObserver::TreeChangeParams p111;
341  p111 = p1;
342  p111.receiver = &v111;
343  p111.phase = NodeObserver::DISPOSITION_CHANGING;
344  EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front()));
345  p111.phase = NodeObserver::DISPOSITION_CHANGED;
346  EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back()));
347}
348
349namespace {
350
351class OrderChangeObserver : public NodeObserver {
352 public:
353  struct Change {
354    Node* node;
355    Node* relative_node;
356    OrderDirection direction;
357    DispositionChangePhase phase;
358  };
359  typedef std::vector<Change> Changes;
360
361  explicit OrderChangeObserver(Node* observee) : observee_(observee) {
362    observee_->AddObserver(this);
363  }
364  virtual ~OrderChangeObserver() {
365    observee_->RemoveObserver(this);
366  }
367
368  Changes GetAndClearChanges() {
369    Changes changes;
370    changes_.swap(changes);
371    return changes;
372  }
373
374 private:
375  // Overridden from NodeObserver:
376  virtual void OnNodeReordered(Node* node,
377                               Node* relative_node,
378                               OrderDirection direction,
379                               DispositionChangePhase phase) OVERRIDE {
380    Change change;
381    change.node = node;
382    change.relative_node = relative_node;
383    change.direction = direction;
384    change.phase = phase;
385    changes_.push_back(change);
386  }
387
388  Node* observee_;
389  Changes changes_;
390
391  DISALLOW_COPY_AND_ASSIGN(OrderChangeObserver);
392};
393
394}  // namespace
395
396TEST_F(NodeObserverTest, Order) {
397  TestNode v1, v11, v12, v13;
398  v1.AddChild(&v11);
399  v1.AddChild(&v12);
400  v1.AddChild(&v13);
401
402  // Order: v11, v12, v13
403  EXPECT_EQ(3U, v1.children().size());
404  EXPECT_EQ(&v11, v1.children().front());
405  EXPECT_EQ(&v13, v1.children().back());
406
407  {
408    OrderChangeObserver observer(&v11);
409
410    // Move v11 to front.
411    // Resulting order: v12, v13, v11
412    v11.MoveToFront();
413    EXPECT_EQ(&v12, v1.children().front());
414    EXPECT_EQ(&v11, v1.children().back());
415
416    OrderChangeObserver::Changes changes = observer.GetAndClearChanges();
417    EXPECT_EQ(2U, changes.size());
418    EXPECT_EQ(&v11, changes[0].node);
419    EXPECT_EQ(&v13, changes[0].relative_node);
420    EXPECT_EQ(ORDER_ABOVE, changes[0].direction);
421    EXPECT_EQ(NodeObserver::DISPOSITION_CHANGING, changes[0].phase);
422
423    EXPECT_EQ(&v11, changes[1].node);
424    EXPECT_EQ(&v13, changes[1].relative_node);
425    EXPECT_EQ(ORDER_ABOVE, changes[1].direction);
426    EXPECT_EQ(NodeObserver::DISPOSITION_CHANGED, changes[1].phase);
427  }
428
429  {
430    OrderChangeObserver observer(&v11);
431
432    // Move v11 to back.
433    // Resulting order: v11, v12, v13
434    v11.MoveToBack();
435    EXPECT_EQ(&v11, v1.children().front());
436    EXPECT_EQ(&v13, v1.children().back());
437
438    OrderChangeObserver::Changes changes = observer.GetAndClearChanges();
439    EXPECT_EQ(2U, changes.size());
440    EXPECT_EQ(&v11, changes[0].node);
441    EXPECT_EQ(&v12, changes[0].relative_node);
442    EXPECT_EQ(ORDER_BELOW, changes[0].direction);
443    EXPECT_EQ(NodeObserver::DISPOSITION_CHANGING, changes[0].phase);
444
445    EXPECT_EQ(&v11, changes[1].node);
446    EXPECT_EQ(&v12, changes[1].relative_node);
447    EXPECT_EQ(ORDER_BELOW, changes[1].direction);
448    EXPECT_EQ(NodeObserver::DISPOSITION_CHANGED, changes[1].phase);
449  }
450
451  {
452    OrderChangeObserver observer(&v11);
453
454    // Move v11 above v12.
455    // Resulting order: v12. v11, v13
456    v11.Reorder(&v12, ORDER_ABOVE);
457    EXPECT_EQ(&v12, v1.children().front());
458    EXPECT_EQ(&v13, v1.children().back());
459
460    OrderChangeObserver::Changes changes = observer.GetAndClearChanges();
461    EXPECT_EQ(2U, changes.size());
462    EXPECT_EQ(&v11, changes[0].node);
463    EXPECT_EQ(&v12, changes[0].relative_node);
464    EXPECT_EQ(ORDER_ABOVE, changes[0].direction);
465    EXPECT_EQ(NodeObserver::DISPOSITION_CHANGING, changes[0].phase);
466
467    EXPECT_EQ(&v11, changes[1].node);
468    EXPECT_EQ(&v12, changes[1].relative_node);
469    EXPECT_EQ(ORDER_ABOVE, changes[1].direction);
470    EXPECT_EQ(NodeObserver::DISPOSITION_CHANGED, changes[1].phase);
471  }
472
473  {
474    OrderChangeObserver observer(&v11);
475
476    // Move v11 below v12.
477    // Resulting order: v11, v12, v13
478    v11.Reorder(&v12, ORDER_BELOW);
479    EXPECT_EQ(&v11, v1.children().front());
480    EXPECT_EQ(&v13, v1.children().back());
481
482    OrderChangeObserver::Changes changes = observer.GetAndClearChanges();
483    EXPECT_EQ(2U, changes.size());
484    EXPECT_EQ(&v11, changes[0].node);
485    EXPECT_EQ(&v12, changes[0].relative_node);
486    EXPECT_EQ(ORDER_BELOW, changes[0].direction);
487    EXPECT_EQ(NodeObserver::DISPOSITION_CHANGING, changes[0].phase);
488
489    EXPECT_EQ(&v11, changes[1].node);
490    EXPECT_EQ(&v12, changes[1].relative_node);
491    EXPECT_EQ(ORDER_BELOW, changes[1].direction);
492    EXPECT_EQ(NodeObserver::DISPOSITION_CHANGED, changes[1].phase);
493  }
494}
495
496namespace {
497
498typedef std::vector<std::string> Changes;
499
500std::string NodeIdToString(Id id) {
501  return (id == 0) ? "null" :
502      base::StringPrintf("%d,%d", HiWord(id), LoWord(id));
503}
504
505std::string RectToString(const gfx::Rect& rect) {
506  return base::StringPrintf("%d,%d %dx%d",
507                            rect.x(), rect.y(), rect.width(), rect.height());
508}
509
510std::string PhaseToString(NodeObserver::DispositionChangePhase phase) {
511  return phase == NodeObserver::DISPOSITION_CHANGING ?
512      "changing" : "changed";
513}
514
515class BoundsChangeObserver : public NodeObserver {
516 public:
517  explicit BoundsChangeObserver(Node* node) : node_(node) {
518    node_->AddObserver(this);
519  }
520  virtual ~BoundsChangeObserver() {
521    node_->RemoveObserver(this);
522  }
523
524  Changes GetAndClearChanges() {
525    Changes changes;
526    changes.swap(changes_);
527    return changes;
528  }
529
530 private:
531  // Overridden from NodeObserver:
532  virtual void OnNodeBoundsChange(Node* node,
533                                  const gfx::Rect& old_bounds,
534                                  const gfx::Rect& new_bounds,
535                                  DispositionChangePhase phase) OVERRIDE {
536    changes_.push_back(
537        base::StringPrintf(
538            "node=%s old_bounds=%s new_bounds=%s phase=%s",
539            NodeIdToString(node->id()).c_str(),
540            RectToString(old_bounds).c_str(),
541            RectToString(new_bounds).c_str(),
542            PhaseToString(phase).c_str()));
543  }
544
545  Node* node_;
546  Changes changes_;
547
548  DISALLOW_COPY_AND_ASSIGN(BoundsChangeObserver);
549};
550
551}  // namespace
552
553TEST_F(NodeObserverTest, SetBounds) {
554  TestNode v1;
555  {
556    BoundsChangeObserver observer(&v1);
557    v1.SetBounds(gfx::Rect(0, 0, 100, 100));
558
559    Changes changes = observer.GetAndClearChanges();
560    EXPECT_EQ(2U, changes.size());
561    EXPECT_EQ(
562        "node=0,1 old_bounds=0,0 0x0 new_bounds=0,0 100x100 phase=changing",
563        changes[0]);
564    EXPECT_EQ(
565        "node=0,1 old_bounds=0,0 0x0 new_bounds=0,0 100x100 phase=changed",
566        changes[1]);
567  }
568}
569
570}  // namespace view_manager
571}  // namespace mojo
572