Add test for SOS POH (#1264)
authorDavid Mason <davmason@microsoft.com>
Tue, 30 Jun 2020 20:31:43 +0000 (13:31 -0700)
committerGitHub <noreply@github.com>
Tue, 30 Jun 2020 20:31:43 +0000 (13:31 -0700)
Tests that GC commands work with objects allocated on the pinned object heap

debuggees.sln
src/SOS/SOS.UnitTests/Debuggees/GCPOH/GCPOH.cs [new file with mode: 0644]
src/SOS/SOS.UnitTests/Debuggees/GCPOH/GCPOH.csproj [new file with mode: 0644]
src/SOS/SOS.UnitTests/SOS.cs
src/SOS/SOS.UnitTests/Scripts/GCPOH.script [new file with mode: 0644]

index abffc6dacdc3e8686e71960d42ef575f454e7a17..dc3ff8c0305affb4ee64e2893f043cfa4b950c56 100644 (file)
@@ -37,6 +37,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SymbolTestDll", "src\SOS\SO
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LineNums", "src\SOS\SOS.UnitTests\Debuggees\LineNums\LineNums.csproj", "{84881FB8-37E1-4D9B-B27E-9831C30DCC04}"
 EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GCPOH", "src\SOS\SOS.UnitTests\Debuggees\GCPOH\GCPOH.csproj", "{0A34CA51-8B8C-41A1-BE24-AB2C574EA144}"
+EndProject
 Global
        GlobalSection(SolutionConfigurationPlatforms) = preSolution
                Checked|Any CPU = Checked|Any CPU
@@ -621,6 +623,46 @@ Global
                {84881FB8-37E1-4D9B-B27E-9831C30DCC04}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
                {84881FB8-37E1-4D9B-B27E-9831C30DCC04}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU
                {84881FB8-37E1-4D9B-B27E-9831C30DCC04}.RelWithDebInfo|x86.Build.0 = Release|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Checked|Any CPU.Build.0 = Debug|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Checked|ARM.ActiveCfg = Debug|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Checked|ARM.Build.0 = Debug|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Checked|ARM64.ActiveCfg = Debug|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Checked|ARM64.Build.0 = Debug|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Checked|x64.ActiveCfg = Debug|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Checked|x64.Build.0 = Debug|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Checked|x86.ActiveCfg = Debug|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Checked|x86.Build.0 = Debug|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Debug|ARM.ActiveCfg = Debug|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Debug|ARM.Build.0 = Debug|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Debug|ARM64.ActiveCfg = Debug|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Debug|ARM64.Build.0 = Debug|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Debug|x64.ActiveCfg = Debug|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Debug|x64.Build.0 = Debug|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Debug|x86.ActiveCfg = Debug|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Debug|x86.Build.0 = Debug|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Release|Any CPU.Build.0 = Release|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Release|ARM.ActiveCfg = Release|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Release|ARM.Build.0 = Release|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Release|ARM64.ActiveCfg = Release|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Release|ARM64.Build.0 = Release|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Release|x64.ActiveCfg = Release|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Release|x64.Build.0 = Release|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Release|x86.ActiveCfg = Release|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Release|x86.Build.0 = Release|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.RelWithDebInfo|ARM.ActiveCfg = Release|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.RelWithDebInfo|ARM.Build.0 = Release|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.RelWithDebInfo|ARM64.ActiveCfg = Release|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.RelWithDebInfo|ARM64.Build.0 = Release|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.RelWithDebInfo|x86.Build.0 = Release|Any CPU
        EndGlobalSection
        GlobalSection(SolutionProperties) = preSolution
                HideSolutionNode = FALSE
@@ -642,6 +684,7 @@ Global
                {112FE2A7-3FD2-4496-8A14-171898AD5CF5} = {C3072949-6D24-451B-A308-2F3621F858B0}
                {8C27904A-47C0-44C7-B191-88FF34580CBE} = {C3072949-6D24-451B-A308-2F3621F858B0}
                {84881FB8-37E1-4D9B-B27E-9831C30DCC04} = {C3072949-6D24-451B-A308-2F3621F858B0}
+               {0A34CA51-8B8C-41A1-BE24-AB2C574EA144} = {C3072949-6D24-451B-A308-2F3621F858B0}
        EndGlobalSection
        GlobalSection(ExtensibilityGlobals) = postSolution
                SolutionGuid = {46465737-C938-44FC-BE1A-4CE139EBB5E0}
diff --git a/src/SOS/SOS.UnitTests/Debuggees/GCPOH/GCPOH.cs b/src/SOS/SOS.UnitTests/Debuggees/GCPOH/GCPOH.cs
new file mode 100644 (file)
index 0000000..a16244e
--- /dev/null
@@ -0,0 +1,23 @@
+using System;
+using System.IO;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+class GCPOH
+{
+    static int Main()
+    {
+        // Use reflection to get the API because the test is compiled against an older version of netstandard
+        // that doesn't have the POH APIs
+        Assembly corlib = typeof(Object).Assembly;
+        Type gc = corlib.GetType("System.GC");
+        MethodInfo method = gc.GetMethod("AllocateArray", BindingFlags.Public | BindingFlags.Static);
+        MethodInfo generic = method.MakeGenericMethod(typeof(byte));
+        // Calls GC.AllocateArray(size: 100, pinned: true)
+        byte[] myArray = (byte[])generic.Invoke(null, new object[] { 100, true });
+        Debugger.Break();
+        GC.KeepAlive(myArray);
+        return 0;
+    }
+}
diff --git a/src/SOS/SOS.UnitTests/Debuggees/GCPOH/GCPOH.csproj b/src/SOS/SOS.UnitTests/Debuggees/GCPOH/GCPOH.csproj
new file mode 100644 (file)
index 0000000..25ce9e1
--- /dev/null
@@ -0,0 +1,7 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework Condition="'$(BuildProjectFramework)' != ''">$(BuildProjectFramework)</TargetFramework>
+    <TargetFrameworks Condition="'$(BuildProjectFramework)' == ''">netcoreapp2.1;netcoreapp3.1</TargetFrameworks>
+  </PropertyGroup>
+</Project>
index 4727c546c0dbd2d3ded4f64ae2a4b8cbfdbb169c..3acc536ffbeb59338ecb84789b048a9c67069e5e 100644 (file)
@@ -132,6 +132,17 @@ public class SOS
         await RunTest(config, "GCWhere", "GCTests.script", testName: "SOS.GCTests", testDump: false);
     }
 
