Home | History | Annotate | Download | only in tests
      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 
     14 namespace mojo {
     15 namespace view_manager {
     16 
     17 // Node ------------------------------------------------------------------------
     18 
     19 typedef testing::Test NodeTest;
     20 
     21 // Subclass with public ctor/dtor.
     22 class 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 
     33 TEST_F(NodeTest, AddChild) {
     34   TestNode v1;
     35   TestNode v11;
     36   v1.AddChild(&v11);
     37   EXPECT_EQ(1U, v1.children().size());
     38 }
     39 
     40 TEST_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 
     49 TEST_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 
     60 TEST_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 
     74 TEST_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 
     91 typedef testing::Test NodeObserverTest;
     92 
     93 bool 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 
    100 class 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.
    130 TEST_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.
    192 TEST_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 
    299 TEST_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 
    349 namespace {
    350 
    351 class 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 
    396 TEST_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 
    496 namespace {
    497 
    498 typedef std::vector<std::string> Changes;
    499 
    500 std::string NodeIdToString(Id id) {
    501   return (id == 0) ? "null" :
    502       base::StringPrintf("%d,%d", HiWord(id), LoWord(id));
    503 }
    504 
    505 std::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 
    510 std::string PhaseToString(NodeObserver::DispositionChangePhase phase) {
    511   return phase == NodeObserver::DISPOSITION_CHANGING ?
    512       "changing" : "changed";
    513 }
    514 
    515 class 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 
    553 TEST_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