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/dns/mojo_host_resolver_impl.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/run_loop.h"
11 #include "base/time/time.h"
12 #include "net/base/address_list.h"
13 #include "net/base/net_errors.h"
14 #include "net/base/net_util.h"
15 #include "net/dns/mock_host_resolver.h"
16 #include "net/dns/mojo_host_type_converters.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h"
19 #include "third_party/mojo/src/mojo/public/cpp/bindings/error_handler.h"
20 #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h"
26 class TestRequestClient
: public interfaces::HostResolverRequestClient
,
27 public mojo::ErrorHandler
{
29 explicit TestRequestClient(
30 mojo::InterfaceRequest
<interfaces::HostResolverRequestClient
> req
)
31 : done_(false), binding_(this, req
.Pass()) {
32 binding_
.set_error_handler(this);
36 void WaitForConnectionError();
39 interfaces::AddressListPtr results_
;
42 // Overridden from interfaces::HostResolverRequestClient.
43 void ReportResult(int32_t error
, interfaces::AddressListPtr results
) override
;
45 // Overridden from mojo::ErrorHandler.
46 void OnConnectionError() override
;
49 base::Closure run_loop_quit_closure_
;
50 base::Closure connection_error_quit_closure_
;
52 mojo::Binding
<interfaces::HostResolverRequestClient
> binding_
;
55 void TestRequestClient::WaitForResult() {
59 base::RunLoop run_loop
;
60 run_loop_quit_closure_
= run_loop
.QuitClosure();
65 void TestRequestClient::WaitForConnectionError() {
66 base::RunLoop run_loop
;
67 connection_error_quit_closure_
= run_loop
.QuitClosure();
71 void TestRequestClient::ReportResult(int32_t error
,
72 interfaces::AddressListPtr results
) {
73 if (!run_loop_quit_closure_
.is_null()) {
74 run_loop_quit_closure_
.Run();
78 results_
= results
.Pass();
82 void TestRequestClient::OnConnectionError() {
83 if (!connection_error_quit_closure_
.is_null())
84 connection_error_quit_closure_
.Run();
87 class CallbackMockHostResolver
: public MockHostResolver
{
89 CallbackMockHostResolver() {}
90 ~CallbackMockHostResolver() override
{}
92 // Set a callback to run whenever Resolve is called. Callback is cleared after
94 void SetResolveCallback(base::Closure callback
) {
95 resolve_callback_
= callback
;
98 // Overridden from MockHostResolver.
99 int Resolve(const RequestInfo
& info
,
100 RequestPriority priority
,
101 AddressList
* addresses
,
102 const CompletionCallback
& callback
,
103 RequestHandle
* out_req
,
104 const BoundNetLog
& net_log
) override
;
107 base::Closure resolve_callback_
;
110 int CallbackMockHostResolver::Resolve(const RequestInfo
& info
,
111 RequestPriority priority
,
112 AddressList
* addresses
,
113 const CompletionCallback
& callback
,
114 RequestHandle
* out_req
,
115 const BoundNetLog
& net_log
) {
116 int result
= MockHostResolver::Resolve(info
, priority
, addresses
, callback
,
118 if (!resolve_callback_
.is_null()) {
119 resolve_callback_
.Run();
120 resolve_callback_
.Reset();
127 class MojoHostResolverImplTest
: public testing::Test
{
129 void SetUp() override
{
130 mock_host_resolver_
.rules()->AddRule("example.com", "1.2.3.4");
131 mock_host_resolver_
.rules()->AddRule("chromium.org", "8.8.8.8");
132 mock_host_resolver_
.rules()->AddSimulatedFailure("failure.fail");
134 resolver_service_
.reset(new MojoHostResolverImpl(&mock_host_resolver_
));
135 resolver_service_binding_
.reset(
136 new mojo::Binding
<interfaces::HostResolver
>(resolver_service_
.get()));
137 resolver_service_binding_
->Bind(mojo::GetProxy(&resolver_service_ptr_
));
140 interfaces::HostResolverRequestInfoPtr
CreateRequest(const std::string
& host
,
142 bool is_my_ip_address
) {
143 interfaces::HostResolverRequestInfoPtr request
=
144 interfaces::HostResolverRequestInfo::New();
145 request
->host
= host
;
146 request
->port
= port
;
147 request
->address_family
= interfaces::ADDRESS_FAMILY_IPV4
;
148 request
->is_my_ip_address
= is_my_ip_address
;
149 return request
.Pass();
152 // Wait until the mock resolver has received |num| resolve requests.
153 void WaitForRequests(size_t num
) {
154 while (mock_host_resolver_
.num_resolve() < num
) {
155 base::RunLoop run_loop
;
156 mock_host_resolver_
.SetResolveCallback(run_loop
.QuitClosure());
161 CallbackMockHostResolver mock_host_resolver_
;
162 scoped_ptr
<MojoHostResolverImpl
> resolver_service_
;
164 scoped_ptr
<mojo::Binding
<interfaces::HostResolver
>> resolver_service_binding_
;
165 interfaces::HostResolverPtr resolver_service_ptr_
;
168 TEST_F(MojoHostResolverImplTest
, Resolve
) {
169 interfaces::HostResolverRequestClientPtr client_ptr
;
170 TestRequestClient
client(mojo::GetProxy(&client_ptr
));
172 interfaces::HostResolverRequestInfoPtr request
=
173 CreateRequest("example.com", 80, false);
174 resolver_service_ptr_
->Resolve(request
.Pass(), client_ptr
.Pass());
175 client
.WaitForResult();
177 EXPECT_EQ(net::OK
, client
.error_
);
178 AddressList address_list
= (*client
.results_
).To
<AddressList
>();
179 EXPECT_EQ(1U, address_list
.size());
180 EXPECT_EQ("1.2.3.4:80", address_list
[0].ToString());
183 TEST_F(MojoHostResolverImplTest
, ResolveSynchronous
) {
184 interfaces::HostResolverRequestClientPtr client_ptr
;
185 TestRequestClient
client(mojo::GetProxy(&client_ptr
));
187 mock_host_resolver_
.set_synchronous_mode(true);
189 interfaces::HostResolverRequestInfoPtr request
=
190 CreateRequest("example.com", 80, false);
191 resolver_service_ptr_
->Resolve(request
.Pass(), client_ptr
.Pass());
192 client
.WaitForResult();
194 EXPECT_EQ(net::OK
, client
.error_
);
195 AddressList address_list
= (*client
.results_
).To
<AddressList
>();
196 EXPECT_EQ(1U, address_list
.size());
197 EXPECT_EQ("1.2.3.4:80", address_list
[0].ToString());
200 TEST_F(MojoHostResolverImplTest
, ResolveMultiple
) {
201 interfaces::HostResolverRequestClientPtr client1_ptr
;
202 TestRequestClient
client1(mojo::GetProxy(&client1_ptr
));
203 interfaces::HostResolverRequestClientPtr client2_ptr
;
204 TestRequestClient
client2(mojo::GetProxy(&client2_ptr
));
206 mock_host_resolver_
.set_ondemand_mode(true);
208 interfaces::HostResolverRequestInfoPtr request1
=
209 CreateRequest("example.com", 80, false);
210 resolver_service_ptr_
->Resolve(request1
.Pass(), client1_ptr
.Pass());
211 interfaces::HostResolverRequestInfoPtr request2
=
212 CreateRequest("chromium.org", 80, false);
213 resolver_service_ptr_
->Resolve(request2
.Pass(), client2_ptr
.Pass());
215 mock_host_resolver_
.ResolveAllPending();
217 client1
.WaitForResult();
218 client2
.WaitForResult();
220 EXPECT_EQ(net::OK
, client1
.error_
);
221 AddressList address_list
= (*client1
.results_
).To
<AddressList
>();
222 EXPECT_EQ(1U, address_list
.size());
223 EXPECT_EQ("1.2.3.4:80", address_list
[0].ToString());
224 EXPECT_EQ(net::OK
, client2
.error_
);
225 address_list
= (*client2
.results_
).To
<AddressList
>();
226 EXPECT_EQ(1U, address_list
.size());
227 EXPECT_EQ("8.8.8.8:80", address_list
[0].ToString());
230 TEST_F(MojoHostResolverImplTest
, ResolveDuplicate
) {
231 interfaces::HostResolverRequestClientPtr client1_ptr
;
232 TestRequestClient
client1(mojo::GetProxy(&client1_ptr
));
233 interfaces::HostResolverRequestClientPtr client2_ptr
;
234 TestRequestClient
client2(mojo::GetProxy(&client2_ptr
));
236 mock_host_resolver_
.set_ondemand_mode(true);
238 interfaces::HostResolverRequestInfoPtr request1
=
239 CreateRequest("example.com", 80, false);
240 resolver_service_ptr_
->Resolve(request1
.Pass(), client1_ptr
.Pass());
241 interfaces::HostResolverRequestInfoPtr request2
=
242 CreateRequest("example.com", 80, false);
243 resolver_service_ptr_
->Resolve(request2
.Pass(), client2_ptr
.Pass());
245 mock_host_resolver_
.ResolveAllPending();
247 client1
.WaitForResult();
248 client2
.WaitForResult();
250 EXPECT_EQ(net::OK
, client1
.error_
);
251 AddressList address_list
= (*client1
.results_
).To
<AddressList
>();
252 EXPECT_EQ(1U, address_list
.size());
253 EXPECT_EQ("1.2.3.4:80", address_list
[0].ToString());
254 EXPECT_EQ(net::OK
, client2
.error_
);
255 address_list
= (*client2
.results_
).To
<AddressList
>();
256 EXPECT_EQ(1U, address_list
.size());
257 EXPECT_EQ("1.2.3.4:80", address_list
[0].ToString());
260 TEST_F(MojoHostResolverImplTest
, ResolveFailure
) {
261 interfaces::HostResolverRequestClientPtr client_ptr
;
262 TestRequestClient
client(mojo::GetProxy(&client_ptr
));
264 interfaces::HostResolverRequestInfoPtr request
=
265 CreateRequest("failure.fail", 80, false);
266 resolver_service_ptr_
->Resolve(request
.Pass(), client_ptr
.Pass());
267 client
.WaitForResult();
269 EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED
, client
.error_
);
270 EXPECT_TRUE(client
.results_
.is_null());
273 TEST_F(MojoHostResolverImplTest
, DestroyClient
) {
274 interfaces::HostResolverRequestClientPtr client_ptr
;
275 scoped_ptr
<TestRequestClient
> client(
276 new TestRequestClient(mojo::GetProxy(&client_ptr
)));
278 mock_host_resolver_
.set_ondemand_mode(true);
280 interfaces::HostResolverRequestInfoPtr request
=
281 CreateRequest("example.com", 80, false);
282 resolver_service_ptr_
->Resolve(request
.Pass(), client_ptr
.Pass());
286 base::RunLoop().RunUntilIdle();
288 mock_host_resolver_
.ResolveAllPending();
289 base::RunLoop().RunUntilIdle();
292 TEST_F(MojoHostResolverImplTest
, DestroyService
) {
293 interfaces::HostResolverRequestClientPtr client_ptr
;
294 TestRequestClient
client(mojo::GetProxy(&client_ptr
));
296 mock_host_resolver_
.set_ondemand_mode(true);
298 interfaces::HostResolverRequestInfoPtr request
=
299 CreateRequest("example.com", 80, false);
300 resolver_service_ptr_
->Resolve(request
.Pass(), client_ptr
.Pass());
303 resolver_service_binding_
.reset();
304 resolver_service_
.reset();
306 client
.WaitForConnectionError();