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