From 5eb9c25574671a8a4bdd4901343fbb938d0ddb6a Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Mon, 13 Nov 2017 12:14:12 +0000 Subject: [PATCH] AggregateException --- src/Ben.Demystifier/ExceptionExtentions.cs | 9 ++ .../AggregateException.cs | 88 +++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 test/Ben.Demystifier.Test/AggregateException.cs diff --git a/src/Ben.Demystifier/ExceptionExtentions.cs b/src/Ben.Demystifier/ExceptionExtentions.cs index f14ee45..b4ab1b9 100644 --- a/src/Ben.Demystifier/ExceptionExtentions.cs +++ b/src/Ben.Demystifier/ExceptionExtentions.cs @@ -1,6 +1,7 @@ // 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. +using System.Collections.Generic.Enumerable; using System.Reflection; namespace System.Diagnostics @@ -20,6 +21,14 @@ namespace System.Diagnostics stackTraceString.SetValue(exception, stackTrace.ToString()); } + if (exception is AggregateException aggEx) + { + foreach (var ex in EnumerableIList.Create(aggEx.InnerExceptions)) + { + ex.Demystify(); + } + } + exception.InnerException?.Demystify(); } catch diff --git a/test/Ben.Demystifier.Test/AggregateException.cs b/test/Ben.Demystifier.Test/AggregateException.cs new file mode 100644 index 0000000..a33d319 --- /dev/null +++ b/test/Ben.Demystifier.Test/AggregateException.cs @@ -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.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]+"); + } +}