Index: chrome/browser/safe_browsing/srt_fetcher_browsertest_win.cc |
diff --git a/chrome/browser/safe_browsing/srt_fetcher_browsertest_win.cc b/chrome/browser/safe_browsing/srt_fetcher_browsertest_win.cc |
index e77870481184d9455df698b491d7641195865259..01b6ce5f0ced083703e2d592f4266ce08e2df4ec 100644 |
--- a/chrome/browser/safe_browsing/srt_fetcher_browsertest_win.cc |
+++ b/chrome/browser/safe_browsing/srt_fetcher_browsertest_win.cc |
@@ -38,8 +38,15 @@ class SRTFetcherTest : public InProcessBrowserTest, |
} |
void RunReporter(const base::FilePath& exe_path = base::FilePath()) { |
- RunSwReporter(SwReporterInvocation::FromFilePath(exe_path), |
- base::Version("1.2.3"), task_runner_, task_runner_); |
+ SwReporterQueue invocations; |
+ invocations.push(SwReporterInvocation::FromFilePath(exe_path)); |
+ RunSwReporters(invocations, base::Version("1.2.3"), task_runner_, |
+ task_runner_); |
+ } |
+ |
+ void RunReporterQueue(const SwReporterQueue& invocations) { |
+ RunSwReporters(invocations, base::Version("1.2.3"), task_runner_, |
+ task_runner_); |
} |
void TriggerPrompt(Browser* browser, const std::string& version) override { |
@@ -71,8 +78,12 @@ class SRTFetcherTest : public InProcessBrowserTest, |
base::TimeDelta::FromDays(days) - base::TimeDelta::FromHours(1)); |
} |
- void TestReporterLaunchCycle(int expected_launch_count, |
- const base::FilePath& expected_launch_path) { |
+ void TestReporterLaunchCycle( |
+ const std::vector<base::FilePath>& expected_launch_paths, |
+ 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.
|
+ reporter_launch_count_ = 0; |
+ reporter_launch_parameters_ = SwReporterInvocation(); |
+ |
// This test has an unfortunate amount of knowledge of the internals of |
// ReporterRunner, because it needs to pump the right message loops at the |
// right time so that all its internal messages are delivered. This |
@@ -107,47 +118,87 @@ class SRTFetcherTest : public InProcessBrowserTest, |
ASSERT_TRUE(task_runner_->HasPendingTask()); |
ASSERT_FALSE(reporter_done_notified_); |
- // Clear out any pending TryToRun calls. Use a bounded loop so that if the |
- // reporter will never be called, we'll eventually continue. (If |
- // LaunchAndWaitForExit was pending but TryToRun wasn't, this will call |
- // it.) |
- const int max_expected_launch_count = reporter_launch_count_ + 1; |
- for (int i = 0; !launch_ready_notified_ && i < 100; ++i) |
+ int current_launch_count = reporter_launch_count_; |
+ for (const auto& expected_launch_path : expected_launch_paths) { |
+ // If RunReporter was called with no pending messages, and it was already |
+ // time to launch the reporter, then |launch_ready_notified_| will |
+ // already be true. Otherwise there will be a TryToRun message pending, |
+ // which must be processed first. |
+ if (!launch_ready_notified_) { |
+ task_runner_->RunPendingTasks(); |
+ // Since we're expecting a launch here, we expect it to schedule |
+ // LaunchAndWaitForExit. So NOW |launch_ready_notified_| should be |
+ // true. |
+ ASSERT_TRUE(task_runner_->HasPendingTask()); |
+ } |
+ ASSERT_TRUE(launch_ready_notified_); |
+ ASSERT_EQ(current_launch_count, reporter_launch_count_); |
+ |
+ // Reset |launch_ready_notified_| so that we can tell if TryToRun gets |
+ // called again unexpectedly. |
+ launch_ready_notified_ = false; |
+ |
+ // Call the pending LaunchAndWaitForExit. |
+ task_runner_->RunPendingTasks(); |
+ ASSERT_FALSE(launch_ready_notified_); |
+ ASSERT_FALSE(reporter_done_notified_); |
+ |
+ // At this point LaunchAndWaitForExit has definitely been called if |
+ // it's going to be called at all. (If not, TryToRun will have been |
+ // scheduled again.) |
+ EXPECT_EQ(current_launch_count + 1, reporter_launch_count_); |
+ EXPECT_EQ(expected_launch_path, |
+ reporter_launch_parameters_.command_line.GetProgram()); |
+ |
+ // Pump the UI message loop to process the ReporterDone call (which |
+ // will schedule the next TryToRun.) If LaunchAndWaitForExit wasn't |
+ // called, this does nothing. |
+ base::RunLoop().RunUntilIdle(); |
+ |
+ // At this point there are three things that could have happened: |
+ // |
+ // 1. LaunchAndWaitForExit was not called. There should be a TryToRun |
+ // scheduled. |
+ // |
+ // 2. ReporterDone was called and there was nothing left in the queue |
+ // of SwReporterInvocation's. There should be a TryToRun scheduled. |
+ // |
+ // 3. ReporterDone was called and there were more |
+ // SwReporterInvocation's in the queue to run immediately. There should |
+ // be a LaunchAndWaitForExit scheduled. |
+ // |
+ // So in all cases there should be a pending task, and if we are expecting |
+ // more launches in this loop, |launch_ready_notified_| will already be |
+ // true. |
+ ASSERT_TRUE(task_runner_->HasPendingTask()); |
+ |
+ // The test task runner does not actually advance the clock. Pretend that |
+ // one day has passed. (Otherwise, when we launch the last |
+ // SwReporterInvocation in the queue, the next call to TryToRun will |
+ // start a whole new launch cycle.) |
+ SetDaysSinceLastReport(1); |
+ |
+ reporter_done_notified_ = false; |
+ current_launch_count = reporter_launch_count_; |
+ } |
+ |
+ // Now that all expected launches have been tested, run the cycle once more |
+ // to make sure no more launches happen. |
+ if (test_if_cycle_complete) { |
+ ASSERT_TRUE(task_runner_->HasPendingTask()); |
+ ASSERT_FALSE(reporter_done_notified_); |
+ ASSERT_FALSE(launch_ready_notified_); |
+ |
+ // Call the pending TryToRun. |
task_runner_->RunPendingTasks(); |
- ASSERT_GE(max_expected_launch_count, reporter_launch_count_); |
- |
- // Reset launch_ready_notified_ so that we can tell if TryToRun gets called |
- // again unexpectedly. |
- launch_ready_notified_ = false; |
- |
- // This will trigger LaunchAndWaitForExit if it's on the queue and hasn't |
- // been called already. If it was called already, this will do nothing. |
- // (There definitely isn't anything queued up yet after |
- // LaunchAndWaitForExit because ReporterDone wasn't called yet.) |
- task_runner_->RunPendingTasks(); |
- ASSERT_GE(max_expected_launch_count, reporter_launch_count_); |
- ASSERT_FALSE(launch_ready_notified_); |
- ASSERT_FALSE(reporter_done_notified_); |
- |
- // At this point LaunchAndWaitForExit has definitely been called if it's |
- // going to be called at all. (If not, TryToRun will have been scheduled |
- // again.) |
- EXPECT_EQ(expected_launch_count, reporter_launch_count_); |
- EXPECT_EQ(expected_launch_path, |
- reporter_launch_parameters_.command_line.GetProgram()); |
- |
- // Pump the UI message loop to process the ReporterDone call (which will |
- // schedule the next TryToRun.) If LaunchAndWaitForExit wasn't called, this |
- // does nothing. |
- base::RunLoop().RunUntilIdle(); |
- |
- // At this point another call to TryToRun should be scheduled, whether or |
- // not LaunchAndWaitForExit was called. |
- ASSERT_TRUE(task_runner_->HasPendingTask()); |
- // Make sure the flags are false for the next launch cycle test. |
- ASSERT_FALSE(launch_ready_notified_); |
- reporter_done_notified_ = false; |
+ // We expect that this scheduled another TryToRun. If it scheduled |
+ // LaunchAndWaitForExit an unexpected launch is about to happen. |
+ ASSERT_TRUE(task_runner_->HasPendingTask()); |
+ ASSERT_FALSE(launch_ready_notified_); |
+ ASSERT_FALSE(reporter_done_notified_); |
+ ASSERT_EQ(current_launch_count, reporter_launch_count_); |
+ } |
} |
scoped_refptr<base::TestSimpleTaskRunner> task_runner_; |
@@ -155,7 +206,11 @@ class SRTFetcherTest : public InProcessBrowserTest, |
int reporter_launch_count_ = 0; |
SwReporterInvocation reporter_launch_parameters_; |
int exit_code_to_report_ = kReporterFailureExitCode; |
+ |
+ // This will be set to true when a call to |LaunchAndWaitForExit| is next in |
+ // the task queue. |
bool launch_ready_notified_ = false; |
+ |
bool reporter_done_notified_ = false; |
}; |
@@ -264,7 +319,7 @@ IN_PROC_BROWSER_TEST_F(SRTFetcherTest, ParameterChange) { |
SCOPED_TRACE("N days left until next reporter run"); |
SetDaysSinceLastReport(kDaysBetweenSuccessfulSwReporterRuns - kDaysLeft); |
RunReporter(path1); |
- TestReporterLaunchCycle(0, base::FilePath()); |
+ TestReporterLaunchCycle({}); |
} |
// Schedule path2 just as we enter the next reporting period. |
@@ -275,15 +330,16 @@ IN_PROC_BROWSER_TEST_F(SRTFetcherTest, ParameterChange) { |
RunReporter(path2); |
// Schedule it twice; it should only actually run once. |
RunReporter(path2); |
- TestReporterLaunchCycle(1, path2); |
+ TestReporterLaunchCycle({path2}); |
} |
// Schedule path3 before any more time has passed. |
// The reporter should not launch. |
{ |
SCOPED_TRACE("No more time passed"); |
+ SetDaysSinceLastReport(0); |
RunReporter(path3); |
- TestReporterLaunchCycle(1, path2); |
+ TestReporterLaunchCycle({}); |
} |
// Enter the next reporting period as path3 is still scheduled. |
@@ -292,7 +348,7 @@ IN_PROC_BROWSER_TEST_F(SRTFetcherTest, ParameterChange) { |
{ |
SCOPED_TRACE("Previous run still scheduled"); |
SetDaysSinceLastReport(kDaysBetweenSuccessfulSwReporterRuns); |
- TestReporterLaunchCycle(2, path3); |
+ TestReporterLaunchCycle({path3}); |
} |
// Schedule path3 again in the next reporting period. |
@@ -302,8 +358,82 @@ IN_PROC_BROWSER_TEST_F(SRTFetcherTest, ParameterChange) { |
SCOPED_TRACE("Run with same parameters"); |
SetDaysSinceLastReport(kDaysBetweenSuccessfulSwReporterRuns); |
RunReporter(path3); |
- TestReporterLaunchCycle(3, path3); |
+ TestReporterLaunchCycle({path3}); |
+ } |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(SRTFetcherTest, MultipleLaunches) { |
+ exit_code_to_report_ = kSwReporterNothingFound; |
+ |
+ const base::FilePath path1(L"path1"); |
+ const base::FilePath path2(L"path2"); |
+ const base::FilePath path3(L"path3"); |
+ |
+ SwReporterQueue invocations; |
+ invocations.push(SwReporterInvocation::FromFilePath(path1)); |
+ invocations.push(SwReporterInvocation::FromFilePath(path2)); |
+ |
+ { |
+ SCOPED_TRACE("Launch 2 times"); |
+ SetDaysSinceLastReport(kDaysBetweenSuccessfulSwReporterRuns); |
+ RunReporterQueue(invocations); |
+ TestReporterLaunchCycle({path1, path2}); |
} |
+ |
+ // Schedule a launch with 2 elements, then another with the same 2. It should |
+ // just run 2 times, not 4. |
+ { |
+ SCOPED_TRACE("Launch 2 times with retry"); |
+ SetDaysSinceLastReport(kDaysBetweenSuccessfulSwReporterRuns); |
+ RunReporterQueue(invocations); |
+ RunReporterQueue(invocations); |
+ TestReporterLaunchCycle({path1, path2}); |
+ } |
+ |
+ // Schedule a launch with 2 elements, then add a third while the queue is |
+ // running. |
+ { |
+ SCOPED_TRACE("Add third launch while running"); |
+ SetDaysSinceLastReport(kDaysBetweenSuccessfulSwReporterRuns); |
+ RunReporterQueue(invocations); |
+ TestReporterLaunchCycle({path1}, false /*test_if_cycle_complete*/); |
+ |
+ invocations.push(SwReporterInvocation::FromFilePath(path3)); |
+ RunReporterQueue(invocations); |
+ |
+ // There is still a 2nd element on the queue - that should execute, and |
+ // nothing more. |
+ TestReporterLaunchCycle({path2}); |
+ |
+ // Time passes... Now the 3-element queue should run. |
+ SetDaysSinceLastReport(kDaysBetweenSuccessfulSwReporterRuns); |
+ TestReporterLaunchCycle({path1, path2, path3}); |
+ } |
+ |
+ // Second launch should not occur after a failure. |
+ { |
+ SCOPED_TRACE("Launch multiple times with failure"); |
+ exit_code_to_report_ = kReporterFailureExitCode; |
+ SetDaysSinceLastReport(kDaysBetweenSuccessfulSwReporterRuns); |
+ RunReporterQueue(invocations); |
+ TestReporterLaunchCycle({path1}); |
+ |
+ // If we try again before the reporting period is up, it should not do |
+ // anything. |
+ TestReporterLaunchCycle({}); |
+ |
+ // After enough time has passed, should try the queue again. |
+ SetDaysSinceLastReport(kDaysBetweenSuccessfulSwReporterRuns); |
+ TestReporterLaunchCycle({path1}); |
+ } |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(SRTFetcherTest, EmptyQueue) { |
+ exit_code_to_report_ = kSwReporterNothingFound; |
+ SetDaysSinceLastReport(kDaysBetweenSuccessfulSwReporterRuns); |
+ SwReporterQueue invocations; |
+ RunReporterQueue(invocations); |
+ TestReporterLaunchCycle({}); |
} |
} // namespace safe_browsing |