Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authortherzok <marius.ungureanu@xamarin.com>2019-05-30 17:11:34 +0300
committertherzok <marius.ungureanu@xamarin.com>2019-05-30 17:11:59 +0300
commitb315e90910728b56a11f0eecc1e768e86aebdeb2 (patch)
tree9f1e03774873a3f1311a50b5c4212e5c6e725494 /main
parent6af6a69b7f49e96e9f53c32abf34a3203a8d89c5 (diff)
Add unit tests to ensure stacktraces in non-errors
Diffstat (limited to 'main')
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/GLibLogging.cs31
-rw-r--r--main/tests/Ide.Tests/MonoDevelop.Ide.Gui/GLibLoggingTests.cs30
2 files changed, 46 insertions, 15 deletions
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/GLibLogging.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/GLibLogging.cs
index 2604d036e7..9aaa7ceddc 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/GLibLogging.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/GLibLogging.cs
@@ -256,7 +256,7 @@ namespace MonoDevelop.Ide.Gui
LoggingService.LogError (message, e);
}
- string msg = string.Format ("{0}-{1}: {2}", logDomain, logLevel, message);
+ string msg = string.Format ("{0}-{1}: {2}\n{3}", logDomain, logLevel, message, GetStacktraceIfNeeded (logLevel));
switch (logLevel) {
case LogLevelFlags.Debug:
@@ -275,9 +275,9 @@ namespace MonoDevelop.Ide.Gui
throw new CriticalGtkException (msg);
} catch (CriticalGtkException e) {
if (logLevel.HasFlag (LogLevelFlags.FlagFatal))
- LoggingService.LogFatalError ("Fatal GLib error", e);
+ LoggingService.LogFatalError ($"Fatal {logDomain} error", e);
else
- LoggingService.LogInternalError ("Critical GLib error", e);
+ LoggingService.LogInternalError ($"Critical {logDomain} error", e);
}
break;
}
@@ -287,17 +287,36 @@ namespace MonoDevelop.Ide.Gui
LoggingService.LogError ("Disabling glib logging for the rest of the session");
}
+ static string GetStacktraceIfNeeded (LogLevelFlags flags)
+ {
+ if (flags.HasFlag (LogLevelFlags.Error | LogLevelFlags.Critical))
+ return string.Empty;
+
+ return "Stack trace: \n" + new StackTrace (1, true);
+ }
+
sealed class CriticalGtkException : Exception
{
+ readonly StackTrace trace = new StackTrace (1, true);
+
public CriticalGtkException (string message) : base (message)
{
const System.Reflection.BindingFlags flags =
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.SetField;
- var trace = new [] { new StackTrace (true), };
- //// Otherwise exception stacktrace is not gathered.
+ // HACK: We need to somehow inject our stacktrace, and this is the only way we can
+ // This is not to transform every glib error into a managed exception
typeof (Exception)
- .InvokeMember ("captured_traces", flags, null, this, new object [] { trace } );
+ .GetField ("captured_traces", flags)
+ ?.SetValue (this, new StackTrace [] { trace });
+ }
+
+ public override string StackTrace => trace.ToString ();
+
+ public override string ToString ()
+ {
+ // Matches normal exception format:
+ return GetType () + ": " + Message + Environment.NewLine + trace;
}
}
}
diff --git a/main/tests/Ide.Tests/MonoDevelop.Ide.Gui/GLibLoggingTests.cs b/main/tests/Ide.Tests/MonoDevelop.Ide.Gui/GLibLoggingTests.cs
index b49711ed74..b75242e373 100644
--- a/main/tests/Ide.Tests/MonoDevelop.Ide.Gui/GLibLoggingTests.cs
+++ b/main/tests/Ide.Tests/MonoDevelop.Ide.Gui/GLibLoggingTests.cs
@@ -27,6 +27,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using MonoDevelop.Core;
+using MonoDevelop.Core.Logging;
using MonoDevelop.Core.LogReporting;
using NUnit.Framework;
using UnitTests;
@@ -65,22 +66,33 @@ namespace MonoDevelop.Ide.Gui
}
[Test]
- public void CriticalErrorsExceptionsHaveFullStacktracesInLog ()
+ public void GLibLoggingHaveFullStacktracesInLog ()
{
var old = GLibLogging.Enabled;
- var logger = new CapturingLogger {
- EnabledLevel = Core.Logging.EnabledLoggingLevel.Error,
- };
try {
- LoggingService.AddLogger (logger);
GLibLogging.Enabled = true;
- GLib.Log.Write ("Gtk", GLib.LogLevelFlags.Critical, "{0}", "critical should be captured");
- var (_, message) = logger.LogMessages.Single (x => x.Level == Core.Logging.LogLevel.Error);
- AssertGLibStackTrace (message);
+ var flagsToCheck = new [] {
+ (GLib.LogLevelFlags.Critical, LogLevel.Error),
+ (GLib.LogLevelFlags.Debug, LogLevel.Debug),
+ (GLib.LogLevelFlags.Info, LogLevel.Info),
+ //(GLib.LogLevelFlags.Error, LogLevel.Fatal),
+ };
+
+ foreach (var (glibLevel, coreLevel) in flagsToCheck) {
+ var logger = new CapturingLogger ();
+
+ LoggingService.AddLogger (logger);
+ try {
+ GLib.Log.Write ("Gtk", glibLevel, "{0}: should be captured", glibLevel);
+ var (_, message) = logger.LogMessages.Single (x => x.Level == coreLevel);
+ AssertGLibStackTrace (message);
+ } finally {
+ LoggingService.RemoveLogger (logger.Name);
+ }
+ }
} finally {
- LoggingService.RemoveLogger (logger.Name);
GLibLogging.Enabled = old;
}
}