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 "net/log/net_log.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h"
20 #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h"
26 class TestRequestClient
: public interfaces::HostResolverRequestClient
{
28 explicit TestRequestClient(
29 mojo::InterfaceRequest
<interfaces::HostResolverRequestClient
> req
)
30 : done_(false), binding_(this, req
.Pass()) {
31 binding_
.set_connection_error_handler(base::Bind(
32 &TestRequestClient::OnConnectionError
, base::Unretained(this)));
36 void WaitForConnectionError();
39 interfaces::AddressListPtr results_
;
42 // Overridden from interfaces::HostResolverRequestClient.
43 void ReportResult(int32_t error
, interfaces::AddressListPtr results
) override
;
45 // Mojo error handler.
46 void OnConnectionError();
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(
135 new MojoHostResolverImpl(&mock_host_resolver_
, BoundNetLog()));
138 interfaces::HostResolverRequestInfoPtr
CreateRequest(const std::string
& host
,
140 bool is_my_ip_address
) {
141 interfaces::HostResolverRequestInfoPtr request
=
142 interfaces::HostResolverRequestInfo::New();
143 request
->host
= host
;
144 request
->port
= port
;
145 request
->address_family
= interfaces::ADDRESS_FAMILY_IPV4
;
146 request
->is_my_ip_address
= is_my_ip_address
;
147 return request
.Pass();
150 // Wait until the mock resolver has received |num| resolve requests.
151 void WaitForRequests(size_t num
) {
152 while (mock_host_resolver_
.num_resolve() < num
) {
153 base::RunLoop run_loop
;
154 mock_host_resolver_
.SetResolveCallback(run_loop
.QuitClosure());
159 CallbackMockHostResolver mock_host_resolver_
;
160 scoped_ptr
<MojoHostResolverImpl
> resolver_service_
;
163 TEST_F(MojoHostResolverImplTest
, Resolve
) {
164 interfaces::HostResolverRequestClientPtr client_ptr
;
165 TestRequestClient
client(mojo::GetProxy(&client_ptr
));
167 interfaces::HostResolverRequestInfoPtr request
=
168 CreateRequest("example.com", 80, false);
169 resolver_service_
->Resolve(request
.Pass(), client_ptr
.Pass());
170 client
.WaitForResult();
172 EXPECT_EQ(net::OK
, client
.error_
);
173 AddressList address_list
= (*client
.results_
).To
<AddressList
>();
174 EXPECT_EQ(1U, address_list
.size());
175 EXPECT_EQ("1.2.3.4:80", address_list
[0].ToString());
178 TEST_F(MojoHostResolverImplTest
, ResolveSynchronous
) {
179 interfaces::HostResolverRequestClientPtr client_ptr
;
180 TestRequestClient
client(mojo::GetProxy(&client_ptr
));
182 mock_host_resolver_
.set_synchronous_mode(true);
184 interfaces::HostResolverRequestInfoPtr request
=
185 CreateRequest("example.com", 80, false);
186 resolver_service_
->Resolve(request
.Pass(), client_ptr
.Pass());
187 client
.WaitForResult();
189 EXPECT_EQ(net::OK
, client
.error_
);
190 AddressList address_list
= (*client
.results_
).To
<AddressList
>();
191 EXPECT_EQ(1U, address_list
.size());
192 EXPECT_EQ("1.2.3.4:80", address_list
[0].ToString());
195 TEST_F(MojoHostResolverImplTest
, ResolveMultiple
) {
196 interfaces::HostResolverRequestClientPtr client1_ptr
;
197 TestRequestClient
client1(mojo::GetProxy(&client1_ptr
));
198 interfaces::HostResolverRequestClientPtr client2_ptr
;
199 TestRequestClient
client2(mojo::GetProxy(&client2_ptr
));
201 mock_host_resolver_
.set_ondemand_mode(true);
203 interfaces::HostResolverRequestInfoPtr request1
=
204 CreateRequest("example.com", 80, false);
205 resolver_service_
->Resolve(request1
.Pass(), client1_ptr
.Pass());
206 interfaces::HostResolverRequestInfoPtr request2
=
207 CreateRequest("chromium.org", 80, false);
208 resolver_service_
->Resolve(request2
.Pass(), client2_ptr
.Pass());
210 mock_host_resolver_
.ResolveAllPending();
212 client1
.WaitForResult();
213 client2
.WaitForResult();
215 EXPECT_EQ(net::OK
, client1
.error_
);
216 AddressList address_list
= (*client1
.results_
).To
<AddressList
>();
217 EXPECT_EQ(1U, address_list
.size());
218 EXPECT_EQ("1.2.3.4:80", address_list
[0].ToString());
219 EXPECT_EQ(net::OK
, client2
.error_
);
220 address_list
= (*client2
.results_
).To
<AddressList
>();
221 EXPECT_EQ(1U, address_list
.size());
222 EXPECT_EQ("8.8.8.8:80", address_list
[0].ToString());
225 TEST_F(MojoHostResolverImplTest
, ResolveDuplicate
) {
226 interfaces::HostResolverRequestClientPtr client1_ptr
;
227 TestRequestClient
client1(mojo::GetProxy(&client1_ptr
));
228 interfaces::HostResolverRequestClientPtr client2_ptr
;
229 TestRequestClient
client2(mojo::GetProxy(&client2_ptr
));
231 mock_host_resolver_
.set_ondemand_mode(true);
233 interfaces::HostResolverRequestInfoPtr request1
=
234 CreateRequest("example.com", 80, false);
235 resolver_service_
->Resolve(request1
.Pass(), client1_ptr
.Pass());
236 interfaces::HostResolverRequestInfoPtr request2
=
237 CreateRequest("example.com", 80, false);
238 resolver_service_
->Resolve(request2
.Pass(), client2_ptr
.Pass());
240 mock_host_resolver_
.ResolveAllPending();
242 client1
.WaitForResult();
243 client2
.WaitForResult();
245 EXPECT_EQ(net::OK
, client1
.error_
);
246 AddressList address_list
= (*client1
.results_
).To
<AddressList
>();
247 EXPECT_EQ(1U, address_list
.size());
248 EXPECT_EQ("1.2.3.4:80", address_list
[0].ToString());
249 EXPECT_EQ(net::OK
, client2
.error_
);
250 address_list
= (*client2
.results_
).To
<AddressList
>();
251 EXPECT_EQ(1U, address_list
.size());
252 EXPECT_EQ("1.2.3.4:80", address_list
[0].ToString());
255 TEST_F(MojoHostResolverImplTest
, ResolveFailure
) {
256 interfaces::HostResolverRequestClientPtr client_ptr
;
257 TestRequestClient
client(mojo::GetProxy(&client_ptr
));
259 interfaces::HostResolverRequestInfoPtr request
=
260 CreateRequest("failure.fail", 80, false);
261 resolver_service_
->Resolve(request
.Pass(), client_ptr
.Pass());
262 client
.WaitForResult();
264 EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED
, client
.error_
);
265 EXPECT_TRUE(client
.results_
.is_null());
268 TEST_F(MojoHostResolverImplTest
, DestroyClient
) {
269 interfaces::HostResolverRequestClientPtr client_ptr
;
270 scoped_ptr
<TestRequestClient
> client(
271 new TestRequestClient(mojo::GetProxy(&client_ptr
)));
273 mock_host_resolver_
.set_ondemand_mode(true);
275 interfaces::HostResolverRequestInfoPtr request
=
276 CreateRequest("example.com", 80, false);
277 resolver_service_
->Resolve(request
.Pass(), client_ptr
.Pass());
281 base::RunLoop().RunUntilIdle();
283 mock_host_resolver_
.ResolveAllPending();
284 base::RunLoop().RunUntilIdle();