Clean up netci.groovy (#15030)
authorBruce Forstall <brucefo@microsoft.com>
Thu, 16 Nov 2017 23:20:57 +0000 (15:20 -0800)
committerGitHub <noreply@github.com>
Thu, 16 Nov 2017 23:20:57 +0000 (15:20 -0800)
* Clean up netci.groovy

1. Don't repeat entire list of JIT stress and R2R scenarios over and over;
use functions to check for scenario groups.
2. Merge handling of R2R baseline and stress scenarios.
3. Add function to determine if a scenario is a JIT stress scenario.
4. Fix JIT stress mode display name generator to handle CoreFx tests
as well, preserving the way they are currently displayed.
5. Fix R2R display name generator to handle baseline R2R scenario.
6. Fix bug where x86 R2R baseline job wasn't created.
7. Fix bugs where triggering some jobs, such as R2R jobs, would trigger lots
of other jobs with insufficient trigger strings. Thus, more trigger strings
now have architecture + scenario in them. E.g., "Innerloop" jobs now much
be triggered using a phrase containing "Innerloop".
8. Simplify code that creates builds, and test run commands.
9. Fix mis-casing of COMPlus_JITMinOpts in R2R stress list.
10. Expand list of valid ARM Windows scenarios to match total list of
scenarios, but with some scenarios commented out. Add the
jitstress2 + jitstressregs to the acceptable list. Add note about the
many scenarios in this list that are not in the full scenario list. Add
function to determine if a scenario is in this list.
11. Support crossgen of frameworks using altjit
12. Don't support 'r2r' scenario on arm/armlb/arm64 Windows.

netci.groovy
tests/runtest.cmd

index d2c38e7..1f23f2d 100755 (executable)
@@ -107,8 +107,8 @@ class Constants {
                'gcstress0xc_minopts_heapverify1'    : ['COMPlus_GCStress' : '0xC', 'COMPlus_JITMinOpts' : '1', 'COMPlus_HeapVerify' : '1']
     ]
 
-    // This is a set of r2r jit stress scenarios
-    def static r2rJitStressScenarios = [
+    // This is a set of ReadyToRun stress scenarios
+    def static r2rStressScenarios = [
                'r2r_jitstress1'             : ["COMPlus_JitStress": "1"],
                'r2r_jitstress2'             : ["COMPlus_JitStress": "2"],
                'r2r_jitstressregs1'         : ["COMPlus_JitStressRegs": "1"],
@@ -119,7 +119,7 @@ class Constants {
                'r2r_jitstressregs0x10'      : ["COMPlus_JitStressRegs": "0x10"],
                'r2r_jitstressregs0x80'      : ["COMPlus_JitStressRegs": "0x80"],
                'r2r_jitstressregs0x1000'    : ["COMPlus_JitStressRegs": "0x1000"],
-               'r2r_jitminopts'             : ["COMPlus_JitMinOpts": "1"], 
+               'r2r_jitminopts'             : ["COMPlus_JITMinOpts": "1"], 
                'r2r_jitforcerelocs'         : ["COMPlus_ForceRelocs": "1"],
                'r2r_gcstress15'             : ["COMPlus_GCStress": "0xF"]
     ]
@@ -135,20 +135,47 @@ class Constants {
                'jitdiff',
                'standalone_gc',
                'gc_reliability_framework',
-               'illink'] + r2rJitStressScenarios.keySet()
+               'illink'] + r2rStressScenarios.keySet()
 
-    // Knowledge of the "validArmWindowsScenarios" scenario names is embedded in the ARM64 CI code, so when adding any,
-    // make sure that code knows how to process them.
+    def static allScenarios = basicScenarios + jitStressModeScenarios.keySet()
+
+    // A set of scenarios that are valid for arm/arm64/armlb tests run on hardware. This is a map from valid scenario name
+    // to Tests.lst file categories to exclude.
+    //
+    // This list should contain a subset of the scenarios from `allScenarios`. Please keep this in the same order as that,
+    // and with the same values, with some commented out, for easier maintenance.
+    //
+    // Note that some scenarios that are commented out should be enabled, but haven't yet been.
+    //
     def static validArmWindowsScenarios = [
                'default':                                [],
-               'r2r':                                    ["R2R_FAIL"],
-               'zapdisable':                             ["ZAPDISABLE_FAIL", "ZAPDISABLE_EXCLUDE"],
+               // 'ilrt'
+               // 'r2r':                                    ["R2R_FAIL"],
+               // 'longgc'
+               // 'formatting'
+               // 'gcsimulator'
+               // 'jitdiff'
+               // 'standalone_gc'
+               // 'gc_reliability_framework'
+               // 'illink'
+               // 'r2r_jitstress1'
+               // 'r2r_jitstress2'
+               // 'r2r_jitstressregs1'
+               // 'r2r_jitstressregs2'
+               // 'r2r_jitstressregs3'
+               // 'r2r_jitstressregs4'
+               // 'r2r_jitstressregs8'
+               // 'r2r_jitstressregs0x10'
+               // 'r2r_jitstressregs0x80'
+               // 'r2r_jitstressregs0x1000'
+               // 'r2r_jitminopts'
+               // 'r2r_jitforcerelocs'
+               // 'r2r_gcstress15'
                'minopts':                                ["MINOPTS_FAIL", "MINOPTS_EXCLUDE"],
-               'tailcallstress':                         ["TAILCALLSTRESS_FAIL", "TAILCALLSTRESS_EXCLUDE"],
+               // 'tieredcompilation'
+               // 'forcerelocs'
                'jitstress1':                             ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
                'jitstress2':                             ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
-               'gcstress0x3':                            ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE"],
-               'gcstress0xc':                            ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE"],
                'jitstressregs1':                         ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
                'jitstressregs2':                         ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
                'jitstressregs3':                         ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
@@ -157,11 +184,48 @@ class Constants {
                'jitstressregs0x10':                      ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
                'jitstressregs0x80':                      ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
                'jitstressregs0x1000':                    ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
+               'jitstress2_jitstressregs1':              ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
+               'jitstress2_jitstressregs2':              ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
+               'jitstress2_jitstressregs3':              ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
+               'jitstress2_jitstressregs4':              ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
+               'jitstress2_jitstressregs8':              ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
+               'jitstress2_jitstressregs0x10':           ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
+               'jitstress2_jitstressregs0x80':           ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
+               'jitstress2_jitstressregs0x1000':         ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
+               'tailcallstress':                         ["TAILCALLSTRESS_FAIL", "TAILCALLSTRESS_EXCLUDE"],
+               // 'jitsse2only'                          // Only relevant to xarch
+               // 'jitnosimd'
+               // 'corefx_baseline'
+               // 'corefx_minopts'
+               // 'corefx_tieredcompilation'
+               // 'corefx_jitstress1'
+               // 'corefx_jitstress2'
+               // 'corefx_jitstressregs1'
+               // 'corefx_jitstressregs2'
+               // 'corefx_jitstressregs3'
+               // 'corefx_jitstressregs4'
+               // 'corefx_jitstressregs8'
+               // 'corefx_jitstressregs0x10'
+               // 'corefx_jitstressregs0x80'
+               // 'corefx_jitstressregs0x1000'
+               'gcstress0x3':                            ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE"],
+               'gcstress0xc':                            ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE"],
+               'zapdisable':                             ["ZAPDISABLE_FAIL", "ZAPDISABLE_EXCLUDE"],
+               // 'heapverify1'
+               // 'gcstress0xc_zapdisable'
+               // 'gcstress0xc_zapdisable_jitstress2'
+               // 'gcstress0xc_zapdisable_heapverify1'
+               'gcstress0xc_jitstress1':                 ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
+               'gcstress0xc_jitstress2':                 ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
+               // 'gcstress0xc_minopts_heapverify1'
+
+               //
+               // NOTE: the following scenarios are not defined in the 'allScenarios' list! Is this a bug?
+               //
+
                'minopts_zapdisable':                     ["ZAPDISABLE_FAIL", "ZAPDISABLE_EXCLUDE", "TAILCALLSTRESS_FAIL", "TAILCALLSTRESS_EXCLUDE"],
                'gcstress0x3_jitstress1':                 ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
                'gcstress0x3_jitstress2':                 ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
-               'gcstress0xc_jitstress1':                 ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
-               'gcstress0xc_jitstress2':                 ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
                'gcstress0x3_jitstressregs1':             ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
                'gcstress0x3_jitstressregs2':             ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
                'gcstress0x3_jitstressregs3':             ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
@@ -263,10 +327,6 @@ def static setMachineAffinity(def job, def os, def architecture, def options = n
     }
 }
 
-def static isJITStressJob(def scenario) {
-    return Constants.jitStressModeScenarios.containsKey(scenario) || Constants.r2rJitStressScenarios.containsKey(scenario)
-}
-
 def static isGCStressRelatedTesting(def scenario) {
     // The 'r2r_gcstress15' scenario is a basic scenario.
     // Detect it and make it a GCStress related.
@@ -286,7 +346,7 @@ def static isGCStressRelatedTesting(def scenario) {
     return isGCStressTesting
 }
 
-def static isCorefxTesting(def scenario) {
+def static isCoreFxScenario(def scenario) {
     def corefx_prefix = 'corefx_'
     if (scenario.length() < corefx_prefix.length()) {
         return false
@@ -294,10 +354,22 @@ def static isCorefxTesting(def scenario) {
     return scenario.substring(0,corefx_prefix.length()) == corefx_prefix
 }
 
-def static isR2R(def scenario) {
+def static isR2RBaselineScenario(def scenario) {
     return (scenario == 'r2r')
 }
 
+def static isR2RStressScenario(def scenario) {
+    return Constants.r2rStressScenarios.containsKey(scenario)
+}
+
+def static isR2RScenario(def scenario) {
+    return isR2RBaselineScenario(scenario) || isR2RStressScenario(scenario)
+}
+
+def static isJitStressScenario(def scenario) {
+    return Constants.jitStressModeScenarios.containsKey(scenario)
+}
+
 def static isLongGc(def scenario) {
     return (scenario == 'longgc' || scenario == 'gcsimulator')
 }
@@ -310,17 +382,21 @@ def static isGcReliabilityFramework(def scenario) {
     return (scenario == 'gc_reliability_framework')
 }
 
+def static isArmWindowsScenario(def scenario) {
+    return Constants.validArmWindowsScenarios.containsKey(scenario)
+}
+
 def static setTestJobTimeOut(newJob, scenario) {
     if (isGCStressRelatedTesting(scenario)) {
         Utilities.setJobTimeout(newJob, 4320)
     }
-    else if (isCorefxTesting(scenario)) {
+    else if (isCoreFxScenario(scenario)) {
         Utilities.setJobTimeout(newJob, 360)
     }
-    else if (Constants.jitStressModeScenarios.containsKey(scenario)) {
+    else if (isJitStressScenario(scenario)) {
         Utilities.setJobTimeout(newJob, 240)
     }
-    else if (isR2R(scenario)) {
+    else if (isR2RBaselineScenario(scenario)) {
         Utilities.setJobTimeout(newJob, 240)
     }
     else if (isLongGc(scenario)) {
@@ -336,7 +412,7 @@ def static setTestJobTimeOut(newJob, scenario) {
 }
 
 def static getJobFolder(def scenario) {
-    if (isJITStressJob(scenario)) {
+    if (isJitStressScenario(scenario) || isR2RStressScenario(scenario)) {
         return 'jitstress'
     }
     if (scenario == 'illink') {
@@ -354,16 +430,22 @@ def static getStressModeDisplayName(def scenario) {
             displayStr += ' ' + modeName + '=' + v
         }
     }
+
+    if (isCoreFxScenario(scenario)) {
+        displayStr = ('CoreFx ' + displayStr).trim()
+    }
+
     return displayStr
 }
 
-def static getR2RStressModeDisplayName(def scenario) {
-    // Assume the scenario name is one from the r2rJitStressScenarios dict, and remove its
-    // "r2r_" prefix.
+def static getR2RDisplayName(def scenario) {
+    // Assume the scenario name is one from the r2rStressScenarios dict, and remove its "r2r_" prefix.
     def displayStr = scenario
     def prefixLength = 'r2r_'.length()
     if (displayStr.length() >= prefixLength) {
-        displayStr = displayStr.substring(prefixLength, displayStr.length())
+        displayStr = "R2R " + displayStr.substring(prefixLength, displayStr.length())
+    } else if (scenario == 'r2r') {
+        displayStr = "R2R"
     }
     return displayStr
 }
@@ -835,7 +917,7 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os,
                 case 'OSX10.12':
                     // Triggers on the non-flow jobs aren't necessary here
                     // Corefx testing uses non-flow jobs.
-                    if (!isFlowJob && !isCorefxTesting(scenario)) {
+                    if (!isFlowJob && !isCoreFxScenario(scenario)) {
                         break
                     }
                     switch (scenario) {
@@ -857,33 +939,6 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os,
                                 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} IL RoundTrip Build and Test", "(?i).*test\\W+${os}\\W+${scenario}.*")
                             }
                             break
-                        case 'r2r':
-                            if (configuration == 'Release' || configuration == 'Checked') {
-                                Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} R2R Build & Test", "(?i).*test\\W+${os}\\W+${configuration}\\W+${scenario}.*")
-                            }
-                            break
-                        case 'r2r_gcstress15':
-                            if (configuration == 'Release' || configuration == 'Checked') {
-                                Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} GCStress 15 R2R Build & Test", "(?i).*test\\W+${os}\\W+${configuration}\\W+${scenario}.*")
-                            }
-                            break
-                        case 'r2r_jitstress1':
-                        case 'r2r_jitstress2':
-                        case 'r2r_jitstressregs1':
-                        case 'r2r_jitstressregs2':
-                        case 'r2r_jitstressregs3':
-                        case 'r2r_jitstressregs4':
-                        case 'r2r_jitstressregs8':
-                        case 'r2r_jitstressregs0x10':
-                        case 'r2r_jitstressregs0x80':
-                        case 'r2r_jitstressregs0x1000':
-                        case 'r2r_jitminopts':
-                        case 'r2r_jitforcerelocs':
-                            if (configuration == 'Release' || configuration == 'Checked') {
-                                def displayStr = getR2RStressModeDisplayName(scenario)
-                                Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} ${displayStr} R2R Build & Test", "(?i).*test\\W+${os}\\W+${configuration}\\W+${scenario}.*")
-                            }
-                            break
                         case 'longgc':
                             if (configuration == 'Release') {
                                 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Long-Running GC Build & Test", "(?i).*test\\W+${os}\\W+${configuration}\\W+${scenario}.*")
@@ -904,69 +959,28 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os,
                                 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} GC Reliability Framework", "(?i).*test\\W+${os}\\W+${configuration}\\W+${scenario}.*")
                             }
                             break
-                        case 'minopts':
-                        case 'tieredcompilation':
-                        case 'forcerelocs':
-                        case 'jitstress1':
-                        case 'jitstress2':
-                        case 'jitstressregs1':
-                        case 'jitstressregs2':
-                        case 'jitstressregs3':
-                        case 'jitstressregs4':
-                        case 'jitstressregs8':
-                        case 'jitstressregs0x10':
-                        case 'jitstressregs0x80':
-                        case 'jitstressregs0x1000':
-                        case 'jitstress2_jitstressregs1':
-                        case 'jitstress2_jitstressregs2':
-                        case 'jitstress2_jitstressregs3':
-                        case 'jitstress2_jitstressregs4':
-                        case 'jitstress2_jitstressregs8':
-                        case 'jitstress2_jitstressregs0x10':
-                        case 'jitstress2_jitstressregs0x80':
-                        case 'jitstress2_jitstressregs0x1000':
-                        case 'tailcallstress':
-                        case 'jitsse2only':
-                        case 'jitnosimd':
-                        case 'gcstress0x3':
-                        case 'gcstress0xc':
-                        case 'zapdisable':
-                        case 'heapverify1':
-                        case 'gcstress0xc_zapdisable':
-                        case 'gcstress0xc_zapdisable_jitstress2':
-                        case 'gcstress0xc_zapdisable_heapverify1':
-                        case 'gcstress0xc_jitstress1':
-                        case 'gcstress0xc_jitstress2':
-                        case 'gcstress0xc_minopts_heapverify1':
-                            def displayStr = getStressModeDisplayName(scenario)
-                            assert (os == 'Windows_NT') || (os in Constants.crossList)
-                            Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test (Jit - ${displayStr})",
-                               "(?i).*test\\W+${os}\\W+${scenario}.*")
-                            break
-                        case 'corefx_baseline':
-                        case 'corefx_minopts':
-                        case 'corefx_tieredcompilation':
-                        case 'corefx_jitstress1':
-                        case 'corefx_jitstress2':
-                        case 'corefx_jitstressregs1':
-                        case 'corefx_jitstressregs2':
-                        case 'corefx_jitstressregs3':
-                        case 'corefx_jitstressregs4':
-                        case 'corefx_jitstressregs8':
-                        case 'corefx_jitstressregs0x10':
-                        case 'corefx_jitstressregs0x80':
-                        case 'corefx_jitstressregs0x1000':
-                            def displayName = ('CoreFx ' + getStressModeDisplayName(scenario)).trim()
-                            assert (os == 'Windows_NT') || (os in Constants.crossList)
-                            Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test (Jit - ${displayName})",
-                               "(?i).*test\\W+${os}\\W+${architecture}\\W+${scenario}.*")
-                            break
                         default:
-                            println("Unknown scenario: ${scenario}");
-                            assert false
+                            if (isJitStressScenario(scenario)) {
+                                def displayStr = getStressModeDisplayName(scenario)
+                                assert (os == 'Windows_NT') || (os in Constants.crossList)
+                                Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test (Jit - ${displayStr})",
+                                   "(?i).*test\\W+${os}\\W+${architecture}\\W${configuration}\\W+${scenario}.*")
+                            }
+                            else if (isR2RScenario(scenario)) {
+                                if (configuration == 'Release' || configuration == 'Checked') {
+                                    def displayStr = getR2RDisplayName(scenario)
+                                    Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} ${displayStr} Build and Test",
+                                        "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
+                                }
+                            }
+                            else {
+                                println("Unknown scenario: ${scenario}");
+                                assert false
+                            }
                             break
                     }
                     break
+
                 case 'CentOS7.1':
                     switch (scenario) {
                         case 'default':
@@ -983,38 +997,18 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os,
                                 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Innerloop Build and Test")
                             }
                             break
-                        case 'r2r':
-                            if (configuration == 'Checked' || configuration == 'Release') {
-                                Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} R2R Build & Test", "(?i).*test\\W+${os}\\W+${configuration}\\W+${scenario}.*")
-                            }
-                            break
-                        case 'r2r_gcstress15':
-                            if (configuration == 'Release' || configuration == 'Checked') {
-                                Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} GCStress 15 R2R Build & Test", "(?i).*test\\W+${os}\\W+${configuration}\\W+${scenario}.*")
-                            }
-                            break
-                        case 'r2r_jitstress1':
-                        case 'r2r_jitstress2':
-                        case 'r2r_jitstressregs1':
-                        case 'r2r_jitstressregs2':
-                        case 'r2r_jitstressregs3':
-                        case 'r2r_jitstressregs4':
-                        case 'r2r_jitstressregs8':
-                        case 'r2r_jitstressregs0x10':
-                        case 'r2r_jitstressregs0x80':
-                        case 'r2r_jitstressregs0x1000':
-                        case 'r2r_jitminopts':
-                        case 'r2r_jitforcerelocs':
-                            if (configuration == 'Release' || configuration == 'Checked') {
-                                def displayStr = getR2RStressModeDisplayName(scenario)
-                                Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} ${displayStr} R2R Build & Test", "(?i).*test\\W+${os}\\W+${configuration}\\W+${scenario}.*")
-                            }
-                            break
                         default:
+                            if (isR2RScenario(scenario)) {
+                                if (configuration == 'Release' || configuration == 'Checked') {
+                                    def displayStr = getR2RDisplayName(scenario)
+                                    Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} ${displayStr} Build & Test",
+                                        "(?i).*test\\W+${os}\\W+{architecture}\\W+${configuration}\\W+${scenario}.*")
+                                }
+                            }
                             break
                     }
