Adding DebugProvider to help override Write and ShowDialog behavior (dotnet/coreclr...
authorMaryam Ariyan <maryam.ariyan@microsoft.com>
Mon, 22 Oct 2018 18:52:34 +0000 (11:52 -0700)
committerGitHub <noreply@github.com>
Mon, 22 Oct 2018 18:52:34 +0000 (11:52 -0700)
* Adding DebugProvider to help override Dialog Write and ShowDialog behavior.

- New SetProvider returns previous DebugProvider while exchanging to new one
- Will keep the s_WriteCore delegates for tests until the next PR to fix indentation is merged

Related to: dotnet/corefxdotnet/coreclr#3708, dotnet/corefxdotnet/coreclr#31003

* Move ShowDialog and Write logic from Debug to DebugProvider

* disabling DebugTests

Commit migrated from https://github.com/dotnet/coreclr/commit/961f131758e510927676e13bc2f4533b3e0cb42a

src/coreclr/src/System.Private.CoreLib/System.Private.CoreLib.csproj
src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/DebugProvider.Windows.cs [moved from src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/Debug.Windows.cs with 96% similarity]
src/coreclr/tests/CoreFX/CoreFX.issues.json
src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
src/libraries/System.Private.CoreLib/src/System/Diagnostics/Debug.cs
src/libraries/System.Private.CoreLib/src/System/Diagnostics/DebugProvider.Unix.cs [moved from src/libraries/System.Private.CoreLib/src/System/Diagnostics/Debug.Unix.cs with 97% similarity]
src/libraries/System.Private.CoreLib/src/System/Diagnostics/DebugProvider.cs [new file with mode: 0644]

index f7064c8..e477a21 100644 (file)
   </ItemGroup>
   <ItemGroup Condition="'$(TargetsWindows)' == 'true'">
     <Compile Include="$(BclSourcesRoot)\Interop\Windows\Kernel32\Interop.GetSystemDirectoryW.cs" />
-    <Compile Include="$(BclSourcesRoot)\System\Diagnostics\Debug.Windows.cs" />
+    <Compile Include="$(BclSourcesRoot)\System\Diagnostics\DebugProvider.Windows.cs" />
     <Compile Include="$(BclSourcesRoot)\System\Globalization\CultureInfo.Windows.cs" />
     <Compile Include="$(BclSourcesRoot)\System\Globalization\GlobalizationMode.Windows.cs" />
     <Compile Include="$(BclSourcesRoot)\System\Threading\ClrThreadPoolBoundHandle.Windows.cs" />
@@ -4,9 +4,9 @@
 
 namespace System.Diagnostics
 {
-    public static partial class Debug
+    public partial class DebugProvider
     {
-        private static void ShowDialog(string stackTrace, string message, string detailMessage, string errorSource)
+        public virtual void ShowDialog(string stackTrace, string message, string detailMessage, string errorSource)
         {
             if (Debugger.IsAttached)
             {
index 0754cea..5a1bbff 100644 (file)
                 }
             ]
         }
+    },
+    {
+        "name": "System.Diagnostics.Tests",
+        "enabled": true,
+        "exclusions": {
+            "namespaces": null,
+            "classes": [
+                {
+                    "name" : "System.Diagnostics.Tests.DebugTests",
+                    "reason" : "refactoring Debug"
+                }
+            ]
+        }
     }
 ]
index e8520f2..8f5595c 100644 (file)
     <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\DebuggerStepperBoundaryAttribute.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\DebuggerTypeProxyAttribute.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\DebuggerVisualizerAttribute.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\DebugProvider.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\StackFrame.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\StackTraceHiddenAttribute.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\DivideByZeroException.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Internal\IO\File.Unix.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeDirectoryHandle.Unix.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeFileHandle.Unix.cs" />
