Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(781)

Unified Diff: net/proxy/single_threaded_proxy_resolver_unittest.cc

Issue 149525: Remove the concept of threading from ProxyService, and move it into the Proxy... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Add missing header for mac Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/proxy/single_threaded_proxy_resolver.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/proxy/single_threaded_proxy_resolver_unittest.cc
===================================================================
--- net/proxy/single_threaded_proxy_resolver_unittest.cc (revision 0)
+++ net/proxy/single_threaded_proxy_resolver_unittest.cc (revision 0)
@@ -0,0 +1,313 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/waitable_event.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/net_errors.h"
+#include "net/base/test_completion_callback.h"
+#include "net/proxy/proxy_info.h"
+#include "net/proxy/single_threaded_proxy_resolver.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace {
+
+// A synchronous mock ProxyResolver implementation, which can be used in
+// conjunction with SingleThreadedProxyResolver.
+// - returns a single-item proxy list with the query's host.
+class MockProxyResolver : public ProxyResolver {
+ public:
+ MockProxyResolver()
+ : ProxyResolver(true /*expects_pac_bytes*/),
+ wrong_loop_(MessageLoop::current()),
+ request_count_(0),
+ resolve_latency_ms_(0) {}
+
+ // ProxyResolver implementation:
+ virtual int GetProxyForURL(const GURL& query_url,
+ ProxyInfo* results,
+ CompletionCallback* callback,
+ RequestHandle* request) {
+ if (resolve_latency_ms_)
+ PlatformThread::Sleep(resolve_latency_ms_);
+
+ CheckIsOnWorkerThread();
+
+ EXPECT_EQ(NULL, callback);
+ EXPECT_EQ(NULL, request);
+
+ results->UseNamedProxy(query_url.host());
+
+ // Return a success code which represents the request's order.
+ return request_count_++;
+ }
+
+ virtual void CancelRequest(RequestHandle request) {
+ NOTREACHED();
+ }
+
+ virtual void SetPacScriptByDataInternal(const std::string& bytes) {
+ CheckIsOnWorkerThread();
+ last_pac_bytes_ = bytes;
+ }
+
+ const std::string& last_pac_bytes() const { return last_pac_bytes_; }
+
+ void SetResolveLatency(int latency_ms) {
+ resolve_latency_ms_ = latency_ms;
+ }
+
+ private:
+ void CheckIsOnWorkerThread() {
+ // We should be running on the worker thread -- while we don't know the
+ // message loop of SingleThreadedProxyResolver's worker thread, we do
+ // know that it is going to be distinct from the loop running the
+ // test, so at least make sure it isn't the main loop.
+ EXPECT_NE(MessageLoop::current(), wrong_loop_);
+ }
+
+ MessageLoop* wrong_loop_;
+ int request_count_;
+ std::string last_pac_bytes_;
+ int resolve_latency_ms_;
+};
+
+
+// A mock synchronous ProxyResolver which can be set to block upon reaching
+// GetProxyForURL().
+class BlockableProxyResolver : public MockProxyResolver {
+ public:
+ BlockableProxyResolver()
+ : should_block_(false),
+ unblocked_(true, true),
+ blocked_(true, false) {
+ }
+
+ void Block() {
+ should_block_ = true;
+ unblocked_.Reset();
+ }
+
+ void Unblock() {
+ should_block_ = false;
+ blocked_.Reset();
+ unblocked_.Signal();
+ }
+
+ void WaitUntilBlocked() {
+ blocked_.Wait();
+ }
+
+ virtual int GetProxyForURL(const GURL& query_url,
+ ProxyInfo* results,
+ CompletionCallback* callback,
+ RequestHandle* request) {
+ if (should_block_) {
+ blocked_.Signal();
+ unblocked_.Wait();
+ }
+
+ return MockProxyResolver::GetProxyForURL(
+ query_url, results, callback, request);
+ }
+
+ private:
+ bool should_block_;
+ base::WaitableEvent unblocked_;
+ base::WaitableEvent blocked_;
+};
+
+TEST(SingleThreadedProxyResolverTest, Basic) {
+ MockProxyResolver* mock = new MockProxyResolver;
+ scoped_ptr<SingleThreadedProxyResolver> resolver(
+ new SingleThreadedProxyResolver(mock));
+
+ int rv;
+
+ EXPECT_TRUE(resolver->expects_pac_bytes());
+
+ // Call SetPacScriptByData() -- we will make sure it reaches the sync resolver
+ // later on.
+ resolver->SetPacScriptByData("pac script bytes");
+
+ // Start request 0.
+ TestCompletionCallback callback0;
+ ProxyInfo results0;
+ rv = resolver->GetProxyForURL(
+ GURL("http://request0"), &results0, &callback0, NULL);
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ // Wait for request 0 to finish.
+ rv = callback0.WaitForResult();
+ EXPECT_EQ(0, rv);
+ EXPECT_EQ("PROXY request0:80", results0.ToPacString());
+
+ // Verify that the data from SetPacScriptByData() reached the resolver.
+ // (Since we waited for the first request to complete, we are guaranteed
+ // that the earlier post completed).
+ EXPECT_EQ("pac script bytes", mock->last_pac_bytes());
+
+ // Start 3 more requests (request1 to request3).
+
+ TestCompletionCallback callback1;
+ ProxyInfo results1;
+ rv = resolver->GetProxyForURL(
+ GURL("http://request1"), &results1, &callback1, NULL);
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ TestCompletionCallback callback2;
+ ProxyInfo results2;
+ rv = resolver->GetProxyForURL(
+ GURL("http://request2"), &results2, &callback2, NULL);
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ TestCompletionCallback callback3;
+ ProxyInfo results3;
+ rv = resolver->GetProxyForURL(
+ GURL("http://request3"), &results3, &callback3, NULL);
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ // Wait for the requests to finish (they must finish in the order they were
+ // started, which is what we check for from their magic return value)
+
+ rv = callback1.WaitForResult();
+ EXPECT_EQ(1, rv);
+ EXPECT_EQ("PROXY request1:80", results1.ToPacString());
+
+ rv = callback2.WaitForResult();
+ EXPECT_EQ(2, rv);
+ EXPECT_EQ("PROXY request2:80", results2.ToPacString());
+
+ rv = callback3.WaitForResult();
+ EXPECT_EQ(3, rv);
+ EXPECT_EQ("PROXY request3:80", results3.ToPacString());
+}
+
+// Cancel a request which is in progress, and then cancel a request which
+// is pending.
+TEST(SingleThreadedProxyResolverTest, CancelRequest) {
+ BlockableProxyResolver* mock = new BlockableProxyResolver;
+ scoped_ptr<SingleThreadedProxyResolver> resolver(
+ new SingleThreadedProxyResolver(mock));
+
+ int rv;
+
+ // Block the proxy resolver, so no request can complete.
+ mock->Block();
+
+ // Start request 0.
+ ProxyResolver::RequestHandle request0;
+ TestCompletionCallback callback0;
+ ProxyInfo results0;
+ rv = resolver->GetProxyForURL(
+ GURL("http://request0"), &results0, &callback0, &request0);
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ // Wait until requests 0 reaches the worker thread.
+ mock->WaitUntilBlocked();
+
+ // Start 3 more requests (request1 : request3).
+
+ TestCompletionCallback callback1;
+ ProxyInfo results1;
+ rv = resolver->GetProxyForURL(
+ GURL("http://request1"), &results1, &callback1, NULL);
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ ProxyResolver::RequestHandle request2;
+ TestCompletionCallback callback2;
+ ProxyInfo results2;
+ rv = resolver->GetProxyForURL(
+ GURL("http://request2"), &results2, &callback2, &request2);
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ TestCompletionCallback callback3;
+ ProxyInfo results3;
+ rv = resolver->GetProxyForURL(
+ GURL("http://request3"), &results3, &callback3, NULL);
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ // Cancel request0 (inprogress) and request2 (pending).
+ resolver->CancelRequest(request0);
+ resolver->CancelRequest(request2);
+
+ // Unblock the worker thread so the requests can continue running.
+ mock->Unblock();
+
+ // Wait for requests 1 and 3 to finish.
+
+ rv = callback1.WaitForResult();
+ EXPECT_EQ(1, rv);
+ EXPECT_EQ("PROXY request1:80", results1.ToPacString());
+
+ rv = callback3.WaitForResult();
+ // Note that since request2 was cancelled before reaching the resolver,
+ // the request count is 2 and not 3 here.
+ EXPECT_EQ(2, rv);
+ EXPECT_EQ("PROXY request3:80", results3.ToPacString());
+
+ // Requests 0 and 2 which were cancelled, hence their completion callbacks
+ // were never summoned.
+ EXPECT_FALSE(callback0.have_result());
+ EXPECT_FALSE(callback2.have_result());
+}
+
+// Test that deleting SingleThreadedProxyResolver while requests are
+// outstanding cancels them (and doesn't leak anything).
+TEST(SingleThreadedProxyResolverTest, CancelRequestByDeleting) {
+ BlockableProxyResolver* mock = new BlockableProxyResolver;
+ scoped_ptr<SingleThreadedProxyResolver> resolver(
+ new SingleThreadedProxyResolver(mock));
+
+ int rv;
+
+ // Block the proxy resolver, so no request can complete.
+ mock->Block();
+
+ // Start 3 requests.
+
+ TestCompletionCallback callback0;
+ ProxyInfo results0;
+ rv = resolver->GetProxyForURL(
+ GURL("http://request0"), &results0, &callback0, NULL);
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ TestCompletionCallback callback1;
+ ProxyInfo results1;
+ rv = resolver->GetProxyForURL(
+ GURL("http://request1"), &results1, &callback1, NULL);
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ TestCompletionCallback callback2;
+ ProxyInfo results2;
+ rv = resolver->GetProxyForURL(
+ GURL("http://request2"), &results2, &callback2, NULL);
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ // Wait until request 0 reaches the worker thread.
+ mock->WaitUntilBlocked();
+
+ // Add some latency, to improve the chance that when
+ // SingleThreadedProxyResolver is deleted below we are still running inside
+ // of the worker thread. The test will pass regardless, so this race doesn't
+ // cause flakiness. However the destruction during execution is a more
+ // interesting case to test.
+ mock->SetResolveLatency(100);
+
+ // Unblock the worker thread and delete the underlying
+ // SingleThreadedProxyResolver immediately.
+ mock->Unblock();
+ resolver.reset();
+
+ // Give any posted tasks a chance to run (in case there is badness).
+ MessageLoop::current()->RunAllPending();
+
+ // Check that none of the outstanding requests were completed.
+ EXPECT_FALSE(callback0.have_result());
+ EXPECT_FALSE(callback1.have_result());
+ EXPECT_FALSE(callback2.have_result());
+}
+
+} // namespace
+} // namespace net
Property changes on: net\proxy\single_threaded_proxy_resolver_unittest.cc
___________________________________________________________________
Added: svn:eol-style
+ LF
« no previous file with comments | « net/proxy/single_threaded_proxy_resolver.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698