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 "chrome/browser/ui/bookmarks/recently_used_folders_combo_model.h" 6 7 #include "base/memory/scoped_ptr.h" 8 #include "base/message_loop/message_loop.h" 9 #include "base/strings/utf_string_conversions.h" 10 #include "chrome/browser/bookmarks/bookmark_model.h" 11 #include "chrome/browser/bookmarks/bookmark_model_factory.h" 12 #include "chrome/browser/bookmarks/bookmark_test_helpers.h" 13 #include "chrome/test/base/testing_profile.h" 14 #include "content/public/test/test_browser_thread.h" 15 #include "testing/gtest/include/gtest/gtest.h" 16 #include "ui/base/models/combobox_model_observer.h" 17 18 using content::BrowserThread; 19 20 // Implementation of ComboboxModelObserver that records when OnModelChanged() 21 // is invoked. 22 class TestComboboxModelObserver : public ui::ComboboxModelObserver { 23 public: 24 TestComboboxModelObserver() : changed_(false) {} 25 virtual ~TestComboboxModelObserver() {} 26 27 // Returns whether the model changed and clears changed state. 28 bool GetAndClearChanged() { 29 const bool changed = changed_; 30 changed_ = false; 31 return changed; 32 } 33 34 // ComboboxModelObserver: 35 virtual void OnModelChanged() OVERRIDE { 36 changed_ = true; 37 } 38 39 private: 40 bool changed_; 41 42 DISALLOW_COPY_AND_ASSIGN(TestComboboxModelObserver); 43 }; 44 45 class RecentlyUsedFoldersComboModelTest : public testing::Test { 46 public: 47 RecentlyUsedFoldersComboModelTest(); 48 49 virtual void SetUp() OVERRIDE; 50 virtual void TearDown() OVERRIDE; 51 52 protected: 53 BookmarkModel* GetModel(); 54 55 private: 56 base::MessageLoopForUI message_loop_; 57 content::TestBrowserThread ui_thread_; 58 content::TestBrowserThread file_thread_; 59 scoped_ptr<TestingProfile> profile_; 60 61 DISALLOW_COPY_AND_ASSIGN(RecentlyUsedFoldersComboModelTest); 62 }; 63 64 RecentlyUsedFoldersComboModelTest::RecentlyUsedFoldersComboModelTest() 65 : ui_thread_(BrowserThread::UI, &message_loop_), 66 file_thread_(BrowserThread::FILE, &message_loop_) { 67 } 68 69 void RecentlyUsedFoldersComboModelTest::SetUp() { 70 profile_.reset(new TestingProfile()); 71 profile_->CreateBookmarkModel(true); 72 test::WaitForBookmarkModelToLoad(GetModel()); 73 } 74 75 void RecentlyUsedFoldersComboModelTest::TearDown() { 76 // Flush the message loop to make application verifiers happy. 77 message_loop_.RunUntilIdle(); 78 } 79 80 BookmarkModel* RecentlyUsedFoldersComboModelTest::GetModel() { 81 return BookmarkModelFactory::GetForProfile(profile_.get()); 82 } 83 84 // Verifies there are no duplicate nodes in the model. 85 TEST_F(RecentlyUsedFoldersComboModelTest, NoDups) { 86 const BookmarkNode* new_node = GetModel()->AddURL( 87 GetModel()->bookmark_bar_node(), 0, ASCIIToUTF16("a"), 88 GURL("http://a")); 89 RecentlyUsedFoldersComboModel model(GetModel(), new_node); 90 std::set<base::string16> items; 91 for (int i = 0; i < model.GetItemCount(); ++i) { 92 if (!model.IsItemSeparatorAt(i)) 93 EXPECT_EQ(0u, items.count(model.GetItemAt(i))); 94 } 95 } 96 97 // Verifies that observers are notified on changes. 98 TEST_F(RecentlyUsedFoldersComboModelTest, NotifyObserver) { 99 const BookmarkNode* folder = GetModel()->AddFolder( 100 GetModel()->bookmark_bar_node(), 0, ASCIIToUTF16("a")); 101 const BookmarkNode* sub_folder = GetModel()->AddFolder( 102 folder, 0, ASCIIToUTF16("b")); 103 const BookmarkNode* new_node = GetModel()->AddURL( 104 sub_folder, 0, ASCIIToUTF16("a"), GURL("http://a")); 105 RecentlyUsedFoldersComboModel model(GetModel(), new_node); 106 TestComboboxModelObserver observer; 107 model.AddObserver(&observer); 108 109 const int initial_count = model.GetItemCount(); 110 // Remove a folder, it should remove an item from the model too. 111 GetModel()->Remove(folder, folder->GetIndexOf(sub_folder)); 112 EXPECT_TRUE(observer.GetAndClearChanged()); 113 const int updated_count = model.GetItemCount(); 114 EXPECT_LT(updated_count, initial_count); 115 116 // Remove all, which should remove a folder too. 117 GetModel()->RemoveAll(); 118 EXPECT_TRUE(observer.GetAndClearChanged()); 119 EXPECT_LT(model.GetItemCount(), updated_count); 120 121 model.RemoveObserver(&observer); 122 } 123