public void DestructuringDepthIsLimitedByConfiguredDepth() { // Arrange var exception = new RecursiveException() { Node = new RecursiveNode() { Name = "PARENT", Child = new RecursiveNode() { Name = "CHILD 1", Child = new RecursiveNode() { Name = "CHILD 2", }, }, }, }; var destructurer = new ReflectionBasedDestructurer(1); // Act var propertiesBag = new ExceptionPropertiesBag(exception); destructurer.Destructure(exception, propertiesBag, EmptyDestructurer()); // Assert // Parent is depth 1 // First child is depth 2 var properties = propertiesBag.GetResultDictionary(); var parent = (IDictionary <string, object>)properties[nameof(RecursiveException.Node)]; Assert.Equal("PARENT", parent[nameof(RecursiveNode.Name)]); Assert.IsType <RecursiveNode>(parent[nameof(RecursiveNode.Child)]); }
public async Task CanDestructureTaskAsync() { using var cancellationTokenSource = new CancellationTokenSource(0); TaskCanceledException exception = null; try { await Task.Delay(1000, cancellationTokenSource.Token).ConfigureAwait(false); } catch (TaskCanceledException taskCancelledException) { exception = taskCancelledException; } var propertiesBag = new ExceptionPropertiesBag(exception); CreateReflectionBasedDestructurer().Destructure(exception, propertiesBag, EmptyDestructurer()); var properties = propertiesBag.GetResultDictionary(); var destructuredTaskObject = (IDictionary)properties[nameof(TaskCanceledException.Task)]; var destructuredTaskProperties = Assert.IsAssignableFrom <IDictionary <string, object> >(destructuredTaskObject); destructuredTaskProperties.Should().ContainKey(nameof(Task.Id)); destructuredTaskProperties.Should().ContainKey(nameof(Task.Status)) .WhichValue.Should().BeOfType <string>() .Which.Should().Be(nameof(TaskStatus.Canceled)); destructuredTaskProperties.Should().ContainKey(nameof(Task.CreationOptions)) .WhichValue.Should().BeOfType <string>() .Which.Should().Contain(nameof(TaskCreationOptions.None)); }
public void WhenObjectContainsCyclicReferencesInList_ThenRecursiveDestructureIsImmediatelyStopped() { // Arrange var cyclic = new MyObjectCollection { Foo = "Cyclic", }; cyclic.Reference = cyclic; var exception = new Cyclic2Exception { MyObjectCollection = new MyObjectCollection(), }; exception.MyObjectCollection.Foo = "bar"; exception.MyObjectCollection.Reference = cyclic; // Act var result = new ExceptionPropertiesBag(new Exception()); var destructurer = new ReflectionBasedDestructurer(10); destructurer.Destructure(exception, result, EmptyDestructurer()); // Assert var myObject = (List <object>)result.GetResultDictionary()[nameof(Cyclic2Exception.MyObjectCollection)]; // exception.MyObjectCollection[0] is still list var firstLevelList = Assert.IsType <List <object> >(myObject[0]); // exception.MyObjectCollection[0][0] we notice that we would again destructure "cyclic" var secondLevelList = Assert.IsType <Dictionary <string, object> >(firstLevelList[0]); Assert.Equal("Cyclic reference", secondLevelList["$ref"]); }
// To be discussed: whether we need to keep consistent behaviour even for inner exceptions //[Fact] //public void WhenDestruringAggregateException_ResultShouldBeEquivalentToAggregateExceptionDestructurer() //{ // var argumentException = ThrowAndCatchException(() => throw new ArgumentException("MESSAGE", "paramName")); // var aggregateException = ThrowAndCatchException(() => throw new AggregateException(argumentException)); // Test_ResultOfReflectionDestructurerShouldBeEquivalentToCustomOne(aggregateException, new AggregateExceptionDestructurer()); //} private static void Test_ResultOfReflectionDestructurerShouldBeEquivalentToCustomOne( Exception exception, IExceptionDestructurer customDestructurer) { // Arrange var reflectionBasedResult = new ExceptionPropertiesBag(exception); var customBasedResult = new ExceptionPropertiesBag(exception); var reflectionBasedDestructurer = CreateReflectionBasedDestructurer(); // Act Func <Exception, IReadOnlyDictionary <string, object> > InnerDestructure(IExceptionDestructurer destructurer) { return((ex) => { var resultsBag = new ExceptionPropertiesBag(ex); destructurer.Destructure(ex, resultsBag, null); return resultsBag.GetResultDictionary(); }); } reflectionBasedDestructurer.Destructure(exception, reflectionBasedResult, InnerDestructure(reflectionBasedDestructurer)); customDestructurer.Destructure(exception, customBasedResult, InnerDestructure(new ArgumentExceptionDestructurer())); // Assert var reflectionBasedDictionary = (Dictionary <string, object>)reflectionBasedResult.GetResultDictionary(); var customBasedDictionary = (Dictionary <string, object>)customBasedResult.GetResultDictionary(); reflectionBasedDictionary.Should().BeEquivalentTo(customBasedDictionary); }
public void WhenObjectContainsCyclicReferencesInTask_ThenRecursiveDestructureIsImmediatelyStopped() { // Arrange var exception = new CyclicTaskException(); var task = Task.FromException(exception); exception.Task = task; // Act var result = new ExceptionPropertiesBag(exception); var destructurer = CreateReflectionBasedDestructurer(); destructurer.Destructure(exception, result, InnerDestructurer(destructurer)); // Assert var resultsDictionary = result.GetResultDictionary(); var destructuredTask = resultsDictionary[nameof(CyclicTaskException.Task)].Should().BeAssignableTo <IDictionary <string, object> >().Which; var destructuredCyclicException = destructuredTask.Should().ContainKey(nameof(Task.Exception)) .WhichValue.Should().BeAssignableTo <IDictionary <string, object> >() .Which.Should().ContainKey(nameof(AggregateException.InnerExceptions)) .WhichValue.Should().BeAssignableTo <IReadOnlyCollection <object> >() .Which.Should().ContainSingle() .Which.Should().BeAssignableTo <IDictionary <string, object> >().Which; destructuredCyclicException.Should().ContainKey(nameof(Exception.Message)) .WhichValue.Should().BeOfType <string>() .Which.Should().Contain(nameof(CyclicTaskException)); destructuredCyclicException.Should().ContainKey(nameof(CyclicTaskException.Task)) .WhichValue.Should().BeAssignableTo <IDictionary <string, object> >() .Which.Should().ContainKey("$ref", "task was already destructured, so inner task should just contain ref"); }
public void DestructureComplexException_EachTypeOfPropertyIsDestructuredAsExpected() { // Arrange var exception = ThrowAndCatchException(() => throw new TestException()); var propertiesBag = new ExceptionPropertiesBag(exception); // Act CreateReflectionBasedDestructurer().Destructure(exception, propertiesBag, EmptyDestructurer()); // Assert var properties = propertiesBag.GetResultDictionary(); Assert.Equal("PublicValue", properties[nameof(TestException.PublicProperty)]); Assert.Equal("threw System.Exception: Exception of type 'System.Exception' was thrown.", properties[nameof(TestException.ExceptionProperty)]); Assert.DoesNotContain(properties, x => string.Equals(x.Key, "InternalProperty", StringComparison.Ordinal)); Assert.DoesNotContain(properties, x => string.Equals(x.Key, "ProtectedProperty", StringComparison.Ordinal)); Assert.DoesNotContain(properties, x => string.Equals(x.Key, "PrivateProperty", StringComparison.Ordinal)); Assert.Equal("MessageValue", properties[nameof(TestException.Message)]); #if NET461 || NET472 Assert.StartsWith("Void DestructureComplexException_EachTypeOfPropertyIsDestructuredAsExpected(", properties[nameof(TestException.TargetSite)].ToString()); #endif Assert.NotEmpty(properties[nameof(TestException.StackTrace)].ToString()); Assert.Equal("Serilog.Exceptions.Test", properties[nameof(TestException.Source)]); Assert.Equal(-2146233088, properties[nameof(TestException.HResult)]); Assert.Contains(typeof(TestException).FullName, properties["Type"].ToString(), StringComparison.Ordinal); }
public void WhenObjectContainsCyclicReferences_ThenNoStackoverflowExceptionIsThrown() { // Arrange var exception = new CyclicException { MyObject = new MyObject(), }; exception.MyObject.Foo = "bar"; exception.MyObject.Reference = exception.MyObject; exception.MyObject.Reference2 = exception.MyObject; // Act var result = new ExceptionPropertiesBag(new Exception()); var destructurer = new ReflectionBasedDestructurer(10); destructurer.Destructure(exception, result, EmptyDestructurer()); // Assert var myObject = (Dictionary <string, object>)result.GetResultDictionary()["MyObject"]; Assert.Equal("bar", myObject["Foo"]); Assert.Equal(myObject["$id"], ((Dictionary <string, object>)myObject["Reference"])["$ref"]); Assert.Equal(myObject["$id"], ((Dictionary <string, object>)myObject["Reference2"])["$ref"]); Assert.Equal("1", myObject["$id"]); }
private static Func <Exception, IReadOnlyDictionary <string, object> > InnerDestructurer( IExceptionDestructurer destructurer) => (ex) => { var resultsBag = new ExceptionPropertiesBag(ex); destructurer.Destructure(ex, resultsBag, InnerDestructurer(destructurer)); return(resultsBag.GetResultDictionary()); };
public void CannotAddProperty_WhenResultWasAlreadyAquired() { // Arrange var properties = new ExceptionPropertiesBag(new Exception(), null); properties.AddProperty("key", "value"); var results = properties.GetResultDictionary(); // Act var ex = Assert.Throws <InvalidOperationException>(() => properties.AddProperty("key2", "value2")); // Assert Assert.Equal("Cannot add exception property 'key2' to bag, after results were already collected", ex.Message); }
public void CanDestructureUriProperty() { const string uriValue = "http://localhost/property"; var exception = new UriException("test", new Uri(uriValue)); var propertiesBag = new ExceptionPropertiesBag(exception); CreateReflectionBasedDestructurer().Destructure(exception, propertiesBag, EmptyDestructurer()); var properties = propertiesBag.GetResultDictionary(); var uriPropertyValue = properties[nameof(UriException.Uri)]; Assert.IsType <string>(uriPropertyValue); Assert.Equal(uriValue, uriPropertyValue); }
public void AddedProperty_WhenFilterIsSetToIgnoreIt_IsSkipped() { // Arrange var properties = new ExceptionPropertiesBag( new Exception(), new IgnorePropertyByNameExceptionFilter(new[] { "key" })); // Act properties.AddProperty("key", "value"); // Assert var results = properties.GetResultDictionary(); Assert.Equal(0, results.Count); }
public void AddedProperty_IsAvailableInReturnedDictionary() { // Arrange var properties = new ExceptionPropertiesBag(new Exception(), null); // Act properties.AddProperty("key", "value"); // Assert var results = properties.GetResultDictionary(); Assert.Equal(1, results.Count); Assert.Contains("key", results.Keys); var value = results["key"]; Assert.Equal("value", value); }
private static void Test_ResultOfReflectionDestructurerShouldBeEquivalentToCustomOne( Exception exception, IExceptionDestructurer customDestructurer) { // Arrange var reflectionBasedResult = new ExceptionPropertiesBag(exception); var customBasedResult = new ExceptionPropertiesBag(exception); var reflectionBasedDestructurer = CreateReflectionBasedDestructurer(); // Act reflectionBasedDestructurer.Destructure(exception, reflectionBasedResult, InnerDestructurer(reflectionBasedDestructurer)); customDestructurer.Destructure(exception, customBasedResult, InnerDestructurer(new ArgumentExceptionDestructurer())); // Assert var reflectionBasedDictionary = (Dictionary <string, object>)reflectionBasedResult.GetResultDictionary(); var customBasedDictionary = (Dictionary <string, object>)customBasedResult.GetResultDictionary(); reflectionBasedDictionary.Should().BeEquivalentTo(customBasedDictionary); }
public void AddedProperty_WhenFilterIsNotSetToIgnoreIt_IsIncluded() { // Arrange var properties = new ExceptionPropertiesBag( new Exception(), new IgnorePropertyByNameExceptionFilter(new[] { "not key" })); // Act properties.AddProperty("key", "value"); // Assert var results = properties.GetResultDictionary(); Assert.Equal(1, results.Count); Assert.Contains("key", results.Keys); var value = results["key"]; Assert.Equal("value", value); }
public void CanDestructureObjectWithHiddenProperty() { var derived = new DerivedClass <int> { HiddenProperty = 123, }; var baseClass = (BaseClass)derived; baseClass.HiddenProperty = 456; var exception = new HiddenException("test", derived); var propertiesBag = new ExceptionPropertiesBag(exception); CreateReflectionBasedDestructurer().Destructure(exception, propertiesBag, EmptyDestructurer()); var properties = propertiesBag.GetResultDictionary(); var info = properties[nameof(HiddenException.Info)] as IDictionary <string, object>; Assert.Equal(derived.HiddenProperty, info[nameof(DerivedClass <object> .HiddenProperty)]); Assert.Equal(baseClass.HiddenProperty, info[$"{typeof(BaseClass).FullName}.{nameof(BaseClass.HiddenProperty)}"]); }
public void CanDestructureTask() { Task task = new TaskFactory <int>().StartNew(() => 12, TaskCreationOptions.LongRunning | TaskCreationOptions.PreferFairness); var exception = new TaskCanceledException(task); var propertiesBag = new ExceptionPropertiesBag(exception); CreateReflectionBasedDestructurer().Destructure(exception, propertiesBag, EmptyDestructurer()); var properties = propertiesBag.GetResultDictionary(); var destructuredTaskObject = (IDictionary)properties[nameof(TaskCanceledException.Task)]; var destructuredTaskProperties = Assert.IsAssignableFrom <IDictionary <string, object> >(destructuredTaskObject); destructuredTaskProperties.Should().ContainKey(nameof(Task.Id)); destructuredTaskProperties.Should().ContainKey(nameof(Task.Status)) .WhichValue.Should().BeOfType <string>() .Which.Should().Be(nameof(TaskStatus.RanToCompletion)); destructuredTaskProperties.Should().ContainKey(nameof(Task.CreationOptions)) .WhichValue.Should().BeOfType <string>() .Which.Should().Contain(nameof(TaskCreationOptions.LongRunning)) .And.Contain(nameof(TaskCreationOptions.PreferFairness)); }
public void CanDestructureUriDataItem() { const string uriValue = "http://localhost/data-item"; var exception = new Exception("test") { Data = { { "UriDataItem", new Uri(uriValue) }, }, }; var propertiesBag = new ExceptionPropertiesBag(exception); CreateReflectionBasedDestructurer().Destructure(exception, propertiesBag, EmptyDestructurer()); var properties = propertiesBag.GetResultDictionary(); var data = (IDictionary)properties[nameof(Exception.Data)]; var uriDataValue = data["UriDataItem"]; Assert.IsType <string>(uriDataValue); Assert.Equal(uriValue, uriDataValue); }
public void CanDestructureStructDataItem() { // Arrange var exception = new Exception("test"); exception.Data["data"] = new TestStruct() { ValueType = 10, ReferenceType = "ABC", }; var propertiesBag = new ExceptionPropertiesBag(exception); // Act CreateReflectionBasedDestructurer().Destructure(exception, propertiesBag, EmptyDestructurer()); // Assert var properties = propertiesBag.GetResultDictionary(); var data = (IDictionary)properties[nameof(Exception.Data)]; var testStructDataValue = data["data"]; Assert.IsAssignableFrom <TestStruct>(testStructDataValue); }
public void CanDestructureFaultedTask() { var taskException = new Exception("INNER EXCEPTION MESSAGE"); var task = Task.FromException(taskException); var exception = new TaskException("TASK EXCEPTION MESSAGE", task); var propertiesBag = new ExceptionPropertiesBag(exception); CreateReflectionBasedDestructurer().Destructure(exception, propertiesBag, InnerDestructurer(CreateReflectionBasedDestructurer())); var properties = propertiesBag.GetResultDictionary(); var destructuredTaskObject = (IDictionary)properties[nameof(TaskCanceledException.Task)]; var destructuredTaskProperties = Assert.IsAssignableFrom <IDictionary <string, object> >(destructuredTaskObject); destructuredTaskProperties.Should().ContainKey(nameof(Task.Id)); destructuredTaskProperties.Should().ContainKey(nameof(Task.Status)) .WhichValue.Should().BeOfType <string>() .Which.Should().Be(nameof(TaskStatus.Faulted)); destructuredTaskProperties.Should().ContainKey(nameof(Task.CreationOptions)) .WhichValue.Should().BeOfType <string>() .Which.Should().Be(nameof(TaskCreationOptions.None)); var taskFirstLevelExceptionDictionary = destructuredTaskProperties.Should().ContainKey(nameof(Task.Exception)) .WhichValue.Should().BeAssignableTo <IDictionary <string, object> >() .Which; taskFirstLevelExceptionDictionary.Should().ContainKey("Message") .WhichValue.Should().BeOfType <string>() .Which.Should().Contain("One or more errors occurred.", "task's first level exception is aggregate exception"); taskFirstLevelExceptionDictionary.Should().ContainKey("InnerExceptions") .WhichValue.Should().BeAssignableTo <IReadOnlyCollection <object> >() .Which.Should().ContainSingle() .Which.Should().BeAssignableTo <IDictionary <string, object> >() .Which.Should().ContainKey("Message") .WhichValue.Should().BeOfType <string>() .Which.Should().Be("INNER EXCEPTION MESSAGE"); }
public void WhenObjectContainsCyclicReferencesInDict_ThenRecursiveDestructureIsImmediatelyStopped() { // Arrange var cyclic = new MyObjectDict { Foo = "Cyclic", Reference = new Dictionary <string, object>(), }; cyclic.Reference["x"] = cyclic.Reference; var exception = new CyclicDictException { MyObjectDict = cyclic, }; // Act var result = new ExceptionPropertiesBag(new Exception()); var destructurer = new ReflectionBasedDestructurer(10); destructurer.Destructure(exception, result, EmptyDestructurer()); // Assert var myObject = (Dictionary <string, object>)result.GetResultDictionary()["MyObjectDict"]; // exception.MyObjectDict["Reference"] is still regular dictionary var firstLevelDict = Assert.IsType <Dictionary <string, object> >(myObject["Reference"]); var id = firstLevelDict["$id"]; Assert.Equal("1", id); // exception.MyObjectDict["Reference"]["x"] we notice that we are destructuring same dictionary var secondLevelDict = Assert.IsType <Dictionary <string, object> >(firstLevelDict["x"]); var refId = Assert.IsType <string>(secondLevelDict["$ref"]); Assert.Equal(id, refId); }
public void CanDestructureClassDataItem() { // Arrange var exception = new Exception("test"); exception.Data["data"] = new TestClass() { ValueType = 10, ReferenceType = "ABC", }; var propertiesBag = new ExceptionPropertiesBag(exception); // Act CreateReflectionBasedDestructurer().Destructure(exception, propertiesBag, EmptyDestructurer()); // Assert var properties = propertiesBag.GetResultDictionary(); var data = (IDictionary)properties[nameof(Exception.Data)]; var testStructDataValue = data["data"]; var destructuredStructDictionary = Assert.IsAssignableFrom <IDictionary <string, object> >(testStructDataValue); Assert.Equal(10, destructuredStructDictionary[nameof(TestClass.ValueType)]); Assert.Equal("ABC", destructuredStructDictionary[nameof(TestClass.ReferenceType)]); }