Skip to content
Open
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 39 additions & 11 deletions src/libraries/System.Net.Sockets/tests/FunctionalTests/SendTo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ namespace System.Net.Sockets.Tests
protected static IPEndPoint GetGetDummyTestEndpoint(AddressFamily addressFamily = AddressFamily.InterNetwork) =>
addressFamily == AddressFamily.InterNetwork ? new IPEndPoint(IPAddress.Parse("1.2.3.4"), 1234) : new IPEndPoint(IPAddress.Parse("1:2:3::4"), 1234);

private static (IPEndPoint endpoint, Socket receiver) CreateLoopbackUdpEndpoint(AddressFamily family)
{
IPAddress loopback = family == AddressFamily.InterNetwork ? IPAddress.Loopback : IPAddress.IPv6Loopback;
Socket receiver = new Socket(family, SocketType.Dgram, ProtocolType.Udp);
receiver.Bind(new IPEndPoint(loopback, 0)); // ephemeral port on loopback
return ((IPEndPoint)receiver.LocalEndPoint!, receiver);
}

protected SendTo(ITestOutputHelper output) : base(output)
{
}
Expand Down Expand Up @@ -78,20 +86,28 @@ public async Task NullSocketAddress_Throws_ArgumentException()
public async Task Datagram_UDP_ShouldImplicitlyBindLocalEndpoint()
{
using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
byte[] buffer = new byte[32];
var (remote, receiver) = CreateLoopbackUdpEndpoint(socket.AddressFamily);
using (receiver)
{
byte[] buffer = new byte[32];

Task sendTask = SendToAsync(socket, new ArraySegment<byte>(buffer), GetGetDummyTestEndpoint());
Task sendTask = SendToAsync(socket, new ArraySegment<byte>(buffer), remote);

// Asynchronous calls shall alter the property immediately:
if (!UsesSync)
{
Assert.NotNull(socket.LocalEndPoint);
}
// Asynchronous calls shall alter the property immediately:
if (!UsesSync)
{
Assert.NotNull(socket.LocalEndPoint);
}

await sendTask;
await sendTask;

// In synchronous calls, we should wait for the completion of the helper task:
Assert.NotNull(socket.LocalEndPoint);
// In synchronous calls, we should wait for the completion of the helper task:
EndPoint? local = socket.LocalEndPoint;
Assert.NotNull(local);
var localIp = (IPEndPoint)local!;
Assert.NotEqual(0, localIp.Port);
Assert.True(IPAddress.IsLoopback(localIp.Address), "Implicit bind should select loopback when sending to loopback.");
}
}

[ConditionalFact]
Expand All @@ -109,7 +125,19 @@ public async Task Datagram_UDP_AccessDenied_Throws_DoesNotBind()
throw new SkipTestException("HostUnreachable indicates missing local network permission; this test might pass or fail depending on the environment. Please verify manually.");
}

Assert.Equal(SocketError.AccessDenied, e.SocketErrorCode);
// On some mobile/restricted queues the send can fail earlier with unreachable
// rather than AccessDenied (see #120526, #114450).
if (OperatingSystem.IsAndroid() || OperatingSystem.IsMacCatalyst() || OperatingSystem.IsIOS() || OperatingSystem.IsTvOS())
{
Assert.True(
e.SocketErrorCode is SocketError.AccessDenied or SocketError.NetworkUnreachable or SocketError.HostUnreachable,
$"Unexpected error: {e.SocketErrorCode}");
}
else
{
Assert.Equal(SocketError.AccessDenied, e.SocketErrorCode);
}

Assert.Null(socket.LocalEndPoint);
}

Expand Down
Loading