OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/safe_browsing/srt_fetcher_win.h" | 5 #include "chrome/browser/safe_browsing/srt_fetcher_win.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
(...skipping 20 matching lines...) Expand all Loading... | |
31 task_runner_ = new base::TestSimpleTaskRunner; | 31 task_runner_ = new base::TestSimpleTaskRunner; |
32 | 32 |
33 SetSwReporterTestingDelegate(this); | 33 SetSwReporterTestingDelegate(this); |
34 } | 34 } |
35 | 35 |
36 void TearDownInProcessBrowserTestFixture() override { | 36 void TearDownInProcessBrowserTestFixture() override { |
37 SetSwReporterTestingDelegate(nullptr); | 37 SetSwReporterTestingDelegate(nullptr); |
38 } | 38 } |
39 | 39 |
40 void RunReporter(const base::FilePath& exe_path = base::FilePath()) { | 40 void RunReporter(const base::FilePath& exe_path = base::FilePath()) { |
41 RunSwReporter(SwReporterInvocation::FromFilePath(exe_path), | 41 SwReporterQueue invocations; |
42 base::Version("1.2.3"), task_runner_, task_runner_); | 42 invocations.push(SwReporterInvocation::FromFilePath(exe_path)); |
43 RunSwReporters(invocations, base::Version("1.2.3"), task_runner_, | |
44 task_runner_); | |
45 } | |
46 | |
47 void RunReporterQueue(const SwReporterQueue& invocations) { | |
48 RunSwReporters(invocations, base::Version("1.2.3"), task_runner_, | |
49 task_runner_); | |
43 } | 50 } |
44 | 51 |
45 void TriggerPrompt(Browser* browser, const std::string& version) override { | 52 void TriggerPrompt(Browser* browser, const std::string& version) override { |
46 prompt_trigger_called_ = true; | 53 prompt_trigger_called_ = true; |
47 } | 54 } |
48 | 55 |
49 int LaunchReporter(const SwReporterInvocation& invocation) override { | 56 int LaunchReporter(const SwReporterInvocation& invocation) override { |
50 ++reporter_launch_count_; | 57 ++reporter_launch_count_; |
51 reporter_launch_parameters_ = invocation; | 58 reporter_launch_parameters_ = invocation; |
52 return exit_code_to_report_; | 59 return exit_code_to_report_; |
(...skipping 11 matching lines...) Expand all Loading... | |
64 } | 71 } |
65 | 72 |
66 void ExpectToRunAgain(int days) { | 73 void ExpectToRunAgain(int days) { |
67 ASSERT_TRUE(task_runner_->HasPendingTask()); | 74 ASSERT_TRUE(task_runner_->HasPendingTask()); |
68 EXPECT_LE(task_runner_->NextPendingTaskDelay(), | 75 EXPECT_LE(task_runner_->NextPendingTaskDelay(), |
69 base::TimeDelta::FromDays(days)); | 76 base::TimeDelta::FromDays(days)); |
70 EXPECT_GT(task_runner_->NextPendingTaskDelay(), | 77 EXPECT_GT(task_runner_->NextPendingTaskDelay(), |
71 base::TimeDelta::FromDays(days) - base::TimeDelta::FromHours(1)); | 78 base::TimeDelta::FromDays(days) - base::TimeDelta::FromHours(1)); |
72 } | 79 } |
73 | 80 |
74 void TestReporterLaunchCycle(int expected_launch_count, | 81 void TestPartialLaunchCycle( |
Jialiu Lin
2016/09/12 20:55:13
nit: maybe add some comment to this function and T
Joe Mason
2016/09/12 23:33:29
Done.
| |
75 const base::FilePath& expected_launch_path) { | 82 const std::vector<base::FilePath>& expected_launch_paths) { |
83 reporter_launch_count_ = 0; | |
84 reporter_launch_parameters_ = SwReporterInvocation(); | |
85 | |
76 // This test has an unfortunate amount of knowledge of the internals of | 86 // This test has an unfortunate amount of knowledge of the internals of |
77 // ReporterRunner, because it needs to pump the right message loops at the | 87 // ReporterRunner, because it needs to pump the right message loops at the |
78 // right time so that all its internal messages are delivered. This | 88 // right time so that all its internal messages are delivered. This |
79 // function might need to be updated if the internals change. | 89 // function might need to be updated if the internals change. |
80 // | 90 // |
81 // The basic sequence is: | 91 // The basic sequence is: |
82 | 92 |
83 // 1. TryToRun kicks the whole thing off. If the reporter should not be | 93 // 1. TryToRun kicks the whole thing off. If the reporter should not be |
84 // launched now (eg. DaysSinceLastReport is too low) it posts a call to | 94 // launched now (eg. DaysSinceLastReport is too low) it posts a call to |
85 // itself again. (In a regular task runner this will be scheduled with a | 95 // itself again. (In a regular task runner this will be scheduled with a |
(...skipping 14 matching lines...) Expand all Loading... | |
100 // it in a loop to make sure we're past all pending TryToRun calls before | 110 // it in a loop to make sure we're past all pending TryToRun calls before |
101 // LaunchAndWaitForExit will be called. | 111 // LaunchAndWaitForExit will be called. |
102 // | 112 // |
103 // Once a call to LaunchAndWaitForExit has been posted, TryToRun won't be | 113 // Once a call to LaunchAndWaitForExit has been posted, TryToRun won't be |
104 // called again until we pump the UI message loop in order to run | 114 // called again until we pump the UI message loop in order to run |
105 // ReporterDone. | 115 // ReporterDone. |
106 | 116 |
107 ASSERT_TRUE(task_runner_->HasPendingTask()); | 117 ASSERT_TRUE(task_runner_->HasPendingTask()); |
108 ASSERT_FALSE(reporter_done_notified_); | 118 ASSERT_FALSE(reporter_done_notified_); |
109 | 119 |
110 // Clear out any pending TryToRun calls. Use a bounded loop so that if the | 120 int current_launch_count = reporter_launch_count_; |
111 // reporter will never be called, we'll eventually continue. (If | 121 for (const auto& expected_launch_path : expected_launch_paths) { |
112 // LaunchAndWaitForExit was pending but TryToRun wasn't, this will call | 122 // If RunReporter was called with no pending messages, and it was already |
113 // it.) | 123 // time to launch the reporter, then |launch_ready_notified_| will |
114 const int max_expected_launch_count = reporter_launch_count_ + 1; | 124 // already be true. Otherwise there will be a TryToRun message pending, |
115 for (int i = 0; !launch_ready_notified_ && i < 100; ++i) | 125 // which must be processed first. |
126 if (!launch_ready_notified_) { | |
127 task_runner_->RunPendingTasks(); | |
128 // Since we're expecting a launch here, we expect it to schedule | |
129 // LaunchAndWaitForExit. So NOW |launch_ready_notified_| should be | |
130 // true. | |
131 ASSERT_TRUE(task_runner_->HasPendingTask()); | |
132 } | |
133 ASSERT_TRUE(launch_ready_notified_); | |
134 ASSERT_EQ(current_launch_count, reporter_launch_count_); | |
135 | |
136 // Reset |launch_ready_notified_| so that we can tell if TryToRun gets | |
137 // called again unexpectedly. | |
138 launch_ready_notified_ = false; | |
139 | |
140 // Call the pending LaunchAndWaitForExit. | |
116 task_runner_->RunPendingTasks(); | 141 task_runner_->RunPendingTasks(); |
117 ASSERT_GE(max_expected_launch_count, reporter_launch_count_); | 142 ASSERT_FALSE(launch_ready_notified_); |
143 ASSERT_FALSE(reporter_done_notified_); | |
118 | 144 |
119 // Reset launch_ready_notified_ so that we can tell if TryToRun gets called | 145 // At this point LaunchAndWaitForExit has definitely been called if |
120 // again unexpectedly. | 146 // it's going to be called at all. (If not, TryToRun will have been |
121 launch_ready_notified_ = false; | 147 // scheduled again.) |
148 EXPECT_EQ(current_launch_count + 1, reporter_launch_count_); | |
149 EXPECT_EQ(expected_launch_path, | |
150 reporter_launch_parameters_.command_line.GetProgram()); | |
122 | 151 |
123 // This will trigger LaunchAndWaitForExit if it's on the queue and hasn't | 152 // Pump the UI message loop to process the ReporterDone call (which |
124 // been called already. If it was called already, this will do nothing. | 153 // will schedule the next TryToRun.) If LaunchAndWaitForExit wasn't |
125 // (There definitely isn't anything queued up yet after | 154 // called, this does nothing. |
126 // LaunchAndWaitForExit because ReporterDone wasn't called yet.) | 155 base::RunLoop().RunUntilIdle(); |
156 | |
157 // At this point there are three things that could have happened: | |
158 // | |
159 // 1. LaunchAndWaitForExit was not called. There should be a TryToRun | |
160 // scheduled. | |
161 // | |
162 // 2. ReporterDone was called and there was nothing left in the queue | |
163 // of SwReporterInvocation's. There should be a TryToRun scheduled. | |
164 // | |
165 // 3. ReporterDone was called and there were more | |
166 // SwReporterInvocation's in the queue to run immediately. There should | |
167 // be a LaunchAndWaitForExit scheduled. | |
168 // | |
169 // So in all cases there should be a pending task, and if we are expecting | |
170 // more launches in this loop, |launch_ready_notified_| will already be | |
171 // true. | |
172 ASSERT_TRUE(task_runner_->HasPendingTask()); | |
173 | |
174 // The test task runner does not actually advance the clock. Pretend that | |
175 // one day has passed. (Otherwise, when we launch the last | |
176 // SwReporterInvocation in the queue, the next call to TryToRun will | |
177 // start a whole new launch cycle.) | |
178 SetDaysSinceLastReport(1); | |
179 | |
180 reporter_done_notified_ = false; | |
181 current_launch_count = reporter_launch_count_; | |
182 } | |
183 } | |
184 | |
185 void TestReporterLaunchCycle( | |
186 const std::vector<base::FilePath>& expected_launch_paths) { | |
187 TestPartialLaunchCycle(expected_launch_paths); | |
188 | |
189 // Now that all expected launches have been tested, run the cycle once more | |
190 // to make sure no more launches happen. | |
191 ASSERT_TRUE(task_runner_->HasPendingTask()); | |
192 ASSERT_FALSE(reporter_done_notified_); | |
193 ASSERT_FALSE(launch_ready_notified_); | |
194 | |
195 int current_launch_count = reporter_launch_count_; | |
196 | |
197 // Call the pending TryToRun. | |
127 task_runner_->RunPendingTasks(); | 198 task_runner_->RunPendingTasks(); |
128 ASSERT_GE(max_expected_launch_count, reporter_launch_count_); | 199 |
200 // We expect that this scheduled another TryToRun. If it scheduled | |
201 // LaunchAndWaitForExit an unexpected launch is about to happen. | |
202 ASSERT_TRUE(task_runner_->HasPendingTask()); | |
129 ASSERT_FALSE(launch_ready_notified_); | 203 ASSERT_FALSE(launch_ready_notified_); |
130 ASSERT_FALSE(reporter_done_notified_); | 204 ASSERT_FALSE(reporter_done_notified_); |
131 | 205 ASSERT_EQ(current_launch_count, reporter_launch_count_); |
132 // At this point LaunchAndWaitForExit has definitely been called if it's | |
133 // going to be called at all. (If not, TryToRun will have been scheduled | |
134 // again.) | |
135 EXPECT_EQ(expected_launch_count, reporter_launch_count_); | |
136 EXPECT_EQ(expected_launch_path, | |
137 reporter_launch_parameters_.command_line.GetProgram()); | |
138 | |
139 // Pump the UI message loop to process the ReporterDone call (which will | |
140 // schedule the next TryToRun.) If LaunchAndWaitForExit wasn't called, this | |
141 // does nothing. | |
142 base::RunLoop().RunUntilIdle(); | |
143 | |
144 // At this point another call to TryToRun should be scheduled, whether or | |
145 // not LaunchAndWaitForExit was called. | |
146 ASSERT_TRUE(task_runner_->HasPendingTask()); | |
147 | |
148 // Make sure the flags are false for the next launch cycle test. | |
149 ASSERT_FALSE(launch_ready_notified_); | |
150 reporter_done_notified_ = false; | |
151 } | 206 } |
152 | 207 |
153 scoped_refptr<base::TestSimpleTaskRunner> task_runner_; | 208 scoped_refptr<base::TestSimpleTaskRunner> task_runner_; |
154 bool prompt_trigger_called_ = false; | 209 bool prompt_trigger_called_ = false; |
155 int reporter_launch_count_ = 0; | 210 int reporter_launch_count_ = 0; |
156 SwReporterInvocation reporter_launch_parameters_; | 211 SwReporterInvocation reporter_launch_parameters_; |
157 int exit_code_to_report_ = kReporterFailureExitCode; | 212 int exit_code_to_report_ = kReporterFailureExitCode; |
213 | |
214 // This will be set to true when a call to |LaunchAndWaitForExit| is next in | |
215 // the task queue. | |
158 bool launch_ready_notified_ = false; | 216 bool launch_ready_notified_ = false; |
217 | |
159 bool reporter_done_notified_ = false; | 218 bool reporter_done_notified_ = false; |
160 }; | 219 }; |
161 | 220 |
162 } // namespace | 221 } // namespace |
163 | 222 |
164 IN_PROC_BROWSER_TEST_F(SRTFetcherTest, NothingFound) { | 223 IN_PROC_BROWSER_TEST_F(SRTFetcherTest, NothingFound) { |
165 exit_code_to_report_ = kSwReporterNothingFound; | 224 exit_code_to_report_ = kSwReporterNothingFound; |
166 RunReporter(); | 225 RunReporter(); |
167 task_runner_->RunPendingTasks(); | 226 task_runner_->RunPendingTasks(); |
168 EXPECT_EQ(1, reporter_launch_count_); | 227 EXPECT_EQ(1, reporter_launch_count_); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
257 const base::FilePath path2(L"path2"); | 316 const base::FilePath path2(L"path2"); |
258 const base::FilePath path3(L"path3"); | 317 const base::FilePath path3(L"path3"); |
259 | 318 |
260 // Schedule path1 with a day left in the reporting period. | 319 // Schedule path1 with a day left in the reporting period. |
261 // The reporter should not launch. | 320 // The reporter should not launch. |
262 constexpr int kDaysLeft = 1; | 321 constexpr int kDaysLeft = 1; |
263 { | 322 { |
264 SCOPED_TRACE("N days left until next reporter run"); | 323 SCOPED_TRACE("N days left until next reporter run"); |
265 SetDaysSinceLastReport(kDaysBetweenSuccessfulSwReporterRuns - kDaysLeft); | 324 SetDaysSinceLastReport(kDaysBetweenSuccessfulSwReporterRuns - kDaysLeft); |
266 RunReporter(path1); | 325 RunReporter(path1); |
267 TestReporterLaunchCycle(0, base::FilePath()); | 326 TestReporterLaunchCycle({}); |
268 } | 327 } |
269 | 328 |
270 // Schedule path2 just as we enter the next reporting period. | 329 // Schedule path2 just as we enter the next reporting period. |
271 // Now the reporter should launch, just once, using path2. | 330 // Now the reporter should launch, just once, using path2. |
272 { | 331 { |
273 SCOPED_TRACE("Reporter runs now"); | 332 SCOPED_TRACE("Reporter runs now"); |
274 SetDaysSinceLastReport(kDaysBetweenSuccessfulSwReporterRuns); | 333 SetDaysSinceLastReport(kDaysBetweenSuccessfulSwReporterRuns); |
275 RunReporter(path2); | 334 RunReporter(path2); |
276 // Schedule it twice; it should only actually run once. | 335 // Schedule it twice; it should only actually run once. |
277 RunReporter(path2); | 336 RunReporter(path2); |
278 TestReporterLaunchCycle(1, path2); | 337 TestReporterLaunchCycle({path2}); |
279 } | 338 } |
280 | 339 |
281 // Schedule path3 before any more time has passed. | 340 // Schedule path3 before any more time has passed. |
282 // The reporter should not launch. | 341 // The reporter should not launch. |
283 { | 342 { |
284 SCOPED_TRACE("No more time passed"); | 343 SCOPED_TRACE("No more time passed"); |
344 SetDaysSinceLastReport(0); | |
285 RunReporter(path3); | 345 RunReporter(path3); |
286 TestReporterLaunchCycle(1, path2); | 346 TestReporterLaunchCycle({}); |
287 } | 347 } |
288 | 348 |
289 // Enter the next reporting period as path3 is still scheduled. | 349 // Enter the next reporting period as path3 is still scheduled. |
290 // Now the reporter should launch again using path3. (Tests that the | 350 // Now the reporter should launch again using path3. (Tests that the |
291 // parameters from the first launch aren't reused.) | 351 // parameters from the first launch aren't reused.) |
292 { | 352 { |
293 SCOPED_TRACE("Previous run still scheduled"); | 353 SCOPED_TRACE("Previous run still scheduled"); |
294 SetDaysSinceLastReport(kDaysBetweenSuccessfulSwReporterRuns); | 354 SetDaysSinceLastReport(kDaysBetweenSuccessfulSwReporterRuns); |
295 TestReporterLaunchCycle(2, path3); | 355 TestReporterLaunchCycle({path3}); |
296 } | 356 } |
297 | 357 |
298 // Schedule path3 again in the next reporting period. | 358 // Schedule path3 again in the next reporting period. |
299 // The reporter should launch again using path3, since enough time has | 359 // The reporter should launch again using path3, since enough time has |
300 // passed, even though the parameters haven't changed. | 360 // passed, even though the parameters haven't changed. |
301 { | 361 { |
302 SCOPED_TRACE("Run with same parameters"); | 362 SCOPED_TRACE("Run with same parameters"); |
303 SetDaysSinceLastReport(kDaysBetweenSuccessfulSwReporterRuns); | 363 SetDaysSinceLastReport(kDaysBetweenSuccessfulSwReporterRuns); |
304 RunReporter(path3); | 364 RunReporter(path3); |
305 TestReporterLaunchCycle(3, path3); | 365 TestReporterLaunchCycle({path3}); |
306 } | 366 } |
307 } | 367 } |
308 | 368 |
369 IN_PROC_BROWSER_TEST_F(SRTFetcherTest, MultipleLaunches) { | |
370 exit_code_to_report_ = kSwReporterNothingFound; | |
371 | |
372 const base::FilePath path1(L"path1"); | |
373 const base::FilePath path2(L"path2"); | |
374 const base::FilePath path3(L"path3"); | |
375 | |
376 SwReporterQueue invocations; | |
377 invocations.push(SwReporterInvocation::FromFilePath(path1)); | |
378 invocations.push(SwReporterInvocation::FromFilePath(path2)); | |
379 | |
380 { | |
381 SCOPED_TRACE("Launch 2 times"); | |
382 SetDaysSinceLastReport(kDaysBetweenSuccessfulSwReporterRuns); | |
383 RunReporterQueue(invocations); | |
384 TestReporterLaunchCycle({path1, path2}); | |
385 } | |
386 | |
387 // Schedule a launch with 2 elements, then another with the same 2. It should | |
388 // just run 2 times, not 4. | |
389 { | |
390 SCOPED_TRACE("Launch 2 times with retry"); | |
391 SetDaysSinceLastReport(kDaysBetweenSuccessfulSwReporterRuns); | |
392 RunReporterQueue(invocations); | |
393 RunReporterQueue(invocations); | |
394 TestReporterLaunchCycle({path1, path2}); | |
395 } | |
396 | |
397 // Schedule a launch with 2 elements, then add a third while the queue is | |
398 // running. | |
399 { | |
400 SCOPED_TRACE("Add third launch while running"); | |
401 SetDaysSinceLastReport(kDaysBetweenSuccessfulSwReporterRuns); | |
402 RunReporterQueue(invocations); | |
403 | |
404 // Only test the cycle once, to process the first element in queue. | |
405 TestPartialLaunchCycle({path1}); | |
406 | |
407 invocations.push(SwReporterInvocation::FromFilePath(path3)); | |
408 RunReporterQueue(invocations); | |
409 | |
410 // There is still a 2nd element on the queue - that should execute, and | |
411 // nothing more. | |
412 TestReporterLaunchCycle({path2}); | |
413 | |
414 // Time passes... Now the 3-element queue should run. | |
415 SetDaysSinceLastReport(kDaysBetweenSuccessfulSwReporterRuns); | |
416 TestReporterLaunchCycle({path1, path2, path3}); | |
417 } | |
418 | |
419 // Second launch should not occur after a failure. | |
420 { | |
421 SCOPED_TRACE("Launch multiple times with failure"); | |
422 exit_code_to_report_ = kReporterFailureExitCode; | |
423 SetDaysSinceLastReport(kDaysBetweenSuccessfulSwReporterRuns); | |
424 RunReporterQueue(invocations); | |
425 TestReporterLaunchCycle({path1}); | |
426 | |
427 // If we try again before the reporting period is up, it should not do | |
428 // anything. | |
429 TestReporterLaunchCycle({}); | |
430 | |
431 // After enough time has passed, should try the queue again. | |
432 SetDaysSinceLastReport(kDaysBetweenSuccessfulSwReporterRuns); | |
433 TestReporterLaunchCycle({path1}); | |
434 } | |
435 } | |
436 | |
309 } // namespace safe_browsing | 437 } // namespace safe_browsing |
OLD | NEW |