15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/multi_threaded_proxy_resolver.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
95e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
105e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/waitable_event.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/threading/platform_thread.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log_unittest.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/test_completion_callback.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_info.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::ASCIIToUTF16;
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A synchronous mock ProxyResolver implementation, which can be used in
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// conjunction with MultiThreadedProxyResolver.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//       - returns a single-item proxy list with the query's host.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockProxyResolver : public ProxyResolver {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockProxyResolver()
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : ProxyResolver(true /*expects_pac_bytes*/),
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        wrong_loop_(base::MessageLoop::current()),
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        request_count_(0) {}
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ProxyResolver implementation.
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int GetProxyForURL(const GURL& query_url,
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             ProxyInfo* results,
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const CompletionCallback& callback,
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             RequestHandle* request,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const BoundNetLog& net_log) OVERRIDE {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (resolve_latency_ != base::TimeDelta())
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::PlatformThread::Sleep(resolve_latency_);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CheckIsOnWorkerThread();
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(callback.is_null());
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(request == NULL);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Write something into |net_log| (doesn't really have any meaning.)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    net_log.BeginEvent(NetLog::TYPE_PAC_JAVASCRIPT_ALERT);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    results->UseNamedProxy(query_url.host());
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Return a success code which represents the request's order.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return request_count_++;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void CancelRequest(RequestHandle request) OVERRIDE {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return LOAD_STATE_IDLE;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void CancelSetPacScript() OVERRIDE {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int SetPacScript(
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const scoped_refptr<ProxyResolverScriptData>& script_data,
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const CompletionCallback& callback) OVERRIDE {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CheckIsOnWorkerThread();
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_script_data_ = script_data;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int request_count() const { return request_count_; }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ProxyResolverScriptData* last_script_data() const {
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return last_script_data_.get();
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetResolveLatency(base::TimeDelta latency) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    resolve_latency_ = latency;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CheckIsOnWorkerThread() {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We should be running on the worker thread -- while we don't know the
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // message loop of MultiThreadedProxyResolver's worker thread, we do
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // know that it is going to be distinct from the loop running the
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // test, so at least make sure it isn't the main loop.
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    EXPECT_NE(base::MessageLoop::current(), wrong_loop_);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop* wrong_loop_;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int request_count_;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<ProxyResolverScriptData> last_script_data_;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta resolve_latency_;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A mock synchronous ProxyResolver which can be set to block upon reaching
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// GetProxyForURL().
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(eroman): WaitUntilBlocked() *must* be called before calling Unblock(),
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//               otherwise there will be a race on |should_block_| since it is
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//               read without any synchronization.
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BlockableProxyResolver : public MockProxyResolver {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BlockableProxyResolver()
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : should_block_(false),
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        unblocked_(true, true),
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        blocked_(true, false) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Block() {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    should_block_ = true;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unblocked_.Reset();
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Unblock() {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    should_block_ = false;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_.Reset();
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unblocked_.Signal();
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WaitUntilBlocked() {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_.Wait();
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int GetProxyForURL(const GURL& query_url,
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             ProxyInfo* results,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const CompletionCallback& callback,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             RequestHandle* request,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const BoundNetLog& net_log) OVERRIDE {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (should_block_) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      blocked_.Signal();
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unblocked_.Wait();
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return MockProxyResolver::GetProxyForURL(
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        query_url, results, callback, request, net_log);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool should_block_;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WaitableEvent unblocked_;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WaitableEvent blocked_;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ForwardingProxyResolver forwards all requests to |impl|.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ForwardingProxyResolver : public ProxyResolver {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit ForwardingProxyResolver(ProxyResolver* impl)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : ProxyResolver(impl->expects_pac_bytes()),
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        impl_(impl) {}
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int GetProxyForURL(const GURL& query_url,
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             ProxyInfo* results,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const CompletionCallback& callback,
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             RequestHandle* request,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const BoundNetLog& net_log) OVERRIDE {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return impl_->GetProxyForURL(
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        query_url, results, callback, request, net_log);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void CancelRequest(RequestHandle request) OVERRIDE {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    impl_->CancelRequest(request);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return LOAD_STATE_IDLE;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void CancelSetPacScript() OVERRIDE {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    impl_->CancelSetPacScript();
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int SetPacScript(
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const scoped_refptr<ProxyResolverScriptData>& script_data,
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const CompletionCallback& callback) OVERRIDE {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return impl_->SetPacScript(script_data, callback);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyResolver* impl_;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This factory returns ProxyResolvers that forward all requests to
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |resolver|.
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ForwardingProxyResolverFactory : public ProxyResolverFactory {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit ForwardingProxyResolverFactory(ProxyResolver* resolver)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : ProxyResolverFactory(resolver->expects_pac_bytes()),
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        resolver_(resolver) {}
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ProxyResolver* CreateProxyResolver() OVERRIDE {
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new ForwardingProxyResolver(resolver_);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyResolver* resolver_;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This factory returns new instances of BlockableProxyResolver.
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BlockableProxyResolverFactory : public ProxyResolverFactory {
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BlockableProxyResolverFactory() : ProxyResolverFactory(true) {}
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~BlockableProxyResolverFactory() {
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STLDeleteElements(&resolvers_);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ProxyResolver* CreateProxyResolver() OVERRIDE {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BlockableProxyResolver* resolver = new BlockableProxyResolver;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    resolvers_.push_back(resolver);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new ForwardingProxyResolver(resolver);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<BlockableProxyResolver*> resolvers() {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return resolvers_;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<BlockableProxyResolver*> resolvers_;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(MultiThreadedProxyResolverTest, SingleThread_Basic) {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t kNumThreads = 1u;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<MockProxyResolver> mock(new MockProxyResolver);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MultiThreadedProxyResolver resolver(
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ForwardingProxyResolverFactory(mock.get()), kNumThreads);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(resolver.expects_pac_bytes());
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Call SetPacScriptByData() -- verify that it reaches the synchronous
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // resolver.
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback set_script_callback;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = resolver.SetPacScript(
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ProxyResolverScriptData::FromUTF8("pac script bytes"),
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      set_script_callback.callback());
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, set_script_callback.WaitForResult());
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("pac script bytes"),
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mock->last_script_data()->utf16());
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start request 0.
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback0;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CapturingBoundNetLog log0;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyInfo results0;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = resolver.GetProxyForURL(GURL("http://request0"), &results0,
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               callback0.callback(), NULL, log0.bound());
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait for request 0 to finish.
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = callback0.WaitForResult();
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, rv);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("PROXY request0:80", results0.ToPacString());
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The mock proxy resolver should have written 1 log entry. And
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on completion, this should have been copied into |log0|.
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We also have 1 log entry that was emitted by the
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MultiThreadedProxyResolver.
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CapturingNetLog::CapturedEntryList entries0;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  log0.GetEntries(&entries0);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(2u, entries0.size());
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(NetLog::TYPE_SUBMITTED_TO_RESOLVER_THREAD, entries0[0].type);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start 3 more requests (request1 to request3).
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback1;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyInfo results1;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = resolver.GetProxyForURL(GURL("http://request1"), &results1,
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               callback1.callback(), NULL, BoundNetLog());
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback2;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyInfo results2;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = resolver.GetProxyForURL(GURL("http://request2"), &results2,
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               callback2.callback(), NULL, BoundNetLog());
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback3;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyInfo results3;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = resolver.GetProxyForURL(GURL("http://request3"), &results3,
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               callback3.callback(), NULL, BoundNetLog());
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait for the requests to finish (they must finish in the order they were
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // started, which is what we check for from their magic return value)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = callback1.WaitForResult();
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, rv);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("PROXY request1:80", results1.ToPacString());
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = callback2.WaitForResult();
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2, rv);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("PROXY request2:80", results2.ToPacString());
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = callback3.WaitForResult();
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(3, rv);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("PROXY request3:80", results3.ToPacString());
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that the NetLog is updated to include the time the request was waiting
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to be scheduled to a thread.
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(MultiThreadedProxyResolverTest,
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     SingleThread_UpdatesNetLogWithThreadWait) {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t kNumThreads = 1u;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<BlockableProxyResolver> mock(new BlockableProxyResolver);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MultiThreadedProxyResolver resolver(
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ForwardingProxyResolverFactory(mock.get()), kNumThreads);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize the resolver.
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback init_callback;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = resolver.SetPacScript(ProxyResolverScriptData::FromUTF8("foo"),
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             init_callback.callback());
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, init_callback.WaitForResult());
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Block the proxy resolver, so no request can complete.
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock->Block();
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start request 0.
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyResolver::RequestHandle request0;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback0;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyInfo results0;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CapturingBoundNetLog log0;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = resolver.GetProxyForURL(GURL("http://request0"), &results0,
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               callback0.callback(), &request0, log0.bound());
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start 2 more requests (request1 and request2).
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback1;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyInfo results1;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CapturingBoundNetLog log1;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = resolver.GetProxyForURL(GURL("http://request1"), &results1,
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               callback1.callback(), NULL, log1.bound());
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyResolver::RequestHandle request2;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback2;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyInfo results2;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CapturingBoundNetLog log2;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = resolver.GetProxyForURL(GURL("http://request2"), &results2,
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               callback2.callback(), &request2, log2.bound());
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Unblock the worker thread so the requests can continue running.
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock->WaitUntilBlocked();
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock->Unblock();
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that request 0 completed as expected.
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The NetLog has 1 entry that came from the MultiThreadedProxyResolver, and
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1 entry from the mock proxy resolver.
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, callback0.WaitForResult());
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("PROXY request0:80", results0.ToPacString());
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CapturingNetLog::CapturedEntryList entries0;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  log0.GetEntries(&entries0);
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(2u, entries0.size());
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(NetLog::TYPE_SUBMITTED_TO_RESOLVER_THREAD,
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            entries0[0].type);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that request 1 completed as expected.
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, callback1.WaitForResult());
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("PROXY request1:80", results1.ToPacString());
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CapturingNetLog::CapturedEntryList entries1;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  log1.GetEntries(&entries1);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(4u, entries1.size());
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(LogContainsBeginEvent(
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entries1, 0,
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NetLog::TYPE_WAITING_FOR_PROXY_RESOLVER_THREAD));
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(LogContainsEndEvent(
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entries1, 1,
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NetLog::TYPE_WAITING_FOR_PROXY_RESOLVER_THREAD));
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that request 2 completed as expected.
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2, callback2.WaitForResult());
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("PROXY request2:80", results2.ToPacString());
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CapturingNetLog::CapturedEntryList entries2;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  log2.GetEntries(&entries2);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(4u, entries2.size());
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(LogContainsBeginEvent(
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entries2, 0,
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NetLog::TYPE_WAITING_FOR_PROXY_RESOLVER_THREAD));
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(LogContainsEndEvent(
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entries2, 1,
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NetLog::TYPE_WAITING_FOR_PROXY_RESOLVER_THREAD));
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Cancel a request which is in progress, and then cancel a request which
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is pending.
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(MultiThreadedProxyResolverTest, SingleThread_CancelRequest) {
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t kNumThreads = 1u;
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<BlockableProxyResolver> mock(new BlockableProxyResolver);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MultiThreadedProxyResolver resolver(
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ForwardingProxyResolverFactory(mock.get()),
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      kNumThreads);
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize the resolver.
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback init_callback;
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = resolver.SetPacScript(ProxyResolverScriptData::FromUTF8("foo"),
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             init_callback.callback());
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, init_callback.WaitForResult());
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Block the proxy resolver, so no request can complete.
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock->Block();
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start request 0.
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyResolver::RequestHandle request0;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback0;
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyInfo results0;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = resolver.GetProxyForURL(GURL("http://request0"), &results0,
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               callback0.callback(), &request0, BoundNetLog());
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait until requests 0 reaches the worker thread.
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock->WaitUntilBlocked();
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start 3 more requests (request1 : request3).
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback1;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyInfo results1;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = resolver.GetProxyForURL(GURL("http://request1"), &results1,
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               callback1.callback(), NULL, BoundNetLog());
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyResolver::RequestHandle request2;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback2;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyInfo results2;
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = resolver.GetProxyForURL(GURL("http://request2"), &results2,
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               callback2.callback(), &request2, BoundNetLog());
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback3;
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyInfo results3;
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = resolver.GetProxyForURL(GURL("http://request3"), &results3,
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               callback3.callback(), NULL, BoundNetLog());
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancel request0 (inprogress) and request2 (pending).
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  resolver.CancelRequest(request0);
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  resolver.CancelRequest(request2);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Unblock the worker thread so the requests can continue running.
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock->Unblock();
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait for requests 1 and 3 to finish.
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = callback1.WaitForResult();
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, rv);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("PROXY request1:80", results1.ToPacString());
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = callback3.WaitForResult();
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that since request2 was cancelled before reaching the resolver,
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the request count is 2 and not 3 here.
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2, rv);
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("PROXY request3:80", results3.ToPacString());
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Requests 0 and 2 which were cancelled, hence their completion callbacks
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // were never summoned.
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(callback0.have_result());
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(callback2.have_result());
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that deleting MultiThreadedProxyResolver while requests are
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// outstanding cancels them (and doesn't leak anything).
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(MultiThreadedProxyResolverTest, SingleThread_CancelRequestByDeleting) {
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t kNumThreads = 1u;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<BlockableProxyResolver> mock(new BlockableProxyResolver);
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<MultiThreadedProxyResolver> resolver(
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new MultiThreadedProxyResolver(
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          new ForwardingProxyResolverFactory(mock.get()), kNumThreads));
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize the resolver.
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback init_callback;
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = resolver->SetPacScript(ProxyResolverScriptData::FromUTF8("foo"),
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              init_callback.callback());
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, init_callback.WaitForResult());
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Block the proxy resolver, so no request can complete.
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock->Block();
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start 3 requests.
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback0;
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyInfo results0;
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = resolver->GetProxyForURL(GURL("http://request0"), &results0,
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                callback0.callback(), NULL, BoundNetLog());
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback1;
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyInfo results1;
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = resolver->GetProxyForURL(GURL("http://request1"), &results1,
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                callback1.callback(), NULL, BoundNetLog());
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback2;
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyInfo results2;
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = resolver->GetProxyForURL(GURL("http://request2"), &results2,
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                callback2.callback(), NULL, BoundNetLog());
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait until request 0 reaches the worker thread.
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock->WaitUntilBlocked();
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add some latency, to improve the chance that when
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MultiThreadedProxyResolver is deleted below we are still running inside
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of the worker thread. The test will pass regardless, so this race doesn't
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cause flakiness. However the destruction during execution is a more
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // interesting case to test.
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock->SetResolveLatency(base::TimeDelta::FromMilliseconds(100));
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Unblock the worker thread and delete the underlying
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MultiThreadedProxyResolver immediately.
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock->Unblock();
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  resolver.reset();
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Give any posted tasks a chance to run (in case there is badness).
54190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that none of the outstanding requests were completed.
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(callback0.have_result());
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(callback1.have_result());
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(callback2.have_result());
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Cancel an outstanding call to SetPacScriptByData().
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(MultiThreadedProxyResolverTest, SingleThread_CancelSetPacScript) {
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t kNumThreads = 1u;
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<BlockableProxyResolver> mock(new BlockableProxyResolver);
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MultiThreadedProxyResolver resolver(
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ForwardingProxyResolverFactory(mock.get()), kNumThreads);
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback set_pac_script_callback;
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = resolver.SetPacScript(ProxyResolverScriptData::FromUTF8("data"),
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             set_pac_script_callback.callback());
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancel the SetPacScriptByData request.
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  resolver.CancelSetPacScript();
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start another SetPacScript request
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback set_pac_script_callback2;
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = resolver.SetPacScript(ProxyResolverScriptData::FromUTF8("data2"),
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             set_pac_script_callback2.callback());
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait for the initialization to complete.
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = set_pac_script_callback2.WaitForResult();
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, rv);
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("data2"), mock->last_script_data()->utf16());
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The first SetPacScript callback should never have been completed.
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(set_pac_script_callback.have_result());
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests setting the PAC script once, lazily creating new threads, and
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cancelling requests.
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(MultiThreadedProxyResolverTest, ThreeThreads_Basic) {
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t kNumThreads = 3u;
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BlockableProxyResolverFactory* factory = new BlockableProxyResolverFactory;
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MultiThreadedProxyResolver resolver(factory, kNumThreads);
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(resolver.expects_pac_bytes());
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Call SetPacScriptByData() -- verify that it reaches the synchronous
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // resolver.
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback set_script_callback;
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = resolver.SetPacScript(
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ProxyResolverScriptData::FromUTF8("pac script bytes"),
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      set_script_callback.callback());
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, set_script_callback.WaitForResult());
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // One thread has been provisioned (i.e. one ProxyResolver was created).
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, factory->resolvers().size());
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("pac script bytes"),
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            factory->resolvers()[0]->last_script_data()->utf16());
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kNumRequests = 9;
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback[kNumRequests];
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyInfo results[kNumRequests];
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyResolver::RequestHandle request[kNumRequests];
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start request 0 -- this should run on thread 0 as there is nothing else
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // going on right now.
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = resolver.GetProxyForURL(
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GURL("http://request0"), &results[0], callback[0].callback(), &request[0],
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BoundNetLog());
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait for request 0 to finish.
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = callback[0].WaitForResult();
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, rv);
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("PROXY request0:80", results[0].ToPacString());
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, factory->resolvers().size());
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, factory->resolvers()[0]->request_count());
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
62590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We now start 8 requests in parallel -- this will cause the maximum of
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // three threads to be provisioned (an additional two from what we already
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // have).
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 1; i < kNumRequests; ++i) {
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = resolver.GetProxyForURL(
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GURL(base::StringPrintf("http://request%d", i)), &results[i],
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        callback[i].callback(), &request[i], BoundNetLog());
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(ERR_IO_PENDING, rv);
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should now have a total of 3 threads, each with its own ProxyResolver
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that will get initialized with the same data. (We check this later since
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the assignment happens on the worker threads and may not have occurred
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // yet.)
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(3u, factory->resolvers().size());
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancel 3 of the 8 oustanding requests.
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  resolver.CancelRequest(request[1]);
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  resolver.CancelRequest(request[3]);
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  resolver.CancelRequest(request[6]);
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait for the remaining requests to complete.
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int kNonCancelledRequests[] = {2, 4, 5, 7, 8};
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arraysize(kNonCancelledRequests); ++i) {
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int request_index = kNonCancelledRequests[i];
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_GE(callback[request_index].WaitForResult(), 0);
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that the cancelled requests never invoked their callback.
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(callback[1].have_result());
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(callback[3].have_result());
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(callback[6].have_result());
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We call SetPacScript again, solely to stop the current worker threads.
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (That way we can test to see the values observed by the synchronous
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // resolvers in a non-racy manner).
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback set_script_callback2;
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = resolver.SetPacScript(ProxyResolverScriptData::FromUTF8("xyz"),
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             set_script_callback2.callback());
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, set_script_callback2.WaitForResult());
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(4u, factory->resolvers().size());
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 3; ++i) {
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ASCIIToUTF16("pac script bytes"),
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        factory->resolvers()[i]->last_script_data()->utf16()) << "i=" << i;
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("xyz"),
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            factory->resolvers()[3]->last_script_data()->utf16());
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't know the exact ordering that requests ran on threads with,
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // but we do know the total count that should have reached the threads.
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 8 total were submitted, and three were cancelled. Of the three that
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // were cancelled, one of them (request 1) was cancelled after it had
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // already been posted to the worker thread. So the resolvers will
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // have seen 6 total (and 1 from the run prior).
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(4u, factory->resolvers().size());
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int total_count = 0;
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 3; ++i) {
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    total_count += factory->resolvers()[i]->request_count();
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(7, total_count);
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests using two threads. The first request hangs the first thread. Checks
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that other requests are able to complete while this first request remains
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// stalled.
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(MultiThreadedProxyResolverTest, OneThreadBlocked) {
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t kNumThreads = 2u;
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BlockableProxyResolverFactory* factory = new BlockableProxyResolverFactory;
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MultiThreadedProxyResolver resolver(factory, kNumThreads);
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(resolver.expects_pac_bytes());
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize the resolver.
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback set_script_callback;
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = resolver.SetPacScript(
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ProxyResolverScriptData::FromUTF8("pac script bytes"),
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      set_script_callback.callback());
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, set_script_callback.WaitForResult());
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // One thread has been provisioned (i.e. one ProxyResolver was created).
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, factory->resolvers().size());
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("pac script bytes"),
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            factory->resolvers()[0]->last_script_data()->utf16());
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kNumRequests = 4;
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback[kNumRequests];
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyInfo results[kNumRequests];
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyResolver::RequestHandle request[kNumRequests];
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start a request that will block the first thread.
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  factory->resolvers()[0]->Block();
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = resolver.GetProxyForURL(
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GURL("http://request0"), &results[0], callback[0].callback(), &request[0],
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BoundNetLog());
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  factory->resolvers()[0]->WaitUntilBlocked();
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start 3 more requests -- they should all be serviced by thread #2
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // since thread #1 is blocked.
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 1; i < kNumRequests; ++i) {
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = resolver.GetProxyForURL(
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GURL(base::StringPrintf("http://request%d", i)),
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &results[i], callback[i].callback(), &request[i], BoundNetLog());
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(ERR_IO_PENDING, rv);
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait for the three requests to complete (they should complete in FIFO
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // order).
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 1; i < kNumRequests; ++i) {
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(i - 1, callback[i].WaitForResult());
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Unblock the first thread.
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  factory->resolvers()[0]->Unblock();
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, callback[0].WaitForResult());
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All in all, the first thread should have seen just 1 request. And the
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // second thread 3 requests.
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(2u, factory->resolvers().size());
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, factory->resolvers()[0]->request_count());
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(3, factory->resolvers()[1]->request_count());
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
764