private static string?TryGetSourceFilePath(TestResult testResult, StackFrame?stackFrame) { // See if test runner provided it (never actually happens) if (!string.IsNullOrWhiteSpace(testResult.TestCase.CodeFilePath)) { return(testResult.TestCase.CodeFilePath); } // Try to extract it from stack trace (works only if there was an exception) if (!string.IsNullOrWhiteSpace(stackFrame?.FilePath)) { return(stackFrame.FilePath); } // Get the project file path instead (not ideal, but the best we can do) if (!string.IsNullOrWhiteSpace(testResult.TestCase.Source)) { var projectFilePath = TryGetProjectFilePath(testResult.TestCase.Source); if (!string.IsNullOrWhiteSpace(projectFilePath)) { return(projectFilePath); } } return(null); }
public StackFrameInfo(int lineNumber, string?filePath, StackFrame?stackFrame, MethodDisplayInfo?methodDisplayInfo) { LineNumber = lineNumber; FilePath = filePath; StackFrame = stackFrame; MethodDisplayInfo = methodDisplayInfo; }
internal static bool TryParseChrome(string line, out StackFrame?frame) { frame = null; var match = ChromeRe.Match(line); if (!match.Success) { return(false); } var isNative = match.Groups[2].Value?.IndexOf("native", StringComparison.Ordinal) == 0; var isEval = match.Groups[2].Value?.IndexOf("eval", StringComparison.Ordinal) == 0; frame = new StackFrame { File = !isNative ? match.Groups[2].Value : null, Method = !string.IsNullOrEmpty(match.Groups[1]?.Value) ? match.Groups[1].Value : null, Arguments = isNative ? new[] { match.Groups[2].Value } : Array.Empty <string>(), LineNumber = !string.IsNullOrEmpty(match.Groups[3].Value) ? int.Parse(match.Groups[3].Value) : (int?)null, ColumnNumber = !string.IsNullOrEmpty(match.Groups[4].Value) ? int.Parse(match.Groups[4].Value) : (int?)null }; var submatch = ChromeEvalRe.Match(match.Groups[2].Value); if (isEval && submatch.Success) { frame.File = !isNative ? submatch.Groups[1].Value : null; frame.LineNumber = !string.IsNullOrEmpty(submatch.Groups[2].Value) ? int.Parse(submatch.Groups[2].Value) : (int?)null; frame.ColumnNumber = !string.IsNullOrEmpty(submatch.Groups[3].Value) ? int.Parse(submatch.Groups[3].Value) : (int?)null; } return(true); }
internal static bool TryParseGecko(string line, out StackFrame?frame) { frame = null; var match = GeckoRe.Match(line); if (!match.Success) { return(false); } var isEval = match.Groups[3].Value.IndexOf("> eval", StringComparison.Ordinal) > -1; frame = new StackFrame { File = match.Groups[3].Value, Method = !string.IsNullOrEmpty(match.Groups[1]?.Value) ? match.Groups[1].Value : null, Arguments = !string.IsNullOrEmpty(match.Groups[2].Value) ? match.Groups[2].Value.Split(',') : Array.Empty <string>(), LineNumber = !string.IsNullOrEmpty(match.Groups[4].Value) ? int.Parse(match.Groups[4].Value) : (int?)null, ColumnNumber = !string.IsNullOrEmpty(match.Groups[5].Value) ? int.Parse(match.Groups[5].Value) : (int?)null, }; var submatch = GeckoEvalRe.Match(line); if (isEval && submatch.Success) { frame.File = submatch.Groups[1].Value; frame.LineNumber = int.Parse(submatch.Groups[2].Value); frame.ColumnNumber = null; } return(true); }
private void RunScriptChecked(UpgradeScript script) { try { script.Method.Invoke(); } catch (Exception e) { int line = 0; StackTrace stack = new StackTrace(e, true); for (int frameIndex = 0; frameIndex < stack.FrameCount; frameIndex++) { StackFrame?frame = stack.GetFrame(frameIndex); MethodBase?method = frame?.GetMethod(); if (method is null) { continue; } VersionAttribute?attr = method.GetCustomAttribute <VersionAttribute>(); if (attr is not null) { line = frame?.GetFileLineNumber() ?? 0; break; } } throw new InvalidOperationException($"Error in script version {script.Major}.{script.Minor}.{script.Patch}, line {line} -> {e.Message}", e); } }
public static string GetTypeName() { StackTrace trace = new StackTrace(); StackFrame?frame = trace.GetFrame(3); if (frame is null) { return(string.Empty); } MethodBase?method = frame.GetMethod(); if (method is null) { return(string.Empty); } Type?declaringType = method.DeclaringType; if (declaringType is null) { return(string.Empty); } string?name = declaringType.ReflectedType?.FullName; if (string.IsNullOrEmpty(name)) { return(declaringType.FullName ?? string.Empty); } return(name); }
public List <string> FirstNonWrappedTraceStack(Type typeToIgnore, Exception ex, int fromLevel) { #if WINDOWS_UWP List <string> stackFrames = new List <string>(); stackFrames.Add(Environment.StackTrace); return(stackFrames); #else try { List <string> stackFrames = new(); StackTrace trace = new(ex, fromLevel, true); bool firstNonWrapErr = false; string ignoreTypeName = typeToIgnore.Name; for (int i = 0; i < trace.FrameCount; i++) { StackFrame?sf = trace.GetFrame(i); if (sf == null) { return(stackFrames); } string frameClass = ClassName(sf); // Skip over all entries until you hit the first not to ignore if (!firstNonWrapErr) { if (frameClass != ignoreTypeName && !IsInternalClass(frameClass)) { firstNonWrapErr = true; } else { continue; } } if (frameClass != ignoreTypeName && !IsInternalClass(frameClass)) { stackFrames.Add( // Also ignore all instances of type to ignore String.Format(" {0} : Line:{1} - {2}.{3}", FileName(sf), Line(sf), frameClass, MethodName(sf))); } } return(stackFrames); } catch (Exception) { List <string> stackFrames = new(); stackFrames.Add("BLAH"); return(stackFrames); } #endif }
private static int?TryGetSourceLine(TestResult testResult, StackFrame?stackFrame) { // See if test runner provided it (never actually happens) if (testResult.TestCase.LineNumber > 0) { return(testResult.TestCase.LineNumber); } // Try to extract it from stack trace (works only if there was an exception) return(stackFrame?.Line); }
/// <summary> /// Initializes a new instance of the <see cref="Frame"/> class. /// </summary> /// <param name="frame">The frame.</param> public Frame(StackFrame?frame) { if (frame == null) { return; } Method = GetMethod(frame); FileName = GetFileName(frame); LineNo = GetLineNumber(frame); ColNo = LineNo.HasValue ? GetFileColumnNumber(frame) : null; }
/// <summary> /// Walk through stack until you encounter the first class that is not to be ignored and /// whose method does not have the <> /// </summary> /// <param name="typeToIgnore">Type to ignore as you travel the stack</param> /// <returns>The class containing class and method information</returns> public ErrorLocation FirstNonWrappedMethod(Type typeToIgnore) { #if WINDOWS_UWP // remove if when Windows universal implements the default constructor on StackTrace return(new ErrorLocation()); #else // Go at least one up to ignore this method. int index = 1; StackTrace st = new(); MethodBase?mb = st.GetFrame(index)?.GetMethod(); if (mb != null) { while (true) { Type?declaringType = mb.DeclaringType; if (declaringType == null) { return(new ErrorLocation()); } if ((typeToIgnore == null) || (declaringType.Name != typeToIgnore.Name && !IsInternalClass(declaringType.Name)) && !mb.Name.Contains('<')) { return(new ErrorLocation(declaringType.Name, mb.Name)); } ++index; StackFrame?sf = st.GetFrame(index); if (sf == null) { return(new ErrorLocation(declaringType.Name, mb.Name)); } MethodBase?tmp = sf.GetMethod(); if (tmp == null) { return(new ErrorLocation(declaringType.Name, mb.Name)); } mb = tmp; } } else { return(new ErrorLocation()); } #endif }
private static void _Log(LogLevel level, string message, int stackFrameIndex = 2) { if (LogFunction != null) { StackTrace?stackTrace = new StackTrace(); StackFrame?stackFrame = stackTrace.GetFrame(stackFrameIndex); if (stackFrame != null) { System.Reflection.MethodBase?method = stackFrame.GetMethod(); if (method != null) { Type?type = method.DeclaringType; if (type != null) { LogFunction(type, level, message); } } } } }
internal static bool TryParseJsc(string line, out StackFrame?frame) { frame = null; var match = JscRe.Match(line); if (!match.Success) { return(false); } frame = new StackFrame { File = match.Groups[3].Value, Method = !string.IsNullOrEmpty(match.Groups[1].Value) ? match.Groups[1].Value : null, Arguments = Array.Empty <string>(), LineNumber = int.Parse(match.Groups[4].Value), ColumnNumber = !string.IsNullOrEmpty(match.Groups[5].Value) ? int.Parse(match.Groups[5].Value) : (int?)null }; return(true); }
internal void ToString(TraceFormat traceFormat, StringBuilder sb) { // Passing a default string for "at" in case SR.UsingResourceKeys() is true // as this is a special case and we don't want to have "Word_At" on stack traces. string word_At = SR.GetResourceString(nameof(SR.Word_At), defaultString: "at"); // We also want to pass in a default for inFileLineNumber. string inFileLineNum = SR.GetResourceString(nameof(SR.StackTrace_InFileLineNumber), defaultString: "in {0}:line {1}"); bool fFirstFrame = true; for (int iFrameIndex = 0; iFrameIndex < _numOfFrames; iFrameIndex++) { StackFrame?sf = GetFrame(iFrameIndex); MethodBase?mb = sf?.GetMethod(); if (mb != null && (ShowInStackTrace(mb) || (iFrameIndex == _numOfFrames - 1))) // Don't filter last frame { // We want a newline at the end of every line except for the last if (fFirstFrame) { fFirstFrame = false; } else { sb.AppendLine(); } sb.AppendFormat(CultureInfo.InvariantCulture, " {0} ", word_At); bool isAsync = false; Type? declaringType = mb.DeclaringType; string methodName = mb.Name; bool methodChanged = false; if (declaringType != null && declaringType.IsDefined(typeof(CompilerGeneratedAttribute), inherit: false)) { isAsync = typeof(IAsyncStateMachine).IsAssignableFrom(declaringType); if (isAsync || typeof(IEnumerator).IsAssignableFrom(declaringType)) { methodChanged = TryResolveStateMachineMethod(ref mb, out declaringType); } } // if there is a type (non global method) print it // ResolveStateMachineMethod may have set declaringType to null if (declaringType != null) { // Append t.FullName, replacing '+' with '.' string fullName = declaringType.FullName !; for (int i = 0; i < fullName.Length; i++) { char ch = fullName[i]; sb.Append(ch == '+' ? '.' : ch); } sb.Append('.'); } sb.Append(mb.Name); // deal with the generic portion of the method if (mb is MethodInfo mi && mi.IsGenericMethod) { Type[] typars = mi.GetGenericArguments(); sb.Append('['); int k = 0; bool fFirstTyParam = true; while (k < typars.Length) { if (!fFirstTyParam) { sb.Append(','); } else { fFirstTyParam = false; } sb.Append(typars[k].Name); k++; } sb.Append(']'); } ParameterInfo[]? pi = null; try { pi = mb.GetParameters(); } catch { // The parameter info cannot be loaded, so we don't // append the parameter list. } if (pi != null) { // arguments printing sb.Append('('); bool fFirstParam = true; for (int j = 0; j < pi.Length; j++) { if (!fFirstParam) { sb.Append(", "); } else { fFirstParam = false; } string typeName = "<UnknownType>"; if (pi[j].ParameterType != null) { typeName = pi[j].ParameterType.Name; } sb.Append(typeName); sb.Append(' '); sb.Append(pi[j].Name); } sb.Append(')'); } if (methodChanged) { // Append original method name e.g. +MoveNext() sb.Append('+'); sb.Append(methodName); sb.Append('(').Append(')'); } // source location printing if (sf !.GetILOffset() != -1) { // If we don't have a PDB or PDB-reading is disabled for the module, // then the file name will be null. string?fileName = sf.GetFileName(); if (fileName != null) { // tack on " in c:\tmp\MyFile.cs:line 5" sb.Append(' '); sb.AppendFormat(CultureInfo.InvariantCulture, inFileLineNum, fileName, sf.GetFileLineNumber()); } } // Skip EDI boundary for async if (sf.IsLastFrameFromForeignExceptionStackTrace && !isAsync) { sb.AppendLine(); // Passing default for Exception_EndStackTraceFromPreviousThrow in case SR.UsingResourceKeys is set. sb.Append(SR.GetResourceString(nameof(SR.Exception_EndStackTraceFromPreviousThrow), defaultString: "--- End of stack trace from previous location ---")); } } } if (traceFormat == TraceFormat.TrailingNewLine) { sb.AppendLine(); } }
/// <summary> /// Run selected cases. /// </summary> /// <param name="which">List of names of test cases to run. If the test case names begin with these values they will run.</param> public void RunSuites(string[] which) { // Locate the test cases. Dictionary <string, TestSuite> suites = new(); foreach (Type t in Assembly.GetCallingAssembly().GetTypes()) { if (t.BaseType is not null && t.BaseType.Name.Contains("TestSuite")) { // It's a test suite. Is it requested? foreach (string ssuite in which) { if (t.Name.StartsWith(ssuite)) { object?o = Activator.CreateInstance(t); if (o is not null) { suites.Add(t.Name, (TestSuite)o); } else { Context.OutputLines.Add($"Couldn't create {t.BaseType.Name}"); } } } } } DateTime startTime = DateTime.Now; // Run through to execute suites. foreach (string ss in suites.Keys) { Context.CurrentSuiteId = ss; TestSuite tc = suites[ss]; tc.Context = Context; Context.CurrentSuitePass = true; Context.CurrentCasePass = true; Context.PropertyLines.Clear(); // Document the start of the suite. switch (Context.Format) { case OutputFormat.Xml: tc.RecordVerbatim($" <testsuite name = {ss}>"); break; case OutputFormat.Readable: tc.RecordVerbatim($"Suite {ss}"); break; } try { // Run the suite. tc.RunSuite(); } catch (AssertException ex) { // Deliberate exception. tc.RecordResult(false, ex.Message, ex.File, ex.Line); } catch (Exception ex) { // Out of scope exception. Top frame contains the cause. StackTrace st = new(ex, true); StackFrame?frame = st.GetFrame(0); if (frame is not null) { int line = frame.GetFileLineNumber(); string fn = Path.GetFileName(frame !.GetFileName() !); string msg = $"{ex.Message} ({fn}:{line})"; tc.RecordResult(false, msg, fn, line); } } // Completed the suite, update the counts. Context.NumSuitesRun++; Context.NumCasesRun += tc.CaseCnt; Context.NumCasesFailed += tc.CaseFailCnt; switch (Context.Format) { case OutputFormat.Xml: // Any properties? if (Context.PropertyLines.Count > 0) { tc.RecordVerbatim($" <properties>"); Context.PropertyLines.ForEach(l => tc.RecordVerbatim(l)); tc.RecordVerbatim($" </properties>"); } tc.RecordVerbatim($" </testsuite>"); break; case OutputFormat.Readable: Context.OutputLines.Add($""); break; } } // Finished the test run, prepare the summary. DateTime endTime = DateTime.Now; TimeSpan dur = endTime - startTime; string sdur = dur.ToString(TIME_FORMAT); List <string> preamble = new(); switch (Context.Format) { case OutputFormat.Xml: preamble.Add($"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); preamble.Add($"<testsuites tests={Context.NumCasesRun} failures={Context.NumCasesFailed} time={sdur} >"); break; case OutputFormat.Readable: string pass = Context.NumCasesFailed > 0 ? "Fail" : "Pass"; preamble.Add($"#------------------------------------------------------------------"); preamble.Add($"# Unit Test Report"); preamble.Add($"# Start Time: {startTime.ToString(DATE_TIME_FORMAT_MSEC)}"); preamble.Add($"# Duration: {sdur}"); //preamble.Add($"# Suites Run: {Context.NumSuitesRun}"); //preamble.Add($"# Suites Failed: {Context.NumSuitesFailed}"); preamble.Add($"# Cases Run: {Context.NumCasesRun}"); preamble.Add($"# Cases Failed: {Context.NumCasesFailed}"); preamble.Add($"# Test Result: {pass}"); preamble.Add($"#------------------------------------------------------------------"); break; } Context.OutputLines.InsertRange(0, preamble); if (Context.Format == OutputFormat.Xml) { Context.OutputLines.Add($"</testsuites>"); } Context.OutputLines.ForEach(l => Console.WriteLine(l)); }
private static string GetStackTrace(Exception exception) { // Output stacktrace in custom format (very similar to Exception.StackTrace property on English systems). // Include filenames where available, but no paths. StackTrace stackTrace = new StackTrace(exception, true); StringBuilder b = new StringBuilder(); for (int i = 0; i < stackTrace.FrameCount; i++) { StackFrame?frame = stackTrace.GetFrame(i); MethodBase?method = frame?.GetMethod(); if (method == null) { continue; } if (b.Length > 0) { b.AppendLine(); } b.Append(" at "); Type?declaringType = method.DeclaringType; if (declaringType != null) { b.Append(declaringType.FullName.Replace('+', '.')); b.Append('.'); } b.Append(method.Name); // output type parameters, if any if (method is MethodInfo && ((MethodInfo)method).IsGenericMethod) { Type[] genericArguments = ((MethodInfo)method).GetGenericArguments(); b.Append('['); for (int j = 0; j < genericArguments.Length; j++) { if (j > 0) { b.Append(','); } b.Append(genericArguments[j].Name); } b.Append(']'); } // output parameters, if any b.Append('('); ParameterInfo[] parameters = method.GetParameters(); for (int j = 0; j < parameters.Length; j++) { if (j > 0) { b.Append(", "); } if (parameters[j].ParameterType != null) { b.Append(parameters[j].ParameterType.Name); } else { b.Append('?'); } if (!string.IsNullOrEmpty(parameters[j].Name)) { b.Append(' '); b.Append(parameters[j].Name); } } b.Append(')'); // source location if (frame is not null && frame.GetILOffset() >= 0) { string?filename = null; try { string fullpath = frame.GetFileName(); if (fullpath != null) { filename = Path.GetFileName(fullpath); } } catch (SecurityException) { // StackFrame.GetFileName requires PathDiscovery permission } catch (ArgumentException) { // Path.GetFileName might throw on paths with invalid chars } b.Append(" in "); if (filename != null) { b.Append(filename); b.Append(":line "); b.Append(frame.GetFileLineNumber()); } else { b.Append("offset "); b.Append(frame.GetILOffset()); } } } return(b.ToString()); }
/// <summary> /// Walk through stack until you encounter the first class that is not to be ignored and /// whose method does not have the /// </summary> /// <param name="typeToIgnore">Type to ignore as you travel the stack</param> /// <returns>The class containing class and method information</returns> public ErrorLocation FirstNonWrappedMethod(Type[] typesToIgnore) { #if WINDOWS_UWP return(new ErrorLocation()); #else // Go at least one up to ignore this method. int index = 1; StackTrace st = new(); MethodBase?mb = st.GetFrame(index)?.GetMethod(); if (mb != null) { while (true) { Type?declaringType = mb.DeclaringType; if (declaringType == null) { return(new ErrorLocation()); } if ((typesToIgnore == null)) { return(new ErrorLocation(declaringType.Name, mb.Name)); } // It must not be equal to any of the ignore types to be the correct level bool matchAny = false; foreach (Type t in typesToIgnore) { if (declaringType.Name == t.Name || mb.Name.Contains('<')) { matchAny = true; break; } } if (!matchAny) { return(new ErrorLocation(declaringType.Name, mb.Name)); } ++index; StackFrame?sf = st.GetFrame(index); if (sf == null) { return(new ErrorLocation(declaringType.Name, mb.Name)); } MethodBase?tmp = sf.GetMethod(); if (tmp == null) { return(new ErrorLocation(declaringType.Name, mb.Name)); } mb = tmp; } } else { return(new ErrorLocation()); } #endif }