+    [SkippableTheory, MemberData(nameof(Configurations))]
+    public async Task GCPOHTests(TestConfiguration config)
+    {
+        if (!config.IsNETCore || config.RuntimeFrameworkVersionMajor < 5)
+        {
+            throw new SkipTestException("This test validates POH behavior, which was introduced in .net 5");
+        }
+
+        await RunTest(config, "GCPOH", "GCPOH.script", testName: "SOS.GCPOHTests", testDump: false);
+    }
+
     [SkippableTheory, MemberData(nameof(Configurations))]
     public async Task Overflow(TestConfiguration config)
     {
diff --git a/src/SOS/SOS.UnitTests/Scripts/GCPOH.script b/src/SOS/SOS.UnitTests/Scripts/GCPOH.script
new file mode 100644 (file)
index 0000000..182a8a7
--- /dev/null
@@ -0,0 +1,66 @@
+#
+# Tests various SOS GC and object based commands on the pinned object heap (POH).
+#
+# Commands Verified: GCWhere, GCRoot, DumpObj, DumpHeap, DumpStackObjects
+#
+# 1) Run to the first debug break
+# 2) Load sos
+# 3) Dump stack objects to get the address of GCWhere!temp
+# 4) Run various commands on the address, verify POH
+#11) Let the program run to completion
+
+# Continue to the DebugBreak
+CONTINUE
+IFDEF:CDB
+VERIFY:Break instruction exception - code 80000003
+ENDIF:CDB
+
+LOADSOS
+
+SOSCOMMAND:DumpStackObjects
+VERIFY:<HEXVAL>\s+<HEXVAL>\s+System.Byte\[\]\s+
+
+SOSCOMMAND:DumpObj <POUT>\w+\s+(<HEXVAL>)\s+(System.Byte\[\]!\$0_)*System.Byte\[\]\s+<POUT>
+VERIFY:\s+Name:        System.Byte\[\]\s+
+VERIFY:\s+Array:       Rank 1, Number of elements 100, Type Byte\s+
+
+SOSCOMMAND:GCWhere <PREVPOUT>
+# we care that the Gen is 4 (POH)
+VERIFY:<HEXVAL>\s+4\s+\d\s+<HEXVAL>\s+<HEXVAL>\s+<HEXVAL>\s+0x<HEXVAL>\s*\(\d+\)
+
+SOSCOMMAND:GCRoot <PREVPOUT>
+VERIFY:.*Thread <HEXVAL>:
+VERIFY:\s+<HEXVAL>\s+<HEXVAL>\s+GCPOH\.Main\(\)\s+\[.*[Gg][Cc][Pp][Oo][Hh]\.cs\s+@\s+19\]\s+
+
+SOSCOMMAND:GCRoot -all <PREVPOUT>
+VERIFY:.*Thread <HEXVAL>:
+VERIFY:\s+<HEXVAL>\s+<HEXVAL>\s+GCPOH\.Main\(\)\s+\[.*[Gg][Cc][Pp][Oo][Hh]\.cs\s+@\s+19\]\s+
+
+SOSCOMMAND:DumpHeap
+VERIFY:\s+<HEXVAL>\s+<HEXVAL>\s+<DECVAL>\s+
+
+SOSCOMMAND:DumpHeap -stat
+VERIFY:\s*Statistics:\s+
+VERIFY:\s+MT\s+Count\s+TotalSize\s+Class\s+Name\s+
+VERIFY:\s+<HEXVAL>\s+<DECVAL>\s+<DECVAL>\s+System.Byte\[\]\s+
+
+SOSCOMMAND:EEHeap
+VERIFY:\s*Loader Heap:\s+
+VERIFY:\s+System Domain:\s+<HEXVAL>\s+
+VERIFY:\s+LowFrequencyHeap:\s+<HEXVAL>.*bytes.*\s+
+VERIFY:\s+HighFrequencyHeap:\s+<HEXVAL>.*bytes.*\s+
+VERIFY:\s+Total size:\s+Size:\s+0x<HEXVAL>\s+\(<DECVAL>|lu\)\s+bytes\.\s+
+VERIFY:\s+Jit code heap:\s+
+VERIFY:\s+LoaderCodeHeap:\s+<HEXVAL>.*bytes\.\s+
+VERIFY:\s+Total LoaderHeap size:\s+Size:\s+0x<HEXVAL>\s+\(<DECVAL>|lu\)\s+bytes\.\s+
+VERIFY:\s+Number of GC Heaps:\s+<DECVAL>\s+
+VERIFY:\s+generation\s+<DECVAL>\s+starts\s+at\s+0x<HEXVAL>\s+
+VERIFY:\s+generation\s+<DECVAL>\s+starts\s+at\s+0x<HEXVAL>\s+
+VERIFY:\s+generation\s+<DECVAL>\s+starts\s+at\s+0x<HEXVAL>\s+
+VERIFY:\s+segment\s+begin\s+allocated\s+size\s+
+VERIFY:\s+<HEXVAL>\s+<HEXVAL>\s+<HEXVAL>\s+0x<HEXVAL>\(<DECVAL>\)
+VERIFY:\s+Large object heap starts at 0x<HEXVAL>\s+
+VERIFY:\s+Pinned object heap starts at 0x<HEXVAL>\s+
+
+# Continue to the next DebugBreak
+CONTINUE