From cb018faf533439473089e227268c8f69a9c44b76 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 13 Dec 2018 11:37:00 -0800 Subject: [PATCH] Remove Microsoft.Extensions.StackTrace.Sources \n\nCommit migrated from https://github.com/dotnet/extensions/commit/1713ada32d3543e17350381f8477ce40715bfd59 --- .../ExceptionDetails/ExceptionDetails.cs | 29 -- .../ExceptionDetailsProvider.cs | 170 --------- .../StackFrame/MethodDisplayInfo.cs | 49 --- .../StackFrame/ParameterDisplayInfo.cs | 33 -- .../StackFrame/PortablePdbReader.cs | 135 ------- .../StackTrace/StackFrame/StackFrameInfo.cs | 18 - .../StackFrame/StackFrameSourceCodeInfo.cs | 54 --- .../StackTrace/StackFrame/StackTraceHelper.cs | 261 ------------- .../Microsoft.AspNetCore.Shared.Tests.csproj | 7 - src/Shared/test/Shared.Tests/Readme.txt | 4 - .../test/Shared.Tests/StackTraceHelperTest.cs | 345 ------------------ .../testassets/ThrowingLibrary/Thrower.cs | 20 - .../ThrowingLibrary/ThrowingLibrary.csproj | 8 - 13 files changed, 1133 deletions(-) delete mode 100644 src/Shared/StackTrace/ExceptionDetails/ExceptionDetails.cs delete mode 100644 src/Shared/StackTrace/ExceptionDetails/ExceptionDetailsProvider.cs delete mode 100644 src/Shared/StackTrace/StackFrame/MethodDisplayInfo.cs delete mode 100644 src/Shared/StackTrace/StackFrame/ParameterDisplayInfo.cs delete mode 100644 src/Shared/StackTrace/StackFrame/PortablePdbReader.cs delete mode 100644 src/Shared/StackTrace/StackFrame/StackFrameInfo.cs delete mode 100644 src/Shared/StackTrace/StackFrame/StackFrameSourceCodeInfo.cs delete mode 100644 src/Shared/StackTrace/StackFrame/StackTraceHelper.cs delete mode 100644 src/Shared/test/Shared.Tests/Readme.txt delete mode 100644 src/Shared/test/Shared.Tests/StackTraceHelperTest.cs delete mode 100644 src/Shared/test/testassets/ThrowingLibrary/Thrower.cs delete mode 100644 src/Shared/test/testassets/ThrowingLibrary/ThrowingLibrary.csproj diff --git a/src/Shared/StackTrace/ExceptionDetails/ExceptionDetails.cs b/src/Shared/StackTrace/ExceptionDetails/ExceptionDetails.cs deleted file mode 100644 index 8862611136..0000000000 --- a/src/Shared/StackTrace/ExceptionDetails/ExceptionDetails.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; - -namespace Microsoft.Extensions.StackTrace.Sources -{ - /// - /// Contains details for individual exception messages. - /// - internal class ExceptionDetails - { - /// - /// An individual exception - /// - public Exception Error { get; set; } - - /// - /// The generated stack frames - /// - public IEnumerable StackFrames { get; set; } - - /// - /// Gets or sets the summary message. - /// - public string ErrorMessage { get; set; } - } -} diff --git a/src/Shared/StackTrace/ExceptionDetails/ExceptionDetailsProvider.cs b/src/Shared/StackTrace/ExceptionDetails/ExceptionDetailsProvider.cs deleted file mode 100644 index 2d1dd20710..0000000000 --- a/src/Shared/StackTrace/ExceptionDetails/ExceptionDetailsProvider.cs +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using Microsoft.Extensions.FileProviders; - -namespace Microsoft.Extensions.StackTrace.Sources -{ - internal class ExceptionDetailsProvider - { - private readonly IFileProvider _fileProvider; - private readonly int _sourceCodeLineCount; - - public ExceptionDetailsProvider(IFileProvider fileProvider, int sourceCodeLineCount) - { - _fileProvider = fileProvider; - _sourceCodeLineCount = sourceCodeLineCount; - } - - public IEnumerable GetDetails(Exception exception) - { - var exceptions = FlattenAndReverseExceptionTree(exception); - - foreach (var ex in exceptions) - { - yield return new ExceptionDetails - { - Error = ex, - StackFrames = StackTraceHelper.GetFrames(ex) - .Select(frame => GetStackFrameSourceCodeInfo( - frame.MethodDisplayInfo.ToString(), - frame.FilePath, - frame.LineNumber)) - }; - } - } - - private static IEnumerable FlattenAndReverseExceptionTree(Exception ex) - { - // ReflectionTypeLoadException is special because the details are in - // the LoaderExceptions property - var typeLoadException = ex as ReflectionTypeLoadException; - if (typeLoadException != null) - { - var typeLoadExceptions = new List(); - foreach (var loadException in typeLoadException.LoaderExceptions) - { - typeLoadExceptions.AddRange(FlattenAndReverseExceptionTree(loadException)); - } - - typeLoadExceptions.Add(ex); - return typeLoadExceptions; - } - - var list = new List(); - if (ex is AggregateException aggregateException) - { - list.Add(ex); - foreach (var innerException in aggregateException.Flatten().InnerExceptions) - { - list.Add(innerException); - } - } - - else - { - while (ex != null) - { - list.Add(ex); - ex = ex.InnerException; - } - list.Reverse(); - } - - return list; - } - - // make it internal to enable unit testing - internal StackFrameSourceCodeInfo GetStackFrameSourceCodeInfo(string method, string filePath, int lineNumber) - { - var stackFrame = new StackFrameSourceCodeInfo - { - Function = method, - File = filePath, - Line = lineNumber - }; - - if (string.IsNullOrEmpty(stackFrame.File)) - { - return stackFrame; - } - - IEnumerable lines = null; - if (File.Exists(stackFrame.File)) - { - lines = File.ReadLines(stackFrame.File); - } - else - { - // Handle relative paths and embedded files - var fileInfo = _fileProvider.GetFileInfo(stackFrame.File); - if (fileInfo.Exists) - { - // ReadLines doesn't accept a stream. Use ReadLines as its more efficient - // relative to reading lines via stream reader - if (!string.IsNullOrEmpty(fileInfo.PhysicalPath)) - { - lines = File.ReadLines(fileInfo.PhysicalPath); - } - else - { - lines = ReadLines(fileInfo); - } - } - } - - if (lines != null) - { - ReadFrameContent(stackFrame, lines, stackFrame.Line, stackFrame.Line); - } - - return stackFrame; - } - - // make it internal to enable unit testing - internal void ReadFrameContent( - StackFrameSourceCodeInfo frame, - IEnumerable allLines, - int errorStartLineNumberInFile, - int errorEndLineNumberInFile) - { - // Get the line boundaries in the file to be read and read all these lines at once into an array. - var preErrorLineNumberInFile = Math.Max(errorStartLineNumberInFile - _sourceCodeLineCount, 1); - var postErrorLineNumberInFile = errorEndLineNumberInFile + _sourceCodeLineCount; - var codeBlock = allLines - .Skip(preErrorLineNumberInFile - 1) - .Take(postErrorLineNumberInFile - preErrorLineNumberInFile + 1) - .ToArray(); - - var numOfErrorLines = (errorEndLineNumberInFile - errorStartLineNumberInFile) + 1; - var errorStartLineNumberInArray = errorStartLineNumberInFile - preErrorLineNumberInFile; - - frame.PreContextLine = preErrorLineNumberInFile; - frame.PreContextCode = codeBlock.Take(errorStartLineNumberInArray).ToArray(); - frame.ContextCode = codeBlock - .Skip(errorStartLineNumberInArray) - .Take(numOfErrorLines) - .ToArray(); - frame.PostContextCode = codeBlock - .Skip(errorStartLineNumberInArray + numOfErrorLines) - .ToArray(); - } - - private static IEnumerable ReadLines(IFileInfo fileInfo) - { - using (var reader = new StreamReader(fileInfo.CreateReadStream())) - { - string line; - while ((line = reader.ReadLine()) != null) - { - yield return line; - } - } - } - } -} diff --git a/src/Shared/StackTrace/StackFrame/MethodDisplayInfo.cs b/src/Shared/StackTrace/StackFrame/MethodDisplayInfo.cs deleted file mode 100644 index b1c0ccc188..0000000000 --- a/src/Shared/StackTrace/StackFrame/MethodDisplayInfo.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) .NET Foundation. 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; -using System.Linq; -using System.Text; - -namespace Microsoft.Extensions.StackTrace.Sources -{ - internal class MethodDisplayInfo - { - public string DeclaringTypeName { get; set; } - - public string Name { get; set; } - - public string GenericArguments { get; set; } - - public string SubMethod { get; set; } - - public IEnumerable Parameters { get; set; } - - public override string ToString() - { - var builder = new StringBuilder(); - if (!string.IsNullOrEmpty(DeclaringTypeName)) - { - builder - .Append(DeclaringTypeName) - .Append("."); - } - - builder.Append(Name); - builder.Append(GenericArguments); - - builder.Append("("); - builder.Append(string.Join(", ", Parameters.Select(p => p.ToString()))); - builder.Append(")"); - - if (!string.IsNullOrEmpty(SubMethod)) - { - builder.Append("+"); - builder.Append(SubMethod); - builder.Append("()"); - } - - return builder.ToString(); - } - } -} diff --git a/src/Shared/StackTrace/StackFrame/ParameterDisplayInfo.cs b/src/Shared/StackTrace/StackFrame/ParameterDisplayInfo.cs deleted file mode 100644 index 1199a8386d..0000000000 --- a/src/Shared/StackTrace/StackFrame/ParameterDisplayInfo.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Text; - -namespace Microsoft.Extensions.StackTrace.Sources -{ - internal class ParameterDisplayInfo - { - public string Name { get; set; } - - public string Type { get; set; } - - public string Prefix { get; set; } - - public override string ToString() - { - var builder = new StringBuilder(); - if (!string.IsNullOrEmpty(Prefix)) - { - builder - .Append(Prefix) - .Append(" "); - } - - builder.Append(Type); - builder.Append(" "); - builder.Append(Name); - - return builder.ToString(); - } - } -} diff --git a/src/Shared/StackTrace/StackFrame/PortablePdbReader.cs b/src/Shared/StackTrace/StackFrame/PortablePdbReader.cs deleted file mode 100644 index ff6a4947f8..0000000000 --- a/src/Shared/StackTrace/StackFrame/PortablePdbReader.cs +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Reflection; -using System.Reflection.Metadata; -using System.Reflection.Metadata.Ecma335; -using System.Reflection.PortableExecutable; - -namespace Microsoft.Extensions.StackTrace.Sources -{ - internal class PortablePdbReader : IDisposable - { - private readonly Dictionary _cache = - new Dictionary(StringComparer.Ordinal); - - public void PopulateStackFrame(StackFrameInfo frameInfo, MethodBase method, int IlOffset) - { - if (method.Module.Assembly.IsDynamic) - { - return; - } - - var metadataReader = GetMetadataReader(method.Module.Assembly.Location); - - if (metadataReader == null) - { - return; - } - - var methodToken = MetadataTokens.Handle(method.MetadataToken); - - Debug.Assert(methodToken.Kind == HandleKind.MethodDefinition); - - var handle = ((MethodDefinitionHandle)methodToken).ToDebugInformationHandle(); - - if (!handle.IsNil) - { - var methodDebugInfo = metadataReader.GetMethodDebugInformation(handle); - var sequencePoints = methodDebugInfo.GetSequencePoints(); - SequencePoint? bestPointSoFar = null; - - foreach (var point in sequencePoints) - { - if (point.Offset > IlOffset) - { - break; - } - - if (point.StartLine != SequencePoint.HiddenLine) - { - bestPointSoFar = point; - } - } - - if (bestPointSoFar.HasValue) - { - frameInfo.LineNumber = bestPointSoFar.Value.StartLine; - frameInfo.FilePath = metadataReader.GetString(metadataReader.GetDocument(bestPointSoFar.Value.Document).Name); - } - } - } - - private MetadataReader GetMetadataReader(string assemblyPath) - { - MetadataReaderProvider provider = null; - if (!_cache.TryGetValue(assemblyPath, out provider)) - { - var pdbPath = GetPdbPath(assemblyPath); - - if (!string.IsNullOrEmpty(pdbPath) && File.Exists(pdbPath) && IsPortable(pdbPath)) - { - var pdbStream = File.OpenRead(pdbPath); - provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream); - } - - _cache[assemblyPath] = provider; - } - - return provider?.GetMetadataReader(); - } - - private static string GetPdbPath(string assemblyPath) - { - if (string.IsNullOrEmpty(assemblyPath)) - { - return null; - } - - if (File.Exists(assemblyPath)) - { - var peStream = File.OpenRead(assemblyPath); - - using (var peReader = new PEReader(peStream)) - { - foreach (var entry in peReader.ReadDebugDirectory()) - { - if (entry.Type == DebugDirectoryEntryType.CodeView) - { - var codeViewData = peReader.ReadCodeViewDebugDirectoryData(entry); - var peDirectory = Path.GetDirectoryName(assemblyPath); - return Path.Combine(peDirectory, Path.GetFileName(codeViewData.Path)); - } - } - } - } - - return null; - } - - private static bool IsPortable(string pdbPath) - { - using (var pdbStream = File.OpenRead(pdbPath)) - { - return pdbStream.ReadByte() == 'B' && - pdbStream.ReadByte() == 'S' && - pdbStream.ReadByte() == 'J' && - pdbStream.ReadByte() == 'B'; - } - } - - public void Dispose() - { - foreach (var entry in _cache) - { - entry.Value?.Dispose(); - } - - _cache.Clear(); - } - } -} diff --git a/src/Shared/StackTrace/StackFrame/StackFrameInfo.cs b/src/Shared/StackTrace/StackFrame/StackFrameInfo.cs deleted file mode 100644 index ffd91f213c..0000000000 --- a/src/Shared/StackTrace/StackFrame/StackFrameInfo.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Diagnostics; - -namespace Microsoft.Extensions.StackTrace.Sources -{ - internal class StackFrameInfo - { - public int LineNumber { get; set; } - - public string FilePath { get; set; } - - public StackFrame StackFrame { get; set; } - - public MethodDisplayInfo MethodDisplayInfo { get; set; } - } -} diff --git a/src/Shared/StackTrace/StackFrame/StackFrameSourceCodeInfo.cs b/src/Shared/StackTrace/StackFrame/StackFrameSourceCodeInfo.cs deleted file mode 100644 index 2932e083b1..0000000000 --- a/src/Shared/StackTrace/StackFrame/StackFrameSourceCodeInfo.cs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) .NET Foundation. 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; -using System.Linq; - -namespace Microsoft.Extensions.StackTrace.Sources -{ - /// - /// Contains the source code where the exception occurred. - /// - internal class StackFrameSourceCodeInfo - { - /// - /// Function containing instruction - /// - public string Function { get; set; } - - /// - /// File containing the instruction - /// - public string File { get; set; } - - /// - /// The line number of the instruction - /// - public int Line { get; set; } - - /// - /// The line preceding the frame line - /// - public int PreContextLine { get; set; } - - /// - /// Lines of code before the actual error line(s). - /// - public IEnumerable PreContextCode { get; set; } = Enumerable.Empty(); - - /// - /// Line(s) of code responsible for the error. - /// - public IEnumerable ContextCode { get; set; } = Enumerable.Empty(); - - /// - /// Lines of code after the actual error line(s). - /// - public IEnumerable PostContextCode { get; set; } = Enumerable.Empty(); - - /// - /// Specific error details for this stack frame. - /// - public string ErrorDetails { get; set; } - } -} diff --git a/src/Shared/StackTrace/StackFrame/StackTraceHelper.cs b/src/Shared/StackTrace/StackFrame/StackTraceHelper.cs deleted file mode 100644 index 5ce9a40903..0000000000 --- a/src/Shared/StackTrace/StackFrame/StackTraceHelper.cs +++ /dev/null @@ -1,261 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.ExceptionServices; -using Microsoft.Extensions.Internal; - -namespace Microsoft.Extensions.StackTrace.Sources -{ - internal class StackTraceHelper - { - public static IList GetFrames(Exception exception) - { - var frames = new List(); - - if (exception == null) - { - return frames; - } - - using (var portablePdbReader = new PortablePdbReader()) - { - var needFileInfo = true; - var stackTrace = new System.Diagnostics.StackTrace(exception, needFileInfo); - var stackFrames = stackTrace.GetFrames(); - - if (stackFrames == null) - { - return frames; - } - - for (var i = 0; i < stackFrames.Length; i++) - { - var frame = stackFrames[i]; - var method = frame.GetMethod(); - - // Always show last stackFrame - if (!ShowInStackTrace(method) && i < stackFrames.Length - 1) - { - continue; - } - - var stackFrame = new StackFrameInfo - { - StackFrame = frame, - FilePath = frame.GetFileName(), - LineNumber = frame.GetFileLineNumber(), - MethodDisplayInfo = GetMethodDisplayString(frame.GetMethod()), - }; - - if (string.IsNullOrEmpty(stackFrame.FilePath)) - { - // .NET Framework and older versions of mono don't support portable PDBs - // so we read it manually to get file name and line information - portablePdbReader.PopulateStackFrame(stackFrame, method, frame.GetILOffset()); - } - - frames.Add(stackFrame); - } - - return frames; - } - } - - internal static MethodDisplayInfo GetMethodDisplayString(MethodBase method) - { - // Special case: no method available - if (method == null) - { - return null; - } - - var methodDisplayInfo = new MethodDisplayInfo(); - - // Type name - var type = method.DeclaringType; - - var methodName = method.Name; - - if (type != null && type.IsDefined(typeof(CompilerGeneratedAttribute)) && - (typeof(IAsyncStateMachine).IsAssignableFrom(type) || typeof(IEnumerator).IsAssignableFrom(type))) - { - // Convert StateMachine methods to correct overload +MoveNext() - if (TryResolveStateMachineMethod(ref method, out type)) - { - methodDisplayInfo.SubMethod = methodName; - } - } - // ResolveStateMachineMethod may have set declaringType to null - if (type != null) - { - methodDisplayInfo.DeclaringTypeName = TypeNameHelper.GetTypeDisplayName(type, includeGenericParameterNames: true); - } - - // Method name - methodDisplayInfo.Name = method.Name; - if (method.IsGenericMethod) - { - var genericArguments = string.Join(", ", method.GetGenericArguments() - .Select(arg => TypeNameHelper.GetTypeDisplayName(arg, fullName: false, includeGenericParameterNames: true))); - methodDisplayInfo.GenericArguments += "<" + genericArguments + ">"; - } - - // Method parameters - methodDisplayInfo.Parameters = method.GetParameters().Select(parameter => - { - var parameterType = parameter.ParameterType; - - var prefix = string.Empty; - if (parameter.IsOut) - { - prefix = "out"; - } - else if (parameterType != null && parameterType.IsByRef) - { - prefix = "ref"; - } - - var parameterTypeString = "?"; - if (parameterType != null) - { - if (parameterType.IsByRef) - { - parameterType = parameterType.GetElementType(); - } - - parameterTypeString = TypeNameHelper.GetTypeDisplayName(parameterType, fullName: false, includeGenericParameterNames: true); - } - - return new ParameterDisplayInfo - { - Prefix = prefix, - Name = parameter.Name, - Type = parameterTypeString, - }; - }); - - return methodDisplayInfo; - } - - private static bool ShowInStackTrace(MethodBase method) - { - Debug.Assert(method != null); - - // Don't show any methods marked with the StackTraceHiddenAttribute - // https://github.com/dotnet/coreclr/pull/14652 - if (HasStackTraceHiddenAttribute(method)) - { - return false; - } - - - var type = method.DeclaringType; - if (type == null) - { - return true; - } - - if (HasStackTraceHiddenAttribute(type)) - { - return false; - } - - // Fallbacks for runtime pre-StackTraceHiddenAttribute - if (type == typeof(ExceptionDispatchInfo) && method.Name == "Throw") - { - return false; - } - else if (type == typeof(TaskAwaiter) || - type == typeof(TaskAwaiter<>) || - type == typeof(ConfiguredTaskAwaitable.ConfiguredTaskAwaiter) || - type == typeof(ConfiguredTaskAwaitable<>.ConfiguredTaskAwaiter)) - { - switch (method.Name) - { - case "HandleNonSuccessAndDebuggerNotification": - case "ThrowForNonSuccess": - case "ValidateEnd": - case "GetResult": - return false; - } - } - - return true; - } - - private static bool TryResolveStateMachineMethod(ref MethodBase method, out Type declaringType) - { - Debug.Assert(method != null); - Debug.Assert(method.DeclaringType != null); - - declaringType = method.DeclaringType; - - var parentType = declaringType.DeclaringType; - if (parentType == null) - { - return false; - } - - var methods = parentType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly); - if (methods == null) - { - return false; - } - - foreach (var candidateMethod in methods) - { - var attributes = candidateMethod.GetCustomAttributes(); - if (attributes == null) - { - continue; - } - - foreach (var asma in attributes) - { - if (asma.StateMachineType == declaringType) - { - method = candidateMethod; - declaringType = candidateMethod.DeclaringType; - // Mark the iterator as changed; so it gets the + annotation of the original method - // async statemachines resolve directly to their builder methods so aren't marked as changed - return asma is IteratorStateMachineAttribute; - } - } - } - - return false; - } - - private static bool HasStackTraceHiddenAttribute(MemberInfo memberInfo) - { - IList attributes; - try - { - // Accessing MembmerInfo.GetCustomAttributesData throws for some types (such as types in dynamically generated assemblies). - // We'll skip looking up StackTraceHiddenAttributes on such types. - attributes = memberInfo.GetCustomAttributesData(); - } - catch - { - return false; - } - - for (var i = 0; i < attributes.Count; i++) - { - if (attributes[i].AttributeType.Name == "StackTraceHiddenAttribute") - { - return true; - } - } - - return false; - } - } -} diff --git a/src/Shared/test/Shared.Tests/Microsoft.AspNetCore.Shared.Tests.csproj b/src/Shared/test/Shared.Tests/Microsoft.AspNetCore.Shared.Tests.csproj index 014c17aba3..1873e485a9 100644 --- a/src/Shared/test/Shared.Tests/Microsoft.AspNetCore.Shared.Tests.csproj +++ b/src/Shared/test/Shared.Tests/Microsoft.AspNetCore.Shared.Tests.csproj @@ -2,7 +2,6 @@ $(StandardTestTfms) - portable true @@ -12,15 +11,9 @@ ..\src\BenchmarkRunner\**\*.cs; ..\src\StackTrace\ExceptionDetails\**\*.cs; " /> - - - - - - diff --git a/src/Shared/test/Shared.Tests/Readme.txt b/src/Shared/test/Shared.Tests/Readme.txt deleted file mode 100644 index b818bd8148..0000000000 --- a/src/Shared/test/Shared.Tests/Readme.txt +++ /dev/null @@ -1,4 +0,0 @@ -NOTE: -1. The tests for 'ExceptionDetailProvider' and 'StackTraceHelper' in project 'Microsoft.Extensions.StackTrace.Sources' are located in Diagnostics - repo. This is because they refer to some packages from FileSystem repo which causes a circular reference and breaks the - build. \ No newline at end of file diff --git a/src/Shared/test/Shared.Tests/StackTraceHelperTest.cs b/src/Shared/test/Shared.Tests/StackTraceHelperTest.cs deleted file mode 100644 index 657a310b6e..0000000000 --- a/src/Shared/test/Shared.Tests/StackTraceHelperTest.cs +++ /dev/null @@ -1,345 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using System.Runtime.CompilerServices; -using System.Threading.Tasks; -using Microsoft.Extensions.StackTrace.Sources; -using ThrowingLibrary; -using Xunit; - -namespace Microsoft.Extensions.Internal -{ - public class StackTraceHelperTest - { - [Fact] - public void StackTraceHelper_IncludesLineNumbersForFiles() - { - // Arrange - Exception exception = null; - try - { - // Throwing an exception in the current assembly always seems to populate the full stack - // trace regardless of symbol type. Crossing assembly boundaries ensures PortablePdbReader gets used - // on desktop. - Thrower.Throw(); - } - catch (Exception ex) - { - exception = ex; - } - - // Act - var stackFrames = StackTraceHelper.GetFrames(exception); - - // Assert - Assert.Collection(stackFrames, - frame => - { - Assert.Contains("Thrower.cs", frame.FilePath); - Assert.Equal(17, frame.LineNumber); - }, - frame => - { - Assert.Contains("StackTraceHelperTest.cs", frame.FilePath); - }); - } - - [Fact] - public void StackTraceHelper_PrettyPrintsStackTraceForGenericMethods() - { - // Arrange - var exception = Record.Exception(() => GenericMethod(null)); - - // Act - var stackFrames = StackTraceHelper.GetFrames(exception); - - // Assert - var methods = stackFrames.Select(frame => frame.MethodDisplayInfo.ToString()).ToArray(); - Assert.Equal("Microsoft.Extensions.Internal.StackTraceHelperTest.GenericMethod(T val)", methods[0]); - } - - [Fact] - public void StackTraceHelper_PrettyPrintsStackTraceForMethodsWithOutParameters() - { - // Arrange - var exception = Record.Exception(() => MethodWithOutParameter(out var value)); - - // Act - var stackFrames = StackTraceHelper.GetFrames(exception); - - // Assert - var methods = stackFrames.Select(frame => frame.MethodDisplayInfo.ToString()).ToArray(); - Assert.Equal("Microsoft.Extensions.Internal.StackTraceHelperTest.MethodWithOutParameter(out int value)", methods[0]); - } - - [Fact] - public void StackTraceHelper_PrettyPrintsStackTraceForMethodsWithGenericOutParameters() - { - // Arrange - var exception = Record.Exception(() => MethodWithGenericOutParameter("Test", out int value)); - - // Act - var stackFrames = StackTraceHelper.GetFrames(exception); - - // Assert - var methods = stackFrames.Select(frame => frame.MethodDisplayInfo.ToString()).ToArray(); - Assert.Equal("Microsoft.Extensions.Internal.StackTraceHelperTest.MethodWithGenericOutParameter(string a, out TVal value)", methods[0]); - } - - [Fact] - public void StackTraceHelper_PrettyPrintsStackTraceForMethodsWithRefParameters() - { - // Arrange - var value = 0; - var exception = Record.Exception(() => MethodWithRefParameter(ref value)); - - // Act - var stackFrames = StackTraceHelper.GetFrames(exception); - - // Assert - var methods = stackFrames.Select(frame => frame.MethodDisplayInfo.ToString()).ToArray(); - Assert.Equal("Microsoft.Extensions.Internal.StackTraceHelperTest.MethodWithRefParameter(ref int value)", methods[0]); - } - - [Fact] - public void StackTraceHelper_PrettyPrintsStackTraceForMethodsWithGenericRefParameters() - { - // Arrange - var value = 0; - var exception = Record.Exception(() => MethodWithGenericRefParameter(ref value)); - - // Act - var stackFrames = StackTraceHelper.GetFrames(exception); - - // Assert - var methods = stackFrames.Select(frame => frame.MethodDisplayInfo.ToString()).ToArray(); - Assert.Equal("Microsoft.Extensions.Internal.StackTraceHelperTest.MethodWithGenericRefParameter(ref TVal value)", methods[0]); - } - - [Fact] - public void StackTraceHelper_PrettyPrintsStackTraceForMethodsWithNullableParameters() - { - // Arrange - var value = 0; - var exception = Record.Exception(() => MethodWithNullableParameter(value)); - - // Act - var stackFrames = StackTraceHelper.GetFrames(exception); - - // Assert - var methods = stackFrames.Select(frame => frame.MethodDisplayInfo.ToString()).ToArray(); - Assert.Equal("Microsoft.Extensions.Internal.StackTraceHelperTest.MethodWithNullableParameter(Nullable value)", methods[0]); - } - - [Fact] - public void StackTraceHelper_PrettyPrintsStackTraceForMethodsOnGenericTypes() - { - // Arrange - var exception = Record.Exception(() => new GenericClass().Throw(0)); - - // Act - var stackFrames = StackTraceHelper.GetFrames(exception); - - // Assert - var methods = stackFrames.Select(frame => frame.MethodDisplayInfo.ToString()).ToArray(); - Assert.Equal("Microsoft.Extensions.Internal.StackTraceHelperTest+GenericClass.Throw(T parameter)", methods[0]); - } - - [Fact] - public void StackTraceHelper_ProducesReadableOutput() - { - // Arrange - var expectedCallStack = new List() - { - "Microsoft.Extensions.Internal.StackTraceHelperTest.Iterator()+MoveNext()", - "string.Join(string separator, IEnumerable values)", - "Microsoft.Extensions.Internal.StackTraceHelperTest+GenericClass.GenericMethod(ref V value)", - "Microsoft.Extensions.Internal.StackTraceHelperTest.MethodAsync(int value)", - "Microsoft.Extensions.Internal.StackTraceHelperTest.MethodAsync(TValue value)", - "Microsoft.Extensions.Internal.StackTraceHelperTest.Method(string value)", - "Microsoft.Extensions.Internal.StackTraceHelperTest.StackTraceHelper_ProducesReadableOutput()", - }; - - Exception exception = null; - try - { - Method("test"); - } - catch (Exception ex) - { - exception = ex; - } - - // Act - var stackFrames = StackTraceHelper.GetFrames(exception); - var methodNames = stackFrames.Select(stackFrame => stackFrame.MethodDisplayInfo.ToString()).ToArray(); - - // Assert - Assert.Equal(expectedCallStack, methodNames); - } - - [Fact] - public void StackTraceHelper_DoesNotIncludeInstanceMethodsOnTypesWithStackTraceHiddenAttribute() - { - // Arrange - var exception = Record.Exception(() => InvokeMethodOnTypeWithStackTraceHiddenAttribute()); - - // Act - var stackFrames = StackTraceHelper.GetFrames(exception); - - // Assert - var methods = stackFrames.Select(frame => frame.MethodDisplayInfo.ToString()).ToArray(); - Assert.Equal("Microsoft.Extensions.Internal.StackTraceHelperTest.ThrowCore()", methods[0]); - Assert.Equal("Microsoft.Extensions.Internal.StackTraceHelperTest.InvokeMethodOnTypeWithStackTraceHiddenAttribute()", methods[1]); - } - - [Fact] - public void StackTraceHelper_DoesNotIncludeStaticMethodsOnTypesWithStackTraceHiddenAttribute() - { - // Arrange - var exception = Record.Exception(() => InvokeStaticMethodOnTypeWithStackTraceHiddenAttribute()); - - // Act - var stackFrames = StackTraceHelper.GetFrames(exception); - - // Assert - var methods = stackFrames.Select(frame => frame.MethodDisplayInfo.ToString()).ToArray(); - Assert.Equal("Microsoft.Extensions.Internal.StackTraceHelperTest.ThrowCore()", methods[0]); - Assert.Equal("Microsoft.Extensions.Internal.StackTraceHelperTest.InvokeStaticMethodOnTypeWithStackTraceHiddenAttribute()", methods[1]); - } - - [Fact] - public void StackTraceHelper_DoesNotIncludeMethodsWithStackTraceHiddenAttribute() - { - // Arrange - var exception = Record.Exception(() => new TypeWithMethodWithStackTraceHiddenAttribute().Throw()); - - // Act - var stackFrames = StackTraceHelper.GetFrames(exception); - - // Assert - var methods = stackFrames.Select(frame => frame.MethodDisplayInfo.ToString()).ToArray(); - Assert.Equal("Microsoft.Extensions.Internal.StackTraceHelperTest.ThrowCore()", methods[0]); - Assert.Equal("Microsoft.Extensions.Internal.StackTraceHelperTest+TypeWithMethodWithStackTraceHiddenAttribute.Throw()", methods[1]); - } - - [Fact] - public void GetFrames_DoesNotFailForDynamicallyGeneratedAssemblies() - { - // Arrange - var action = (Action)Expression.Lambda( - Expression.Throw( - Expression.New(typeof(Exception)))).Compile(); - var exception = Record.Exception(action); - - // Act - var frames = StackTraceHelper.GetFrames(exception).ToArray(); - - // Assert - var frame = frames[0]; - Assert.Null(frame.FilePath); - Assert.Equal($"lambda_method(Closure )", frame.MethodDisplayInfo.ToString()); - } - - [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - async Task MethodAsync(int value) - { - await Task.Delay(0); - return GenericClass.GenericMethod(ref value); - } - - [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - async Task MethodAsync(TValue value) - { - return await MethodAsync(1); - } - - [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - string Method(string value) - { - return MethodAsync(value).GetAwaiter().GetResult(); - } - - [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - static IEnumerable Iterator() - { - yield return "Success"; - throw new Exception(); - } - - [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - void MethodWithOutParameter(out int value) => throw new Exception(); - - [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - void MethodWithGenericOutParameter(string a, out TVal value) => throw new Exception(); - - [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - void MethodWithRefParameter(ref int value) => throw new Exception(); - - [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - void MethodWithGenericRefParameter(ref TVal value) => throw new Exception(); - - [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - void MethodWithNullableParameter(int? value) => throw new Exception(); - - [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - void InvokeMethodOnTypeWithStackTraceHiddenAttribute() => new TypeWithStackTraceHiddenAttribute().Throw(); - - [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - void InvokeStaticMethodOnTypeWithStackTraceHiddenAttribute() => TypeWithStackTraceHiddenAttribute.ThrowStatic(); - - class GenericClass - { - [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - public static string GenericMethod(ref V value) - { - var returnVal = ""; - for (var i = 0; i < 10; i++) - { - returnVal += string.Join(", ", Iterator()); - } - return returnVal; - } - - [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - public void Throw(T parameter) => throw new Exception(); - } - - [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - private void GenericMethod(T val) where T : class => throw new Exception(); - - private class StackTraceHiddenAttribute : Attribute - { - } - - [StackTraceHidden] - private class TypeWithStackTraceHiddenAttribute - { - [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - public void Throw() => ThrowCore(); - - [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - public static void ThrowStatic() => ThrowCore(); - } - - private class TypeWithMethodWithStackTraceHiddenAttribute - { - [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - [StackTraceHidden] - public void MethodWithStackTraceHiddenAttribute() - { - ThrowCore(); - } - - [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - public void Throw() => MethodWithStackTraceHiddenAttribute(); - } - - [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - private static void ThrowCore() => throw new Exception(); - } -} diff --git a/src/Shared/test/testassets/ThrowingLibrary/Thrower.cs b/src/Shared/test/testassets/ThrowingLibrary/Thrower.cs deleted file mode 100644 index babe2387c6..0000000000 --- a/src/Shared/test/testassets/ThrowingLibrary/Thrower.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Runtime.CompilerServices; - -namespace ThrowingLibrary -{ - // Throwing an exception in the current assembly always seems to populate the full stack - // trace regardless of symbol type. This type exists to simulate an exception thrown - // across assemblies which is the typical use case for StackTraceHelper. - public static class Thrower - { - [MethodImpl(MethodImplOptions.NoInlining)] - public static void Throw() - { - throw new DivideByZeroException(); - } - } -} diff --git a/src/Shared/test/testassets/ThrowingLibrary/ThrowingLibrary.csproj b/src/Shared/test/testassets/ThrowingLibrary/ThrowingLibrary.csproj deleted file mode 100644 index d77d392873..0000000000 --- a/src/Shared/test/testassets/ThrowingLibrary/ThrowingLibrary.csproj +++ /dev/null @@ -1,8 +0,0 @@ - - - - netstandard2.0 - portable - - -