OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/base/host_resolver.h" | 5 #include "net/base/host_resolver.h" |
6 | 6 |
7 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
8 #include <ws2tcpip.h> | 8 #include <ws2tcpip.h> |
9 #include <wspiapi.h> | 9 #include <wspiapi.h> |
10 #elif defined(OS_POSIX) | 10 #elif defined(OS_POSIX) |
11 #include <netdb.h> | 11 #include <netdb.h> |
12 #endif | 12 #endif |
13 | 13 |
14 #include <string> | 14 #include <string> |
15 | 15 |
16 #include "base/compiler_specific.h" | 16 #include "base/compiler_specific.h" |
17 #include "base/message_loop.h" | 17 #include "base/message_loop.h" |
18 #include "base/ref_counted.h" | 18 #include "base/ref_counted.h" |
19 #include "net/base/address_list.h" | 19 #include "net/base/address_list.h" |
20 #include "net/base/completion_callback.h" | 20 #include "net/base/completion_callback.h" |
21 #include "net/base/host_resolver_unittest.h" | 21 #include "net/base/host_resolver_unittest.h" |
22 #include "net/base/net_errors.h" | 22 #include "net/base/net_errors.h" |
23 #include "testing/gtest/include/gtest/gtest.h" | 23 #include "testing/gtest/include/gtest/gtest.h" |
24 | 24 |
25 using net::RuleBasedHostMapper; | 25 using net::RuleBasedHostMapper; |
26 using net::ScopedHostMapper; | 26 using net::ScopedHostMapper; |
27 using net::WaitingHostMapper; | 27 using net::WaitingHostMapper; |
28 | 28 |
| 29 // TODO(eroman): |
| 30 // - Test mixing async with sync (in particular how does sync update the |
| 31 // cache while an async is already pending). |
| 32 |
29 namespace { | 33 namespace { |
30 | 34 |
| 35 // A variant of WaitingHostMapper that pushes each host mapped into a list. |
| 36 // (and uses a manual-reset event rather than auto-reset). |
| 37 class CapturingHostMapper : public net::HostMapper { |
| 38 public: |
| 39 CapturingHostMapper() : event_(true, false) { |
| 40 } |
| 41 |
| 42 void Signal() { |
| 43 event_.Signal(); |
| 44 } |
| 45 |
| 46 virtual std::string Map(const std::string& host) { |
| 47 event_.Wait(); |
| 48 { |
| 49 AutoLock l(lock_); |
| 50 capture_list_.push_back(host); |
| 51 } |
| 52 return MapUsingPrevious(host); |
| 53 } |
| 54 |
| 55 std::vector<std::string> GetCaptureList() const { |
| 56 std::vector<std::string> copy; |
| 57 { |
| 58 AutoLock l(lock_); |
| 59 copy = capture_list_; |
| 60 } |
| 61 return copy; |
| 62 } |
| 63 |
| 64 private: |
| 65 std::vector<std::string> capture_list_; |
| 66 mutable Lock lock_; |
| 67 base::WaitableEvent event_; |
| 68 }; |
| 69 |
| 70 // Helper that represents a single Resolve() result, used to inspect all the |
| 71 // resolve results by forwarding them to Delegate. |
| 72 class ResolveRequest { |
| 73 public: |
| 74 // Delegate interface, for notification when the ResolveRequest completes. |
| 75 class Delegate { |
| 76 public: |
| 77 virtual ~Delegate() {} |
| 78 virtual void OnCompleted(ResolveRequest* resolve) = 0; |
| 79 }; |
| 80 |
| 81 ResolveRequest(net::HostResolver* resolver, |
| 82 const std::string& hostname, |
| 83 int port, |
| 84 Delegate* delegate) |
| 85 : hostname_(hostname), port_(port), resolver_(resolver), |
| 86 delegate_(delegate), |
| 87 ALLOW_THIS_IN_INITIALIZER_LIST( |
| 88 callback_(this, &ResolveRequest::OnLookupFinished)) { |
| 89 // Start the request. |
| 90 int err = resolver->Resolve(hostname, port, &addrlist_, &callback_, &req_); |
| 91 EXPECT_EQ(net::ERR_IO_PENDING, err); |
| 92 } |
| 93 |
| 94 void Cancel() { |
| 95 resolver_->CancelRequest(req_); |
| 96 } |
| 97 |
| 98 const std::string& hostname() const { |
| 99 return hostname_; |
| 100 } |
| 101 |
| 102 int port() const { |
| 103 return port_; |
| 104 } |
| 105 |
| 106 int result() const { |
| 107 return result_; |
| 108 } |
| 109 |
| 110 const net::AddressList& addrlist() const { |
| 111 return addrlist_; |
| 112 } |
| 113 |
| 114 net::HostResolver* resolver() const { |
| 115 return resolver_; |
| 116 } |
| 117 |
| 118 private: |
| 119 void OnLookupFinished(int result) { |
| 120 result_ = result; |
| 121 delegate_->OnCompleted(this); |
| 122 } |
| 123 |
| 124 // The request details. |
| 125 std::string hostname_; |
| 126 int port_; |
| 127 net::HostResolver::Request* req_; |
| 128 |
| 129 // The result of the resolve. |
| 130 int result_; |
| 131 net::AddressList addrlist_; |
| 132 |
| 133 net::HostResolver* resolver_; |
| 134 |
| 135 Delegate* delegate_; |
| 136 net::CompletionCallbackImpl<ResolveRequest> callback_; |
| 137 |
| 138 DISALLOW_COPY_AND_ASSIGN(ResolveRequest); |
| 139 }; |
| 140 |
31 class HostResolverTest : public testing::Test { | 141 class HostResolverTest : public testing::Test { |
32 public: | 142 public: |
33 HostResolverTest() | 143 HostResolverTest() |
34 : callback_called_(false), | 144 : callback_called_(false), |
35 ALLOW_THIS_IN_INITIALIZER_LIST( | 145 ALLOW_THIS_IN_INITIALIZER_LIST( |
36 callback_(this, &HostResolverTest::OnLookupFinished)) { | 146 callback_(this, &HostResolverTest::OnLookupFinished)) { |
37 } | 147 } |
38 | 148 |
39 protected: | 149 protected: |
40 bool callback_called_; | 150 bool callback_called_; |
(...skipping 10 matching lines...) Expand all Loading... |
51 | 161 |
52 TEST_F(HostResolverTest, SynchronousLookup) { | 162 TEST_F(HostResolverTest, SynchronousLookup) { |
53 net::HostResolver host_resolver; | 163 net::HostResolver host_resolver; |
54 net::AddressList adrlist; | 164 net::AddressList adrlist; |
55 const int kPortnum = 80; | 165 const int kPortnum = 80; |
56 | 166 |
57 scoped_refptr<RuleBasedHostMapper> mapper = new RuleBasedHostMapper(); | 167 scoped_refptr<RuleBasedHostMapper> mapper = new RuleBasedHostMapper(); |
58 mapper->AddRule("just.testing", "192.168.1.42"); | 168 mapper->AddRule("just.testing", "192.168.1.42"); |
59 ScopedHostMapper scoped_mapper(mapper.get()); | 169 ScopedHostMapper scoped_mapper(mapper.get()); |
60 | 170 |
61 int err = host_resolver.Resolve("just.testing", kPortnum, &adrlist, NULL); | 171 int err = host_resolver.Resolve("just.testing", kPortnum, &adrlist, NULL, |
| 172 NULL); |
62 EXPECT_EQ(net::OK, err); | 173 EXPECT_EQ(net::OK, err); |
63 | 174 |
64 const struct addrinfo* ainfo = adrlist.head(); | 175 const struct addrinfo* ainfo = adrlist.head(); |
65 EXPECT_EQ(static_cast<addrinfo*>(NULL), ainfo->ai_next); | 176 EXPECT_EQ(static_cast<addrinfo*>(NULL), ainfo->ai_next); |
66 EXPECT_EQ(sizeof(struct sockaddr_in), ainfo->ai_addrlen); | 177 EXPECT_EQ(sizeof(struct sockaddr_in), ainfo->ai_addrlen); |
67 | 178 |
68 const struct sockaddr* sa = ainfo->ai_addr; | 179 const struct sockaddr* sa = ainfo->ai_addr; |
69 const struct sockaddr_in* sa_in = (const struct sockaddr_in*) sa; | 180 const struct sockaddr_in* sa_in = (const struct sockaddr_in*) sa; |
70 EXPECT_TRUE(htons(kPortnum) == sa_in->sin_port); | 181 EXPECT_TRUE(htons(kPortnum) == sa_in->sin_port); |
71 EXPECT_TRUE(htonl(0xc0a8012a) == sa_in->sin_addr.s_addr); | 182 EXPECT_TRUE(htonl(0xc0a8012a) == sa_in->sin_addr.s_addr); |
72 } | 183 } |
73 | 184 |
74 TEST_F(HostResolverTest, AsynchronousLookup) { | 185 TEST_F(HostResolverTest, AsynchronousLookup) { |
75 net::HostResolver host_resolver; | 186 net::HostResolver host_resolver; |
76 net::AddressList adrlist; | 187 net::AddressList adrlist; |
77 const int kPortnum = 80; | 188 const int kPortnum = 80; |
78 | 189 |
79 scoped_refptr<RuleBasedHostMapper> mapper = new RuleBasedHostMapper(); | 190 scoped_refptr<RuleBasedHostMapper> mapper = new RuleBasedHostMapper(); |
80 mapper->AddRule("just.testing", "192.168.1.42"); | 191 mapper->AddRule("just.testing", "192.168.1.42"); |
81 ScopedHostMapper scoped_mapper(mapper.get()); | 192 ScopedHostMapper scoped_mapper(mapper.get()); |
82 | 193 |
83 int err = host_resolver.Resolve("just.testing", kPortnum, &adrlist, | 194 int err = host_resolver.Resolve("just.testing", kPortnum, &adrlist, |
84 &callback_); | 195 &callback_, NULL); |
85 EXPECT_EQ(net::ERR_IO_PENDING, err); | 196 EXPECT_EQ(net::ERR_IO_PENDING, err); |
86 | 197 |
87 MessageLoop::current()->Run(); | 198 MessageLoop::current()->Run(); |
88 | 199 |
89 ASSERT_TRUE(callback_called_); | 200 ASSERT_TRUE(callback_called_); |
90 ASSERT_EQ(net::OK, callback_result_); | 201 ASSERT_EQ(net::OK, callback_result_); |
91 | 202 |
92 const struct addrinfo* ainfo = adrlist.head(); | 203 const struct addrinfo* ainfo = adrlist.head(); |
93 EXPECT_EQ(static_cast<addrinfo*>(NULL), ainfo->ai_next); | 204 EXPECT_EQ(static_cast<addrinfo*>(NULL), ainfo->ai_next); |
94 EXPECT_EQ(sizeof(struct sockaddr_in), ainfo->ai_addrlen); | 205 EXPECT_EQ(sizeof(struct sockaddr_in), ainfo->ai_addrlen); |
95 | 206 |
96 const struct sockaddr* sa = ainfo->ai_addr; | 207 const struct sockaddr* sa = ainfo->ai_addr; |
97 const struct sockaddr_in* sa_in = (const struct sockaddr_in*) sa; | 208 const struct sockaddr_in* sa_in = (const struct sockaddr_in*) sa; |
98 EXPECT_TRUE(htons(kPortnum) == sa_in->sin_port); | 209 EXPECT_TRUE(htons(kPortnum) == sa_in->sin_port); |
99 EXPECT_TRUE(htonl(0xc0a8012a) == sa_in->sin_addr.s_addr); | 210 EXPECT_TRUE(htonl(0xc0a8012a) == sa_in->sin_addr.s_addr); |
100 } | 211 } |
101 | 212 |
102 TEST_F(HostResolverTest, CanceledAsynchronousLookup) { | 213 TEST_F(HostResolverTest, CanceledAsynchronousLookup) { |
103 scoped_refptr<WaitingHostMapper> mapper = new WaitingHostMapper(); | 214 scoped_refptr<WaitingHostMapper> mapper = new WaitingHostMapper(); |
104 ScopedHostMapper scoped_mapper(mapper.get()); | 215 ScopedHostMapper scoped_mapper(mapper.get()); |
105 | 216 |
106 { | 217 { |
107 net::HostResolver host_resolver; | 218 net::HostResolver host_resolver; |
108 net::AddressList adrlist; | 219 net::AddressList adrlist; |
109 const int kPortnum = 80; | 220 const int kPortnum = 80; |
110 | 221 |
111 int err = host_resolver.Resolve("just.testing", kPortnum, &adrlist, | 222 int err = host_resolver.Resolve("just.testing", kPortnum, &adrlist, |
112 &callback_); | 223 &callback_, NULL); |
113 EXPECT_EQ(net::ERR_IO_PENDING, err); | 224 EXPECT_EQ(net::ERR_IO_PENDING, err); |
114 | 225 |
115 // Make sure we will exit the queue even when callback is not called. | 226 // Make sure we will exit the queue even when callback is not called. |
116 MessageLoop::current()->PostDelayedTask(FROM_HERE, | 227 MessageLoop::current()->PostDelayedTask(FROM_HERE, |
117 new MessageLoop::QuitTask(), | 228 new MessageLoop::QuitTask(), |
118 1000); | 229 1000); |
119 MessageLoop::current()->Run(); | 230 MessageLoop::current()->Run(); |
120 } | 231 } |
121 | 232 |
122 mapper->Signal(); | 233 mapper->Signal(); |
123 | 234 |
124 EXPECT_FALSE(callback_called_); | 235 EXPECT_FALSE(callback_called_); |
125 } | 236 } |
126 | 237 |
127 TEST_F(HostResolverTest, NumericIPv4Address) { | 238 TEST_F(HostResolverTest, NumericIPv4Address) { |
128 // Stevens says dotted quads with AI_UNSPEC resolve to a single sockaddr_in. | 239 // Stevens says dotted quads with AI_UNSPEC resolve to a single sockaddr_in. |
129 | 240 |
130 scoped_refptr<RuleBasedHostMapper> mapper = new RuleBasedHostMapper(); | 241 scoped_refptr<RuleBasedHostMapper> mapper = new RuleBasedHostMapper(); |
131 mapper->AllowDirectLookup("*"); | 242 mapper->AllowDirectLookup("*"); |
132 ScopedHostMapper scoped_mapper(mapper.get()); | 243 ScopedHostMapper scoped_mapper(mapper.get()); |
133 | 244 |
134 net::HostResolver host_resolver; | 245 net::HostResolver host_resolver; |
135 net::AddressList adrlist; | 246 net::AddressList adrlist; |
136 const int kPortnum = 5555; | 247 const int kPortnum = 5555; |
137 int err = host_resolver.Resolve("127.1.2.3", kPortnum, &adrlist, NULL); | 248 int err = host_resolver.Resolve("127.1.2.3", kPortnum, &adrlist, NULL, NULL); |
138 EXPECT_EQ(net::OK, err); | 249 EXPECT_EQ(net::OK, err); |
139 | 250 |
140 const struct addrinfo* ainfo = adrlist.head(); | 251 const struct addrinfo* ainfo = adrlist.head(); |
141 EXPECT_EQ(static_cast<addrinfo*>(NULL), ainfo->ai_next); | 252 EXPECT_EQ(static_cast<addrinfo*>(NULL), ainfo->ai_next); |
142 EXPECT_EQ(sizeof(struct sockaddr_in), ainfo->ai_addrlen); | 253 EXPECT_EQ(sizeof(struct sockaddr_in), ainfo->ai_addrlen); |
143 | 254 |
144 const struct sockaddr* sa = ainfo->ai_addr; | 255 const struct sockaddr* sa = ainfo->ai_addr; |
145 const struct sockaddr_in* sa_in = (const struct sockaddr_in*) sa; | 256 const struct sockaddr_in* sa_in = (const struct sockaddr_in*) sa; |
146 EXPECT_TRUE(htons(kPortnum) == sa_in->sin_port); | 257 EXPECT_TRUE(htons(kPortnum) == sa_in->sin_port); |
147 EXPECT_TRUE(htonl(0x7f010203) == sa_in->sin_addr.s_addr); | 258 EXPECT_TRUE(htonl(0x7f010203) == sa_in->sin_addr.s_addr); |
148 } | 259 } |
149 | 260 |
150 TEST_F(HostResolverTest, NumericIPv6Address) { | 261 TEST_F(HostResolverTest, NumericIPv6Address) { |
151 scoped_refptr<RuleBasedHostMapper> mapper = new RuleBasedHostMapper(); | 262 scoped_refptr<RuleBasedHostMapper> mapper = new RuleBasedHostMapper(); |
152 mapper->AllowDirectLookup("*"); | 263 mapper->AllowDirectLookup("*"); |
153 ScopedHostMapper scoped_mapper(mapper.get()); | 264 ScopedHostMapper scoped_mapper(mapper.get()); |
154 | 265 |
155 // Resolve a plain IPv6 address. Don't worry about [brackets], because | 266 // Resolve a plain IPv6 address. Don't worry about [brackets], because |
156 // the caller should have removed them. | 267 // the caller should have removed them. |
157 net::HostResolver host_resolver; | 268 net::HostResolver host_resolver; |
158 net::AddressList adrlist; | 269 net::AddressList adrlist; |
159 const int kPortnum = 5555; | 270 const int kPortnum = 5555; |
160 int err = host_resolver.Resolve("2001:db8::1", kPortnum, &adrlist, NULL); | 271 int err = host_resolver.Resolve("2001:db8::1", kPortnum, &adrlist, NULL, |
| 272 NULL); |
161 // On computers without IPv6 support, getaddrinfo cannot convert IPv6 | 273 // On computers without IPv6 support, getaddrinfo cannot convert IPv6 |
162 // address literals to addresses (getaddrinfo returns EAI_NONAME). So this | 274 // address literals to addresses (getaddrinfo returns EAI_NONAME). So this |
163 // test has to allow host_resolver.Resolve to fail. | 275 // test has to allow host_resolver.Resolve to fail. |
164 if (err == net::ERR_NAME_NOT_RESOLVED) | 276 if (err == net::ERR_NAME_NOT_RESOLVED) |
165 return; | 277 return; |
166 EXPECT_EQ(net::OK, err); | 278 EXPECT_EQ(net::OK, err); |
167 | 279 |
168 const struct addrinfo* ainfo = adrlist.head(); | 280 const struct addrinfo* ainfo = adrlist.head(); |
169 EXPECT_EQ(static_cast<addrinfo*>(NULL), ainfo->ai_next); | 281 EXPECT_EQ(static_cast<addrinfo*>(NULL), ainfo->ai_next); |
170 EXPECT_EQ(sizeof(struct sockaddr_in6), ainfo->ai_addrlen); | 282 EXPECT_EQ(sizeof(struct sockaddr_in6), ainfo->ai_addrlen); |
(...skipping 12 matching lines...) Expand all Loading... |
183 } | 295 } |
184 | 296 |
185 TEST_F(HostResolverTest, EmptyHost) { | 297 TEST_F(HostResolverTest, EmptyHost) { |
186 scoped_refptr<RuleBasedHostMapper> mapper = new RuleBasedHostMapper(); | 298 scoped_refptr<RuleBasedHostMapper> mapper = new RuleBasedHostMapper(); |
187 mapper->AllowDirectLookup("*"); | 299 mapper->AllowDirectLookup("*"); |
188 ScopedHostMapper scoped_mapper(mapper.get()); | 300 ScopedHostMapper scoped_mapper(mapper.get()); |
189 | 301 |
190 net::HostResolver host_resolver; | 302 net::HostResolver host_resolver; |
191 net::AddressList adrlist; | 303 net::AddressList adrlist; |
192 const int kPortnum = 5555; | 304 const int kPortnum = 5555; |
193 int err = host_resolver.Resolve("", kPortnum, &adrlist, NULL); | 305 int err = host_resolver.Resolve("", kPortnum, &adrlist, NULL, NULL); |
194 EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, err); | 306 EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, err); |
195 } | 307 } |
196 | 308 |
| 309 // Helper class used by HostResolverTest.DeDupeRequests. It receives request |
| 310 // completion notifications for all the resolves, so it can tally up and |
| 311 // determine when we are done. |
| 312 class DeDupeRequestsVerifier : public ResolveRequest::Delegate { |
| 313 public: |
| 314 explicit DeDupeRequestsVerifier(CapturingHostMapper* mapper) |
| 315 : count_a_(0), count_b_(0), mapper_(mapper) {} |
| 316 |
| 317 // The test does 5 resolves (which can complete in any order). |
| 318 virtual void OnCompleted(ResolveRequest* resolve) { |
| 319 // Tally up how many requests we have seen. |
| 320 if (resolve->hostname() == "a") { |
| 321 count_a_++; |
| 322 } else if (resolve->hostname() == "b") { |
| 323 count_b_++; |
| 324 } else { |
| 325 FAIL() << "Unexpected hostname: " << resolve->hostname(); |
| 326 } |
| 327 |
| 328 // Check that the port was set correctly. |
| 329 EXPECT_EQ(resolve->port(), resolve->addrlist().GetPort()); |
| 330 |
| 331 // Check whether all the requests have finished yet. |
| 332 int total_completions = count_a_ + count_b_; |
| 333 if (total_completions == 5) { |
| 334 EXPECT_EQ(2, count_a_); |
| 335 EXPECT_EQ(3, count_b_); |
| 336 |
| 337 // The mapper should have been called only twice -- once with "a", once |
| 338 // with "b". |
| 339 std::vector<std::string> capture_list = mapper_->GetCaptureList(); |
| 340 EXPECT_EQ(2U, capture_list.size()); |
| 341 |
| 342 // End this test, we are done. |
| 343 MessageLoop::current()->Quit(); |
| 344 } |
| 345 } |
| 346 |
| 347 private: |
| 348 int count_a_; |
| 349 int count_b_; |
| 350 CapturingHostMapper* mapper_; |
| 351 |
| 352 DISALLOW_COPY_AND_ASSIGN(DeDupeRequestsVerifier); |
| 353 }; |
| 354 |
| 355 TEST_F(HostResolverTest, DeDupeRequests) { |
| 356 // Use a capturing mapper, since the verifier needs to know what calls |
| 357 // reached Map(). Also, the capturing mapper is initially blocked. |
| 358 scoped_refptr<CapturingHostMapper> mapper = new CapturingHostMapper(); |
| 359 ScopedHostMapper scoped_mapper(mapper.get()); |
| 360 |
| 361 net::HostResolver host_resolver; |
| 362 |
| 363 // The class will receive callbacks for when each resolve completes. It |
| 364 // checks that the right things happened. |
| 365 DeDupeRequestsVerifier verifier(mapper.get()); |
| 366 |
| 367 // Start 5 requests, duplicating hosts "a" and "b". Since the mapper is |
| 368 // blocked, these should all pile up until we signal it. |
| 369 |
| 370 ResolveRequest req1(&host_resolver, "a", 80, &verifier); |
| 371 ResolveRequest req2(&host_resolver, "b", 80, &verifier); |
| 372 ResolveRequest req3(&host_resolver, "b", 81, &verifier); |
| 373 ResolveRequest req4(&host_resolver, "a", 82, &verifier); |
| 374 ResolveRequest req5(&host_resolver, "b", 83, &verifier); |
| 375 |
| 376 // Ready, Set, GO!!! |
| 377 mapper->Signal(); |
| 378 |
| 379 // |verifier| will send quit message once all the requests have finished. |
| 380 MessageLoop::current()->Run(); |
| 381 } |
| 382 |
| 383 // Helper class used by HostResolverTest.CancelMultipleRequests. |
| 384 class CancelMultipleRequestsVerifier : public ResolveRequest::Delegate { |
| 385 public: |
| 386 CancelMultipleRequestsVerifier() {} |
| 387 |
| 388 // The cancels kill all but one request. |
| 389 virtual void OnCompleted(ResolveRequest* resolve) { |
| 390 EXPECT_EQ("a", resolve->hostname()); |
| 391 EXPECT_EQ(82, resolve->port()); |
| 392 |
| 393 // Check that the port was set correctly. |
| 394 EXPECT_EQ(resolve->port(), resolve->addrlist().GetPort()); |
| 395 |
| 396 // End this test, we are done. |
| 397 MessageLoop::current()->Quit(); |
| 398 } |
| 399 |
| 400 private: |
| 401 DISALLOW_COPY_AND_ASSIGN(CancelMultipleRequestsVerifier); |
| 402 }; |
| 403 |
| 404 TEST_F(HostResolverTest, CancelMultipleRequests) { |
| 405 // Use a capturing mapper, since the verifier needs to know what calls |
| 406 // reached Map(). Also, the capturing mapper is initially blocked. |
| 407 scoped_refptr<CapturingHostMapper> mapper = new CapturingHostMapper(); |
| 408 ScopedHostMapper scoped_mapper(mapper.get()); |
| 409 |
| 410 net::HostResolver host_resolver; |
| 411 |
| 412 // The class will receive callbacks for when each resolve completes. It |
| 413 // checks that the right things happened. |
| 414 CancelMultipleRequestsVerifier verifier; |
| 415 |
| 416 // Start 5 requests, duplicating hosts "a" and "b". Since the mapper is |
| 417 // blocked, these should all pile up until we signal it. |
| 418 |
| 419 ResolveRequest req1(&host_resolver, "a", 80, &verifier); |
| 420 ResolveRequest req2(&host_resolver, "b", 80, &verifier); |
| 421 ResolveRequest req3(&host_resolver, "b", 81, &verifier); |
| 422 ResolveRequest req4(&host_resolver, "a", 82, &verifier); |
| 423 ResolveRequest req5(&host_resolver, "b", 83, &verifier); |
| 424 |
| 425 // Cancel everything except request 4. |
| 426 req1.Cancel(); |
| 427 req2.Cancel(); |
| 428 req3.Cancel(); |
| 429 req5.Cancel(); |
| 430 |
| 431 // Ready, Set, GO!!! |
| 432 mapper->Signal(); |
| 433 |
| 434 // |verifier| will send quit message once all the requests have finished. |
| 435 MessageLoop::current()->Run(); |
| 436 } |
| 437 |
| 438 // Helper class used by HostResolverTest.CancelWithinCallback. |
| 439 class CancelWithinCallbackVerifier : public ResolveRequest::Delegate { |
| 440 public: |
| 441 CancelWithinCallbackVerifier() |
| 442 : req_to_cancel1_(NULL), req_to_cancel2_(NULL), num_completions_(0) { |
| 443 } |
| 444 |
| 445 virtual void OnCompleted(ResolveRequest* resolve) { |
| 446 num_completions_++; |
| 447 |
| 448 // Port 80 is the first request that the callback will be invoked for. |
| 449 // While we are executing within that callback, cancel the other requests |
| 450 // in the job and start another request. |
| 451 if (80 == resolve->port()) { |
| 452 EXPECT_EQ("a", resolve->hostname()); |
| 453 |
| 454 req_to_cancel1_->Cancel(); |
| 455 req_to_cancel2_->Cancel(); |
| 456 |
| 457 // Start a request (so we can make sure the canceled requests don't |
| 458 // complete before "finalrequest" finishes. |
| 459 final_request_.reset(new ResolveRequest( |
| 460 resolve->resolver(), "finalrequest", 70, this)); |
| 461 |
| 462 } else if (83 == resolve->port()) { |
| 463 EXPECT_EQ("a", resolve->hostname()); |
| 464 } else if (resolve->hostname() == "finalrequest") { |
| 465 EXPECT_EQ(70, resolve->addrlist().GetPort()); |
| 466 |
| 467 // End this test, we are done. |
| 468 MessageLoop::current()->Quit(); |
| 469 } else { |
| 470 FAIL() << "Unexpected completion: " << resolve->hostname() << ", " |
| 471 << resolve->port(); |
| 472 } |
| 473 } |
| 474 |
| 475 void SetRequestsToCancel(ResolveRequest* req_to_cancel1, |
| 476 ResolveRequest* req_to_cancel2) { |
| 477 req_to_cancel1_ = req_to_cancel1; |
| 478 req_to_cancel2_ = req_to_cancel2; |
| 479 } |
| 480 |
| 481 private: |
| 482 scoped_ptr<ResolveRequest> final_request_; |
| 483 ResolveRequest* req_to_cancel1_; |
| 484 ResolveRequest* req_to_cancel2_; |
| 485 int num_completions_; |
| 486 DISALLOW_COPY_AND_ASSIGN(CancelWithinCallbackVerifier); |
| 487 }; |
| 488 |
| 489 TEST_F(HostResolverTest, CancelWithinCallback) { |
| 490 // Use a capturing mapper, since the verifier needs to know what calls |
| 491 // reached Map(). Also, the capturing mapper is initially blocked. |
| 492 scoped_refptr<CapturingHostMapper> mapper = new CapturingHostMapper(); |
| 493 ScopedHostMapper scoped_mapper(mapper.get()); |
| 494 |
| 495 net::HostResolver host_resolver; |
| 496 |
| 497 // The class will receive callbacks for when each resolve completes. It |
| 498 // checks that the right things happened. |
| 499 CancelWithinCallbackVerifier verifier; |
| 500 |
| 501 // Start 4 requests, duplicating hosts "a". Since the mapper is |
| 502 // blocked, these should all pile up until we signal it. |
| 503 |
| 504 ResolveRequest req1(&host_resolver, "a", 80, &verifier); |
| 505 ResolveRequest req2(&host_resolver, "a", 81, &verifier); |
| 506 ResolveRequest req3(&host_resolver, "a", 82, &verifier); |
| 507 ResolveRequest req4(&host_resolver, "a", 83, &verifier); |
| 508 |
| 509 // Once "a:80" completes, it will cancel "a:81" and "a:82". |
| 510 verifier.SetRequestsToCancel(&req2, &req3); |
| 511 |
| 512 // Ready, Set, GO!!! |
| 513 mapper->Signal(); |
| 514 |
| 515 // |verifier| will send quit message once all the requests have finished. |
| 516 MessageLoop::current()->Run(); |
| 517 } |
| 518 |
| 519 // Helper class used by HostResolverTest.DeleteWithinCallback. |
| 520 class DeleteWithinCallbackVerifier : public ResolveRequest::Delegate { |
| 521 public: |
| 522 DeleteWithinCallbackVerifier() {} |
| 523 |
| 524 virtual void OnCompleted(ResolveRequest* resolve) { |
| 525 EXPECT_EQ("a", resolve->hostname()); |
| 526 EXPECT_EQ(80, resolve->port()); |
| 527 delete resolve->resolver(); |
| 528 |
| 529 // Quit after returning from OnCompleted (to give it a chance at |
| 530 // incorrectly running the cancelled tasks). |
| 531 MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); |
| 532 } |
| 533 |
| 534 private: |
| 535 DISALLOW_COPY_AND_ASSIGN(DeleteWithinCallbackVerifier); |
| 536 }; |
| 537 |
| 538 TEST_F(HostResolverTest, DeleteWithinCallback) { |
| 539 // Use a capturing mapper, since the verifier needs to know what calls |
| 540 // reached Map(). Also, the capturing mapper is initially blocked. |
| 541 scoped_refptr<CapturingHostMapper> mapper = new CapturingHostMapper(); |
| 542 ScopedHostMapper scoped_mapper(mapper.get()); |
| 543 |
| 544 // This should be deleted by DeleteWithinCallbackVerifier -- if it leaks |
| 545 // then the test has failed. |
| 546 net::HostResolver* host_resolver = new net::HostResolver; |
| 547 |
| 548 // The class will receive callbacks for when each resolve completes. It |
| 549 // checks that the right things happened. |
| 550 DeleteWithinCallbackVerifier verifier; |
| 551 |
| 552 // Start 4 requests, duplicating hosts "a". Since the mapper is |
| 553 // blocked, these should all pile up until we signal it. |
| 554 |
| 555 ResolveRequest req1(host_resolver, "a", 80, &verifier); |
| 556 ResolveRequest req2(host_resolver, "a", 81, &verifier); |
| 557 ResolveRequest req3(host_resolver, "a", 82, &verifier); |
| 558 ResolveRequest req4(host_resolver, "a", 83, &verifier); |
| 559 |
| 560 // Ready, Set, GO!!! |
| 561 mapper->Signal(); |
| 562 |
| 563 // |verifier| will send quit message once all the requests have finished. |
| 564 MessageLoop::current()->Run(); |
| 565 } |
| 566 |
| 567 // Helper class used by HostResolverTest.StartWithinCallback. |
| 568 class StartWithinCallbackVerifier : public ResolveRequest::Delegate { |
| 569 public: |
| 570 StartWithinCallbackVerifier() : num_requests_(0) {} |
| 571 |
| 572 virtual void OnCompleted(ResolveRequest* resolve) { |
| 573 EXPECT_EQ("a", resolve->hostname()); |
| 574 |
| 575 if (80 == resolve->port()) { |
| 576 // On completing the first request, start another request for "a". |
| 577 // Since caching is disabled, this will result in another async request. |
| 578 final_request_.reset(new ResolveRequest( |
| 579 resolve->resolver(), "a", 70, this)); |
| 580 } |
| 581 if (++num_requests_ == 5) { |
| 582 // Test is done. |
| 583 MessageLoop::current()->Quit(); |
| 584 } |
| 585 } |
| 586 |
| 587 private: |
| 588 int num_requests_; |
| 589 scoped_ptr<ResolveRequest> final_request_; |
| 590 DISALLOW_COPY_AND_ASSIGN(StartWithinCallbackVerifier); |
| 591 }; |
| 592 |
| 593 TEST_F(HostResolverTest, StartWithinCallback) { |
| 594 // Use a capturing mapper, since the verifier needs to know what calls |
| 595 // reached Map(). Also, the capturing mapper is initially blocked. |
| 596 scoped_refptr<CapturingHostMapper> mapper = new CapturingHostMapper(); |
| 597 ScopedHostMapper scoped_mapper(mapper.get()); |
| 598 |
| 599 // Turn off caching for this host resolver. |
| 600 net::HostResolver host_resolver(0, 0); |
| 601 |
| 602 // The class will receive callbacks for when each resolve completes. It |
| 603 // checks that the right things happened. |
| 604 StartWithinCallbackVerifier verifier; |
| 605 |
| 606 // Start 4 requests, duplicating hosts "a". Since the mapper is |
| 607 // blocked, these should all pile up until we signal it. |
| 608 |
| 609 ResolveRequest req1(&host_resolver, "a", 80, &verifier); |
| 610 ResolveRequest req2(&host_resolver, "a", 81, &verifier); |
| 611 ResolveRequest req3(&host_resolver, "a", 82, &verifier); |
| 612 ResolveRequest req4(&host_resolver, "a", 83, &verifier); |
| 613 |
| 614 // Ready, Set, GO!!! |
| 615 mapper->Signal(); |
| 616 |
| 617 // |verifier| will send quit message once all the requests have finished. |
| 618 MessageLoop::current()->Run(); |
| 619 } |
| 620 |
197 } // namespace | 621 } // namespace |
OLD | NEW |