12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867 |
- // Copyright (c) 2012 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "net/socket/transport_client_socket_pool.h"
- #include <memory>
- #include <utility>
- #include "base/bind.h"
- #include "base/callback.h"
- #include "base/callback_helpers.h"
- #include "base/memory/raw_ptr.h"
- #include "base/memory/ref_counted.h"
- #include "base/run_loop.h"
- #include "base/test/bind.h"
- #include "base/test/scoped_feature_list.h"
- #include "base/threading/platform_thread.h"
- #include "build/build_config.h"
- #include "net/base/completion_once_callback.h"
- #include "net/base/features.h"
- #include "net/base/ip_endpoint.h"
- #include "net/base/load_timing_info.h"
- #include "net/base/load_timing_info_test_util.h"
- #include "net/base/net_errors.h"
- #include "net/base/privacy_mode.h"
- #include "net/base/proxy_server.h"
- #include "net/base/proxy_string_util.h"
- #include "net/base/schemeful_site.h"
- #include "net/base/test_completion_callback.h"
- #include "net/cert/ct_policy_enforcer.h"
- #include "net/cert/mock_cert_verifier.h"
- #include "net/dns/mock_host_resolver.h"
- #include "net/dns/public/secure_dns_policy.h"
- #include "net/http/http_network_session.h"
- #include "net/http/http_proxy_connect_job.h"
- #include "net/http/transport_security_state.h"
- #include "net/log/net_log.h"
- #include "net/log/net_log_with_source.h"
- #include "net/proxy_resolution/configured_proxy_resolution_service.h"
- #include "net/socket/client_socket_handle.h"
- #include "net/socket/connect_job.h"
- #include "net/socket/socket_tag.h"
- #include "net/socket/socket_test_util.h"
- #include "net/socket/socks_connect_job.h"
- #include "net/socket/ssl_connect_job.h"
- #include "net/socket/stream_socket.h"
- #include "net/socket/transport_client_socket_pool.h"
- #include "net/socket/transport_client_socket_pool_test_util.h"
- #include "net/socket/transport_connect_job.h"
- #include "net/spdy/spdy_test_util_common.h"
- #include "net/ssl/ssl_config_service.h"
- #include "net/test/embedded_test_server/embedded_test_server.h"
- #include "net/test/gtest_util.h"
- #include "net/test/test_with_task_environment.h"
- #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- #include "url/gurl.h"
- #include "url/scheme_host_port.h"
- #include "url/url_constants.h"
- using net::test::IsError;
- using net::test::IsOk;
- namespace net {
- namespace {
- const int kMaxSockets = 32;
- const int kMaxSocketsPerGroup = 6;
- constexpr base::TimeDelta kUnusedIdleSocketTimeout = base::Seconds(10);
- const RequestPriority kDefaultPriority = LOW;
- class SOCKS5MockData {
- public:
- explicit SOCKS5MockData(IoMode mode) {
- writes_ = std::make_unique<MockWrite[]>(2);
- writes_[0] =
- MockWrite(mode, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength);
- writes_[1] = MockWrite(mode, kSOCKS5OkRequest, kSOCKS5OkRequestLength);
- reads_ = std::make_unique<MockRead[]>(2);
- reads_[0] =
- MockRead(mode, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength);
- reads_[1] = MockRead(mode, kSOCKS5OkResponse, kSOCKS5OkResponseLength);
- data_ = std::make_unique<StaticSocketDataProvider>(
- base::make_span(reads_.get(), 2), base::make_span(writes_.get(), 2));
- }
- SocketDataProvider* data_provider() { return data_.get(); }
- private:
- std::unique_ptr<StaticSocketDataProvider> data_;
- std::unique_ptr<MockWrite[]> writes_;
- std::unique_ptr<MockRead[]> reads_;
- };
- class TransportClientSocketPoolTest : public ::testing::Test,
- public WithTaskEnvironment {
- public:
- TransportClientSocketPoolTest(const TransportClientSocketPoolTest&) = delete;
- TransportClientSocketPoolTest& operator=(
- const TransportClientSocketPoolTest&) = delete;
- protected:
- // Constructor that allows mocking of the time.
- explicit TransportClientSocketPoolTest(
- base::test::TaskEnvironment::TimeSource time_source =
- base::test::TaskEnvironment::TimeSource::DEFAULT)
- : WithTaskEnvironment(time_source),
- connect_backup_jobs_enabled_(
- TransportClientSocketPool::set_connect_backup_jobs_enabled(true)),
- group_id_(url::SchemeHostPort(url::kHttpScheme, "www.google.com", 80),
- PrivacyMode::PRIVACY_MODE_DISABLED,
- NetworkIsolationKey(),
- SecureDnsPolicy::kAllow),
- params_(ClientSocketPool::SocketParams::CreateForHttpForTesting()),
- client_socket_factory_(NetLog::Get()) {
- std::unique_ptr<MockCertVerifier> cert_verifier =
- std::make_unique<MockCertVerifier>();
- cert_verifier->set_default_result(OK);
- session_deps_.cert_verifier = std::move(cert_verifier);
- http_network_session_ =
- SpdySessionDependencies::SpdyCreateSession(&session_deps_);
- common_connect_job_params_ = std::make_unique<CommonConnectJobParams>(
- http_network_session_->CreateCommonConnectJobParams());
- common_connect_job_params_->client_socket_factory = &client_socket_factory_;
- pool_ = std::make_unique<TransportClientSocketPool>(
- kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout,
- ProxyServer::Direct(), false /* is_for_websockets */,
- common_connect_job_params_.get());
- tagging_common_connect_job_params_ =
- std::make_unique<CommonConnectJobParams>(
- http_network_session_->CreateCommonConnectJobParams());
- tagging_common_connect_job_params_->client_socket_factory =
- &tagging_client_socket_factory_;
- tagging_pool_ = std::make_unique<TransportClientSocketPool>(
- kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout,
- ProxyServer::Direct(), false /* is_for_websockets */,
- tagging_common_connect_job_params_.get());
- common_connect_job_params_for_real_sockets_ =
- std::make_unique<CommonConnectJobParams>(
- http_network_session_->CreateCommonConnectJobParams());
- common_connect_job_params_for_real_sockets_->client_socket_factory =
- ClientSocketFactory::GetDefaultFactory();
- pool_for_real_sockets_ = std::make_unique<TransportClientSocketPool>(
- kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout,
- ProxyServer::Direct(), false /* is_for_websockets */,
- common_connect_job_params_for_real_sockets_.get());
- }
- ~TransportClientSocketPoolTest() override {
- TransportClientSocketPool::set_connect_backup_jobs_enabled(
- connect_backup_jobs_enabled_);
- }
- int StartRequest(const std::string& host_name, RequestPriority priority) {
- ClientSocketPool::GroupId group_id(
- url::SchemeHostPort(url::kHttpScheme, host_name, 80),
- PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
- SecureDnsPolicy::kAllow);
- return test_base_.StartRequestUsingPool(
- pool_.get(), group_id, priority,
- ClientSocketPool::RespectLimits::ENABLED,
- ClientSocketPool::SocketParams::CreateForHttpForTesting());
- }
- int GetOrderOfRequest(size_t index) {
- return test_base_.GetOrderOfRequest(index);
- }
- bool ReleaseOneConnection(ClientSocketPoolTest::KeepAlive keep_alive) {
- return test_base_.ReleaseOneConnection(keep_alive);
- }
- void ReleaseAllConnections(ClientSocketPoolTest::KeepAlive keep_alive) {
- test_base_.ReleaseAllConnections(keep_alive);
- }
- std::vector<std::unique_ptr<TestSocketRequest>>* requests() {
- return test_base_.requests();
- }
- size_t completion_count() const { return test_base_.completion_count(); }
- bool connect_backup_jobs_enabled_;
- // |group_id_| and |params_| correspond to the same group.
- const ClientSocketPool::GroupId group_id_;
- scoped_refptr<ClientSocketPool::SocketParams> params_;
- MockTransportClientSocketFactory client_socket_factory_;
- MockTaggingClientSocketFactory tagging_client_socket_factory_;
- // None of these tests check SPDY behavior, but this is a convenient way to
- // create most objects needed by the socket pools, as well as a SpdySession
- // pool, which is required by HttpProxyConnectJobs when using an HTTPS proxy.
- SpdySessionDependencies session_deps_;
- // As with |session_deps_|, this is a convenient way to construct objects
- // these tests depend on.
- std::unique_ptr<HttpNetworkSession> http_network_session_;
- std::unique_ptr<CommonConnectJobParams> common_connect_job_params_;
- std::unique_ptr<TransportClientSocketPool> pool_;
- // Just like |pool_|, except it uses a real MockTaggingClientSocketFactory
- // instead of MockTransportClientSocketFactory.
- std::unique_ptr<CommonConnectJobParams> tagging_common_connect_job_params_;
- std::unique_ptr<TransportClientSocketPool> tagging_pool_;
- // Just like |pool_|, except it uses a real ClientSocketFactory instead of
- // |client_socket_factory_|.
- std::unique_ptr<CommonConnectJobParams>
- common_connect_job_params_for_real_sockets_;
- std::unique_ptr<TransportClientSocketPool> pool_for_real_sockets_;
- ClientSocketPoolTest test_base_;
- };
- TEST_F(TransportClientSocketPoolTest, Basic) {
- TestCompletionCallback callback;
- ClientSocketHandle handle;
- int rv =
- handle.Init(group_id_, params_, absl::nullopt /* proxy_annotation_tag */,
- LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback.callback(), ClientSocketPool::ProxyAuthCallback(),
- pool_.get(), NetLogWithSource());
- EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
- EXPECT_FALSE(handle.is_initialized());
- EXPECT_FALSE(handle.socket());
- EXPECT_THAT(callback.WaitForResult(), IsOk());
- EXPECT_TRUE(handle.is_initialized());
- EXPECT_TRUE(handle.socket());
- TestLoadTimingInfoConnectedNotReused(handle);
- EXPECT_EQ(0u, handle.connection_attempts().size());
- }
- // Make sure that TransportConnectJob passes on its priority to its
- // HostResolver request on Init.
- TEST_F(TransportClientSocketPoolTest, SetResolvePriorityOnInit) {
- for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) {
- RequestPriority priority = static_cast<RequestPriority>(i);
- TestCompletionCallback callback;
- ClientSocketHandle handle;
- EXPECT_EQ(
- ERR_IO_PENDING,
- handle.Init(group_id_, params_,
- absl::nullopt /* proxy_annotation_tag */, priority,
- SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback.callback(), ClientSocketPool::ProxyAuthCallback(),
- pool_.get(), NetLogWithSource()));
- EXPECT_EQ(priority, session_deps_.host_resolver->last_request_priority());
- }
- }
- TEST_F(TransportClientSocketPoolTest, SetSecureDnsPolicy) {
- for (auto secure_dns_policy :
- {SecureDnsPolicy::kAllow, SecureDnsPolicy::kDisable}) {
- TestCompletionCallback callback;
- ClientSocketHandle handle;
- ClientSocketPool::GroupId group_id(
- url::SchemeHostPort(url::kHttpScheme, "www.google.com", 80),
- PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
- secure_dns_policy);
- EXPECT_EQ(
- ERR_IO_PENDING,
- handle.Init(group_id, params_, absl::nullopt /* proxy_annotation_tag */,
- LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback.callback(), ClientSocketPool::ProxyAuthCallback(),
- pool_.get(), NetLogWithSource()));
- EXPECT_EQ(secure_dns_policy,
- session_deps_.host_resolver->last_secure_dns_policy());
- }
- }
- TEST_F(TransportClientSocketPoolTest, ReprioritizeRequests) {
- session_deps_.host_resolver->set_ondemand_mode(true);
- TestCompletionCallback callback1;
- ClientSocketHandle handle1;
- int rv1 =
- handle1.Init(group_id_, params_, absl::nullopt /* proxy_annotation_tag */,
- LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
- pool_.get(), NetLogWithSource());
- EXPECT_THAT(rv1, IsError(ERR_IO_PENDING));
- TestCompletionCallback callback2;
- ClientSocketHandle handle2;
- int rv2 = handle2.Init(
- group_id_, params_, absl::nullopt /* proxy_annotation_tag */, HIGHEST,
- SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback2.callback(), ClientSocketPool::ProxyAuthCallback(), pool_.get(),
- NetLogWithSource());
- EXPECT_THAT(rv2, IsError(ERR_IO_PENDING));
- TestCompletionCallback callback3;
- ClientSocketHandle handle3;
- int rv3 = handle3.Init(
- group_id_, params_, absl::nullopt /* proxy_annotation_tag */, LOWEST,
- SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback3.callback(), ClientSocketPool::ProxyAuthCallback(), pool_.get(),
- NetLogWithSource());
- EXPECT_THAT(rv3, IsError(ERR_IO_PENDING));
- TestCompletionCallback callback4;
- ClientSocketHandle handle4;
- int rv4 = handle4.Init(
- group_id_, params_, absl::nullopt /* proxy_annotation_tag */, MEDIUM,
- SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback4.callback(), ClientSocketPool::ProxyAuthCallback(), pool_.get(),
- NetLogWithSource());
- EXPECT_THAT(rv4, IsError(ERR_IO_PENDING));
- TestCompletionCallback callback5;
- ClientSocketHandle handle5;
- int rv5 = handle5.Init(
- group_id_, params_, absl::nullopt /* proxy_annotation_tag */, HIGHEST,
- SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback5.callback(), ClientSocketPool::ProxyAuthCallback(), pool_.get(),
- NetLogWithSource());
- EXPECT_THAT(rv5, IsError(ERR_IO_PENDING));
- TestCompletionCallback callback6;
- ClientSocketHandle handle6;
- int rv6 =
- handle6.Init(group_id_, params_, absl::nullopt /* proxy_annotation_tag */,
- LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback6.callback(), ClientSocketPool::ProxyAuthCallback(),
- pool_.get(), NetLogWithSource());
- EXPECT_THAT(rv6, IsError(ERR_IO_PENDING));
- // New jobs are created for each of the first 6 requests with the
- // corresponding priority.
- //
- // Queue of pending requests:
- // Request Job Priority
- // ======= === ========
- // 2 2 HIGHEST
- // 5 5 HIGHEST
- // 4 4 MEDIUM
- // 1 1 LOW
- // 6 6 LOW
- // 3 3 LOWEST
- EXPECT_EQ(LOW, session_deps_.host_resolver->request_priority(1));
- EXPECT_EQ(HIGHEST, session_deps_.host_resolver->request_priority(2));
- EXPECT_EQ(LOWEST, session_deps_.host_resolver->request_priority(3));
- EXPECT_EQ(MEDIUM, session_deps_.host_resolver->request_priority(4));
- EXPECT_EQ(HIGHEST, session_deps_.host_resolver->request_priority(5));
- EXPECT_EQ(LOW, session_deps_.host_resolver->request_priority(6));
- // Inserting a highest-priority request steals the job from the lowest
- // priority request and reprioritizes it to match the new request.
- TestCompletionCallback callback7;
- ClientSocketHandle handle7;
- int rv7 = handle7.Init(
- group_id_, params_, absl::nullopt /* proxy_annotation_tag */, HIGHEST,
- SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback7.callback(), ClientSocketPool::ProxyAuthCallback(), pool_.get(),
- NetLogWithSource());
- EXPECT_THAT(rv7, IsError(ERR_IO_PENDING));
- // Request Job Priority
- // ======= === ========
- // 2 2 HIGHEST
- // 5 5 HIGHEST
- // 7 3 HIGHEST
- // 4 4 MEDIUM
- // 1 1 LOW
- // 6 6 LOW
- // 3 LOWEST
- EXPECT_EQ(LOW, session_deps_.host_resolver->request_priority(1));
- EXPECT_EQ(HIGHEST, session_deps_.host_resolver->request_priority(2));
- EXPECT_EQ(HIGHEST,
- session_deps_.host_resolver->request_priority(3)); // reprioritized
- EXPECT_EQ(MEDIUM, session_deps_.host_resolver->request_priority(4));
- EXPECT_EQ(HIGHEST, session_deps_.host_resolver->request_priority(5));
- EXPECT_EQ(LOW, session_deps_.host_resolver->request_priority(6));
- TestCompletionCallback callback8;
- ClientSocketHandle handle8;
- int rv8 = handle8.Init(
- group_id_, params_, absl::nullopt /* proxy_annotation_tag */, HIGHEST,
- SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback8.callback(), ClientSocketPool::ProxyAuthCallback(), pool_.get(),
- NetLogWithSource());
- EXPECT_THAT(rv8, IsError(ERR_IO_PENDING));
- // Request Job Priority
- // ======= === ========
- // 2 2 HIGHEST
- // 5 5 HIGHEST
- // 7 3 HIGHEST
- // 8 6 HIGHEST
- // 4 4 MEDIUM
- // 1 1 LOW
- // 6 LOW
- // 3 LOWEST
- EXPECT_EQ(LOW, session_deps_.host_resolver->request_priority(1));
- EXPECT_EQ(HIGHEST, session_deps_.host_resolver->request_priority(2));
- EXPECT_EQ(HIGHEST, session_deps_.host_resolver->request_priority(3));
- EXPECT_EQ(MEDIUM, session_deps_.host_resolver->request_priority(4));
- EXPECT_EQ(HIGHEST, session_deps_.host_resolver->request_priority(5));
- EXPECT_EQ(HIGHEST,
- session_deps_.host_resolver->request_priority(6)); // reprioritized
- // A request completes, then the socket is returned to the socket pool and
- // goes to the highest remaining request. The job from the highest request
- // should then be reassigned to the first request without a job.
- session_deps_.host_resolver->ResolveNow(2);
- EXPECT_THAT(callback2.WaitForResult(), IsOk());
- EXPECT_TRUE(handle2.is_initialized());
- EXPECT_TRUE(handle2.socket());
- handle2.Reset();
- EXPECT_THAT(callback5.WaitForResult(), IsOk());
- EXPECT_TRUE(handle5.is_initialized());
- EXPECT_TRUE(handle5.socket());
- // Request Job Priority
- // ======= === ========
- // 7 3 HIGHEST
- // 8 6 HIGHEST
- // 4 4 MEDIUM
- // 1 1 LOW
- // 6 5 LOW
- // 3 LOWEST
- EXPECT_EQ(LOW, session_deps_.host_resolver->request_priority(1));
- EXPECT_EQ(HIGHEST, session_deps_.host_resolver->request_priority(3));
- EXPECT_EQ(MEDIUM, session_deps_.host_resolver->request_priority(4));
- EXPECT_EQ(LOW,
- session_deps_.host_resolver->request_priority(5)); // reprioritized
- EXPECT_EQ(HIGHEST, session_deps_.host_resolver->request_priority(6));
- // Cancelling a request with a job reassigns the job to a lower request.
- handle7.Reset();
- // Request Job Priority
- // ======= === ========
- // 8 6 HIGHEST
- // 4 4 MEDIUM
- // 1 1 LOW
- // 6 5 LOW
- // 3 3 LOWEST
- EXPECT_EQ(LOW, session_deps_.host_resolver->request_priority(1));
- EXPECT_EQ(LOWEST,
- session_deps_.host_resolver->request_priority(3)); // reprioritized
- EXPECT_EQ(MEDIUM, session_deps_.host_resolver->request_priority(4));
- EXPECT_EQ(LOW, session_deps_.host_resolver->request_priority(5));
- EXPECT_EQ(HIGHEST, session_deps_.host_resolver->request_priority(6));
- // Reprioritizing a request changes its job's priority.
- pool_->SetPriority(group_id_, &handle4, LOWEST);
- // Request Job Priority
- // ======= === ========
- // 8 6 HIGHEST
- // 1 1 LOW
- // 6 5 LOW
- // 3 3 LOWEST
- // 4 4 LOWEST
- EXPECT_EQ(LOW, session_deps_.host_resolver->request_priority(1));
- EXPECT_EQ(LOWEST, session_deps_.host_resolver->request_priority(3));
- EXPECT_EQ(LOWEST,
- session_deps_.host_resolver->request_priority(4)); // reprioritized
- EXPECT_EQ(LOW, session_deps_.host_resolver->request_priority(5));
- EXPECT_EQ(HIGHEST, session_deps_.host_resolver->request_priority(6));
- pool_->SetPriority(group_id_, &handle3, MEDIUM);
- // Request Job Priority
- // ======= === ========
- // 8 6 HIGHEST
- // 3 3 MEDIUM
- // 1 1 LOW
- // 6 5 LOW
- // 4 4 LOWEST
- EXPECT_EQ(LOW, session_deps_.host_resolver->request_priority(1));
- EXPECT_EQ(MEDIUM,
- session_deps_.host_resolver->request_priority(3)); // reprioritized
- EXPECT_EQ(LOWEST, session_deps_.host_resolver->request_priority(4));
- EXPECT_EQ(LOW, session_deps_.host_resolver->request_priority(5));
- EXPECT_EQ(HIGHEST, session_deps_.host_resolver->request_priority(6));
- // Host resolution finishes for a lower-down request. The highest request
- // should get the socket and its job should be reassigned to the lower
- // request.
- session_deps_.host_resolver->ResolveNow(1);
- EXPECT_THAT(callback8.WaitForResult(), IsOk());
- EXPECT_TRUE(handle8.is_initialized());
- EXPECT_TRUE(handle8.socket());
- // Request Job Priority
- // ======= === ========
- // 3 3 MEDIUM
- // 1 6 LOW
- // 6 5 LOW
- // 4 4 LOWEST
- EXPECT_EQ(MEDIUM, session_deps_.host_resolver->request_priority(3));
- EXPECT_EQ(LOWEST, session_deps_.host_resolver->request_priority(4));
- EXPECT_EQ(LOW, session_deps_.host_resolver->request_priority(5));
- EXPECT_EQ(LOW,
- session_deps_.host_resolver->request_priority(6)); // reprioritized
- // Host resolution finishes for the highest request. Nothing gets
- // reprioritized.
- session_deps_.host_resolver->ResolveNow(3);
- EXPECT_THAT(callback3.WaitForResult(), IsOk());
- EXPECT_TRUE(handle3.is_initialized());
- EXPECT_TRUE(handle3.socket());
- // Request Job Priority
- // ======= === ========
- // 1 6 LOW
- // 6 5 LOW
- // 4 4 LOWEST
- EXPECT_EQ(LOWEST, session_deps_.host_resolver->request_priority(4));
- EXPECT_EQ(LOW, session_deps_.host_resolver->request_priority(5));
- EXPECT_EQ(LOW, session_deps_.host_resolver->request_priority(6));
- session_deps_.host_resolver->ResolveAllPending();
- EXPECT_THAT(callback1.WaitForResult(), IsOk());
- EXPECT_TRUE(handle1.is_initialized());
- EXPECT_TRUE(handle1.socket());
- EXPECT_THAT(callback4.WaitForResult(), IsOk());
- EXPECT_TRUE(handle4.is_initialized());
- EXPECT_TRUE(handle4.socket());
- EXPECT_THAT(callback6.WaitForResult(), IsOk());
- EXPECT_TRUE(handle6.is_initialized());
- EXPECT_TRUE(handle6.socket());
- }
- TEST_F(TransportClientSocketPoolTest, RequestIgnoringLimitsIsReprioritized) {
- TransportClientSocketPool pool(
- kMaxSockets, 1, kUnusedIdleSocketTimeout, ProxyServer::Direct(),
- false /* is_for_websockets */, common_connect_job_params_.get());
- // Creates a job which ignores limits whose priority is MAXIMUM_PRIORITY.
- TestCompletionCallback callback1;
- ClientSocketHandle handle1;
- int rv1 = handle1.Init(
- group_id_, params_, absl::nullopt /* proxy_annotation_tag */,
- MAXIMUM_PRIORITY, SocketTag(), ClientSocketPool::RespectLimits::DISABLED,
- callback1.callback(), ClientSocketPool::ProxyAuthCallback(), &pool,
- NetLogWithSource());
- EXPECT_THAT(rv1, IsError(ERR_IO_PENDING));
- EXPECT_EQ(MAXIMUM_PRIORITY, session_deps_.host_resolver->request_priority(1));
- TestCompletionCallback callback2;
- ClientSocketHandle handle2;
- int rv2 =
- handle2.Init(group_id_, params_, absl::nullopt /* proxy_annotation_tag */,
- LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
- &pool, NetLogWithSource());
- EXPECT_THAT(rv2, IsError(ERR_IO_PENDING));
- // |handle2| gets assigned the job, which is reprioritized.
- handle1.Reset();
- EXPECT_EQ(LOW, session_deps_.host_resolver->request_priority(1));
- }
- TEST_F(TransportClientSocketPoolTest, InitHostResolutionFailure) {
- session_deps_.host_resolver->rules()->AddSimulatedTimeoutFailure(
- group_id_.destination().host());
- TestCompletionCallback callback;
- ClientSocketHandle handle;
- EXPECT_EQ(
- ERR_IO_PENDING,
- handle.Init(group_id_, params_, absl::nullopt /* proxy_annotation_tag */,
- kDefaultPriority, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
- ClientSocketPool::ProxyAuthCallback(), pool_.get(),
- NetLogWithSource()));
- EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NAME_NOT_RESOLVED));
- EXPECT_THAT(handle.resolve_error_info().error, IsError(ERR_DNS_TIMED_OUT));
- ASSERT_EQ(1u, handle.connection_attempts().size());
- EXPECT_TRUE(handle.connection_attempts()[0].endpoint.address().empty());
- EXPECT_THAT(handle.connection_attempts()[0].result,
- IsError(ERR_NAME_NOT_RESOLVED));
- }
- TEST_F(TransportClientSocketPoolTest, InitConnectionFailure) {
- client_socket_factory_.set_default_client_socket_type(
- MockTransportClientSocketFactory::Type::kFailing);
- TestCompletionCallback callback;
- ClientSocketHandle handle;
- EXPECT_EQ(
- ERR_IO_PENDING,
- handle.Init(group_id_, params_, absl::nullopt /* proxy_annotation_tag */,
- kDefaultPriority, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
- ClientSocketPool::ProxyAuthCallback(), pool_.get(),
- NetLogWithSource()));
- EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_FAILED));
- ASSERT_EQ(1u, handle.connection_attempts().size());
- EXPECT_EQ("127.0.0.1:80",
- handle.connection_attempts()[0].endpoint.ToString());
- EXPECT_THAT(handle.connection_attempts()[0].result,
- IsError(ERR_CONNECTION_FAILED));
- // Make the host resolutions complete synchronously this time.
- session_deps_.host_resolver->set_synchronous_mode(true);
- EXPECT_EQ(
- ERR_CONNECTION_FAILED,
- handle.Init(group_id_, params_, absl::nullopt /* proxy_annotation_tag */,
- kDefaultPriority, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
- ClientSocketPool::ProxyAuthCallback(), pool_.get(),
- NetLogWithSource()));
- ASSERT_EQ(1u, handle.connection_attempts().size());
- EXPECT_EQ("127.0.0.1:80",
- handle.connection_attempts()[0].endpoint.ToString());
- EXPECT_THAT(handle.connection_attempts()[0].result,
- IsError(ERR_CONNECTION_FAILED));
- }
- TEST_F(TransportClientSocketPoolTest, PendingRequests) {
- // First request finishes asynchronously.
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsError(ERR_IO_PENDING));
- EXPECT_THAT((*requests())[0]->WaitForResult(), IsOk());
- // Make all subsequent host resolutions complete synchronously.
- session_deps_.host_resolver->set_synchronous_mode(true);
- // Rest of them finish synchronously, until we reach the per-group limit.
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsOk());
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsOk());
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsOk());
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsOk());
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsOk());
- // The rest are pending since we've used all active sockets.
- EXPECT_THAT(StartRequest("a", HIGHEST), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", LOWEST), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", LOWEST), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", MEDIUM), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", LOW), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", HIGHEST), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", LOWEST), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", MEDIUM), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", MEDIUM), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", HIGHEST), IsError(ERR_IO_PENDING));
- ReleaseAllConnections(ClientSocketPoolTest::KEEP_ALIVE);
- EXPECT_EQ(kMaxSocketsPerGroup, client_socket_factory_.allocation_count());
- // One initial asynchronous request and then 10 pending requests.
- EXPECT_EQ(11U, completion_count());
- // First part of requests, all with the same priority, finishes in FIFO order.
- EXPECT_EQ(1, GetOrderOfRequest(1));
- EXPECT_EQ(2, GetOrderOfRequest(2));
- EXPECT_EQ(3, GetOrderOfRequest(3));
- EXPECT_EQ(4, GetOrderOfRequest(4));
- EXPECT_EQ(5, GetOrderOfRequest(5));
- EXPECT_EQ(6, GetOrderOfRequest(6));
- // Make sure that rest of the requests complete in the order of priority.
- EXPECT_EQ(7, GetOrderOfRequest(7));
- EXPECT_EQ(14, GetOrderOfRequest(8));
- EXPECT_EQ(15, GetOrderOfRequest(9));
- EXPECT_EQ(10, GetOrderOfRequest(10));
- EXPECT_EQ(13, GetOrderOfRequest(11));
- EXPECT_EQ(8, GetOrderOfRequest(12));
- EXPECT_EQ(16, GetOrderOfRequest(13));
- EXPECT_EQ(11, GetOrderOfRequest(14));
- EXPECT_EQ(12, GetOrderOfRequest(15));
- EXPECT_EQ(9, GetOrderOfRequest(16));
- // Make sure we test order of all requests made.
- EXPECT_EQ(ClientSocketPoolTest::kIndexOutOfBounds, GetOrderOfRequest(17));
- }
- TEST_F(TransportClientSocketPoolTest, PendingRequests_NoKeepAlive) {
- // First request finishes asynchronously.
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsError(ERR_IO_PENDING));
- EXPECT_THAT((*requests())[0]->WaitForResult(), IsOk());
- // Make all subsequent host resolutions complete synchronously.
- session_deps_.host_resolver->set_synchronous_mode(true);
- // Rest of them finish synchronously, until we reach the per-group limit.
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsOk());
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsOk());
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsOk());
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsOk());
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsOk());
- // The rest are pending since we've used all active sockets.
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsError(ERR_IO_PENDING));
- ReleaseAllConnections(ClientSocketPoolTest::NO_KEEP_ALIVE);
- // The pending requests should finish successfully.
- EXPECT_THAT((*requests())[6]->WaitForResult(), IsOk());
- EXPECT_THAT((*requests())[7]->WaitForResult(), IsOk());
- EXPECT_THAT((*requests())[8]->WaitForResult(), IsOk());
- EXPECT_THAT((*requests())[9]->WaitForResult(), IsOk());
- EXPECT_THAT((*requests())[10]->WaitForResult(), IsOk());
- EXPECT_EQ(static_cast<int>(requests()->size()),
- client_socket_factory_.allocation_count());
- // First asynchronous request, and then last 5 pending requests.
- EXPECT_EQ(6U, completion_count());
- }
- // This test will start up a RequestSocket() and then immediately Cancel() it.
- // The pending host resolution will eventually complete, and destroy the
- // ClientSocketPool which will crash if the group was not cleared properly.
- TEST_F(TransportClientSocketPoolTest, CancelRequestClearGroup) {
- TestCompletionCallback callback;
- ClientSocketHandle handle;
- EXPECT_EQ(
- ERR_IO_PENDING,
- handle.Init(group_id_, params_, absl::nullopt /* proxy_annotation_tag */,
- kDefaultPriority, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
- ClientSocketPool::ProxyAuthCallback(), pool_.get(),
- NetLogWithSource()));
- handle.Reset();
- }
- TEST_F(TransportClientSocketPoolTest, TwoRequestsCancelOne) {
- ClientSocketHandle handle;
- TestCompletionCallback callback;
- ClientSocketHandle handle2;
- TestCompletionCallback callback2;
- EXPECT_EQ(
- ERR_IO_PENDING,
- handle.Init(group_id_, params_, absl::nullopt /* proxy_annotation_tag */,
- kDefaultPriority, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
- ClientSocketPool::ProxyAuthCallback(), pool_.get(),
- NetLogWithSource()));
- EXPECT_EQ(
- ERR_IO_PENDING,
- handle2.Init(group_id_, params_, absl::nullopt /* proxy_annotation_tag */,
- kDefaultPriority, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED,
- callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
- pool_.get(), NetLogWithSource()));
- handle.Reset();
- EXPECT_THAT(callback2.WaitForResult(), IsOk());
- handle2.Reset();
- }
- TEST_F(TransportClientSocketPoolTest, ConnectCancelConnect) {
- client_socket_factory_.set_default_client_socket_type(
- MockTransportClientSocketFactory::Type::kPending);
- ClientSocketHandle handle;
- TestCompletionCallback callback;
- EXPECT_EQ(
- ERR_IO_PENDING,
- handle.Init(group_id_, params_, absl::nullopt /* proxy_annotation_tag */,
- kDefaultPriority, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
- ClientSocketPool::ProxyAuthCallback(), pool_.get(),
- NetLogWithSource()));
- handle.Reset();
- TestCompletionCallback callback2;
- EXPECT_EQ(
- ERR_IO_PENDING,
- handle.Init(group_id_, params_, absl::nullopt /* proxy_annotation_tag */,
- kDefaultPriority, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED,
- callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
- pool_.get(), NetLogWithSource()));
- session_deps_.host_resolver->set_synchronous_mode(true);
- // At this point, handle has two ConnectingSockets out for it. Due to the
- // setting the mock resolver into synchronous mode, the host resolution for
- // both will return in the same loop of the MessageLoop. The client socket
- // is a pending socket, so the Connect() will asynchronously complete on the
- // next loop of the MessageLoop. That means that the first
- // ConnectingSocket will enter OnIOComplete, and then the second one will.
- // If the first one is not cancelled, it will advance the load state, and
- // then the second one will crash.
- EXPECT_THAT(callback2.WaitForResult(), IsOk());
- EXPECT_FALSE(callback.have_result());
- handle.Reset();
- }
- TEST_F(TransportClientSocketPoolTest, CancelRequest) {
- // First request finishes asynchronously.
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsError(ERR_IO_PENDING));
- EXPECT_THAT((*requests())[0]->WaitForResult(), IsOk());
- // Make all subsequent host resolutions complete synchronously.
- session_deps_.host_resolver->set_synchronous_mode(true);
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsOk());
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsOk());
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsOk());
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsOk());
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsOk());
- // Reached per-group limit, queue up requests.
- EXPECT_THAT(StartRequest("a", LOWEST), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", HIGHEST), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", HIGHEST), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", MEDIUM), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", MEDIUM), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", LOW), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", HIGHEST), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", LOW), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", LOW), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", LOWEST), IsError(ERR_IO_PENDING));
- // Cancel a request.
- size_t index_to_cancel = kMaxSocketsPerGroup + 2;
- EXPECT_FALSE((*requests())[index_to_cancel]->handle()->is_initialized());
- (*requests())[index_to_cancel]->handle()->Reset();
- ReleaseAllConnections(ClientSocketPoolTest::KEEP_ALIVE);
- EXPECT_EQ(kMaxSocketsPerGroup,
- client_socket_factory_.allocation_count());
- EXPECT_EQ(requests()->size() - kMaxSocketsPerGroup, completion_count());
- EXPECT_EQ(1, GetOrderOfRequest(1));
- EXPECT_EQ(2, GetOrderOfRequest(2));
- EXPECT_EQ(3, GetOrderOfRequest(3));
- EXPECT_EQ(4, GetOrderOfRequest(4));
- EXPECT_EQ(5, GetOrderOfRequest(5));
- EXPECT_EQ(6, GetOrderOfRequest(6));
- EXPECT_EQ(14, GetOrderOfRequest(7));
- EXPECT_EQ(7, GetOrderOfRequest(8));
- EXPECT_EQ(ClientSocketPoolTest::kRequestNotFound,
- GetOrderOfRequest(9)); // Canceled request.
- EXPECT_EQ(9, GetOrderOfRequest(10));
- EXPECT_EQ(10, GetOrderOfRequest(11));
- EXPECT_EQ(11, GetOrderOfRequest(12));
- EXPECT_EQ(8, GetOrderOfRequest(13));
- EXPECT_EQ(12, GetOrderOfRequest(14));
- EXPECT_EQ(13, GetOrderOfRequest(15));
- EXPECT_EQ(15, GetOrderOfRequest(16));
- // Make sure we test order of all requests made.
- EXPECT_EQ(ClientSocketPoolTest::kIndexOutOfBounds, GetOrderOfRequest(17));
- }
- class RequestSocketCallback : public TestCompletionCallbackBase {
- public:
- RequestSocketCallback(
- const ClientSocketPool::GroupId& group_id,
- scoped_refptr<ClientSocketPool::SocketParams> socket_params,
- ClientSocketHandle* handle,
- TransportClientSocketPool* pool)
- : group_id_(group_id),
- socket_params_(socket_params),
- handle_(handle),
- pool_(pool) {}
- RequestSocketCallback(const RequestSocketCallback&) = delete;
- RequestSocketCallback& operator=(const RequestSocketCallback&) = delete;
- ~RequestSocketCallback() override = default;
- CompletionOnceCallback callback() {
- return base::BindOnce(&RequestSocketCallback::OnComplete,
- base::Unretained(this));
- }
- private:
- void OnComplete(int result) {
- SetResult(result);
- ASSERT_THAT(result, IsOk());
- if (!within_callback_) {
- // Don't allow reuse of the socket. Disconnect it and then release it and
- // run through the MessageLoop once to get it completely released.
- handle_->socket()->Disconnect();
- handle_->Reset();
- base::RunLoop(base::RunLoop::Type::kNestableTasksAllowed).RunUntilIdle();
- within_callback_ = true;
- int rv = handle_->Init(
- group_id_, socket_params_, absl::nullopt /* proxy_annotation_tag */,
- LOWEST, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback(), ClientSocketPool::ProxyAuthCallback(), pool_,
- NetLogWithSource());
- EXPECT_THAT(rv, IsOk());
- }
- }
- const ClientSocketPool::GroupId group_id_;
- scoped_refptr<ClientSocketPool::SocketParams> socket_params_;
- const raw_ptr<ClientSocketHandle> handle_;
- const raw_ptr<TransportClientSocketPool> pool_;
- bool within_callback_ = false;
- };
- TEST_F(TransportClientSocketPoolTest, RequestTwice) {
- ClientSocketHandle handle;
- RequestSocketCallback callback(group_id_, params_, &handle, pool_.get());
- int rv =
- handle.Init(group_id_, params_, absl::nullopt /* proxy_annotation_tag */,
- LOWEST, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback.callback(), ClientSocketPool::ProxyAuthCallback(),
- pool_.get(), NetLogWithSource());
- ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
- // The callback is going to request "www.google.com". We want it to complete
- // synchronously this time.
- session_deps_.host_resolver->set_synchronous_mode(true);
- EXPECT_THAT(callback.WaitForResult(), IsOk());
- handle.Reset();
- }
- // Make sure that pending requests get serviced after active requests get
- // cancelled.
- TEST_F(TransportClientSocketPoolTest, CancelActiveRequestWithPendingRequests) {
- client_socket_factory_.set_default_client_socket_type(
- MockTransportClientSocketFactory::Type::kPending);
- // Queue up all the requests
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsError(ERR_IO_PENDING));
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsError(ERR_IO_PENDING));
- // Now, kMaxSocketsPerGroup requests should be active. Let's cancel them.
- ASSERT_LE(kMaxSocketsPerGroup, static_cast<int>(requests()->size()));
- for (int i = 0; i < kMaxSocketsPerGroup; i++)
- (*requests())[i]->handle()->Reset();
- // Let's wait for the rest to complete now.
- for (size_t i = kMaxSocketsPerGroup; i < requests()->size(); ++i) {
- EXPECT_THAT((*requests())[i]->WaitForResult(), IsOk());
- (*requests())[i]->handle()->Reset();
- }
- EXPECT_EQ(requests()->size() - kMaxSocketsPerGroup, completion_count());
- }
- // Make sure that pending requests get serviced after active requests fail.
- TEST_F(TransportClientSocketPoolTest, FailingActiveRequestWithPendingRequests) {
- client_socket_factory_.set_default_client_socket_type(
- MockTransportClientSocketFactory::Type::kPendingFailing);
- const int kNumRequests = 2 * kMaxSocketsPerGroup + 1;
- ASSERT_LE(kNumRequests, kMaxSockets); // Otherwise the test will hang.
- // Queue up all the requests
- for (int i = 0; i < kNumRequests; i++)
- EXPECT_THAT(StartRequest("a", kDefaultPriority), IsError(ERR_IO_PENDING));
- for (int i = 0; i < kNumRequests; i++)
- EXPECT_THAT((*requests())[i]->WaitForResult(),
- IsError(ERR_CONNECTION_FAILED));
- }
- TEST_F(TransportClientSocketPoolTest, IdleSocketLoadTiming) {
- TestCompletionCallback callback;
- ClientSocketHandle handle;
- int rv =
- handle.Init(group_id_, params_, absl::nullopt /* proxy_annotation_tag */,
- LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback.callback(), ClientSocketPool::ProxyAuthCallback(),
- pool_.get(), NetLogWithSource());
- EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
- EXPECT_FALSE(handle.is_initialized());
- EXPECT_FALSE(handle.socket());
- EXPECT_THAT(callback.WaitForResult(), IsOk());
- EXPECT_TRUE(handle.is_initialized());
- EXPECT_TRUE(handle.socket());
- TestLoadTimingInfoConnectedNotReused(handle);
- handle.Reset();
- // Need to run all pending to release the socket back to the pool.
- base::RunLoop().RunUntilIdle();
- // Now we should have 1 idle socket.
- EXPECT_EQ(1, pool_->IdleSocketCount());
- rv = handle.Init(group_id_, params_, absl::nullopt /* proxy_annotation_tag */,
- LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback.callback(), ClientSocketPool::ProxyAuthCallback(),
- pool_.get(), NetLogWithSource());
- EXPECT_THAT(rv, IsOk());
- EXPECT_EQ(0, pool_->IdleSocketCount());
- TestLoadTimingInfoConnectedReused(handle);
- }
- TEST_F(TransportClientSocketPoolTest, CloseIdleSocketsOnIPAddressChange) {
- TestCompletionCallback callback;
- ClientSocketHandle handle;
- int rv =
- handle.Init(group_id_, params_, absl::nullopt /* proxy_annotation_tag */,
- LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback.callback(), ClientSocketPool::ProxyAuthCallback(),
- pool_.get(), NetLogWithSource());
- EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
- EXPECT_FALSE(handle.is_initialized());
- EXPECT_FALSE(handle.socket());
- EXPECT_THAT(callback.WaitForResult(), IsOk());
- EXPECT_TRUE(handle.is_initialized());
- EXPECT_TRUE(handle.socket());
- handle.Reset();
- // Need to run all pending to release the socket back to the pool.
- base::RunLoop().RunUntilIdle();
- // Now we should have 1 idle socket.
- EXPECT_EQ(1, pool_->IdleSocketCount());
- // After an IP address change, we should have 0 idle sockets.
- NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
- base::RunLoop().RunUntilIdle(); // Notification happens async.
- EXPECT_EQ(0, pool_->IdleSocketCount());
- }
- TEST(TransportClientSocketPoolStandaloneTest, DontCleanupOnIPAddressChange) {
- // This test manually sets things up in the same way
- // TransportClientSocketPoolTest does, but it creates a
- // TransportClientSocketPool with cleanup_on_ip_address_changed = false. Since
- // this is the only test doing this, it's not worth extending
- // TransportClientSocketPoolTest to support this scenario.
- base::test::SingleThreadTaskEnvironment task_environment;
- std::unique_ptr<MockCertVerifier> cert_verifier =
- std::make_unique<MockCertVerifier>();
- SpdySessionDependencies session_deps;
- session_deps.cert_verifier = std::move(cert_verifier);
- std::unique_ptr<HttpNetworkSession> http_network_session =
- SpdySessionDependencies::SpdyCreateSession(&session_deps);
- auto common_connect_job_params = std::make_unique<CommonConnectJobParams>(
- http_network_session->CreateCommonConnectJobParams());
- MockTransportClientSocketFactory client_socket_factory(NetLog::Get());
- common_connect_job_params->client_socket_factory = &client_socket_factory;
- scoped_refptr<ClientSocketPool::SocketParams> params(
- ClientSocketPool::SocketParams::CreateForHttpForTesting());
- auto pool = std::make_unique<TransportClientSocketPool>(
- kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout,
- ProxyServer::Direct(), false /* is_for_websockets */,
- common_connect_job_params.get(),
- false /* cleanup_on_ip_address_change */);
- const ClientSocketPool::GroupId group_id(
- url::SchemeHostPort(url::kHttpScheme, "www.google.com", 80),
- PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
- SecureDnsPolicy::kAllow);
- TestCompletionCallback callback;
- ClientSocketHandle handle;
- int rv =
- handle.Init(group_id, params, absl::nullopt /* proxy_annotation_tag */,
- LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback.callback(), ClientSocketPool::ProxyAuthCallback(),
- pool.get(), NetLogWithSource());
- EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
- EXPECT_FALSE(handle.is_initialized());
- EXPECT_FALSE(handle.socket());
- EXPECT_THAT(callback.WaitForResult(), IsOk());
- EXPECT_TRUE(handle.is_initialized());
- EXPECT_TRUE(handle.socket());
- handle.Reset();
- // Need to run all pending to release the socket back to the pool.
- base::RunLoop().RunUntilIdle();
- // Now we should have 1 idle socket.
- EXPECT_EQ(1, pool->IdleSocketCount());
- // Since we set cleanup_on_ip_address_change = false, we should still have 1
- // idle socket after an IP address change.
- NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
- base::RunLoop().RunUntilIdle(); // Notification happens async.
- EXPECT_EQ(1, pool->IdleSocketCount());
- }
- TEST_F(TransportClientSocketPoolTest, SSLCertError) {
- StaticSocketDataProvider data;
- tagging_client_socket_factory_.AddSocketDataProvider(&data);
- SSLSocketDataProvider ssl(ASYNC, ERR_CERT_COMMON_NAME_INVALID);
- tagging_client_socket_factory_.AddSSLSocketDataProvider(&ssl);
- const url::SchemeHostPort kEndpoint(url::kHttpsScheme, "ssl.server.test",
- 443);
- auto ssl_config_for_origin = std::make_unique<SSLConfig>();
- ssl_config_for_origin->alpn_protos = {kProtoHTTP2, kProtoHTTP11};
- scoped_refptr<ClientSocketPool::SocketParams> socket_params =
- base::MakeRefCounted<ClientSocketPool::SocketParams>(
- std::move(ssl_config_for_origin),
- /*ssl_config_for_proxy=*/nullptr);
- ClientSocketHandle handle;
- TestCompletionCallback callback;
- int rv = handle.Init(
- ClientSocketPool::GroupId(kEndpoint, PrivacyMode::PRIVACY_MODE_DISABLED,
- NetworkIsolationKey(), SecureDnsPolicy::kAllow),
- socket_params, absl::nullopt /* proxy_annotation_tag */, MEDIUM,
- SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback.callback(), ClientSocketPool::ProxyAuthCallback(),
- tagging_pool_.get(), NetLogWithSource());
- EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
- EXPECT_FALSE(handle.is_initialized());
- EXPECT_FALSE(handle.socket());
- EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CERT_COMMON_NAME_INVALID));
- EXPECT_TRUE(handle.is_initialized());
- EXPECT_TRUE(handle.socket());
- }
- TEST_F(TransportClientSocketPoolTest, CloseIdleSocketsOnSSLConfigChange) {
- TestCompletionCallback callback;
- ClientSocketHandle handle;
- int rv =
- handle.Init(group_id_, params_, absl::nullopt /* proxy_annotation_tag */,
- LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback.callback(), ClientSocketPool::ProxyAuthCallback(),
- pool_.get(), NetLogWithSource());
- EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
- EXPECT_FALSE(handle.is_initialized());
- EXPECT_FALSE(handle.socket());
- EXPECT_THAT(callback.WaitForResult(), IsOk());
- EXPECT_TRUE(handle.is_initialized());
- EXPECT_TRUE(handle.socket());
- handle.Reset();
- // Need to run all pending to release the socket back to the pool.
- base::RunLoop().RunUntilIdle();
- // Now we should have 1 idle socket.
- EXPECT_EQ(1, pool_->IdleSocketCount());
- // After an SSL configuration change, we should have 0 idle sockets.
- session_deps_.ssl_config_service->NotifySSLContextConfigChange();
- base::RunLoop().RunUntilIdle(); // Notification happens async.
- EXPECT_EQ(0, pool_->IdleSocketCount());
- }
- TEST_F(TransportClientSocketPoolTest, BackupSocketConnect) {
- // Case 1 tests the first socket stalling, and the backup connecting.
- MockTransportClientSocketFactory::Rule rules1[] = {
- // The first socket will not connect.
- MockTransportClientSocketFactory::Rule(
- MockTransportClientSocketFactory::Type::kStalled),
- // The second socket will connect more quickly.
- MockTransportClientSocketFactory::Rule(
- MockTransportClientSocketFactory::Type::kSynchronous),
- };
- // Case 2 tests the first socket being slow, so that we start the
- // second connect, but the second connect stalls, and we still
- // complete the first.
- MockTransportClientSocketFactory::Rule rules2[] = {
- // The first socket will connect, although delayed.
- MockTransportClientSocketFactory::Rule(
- MockTransportClientSocketFactory::Type::kDelayed),
- // The second socket will not connect.
- MockTransportClientSocketFactory::Rule(
- MockTransportClientSocketFactory::Type::kStalled),
- };
- base::span<const MockTransportClientSocketFactory::Rule> cases[2] = {rules1,
- rules2};
- for (auto rules : cases) {
- client_socket_factory_.SetRules(rules);
- EXPECT_EQ(0, pool_->IdleSocketCount());
- TestCompletionCallback callback;
- ClientSocketHandle handle;
- int rv = handle.Init(
- group_id_, params_, absl::nullopt /* proxy_annotation_tag */, LOW,
- SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback.callback(), ClientSocketPool::ProxyAuthCallback(), pool_.get(),
- NetLogWithSource());
- EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
- EXPECT_FALSE(handle.is_initialized());
- EXPECT_FALSE(handle.socket());
- // Create the first socket, set the timer.
- base::RunLoop().RunUntilIdle();
- // Wait for the backup socket timer to fire.
- base::PlatformThread::Sleep(
- base::Milliseconds(ClientSocketPool::kMaxConnectRetryIntervalMs + 50));
- // Let the appropriate socket connect.
- base::RunLoop().RunUntilIdle();
- EXPECT_THAT(callback.WaitForResult(), IsOk());
- EXPECT_TRUE(handle.is_initialized());
- EXPECT_TRUE(handle.socket());
- // One socket is stalled, the other is active.
- EXPECT_EQ(0, pool_->IdleSocketCount());
- handle.Reset();
- // Close all pending connect jobs and existing sockets.
- pool_->FlushWithError(ERR_NETWORK_CHANGED, "Network changed");
- }
- }
- // Test the case where a socket took long enough to start the creation
- // of the backup socket, but then we cancelled the request after that.
- TEST_F(TransportClientSocketPoolTest, BackupSocketCancel) {
- client_socket_factory_.set_default_client_socket_type(
- MockTransportClientSocketFactory::Type::kStalled);
- enum { CANCEL_BEFORE_WAIT, CANCEL_AFTER_WAIT };
- for (int index = CANCEL_BEFORE_WAIT; index < CANCEL_AFTER_WAIT; ++index) {
- EXPECT_EQ(0, pool_->IdleSocketCount());
- TestCompletionCallback callback;
- ClientSocketHandle handle;
- int rv = handle.Init(
- group_id_, params_, absl::nullopt /* proxy_annotation_tag */, LOW,
- SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback.callback(), ClientSocketPool::ProxyAuthCallback(), pool_.get(),
- NetLogWithSource());
- EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
- EXPECT_FALSE(handle.is_initialized());
- EXPECT_FALSE(handle.socket());
- // Create the first socket, set the timer.
- base::RunLoop().RunUntilIdle();
- if (index == CANCEL_AFTER_WAIT) {
- // Wait for the backup socket timer to fire.
- base::PlatformThread::Sleep(
- base::Milliseconds(ClientSocketPool::kMaxConnectRetryIntervalMs));
- }
- // Let the appropriate socket connect.
- base::RunLoop().RunUntilIdle();
- handle.Reset();
- EXPECT_FALSE(callback.have_result());
- EXPECT_FALSE(handle.is_initialized());
- EXPECT_FALSE(handle.socket());
- // One socket is stalled, the other is active.
- EXPECT_EQ(0, pool_->IdleSocketCount());
- }
- }
- // Test the case where a socket took long enough to start the creation
- // of the backup socket and never completes, and then the backup
- // connection fails.
- TEST_F(TransportClientSocketPoolTest, BackupSocketFailAfterStall) {
- MockTransportClientSocketFactory::Rule rules[] = {
- // The first socket will not connect.
- MockTransportClientSocketFactory::Rule(
- MockTransportClientSocketFactory::Type::kStalled),
- // The second socket will fail immediately.
- MockTransportClientSocketFactory::Rule(
- MockTransportClientSocketFactory::Type::kFailing),
- };
- client_socket_factory_.SetRules(rules);
- EXPECT_EQ(0, pool_->IdleSocketCount());
- TestCompletionCallback callback;
- ClientSocketHandle handle;
- int rv =
- handle.Init(group_id_, params_, absl::nullopt /* proxy_annotation_tag */,
- LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback.callback(), ClientSocketPool::ProxyAuthCallback(),
- pool_.get(), NetLogWithSource());
- EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
- EXPECT_FALSE(handle.is_initialized());
- EXPECT_FALSE(handle.socket());
- // Create the first socket, set the timer.
- base::RunLoop().RunUntilIdle();
- // Wait for the backup socket timer to fire.
- base::PlatformThread::Sleep(
- base::Milliseconds(ClientSocketPool::kMaxConnectRetryIntervalMs));
- // Let the second connect be synchronous. Otherwise, the emulated
- // host resolution takes an extra trip through the message loop.
- session_deps_.host_resolver->set_synchronous_mode(true);
- // Let the appropriate socket connect.
- base::RunLoop().RunUntilIdle();
- EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_FAILED));
- EXPECT_FALSE(handle.is_initialized());
- EXPECT_FALSE(handle.socket());
- ASSERT_EQ(1u, handle.connection_attempts().size());
- EXPECT_THAT(handle.connection_attempts()[0].result,
- IsError(ERR_CONNECTION_FAILED));
- EXPECT_EQ(0, pool_->IdleSocketCount());
- handle.Reset();
- }
- // Test the case where a socket took long enough to start the creation
- // of the backup socket and eventually completes, but the backup socket
- // fails.
- TEST_F(TransportClientSocketPoolTest, BackupSocketFailAfterDelay) {
- MockTransportClientSocketFactory::Rule rules[] = {
- // The first socket will connect, although delayed.
- MockTransportClientSocketFactory::Rule(
- MockTransportClientSocketFactory::Type::kDelayed),
- // The second socket will not connect.
- MockTransportClientSocketFactory::Rule(
- MockTransportClientSocketFactory::Type::kFailing),
- };
- client_socket_factory_.SetRules(rules);
- client_socket_factory_.set_delay(base::Seconds(5));
- EXPECT_EQ(0, pool_->IdleSocketCount());
- TestCompletionCallback callback;
- ClientSocketHandle handle;
- int rv =
- handle.Init(group_id_, params_, absl::nullopt /* proxy_annotation_tag */,
- LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback.callback(), ClientSocketPool::ProxyAuthCallback(),
- pool_.get(), NetLogWithSource());
- EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
- EXPECT_FALSE(handle.is_initialized());
- EXPECT_FALSE(handle.socket());
- // Create the first socket, set the timer.
- base::RunLoop().RunUntilIdle();
- // Wait for the backup socket timer to fire.
- base::PlatformThread::Sleep(
- base::Milliseconds(ClientSocketPool::kMaxConnectRetryIntervalMs));
- // Let the second connect be synchronous. Otherwise, the emulated
- // host resolution takes an extra trip through the message loop.
- session_deps_.host_resolver->set_synchronous_mode(true);
- // Let the appropriate socket connect.
- base::RunLoop().RunUntilIdle();
- EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_FAILED));
- EXPECT_FALSE(handle.is_initialized());
- EXPECT_FALSE(handle.socket());
- ASSERT_EQ(1u, handle.connection_attempts().size());
- EXPECT_THAT(handle.connection_attempts()[0].result,
- IsError(ERR_CONNECTION_FAILED));
- handle.Reset();
- }
- // Test the case that SOCKSSocketParams are provided.
- TEST_F(TransportClientSocketPoolTest, SOCKS) {
- const url::SchemeHostPort kDestination(url::kHttpScheme, "host", 80);
- TransportClientSocketPool proxy_pool(
- kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout,
- ProxyUriToProxyServer("socks5://foopy",
- ProxyServer::SCHEME_HTTP /* default_scheme */),
- false /* is_for_websockets */, tagging_common_connect_job_params_.get());
- for (IoMode socket_io_mode : {SYNCHRONOUS, ASYNC}) {
- scoped_refptr<ClientSocketPool::SocketParams> socket_params =
- base::MakeRefCounted<ClientSocketPool::SocketParams>(
- nullptr /* ssl_config_for_origin */,
- nullptr /* ssl_config_for_proxy */);
- SOCKS5MockData data(socket_io_mode);
- data.data_provider()->set_connect_data(MockConnect(socket_io_mode, OK));
- tagging_client_socket_factory_.AddSocketDataProvider(data.data_provider());
- ClientSocketHandle handle;
- TestCompletionCallback callback;
- int rv = handle.Init(
- ClientSocketPool::GroupId(
- kDestination, PrivacyMode::PRIVACY_MODE_DISABLED,
- NetworkIsolationKey(), SecureDnsPolicy::kAllow),
- socket_params, TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
- ClientSocketPool::ProxyAuthCallback(), &proxy_pool, NetLogWithSource());
- EXPECT_THAT(callback.GetResult(rv), IsOk());
- EXPECT_TRUE(handle.is_initialized());
- EXPECT_TRUE(handle.socket());
- EXPECT_TRUE(data.data_provider()->AllReadDataConsumed());
- EXPECT_TRUE(data.data_provider()->AllWriteDataConsumed());
- }
- }
- // Make sure there's no crash when an auth challenge is received over HTTP2
- // and there are two pending Requests to the socket pool, with a single
- // ConnectJob.
- //
- // See https://crbug.com/940848
- TEST_F(TransportClientSocketPoolTest, SpdyOneConnectJobTwoRequestsError) {
- const url::SchemeHostPort kEndpoint(url::kHttpsScheme,
- "unresolvable.host.name", 443);
- session_deps_.host_resolver->set_synchronous_mode(true);
- // Create a socket pool which only allows a single connection at a time.
- TransportClientSocketPool pool(
- 1, 1, kUnusedIdleSocketTimeout,
- ProxyUriToProxyServer("https://unresolvable.proxy.name",
- ProxyServer::SCHEME_HTTP /* default_scheme */),
- false /* is_for_websockets */, tagging_common_connect_job_params_.get());
- // First connection attempt will get an error after creating the SpdyStream.
- SpdyTestUtil spdy_util;
- spdy::SpdySerializedFrame connect(spdy_util.ConstructSpdyConnect(
- nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
- HostPortPair::FromSchemeHostPort(kEndpoint)));
- MockWrite writes[] = {
- CreateMockWrite(connect, 0, ASYNC),
- MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 2),
- };
- MockRead reads[] = {
- MockRead(ASYNC, ERR_FAILED, 1),
- };
- SequencedSocketData socket_data(MockConnect(SYNCHRONOUS, OK), reads, writes);
- tagging_client_socket_factory_.AddSocketDataProvider(&socket_data);
- SSLSocketDataProvider ssl_data(SYNCHRONOUS, OK);
- ssl_data.next_proto = kProtoHTTP2;
- tagging_client_socket_factory_.AddSSLSocketDataProvider(&ssl_data);
- // Second connection also fails. Not a vital part of this test, but allows
- // waiting for the second request to complete without too much extra code.
- SequencedSocketData socket_data2(
- MockConnect(SYNCHRONOUS, ERR_CONNECTION_TIMED_OUT),
- base::span<const MockRead>(), base::span<const MockWrite>());
- tagging_client_socket_factory_.AddSocketDataProvider(&socket_data2);
- SSLSocketDataProvider ssl_data2(SYNCHRONOUS, OK);
- tagging_client_socket_factory_.AddSSLSocketDataProvider(&ssl_data2);
- scoped_refptr<ClientSocketPool::SocketParams> socket_params =
- base::MakeRefCounted<ClientSocketPool::SocketParams>(
- std::make_unique<SSLConfig>() /* ssl_config_for_origin */,
- std::make_unique<SSLConfig>() /* ssl_config_for_proxy */);
- ClientSocketPool::GroupId group_id(
- kEndpoint, PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
- SecureDnsPolicy::kAllow);
- // Start the first connection attempt.
- TestCompletionCallback callback1;
- ClientSocketHandle handle1;
- int rv1 = handle1.Init(
- group_id, socket_params, TRAFFIC_ANNOTATION_FOR_TESTS, HIGHEST,
- SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback1.callback(), ClientSocketPool::ProxyAuthCallback(), &pool,
- NetLogWithSource());
- ASSERT_THAT(rv1, IsError(ERR_IO_PENDING));
- // Create a second request with a lower priority.
- TestCompletionCallback callback2;
- ClientSocketHandle handle2;
- int rv2 = handle2.Init(
- group_id, socket_params, TRAFFIC_ANNOTATION_FOR_TESTS, LOWEST,
- SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback2.callback(), ClientSocketPool::ProxyAuthCallback(), &pool,
- NetLogWithSource());
- ASSERT_THAT(rv2, IsError(ERR_IO_PENDING));
- // First connection fails after creating a SpdySession and a SpdyStream on
- // that session. The SpdyStream will be destroyed under the
- // SpdyProxyClientSocket. The failure will result in temporarily assigning the
- // failed ConnectJob to the second request, which results in an unneeded
- // reprioritization, which should not dereference the null SpdyStream.
- //
- // TODO(mmenke): Avoid that temporary reassignment.
- ASSERT_THAT(callback1.WaitForResult(), IsError(ERR_FAILED));
- // Second connection fails, getting a connection error.
- ASSERT_THAT(callback2.WaitForResult(), IsError(ERR_PROXY_CONNECTION_FAILED));
- }
- // Make sure there's no crash when an auth challenge is received over HTTP2
- // and there are two pending Requests to the socket pool, with a single
- // ConnectJob.
- //
- // See https://crbug.com/940848
- TEST_F(TransportClientSocketPoolTest, SpdyAuthOneConnectJobTwoRequests) {
- const url::SchemeHostPort kEndpoint(url::kHttpsScheme,
- "unresolvable.host.name", 443);
- const HostPortPair kProxy("unresolvable.proxy.name", 443);
- session_deps_.host_resolver->set_synchronous_mode(true);
- // Create a socket pool which only allows a single connection at a time.
- TransportClientSocketPool pool(
- 1, 1, kUnusedIdleSocketTimeout,
- ProxyUriToProxyServer("https://unresolvable.proxy.name",
- ProxyServer::SCHEME_HTTP /* default_scheme */),
- false /* is_for_websockets */, tagging_common_connect_job_params_.get());
- SpdyTestUtil spdy_util;
- spdy::SpdySerializedFrame connect(spdy_util.ConstructSpdyConnect(
- nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
- HostPortPair::FromSchemeHostPort(kEndpoint)));
- MockWrite writes[] = {
- CreateMockWrite(connect, 0, ASYNC),
- MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 4),
- };
- // The proxy responds to the connect with a 407, and them an
- // ERROR_CODE_HTTP_1_1_REQUIRED.
- const char kAuthStatus[] = "407";
- const char* const kAuthChallenge[] = {
- "proxy-authenticate",
- "NTLM",
- };
- spdy::SpdySerializedFrame connect_auth_resp(spdy_util.ConstructSpdyReplyError(
- kAuthStatus, kAuthChallenge, std::size(kAuthChallenge) / 2, 1));
- spdy::SpdySerializedFrame reset(
- spdy_util.ConstructSpdyRstStream(1, spdy::ERROR_CODE_HTTP_1_1_REQUIRED));
- MockRead reads[] = {
- CreateMockRead(connect_auth_resp, 1, ASYNC),
- CreateMockRead(reset, 2, SYNCHRONOUS),
- MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
- };
- SequencedSocketData socket_data(MockConnect(SYNCHRONOUS, OK), reads, writes);
- tagging_client_socket_factory_.AddSocketDataProvider(&socket_data);
- SSLSocketDataProvider ssl_data(SYNCHRONOUS, OK);
- ssl_data.next_proto = kProtoHTTP2;
- tagging_client_socket_factory_.AddSSLSocketDataProvider(&ssl_data);
- // Second connection fails, and gets a different error. Not a vital part of
- // this test, but allows waiting for the second request to complete without
- // too much extra code.
- SequencedSocketData socket_data2(
- MockConnect(SYNCHRONOUS, ERR_CONNECTION_TIMED_OUT),
- base::span<const MockRead>(), base::span<const MockWrite>());
- tagging_client_socket_factory_.AddSocketDataProvider(&socket_data2);
- SSLSocketDataProvider ssl_data2(SYNCHRONOUS, OK);
- tagging_client_socket_factory_.AddSSLSocketDataProvider(&ssl_data2);
- scoped_refptr<ClientSocketPool::SocketParams> socket_params =
- base::MakeRefCounted<ClientSocketPool::SocketParams>(
- std::make_unique<SSLConfig>() /* ssl_config_for_origin */,
- std::make_unique<SSLConfig>() /* ssl_config_for_proxy */);
- ClientSocketPool::GroupId group_id(
- kEndpoint, PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
- SecureDnsPolicy::kAllow);
- // Start the first connection attempt.
- TestCompletionCallback callback1;
- ClientSocketHandle handle1;
- base::RunLoop run_loop;
- int rv1 = handle1.Init(group_id, socket_params, TRAFFIC_ANNOTATION_FOR_TESTS,
- HIGHEST, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED,
- callback1.callback(),
- base::BindLambdaForTesting(
- [&](const HttpResponseInfo& response,
- HttpAuthController* auth_controller,
- base::OnceClosure restart_with_auth_callback) {
- run_loop.Quit();
- }),
- &pool, NetLogWithSource());
- ASSERT_THAT(rv1, IsError(ERR_IO_PENDING));
- // Create a second request with a lower priority.
- TestCompletionCallback callback2;
- ClientSocketHandle handle2;
- int rv2 = handle2.Init(
- group_id, socket_params, TRAFFIC_ANNOTATION_FOR_TESTS, LOWEST,
- SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback2.callback(), ClientSocketPool::ProxyAuthCallback(), &pool,
- NetLogWithSource());
- ASSERT_THAT(rv2, IsError(ERR_IO_PENDING));
- // The ConnectJob connection sees the auth challenge and HTTP2 error, which
- // causes the SpdySession to be destroyed, as well as the SpdyStream. Then the
- // ConnectJob is bound to the first request. Binding the request will result
- // in temporarily assigning the ConnectJob to the second request, which
- // results in an unneeded reprioritization, which should not dereference the
- // null SpdyStream.
- //
- // TODO(mmenke): Avoid that temporary reassignment.
- run_loop.Run();
- // Just tear down everything without continuing - there are other tests for
- // auth over HTTP2.
- }
- TEST_F(TransportClientSocketPoolTest, HttpTunnelSetupRedirect) {
- const url::SchemeHostPort kEndpoint(url::kHttpsScheme, "host.test", 443);
- const std::string kRedirectTarget = "https://some.other.host.test/";
- const std::string kResponseText =
- "HTTP/1.1 302 Found\r\n"
- "Location: " +
- kRedirectTarget +
- "\r\n"
- "Set-Cookie: foo=bar\r\n"
- "\r\n";
- for (IoMode io_mode : {SYNCHRONOUS, ASYNC}) {
- SCOPED_TRACE(io_mode);
- session_deps_.host_resolver->set_synchronous_mode(io_mode == SYNCHRONOUS);
- for (bool use_https_proxy : {false, true}) {
- SCOPED_TRACE(use_https_proxy);
- TransportClientSocketPool proxy_pool(
- kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout,
- ProxyUriToProxyServer(
- use_https_proxy ? "https://proxy.test" : "http://proxy.test",
- ProxyServer::SCHEME_HTTP /* default_scheme */),
- false /* is_for_websockets */,
- tagging_common_connect_job_params_.get());
- MockWrite writes[] = {
- MockWrite(ASYNC, 0,
- "CONNECT host.test:443 HTTP/1.1\r\n"
- "Host: host.test:443\r\n"
- "Proxy-Connection: keep-alive\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(ASYNC, 1, kResponseText.c_str()),
- };
- SequencedSocketData data(reads, writes);
- tagging_client_socket_factory_.AddSocketDataProvider(&data);
- SSLSocketDataProvider ssl(ASYNC, OK);
- tagging_client_socket_factory_.AddSSLSocketDataProvider(&ssl);
- ClientSocketHandle handle;
- TestCompletionCallback callback;
- scoped_refptr<ClientSocketPool::SocketParams> socket_params =
- base::MakeRefCounted<ClientSocketPool::SocketParams>(
- std::make_unique<SSLConfig>() /* ssl_config_for_origin */,
- std::make_unique<SSLConfig>() /* ssl_config_for_proxy */);
- int rv = handle.Init(
- ClientSocketPool::GroupId(
- kEndpoint, PrivacyMode::PRIVACY_MODE_DISABLED,
- NetworkIsolationKey(), SecureDnsPolicy::kAllow),
- socket_params, TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
- ClientSocketPool::ProxyAuthCallback(), &proxy_pool,
- NetLogWithSource());
- rv = callback.GetResult(rv);
- // We don't trust 302 responses to CONNECT.
- EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
- EXPECT_FALSE(handle.is_initialized());
- }
- }
- }
- TEST_F(TransportClientSocketPoolTest, NetworkIsolationKey) {
- const SchemefulSite kSite(GURL("https://foo.test/"));
- const NetworkIsolationKey kNetworkIsolationKey(kSite, kSite);
- const char kHost[] = "bar.test";
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitWithFeatures(
- // enabled_features
- {features::kPartitionConnectionsByNetworkIsolationKey,
- features::kSplitHostCacheByNetworkIsolationKey},
- // disabled_features
- {});
- session_deps_.host_resolver->set_ondemand_mode(true);
- TransportClientSocketPool::GroupId group_id(
- url::SchemeHostPort(url::kHttpScheme, kHost, 80),
- PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey,
- SecureDnsPolicy::kAllow);
- ClientSocketHandle handle;
- TestCompletionCallback callback;
- EXPECT_THAT(
- handle.Init(group_id,
- base::MakeRefCounted<ClientSocketPool::SocketParams>(
- nullptr /* ssl_config_for_origin */,
- nullptr /* ssl_config_for_proxy */),
- TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
- ClientSocketPool::ProxyAuthCallback(), pool_.get(),
- NetLogWithSource()),
- IsError(ERR_IO_PENDING));
- ASSERT_EQ(1u, session_deps_.host_resolver->last_id());
- EXPECT_EQ(kHost, session_deps_.host_resolver->request_host(1));
- EXPECT_EQ(kNetworkIsolationKey,
- session_deps_.host_resolver->request_network_isolation_key(1));
- }
- TEST_F(TransportClientSocketPoolTest, NetworkIsolationKeySsl) {
- const SchemefulSite kSite(GURL("https://foo.test/"));
- const NetworkIsolationKey kNetworkIsolationKey(kSite, kSite);
- const char kHost[] = "bar.test";
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitWithFeatures(
- // enabled_features
- {features::kPartitionConnectionsByNetworkIsolationKey,
- features::kSplitHostCacheByNetworkIsolationKey},
- // disabled_features
- {});
- session_deps_.host_resolver->set_ondemand_mode(true);
- TransportClientSocketPool::GroupId group_id(
- url::SchemeHostPort(url::kHttpsScheme, kHost, 443),
- PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey,
- SecureDnsPolicy::kAllow);
- auto ssl_config_for_origin = std::make_unique<SSLConfig>();
- ssl_config_for_origin->alpn_protos = {kProtoHTTP2, kProtoHTTP11};
- ClientSocketHandle handle;
- TestCompletionCallback callback;
- EXPECT_THAT(
- handle.Init(group_id,
- base::MakeRefCounted<ClientSocketPool::SocketParams>(
- std::move(ssl_config_for_origin),
- /*ssl_config_for_proxy=*/nullptr),
- TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
- ClientSocketPool::ProxyAuthCallback(), pool_.get(),
- NetLogWithSource()),
- IsError(ERR_IO_PENDING));
- ASSERT_EQ(1u, session_deps_.host_resolver->last_id());
- EXPECT_EQ(kHost, session_deps_.host_resolver->request_host(1));
- EXPECT_EQ(kNetworkIsolationKey,
- session_deps_.host_resolver->request_network_isolation_key(1));
- }
- // Test that, in the case of an HTTP proxy, the same transient
- // NetworkIsolationKey is reused for resolving the proxy's host, regardless of
- // input NIK.
- TEST_F(TransportClientSocketPoolTest, NetworkIsolationKeyHttpProxy) {
- const SchemefulSite kSite1(GURL("https://foo.test/"));
- const NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
- const SchemefulSite kSite2(GURL("https://bar.test/"));
- const NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
- const char kHost[] = "bar.test";
- const ProxyServer kProxyServer = ProxyUriToProxyServer(
- "http://proxy.test", ProxyServer::SCHEME_HTTP /* default_scheme */);
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitWithFeatures(
- // enabled_features
- {features::kPartitionConnectionsByNetworkIsolationKey,
- features::kSplitHostCacheByNetworkIsolationKey},
- // disabled_features
- {});
- session_deps_.host_resolver->set_ondemand_mode(true);
- TransportClientSocketPool proxy_pool(
- kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout, kProxyServer,
- false /* is_for_websockets */, tagging_common_connect_job_params_.get());
- TransportClientSocketPool::GroupId group_id1(
- url::SchemeHostPort(url::kHttpScheme, kHost, 80),
- PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey1,
- SecureDnsPolicy::kAllow);
- ClientSocketHandle handle1;
- TestCompletionCallback callback1;
- EXPECT_THAT(
- handle1.Init(group_id1,
- base::MakeRefCounted<ClientSocketPool::SocketParams>(
- nullptr /* ssl_config_for_origin */,
- nullptr /* ssl_config_for_proxy */),
- TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED,
- callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
- &proxy_pool, NetLogWithSource()),
- IsError(ERR_IO_PENDING));
- TransportClientSocketPool::GroupId group_id2(
- url::SchemeHostPort(url::kHttpScheme, kHost, 80),
- PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey2,
- SecureDnsPolicy::kAllow);
- ClientSocketHandle handle2;
- TestCompletionCallback callback2;
- EXPECT_THAT(
- handle2.Init(group_id2,
- base::MakeRefCounted<ClientSocketPool::SocketParams>(
- nullptr /* ssl_config_for_origin */,
- nullptr /* ssl_config_for_proxy */),
- TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED,
- callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
- &proxy_pool, NetLogWithSource()),
- IsError(ERR_IO_PENDING));
- ASSERT_EQ(2u, session_deps_.host_resolver->last_id());
- EXPECT_EQ(kProxyServer.host_port_pair().host(),
- session_deps_.host_resolver->request_host(1));
- EXPECT_EQ(kProxyServer.host_port_pair().host(),
- session_deps_.host_resolver->request_host(2));
- EXPECT_TRUE(session_deps_.host_resolver->request_network_isolation_key(1)
- .IsTransient());
- EXPECT_EQ(session_deps_.host_resolver->request_network_isolation_key(1),
- session_deps_.host_resolver->request_network_isolation_key(2));
- }
- // Test that, in the case of an HTTPS proxy, the same transient
- // NetworkIsolationKey is reused for resolving the proxy's host, regardless of
- // input NIK.
- TEST_F(TransportClientSocketPoolTest, NetworkIsolationKeyHttpsProxy) {
- const SchemefulSite kSite1(GURL("https://foo.test/"));
- const NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
- const SchemefulSite kSite2(GURL("https://bar.test/"));
- const NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
- const char kHost[] = "bar.test";
- const ProxyServer kProxyServer = ProxyUriToProxyServer(
- "https://proxy.test", ProxyServer::SCHEME_HTTP /* default_scheme */);
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitWithFeatures(
- // enabled_features
- {features::kPartitionConnectionsByNetworkIsolationKey,
- features::kSplitHostCacheByNetworkIsolationKey},
- // disabled_features
- {});
- session_deps_.host_resolver->set_ondemand_mode(true);
- TransportClientSocketPool proxy_pool(
- kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout, kProxyServer,
- false /* is_for_websockets */, tagging_common_connect_job_params_.get());
- TransportClientSocketPool::GroupId group_id1(
- url::SchemeHostPort(url::kHttpScheme, kHost, 80),
- PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey1,
- SecureDnsPolicy::kAllow);
- ClientSocketHandle handle1;
- TestCompletionCallback callback1;
- EXPECT_THAT(handle1.Init(
- group_id1,
- base::MakeRefCounted<ClientSocketPool::SocketParams>(
- nullptr /* ssl_config_for_origin */,
- std::make_unique<SSLConfig>() /* ssl_config_for_proxy */),
- TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED,
- callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
- &proxy_pool, NetLogWithSource()),
- IsError(ERR_IO_PENDING));
- TransportClientSocketPool::GroupId group_id2(
- url::SchemeHostPort(url::kHttpScheme, kHost, 80),
- PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey2,
- SecureDnsPolicy::kAllow);
- ClientSocketHandle handle2;
- TestCompletionCallback callback2;
- EXPECT_THAT(handle2.Init(
- group_id2,
- base::MakeRefCounted<ClientSocketPool::SocketParams>(
- nullptr /* ssl_config_for_origin */,
- std::make_unique<SSLConfig>() /* ssl_config_for_proxy */),
- TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED,
- callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
- &proxy_pool, NetLogWithSource()),
- IsError(ERR_IO_PENDING));
- ASSERT_EQ(2u, session_deps_.host_resolver->last_id());
- EXPECT_EQ(kProxyServer.host_port_pair().host(),
- session_deps_.host_resolver->request_host(1));
- EXPECT_EQ(kProxyServer.host_port_pair().host(),
- session_deps_.host_resolver->request_host(2));
- EXPECT_TRUE(session_deps_.host_resolver->request_network_isolation_key(1)
- .IsTransient());
- EXPECT_EQ(session_deps_.host_resolver->request_network_isolation_key(1),
- session_deps_.host_resolver->request_network_isolation_key(2));
- }
- // Test that, in the case of a SOCKS5 proxy, the passed in NetworkIsolationKey
- // is used for the destination DNS lookup, and the same transient
- // NetworkIsolationKey is reused for resolving the proxy's host, regardless of
- // input NIK.
- TEST_F(TransportClientSocketPoolTest, NetworkIsolationKeySocks4Proxy) {
- const SchemefulSite kSite1(GURL("https://foo.test/"));
- const NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
- const SchemefulSite kSite2(GURL("https://bar.test/"));
- const NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
- const char kHost[] = "bar.test";
- const ProxyServer kProxyServer = ProxyUriToProxyServer(
- "socks4://proxy.test", ProxyServer::SCHEME_HTTP /* default_scheme */);
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitWithFeatures(
- // enabled_features
- {features::kPartitionConnectionsByNetworkIsolationKey,
- features::kSplitHostCacheByNetworkIsolationKey},
- // disabled_features
- {});
- session_deps_.host_resolver->set_ondemand_mode(true);
- // Test will establish two connections, but never use them to transfer data,
- // since thet stall on the followup DNS lookups.
- StaticSocketDataProvider data1;
- data1.set_connect_data(MockConnect(SYNCHRONOUS, OK));
- tagging_client_socket_factory_.AddSocketDataProvider(&data1);
- StaticSocketDataProvider data2;
- data2.set_connect_data(MockConnect(SYNCHRONOUS, OK));
- tagging_client_socket_factory_.AddSocketDataProvider(&data2);
- TransportClientSocketPool proxy_pool(
- kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout, kProxyServer,
- false /* is_for_websockets */, tagging_common_connect_job_params_.get());
- TransportClientSocketPool::GroupId group_id1(
- url::SchemeHostPort(url::kHttpScheme, kHost, 80),
- PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey1,
- SecureDnsPolicy::kAllow);
- ClientSocketHandle handle1;
- TestCompletionCallback callback1;
- EXPECT_THAT(
- handle1.Init(group_id1,
- base::MakeRefCounted<ClientSocketPool::SocketParams>(
- nullptr /* ssl_config_for_origin */,
- nullptr /* ssl_config_for_proxy */),
- TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED,
- callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
- &proxy_pool, NetLogWithSource()),
- IsError(ERR_IO_PENDING));
- TransportClientSocketPool::GroupId group_id2(
- url::SchemeHostPort(url::kHttpScheme, kHost, 80),
- PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey2,
- SecureDnsPolicy::kAllow);
- ClientSocketHandle handle2;
- TestCompletionCallback callback2;
- EXPECT_THAT(
- handle2.Init(group_id2,
- base::MakeRefCounted<ClientSocketPool::SocketParams>(
- nullptr /* ssl_config_for_origin */,
- nullptr /* ssl_config_for_proxy */),
- TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED,
- callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
- &proxy_pool, NetLogWithSource()),
- IsError(ERR_IO_PENDING));
- // First two lookups are for the proxy's hostname, and should use the same
- // transient NIK.
- ASSERT_EQ(2u, session_deps_.host_resolver->last_id());
- EXPECT_EQ(kProxyServer.host_port_pair().host(),
- session_deps_.host_resolver->request_host(1));
- EXPECT_EQ(kProxyServer.host_port_pair().host(),
- session_deps_.host_resolver->request_host(2));
- EXPECT_TRUE(session_deps_.host_resolver->request_network_isolation_key(1)
- .IsTransient());
- EXPECT_EQ(session_deps_.host_resolver->request_network_isolation_key(1),
- session_deps_.host_resolver->request_network_isolation_key(2));
- // First two lookups completes, starting the next two, which should be for the
- // destination's hostname, and should use the passed in NIKs.
- session_deps_.host_resolver->ResolveNow(1);
- session_deps_.host_resolver->ResolveNow(2);
- ASSERT_EQ(4u, session_deps_.host_resolver->last_id());
- EXPECT_EQ(kHost, session_deps_.host_resolver->request_host(3));
- EXPECT_EQ(kNetworkIsolationKey1,
- session_deps_.host_resolver->request_network_isolation_key(3));
- EXPECT_EQ(kHost, session_deps_.host_resolver->request_host(4));
- EXPECT_EQ(kNetworkIsolationKey2,
- session_deps_.host_resolver->request_network_isolation_key(4));
- }
- // Test that, in the case of a SOCKS5 proxy, the same transient
- // NetworkIsolationKey is reused for resolving the proxy's host, regardless of
- // input NIK.
- TEST_F(TransportClientSocketPoolTest, NetworkIsolationKeySocks5Proxy) {
- const SchemefulSite kSite1(GURL("https://foo.test/"));
- const NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
- const SchemefulSite kSite2(GURL("https://bar.test/"));
- const NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
- const char kHost[] = "bar.test";
- const ProxyServer kProxyServer = ProxyUriToProxyServer(
- "socks5://proxy.test", ProxyServer::SCHEME_HTTP /* default_scheme */);
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitWithFeatures(
- // enabled_features
- {features::kPartitionConnectionsByNetworkIsolationKey,
- features::kSplitHostCacheByNetworkIsolationKey},
- // disabled_features
- {});
- session_deps_.host_resolver->set_ondemand_mode(true);
- TransportClientSocketPool proxy_pool(
- kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout, kProxyServer,
- false /* is_for_websockets */, tagging_common_connect_job_params_.get());
- TransportClientSocketPool::GroupId group_id1(
- url::SchemeHostPort(url::kHttpScheme, kHost, 80),
- PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey1,
- SecureDnsPolicy::kAllow);
- ClientSocketHandle handle1;
- TestCompletionCallback callback1;
- EXPECT_THAT(
- handle1.Init(group_id1,
- base::MakeRefCounted<ClientSocketPool::SocketParams>(
- nullptr /* ssl_config_for_origin */,
- nullptr /* ssl_config_for_proxy */),
- TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED,
- callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
- &proxy_pool, NetLogWithSource()),
- IsError(ERR_IO_PENDING));
- TransportClientSocketPool::GroupId group_id2(
- url::SchemeHostPort(url::kHttpScheme, kHost, 80),
- PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey2,
- SecureDnsPolicy::kAllow);
- ClientSocketHandle handle2;
- TestCompletionCallback callback2;
- EXPECT_THAT(
- handle2.Init(group_id2,
- base::MakeRefCounted<ClientSocketPool::SocketParams>(
- nullptr /* ssl_config_for_origin */,
- nullptr /* ssl_config_for_proxy */),
- TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED,
- callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
- &proxy_pool, NetLogWithSource()),
- IsError(ERR_IO_PENDING));
- ASSERT_EQ(2u, session_deps_.host_resolver->last_id());
- EXPECT_EQ(kProxyServer.host_port_pair().host(),
- session_deps_.host_resolver->request_host(1));
- EXPECT_EQ(kProxyServer.host_port_pair().host(),
- session_deps_.host_resolver->request_host(2));
- EXPECT_TRUE(session_deps_.host_resolver->request_network_isolation_key(1)
- .IsTransient());
- EXPECT_EQ(session_deps_.host_resolver->request_network_isolation_key(1),
- session_deps_.host_resolver->request_network_isolation_key(2));
- }
- TEST_F(TransportClientSocketPoolTest, HasActiveSocket) {
- const url::SchemeHostPort kEndpoint1(url::kHttpScheme, "host1.test", 80);
- const url::SchemeHostPort kEndpoint2(url::kHttpScheme, "host2.test", 80);
- ClientSocketHandle handle;
- ClientSocketPool::GroupId group_id1(
- kEndpoint1, PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
- SecureDnsPolicy::kAllow);
- ClientSocketPool::GroupId group_id2(
- kEndpoint2, PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
- SecureDnsPolicy::kAllow);
- // HasActiveSocket() must return false before creating a socket.
- EXPECT_FALSE(pool_->HasActiveSocket(group_id1));
- TestCompletionCallback callback1;
- int rv1 =
- handle.Init(group_id1, params_, absl::nullopt /* proxy_annotation_tag */,
- LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
- pool_.get(), NetLogWithSource());
- EXPECT_THAT(rv1, IsError(ERR_IO_PENDING));
- // HasActiveSocket() must return true while connecting.
- EXPECT_TRUE(pool_->HasActiveSocket(group_id1));
- EXPECT_FALSE(handle.is_initialized());
- EXPECT_FALSE(handle.socket());
- EXPECT_THAT(callback1.WaitForResult(), IsOk());
- // HasActiveSocket() must return true after handed out.
- EXPECT_TRUE(pool_->HasActiveSocket(group_id1));
- EXPECT_TRUE(handle.is_initialized());
- EXPECT_TRUE(handle.socket());
- handle.Reset();
- // HasActiveSocket returns true for the idle socket.
- EXPECT_TRUE(pool_->HasActiveSocket(group_id1));
- // Now we should have 1 idle socket.
- EXPECT_EQ(1, pool_->IdleSocketCount());
- // HasActiveSocket() for group_id2 must still return false.
- EXPECT_FALSE(pool_->HasActiveSocket(group_id2));
- TestCompletionCallback callback2;
- int rv2 =
- handle.Init(group_id2, params_, absl::nullopt /* proxy_annotation_tag */,
- LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
- pool_.get(), NetLogWithSource());
- EXPECT_THAT(rv2, IsError(ERR_IO_PENDING));
- // HasActiveSocket(group_id2) must return true while connecting.
- EXPECT_TRUE(pool_->HasActiveSocket(group_id2));
- // HasActiveSocket(group_id1) must still return true.
- EXPECT_TRUE(pool_->HasActiveSocket(group_id2));
- // Close the sockets.
- pool_->FlushWithError(ERR_NETWORK_CHANGED, "Network changed");
- // HasActiveSocket() must return false after closing the socket.
- EXPECT_FALSE(pool_->HasActiveSocket(group_id1));
- EXPECT_FALSE(pool_->HasActiveSocket(group_id2));
- }
- // Test that SocketTag passed into TransportClientSocketPool is applied to
- // returned sockets.
- #if BUILDFLAG(IS_ANDROID)
- TEST_F(TransportClientSocketPoolTest, Tag) {
- if (!CanGetTaggedBytes()) {
- DVLOG(0) << "Skipping test - GetTaggedBytes unsupported.";
- return;
- }
- // Start test server.
- EmbeddedTestServer test_server;
- test_server.AddDefaultHandlers(base::FilePath());
- ASSERT_TRUE(test_server.Start());
- ClientSocketHandle handle;
- int32_t tag_val1 = 0x12345678;
- SocketTag tag1(SocketTag::UNSET_UID, tag_val1);
- int32_t tag_val2 = 0x87654321;
- SocketTag tag2(getuid(), tag_val2);
- // Test socket is tagged before connected.
- uint64_t old_traffic = GetTaggedBytes(tag_val1);
- const ClientSocketPool::GroupId kGroupId(
- url::SchemeHostPort(test_server.base_url()),
- PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
- SecureDnsPolicy::kAllow);
- scoped_refptr<ClientSocketPool::SocketParams> params =
- ClientSocketPool::SocketParams::CreateForHttpForTesting();
- TestCompletionCallback callback;
- int rv =
- handle.Init(kGroupId, params, absl::nullopt /* proxy_annotation_tag */,
- LOW, tag1, ClientSocketPool::RespectLimits::ENABLED,
- callback.callback(), ClientSocketPool::ProxyAuthCallback(),
- pool_for_real_sockets_.get(), NetLogWithSource());
- EXPECT_THAT(callback.GetResult(rv), IsOk());
- EXPECT_TRUE(handle.socket());
- EXPECT_TRUE(handle.socket()->IsConnected());
- EXPECT_GT(GetTaggedBytes(tag_val1), old_traffic);
- // Test reused socket is retagged.
- StreamSocket* socket = handle.socket();
- handle.Reset();
- old_traffic = GetTaggedBytes(tag_val2);
- rv = handle.Init(kGroupId, params, absl::nullopt /* proxy_annotation_tag */,
- LOW, tag2, ClientSocketPool::RespectLimits::ENABLED,
- callback.callback(), ClientSocketPool::ProxyAuthCallback(),
- pool_for_real_sockets_.get(), NetLogWithSource());
- EXPECT_THAT(rv, IsOk());
- EXPECT_TRUE(handle.socket());
- EXPECT_TRUE(handle.socket()->IsConnected());
- EXPECT_EQ(handle.socket(), socket);
- const char kRequest[] = "GET / HTTP/1.0\n\n";
- scoped_refptr<IOBuffer> write_buffer =
- base::MakeRefCounted<StringIOBuffer>(kRequest);
- rv =
- handle.socket()->Write(write_buffer.get(), strlen(kRequest),
- callback.callback(), TRAFFIC_ANNOTATION_FOR_TESTS);
- EXPECT_EQ(static_cast<int>(strlen(kRequest)), callback.GetResult(rv));
- EXPECT_GT(GetTaggedBytes(tag_val2), old_traffic);
- // Disconnect socket to prevent reuse.
- handle.socket()->Disconnect();
- handle.Reset();
- // Test connect jobs that are orphaned and then adopted, appropriately apply
- // new tag. Request socket with |tag1|.
- TestCompletionCallback callback2;
- rv = handle.Init(kGroupId, params, absl::nullopt /* proxy_annotation_tag */,
- LOW, tag1, ClientSocketPool::RespectLimits::ENABLED,
- callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
- pool_for_real_sockets_.get(), NetLogWithSource());
- EXPECT_TRUE(rv == OK || rv == ERR_IO_PENDING) << "Result: " << rv;
- // Abort and request socket with |tag2|.
- handle.Reset();
- rv = handle.Init(kGroupId, params, absl::nullopt /* proxy_annotation_tag */,
- LOW, tag2, ClientSocketPool::RespectLimits::ENABLED,
- callback.callback(), ClientSocketPool::ProxyAuthCallback(),
- pool_for_real_sockets_.get(), NetLogWithSource());
- EXPECT_THAT(callback.GetResult(rv), IsOk());
- EXPECT_TRUE(handle.socket());
- EXPECT_TRUE(handle.socket()->IsConnected());
- // Verify socket has |tag2| applied.
- old_traffic = GetTaggedBytes(tag_val2);
- rv =
- handle.socket()->Write(write_buffer.get(), strlen(kRequest),
- callback.callback(), TRAFFIC_ANNOTATION_FOR_TESTS);
- EXPECT_EQ(static_cast<int>(strlen(kRequest)), callback.GetResult(rv));
- EXPECT_GT(GetTaggedBytes(tag_val2), old_traffic);
- // Disconnect socket to prevent reuse.
- handle.socket()->Disconnect();
- handle.Reset();
- // Eat the left over connect job from the second request.
- // TODO(pauljensen): remove when crbug.com/800731 fixed.
- rv = handle.Init(kGroupId, params, absl::nullopt /* proxy_annotation_tag */,
- LOW, tag1, ClientSocketPool::RespectLimits::ENABLED,
- callback.callback(), ClientSocketPool::ProxyAuthCallback(),
- pool_for_real_sockets_.get(), NetLogWithSource());
- EXPECT_THAT(rv, IsOk());
- // Disconnect socket to prevent reuse.
- handle.socket()->Disconnect();
- handle.Reset();
- // Test two connect jobs of differing priorities. Start the lower priority one
- // first but expect its socket to get vended to the higher priority request.
- ClientSocketHandle handle_high_pri;
- TestCompletionCallback callback_high_pri;
- rv = handle.Init(kGroupId, params, absl::nullopt /* proxy_annotation_tag */,
- LOW, tag1, ClientSocketPool::RespectLimits::ENABLED,
- callback.callback(), ClientSocketPool::ProxyAuthCallback(),
- pool_for_real_sockets_.get(), NetLogWithSource());
- EXPECT_TRUE(rv == OK || rv == ERR_IO_PENDING) << "Result: " << rv;
- int rv_high_pri = handle_high_pri.Init(
- kGroupId, params, absl::nullopt /* proxy_annotation_tag */, HIGHEST, tag2,
- ClientSocketPool::RespectLimits::ENABLED, callback_high_pri.callback(),
- ClientSocketPool::ProxyAuthCallback(), pool_for_real_sockets_.get(),
- NetLogWithSource());
- EXPECT_THAT(callback_high_pri.GetResult(rv_high_pri), IsOk());
- EXPECT_TRUE(handle_high_pri.socket());
- EXPECT_TRUE(handle_high_pri.socket()->IsConnected());
- EXPECT_THAT(callback.GetResult(rv), IsOk());
- EXPECT_TRUE(handle.socket());
- EXPECT_TRUE(handle.socket()->IsConnected());
- // Verify |handle_high_pri| has |tag2| applied.
- old_traffic = GetTaggedBytes(tag_val2);
- rv = handle_high_pri.socket()->Write(write_buffer.get(), strlen(kRequest),
- callback.callback(),
- TRAFFIC_ANNOTATION_FOR_TESTS);
- EXPECT_EQ(static_cast<int>(strlen(kRequest)), callback.GetResult(rv));
- EXPECT_GT(GetTaggedBytes(tag_val2), old_traffic);
- // Verify |handle| has |tag1| applied.
- old_traffic = GetTaggedBytes(tag_val1);
- rv =
- handle.socket()->Write(write_buffer.get(), strlen(kRequest),
- callback.callback(), TRAFFIC_ANNOTATION_FOR_TESTS);
- EXPECT_EQ(static_cast<int>(strlen(kRequest)), callback.GetResult(rv));
- EXPECT_GT(GetTaggedBytes(tag_val1), old_traffic);
- }
- TEST_F(TransportClientSocketPoolTest, TagSOCKSProxy) {
- session_deps_.host_resolver->set_synchronous_mode(true);
- TransportClientSocketPool proxy_pool(
- kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout,
- ProxyUriToProxyServer("socks5://proxy",
- ProxyServer::SCHEME_HTTP /* default_scheme */),
- false /* is_for_websockets */, tagging_common_connect_job_params_.get());
- SocketTag tag1(SocketTag::UNSET_UID, 0x12345678);
- SocketTag tag2(getuid(), 0x87654321);
- const url::SchemeHostPort kDestination(url::kHttpScheme, "host", 80);
- const ClientSocketPool::GroupId kGroupId(
- kDestination, PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
- SecureDnsPolicy::kAllow);
- scoped_refptr<ClientSocketPool::SocketParams> socks_params =
- base::MakeRefCounted<ClientSocketPool::SocketParams>(
- nullptr /* ssl_config_for_origin */,
- nullptr /* ssl_config_for_proxy */);
- // Test socket is tagged when created synchronously.
- SOCKS5MockData data_sync(SYNCHRONOUS);
- data_sync.data_provider()->set_connect_data(MockConnect(SYNCHRONOUS, OK));
- tagging_client_socket_factory_.AddSocketDataProvider(
- data_sync.data_provider());
- ClientSocketHandle handle;
- int rv = handle.Init(
- kGroupId, socks_params, TRAFFIC_ANNOTATION_FOR_TESTS, LOW, tag1,
- ClientSocketPool::RespectLimits::ENABLED, CompletionOnceCallback(),
- ClientSocketPool::ProxyAuthCallback(), &proxy_pool, NetLogWithSource());
- EXPECT_THAT(rv, IsOk());
- EXPECT_TRUE(handle.is_initialized());
- EXPECT_TRUE(handle.socket());
- EXPECT_EQ(tagging_client_socket_factory_.GetLastProducedTCPSocket()->tag(),
- tag1);
- EXPECT_TRUE(tagging_client_socket_factory_.GetLastProducedTCPSocket()
- ->tagged_before_connected());
- // Test socket is tagged when reused synchronously.
- StreamSocket* socket = handle.socket();
- handle.Reset();
- rv = handle.Init(
- kGroupId, socks_params, TRAFFIC_ANNOTATION_FOR_TESTS, LOW, tag2,
- ClientSocketPool::RespectLimits::ENABLED, CompletionOnceCallback(),
- ClientSocketPool::ProxyAuthCallback(), &proxy_pool, NetLogWithSource());
- EXPECT_THAT(rv, IsOk());
- EXPECT_TRUE(handle.socket());
- EXPECT_TRUE(handle.socket()->IsConnected());
- EXPECT_EQ(handle.socket(), socket);
- EXPECT_EQ(tagging_client_socket_factory_.GetLastProducedTCPSocket()->tag(),
- tag2);
- handle.socket()->Disconnect();
- handle.Reset();
- // Test socket is tagged when created asynchronously.
- SOCKS5MockData data_async(ASYNC);
- tagging_client_socket_factory_.AddSocketDataProvider(
- data_async.data_provider());
- TestCompletionCallback callback;
- rv = handle.Init(kGroupId, socks_params, TRAFFIC_ANNOTATION_FOR_TESTS, LOW,
- tag1, ClientSocketPool::RespectLimits::ENABLED,
- callback.callback(), ClientSocketPool::ProxyAuthCallback(),
- &proxy_pool, NetLogWithSource());
- EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
- EXPECT_THAT(callback.WaitForResult(), IsOk());
- EXPECT_TRUE(handle.is_initialized());
- EXPECT_TRUE(handle.socket());
- EXPECT_EQ(tagging_client_socket_factory_.GetLastProducedTCPSocket()->tag(),
- tag1);
- EXPECT_TRUE(tagging_client_socket_factory_.GetLastProducedTCPSocket()
- ->tagged_before_connected());
- // Test socket is tagged when reused after being created asynchronously.
- socket = handle.socket();
- handle.Reset();
- rv = handle.Init(
- kGroupId, socks_params, TRAFFIC_ANNOTATION_FOR_TESTS, LOW, tag2,
- ClientSocketPool::RespectLimits::ENABLED, CompletionOnceCallback(),
- ClientSocketPool::ProxyAuthCallback(), &proxy_pool, NetLogWithSource());
- EXPECT_THAT(rv, IsOk());
- EXPECT_TRUE(handle.socket());
- EXPECT_TRUE(handle.socket()->IsConnected());
- EXPECT_EQ(handle.socket(), socket);
- EXPECT_EQ(tagging_client_socket_factory_.GetLastProducedTCPSocket()->tag(),
- tag2);
- }
- TEST_F(TransportClientSocketPoolTest, TagSSLDirect) {
- if (!CanGetTaggedBytes()) {
- DVLOG(0) << "Skipping test - GetTaggedBytes unsupported.";
- return;
- }
- // Start test server.
- EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK, SSLServerConfig());
- test_server.AddDefaultHandlers(base::FilePath());
- ASSERT_TRUE(test_server.Start());
- TestCompletionCallback callback;
- ClientSocketHandle handle;
- int32_t tag_val1 = 0x12345678;
- SocketTag tag1(SocketTag::UNSET_UID, tag_val1);
- int32_t tag_val2 = 0x87654321;
- SocketTag tag2(getuid(), tag_val2);
- const ClientSocketPool::GroupId kGroupId(
- url::SchemeHostPort(test_server.base_url()),
- PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
- SecureDnsPolicy::kAllow);
- auto ssl_config_for_origin = std::make_unique<SSLConfig>();
- ssl_config_for_origin->alpn_protos = {kProtoHTTP2, kProtoHTTP11};
- scoped_refptr<ClientSocketPool::SocketParams> socket_params =
- base::MakeRefCounted<ClientSocketPool::SocketParams>(
- std::move(ssl_config_for_origin),
- /*ssl_config_for_proxy=*/nullptr);
- // Test socket is tagged before connected.
- uint64_t old_traffic = GetTaggedBytes(tag_val1);
- int rv = handle.Init(
- kGroupId, socket_params, absl::nullopt /* proxy_annotation_tag */, LOW,
- tag1, ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
- ClientSocketPool::ProxyAuthCallback(), pool_for_real_sockets_.get(),
- NetLogWithSource());
- EXPECT_THAT(callback.GetResult(rv), IsOk());
- EXPECT_TRUE(handle.socket());
- EXPECT_TRUE(handle.socket()->IsConnected());
- EXPECT_GT(GetTaggedBytes(tag_val1), old_traffic);
- // Test reused socket is retagged.
- StreamSocket* socket = handle.socket();
- handle.Reset();
- old_traffic = GetTaggedBytes(tag_val2);
- TestCompletionCallback callback2;
- rv = handle.Init(kGroupId, socket_params,
- absl::nullopt /* proxy_annotation_tag */, LOW, tag2,
- ClientSocketPool::RespectLimits::ENABLED,
- callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
- pool_for_real_sockets_.get(), NetLogWithSource());
- EXPECT_THAT(rv, IsOk());
- EXPECT_TRUE(handle.socket());
- EXPECT_TRUE(handle.socket()->IsConnected());
- EXPECT_EQ(handle.socket(), socket);
- const char kRequest[] = "GET / HTTP/1.1\r\n\r\n";
- scoped_refptr<IOBuffer> write_buffer =
- base::MakeRefCounted<StringIOBuffer>(kRequest);
- rv =
- handle.socket()->Write(write_buffer.get(), strlen(kRequest),
- callback.callback(), TRAFFIC_ANNOTATION_FOR_TESTS);
- EXPECT_EQ(static_cast<int>(strlen(kRequest)), callback.GetResult(rv));
- scoped_refptr<IOBufferWithSize> read_buffer =
- base::MakeRefCounted<IOBufferWithSize>(1);
- rv = handle.socket()->Read(read_buffer.get(), read_buffer->size(),
- callback.callback());
- EXPECT_EQ(read_buffer->size(), callback.GetResult(rv));
- EXPECT_GT(GetTaggedBytes(tag_val2), old_traffic);
- // Disconnect socket to prevent reuse.
- handle.socket()->Disconnect();
- handle.Reset();
- }
- TEST_F(TransportClientSocketPoolTest, TagSSLDirectTwoSockets) {
- if (!CanGetTaggedBytes()) {
- DVLOG(0) << "Skipping test - GetTaggedBytes unsupported.";
- return;
- }
- // Start test server.
- EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK, SSLServerConfig());
- test_server.AddDefaultHandlers(base::FilePath());
- ASSERT_TRUE(test_server.Start());
- ClientSocketHandle handle;
- int32_t tag_val1 = 0x12345678;
- SocketTag tag1(SocketTag::UNSET_UID, tag_val1);
- int32_t tag_val2 = 0x87654321;
- SocketTag tag2(getuid(), tag_val2);
- const ClientSocketPool::GroupId kGroupId(
- url::SchemeHostPort(test_server.base_url()),
- PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
- SecureDnsPolicy::kAllow);
- auto ssl_config_for_origin = std::make_unique<SSLConfig>();
- ssl_config_for_origin->alpn_protos = {kProtoHTTP2, kProtoHTTP11};
- scoped_refptr<ClientSocketPool::SocketParams> socket_params =
- base::MakeRefCounted<ClientSocketPool::SocketParams>(
- std::move(ssl_config_for_origin),
- /*ssl_config_for_proxy=*/nullptr);
- // Test connect jobs that are orphaned and then adopted, appropriately apply
- // new tag. Request socket with |tag1|.
- TestCompletionCallback callback;
- int rv = handle.Init(
- kGroupId, socket_params, absl::nullopt /* proxy_annotation_tag */, LOW,
- tag1, ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
- ClientSocketPool::ProxyAuthCallback(), pool_for_real_sockets_.get(),
- NetLogWithSource());
- EXPECT_TRUE(rv == OK || rv == ERR_IO_PENDING) << "Result: " << rv;
- // Abort and request socket with |tag2|.
- handle.Reset();
- TestCompletionCallback callback2;
- rv = handle.Init(kGroupId, socket_params,
- absl::nullopt /* proxy_annotation_tag */, LOW, tag2,
- ClientSocketPool::RespectLimits::ENABLED,
- callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
- pool_for_real_sockets_.get(), NetLogWithSource());
- EXPECT_THAT(callback2.GetResult(rv), IsOk());
- EXPECT_TRUE(handle.socket());
- EXPECT_TRUE(handle.socket()->IsConnected());
- // Verify socket has |tag2| applied.
- uint64_t old_traffic = GetTaggedBytes(tag_val2);
- const char kRequest[] = "GET / HTTP/1.1\r\n\r\n";
- scoped_refptr<IOBuffer> write_buffer =
- base::MakeRefCounted<StringIOBuffer>(kRequest);
- rv = handle.socket()->Write(write_buffer.get(), strlen(kRequest),
- callback2.callback(),
- TRAFFIC_ANNOTATION_FOR_TESTS);
- EXPECT_EQ(static_cast<int>(strlen(kRequest)), callback2.GetResult(rv));
- scoped_refptr<IOBufferWithSize> read_buffer =
- base::MakeRefCounted<IOBufferWithSize>(1);
- rv = handle.socket()->Read(read_buffer.get(), read_buffer->size(),
- callback2.callback());
- EXPECT_EQ(read_buffer->size(), callback2.GetResult(rv));
- EXPECT_GT(GetTaggedBytes(tag_val2), old_traffic);
- }
- TEST_F(TransportClientSocketPoolTest, TagSSLDirectTwoSocketsFullPool) {
- if (!CanGetTaggedBytes()) {
- DVLOG(0) << "Skipping test - GetTaggedBytes unsupported.";
- return;
- }
- // Start test server.
- EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK, SSLServerConfig());
- test_server.AddDefaultHandlers(base::FilePath());
- ASSERT_TRUE(test_server.Start());
- TestCompletionCallback callback;
- ClientSocketHandle handle;
- int32_t tag_val1 = 0x12345678;
- SocketTag tag1(SocketTag::UNSET_UID, tag_val1);
- int32_t tag_val2 = 0x87654321;
- SocketTag tag2(getuid(), tag_val2);
- const ClientSocketPool::GroupId kGroupId(
- url::SchemeHostPort(test_server.base_url()),
- PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
- SecureDnsPolicy::kAllow);
- auto ssl_config_for_origin = std::make_unique<SSLConfig>();
- ssl_config_for_origin->alpn_protos = {kProtoHTTP2, kProtoHTTP11};
- scoped_refptr<ClientSocketPool::SocketParams> socket_params =
- base::MakeRefCounted<ClientSocketPool::SocketParams>(
- std::move(ssl_config_for_origin),
- /*ssl_config_for_proxy=*/nullptr);
- // Test that sockets paused by a full underlying socket pool are properly
- // connected and tagged when underlying pool is freed up.
- // Fill up all slots in TCP pool.
- ClientSocketHandle tcp_handles[kMaxSocketsPerGroup];
- int rv;
- for (auto& tcp_handle : tcp_handles) {
- rv = tcp_handle.Init(
- kGroupId, socket_params, absl::nullopt /* proxy_annotation_tag */, LOW,
- tag1, ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
- ClientSocketPool::ProxyAuthCallback(), pool_for_real_sockets_.get(),
- NetLogWithSource());
- EXPECT_THAT(callback.GetResult(rv), IsOk());
- EXPECT_TRUE(tcp_handle.socket());
- EXPECT_TRUE(tcp_handle.socket()->IsConnected());
- }
- // Request two SSL sockets.
- ClientSocketHandle handle_to_be_canceled;
- rv = handle_to_be_canceled.Init(
- kGroupId, socket_params, absl::nullopt /* proxy_annotation_tag */, LOW,
- tag1, ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
- ClientSocketPool::ProxyAuthCallback(), pool_for_real_sockets_.get(),
- NetLogWithSource());
- EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
- rv = handle.Init(kGroupId, socket_params,
- absl::nullopt /* proxy_annotation_tag */, LOW, tag2,
- ClientSocketPool::RespectLimits::ENABLED,
- callback.callback(), ClientSocketPool::ProxyAuthCallback(),
- pool_for_real_sockets_.get(), NetLogWithSource());
- EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
- // Cancel first request.
- handle_to_be_canceled.Reset();
- // Disconnect a TCP socket to free up a slot.
- tcp_handles[0].socket()->Disconnect();
- tcp_handles[0].Reset();
- // Verify |handle| gets a valid tagged socket.
- EXPECT_THAT(callback.WaitForResult(), IsOk());
- EXPECT_TRUE(handle.socket());
- EXPECT_TRUE(handle.socket()->IsConnected());
- uint64_t old_traffic = GetTaggedBytes(tag_val2);
- const char kRequest[] = "GET / HTTP/1.1\r\n\r\n";
- scoped_refptr<IOBuffer> write_buffer =
- base::MakeRefCounted<StringIOBuffer>(kRequest);
- rv =
- handle.socket()->Write(write_buffer.get(), strlen(kRequest),
- callback.callback(), TRAFFIC_ANNOTATION_FOR_TESTS);
- EXPECT_EQ(static_cast<int>(strlen(kRequest)), callback.GetResult(rv));
- scoped_refptr<IOBufferWithSize> read_buffer =
- base::MakeRefCounted<IOBufferWithSize>(1);
- EXPECT_EQ(handle.socket()->Read(read_buffer.get(), read_buffer->size(),
- callback.callback()),
- ERR_IO_PENDING);
- EXPECT_THAT(callback.WaitForResult(), read_buffer->size());
- EXPECT_GT(GetTaggedBytes(tag_val2), old_traffic);
- }
- TEST_F(TransportClientSocketPoolTest, TagHttpProxyNoTunnel) {
- SocketTag tag1(SocketTag::UNSET_UID, 0x12345678);
- SocketTag tag2(getuid(), 0x87654321);
- TransportClientSocketPool proxy_pool(
- kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout,
- ProxyUriToProxyServer("http://proxy",
- ProxyServer::SCHEME_HTTP /* default_scheme */),
- false /* is_for_websockets */, tagging_common_connect_job_params_.get());
- session_deps_.host_resolver->set_synchronous_mode(true);
- SequencedSocketData socket_data;
- socket_data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
- tagging_client_socket_factory_.AddSocketDataProvider(&socket_data);
- const url::SchemeHostPort kDestination(url::kHttpScheme, "www.google.com",
- 80);
- const ClientSocketPool::GroupId kGroupId(
- kDestination, PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
- SecureDnsPolicy::kAllow);
- scoped_refptr<ClientSocketPool::SocketParams> socket_params =
- base::MakeRefCounted<ClientSocketPool::SocketParams>(
- nullptr /* ssl_config_for_origin */,
- nullptr /* ssl_config_for_proxy */);
- // Verify requested socket is tagged properly.
- ClientSocketHandle handle;
- int rv = handle.Init(
- kGroupId, socket_params, TRAFFIC_ANNOTATION_FOR_TESTS, LOW, tag1,
- ClientSocketPool::RespectLimits::ENABLED, CompletionOnceCallback(),
- ClientSocketPool::ProxyAuthCallback(), &proxy_pool, NetLogWithSource());
- EXPECT_THAT(rv, IsOk());
- EXPECT_TRUE(handle.is_initialized());
- ASSERT_TRUE(handle.socket());
- EXPECT_TRUE(handle.socket()->IsConnected());
- EXPECT_EQ(tagging_client_socket_factory_.GetLastProducedTCPSocket()->tag(),
- tag1);
- EXPECT_TRUE(tagging_client_socket_factory_.GetLastProducedTCPSocket()
- ->tagged_before_connected());
- // Verify reused socket is retagged properly.
- StreamSocket* socket = handle.socket();
- handle.Reset();
- rv = handle.Init(
- kGroupId, socket_params, TRAFFIC_ANNOTATION_FOR_TESTS, LOW, tag2,
- ClientSocketPool::RespectLimits::ENABLED, CompletionOnceCallback(),
- ClientSocketPool::ProxyAuthCallback(), &proxy_pool, NetLogWithSource());
- EXPECT_THAT(rv, IsOk());
- EXPECT_TRUE(handle.socket());
- EXPECT_TRUE(handle.socket()->IsConnected());
- EXPECT_EQ(handle.socket(), socket);
- EXPECT_EQ(tagging_client_socket_factory_.GetLastProducedTCPSocket()->tag(),
- tag2);
- handle.socket()->Disconnect();
- handle.Reset();
- }
- // This creates a tunnel without SSL on top of it - something not normally done,
- // though some non-HTTP consumers use this path to create tunnels for other
- // uses.
- TEST_F(TransportClientSocketPoolTest, TagHttpProxyTunnel) {
- SocketTag tag1(SocketTag::UNSET_UID, 0x12345678);
- SocketTag tag2(getuid(), 0x87654321);
- TransportClientSocketPool proxy_pool(
- kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout,
- ProxyUriToProxyServer("http://proxy",
- ProxyServer::SCHEME_HTTP /* default_scheme */),
- false /* is_for_websockets */, tagging_common_connect_job_params_.get());
- session_deps_.host_resolver->set_synchronous_mode(true);
- std::string request =
- "CONNECT www.google.com:443 HTTP/1.1\r\n"
- "Host: www.google.com:443\r\n"
- "Proxy-Connection: keep-alive\r\n\r\n";
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, request.c_str()),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
- };
- SequencedSocketData socket_data(MockConnect(SYNCHRONOUS, OK), reads, writes);
- tagging_client_socket_factory_.AddSocketDataProvider(&socket_data);
- SSLSocketDataProvider ssl_data(SYNCHRONOUS, OK);
- tagging_client_socket_factory_.AddSSLSocketDataProvider(&ssl_data);
- const url::SchemeHostPort kDestination(url::kHttpsScheme, "www.google.com",
- 443);
- const ClientSocketPool::GroupId kGroupId(
- kDestination, PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
- SecureDnsPolicy::kAllow);
- auto ssl_config_for_origin = std::make_unique<SSLConfig>();
- ssl_config_for_origin->alpn_protos = {kProtoHTTP2, kProtoHTTP11};
- scoped_refptr<ClientSocketPool::SocketParams> socket_params =
- base::MakeRefCounted<ClientSocketPool::SocketParams>(
- std::move(ssl_config_for_origin),
- /*ssl_config_for_proxy=*/nullptr);
- // Verify requested socket is tagged properly.
- ClientSocketHandle handle;
- int rv = handle.Init(
- kGroupId, socket_params, TRAFFIC_ANNOTATION_FOR_TESTS, LOW, tag1,
- ClientSocketPool::RespectLimits::ENABLED, CompletionOnceCallback(),
- ClientSocketPool::ProxyAuthCallback(), &proxy_pool, NetLogWithSource());
- EXPECT_THAT(rv, IsOk());
- EXPECT_TRUE(handle.is_initialized());
- ASSERT_TRUE(handle.socket());
- EXPECT_TRUE(handle.socket()->IsConnected());
- EXPECT_EQ(tagging_client_socket_factory_.GetLastProducedTCPSocket()->tag(),
- tag1);
- EXPECT_TRUE(tagging_client_socket_factory_.GetLastProducedTCPSocket()
- ->tagged_before_connected());
- // Verify reused socket is retagged properly.
- StreamSocket* socket = handle.socket();
- handle.Reset();
- rv = handle.Init(
- kGroupId, socket_params, TRAFFIC_ANNOTATION_FOR_TESTS, LOW, tag2,
- ClientSocketPool::RespectLimits::ENABLED, CompletionOnceCallback(),
- ClientSocketPool::ProxyAuthCallback(), &proxy_pool, NetLogWithSource());
- EXPECT_THAT(rv, IsOk());
- EXPECT_TRUE(handle.socket());
- EXPECT_TRUE(handle.socket()->IsConnected());
- EXPECT_EQ(handle.socket(), socket);
- EXPECT_EQ(tagging_client_socket_factory_.GetLastProducedTCPSocket()->tag(),
- tag2);
- handle.socket()->Disconnect();
- handle.Reset();
- }
- #endif // BUILDFLAG(IS_ANDROID)
- // Class that enables tests to set mock time.
- class TransportClientSocketPoolMockNowSourceTest
- : public TransportClientSocketPoolTest {
- public:
- TransportClientSocketPoolMockNowSourceTest(
- const TransportClientSocketPoolMockNowSourceTest&) = delete;
- TransportClientSocketPoolMockNowSourceTest& operator=(
- const TransportClientSocketPoolMockNowSourceTest&) = delete;
- protected:
- TransportClientSocketPoolMockNowSourceTest()
- : TransportClientSocketPoolTest(
- base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
- };
- // Tests that changing the idle unused socket timeout using the experiment
- // works. The test first sets the value of timeout duration for idle sockets.
- // Next, it opens |kNumIdleSockets| sockets. To trigger the cleanup of idle
- // sockets that may have timedout, it then opens one more socket. This is
- // required since requesting a new socket triggers cleanup of idle timedout
- // sockets. Next, the test verifies the count of idle timed-out sockets.
- TEST_F(TransportClientSocketPoolMockNowSourceTest, IdleUnusedSocketTimeout) {
- const url::SchemeHostPort kSchemeHostPort1(url::kHttpScheme, "www.foo.com",
- 80);
- const url::SchemeHostPort kSchemeHostPort2(url::kHttpScheme, "www.bar.com",
- 80);
- const struct {
- bool use_first_socket;
- int fast_forward_seconds;
- int unused_idle_socket_timeout_seconds;
- bool expect_idle_socket;
- } kTests[] = {
- // When the clock is fast forwarded by a duration longer than
- // |unused_idle_socket_timeout_seconds|, the first unused idle socket is
- // expected to be timedout, and cleared.
- {false, 0, 0, false},
- {false, 9, 10, true},
- {false, 11, 10, false},
- {false, 19, 20, true},
- {false, 21, 20, false},
- // If |use_first_socket| is true, then the test would write some data to
- // the socket, thereby marking it as "used". Thereafter, this idle socket
- // should be timedout based on used idle socket timeout, and changing
- // |unused_idle_socket_timeout_seconds| should not affect the
- // |expected_idle_sockets|.
- {true, 0, 0, true},
- {true, 9, 10, true},
- {true, 11, 10, true},
- {true, 19, 20, true},
- {true, 21, 20, true},
- };
- for (const auto& test : kTests) {
- SpdySessionDependencies session_deps(
- ConfiguredProxyResolutionService::CreateDirect());
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- base::test::ScopedFeatureList scoped_feature_list_;
- std::map<std::string, std::string> parameters;
- parameters["unused_idle_socket_timeout_seconds"] =
- base::NumberToString(test.unused_idle_socket_timeout_seconds);
- scoped_feature_list_.InitAndEnableFeatureWithParameters(
- net::features::kNetUnusedIdleSocketTimeout, parameters);
- const char kWriteData[] = "1";
- const MockWrite kWrites[] = {MockWrite(SYNCHRONOUS, kWriteData)};
- SequencedSocketData provider_socket_1(MockConnect(ASYNC, OK),
- base::span<MockRead>(), kWrites);
- {
- // Create 1 socket.
- scoped_refptr<ClientSocketPool::SocketParams> socket_params =
- base::MakeRefCounted<ClientSocketPool::SocketParams>(
- nullptr /* ssl_config_for_origin */,
- nullptr /* ssl_config_for_proxy */);
- session_deps.socket_factory->AddSocketDataProvider(&provider_socket_1);
- ClientSocketHandle connection;
- TestCompletionCallback callback;
- int rv = connection.Init(
- ClientSocketPool::GroupId(
- kSchemeHostPort1, PrivacyMode::PRIVACY_MODE_DISABLED,
- NetworkIsolationKey(), SecureDnsPolicy::kAllow),
- ClientSocketPool::SocketParams::CreateForHttpForTesting(),
- absl::nullopt /* proxy_annotation_tag */, MEDIUM, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
- ClientSocketPool::ProxyAuthCallback(),
- session->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
- ProxyServer::Direct()),
- NetLogWithSource());
- EXPECT_THAT(callback.GetResult(rv), IsOk());
- EXPECT_FALSE(connection.socket()->WasEverUsed());
- // Writing some data to the socket should set WasEverUsed.
- if (test.use_first_socket) {
- // Generate |socket_write_data| from kMockWriteData by appending null
- // character to the latter.
- auto write_buffer = base::MakeRefCounted<StringIOBuffer>(kWriteData);
- TestCompletionCallback write_callback;
- rv = connection.socket()->Write(
- write_buffer.get(), write_buffer->size(), write_callback.callback(),
- TRAFFIC_ANNOTATION_FOR_TESTS);
- EXPECT_EQ(rv, 1);
- EXPECT_TRUE(connection.socket()->WasEverUsed());
- }
- }
- EXPECT_EQ(1, session
- ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
- ProxyServer::Direct())
- ->IdleSocketCount());
- // Moving the clock forward may cause the idle socket to be timedout.
- FastForwardBy(base::Seconds(test.fast_forward_seconds));
- {
- // Request a new socket to trigger cleanup of idle timedout sockets.
- scoped_refptr<ClientSocketPool::SocketParams> socket_params =
- base::MakeRefCounted<ClientSocketPool::SocketParams>(
- nullptr /* ssl_config_for_origin */,
- nullptr /* ssl_config_for_proxy */);
- SequencedSocketData provider_socket_2(MockConnect(ASYNC, OK),
- base::span<MockRead>(),
- base::span<MockWrite>());
- session_deps.socket_factory->AddSocketDataProvider(&provider_socket_2);
- ClientSocketHandle connection;
- TestCompletionCallback callback;
- int rv = connection.Init(
- ClientSocketPool::GroupId(
- kSchemeHostPort2, PrivacyMode::PRIVACY_MODE_DISABLED,
- NetworkIsolationKey(), SecureDnsPolicy::kAllow),
- socket_params, absl::nullopt /* proxy_annotation_tag */, MEDIUM,
- SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback.callback(), ClientSocketPool::ProxyAuthCallback(),
- session->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
- ProxyServer::Direct()),
- NetLogWithSource());
- EXPECT_THAT(callback.GetResult(rv), IsOk());
- connection.socket()->Disconnect();
- }
- EXPECT_EQ(test.expect_idle_socket ? 1 : 0,
- session
- ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
- ProxyServer::Direct())
- ->IdleSocketCount());
- }
- }
- } // namespace
- } // namespace net
|