-
                     break
+
                 case 'Windows_NT':
                     switch (scenario) {
                         case 'default':
@@ -1033,33 +1027,6 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os,
                                 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} IL RoundTrip Build and Test", "(?i).*test\\W+${os}\\W+${scenario}.*")
                             }
                             break
-                        case 'r2r':
-                            if (configuration == 'Checked' || configuration == 'Release') {
-                                Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} R2R Build & Test", "(?i).*test\\W+${os}\\W+${configuration}\\W+${scenario}.*")
-                            }
-                            break
-                        case 'r2r_gcstress15':
-                            if (configuration == 'Release' || configuration == 'Checked') {
-                                Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} GCStress 15 R2R Build & Test", "(?i).*test\\W+${os}\\W+${configuration}\\W+${scenario}.*")
-                            }
-                            break
-                        case 'r2r_jitstress1':
-                        case 'r2r_jitstress2':
-                        case 'r2r_jitstressregs1':
-                        case 'r2r_jitstressregs2':
-                        case 'r2r_jitstressregs3':
-                        case 'r2r_jitstressregs4':
-                        case 'r2r_jitstressregs8':
-                        case 'r2r_jitstressregs0x10':
-                        case 'r2r_jitstressregs0x80':
-                        case 'r2r_jitstressregs0x1000':
-                        case 'r2r_jitminopts':
-                        case 'r2r_jitforcerelocs':
-                            if (configuration == 'Release' || configuration == 'Checked') {
-                                def displayStr = getR2RStressModeDisplayName(scenario)
-                                Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} ${displayStr} R2R Build & Test", "(?i).*test\\W+${os}\\W+${configuration}\\W+${scenario}.*")
-                            }
-                            break
                         case 'longgc':
                             if (configuration == 'Release') {
                                 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Long-Running GC Build & Test", "(?i).*test\\W+${os}\\W+${configuration}\\W+${scenario}.*")
@@ -1080,69 +1047,27 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os,
                                 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} GC Reliability Framework", "(?i).*test\\W+${os}\\W+${configuration}\\W+${scenario}.*")
                             }
                             break
