| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2009 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 entry. | |
| 4 | |
| 5 #include "chrome/browser/sync/util/extensions_activity_monitor.h" | |
| 6 | |
| 7 #include "base/file_path.h" | |
| 8 #include "base/string_util.h" | |
| 9 #include "base/waitable_event.h" | |
| 10 #include "chrome/browser/chrome_thread.h" | |
| 11 #include "chrome/browser/extensions/extension_bookmarks_module.h" | |
| 12 #include "chrome/common/extensions/extension.h" | |
| 13 #include "chrome/common/extensions/extension_constants.h" | |
| 14 #include "chrome/common/notification_service.h" | |
| 15 #include "testing/gtest/include/gtest/gtest.h" | |
| 16 | |
| 17 using browser_sync::ExtensionsActivityMonitor; | |
| 18 namespace keys = extension_manifest_keys; | |
| 19 | |
| 20 namespace { | |
| 21 | |
| 22 static const char* kTestExtensionPath1 = "c:\\testextension1"; | |
| 23 static const char* kTestExtensionPath2 = "c:\\testextension2"; | |
| 24 static const char* kTestExtensionVersion = "1.0.0.0"; | |
| 25 static const char* kTestExtensionName = "foo extension"; | |
| 26 | |
| 27 template <class FunctionType> | |
| 28 class BookmarkAPIEventTask : public Task { | |
| 29 public: | |
| 30 BookmarkAPIEventTask(FunctionType* t, Extension* e, size_t repeats, | |
| 31 base::WaitableEvent* done) : | |
| 32 function_(t), extension_(e), repeats_(repeats), done_(done) {} | |
| 33 virtual void Run() { | |
| 34 for (size_t i = 0; i < repeats_; i++) { | |
| 35 NotificationService::current()->Notify( | |
| 36 NotificationType::EXTENSION_BOOKMARKS_API_INVOKED, | |
| 37 Source<Extension>(extension_.get()), | |
| 38 Details<const BookmarksFunction>(function_.get())); | |
| 39 } | |
| 40 done_->Signal(); | |
| 41 } | |
| 42 private: | |
| 43 scoped_ptr<Extension> extension_; | |
| 44 scoped_refptr<FunctionType> function_; | |
| 45 size_t repeats_; | |
| 46 base::WaitableEvent* done_; | |
| 47 | |
| 48 DISALLOW_COPY_AND_ASSIGN(BookmarkAPIEventTask); | |
| 49 }; | |
| 50 | |
| 51 class BookmarkAPIEventGenerator { | |
| 52 public: | |
| 53 BookmarkAPIEventGenerator(MessageLoop* ui_loop) : ui_loop_(ui_loop) {} | |
| 54 virtual ~BookmarkAPIEventGenerator() {} | |
| 55 template <class T> | |
| 56 void NewEvent(const std::string& extension_path, | |
| 57 T* bookmarks_function, size_t repeats) { | |
| 58 FilePath path(UTF8ToWide(extension_path)); | |
| 59 Extension* extension = new Extension(path); | |
| 60 std::string error; | |
| 61 DictionaryValue input; | |
| 62 input.SetString(keys::kVersion, kTestExtensionVersion); | |
| 63 input.SetString(keys::kName, kTestExtensionName); | |
| 64 extension->InitFromValue(input, false, &error); | |
| 65 bookmarks_function->set_name(T::function_name()); | |
| 66 base::WaitableEvent done_event(false, false); | |
| 67 ui_loop_->PostTask(FROM_HERE, new BookmarkAPIEventTask<T>( | |
| 68 bookmarks_function, extension, repeats, &done_event)); | |
| 69 done_event.Wait(); | |
| 70 } | |
| 71 | |
| 72 private: | |
| 73 MessageLoop* ui_loop_; | |
| 74 DISALLOW_COPY_AND_ASSIGN(BookmarkAPIEventGenerator); | |
| 75 }; | |
| 76 } // namespace | |
| 77 | |
| 78 class DoUIThreadSetupTask : public Task { | |
| 79 public: | |
| 80 DoUIThreadSetupTask(NotificationService** service, | |
| 81 base::WaitableEvent* done) | |
| 82 : service_(service), signal_when_done_(done) {} | |
| 83 virtual ~DoUIThreadSetupTask() {} | |
| 84 virtual void Run() { | |
| 85 *service_ = new NotificationService(); | |
| 86 signal_when_done_->Signal(); | |
| 87 } | |
| 88 private: | |
| 89 NotificationService** service_; | |
| 90 base::WaitableEvent* signal_when_done_; | |
| 91 DISALLOW_COPY_AND_ASSIGN(DoUIThreadSetupTask); | |
| 92 }; | |
| 93 | |
| 94 class ExtensionsActivityMonitorTest : public testing::Test { | |
| 95 public: | |
| 96 ExtensionsActivityMonitorTest() : service_(NULL), | |
| 97 ui_thread_(ChromeThread::UI) { } | |
| 98 virtual ~ExtensionsActivityMonitorTest() {} | |
| 99 | |
| 100 virtual void SetUp() { | |
| 101 ui_thread_.Start(); | |
| 102 base::WaitableEvent service_created(false, false); | |
| 103 ui_thread_.message_loop()->PostTask(FROM_HERE, | |
| 104 new DoUIThreadSetupTask(&service_, &service_created)); | |
| 105 service_created.Wait(); | |
| 106 } | |
| 107 | |
| 108 virtual void TearDown() { | |
| 109 ui_thread_.message_loop()->DeleteSoon(FROM_HERE, service_); | |
| 110 ui_thread_.Stop(); | |
| 111 } | |
| 112 | |
| 113 MessageLoop* ui_loop() { return ui_thread_.message_loop(); } | |
| 114 | |
| 115 static std::string GetExtensionIdForPath(const std::string& extension_path) { | |
| 116 std::string error; | |
| 117 FilePath path(UTF8ToWide(extension_path)); | |
| 118 Extension e(path); | |
| 119 DictionaryValue input; | |
| 120 input.SetString(keys::kVersion, kTestExtensionVersion); | |
| 121 input.SetString(keys::kName, kTestExtensionName); | |
| 122 e.InitFromValue(input, false, &error); | |
| 123 EXPECT_EQ("", error); | |
| 124 return e.id(); | |
| 125 } | |
| 126 private: | |
| 127 NotificationService* service_; | |
| 128 ChromeThread ui_thread_; | |
| 129 }; | |
| 130 | |
| 131 TEST_F(ExtensionsActivityMonitorTest, Basic) { | |
| 132 ExtensionsActivityMonitor* monitor = new ExtensionsActivityMonitor(ui_loop()); | |
| 133 BookmarkAPIEventGenerator generator(ui_loop()); | |
| 134 | |
| 135 generator.NewEvent<RemoveBookmarkFunction>(kTestExtensionPath1, | |
| 136 new RemoveBookmarkFunction(), 1); | |
| 137 generator.NewEvent<MoveBookmarkFunction>(kTestExtensionPath1, | |
| 138 new MoveBookmarkFunction(), 1); | |
| 139 generator.NewEvent<UpdateBookmarkFunction>(kTestExtensionPath1, | |
| 140 new UpdateBookmarkFunction(), 2); | |
| 141 generator.NewEvent<CreateBookmarkFunction>(kTestExtensionPath1, | |
| 142 new CreateBookmarkFunction(), 3); | |
| 143 generator.NewEvent<SearchBookmarksFunction>(kTestExtensionPath1, | |
| 144 new SearchBookmarksFunction(), 5); | |
| 145 const int writes_by_extension1 = 1 + 1 + 2 + 3; | |
| 146 | |
| 147 generator.NewEvent<RemoveTreeBookmarkFunction>(kTestExtensionPath2, | |
| 148 new RemoveTreeBookmarkFunction(), 8); | |
| 149 generator.NewEvent<GetBookmarkTreeFunction>(kTestExtensionPath2, | |
| 150 new GetBookmarkTreeFunction(), 13); | |
| 151 generator.NewEvent<GetBookmarkChildrenFunction>(kTestExtensionPath2, | |
| 152 new GetBookmarkChildrenFunction(), 21); | |
| 153 generator.NewEvent<GetBookmarksFunction>(kTestExtensionPath2, | |
| 154 new GetBookmarksFunction(), 33); | |
| 155 const int writes_by_extension2 = 8; | |
| 156 | |
| 157 ExtensionsActivityMonitor::Records results; | |
| 158 monitor->GetAndClearRecords(&results); | |
| 159 | |
| 160 std::string id1 = GetExtensionIdForPath(kTestExtensionPath1); | |
| 161 std::string id2 = GetExtensionIdForPath(kTestExtensionPath2); | |
| 162 | |
| 163 EXPECT_EQ(2, results.size()); | |
| 164 EXPECT_TRUE(results.end() != results.find(id1)); | |
| 165 EXPECT_TRUE(results.end() != results.find(id2)); | |
| 166 EXPECT_EQ(writes_by_extension1, results[id1].bookmark_write_count); | |
| 167 EXPECT_EQ(writes_by_extension2, results[id2].bookmark_write_count); | |
| 168 | |
| 169 ui_loop()->DeleteSoon(FROM_HERE, monitor); | |
| 170 } | |
| 171 | |
| 172 TEST_F(ExtensionsActivityMonitorTest, Put) { | |
| 173 ExtensionsActivityMonitor* monitor = new ExtensionsActivityMonitor(ui_loop()); | |
| 174 BookmarkAPIEventGenerator generator(ui_loop()); | |
| 175 std::string id1 = GetExtensionIdForPath(kTestExtensionPath1); | |
| 176 std::string id2 = GetExtensionIdForPath(kTestExtensionPath2); | |
| 177 | |
| 178 generator.NewEvent<CreateBookmarkFunction>(kTestExtensionPath1, | |
| 179 new CreateBookmarkFunction(), 5); | |
| 180 generator.NewEvent<MoveBookmarkFunction>(kTestExtensionPath2, | |
| 181 new MoveBookmarkFunction(), 8); | |
| 182 | |
| 183 ExtensionsActivityMonitor::Records results; | |
| 184 monitor->GetAndClearRecords(&results); | |
| 185 | |
| 186 EXPECT_EQ(2, results.size()); | |
| 187 EXPECT_EQ(5, results[id1].bookmark_write_count); | |
| 188 EXPECT_EQ(8, results[id2].bookmark_write_count); | |
| 189 | |
| 190 generator.NewEvent<GetBookmarksFunction>(kTestExtensionPath2, | |
| 191 new GetBookmarksFunction(), 3); | |
| 192 generator.NewEvent<UpdateBookmarkFunction>(kTestExtensionPath2, | |
| 193 new UpdateBookmarkFunction(), 2); | |
| 194 | |
| 195 // Simulate a commit failure, which augments the active record set with the | |
| 196 // refugee records. | |
| 197 monitor->PutRecords(results); | |
| 198 ExtensionsActivityMonitor::Records new_records; | |
| 199 monitor->GetAndClearRecords(&new_records); | |
| 200 | |
| 201 EXPECT_EQ(2, results.size()); | |
| 202 EXPECT_EQ(id1, new_records[id1].extension_id); | |
| 203 EXPECT_EQ(id2, new_records[id2].extension_id); | |
| 204 EXPECT_EQ(5, new_records[id1].bookmark_write_count); | |
| 205 EXPECT_EQ(8 + 2, new_records[id2].bookmark_write_count); | |
| 206 ui_loop()->DeleteSoon(FROM_HERE, monitor); | |
| 207 } | |
| 208 | |
| 209 TEST_F(ExtensionsActivityMonitorTest, MultiGet) { | |
| 210 ExtensionsActivityMonitor* monitor = new ExtensionsActivityMonitor(ui_loop()); | |
| 211 BookmarkAPIEventGenerator generator(ui_loop()); | |
| 212 std::string id1 = GetExtensionIdForPath(kTestExtensionPath1); | |
| 213 | |
| 214 generator.NewEvent<CreateBookmarkFunction>(kTestExtensionPath1, | |
| 215 new CreateBookmarkFunction(), 5); | |
| 216 | |
| 217 ExtensionsActivityMonitor::Records results; | |
| 218 monitor->GetAndClearRecords(&results); | |
| 219 | |
| 220 EXPECT_EQ(1, results.size()); | |
| 221 EXPECT_EQ(5, results[id1].bookmark_write_count); | |
| 222 | |
| 223 monitor->GetAndClearRecords(&results); | |
| 224 EXPECT_TRUE(results.empty()); | |
| 225 | |
| 226 generator.NewEvent<CreateBookmarkFunction>(kTestExtensionPath1, | |
| 227 new CreateBookmarkFunction(), 3); | |
| 228 monitor->GetAndClearRecords(&results); | |
| 229 | |
| 230 EXPECT_EQ(1, results.size()); | |
| 231 EXPECT_EQ(3, results[id1].bookmark_write_count); | |
| 232 | |
| 233 ui_loop()->DeleteSoon(FROM_HERE, monitor); | |
| 234 } | |
| OLD | NEW |