Evict resources from resource pool after timeout
[chromium-blink-merge.git] / net / proxy / mojo_proxy_resolver_impl_unittest.cc
blobbfc777325a7953be0e37da5b03d86b43a128d43b
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/proxy/mojo_proxy_resolver_impl.h"
7 #include <string>
8 #include <vector>
10 #include "base/run_loop.h"
11 #include "net/base/net_errors.h"
12 #include "net/proxy/mock_proxy_resolver.h"
13 #include "net/proxy/mojo_proxy_type_converters.h"
14 #include "net/proxy/proxy_info.h"
15 #include "net/proxy/proxy_resolver_v8_tracing.h"
16 #include "net/proxy/proxy_server.h"
17 #include "net/test/event_waiter.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h"
21 namespace net {
22 namespace {
24 class TestRequestClient : public interfaces::ProxyResolverRequestClient {
25 public:
26 enum Event {
27 RESULT_RECEIVED,
28 CONNECTION_ERROR,
31 explicit TestRequestClient(
32 mojo::InterfaceRequest<interfaces::ProxyResolverRequestClient> request);
34 void WaitForResult();
36 Error error() { return error_; }
37 const mojo::Array<interfaces::ProxyServerPtr>& results() { return results_; }
38 EventWaiter<Event>& event_waiter() { return event_waiter_; }
40 private:
41 // interfaces::ProxyResolverRequestClient override.
42 void ReportResult(int32_t error,
43 mojo::Array<interfaces::ProxyServerPtr> results) override;
44 void Alert(const mojo::String& message) override;
45 void OnError(int32_t line_number, const mojo::String& message) override;
46 void ResolveDns(interfaces::HostResolverRequestInfoPtr request_info,
47 interfaces::HostResolverRequestClientPtr client) override;
49 // Mojo error handler.
50 void OnConnectionError();
52 bool done_ = false;
53 Error error_ = ERR_FAILED;
54 mojo::Array<interfaces::ProxyServerPtr> results_;
56 mojo::Binding<interfaces::ProxyResolverRequestClient> binding_;
58 EventWaiter<Event> event_waiter_;
61 TestRequestClient::TestRequestClient(
62 mojo::InterfaceRequest<interfaces::ProxyResolverRequestClient> request)
63 : binding_(this, request.Pass()) {
64 binding_.set_connection_error_handler(base::Bind(
65 &TestRequestClient::OnConnectionError, base::Unretained(this)));
68 void TestRequestClient::WaitForResult() {
69 if (done_)
70 return;
72 event_waiter_.WaitForEvent(RESULT_RECEIVED);
73 ASSERT_TRUE(done_);
76 void TestRequestClient::ReportResult(
77 int32_t error,
78 mojo::Array<interfaces::ProxyServerPtr> results) {
79 event_waiter_.NotifyEvent(RESULT_RECEIVED);
80 ASSERT_FALSE(done_);
81 error_ = static_cast<Error>(error);
82 results_ = results.Pass();
83 done_ = true;
86 void TestRequestClient::Alert(const mojo::String& message) {
89 void TestRequestClient::OnError(int32_t line_number,
90 const mojo::String& message) {
93 void TestRequestClient::ResolveDns(
94 interfaces::HostResolverRequestInfoPtr request_info,
95 interfaces::HostResolverRequestClientPtr client) {
98 void TestRequestClient::OnConnectionError() {
99 event_waiter_.NotifyEvent(CONNECTION_ERROR);
102 class MockProxyResolverV8Tracing : public ProxyResolverV8Tracing {
103 public:
104 struct Request {
105 GURL url;
106 ProxyInfo* results;
107 CompletionCallback callback;
108 bool cancelled = false;
110 MockProxyResolverV8Tracing() {}
112 // ProxyResolverV8Tracing overrides.
113 void GetProxyForURL(const GURL& url,
114 ProxyInfo* results,
115 const CompletionCallback& callback,
116 ProxyResolver::RequestHandle* request,
117 scoped_ptr<Bindings> bindings) override;
118 void CancelRequest(ProxyResolver::RequestHandle request_handle) override;
119 LoadState GetLoadState(ProxyResolver::RequestHandle request) const override;
121 // Wait until the mock resolver has received a CancelRequest call.
122 void WaitForCancel();
124 const std::vector<Request>& pending_requests() { return pending_requests_; }
126 private:
127 base::Closure cancel_callback_;
128 std::vector<Request> pending_requests_;
131 void MockProxyResolverV8Tracing::GetProxyForURL(
132 const GURL& url,
133 ProxyInfo* results,
134 const CompletionCallback& callback,
135 ProxyResolver::RequestHandle* request,
136 scoped_ptr<Bindings> bindings) {
137 pending_requests_.push_back(Request());
138 auto& pending_request = pending_requests_.back();
139 pending_request.url = url;
140 pending_request.results = results;
141 pending_request.callback = callback;
142 *request =
143 reinterpret_cast<ProxyResolver::RequestHandle>(pending_requests_.size());
146 void MockProxyResolverV8Tracing::CancelRequest(
147 ProxyResolver::RequestHandle request_handle) {
148 size_t id = reinterpret_cast<size_t>(request_handle) - 1;
149 pending_requests_[id].cancelled = true;
150 if (!cancel_callback_.is_null()) {
151 cancel_callback_.Run();
152 cancel_callback_.Reset();
156 LoadState MockProxyResolverV8Tracing::GetLoadState(
157 ProxyResolver::RequestHandle request) const {
158 return LOAD_STATE_RESOLVING_PROXY_FOR_URL;
161 void MockProxyResolverV8Tracing::WaitForCancel() {
162 while (std::find_if(pending_requests_.begin(), pending_requests_.end(),
163 [](const Request& request) {
164 return request.cancelled;
165 }) != pending_requests_.end()) {
166 base::RunLoop run_loop;
167 cancel_callback_ = run_loop.QuitClosure();
168 run_loop.Run();
172 } // namespace
174 class MojoProxyResolverImplTest : public testing::Test {
175 protected:
176 void SetUp() override {
177 scoped_ptr<MockProxyResolverV8Tracing> mock_resolver(
178 new MockProxyResolverV8Tracing);
179 mock_proxy_resolver_ = mock_resolver.get();
180 resolver_impl_.reset(new MojoProxyResolverImpl(mock_resolver.Pass()));
181 resolver_ = resolver_impl_.get();
184 MockProxyResolverV8Tracing* mock_proxy_resolver_;
186 scoped_ptr<MojoProxyResolverImpl> resolver_impl_;
187 interfaces::ProxyResolver* resolver_;
190 TEST_F(MojoProxyResolverImplTest, GetProxyForUrl) {
191 interfaces::ProxyResolverRequestClientPtr client_ptr;
192 TestRequestClient client(mojo::GetProxy(&client_ptr));
194 resolver_->GetProxyForUrl("http://example.com", client_ptr.Pass());
195 ASSERT_EQ(1u, mock_proxy_resolver_->pending_requests().size());
196 const MockProxyResolverV8Tracing::Request& request =
197 mock_proxy_resolver_->pending_requests()[0];
198 EXPECT_EQ(GURL("http://example.com"), request.url);
200 request.results->UsePacString(
201 "PROXY proxy.example.com:1; "
202 "SOCKS4 socks4.example.com:2; "
203 "SOCKS5 socks5.example.com:3; "
204 "HTTPS https.example.com:4; "
205 "QUIC quic.example.com:65000; "
206 "DIRECT");
207 request.callback.Run(OK);
208 client.WaitForResult();
210 EXPECT_EQ(OK, client.error());
211 std::vector<ProxyServer> servers =
212 client.results().To<std::vector<ProxyServer>>();
213 ASSERT_EQ(6u, servers.size());
214 EXPECT_EQ(ProxyServer::SCHEME_HTTP, servers[0].scheme());
215 EXPECT_EQ("proxy.example.com", servers[0].host_port_pair().host());
216 EXPECT_EQ(1, servers[0].host_port_pair().port());
218 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, servers[1].scheme());
219 EXPECT_EQ("socks4.example.com", servers[1].host_port_pair().host());
220 EXPECT_EQ(2, servers[1].host_port_pair().port());
222 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, servers[2].scheme());
223 EXPECT_EQ("socks5.example.com", servers[2].host_port_pair().host());
224 EXPECT_EQ(3, servers[2].host_port_pair().port());
226 EXPECT_EQ(ProxyServer::SCHEME_HTTPS, servers[3].scheme());
227 EXPECT_EQ("https.example.com", servers[3].host_port_pair().host());
228 EXPECT_EQ(4, servers[3].host_port_pair().port());
230 EXPECT_EQ(ProxyServer::SCHEME_QUIC, servers[4].scheme());
231 EXPECT_EQ("quic.example.com", servers[4].host_port_pair().host());
232 EXPECT_EQ(65000, servers[4].host_port_pair().port());
234 EXPECT_EQ(ProxyServer::SCHEME_DIRECT, servers[5].scheme());
237 TEST_F(MojoProxyResolverImplTest, GetProxyForUrlFailure) {
238 interfaces::ProxyResolverRequestClientPtr client_ptr;
239 TestRequestClient client(mojo::GetProxy(&client_ptr));
241 resolver_->GetProxyForUrl("http://example.com", client_ptr.Pass());
242 ASSERT_EQ(1u, mock_proxy_resolver_->pending_requests().size());
243 const MockProxyResolverV8Tracing::Request& request =
244 mock_proxy_resolver_->pending_requests()[0];
245 EXPECT_EQ(GURL("http://example.com"), request.url);
246 request.callback.Run(ERR_FAILED);
247 client.WaitForResult();
249 EXPECT_EQ(ERR_FAILED, client.error());
250 std::vector<ProxyServer> proxy_servers =
251 client.results().To<std::vector<ProxyServer>>();
252 EXPECT_TRUE(proxy_servers.empty());
255 TEST_F(MojoProxyResolverImplTest, GetProxyForUrlMultiple) {
256 interfaces::ProxyResolverRequestClientPtr client_ptr1;
257 TestRequestClient client1(mojo::GetProxy(&client_ptr1));
258 interfaces::ProxyResolverRequestClientPtr client_ptr2;
259 TestRequestClient client2(mojo::GetProxy(&client_ptr2));
261 resolver_->GetProxyForUrl("http://example.com", client_ptr1.Pass());
262 resolver_->GetProxyForUrl("https://example.com", client_ptr2.Pass());
263 ASSERT_EQ(2u, mock_proxy_resolver_->pending_requests().size());
264 const MockProxyResolverV8Tracing::Request& request1 =
265 mock_proxy_resolver_->pending_requests()[0];
266 EXPECT_EQ(GURL("http://example.com"), request1.url);
267 const MockProxyResolverV8Tracing::Request& request2 =
268 mock_proxy_resolver_->pending_requests()[1];
269 EXPECT_EQ(GURL("https://example.com"), request2.url);
270 request1.results->UsePacString("HTTPS proxy.example.com:12345");
271 request1.callback.Run(OK);
272 request2.results->UsePacString("SOCKS5 another-proxy.example.com:6789");
273 request2.callback.Run(OK);
274 client1.WaitForResult();
275 client2.WaitForResult();
277 EXPECT_EQ(OK, client1.error());
278 std::vector<ProxyServer> proxy_servers1 =
279 client1.results().To<std::vector<ProxyServer>>();
280 ASSERT_EQ(1u, proxy_servers1.size());
281 ProxyServer& server1 = proxy_servers1[0];
282 EXPECT_EQ(ProxyServer::SCHEME_HTTPS, server1.scheme());
283 EXPECT_EQ("proxy.example.com", server1.host_port_pair().host());
284 EXPECT_EQ(12345, server1.host_port_pair().port());
286 EXPECT_EQ(OK, client2.error());
287 std::vector<ProxyServer> proxy_servers2 =
288 client2.results().To<std::vector<ProxyServer>>();
289 ASSERT_EQ(1u, proxy_servers1.size());
290 ProxyServer& server2 = proxy_servers2[0];
291 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, server2.scheme());
292 EXPECT_EQ("another-proxy.example.com", server2.host_port_pair().host());
293 EXPECT_EQ(6789, server2.host_port_pair().port());
296 TEST_F(MojoProxyResolverImplTest, DestroyClient) {
297 interfaces::ProxyResolverRequestClientPtr client_ptr;
298 scoped_ptr<TestRequestClient> client(
299 new TestRequestClient(mojo::GetProxy(&client_ptr)));
301 resolver_->GetProxyForUrl("http://example.com", client_ptr.Pass());
302 ASSERT_EQ(1u, mock_proxy_resolver_->pending_requests().size());
303 const MockProxyResolverV8Tracing::Request& request =
304 mock_proxy_resolver_->pending_requests()[0];
305 EXPECT_EQ(GURL("http://example.com"), request.url);
306 request.results->UsePacString("PROXY proxy.example.com:8080");
307 client.reset();
308 mock_proxy_resolver_->WaitForCancel();
311 TEST_F(MojoProxyResolverImplTest, DestroyService) {
312 interfaces::ProxyResolverRequestClientPtr client_ptr;
313 TestRequestClient client(mojo::GetProxy(&client_ptr));
315 resolver_->GetProxyForUrl("http://example.com", client_ptr.Pass());
316 ASSERT_EQ(1u, mock_proxy_resolver_->pending_requests().size());
317 resolver_impl_.reset();
318 client.event_waiter().WaitForEvent(TestRequestClient::CONNECTION_ERROR);
321 } // namespace net