OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 #include "net/dns/host_resolver_mojo.h" | |
6 | |
7 #include <string> | |
8 | |
9 #include "base/memory/scoped_vector.h" | |
10 #include "net/base/address_list.h" | |
11 #include "net/base/net_errors.h" | |
12 #include "net/base/request_priority.h" | |
13 #include "net/base/test_completion_callback.h" | |
14 #include "net/dns/mojo_type_converters.h" | |
15 #include "net/test/event_waiter.h" | |
16 #include "testing/gtest/include/gtest/gtest.h" | |
17 #include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h" | |
18 #include "third_party/mojo/src/mojo/public/cpp/bindings/error_handler.h" | |
19 | |
20 namespace net { | |
21 namespace { | |
22 | |
23 void Fail(int result) { | |
24 FAIL() << "Unexpected callback called with error " << result; | |
25 } | |
26 | |
27 class MockMojoHostResolverRequest : public mojo::ErrorHandler { | |
28 public: | |
29 MockMojoHostResolverRequest(interfaces::HostResolverRequestClientPtr client, | |
30 const base::Closure& error_callback); | |
31 void OnConnectionError() override; | |
32 | |
33 private: | |
34 interfaces::HostResolverRequestClientPtr client_; | |
35 const base::Closure error_callback_; | |
36 }; | |
37 | |
38 MockMojoHostResolverRequest::MockMojoHostResolverRequest( | |
39 interfaces::HostResolverRequestClientPtr client, | |
40 const base::Closure& error_callback) | |
41 : client_(client.Pass()), error_callback_(error_callback) { | |
42 client_.set_error_handler(this); | |
43 } | |
44 | |
45 void MockMojoHostResolverRequest::OnConnectionError() { | |
46 error_callback_.Run(); | |
47 } | |
48 | |
49 struct HostResolverAction { | |
50 public: | |
eroman
2015/02/25 00:50:44
nit: no need for public
Sam McNally
2015/02/25 02:17:45
Done.
| |
51 enum Action { | |
52 COMPLETE, | |
53 DROP, | |
54 RETAIN, | |
55 }; | |
56 | |
57 static scoped_ptr<HostResolverAction> ReturnError(int error) { | |
58 scoped_ptr<HostResolverAction> result(new HostResolverAction); | |
59 result->error = error; | |
60 return result.Pass(); | |
61 } | |
62 | |
63 static scoped_ptr<HostResolverAction> ReturnResult( | |
64 const AddressList& address_list) { | |
65 scoped_ptr<HostResolverAction> result(new HostResolverAction); | |
66 result->addresses = interfaces::AddressList::From(address_list); | |
67 return result.Pass(); | |
68 } | |
69 | |
70 static scoped_ptr<HostResolverAction> DropRequest() { | |
71 scoped_ptr<HostResolverAction> result(new HostResolverAction); | |
72 result->action = DROP; | |
73 return result.Pass(); | |
74 } | |
75 | |
76 static scoped_ptr<HostResolverAction> RetainRequest() { | |
77 scoped_ptr<HostResolverAction> result(new HostResolverAction); | |
78 result->action = RETAIN; | |
79 return result.Pass(); | |
80 } | |
81 | |
82 Action action = COMPLETE; | |
83 interfaces::AddressListPtr addresses; | |
84 int error = OK; | |
eroman
2015/02/25 00:50:44
probably want to use net::Error consistently throu
Sam McNally
2015/02/25 02:17:45
Done.
| |
85 }; | |
86 | |
87 class MockMojoHostResolver : public interfaces::HostResolver, | |
88 public mojo::ErrorHandler { | |
89 public: | |
90 explicit MockMojoHostResolver( | |
eroman
2015/02/25 00:50:44
no need for explicit
Sam McNally
2015/02/25 02:17:45
Done.
| |
91 mojo::InterfaceRequest<interfaces::HostResolver> request, | |
92 const base::Closure& resolver_connection_error_callback, | |
93 const base::Closure& request_connection_error_callback); | |
94 ~MockMojoHostResolver() override; | |
95 | |
96 void AddAction(scoped_ptr<HostResolverAction> action); | |
97 | |
98 const mojo::Array<interfaces::HostResolverRequestInfoPtr>& requests() { | |
99 return requests_received_; | |
100 } | |
101 | |
102 private: | |
103 // interfaces::HostResolver override. | |
104 void Resolve(interfaces::HostResolverRequestInfoPtr request_info, | |
105 interfaces::HostResolverRequestClientPtr client) override; | |
106 | |
107 // mojo::ErrorHandler override. | |
108 void OnConnectionError() override; | |
109 | |
110 mojo::Binding<interfaces::HostResolver> binding_; | |
111 ScopedVector<HostResolverAction> actions_; | |
112 size_t results_returned_ = 0; | |
113 mojo::Array<interfaces::HostResolverRequestInfoPtr> requests_received_; | |
114 const base::Closure resolver_connection_error_callback_; | |
115 const base::Closure request_connection_error_callback_; | |
116 ScopedVector<MockMojoHostResolverRequest> requests_; | |
117 }; | |
118 | |
119 MockMojoHostResolver::MockMojoHostResolver( | |
120 mojo::InterfaceRequest<interfaces::HostResolver> request, | |
121 const base::Closure& resolver_connection_error_callback, | |
122 const base::Closure& request_connection_error_callback) | |
123 : binding_(this, request.Pass()), | |
124 resolver_connection_error_callback_(resolver_connection_error_callback), | |
125 request_connection_error_callback_(request_connection_error_callback) { | |
126 binding_.set_error_handler(this); | |
127 } | |
128 | |
129 MockMojoHostResolver::~MockMojoHostResolver() { | |
130 EXPECT_EQ(results_returned_, actions_.size()); | |
131 } | |
132 | |
133 void MockMojoHostResolver::OnConnectionError() { | |
134 resolver_connection_error_callback_.Run(); | |
135 } | |
136 | |
137 void MockMojoHostResolver::AddAction(scoped_ptr<HostResolverAction> action) { | |
138 actions_.push_back(action.release()); | |
139 } | |
140 | |
141 void MockMojoHostResolver::Resolve( | |
142 interfaces::HostResolverRequestInfoPtr request_info, | |
143 interfaces::HostResolverRequestClientPtr client) { | |
144 requests_received_.push_back(request_info.Pass()); | |
145 ASSERT_LE(results_returned_, actions_.size()); | |
146 switch (actions_[results_returned_]->action) { | |
147 case HostResolverAction::COMPLETE: | |
148 client->ReportResult(actions_[results_returned_]->error, | |
149 actions_[results_returned_]->addresses.Pass()); | |
150 break; | |
151 case HostResolverAction::RETAIN: | |
152 requests_.push_back(new MockMojoHostResolverRequest( | |
153 client.Pass(), request_connection_error_callback_)); | |
154 break; | |
155 case HostResolverAction::DROP: | |
156 client.reset(); | |
157 break; | |
158 } | |
159 results_returned_++; | |
160 } | |
161 | |
162 } // namespace | |
163 | |
164 class HostResolverMojoTest : public testing::Test { | |
165 protected: | |
166 enum class ConnectionErrorSource { | |
167 RESOLVER, | |
168 REQUEST, | |
169 CLIENT, | |
170 }; | |
171 using Waiter = EventWaiter<ConnectionErrorSource>; | |
172 | |
173 void SetUp() override { | |
174 interfaces::HostResolverPtr resolver_ptr; | |
175 mock_resolver_.reset(new MockMojoHostResolver( | |
176 mojo::GetProxy(&resolver_ptr), | |
177 base::Bind(&Waiter::NotifyEvent, base::Unretained(&waiter_), | |
178 ConnectionErrorSource::RESOLVER), | |
179 base::Bind(&Waiter::NotifyEvent, base::Unretained(&waiter_), | |
180 ConnectionErrorSource::REQUEST))); | |
181 resolver_.reset(new HostResolverMojo( | |
182 resolver_ptr.Pass(), | |
183 base::Bind(&Waiter::NotifyEvent, base::Unretained(&waiter_), | |
184 ConnectionErrorSource::CLIENT))); | |
185 } | |
186 | |
187 int Resolve(const HostResolver::RequestInfo& request_info, | |
188 AddressList* result) { | |
189 HostResolver::RequestHandle request_handle = nullptr; | |
190 TestCompletionCallback callback; | |
191 return callback.GetResult(resolver_->Resolve( | |
192 request_info, DEFAULT_PRIORITY, result, callback.callback(), | |
193 &request_handle, BoundNetLog())); | |
194 } | |
195 | |
196 scoped_ptr<MockMojoHostResolver> mock_resolver_; | |
197 | |
198 scoped_ptr<HostResolverMojo> resolver_; | |
199 | |
200 Waiter waiter_; | |
201 }; | |
202 | |
203 TEST_F(HostResolverMojoTest, Basic) { | |
204 AddressList address_list; | |
205 IPAddressNumber address_number; | |
206 ASSERT_TRUE(ParseIPLiteralToNumber("1.2.3.4", &address_number)); | |
207 address_list.push_back(IPEndPoint(address_number, 12345)); | |
208 address_list.push_back( | |
209 IPEndPoint(ConvertIPv4NumberToIPv6Number(address_number), 12345)); | |
210 mock_resolver_->AddAction(HostResolverAction::ReturnResult(address_list)); | |
211 HostResolver::RequestInfo request_info( | |
212 HostPortPair::FromString("example.com:12345")); | |
213 AddressList result; | |
214 EXPECT_EQ(OK, Resolve(request_info, &result)); | |
215 ASSERT_EQ(2u, result.size()); | |
216 EXPECT_EQ(address_list[0], result[0]); | |
217 EXPECT_EQ(address_list[1], result[1]); | |
218 | |
219 ASSERT_EQ(1u, mock_resolver_->requests().size()); | |
220 interfaces::HostResolverRequestInfo& request = *mock_resolver_->requests()[0]; | |
221 EXPECT_EQ("example.com", request.host.To<std::string>()); | |
222 EXPECT_EQ(12345, request.port); | |
223 EXPECT_EQ(interfaces::ADDRESS_FAMILY_UNSPECIFIED, request.address_family); | |
224 EXPECT_FALSE(request.is_my_ip_address); | |
225 } | |
226 | |
227 TEST_F(HostResolverMojoTest, Multiple) { | |
228 AddressList address_list; | |
229 IPAddressNumber address_number; | |
230 ASSERT_TRUE(ParseIPLiteralToNumber("1.2.3.4", &address_number)); | |
231 address_list.push_back(IPEndPoint(address_number, 12345)); | |
232 mock_resolver_->AddAction(HostResolverAction::ReturnResult(address_list)); | |
233 mock_resolver_->AddAction( | |
234 HostResolverAction::ReturnError(ERR_NAME_NOT_RESOLVED)); | |
235 HostResolver::RequestInfo request_info1( | |
236 HostPortPair::FromString("example.com:12345")); | |
237 request_info1.set_address_family(ADDRESS_FAMILY_IPV4); | |
238 request_info1.set_is_my_ip_address(true); | |
239 HostResolver::RequestInfo request_info2( | |
240 HostPortPair::FromString("example.org:80")); | |
241 request_info2.set_address_family(ADDRESS_FAMILY_IPV6); | |
242 AddressList result1; | |
243 AddressList result2; | |
244 HostResolver::RequestHandle request_handle1 = nullptr; | |
245 HostResolver::RequestHandle request_handle2 = nullptr; | |
246 TestCompletionCallback callback1; | |
247 TestCompletionCallback callback2; | |
248 ASSERT_EQ(ERR_IO_PENDING, | |
249 resolver_->Resolve(request_info1, DEFAULT_PRIORITY, &result1, | |
250 callback1.callback(), &request_handle1, | |
251 BoundNetLog())); | |
252 ASSERT_EQ(ERR_IO_PENDING, | |
253 resolver_->Resolve(request_info2, DEFAULT_PRIORITY, &result2, | |
254 callback2.callback(), &request_handle2, | |
255 BoundNetLog())); | |
256 EXPECT_EQ(OK, callback1.GetResult(ERR_IO_PENDING)); | |
257 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, callback2.GetResult(ERR_IO_PENDING)); | |
258 ASSERT_EQ(1u, result1.size()); | |
259 EXPECT_EQ(address_list[0], result1[0]); | |
260 ASSERT_EQ(0u, result2.size()); | |
261 | |
262 ASSERT_EQ(2u, mock_resolver_->requests().size()); | |
263 interfaces::HostResolverRequestInfo& request1 = | |
264 *mock_resolver_->requests()[0]; | |
265 EXPECT_EQ("example.com", request1.host.To<std::string>()); | |
266 EXPECT_EQ(12345, request1.port); | |
267 EXPECT_EQ(interfaces::ADDRESS_FAMILY_IPV4, request1.address_family); | |
268 EXPECT_TRUE(request1.is_my_ip_address); | |
269 interfaces::HostResolverRequestInfo& request2 = | |
270 *mock_resolver_->requests()[1]; | |
271 EXPECT_EQ("example.org", request2.host.To<std::string>()); | |
272 EXPECT_EQ(80, request2.port); | |
273 EXPECT_EQ(interfaces::ADDRESS_FAMILY_IPV6, request2.address_family); | |
274 EXPECT_FALSE(request2.is_my_ip_address); | |
275 } | |
276 | |
277 TEST_F(HostResolverMojoTest, Error) { | |
278 mock_resolver_->AddAction( | |
279 HostResolverAction::ReturnError(ERR_NAME_NOT_RESOLVED)); | |
280 HostResolver::RequestInfo request_info( | |
281 HostPortPair::FromString("example.com:8080")); | |
282 request_info.set_address_family(ADDRESS_FAMILY_IPV4); | |
283 AddressList result; | |
284 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, Resolve(request_info, &result)); | |
285 EXPECT_TRUE(result.empty()); | |
286 | |
287 ASSERT_EQ(1u, mock_resolver_->requests().size()); | |
288 interfaces::HostResolverRequestInfo& request = *mock_resolver_->requests()[0]; | |
289 EXPECT_EQ("example.com", request.host.To<std::string>()); | |
290 EXPECT_EQ(8080, request.port); | |
291 EXPECT_EQ(interfaces::ADDRESS_FAMILY_IPV4, request.address_family); | |
292 EXPECT_FALSE(request.is_my_ip_address); | |
293 } | |
294 | |
295 TEST_F(HostResolverMojoTest, EmptyResult) { | |
296 mock_resolver_->AddAction(HostResolverAction::ReturnError(OK)); | |
297 HostResolver::RequestInfo request_info( | |
298 HostPortPair::FromString("example.com:8080")); | |
299 AddressList result; | |
300 EXPECT_EQ(OK, Resolve(request_info, &result)); | |
301 EXPECT_TRUE(result.empty()); | |
302 | |
303 ASSERT_EQ(1u, mock_resolver_->requests().size()); | |
304 } | |
305 | |
306 TEST_F(HostResolverMojoTest, Cancel) { | |
307 mock_resolver_->AddAction(HostResolverAction::RetainRequest()); | |
308 HostResolver::RequestInfo request_info( | |
309 HostPortPair::FromString("example.com:80")); | |
310 request_info.set_address_family(ADDRESS_FAMILY_IPV6); | |
311 AddressList result; | |
312 HostResolver::RequestHandle request_handle = nullptr; | |
313 resolver_->Resolve(request_info, DEFAULT_PRIORITY, &result, base::Bind(&Fail), | |
314 &request_handle, BoundNetLog()); | |
315 resolver_->CancelRequest(request_handle); | |
316 waiter_.WaitForEvent(ConnectionErrorSource::REQUEST); | |
317 EXPECT_TRUE(result.empty()); | |
318 | |
319 ASSERT_EQ(1u, mock_resolver_->requests().size()); | |
320 interfaces::HostResolverRequestInfo& request = *mock_resolver_->requests()[0]; | |
321 EXPECT_EQ("example.com", request.host.To<std::string>()); | |
322 EXPECT_EQ(80, request.port); | |
323 EXPECT_EQ(interfaces::ADDRESS_FAMILY_IPV6, request.address_family); | |
324 EXPECT_FALSE(request.is_my_ip_address); | |
325 } | |
326 | |
327 TEST_F(HostResolverMojoTest, ImplDropsClientConnection) { | |
328 mock_resolver_->AddAction(HostResolverAction::DropRequest()); | |
329 HostResolver::RequestInfo request_info( | |
330 HostPortPair::FromString("example.com:1")); | |
331 AddressList result; | |
332 EXPECT_EQ(ERR_FAILED, Resolve(request_info, &result)); | |
333 EXPECT_TRUE(result.empty()); | |
334 | |
335 ASSERT_EQ(1u, mock_resolver_->requests().size()); | |
336 interfaces::HostResolverRequestInfo& request = *mock_resolver_->requests()[0]; | |
337 EXPECT_EQ("example.com", request.host.To<std::string>()); | |
338 EXPECT_EQ(1, request.port); | |
339 EXPECT_EQ(interfaces::ADDRESS_FAMILY_UNSPECIFIED, request.address_family); | |
340 EXPECT_FALSE(request.is_my_ip_address); | |
341 } | |
342 | |
343 TEST_F(HostResolverMojoTest, DestroyImpl) { | |
344 mock_resolver_.reset(); | |
345 waiter_.WaitForEvent(ConnectionErrorSource::CLIENT); | |
346 } | |
347 | |
348 TEST_F(HostResolverMojoTest, DestroyClient) { | |
349 resolver_.reset(); | |
350 waiter_.WaitForEvent(ConnectionErrorSource::RESOLVER); | |
351 } | |
352 | |
353 TEST_F(HostResolverMojoTest, ResolveFromCache) { | |
354 HostResolver::RequestInfo request_info( | |
355 HostPortPair::FromString("example.com:8080")); | |
356 AddressList result; | |
357 EXPECT_EQ(ERR_DNS_CACHE_MISS, | |
358 resolver_->ResolveFromCache(request_info, &result, BoundNetLog())); | |
359 EXPECT_TRUE(result.empty()); | |
360 } | |
361 | |
362 } // namespace net | |
OLD | NEW |