-                        case 'minopts':
-                        case 'tieredcompilation':
-                        case 'forcerelocs':
-                        case 'jitstress1':
-                        case 'jitstress2':
-                        case 'jitstressregs1':
-                        case 'jitstressregs2':
-                        case 'jitstressregs3':
-                        case 'jitstressregs4':
-                        case 'jitstressregs8':
-                        case 'jitstressregs0x10':
-                        case 'jitstressregs0x80':
-                        case 'jitstressregs0x1000':
-                        case 'jitstress2_jitstressregs1':
-                        case 'jitstress2_jitstressregs2':
-                        case 'jitstress2_jitstressregs3':
-                        case 'jitstress2_jitstressregs4':
-                        case 'jitstress2_jitstressregs8':
-                        case 'jitstress2_jitstressregs0x10':
-                        case 'jitstress2_jitstressregs0x80':
-                        case 'jitstress2_jitstressregs0x1000':
-                        case 'tailcallstress':
-                        case 'jitsse2only':
-                        case 'jitnosimd':
-                        case 'gcstress0x3':
-                        case 'gcstress0xc':
-                        case 'zapdisable':
-                        case 'heapverify1':
-                        case 'gcstress0xc_zapdisable':
-                        case 'gcstress0xc_zapdisable_jitstress2':
-                        case 'gcstress0xc_zapdisable_heapverify1':
-                        case 'gcstress0xc_jitstress1':
-                        case 'gcstress0xc_jitstress2':
-                        case 'gcstress0xc_minopts_heapverify1':
-                            def displayStr = getStressModeDisplayName(scenario)
-                            assert (os == 'Windows_NT') || (os in Constants.crossList)
-                            Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test (Jit - ${displayStr})",
-                               "(?i).*test\\W+${os}\\W+${scenario}.*")
-                            break
-                        case 'corefx_baseline':
-                        case 'corefx_minopts':
-                        case 'corefx_tieredcompilation':
-                        case 'corefx_jitstress1':
-                        case 'corefx_jitstress2':
-                        case 'corefx_jitstressregs1':
-                        case 'corefx_jitstressregs2':
-                        case 'corefx_jitstressregs3':
-                        case 'corefx_jitstressregs4':
-                        case 'corefx_jitstressregs8':
-                        case 'corefx_jitstressregs0x10':
-                        case 'corefx_jitstressregs0x80':
-                        case 'corefx_jitstressregs0x1000':
-                            def displayName = ('CoreFx ' + getStressModeDisplayName(scenario)).trim()
-                            assert (os == 'Windows_NT') || (os in Constants.crossList)
-                            Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test (Jit - ${displayName})",
-                               "(?i).*test\\W+${os}\\W+${architecture}\\W+${scenario}.*")
-                            break
                         case 'illink':
                             Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} via ILLink", "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
                             break
                         default:
-                            println("Unknown scenario: ${scenario}");
-                            assert false
+                            if (isJitStressScenario(scenario)) {
+                                def displayStr = getStressModeDisplayName(scenario)
+                                assert (os == 'Windows_NT') || (os in Constants.crossList)
+                                Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test (Jit - ${displayStr})",
+                                   "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
+                            }
+                            else if (isR2RScenario(scenario)) {
+                                if (configuration == 'Release' || configuration == 'Checked') {
+                                    def displayStr = getR2RDisplayName(scenario)
+                                    Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} ${displayStr} Build & Test",
+                                        "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
+                                }
+                            }
+                            else {
+                                println("Unknown scenario: ${scenario}");
+                                assert false
+                            }
                             break
                     }
                     break
@@ -1199,18 +1124,26 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os,
                 case 'Windows_NT':
                     // Set up a private trigger
                     def contextString = "${os} ${architecture} Cross ${configuration}"
+                    def triggerString = "(?i).*test\\W+${os}\\W+${architecture}\\W+Cross\\W+${configuration}"
                     if (scenario == 'default') {
                         contextString += " Innerloop"
+                        triggerString += "\\W+Innerloop"
                     }
                     else {
                         contextString += " ${scenario}"
+                        triggerString += "\\W+${scenario}"
                     }
 
-                    contextString += " Build"
-                    // Debug configuration only does builds, no tests.
-                    if (configuration != 'Debug') {
-                        contextString += " and Test"
+                    if (configuration == 'Debug') {
+                        contextString += " Build"
+                        triggerString += "\\W+Build"
+                    } else {
+                        contextString += " Build and Test"
+                        triggerString += "\\W+Build and Test"
                     }
+
+                    triggerString += ".*"
+
                     switch (scenario) {
                         case 'default':
                             // Only Checked is a default trigger.
@@ -1220,15 +1153,13 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os,
                             }
                             else 
                             {
-                                Utilities.addPrivateGithubPRTriggerForBranch(job, branch, contextString,
-                                "(?i).*test\\W+${os}\\W+${architecture}\\W+Cross\\W+${configuration}.*", null, arm64Users)
+                                Utilities.addPrivateGithubPRTriggerForBranch(job, branch, contextString, triggerString, null, arm64Users)
                             }
                             break
                         default:
                             // Stress jobs will use this code path.
-                            if (Constants.validArmWindowsScenarios.containsKey(scenario)) {
-                                Utilities.addPrivateGithubPRTriggerForBranch(job, branch, contextString,
-                                "(?i).*test\\W+${os}\\W+${architecture}\\W+Cross\\W+${configuration}\\W+${scenario}.*", null, arm64Users)
+                            if (isArmWindowsScenario(scenario)) {
+                                Utilities.addPrivateGithubPRTriggerForBranch(job, branch, contextString, triggerString, null, arm64Users)
                             }
                             break
                     }
@@ -1241,23 +1172,28 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os,
             break
         // editor brace matching: }
         case 'arm64': // editor brace matching: {
-            assert Constants.validArmWindowsScenarios.containsKey(scenario)
-
             // Set up a private trigger
             def contextString = "${os} ${architecture} Cross ${configuration}"
+            def triggerString = "(?i).*test\\W+${os}\\W+${architecture}\\W+Cross\\W+${configuration}"
             if (scenario == 'default') {
                 contextString += " Innerloop"
+                triggerString += "\\W+Innerloop"
             }
             else {
                 contextString += " ${scenario}"
+                triggerString += "\\W+${scenario}"
             }
 
-            contextString += " Build"
-            // Debug builds only.
-            if (configuration != 'Debug') {
-               contextString += " and Test"
+            if (configuration == 'Debug') {
+                contextString += " Build"
+                triggerString += "\\W+Build"
+            } else {
+                contextString += " Build and Test"
+                triggerString += "\\W+Build and Test"
             }
 
+            triggerString += ".*"
+
             switch (os) {
                 case 'Ubuntu':
                 case 'Ubuntu16.04':
@@ -1267,64 +1203,35 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os,
                                 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} Cross ${configuration} Innerloop Build")
                             }
                             else {
-                                Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build & Test", "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
+                                Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test", triggerString)
                             }
                             
                             break
-                        case 'r2r':
-                            if (configuration == 'Checked' || configuration == 'Release') {
-                                Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} R2R Build & Test",
-                                "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
-                            }
-                            break
-                        case 'r2r_gcstress15':
-                            if (configuration == 'Release' || configuration == 'Checked') {
-                                Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} GCStress 15 R2R Build & Test",
-                                "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
-                            }
-                            break
-                        case 'r2r_jitstress1':
-                        case 'r2r_jitstress2':
-                        case 'r2r_jitstressregs1':
-                        case 'r2r_jitstressregs2':
-                        case 'r2r_jitstressregs3':
-                        case 'r2r_jitstressregs4':
-                        case 'r2r_jitstressregs8':
-                        case 'r2r_jitstressregs0x10':
-                        case 'r2r_jitstressregs0x80':
-                        case 'r2r_jitstressregs0x1000':
-                        case 'r2r_jitminopts':
-                        case 'r2r_jitforcerelocs':
-                            if (configuration == 'Release' || configuration == 'Checked') {
-                                def displayStr = getR2RStressModeDisplayName(scenario)
-                                Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} ${displayStr} R2R Build & Test",
-                                "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
-                            }
-                            break
                         default:
+                            if (isR2RScenario(scenario)) {
+                                if (configuration == 'Checked' || configuration == 'Release') {
+                                    def displayStr = getR2RDisplayName(scenario)
+                                    Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} ${displayStr} Build and Test", triggerString)
+                                }
+                            }
                             break
                     }
                     break
                 case 'Windows_NT':