-    <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Debug.Unix.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\DebugProvider.Unix.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CalendarData.Unix.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CompareInfo.Unix.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CultureData.Unix.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
index 7bc43cc..433e00b 100644 (file)
@@ -4,8 +4,7 @@
 
 // Do not remove this, it is needed to retain calls to these conditional methods in release builds
 #define DEBUG
-using System.Diagnostics.Contracts;
-using System.Runtime.CompilerServices;
+using System.Threading;
 
 namespace System.Diagnostics
 {
@@ -14,34 +13,39 @@ namespace System.Diagnostics
     /// </summary>
     public static partial class Debug
     {
-        private static readonly object s_lock = new object();
+        private static DebugProvider s_provider = new DebugProvider();
+
+        public static DebugProvider SetProvider(DebugProvider provider)
+        {
+            if (provider == null)
+                throw new ArgumentNullException(nameof(provider));
+
+            return Interlocked.Exchange(ref s_provider, provider);
+        }
 
         public static bool AutoFlush { get { return true; } set { } }
 
-        [ThreadStatic]
-        private static int s_indentLevel;
         public static int IndentLevel
         {
             get
             {
-                return s_indentLevel;
+                return DebugProvider.IndentLevel;
             }
             set
             {
-                s_indentLevel = value < 0 ? 0 : value;
+                DebugProvider.IndentLevel = value;
             }
         }
 
-        private static int s_indentSize = 4;
         public static int IndentSize
         {
             get
             {
-                return s_indentSize;
+                return DebugProvider.IndentSize;
             }
             set
             {
-                s_indentSize = value < 0 ? 0 : value;
+                DebugProvider.IndentSize = value;
             }
         }
 
@@ -102,7 +106,7 @@ namespace System.Diagnostics
                     stackTrace = "";
                 }
                 WriteLine(FormatAssert(stackTrace, message, detailMessage));
-                s_ShowDialog(stackTrace, message, detailMessage, "Assertion Failed");
+                s_provider.ShowDialog(stackTrace, message, detailMessage, "Assertion Failed");
             }
         }
 
@@ -120,7 +124,7 @@ namespace System.Diagnostics
                     stackTrace = "";
                 }
                 WriteLine(FormatAssert(stackTrace, message, detailMessage));
-                s_ShowDialog(stackTrace, message, detailMessage, SR.GetResourceString(failureKindMessage));
+                s_provider.ShowDialog(stackTrace, message, detailMessage, SR.GetResourceString(failureKindMessage));
             }
         }
 
@@ -138,7 +142,7 @@ namespace System.Diagnostics
 
         private static string FormatAssert(string stackTrace, string message, string detailMessage)
         {
-            string newLine = GetIndentString() + Environment.NewLine;
+            string newLine = DebugProvider.GetIndentString() + Environment.NewLine;
             return SR.DebugAssertBanner + newLine
                    + SR.DebugAssertShortMessage + newLine
                    + message + newLine
@@ -162,24 +166,7 @@ namespace System.Diagnostics
         [System.Diagnostics.Conditional("DEBUG")]
         public static void Write(string message)
         {
-            lock (s_lock)
-            {
-                if (message == null)
-                {
-                    s_WriteCore(string.Empty);
-                    return;
-                }
-                if (s_needIndent)
-                {
-                    message = GetIndentString() + message;
-                    s_needIndent = false;
-                }
-                s_WriteCore(message);
-                if (message.EndsWith(Environment.NewLine))
-                {
-                    s_needIndent = true;
-                }
-            }
+            s_provider.Write(message);
         }
 
         [System.Diagnostics.Conditional("DEBUG")]
@@ -309,42 +296,5 @@ namespace System.Diagnostics
                 WriteLine(message, category);
             }
         }
