Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / bookmarks / bookmark_tag_model_unittest.cc
1 // Copyright 2013 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 "chrome/browser/bookmarks/bookmark_tag_model.h"
6
7 #include "base/strings/utf_string_conversions.h"
8 #include "chrome/browser/bookmarks/bookmark_tag_model_observer.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10
11 using base::ASCIIToUTF16;
12
13 namespace {
14
15 static struct {
16   const std::string input_tag;
17   const std::string expected_tag;
18 } whitespace_test_cases[] = {
19   // Newlines.
20   {"foo\nbar", "foo bar"},
21   {"foo\n\nbar", "foo bar"},
22   {"foo\n\n\nbar", "foo bar"},
23   {"foo\r\nbar", "foo bar"},
24   {"foo\r\n\r\nbar", "foo bar"},
25   {"\nfoo\nbar\n", "foo bar"},
26   // Spaces.
27   {"foo  bar", "foo bar"},
28   {" foo bar ", "foo bar"},
29   {"  foo  bar  ", "foo bar"},
30   // Tabs.
31   {"\tfoo\tbar\t", "foo bar"},
32   {"\tfoo bar\t", "foo bar"},
33   // Mixed cases.
34   {"\tfoo\nbar\t", "foo bar"},
35   {"\tfoo\r\nbar\t", "foo bar"},
36   {"  foo\tbar\n", "foo bar"},
37   {"\t foo \t  bar  \t", "foo bar"},
38   {"\n foo\r\n\tbar\n \t", "foo bar"},
39 };
40
41 enum ObserverCounts {
42   OBSERVER_COUNTS_ADD = 0,
43   OBSERVER_COUNTS_BEFORE_REMOVE,
44   OBSERVER_COUNTS_REMOVE,
45   OBSERVER_COUNTS_BEFORE_CHANGE,
46   OBSERVER_COUNTS_CHANGE,
47   OBSERVER_COUNTS_BEFORE_TAG_CHANGE,
48   OBSERVER_COUNTS_TAG_CHANGE,
49   OBSERVER_COUNTS_FAVICON_CHANGE,
50   OBSERVER_COUNTS_EXTENSIVE_CHANGE_BEGIN,
51   OBSERVER_COUNTS_EXTENSIVE_CHANGE_END,
52   OBSERVER_COUNTS_BEFORE_REMOVE_ALL,
53   OBSERVER_COUNTS_REMOVE_ALL,
54   OBSERVER_COUNTS_TOTAL_NUMBER_OF_COUNTS
55 };
56
57 const std::string count_name[] = {
58   "OBSERVER_COUNTS_ADD",
59   "OBSERVER_COUNTS_BEFORE_REMOVE",
60   "OBSERVER_COUNTS_REMOVE",
61   "OBSERVER_COUNTS_BEFORE_CHANGE",
62   "OBSERVER_COUNTS_CHANGE",
63   "OBSERVER_COUNTS_BEFORE_TAG_CHANGE",
64   "OBSERVER_COUNTS_TAG_CHANGE",
65   "OBSERVER_COUNTS_FAVICON_CHANGE",
66   "OBSERVER_COUNTS_EXTENSIVE_CHANGE_BEGIN",
67   "OBSERVER_COUNTS_EXTENSIVE_CHANGE_END",
68   "OBSERVER_COUNTS_BEFORE_REMOVE_ALL",
69   "OBSERVER_COUNTS_REMOVE_ALL"
70 };
71
72
73 class BookmarkTagModelTest
74     : public testing::Test, public BookmarkTagModelObserver {
75  public:
76   struct ObserverDetails {
77     ObserverDetails() : bookmark_(NULL) {}
78
79     void Set(const BookmarkNode* bookmark,
80              const std::set<BookmarkTag>& tags) {
81       bookmark_ = bookmark;
82       tags_ = tags;
83     }
84
85     void ExpectEquals(const BookmarkNode* bookmark,
86              const std::set<BookmarkTag>& tags) {
87       EXPECT_EQ(bookmark_, bookmark);
88       EXPECT_EQ(tags_, tags);
89     }
90
91    private:
92     const BookmarkNode* bookmark_;
93     std::set<BookmarkTag> tags_;
94   };
95
96   BookmarkTagModelTest() : model_(NULL),
97                            tag_model_(new BookmarkTagModel(&model_)) {
98     tag_model_->AddObserver(this);
99     ClearCounts();
100   }
101
102   virtual ~BookmarkTagModelTest() {
103   }
104
105   // BookmarkTagModelObserver:
106   virtual void BookmarkTagModelLoaded(BookmarkTagModel* model) OVERRIDE {
107     // We never load from the db, so that this should never get invoked.
108     NOTREACHED();
109   }
110
111   // Invoked when a node has been added.
112   virtual void BookmarkNodeAdded(BookmarkTagModel* model,
113                                  const BookmarkNode* bookmark) OVERRIDE {
114     ++counts_[OBSERVER_COUNTS_ADD];
115     observer_details_.Set(bookmark, model->GetTagsForBookmark(bookmark));
116   }
117
118   // Invoked before a node is removed.
119   // |node| is the node to be removed.
120   virtual void OnWillRemoveBookmarks(BookmarkTagModel* model,
121                                      const BookmarkNode* bookmark) OVERRIDE {
122     ++counts_[OBSERVER_COUNTS_BEFORE_REMOVE];
123   }
124
125   // Invoked when a node has been removed, the item may still be starred though.
126   // |node| is the node that was removed.
127   virtual void BookmarkNodeRemoved(BookmarkTagModel* model,
128                                    const BookmarkNode* bookmark) OVERRIDE {
129     ++counts_[OBSERVER_COUNTS_REMOVE];
130   }
131
132   // Invoked before the title or url of a node is changed.
133   virtual void OnWillChangeBookmarkNode(BookmarkTagModel* model,
134                                         const BookmarkNode* bookmark) OVERRIDE {
135     ++counts_[OBSERVER_COUNTS_BEFORE_CHANGE];
136   }
137
138   // Invoked when the title or url of a node changes.
139   virtual void BookmarkNodeChanged(BookmarkTagModel* model,
140                                    const BookmarkNode* bookmark) OVERRIDE {
141     ++counts_[OBSERVER_COUNTS_CHANGE];
142     observer_details_.Set(bookmark, model->GetTagsForBookmark(bookmark));
143   }
144
145   virtual void OnWillChangeBookmarkTags(BookmarkTagModel* model,
146                                         const BookmarkNode* bookmark) OVERRIDE {
147     ++counts_[OBSERVER_COUNTS_BEFORE_TAG_CHANGE];
148   }
149
150   virtual void BookmarkTagsChanged(BookmarkTagModel* model,
151                                    const BookmarkNode* bookmark) OVERRIDE {
152     ++counts_[OBSERVER_COUNTS_TAG_CHANGE];
153     observer_details_.Set(bookmark, model->GetTagsForBookmark(bookmark));
154   }
155
156   virtual void BookmarkNodeFaviconChanged(BookmarkTagModel* model,
157                                           const BookmarkNode* node) OVERRIDE {
158     ++counts_[OBSERVER_COUNTS_FAVICON_CHANGE];
159   }
160
161   virtual void ExtensiveBookmarkChangesBeginning(BookmarkTagModel* model)
162       OVERRIDE {
163     ++counts_[OBSERVER_COUNTS_EXTENSIVE_CHANGE_BEGIN];
164   }
165
166   virtual void ExtensiveBookmarkChangesEnded(BookmarkTagModel* model) OVERRIDE {
167     ++counts_[OBSERVER_COUNTS_EXTENSIVE_CHANGE_END];
168   }
169
170   virtual void OnWillRemoveAllBookmarks(BookmarkTagModel* model) OVERRIDE {
171     ++counts_[OBSERVER_COUNTS_BEFORE_REMOVE_ALL];
172   }
173
174   virtual void BookmarkAllNodesRemoved(BookmarkTagModel* model) OVERRIDE {
175     ++counts_[OBSERVER_COUNTS_REMOVE_ALL];
176   }
177
178   void ClearCounts() {
179     for (unsigned int i = 0; i < OBSERVER_COUNTS_TOTAL_NUMBER_OF_COUNTS; ++i)
180       counts_[i] = 0;
181   }
182
183   void AssertAndClearObserverCount(ObserverCounts count, int expected) {
184     ASSERT_EQ(expected, counts_[count]) << count_name[count];
185     counts_[count] = 0;
186   }
187
188   void AssertAllCountsClear() {
189     for (unsigned int i = 0; i < OBSERVER_COUNTS_TOTAL_NUMBER_OF_COUNTS; ++i)
190       ASSERT_EQ(0, counts_[i]) << count_name[i];
191   }
192
193   const BookmarkNode* AddURLWithTags(
194       const std::string& name,
195       const std::set<BookmarkTag>& tags) {
196     const base::string16 title(ASCIIToUTF16(name));
197     const GURL url("http://" + name + ".com");
198
199     return tag_model_->AddURL(title, url, tags);
200   }
201
202  protected:
203   BookmarkModel model_;
204   scoped_ptr<BookmarkTagModel> tag_model_;
205   ObserverDetails observer_details_;
206
207  private:
208   int counts_[OBSERVER_COUNTS_TOTAL_NUMBER_OF_COUNTS];
209
210   DISALLOW_COPY_AND_ASSIGN(BookmarkTagModelTest);
211 };
212
213 TEST_F(BookmarkTagModelTest, InitialState) {
214   std::vector<BookmarkTag> tags(tag_model_->TagsRelatedToTag(base::string16()));
215   EXPECT_EQ(0UL, tags.size());
216 }
217
218 TEST_F(BookmarkTagModelTest, AddURL) {
219   std::set<BookmarkTag> tags;
220   tags.insert(ASCIIToUTF16("bar"));
221   tags.insert(ASCIIToUTF16("baz"));
222
223   AddURLWithTags("orly", tags);
224   const BookmarkNode* new_node = AddURLWithTags("foo", tags);
225   AssertAndClearObserverCount(OBSERVER_COUNTS_ADD, 2);
226   AssertAllCountsClear();
227
228   observer_details_.ExpectEquals(new_node, tags);
229
230   EXPECT_EQ(2UL, tag_model_->BookmarksForTag(ASCIIToUTF16("bar")).size());
231   EXPECT_EQ(2UL, tag_model_->BookmarksForTag(ASCIIToUTF16("baz")).size());
232   EXPECT_EQ(tags, tag_model_->GetTagsForBookmark(new_node));
233
234   std::vector<BookmarkTag> alltags(
235       tag_model_->TagsRelatedToTag(base::string16()));
236   EXPECT_EQ(2UL, alltags.size());
237 }
238
239 TEST_F(BookmarkTagModelTest, RelatedTo) {
240   std::set<BookmarkTag> tags;
241   tags.insert(ASCIIToUTF16("bar"));
242   tags.insert(ASCIIToUTF16("baz"));
243
244   AddURLWithTags("orly", tags);
245   AddURLWithTags("foo", tags);
246   AssertAndClearObserverCount(OBSERVER_COUNTS_ADD, 2);
247   AssertAllCountsClear();
248
249   std::vector<BookmarkTag> bartags(tag_model_->TagsRelatedToTag(
250       ASCIIToUTF16("bar")));
251   EXPECT_EQ(1UL, bartags.size());
252   std::vector<BookmarkTag> baztags(tag_model_->TagsRelatedToTag(
253       ASCIIToUTF16("baz")));
254   EXPECT_EQ(1UL, baztags.size());
255 }
256
257 TEST_F(BookmarkTagModelTest, AddURLWithWhitespaceTitle) {
258   std::set<BookmarkTag> tags;
259
260   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(whitespace_test_cases); ++i) {
261     const BookmarkNode* new_node = AddURLWithTags(
262         whitespace_test_cases[i].input_tag, tags);
263
264     EXPECT_EQ(ASCIIToUTF16(whitespace_test_cases[i].expected_tag),
265               new_node->GetTitle());
266     EXPECT_EQ(BookmarkNode::URL, new_node->type());
267   }
268 }
269
270 TEST_F(BookmarkTagModelTest, CheckTagsWithWhitespace) {
271   std::set<BookmarkTag> tags;
272
273   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(whitespace_test_cases); ++i)
274     tags.insert(ASCIIToUTF16(whitespace_test_cases[i].input_tag));
275
276   AddURLWithTags("foo", tags);
277
278   std::vector<BookmarkTag> alltags(tag_model_->TagsRelatedToTag(
279       base::string16()));
280
281   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(whitespace_test_cases); ++i) {
282     EXPECT_EQ(0UL, tag_model_->BookmarksForTag(
283         ASCIIToUTF16(whitespace_test_cases[i].input_tag)).size());
284     EXPECT_EQ(1UL, tag_model_->BookmarksForTag(
285         ASCIIToUTF16(whitespace_test_cases[i].expected_tag)).size());
286   }
287 }
288
289 TEST_F(BookmarkTagModelTest, RemoveURL) {
290   std::set<BookmarkTag> tags;
291   tags.insert(ASCIIToUTF16("bar"));
292   tags.insert(ASCIIToUTF16("baz"));
293
294   const BookmarkNode* new_node = AddURLWithTags("foo", tags);
295   const BookmarkNode* new_node2 = AddURLWithTags("flou", tags);
296   ClearCounts();
297
298   tag_model_->Remove(new_node);
299   tag_model_->Remove(new_node2);
300   AssertAndClearObserverCount(OBSERVER_COUNTS_BEFORE_REMOVE, 2);
301   AssertAndClearObserverCount(OBSERVER_COUNTS_REMOVE, 2);
302   AssertAllCountsClear();
303
304   std::vector<BookmarkTag> alltags(tag_model_->TagsRelatedToTag(
305       base::string16()));
306   EXPECT_EQ(0UL, alltags.size());
307 }
308
309 TEST_F(BookmarkTagModelTest, AddTagToBookmarks) {
310   std::set<BookmarkTag> tags;
311   tags.insert(ASCIIToUTF16("bar"));
312   tags.insert(ASCIIToUTF16("baz"));
313
314   std::set<const BookmarkNode*> bookmarks;
315   bookmarks.insert(AddURLWithTags("foo", tags));
316   bookmarks.insert(AddURLWithTags("flou", tags));
317   ClearCounts();
318
319   std::set<BookmarkTag> new_tags;
320   new_tags.insert(ASCIIToUTF16("new_bar"));
321   new_tags.insert(ASCIIToUTF16("new_baz"));
322
323   tag_model_->AddTagsToBookmarks(new_tags, bookmarks);
324   AssertAndClearObserverCount(OBSERVER_COUNTS_BEFORE_TAG_CHANGE, 2);
325   AssertAndClearObserverCount(OBSERVER_COUNTS_TAG_CHANGE, 2);
326   AssertAllCountsClear();
327
328   std::vector<BookmarkTag> alltags(tag_model_->TagsRelatedToTag(
329       base::string16()));
330   EXPECT_EQ(4UL, alltags.size());
331 }
332
333 TEST_F(BookmarkTagModelTest, AddTagToBookmark) {
334   std::set<BookmarkTag> tags;
335   tags.insert(ASCIIToUTF16("bar"));
336   tags.insert(ASCIIToUTF16("baz"));
337
338   const BookmarkNode* bookmark = AddURLWithTags("foo", tags);
339   ClearCounts();
340
341   std::set<BookmarkTag> new_tags;
342   new_tags.insert(ASCIIToUTF16("new_bar"));
343   new_tags.insert(ASCIIToUTF16("new_baz"));
344
345   tag_model_->AddTagsToBookmark(new_tags, bookmark);
346   AssertAndClearObserverCount(OBSERVER_COUNTS_BEFORE_TAG_CHANGE, 1);
347   AssertAndClearObserverCount(OBSERVER_COUNTS_TAG_CHANGE, 1);
348   AssertAllCountsClear();
349
350   std::vector<BookmarkTag> alltags(tag_model_->TagsRelatedToTag(
351       base::string16()));
352   EXPECT_EQ(4UL, alltags.size());
353 }
354
355 TEST_F(BookmarkTagModelTest, RemoveTagFromBookmarks) {
356   std::set<BookmarkTag> tags;
357   tags.insert(ASCIIToUTF16("bar"));
358   tags.insert(ASCIIToUTF16("baz"));
359
360   std::set<const BookmarkNode*> bookmarks;
361
362   bookmarks.insert(AddURLWithTags("foo", tags));
363   bookmarks.insert(AddURLWithTags("flou", tags));
364   ClearCounts();
365
366   tag_model_->RemoveTagsFromBookmarks(tags, bookmarks);
367   AssertAndClearObserverCount(OBSERVER_COUNTS_BEFORE_TAG_CHANGE, 2);
368   AssertAndClearObserverCount(OBSERVER_COUNTS_TAG_CHANGE, 2);
369   AssertAllCountsClear();
370
371   std::vector<BookmarkTag> alltags(tag_model_->TagsRelatedToTag(
372       base::string16()));
373   EXPECT_EQ(0UL, alltags.size());
374 }
375
376 TEST_F(BookmarkTagModelTest, RemoveTagFromBookmark) {
377   std::set<BookmarkTag> tags;
378   tags.insert(ASCIIToUTF16("bar"));
379   tags.insert(ASCIIToUTF16("baz"));
380
381   const BookmarkNode* bookmark = AddURLWithTags("foo", tags);
382   ClearCounts();
383
384   tag_model_->RemoveTagsFromBookmark(tags, bookmark);
385   AssertAndClearObserverCount(OBSERVER_COUNTS_BEFORE_TAG_CHANGE, 1);
386   AssertAndClearObserverCount(OBSERVER_COUNTS_TAG_CHANGE, 1);
387   AssertAllCountsClear();
388
389   std::vector<BookmarkTag> alltags(tag_model_->TagsRelatedToTag(
390       base::string16()));
391   EXPECT_EQ(0UL, alltags.size());
392 }
393
394 TEST_F(BookmarkTagModelTest, RemoveAll) {
395   std::set<BookmarkTag> tags;
396   tags.insert(ASCIIToUTF16("bar"));
397   tags.insert(ASCIIToUTF16("baz"));
398
399   AddURLWithTags("foo", tags);
400   ClearCounts();
401
402   model_.RemoveAll();
403   AssertAndClearObserverCount(OBSERVER_COUNTS_EXTENSIVE_CHANGE_BEGIN, 1);
404   AssertAndClearObserverCount(OBSERVER_COUNTS_BEFORE_REMOVE_ALL, 1);
405   AssertAndClearObserverCount(OBSERVER_COUNTS_REMOVE_ALL, 1);
406   AssertAndClearObserverCount(OBSERVER_COUNTS_EXTENSIVE_CHANGE_END, 1);
407   AssertAllCountsClear();
408
409   std::vector<BookmarkTag> alltags(tag_model_->TagsRelatedToTag(
410       base::string16()));
411   EXPECT_EQ(0UL, alltags.size());
412 }
413
414 TEST_F(BookmarkTagModelTest, DuplicateFolders) {
415   const BookmarkNode* left = model_.AddFolder(model_.bookmark_bar_node(), 0,
416                                               ASCIIToUTF16("left"));
417   const BookmarkNode* right = model_.AddFolder(model_.bookmark_bar_node(), 0,
418                                                ASCIIToUTF16("right"));
419   const BookmarkNode* left_handed = model_.AddFolder(left, 0,
420                                                      ASCIIToUTF16("handed"));
421   const BookmarkNode* right_handed = model_.AddFolder(right, 0,
422                                                      ASCIIToUTF16("handed"));
423   model_.AddURL(
424       left_handed, 0, ASCIIToUTF16("red"), GURL("http://random.com"));
425   model_.AddURL(
426       right_handed, 0, ASCIIToUTF16("der"), GURL("http://random.com"));
427
428   EXPECT_EQ(2UL, tag_model_->BookmarksForTag(ASCIIToUTF16("handed")).size());
429   EXPECT_EQ(1UL, tag_model_->BookmarksForTag(ASCIIToUTF16("left")).size());
430   EXPECT_EQ(1UL, tag_model_->BookmarksForTag(ASCIIToUTF16("right")).size());
431   std::set<BookmarkTag> tags;
432   tags.insert(ASCIIToUTF16("left"));
433   tags.insert(ASCIIToUTF16("handed"));
434   EXPECT_EQ(1UL, tag_model_->BookmarksForTags(tags).size());
435 }
436
437 class PreloadedBookmarkTagModelTest : public BookmarkTagModelTest {
438  public:
439   PreloadedBookmarkTagModelTest() : BookmarkTagModelTest() {
440     PopulateUnderlyingModel();
441   }
442
443   void PopulateUnderlyingModel() {
444     ClearCounts();
445     top_node_ = model_.AddURL(model_.bookmark_bar_node(), 0,
446         ASCIIToUTF16("Tagless"), GURL("http://example.com"));
447     folder_1_ = model_.AddFolder(model_.bookmark_bar_node(), 0,
448                                  ASCIIToUTF16("folder1"));
449     one_tag_ = model_.AddURL(folder_1_, 0, ASCIIToUTF16("OneTag"),
450                              GURL("http://random.com"));
451     folder_2_ = model_.AddFolder(folder_1_, 0, ASCIIToUTF16("folder2"));
452     two_tags_ = model_.AddURL(folder_2_, 0, ASCIIToUTF16("TwoTags"),
453                               GURL("http://moveit.com"));
454     AssertAndClearObserverCount(OBSERVER_COUNTS_ADD, 3);
455     AssertAllCountsClear();
456   }
457
458   void AssertModelMatches() {
459     EXPECT_EQ(2UL, tag_model_->BookmarksForTag(ASCIIToUTF16("folder1")).size());
460     EXPECT_EQ(1UL, tag_model_->BookmarksForTag(ASCIIToUTF16("folder2")).size());
461
462     std::set<BookmarkTag> tags;
463     tags.insert(ASCIIToUTF16("folder1"));
464     EXPECT_EQ(tags, tag_model_->GetTagsForBookmark(one_tag_));
465
466     tags.insert(ASCIIToUTF16("folder2"));
467     const BookmarkNode* two_tags = tag_model_->
468         GetMostRecentlyAddedBookmarkForURL(GURL("http://moveit.com"));
469     EXPECT_EQ(tags, tag_model_->GetTagsForBookmark(two_tags));
470
471     std::vector<BookmarkTag> alltags(tag_model_->TagsRelatedToTag(
472         base::string16()));
473     EXPECT_EQ(2UL, alltags.size());
474   }
475
476  protected:
477   const BookmarkNode* folder_1_;
478   const BookmarkNode* folder_2_;
479   const BookmarkNode* top_node_;
480   const BookmarkNode* one_tag_;
481   const BookmarkNode* two_tags_;
482
483   DISALLOW_COPY_AND_ASSIGN(PreloadedBookmarkTagModelTest);
484 };
485
486 TEST_F(PreloadedBookmarkTagModelTest, InitialState) {
487   AssertAllCountsClear();
488   AssertModelMatches();
489 }
490
491 TEST_F(PreloadedBookmarkTagModelTest, FromExistingState) {
492   tag_model_.reset(new BookmarkTagModel(&model_));
493   tag_model_->AddObserver(this);
494   AssertAllCountsClear();
495   AssertModelMatches();
496 }
497
498 TEST_F(PreloadedBookmarkTagModelTest, BookmarkChange) {
499   AssertAllCountsClear();
500   tag_model_->SetTitle(top_node_, ASCIIToUTF16("newname"));
501   AssertAndClearObserverCount(OBSERVER_COUNTS_BEFORE_CHANGE, 1);
502   AssertAndClearObserverCount(OBSERVER_COUNTS_CHANGE, 1);
503   AssertAllCountsClear();
504 }
505
506 TEST_F(PreloadedBookmarkTagModelTest, UnchangedBookmarkMove) {
507   AssertAllCountsClear();
508   model_.Move(top_node_, folder_2_, 0);
509   AssertAndClearObserverCount(OBSERVER_COUNTS_BEFORE_TAG_CHANGE, 1);
510   AssertAndClearObserverCount(OBSERVER_COUNTS_TAG_CHANGE, 1);
511   AssertAllCountsClear();
512 }
513
514 TEST_F(PreloadedBookmarkTagModelTest, ChangedBookmarkMove) {
515   std::set<BookmarkTag> tags;
516   tags.insert(ASCIIToUTF16("bar"));
517
518   AssertAllCountsClear();
519   tag_model_->AddTagsToBookmark(tags, top_node_);
520   AssertAndClearObserverCount(OBSERVER_COUNTS_BEFORE_TAG_CHANGE, 1);
521   AssertAndClearObserverCount(OBSERVER_COUNTS_TAG_CHANGE, 1);
522   AssertAllCountsClear();
523
524   model_.Move(top_node_, folder_2_, 0);
525   AssertAllCountsClear();
526 }
527
528 TEST_F(PreloadedBookmarkTagModelTest, DuplicateBookmark) {
529   EXPECT_EQ(2UL, tag_model_->BookmarksForTag(folder_1_->GetTitle()).size());
530   model_.AddURL(folder_1_, 0, one_tag_->GetTitle(), one_tag_->url());
531   EXPECT_EQ(3UL, tag_model_->BookmarksForTag(folder_1_->GetTitle()).size());
532 }
533
534 TEST_F(PreloadedBookmarkTagModelTest, NamelessFolders) {
535   const BookmarkNode* folder = model_.AddFolder(model_.bookmark_bar_node(), 0,
536                                                 ASCIIToUTF16(""));
537   model_.AddURL(folder, 0, ASCIIToUTF16("StillNotag"),
538                 GURL("http://random.com"));
539   AssertModelMatches();
540 }
541
542 TEST_F(PreloadedBookmarkTagModelTest, FolderNameChange) {
543   EXPECT_EQ(2UL, tag_model_->BookmarksForTag(folder_1_->GetTitle()).size());
544   model_.SetTitle(folder_1_, ASCIIToUTF16("Bummer"));
545   AssertAndClearObserverCount(OBSERVER_COUNTS_EXTENSIVE_CHANGE_BEGIN, 1);
546   AssertAndClearObserverCount(OBSERVER_COUNTS_EXTENSIVE_CHANGE_END, 1);
547   AssertAndClearObserverCount(OBSERVER_COUNTS_BEFORE_TAG_CHANGE, 2);
548   AssertAndClearObserverCount(OBSERVER_COUNTS_TAG_CHANGE, 2);
549   AssertAllCountsClear();
550
551   EXPECT_EQ(2UL, tag_model_->BookmarksForTag(folder_1_->GetTitle()).size());
552 }
553
554 TEST_F(PreloadedBookmarkTagModelTest, FolderMoved) {
555   EXPECT_EQ(2UL, tag_model_->BookmarksForTag(folder_1_->GetTitle()).size());
556   model_.Move(folder_2_, model_.bookmark_bar_node(), 0);
557   AssertAndClearObserverCount(OBSERVER_COUNTS_EXTENSIVE_CHANGE_BEGIN, 1);
558   AssertAndClearObserverCount(OBSERVER_COUNTS_EXTENSIVE_CHANGE_END, 1);
559   AssertAndClearObserverCount(OBSERVER_COUNTS_BEFORE_TAG_CHANGE, 1);
560   AssertAndClearObserverCount(OBSERVER_COUNTS_TAG_CHANGE, 1);
561   AssertAllCountsClear();
562
563   EXPECT_EQ(1UL, tag_model_->BookmarksForTag(folder_1_->GetTitle()).size());
564 }
565
566 }  // namespace