1 // Copyright 2012 The Chromium Authors
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/address_sorter_posix.h"
6
7 #include <memory>
8 #include <string>
9 #include <vector>
10
11 #include "base/check_op.h"
12 #include "base/functional/bind.h"
13 #include "base/memory/raw_ptr.h"
14 #include "base/notreached.h"
15 #include "base/task/single_thread_task_runner.h"
16 #include "net/base/ip_address.h"
17 #include "net/base/ip_endpoint.h"
18 #include "net/base/net_errors.h"
19 #include "net/base/network_change_notifier.h"
20 #include "net/base/test_completion_callback.h"
21 #include "net/log/net_log_with_source.h"
22 #include "net/socket/client_socket_factory.h"
23 #include "net/socket/datagram_client_socket.h"
24 #include "net/socket/socket_performance_watcher.h"
25 #include "net/socket/ssl_client_socket.h"
26 #include "net/socket/stream_socket.h"
27 #include "net/test/test_with_task_environment.h"
28 #include "net/traffic_annotation/network_traffic_annotation.h"
29 #include "testing/gmock/include/gmock/gmock.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31
32 namespace net {
33 namespace {
34
35 // Used to map destination address to source address.
36 typedef std::map<IPAddress, IPAddress> AddressMapping;
37
ParseIP(const std::string & str)38 IPAddress ParseIP(const std::string& str) {
39 IPAddress addr;
40 CHECK(addr.AssignFromIPLiteral(str));
41 return addr;
42 }
43
44 // A mock socket which binds to source address according to AddressMapping.
45 class TestUDPClientSocket : public DatagramClientSocket {
46 public:
47 enum class ConnectMode { kSynchronous, kAsynchronous, kAsynchronousManual };
TestUDPClientSocket(const AddressMapping * mapping,ConnectMode connect_mode)48 explicit TestUDPClientSocket(const AddressMapping* mapping,
49 ConnectMode connect_mode)
50 : mapping_(mapping), connect_mode_(connect_mode) {}
51
52 TestUDPClientSocket(const TestUDPClientSocket&) = delete;
53 TestUDPClientSocket& operator=(const TestUDPClientSocket&) = delete;
54
55 ~TestUDPClientSocket() override = default;
56
Read(IOBuffer *,int,CompletionOnceCallback)57 int Read(IOBuffer*, int, CompletionOnceCallback) override {
58 NOTIMPLEMENTED();
59 return OK;
60 }
Write(IOBuffer *,int,CompletionOnceCallback,const NetworkTrafficAnnotationTag & traffic_annotation)61 int Write(IOBuffer*,
62 int,
63 CompletionOnceCallback,
64 const NetworkTrafficAnnotationTag& traffic_annotation) override {
65 NOTIMPLEMENTED();
66 return OK;
67 }
SetReceiveBufferSize(int32_t)68 int SetReceiveBufferSize(int32_t) override { return OK; }
SetSendBufferSize(int32_t)69 int SetSendBufferSize(int32_t) override { return OK; }
SetDoNotFragment()70 int SetDoNotFragment() override { return OK; }
SetRecvEcn()71 int SetRecvEcn() override { return OK; }
72
Close()73 void Close() override {}
GetPeerAddress(IPEndPoint * address) const74 int GetPeerAddress(IPEndPoint* address) const override {
75 NOTIMPLEMENTED();
76 return OK;
77 }
GetLocalAddress(IPEndPoint * address) const78 int GetLocalAddress(IPEndPoint* address) const override {
79 if (!connected_)
80 return ERR_UNEXPECTED;
81 *address = local_endpoint_;
82 return OK;
83 }
UseNonBlockingIO()84 void UseNonBlockingIO() override {}
SetMulticastInterface(uint32_t interface_index)85 int SetMulticastInterface(uint32_t interface_index) override {
86 NOTIMPLEMENTED();
87 return ERR_NOT_IMPLEMENTED;
88 }
89
ConnectUsingNetwork(handles::NetworkHandle network,const IPEndPoint & address)90 int ConnectUsingNetwork(handles::NetworkHandle network,
91 const IPEndPoint& address) override {
92 NOTIMPLEMENTED();
93 return ERR_NOT_IMPLEMENTED;
94 }
95
ConnectUsingDefaultNetwork(const IPEndPoint & address)96 int ConnectUsingDefaultNetwork(const IPEndPoint& address) override {
97 NOTIMPLEMENTED();
98 return ERR_NOT_IMPLEMENTED;
99 }
100
ConnectAsync(const IPEndPoint & address,CompletionOnceCallback callback)101 int ConnectAsync(const IPEndPoint& address,
102 CompletionOnceCallback callback) override {
103 DCHECK(callback);
104 int rv = Connect(address);
105 finish_connect_callback_ =
106 base::BindOnce(&TestUDPClientSocket::RunConnectCallback,
107 weak_ptr_factory_.GetWeakPtr(), std::move(callback), rv);
108 if (connect_mode_ == ConnectMode::kAsynchronous) {
109 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
110 FROM_HERE, std::move(finish_connect_callback_));
111 return ERR_IO_PENDING;
112 } else if (connect_mode_ == ConnectMode::kAsynchronousManual) {
113 return ERR_IO_PENDING;
114 }
115 return rv;
116 }
117
ConnectUsingNetworkAsync(handles::NetworkHandle network,const IPEndPoint & address,CompletionOnceCallback callback)118 int ConnectUsingNetworkAsync(handles::NetworkHandle network,
119 const IPEndPoint& address,
120 CompletionOnceCallback callback) override {
121 NOTIMPLEMENTED();
122 return ERR_NOT_IMPLEMENTED;
123 }
124
ConnectUsingDefaultNetworkAsync(const IPEndPoint & address,CompletionOnceCallback callback)125 int ConnectUsingDefaultNetworkAsync(
126 const IPEndPoint& address,
127 CompletionOnceCallback callback) override {
128 NOTIMPLEMENTED();
129 return ERR_NOT_IMPLEMENTED;
130 }
131
GetBoundNetwork() const132 handles::NetworkHandle GetBoundNetwork() const override {
133 return handles::kInvalidNetworkHandle;
134 }
ApplySocketTag(const SocketTag & tag)135 void ApplySocketTag(const SocketTag& tag) override {}
SetMsgConfirm(bool confirm)136 void SetMsgConfirm(bool confirm) override {}
137
Connect(const IPEndPoint & remote)138 int Connect(const IPEndPoint& remote) override {
139 if (connected_)
140 return ERR_UNEXPECTED;
141 auto it = mapping_->find(remote.address());
142 if (it == mapping_->end())
143 return ERR_FAILED;
144 connected_ = true;
145 local_endpoint_ = IPEndPoint(it->second, 39874 /* arbitrary port */);
146 return OK;
147 }
148
NetLog() const149 const NetLogWithSource& NetLog() const override { return net_log_; }
150
FinishConnect()151 void FinishConnect() { std::move(finish_connect_callback_).Run(); }
152
153 private:
RunConnectCallback(CompletionOnceCallback callback,int rv)154 void RunConnectCallback(CompletionOnceCallback callback, int rv) {
155 std::move(callback).Run(rv);
156 }
157 NetLogWithSource net_log_;
158 raw_ptr<const AddressMapping> mapping_;
159 bool connected_ = false;
160 IPEndPoint local_endpoint_;
161 ConnectMode connect_mode_;
162 base::OnceClosure finish_connect_callback_;
163
164 base::WeakPtrFactory<TestUDPClientSocket> weak_ptr_factory_{this};
165 };
166
167 // Creates TestUDPClientSockets and maintains an AddressMapping.
168 class TestSocketFactory : public ClientSocketFactory {
169 public:
170 TestSocketFactory() = default;
171
172 TestSocketFactory(const TestSocketFactory&) = delete;
173 TestSocketFactory& operator=(const TestSocketFactory&) = delete;
174
175 ~TestSocketFactory() override = default;
176
CreateDatagramClientSocket(DatagramSocket::BindType,NetLog *,const NetLogSource &)177 std::unique_ptr<DatagramClientSocket> CreateDatagramClientSocket(
178 DatagramSocket::BindType,
179 NetLog*,
180 const NetLogSource&) override {
181 auto new_socket =
182 std::make_unique<TestUDPClientSocket>(&mapping_, connect_mode_);
183 if (socket_create_callback_) {
184 socket_create_callback_.Run(new_socket.get());
185 }
186 return new_socket;
187 }
CreateTransportClientSocket(const AddressList &,std::unique_ptr<SocketPerformanceWatcher>,net::NetworkQualityEstimator *,NetLog *,const NetLogSource &)188 std::unique_ptr<TransportClientSocket> CreateTransportClientSocket(
189 const AddressList&,
190 std::unique_ptr<SocketPerformanceWatcher>,
191 net::NetworkQualityEstimator*,
192 NetLog*,
193 const NetLogSource&) override {
194 NOTIMPLEMENTED();
195 return nullptr;
196 }
CreateSSLClientSocket(SSLClientContext *,std::unique_ptr<StreamSocket>,const HostPortPair &,const SSLConfig &)197 std::unique_ptr<SSLClientSocket> CreateSSLClientSocket(
198 SSLClientContext*,
199 std::unique_ptr<StreamSocket>,
200 const HostPortPair&,
201 const SSLConfig&) override {
202 NOTIMPLEMENTED();
203 return nullptr;
204 }
AddMapping(const IPAddress & dst,const IPAddress & src)205 void AddMapping(const IPAddress& dst, const IPAddress& src) {
206 mapping_[dst] = src;
207 }
SetConnectMode(TestUDPClientSocket::ConnectMode connect_mode)208 void SetConnectMode(TestUDPClientSocket::ConnectMode connect_mode) {
209 connect_mode_ = connect_mode;
210 }
SetSocketCreateCallback(base::RepeatingCallback<void (TestUDPClientSocket *)> socket_create_callback)211 void SetSocketCreateCallback(
212 base::RepeatingCallback<void(TestUDPClientSocket*)>
213 socket_create_callback) {
214 socket_create_callback_ = std::move(socket_create_callback);
215 }
216
217 private:
218 AddressMapping mapping_;
219 TestUDPClientSocket::ConnectMode connect_mode_;
220 base::RepeatingCallback<void(TestUDPClientSocket*)> socket_create_callback_;
221 };
222
OnSortComplete(bool & completed,std::vector<IPEndPoint> * sorted_buf,CompletionOnceCallback callback,bool success,std::vector<IPEndPoint> sorted)223 void OnSortComplete(bool& completed,
224 std::vector<IPEndPoint>* sorted_buf,
225 CompletionOnceCallback callback,
226 bool success,
227 std::vector<IPEndPoint> sorted) {
228 EXPECT_TRUE(success);
229 completed = true;
230 if (success)
231 *sorted_buf = std::move(sorted);
232 std::move(callback).Run(OK);
233 }
234
235 } // namespace
236
237 // TaskEnvironment is required to register an IPAddressObserver from the
238 // constructor of AddressSorterPosix.
239 class AddressSorterPosixTest : public TestWithTaskEnvironment {
240 protected:
AddressSorterPosixTest()241 AddressSorterPosixTest()
242 : sorter_(std::make_unique<AddressSorterPosix>(&socket_factory_)) {}
243
AddMapping(const std::string & dst,const std::string & src)244 void AddMapping(const std::string& dst, const std::string& src) {
245 socket_factory_.AddMapping(ParseIP(dst), ParseIP(src));
246 }
247
SetSocketCreateCallback(base::RepeatingCallback<void (TestUDPClientSocket *)> socket_create_callback)248 void SetSocketCreateCallback(
249 base::RepeatingCallback<void(TestUDPClientSocket*)>
250 socket_create_callback) {
251 socket_factory_.SetSocketCreateCallback(std::move(socket_create_callback));
252 }
253
SetConnectMode(TestUDPClientSocket::ConnectMode connect_mode)254 void SetConnectMode(TestUDPClientSocket::ConnectMode connect_mode) {
255 socket_factory_.SetConnectMode(connect_mode);
256 }
257
GetSourceInfo(const std::string & addr)258 AddressSorterPosix::SourceAddressInfo* GetSourceInfo(
259 const std::string& addr) {
260 IPAddress address = ParseIP(addr);
261 AddressSorterPosix::SourceAddressInfo* info =
262 &sorter_->source_map_[address];
263 if (info->scope == AddressSorterPosix::SCOPE_UNDEFINED)
264 sorter_->FillPolicy(address, info);
265 return info;
266 }
267
268 TestSocketFactory socket_factory_;
269 std::unique_ptr<AddressSorterPosix> sorter_;
270 bool completed_ = false;
271
272 private:
273 friend class AddressSorterPosixSyncOrAsyncTest;
274 };
275
276 // Parameterized subclass of AddressSorterPosixTest. Necessary because not every
277 // test needs to be parameterized.
278 class AddressSorterPosixSyncOrAsyncTest
279 : public AddressSorterPosixTest,
280 public testing::WithParamInterface<TestUDPClientSocket::ConnectMode> {
281 protected:
AddressSorterPosixSyncOrAsyncTest()282 AddressSorterPosixSyncOrAsyncTest() { SetConnectMode(GetParam()); }
283
284 // Verify that NULL-terminated |addresses| matches (-1)-terminated |order|
285 // after sorting.
Verify(const char * const addresses[],const int order[])286 void Verify(const char* const addresses[], const int order[]) {
287 std::vector<IPEndPoint> endpoints;
288 for (const char* const* addr = addresses; *addr != nullptr; ++addr)
289 endpoints.emplace_back(ParseIP(*addr), 80);
290 for (size_t i = 0; order[i] >= 0; ++i)
291 CHECK_LT(order[i], static_cast<int>(endpoints.size()));
292
293 std::vector<IPEndPoint> sorted;
294 TestCompletionCallback callback;
295 sorter_->Sort(endpoints,
296 base::BindOnce(&OnSortComplete, std::ref(completed_), &sorted,
297 callback.callback()));
298 callback.WaitForResult();
299
300 for (size_t i = 0; (i < sorted.size()) || (order[i] >= 0); ++i) {
301 IPEndPoint expected = order[i] >= 0 ? endpoints[order[i]] : IPEndPoint();
302 IPEndPoint actual = i < sorted.size() ? sorted[i] : IPEndPoint();
303 EXPECT_TRUE(expected == actual)
304 << "Endpoint out of order at position " << i << "\n"
305 << " Actual: " << actual.ToString() << "\n"
306 << "Expected: " << expected.ToString();
307 }
308 EXPECT_TRUE(completed_);
309 }
310 };
311
312 INSTANTIATE_TEST_SUITE_P(
313 AddressSorterPosix,
314 AddressSorterPosixSyncOrAsyncTest,
315 ::testing::Values(TestUDPClientSocket::ConnectMode::kSynchronous,
316 TestUDPClientSocket::ConnectMode::kAsynchronous));
317
318 // Rule 1: Avoid unusable destinations.
TEST_P(AddressSorterPosixSyncOrAsyncTest,Rule1)319 TEST_P(AddressSorterPosixSyncOrAsyncTest, Rule1) {
320 AddMapping("10.0.0.231", "10.0.0.1");
321 const char* const addresses[] = {"::1", "10.0.0.231", "127.0.0.1", nullptr};
322 const int order[] = { 1, -1 };
323 Verify(addresses, order);
324 }
325
326 // Rule 2: Prefer matching scope.
TEST_P(AddressSorterPosixSyncOrAsyncTest,Rule2)327 TEST_P(AddressSorterPosixSyncOrAsyncTest, Rule2) {
328 AddMapping("3002::1", "4000::10"); // matching global
329 AddMapping("ff32::1", "fe81::10"); // matching link-local
330 AddMapping("fec1::1", "fec1::10"); // matching node-local
331 AddMapping("3002::2", "::1"); // global vs. link-local
332 AddMapping("fec1::2", "fe81::10"); // site-local vs. link-local
333 AddMapping("8.0.0.1", "169.254.0.10"); // global vs. link-local
334 // In all three cases, matching scope is preferred.
335 const int order[] = { 1, 0, -1 };
336 const char* const addresses1[] = {"3002::2", "3002::1", nullptr};
337 Verify(addresses1, order);
338 const char* const addresses2[] = {"fec1::2", "ff32::1", nullptr};
339 Verify(addresses2, order);
340 const char* const addresses3[] = {"8.0.0.1", "fec1::1", nullptr};
341 Verify(addresses3, order);
342 }
343
344 // Rule 3: Avoid deprecated addresses.
TEST_P(AddressSorterPosixSyncOrAsyncTest,Rule3)345 TEST_P(AddressSorterPosixSyncOrAsyncTest, Rule3) {
346 // Matching scope.
347 AddMapping("3002::1", "4000::10");
348 GetSourceInfo("4000::10")->deprecated = true;
349 AddMapping("3002::2", "4000::20");
350 const char* const addresses[] = {"3002::1", "3002::2", nullptr};
351 const int order[] = { 1, 0, -1 };
352 Verify(addresses, order);
353 }
354
355 // Rule 4: Prefer home addresses.
TEST_P(AddressSorterPosixSyncOrAsyncTest,Rule4)356 TEST_P(AddressSorterPosixSyncOrAsyncTest, Rule4) {
357 AddMapping("3002::1", "4000::10");
358 AddMapping("3002::2", "4000::20");
359 GetSourceInfo("4000::20")->home = true;
360 const char* const addresses[] = {"3002::1", "3002::2", nullptr};
361 const int order[] = { 1, 0, -1 };
362 Verify(addresses, order);
363 }
364
365 // Rule 5: Prefer matching label.
TEST_P(AddressSorterPosixSyncOrAsyncTest,Rule5)366 TEST_P(AddressSorterPosixSyncOrAsyncTest, Rule5) {
367 AddMapping("::1", "::1"); // matching loopback
368 AddMapping("::ffff:1234:1", "::ffff:1234:10"); // matching IPv4-mapped
369 AddMapping("2001::1", "::ffff:1234:10"); // Teredo vs. IPv4-mapped
370 AddMapping("2002::1", "2001::10"); // 6to4 vs. Teredo
371 const int order[] = { 1, 0, -1 };
372 {
373 const char* const addresses[] = {"2001::1", "::1", nullptr};
374 Verify(addresses, order);
375 }
376 {
377 const char* const addresses[] = {"2002::1", "::ffff:1234:1", nullptr};
378 Verify(addresses, order);
379 }
380 }
381
382 // Rule 6: Prefer higher precedence.
TEST_P(AddressSorterPosixSyncOrAsyncTest,Rule6)383 TEST_P(AddressSorterPosixSyncOrAsyncTest, Rule6) {
384 AddMapping("::1", "::1"); // loopback
385 AddMapping("ff32::1", "fe81::10"); // multicast
386 AddMapping("::ffff:1234:1", "::ffff:1234:10"); // IPv4-mapped
387 AddMapping("2001::1", "2001::10"); // Teredo
388 const char* const addresses[] = {"2001::1", "::ffff:1234:1", "ff32::1", "::1",
389 nullptr};
390 const int order[] = { 3, 2, 1, 0, -1 };
391 Verify(addresses, order);
392 }
393
394 // Rule 7: Prefer native transport.
TEST_P(AddressSorterPosixSyncOrAsyncTest,Rule7)395 TEST_P(AddressSorterPosixSyncOrAsyncTest, Rule7) {
396 AddMapping("3002::1", "4000::10");
397 AddMapping("3002::2", "4000::20");
398 GetSourceInfo("4000::20")->native = true;
399 const char* const addresses[] = {"3002::1", "3002::2", nullptr};
400 const int order[] = { 1, 0, -1 };
401 Verify(addresses, order);
402 }
403
404 // Rule 8: Prefer smaller scope.
TEST_P(AddressSorterPosixSyncOrAsyncTest,Rule8)405 TEST_P(AddressSorterPosixSyncOrAsyncTest, Rule8) {
406 // Matching scope. Should precede the others by Rule 2.
407 AddMapping("fe81::1", "fe81::10"); // link-local
408 AddMapping("3000::1", "4000::10"); // global
409 // Mismatched scope.
410 AddMapping("ff32::1", "4000::10"); // link-local
411 AddMapping("ff35::1", "4000::10"); // site-local
412 AddMapping("ff38::1", "4000::10"); // org-local
413 const char* const addresses[] = {"ff38::1", "3000::1", "ff35::1",
414 "ff32::1", "fe81::1", nullptr};
415 const int order[] = { 4, 1, 3, 2, 0, -1 };
416 Verify(addresses, order);
417 }
418
419 // Rule 9: Use longest matching prefix.
TEST_P(AddressSorterPosixSyncOrAsyncTest,Rule9)420 TEST_P(AddressSorterPosixSyncOrAsyncTest, Rule9) {
421 AddMapping("3000::1", "3000:ffff::10"); // 16 bit match
422 GetSourceInfo("3000:ffff::10")->prefix_length = 16;
423 AddMapping("4000::1", "4000::10"); // 123 bit match, limited to 15
424 GetSourceInfo("4000::10")->prefix_length = 15;
425 AddMapping("4002::1", "4000::10"); // 14 bit match
426 AddMapping("4080::1", "4000::10"); // 8 bit match
427 const char* const addresses[] = {"4080::1", "4002::1", "4000::1", "3000::1",
428 nullptr};
429 const int order[] = { 3, 2, 1, 0, -1 };
430 Verify(addresses, order);
431 }
432
433 // Rule 10: Leave the order unchanged.
TEST_P(AddressSorterPosixSyncOrAsyncTest,Rule10)434 TEST_P(AddressSorterPosixSyncOrAsyncTest, Rule10) {
435 AddMapping("4000::1", "4000::10");
436 AddMapping("4000::2", "4000::10");
437 AddMapping("4000::3", "4000::10");
438 const char* const addresses[] = {"4000::1", "4000::2", "4000::3", nullptr};
439 const int order[] = { 0, 1, 2, -1 };
440 Verify(addresses, order);
441 }
442
TEST_P(AddressSorterPosixSyncOrAsyncTest,MultipleRules)443 TEST_P(AddressSorterPosixSyncOrAsyncTest, MultipleRules) {
444 AddMapping("::1", "::1"); // loopback
445 AddMapping("ff32::1", "fe81::10"); // link-local multicast
446 AddMapping("ff3e::1", "4000::10"); // global multicast
447 AddMapping("4000::1", "4000::10"); // global unicast
448 AddMapping("ff32::2", "fe81::20"); // deprecated link-local multicast
449 GetSourceInfo("fe81::20")->deprecated = true;
450 const char* const addresses[] = {"ff3e::1", "ff32::2", "4000::1", "ff32::1",
451 "::1", "8.0.0.1", nullptr};
452 const int order[] = { 4, 3, 0, 2, 1, -1 };
453 Verify(addresses, order);
454 }
455
TEST_P(AddressSorterPosixSyncOrAsyncTest,InputPortsAreMaintained)456 TEST_P(AddressSorterPosixSyncOrAsyncTest, InputPortsAreMaintained) {
457 AddMapping("::1", "::1");
458 AddMapping("::2", "::2");
459 AddMapping("::3", "::3");
460
461 IPEndPoint endpoint1(ParseIP("::1"), /*port=*/111);
462 IPEndPoint endpoint2(ParseIP("::2"), /*port=*/222);
463 IPEndPoint endpoint3(ParseIP("::3"), /*port=*/333);
464
465 std::vector<IPEndPoint> input = {endpoint1, endpoint2, endpoint3};
466 std::vector<IPEndPoint> sorted;
467 TestCompletionCallback callback;
468 sorter_->Sort(input, base::BindOnce(&OnSortComplete, std::ref(completed_),
469 &sorted, callback.callback()));
470 callback.WaitForResult();
471
472 EXPECT_THAT(sorted, testing::ElementsAre(endpoint1, endpoint2, endpoint3));
473 }
474
TEST_P(AddressSorterPosixSyncOrAsyncTest,AddressSorterPosixDestroyed)475 TEST_P(AddressSorterPosixSyncOrAsyncTest, AddressSorterPosixDestroyed) {
476 AddMapping("::1", "::1");
477 AddMapping("::2", "::2");
478 AddMapping("::3", "::3");
479
480 IPEndPoint endpoint1(ParseIP("::1"), /*port=*/111);
481 IPEndPoint endpoint2(ParseIP("::2"), /*port=*/222);
482 IPEndPoint endpoint3(ParseIP("::3"), /*port=*/333);
483
484 std::vector<IPEndPoint> input = {endpoint1, endpoint2, endpoint3};
485 std::vector<IPEndPoint> sorted;
486 TestCompletionCallback callback;
487 sorter_->Sort(input, base::BindOnce(&OnSortComplete, std::ref(completed_),
488 &sorted, callback.callback()));
489 sorter_.reset();
490 base::RunLoop().RunUntilIdle();
491
492 TestUDPClientSocket::ConnectMode connect_mode = GetParam();
493 if (connect_mode == TestUDPClientSocket::ConnectMode::kAsynchronous) {
494 EXPECT_FALSE(completed_);
495 } else {
496 EXPECT_TRUE(completed_);
497 }
498 }
499
TEST_F(AddressSorterPosixTest,RandomAsyncSocketOrder)500 TEST_F(AddressSorterPosixTest, RandomAsyncSocketOrder) {
501 SetConnectMode(TestUDPClientSocket::ConnectMode::kAsynchronousManual);
502 std::vector<TestUDPClientSocket*> created_sockets;
503 SetSocketCreateCallback(base::BindRepeating(
504 [](std::vector<TestUDPClientSocket*>& created_sockets,
505 TestUDPClientSocket* socket) { created_sockets.push_back(socket); },
506 std::ref(created_sockets)));
507
508 AddMapping("::1", "::1");
509 AddMapping("::2", "::2");
510 AddMapping("::3", "::3");
511
512 IPEndPoint endpoint1(ParseIP("::1"), /*port=*/111);
513 IPEndPoint endpoint2(ParseIP("::2"), /*port=*/222);
514 IPEndPoint endpoint3(ParseIP("::3"), /*port=*/333);
515
516 std::vector<IPEndPoint> input = {endpoint1, endpoint2, endpoint3};
517 std::vector<IPEndPoint> sorted;
518 TestCompletionCallback callback;
519 sorter_->Sort(input, base::BindOnce(&OnSortComplete, std::ref(completed_),
520 &sorted, callback.callback()));
521
522 ASSERT_EQ(created_sockets.size(), 3u);
523 created_sockets[1]->FinishConnect();
524 created_sockets[2]->FinishConnect();
525 created_sockets[0]->FinishConnect();
526
527 base::RunLoop().RunUntilIdle();
528 EXPECT_TRUE(completed_);
529 }
530
531 // Regression test for https://crbug.com/1374387
TEST_F(AddressSorterPosixTest,IPAddressChangedSort)532 TEST_F(AddressSorterPosixTest, IPAddressChangedSort) {
533 SetConnectMode(TestUDPClientSocket::ConnectMode::kAsynchronousManual);
534 std::vector<TestUDPClientSocket*> created_sockets;
535 SetSocketCreateCallback(base::BindRepeating(
536 [](std::vector<TestUDPClientSocket*>& created_sockets,
537 TestUDPClientSocket* socket) { created_sockets.push_back(socket); },
538 std::ref(created_sockets)));
539
540 AddMapping("::1", "::1");
541 AddMapping("::2", "::2");
542 AddMapping("::3", "::3");
543
544 IPEndPoint endpoint1(ParseIP("::1"), /*port=*/111);
545 IPEndPoint endpoint2(ParseIP("::2"), /*port=*/222);
546 IPEndPoint endpoint3(ParseIP("::3"), /*port=*/333);
547
548 std::vector<IPEndPoint> input = {endpoint1, endpoint2, endpoint3};
549 std::vector<IPEndPoint> sorted;
550 TestCompletionCallback callback;
551 sorter_->Sort(input, base::BindOnce(&OnSortComplete, std::ref(completed_),
552 &sorted, callback.callback()));
553
554 ASSERT_EQ(created_sockets.size(), 3u);
555 created_sockets[0]->FinishConnect();
556 // Trigger OnIPAddressChanged() to reset `source_map_`
557 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
558 base::RunLoop().RunUntilIdle();
559 created_sockets[1]->FinishConnect();
560 created_sockets[2]->FinishConnect();
561
562 base::RunLoop().RunUntilIdle();
563 EXPECT_TRUE(completed_);
564 }
565
566 } // namespace net
567