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 // 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 |