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