Chromium Code Reviews| 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 |