1// Copyright (c) 2012 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 "ui/base/models/tree_node_model.h"
6
7#include "base/basictypes.h"
8#include "base/compiler_specific.h"
9#include "base/memory/scoped_ptr.h"
10#include "base/strings/string16.h"
11#include "base/strings/stringprintf.h"
12#include "base/strings/utf_string_conversions.h"
13#include "testing/gtest/include/gtest/gtest.h"
14
15using base::ASCIIToUTF16;
16
17namespace ui {
18
19class TreeNodeModelTest : public testing::Test, public TreeModelObserver {
20 public:
21  TreeNodeModelTest()
22      : added_count_(0),
23        removed_count_(0),
24        changed_count_(0) {}
25  virtual ~TreeNodeModelTest() {}
26
27 protected:
28  std::string GetObserverCountStateAndClear() {
29    std::string result(base::StringPrintf("added=%d removed=%d changed=%d",
30        added_count_, removed_count_, changed_count_));
31    added_count_ = removed_count_ = changed_count_ = 0;
32    return result;
33  }
34
35 private:
36  // Overridden from TreeModelObserver:
37  virtual void TreeNodesAdded(TreeModel* model,
38                              TreeModelNode* parent,
39                              int start,
40                              int count) OVERRIDE {
41    added_count_++;
42  }
43  virtual void TreeNodesRemoved(TreeModel* model,
44                                TreeModelNode* parent,
45                                int start,
46                                int count) OVERRIDE {
47    removed_count_++;
48  }
49  virtual void TreeNodeChanged(TreeModel* model, TreeModelNode* node) OVERRIDE {
50    changed_count_++;
51  }
52
53  int added_count_;
54  int removed_count_;
55  int changed_count_;
56
57  DISALLOW_COPY_AND_ASSIGN(TreeNodeModelTest);
58};
59
60typedef TreeNodeWithValue<int> TestNode;
61
62// Verifies if the model is properly adding a new node in the tree and
63// notifying the observers.
64// The tree looks like this:
65// root
66// +-- child1
67//     +-- foo1
68//     +-- foo2
69// +-- child2
70TEST_F(TreeNodeModelTest, AddNode) {
71  TestNode* root = new TestNode;
72  TreeNodeModel<TestNode > model(root);
73  model.AddObserver(this);
74
75  TestNode* child1 = new TestNode;
76  model.Add(root, child1, 0);
77
78  EXPECT_EQ("added=1 removed=0 changed=0", GetObserverCountStateAndClear());
79
80  for (int i = 0; i < 2; ++i)
81    child1->Add(new TestNode, i);
82
83  TestNode* child2 = new TestNode;
84  model.Add(root, child2, 1);
85
86  EXPECT_EQ("added=1 removed=0 changed=0", GetObserverCountStateAndClear());
87
88  EXPECT_EQ(2, root->child_count());
89  EXPECT_EQ(2, child1->child_count());
90  EXPECT_EQ(0, child2->child_count());
91}
92
93// Verifies if the model is properly removing a node from the tree
94// and notifying the observers.
95TEST_F(TreeNodeModelTest, RemoveNode) {
96  TestNode* root = new TestNode;
97  TreeNodeModel<TestNode > model(root);
98  model.AddObserver(this);
99
100  TestNode* child1 = new TestNode;
101  root->Add(child1, 0);
102
103  EXPECT_EQ(1, model.GetChildCount(root));
104
105  // Now remove |child1| from |root| and release the memory.
106  delete model.Remove(root, child1);
107
108  EXPECT_EQ("added=0 removed=1 changed=0", GetObserverCountStateAndClear());
109
110  EXPECT_EQ(0, model.GetChildCount(root));
111}
112
113// Verifies if the nodes added under the root are all deleted when calling
114// RemoveAll. Note that is responsability of the caller to free the memory
115// of the nodes removed after RemoveAll is called.
116// The tree looks like this:
117// root
118// +-- child1
119//     +-- foo
120//         +-- bar0
121//         +-- bar1
122//         +-- bar2
123// +-- child2
124// +-- child3
125TEST_F(TreeNodeModelTest, RemoveAllNodes) {
126  TestNode root;
127
128  TestNode child1;
129  TestNode child2;
130  TestNode child3;
131
132  root.Add(&child1, 0);
133  root.Add(&child2, 1);
134  root.Add(&child3, 2);
135
136  TestNode* foo = new TestNode;
137  child1.Add(foo, 0);
138
139  // Add some nodes to |foo|.
140  for (int i = 0; i < 3; ++i)
141    foo->Add(new TestNode, i);
142
143  EXPECT_EQ(3, root.child_count());
144  EXPECT_EQ(1, child1.child_count());
145  EXPECT_EQ(3, foo->child_count());
146
147  // Now remove the child nodes from root.
148  root.RemoveAll();
149
150  EXPECT_EQ(0, root.child_count());
151  EXPECT_TRUE(root.empty());
152
153  EXPECT_EQ(1, child1.child_count());
154  EXPECT_EQ(3, foo->child_count());
155}
156
157// Verifies if GetIndexOf() returns the correct index for the specified node.
158// The tree looks like this:
159// root
160// +-- child1
161//     +-- foo1
162// +-- child2
163TEST_F(TreeNodeModelTest, GetIndexOf) {
164  TestNode root;
165
166  TestNode* child1 = new TestNode;
167  root.Add(child1, 0);
168
169  TestNode* child2 = new TestNode;
170  root.Add(child2, 1);
171
172  TestNode* foo1 = new TestNode;
173  child1->Add(foo1, 0);
174
175  EXPECT_EQ(-1, root.GetIndexOf(&root));
176  EXPECT_EQ(0, root.GetIndexOf(child1));
177  EXPECT_EQ(1, root.GetIndexOf(child2));
178  EXPECT_EQ(-1, root.GetIndexOf(foo1));
179
180  EXPECT_EQ(-1, child1->GetIndexOf(&root));
181  EXPECT_EQ(-1, child1->GetIndexOf(child1));
182  EXPECT_EQ(-1, child1->GetIndexOf(child2));
183  EXPECT_EQ(0, child1->GetIndexOf(foo1));
184
185  EXPECT_EQ(-1, child2->GetIndexOf(&root));
186  EXPECT_EQ(-1, child2->GetIndexOf(child2));
187  EXPECT_EQ(-1, child2->GetIndexOf(child1));
188  EXPECT_EQ(-1, child2->GetIndexOf(foo1));
189}
190
191// Verifies whether a specified node has or not an ancestor.
192// The tree looks like this:
193// root
194// +-- child1
195//     +-- foo1
196// +-- child2
197TEST_F(TreeNodeModelTest, HasAncestor) {
198  TestNode root;
199  TestNode* child1 = new TestNode;
200  TestNode* child2 = new TestNode;
201
202  root.Add(child1, 0);
203  root.Add(child2, 1);
204
205  TestNode* foo1 = new TestNode;
206  child1->Add(foo1, 0);
207
208  EXPECT_TRUE(root.HasAncestor(&root));
209  EXPECT_FALSE(root.HasAncestor(child1));
210  EXPECT_FALSE(root.HasAncestor(child2));
211  EXPECT_FALSE(root.HasAncestor(foo1));
212
213  EXPECT_TRUE(child1->HasAncestor(child1));
214  EXPECT_TRUE(child1->HasAncestor(&root));
215  EXPECT_FALSE(child1->HasAncestor(child2));
216  EXPECT_FALSE(child1->HasAncestor(foo1));
217
218  EXPECT_TRUE(child2->HasAncestor(child2));
219  EXPECT_TRUE(child2->HasAncestor(&root));
220  EXPECT_FALSE(child2->HasAncestor(child1));
221  EXPECT_FALSE(child2->HasAncestor(foo1));
222
223  EXPECT_TRUE(foo1->HasAncestor(foo1));
224  EXPECT_TRUE(foo1->HasAncestor(child1));
225  EXPECT_TRUE(foo1->HasAncestor(&root));
226  EXPECT_FALSE(foo1->HasAncestor(child2));
227}
228
229// Verifies if GetTotalNodeCount returns the correct number of nodes from the
230// node specifed. The count should include the node itself.
231// The tree looks like this:
232// root
233// +-- child1
234//     +-- child2
235//         +-- child3
236// +-- foo1
237//     +-- foo2
238//         +-- foo3
239//     +-- foo4
240// +-- bar1
241//
242// The TotalNodeCount of root is:            9
243// The TotalNodeCount of child1 is:          3
244// The TotalNodeCount of child2 and foo2 is: 2
245// The TotalNodeCount of bar1 is:            1
246// And so on...
247TEST_F(TreeNodeModelTest, GetTotalNodeCount) {
248  TestNode root;
249
250  TestNode* child1 = new TestNode;
251  TestNode* child2 = new TestNode;
252  TestNode* child3 = new TestNode;
253
254  root.Add(child1, 0);
255  child1->Add(child2, 0);
256  child2->Add(child3, 0);
257
258  TestNode* foo1 = new TestNode;
259  TestNode* foo2 = new TestNode;
260  TestNode* foo3 = new TestNode;
261  TestNode* foo4 = new TestNode;
262
263  root.Add(foo1, 1);
264  foo1->Add(foo2, 0);
265  foo2->Add(foo3, 0);
266  foo1->Add(foo4, 1);
267
268  TestNode* bar1 = new TestNode;
269
270  root.Add(bar1, 2);
271
272  EXPECT_EQ(9, root.GetTotalNodeCount());
273  EXPECT_EQ(3, child1->GetTotalNodeCount());
274  EXPECT_EQ(2, child2->GetTotalNodeCount());
275  EXPECT_EQ(2, foo2->GetTotalNodeCount());
276  EXPECT_EQ(1, bar1->GetTotalNodeCount());
277}
278
279// Makes sure that we are notified when the node is renamed,
280// also makes sure the node is properly renamed.
281TEST_F(TreeNodeModelTest, SetTitle) {
282  TestNode* root = new TestNode(ASCIIToUTF16("root"), 0);
283  TreeNodeModel<TestNode > model(root);
284  model.AddObserver(this);
285
286  const base::string16 title(ASCIIToUTF16("root2"));
287  model.SetTitle(root, title);
288  EXPECT_EQ("added=0 removed=0 changed=1", GetObserverCountStateAndClear());
289  EXPECT_EQ(title, root->GetTitle());
290}
291
292TEST_F(TreeNodeModelTest, BasicOperations) {
293  TestNode root;
294  EXPECT_EQ(0, root.child_count());
295
296  TestNode* child1 = new TestNode;
297  root.Add(child1, root.child_count());
298  EXPECT_EQ(1, root.child_count());
299  EXPECT_EQ(&root, child1->parent());
300
301  TestNode* child2 = new TestNode;
302  root.Add(child2, root.child_count());
303  EXPECT_EQ(2, root.child_count());
304  EXPECT_EQ(child1->parent(), child2->parent());
305
306  scoped_ptr<TestNode > c2(root.Remove(child2));
307  EXPECT_EQ(1, root.child_count());
308  EXPECT_EQ(NULL, child2->parent());
309
310  scoped_ptr<TestNode > c1(root.Remove(child1));
311  EXPECT_EQ(0, root.child_count());
312}
313
314TEST_F(TreeNodeModelTest, IsRoot) {
315  TestNode root;
316  EXPECT_TRUE(root.is_root());
317
318  TestNode* child1 = new TestNode;
319  root.Add(child1, root.child_count());
320  EXPECT_FALSE(child1->is_root());
321}
322
323}  // namespace ui
324