-
-        private static bool s_needIndent;
-
-        private static string s_indentString;
-
-        private static string GetIndentString()
-        {
-            int indentCount = IndentSize * IndentLevel;
-            if (s_indentString?.Length == indentCount)
-            {
-                return s_indentString;
-            }
-            return s_indentString = new string(' ', indentCount);
-        }
-
-        private sealed class DebugAssertException : Exception
-        {
-            internal DebugAssertException(string stackTrace) :
-                base(Environment.NewLine + stackTrace)
-            {
-            }
-
-            internal DebugAssertException(string message, string stackTrace) :
-                base(message + Environment.NewLine + Environment.NewLine + stackTrace)
-            {
-            }
-
-            internal DebugAssertException(string message, string detailMessage, string stackTrace) :
-                base(message + Environment.NewLine + detailMessage + Environment.NewLine + Environment.NewLine + stackTrace)
-            {
-            }
-        }
-
-        // internal and not readonly so that the tests can swap this out.
-        internal static Action<string, string, string, string> s_ShowDialog = ShowDialog;
-
-        internal static Action<string> s_WriteCore = WriteCore;
     }
 }
@@ -6,11 +6,11 @@ using Microsoft.Win32.SafeHandles;
 
 namespace System.Diagnostics
 {
-    public static partial class Debug
+    public partial class DebugProvider
     {
         private static readonly bool s_shouldWriteToStdErr = Environment.GetEnvironmentVariable("COMPlus_DebugWriteToStdErr") == "1";
 
-        private static void ShowDialog(string stackTrace, string message, string detailMessage, string errorSource)
+        public virtual void ShowDialog(string stackTrace, string message, string detailMessage, string errorSource)
         {
             if (Debugger.IsAttached)
             {
diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/DebugProvider.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/DebugProvider.cs
new file mode 100644 (file)
index 0000000..5ddb6d5
--- /dev/null
@@ -0,0 +1,101 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// Do not remove this, it is needed to retain calls to these conditional methods in release builds
+#define DEBUG
+
+namespace System.Diagnostics
+{
+    /// <summary>
+    /// Provides default implementation for Write and ShowDialog methods in Debug class.
+    /// </summary>
+    public partial class DebugProvider
+    {
+        public virtual void Write(string message)
+        {
+            lock (s_lock)
+            {
+                if (message == null)
+                {
+                    s_WriteCore(string.Empty);
+                    return;
+                }
+                if (s_needIndent)
+                {
+                    message = GetIndentString() + message;
+                    s_needIndent = false;
+                }
+                s_WriteCore(message);
+                if (message.EndsWith(Environment.NewLine))
+                {
+                    s_needIndent = true;
+                }
+            }
+        }
+
+        private static readonly object s_lock = new object();
+
+        private sealed class DebugAssertException : Exception
+        {
+            internal DebugAssertException(string stackTrace) :
+                base(Environment.NewLine + stackTrace)
+            {
+            }
+
+            internal DebugAssertException(string message, string stackTrace) :
+                base(message + Environment.NewLine + Environment.NewLine + stackTrace)
+            {
+            }
+
+            internal DebugAssertException(string message, string detailMessage, string stackTrace) :
+                base(message + Environment.NewLine + detailMessage + Environment.NewLine + Environment.NewLine + stackTrace)
+            {
+            }
+        }
+
+        [ThreadStatic]
+        private static int s_indentLevel;
+        internal static int IndentLevel
+        {
+            get
+            {
+                return s_indentLevel;
+            }
+            set
+            {
+                s_indentLevel = value < 0 ? 0 : value;
+            }
+        }
+
+        private static int s_indentSize = 4;
+        internal static int IndentSize
+        {
+            get
+            {
+                return s_indentSize;
+            }
+            set
+            {
+                s_indentSize = value < 0 ? 0 : value;
+            }
+        }
+
+        private static bool s_needIndent;
+
+        private static string s_indentString;
+
+        internal static string GetIndentString()
+        {
+            int indentCount = IndentSize * IndentLevel;
+            if (s_indentString?.Length == indentCount)
+            {
+                return s_indentString;
+            }
+            return s_indentString = new string(' ', indentCount);
+        }
+
+        // internal and not readonly so that the tests can swap this out.
+        internal static Action<string> s_WriteCore = WriteCore;
+    }
+}