blob: dd5e49d92b8a9d95646b8b6aa0db4810e53e34a1 [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
danakj22f90e72016-04-16 01:55:407#include <memory>
amistry7e6ebfdc82015-02-13 04:19:118#include <string>
dchengc7eeda422015-12-26 03:56:489#include <utility>
amistry7e6ebfdc82015-02-13 04:19:1110
amistry7e6ebfdc82015-02-13 04:19:1111#include "base/run_loop.h"
12#include "base/time/time.h"
rockot85dce0862015-11-13 01:33:5913#include "mojo/public/cpp/bindings/binding.h"
14#include "mojo/public/cpp/bindings/interface_request.h"
amistry7e6ebfdc82015-02-13 04:19:1115#include "net/base/address_list.h"
16#include "net/base/net_errors.h"
amistry7e6ebfdc82015-02-13 04:19:1117#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"
robpercival214763f2016-07-01 23:27:0120#include "net/test/gtest_util.h"
21#include "testing/gmock/include/gmock/gmock.h"
amistry7e6ebfdc82015-02-13 04:19:1122#include "testing/gtest/include/gtest/gtest.h"
amistry7e6ebfdc82015-02-13 04:19:1123
robpercival214763f2016-07-01 23:27:0124using net::test::IsError;
25using net::test::IsOk;
26
amistry7e6ebfdc82015-02-13 04:19:1127namespace net {
28
29namespace {
30
amistry39230722015-07-03 00:24:3931class TestRequestClient : public interfaces::HostResolverRequestClient {
amistry7e6ebfdc82015-02-13 04:19:1132 public:
33 explicit TestRequestClient(
34 mojo::InterfaceRequest<interfaces::HostResolverRequestClient> req)
dchengc7eeda422015-12-26 03:56:4835 : done_(false), binding_(this, std::move(req)) {
amistry39230722015-07-03 00:24:3936 binding_.set_connection_error_handler(base::Bind(
37 &TestRequestClient::OnConnectionError, base::Unretained(this)));
amistry7e6ebfdc82015-02-13 04:19:1138 }
39
40 void WaitForResult();
41 void WaitForConnectionError();
42
43 int32_t error_;
44 interfaces::AddressListPtr results_;
45
46 private:
47 // Overridden from interfaces::HostResolverRequestClient.
48 void ReportResult(int32_t error, interfaces::AddressListPtr results) override;
49
amistry39230722015-07-03 00:24:3950 // Mojo error handler.
51 void OnConnectionError();
amistry7e6ebfdc82015-02-13 04:19:1152
53 bool done_;
54 base::Closure run_loop_quit_closure_;
55 base::Closure connection_error_quit_closure_;
56
57 mojo::Binding<interfaces::HostResolverRequestClient> binding_;
58};
59
60void TestRequestClient::WaitForResult() {
61 if (done_)
62 return;
63
64 base::RunLoop run_loop;
65 run_loop_quit_closure_ = run_loop.QuitClosure();
66 run_loop.Run();
67 ASSERT_TRUE(done_);
68}
69
70void TestRequestClient::WaitForConnectionError() {
71 base::RunLoop run_loop;
72 connection_error_quit_closure_ = run_loop.QuitClosure();
73 run_loop.Run();
74}
75
76void TestRequestClient::ReportResult(int32_t error,
77 interfaces::AddressListPtr results) {
78 if (!run_loop_quit_closure_.is_null()) {
79 run_loop_quit_closure_.Run();
80 }
81 ASSERT_FALSE(done_);
82 error_ = error;
dchengc7eeda422015-12-26 03:56:4883 results_ = std::move(results);
amistry7e6ebfdc82015-02-13 04:19:1184 done_ = true;
85}
86
87void TestRequestClient::OnConnectionError() {
88 if (!connection_error_quit_closure_.is_null())
89 connection_error_quit_closure_.Run();
90}
91
92class CallbackMockHostResolver : public MockHostResolver {
93 public:
94 CallbackMockHostResolver() {}
95 ~CallbackMockHostResolver() override {}
96
97 // Set a callback to run whenever Resolve is called. Callback is cleared after
98 // every run.
99 void SetResolveCallback(base::Closure callback) {
100 resolve_callback_ = callback;
101 }
102
103 // Overridden from MockHostResolver.
104 int Resolve(const RequestInfo& info,
105 RequestPriority priority,
106 AddressList* addresses,
107 const CompletionCallback& callback,
maksim.sisov31452af2016-07-27 06:38:10108 std::unique_ptr<Request>* request,
tfarina428341112016-09-22 13:38:20109 const NetLogWithSource& net_log) override;
amistry7e6ebfdc82015-02-13 04:19:11110
111 private:
112 base::Closure resolve_callback_;
113};
114
115int CallbackMockHostResolver::Resolve(const RequestInfo& info,
116 RequestPriority priority,
117 AddressList* addresses,
118 const CompletionCallback& callback,
maksim.sisov31452af2016-07-27 06:38:10119 std::unique_ptr<Request>* request,
tfarina428341112016-09-22 13:38:20120 const NetLogWithSource& net_log) {
amistry7e6ebfdc82015-02-13 04:19:11121 int result = MockHostResolver::Resolve(info, priority, addresses, callback,
maksim.sisov31452af2016-07-27 06:38:10122 request, net_log);
amistry7e6ebfdc82015-02-13 04:19:11123 if (!resolve_callback_.is_null()) {
124 resolve_callback_.Run();
125 resolve_callback_.Reset();
126 }
127 return result;
128}
129
130} // namespace
131
132class MojoHostResolverImplTest : public testing::Test {
133 protected:
134 void SetUp() override {
135 mock_host_resolver_.rules()->AddRule("example.com", "1.2.3.4");
136 mock_host_resolver_.rules()->AddRule("chromium.org", "8.8.8.8");
137 mock_host_resolver_.rules()->AddSimulatedFailure("failure.fail");
138
sammca3242c92015-07-10 02:38:51139 resolver_service_.reset(
tfarina428341112016-09-22 13:38:20140 new MojoHostResolverImpl(&mock_host_resolver_, NetLogWithSource()));
amistry7e6ebfdc82015-02-13 04:19:11141 }
142
143 interfaces::HostResolverRequestInfoPtr CreateRequest(const std::string& host,
144 uint16_t port,
145 bool is_my_ip_address) {
146 interfaces::HostResolverRequestInfoPtr request =
147 interfaces::HostResolverRequestInfo::New();
148 request->host = host;
149 request->port = port;
sammc16fb38a82016-01-21 05:30:18150 request->address_family = interfaces::AddressFamily::IPV4;
amistry7e6ebfdc82015-02-13 04:19:11151 request->is_my_ip_address = is_my_ip_address;
dchengc7eeda422015-12-26 03:56:48152 return request;
amistry7e6ebfdc82015-02-13 04:19:11153 }
154
155 // Wait until the mock resolver has received |num| resolve requests.
156 void WaitForRequests(size_t num) {
157 while (mock_host_resolver_.num_resolve() < num) {
158 base::RunLoop run_loop;
159 mock_host_resolver_.SetResolveCallback(run_loop.QuitClosure());
160 run_loop.Run();
161 }
162 }
163
164 CallbackMockHostResolver mock_host_resolver_;
danakj22f90e72016-04-16 01:55:40165 std::unique_ptr<MojoHostResolverImpl> resolver_service_;
amistry7e6ebfdc82015-02-13 04:19:11166};
167
168TEST_F(MojoHostResolverImplTest, Resolve) {
169 interfaces::HostResolverRequestClientPtr client_ptr;
170 TestRequestClient client(mojo::GetProxy(&client_ptr));
171
172 interfaces::HostResolverRequestInfoPtr request =
173 CreateRequest("example.com", 80, false);
dchengc7eeda422015-12-26 03:56:48174 resolver_service_->Resolve(std::move(request), std::move(client_ptr));
amistry7e6ebfdc82015-02-13 04:19:11175 client.WaitForResult();
176
robpercival214763f2016-07-01 23:27:01177 EXPECT_THAT(client.error_, IsOk());
amistry7e6ebfdc82015-02-13 04:19:11178 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());
181}
182
183TEST_F(MojoHostResolverImplTest, ResolveSynchronous) {
184 interfaces::HostResolverRequestClientPtr client_ptr;
185 TestRequestClient client(mojo::GetProxy(&client_ptr));
186
187 mock_host_resolver_.set_synchronous_mode(true);
188
189 interfaces::HostResolverRequestInfoPtr request =
190 CreateRequest("example.com", 80, false);
dchengc7eeda422015-12-26 03:56:48191 resolver_service_->Resolve(std::move(request), std::move(client_ptr));
amistry7e6ebfdc82015-02-13 04:19:11192 client.WaitForResult();
193
robpercival214763f2016-07-01 23:27:01194 EXPECT_THAT(client.error_, IsOk());
amistry7e6ebfdc82015-02-13 04:19:11195 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());
198}
199
200TEST_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));
205
206 mock_host_resolver_.set_ondemand_mode(true);
207
208 interfaces::HostResolverRequestInfoPtr request1 =
209 CreateRequest("example.com", 80, false);
dchengc7eeda422015-12-26 03:56:48210 resolver_service_->Resolve(std::move(request1), std::move(client1_ptr));
amistry7e6ebfdc82015-02-13 04:19:11211 interfaces::HostResolverRequestInfoPtr request2 =
212 CreateRequest("chromium.org", 80, false);
dchengc7eeda422015-12-26 03:56:48213 resolver_service_->Resolve(std::move(request2), std::move(client2_ptr));
amistry7e6ebfdc82015-02-13 04:19:11214 WaitForRequests(2);
215 mock_host_resolver_.ResolveAllPending();
216
217 client1.WaitForResult();
218 client2.WaitForResult();
219
robpercival214763f2016-07-01 23:27:01220 EXPECT_THAT(client1.error_, IsOk());
amistry7e6ebfdc82015-02-13 04:19:11221 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());
robpercival214763f2016-07-01 23:27:01224 EXPECT_THAT(client2.error_, IsOk());
amistry7e6ebfdc82015-02-13 04:19:11225 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());
228}
229
230TEST_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));
235
236 mock_host_resolver_.set_ondemand_mode(true);
237
238 interfaces::HostResolverRequestInfoPtr request1 =
239 CreateRequest("example.com", 80, false);
dchengc7eeda422015-12-26 03:56:48240 resolver_service_->Resolve(std::move(request1), std::move(client1_ptr));
amistry7e6ebfdc82015-02-13 04:19:11241 interfaces::HostResolverRequestInfoPtr request2 =
242 CreateRequest("example.com", 80, false);
dchengc7eeda422015-12-26 03:56:48243 resolver_service_->Resolve(std::move(request2), std::move(client2_ptr));
amistry7e6ebfdc82015-02-13 04:19:11244 WaitForRequests(2);
245 mock_host_resolver_.ResolveAllPending();
246
247 client1.WaitForResult();
248 client2.WaitForResult();
249
robpercival214763f2016-07-01 23:27:01250 EXPECT_THAT(client1.error_, IsOk());
amistry7e6ebfdc82015-02-13 04:19:11251 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());
robpercival214763f2016-07-01 23:27:01254 EXPECT_THAT(client2.error_, IsOk());
amistry7e6ebfdc82015-02-13 04:19:11255 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());
258}
259
260TEST_F(MojoHostResolverImplTest, ResolveFailure) {
261 interfaces::HostResolverRequestClientPtr client_ptr;
262 TestRequestClient client(mojo::GetProxy(&client_ptr));
263
264 interfaces::HostResolverRequestInfoPtr request =
265 CreateRequest("failure.fail", 80, false);
dchengc7eeda422015-12-26 03:56:48266 resolver_service_->Resolve(std::move(request), std::move(client_ptr));
amistry7e6ebfdc82015-02-13 04:19:11267 client.WaitForResult();
268
robpercival214763f2016-07-01 23:27:01269 EXPECT_THAT(client.error_, IsError(net::ERR_NAME_NOT_RESOLVED));
amistry7e6ebfdc82015-02-13 04:19:11270 EXPECT_TRUE(client.results_.is_null());
271}
272
273TEST_F(MojoHostResolverImplTest, DestroyClient) {
274 interfaces::HostResolverRequestClientPtr client_ptr;
danakj22f90e72016-04-16 01:55:40275 std::unique_ptr<TestRequestClient> client(
amistry7e6ebfdc82015-02-13 04:19:11276 new TestRequestClient(mojo::GetProxy(&client_ptr)));
277
278 mock_host_resolver_.set_ondemand_mode(true);
279
280 interfaces::HostResolverRequestInfoPtr request =
281 CreateRequest("example.com", 80, false);
dchengc7eeda422015-12-26 03:56:48282 resolver_service_->Resolve(std::move(request), std::move(client_ptr));
amistry7e6ebfdc82015-02-13 04:19:11283 WaitForRequests(1);
284
285 client.reset();
286 base::RunLoop().RunUntilIdle();
287
288 mock_host_resolver_.ResolveAllPending();
289 base::RunLoop().RunUntilIdle();
290}
291
amistry7e6ebfdc82015-02-13 04:19:11292} // namespace net