+                    assert isArmWindowsScenario(scenario)
                     switch (scenario) {
                         case 'default':
-                            // Only run Checked jobs on PR Trigger.
                             if (configuration == 'Debug' || configuration == 'Checked') {
-                                // Add "Debug Build" to the above users' PRs since many of them are at higher risk of ARM64-breaking changes.
-                                //
-                                // Arm64 Ubuntu only builds at the moment due to insufficient hardware to do testing on pr.
                                 Utilities.addDefaultPrivateGithubPRTriggerForBranch(job, branch, contextString, null, arm64Users)
                             }
                             else {
-                                Utilities.addPrivateGithubPRTriggerForBranch(job, branch, contextString,
-                                "(?i).*test\\W+${os}\\W+${architecture}\\W+Cross\\W+${configuration}.*", null, arm64Users)
+                                Utilities.addPrivateGithubPRTriggerForBranch(job, branch, contextString, triggerString, null, arm64Users)
                             }
                             break
                         default:
                             // Stress jobs will use this code path.
-                            if (Constants.validArmWindowsScenarios.containsKey(scenario)) {
-                                Utilities.addPrivateGithubPRTriggerForBranch(job, branch, contextString,
-                                "(?i).*test\\W+${os}\\W+${architecture}\\W+Cross\\W+${configuration}\\W+${scenario}.*", null, arm64Users)
+                            if (isArmWindowsScenario(scenario)) {
+                                Utilities.addPrivateGithubPRTriggerForBranch(job, branch, contextString, triggerString, null, arm64Users)
                             }
                             break
                     }
@@ -1361,36 +1268,6 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os,
                             "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
                     }
                     break
-                case 'r2r':
-                    if (configuration == 'Checked' || configuration == 'Release') {
-                        Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} R2R Build & Test",
-                            "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
-                    }
-                    break
-                case 'r2r_gcstress15':
-                    if (configuration == 'Release' || configuration == 'Checked') {
-                        Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} GCStress 15 R2R Build & Test",
-                            "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
-                    }
-                    break
-                case 'r2r_jitstress1':
-                case 'r2r_jitstress2':
-                case 'r2r_jitstressregs1':
-                case 'r2r_jitstressregs2':
-                case 'r2r_jitstressregs3':
-                case 'r2r_jitstressregs4':
-                case 'r2r_jitstressregs8':
-                case 'r2r_jitstressregs0x10':
-                case 'r2r_jitstressregs0x80':
-                case 'r2r_jitstressregs0x1000':
-                case 'r2r_jitminopts':
-                case 'r2r_jitforcerelocs':
-                    if (configuration == 'Release' || configuration == 'Checked') {
-                        def displayStr = getR2RStressModeDisplayName(scenario)
-                        Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} ${displayStr} R2R Build & Test",
-                            "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
-                    }
-                    break
                 case 'longgc':
                     if (configuration == 'Release') {
                         Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Long-Running GC Build & Test",
@@ -1409,75 +1286,32 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os,
                             "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
                     }
                     break
-                case 'minopts':
-                case 'tieredcompilation':
-                case 'forcerelocs':
-                case 'jitstress1':
-                case 'jitstress2':
-                case 'jitstressregs1':
-                case 'jitstressregs2':
-                case 'jitstressregs3':
-                case 'jitstressregs4':
-                case 'jitstressregs8':
-                case 'jitstressregs0x10':
-                case 'jitstressregs0x80':
-                case 'jitstressregs0x1000':
-                case 'jitstress2_jitstressregs1':
-                case 'jitstress2_jitstressregs2':
-                case 'jitstress2_jitstressregs3':
-                case 'jitstress2_jitstressregs4':
-                case 'jitstress2_jitstressregs8':
-                case 'jitstress2_jitstressregs0x10':
-                case 'jitstress2_jitstressregs0x80':
-                case 'jitstress2_jitstressregs0x1000':
-                case 'tailcallstress':
-                case 'jitsse2only':
-                case 'jitnosimd':
-                case 'gcstress0x3':
-                case 'gcstress0xc':
-                case 'zapdisable':
-                case 'heapverify1':
-                case 'gcstress0xc_zapdisable':
-                case 'gcstress0xc_zapdisable_jitstress2':
-                case 'gcstress0xc_zapdisable_heapverify1':
-                case 'gcstress0xc_jitstress1':
-                case 'gcstress0xc_jitstress2':
-                case 'gcstress0xc_minopts_heapverify1':
-                    def displayStr = getStressModeDisplayName(scenario)
-                    Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test (Jit - ${displayStr})",
-                       "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
-                    break
-                case 'corefx_baseline':
-                case 'corefx_minopts':
-                case 'corefx_tieredcompilation':
-                case 'corefx_jitstress1':
-                case 'corefx_jitstress2':
-                case 'corefx_jitstressregs1':
-                case 'corefx_jitstressregs2':
-                case 'corefx_jitstressregs3':
-                case 'corefx_jitstressregs4':
-                case 'corefx_jitstressregs8':
-                case 'corefx_jitstressregs0x10':
-                case 'corefx_jitstressregs0x80':
-                case 'corefx_jitstressregs0x1000':
-                    def displayName = ('CoreFx ' + getStressModeDisplayName(scenario)).trim()
-                    assert (os == 'Windows_NT') || (os in Constants.crossList)
-                    Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test (Jit - ${displayName})",
-                       "(?i).*test\\W+${os}\\W+${architecture}\\W+${scenario}.*")
-                    break
                 case 'illink':
                     Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} via ILLink", "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
                     break
                 default:
-                    println("Unknown scenario: ${os} ${architecture} ${scenario}");
-                    assert false
+                    if (isJitStressScenario(scenario)) {
+                        def displayStr = getStressModeDisplayName(scenario)
+                        Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test (Jit - ${displayStr})",
+                           "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
+                    }
+                    else if (isR2RScenario(scenario)) {
+                        if (configuration == 'Release' || configuration == 'Checked') {
+                            def displayStr = getR2RDisplayName(scenario)
+                            Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} ${displayStr} Build & Test",
+                                "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
+                        }
+                    }
+                    else {
+                        println("Unknown scenario: ${os} ${architecture} ${scenario}");
+                        assert false
+                    }
                     break
             }
             break
          // editor brace matching: }
         case 'x86lb': // editor brace matching: {
             assert (os == 'Windows_NT')
-            assert (scenario == 'default' || Constants.r2rJitStressScenarios.containsKey(scenario))
 
             def arch = 'x86'
             def jit = 'legacy_backend'
@@ -1485,7 +1319,7 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os,
                 case 'default':
                     if (configuration == 'Checked') {
                         Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} Build and Test",
-                            "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}.*")
+                            "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+Build and Test.*")
                     }
                     break
                 default:
@@ -1517,7 +1351,7 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os,
     }
 }
 
