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/interface_request.h"
25 class TestRequestClient
: public interfaces::HostResolverRequestClient
{
27 explicit TestRequestClient(
28 mojo::InterfaceRequest
<interfaces::HostResolverRequestClient
> req
)
29 : done_(false), binding_(this, req
.Pass()) {
30 binding_
.set_connection_error_handler(base::Bind(
31 &TestRequestClient::OnConnectionError
, base::Unretained(this)));
35 void WaitForConnectionError();
38 interfaces::AddressListPtr results_
;
41 // Overridden from interfaces::HostResolverRequestClient.
42 void ReportResult(int32_t error
, interfaces::AddressListPtr results
) override
;
44 // Mojo error handler.
45 void OnConnectionError();
48 base::Closure run_loop_quit_closure_
;
49 base::Closure connection_error_quit_closure_
;
51 mojo::Binding
<interfaces::HostResolverRequestClient
> binding_
;
54 void TestRequestClient::WaitForResult() {
58 base::RunLoop run_loop
;
59 run_loop_quit_closure_
= run_loop
.QuitClosure();
64 void TestRequestClient::WaitForConnectionError() {
65 base::RunLoop run_loop
;
66 connection_error_quit_closure_
= run_loop
.QuitClosure();
70 void TestRequestClient::ReportResult(int32_t error
,
71 interfaces::AddressListPtr results
) {
72 if (!run_loop_quit_closure_
.is_null()) {
73 run_loop_quit_closure_
.Run();
77 results_
= results
.Pass();
81 void TestRequestClient::OnConnectionError() {
82 if (!connection_error_quit_closure_
.is_null())
83 connection_error_quit_closure_
.Run();
86 class CallbackMockHostResolver
: public MockHostResolver
{
88 CallbackMockHostResolver() {}
89 ~CallbackMockHostResolver() override
{}
91 // Set a callback to run whenever Resolve is called. Callback is cleared after
93 void SetResolveCallback(base::Closure callback
) {
94 resolve_callback_
= callback
;
97 // Overridden from MockHostResolver.
98 int Resolve(const RequestInfo
& info
,
99 RequestPriority priority
,
100 AddressList
* addresses
,
101 const CompletionCallback
& callback
,
102 RequestHandle
* out_req
,
103 const BoundNetLog
& net_log
) override
;
106 base::Closure resolve_callback_
;
109 int CallbackMockHostResolver::Resolve(const RequestInfo
& info
,
110 RequestPriority priority
,
111 AddressList
* addresses
,
112 const CompletionCallback
& callback
,
113 RequestHandle
* out_req
,
114 const BoundNetLog
& net_log
) {
115 int result
= MockHostResolver::Resolve(info
, priority
, addresses
, callback
,
117 if (!resolve_callback_
.is_null()) {
118 resolve_callback_
.Run();
119 resolve_callback_
.Reset();
126 class MojoHostResolverImplTest
: public testing::Test
{
128 void SetUp() override
{
129 mock_host_resolver_
.rules()->AddRule("example.com", "1.2.3.4");
130 mock_host_resolver_
.rules()->AddRule("chromium.org", "8.8.8.8");
131 mock_host_resolver_
.rules()->AddSimulatedFailure("failure.fail");
133 resolver_service_
.reset(new MojoHostResolverImpl(&mock_host_resolver_
));
134 resolver_service_binding_
.reset(
135 new mojo::Binding
<interfaces::HostResolver
>(resolver_service_
.get()));
136 resolver_service_binding_
->Bind(mojo::GetProxy(&resolver_service_ptr_
));
139 interfaces::HostResolverRequestInfoPtr
CreateRequest(const std::string
& host
,
141 bool is_my_ip_address
) {
142 interfaces::HostResolverRequestInfoPtr request
=
143 interfaces::HostResolverRequestInfo::New();
144 request
->host
= host
;
145 request
->port
= port
;
146 request
->address_family
= interfaces::ADDRESS_FAMILY_IPV4
;
147 request
->is_my_ip_address
= is_my_ip_address
;
148 return request
.Pass();
151 // Wait until the mock resolver has received |num| resolve requests.
152 void WaitForRequests(size_t num
) {
153 while (mock_host_resolver_
.num_resolve() < num
) {
154 base::RunLoop run_loop
;
155 mock_host_resolver_
.SetResolveCallback(run_loop
.QuitClosure());
160 CallbackMockHostResolver mock_host_resolver_
;
161 scoped_ptr
<MojoHostResolverImpl
> resolver_service_
;
163 scoped_ptr
<mojo::Binding
<interfaces::HostResolver
>> resolver_service_binding_
;
164 interfaces::HostResolverPtr resolver_service_ptr_
;
167 TEST_F(MojoHostResolverImplTest
, Resolve
) {
168 interfaces::HostResolverRequestClientPtr client_ptr
;
169 TestRequestClient
client(mojo::GetProxy(&client_ptr
));
171 interfaces::HostResolverRequestInfoPtr request
=
172 CreateRequest("example.com", 80, false);
173 resolver_service_ptr_
->Resolve(request
.Pass(), client_ptr
.Pass());
174 client
.WaitForResult();
176 EXPECT_EQ(net::OK
, client
.error_
);
177 AddressList address_list
= (*client
.results_
).To
<AddressList
>();
178 EXPECT_EQ(1U, address_list
.size());
179 EXPECT_EQ("1.2.3.4:80", address_list
[0].ToString());
182 TEST_F(MojoHostResolverImplTest
, ResolveSynchronous
) {
183 interfaces::HostResolverRequestClientPtr client_ptr
;
184 TestRequestClient
client(mojo::GetProxy(&client_ptr
));
186 mock_host_resolver_
.set_synchronous_mode(true);
188 interfaces::HostResolverRequestInfoPtr request
=
189 CreateRequest("example.com", 80, false);
190 resolver_service_ptr_
->Resolve(request
.Pass(), client_ptr
.Pass());
191 client
.WaitForResult();
193 EXPECT_EQ(net::OK
, client
.error_
);
194 AddressList address_list
= (*client
.results_
).To
<AddressList
>();
195 EXPECT_EQ(1U, address_list
.size());
196 EXPECT_EQ("1.2.3.4:80", address_list
[0].ToString());
199 TEST_F(MojoHostResolverImplTest
, ResolveMultiple
) {
200 interfaces::HostResolverRequestClientPtr client1_ptr
;
201 TestRequestClient
client1(mojo::GetProxy(&client1_ptr
));
202 interfaces::HostResolverRequestClientPtr client2_ptr
;
203 TestRequestClient
client2(mojo::GetProxy(&client2_ptr
));
205 mock_host_resolver_
.set_ondemand_mode(true);
207 interfaces::HostResolverRequestInfoPtr request1
=
208 CreateRequest("example.com", 80, false);
209 resolver_service_ptr_
->Resolve(request1
.Pass(), client1_ptr
.Pass());
210 interfaces::HostResolverRequestInfoPtr request2
=
211 CreateRequest("chromium.org", 80, false);
212 resolver_service_ptr_
->Resolve(request2
.Pass(), client2_ptr
.Pass());
214 mock_host_resolver_
.ResolveAllPending();
216 client1
.WaitForResult();
217 client2
.WaitForResult();
219 EXPECT_EQ(net::OK
, client1
.error_
);
220 AddressList address_list
= (*client1
.results_
).To
<AddressList
>();
221 EXPECT_EQ(1U, address_list
.size());
222 EXPECT_EQ("1.2.3.4:80", address_list
[0].ToString());
223 EXPECT_EQ(net::OK
, client2
.error_
);
224 address_list
= (*client2
.results_
).To
<AddressList
>();
225 EXPECT_EQ(1U, address_list
.size());
226 EXPECT_EQ("8.8.8.8:80", address_list
[0].ToString());
229 TEST_F(MojoHostResolverImplTest
, ResolveDuplicate
) {
230 interfaces::HostResolverRequestClientPtr client1_ptr
;
231 TestRequestClient
client1(mojo::GetProxy(&client1_ptr
));
232 interfaces::HostResolverRequestClientPtr client2_ptr
;
233 TestRequestClient
client2(mojo::GetProxy(&client2_ptr
));
235 mock_host_resolver_
.set_ondemand_mode(true);
237 interfaces::HostResolverRequestInfoPtr request1
=
238 CreateRequest("example.com", 80, false);
239 resolver_service_ptr_
->Resolve(request1
.Pass(), client1_ptr
.Pass());
240 interfaces::HostResolverRequestInfoPtr request2
=
241 CreateRequest("example.com", 80, false);
242 resolver_service_ptr_
->Resolve(request2
.Pass(), client2_ptr
.Pass());
244 mock_host_resolver_
.ResolveAllPending();
246 client1
.WaitForResult();
247 client2
.WaitForResult();
249 EXPECT_EQ(net::OK
, client1
.error_
);
250 AddressList address_list
= (*client1
.results_
).To
<AddressList
>();
251 EXPECT_EQ(1U, address_list
.size());
252 EXPECT_EQ("1.2.3.4:80", address_list
[0].ToString());
253 EXPECT_EQ(net::OK
, client2
.error_
);
254 address_list
= (*client2
.results_
).To
<AddressList
>();
255 EXPECT_EQ(1U, address_list
.size());
256 EXPECT_EQ("1.2.3.4:80", address_list
[0].ToString());
259 TEST_F(MojoHostResolverImplTest
, ResolveFailure
) {
260 interfaces::HostResolverRequestClientPtr client_ptr
;
261 TestRequestClient
client(mojo::GetProxy(&client_ptr
));
263 interfaces::HostResolverRequestInfoPtr request
=
264 CreateRequest("failure.fail", 80, false);
265 resolver_service_ptr_
->Resolve(request
.Pass(), client_ptr
.Pass());
266 client
.WaitForResult();
268 EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED
, client
.error_
);
269 EXPECT_TRUE(client
.results_
.is_null());
272 TEST_F(MojoHostResolverImplTest
, DestroyClient
) {
273 interfaces::HostResolverRequestClientPtr client_ptr
;
274 scoped_ptr
<TestRequestClient
> client(
275 new TestRequestClient(mojo::GetProxy(&client_ptr
)));
277 mock_host_resolver_
.set_ondemand_mode(true);
279 interfaces::HostResolverRequestInfoPtr request
=
280 CreateRequest("example.com", 80, false);
281 resolver_service_ptr_
->Resolve(request
.Pass(), client_ptr
.Pass());
285 base::RunLoop().RunUntilIdle();
287 mock_host_resolver_
.ResolveAllPending();
288 base::RunLoop().RunUntilIdle();
291 TEST_F(MojoHostResolverImplTest
, DestroyService
) {
292 interfaces::HostResolverRequestClientPtr client_ptr
;
293 TestRequestClient
client(mojo::GetProxy(&client_ptr
));
295 mock_host_resolver_
.set_ondemand_mode(true);
297 interfaces::HostResolverRequestInfoPtr request
=
298 CreateRequest("example.com", 80, false);
299 resolver_service_ptr_
->Resolve(request
.Pass(), client_ptr
.Pass());
302 resolver_service_binding_
.reset();
303 resolver_service_
.reset();
305 client
.WaitForConnectionError();