diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveMessageFrom.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveMessageFrom.cs index c4866b8ae78905..6bc70e67a7fa87 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveMessageFrom.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveMessageFrom.cs @@ -3,135 +3,81 @@ using System.Collections.Generic; using System.Threading; +using System.Threading.Tasks; using Xunit; +using Xunit.Abstractions; namespace System.Net.Sockets.Tests { - public class ReceiveMessageFrom + public abstract class ReceiveMessageFrom : SocketTestHelperBase where T : SocketHelperBase, new() { - [OuterLoop] - [Theory] - [InlineData(false)] - [InlineData(true)] - public void Success(bool forceNonBlocking) - { - if (Socket.OSSupportsIPv4) - { - using (Socket receiver = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)) - { - int port = receiver.BindToAnonymousPort(IPAddress.Loopback); - receiver.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.PacketInformation, true); - - receiver.ForceNonBlocking(forceNonBlocking); - - Socket sender = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - sender.Bind(new IPEndPoint(IPAddress.Loopback, 0)); - - sender.ForceNonBlocking(forceNonBlocking); - - sender.SendTo(new byte[1024], new IPEndPoint(IPAddress.Loopback, port)); + protected ReceiveMessageFrom(ITestOutputHelper output) : base(output) { } - IPPacketInformation packetInformation; - SocketFlags flags = SocketFlags.None; - EndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0); - - int len = receiver.ReceiveMessageFrom(new byte[1024], 0, 1024, ref flags, ref remoteEP, out packetInformation); - - Assert.Equal(1024, len); - Assert.Equal(sender.LocalEndPoint, remoteEP); - Assert.Equal(((IPEndPoint)sender.LocalEndPoint).Address, packetInformation.Address); - - sender.Dispose(); - } - } - } - - [OuterLoop] [Theory] [InlineData(false)] [InlineData(true)] - public void Success_IPv6(bool forceNonBlocking) + public async Task ReceiveSentMessages_Success(bool ipv4) { - if (Socket.OSSupportsIPv6) - { - using (Socket receiver = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp)) - { - int port = receiver.BindToAnonymousPort(IPAddress.IPv6Loopback); - receiver.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.PacketInformation, true); + const int DatagramSize = 256; + const int DatagramsToSend = 16; - receiver.ForceNonBlocking(forceNonBlocking); + IPAddress address = ipv4 ? IPAddress.Loopback : IPAddress.IPv6Loopback; + using Socket receiver = new Socket(address.AddressFamily, SocketType.Dgram, ProtocolType.Udp); + using Socket sender = new Socket(address.AddressFamily, SocketType.Dgram, ProtocolType.Udp); - Socket sender = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp); - sender.Bind(new IPEndPoint(IPAddress.IPv6Loopback, 0)); + receiver.SetSocketOption(ipv4 ? SocketOptionLevel.IP : SocketOptionLevel.IPv6, SocketOptionName.PacketInformation, true); + ConfigureNonBlocking(sender); + ConfigureNonBlocking(receiver); - sender.ForceNonBlocking(forceNonBlocking); + receiver.BindToAnonymousPort(address); + sender.BindToAnonymousPort(address); - sender.SendTo(new byte[1024], new IPEndPoint(IPAddress.IPv6Loopback, port)); + byte[] sendBuffer = new byte[DatagramSize]; + byte[] receiveBuffer = new byte[DatagramSize]; + Random rnd = new Random(0); - IPPacketInformation packetInformation; - SocketFlags flags = SocketFlags.None; - EndPoint remoteEP = new IPEndPoint(IPAddress.IPv6Any, 0); + IPEndPoint remoteEp = new IPEndPoint(ipv4 ? IPAddress.Any : IPAddress.IPv6Any, 0); - int len = receiver.ReceiveMessageFrom(new byte[1024], 0, 1024, ref flags, ref remoteEP, out packetInformation); + for (int i = 0; i < DatagramsToSend; i++) + { + rnd.NextBytes(sendBuffer); + sender.SendTo(sendBuffer, receiver.LocalEndPoint); - Assert.Equal(1024, len); - Assert.Equal(sender.LocalEndPoint, remoteEP); - Assert.Equal(((IPEndPoint)sender.LocalEndPoint).Address, packetInformation.Address); + SocketReceiveMessageFromResult result = await ReceiveMessageFromAsync(receiver, receiveBuffer, remoteEp); + IPPacketInformation packetInformation = result.PacketInformation; - sender.Dispose(); - } + Assert.Equal(DatagramSize, result.ReceivedBytes); + AssertExtensions.SequenceEqual(sendBuffer, receiveBuffer); + Assert.Equal(sender.LocalEndPoint, result.RemoteEndPoint); + Assert.Equal(((IPEndPoint)sender.LocalEndPoint).Address, packetInformation.Address); } } + } - [OuterLoop] - [Theory] - [InlineData(false)] - [InlineData(true)] - public void Success_APM(bool ipv4) - { - AddressFamily family; - IPAddress loopback, any; - SocketOptionLevel level; - if (ipv4) - { - if (!Socket.OSSupportsIPv4) return; - family = AddressFamily.InterNetwork; - loopback = IPAddress.Loopback; - any = IPAddress.Any; - level = SocketOptionLevel.IP; - } - else - { - if (!Socket.OSSupportsIPv6) return; - family = AddressFamily.InterNetworkV6; - loopback = IPAddress.IPv6Loopback; - any = IPAddress.IPv6Any; - level = SocketOptionLevel.IPv6; - } - - using (var receiver = new Socket(family, SocketType.Dgram, ProtocolType.Udp)) - using (var sender = new Socket(family, SocketType.Dgram, ProtocolType.Udp)) - { - int port = receiver.BindToAnonymousPort(loopback); - receiver.SetSocketOption(level, SocketOptionName.PacketInformation, true); - sender.Bind(new IPEndPoint(loopback, 0)); + public sealed class ReceiveMessageFrom_Sync : ReceiveMessageFrom + { + public ReceiveMessageFrom_Sync(ITestOutputHelper output) : base(output) { } + } - sender.SendTo(new byte[1024], new IPEndPoint(loopback, port)); + public sealed class ReceiveMessageFrom_SyncForceNonBlocking : ReceiveMessageFrom + { + public ReceiveMessageFrom_SyncForceNonBlocking(ITestOutputHelper output) : base(output) { } + } - IPPacketInformation packetInformation; - SocketFlags flags = SocketFlags.None; - EndPoint remoteEP = new IPEndPoint(any, 0); + public sealed class ReceiveMessageFrom_Apm : ReceiveMessageFrom + { + public ReceiveMessageFrom_Apm(ITestOutputHelper output) : base(output) { } + } - IAsyncResult ar = receiver.BeginReceiveMessageFrom(new byte[1024], 0, 1024, flags, ref remoteEP, null, null); - int len = receiver.EndReceiveMessageFrom(ar, ref flags, ref remoteEP, out packetInformation); + public sealed class ReceiveMessageFrom_Task : ReceiveMessageFrom + { + public ReceiveMessageFrom_Task(ITestOutputHelper output) : base(output) { } + } - Assert.Equal(1024, len); - Assert.Equal(sender.LocalEndPoint, remoteEP); - Assert.Equal(((IPEndPoint)sender.LocalEndPoint).Address, packetInformation.Address); - } - } + public sealed class ReceiveMessageFrom_Eap : ReceiveMessageFrom + { + public ReceiveMessageFrom_Eap(ITestOutputHelper output) : base(output) { } - [OuterLoop] [Theory] [InlineData(false, 0)] [InlineData(false, 1)] @@ -139,14 +85,16 @@ public void Success_APM(bool ipv4) [InlineData(true, 0)] [InlineData(true, 1)] [InlineData(true, 2)] - public void Success_EventArgs(bool ipv4, int bufferMode) + public void ReceiveSentMessages_ReuseEventArgs_Success(bool ipv4, int bufferMode) { + const int DatagramsToSend = 30; + const int TimeoutMs = 30_000; + AddressFamily family; IPAddress loopback, any; SocketOptionLevel level; if (ipv4) { - if (!Socket.OSSupportsIPv4) return; family = AddressFamily.InterNetwork; loopback = IPAddress.Loopback; any = IPAddress.Any; @@ -154,22 +102,25 @@ public void Success_EventArgs(bool ipv4, int bufferMode) } else { - if (!Socket.OSSupportsIPv6) return; family = AddressFamily.InterNetworkV6; loopback = IPAddress.IPv6Loopback; any = IPAddress.IPv6Any; level = SocketOptionLevel.IPv6; } - using (var receiver = new Socket(family, SocketType.Dgram, ProtocolType.Udp)) - using (var sender = new Socket(family, SocketType.Dgram, ProtocolType.Udp)) - using (var saea = new SocketAsyncEventArgs()) - { - int port = receiver.BindToAnonymousPort(loopback); - receiver.SetSocketOption(level, SocketOptionName.PacketInformation, true); - sender.Bind(new IPEndPoint(loopback, 0)); + using var receiver = new Socket(family, SocketType.Dgram, ProtocolType.Udp); + using var sender = new Socket(family, SocketType.Dgram, ProtocolType.Udp); + using var saea = new SocketAsyncEventArgs(); + var completed = new ManualResetEventSlim(); + saea.Completed += delegate { completed.Set(); }; - saea.RemoteEndPoint = new IPEndPoint(any, 0); + int port = receiver.BindToAnonymousPort(loopback); + receiver.SetSocketOption(level, SocketOptionName.PacketInformation, true); + sender.Bind(new IPEndPoint(loopback, 0)); + saea.RemoteEndPoint = new IPEndPoint(any, 0); + + for (int i = 0; i < DatagramsToSend; i++) + { switch (bufferMode) { case 0: // single buffer @@ -190,17 +141,35 @@ public void Success_EventArgs(bool ipv4, int bufferMode) break; } - var mres = new ManualResetEventSlim(); - saea.Completed += delegate { mres.Set(); }; - bool pending = receiver.ReceiveMessageFromAsync(saea); sender.SendTo(new byte[1024], new IPEndPoint(loopback, port)); - if (pending) Assert.True(mres.Wait(30000), "Expected operation to complete within timeout"); + if (pending) Assert.True(completed.Wait(TimeoutMs), "Expected operation to complete within timeout"); + completed.Reset(); Assert.Equal(1024, saea.BytesTransferred); Assert.Equal(sender.LocalEndPoint, saea.RemoteEndPoint); Assert.Equal(((IPEndPoint)sender.LocalEndPoint).Address, saea.ReceiveMessageFromPacketInfo.Address); - } + } } } + + public sealed class ReceiveMessageFrom_SpanSync : ReceiveMessageFrom + { + public ReceiveMessageFrom_SpanSync(ITestOutputHelper output) : base(output) { } + } + + public sealed class ReceiveMessageFrom_SpanSyncForceNonBlocking : ReceiveMessageFrom + { + public ReceiveMessageFrom_SpanSyncForceNonBlocking(ITestOutputHelper output) : base(output) { } + } + + public sealed class ReceiveMessageFrom_MemoryArrayTask : ReceiveMessageFrom + { + public ReceiveMessageFrom_MemoryArrayTask(ITestOutputHelper output) : base(output) { } + } + + public sealed class ReceiveMessageFrom_MemoryNativeTask : ReceiveMessageFrom + { + public ReceiveMessageFrom_MemoryNativeTask(ITestOutputHelper output) : base(output) { } + } } diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveMessageFromAsync.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveMessageFromAsync.cs deleted file mode 100644 index d0e7131a920726..00000000000000 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveMessageFromAsync.cs +++ /dev/null @@ -1,90 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Threading; -using System.Threading.Tasks; -using Xunit; - -namespace System.Net.Sockets.Tests -{ - public class ReceiveMessageFromAsync - { - [OuterLoop] - [Theory] - [InlineData(false, false)] - [InlineData(false, true)] - [InlineData(true, false)] - [InlineData(true, true)] - public void ReceiveSentMessages_SocketAsyncEventArgs_Success(bool ipv4, bool changeReceiveBufferEachCall) - { - const int DataLength = 1024; - AddressFamily family = ipv4 ? AddressFamily.InterNetwork : AddressFamily.InterNetworkV6; - IPAddress loopback = ipv4 ? IPAddress.Loopback : IPAddress.IPv6Loopback; - - var completed = new ManualResetEventSlim(false); - using (var sender = new Socket(family, SocketType.Dgram, ProtocolType.Udp)) - using (var receiver = new Socket(family, SocketType.Dgram, ProtocolType.Udp)) - { - sender.Bind(new IPEndPoint(loopback, 0)); - receiver.SetSocketOption(ipv4 ? SocketOptionLevel.IP : SocketOptionLevel.IPv6, SocketOptionName.PacketInformation, true); - int port = receiver.BindToAnonymousPort(loopback); - - var args = new SocketAsyncEventArgs() { RemoteEndPoint = new IPEndPoint(ipv4 ? IPAddress.Any : IPAddress.IPv6Any, 0) }; - args.Completed += (s,e) => completed.Set(); - args.SetBuffer(new byte[DataLength], 0, DataLength); - - for (int iters = 0; iters < 5; iters++) - { - sender.SendTo(new byte[DataLength], new IPEndPoint(loopback, port)); - - if (changeReceiveBufferEachCall) - { - args.SetBuffer(new byte[DataLength], 0, DataLength); - } - - if (!receiver.ReceiveMessageFromAsync(args)) - { - completed.Set(); - } - Assert.True(completed.Wait(TestSettings.PassingTestTimeout), "Timeout while waiting for connection"); - completed.Reset(); - - Assert.Equal(DataLength, args.BytesTransferred); - Assert.Equal(sender.LocalEndPoint, args.RemoteEndPoint); - Assert.Equal(((IPEndPoint)sender.LocalEndPoint).Address, args.ReceiveMessageFromPacketInfo.Address); - } - } - } - - [OuterLoop] - [Theory] - [InlineData(false)] - [InlineData(true)] - public async Task ReceiveSentMessages_Tasks_Success(bool ipv4) - { - const int DataLength = 1024; - AddressFamily family = ipv4 ? AddressFamily.InterNetwork : AddressFamily.InterNetworkV6; - IPAddress loopback = ipv4 ? IPAddress.Loopback : IPAddress.IPv6Loopback; - - using (var receiver = new Socket(family, SocketType.Dgram, ProtocolType.Udp)) - using (var sender = new Socket(family, SocketType.Dgram, ProtocolType.Udp)) - { - sender.Bind(new IPEndPoint(loopback, 0)); - receiver.SetSocketOption(ipv4 ? SocketOptionLevel.IP : SocketOptionLevel.IPv6, SocketOptionName.PacketInformation, true); - int port = receiver.BindToAnonymousPort(loopback); - - for (int iters = 0; iters < 5; iters++) - { - sender.SendTo(new byte[DataLength], new IPEndPoint(loopback, port)); - - SocketReceiveMessageFromResult result = await receiver.ReceiveMessageFromAsync( - new ArraySegment(new byte[DataLength], 0, DataLength), SocketFlags.None, - new IPEndPoint(ipv4 ? IPAddress.Any : IPAddress.IPv6Any, 0)); - Assert.Equal(DataLength, result.ReceivedBytes); - Assert.Equal(sender.LocalEndPoint, result.RemoteEndPoint); - Assert.Equal(((IPEndPoint)sender.LocalEndPoint).Address, result.PacketInformation.Address); - } - } - } - } -} diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketTestHelper.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketTestHelper.cs index b6ff51778cc528..93e050059ca719 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketTestHelper.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketTestHelper.cs @@ -27,6 +27,8 @@ public abstract class SocketHelperBase public abstract Task ReceiveAsync(Socket s, ArraySegment buffer); public abstract Task ReceiveFromAsync( Socket s, ArraySegment buffer, EndPoint endPoint); + public abstract Task ReceiveMessageFromAsync( + Socket s, ArraySegment buffer, EndPoint endPoint); public abstract Task ReceiveAsync(Socket s, IList> bufferList); public abstract Task SendAsync(Socket s, ArraySegment buffer); public abstract Task SendAsync(Socket s, IList> bufferList); @@ -68,6 +70,20 @@ public override Task ReceiveFromAsync(Socket s, ArraySe RemoteEndPoint = endPoint }; }); + public override Task ReceiveMessageFromAsync(Socket s, ArraySegment buffer, EndPoint endPoint) => + Task.Run(() => + { + SocketFlags socketFlags = SocketFlags.None; + IPPacketInformation ipPacketInformation; + int received = s.ReceiveMessageFrom(buffer.Array, buffer.Offset, buffer.Count, ref socketFlags, ref endPoint, out ipPacketInformation); + return new SocketReceiveMessageFromResult + { + ReceivedBytes = received, + SocketFlags = socketFlags, + RemoteEndPoint = endPoint, + PacketInformation = ipPacketInformation + }; + }); public override Task SendAsync(Socket s, ArraySegment buffer) => Task.Run(() => s.Send(buffer.Array, buffer.Offset, buffer.Count, SocketFlags.None)); public override Task SendAsync(Socket s, IList> bufferList) => @@ -142,6 +158,29 @@ public override Task ReceiveFromAsync(Socket s, ArraySe }, null); return tcs.Task; } + public override Task ReceiveMessageFromAsync(Socket s, ArraySegment buffer, EndPoint endPoint) + { + var tcs = new TaskCompletionSource(); + SocketFlags socketFlags = SocketFlags.None; + s.BeginReceiveMessageFrom(buffer.Array, buffer.Offset, buffer.Count, socketFlags, ref endPoint, iar => + { + try + { + int receivedBytes = s.EndReceiveMessageFrom(iar, ref socketFlags, ref endPoint, out IPPacketInformation ipPacketInformation); + var result = new SocketReceiveMessageFromResult + { + ReceivedBytes = receivedBytes, + SocketFlags = socketFlags, + RemoteEndPoint = endPoint, + PacketInformation = ipPacketInformation + }; + tcs.TrySetResult(result); + } + catch (Exception e) { tcs.TrySetException(e); } + + }, null); + return tcs.Task; + } public override Task SendAsync(Socket s, ArraySegment buffer) => Task.Factory.FromAsync((callback, state) => s.BeginSend(buffer.Array, buffer.Offset, buffer.Count, SocketFlags.None, callback, state), @@ -174,6 +213,8 @@ public override Task ReceiveAsync(Socket s, IList> buffe s.ReceiveAsync(bufferList, SocketFlags.None); public override Task ReceiveFromAsync(Socket s, ArraySegment buffer, EndPoint endPoint) => s.ReceiveFromAsync(buffer, SocketFlags.None, endPoint); + public override Task ReceiveMessageFromAsync(Socket s, ArraySegment buffer, EndPoint endPoint) => + s.ReceiveMessageFromAsync(buffer, SocketFlags.None, endPoint); public override Task SendAsync(Socket s, ArraySegment buffer) => s.SendAsync(buffer, SocketFlags.None); public override Task SendAsync(Socket s, IList> bufferList) => @@ -204,6 +245,8 @@ public override Task ReceiveAsync(Socket s, IList> buffe s.ReceiveAsync(bufferList, SocketFlags.None); public override Task ReceiveFromAsync(Socket s, ArraySegment buffer, EndPoint endPoint) => s.ReceiveFromAsync(buffer, SocketFlags.None, endPoint); + public override Task ReceiveMessageFromAsync(Socket s, ArraySegment buffer, EndPoint endPoint) => + s.ReceiveMessageFromAsync(buffer, SocketFlags.None, endPoint); public override Task SendAsync(Socket s, ArraySegment buffer) => s.SendAsync(buffer, SocketFlags.None, _cts.Token).AsTask(); public override Task SendAsync(Socket s, IList> bufferList) => @@ -265,6 +308,21 @@ public override Task ReceiveFromAsync(Socket s, ArraySe e.RemoteEndPoint = endPoint; return s.ReceiveFromAsync(e); }); + public override Task ReceiveMessageFromAsync(Socket s, ArraySegment buffer, EndPoint endPoint) => + InvokeAsync(s, + e => new SocketReceiveMessageFromResult + { + ReceivedBytes = e.BytesTransferred, + RemoteEndPoint = e.RemoteEndPoint, + SocketFlags = e.SocketFlags, + PacketInformation = e.ReceiveMessageFromPacketInfo + }, + e => + { + e.SetBuffer(buffer.Array, buffer.Offset, buffer.Count); + e.RemoteEndPoint = endPoint; + return s.ReceiveMessageFromAsync(e); + }); public override Task SendAsync(Socket s, ArraySegment buffer) => InvokeAsync(s, e => e.BytesTransferred, e => { @@ -331,8 +389,10 @@ public SocketTestHelperBase(ITestOutputHelper output) public Task ConnectAsync(Socket s, EndPoint endPoint) => _socketHelper.ConnectAsync(s, endPoint); public Task MultiConnectAsync(Socket s, IPAddress[] addresses, int port) => _socketHelper.MultiConnectAsync(s, addresses, port); public Task ReceiveAsync(Socket s, ArraySegment buffer) => _socketHelper.ReceiveAsync(s, buffer); - public Task ReceiveFromAsync( - Socket s, ArraySegment buffer, EndPoint endPoint) => _socketHelper.ReceiveFromAsync(s, buffer, endPoint); + public Task ReceiveFromAsync(Socket s, ArraySegment buffer, EndPoint endPoint) => + _socketHelper.ReceiveFromAsync(s, buffer, endPoint); + public Task ReceiveMessageFromAsync(Socket s, ArraySegment buffer, EndPoint endPoint) => + _socketHelper.ReceiveMessageFromAsync(s, buffer, endPoint); public Task ReceiveAsync(Socket s, IList> bufferList) => _socketHelper.ReceiveAsync(s, bufferList); public Task SendAsync(Socket s, ArraySegment buffer) => _socketHelper.SendAsync(s, buffer); public Task SendAsync(Socket s, IList> bufferList) => _socketHelper.SendAsync(s, bufferList); @@ -391,6 +451,7 @@ public override async Task ReceiveAsync(Socket s, ArraySegment buffer return bytesReceived; } } + public override async Task SendAsync(Socket s, ArraySegment buffer) { using (var m = new NativeMemoryManager(buffer.Count)) diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj b/src/libraries/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj index a7e0c5f6aa90df..7ce628db90aae5 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj @@ -1,4 +1,4 @@ - + true true @@ -27,7 +27,6 @@ -