blob: 130462cd3764d26eeae67a25dbf1d97699ebc778 [file] [log] [blame]
amistry7e6ebfdc82015-02-13 04:19:111// 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.
4
5#include "net/dns/mojo_host_resolver_impl.h"
6
7#include <string>
8
9#include "base/memory/scoped_ptr.h"
10#include "base/run_loop.h"
11#include "base/time/time.h"
rockot85dce0862015-11-13 01:33:5912#include "mojo/public/cpp/bindings/binding.h"
13#include "mojo/public/cpp/bindings/interface_request.h"
amistry7e6ebfdc82015-02-13 04:19:1114#include "net/base/address_list.h"
15#include "net/base/net_errors.h"
16#include "net/base/net_util.h"
17#include "net/dns/mock_host_resolver.h"
amistry7ec58112015-02-26 06:03:0018#include "net/dns/mojo_host_type_converters.h"
sammca3242c92015-07-10 02:38:5119#include "net/log/net_log.h"
amistry7e6ebfdc82015-02-13 04:19:1120#include "testing/gtest/include/gtest/gtest.h"
amistry7e6ebfdc82015-02-13 04:19:1121
22namespace net {
23
24namespace {
25
amistry39230722015-07-03 00:24:3926class TestRequestClient : public interfaces::HostResolverRequestClient {
amistry7e6ebfdc82015-02-13 04:19:1127 public:
28 explicit TestRequestClient(
29 mojo::InterfaceRequest<interfaces::HostResolverRequestClient> req)
30 : done_(false), binding_(this, req.Pass()) {
amistry39230722015-07-03 00:24:3931 binding_.set_connection_error_handler(base::Bind(
32 &TestRequestClient::OnConnectionError, base::Unretained(this)));
amistry7e6ebfdc82015-02-13 04:19:1133 }
34
35 void WaitForResult();
36 void WaitForConnectionError();
37
38 int32_t error_;
39 interfaces::AddressListPtr results_;
40
41 private:
42 // Overridden from interfaces::HostResolverRequestClient.
43 void ReportResult(int32_t error, interfaces::AddressListPtr results) override;
44
amistry39230722015-07-03 00:24:3945 // Mojo error handler.
46 void OnConnectionError();
amistry7e6ebfdc82015-02-13 04:19:1147
48 bool done_;
49 base::Closure run_loop_quit_closure_;
50 base::Closure connection_error_quit_closure_;
51
52 mojo::Binding<interfaces::HostResolverRequestClient> binding_;
53};
54
55void TestRequestClient::WaitForResult() {
56 if (done_)
57 return;
58
59 base::RunLoop run_loop;
60 run_loop_quit_closure_ = run_loop.QuitClosure();
61 run_loop.Run();
62 ASSERT_TRUE(done_);
63}
64
65void TestRequestClient::WaitForConnectionError() {
66 base::RunLoop run_loop;
67 connection_error_quit_closure_ = run_loop.QuitClosure();
68 run_loop.Run();
69}
70
71void TestRequestClient::ReportResult(int32_t error,
72 interfaces::AddressListPtr results) {
73 if (!run_loop_quit_closure_.is_null()) {
74 run_loop_quit_closure_.Run();
75 }
76 ASSERT_FALSE(done_);
77 error_ = error;
78 results_ = results.Pass();
79 done_ = true;
80}
81
82void TestRequestClient::OnConnectionError() {
83 if (!connection_error_quit_closure_.is_null())
84 connection_error_quit_closure_.Run();
85}
86
87class CallbackMockHostResolver : public MockHostResolver {
88 public:
89 CallbackMockHostResolver() {}
90 ~CallbackMockHostResolver() override {}
91
92 // Set a callback to run whenever Resolve is called. Callback is cleared after
93 // every run.
94 void SetResolveCallback(base::Closure callback) {
95 resolve_callback_ = callback;
96 }
97
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;
105
106 private:
107 base::Closure resolve_callback_;
108};
109
110int 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,
117 out_req, net_log);
118 if (!resolve_callback_.is_null()) {
119 resolve_callback_.Run();
120 resolve_callback_.Reset();
121 }
122 return result;
123}
124
125} // namespace
126
127class MojoHostResolverImplTest : public testing::Test {
128 protected:
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");
133
sammca3242c92015-07-10 02:38:51134 resolver_service_.reset(
135 new MojoHostResolverImpl(&mock_host_resolver_, BoundNetLog()));
amistry7e6ebfdc82015-02-13 04:19:11136 }
137
138 interfaces::HostResolverRequestInfoPtr CreateRequest(const std::string& host,
139 uint16_t port,
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();
148 }
149
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());
155 run_loop.Run();
156 }
157 }
158
159 CallbackMockHostResolver mock_host_resolver_;
160 scoped_ptr<MojoHostResolverImpl> resolver_service_;
amistry7e6ebfdc82015-02-13 04:19:11161};
162
163TEST_F(MojoHostResolverImplTest, Resolve) {
164 interfaces::HostResolverRequestClientPtr client_ptr;
165 TestRequestClient client(mojo::GetProxy(&client_ptr));
166
167 interfaces::HostResolverRequestInfoPtr request =
168 CreateRequest("example.com", 80, false);
sammca3242c92015-07-10 02:38:51169 resolver_service_->Resolve(request.Pass(), client_ptr.Pass());
amistry7e6ebfdc82015-02-13 04:19:11170 client.WaitForResult();
171
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());
176}
177
178TEST_F(MojoHostResolverImplTest, ResolveSynchronous) {
179 interfaces::HostResolverRequestClientPtr client_ptr;
180 TestRequestClient client(mojo::GetProxy(&client_ptr));
181
182 mock_host_resolver_.set_synchronous_mode(true);
183
184 interfaces::HostResolverRequestInfoPtr request =
185 CreateRequest("example.com", 80, false);
sammca3242c92015-07-10 02:38:51186 resolver_service_->Resolve(request.Pass(), client_ptr.Pass());
amistry7e6ebfdc82015-02-13 04:19:11187 client.WaitForResult();
188
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());
193}
194
195TEST_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));
200
201 mock_host_resolver_.set_ondemand_mode(true);
202
203 interfaces::HostResolverRequestInfoPtr request1 =
204 CreateRequest("example.com", 80, false);
sammca3242c92015-07-10 02:38:51205 resolver_service_->Resolve(request1.Pass(), client1_ptr.Pass());
amistry7e6ebfdc82015-02-13 04:19:11206 interfaces::HostResolverRequestInfoPtr request2 =
207 CreateRequest("chromium.org", 80, false);
sammca3242c92015-07-10 02:38:51208 resolver_service_->Resolve(request2.Pass(), client2_ptr.Pass());
amistry7e6ebfdc82015-02-13 04:19:11209 WaitForRequests(2);
210 mock_host_resolver_.ResolveAllPending();
211
212 client1.WaitForResult();
213 client2.WaitForResult();
214
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());
223}
224
225TEST_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));
230
231 mock_host_resolver_.set_ondemand_mode(true);
232
233 interfaces::HostResolverRequestInfoPtr request1 =
234 CreateRequest("example.com", 80, false);
sammca3242c92015-07-10 02:38:51235 resolver_service_->Resolve(request1.Pass(), client1_ptr.Pass());
amistry7e6ebfdc82015-02-13 04:19:11236 interfaces::HostResolverRequestInfoPtr request2 =
237 CreateRequest("example.com", 80, false);
sammca3242c92015-07-10 02:38:51238 resolver_service_->Resolve(request2.Pass(), client2_ptr.Pass());
amistry7e6ebfdc82015-02-13 04:19:11239 WaitForRequests(2);
240 mock_host_resolver_.ResolveAllPending();
241
242 client1.WaitForResult();
243 client2.WaitForResult();
244
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());
253}
254
255TEST_F(MojoHostResolverImplTest, ResolveFailure) {
256 interfaces::HostResolverRequestClientPtr client_ptr;
257 TestRequestClient client(mojo::GetProxy(&client_ptr));
258
259 interfaces::HostResolverRequestInfoPtr request =
260 CreateRequest("failure.fail", 80, false);
sammca3242c92015-07-10 02:38:51261 resolver_service_->Resolve(request.Pass(), client_ptr.Pass());
amistry7e6ebfdc82015-02-13 04:19:11262 client.WaitForResult();
263
264 EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, client.error_);
265 EXPECT_TRUE(client.results_.is_null());
266}
267
268TEST_F(MojoHostResolverImplTest, DestroyClient) {
269 interfaces::HostResolverRequestClientPtr client_ptr;
270 scoped_ptr<TestRequestClient> client(
271 new TestRequestClient(mojo::GetProxy(&client_ptr)));
272
273 mock_host_resolver_.set_ondemand_mode(true);
274
275 interfaces::HostResolverRequestInfoPtr request =
276 CreateRequest("example.com", 80, false);
sammca3242c92015-07-10 02:38:51277 resolver_service_->Resolve(request.Pass(), client_ptr.Pass());
amistry7e6ebfdc82015-02-13 04:19:11278 WaitForRequests(1);
279
280 client.reset();
281 base::RunLoop().RunUntilIdle();
282
283 mock_host_resolver_.ResolveAllPending();
284 base::RunLoop().RunUntilIdle();
285}
286
amistry7e6ebfdc82015-02-13 04:19:11287} // namespace net