-def static calculateBuildCommands(def newJob, def scenario, def branch, def isPR, def architecture, def configuration, def os, def enableCorefxTesting, def isBuildOnly) {
+def static calculateBuildCommands(def newJob, def scenario, def branch, def isPR, def architecture, def configuration, def os, def isBuildOnly) {
     def buildCommands = [];
     def osGroup = getOSGroup(os)
     def lowerConfiguration = configuration.toLowerCase()
@@ -1527,6 +1361,8 @@ def static calculateBuildCommands(def newJob, def scenario, def branch, def isPR
         priority = '0'
     }
 
+    def enableCorefxTesting = isCoreFxScenario(scenario)
+
     // Calculate the build steps, archival, and xunit results
     switch (os) {
         case 'Windows_NT': // editor brace matching: {
@@ -1545,6 +1381,12 @@ def static calculateBuildCommands(def newJob, def scenario, def branch, def isPR
                         arch = 'x64'
                     }
 
+                    if (scenario == 'formatting') {
+                        buildCommands += "python -u tests\\scripts\\format.py -c %WORKSPACE% -o Windows_NT -a ${arch}"
+                        Utilities.addArchival(newJob, "format.patch", "", true, false)
+                        break
+                    }
+
                     if (scenario == 'illink') {
                         buildCommands += "tests\\scripts\\build_illink.cmd clone ${arch}"
                     }
@@ -1562,124 +1404,94 @@ def static calculateBuildCommands(def newJob, def scenario, def branch, def isPR
                     if (enableCorefxTesting) {
                         buildOpts += ' skiptests';
                     } else {
-                        // Note: currently, build.cmd will pass through all arguments starting with an argument it doesn't recognize.
-                        // Since it doesn't process/recognize '-priority', make sure this is the last argument passed.
                         buildOpts += " -priority=${priority}"
                     }
 
-                    // Set __TestIntermediateDir for pri1 test builds. 
-                    // if __TestIntermediateDir is already set, build-test.cmd will
-                    // output test binaries to that directory. If it is not set, the
-                    // binaries are sent to a default directory whose name is about
+                    // Set __TestIntermediateDir to something short. If __TestIntermediateDir is already set, build-test.cmd will
+                    // output test binaries to that directory. If it is not set, the binaries are sent to a default directory whose name is about
                     // 35 characters long.
 
-                    if (Constants.jitStressModeScenarios.containsKey(scenario) ||
-                            scenario == 'default' ||
-                            scenario == 'r2r' ||
-                            scenario == 'r2r_gcstress15' ||
-                            isGcReliabilityFramework(scenario) ||
-                            scenario == 'jitdiff' ||
-                            scenario == 'ilrt' ||
-                            scenario == 'illink' ||
-                            Constants.r2rJitStressScenarios.containsKey(scenario)) {
-                        buildCommands += "set __TestIntermediateDir=int&&build.cmd ${lowerConfiguration} ${arch} ${buildOpts}"
-                    }
-                    else if (isLongGc(scenario) || scenario == 'standalone_gc') {
-                        buildCommands += "set __TestIntermediateDir=int&&build.cmd ${lowerConfiguration} ${arch} ${buildOpts}"
-                    }
-                    else if (scenario == 'formatting') {
-                        buildCommands += "python -u tests\\scripts\\format.py -c %WORKSPACE% -o Windows_NT -a ${arch}"
-                        Utilities.addArchival(newJob, "format.patch", "", true, false)
-                        break
-                    }
-                    else {
-                        println("Unknown scenario: ${scenario}")
-                        assert false
-                    }
+                    buildCommands += "set __TestIntermediateDir=int&&build.cmd ${lowerConfiguration} ${arch} ${buildOpts}"
 
                     if (!isBuildOnly) {
-                        def crossgenStr = ''
-                        def runcrossgentestsStr = ''
-                        def runjitstressStr = ''
-                        def runjitstressregsStr = ''
-                        def runjitmioptsStr = ''
-                        def runjitforcerelocsStr = ''
-                        def runjitdisasmStr = ''
-                        def runilasmroundtripStr = ''
-                        def gcstressStr = ''
-                        def gcTestArguments = ''
-                        def illinkArguments = ''
-                        def testEnvStr = ''
                         def runtestArguments = ''
-                        def standaloneGcStr = ''
+                        def testOpts = 'collectdumps'
 
-                        if (scenario == 'r2r' ||
-                            scenario == 'r2r_gcstress15' ||
-                            Constants.r2rJitStressScenarios.containsKey(scenario)) {
+                        if (isR2RScenario(scenario)) {
 
-                            // If this is a crossgen build, pass 'crossgen' to runtest.cmd
-                            crossgenStr = 'crossgen'
-                            runcrossgentestsStr = 'runcrossgentests'
+                            // If this is a ReadyToRun scenario, pass 'crossgen' or 'crossgenaltjit'
+                            // to cause framework assemblies to be crossgen'ed. Pass 'runcrossgentests'
+                            // to cause the tests to be crossgen'ed.
 
-                            if (scenario == 'r2r_jitstress1'){
-                                runjitstressStr = 'jitstress 1'
+                            if ((architecture == 'x86_arm_altjit') || (architecture == 'x64_arm64_altjit')) {
+                                testOpts += ' crossgenaltjit protononjit.dll'
+                            } else {
+                                testOpts += ' crossgen'
+                            }
+
+                            testOpts += ' runcrossgentests'
+
+                            if (scenario == 'r2r_jitstress1') {
+                                testOpts += ' jitstress 1'
                             }
                             else if (scenario == 'r2r_jitstress2') {
-                                runjitstressStr = 'jitstress 2'
+                                testOpts += ' jitstress 2'
                             }
-                            else if (scenario == 'r2r_jitstressregs1'){
-                                runjitstressregsStr = 'jitstressregs 1'
+                            else if (scenario == 'r2r_jitstressregs1') {
+                                testOpts += ' jitstressregs 1'
                             }
                             else if (scenario == 'r2r_jitstressregs2') {
-                                runjitstressregsStr = 'jitstressregs 2'
+                                testOpts += ' jitstressregs 2'
                             }
                             else if (scenario == 'r2r_jitstressregs3') {
-                                runjitstressregsStr = 'jitstressregs 3'
-                               }
+                                testOpts += ' jitstressregs 3'
+                            }
                             else if (scenario == 'r2r_jitstressregs4') {
-                                runjitstressregsStr = 'jitstressregs 4'
+                                testOpts += ' jitstressregs 4'
                             }
                             else if (scenario == 'r2r_jitstressregs8') {
-                                runjitstressregsStr = 'jitstressregs 8'
+                                testOpts += ' jitstressregs 8'
                             }
                             else if (scenario == 'r2r_jitstressregs0x10') {
-                                runjitstressregsStr = 'jitstressregs 0x10'
+                                testOpts += ' jitstressregs 0x10'
                             }
                             else if (scenario == 'r2r_jitstressregs0x80') {
-                                runjitstressregsStr = 'jitstressregs 0x80'
+                                testOpts += ' jitstressregs 0x80'
                             }
                             else if (scenario == 'r2r_jitstressregs0x1000') {
-                                runjitstressregsStr = 'jitstressregs 0x1000'
+                                testOpts += ' jitstressregs 0x1000'
                             }
                             else if (scenario == 'r2r_jitminopts') {
-                                runjitmioptsStr = 'jitminopts'
+                                testOpts += ' jitminopts'
                             }
                             else if (scenario == 'r2r_jitforcerelocs') {
-                                runjitforcerelocsStr = 'jitforcerelocs'
+                                testOpts += ' jitforcerelocs'
+                            }
+                            else if (scenario == 'r2r_gcstress15') {
+                                testOpts += ' gcstresslevel 0xF'
                             }
-                        }
-                        else if (scenario == 'r2r_gcstress15') {
-                            gcstressStr = 'gcstresslevel 0xF'
                         }
                         else if (scenario == 'jitdiff') {
-                            runjitdisasmStr = 'jitdisasm crossgen'
+                            testOpts += ' jitdisasm crossgen'
                         }
                         else if (scenario == 'ilrt') {
-                            runilasmroundtripStr = 'ilasmroundtrip'
+                            testOpts += ' ilasmroundtrip'
                         }
                         else if (isLongGc(scenario)) {
-                            gcTestArguments = "${scenario} sequential"
+                            testOpts += " ${scenario} sequential"
                         }
                         else if (scenario == 'standalone_gc') {
-                            standaloneGcStr = "gcname clrgc.dll"
+                            testOpts += ' gcname clrgc.dll'
                         }
-                        else if (scenario == 'illink')
-                        {
-                            illinkArguments = "link %WORKSPACE%\\linker\\linker\\bin\\netcore_Release\\netcoreapp2.0\\win10-${arch}\\publish\\illink.exe"
+                        else if (scenario == 'illink') {
+                            testOpts += " link %WORKSPACE%\\linker\\linker\\bin\\netcore_Release\\netcoreapp2.0\\win10-${arch}\\publish\\illink.exe"
                         }
 
+                        // If we are running a stress mode, we should write out the set of key
+                        // value env pairs to a file at this point and then we'll pass that to runtest.cmd
+
                         def envScriptPath = ''
-                        if (Constants.jitStressModeScenarios.containsKey(scenario)) {
+                        if (isJitStressScenario(scenario)) {
                             def buildCommandsStr = ''
                             envScriptPath = "%WORKSPACE%\\SetStressModes.bat"
                             buildCommandsStr += genStressModeScriptStep(os, scenario, Constants.jitStressModeScenarios[scenario], envScriptPath)
@@ -1708,15 +1520,12 @@ def static calculateBuildCommands(def newJob, def scenario, def branch, def isPR
                             envScriptPath = "%WORKSPACE%\\tests\\x64_arm64_altjit.cmd"
                         }
                         if (envScriptPath != '') {
-                            testEnvStr = "TestEnv ${envScriptPath}"
+                            testOpts += " TestEnv ${envScriptPath}"
                         }
 
-                        runtestArguments = "${lowerConfiguration} ${arch} ${gcstressStr} ${crossgenStr} ${runcrossgentestsStr} ${runjitstressStr} ${runjitstressregsStr} ${runjitmioptsStr} ${runjitforcerelocsStr} ${runjitdisasmStr} ${runilasmroundtripStr} ${gcTestArguments} ${illinkArguments} collectdumps ${testEnvStr} ${standaloneGcStr}"
+                        runtestArguments = "${lowerConfiguration} ${arch} ${testOpts}"
 
-                        // If we are running a stress mode, we should write out the set of key
-                        // value env pairs to a file at this point and then we'll pass that to runtest.cmd
-
-                        if (Constants.jitStressModeScenarios.containsKey(scenario) && enableCorefxTesting) {
+                        if (enableCorefxTesting) {
                             def workspaceRelativeFxRoot = "_/fx"
                             def absoluteFxRoot = "%WORKSPACE%\\_\\fx"
 
@@ -1755,7 +1564,7 @@ def static calculateBuildCommands(def newJob, def scenario, def branch, def isPR
                         // 10s of thousands of files around.
                         buildCommands += "powershell -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('.\\bin\\tests\\${osGroup}.${arch}.${configuration}', '.\\bin\\tests\\tests.zip')\"";
 
-                        if (!Constants.jitStressModeScenarios.containsKey(scenario)) {
+                        if (!isJitStressScenario(scenario)) {
                             // For windows, pull full test results and test drops for x86/x64.
                             // No need to pull for stress mode scenarios (downstream builds use the default scenario)
                             Utilities.addArchival(newJob, "bin/Product/**,bin/tests/tests.zip", "bin/Product/**/.nuget/**")
@@ -1777,7 +1586,7 @@ def static calculateBuildCommands(def newJob, def scenario, def branch, def isPR
                     break
                 case 'armlb':
                 case 'arm':
-                    assert Constants.validArmWindowsScenarios.containsKey(scenario)
+                    assert isArmWindowsScenario(scenario)
 
                     def machineAffinityOptions = ['use_arm64_build_machine' : true]
                     setMachineAffinity(newJob, os, architecture, machineAffinityOptions)
@@ -1812,7 +1621,7 @@ def static calculateBuildCommands(def newJob, def scenario, def branch, def isPR
                     Utilities.addArchival(newJob, "bin/Product/**,bin/tests/tests.zip", "bin/Product/**/.nuget/**")
                     break
                 case 'arm64':
-                    assert Constants.validArmWindowsScenarios.containsKey(scenario)
+                    assert isArmWindowsScenario(scenario)
 
                     def machineAffinityOptions = ['use_arm64_build_machine' : true]
                     setMachineAffinity(newJob, os, architecture, machineAffinityOptions)
@@ -1893,7 +1702,7 @@ def static calculateBuildCommands(def newJob, def scenario, def branch, def isPR
                         assert os == 'Ubuntu'
                         assert architecture == 'x64'
                         assert lowerConfiguration == 'checked'
-                        assert Constants.jitStressModeScenarios.containsKey(scenario)
+                        assert isJitStressScenario(scenario)
 
                         // Build coreclr
                         buildCommands += "./build.sh verbose ${lowerConfiguration} ${architecture}"
@@ -1924,7 +1733,6 @@ def static calculateBuildCommands(def newJob, def scenario, def branch, def isPR
                         buildCommands += "mkdir ./bin/Product/Linux.arm64.${configuration}/corefxNative"
                         buildCommands += "cp fx/bin/Linux.arm64.Release/native/* ./bin/Product/Linux.arm64.${configuration}/corefxNative"
 
-                        // Set time out
                         setTestJobTimeOut(newJob, scenario)
                         // Basic archiving of the build
                         Utilities.addArchival(newJob, "bin/Product/**,bin/obj/*/tests/**/*.dylib,bin/obj/*/tests/**/*.so", "bin/Product/**/.nuget/**")
@@ -1991,8 +1799,7 @@ def static calculateBuildCommands(def newJob, def scenario, def branch, def isPR
 
 // Additional scenario which can alter behavior
 
-def combinedScenarios = Constants.basicScenarios + Constants.jitStressModeScenarios.keySet()
-combinedScenarios.each { scenario ->
+Constants.allScenarios.each { scenario ->
     [true, false].each { isPR ->
         Constants.architectureList.each { architecture ->
             Constants.configurationList.each { configuration ->
@@ -2055,29 +1862,19 @@ combinedScenarios.each { scenario ->
 
                     // Skip scenarios (blanket skipping for jit stress modes, which are good most everywhere
                     // with checked builds)
-                    def enableCorefxTesting = false
-                    if (Constants.jitStressModeScenarios.containsKey(scenario)) {
+                    if (isJitStressScenario(scenario)) {
                         if (configuration != 'Checked') {
                             return
                         }
 
-                        enableCorefxTesting = isCorefxTesting(scenario)
-
                         // Since these are just execution time differences,
                         // skip platforms that don't execute the tests here (Windows_NT only)
-                        def isEnabledOS = (os == 'Windows_NT') || (os == 'Ubuntu' && enableCorefxTesting)
+                        def isEnabledOS = (os == 'Windows_NT') || (os == 'Ubuntu' && isCoreFxScenario(scenario))
                         if (!isEnabledOS || isBuildOnly) {
                             return
                         }
 
                         switch (architecture) {
-                            case 'armlb':
-                            case 'arm':
-                            case 'arm64':
-                                // Arm(64) stress is now handled through flow jobs.
-                                return
-                                
-                                break
                             case 'x64':
                             case 'x86':
                             case 'x86_arm_altjit':
@@ -2088,21 +1885,27 @@ combinedScenarios.each { scenario ->
                                 }
                                 // Windows: Everything implemented
                                 break
-                            case 'x86lb':
-                                // No stress modes for legacy jit.
-                                // (There's no technical reason we couldn't allow these.)
-                                return                            
+
                             default:
+                                // arm, arm64, armlb: stress is handled through flow jobs.
+                                // x86lb: No stress modes for legacy jit. (There's no technical reason we couldn't allow these.)
                                 return
                         }
                     }
-                    else {
-                        // If this is a r2r jitstress, jitstressregs, jitminopts, or forcerelocs scenario
-                        // and configuration is not Checked, bail out.
-                        if (configuration != 'Checked' && Constants.r2rJitStressScenarios.containsKey(scenario)) {
-                            return;
+                    else if (isR2RScenario(scenario)) {
+                        if (os != 'Windows_NT') {
+                            return
                         }
-
+                        // R2R test runs are not implemented for arm/armlb/arm64.
+                        if (architecture == 'arm' || architecture == 'armlb' || architecture == 'arm64') {
+                            return
+                        }
+                        // Stress scenarios only run with Checked builds, not Release (they would work with Debug, but be slow).
+                        if ((configuration != 'Checked') && isR2RStressScenario(scenario)) {
+                            return
+                        }
+                    }
+                    else {
                         // Skip scenarios
                         switch (scenario) {
                             case 'ilrt':
@@ -2131,40 +1934,6 @@ combinedScenarios.each { scenario ->
                                     return
                                 }
                                 break
-                            case 'r2r':
-                                // The r2r build isn't necessary except for Windows_NT.  Non-Windows NT uses
-                                // the default scenario build
-                                if (os != 'Windows_NT') {
-                                    return
-                                }
-                                if (architecture != 'x64') {
-                                    if ((architecture != 'arm64' && architecture != 'armlb' && architecture != 'arm') || (configuration == 'Debug')) {
-                                        return
-                                    }
-                                }
-                                break
-                            case 'r2r_gcstress15':
-                            case 'r2r_jitstress1':
-                            case 'r2r_jitstress2':
-                            case 'r2r_jitstressregs1':
-                            case 'r2r_jitstressregs2':
-                            case 'r2r_jitstressregs3':
-                            case 'r2r_jitstressregs4':
-                            case 'r2r_jitstressregs8':
-                            case 'r2r_jitstressregs0x10':
-                            case 'r2r_jitstressregs0x80':
-                            case 'r2r_jitstressregs0x1000':
-                            case 'r2r_jitminopts':
-                            case 'r2r_jitforcerelocs':
-                                // The above builds are not necessary except for Windows_NT.  Non-Windows NT uses
-                                // the default scenario build
-                                if (os != 'Windows_NT') {
-                                    return
-                                }
-                                if (architecture != 'x64' && architecture != 'x86') {
-                                    return
-                                }
-                                break
                             case 'longgc':
                             case 'gcsimulator':
                                 if (os != 'Windows_NT' && os != 'Ubuntu' && os != 'OSX10.12') {
@@ -2240,6 +2009,11 @@ combinedScenarios.each { scenario ->
                             break
                     }
 
+                    // Only implement 'default' for x86lb.
+                    if ((architecture == 'x86lb') && (scenario != 'default')) {
+                        return
+                    }
+
                     // Calculate names
                     def lowerConfiguration = configuration.toLowerCase()
                     def jobName = getJobName(configuration, architecture, os, scenario, isBuildOnly)
@@ -2263,7 +2037,7 @@ combinedScenarios.each { scenario ->
                     Utilities.standardJobSetup(newJob, project, isPR, "*/${branch}")
                     addTriggers(newJob, branch, isPR, architecture, os, configuration, scenario, false, isBuildOnly)
 
-                    def buildCommands = calculateBuildCommands(newJob, scenario, branch, isPR, architecture, configuration, os, enableCorefxTesting, isBuildOnly)
+                    def buildCommands = calculateBuildCommands(newJob, scenario, branch, isPR, architecture, configuration, os, isBuildOnly)
                     def osGroup = getOSGroup(os)
 
                     newJob.with {
@@ -2333,20 +2107,16 @@ combinedScenarios.each { scenario ->
 } // scenario
 
 
-// Create the Linux/OSX/CentOS coreclr test leg for debug and release and each scenario
-combinedScenarios.each { scenario ->
+// Create jobs requiring flow jobs. This includes x64 non-Windows, arm64 Ubuntu, and arm/arm64/armlb Windows.
+Constants.allScenarios.each { scenario ->
     [true, false].each { isPR ->
-        // Architectures.  x64 only at this point
         ['arm', 'armlb', 'x64', 'arm64'].each { architecture ->
-            // Put the OS's supported for coreclr cross testing here
             Constants.crossList.each { os ->
                 if (architecture == 'arm64') {
                     if (os != "Ubuntu" && os != "Windows_NT") {
                         return
                     }
-                }
-
-                if (architecture == 'arm' || architecture == 'armlb') {
+                } else if (architecture == 'arm' || architecture == 'armlb') {
                     if (os != 'Windows_NT') {
                         return
                     }
@@ -2360,63 +2130,70 @@ combinedScenarios.each { scenario ->
 
                 Constants.configurationList.each { configuration ->
 
-                    if (architecture == 'arm64' && os != "Windows_NT") {
-                        if (scenario != 'default' && scenario != 'r2r' && scenario != 'gcstress0x3' && scenario != 'gcstress0xc') {
+                    // First, filter based on OS.
+
+                    if (os == 'Windows_NT') {
+                        if (!isArmWindowsScenario(scenario)) {
                             return
                         }
                     }
-
-                    if (os == 'Windows_NT' && (architecture == 'arm' || architecture == 'armlb' || architecture == 'arm64')) {
-                        if (!(Constants.validArmWindowsScenarios.containsKey(scenario))) {
-                            return
+                    else {
+                        if (architecture == 'arm64') {
+                            if (scenario != 'default' && scenario != 'r2r' && scenario != 'gcstress0x3' && scenario != 'gcstress0xc') {
+                                return
+                            }
                         }
                     }
 
-                    if (Constants.jitStressModeScenarios.containsKey(scenario)) {
-                        if (configuration != 'Checked') {
+                    // For CentOS, we only want Checked/Release builds.
+                    if (os == 'CentOS7.1') {
+                        if (configuration != 'Checked' && configuration != 'Release') {
                             return
                         }
-                        if (isCorefxTesting(scenario)) {
+                        if (scenario != 'default' && !isR2RScenario(scenario) && !isJitStressScenario(scenario)) {
                             return
                         }
-                        //Skip stress modes for these scenarios
-                        if (os == 'RHEL7.2' || os == 'Debian8.4') {
+                    }
+
+                    // For RedHat and Debian, we only do Release builds.
+                    else if (os == 'RHEL7.2' || os == 'Debian8.4') {
+                        if (configuration != 'Release') {
+                            return
+                        }
+                        if (scenario != 'default') {
                             return
                         }
                     }
 
-                    // If this is a r2r jitstress, jitstressregs, jitminopts or forcerelocs scenario
-                    // and configuration is not Checked, bail out.
-                    else if (configuration != 'Checked' && Constants.r2rJitStressScenarios.containsKey(scenario)) {
-                        return;
-                    }
+                    // Next, filter based on scenario.
 
-                    // For CentOS, we only want Checked/Release builds.
-                    else if (os == 'CentOS7.1') {
-                        if (scenario != 'default' && 
-                            scenario != 'r2r' &&
-                            scenario != 'r2r_gcstress15' &&
-                            !(Constants.r2rJitStressScenarios.containsKey(scenario))) {
+                    if (isJitStressScenario(scenario)) {
+                        if (configuration != 'Checked') {
                             return
                         }
+                        // CoreFx JIT stress tests currently not implemented for flow jobs.
+                        if (isCoreFxScenario(scenario)) {
+                            return
+                        }
+                    }
+                    else if (isR2RBaselineScenario(scenario)) {
                         if (configuration != 'Checked' && configuration != 'Release') {
                             return
                         }
                     }
-
-                    // For RedHat and Debian, we only do Release builds.
-                    else if (os == 'RHEL7.2' || os == 'Debian8.4') {
-
-                        if (configuration != 'Release' || scenario != 'default') {
+                    else if (isR2RStressScenario(scenario)) {
+                        if (configuration != 'Checked') {
                             return
                         }
                     }
-
                     else {
                         // Skip scenarios
                         switch (scenario) {
                             case 'ilrt':
-                                // Release only
+                            case 'longgc':
+                            case 'gcsimulator':
+                                // Long GC tests take a long time on non-Release builds
+                                // ilrt is also Release only
                                 if (configuration != 'Release') {
                                     return
                                 }
@@ -2425,42 +2202,6 @@ combinedScenarios.each { scenario ->
                                 if (configuration != 'Checked') {
                                     return;
                                 }
-                            case 'r2r':
-                                //Skip configs that aren't Checked or Release (so just Debug, for now)
-                                if (configuration != 'Checked' && configuration != 'Release') {
-                                    return
-                                }
-                                break
-                            case 'r2r':
-                                //Skip configs that aren't Checked or Release (so just Debug, for now)
-                                if (configuration != 'Checked' && configuration != 'Release') {
-                                    return
-                                }
-                                break
-                            case 'r2r_gcstress15':
-                            case 'r2r_jitstress1':
-                            case 'r2r_jitstress2':
-                            case 'r2r_jitstressregs1':
-                            case 'r2r_jitstressregs2':
-                            case 'r2r_jitstressregs3':
-                            case 'r2r_jitstressregs4':
-                            case 'r2r_jitstressregs8':
-                            case 'r2r_jitstressregs0x10':
-                            case 'r2r_jitstressregs0x80':
-                            case 'r2r_jitstressregs0x1000':
-                            case 'r2r_jitminopts':
-                            case 'r2r_jitforcerelocs':
-                                //Skip configs that aren't Checked or Release (so just Debug, for now)
-                                if (configuration != 'Checked' && configuration != 'Release') {
-                                    return
-                                }
-                                break
-                            case 'longgc':
-                            case 'gcsimulator':
-                                // Long GC tests take a long time on non-Release builds
-                                if (configuration != 'Release') {
-                                    return
-                                }
                                 break
                             case 'gc_reliability_framework':
                             case 'standalone_gc':
@@ -2485,150 +2226,118 @@ combinedScenarios.each { scenario ->
                         }
                     }
 
+                    // Done filtering. Now, create the jobs.
+
                     def lowerConfiguration = configuration.toLowerCase()
                     def osGroup = getOSGroup(os)
                     def jobName = getJobName(configuration, architecture, os, scenario, false) + "_tst"
 
-                    def inputScenario = 'default'
                     def inputCoreCLRBuildName = projectFolder + '/' +
-                        Utilities.getFullJobName(project, getJobName(configuration, architecture, os, inputScenario, false), isPR)
-                    // If this is a stress scenario, there isn't any difference in the build job
-                    // so we didn't create a build only job for windows_nt specific to that stress mode.  Just copy
-                    // from the default scenario
+                        Utilities.getFullJobName(project, getJobName(configuration, architecture, os, 'default', false), isPR)
+
+                    // If this is a stress scenario, there isn't any difference in the build job, so we didn't create a build only
+                    // job for Windows_NT specific to that stress mode. Just copy from the default scenario.
                     def testBuildScenario = scenario
-                    if ( testBuildScenario == 'r2r' || Constants.r2rJitStressScenarios.containsKey(testBuildScenario) || isLongGc(testBuildScenario)) {
+                    if (isJitStressScenario(testBuildScenario) || isR2RScenario(testBuildScenario) || isLongGc(testBuildScenario)) {
                         testBuildScenario = 'default'
                     }
-                    def inputWindowTestsBuildName = ''
+
                     def inputWindowsTestBuildArch = architecture
                     if (architecture == "arm64" && os != "Windows_NT") {
                         // Use the x64 test build for arm64 unix
                         inputWindowsTestBuildArch = "x64"
                     }
-                    if (Constants.jitStressModeScenarios.containsKey(testBuildScenario)) {
-                        inputWindowTestsBuildName = projectFolder + '/' +
-                            Utilities.getFullJobName(project, getJobName(configuration, inputWindowsTestBuildArch, 'windows_nt', 'default', true), isPR)
-                    }
-                    else {
-                        inputWindowTestsBuildName = projectFolder + '/' +
-                            Utilities.getFullJobName(project, getJobName(configuration, inputWindowsTestBuildArch, 'windows_nt', testBuildScenario, true), isPR)
-                    }
-                    // Enable Server GC for Ubuntu PR builds
-                    def serverGCString = ''
 
-                    // Whether or not this test run should be run sequentially instead
-                    // of in parallel. Only used for long GC tests.
-                    def sequentialString = ''
+                    def inputWindowTestsBuildName = projectFolder + '/' +
+                        Utilities.getFullJobName(project, getJobName(configuration, inputWindowsTestBuildArch, 'windows_nt', testBuildScenario, true), isPR)
 
-                    // Whether or not this test run should run a specific playlist.
-                    // Only used for long GC tests.
-
-                    // A note - runtest.sh does have "--long-gc" and "--gcsimulator" options
-                    // for running long GC and GCSimulator tests, respectively. We don't use them
-                    // here because using a playlist file produces much more readable output on the CI machines
-                    // and reduces running time.
-                    def playlistString = ''
-
-                    if (os == 'Ubuntu' && isPR){
+                    // Enable Server GC for Ubuntu PR builds
+                    def serverGCString = ''
+                    if (os == 'Ubuntu' && isPR) {
                         serverGCString = '--useServerGC'
                     }
 
-                    // pass --crossgen to runtest.sh for crossgen builds
-                    def crossgenStr = ''
-                    def runcrossgentestsStr = ''
-                    def runjitstressStr = ''
-                    def runjitstressregsStr = ''
-                    def runjitmioptsStr = ''
-                    def runjitforcerelocsStr = ''
-                    def runjitdisasmStr = ''
-                    def runilasmroundtripStr = ''
-                    def gcstressStr = ''
-                    def illinkStr = ''
-                    def layoutOnlyStr =''
-                    def standaloneGcStr = ''
+                    def testOpts = ''
 
-                    if (scenario == 'r2r' || Constants.r2rJitStressScenarios.containsKey(scenario) ) {
-                            crossgenStr = '--crossgen'
-                            runcrossgentestsStr = '--runcrossgentests'
+                    if (isR2RScenario(scenario)) {
 
-                            if (scenario == 'r2r_jitstress1'){
-                                runjitstressStr = '--jitstress=1'
-                            }
-                            else if (scenario == 'r2r_jitstress2') {
-                                runjitstressStr = '--jitstress=2'
-                            }
-                            else if (scenario == 'r2r_jitstressregs1'){
-                                runjitstressregsStr = '--jitstressregs=1'
-                            }
-                            else if (scenario == 'r2r_jitstressregs2') {
-                                runjitstressregsStr = '--jitstressregs=2'
-                            }
-                            else if (scenario == 'r2r_jitstressregs3') {
-                                runjitstressregsStr = '--jitstressregs=3'
-                            }
-                            else if (scenario == 'r2r_jitstressregs4') {
-                                runjitstressregsStr = '--jitstressregs=4'
-                            }
-                            else if (scenario == 'r2r_jitstressregs8') {
-                                runjitstressregsStr = '--jitstressregs=8'
-                            }
-                            else if (scenario == 'r2r_jitstressregs0x10') {
-                                runjitstressregsStr = '--jitstressregs=0x10'
-                            }
-                            else if (scenario == 'r2r_jitstressregs0x80') {
-                                runjitstressregsStr = '--jitstressregs=0x80'
-                            }
-                            else if (scenario == 'r2r_jitstressregs0x1000') {
-                                runjitstressregsStr = '--jitstressregs=0x1000'
-                            }
-                            else if (scenario == 'r2r_jitminopts') {
-                                runjitmioptsStr = '--jitminopts'
-                            }
-                            else if (scenario == 'r2r_jitforcerelocs') {
-                                runjitforcerelocsStr = '--jitforcerelocs'
-                            }
-                    }
-                    if  (scenario == 'r2r_gcstress15')
-                    {
-                        gcstressStr = '--gcstresslevel=0xF'
-                    }
+                        testOpts += ' --crossgen --runcrossgentests'
 
-                    if (scenario == 'jitdiff')
-                    {
-                        runjitdisasmStr = '--jitdisasm --crossgen'
+                        if (scenario == 'r2r_jitstress1') {
+                            testOpts += ' --jitstress=1'
+                        }
+                        else if (scenario == 'r2r_jitstress2') {
+                            testOpts += ' --jitstress=2'
+                        }
+                        else if (scenario == 'r2r_jitstressregs1') {
+                            testOpts += ' --jitstressregs=1'
+                        }
+                        else if (scenario == 'r2r_jitstressregs2') {
+                            testOpts += ' --jitstressregs=2'
+                        }
+                        else if (scenario == 'r2r_jitstressregs3') {
+                            testOpts += ' --jitstressregs=3'
+                        }
+                        else if (scenario == 'r2r_jitstressregs4') {
+                            testOpts += ' --jitstressregs=4'
+                        }
+                        else if (scenario == 'r2r_jitstressregs8') {
+                            testOpts += ' --jitstressregs=8'
+                        }
+                        else if (scenario == 'r2r_jitstressregs0x10') {
+                            testOpts += ' --jitstressregs=0x10'
+                        }
+                        else if (scenario == 'r2r_jitstressregs0x80') {
+                            testOpts += ' --jitstressregs=0x80'
+                        }
+                        else if (scenario == 'r2r_jitstressregs0x1000') {
+                            testOpts += ' --jitstressregs=0x1000'
+                        }
+                        else if (scenario == 'r2r_jitminopts') {
+                            testOpts += ' --jitminopts'
+                        }
+                        else if (scenario == 'r2r_jitforcerelocs') {
+                            testOpts += ' --jitforcerelocs'
+                        }
+                        else if (scenario == 'r2r_gcstress15') {
+                            testOpts += ' --gcstresslevel=0xF'
+                        }
                     }
-
-                    if (scenario == 'illink')
-                    {
-                        illinkStr = '--link=\$WORKSPACE/linker/linker/bin/netcore_Release/netcoreapp2.0/ubuntu-x64/publish/illink'
+                    else if (scenario == 'jitdiff') {
+                        testOpts += ' --jitdisasm --crossgen'
                     }
-
-                    if (isLongGc(scenario)) {
+                    else if (scenario == 'illink') {
+                        testOpts += ' --link=\$WORKSPACE/linker/linker/bin/netcore_Release/netcoreapp2.0/ubuntu-x64/publish/illink'
+                    }
+                    else if (isLongGc(scenario)) {
                         // Long GC tests behave very poorly when they are not
                         // the only test running (many of them allocate until OOM).
-                        sequentialString = '--sequential'
+                        testOpts += ' --sequential'
 
+                        // A note - runtest.sh does have "--long-gc" and "--gcsimulator" options
+                        // for running long GC and GCSimulator tests, respectively. We don't use them
+                        // here because using a playlist file produces much more readable output on the CI machines
+                        // and reduces running time.
+                        //
                         // The Long GC playlist contains all of the tests that are
                         // going to be run. The GCSimulator playlist contains all of
                         // the GC simulator tests.
                         if (scenario == 'longgc') {
-                            playlistString = '--long-gc --playlist=./tests/longRunningGcTests.txt'
+                            testOpts += ' --long-gc --playlist=./tests/longRunningGcTests.txt'
                         }
                         else if (scenario == 'gcsimulator') {
-                            playlistString = '--gcsimulator --playlist=./tests/gcSimulatorTests.txt'
+                            testOpts += ' --gcsimulator --playlist=./tests/gcSimulatorTests.txt'
                         }
                     }
-
-                    if (isGcReliabilityFramework(scenario)) {
-                        layoutOnlyStr = '--build-overlay-only'
+                    else if (isGcReliabilityFramework(scenario)) {
+                        testOpts += ' --build-overlay-only'
                     }
-
-                    if (scenario == 'standalone_gc') {
+                    else if (scenario == 'standalone_gc') {
                         if (osGroup == 'OSX') {
-                            standaloneGcStr = '--gcname=libclrgc.dylib'
+                            testOpts += ' --gcname=libclrgc.dylib'
                         }
                         else if (osGroup == 'Linux') {
-                            standaloneGcStr = '--gcname=libclrgc.so'
+                            testOpts += ' --gcname=libclrgc.so'
                         }
                         else {
                             println("Unexpected OS group: ${osGroup} for os ${os}")
@@ -2717,7 +2426,7 @@ combinedScenarios.each { scenario ->
                                 // Execute the tests
                                 // If we are running a stress mode, we'll set those variables first
                                 def testEnvOpt = ""
-                                if (Constants.jitStressModeScenarios.containsKey(scenario)) {
+                                if (isJitStressScenario(scenario)) {
                                     def scriptFileName = "\$WORKSPACE/set_stress_test_env.sh"
                                     def createScriptCmds = genStressModeScriptStep(os, scenario, Constants.jitStressModeScenarios[scenario], scriptFileName)
                                     shell("${createScriptCmds}")
@@ -2734,10 +2443,7 @@ combinedScenarios.each { scenario ->
                 --coreClrBinDir=\"\${WORKSPACE}/bin/Product/${osGroup}.${architecture}.${configuration}\" \\
                 --mscorlibDir=\"\${WORKSPACE}/bin/Product/${osGroup}.${architecture}.${configuration}\" \\
                 --coreFxBinDir=\"\${WORKSPACE}/bin/CoreFxBinDir\" \\
-                --limitedDumpGeneration \\
-            ${testEnvOpt} ${serverGCString} ${gcstressStr} ${crossgenStr} ${runcrossgentestsStr} ${runjitstressStr} \\
-            ${runjitstressregsStr} ${runjitmioptsStr} ${runjitforcerelocsStr} ${runjitdisasmStr} ${runilasmroundtripStr} \\
-            ${illinkStr} ${sequentialString} ${playlistString} ${layoutOnlyStr} ${standaloneGcStr}""")
+                --limitedDumpGeneration ${testEnvOpt} ${serverGCString} ${testOpts}""")
 
                                 if (isGcReliabilityFramework(scenario)) {
                                     // runtest.sh doesn't actually execute the reliability framework - do it here.
@@ -2778,12 +2484,12 @@ combinedScenarios.each { scenario ->
 
                                 // If we are running a stress mode, we'll set those variables as well
                                 def stressValues = null
-                                if (Constants.jitStressModeScenarios.containsKey(scenario) || Constants.r2rJitStressScenarios.containsKey(scenario)) {
-                                    if (Constants.jitStressModeScenarios.containsKey(scenario)) {
+                                if (isJitStressScenario(scenario) || isR2RStressScenario(scenario)) {
+                                    if (isJitStressScenario(scenario)) {
                                         stressValues = Constants.jitStressModeScenarios[scenario]
                                     }
                                     else {
-                                        stressValues = Constants.r2rJitStressScenarios[scenario]
+                                        stressValues = Constants.r2rStressScenarios[scenario]
                                     }
 
                                     stressValues.each { key, value -> 
@@ -2791,6 +2497,9 @@ combinedScenarios.each { scenario ->
                                     }
                                 }
 
+                                // TODO: do whatever is necessary to support enabling R2R testing. Environment variables,
+                                // crossgen the framework assemblies, etc.
+
                                 // Create the smarty command
                                 def smartyCommand = "C:\\Tools\\Smarty.exe /noecid /noie /workers 9 /inc EXPECTED_PASS "
                                 def addSmartyFlag = { flag -> smartyCommand += flag + " "}
@@ -2802,7 +2511,7 @@ combinedScenarios.each { scenario ->
                                     addExclude("PROTOJIT_FAIL")
                                 }
 
-                                if (Constants.jitStressModeScenarios.containsKey(scenario)) {
+                                if (isJitStressScenario(scenario) || isR2RStressScenario(scenario)) {
                                     def failTag = "JITSTRESS_FAIL"
                                     def excludeTag = "JITSTRESS_EXCLUDE"
 
@@ -2851,7 +2560,7 @@ combinedScenarios.each { scenario ->
 
                     def affinityOptions = null
 
-                    if ((architecture == 'arm' || architecture == 'armlb' || architecture == 'arm64') && os == 'Windows_NT') {
+                    if (windowsArmJob == true) {
                         affinityOptions = [
                             "use_arm64_build_machine" : false
                         ]
@@ -2865,22 +2574,23 @@ combinedScenarios.each { scenario ->
 
                     setMachineAffinity(newJob, os, architecture, affinityOptions)
                     Utilities.standardJobSetup(newJob, project, isPR, "*/${branch}")
-                    // Set timeouts to 240.
-                    setTestJobTimeOut(newJob, scenario)
 
+                    // REVIEW: Should the scenario-base timeout be set in the "else" clause of the "architecture==arm64"?
+                    //         Should the "architecture==arm64" include arm/armlb?
+                    //         Should we be overriding possibly higher timeouts that would be set by setTestJobTimeOut()?
+                    setTestJobTimeOut(newJob, scenario)
                     if (architecture == 'arm64') {
                         Utilities.setJobTimeout(newJob, 240)
                     }
 
-                    if (os != "Windows_NT") {
+                    if (windowsArmJob != true) {
                         Utilities.addXUnitDotNETResults(newJob, '**/coreclrtests.xml')
                     }
                     else {
                         Utilities.addArchival(newJob, "bin/tests/${osGroup}.${architecture}.${configuration}/Smarty.run.0/*.smrt", '', true, false)
                     }
 
-                    // Create a build flow to join together the build and tests required to run this
-                    // test.
+                    // Create a build flow to join together the build and tests required to run this test.
                     // Windows CoreCLR build and Linux CoreCLR build (in parallel) ->
                     // Linux CoreCLR test
                     def flowJobName = getJobName(configuration, architecture, os, scenario, false) + "_flow"
@@ -2896,9 +2606,9 @@ combinedScenarios.each { scenario ->
                         return
                     }
 
-                    if (os == "Windows_NT" && architecture in validWindowsNTCrossArches) {
-                        // For windows arm jobs there is no reason to build a parrallel test job.
-                        // The product build support building and archiving the tests.
+                    if (windowsArmJob == true) {
+                        // For Windows arm jobs there is no reason to build a parallel test job.
+                        // The product build supports building and archiving the tests.
 
                         newFlowJob = buildFlowJob(Utilities.getFullJobName(project, flowJobName, isPR, folder)) {
                         buildFlow("""
@@ -2925,8 +2635,7 @@ build(params + [CORECLR_BUILD: coreclrBuildJob.build.number,
                         }
                     }
 
-                    // For the flow jobs set the machine affinity as x64
-                    // if an armarch
+                    // For the flow jobs set the machine affinity as x64 if an armarch.
                     def flowArch = architecture
 
                     if (flowArch in validWindowsNTCrossArches) {
index 1c58c92..2ddda53 100644 (file)
@@ -66,6 +66,8 @@ set __AgainstPackages=
 set __JitDisasm=
 set __IlasmRoundTrip=
 set __CollectDumps=
+set __DoCrossgen=
+set __CrossgenAltJit=
 
 :Arg_Loop
 if "%1" == "" goto ArgsDone
@@ -93,6 +95,7 @@ if /i "%1" == "TestEnv"               (set __TestEnv=%2&shift&shift&goto Arg_Loo
 if /i "%1" == "AgainstPackages"       (set __AgainstPackages=1&shift&goto Arg_Loop)
 if /i "%1" == "sequential"            (set __Sequential=1&shift&goto Arg_Loop)
 if /i "%1" == "crossgen"              (set __DoCrossgen=1&shift&goto Arg_Loop)
+if /i "%1" == "crossgenaltjit"        (set __DoCrossgen=1&set __CrossgenAltJit=%2&shift&shift&goto Arg_Loop)
 if /i "%1" == "longgc"                (set __LongGCTests=1&shift&goto Arg_Loop)
 if /i "%1" == "gcsimulator"           (set __GCSimulatorTests=1&shift&goto Arg_Loop)
 if /i "%1" == "jitstress"             (set COMPlus_JitStress=%2&shift&shift&goto Arg_Loop)
@@ -214,10 +217,7 @@ if "%__PerfTests%"=="true" goto RunPerfTests
 
 call :ResolveDependecies
 
-if not defined __DoCrossgen goto :SkipPrecompileFX
-call :PrecompileFX
-
-:SkipPrecompileFX
+if defined __DoCrossgen call :PrecompileFX
 
 if  defined __GenerateLayoutOnly (
     REM Delete the unecessary mscorlib.ni file.
@@ -353,7 +353,22 @@ echo %__MsgPrefix%Successfully precompiled and generated dasm for %2
 exit /b 0
 
 :PrecompileFX
+setlocal
+
+if defined __CrossgenAltJit (
+    REM Set altjit flags for the crossgen run. Note that this entire crossgen section is within a setlocal/endlocal scope,
+    REM so we don't need to save or unset these afterwards.
+    echo %__MsgPrefix%Setting altjit environment variables for %__CrossgenAltJit%.
+    set COMPlus_AltJit=*
+    set COMPlus_AltJitNgen=*
+    set COMPlus_AltJitName=%__CrossgenAltJit%
+    set COMPlus_AltJitAssertOnNYI=1
+    set COMPlus_NoGuiOnAssert=1
+    set COMPlus_ContinueOnAssert=0
+)
+
 for %%F in (%CORE_ROOT%\*.dll) do call :PrecompileAssembly "%CORE_ROOT%" "%%F" %%~nF%%~xF
+endlocal
 exit /b 0
 
 :msbuild
@@ -466,6 +481,7 @@ echo AgainstPackages           - This indicates that we are running tests that w
 echo GenerateLayoutOnly        - If specified will not run the tests and will only create the Runtime Dependency Layout
 echo sequential                - Run tests sequentially (no parallelism).
 echo crossgen                  - Precompile ^(crossgen^) the managed assemblies in CORE_ROOT before running the tests.
+echo crossgenaltjit ^<altjit^>   - Precompile ^(crossgen^) the managed assemblies in CORE_ROOT before running the tests, using the given altjit.
 echo link ^<ILlink^>             - Runs the tests after linking via the IL linker ^<ILlink^>.
 echo RunCrossgenTests          - Runs ReadytoRun tests
 echo jitstress ^<n^>             - Runs the tests with COMPlus_JitStress=n