Commit 3299f75f authored by Wez's avatar Wez Committed by Commit Bot

Fix URLFetcherTest.SequencedTaskTest to run things on the Sequence.

This test previously used the WaitingURLFetcherDelegate helper's APIs
to run a RunLoop on the main thread, and wait for it to be quit by a
fetch completing on the Sequence. However, this violated the constraint
that the RunLoop may only be created, run and destroyed from the same
thread.

Bug: 729716
Change-Id: I4b699d17da7888527ef8d22f8e73a7f91236ef23
Reviewed-on: https://chromium-review.googlesource.com/1056265
Commit-Queue: Wez <wez@chromium.org>
Reviewed-by: default avatarMatt Menke <mmenke@chromium.org>
Cr-Commit-Position: refs/heads/master@{#558344}
parent 30dd04d5
...@@ -21,13 +21,14 @@ ...@@ -21,13 +21,14 @@
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
#include "base/path_service.h" #include "base/path_service.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/single_thread_task_runner.h" #include "base/sequenced_task_runner.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/synchronization/waitable_event.h" #include "base/synchronization/waitable_event.h"
#include "base/task_scheduler/post_task.h" #include "base/task_scheduler/post_task.h"
#include "base/test/test_timeouts.h" #include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h" #include "base/threading/platform_thread.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/threading/thread.h" #include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h" #include "build/build_config.h"
...@@ -91,6 +92,10 @@ class WaitingURLFetcherDelegate : public URLFetcherDelegate { ...@@ -91,6 +92,10 @@ class WaitingURLFetcherDelegate : public URLFetcherDelegate {
const GURL& url, const GURL& url,
URLFetcher::RequestType request_type, URLFetcher::RequestType request_type,
scoped_refptr<net::URLRequestContextGetter> context_getter) { scoped_refptr<net::URLRequestContextGetter> context_getter) {
if (!on_complete_or_cancel_) {
run_loop_ = std::make_unique<base::RunLoop>();
on_complete_or_cancel_ = run_loop_->QuitClosure();
}
fetcher_.reset(new URLFetcherImpl(url, request_type, this, fetcher_.reset(new URLFetcherImpl(url, request_type, this,
TRAFFIC_ANNOTATION_FOR_TESTS)); TRAFFIC_ANNOTATION_FOR_TESTS));
fetcher_->SetRequestContext(context_getter.get()); fetcher_->SetRequestContext(context_getter.get());
...@@ -107,15 +112,15 @@ class WaitingURLFetcherDelegate : public URLFetcherDelegate { ...@@ -107,15 +112,15 @@ class WaitingURLFetcherDelegate : public URLFetcherDelegate {
// Wait until the request has completed or been canceled. Does not start the // Wait until the request has completed or been canceled. Does not start the
// request. // request.
void WaitForComplete() { void WaitForComplete() {
EXPECT_TRUE(task_runner_->BelongsToCurrentThread()); EXPECT_TRUE(task_runner_->RunsTasksInCurrentSequence());
run_loop_.Run(); run_loop_->Run();
} }
// Cancels the fetch by deleting the fetcher. // Cancels the fetch by deleting the fetcher.
void CancelFetch() { void CancelFetch() {
EXPECT_TRUE(fetcher_); EXPECT_TRUE(fetcher_);
fetcher_.reset(); fetcher_.reset();
task_runner_->PostTask(FROM_HERE, run_loop_.QuitClosure()); std::move(on_complete_or_cancel_).Run();
} }
// URLFetcherDelegate: // URLFetcherDelegate:
...@@ -124,7 +129,7 @@ class WaitingURLFetcherDelegate : public URLFetcherDelegate { ...@@ -124,7 +129,7 @@ class WaitingURLFetcherDelegate : public URLFetcherDelegate {
EXPECT_TRUE(fetcher_); EXPECT_TRUE(fetcher_);
EXPECT_EQ(fetcher_.get(), source); EXPECT_EQ(fetcher_.get(), source);
did_complete_ = true; did_complete_ = true;
task_runner_->PostTask(FROM_HERE, run_loop_.QuitClosure()); std::move(on_complete_or_cancel_).Run();
} }
void OnURLFetchDownloadProgress(const URLFetcher* source, void OnURLFetchDownloadProgress(const URLFetcher* source,
...@@ -160,13 +165,18 @@ class WaitingURLFetcherDelegate : public URLFetcherDelegate { ...@@ -160,13 +165,18 @@ class WaitingURLFetcherDelegate : public URLFetcherDelegate {
bool did_complete() const { return did_complete_; } bool did_complete() const { return did_complete_; }
void set_on_complete_or_cancel_closure(base::OnceClosure closure) {
on_complete_or_cancel_ = std::move(closure);
}
private: private:
bool did_complete_; bool did_complete_;
std::unique_ptr<URLFetcherImpl> fetcher_; std::unique_ptr<URLFetcherImpl> fetcher_;
const scoped_refptr<base::SingleThreadTaskRunner> task_runner_ = const scoped_refptr<base::SequencedTaskRunner> task_runner_ =
base::ThreadTaskRunnerHandle::Get(); base::SequencedTaskRunnerHandle::Get();
base::RunLoop run_loop_; std::unique_ptr<base::RunLoop> run_loop_;
base::OnceClosure on_complete_or_cancel_;
DISALLOW_COPY_AND_ASSIGN(WaitingURLFetcherDelegate); DISALLOW_COPY_AND_ASSIGN(WaitingURLFetcherDelegate);
}; };
...@@ -210,9 +220,8 @@ class FetcherTestURLRequestContextGetter : public URLRequestContextGetter { ...@@ -210,9 +220,8 @@ class FetcherTestURLRequestContextGetter : public URLRequestContextGetter {
shutting_down_(false) {} shutting_down_(false) {}
// Sets callback to be invoked when the getter is destroyed. // Sets callback to be invoked when the getter is destroyed.
void set_on_destruction_callback( void set_on_destruction_callback(base::OnceClosure on_destruction_callback) {
const base::Closure& on_destruction_callback) { on_destruction_callback_ = std::move(on_destruction_callback);
on_destruction_callback_ = on_destruction_callback;
} }
// URLRequestContextGetter: // URLRequestContextGetter:
...@@ -310,7 +319,7 @@ class FetcherTestURLRequestContextGetter : public URLRequestContextGetter { ...@@ -310,7 +319,7 @@ class FetcherTestURLRequestContextGetter : public URLRequestContextGetter {
// the parent class already ensures it's deleted on the network thread. // the parent class already ensures it's deleted on the network thread.
DCHECK(network_task_runner_->BelongsToCurrentThread()); DCHECK(network_task_runner_->BelongsToCurrentThread());
if (!on_destruction_callback_.is_null()) if (!on_destruction_callback_.is_null())
on_destruction_callback_.Run(); std::move(on_destruction_callback_).Run();
} }
private: private:
...@@ -323,7 +332,7 @@ class FetcherTestURLRequestContextGetter : public URLRequestContextGetter { ...@@ -323,7 +332,7 @@ class FetcherTestURLRequestContextGetter : public URLRequestContextGetter {
std::unique_ptr<FetcherTestURLRequestContext> context_; std::unique_ptr<FetcherTestURLRequestContext> context_;
bool shutting_down_; bool shutting_down_;
base::Closure on_destruction_callback_; base::OnceClosure on_destruction_callback_;
DISALLOW_COPY_AND_ASSIGN(FetcherTestURLRequestContextGetter); DISALLOW_COPY_AND_ASSIGN(FetcherTestURLRequestContextGetter);
}; };
...@@ -398,12 +407,12 @@ class URLFetcherTest : public TestWithScopedTaskEnvironment { ...@@ -398,12 +407,12 @@ class URLFetcherTest : public TestWithScopedTaskEnvironment {
URLFetcher::GET, CreateSameThreadContextGetter()); URLFetcher::GET, CreateSameThreadContextGetter());
if (save_to_temporary_file) { if (save_to_temporary_file) {
delegate->fetcher()->SaveResponseToTemporaryFile( delegate->fetcher()->SaveResponseToTemporaryFile(
scoped_refptr<base::SingleThreadTaskRunner>( scoped_refptr<base::SequencedTaskRunner>(
base::ThreadTaskRunnerHandle::Get())); base::SequencedTaskRunnerHandle::Get()));
} else { } else {
delegate->fetcher()->SaveResponseToFileAtPath( delegate->fetcher()->SaveResponseToFileAtPath(
requested_out_path, scoped_refptr<base::SingleThreadTaskRunner>( requested_out_path, scoped_refptr<base::SequencedTaskRunner>(
base::ThreadTaskRunnerHandle::Get())); base::SequencedTaskRunnerHandle::Get()));
} }
delegate->StartFetcherAndWait(); delegate->StartFetcherAndWait();
...@@ -559,26 +568,48 @@ TEST_F(URLFetcherTest, DifferentThreadsTest) { ...@@ -559,26 +568,48 @@ TEST_F(URLFetcherTest, DifferentThreadsTest) {
EXPECT_EQ(kDefaultResponseBody, data); EXPECT_EQ(kDefaultResponseBody, data);
} }
// Create the fetcher from a sequenced (not single-threaded) task. Verify that // Verifies that a URLFetcher works correctly on a TaskScheduler Sequence.
// the expected response is received.
TEST_F(URLFetcherTest, SequencedTaskTest) { TEST_F(URLFetcherTest, SequencedTaskTest) {
auto sequenced_task_runner = base::CreateSequencedTaskRunnerWithTraits({}); auto sequenced_task_runner = base::CreateSequencedTaskRunnerWithTraits({});
auto delegate = std::make_unique<WaitingURLFetcherDelegate>();
sequenced_task_runner->PostTask(
FROM_HERE, base::Bind(&WaitingURLFetcherDelegate::CreateFetcher,
base::Unretained(delegate.get()),
test_server_->GetURL(kDefaultResponsePath),
URLFetcher::GET, CreateCrossThreadContextGetter()));
RunUntilIdle();
delegate->StartFetcherAndWait();
EXPECT_TRUE(delegate->fetcher()->GetStatus().is_success()); // Since we cannot use StartFetchAndWait(), which runs a nested RunLoop owned
EXPECT_EQ(200, delegate->fetcher()->GetResponseCode()); // by the Delegate, on a SchedulerWorker Sequence, this test is split into
std::string data; // two Callbacks, both run on |sequenced_task_runner_|. The test main thread
ASSERT_TRUE(delegate->fetcher()->GetResponseAsString(&data)); // then runs its own RunLoop, which the second of the Callbacks will quit.
EXPECT_EQ(kDefaultResponseBody, data); base::RunLoop run_loop;
sequenced_task_runner->DeleteSoon(FROM_HERE, delegate.release()); // Actually start the test fetch, on the Sequence.
sequenced_task_runner->PostTask(
FROM_HERE,
base::BindOnce(
[](scoped_refptr<FetcherTestURLRequestContextGetter> context_getter,
const GURL& response_path, base::OnceClosure quit_closure) {
std::unique_ptr<WaitingURLFetcherDelegate> delegate =
std::make_unique<WaitingURLFetcherDelegate>();
WaitingURLFetcherDelegate* raw_delegate = delegate.get();
// Configure the delegate to run our |on_complete_closure_| rather
// than quitting its own |run_loop_|, on completion.
raw_delegate->set_on_complete_or_cancel_closure(base::BindOnce(
[](base::OnceClosure quit_closure,
std::unique_ptr<WaitingURLFetcherDelegate> delegate) {
EXPECT_TRUE(delegate->fetcher()->GetStatus().is_success());
EXPECT_EQ(200, delegate->fetcher()->GetResponseCode());
std::string data;
ASSERT_TRUE(delegate->fetcher()->GetResponseAsString(&data));
EXPECT_EQ(kDefaultResponseBody, data);
std::move(quit_closure).Run();
},
base::Passed(&quit_closure), base::Passed(&delegate)));
raw_delegate->CreateFetcher(response_path, URLFetcher::GET,
context_getter);
raw_delegate->fetcher()->Start();
},
CreateCrossThreadContextGetter(),
test_server_->GetURL(kDefaultResponsePath), run_loop.QuitClosure()));
run_loop.Run();
RunUntilIdle(); RunUntilIdle();
} }
...@@ -780,7 +811,7 @@ TEST_F(URLFetcherTest, PostEntireFile) { ...@@ -780,7 +811,7 @@ TEST_F(URLFetcherTest, PostEntireFile) {
delegate.fetcher()->SetUploadFilePath("application/x-www-form-urlencoded", delegate.fetcher()->SetUploadFilePath("application/x-www-form-urlencoded",
upload_path, 0, upload_path, 0,
std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::max(),
base::ThreadTaskRunnerHandle::Get()); base::SequencedTaskRunnerHandle::Get());
delegate.StartFetcherAndWait(); delegate.StartFetcherAndWait();
EXPECT_TRUE(delegate.fetcher()->GetStatus().is_success()); EXPECT_TRUE(delegate.fetcher()->GetStatus().is_success());
...@@ -803,7 +834,7 @@ TEST_F(URLFetcherTest, PostFileRange) { ...@@ -803,7 +834,7 @@ TEST_F(URLFetcherTest, PostFileRange) {
CreateSameThreadContextGetter()); CreateSameThreadContextGetter());
delegate.fetcher()->SetUploadFilePath("application/x-www-form-urlencoded", delegate.fetcher()->SetUploadFilePath("application/x-www-form-urlencoded",
upload_path, kRangeStart, kRangeLength, upload_path, kRangeStart, kRangeLength,
base::ThreadTaskRunnerHandle::Get()); base::SequencedTaskRunnerHandle::Get());
delegate.StartFetcherAndWait(); delegate.StartFetcherAndWait();
EXPECT_TRUE(delegate.fetcher()->GetStatus().is_success()); EXPECT_TRUE(delegate.fetcher()->GetStatus().is_success());
...@@ -1326,14 +1357,15 @@ TEST_F(URLFetcherTest, CancelSameThread) { ...@@ -1326,14 +1357,15 @@ TEST_F(URLFetcherTest, CancelSameThread) {
// Make sure that the URLFetcher releases its context getter pointer on // Make sure that the URLFetcher releases its context getter pointer on
// cancellation, cross-thread case. // cancellation, cross-thread case.
TEST_F(URLFetcherTest, CancelDifferentThreads) { TEST_F(URLFetcherTest, CancelDifferentThreads) {
base::RunLoop run_loop_; base::RunLoop run_loop;
WaitingURLFetcherDelegate delegate; WaitingURLFetcherDelegate delegate;
scoped_refptr<FetcherTestURLRequestContextGetter> context_getter( scoped_refptr<FetcherTestURLRequestContextGetter> context_getter(
CreateCrossThreadContextGetter()); CreateCrossThreadContextGetter());
context_getter->set_on_destruction_callback(base::Bind( context_getter->set_on_destruction_callback(
base::IgnoreResult(&base::SingleThreadTaskRunner::PostTask), base::BindOnce(base::IgnoreResult(&base::SequencedTaskRunner::PostTask),
base::ThreadTaskRunnerHandle::Get(), FROM_HERE, run_loop_.QuitClosure())); base::SequencedTaskRunnerHandle::Get(), FROM_HERE,
run_loop.QuitClosure()));
delegate.CreateFetcher(hanging_url(), URLFetcher::GET, context_getter); delegate.CreateFetcher(hanging_url(), URLFetcher::GET, context_getter);
// The getter won't be destroyed if the test holds on to a reference to it. // The getter won't be destroyed if the test holds on to a reference to it.
...@@ -1341,21 +1373,22 @@ TEST_F(URLFetcherTest, CancelDifferentThreads) { ...@@ -1341,21 +1373,22 @@ TEST_F(URLFetcherTest, CancelDifferentThreads) {
delegate.fetcher()->Start(); delegate.fetcher()->Start();
delegate.CancelFetch(); delegate.CancelFetch();
run_loop_.Run(); run_loop.Run();
EXPECT_FALSE(delegate.did_complete()); EXPECT_FALSE(delegate.did_complete());
} }
TEST_F(URLFetcherTest, CancelWhileDelayedByThrottleDifferentThreads) { TEST_F(URLFetcherTest, CancelWhileDelayedByThrottleDifferentThreads) {
GURL url = test_server_->GetURL(kDefaultResponsePath); GURL url = test_server_->GetURL(kDefaultResponsePath);
base::RunLoop run_loop_; base::RunLoop run_loop;
WaitingURLFetcherDelegate delegate; WaitingURLFetcherDelegate delegate;
scoped_refptr<FetcherTestURLRequestContextGetter> context_getter( scoped_refptr<FetcherTestURLRequestContextGetter> context_getter(
CreateCrossThreadContextGetter()); CreateCrossThreadContextGetter());
context_getter->set_on_destruction_callback(base::Bind( context_getter->set_on_destruction_callback(
base::IgnoreResult(&base::SingleThreadTaskRunner::PostTask), base::BindOnce(base::IgnoreResult(&base::SequencedTaskRunner::PostTask),
base::ThreadTaskRunnerHandle::Get(), FROM_HERE, run_loop_.QuitClosure())); base::SequencedTaskRunnerHandle::Get(), FROM_HERE,
run_loop.QuitClosure()));
delegate.CreateFetcher(url, URLFetcher::GET, context_getter); delegate.CreateFetcher(url, URLFetcher::GET, context_getter);
// Register an entry for test url using a sliding window of 400 seconds, and // Register an entry for test url using a sliding window of 400 seconds, and
...@@ -1373,7 +1406,7 @@ TEST_F(URLFetcherTest, CancelWhileDelayedByThrottleDifferentThreads) { ...@@ -1373,7 +1406,7 @@ TEST_F(URLFetcherTest, CancelWhileDelayedByThrottleDifferentThreads) {
delegate.fetcher()->Start(); delegate.fetcher()->Start();
delegate.CancelFetch(); delegate.CancelFetch();
run_loop_.Run(); run_loop.Run();
EXPECT_FALSE(delegate.did_complete()); EXPECT_FALSE(delegate.did_complete());
} }
...@@ -1568,8 +1601,8 @@ TEST_F(URLFetcherTest, FileTestTryToOverwriteDirectory) { ...@@ -1568,8 +1601,8 @@ TEST_F(URLFetcherTest, FileTestTryToOverwriteDirectory) {
test_server_->GetURL(std::string(kTestServerFilePrefix) + kFileToFetch), test_server_->GetURL(std::string(kTestServerFilePrefix) + kFileToFetch),
URLFetcher::GET, CreateSameThreadContextGetter()); URLFetcher::GET, CreateSameThreadContextGetter());
delegate.fetcher()->SaveResponseToFileAtPath( delegate.fetcher()->SaveResponseToFileAtPath(
out_path, scoped_refptr<base::SingleThreadTaskRunner>( out_path, scoped_refptr<base::SequencedTaskRunner>(
base::ThreadTaskRunnerHandle::Get())); base::SequencedTaskRunnerHandle::Get()));
delegate.StartFetcherAndWait(); delegate.StartFetcherAndWait();
EXPECT_FALSE(delegate.fetcher()->GetStatus().is_success()); EXPECT_FALSE(delegate.fetcher()->GetStatus().is_success());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment