From 60cced0a71e969de7021f250326cd6c4a99116b9 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Thu, 16 Apr 2026 15:05:12 -0400
Subject: [PATCH] Add TestCDACNoFallback flag for cDAC-only testing
Add a new TestCDACNoFallback test configuration flag (SOS_TEST_CDAC_NO_FALLBACK
env var) that enables cDAC with no fallback to the legacy DAC.
When enabled:
- Sets DOTNET_ENABLE_CDAC=1 and CDAC_NO_FALLBACK=1 on the debugger process
- Adds CDAC_TESTING define to skip ClrStack -i tests (ICorDebug is not
implemented in the cDAC)
Wraps ClrStack -i commands with !IFDEF:CDAC_TESTING in 7 script files.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
eng/build.ps1 | 10 ++++++++++
eng/build.sh | 14 ++++++++++++++
.../TestConfiguration.cs | 17 +++++++++++++++--
src/tests/SOS.UnitTests/SOSRunner.cs | 11 ++++++++++-
.../Scripts/ClrStackWithNumberOfFrames.script | 2 ++
.../SOS.UnitTests/Scripts/DualRuntimes.script | 2 ++
.../SOS.UnitTests/Scripts/DynamicMethod.script | 2 ++
.../Scripts/MiniDumpLocalVarLookup.script | 2 ++
.../Scripts/StackAndOtherTests.script | 2 ++
.../SOS.UnitTests/Scripts/StackTests.script | 2 ++
src/tests/SOS.UnitTests/Scripts/WebApp.script | 2 ++
11 files changed, 63 insertions(+), 3 deletions(-)
diff --git a/eng/build.ps1 b/eng/build.ps1
index 21e15851a2..cfab1c3a6a 100644
--- a/eng/build.ps1
+++ b/eng/build.ps1
@@ -12,6 +12,7 @@ Param(
[switch] $skipnative,
[switch] $bundletools,
[switch] $useCdac,
+ [switch] $noFallback,
[string] $methodfilter = '',
[string] $classfilter = '',
[ValidatePattern("(default|\d+\.\d+.\d+(-[a-z0-9\.]+)?)")][string] $dotnetruntimeversion = 'default',
@@ -25,6 +26,11 @@ Param(
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
+if ($noFallback -and -not $useCdac) {
+ Write-Error "-noFallback requires -useCdac to also be specified."
+ exit 1
+}
+
$crossbuild = $false
if (($architecture -eq "arm") -or ($architecture -eq "arm64")) {
$processor = @([System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture.ToString().ToLowerInvariant())
@@ -101,6 +107,10 @@ if ($test) {
$env:SOS_TEST_CDAC="true"
}
+ if ($noFallback) {
+ $env:SOS_TEST_CDAC_NO_FALLBACK="true"
+ }
+
# Build the test filter argument if provided
# Use backslash-escaped quotes so they survive the additional quoting in tools.ps1
$testFilterArg = ''
diff --git a/eng/build.sh b/eng/build.sh
index d0c61fa7b7..e1a9df5ff7 100755
--- a/eng/build.sh
+++ b/eng/build.sh
@@ -32,6 +32,7 @@ __Test=0
__TestFilter=
__UnprocessedBuildArgs=
__UseCdac=0
+__NoFallback=0
__LiveRuntimeDir=
usage_list+=("-skipmanaged: do not build managed components.")
@@ -122,6 +123,10 @@ handle_arguments() {
__UseCdac=1
;;
+ nofallback|-nofallback)
+ __NoFallback=1
+ ;;
+
-warnaserror|-nodereuse)
__ManagedBuildArgs="$__ManagedBuildArgs $1 $2"
__ShiftArgs=1
@@ -135,6 +140,11 @@ handle_arguments() {
source "$__RepoRootDir"/eng/native/build-commons.sh
+if [[ "$__NoFallback" == 1 && "$__UseCdac" != 1 ]]; then
+ echo "-nofallback requires -usecdac to also be specified."
+ exit 1
+fi
+
__LogsDir="$__RootBinDir/log/$__BuildType"
__ConfigTriplet="$__TargetOS.$__TargetArch.$__BuildType"
__BinDir="$__RootBinDir/bin/$__ConfigTriplet"
@@ -315,6 +325,10 @@ if [[ "$__Test" == 1 ]]; then
export SOS_TEST_CDAC="true"
fi
+ if [[ "$__NoFallback" == 1 ]]; then
+ export SOS_TEST_CDAC_NO_FALLBACK="true"
+ fi
+
# Build the test filter argument if provided
__TestFilterArg=
if [[ -n "$__TestFilter" ]]; then
diff --git a/src/Microsoft.Diagnostics.TestHelpers/TestConfiguration.cs b/src/Microsoft.Diagnostics.TestHelpers/TestConfiguration.cs
index 256f271b44..58c3db27dc 100644
--- a/src/Microsoft.Diagnostics.TestHelpers/TestConfiguration.cs
+++ b/src/Microsoft.Diagnostics.TestHelpers/TestConfiguration.cs
@@ -72,7 +72,8 @@ private void ParseConfigFile(string path)
["TargetRid"] = GetRid(),
["TargetArchitecture"] = OS.TargetArchitecture.ToString().ToLowerInvariant(),
["NuGetPackageCacheDir"] = nugetPackages,
- ["TestCDAC"] = Environment.GetEnvironmentVariable("SOS_TEST_CDAC")
+ ["TestCDAC"] = Environment.GetEnvironmentVariable("SOS_TEST_CDAC"),
+ ["TestCDACNoFallback"] = Environment.GetEnvironmentVariable("SOS_TEST_CDAC_NO_FALLBACK")
};
if (OS.Kind == OSKind.Windows)
{
@@ -454,7 +455,11 @@ private string GetStringViewWithVersion(string version)
{
sb.Append(".singlefile");
}
- if (TestCDAC)
+ if (TestCDACNoFallback)
+ {
+ sb.Append(".cdac_no_fallback");
+ }
+ else if (TestCDAC)
{
sb.Append(".cdac");
}
@@ -560,6 +565,14 @@ public bool TestCDAC
get { return string.Equals(GetValue("TestCDAC"), "true", StringComparison.InvariantCultureIgnoreCase); }
}
+ ///
+ /// Returns true if tests should use the cDAC with no fallback to the legacy DAC.
+ ///
+ public bool TestCDACNoFallback
+ {
+ get { return string.Equals(GetValue("TestCDACNoFallback"), "true", StringComparison.InvariantCultureIgnoreCase); }
+ }
+
///
/// The test runner script directory
///
diff --git a/src/tests/SOS.UnitTests/SOSRunner.cs b/src/tests/SOS.UnitTests/SOSRunner.cs
index 80fed0eb5e..63a3987d95 100644
--- a/src/tests/SOS.UnitTests/SOSRunner.cs
+++ b/src/tests/SOS.UnitTests/SOSRunner.cs
@@ -699,7 +699,12 @@ public static async Task StartDebugger(TestInformation information, D
WithLog(scriptLogger).
WithTimeout(TimeSpan.FromMinutes(10));
- if (config.TestCDAC)
+ if (config.TestCDACNoFallback)
+ {
+ processRunner.WithEnvironmentVariable("DOTNET_ENABLE_CDAC", "1");
+ processRunner.WithEnvironmentVariable("CDAC_NO_FALLBACK", "1");
+ }
+ else if (config.TestCDAC)
{
processRunner.WithEnvironmentVariable("DOTNET_ENABLE_CDAC", "1");
}
@@ -1558,6 +1563,10 @@ private HashSet GetEnabledDefines()
{
defines.Add("HOST_RUNTIME_NONE");
}
+ if (_config.TestCDACNoFallback)
+ {
+ defines.Add("CDAC_NO_FALLBACK_TESTING");
+ }
return defines;
}
diff --git a/src/tests/SOS.UnitTests/Scripts/ClrStackWithNumberOfFrames.script b/src/tests/SOS.UnitTests/Scripts/ClrStackWithNumberOfFrames.script
index 29fedbfa2e..5dbe404d4b 100644
--- a/src/tests/SOS.UnitTests/Scripts/ClrStackWithNumberOfFrames.script
+++ b/src/tests/SOS.UnitTests/Scripts/ClrStackWithNumberOfFrames.script
@@ -37,6 +37,7 @@ VERIFY:(?:[^\r\n]*\r?\n){6}[ \t]*\r?\n
!VERIFY:(?:[^\r\n]*\r?\n){8}[ \t]*\r?\n
# Verify that ClrStack with number of frames works using ICorDebug
+!IFDEF:CDAC_NO_FALLBACK_TESTING
SOSCOMMAND:ClrStack -i -c 1
VERIFY:(?:[^\r\n]*\r?\n){8}[ \t]*\r?\n
!VERIFY:(?:[^\r\n]*\r?\n){10}[ \t]*\r?\n
@@ -55,3 +56,4 @@ VERIFY:(?:[^\r\n]*\r?\n){10}[ \t]*\r?\n
SOSCOMMAND:ClrStack -i -c 4
VERIFY:(?:[^\r\n]*\r?\n){11}[ \t]*\r?\n
!VERIFY:(?:[^\r\n]*\r?\n){13}[ \t]*\r?\n
+ENDIF:CDAC_NO_FALLBACK_TESTING
diff --git a/src/tests/SOS.UnitTests/Scripts/DualRuntimes.script b/src/tests/SOS.UnitTests/Scripts/DualRuntimes.script
index 02dfa9555e..8a3b872882 100644
--- a/src/tests/SOS.UnitTests/Scripts/DualRuntimes.script
+++ b/src/tests/SOS.UnitTests/Scripts/DualRuntimes.script
@@ -29,10 +29,12 @@ VERIFY:.*OS Thread Id:\s+0x\s+.*
VERIFY:\s+Child\s+SP\s+IP\s+Call Site\s+
# Verify that ClrStack with the ICorDebug options works
+!IFDEF:CDAC_NO_FALLBACK_TESTING
SOSCOMMAND:ClrStack -i
VERIFY:.*\s+Dumping managed stack and managed variables using ICorDebug.\s+
VERIFY:.*\s+Child\s+SP\s+IP\s+Call Site\s+
VERIFY:.*\s+Stack walk complete.\s+
+ENDIF:CDAC_NO_FALLBACK_TESTING
# Verify that Threads (clrthreads) works
IFDEF:DOTNETDUMP
diff --git a/src/tests/SOS.UnitTests/Scripts/DynamicMethod.script b/src/tests/SOS.UnitTests/Scripts/DynamicMethod.script
index ea20901c36..2a4c31aeba 100644
--- a/src/tests/SOS.UnitTests/Scripts/DynamicMethod.script
+++ b/src/tests/SOS.UnitTests/Scripts/DynamicMethod.script
@@ -3,9 +3,11 @@ CONTINUE
LOADSOS
+!IFDEF:CDAC_NO_FALLBACK_TESTING
SOSCOMMAND:ClrStack -i -a
VERIFY:\s+LOCALS:\s+
SOSCOMMAND:DumpIL .*System\.Reflection\.Emit\.DynamicMethod dynamicMethod @ 0x().*\s+
VERIFY:\s+IL_0000: ldarg.0\s+
VERIFY:\s+IL_0001: ldc.i4.0\s+
+ENDIF:CDAC_NO_FALLBACK_TESTING
diff --git a/src/tests/SOS.UnitTests/Scripts/MiniDumpLocalVarLookup.script b/src/tests/SOS.UnitTests/Scripts/MiniDumpLocalVarLookup.script
index 8ce9245019..38dedc2522 100644
--- a/src/tests/SOS.UnitTests/Scripts/MiniDumpLocalVarLookup.script
+++ b/src/tests/SOS.UnitTests/Scripts/MiniDumpLocalVarLookup.script
@@ -11,5 +11,7 @@ LOADSOS
SOSCOMMAND:clrstack -l
# stackwalk through ICorDebug with locals
+!IFDEF:CDAC_NO_FALLBACK_TESTING
SOSCOMMAND:clrstack -i -l
VERIFY:int\s+length\s+=\s+13
+ENDIF:CDAC_NO_FALLBACK_TESTING
diff --git a/src/tests/SOS.UnitTests/Scripts/StackAndOtherTests.script b/src/tests/SOS.UnitTests/Scripts/StackAndOtherTests.script
index acbf7633dd..c3378e36d2 100644
--- a/src/tests/SOS.UnitTests/Scripts/StackAndOtherTests.script
+++ b/src/tests/SOS.UnitTests/Scripts/StackAndOtherTests.script
@@ -153,6 +153,7 @@ VERIFY:.*\s+\s+\s+SymbolTestApp\.Program\.Main\(.*\)\s+\[(?i:.*[
IFDEF:NETCORE_OR_DOTNETDUMP
# Verify that ClrStack with the ICorDebug options works
+!IFDEF:CDAC_NO_FALLBACK_TESTING
SOSCOMMAND:ClrStack -i
VERIFY:.*\s+Dumping managed stack and managed variables using ICorDebug.\s+
VERIFY:.*\s+Child\s+SP\s+IP\s+Call Site\s+
@@ -179,6 +180,7 @@ VERIFY:.*\s+\s+\s+\[DEFAULT\] I4 SymbolTestApp\.Program\.Foo2\(.
VERIFY:.*\s+\s+\s+\[DEFAULT\] I4 SymbolTestApp\.Program\.Foo1\(.*\)\s+\(.*\)\s+
VERIFY:.*\s+\s+\s+\[DEFAULT\] Void SymbolTestApp\.Program\.Main\(.*\)\s+\(.*\)\s+
VERIFY:.*\s+Stack walk complete.\s+
+ENDIF:CDAC_NO_FALLBACK_TESTING
SOSCOMMAND: runtimes
diff --git a/src/tests/SOS.UnitTests/Scripts/StackTests.script b/src/tests/SOS.UnitTests/Scripts/StackTests.script
index 485774da01..5bebe49991 100644
--- a/src/tests/SOS.UnitTests/Scripts/StackTests.script
+++ b/src/tests/SOS.UnitTests/Scripts/StackTests.script
@@ -108,6 +108,7 @@ IFDEF:NETCORE_OR_DOTNETDUMP
!IFDEF:ALPINE
# 5) Verifying that ClrStack with the ICorDebug options works
+!IFDEF:CDAC_NO_FALLBACK_TESTING
SOSCOMMAND:ClrStack -i
VERIFY:.*\s+Dumping managed stack and managed variables using ICorDebug.\s+
VERIFY:.*\s+Child\s+SP\s+IP\s+Call Site\s+
@@ -130,6 +131,7 @@ VERIFY:\s+\+ System.FormatException ex @ 0x\s+
ENDIF:SINGLE_FILE_APP
VERIFY:.*\s+\s+\s+\[DEFAULT\] Void NestedExceptionTest\.Program\.Main\(.*\)\s+\(.*\)\s+
VERIFY:.*\s+Stack walk complete.\s+
+ENDIF:CDAC_NO_FALLBACK_TESTING
ENDIF:ALPINE
ENDIF:NETCORE_OR_DOTNETDUMP
diff --git a/src/tests/SOS.UnitTests/Scripts/WebApp.script b/src/tests/SOS.UnitTests/Scripts/WebApp.script
index a304a2f001..a6145fc168 100644
--- a/src/tests/SOS.UnitTests/Scripts/WebApp.script
+++ b/src/tests/SOS.UnitTests/Scripts/WebApp.script
@@ -95,10 +95,12 @@ VERIFY:\s+eax=\s+ebx=\s+ecx=\s+
ENDIF:X86
# Verify that ClrStack with the ICorDebug options works
+!IFDEF:CDAC_NO_FALLBACK_TESTING
SOSCOMMAND:ClrStack -i
VERIFY:.*\s+Dumping managed stack and managed variables using ICorDebug.\s+
VERIFY:.*\s+Child\s+SP\s+IP\s+Call Site\s+
VERIFY:.*\s+Stack walk complete.\s+
+ENDIF:CDAC_NO_FALLBACK_TESTING
# Verify that Threads (clrthreads) works
SOSCOMMAND:clrthreads