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