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 |