Separate ASP.NET Core tests into a distinct project and make the main test project netfx compatible. (#254)
* Separate ASP.NET Core tests into a distinct project and make the main test project netfx compatible. * Fix merge conflicts. * Update tests/ModelContextProtocol.Tests/ModelContextProtocol.Tests.csproj Co-authored-by: Stephen Halter <halter73@gmail.com> * Revert "Fix merge conflicts." This reverts commit 852169b96786bad2144795540fa164e20b4b197e. * Fix merge conflicts --------- Co-authored-by: Stephen Halter <halter73@gmail.com>
This commit is contained in:
parent
08f9cdbf7d
commit
39ab6cde0d
6 changed files with 324 additions and 63 deletions
|
|
@ -10,4 +10,28 @@ internal static class ProcessExtensions
|
|||
_ = entireProcessTree;
|
||||
process.Kill();
|
||||
}
|
||||
|
||||
public static async Task WaitForExitAsync(this Process process, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (process.HasExited)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
void ProcessExitedHandler(object? sender, EventArgs e) => tcs.TrySetResult(true);
|
||||
|
||||
try
|
||||
{
|
||||
process.EnableRaisingEvents = true;
|
||||
process.Exited += ProcessExitedHandler;
|
||||
|
||||
using var _ = cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken));
|
||||
await tcs.Task.ConfigureAwait(false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
process.Exited -= ProcessExitedHandler;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,21 +4,7 @@ internal static class TextReaderExtensions
|
|||
{
|
||||
public static Task<string> ReadLineAsync(this TextReader reader, CancellationToken cancellationToken)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
return Task.FromCanceled<string>(cancellationToken);
|
||||
}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return reader.ReadLineAsync();
|
||||
}
|
||||
|
||||
public static Task<string> ReadToEndAsync(this TextReader reader, CancellationToken cancellationToken)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
return Task.FromCanceled<string>(cancellationToken);
|
||||
}
|
||||
|
||||
return reader.ReadToEndAsync();
|
||||
}
|
||||
}
|
||||
|
|
@ -5,33 +5,6 @@ namespace System.IO;
|
|||
|
||||
internal static class TextWriterExtensions
|
||||
{
|
||||
public static async Task WriteLineAsync(this TextWriter writer, ReadOnlyMemory<char> value, CancellationToken cancellationToken)
|
||||
{
|
||||
Throw.IfNull(writer);
|
||||
|
||||
if (value.IsEmpty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (MemoryMarshal.TryGetString(value, out string str, out int start, out int length) &&
|
||||
start == 0 && length == str.Length)
|
||||
{
|
||||
await writer.WriteLineAsync(str).ConfigureAwait(false);
|
||||
}
|
||||
else if (MemoryMarshal.TryGetArray(value, out ArraySegment<char> array) &&
|
||||
array.Array is not null && array.Offset == 0 && array.Count == array.Array.Length)
|
||||
{
|
||||
await writer.WriteLineAsync(array.Array).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
await writer.WriteLineAsync(value.ToArray()).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task FlushAsync(this TextWriter writer, CancellationToken cancellationToken)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
|
|
|||
|
|
@ -9,13 +9,18 @@ internal static class TaskExtensions
|
|||
return WaitAsync(task, Timeout.InfiniteTimeSpan, cancellationToken);
|
||||
}
|
||||
|
||||
public static async Task<T> WaitAsync<T>(this Task<T> task, CancellationToken cancellationToken)
|
||||
public static Task<T> WaitAsync<T>(this Task<T> task, CancellationToken cancellationToken)
|
||||
{
|
||||
await WaitAsync(task, Timeout.InfiniteTimeSpan, cancellationToken);
|
||||
return WaitAsync(task, Timeout.InfiniteTimeSpan, cancellationToken);
|
||||
}
|
||||
|
||||
public static async Task<T> WaitAsync<T>(this Task<T> task, TimeSpan timeout, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await WaitAsync((Task)task, timeout, cancellationToken).ConfigureAwait(false);
|
||||
return task.Result;
|
||||
}
|
||||
|
||||
public static async Task WaitAsync(this Task task, TimeSpan timeout, CancellationToken cancellationToken)
|
||||
public static async Task WaitAsync(this Task task, TimeSpan timeout, CancellationToken cancellationToken = default)
|
||||
{
|
||||
Throw.IfNull(task);
|
||||
|
||||
|
|
|
|||
41
src/Common/Throw.cs
Normal file
41
src/Common/Throw.cs
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace ModelContextProtocol.Utils;
|
||||
|
||||
/// <summary>Provides helper methods for throwing exceptions.</summary>
|
||||
internal static class Throw
|
||||
{
|
||||
// NOTE: Most of these should be replaced with extension statics for the relevant extension
|
||||
// type as downlevel polyfills once the C# 14 extension everything feature is available.
|
||||
|
||||
public static void IfNull([NotNull] object? arg, [CallerArgumentExpression(nameof(arg))] string? parameterName = null)
|
||||
{
|
||||
if (arg is null)
|
||||
{
|
||||
ThrowArgumentNullException(parameterName);
|
||||
}
|
||||
}
|
||||
|
||||
public static void IfNullOrWhiteSpace([NotNull] string? arg, [CallerArgumentExpression(nameof(arg))] string? parameterName = null)
|
||||
{
|
||||
if (arg is null || arg.AsSpan().IsWhiteSpace())
|
||||
{
|
||||
ThrowArgumentNullOrWhiteSpaceException(parameterName);
|
||||
}
|
||||
}
|
||||
|
||||
[DoesNotReturn]
|
||||
private static void ThrowArgumentNullOrWhiteSpaceException(string? parameterName)
|
||||
{
|
||||
if (parameterName is null)
|
||||
{
|
||||
ThrowArgumentNullException(parameterName);
|
||||
}
|
||||
|
||||
throw new ArgumentException("Value cannot be empty or composed entirely of whitespace.", parameterName);
|
||||
}
|
||||
|
||||
[DoesNotReturn]
|
||||
private static void ThrowArgumentNullException(string? parameterName) => throw new ArgumentNullException(parameterName);
|
||||
}
|
||||
|
|
@ -14,6 +14,10 @@
|
|||
<IsAotCompatible>true</IsAotCompatible>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Common\Throw.cs" Link="Utils\Throw.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Dependencies only needed by netstandard2.0 -->
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
||||
<Compile Include="..\Common\Polyfills\**\*.cs" />
|
||||
|
|
|
|||
Loading…
Reference in a new issue