Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(42)

Side by Side Diff: chrome/browser/extensions/extension_record_api_test.cc

Issue 10696144: Moving record API to api/record/ . (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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/extensions/extension_record_api.h"
6
7 #include <string>
8
9 #include "base/memory/ref_counted.h"
10 #include "base/file_path.h"
11 #include "base/file_util.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/path_service.h"
14 #include "base/string_split.h"
15 #include "base/stringprintf.h"
16 #include "base/string_util.h"
17 #include "base/threading/sequenced_worker_pool.h"
18 #include "base/values.h"
19 #include "chrome/browser/extensions/extension_function_test_utils.h"
20 #include "chrome/browser/ui/browser.h"
21 #include "chrome/browser/ui/browser_window.h"
22 #include "chrome/common/chrome_paths.h"
23 #include "chrome/common/chrome_switches.h"
24 #include "chrome/common/extensions/api/experimental_record.h"
25 #include "chrome/test/base/in_process_browser_test.h"
26 #include "chrome/test/base/ui_test_utils.h"
27 #include "content/public/browser/browser_thread.h"
28 #include "content/public/common/content_switches.h"
29
30 namespace utils = extension_function_test_utils;
31
32 namespace {
33
34 // Dummy content for mock stats file.
35 const std::string kTestStatistics = "Sample Stat 1\nSample Stat 2\n";
36
37 // Standard capture parameters, with a mix of good and bad URLs, and
38 // a hole for filling in the user data dir.
39 const char kCaptureArgs1[] =
40 "[[\"URL 1\", \"URL 2(bad)\", \"URL 3\", \"URL 4(bad)\"]"
41 ", \"%s\"]";
42
43 // Standard playback parameters, with the same mix of good and bad URLs
44 // as the capture parameters, a hole for filling in the user data dir, and
45 // a mocked-up extension path and repeat count (which are used only to
46 // verify that they made it into the CommandLine, since extension loading
47 // and repeat-counting are hard to emulate in the test ProcessStrategy.
48 const char kPlaybackArgs1[] =
49 "[[\"URL 1\", \"URL 2(bad)\", \"URL 3\", \"URL 4(bad)\"], \"%s\""
50 ", 2, {\"extensionPath\": \"MockExtension\"}]";
51
52 // Use this as the value of FilePath switches (e.g. user-data-dir) that
53 // should be replaced by the record methods.
54 const FilePath::CharType kDummyDirName[] = FILE_PATH_LITERAL("ReplaceMe");
55
56 // Use this as the filename for a mock "cache" file in the user-data-dir.
57 const FilePath::CharType kMockCacheFile[] = FILE_PATH_LITERAL("MockCache");
58
59 // Prefix for temporary user data directory
60 const FilePath::CharType kUserDataDirPrefix[]
61 = FILE_PATH_LITERAL("PageCyclerTest");
62
63 }
64
65 class TestProcessStrategy : public ProcessStrategy {
66 public:
67 explicit TestProcessStrategy(std::vector<FilePath>* temp_files)
68 : command_line_(CommandLine::NO_PROGRAM), temp_files_(temp_files) {}
69
70 ~TestProcessStrategy() {}
71
72 // Pump the blocking pool queue, since this is needed during test.
73 void PumpBlockingPool() OVERRIDE {
74 content::BrowserThread::GetBlockingPool()->FlushForTesting();
75 }
76
77 // Act somewhat like a real test browser instance. In particular:
78 // 1. If visit-urls, then
79 // a. If record-mode, then put a copy of the URL list into the user data
80 // directory in a mocked up cache file
81 // b. If playback-mode, then check for existence of that URL list copy
82 // in the cache
83 // c. Scan list of URLS, noting in |urls_visited_| all those
84 // visited. If there are any "bad" URLS, don't visit these, but
85 // create a ".errors" file listing them.
86 // 2. If record-stats, then create a mock stats file.
87 void RunProcess(const CommandLine& command_line,
88 std::vector<std::string>* errors) OVERRIDE {
89 command_line_ = command_line;
90 visited_urls_.clear();
91
92 if (command_line.HasSwitch(switches::kVisitURLs)) {
93 FilePath url_path =
94 command_line.GetSwitchValuePath(switches::kVisitURLs);
95
96 temp_files_->push_back(url_path);
97 if (command_line.HasSwitch(switches::kRecordMode) ||
98 command_line.HasSwitch(switches::kPlaybackMode)) {
99 FilePath url_path_copy = command_line.GetSwitchValuePath(
100 switches::kUserDataDir).Append(
101 FilePath(FilePath::StringType(kMockCacheFile)));
102
103 if (command_line.HasSwitch(switches::kRecordMode)) {
104 file_util::CopyFile(url_path, url_path_copy);
105 } else {
106 if (!file_util::ContentsEqual(url_path, url_path_copy)) {
107 std::string contents1, contents2;
108 file_util::ReadFileToString(url_path, &contents1);
109 file_util::ReadFileToString(url_path_copy, &contents2);
110 LOG(ERROR) << "FILE MISMATCH" << contents1 << " VS " << contents2;
111 }
112 EXPECT_TRUE(file_util::ContentsEqual(url_path, url_path_copy));
113 }
114 }
115
116 std::string urls;
117 file_util::ReadFileToString(url_path, &urls);
118
119 std::vector<std::string> url_vector, bad_urls;
120 base::SplitString(urls, '\n', &url_vector);
121 for (std::vector<std::string>::iterator itr = url_vector.begin();
122 itr != url_vector.end(); ++itr) {
123 if (itr->find_first_of("bad") != std::string::npos)
124 bad_urls.push_back(*itr);
125 else
126 visited_urls_.push_back(*itr);
127 }
128
129 if (!bad_urls.empty()) {
130 FilePath url_errors_path = url_path.DirName()
131 .Append(url_path.BaseName().value() +
132 FilePath::StringType(kURLErrorsSuffix));
133 std::string error_content = JoinString(bad_urls, '\n');
134 temp_files_->push_back(url_errors_path);
135 file_util::WriteFile(url_errors_path, error_content.c_str(),
136 error_content.size());
137 }
138 }
139
140 if (command_line.HasSwitch(switches::kRecordStats)) {
141 FilePath record_stats_path(command_line.GetSwitchValuePath(
142 switches::kRecordStats));
143 temp_files_->push_back(record_stats_path);
144 file_util::WriteFile(record_stats_path, kTestStatistics.c_str(),
145 kTestStatistics.size());
146 }
147 }
148
149 const CommandLine& GetCommandLine() const {
150 return command_line_;
151 }
152
153 const std::vector<std::string>& GetVisitedURLs() const {
154 return visited_urls_;
155 }
156
157 private:
158 CommandLine command_line_;
159 std::vector<std::string> visited_urls_;
160 std::vector<FilePath>* temp_files_;
161 };
162
163 class RecordApiTest : public InProcessBrowserTest {
164 public:
165 RecordApiTest() {}
166 virtual ~RecordApiTest() {}
167
168 // Override to scope known temp directories outside the scope of the running
169 // browser test.
170 virtual void SetUp() OVERRIDE {
171 InProcessBrowserTest::SetUp();
172 if (!scoped_temp_user_data_dir_.Set(FilePath(kDummyDirName)))
173 NOTREACHED();
174 }
175
176 // Override to delete temp directories.
177 virtual void TearDown() OVERRIDE {
178 if (!scoped_temp_user_data_dir_.Delete())
179 NOTREACHED();
180 InProcessBrowserTest::TearDown();
181 }
182
183 // Override to delete temporary files created during execution.
184 virtual void CleanUpOnMainThread() OVERRIDE {
185 InProcessBrowserTest::CleanUpOnMainThread();
186 for (std::vector<FilePath>::const_iterator it = temp_files_.begin();
187 it != temp_files_.end(); ++it) {
188 if (!file_util::Delete(*it, false))
189 NOTREACHED();
190 }
191 }
192
193 // Override SetUpCommandline to specify a dummy user_data_dir, which
194 // should be replaced. Clear record-mode, playback-mode, visit-urls,
195 // record-stats, and load-extension.
196 void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
197 InProcessBrowserTest::SetUpCommandLine(command_line);
198 std::vector<std::string> remove_switches;
199
200 remove_switches.push_back(switches::kUserDataDir);
201 remove_switches.push_back(switches::kVisitURLs);
202 remove_switches.push_back(switches::kPlaybackMode);
203 remove_switches.push_back(switches::kRecordStats);
204 remove_switches.push_back(switches::kLoadExtension);
205 *command_line = RunPageCyclerFunction::RemoveSwitches(*command_line,
206 remove_switches);
207
208 command_line->AppendSwitchPath(switches::kUserDataDir,
209 FilePath(kDummyDirName));
210 // Adding a dummy load-extension switch is rather complex since the
211 // preent design of InProcessBrowserTest requires a *real* extension
212 // for the flag, even if we're just testing its replacement. Opted
213 // to omit this for the sake of simplicity.
214 }
215
216 // Run a capture, using standard URL test list and the specified
217 // user data dir. Return via |out_list| the list of error URLs,
218 // if any, resulting from the capture. And return directly the
219 // CaptureURLsFunction that was used, so that its state may be
220 // queried.
221 scoped_refptr<CaptureURLsFunction> RunCapture(const FilePath& user_data_dir,
222 scoped_ptr<base::ListValue>* out_list) {
223
224 scoped_refptr<CaptureURLsFunction> capture_function(
225 new CaptureURLsFunction(new TestProcessStrategy(&temp_files_)));
226
227 std::string escaped_user_data_dir;
228 ReplaceChars(user_data_dir.AsUTF8Unsafe(), "\\", "\\\\",
229 &escaped_user_data_dir);
230
231 out_list->reset(utils::ToList(
232 utils::RunFunctionAndReturnResult(capture_function.get(),
233 base::StringPrintf(kCaptureArgs1, escaped_user_data_dir.c_str()),
234 browser())));
235
236 return capture_function;
237 }
238
239 // Verify that the URL list of good and bad URLs was properly handled.
240 // Needed by several tests.
241 bool VerifyURLHandling(const ListValue* result,
242 const TestProcessStrategy& strategy) {
243
244 // Check that the two bad URLs are returned.
245 base::Value* string_value = NULL;
246 StringValue badURL2("URL 2(bad)"), badURL4("URL 4(bad)");
247
248 EXPECT_TRUE(result->GetSize() == 2);
249 result->Get(0, &string_value);
250 EXPECT_TRUE(base::Value::Equals(string_value, &badURL2));
251 result->Get(1, &string_value);
252 EXPECT_TRUE(base::Value::Equals(string_value, &badURL4));
253
254 // Check that both good URLs were visited.
255 std::string goodURL1("URL 1"), goodURL3("URL 3");
256 EXPECT_TRUE(strategy.GetVisitedURLs()[0].compare(goodURL1) == 0
257 && strategy.GetVisitedURLs()[1].compare(goodURL3) == 0);
258
259 return true;
260 }
261
262 protected:
263 std::vector<FilePath> temp_files_;
264
265 private:
266 ScopedTempDir scoped_temp_user_data_dir_;
267
268 DISALLOW_COPY_AND_ASSIGN(RecordApiTest);
269 };
270
271
272 IN_PROC_BROWSER_TEST_F(RecordApiTest, CheckCapture) {
273 ScopedTempDir user_data_dir;
274 scoped_ptr<base::ListValue> result;
275
276 EXPECT_TRUE(user_data_dir.CreateUniqueTempDir());
277 scoped_refptr<CaptureURLsFunction> capture_URLs_function =
278 RunCapture(user_data_dir.path(), &result);
279
280 // Check that user-data-dir switch has been properly overridden.
281 const TestProcessStrategy &strategy =
282 static_cast<const TestProcessStrategy &>(
283 capture_URLs_function->GetProcessStrategy());
284 const CommandLine& command_line = strategy.GetCommandLine();
285
286 EXPECT_TRUE(command_line.HasSwitch(switches::kUserDataDir));
287 EXPECT_TRUE(command_line.GetSwitchValuePath(switches::kUserDataDir) !=
288 FilePath(kDummyDirName));
289
290 EXPECT_TRUE(VerifyURLHandling(result.get(), strategy));
291 }
292
293 #if defined(ADDRESS_SANITIZER)
294 // Times out under ASan, see http://crbug.com/130267.
295 #define MAYBE_CheckPlayback DISABLED_CheckPlayback
296 #else
297 #define MAYBE_CheckPlayback CheckPlayback
298 #endif
299 IN_PROC_BROWSER_TEST_F(RecordApiTest, MAYBE_CheckPlayback) {
300 ScopedTempDir user_data_dir;
301
302 EXPECT_TRUE(user_data_dir.CreateUniqueTempDir());
303
304 // Assume this RunCapture operates w/o error, since it's tested
305 // elsewhere.
306 scoped_ptr<base::ListValue> capture_result;
307 RunCapture(user_data_dir.path(), &capture_result);
308
309 std::string escaped_user_data_dir;
310 ReplaceChars(user_data_dir.path().AsUTF8Unsafe(), "\\", "\\\\",
311 &escaped_user_data_dir);
312
313 scoped_refptr<ReplayURLsFunction> playback_function(new ReplayURLsFunction(
314 new TestProcessStrategy(&temp_files_)));
315 scoped_ptr<base::DictionaryValue> result(utils::ToDictionary(
316 utils::RunFunctionAndReturnResult(playback_function,
317 base::StringPrintf(kPlaybackArgs1, escaped_user_data_dir.c_str()),
318 browser())));
319
320 // Check that command line user-data-dir was overridden. (That
321 // it was *consistently* overridden in both capture and replay
322 // is verified elsewhere.
323 const TestProcessStrategy &strategy =
324 static_cast<const TestProcessStrategy &>(
325 playback_function->GetProcessStrategy());
326 const CommandLine& command_line = strategy.GetCommandLine();
327
328 EXPECT_TRUE(command_line.HasSwitch(switches::kUserDataDir));
329 EXPECT_TRUE(command_line.GetSwitchValuePath(switches::kUserDataDir) !=
330 FilePath(kDummyDirName));
331
332 // Check that command line load-extension was overridden.
333 EXPECT_TRUE(command_line.HasSwitch(switches::kLoadExtension) &&
334 command_line.GetSwitchValuePath(switches::kLoadExtension)
335 != FilePath(kDummyDirName));
336
337 // Check for return value with proper stats.
338 EXPECT_EQ(kTestStatistics, utils::GetString(result.get(), kStatsKey));
339
340 ListValue* errors = NULL;
341 EXPECT_TRUE(result->GetList(kErrorsKey, &errors));
342 EXPECT_TRUE(VerifyURLHandling(errors, strategy));
343 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698