Merge pull request #17 from benaadams/aggregate
AggregateException + Full framework testing
This commit is contained in:
commit
afb07c740e
@ -16,9 +16,11 @@ class Program
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
Console.WriteLine(ex);
|
||||||
exception = ex.Demystify();
|
exception = ex.Demystify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Console.WriteLine();
|
||||||
Console.WriteLine(exception);
|
Console.WriteLine(exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,9 +65,14 @@ class Program
|
|||||||
|
|
||||||
[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
|
||||||
static async Task<string> MethodAsync<TValue>(TValue value)
|
static async Task<string> MethodAsync<TValue>(TValue value)
|
||||||
|
{
|
||||||
|
return await MethodLocalAsync();
|
||||||
|
|
||||||
|
async Task<string> MethodLocalAsync()
|
||||||
{
|
{
|
||||||
return await MethodAsync(1);
|
return await MethodAsync(1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
|
||||||
static void RunAction(Action<object> lambda, object state)
|
static void RunAction(Action<object> lambda, object state)
|
||||||
|
|||||||
@ -12,6 +12,7 @@ using System.Reflection;
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.ExceptionServices;
|
using System.Runtime.ExceptionServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace System.Diagnostics
|
namespace System.Diagnostics
|
||||||
@ -297,6 +298,17 @@ namespace System.Diagnostics
|
|||||||
candidateConstructors = dt.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly).Where(m => m.Name == matchName);
|
candidateConstructors = dt.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly).Where(m => m.Name == matchName);
|
||||||
if (TryResolveSourceMethod(candidateConstructors, kind, matchHint, ref method, ref type, out ordinal)) return true;
|
if (TryResolveSourceMethod(candidateConstructors, kind, matchHint, ref method, ref type, out ordinal)) return true;
|
||||||
|
|
||||||
|
if (methodName == ".cctor")
|
||||||
|
{
|
||||||
|
candidateConstructors = dt.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.DeclaredOnly).Where(m => m.Name == matchName);
|
||||||
|
foreach (var cctor in candidateConstructors)
|
||||||
|
{
|
||||||
|
method = cctor;
|
||||||
|
type = dt;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,7 +333,6 @@ namespace System.Diagnostics
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var rawIL = nethodBody?.GetILAsByteArray();
|
var rawIL = nethodBody?.GetILAsByteArray();
|
||||||
if (rawIL == null) continue;
|
if (rawIL == null) continue;
|
||||||
|
|
||||||
@ -342,23 +353,15 @@ namespace System.Diagnostics
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (reader.Operand is Type t)
|
|
||||||
{
|
|
||||||
if (t == type)
|
|
||||||
{
|
|
||||||
method = candidateMethod;
|
|
||||||
type = method.DeclaringType;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GetOrdinal(MethodBase method, ref int? ordinal)
|
private static void GetOrdinal(MethodBase method, ref int? ordinal)
|
||||||
{
|
{
|
||||||
var lamdaStart = method.Name.IndexOf((char) GeneratedNameKind.LambdaMethod + "__") + 3;
|
var lamdaStart = method.Name.IndexOf((char)GeneratedNameKind.LambdaMethod + "__") + 3;
|
||||||
if (lamdaStart > 3)
|
if (lamdaStart > 3)
|
||||||
{
|
{
|
||||||
var secondStart = method.Name.IndexOf("_", lamdaStart) + 1;
|
var secondStart = method.Name.IndexOf("_", lamdaStart) + 1;
|
||||||
@ -584,7 +587,28 @@ namespace System.Diagnostics
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (type == typeof(Task) && method.Name == "ExecuteWithThreadLocal")
|
if (type == typeof(Task))
|
||||||
|
{
|
||||||
|
switch (method.Name)
|
||||||
|
{
|
||||||
|
case "ExecuteWithThreadLocal":
|
||||||
|
case "Execute":
|
||||||
|
case "ExecutionContextCallback":
|
||||||
|
case "ExecuteEntry":
|
||||||
|
case "InnerInvoke":
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (type == typeof(ExecutionContext))
|
||||||
|
{
|
||||||
|
switch (method.Name)
|
||||||
|
{
|
||||||
|
case "RunInternal":
|
||||||
|
case "Run":
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (type.Namespace == "System.Threading" && (type.Name?.StartsWith("_") ?? false))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) Ben A Adams. All rights reserved.
|
// Copyright (c) Ben A Adams. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic.Enumerable;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace System.Diagnostics
|
namespace System.Diagnostics
|
||||||
@ -20,6 +21,14 @@ namespace System.Diagnostics
|
|||||||
stackTraceString.SetValue(exception, stackTrace.ToString());
|
stackTraceString.SetValue(exception, stackTrace.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (exception is AggregateException aggEx)
|
||||||
|
{
|
||||||
|
foreach (var ex in EnumerableIList.Create(aggEx.InnerExceptions))
|
||||||
|
{
|
||||||
|
ex.Demystify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
exception.InnerException?.Demystify();
|
exception.InnerException?.Demystify();
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
|
|||||||
@ -19,7 +19,7 @@ namespace System.Diagnostics.Internal
|
|||||||
|
|
||||||
public OpCode OpCode { get; private set; }
|
public OpCode OpCode { get; private set; }
|
||||||
public int MetadataToken { get; private set; }
|
public int MetadataToken { get; private set; }
|
||||||
public object Operand { get; private set; }
|
public MemberInfo Operand { get; private set; }
|
||||||
|
|
||||||
public bool Read(MethodBase methodInfo)
|
public bool Read(MethodBase methodInfo)
|
||||||
{
|
{
|
||||||
@ -35,13 +35,13 @@ namespace System.Diagnostics.Internal
|
|||||||
OpCode ReadOpCode()
|
OpCode ReadOpCode()
|
||||||
{
|
{
|
||||||
byte instruction = ReadByte();
|
byte instruction = ReadByte();
|
||||||
if (instruction != 254)
|
if (instruction < 254)
|
||||||
return singleByteOpCode[instruction];
|
return singleByteOpCode[instruction];
|
||||||
else
|
else
|
||||||
return doubleByteOpCode[ReadByte()];
|
return doubleByteOpCode[ReadByte()];
|
||||||
}
|
}
|
||||||
|
|
||||||
object ReadOperand(OpCode code, MethodBase methodInfo)
|
MemberInfo ReadOperand(OpCode code, MethodBase methodInfo)
|
||||||
{
|
{
|
||||||
MetadataToken = 0;
|
MetadataToken = 0;
|
||||||
switch (code.OperandType)
|
switch (code.OperandType)
|
||||||
@ -50,12 +50,24 @@ namespace System.Diagnostics.Internal
|
|||||||
MetadataToken = ReadInt();
|
MetadataToken = ReadInt();
|
||||||
Type[] methodArgs = null;
|
Type[] methodArgs = null;
|
||||||
if (methodInfo.GetType() != typeof(ConstructorInfo) && !methodInfo.GetType().IsSubclassOf(typeof(ConstructorInfo)))
|
if (methodInfo.GetType() != typeof(ConstructorInfo) && !methodInfo.GetType().IsSubclassOf(typeof(ConstructorInfo)))
|
||||||
|
{
|
||||||
methodArgs = methodInfo.GetGenericArguments();
|
methodArgs = methodInfo.GetGenericArguments();
|
||||||
|
}
|
||||||
Type[] typeArgs = null;
|
Type[] typeArgs = null;
|
||||||
if (methodInfo.DeclaringType != null)
|
if (methodInfo.DeclaringType != null)
|
||||||
|
{
|
||||||
typeArgs = methodInfo.DeclaringType.GetGenericArguments();
|
typeArgs = methodInfo.DeclaringType.GetGenericArguments();
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
return methodInfo.Module.ResolveMember(MetadataToken, typeArgs, methodArgs);
|
return methodInfo.Module.ResolveMember(MetadataToken, typeArgs, methodArgs);
|
||||||
}
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Can return System.ArgumentException : Token xxx is not a valid MemberInfo token in the scope of module xxx.dll
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
88
test/Ben.Demystifier.Test/AggregateException.cs
Normal file
88
test/Ben.Demystifier.Test/AggregateException.cs
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Demystify
|
||||||
|
{
|
||||||
|
public class AggregateException
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void DemystifiesAggregateExceptions()
|
||||||
|
{
|
||||||
|
Exception demystifiedException = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var tasks = new List<Task>
|
||||||
|
{
|
||||||
|
Task.Run(async () => await Throw1()),
|
||||||
|
Task.Run(async () => await Throw2()),
|
||||||
|
Task.Run(async () => await Throw3())
|
||||||
|
};
|
||||||
|
|
||||||
|
Task.WaitAll(tasks.ToArray());
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
demystifiedException = ex.Demystify();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var stackTrace = demystifiedException.ToString();
|
||||||
|
stackTrace = ReplaceLineEndings.Replace(stackTrace, "");
|
||||||
|
var trace = string.Join("", stackTrace.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)
|
||||||
|
// Remove items that vary between test runners
|
||||||
|
.Where(s =>
|
||||||
|
s != " at Task Demystify.DynamicCompilation.DoesNotPreventStackTrace()+()=>{}" &&
|
||||||
|
!s.Contains("System.Threading.Tasks.Task.WaitAll")
|
||||||
|
)
|
||||||
|
.Skip(1)
|
||||||
|
.ToArray())
|
||||||
|
// Remove Full framework back arrow
|
||||||
|
.Replace("<---", "");
|
||||||
|
|
||||||
|
var expected = string.Join("", new[] {
|
||||||
|
" at async Task Demystify.AggregateException.Throw1()",
|
||||||
|
" at async void Demystify.AggregateException.DemystifiesAggregateExceptions()+(?)=>{}",
|
||||||
|
" --- End of inner exception stack trace ---",
|
||||||
|
" at void Demystify.AggregateException.DemystifiesAggregateExceptions()",
|
||||||
|
"---> (Inner Exception #0) System.ArgumentException: Value does not fall within the expected range.",
|
||||||
|
" at async Task Demystify.AggregateException.Throw1()",
|
||||||
|
" at async void Demystify.AggregateException.DemystifiesAggregateExceptions()+(?)=>{}",
|
||||||
|
"---> (Inner Exception #1) System.NullReferenceException: Object reference not set to an instance of an object.",
|
||||||
|
" at async Task Demystify.AggregateException.Throw2()",
|
||||||
|
" at async void Demystify.AggregateException.DemystifiesAggregateExceptions()+(?)=>{}",
|
||||||
|
"---> (Inner Exception #2) System.InvalidOperationException: Operation is not valid due to the current state of the object.",
|
||||||
|
" at async Task Demystify.AggregateException.Throw3()",
|
||||||
|
" at async void Demystify.AggregateException.DemystifiesAggregateExceptions()+(?)=>{}"});
|
||||||
|
|
||||||
|
Assert.Equal(expected, trace);
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task Throw1()
|
||||||
|
{
|
||||||
|
await Task.Delay(1).ConfigureAwait(false);
|
||||||
|
throw new ArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task Throw2()
|
||||||
|
{
|
||||||
|
await Task.Delay(1).ConfigureAwait(false);
|
||||||
|
throw new NullReferenceException();
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task Throw3()
|
||||||
|
{
|
||||||
|
await Task.Delay(1).ConfigureAwait(false);
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Regex ReplaceLineEndings = new Regex(" in [^\n\r]+");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
<TargetFrameworks>netcoreapp2.0;net46</TargetFrameworks>
|
||||||
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@ -38,7 +38,7 @@ namespace Demystify
|
|||||||
// Assert
|
// Assert
|
||||||
var stackTrace = demystifiedException.ToString();
|
var stackTrace = demystifiedException.ToString();
|
||||||
stackTrace = ReplaceLineEndings.Replace(stackTrace, "");
|
stackTrace = ReplaceLineEndings.Replace(stackTrace, "");
|
||||||
var trace = stackTrace.Split(Environment.NewLine)
|
var trace = stackTrace.Split(new[] { Environment.NewLine }, StringSplitOptions.None)
|
||||||
// Remove items that vary between test runners
|
// Remove items that vary between test runners
|
||||||
.Where(s =>
|
.Where(s =>
|
||||||
s != " at void System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, object state)" &&
|
s != " at void System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, object state)" &&
|
||||||
|
|||||||
@ -22,16 +22,21 @@ namespace Demystify
|
|||||||
stackFrame => stackFrame.MethodInfo.ToString()
|
stackFrame => stackFrame.MethodInfo.ToString()
|
||||||
)
|
)
|
||||||
// Remove Framework method that can be optimized out (inlined)
|
// Remove Framework method that can be optimized out (inlined)
|
||||||
.Where(methodName => methodName != "System.Collections.Generic.List<T>+Enumerator.MoveNext()")
|
.Where(methodName => !methodName.StartsWith("bool System.Collections.Generic.List<T>+"));
|
||||||
// Don't include this method as call stack shared between multiple tests
|
|
||||||
.SkipLast(1);
|
var count = methodNames.Count();
|
||||||
|
methodNames = methodNames.Take(count - 1);
|
||||||
|
|
||||||
foreach (var method in methodNames)
|
|
||||||
{
|
|
||||||
Console.WriteLine(method.ToString());
|
|
||||||
}
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal (ExpectedCallStack, methodNames.ToList());
|
var expected = ExpectedCallStack.ToArray();
|
||||||
|
var trace = methodNames.ToArray();
|
||||||
|
|
||||||
|
Assert.Equal(expected.Length, trace.Length);
|
||||||
|
|
||||||
|
for (var i = 0; i < expected.Length; i++)
|
||||||
|
{
|
||||||
|
Assert.Equal(expected[i], trace[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -52,7 +57,6 @@ namespace Demystify
|
|||||||
|
|
||||||
static List<string> ExpectedCallStack = new List<string>()
|
static List<string> ExpectedCallStack = new List<string>()
|
||||||
{
|
{
|
||||||
"bool System.Collections.Generic.List<T>+Enumerator.MoveNextRare()",
|
|
||||||
"IEnumerable<string> Demystify.MixedStack.Iterator()+MoveNext()",
|
"IEnumerable<string> Demystify.MixedStack.Iterator()+MoveNext()",
|
||||||
"string string.Join(string separator, IEnumerable<string> values)",
|
"string string.Join(string separator, IEnumerable<string> values)",
|
||||||
"string Demystify.MixedStack+GenericClass<T>.GenericMethod<V>(ref V value)",
|
"string Demystify.MixedStack+GenericClass<T>.GenericMethod<V>(ref V value)",
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
@ -28,13 +29,12 @@ namespace Demystify
|
|||||||
// Assert
|
// Assert
|
||||||
var stackTrace = demystifiedException.ToString();
|
var stackTrace = demystifiedException.ToString();
|
||||||
stackTrace = ReplaceLineEndings.Replace(stackTrace, "");
|
stackTrace = ReplaceLineEndings.Replace(stackTrace, "");
|
||||||
var trace = stackTrace.Split(Environment.NewLine);
|
var trace = stackTrace.Split(new[]{Environment.NewLine}, StringSplitOptions.None);
|
||||||
|
|
||||||
Assert.Equal(
|
Assert.Equal(
|
||||||
new[] {
|
new[] {
|
||||||
"System.Exception: Exception of type 'System.Exception' was thrown. ---> System.Exception: Exception of type 'System.Exception' was thrown.",
|
"System.Exception: Exception of type 'System.Exception' was thrown. ---> System.Exception: Exception of type 'System.Exception' was thrown.",
|
||||||
" at Task Demystify.NonThrownException.DoesNotPreventThrowStackTrace()+()=>{}",
|
" at Task Demystify.NonThrownException.DoesNotPreventThrowStackTrace()+()=>{}",
|
||||||
" at void System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, object state)",
|
|
||||||
" at async Task Demystify.NonThrownException.DoesNotPreventThrowStackTrace()",
|
" at async Task Demystify.NonThrownException.DoesNotPreventThrowStackTrace()",
|
||||||
" --- End of inner exception stack trace ---"},
|
" --- End of inner exception stack trace ---"},
|
||||||
trace);
|
trace);
|
||||||
@ -52,13 +52,12 @@ namespace Demystify
|
|||||||
// Assert
|
// Assert
|
||||||
stackTrace = demystifiedException.ToString();
|
stackTrace = demystifiedException.ToString();
|
||||||
stackTrace = ReplaceLineEndings.Replace(stackTrace, "");
|
stackTrace = ReplaceLineEndings.Replace(stackTrace, "");
|
||||||
trace = stackTrace.Split(Environment.NewLine);
|
trace = stackTrace.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
|
||||||
|
|
||||||
Assert.Equal(
|
Assert.Equal(
|
||||||
new[] {
|
new[] {
|
||||||
"System.Exception: Exception of type 'System.Exception' was thrown. ---> System.Exception: Exception of type 'System.Exception' was thrown.",
|
"System.Exception: Exception of type 'System.Exception' was thrown. ---> System.Exception: Exception of type 'System.Exception' was thrown.",
|
||||||
" at Task Demystify.NonThrownException.DoesNotPreventThrowStackTrace()+()=>{}",
|
" at Task Demystify.NonThrownException.DoesNotPreventThrowStackTrace()+()=>{}",
|
||||||
" at void System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, object state)",
|
|
||||||
" at async Task Demystify.NonThrownException.DoesNotPreventThrowStackTrace()",
|
" at async Task Demystify.NonThrownException.DoesNotPreventThrowStackTrace()",
|
||||||
" --- End of inner exception stack trace ---",
|
" --- End of inner exception stack trace ---",
|
||||||
" at async Task Demystify.NonThrownException.DoesNotPreventThrowStackTrace()"
|
" at async Task Demystify.NonThrownException.DoesNotPreventThrowStackTrace()"
|
||||||
@ -78,11 +77,14 @@ namespace Demystify
|
|||||||
// Assert
|
// Assert
|
||||||
var stackTrace = est.ToString();
|
var stackTrace = est.ToString();
|
||||||
stackTrace = ReplaceLineEndings.Replace(stackTrace, "");
|
stackTrace = ReplaceLineEndings.Replace(stackTrace, "");
|
||||||
var trace = stackTrace.Split(Environment.NewLine);
|
var trace = stackTrace.Split(new[] { Environment.NewLine }, StringSplitOptions.None)
|
||||||
|
// Remove Full framework entries
|
||||||
|
.Where(s => !s.StartsWith(" at bool System.Threading._ThreadPoolWaitCallbac") &&
|
||||||
|
!s.StartsWith(" at void System.Threading.Tasks.Task.System.Thre"));
|
||||||
|
|
||||||
|
|
||||||
Assert.Equal(
|
Assert.Equal(
|
||||||
new[] {
|
new[] {
|
||||||
" at void System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, object state)",
|
|
||||||
" at bool System.Threading.ThreadPoolWorkQueue.Dispatch()"},
|
" at bool System.Threading.ThreadPoolWorkQueue.Dispatch()"},
|
||||||
trace);
|
trace);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user