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