You've already forked linux-packaging-mono
Imported Upstream version 5.16.0.100
Former-commit-id: 38faa55fb9669e35e7d8448b15c25dc447f25767
This commit is contained in:
parent
0a9828183b
commit
7d7f676260
@@ -276,6 +276,30 @@ namespace System.Net.Sockets.Tests
|
||||
Assert.Throws<InvalidOperationException>(() => { AcceptAsync(listener, server); });
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AcceptAsync_MultipleAcceptsThenDispose_AcceptsThrowAfterDispose()
|
||||
{
|
||||
if (UsesSync)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
using (var listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
{
|
||||
listener.Bind(new IPEndPoint(IPAddress.Loopback, 0));
|
||||
listener.Listen(2);
|
||||
|
||||
Task accept1 = AcceptAsync(listener);
|
||||
Task accept2 = AcceptAsync(listener);
|
||||
listener.Dispose();
|
||||
await Assert.ThrowsAnyAsync<Exception>(() => accept1);
|
||||
await Assert.ThrowsAnyAsync<Exception>(() => accept2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class AcceptSync : Accept<SocketHelperArraySync> { }
|
||||
|
@@ -44,9 +44,7 @@ namespace System.Net.Sockets.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[OuterLoop] // TODO: Issue #11345
|
||||
[Fact]
|
||||
[ActiveIssue(22765, TestPlatforms.AnyUnix)]
|
||||
public async Task Connect_OnConnectedSocket_Fails()
|
||||
{
|
||||
int port;
|
||||
|
501
external/corefx/src/System.Net.Sockets/tests/FunctionalTests/ExecutionContextFlowTest.cs
vendored
Normal file
501
external/corefx/src/System.Net.Sockets/tests/FunctionalTests/ExecutionContextFlowTest.cs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,89 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace System.Net.Sockets.Tests
|
||||
{
|
||||
public partial class ExecutionContextFlowTest : FileCleanupTestBase
|
||||
{
|
||||
[Fact]
|
||||
public Task ExecutionContext_FlowsOnlyOnceAcrossAsyncOperations()
|
||||
{
|
||||
return Task.Run(async () => // escape xunit's sync ctx
|
||||
{
|
||||
using (var listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
using (var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
{
|
||||
listener.Bind(new IPEndPoint(IPAddress.Loopback, 0));
|
||||
listener.Listen(1);
|
||||
|
||||
client.Connect(listener.LocalEndPoint);
|
||||
using (Socket server = listener.Accept())
|
||||
{
|
||||
var stackLog = new StringBuilder();
|
||||
int executionContextChanges = 0;
|
||||
var asyncLocal = new AsyncLocal<int>(_ =>
|
||||
{
|
||||
executionContextChanges++;
|
||||
stackLog.AppendLine($"#{executionContextChanges}: {Environment.StackTrace}");
|
||||
});
|
||||
Assert.Equal(0, executionContextChanges);
|
||||
|
||||
int numAwaits = 20;
|
||||
for (int i = 1; i <= numAwaits; i++)
|
||||
{
|
||||
asyncLocal.Value = i;
|
||||
|
||||
await new AwaitWithOnCompletedInvocation<int>(
|
||||
client.ReceiveAsync(new Memory<byte>(new byte[1]), SocketFlags.None),
|
||||
() => server.Send(new byte[1]));
|
||||
|
||||
Assert.Equal(i, asyncLocal.Value);
|
||||
}
|
||||
|
||||
// This doesn't count EC changes where EC.Run is passed the same context
|
||||
// as is current, but it's the best we can track via public API.
|
||||
try
|
||||
{
|
||||
Assert.InRange(executionContextChanges, 1, numAwaits * 3); // at most: 1 / AsyncLocal change + 1 / suspend + 1 / resume
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new Exception($"{nameof(executionContextChanges)} == {executionContextChanges} with log: {stackLog.ToString()}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private readonly struct AwaitWithOnCompletedInvocation<T> : ICriticalNotifyCompletion
|
||||
{
|
||||
private readonly ValueTask<T> _valueTask;
|
||||
private readonly Action _invokeAfterOnCompleted;
|
||||
|
||||
public AwaitWithOnCompletedInvocation(ValueTask<T> valueTask, Action invokeAfterOnCompleted)
|
||||
{
|
||||
_valueTask = valueTask;
|
||||
_invokeAfterOnCompleted = invokeAfterOnCompleted;
|
||||
}
|
||||
|
||||
public AwaitWithOnCompletedInvocation<T> GetAwaiter() => this;
|
||||
|
||||
public bool IsCompleted => false;
|
||||
public T GetResult() => _valueTask.GetAwaiter().GetResult();
|
||||
public void OnCompleted(Action continuation) => throw new NotSupportedException();
|
||||
public void UnsafeOnCompleted(Action continuation)
|
||||
{
|
||||
_valueTask.GetAwaiter().UnsafeOnCompleted(continuation);
|
||||
_invokeAfterOnCompleted();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -454,6 +454,21 @@ namespace System.Net.Sockets.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReadWrite_Byte_Success()
|
||||
{
|
||||
await RunWithConnectedNetworkStreamsAsync(async (server, client) =>
|
||||
{
|
||||
for (byte i = 0; i < 10; i++)
|
||||
{
|
||||
Task<int> read = Task.Run(() => client.ReadByte());
|
||||
Task write = Task.Run(() => server.WriteByte(i));
|
||||
await Task.WhenAll(read, write);
|
||||
Assert.Equal(i, await read);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReadWrite_Array_Success()
|
||||
{
|
||||
|
@@ -2,6 +2,9 @@
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
@@ -43,17 +46,333 @@ namespace System.Net.Sockets.Tests
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReadWrite_Memory_LargeWrite_Success()
|
||||
{
|
||||
await RunWithConnectedNetworkStreamsAsync(async (server, client) =>
|
||||
{
|
||||
var writeBuffer = new byte[10 * 1024 * 1024];
|
||||
var readBuffer = new byte[writeBuffer.Length];
|
||||
RandomNumberGenerator.Fill(writeBuffer);
|
||||
|
||||
ValueTask writeTask = client.WriteAsync((ReadOnlyMemory<byte>)writeBuffer);
|
||||
|
||||
int totalRead = 0;
|
||||
while (totalRead < readBuffer.Length)
|
||||
{
|
||||
int bytesRead = await server.ReadAsync(new Memory<byte>(readBuffer).Slice(totalRead));
|
||||
Assert.InRange(bytesRead, 0, int.MaxValue);
|
||||
if (bytesRead == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
totalRead += bytesRead;
|
||||
}
|
||||
Assert.Equal(readBuffer.Length, totalRead);
|
||||
Assert.Equal<byte>(writeBuffer, readBuffer);
|
||||
|
||||
await writeTask;
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReadWrite_Precanceled_Throws()
|
||||
{
|
||||
await RunWithConnectedNetworkStreamsAsync(async (server, client) =>
|
||||
{
|
||||
await Assert.ThrowsAnyAsync<OperationCanceledException>(() => server.WriteAsync((ArraySegment<byte>)new byte[0], new CancellationToken(true)));
|
||||
await Assert.ThrowsAnyAsync<OperationCanceledException>(() => server.ReadAsync((ArraySegment<byte>)new byte[0], new CancellationToken(true)).AsTask());
|
||||
await Assert.ThrowsAnyAsync<OperationCanceledException>(async () => await server.WriteAsync((ArraySegment<byte>)new byte[0], new CancellationToken(true)));
|
||||
await Assert.ThrowsAnyAsync<OperationCanceledException>(async () => await server.ReadAsync((ArraySegment<byte>)new byte[0], new CancellationToken(true)));
|
||||
|
||||
await Assert.ThrowsAnyAsync<OperationCanceledException>(() => server.WriteAsync((ReadOnlyMemory<byte>)new byte[0], new CancellationToken(true)));
|
||||
await Assert.ThrowsAnyAsync<OperationCanceledException>(() => server.ReadAsync((Memory<byte>)new byte[0], new CancellationToken(true)).AsTask());
|
||||
await Assert.ThrowsAnyAsync<OperationCanceledException>(async () => await server.WriteAsync((ReadOnlyMemory<byte>)new byte[0], new CancellationToken(true)));
|
||||
await Assert.ThrowsAnyAsync<OperationCanceledException>(async () => await server.ReadAsync((Memory<byte>)new byte[0], new CancellationToken(true)));
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReadAsync_AwaitMultipleTimes_Throws()
|
||||
{
|
||||
await RunWithConnectedNetworkStreamsAsync(async (server, client) =>
|
||||
{
|
||||
var b = new byte[1];
|
||||
ValueTask<int> r = server.ReadAsync(b);
|
||||
await client.WriteAsync(new byte[] { 42 });
|
||||
Assert.Equal(1, await r);
|
||||
Assert.Equal(42, b[0]);
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(async () => await r);
|
||||
Assert.Throws<InvalidOperationException>(() => r.GetAwaiter().IsCompleted);
|
||||
Assert.Throws<InvalidOperationException>(() => r.GetAwaiter().OnCompleted(() => { }));
|
||||
Assert.Throws<InvalidOperationException>(() => r.GetAwaiter().GetResult());
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReadAsync_MultipleContinuations_Throws()
|
||||
{
|
||||
await RunWithConnectedNetworkStreamsAsync((server, client) =>
|
||||
{
|
||||
var b = new byte[1];
|
||||
ValueTask<int> r = server.ReadAsync(b);
|
||||
r.GetAwaiter().OnCompleted(() => { });
|
||||
Assert.Throws<InvalidOperationException>(() => r.GetAwaiter().OnCompleted(() => { }));
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReadAsync_MultipleConcurrentValueTaskReads_Success()
|
||||
{
|
||||
await RunWithConnectedNetworkStreamsAsync(async (server, client) =>
|
||||
{
|
||||
// Technically this isn't supported behavior, but it happens to work because it's supported on socket.
|
||||
// So validate it to alert us to any potential future breaks.
|
||||
|
||||
byte[] b1 = new byte[1], b2 = new byte[1], b3 = new byte[1];
|
||||
ValueTask<int> r1 = server.ReadAsync(b1);
|
||||
ValueTask<int> r2 = server.ReadAsync(b2);
|
||||
ValueTask<int> r3 = server.ReadAsync(b3);
|
||||
|
||||
await client.WriteAsync(new byte[] { 42, 43, 44 });
|
||||
|
||||
Assert.Equal(3, await r1 + await r2 + await r3);
|
||||
Assert.Equal(42 + 43 + 44, b1[0] + b2[0] + b3[0]);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReadAsync_MultipleConcurrentValueTaskReads_AsTask_Success()
|
||||
{
|
||||
await RunWithConnectedNetworkStreamsAsync(async (server, client) =>
|
||||
{
|
||||
// Technically this isn't supported behavior, but it happens to work because it's supported on socket.
|
||||
// So validate it to alert us to any potential future breaks.
|
||||
|
||||
byte[] b1 = new byte[1], b2 = new byte[1], b3 = new byte[1];
|
||||
Task<int> r1 = server.ReadAsync((Memory<byte>)b1).AsTask();
|
||||
Task<int> r2 = server.ReadAsync((Memory<byte>)b2).AsTask();
|
||||
Task<int> r3 = server.ReadAsync((Memory<byte>)b3).AsTask();
|
||||
|
||||
await client.WriteAsync(new byte[] { 42, 43, 44 });
|
||||
|
||||
Assert.Equal(3, await r1 + await r2 + await r3);
|
||||
Assert.Equal(42 + 43 + 44, b1[0] + b2[0] + b3[0]);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WriteAsync_MultipleConcurrentValueTaskWrites_Success()
|
||||
{
|
||||
await RunWithConnectedNetworkStreamsAsync(async (server, client) =>
|
||||
{
|
||||
// Technically this isn't supported behavior, but it happens to work because it's supported on socket.
|
||||
// So validate it to alert us to any potential future breaks.
|
||||
|
||||
ValueTask s1 = server.WriteAsync(new ReadOnlyMemory<byte>(new byte[] { 42 }));
|
||||
ValueTask s2 = server.WriteAsync(new ReadOnlyMemory<byte>(new byte[] { 43 }));
|
||||
ValueTask s3 = server.WriteAsync(new ReadOnlyMemory<byte>(new byte[] { 44 }));
|
||||
|
||||
byte[] b1 = new byte[1], b2 = new byte[1], b3 = new byte[1];
|
||||
Assert.Equal(3,
|
||||
await client.ReadAsync((Memory<byte>)b1) +
|
||||
await client.ReadAsync((Memory<byte>)b2) +
|
||||
await client.ReadAsync((Memory<byte>)b3));
|
||||
|
||||
await s1;
|
||||
await s2;
|
||||
await s3;
|
||||
|
||||
Assert.Equal(42 + 43 + 44, b1[0] + b2[0] + b3[0]);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WriteAsync_MultipleConcurrentValueTaskWrites_AsTask_Success()
|
||||
{
|
||||
await RunWithConnectedNetworkStreamsAsync(async (server, client) =>
|
||||
{
|
||||
// Technically this isn't supported behavior, but it happens to work because it's supported on socket.
|
||||
// So validate it to alert us to any potential future breaks.
|
||||
|
||||
Task s1 = server.WriteAsync(new ReadOnlyMemory<byte>(new byte[] { 42 })).AsTask();
|
||||
Task s2 = server.WriteAsync(new ReadOnlyMemory<byte>(new byte[] { 43 })).AsTask();
|
||||
Task s3 = server.WriteAsync(new ReadOnlyMemory<byte>(new byte[] { 44 })).AsTask();
|
||||
|
||||
byte[] b1 = new byte[1], b2 = new byte[1], b3 = new byte[1];
|
||||
Task<int> r1 = client.ReadAsync((Memory<byte>)b1).AsTask();
|
||||
Task<int> r2 = client.ReadAsync((Memory<byte>)b2).AsTask();
|
||||
Task<int> r3 = client.ReadAsync((Memory<byte>)b3).AsTask();
|
||||
|
||||
await Task.WhenAll(s1, s2, s3, r1, r2, r3);
|
||||
|
||||
Assert.Equal(3, await r1 + await r2 + await r3);
|
||||
Assert.Equal(42 + 43 + 44, b1[0] + b2[0] + b3[0]);
|
||||
});
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> ReadAsync_ContinuesOnCurrentContextIfDesired_MemberData() =>
|
||||
from flowExecutionContext in new[] { true, false }
|
||||
from continueOnCapturedContext in new bool?[] { null, false, true }
|
||||
select new object[] { flowExecutionContext, continueOnCapturedContext };
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(ReadAsync_ContinuesOnCurrentContextIfDesired_MemberData))]
|
||||
public async Task ReadAsync_ContinuesOnCurrentSynchronizationContextIfDesired(
|
||||
bool flowExecutionContext, bool? continueOnCapturedContext)
|
||||
{
|
||||
await Task.Run(async () => // escape xunit sync ctx
|
||||
{
|
||||
await RunWithConnectedNetworkStreamsAsync(async (server, client) =>
|
||||
{
|
||||
Assert.Null(SynchronizationContext.Current);
|
||||
|
||||
var continuationRan = new TaskCompletionSource<bool>();
|
||||
var asyncLocal = new AsyncLocal<int>();
|
||||
bool schedulerWasFlowed = false;
|
||||
bool executionContextWasFlowed = false;
|
||||
Action continuation = () =>
|
||||
{
|
||||
schedulerWasFlowed = SynchronizationContext.Current is CustomSynchronizationContext;
|
||||
executionContextWasFlowed = 42 == asyncLocal.Value;
|
||||
continuationRan.SetResult(true);
|
||||
};
|
||||
|
||||
var readBuffer = new byte[1];
|
||||
ValueTask<int> readValueTask = client.ReadAsync((Memory<byte>)new byte[1]);
|
||||
|
||||
SynchronizationContext.SetSynchronizationContext(new CustomSynchronizationContext());
|
||||
asyncLocal.Value = 42;
|
||||
switch (continueOnCapturedContext)
|
||||
{
|
||||
case null:
|
||||
if (flowExecutionContext)
|
||||
{
|
||||
readValueTask.GetAwaiter().OnCompleted(continuation);
|
||||
}
|
||||
else
|
||||
{
|
||||
readValueTask.GetAwaiter().UnsafeOnCompleted(continuation);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (flowExecutionContext)
|
||||
{
|
||||
readValueTask.ConfigureAwait(continueOnCapturedContext.Value).GetAwaiter().OnCompleted(continuation);
|
||||
}
|
||||
else
|
||||
{
|
||||
readValueTask.ConfigureAwait(continueOnCapturedContext.Value).GetAwaiter().UnsafeOnCompleted(continuation);
|
||||
}
|
||||
break;
|
||||
}
|
||||
asyncLocal.Value = 0;
|
||||
SynchronizationContext.SetSynchronizationContext(null);
|
||||
|
||||
Assert.False(readValueTask.IsCompleted);
|
||||
Assert.False(readValueTask.IsCompletedSuccessfully);
|
||||
await server.WriteAsync(new byte[] { 42 });
|
||||
|
||||
await continuationRan.Task;
|
||||
Assert.True(readValueTask.IsCompleted);
|
||||
Assert.True(readValueTask.IsCompletedSuccessfully);
|
||||
|
||||
Assert.Equal(continueOnCapturedContext != false, schedulerWasFlowed);
|
||||
Assert.Equal(flowExecutionContext, executionContextWasFlowed);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(ReadAsync_ContinuesOnCurrentContextIfDesired_MemberData))]
|
||||
public async Task ReadAsync_ContinuesOnCurrentTaskSchedulerIfDesired(
|
||||
bool flowExecutionContext, bool? continueOnCapturedContext)
|
||||
{
|
||||
await Task.Run(async () => // escape xunit sync ctx
|
||||
{
|
||||
await RunWithConnectedNetworkStreamsAsync(async (server, client) =>
|
||||
{
|
||||
Assert.Null(SynchronizationContext.Current);
|
||||
|
||||
var continuationRan = new TaskCompletionSource<bool>();
|
||||
var asyncLocal = new AsyncLocal<int>();
|
||||
bool schedulerWasFlowed = false;
|
||||
bool executionContextWasFlowed = false;
|
||||
Action continuation = () =>
|
||||
{
|
||||
schedulerWasFlowed = TaskScheduler.Current is CustomTaskScheduler;
|
||||
executionContextWasFlowed = 42 == asyncLocal.Value;
|
||||
continuationRan.SetResult(true);
|
||||
};
|
||||
|
||||
var readBuffer = new byte[1];
|
||||
ValueTask<int> readValueTask = client.ReadAsync((Memory<byte>)new byte[1]);
|
||||
|
||||
await Task.Factory.StartNew(() =>
|
||||
{
|
||||
Assert.IsType<CustomTaskScheduler>(TaskScheduler.Current);
|
||||
asyncLocal.Value = 42;
|
||||
switch (continueOnCapturedContext)
|
||||
{
|
||||
case null:
|
||||
if (flowExecutionContext)
|
||||
{
|
||||
readValueTask.GetAwaiter().OnCompleted(continuation);
|
||||
}
|
||||
else
|
||||
{
|
||||
readValueTask.GetAwaiter().UnsafeOnCompleted(continuation);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (flowExecutionContext)
|
||||
{
|
||||
readValueTask.ConfigureAwait(continueOnCapturedContext.Value).GetAwaiter().OnCompleted(continuation);
|
||||
}
|
||||
else
|
||||
{
|
||||
readValueTask.ConfigureAwait(continueOnCapturedContext.Value).GetAwaiter().UnsafeOnCompleted(continuation);
|
||||
}
|
||||
break;
|
||||
}
|
||||
asyncLocal.Value = 0;
|
||||
}, CancellationToken.None, TaskCreationOptions.None, new CustomTaskScheduler());
|
||||
|
||||
Assert.False(readValueTask.IsCompleted);
|
||||
Assert.False(readValueTask.IsCompletedSuccessfully);
|
||||
await server.WriteAsync(new byte[] { 42 });
|
||||
|
||||
await continuationRan.Task;
|
||||
Assert.True(readValueTask.IsCompleted);
|
||||
Assert.True(readValueTask.IsCompletedSuccessfully);
|
||||
|
||||
Assert.Equal(continueOnCapturedContext != false, schedulerWasFlowed);
|
||||
Assert.Equal(flowExecutionContext, executionContextWasFlowed);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private sealed class CustomSynchronizationContext : SynchronizationContext
|
||||
{
|
||||
public override void Post(SendOrPostCallback d, object state)
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem(delegate
|
||||
{
|
||||
SetSynchronizationContext(this);
|
||||
try
|
||||
{
|
||||
d(state);
|
||||
}
|
||||
finally
|
||||
{
|
||||
SetSynchronizationContext(null);
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class CustomTaskScheduler : TaskScheduler
|
||||
{
|
||||
protected override void QueueTask(Task task) => ThreadPool.QueueUserWorkItem(_ => TryExecuteTask(task));
|
||||
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) => false;
|
||||
protected override IEnumerable<Task> GetScheduledTasks() => null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -81,9 +81,9 @@ namespace System.Net.Sockets.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[ActiveIssue(25639)]
|
||||
[PlatformSpecific(TestPlatforms.AnyUnix)]
|
||||
[Fact]
|
||||
public void IOControl_SIOCATMARK_Success()
|
||||
public void IOControl_SIOCATMARK_Unix_Success()
|
||||
{
|
||||
using (var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
{
|
||||
@@ -101,25 +101,89 @@ namespace System.Net.Sockets.Tests
|
||||
{
|
||||
byte[] siocatmarkResult = new byte[sizeof(int)];
|
||||
|
||||
// Socket connected but no data sent.
|
||||
Assert.Equal(4, client.IOControl(IOControlCode.OobDataRead, null, siocatmarkResult));
|
||||
Assert.Equal(0, BitConverter.ToInt32(siocatmarkResult, 0));
|
||||
|
||||
server.Send(new byte[] { 42 }, SocketFlags.None);
|
||||
server.Send(new byte[] { 43 }, SocketFlags.OutOfBand);
|
||||
|
||||
Assert.Equal(4, client.IOControl(IOControlCode.OobDataRead, null, siocatmarkResult));
|
||||
Assert.Equal(0, BitConverter.ToInt32(siocatmarkResult, 0));
|
||||
// OOB data recieved, but read pointer not at mark.
|
||||
Assert.True(SpinWait.SpinUntil(() =>
|
||||
{
|
||||
Assert.Equal(4, client.IOControl(IOControlCode.OobDataRead, null, siocatmarkResult));
|
||||
return BitConverter.ToInt32(siocatmarkResult, 0) == 0;
|
||||
}, 10_000));
|
||||
|
||||
var received = new byte[1];
|
||||
|
||||
Assert.Equal(1, client.Receive(received));
|
||||
Assert.Equal(42, received[0]);
|
||||
|
||||
// OOB data recieved, read pointer at mark.
|
||||
Assert.Equal(4, client.IOControl(IOControlCode.OobDataRead, null, siocatmarkResult));
|
||||
Assert.Equal(1, BitConverter.ToInt32(siocatmarkResult, 0));
|
||||
|
||||
Assert.Equal(1, client.Receive(received, SocketFlags.OutOfBand));
|
||||
Assert.Equal(43, received[0]);
|
||||
|
||||
// OOB data read, read pointer at mark.
|
||||
Assert.Equal(4, client.IOControl(IOControlCode.OobDataRead, null, siocatmarkResult));
|
||||
Assert.Equal(PlatformDetection.IsOSX ? 0 : 1, BitConverter.ToInt32(siocatmarkResult, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[PlatformSpecific(TestPlatforms.Windows)]
|
||||
[Fact]
|
||||
public void IOControl_SIOCATMARK_Windows_Success()
|
||||
{
|
||||
using (var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
{
|
||||
Assert.Throws<SocketException>(() => client.IOControl(IOControlCode.OobDataRead, null, null));
|
||||
Assert.Throws<SocketException>(() => client.IOControl(IOControlCode.OobDataRead, null, new byte[0]));
|
||||
Assert.Throws<SocketException>(() => client.IOControl(IOControlCode.OobDataRead, null, new byte[sizeof(int) - 1]));
|
||||
|
||||
using (var listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
{
|
||||
listener.Bind(new IPEndPoint(IPAddress.Loopback, 0));
|
||||
listener.Listen(1);
|
||||
|
||||
client.Connect(listener.LocalEndPoint);
|
||||
using (Socket server = listener.Accept())
|
||||
{
|
||||
byte[] siocatmarkResult = new byte[sizeof(int)];
|
||||
|
||||
// Socket connected but no data sent.
|
||||
Assert.Equal(4, client.IOControl(IOControlCode.OobDataRead, null, siocatmarkResult));
|
||||
Assert.Equal(1, BitConverter.ToInt32(siocatmarkResult, 0));
|
||||
|
||||
server.Send(new byte[] { 42 }, SocketFlags.None);
|
||||
server.Send(new byte[] { 43 }, SocketFlags.OutOfBand);
|
||||
|
||||
// OOB data recieved, but read pointer not at mark
|
||||
Assert.True(SpinWait.SpinUntil(() =>
|
||||
{
|
||||
Assert.Equal(4, client.IOControl(IOControlCode.OobDataRead, null, siocatmarkResult));
|
||||
return BitConverter.ToInt32(siocatmarkResult, 0) == 1;
|
||||
return BitConverter.ToInt32(siocatmarkResult, 0) == 0;
|
||||
}, 10_000));
|
||||
|
||||
var received = new byte[1];
|
||||
|
||||
Assert.Equal(1, client.Receive(received));
|
||||
Assert.Equal(42, received[0]);
|
||||
|
||||
// OOB data recieved, read pointer at mark.
|
||||
Assert.Equal(4, client.IOControl(IOControlCode.OobDataRead, null, siocatmarkResult));
|
||||
Assert.Equal(0, BitConverter.ToInt32(siocatmarkResult, 0));
|
||||
|
||||
Assert.Equal(1, client.Receive(received, SocketFlags.OutOfBand));
|
||||
Assert.Equal(43, received[0]);
|
||||
|
||||
// OOB data read, read pointer at mark.
|
||||
Assert.Equal(4, client.IOControl(IOControlCode.OobDataRead, null, siocatmarkResult));
|
||||
Assert.Equal(1, BitConverter.ToInt32(siocatmarkResult, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -286,11 +286,12 @@ namespace System.Net.Sockets.Tests
|
||||
AssertExtensions.Throws<ArgumentException>("path", null, () =>
|
||||
{
|
||||
// Existence is validated on send
|
||||
SendPackets(type, new SendPacketsElement(" \t "), 0);
|
||||
SendPackets(type, new SendPacketsElement(" "), 0);
|
||||
});
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[ActiveIssue(27269)]
|
||||
[InlineData(SocketImplementationType.APM)]
|
||||
[InlineData(SocketImplementationType.Async)]
|
||||
[PlatformSpecific(TestPlatforms.Windows)] // valid filename chars on Unix
|
||||
|
@@ -3,6 +3,7 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
@@ -1196,7 +1197,74 @@ namespace System.Net.Sockets.Tests
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class SendReceiveSync : SendReceive<SocketHelperArraySync> { }
|
||||
public sealed class SendReceiveSync : SendReceive<SocketHelperArraySync>
|
||||
{
|
||||
[OuterLoop]
|
||||
[Fact]
|
||||
public void BlockingRead_DoesntRequireAnotherThreadPoolThread()
|
||||
{
|
||||
RemoteInvoke(() =>
|
||||
{
|
||||
// Set the max number of worker threads to a low value.
|
||||
ThreadPool.GetMaxThreads(out int workerThreads, out int completionPortThreads);
|
||||
ThreadPool.SetMaxThreads(Environment.ProcessorCount, completionPortThreads);
|
||||
|
||||
// Create twice that many socket pairs, for good measure.
|
||||
(Socket, Socket)[] socketPairs = Enumerable.Range(0, Environment.ProcessorCount * 2).Select(_ => CreateConnectedSocketPair()).ToArray();
|
||||
try
|
||||
{
|
||||
// Ensure that on Unix all of the first socket in each pair are configured for sync-over-async.
|
||||
foreach ((Socket, Socket) pair in socketPairs)
|
||||
{
|
||||
pair.Item1.ForceNonBlocking(force: true);
|
||||
}
|
||||
|
||||
// Queue a work item for each first socket to do a blocking receive.
|
||||
Task[] receives =
|
||||
(from pair in socketPairs
|
||||
select Task.Factory.StartNew(() => pair.Item1.Receive(new byte[1]), CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default))
|
||||
.ToArray();
|
||||
|
||||
// Give a bit of time for the pool to start executing the receives. It's possible this won't be enough,
|
||||
// in which case the test we could get a false negative on the test, but we won't get spurious failures.
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// Now send to each socket.
|
||||
foreach ((Socket, Socket) pair in socketPairs)
|
||||
{
|
||||
pair.Item2.Send(new byte[1]);
|
||||
}
|
||||
|
||||
// And wait for all the receives to complete.
|
||||
Assert.True(Task.WaitAll(receives, 60_000), "Expected all receives to complete within timeout");
|
||||
}
|
||||
finally
|
||||
{
|
||||
foreach ((Socket, Socket) pair in socketPairs)
|
||||
{
|
||||
pair.Item1.Dispose();
|
||||
pair.Item2.Dispose();
|
||||
}
|
||||
}
|
||||
}).Dispose();
|
||||
}
|
||||
|
||||
private static (Socket, Socket) CreateConnectedSocketPair()
|
||||
{
|
||||
using (Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
{
|
||||
listener.Bind(new IPEndPoint(IPAddress.Loopback, 0));
|
||||
listener.Listen(1);
|
||||
|
||||
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
client.Connect(listener.LocalEndPoint);
|
||||
Socket server = listener.Accept();
|
||||
|
||||
return (client, server);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class SendReceiveSyncForceNonBlocking : SendReceive<SocketHelperSyncForceNonBlocking> { }
|
||||
public sealed class SendReceiveApm : SendReceive<SocketHelperApm> { }
|
||||
public sealed class SendReceiveTask : SendReceive<SocketHelperTask> { }
|
||||
|
@@ -2,10 +2,58 @@
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace System.Net.Sockets.Tests
|
||||
{
|
||||
public sealed class SendReceiveSpanSync : SendReceive<SocketHelperSpanSync> { }
|
||||
public sealed class SendReceiveSpanSyncForceNonBlocking : SendReceive<SocketHelperSpanSyncForceNonBlocking> { }
|
||||
public sealed class SendReceiveMemoryArrayTask : SendReceive<SocketHelperMemoryArrayTask> { }
|
||||
public sealed class SendReceiveMemoryArrayTask : SendReceive<SocketHelperMemoryArrayTask>
|
||||
{
|
||||
[Fact]
|
||||
public async Task Precanceled_Throws()
|
||||
{
|
||||
using (var listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
using (var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
{
|
||||
listener.BindToAnonymousPort(IPAddress.Loopback);
|
||||
listener.Listen(1);
|
||||
|
||||
await client.ConnectAsync(listener.LocalEndPoint);
|
||||
using (Socket server = await listener.AcceptAsync())
|
||||
{
|
||||
var cts = new CancellationTokenSource();
|
||||
cts.Cancel();
|
||||
|
||||
await Assert.ThrowsAnyAsync<OperationCanceledException>(async () => await server.SendAsync((ReadOnlyMemory<byte>)new byte[0], SocketFlags.None, cts.Token));
|
||||
await Assert.ThrowsAnyAsync<OperationCanceledException>(async () => await server.ReceiveAsync((Memory<byte>)new byte[0], SocketFlags.None, cts.Token));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DisposedSocket_ThrowsOperationCanceledException()
|
||||
{
|
||||
using (var listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
using (var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
{
|
||||
listener.BindToAnonymousPort(IPAddress.Loopback);
|
||||
listener.Listen(1);
|
||||
|
||||
await client.ConnectAsync(listener.LocalEndPoint);
|
||||
using (Socket server = await listener.AcceptAsync())
|
||||
{
|
||||
var cts = new CancellationTokenSource();
|
||||
cts.Cancel();
|
||||
|
||||
server.Shutdown(SocketShutdown.Both);
|
||||
await Assert.ThrowsAnyAsync<OperationCanceledException>(async () => await server.SendAsync((ReadOnlyMemory<byte>)new byte[0], SocketFlags.None, cts.Token));
|
||||
await Assert.ThrowsAnyAsync<OperationCanceledException>(async () => await server.ReceiveAsync((Memory<byte>)new byte[0], SocketFlags.None, cts.Token));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public sealed class SendReceiveMemoryNativeTask : SendReceive<SocketHelperMemoryNativeTask> { }
|
||||
}
|
||||
|
@@ -4,6 +4,10 @@
|
||||
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using Xunit;
|
||||
|
||||
namespace System.Net.Sockets.Tests
|
||||
@@ -48,7 +52,7 @@ namespace System.Net.Sockets.Tests
|
||||
byte[] array = new byte[42];
|
||||
|
||||
saea.SetBuffer(array, 0, array.Length);
|
||||
Assert.True(saea.MemoryBuffer.TryGetArray(out ArraySegment<byte> result));
|
||||
Assert.True(MemoryMarshal.TryGetArray(saea.MemoryBuffer, out ArraySegment<byte> result));
|
||||
Assert.Same(array, result.Array);
|
||||
Assert.Same(saea.Buffer, array);
|
||||
Assert.Equal(0, result.Offset);
|
||||
@@ -59,7 +63,7 @@ namespace System.Net.Sockets.Tests
|
||||
Assert.Equal(1, saea.Offset);
|
||||
Assert.Equal(2, saea.Count);
|
||||
|
||||
Assert.True(saea.MemoryBuffer.TryGetArray(out result));
|
||||
Assert.True(MemoryMarshal.TryGetArray(saea.MemoryBuffer, out result));
|
||||
Assert.Same(array, result.Array);
|
||||
Assert.Equal(0, result.Offset);
|
||||
Assert.Equal(array.Length, result.Count);
|
||||
@@ -181,15 +185,64 @@ namespace System.Net.Sockets.Tests
|
||||
[Fact]
|
||||
public void SetBufferMemory_NonArray_BufferReturnsNull()
|
||||
{
|
||||
using (var m = new NativeOwnedMemory(42))
|
||||
using (var m = new NativeMemoryManager(42))
|
||||
using (var saea = new SocketAsyncEventArgs())
|
||||
{
|
||||
saea.SetBuffer(m.Memory);
|
||||
Assert.True(saea.MemoryBuffer.Equals(m.Memory));
|
||||
Assert.Equal(0, saea.Offset);
|
||||
Assert.Equal(m.Length, saea.Count);
|
||||
Assert.Equal(m.Memory.Length, saea.Count);
|
||||
Assert.Null(saea.Buffer);
|
||||
}
|
||||
}
|
||||
|
||||
[OuterLoop("Involves GC and finalization")]
|
||||
[Theory]
|
||||
[InlineData(false)]
|
||||
[InlineData(true)]
|
||||
public void Finalizer_InvokedWhenNoLongerReferenced(bool afterAsyncOperation)
|
||||
{
|
||||
var cwt = new ConditionalWeakTable<object, object>();
|
||||
|
||||
for (int i = 0; i < 5; i++) // create several SAEA instances, stored into cwt
|
||||
{
|
||||
CreateSocketAsyncEventArgs();
|
||||
|
||||
void CreateSocketAsyncEventArgs() // separated out so that JIT doesn't extend lifetime of SAEA instances
|
||||
{
|
||||
var saea = new SocketAsyncEventArgs();
|
||||
cwt.Add(saea, saea);
|
||||
|
||||
if (afterAsyncOperation)
|
||||
{
|
||||
using (Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
{
|
||||
listener.Bind(new IPEndPoint(IPAddress.Loopback, 0));
|
||||
listener.Listen(1);
|
||||
|
||||
using (Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
{
|
||||
saea.RemoteEndPoint = listener.LocalEndPoint;
|
||||
using (var mres = new ManualResetEventSlim())
|
||||
{
|
||||
saea.Completed += (s, e) => mres.Set();
|
||||
if (client.ConnectAsync(saea))
|
||||
{
|
||||
mres.Wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Assert.True(SpinWait.SpinUntil(() =>
|
||||
{
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
return cwt.Count() == 0; // validate that the cwt becomes empty
|
||||
}, 30_000));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,6 +3,7 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -269,7 +270,7 @@ namespace System.Net.Sockets.Tests
|
||||
// MemberDatas that are generally useful
|
||||
//
|
||||
|
||||
public abstract class MemberDatas
|
||||
public abstract class MemberDatas : RemoteExecutorTestBase
|
||||
{
|
||||
public static readonly object[][] Loopbacks = new[]
|
||||
{
|
||||
|
@@ -39,7 +39,7 @@ namespace System.Net.Sockets.Tests
|
||||
public override bool ValidatesArrayArguments => false;
|
||||
public override async Task<int> ReceiveAsync(Socket s, ArraySegment<byte> buffer)
|
||||
{
|
||||
using (var m = new NativeOwnedMemory(buffer.Count))
|
||||
using (var m = new NativeMemoryManager(buffer.Count))
|
||||
{
|
||||
int bytesReceived = await s.ReceiveAsync(m.Memory, SocketFlags.None).ConfigureAwait(false);
|
||||
m.Memory.Span.Slice(0, bytesReceived).CopyTo(buffer.AsSpan());
|
||||
@@ -48,7 +48,7 @@ namespace System.Net.Sockets.Tests
|
||||
}
|
||||
public override async Task<int> SendAsync(Socket s, ArraySegment<byte> buffer)
|
||||
{
|
||||
using (var m = new NativeOwnedMemory(buffer.Count))
|
||||
using (var m = new NativeMemoryManager(buffer.Count))
|
||||
{
|
||||
buffer.AsSpan().CopyTo(m.Memory.Span);
|
||||
return await s.SendAsync(m.Memory, SocketFlags.None).ConfigureAwait(false);
|
||||
|
@@ -21,6 +21,8 @@
|
||||
<Compile Include="DisposedSocketTests.cs" />
|
||||
<Compile Include="DnsEndPointTest.cs" />
|
||||
<Compile Include="DualModeSocketTest.cs" />
|
||||
<Compile Include="ExecutionContextFlowTest.cs" />
|
||||
<Compile Include="ExecutionContextFlowTest.netcoreapp.cs" Condition="'$(TargetGroup)' != 'netstandard'" />
|
||||
<Compile Include="IPPacketInformationTest.cs" />
|
||||
<Compile Include="LingerStateTest.cs" />
|
||||
<Compile Include="LoggingTest.cs" />
|
||||
@@ -48,7 +50,6 @@
|
||||
<Compile Include="SocketOptionNameTest.cs" />
|
||||
<Compile Include="MulticastOptionTest.cs" />
|
||||
<Compile Include="UdpClientTest.cs" />
|
||||
<Compile Include="UnixDomainSocketTest.cs" />
|
||||
<Compile Include="UnixDomainSocketTest.netcoreapp.cs" Condition="'$(TargetGroup)' != 'netstandard'" />
|
||||
<!-- Common Sockets files -->
|
||||
<Compile Include="$(CommonTestPath)\System\Net\Configuration.cs">
|
||||
@@ -97,8 +98,8 @@
|
||||
<Compile Include="$(CommonTestPath)\System\Threading\Tasks\TaskTimeoutExtensions.cs">
|
||||
<Link>Common\System\Threading\Tasks\TaskTimeoutExtensions.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonTestPath)\System\Buffers\NativeOwnedMemory.cs">
|
||||
<Link>Common\System\Buffers\NativeOwnedMemory.cs</Link>
|
||||
<Compile Include="$(CommonTestPath)\System\Buffers\NativeMemoryManager.cs">
|
||||
<Link>Common\System\Buffers\NativeMemoryManager.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\System\Threading\Tasks\TaskToApm.cs">
|
||||
<Link>Common\System\Threading\Tasks\TaskToApm.cs</Link>
|
||||
@@ -119,5 +120,8 @@
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\$(AssemblyName).rd.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
|
||||
</ItemGroup>
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
|
||||
</Project>
|
||||
|
@@ -124,6 +124,24 @@ namespace System.Net.Sockets.Tests
|
||||
listener.Stop();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
// This verify that basic constructs do work when IPv6 is NOT available.
|
||||
public void IPv6_Only_Works()
|
||||
{
|
||||
if (Socket.OSSupportsIPv6 || !Socket.OSSupportsIPv4)
|
||||
{
|
||||
// TBD we should figure out better way how to execute this in IPv4 only environment.
|
||||
return;
|
||||
}
|
||||
|
||||
// This should not throw e.g. default to IPv6.
|
||||
TcpListener l = TcpListener.Create(0);
|
||||
l.Stop();
|
||||
|
||||
Socket s = new Socket(SocketType.Stream, ProtocolType.Tcp);
|
||||
s.Close();
|
||||
}
|
||||
|
||||
private sealed class DerivedTcpListener : TcpListener
|
||||
{
|
||||
#pragma warning disable 0618
|
||||
|
@@ -1,30 +0,0 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Net.Test.Common;
|
||||
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace System.Net.Sockets.Tests
|
||||
{
|
||||
public partial class UnixDomainSocketTest
|
||||
{
|
||||
private readonly ITestOutputHelper _log;
|
||||
|
||||
public UnixDomainSocketTest(ITestOutputHelper output)
|
||||
{
|
||||
_log = TestLogging.GetInstance();
|
||||
}
|
||||
|
||||
[OuterLoop] // TODO: Issue #11345
|
||||
[Fact]
|
||||
[PlatformSpecific(TestPlatforms.Windows)] // CreateUnixDomainSocket should throw on Windows
|
||||
public void Socket_CreateUnixDomainSocket_Throws_OnWindows()
|
||||
{
|
||||
SocketException e = Assert.Throws<SocketException>(() => new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified));
|
||||
Assert.Equal(SocketError.AddressFamilyNotSupported, e.SocketErrorCode);
|
||||
}
|
||||
}
|
||||
}
|
@@ -15,16 +15,8 @@ namespace System.Net.Sockets.Tests
|
||||
{
|
||||
public partial class UnixDomainSocketTest
|
||||
{
|
||||
[Fact]
|
||||
[PlatformSpecific(TestPlatforms.Windows)] // new UnixDomainSocketEndPoint should throw on Windows
|
||||
public void UnixDomainSocketEndPoint_Throws_OnWindows()
|
||||
{
|
||||
Assert.Throws<PlatformNotSupportedException>(() => new UnixDomainSocketEndPoint("/path"));
|
||||
}
|
||||
|
||||
[OuterLoop] // TODO: Issue #11345
|
||||
[Fact]
|
||||
[PlatformSpecific(TestPlatforms.AnyUnix)] // Tests ConnectAsyncUnixDomainSocketEndPoint success on Unix
|
||||
[PlatformSpecific(~TestPlatforms.Windows)] // Windows doesn't currently support ConnectEx with domain sockets
|
||||
[ConditionalFact(nameof(PlatformSupportsUnixDomainSockets))]
|
||||
public async Task Socket_ConnectAsyncUnixDomainSocketEndPoint_Success()
|
||||
{
|
||||
string path = null;
|
||||
@@ -79,9 +71,7 @@ namespace System.Net.Sockets.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[OuterLoop] // TODO: Issue #11345
|
||||
[Fact]
|
||||
[PlatformSpecific(TestPlatforms.AnyUnix)] // Tests ConnectAsyncUnixDomainSocketEndPoint seccess on Unix
|
||||
[ConditionalFact(nameof(PlatformSupportsUnixDomainSockets))]
|
||||
public async Task Socket_ConnectAsyncUnixDomainSocketEndPoint_NotServer()
|
||||
{
|
||||
string path = GetRandomNonExistingFilePath();
|
||||
@@ -103,7 +93,9 @@ namespace System.Net.Sockets.Tests
|
||||
await complete.Task;
|
||||
}
|
||||
|
||||
Assert.Equal(SocketError.AddressNotAvailable, args.SocketError);
|
||||
Assert.Equal(
|
||||
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? SocketError.InvalidArgument : SocketError.AddressNotAvailable,
|
||||
args.SocketError);
|
||||
}
|
||||
}
|
||||
finally
|
||||
@@ -113,9 +105,7 @@ namespace System.Net.Sockets.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[OuterLoop] // TODO: Issue #11345
|
||||
[Fact]
|
||||
[PlatformSpecific(TestPlatforms.AnyUnix)] // Tests SendReceive success for UnixDomainSocketEndPoint on Unix
|
||||
[ConditionalFact(nameof(PlatformSupportsUnixDomainSockets))]
|
||||
public void Socket_SendReceive_Success()
|
||||
{
|
||||
string path = GetRandomNonExistingFilePath();
|
||||
@@ -152,9 +142,7 @@ namespace System.Net.Sockets.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[OuterLoop] // TODO: Issue #11345
|
||||
[Fact]
|
||||
[PlatformSpecific(TestPlatforms.AnyUnix)] // Tests SendReceiveAsync success for UnixDomainSocketEndPoint on Unix
|
||||
[ConditionalFact(nameof(PlatformSupportsUnixDomainSockets))]
|
||||
public async Task Socket_SendReceiveAsync_Success()
|
||||
{
|
||||
string path = GetRandomNonExistingFilePath();
|
||||
@@ -191,13 +179,11 @@ namespace System.Net.Sockets.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[OuterLoop] // TODO: Issue #11345
|
||||
[Theory]
|
||||
[ConditionalTheory(nameof(PlatformSupportsUnixDomainSockets))]
|
||||
[InlineData(5000, 1, 1)]
|
||||
[InlineData(500, 18, 21)]
|
||||
[InlineData(500, 21, 18)]
|
||||
[InlineData(5, 128000, 64000)]
|
||||
[PlatformSpecific(TestPlatforms.AnyUnix)] // Tests SendReceiveAsync success for UnixDomainSocketEndPoint on Unix
|
||||
public async Task Socket_SendReceiveAsync_PropagateToStream_Success(int iterations, int writeBufferSize, int readBufferSize)
|
||||
{
|
||||
var writeBuffer = new byte[writeBufferSize * iterations];
|
||||
@@ -219,10 +205,15 @@ namespace System.Net.Sockets.Tests
|
||||
|
||||
Task clientReceives = Task.Run(async () =>
|
||||
{
|
||||
int bytesRead;
|
||||
byte[] buffer = new byte[readBufferSize];
|
||||
while ((bytesRead = await client.ReceiveAsync(new ArraySegment<byte>(buffer), SocketFlags.None)) > 0)
|
||||
while (true)
|
||||
{
|
||||
int bytesRead = await client.ReceiveAsync(new Memory<byte>(buffer), SocketFlags.None);
|
||||
if (bytesRead == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
Assert.InRange(bytesRead, 1, writeBuffer.Length - readData.Length);
|
||||
readData.Write(buffer, 0, bytesRead);
|
||||
}
|
||||
});
|
||||
@@ -250,11 +241,9 @@ namespace System.Net.Sockets.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[OuterLoop] // TODO: Issue #11345
|
||||
[Theory]
|
||||
[ConditionalTheory(nameof(PlatformSupportsUnixDomainSockets))]
|
||||
[InlineData(false)]
|
||||
[InlineData(true)]
|
||||
[PlatformSpecific(TestPlatforms.AnyUnix)] // Tests ConcurrentSendReceive success for UnixDomainSocketEndPoint on Unix
|
||||
public async Task ConcurrentSendReceive(bool forceNonBlocking)
|
||||
{
|
||||
using (Socket server = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified))
|
||||
@@ -296,9 +285,7 @@ namespace System.Net.Sockets.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[OuterLoop] // TODO: Issue #11345
|
||||
[Fact]
|
||||
[PlatformSpecific(TestPlatforms.AnyUnix)] // Tests ConcurrentSendReceive success for UnixDomainSocketEndPoint on Unix
|
||||
[ConditionalFact(nameof(PlatformSupportsUnixDomainSockets))]
|
||||
public async Task ConcurrentSendReceiveAsync()
|
||||
{
|
||||
using (Socket server = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified))
|
||||
@@ -336,8 +323,7 @@ namespace System.Net.Sockets.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[PlatformSpecific(TestPlatforms.AnyUnix)] // Tests new UnixDomainSocketEndPoint throws the correct exception for invalid args
|
||||
[ConditionalFact(nameof(PlatformSupportsUnixDomainSockets))]
|
||||
public void UnixDomainSocketEndPoint_InvalidPaths_Throws()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>(() => new UnixDomainSocketEndPoint(null));
|
||||
@@ -351,8 +337,7 @@ namespace System.Net.Sockets.Tests
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => new UnixDomainSocketEndPoint(invalidLengthString));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[PlatformSpecific(TestPlatforms.AnyUnix)]
|
||||
[ConditionalTheory(nameof(PlatformSupportsUnixDomainSockets))]
|
||||
[InlineData(false)]
|
||||
[InlineData(true)]
|
||||
public void UnixDomainSocketEndPoint_RemoteEndPointEqualsBindAddress(bool abstractAddress)
|
||||
@@ -412,7 +397,7 @@ namespace System.Net.Sockets.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[ConditionalFact(nameof(PlatformSupportsUnixDomainSockets))]
|
||||
[PlatformSpecific(TestPlatforms.AnyUnix & ~TestPlatforms.Linux)] // Don't support abstract socket addresses.
|
||||
public void UnixDomainSocketEndPoint_UsingAbstractSocketAddressOnUnsupported_Throws()
|
||||
{
|
||||
@@ -432,6 +417,16 @@ namespace System.Net.Sockets.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[ConditionalFact(nameof(PlatformDoesntSupportUnixDomainSockets))]
|
||||
[PlatformSpecific(TestPlatforms.Windows)]
|
||||
public void Socket_CreateUnixDomainSocket_Throws_OnWindows()
|
||||
{
|
||||
AssertExtensions.Throws<ArgumentNullException>("path", () => new UnixDomainSocketEndPoint(null));
|
||||
AssertExtensions.Throws<ArgumentOutOfRangeException>("path", () => new UnixDomainSocketEndPoint(""));
|
||||
AssertExtensions.Throws<ArgumentOutOfRangeException>("path", () => new UnixDomainSocketEndPoint(new string('s', 1000)));
|
||||
Assert.Throws<PlatformNotSupportedException>(() => new UnixDomainSocketEndPoint("hello"));
|
||||
}
|
||||
|
||||
private static string GetRandomNonExistingFilePath()
|
||||
{
|
||||
string result;
|
||||
@@ -443,5 +438,34 @@ namespace System.Net.Sockets.Tests
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static bool PlatformSupportsUnixDomainSockets => s_platformSupportsUnixDomainSockets.Value;
|
||||
|
||||
private static bool PlatformDoesntSupportUnixDomainSockets => !s_platformSupportsUnixDomainSockets.Value;
|
||||
|
||||
private static readonly Lazy<bool> s_platformSupportsUnixDomainSockets = new Lazy<bool>(() =>
|
||||
{
|
||||
// All Unixes should support UDS. Some Windows will.
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
IntPtr s = socket((int)AddressFamily.Unix, (int)SocketType.Stream, (int)ProtocolType.Unspecified);
|
||||
if (s == (IntPtr)(-1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
closesocket(s);
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
[DllImport("ws2_32.dll")]
|
||||
internal static extern IntPtr socket(int af, int type, int protocol);
|
||||
|
||||
[DllImport("ws2_32.dll")]
|
||||
internal static extern int closesocket(IntPtr socketHandle);
|
||||
}
|
||||
}
|
||||
|
@@ -68,5 +68,8 @@
|
||||
<Name>PerfRunner</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
|
||||
</ItemGroup>
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
|
||||
</Project>
|
||||
</Project>
|
@@ -17,8 +17,8 @@ namespace System.Net.Sockets.Tests
|
||||
{
|
||||
await OpenLoopbackConnectionAsync(async (client, server) =>
|
||||
{
|
||||
byte[] clientBuffer = new byte[1];
|
||||
byte[] serverBuffer = new byte[1];
|
||||
ReadOnlyMemory<byte> clientBuffer = new byte[1];
|
||||
Memory<byte> serverBuffer = new byte[1];
|
||||
foreach (BenchmarkIteration iteration in Benchmark.Iterations)
|
||||
{
|
||||
long iters = Benchmark.InnerIterationCount;
|
||||
@@ -39,8 +39,8 @@ namespace System.Net.Sockets.Tests
|
||||
{
|
||||
await OpenLoopbackConnectionAsync(async (client, server) =>
|
||||
{
|
||||
byte[] clientBuffer = new byte[1];
|
||||
byte[] serverBuffer = new byte[1];
|
||||
ReadOnlyMemory<byte> clientBuffer = new byte[1];
|
||||
Memory<byte> serverBuffer = new byte[1];
|
||||
foreach (BenchmarkIteration iteration in Benchmark.Iterations)
|
||||
{
|
||||
long iters = Benchmark.InnerIterationCount;
|
||||
@@ -48,7 +48,7 @@ namespace System.Net.Sockets.Tests
|
||||
{
|
||||
for (int i = 0; i < iters; i++)
|
||||
{
|
||||
Task r = server.ReceiveAsync(serverBuffer, SocketFlags.None);
|
||||
ValueTask<int> r = server.ReceiveAsync(serverBuffer, SocketFlags.None);
|
||||
await client.SendAsync(clientBuffer, SocketFlags.None);
|
||||
await r;
|
||||
}
|
||||
@@ -57,30 +57,6 @@ namespace System.Net.Sockets.Tests
|
||||
});
|
||||
}
|
||||
|
||||
[Benchmark(InnerIterationCount = 1_000_000)]
|
||||
[InlineData(16)]
|
||||
public async Task ReceiveAsyncThenSendAsync_Task_Parallel(int numConnections)
|
||||
{
|
||||
byte[] clientBuffer = new byte[1];
|
||||
byte[] serverBuffer = new byte[1];
|
||||
foreach (BenchmarkIteration iteration in Benchmark.Iterations)
|
||||
{
|
||||
await OpenLoopbackConnectionAsync(async (client, server) =>
|
||||
{
|
||||
long iters = Benchmark.InnerIterationCount;
|
||||
using (iteration.StartMeasurement())
|
||||
{
|
||||
for (int i = 0; i < iters; i++)
|
||||
{
|
||||
Task r = server.ReceiveAsync(serverBuffer, SocketFlags.None);
|
||||
await client.SendAsync(clientBuffer, SocketFlags.None);
|
||||
await r;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(InnerIterationCount = 10_000), MeasureGCAllocations]
|
||||
public async Task SendAsyncThenReceiveAsync_SocketAsyncEventArgs()
|
||||
{
|
||||
|
@@ -20,5 +20,8 @@
|
||||
<Name>PerfRunner</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
|
||||
</ItemGroup>
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
|
||||
</Project>
|
Reference in New Issue
Block a user