1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using System;
6 using System.Runtime.CompilerServices;
7 using System.Threading;
8 using System.Threading.Tasks;
9 using Xunit;
10 
11 namespace System.Net.Sockets.Tests
12 {
13     public class UdpClientTest
14     {
15         // Port 8 is unassigned as per https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.txt
16         private const int UnusedPort = 8;
17 
18         private ManualResetEvent _waitHandle = new ManualResetEvent(false);
19 
20         [Theory]
21         [InlineData(AddressFamily.InterNetwork)]
22         [InlineData(AddressFamily.InterNetworkV6)]
Ctor_ValidAddressFamily_Succeeds(AddressFamily family)23         public void Ctor_ValidAddressFamily_Succeeds(AddressFamily family)
24         {
25             new UdpClient(family).Dispose();
26         }
27 
28         [Theory]
29         [InlineData(AddressFamily.DataKit)]
30         [InlineData(AddressFamily.Unix)]
31         [InlineData(AddressFamily.Unspecified)]
Ctor_InvalidAddressFamily_Throws(AddressFamily family)32         public void Ctor_InvalidAddressFamily_Throws(AddressFamily family)
33         {
34             AssertExtensions.Throws<ArgumentException>("family", () => new UdpClient(family));
35             AssertExtensions.Throws<ArgumentException>("family", () => new UdpClient(0, family));
36         }
37 
38         [Fact]
Ctor_InvalidHostName_Throws()39         public void Ctor_InvalidHostName_Throws()
40         {
41             AssertExtensions.Throws<ArgumentNullException>("hostname", () => new UdpClient(null, 0));
42         }
43 
44         [Theory]
45         [InlineData(-1)]
46         [InlineData(66000)]
Ctor_InvalidPort_Throws(int port)47         public void Ctor_InvalidPort_Throws(int port)
48         {
49             AssertExtensions.Throws<ArgumentOutOfRangeException>("port", () => new UdpClient(port));
50             AssertExtensions.Throws<ArgumentOutOfRangeException>("port", () => new UdpClient(port, AddressFamily.InterNetwork));
51             AssertExtensions.Throws<ArgumentOutOfRangeException>("port", () => new UdpClient(port, AddressFamily.InterNetworkV6));
52             AssertExtensions.Throws<ArgumentOutOfRangeException>("port", () => new UdpClient("localhost", port));
53         }
54 
55         [Fact]
Ctor_NullEndpoint_Throws()56         public void Ctor_NullEndpoint_Throws()
57         {
58             AssertExtensions.Throws<ArgumentNullException>("localEP", () => new UdpClient(null));
59         }
60 
61         [OuterLoop] // TODO: Issue #11345
62         [Fact]
Ctor_CanSend()63         public void Ctor_CanSend()
64         {
65             using (var udpClient = new DerivedUdpClient())
66             {
67                 Assert.Equal(1, udpClient.Send(new byte[1], 1, new IPEndPoint(IPAddress.Loopback, UnusedPort)));
68                 Assert.False(udpClient.Active);
69             }
70         }
71 
72         [OuterLoop] // TODO: Issue #11345
73         [Fact]
Ctor_Int_CanSend()74         public void Ctor_Int_CanSend()
75         {
76             try
77             {
78                 using (var udpClient = new UdpClient(UnusedPort))
79                 {
80                     Assert.Equal(1, udpClient.Send(new byte[1], 1, new IPEndPoint(IPAddress.Loopback, UnusedPort)));
81                 }
82             }
83             catch (SocketException e)
84             {
85                 // Some configurations require elevation to bind to UnusedPort
86                 Assert.Equal(SocketError.AccessDenied, e.SocketErrorCode);
87             }
88         }
89 
90         [OuterLoop] // TODO: Issue #11345
91         [Fact]
Ctor_IntAddressFamily_IPv4_CanSend()92         public void Ctor_IntAddressFamily_IPv4_CanSend()
93         {
94             try
95             {
96                 using (var udpClient = new UdpClient(UnusedPort, AddressFamily.InterNetwork))
97                 {
98                     Assert.Equal(1, udpClient.Send(new byte[1], 1, new IPEndPoint(IPAddress.Loopback, UnusedPort)));
99                 }
100             }
101             catch (SocketException e)
102             {
103                 // Some configurations require elevation to bind to UnusedPort
104                 Assert.Equal(SocketError.AccessDenied, e.SocketErrorCode);
105             }
106         }
107 
108         [OuterLoop] // TODO: Issue #11345
109         [Fact]
Ctor_IntAddressFamily_IPv6_CanSend()110         public void Ctor_IntAddressFamily_IPv6_CanSend()
111         {
112             try
113             {
114                 using (var udpClient = new UdpClient(UnusedPort, AddressFamily.InterNetworkV6))
115                 {
116                     Assert.Equal(1, udpClient.Send(new byte[1], 1, new IPEndPoint(IPAddress.IPv6Loopback, UnusedPort)));
117                 }
118             }
119             catch (SocketException e)
120             {
121                 // Some configurations require elevation to bind to UnusedPort
122                 Assert.Equal(SocketError.AccessDenied, e.SocketErrorCode);
123             }
124         }
125 
126         [OuterLoop] // TODO: Issue #11345
127         [Fact]
Ctor_IPEndPoint_CanSend()128         public void Ctor_IPEndPoint_CanSend()
129         {
130             try
131             {
132                 using (var udpClient = new UdpClient(new IPEndPoint(IPAddress.IPv6Any, UnusedPort)))
133                 {
134                     Assert.Equal(1, udpClient.Send(new byte[1], 1, new IPEndPoint(IPAddress.IPv6Loopback, UnusedPort)));
135                 }
136             }
137             catch (SocketException e)
138             {
139                 // Some configurations require elevation to bind to UnusedPort
140                 Assert.Equal(SocketError.AccessDenied, e.SocketErrorCode);
141             }
142         }
143 
144         [OuterLoop] // TODO: Issue #11345
145         [Fact]
Ctor_StringInt_CanSend()146         public void Ctor_StringInt_CanSend()
147         {
148             using (var udpClient = new DerivedUdpClient("localhost", UnusedPort))
149             {
150                 Assert.Equal(1, udpClient.Send(new byte[1], 1));
151                 Assert.True(udpClient.Active);
152             }
153         }
154 
155         [Theory]
156         [InlineData(false)]
157         [InlineData(true)]
DisposeClose_OperationsThrow(bool close)158         public void DisposeClose_OperationsThrow(bool close)
159         {
160             var udpClient = new UdpClient();
161 
162             for (int i = 0; i < 2; i++) // verify double dispose doesn't throw
163             {
164                 if (close) udpClient.Close();
165                 else udpClient.Dispose();
166             }
167 
168             IPEndPoint remoteEP = null;
169 
170             Assert.Throws<ObjectDisposedException>(() => udpClient.BeginSend(new byte[1], 1, null, null));
171             Assert.Throws<ObjectDisposedException>(() => udpClient.EndSend(null));
172 
173             Assert.Throws<ObjectDisposedException>(() => udpClient.BeginReceive(null, null));
174             Assert.Throws<ObjectDisposedException>(() => udpClient.EndReceive(null, ref remoteEP));
175 
176             Assert.Throws<ObjectDisposedException>(() => udpClient.JoinMulticastGroup(IPAddress.Loopback));
177             Assert.Throws<ObjectDisposedException>(() => udpClient.JoinMulticastGroup(IPAddress.Loopback, IPAddress.Loopback));
178             Assert.Throws<ObjectDisposedException>(() => udpClient.JoinMulticastGroup(0, IPAddress.Loopback));
179             Assert.Throws<ObjectDisposedException>(() => udpClient.JoinMulticastGroup(IPAddress.Loopback, 0));
180 
181             Assert.Throws<ObjectDisposedException>(() => udpClient.DropMulticastGroup(IPAddress.Loopback));
182             Assert.Throws<ObjectDisposedException>(() => udpClient.DropMulticastGroup(IPAddress.Loopback, 0));
183 
184             Assert.Throws<ObjectDisposedException>(() => udpClient.Connect(null));
185             Assert.Throws<ObjectDisposedException>(() => udpClient.Connect(IPAddress.Loopback, 0));
186             Assert.Throws<ObjectDisposedException>(() => udpClient.Connect("localhost", 0));
187 
188             Assert.Throws<ObjectDisposedException>(() => udpClient.Receive(ref remoteEP));
189 
190             Assert.Throws<ObjectDisposedException>(() => udpClient.Send(null, 0, remoteEP));
191             Assert.Throws<ObjectDisposedException>(() => udpClient.Send(null, 0));
192             Assert.Throws<ObjectDisposedException>(() => udpClient.Send(null, 0, "localhost", 0));
193         }
194 
195         [Fact]
Finalize_NoExceptionsThrown()196         public void Finalize_NoExceptionsThrown()
197         {
198             WeakReference<UdpClient> udpClientWeakRef = CreateAndDiscardUdpClient();
199 
200             GC.Collect();
201             GC.WaitForPendingFinalizers();
202             GC.Collect();
203 
204             UdpClient ignored;
205             Assert.False(udpClientWeakRef.TryGetTarget(out ignored));
206         }
207 
208         [MethodImpl(MethodImplOptions.NoInlining)]
CreateAndDiscardUdpClient()209         private static WeakReference<UdpClient> CreateAndDiscardUdpClient() => new WeakReference<UdpClient>(new DerivedUdpClient());
210 
211         [Fact]
Active_Roundtrips()212         public void Active_Roundtrips()
213         {
214             using (var udpClient = new DerivedUdpClient())
215             {
216                 Assert.False(udpClient.Active);
217                 udpClient.Active = true;
218                 Assert.True(udpClient.Active);
219                 udpClient.Active = false;
220                 Assert.False(udpClient.Active);
221             }
222         }
223 
224         [Fact]
Client_Idemptotent()225         public void Client_Idemptotent()
226         {
227             using (var udpClient = new UdpClient())
228             {
229                 Socket s = udpClient.Client;
230                 Assert.NotNull(s);
231                 Assert.Same(s, udpClient.Client);
232 
233                 udpClient.Client = null;
234                 Assert.Null(udpClient.Client);
235 
236                 udpClient.Client = s;
237                 Assert.Same(s, udpClient.Client);
238 
239                 udpClient.Client = null;
240                 s.Dispose();
241             }
242         }
243 
244         [Fact]
Ttl_Roundtrips()245         public void Ttl_Roundtrips()
246         {
247             using (var udpClient = new UdpClient())
248             {
249                 short ttl = udpClient.Ttl;
250                 Assert.Equal(ttl, udpClient.Ttl);
251 
252                 udpClient.Ttl = 100;
253                 Assert.Equal(100, udpClient.Ttl);
254             }
255         }
256 
257         [PlatformSpecific(~TestPlatforms.OSX)] // macOS doesn't have an equivalent of DontFragment
258         [Fact]
DontFragment_Roundtrips()259         public void DontFragment_Roundtrips()
260         {
261             using (var udpClient = new UdpClient())
262             {
263                 Assert.False(udpClient.DontFragment);
264                 udpClient.DontFragment = true;
265                 Assert.True(udpClient.DontFragment);
266                 udpClient.DontFragment = false;
267                 Assert.False(udpClient.DontFragment);
268             }
269         }
270 
271         [Fact]
MulticastLoopback_Roundtrips()272         public void MulticastLoopback_Roundtrips()
273         {
274             using (var udpClient = new UdpClient())
275             {
276                 Assert.True(udpClient.MulticastLoopback);
277                 udpClient.MulticastLoopback = false;
278                 Assert.False(udpClient.MulticastLoopback);
279                 udpClient.MulticastLoopback = true;
280                 Assert.True(udpClient.MulticastLoopback);
281             }
282         }
283 
284         [Fact]
EnableBroadcast_Roundtrips()285         public void EnableBroadcast_Roundtrips()
286         {
287             using (var udpClient = new UdpClient())
288             {
289                 Assert.False(udpClient.EnableBroadcast);
290                 udpClient.EnableBroadcast = true;
291                 Assert.True(udpClient.EnableBroadcast);
292                 udpClient.EnableBroadcast = false;
293                 Assert.False(udpClient.EnableBroadcast);
294             }
295         }
296 
297         [PlatformSpecific(TestPlatforms.Windows)] // ExclusiveAddressUse is Windows-specific
298         [Fact]
ExclusiveAddressUse_Roundtrips()299         public void ExclusiveAddressUse_Roundtrips()
300         {
301             using (var udpClient = new UdpClient())
302             {
303                 Assert.False(udpClient.ExclusiveAddressUse);
304                 udpClient.ExclusiveAddressUse = true;
305                 Assert.True(udpClient.ExclusiveAddressUse);
306                 udpClient.ExclusiveAddressUse = false;
307                 Assert.False(udpClient.ExclusiveAddressUse);
308             }
309         }
310 
311         [Fact]
InvalidArguments_Throw()312         public void InvalidArguments_Throw()
313         {
314             using (var udpClient = new UdpClient("localhost", UnusedPort))
315             {
316                 AssertExtensions.Throws<ArgumentNullException>("datagram", () => udpClient.BeginSend(null, 0, null, null));
317                 Assert.Throws<InvalidOperationException>(() => udpClient.BeginSend(new byte[1], 1, "localhost", 0, null, null));
318                 Assert.Throws<InvalidOperationException>(() => udpClient.BeginSend(new byte[1], 1, new IPEndPoint(IPAddress.Loopback, 0), null, null));
319             }
320         }
321 
322         [OuterLoop] // TODO: Issue #11345
323         [Fact]
BeginSend_NegativeBytes_Throws()324         public void BeginSend_NegativeBytes_Throws()
325         {
326             using (UdpClient udpClient = new UdpClient(AddressFamily.InterNetwork))
327             {
328                 byte[] sendBytes = new byte[1];
329                 IPEndPoint remoteServer = new IPEndPoint(IPAddress.Loopback, UnusedPort);
330 
331                 AssertExtensions.Throws<ArgumentOutOfRangeException>("bytes", () =>
332                 {
333                     udpClient.BeginSend(sendBytes, -1, remoteServer, new AsyncCallback(AsyncCompleted), udpClient);
334                 });
335             }
336         }
337 
338         [OuterLoop] // TODO: Issue #11345
339         [Fact]
BeginSend_BytesMoreThanArrayLength_Throws()340         public void BeginSend_BytesMoreThanArrayLength_Throws()
341         {
342             using (UdpClient udpClient = new UdpClient(AddressFamily.InterNetwork))
343             {
344                 byte[] sendBytes = new byte[1];
345                 IPEndPoint remoteServer = new IPEndPoint(IPAddress.Loopback, UnusedPort);
346 
347                 AssertExtensions.Throws<ArgumentOutOfRangeException>("bytes", () =>
348                 {
349                     udpClient.BeginSend(sendBytes, sendBytes.Length + 1, remoteServer, new AsyncCallback(AsyncCompleted), udpClient);
350                 });
351             }
352         }
353 
354         [OuterLoop] // TODO: Issue #11345
355         [Fact]
BeginSend_AsyncOperationCompletes_Success()356         public void BeginSend_AsyncOperationCompletes_Success()
357         {
358             using (UdpClient udpClient = new UdpClient())
359             {
360                 byte[] sendBytes = new byte[1];
361                 IPEndPoint remoteServer = new IPEndPoint(IPAddress.Loopback, UnusedPort);
362                 _waitHandle.Reset();
363                 udpClient.BeginSend(sendBytes, sendBytes.Length, remoteServer, new AsyncCallback(AsyncCompleted), udpClient);
364 
365                 Assert.True(_waitHandle.WaitOne(TestSettings.PassingTestTimeout), "Timed out while waiting for connection");
366             }
367         }
368 
369         [Fact]
Send_InvalidArguments_Throws()370         public void Send_InvalidArguments_Throws()
371         {
372             using (var udpClient = new DerivedUdpClient())
373             {
374                 AssertExtensions.Throws<ArgumentNullException>("dgram", () => udpClient.Send(null, 0));
375                 AssertExtensions.Throws<ArgumentNullException>("dgram", () => udpClient.Send(null, 0, "localhost", 0));
376                 AssertExtensions.Throws<ArgumentNullException>("dgram", () => udpClient.Send(null, 0, new IPEndPoint(IPAddress.Loopback, 0)));
377                 Assert.Throws<InvalidOperationException>(() => udpClient.Send(new byte[1], 1));
378                 udpClient.Active = true;
379                 Assert.Throws<InvalidOperationException>(() => udpClient.Send(new byte[1], 1, new IPEndPoint(IPAddress.Loopback, 0)));
380             }
381         }
382 
383         [PlatformSpecific(TestPlatforms.Windows)] // localhost on Windows resolves to both IPV4/6, but doesn't on all Unix
Send_InvalidArguments_StringInt_Throws()384         public void Send_InvalidArguments_StringInt_Throws()
385         {
386             using (var udpClient = new UdpClient("localhost", 0))
387             {
388                 Assert.Throws<InvalidOperationException>(() => udpClient.Send(new byte[1], 1, "localhost", 0));
389             }
390         }
391 
392         [OuterLoop] // TODO: Issue #11345
393         [Fact]
Client_Idempotent()394         public void Client_Idempotent()
395         {
396             using (var c = new UdpClient())
397             {
398                 Socket client = c.Client;
399                 Assert.NotNull(client);
400                 Assert.Same(client, c.Client);
401             }
402         }
403 
404         [Fact]
Connect_InvalidArguments_Throws()405         public void Connect_InvalidArguments_Throws()
406         {
407             using (var udpClient = new UdpClient())
408             {
409                 AssertExtensions.Throws<ArgumentNullException>("hostname", () => udpClient.Connect((string)null, 0));
410                 AssertExtensions.Throws<ArgumentOutOfRangeException>("port", () => udpClient.Connect("localhost", -1));
411                 AssertExtensions.Throws<ArgumentOutOfRangeException>("port", () => udpClient.Connect("localhost", 66000));
412 
413                 AssertExtensions.Throws<ArgumentNullException>("addr", () => udpClient.Connect((IPAddress)null, 0));
414                 AssertExtensions.Throws<ArgumentOutOfRangeException>("port", () => udpClient.Connect(IPAddress.Loopback, -1));
415                 AssertExtensions.Throws<ArgumentOutOfRangeException>("port", () => udpClient.Connect(IPAddress.Loopback, 66000));
416 
417                 AssertExtensions.Throws<ArgumentNullException>("endPoint", () => udpClient.Connect(null));
418             }
419         }
420 
421         [OuterLoop] // TODO: Issue #11345
422         [Fact]
ConnectAsync_StringHost_Success()423         public async Task ConnectAsync_StringHost_Success()
424         {
425             using (var c = new UdpClient())
426             {
427                 await c.Client.ConnectAsync("114.114.114.114", 53);
428             }
429         }
430 
431         [OuterLoop] // TODO: Issue #11345
432         [Fact]
ConnectAsync_IPAddressHost_Success()433         public async Task ConnectAsync_IPAddressHost_Success()
434         {
435             using (var c = new UdpClient())
436             {
437                 await c.Client.ConnectAsync(IPAddress.Parse("114.114.114.114"), 53);
438             }
439         }
440 
441         [OuterLoop] // TODO: Issue #11345
442         [Fact]
Connect_StringHost_Success()443         public void Connect_StringHost_Success()
444         {
445             using (var c = new UdpClient())
446             {
447                 c.Client.Connect("114.114.114.114", 53);
448             }
449         }
450 
451         [OuterLoop] // TODO: Issue #11345
452         [Fact]
Connect_IPAddressHost_Success()453         public void Connect_IPAddressHost_Success()
454         {
455             using (var c = new UdpClient())
456             {
457                 c.Client.Connect(IPAddress.Parse("114.114.114.114"), 53);
458             }
459         }
460 
AsyncCompleted(IAsyncResult ar)461         private void AsyncCompleted(IAsyncResult ar)
462         {
463             UdpClient udpService = (UdpClient)ar.AsyncState;
464             udpService.EndSend(ar);
465             _waitHandle.Set();
466         }
467 
468         [OuterLoop] // TODO: Issue #11345
469         [Theory]
470         [PlatformSpecific(TestPlatforms.Windows)]  // Udp.AllowNatTraversal only supported on Windows
471         [InlineData(true, IPProtectionLevel.Unrestricted)]
472         [InlineData(false, IPProtectionLevel.EdgeRestricted)]
AllowNatTraversal_Windows(bool allow, IPProtectionLevel resultLevel)473         public void AllowNatTraversal_Windows(bool allow, IPProtectionLevel resultLevel)
474         {
475             using (var c = new UdpClient())
476             {
477                 c.AllowNatTraversal(allow);
478                 Assert.Equal((int)resultLevel, (int)c.Client.GetSocketOption(SocketOptionLevel.IP, SocketOptionName.IPProtectionLevel));
479             }
480         }
481 
482         [OuterLoop] // TODO: Issue #11345
483         [Theory]
484         [PlatformSpecific(TestPlatforms.AnyUnix)]  // Udp.AllowNatTraversal throws PNSE on Unix
485         [InlineData(true)]
486         [InlineData(false)]
AllowNatTraversal_AnyUnix(bool allow)487         public void AllowNatTraversal_AnyUnix(bool allow)
488         {
489             using (var c = new UdpClient())
490             {
491                 Assert.Throws<PlatformNotSupportedException>(() => c.AllowNatTraversal(allow));
492             }
493         }
494 
495         [OuterLoop] // TODO: Issue #11345
496         [Theory]
497         [InlineData(false)]
498         [InlineData(true)]
Send_Receive_Success(bool ipv4)499         public void Send_Receive_Success(bool ipv4)
500         {
501             IPAddress address = ipv4 ? IPAddress.Loopback : IPAddress.IPv6Loopback;
502 
503             using (var receiver = new UdpClient(new IPEndPoint(address, 0)))
504             using (var sender = new UdpClient(new IPEndPoint(address, 0)))
505             {
506                 for (int i = 0; i < TestSettings.UDPRedundancy; i++)
507                 {
508                     sender.Send(new byte[1], 1, new IPEndPoint(address, ((IPEndPoint)receiver.Client.LocalEndPoint).Port));
509                 }
510 
511                 IPEndPoint remoteEP = null;
512                 byte[] data = receiver.Receive(ref remoteEP);
513                 Assert.NotNull(remoteEP);
514                 Assert.InRange(data.Length, 1, int.MaxValue);
515             }
516         }
517 
518         [PlatformSpecific(TestPlatforms.Windows)] // "localhost" resolves to IPv4 & IPV6 on Windows, but may resolve to only one of those on Unix
519         [OuterLoop] // TODO: Issue #11345
Send_Receive_Connected_Success()520         public void Send_Receive_Connected_Success()
521         {
522             using (var receiver = new UdpClient("localhost", 0))
523             using (var sender = new UdpClient("localhost", ((IPEndPoint)receiver.Client.LocalEndPoint).Port))
524             {
525                 for (int i = 0; i < TestSettings.UDPRedundancy; i++)
526                 {
527                     sender.Send(new byte[1], 1);
528                 }
529 
530                 IPEndPoint remoteEP = null;
531                 byte[] data = receiver.Receive(ref remoteEP);
532                 Assert.NotNull(remoteEP);
533                 Assert.InRange(data.Length, 1, int.MaxValue);
534             }
535         }
536 
537         [OuterLoop] // TODO: Issue #11345
538         [Theory]
539         [InlineData(false)]
540         [InlineData(true)]
Send_Available_Success(bool ipv4)541         public void Send_Available_Success(bool ipv4)
542         {
543             IPAddress address = ipv4 ? IPAddress.Loopback : IPAddress.IPv6Loopback;
544 
545             using (var receiver = new UdpClient(new IPEndPoint(address, 0)))
546             using (var sender = new UdpClient(new IPEndPoint(address, 0)))
547             {
548                 for (int i = 0; i < TestSettings.UDPRedundancy; i++)
549                 {
550                     sender.Send(new byte[1], 1, new IPEndPoint(address, ((IPEndPoint)receiver.Client.LocalEndPoint).Port));
551                 }
552 
553                 Assert.True(SpinWait.SpinUntil(() => receiver.Available > 0, 30000), "Expected data to be available for receive within time limit");
554             }
555         }
556 
557         [OuterLoop] // TODO: Issue #11345
558         [Theory]
559         [InlineData(false)]
560         [InlineData(true)]
BeginEndSend_BeginEndReceive_Success(bool ipv4)561         public void BeginEndSend_BeginEndReceive_Success(bool ipv4)
562         {
563             IPAddress address = ipv4 ? IPAddress.Loopback : IPAddress.IPv6Loopback;
564 
565             using (var receiver = new UdpClient(new IPEndPoint(address, 0)))
566             using (var sender = new UdpClient(new IPEndPoint(address, 0)))
567             {
568                 for (int i = 0; i < TestSettings.UDPRedundancy; i++)
569                 {
570                     sender.EndSend(sender.BeginSend(new byte[1], 1, new IPEndPoint(address, ((IPEndPoint)receiver.Client.LocalEndPoint).Port), null, null));
571                 }
572 
573                 IPEndPoint remoteEP = null;
574                 byte[] data = receiver.EndReceive(receiver.BeginReceive(null, null), ref remoteEP);
575                 Assert.NotNull(remoteEP);
576                 Assert.InRange(data.Length, 1, int.MaxValue);
577             }
578         }
579 
580         [PlatformSpecific(TestPlatforms.Windows)] // "localhost" resolves to IPv4 & IPV6 on Windows, but may resolve to only one of those on Unix
581         [OuterLoop] // TODO: Issue #11345
BeginEndSend_BeginEndReceive_Connected_Success()582         public void BeginEndSend_BeginEndReceive_Connected_Success()
583         {
584             using (var receiver = new UdpClient("localhost", 0))
585             using (var sender = new UdpClient("localhost", ((IPEndPoint)receiver.Client.LocalEndPoint).Port))
586             {
587                 for (int i = 0; i < TestSettings.UDPRedundancy; i++)
588                 {
589                     sender.EndSend(sender.BeginSend(new byte[1], 1, null, null));
590                 }
591 
592                 IPEndPoint remoteEP = null;
593                 byte[] data = receiver.EndReceive(receiver.BeginReceive(null, null), ref remoteEP);
594                 Assert.NotNull(remoteEP);
595                 Assert.InRange(data.Length, 1, int.MaxValue);
596             }
597         }
598 
599         [OuterLoop] // TODO: Issue #11345
600         [Theory]
601         [InlineData(false)]
602         [InlineData(true)]
SendAsync_ReceiveAsync_Success(bool ipv4)603         public async Task SendAsync_ReceiveAsync_Success(bool ipv4)
604         {
605             IPAddress address = ipv4 ? IPAddress.Loopback : IPAddress.IPv6Loopback;
606 
607             using (var receiver = new UdpClient(new IPEndPoint(address, 0)))
608             using (var sender = new UdpClient(new IPEndPoint(address, 0)))
609             {
610                 for (int i = 0; i < TestSettings.UDPRedundancy; i++)
611                 {
612                     await sender.SendAsync(new byte[1], 1, new IPEndPoint(address, ((IPEndPoint)receiver.Client.LocalEndPoint).Port));
613                 }
614 
615                 UdpReceiveResult result = await receiver.ReceiveAsync();
616                 Assert.NotNull(result);
617                 Assert.NotNull(result.RemoteEndPoint);
618                 Assert.NotNull(result.Buffer);
619                 Assert.InRange(result.Buffer.Length, 1, int.MaxValue);
620             }
621         }
622 
623         [PlatformSpecific(TestPlatforms.Windows)] // "localhost" resolves to IPv4 & IPV6 on Windows, but may resolve to only one of those on Unix
624         [OuterLoop] // TODO: Issue #11345
SendAsync_ReceiveAsync_Connected_Success()625         public async Task SendAsync_ReceiveAsync_Connected_Success()
626         {
627             using (var receiver = new UdpClient("localhost", 0))
628             using (var sender = new UdpClient("localhost", ((IPEndPoint)receiver.Client.LocalEndPoint).Port))
629             {
630                 for (int i = 0; i < TestSettings.UDPRedundancy; i++)
631                 {
632                     await sender.SendAsync(new byte[1], 1);
633                 }
634 
635                 UdpReceiveResult result = await receiver.ReceiveAsync();
636                 Assert.NotNull(result);
637                 Assert.NotNull(result.RemoteEndPoint);
638                 Assert.NotNull(result.Buffer);
639                 Assert.InRange(result.Buffer.Length, 1, int.MaxValue);
640             }
641         }
642 
643         [Fact]
JoinDropMulticastGroup_InvalidArguments_Throws()644         public void JoinDropMulticastGroup_InvalidArguments_Throws()
645         {
646             using (var udpClient = new UdpClient(AddressFamily.InterNetwork))
647             {
648                 AssertExtensions.Throws<ArgumentNullException>("multicastAddr", () => udpClient.JoinMulticastGroup(null));
649                 AssertExtensions.Throws<ArgumentNullException>("multicastAddr", () => udpClient.JoinMulticastGroup(0, null));
650                 AssertExtensions.Throws<ArgumentNullException>("multicastAddr", () => udpClient.JoinMulticastGroup(null, 0));
651                 AssertExtensions.Throws<ArgumentException>("ifindex", () => udpClient.JoinMulticastGroup(-1, IPAddress.Any));
652                 AssertExtensions.Throws<ArgumentOutOfRangeException>("timeToLive", () => udpClient.JoinMulticastGroup(IPAddress.Loopback, -1));
653 
654                 AssertExtensions.Throws<ArgumentNullException>("multicastAddr", () => udpClient.DropMulticastGroup(null));
655                 AssertExtensions.Throws<ArgumentNullException>("multicastAddr", () => udpClient.DropMulticastGroup(null, 0));
656                 AssertExtensions.Throws<ArgumentException>("multicastAddr", () => udpClient.DropMulticastGroup(IPAddress.IPv6Loopback));
657                 AssertExtensions.Throws<ArgumentException>("ifindex", () => udpClient.DropMulticastGroup(IPAddress.Loopback, -1));
658             }
659         }
660 
661         [Fact]
UdpReceiveResult_InvalidArguments_Throws()662         public void UdpReceiveResult_InvalidArguments_Throws()
663         {
664             AssertExtensions.Throws<ArgumentNullException>("buffer", () => new UdpReceiveResult(null, null));
665             AssertExtensions.Throws<ArgumentNullException>("remoteEndPoint", () => new UdpReceiveResult(new byte[1], null));
666         }
667 
668         [Fact]
UdpReceiveResult_Equality()669         public void UdpReceiveResult_Equality()
670         {
671             byte[] buffer1 = new byte[1] { 42 }, buffer2 = new byte[1] { 42 };
672             IPEndPoint ep1 = new IPEndPoint(IPAddress.Loopback, 123), ep2 = new IPEndPoint(IPAddress.Loopback, 123), ep3 = new IPEndPoint(IPAddress.Any, 456);
673 
674             Assert.Equal(new UdpReceiveResult().GetHashCode(), new UdpReceiveResult().GetHashCode());
675             Assert.Equal(new UdpReceiveResult(buffer1, ep1).GetHashCode(), new UdpReceiveResult(buffer1, ep2).GetHashCode());
676 
677             Assert.True(new UdpReceiveResult(buffer1, ep1).Equals(new UdpReceiveResult(buffer1, ep2)));
678             Assert.False(new UdpReceiveResult(buffer1, ep1).Equals(new UdpReceiveResult(buffer2, ep1)));
679             Assert.False(new UdpReceiveResult(buffer1, ep1).Equals(new UdpReceiveResult(buffer1, ep3)));
680 
681             Assert.True(new UdpReceiveResult(buffer1, ep1).Equals((object)new UdpReceiveResult(buffer1, ep2)));
682             Assert.False(new UdpReceiveResult(buffer1, ep1).Equals((object)new UdpReceiveResult(buffer2, ep1)));
683             Assert.False(new UdpReceiveResult(buffer1, ep1).Equals((object)new UdpReceiveResult(buffer1, ep3)));
684             Assert.False(new UdpReceiveResult(buffer1, ep1).Equals(new object()));
685 
686             Assert.True(new UdpReceiveResult(buffer1, ep1) == new UdpReceiveResult(buffer1, ep2));
687             Assert.True(new UdpReceiveResult(buffer1, ep1) != new UdpReceiveResult(buffer2, ep1));
688             Assert.True(new UdpReceiveResult(buffer1, ep1) != new UdpReceiveResult(buffer1, ep3));
689         }
690 
691         private sealed class DerivedUdpClient : UdpClient
692         {
DerivedUdpClient()693             public DerivedUdpClient() { }
DerivedUdpClient(string hostname, int port)694             public DerivedUdpClient(string hostname, int port) : base(hostname, port) { }
~DerivedUdpClient()695             ~DerivedUdpClient() { Dispose(false); }
696 
697             public new bool Active
698             {
699                 get { return base.Active; }
700                 set { base.Active = value; }
701             }
702         }
703     }
704 }
705