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