1 // Import the utility functionality.
3 import jobs.generation.*
5 // The input project name (e.g. dotnet/coreclr)
6 def project = GithubProject
7 // The input branch name (e.g. master)
8 def branch = GithubBranchName
9 def projectFolder = Utilities.getFolderName(project) + '/' + Utilities.getFolderName(branch)
11 // Create a folder for JIT stress jobs and associated folder views
13 Utilities.addStandardFolderView(this, 'jitstress', project)
15 // Create a folder for testing via illink
17 Utilities.addStandardFolderView(this, 'illink', project)
19 def static getOSGroup(def os) {
20 def osGroupMap = ['Ubuntu':'Linux',
22 'Ubuntu16.04': 'Linux',
23 'Ubuntu16.10': 'Linux',
27 'Windows_NT':'Windows_NT',
30 def osGroup = osGroupMap.get(os, null)
31 assert osGroup != null : "Could not find os group for ${os}"
35 // We use this class (vs variables) so that the static functions can access data here.
38 // We have very limited ARM64 hardware (used for ARM/ARM64 testing). So only allow certain branches to use it.
39 def static LimitedHardwareBranches = [
42 // Innerloop build OS's
43 // The Windows_NT_BuildOnly OS is a way to speed up the Non-Windows builds by avoiding
44 // test execution in the build flow runs. It generates the exact same build
45 // as Windows_NT but without running the tests.
51 'Windows_NT_BuildOnly',
59 def static crossList = [
67 // This is a set of JIT stress modes combined with the set of variables that
68 // need to be set to actually enable that stress mode. The key of the map is the stress mode and
69 // the values are the environment variables
70 def static jitStressModeScenarios = [
71 'minopts' : ['COMPlus_JITMinOpts' : '1'],
72 'tieredcompilation' : ['COMPlus_EXPERIMENTAL_TieredCompilation' : '1'],
73 'forcerelocs' : ['COMPlus_ForceRelocs' : '1'],
74 'jitstress1' : ['COMPlus_JitStress' : '1'],
75 'jitstress2' : ['COMPlus_JitStress' : '2'],
76 'jitstressregs1' : ['COMPlus_JitStressRegs' : '1'],
77 'jitstressregs2' : ['COMPlus_JitStressRegs' : '2'],
78 'jitstressregs3' : ['COMPlus_JitStressRegs' : '3'],
79 'jitstressregs4' : ['COMPlus_JitStressRegs' : '4'],
80 'jitstressregs8' : ['COMPlus_JitStressRegs' : '8'],
81 'jitstressregs0x10' : ['COMPlus_JitStressRegs' : '0x10'],
82 'jitstressregs0x80' : ['COMPlus_JitStressRegs' : '0x80'],
83 'jitstressregs0x1000' : ['COMPlus_JitStressRegs' : '0x1000'],
84 'jitstress2_jitstressregs1' : ['COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '1'],
85 'jitstress2_jitstressregs2' : ['COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '2'],
86 'jitstress2_jitstressregs3' : ['COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '3'],
87 'jitstress2_jitstressregs4' : ['COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '4'],
88 'jitstress2_jitstressregs8' : ['COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '8'],
89 'jitstress2_jitstressregs0x10' : ['COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '0x10'],
90 'jitstress2_jitstressregs0x80' : ['COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '0x80'],
91 'jitstress2_jitstressregs0x1000' : ['COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '0x1000'],
92 'tailcallstress' : ['COMPlus_TailcallStress' : '1'],
93 'jitsse2only' : ['COMPlus_EnableAVX' : '0', 'COMPlus_EnableSSE3_4' : '0'],
94 'jitnosimd' : ['COMPlus_FeatureSIMD' : '0'],
95 'jitincompletehwintrinsic' : ['COMPlus_EnableIncompleteISAClass' : '1'],
96 'jitx86hwintrinsicnoavx' : ['COMPlus_EnableIncompleteISAClass' : '1', 'COMPlus_EnableAVX' : '0'], // testing the legacy SSE encoding
97 'jitx86hwintrinsicnoavx2' : ['COMPlus_EnableIncompleteISAClass' : '1', 'COMPlus_EnableAVX2' : '0'], // testing SNB/IVB
98 'jitx86hwintrinsicnosimd' : ['COMPlus_EnableIncompleteISAClass' : '1', 'COMPlus_FeatureSIMD' : '0'], // match "jitnosimd", may need to remove after decoupling HW intrinsic from FeatureSIMD
99 'jitnox86hwintrinsic' : ['COMPlus_EnableIncompleteISAClass' : '1', 'COMPlus_EnableSSE' : '0' , 'COMPlus_EnableSSE2' : '0' , 'COMPlus_EnableSSE3' : '0' , 'COMPlus_EnableSSSE3' : '0' , 'COMPlus_EnableSSE41' : '0' , 'COMPlus_EnableSSE42' : '0' , 'COMPlus_EnableAVX' : '0' , 'COMPlus_EnableAVX2' : '0' , 'COMPlus_EnableAES' : '0' , 'COMPlus_EnableBMI1' : '0' , 'COMPlus_EnableBMI2' : '0' , 'COMPlus_EnableFMA' : '0' , 'COMPlus_EnableLZCNT' : '0' , 'COMPlus_EnablePCLMULQDQ' : '0' , 'COMPlus_EnablePOPCNT' : '0'],
100 'corefx_baseline' : [ : ], // corefx baseline
101 'corefx_minopts' : ['COMPlus_JITMinOpts' : '1'],
102 'corefx_tieredcompilation' : ['COMPlus_EXPERIMENTAL_TieredCompilation' : '1'],
103 'corefx_jitstress1' : ['COMPlus_JitStress' : '1'],
104 'corefx_jitstress2' : ['COMPlus_JitStress' : '2'],
105 'corefx_jitstressregs1' : ['COMPlus_JitStressRegs' : '1'],
106 'corefx_jitstressregs2' : ['COMPlus_JitStressRegs' : '2'],
107 'corefx_jitstressregs3' : ['COMPlus_JitStressRegs' : '3'],
108 'corefx_jitstressregs4' : ['COMPlus_JitStressRegs' : '4'],
109 'corefx_jitstressregs8' : ['COMPlus_JitStressRegs' : '8'],
110 'corefx_jitstressregs0x10' : ['COMPlus_JitStressRegs' : '0x10'],
111 'corefx_jitstressregs0x80' : ['COMPlus_JitStressRegs' : '0x80'],
112 'corefx_jitstressregs0x1000' : ['COMPlus_JitStressRegs' : '0x1000'],
113 'gcstress0x3' : ['COMPlus_GCStress' : '0x3'],
114 'gcstress0xc' : ['COMPlus_GCStress' : '0xC'],
115 'zapdisable' : ['COMPlus_ZapDisable' : '1', 'COMPlus_ReadyToRun' : '0'],
116 'heapverify1' : ['COMPlus_HeapVerify' : '1'],
117 'gcstress0xc_zapdisable' : ['COMPlus_GCStress' : '0xC', 'COMPlus_ZapDisable' : '1', 'COMPlus_ReadyToRun' : '0'],
118 'gcstress0xc_zapdisable_jitstress2' : ['COMPlus_GCStress' : '0xC', 'COMPlus_ZapDisable' : '1', 'COMPlus_ReadyToRun' : '0', 'COMPlus_JitStress' : '2'],
119 'gcstress0xc_zapdisable_heapverify1' : ['COMPlus_GCStress' : '0xC', 'COMPlus_ZapDisable' : '1', 'COMPlus_ReadyToRun' : '0', 'COMPlus_HeapVerify' : '1'],
120 'gcstress0xc_jitstress1' : ['COMPlus_GCStress' : '0xC', 'COMPlus_JitStress' : '1'],
121 'gcstress0xc_jitstress2' : ['COMPlus_GCStress' : '0xC', 'COMPlus_JitStress' : '2'],
122 'gcstress0xc_minopts_heapverify1' : ['COMPlus_GCStress' : '0xC', 'COMPlus_JITMinOpts' : '1', 'COMPlus_HeapVerify' : '1']
125 // This is a set of ReadyToRun stress scenarios
126 def static r2rStressScenarios = [
127 'r2r_jitstress1' : ["COMPlus_JitStress": "1"],
128 'r2r_jitstress2' : ["COMPlus_JitStress": "2"],
129 'r2r_jitstressregs1' : ["COMPlus_JitStressRegs": "1"],
130 'r2r_jitstressregs2' : ["COMPlus_JitStressRegs": "2"],
131 'r2r_jitstressregs3' : ["COMPlus_JitStressRegs": "3"],
132 'r2r_jitstressregs4' : ["COMPlus_JitStressRegs": "4"],
133 'r2r_jitstressregs8' : ["COMPlus_JitStressRegs": "8"],
134 'r2r_jitstressregs0x10' : ["COMPlus_JitStressRegs": "0x10"],
135 'r2r_jitstressregs0x80' : ["COMPlus_JitStressRegs": "0x80"],
136 'r2r_jitstressregs0x1000' : ["COMPlus_JitStressRegs": "0x1000"],
137 'r2r_jitminopts' : ["COMPlus_JITMinOpts": "1"],
138 'r2r_jitforcerelocs' : ["COMPlus_ForceRelocs": "1"],
139 'r2r_gcstress15' : ["COMPlus_GCStress": "0xF"]
142 // This is the basic set of scenarios
143 def static basicScenarios = [
151 // 'jitdiff', // jitdiff is currently disabled, until someone spends the effort to make it fully work
153 'gc_reliability_framework',
157 def static allScenarios = basicScenarios + r2rStressScenarios.keySet() + jitStressModeScenarios.keySet()
159 // Valid PR trigger combinations.
160 def static prTriggeredValidInnerLoopCombos = [
176 'Windows_NT_BuildOnly': [
218 // A set of scenarios that are valid for arm/arm64 tests run on hardware. This is a map from valid scenario name
219 // to Tests.lst file categories to exclude.
221 // This list should contain a subset of the scenarios from `allScenarios`. Please keep this in the same order as that,
222 // and with the same values, with some commented out, for easier maintenance.
224 // Note that some scenarios that are commented out should be enabled, but haven't yet been.
226 def static validArmWindowsScenarios = [
230 'r2r': ["R2R_FAIL", "R2R_EXCLUDE"],
236 // 'gc_reliability_framework'
238 'r2r_jitstress1': ["R2R_FAIL", "R2R_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
239 'r2r_jitstress2': ["R2R_FAIL", "R2R_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
240 'r2r_jitstressregs1': ["R2R_FAIL", "R2R_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
241 'r2r_jitstressregs2': ["R2R_FAIL", "R2R_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
242 'r2r_jitstressregs3': ["R2R_FAIL", "R2R_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
243 'r2r_jitstressregs4': ["R2R_FAIL", "R2R_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
244 'r2r_jitstressregs8': ["R2R_FAIL", "R2R_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
245 'r2r_jitstressregs0x10': ["R2R_FAIL", "R2R_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
246 'r2r_jitstressregs0x80': ["R2R_FAIL", "R2R_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
247 'r2r_jitstressregs0x1000': ["R2R_FAIL", "R2R_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
248 'r2r_jitminopts': ["R2R_FAIL", "R2R_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE", "MINOPTS_FAIL", "MINOPTS_EXCLUDE"],
249 'r2r_jitforcerelocs': ["R2R_FAIL", "R2R_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
250 'r2r_gcstress15': ["R2R_FAIL", "R2R_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE", "GCSTRESS_FAIL", "GCSTRESS_EXCLUDE"],
251 'minopts': ["MINOPTS_FAIL", "MINOPTS_EXCLUDE"],
252 'tieredcompilation': [],
254 'jitstress1': ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
255 'jitstress2': ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
256 'jitstressregs1': ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
257 'jitstressregs2': ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
258 'jitstressregs3': ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
259 'jitstressregs4': ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
260 'jitstressregs8': ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
261 'jitstressregs0x10': ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
262 'jitstressregs0x80': ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
263 'jitstressregs0x1000': ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
264 'jitstress2_jitstressregs1': ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
265 'jitstress2_jitstressregs2': ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
266 'jitstress2_jitstressregs3': ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
267 'jitstress2_jitstressregs4': ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
268 'jitstress2_jitstressregs8': ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
269 'jitstress2_jitstressregs0x10': ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
270 'jitstress2_jitstressregs0x80': ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
271 'jitstress2_jitstressregs0x1000': ["JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
272 'tailcallstress': ["TAILCALLSTRESS_FAIL", "TAILCALLSTRESS_EXCLUDE"],
273 // 'jitsse2only' // Only relevant to xarch
274 'jitnosimd': [], // Only interesting on platforms where SIMD support exists.
275 // 'jitincompletehwintrinsic'
276 // 'jitx86hwintrinsicnoavx'
277 // 'jitx86hwintrinsicnoavx2'
278 // 'jitx86hwintrinsicnosimd'
279 // 'jitnox86hwintrinsic'
280 'corefx_baseline': [], // corefx tests don't use smarty
281 'corefx_minopts': [], // corefx tests don't use smarty
282 'corefx_tieredcompilation': [], // corefx tests don't use smarty
283 'corefx_jitstress1': [], // corefx tests don't use smarty
284 'corefx_jitstress2': [], // corefx tests don't use smarty
285 'corefx_jitstressregs1': [], // corefx tests don't use smarty
286 'corefx_jitstressregs2': [], // corefx tests don't use smarty
287 'corefx_jitstressregs3': [], // corefx tests don't use smarty
288 'corefx_jitstressregs4': [], // corefx tests don't use smarty
289 'corefx_jitstressregs8': [], // corefx tests don't use smarty
290 'corefx_jitstressregs0x10': [], // corefx tests don't use smarty
291 'corefx_jitstressregs0x80': [], // corefx tests don't use smarty
292 'corefx_jitstressregs0x1000': [], // corefx tests don't use smarty
293 'gcstress0x3': ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE"],
294 'gcstress0xc': ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE"],
295 'zapdisable': ["ZAPDISABLE_FAIL", "ZAPDISABLE_EXCLUDE"],
297 'gcstress0xc_zapdisable': ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "ZAPDISABLE_FAIL", "ZAPDISABLE_EXCLUDE"],
298 'gcstress0xc_zapdisable_jitstress2': ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "ZAPDISABLE_FAIL", "ZAPDISABLE_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
299 'gcstress0xc_zapdisable_heapverify1': ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "ZAPDISABLE_FAIL", "ZAPDISABLE_EXCLUDE"],
300 'gcstress0xc_jitstress1': ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
301 'gcstress0xc_jitstress2': ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
302 'gcstress0xc_minopts_heapverify1': ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "MINOPTS_FAIL", "MINOPTS_EXCLUDE"],
305 // NOTE: the following scenarios are not defined in the 'allScenarios' list! Is this a bug?
308 'minopts_zapdisable': ["ZAPDISABLE_FAIL", "ZAPDISABLE_EXCLUDE", "MINOPTS_FAIL", "MINOPTS_EXCLUDE"],
309 'gcstress0x3_jitstress1': ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
310 'gcstress0x3_jitstress2': ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
311 'gcstress0x3_jitstressregs1': ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
312 'gcstress0x3_jitstressregs2': ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
313 'gcstress0x3_jitstressregs3': ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
314 'gcstress0x3_jitstressregs4': ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
315 'gcstress0x3_jitstressregs8': ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
316 'gcstress0x3_jitstressregs0x10': ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
317 'gcstress0x3_jitstressregs0x80': ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
318 'gcstress0x3_jitstressregs0x1000': ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
319 'gcstress0xc_jitstressregs1': ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
320 'gcstress0xc_jitstressregs2': ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
321 'gcstress0xc_jitstressregs3': ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
322 'gcstress0xc_jitstressregs4': ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
323 'gcstress0xc_jitstressregs8': ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
324 'gcstress0xc_jitstressregs0x10': ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
325 'gcstress0xc_jitstressregs0x80': ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"],
326 'gcstress0xc_jitstressregs0x1000': ["GCSTRESS_FAIL", "GCSTRESS_EXCLUDE", "JITSTRESS_FAIL", "JITSTRESS_EXCLUDE"]
329 def static validLinuxArmScenarios = [
339 // 'gc_reliability_framework'
343 'r2r_jitstressregs1',
344 'r2r_jitstressregs2',
345 'r2r_jitstressregs3',
346 'r2r_jitstressregs4',
347 'r2r_jitstressregs8',
348 'r2r_jitstressregs0x10',
349 'r2r_jitstressregs0x80',
350 'r2r_jitstressregs0x1000',
352 'r2r_jitforcerelocs',
366 'jitstressregs0x1000',
367 'jitstress2_jitstressregs1',
368 'jitstress2_jitstressregs2',
369 'jitstress2_jitstressregs3',
370 'jitstress2_jitstressregs4',
371 'jitstress2_jitstressregs8',
372 'jitstress2_jitstressregs0x10',
373 'jitstress2_jitstressregs0x80',
374 'jitstress2_jitstressregs0x1000',
376 // 'jitsse2only' // Only relevant to xarch
378 // 'jitincompletehwintrinsic'
379 // 'jitx86hwintrinsicnoavx'
380 // 'jitx86hwintrinsicnoavx2'
381 // 'jitx86hwintrinsicnosimd'
382 // 'jitnox86hwintrinsic'
385 'corefx_tieredcompilation',
388 'corefx_jitstressregs1',
389 'corefx_jitstressregs2',
390 'corefx_jitstressregs3',
391 'corefx_jitstressregs4',
392 'corefx_jitstressregs8',
393 'corefx_jitstressregs0x10',
394 'corefx_jitstressregs0x80',
395 'corefx_jitstressregs0x1000',
400 'gcstress0xc_zapdisable',
401 'gcstress0xc_zapdisable_jitstress2',
402 'gcstress0xc_zapdisable_heapverify1',
403 'gcstress0xc_jitstress1',
404 'gcstress0xc_jitstress2',
405 'gcstress0xc_minopts_heapverify1'
408 def static configurationList = ['Debug', 'Checked', 'Release']
410 // This is the set of architectures
411 // Some of these are pseudo-architectures:
412 // armem -- ARM builds/runs using an emulator. Used for Ubuntu/Ubuntu16.04/Tizen runs.
413 // x86_arm_altjit -- ARM runs on x86 using the ARM altjit
414 // x64_arm64_altjit -- ARM64 runs on x64 using the ARM64 altjit
415 def static architectureList = ['arm', 'armem', 'x86_arm_altjit', 'x64_arm64_altjit', 'arm64', 'x64', 'x86']
417 // This set of architectures that cross build on Windows and run on Windows ARM64 hardware.
418 def static armWindowsCrossArchitectureList = ['arm', 'arm64']
421 // **************************************************************
422 // Create some specific views
424 // These aren't using the Utilities.addStandardFolderView() function, because that creates
425 // views based on a single regular expression. These views will be generated by adding a
426 // specific set of jobs to them.
428 // Utilities.addStandardFolderView() also creates a lot of additional stuff around the
429 // view, like "Build Statistics", "Job Statistics", "Unstable Jobs". Until it is determined
430 // those are required, don't add them (which simplifies the view pages, as well).
431 // **************************************************************
434 def static MergeJobView = null
435 def static PeriodicJobView = null
436 def static ArchitectureViews = [:]
437 def static OSViews = [:]
440 // MergeJobView: include all jobs that execute when a PR change is merged.
441 Views.MergeJobView = listView('Merge') {
454 // PeriodicJobView: include all jobs that execute on a schedule
455 Views.PeriodicJobView = listView('Periodic') {
468 // Create a view for non-PR jobs for each architecture.
469 Constants.architectureList.each { architecture ->
470 Views.ArchitectureViews[architecture] = listView(architecture) {
484 // Create a view for non-PR jobs for each OS.
485 Constants.osList.each { os ->
486 // Don't create one for the special 'Windows_NT_BuildOnly'
487 if (os == 'Windows_NT_BuildOnly') {
490 Views.OSViews[os] = listView(os) {
504 def static addToMergeView(def job) {
505 Views.MergeJobView.with {
512 def static addToPeriodicView(def job) {
513 Views.PeriodicJobView.with {
520 def static addToViews(def job, def isPR, def architecture, def os) {
522 // No views want PR jobs currently.
526 // Add to architecture view.
527 Views.ArchitectureViews[architecture].with {
534 Views.OSViews[os].with {
541 def static addPeriodicTriggerHelper(def job, String cronString, boolean alwaysRuns = false) {
542 addToPeriodicView(job)
543 Utilities.addPeriodicTrigger(job, cronString, alwaysRuns)
546 def static addGithubPushTriggerHelper(def job) {
548 Utilities.addGithubPushTrigger(job)
552 def static setMachineAffinity(def job, def os, def architecture, def options = null) {
553 assert os instanceof String
554 assert architecture instanceof String
556 def armArches = ['arm', 'armem', 'arm64']
557 def supportedArmLinuxOs = ['Ubuntu', 'Ubuntu16.04', 'Tizen']
559 if (!(architecture in armArches)) {
560 assert options == null
561 Utilities.setMachineAffinity(job, os, 'latest-or-auto')
566 // This is an arm(64) job.
568 // There are several options.
572 // Arm32 (Build) -> latest-arm64
573 // |-> os == "Windows_NT" && (architecture == "arm") && options['use_arm64_build_machine'] == true
574 // Arm32 (Test) -> arm64-windows_nt
575 // |-> os == "Windows_NT" && (architecture == "arm") && options['use_arm64_build_machine'] == false
577 // Arm64 (Build) -> latest-arm64
578 // |-> os == "Windows_NT" && architecture == "arm64" && options['use_arm64_build_machine'] == true
579 // Arm64 (Test) -> arm64-windows_nt
580 // |-> os == "Windows_NT" && architecture == "arm64" && options['use_arm64_build_machine'] == false
584 // Arm32 emulator (Build, Test) -> arm-cross-latest
585 // |-> os in supportedArmLinuxOs && (architecture == "armem")
587 // Arm32 hardware (Flow) -> Ubuntu 16.04 latest-or-auto (don't use limited arm hardware)
588 // |-> os == "Ubuntu" && (architecture == "arm") && options['is_flow_job'] == true
589 // Arm32 hardware (Build) -> Ubuntu 16.04 latest-or-auto
590 // |-> os == "Ubuntu" && (architecture == "arm") && options['is_build_job'] == true
591 // Arm32 hardware (Test) -> ubuntu.1404.arm32.open
592 // |-> os == "Ubuntu" && (architecture == "arm")
594 // Arm64 (Build) -> arm64-cross-latest
595 // |-> os != "Windows_NT" && architecture == "arm64" && options['is_build_only'] == true
596 // Arm64 Small Page Size (Test) -> arm64-small-page-size
597 // |-> os != "Windows_NT" && architecture == "arm64" && options['large_pages'] == false
598 // Arm64 Large Page Size (Test) -> arm64-huge-page-size
599 // |-> os != "Windows_NT" && architecture == "arm64" && options['large_pages'] == true
601 // This has to be a arm arch
602 assert architecture in armArches
603 if (os == "Windows_NT") {
604 // arm32/arm64 Windows jobs share the same machines for now
605 def isBuild = options['use_arm64_build_machine'] == true
607 if (isBuild == true) {
608 Utilities.setMachineAffinity(job, os, 'latest-arm64')
610 Utilities.setMachineAffinity(job, os, 'arm64-windows_nt')
613 assert os != 'Windows_NT'
614 assert os in supportedArmLinuxOs
616 if (architecture == 'arm64') {
617 assert (architecture == 'arm64') && (os == 'Ubuntu')
618 def isFlow = (options != null) && (options['is_flow_job'] == true)
619 def isBuild = (options != null) && (options['is_build_job'] == true)
620 if (isFlow || isBuild) {
621 // Arm64 Ubuntu build machine. Build uses docker, so the actual host OS is not
622 // very important. Therefore, use latest or auto. Flow jobs don't need to use
624 Utilities.setMachineAffinity(job, 'Ubuntu16.04', 'latest-or-auto')
626 // Arm64 Linux test machines
627 if ((options != null) && (options['large_pages'] == true)) {
628 Utilities.setMachineAffinity(job, os, 'arm64-huge-page-size')
630 Utilities.setMachineAffinity(job, os, 'arm64-small-page-size')
634 else if (architecture == 'armem') {
635 // arm emulator (Ubuntu/Ubuntu16.04/Tizen). Build and test on same machine,
637 Utilities.setMachineAffinity(job, 'Ubuntu', 'arm-cross-latest')
640 // arm Ubuntu on hardware.
641 assert (architecture == 'arm') && (os == 'Ubuntu')
642 def isFlow = (options != null) && (options['is_flow_job'] == true)
643 def isBuild = (options != null) && (options['is_build_job'] == true)
644 if (isFlow || isBuild) {
645 // arm Ubuntu build machine. Build uses docker, so the actual host OS is not
646 // very important. Therefore, use latest or auto. Flow jobs don't need to use
648 Utilities.setMachineAffinity(job, 'Ubuntu16.04', 'latest-or-auto')
650 // arm Ubuntu test machine
651 // There is no tag (like, e.g., "arm-latest") for this, so don't call
652 // Utilities.setMachineAffinity. Just add the machine affinity
653 // manually. We specify the Helix queue name here.
655 label('ubuntu.1404.arm32.open')
662 // setJobMachineAffinity: compute the machine affinity options for a job,
663 // then set the job with those affinity options.
664 def static setJobMachineAffinity(def architecture, def os, def isBuildJob, def isTestJob, def isFlowJob, def job)
666 assert (isBuildJob && !isTestJob && !isFlowJob) ||
667 (!isBuildJob && isTestJob && !isFlowJob) ||
668 (!isBuildJob && !isTestJob && isFlowJob)
670 def affinityOptions = null
671 def affinityArchitecture = architecture
673 if (os == "Windows_NT") {
674 if (architecture in Constants.armWindowsCrossArchitectureList) {
676 affinityOptions = [ "use_arm64_build_machine" : true ]
677 } else if (isTestJob) {
678 affinityOptions = [ "use_arm64_build_machine" : false ]
679 } else if (isFlowJob) {
680 // For the flow jobs set the machine affinity as x64
681 affinityArchitecture = 'x64'
686 if (architecture == 'arm64') {
688 affinityOptions = ['is_build_job': true]
689 } else if (isFlowJob) {
690 affinityOptions = ['is_flow_job': true]
691 } else if (isTestJob) {
692 affinityOptions = [ "large_pages" : false ]
695 else if (architecture == 'arm') {
697 affinityOptions = ['is_build_job': true]
698 } else if (isFlowJob) {
699 affinityOptions = ['is_flow_job': true]
704 setMachineAffinity(job, os, affinityArchitecture, affinityOptions)
707 def static isGCStressRelatedTesting(def scenario) {
708 // The 'r2r_gcstress15' scenario is a basic scenario.
709 // Detect it and make it a GCStress related.
710 if (scenario == 'r2r_gcstress15')
715 def gcStressTestEnvVars = [ 'COMPlus_GCStress', 'COMPlus_ZapDisable', 'COMPlus_HeapVerify']
716 def scenarioName = scenario.toLowerCase()
717 def isGCStressTesting = false
718 Constants.jitStressModeScenarios[scenario].each{ k, v ->
719 if (k in gcStressTestEnvVars) {
720 isGCStressTesting = true;
723 return isGCStressTesting
726 def static isCoreFxScenario(def scenario) {
727 def corefx_prefix = 'corefx_'
728 if (scenario.length() < corefx_prefix.length()) {
731 return scenario.substring(0,corefx_prefix.length()) == corefx_prefix
734 def static isR2RBaselineScenario(def scenario) {
735 return (scenario == 'r2r')
738 def static isR2RStressScenario(def scenario) {
739 return Constants.r2rStressScenarios.containsKey(scenario)
742 def static isR2RScenario(def scenario) {
743 return isR2RBaselineScenario(scenario) || isR2RStressScenario(scenario)
746 def static isJitStressScenario(def scenario) {
747 return Constants.jitStressModeScenarios.containsKey(scenario)
750 def static isLongGc(def scenario) {
751 return (scenario == 'longgc' || scenario == 'gcsimulator')
754 def static isJitDiff(def scenario) {
755 return (scenario == 'jitdiff')
758 def static isGcReliabilityFramework(def scenario) {
759 return (scenario == 'gc_reliability_framework')
762 def static isArmWindowsScenario(def scenario) {
763 return Constants.validArmWindowsScenarios.containsKey(scenario)
766 def static isValidPrTriggeredInnerLoopJob(os, architecture, configuration, isBuildOnly) {
767 if (isBuildOnly == true) {
768 os = 'Windows_NT_BuildOnly'
771 def validOsPrTriggerArchConfigs = Constants.prTriggeredValidInnerLoopCombos[os]
773 if (validOsPrTriggerArchConfigs == null) {
777 if (validOsPrTriggerArchConfigs[architecture] != null) {
778 def validOsPrTriggerConfigs = validOsPrTriggerArchConfigs[architecture]
780 if (!(configuration in validOsPrTriggerConfigs)) {
790 def static getFxBranch(def branch) {
791 def fxBranch = branch
792 // Map 'dev/unix_test_workflow' to 'master' so we can test CoreFX jobs in the CoreCLR dev/unix_test_workflow
793 // branch even though CoreFX doesn't have such a branch.
794 if (branch == 'dev/unix_test_workflow') {
800 def static setJobTimeout(newJob, isPR, architecture, configuration, scenario, isBuildOnly) {
801 // 2 hours (120 minutes) is the default timeout
803 def innerLoop = (scenario == "innerloop")
806 // Pri-1 test builds take a long time. Default PR jobs are Pri-0; everything else is Pri-1
807 // (see calculateBuildCommands()). So up the Pri-1 build jobs timeout.
812 // Note that these can only increase, never decrease, the Pri-1 timeout possibly set above.
813 if (isGCStressRelatedTesting(scenario)) {
816 else if (isCoreFxScenario(scenario)) {
819 else if (isJitStressScenario(scenario)) {
822 else if (isR2RBaselineScenario(scenario)) {
825 else if (isLongGc(scenario)) {
828 else if (isJitDiff(scenario)) {
831 else if (isGcReliabilityFramework(scenario)) {
834 else if (architecture == 'armem' || architecture == 'arm64') {
838 if (architecture == 'arm') {
839 // ARM32 machines are particularly slow.
844 if (configuration == 'Debug') {
845 // Debug runs can be very slow. Add an hour.
849 if (architecture == 'x86_arm_altjit' || architecture == 'x64_arm64_altjit') {
850 // AltJit runs compile all methods twice.
854 // If we've changed the timeout from the default, set it in the job.
856 if (timeout != 120) {
857 Utilities.setJobTimeout(newJob, timeout)
861 def static getJobFolder(def scenario) {
862 if (isJitStressScenario(scenario) || isR2RStressScenario(scenario)) {
865 if (scenario == 'illink') {
871 def static getStressModeDisplayName(def scenario) {
873 Constants.jitStressModeScenarios[scenario].each{ k, v ->
874 def prefixLength = 'COMPlus_'.length()
875 if (k.length() >= prefixLength) {
876 def modeName = k.substring(prefixLength, k.length())
877 displayStr += ' ' + modeName + '=' + v
881 if (isCoreFxScenario(scenario)) {
882 displayStr = ('CoreFx ' + displayStr).trim()
888 def static getR2RDisplayName(def scenario) {
889 // Assume the scenario name is one from the r2rStressScenarios dict, and remove its "r2r_" prefix.
890 def displayStr = scenario
891 def prefixLength = 'r2r_'.length()
892 if (displayStr.length() >= prefixLength) {
893 displayStr = "R2R " + displayStr.substring(prefixLength, displayStr.length())
894 } else if (scenario == 'r2r') {
901 // Functions to create an environment script.
902 // envScriptCreate -- initialize the script (call first)
903 // envScriptFinalize -- finalize the script (call last)
904 // envScriptSetStressModeVariables -- set stress mode variables in the env script
905 // envScriptAppendExistingScript -- append an existing script to the generated script
907 // Each script returns a string of commands. Concatenate all the strings together before
908 // adding them to the builds commands, to make sure they get executed as one Jenkins script.
911 // Initialize the environment setting script.
912 def static envScriptCreate(def os, def stepScriptLocation) {
914 if (os == 'Windows_NT') {
915 stepScript += "echo Creating TestEnv script\r\n"
916 stepScript += "if exist ${stepScriptLocation} del ${stepScriptLocation}\r\n"
918 // Create at least an empty script.
919 stepScript += "echo. > ${stepScriptLocation}\r\n"
922 stepScript += "echo Creating environment setting script\n"
923 stepScript += "echo \\#\\!/usr/bin/env bash > ${stepScriptLocation}\n"
929 // Generates the string for setting stress mode variables.
930 def static envScriptSetStressModeVariables(def os, def stressModeVars, def stepScriptLocation) {
932 if (os == 'Windows_NT') {
933 stressModeVars.each{ k, v ->
934 // Write out what we are writing to the script file
935 stepScript += "echo Setting ${k}=${v}\r\n"
936 // Write out the set itself to the script file`
937 stepScript += "echo set ${k}=${v} >> ${stepScriptLocation}\r\n"
941 stressModeVars.each{ k, v ->
942 // Write out what we are writing to the script file
943 stepScript += "echo Setting ${k}=${v}\n"
944 // Write out the set itself to the script file`
945 stepScript += "echo export ${k}=${v} >> ${stepScriptLocation}\n"
952 // Append an existing script to an environment script.
953 // Returns string of commands to do this.
954 def static envScriptAppendExistingScript(def os, def appendScript, def stepScriptLocation) {
955 assert (os == 'Windows_NT')
958 stepScript += "echo Appending ${appendScript} to ${stepScriptLocation}\r\n"
959 stepScript += "type ${appendScript} >> ${stepScriptLocation}\r\n"
964 // Finalize an environment setting script.
965 // Returns string of commands to do this.
966 def static envScriptFinalize(def os, def stepScriptLocation) {
969 if (os == 'Windows_NT') {
970 // Display the resulting script. This is useful when looking at the output log file.
971 stepScript += "echo Display the total script ${stepScriptLocation}\r\n"
972 stepScript += "type ${stepScriptLocation}\r\n"
975 stepScript += "chmod +x ${stepScriptLocation}\n"
981 def static isNeedDocker(def architecture, def os, def isBuild) {
983 if (architecture == 'x86' && os == 'Ubuntu') {
986 else if (architecture == 'armem') {
989 else if (architecture == 'arm') {
990 if (os == 'Ubuntu') {
994 else if (architecture == 'arm64') {
995 if (os == 'Ubuntu') {
1001 if (architecture == 'x86' && os == 'Ubuntu') {
1008 def static getDockerImageName(def architecture, def os, def isBuild) {
1009 // We must change some docker private images to official later
1011 if (architecture == 'x86' && os == 'Ubuntu') {
1012 return "hseok82/dotnet-buildtools-prereqs:ubuntu-16.04-crossx86-ef0ac75-20175511035548"
1014 else if (architecture == 'armem') {
1015 if (os == 'Ubuntu') {
1016 return "microsoft/dotnet-buildtools-prereqs:ubuntu-14.04-cross-e435274-20180405193556"
1018 else if (os == 'Ubuntu16.04') {
1019 return "microsoft/dotnet-buildtools-prereqs:ubuntu-16.04-cross-e435274-20180404203310"
1021 else if (os == 'Tizen') {
1022 return "tizendotnet/dotnet-buildtools-prereqs:ubuntu-16.04-cross-e435274-20180426002255-tizen-rootfs-5.0m1"
1025 else if (architecture == 'arm') {
1026 if (os == 'Ubuntu') {
1027 return "microsoft/dotnet-buildtools-prereqs:ubuntu-14.04-cross-e435274-20180426002420"
1030 else if (architecture == 'arm64') {
1031 if (os == 'Ubuntu') {
1032 return "microsoft/dotnet-buildtools-prereqs:ubuntu-16.04-cross-arm64-a3ae44b-20180315221921"
1037 if (architecture == 'x86' && os == 'Ubuntu') {
1038 return "hseok82/dotnet-buildtools-prereqs:ubuntu1604_x86_test"
1041 println("Unknown architecture to use docker: ${architecture} ${os}");
1046 // We have a limited amount of some hardware. For these, scale back the periodic testing we do,
1047 // and only allowing using this hardware in some specific branches.
1048 def static jobRequiresLimitedHardware(def architecture, def os) {
1049 if (((architecture == 'arm64') || (architecture == 'arm')) && (os == 'Windows_NT')) {
1050 // These test jobs require ARM64 hardware
1053 else if ((architecture == 'arm') && (os == 'Ubuntu')) {
1054 // These test jobs require Linux/arm32 hardware
1057 else if ((architecture == 'arm64') && (os == 'Ubuntu')) {
1058 // These test jobs require Linux/arm64 hardware
1066 // Calculates the name of the build job based on some typical parameters.
1068 def static getJobName(def configuration, def architecture, def os, def scenario, def isBuildOnly) {
1069 // If the architecture is x64, do not add that info into the build name.
1070 // Need to change around some systems and other builds to pick up the right builds
1073 def suffix = scenario != 'normal' ? "_${scenario}" : '';
1078 switch (architecture) {
1080 if (scenario == 'normal') {
1081 // For now we leave x64 off of the name for compatibility with other jobs
1082 baseName = configuration.toLowerCase() + '_' + os.toLowerCase()
1084 else if (scenario == 'formatting') {
1085 // we don't care about the configuration for the formatting job. It runs all configs
1086 baseName = architecture.toLowerCase() + '_' + os.toLowerCase()
1089 baseName = architecture.toLowerCase() + '_' + configuration.toLowerCase() + '_' + os.toLowerCase()
1093 if (os.toLowerCase() == "windows_nt") {
1094 // These are cross builds
1095 baseName = architecture.toLowerCase() + '_cross_' + configuration.toLowerCase() + '_' + os.toLowerCase()
1098 // Defaults to a small page size set of machines.
1099 baseName = architecture.toLowerCase() + '_' + configuration.toLowerCase() + '_' + "small_page_size"
1103 // These are cross builds
1104 if (os == 'Tizen') {
1106 baseName = 'armel_cross_' + configuration.toLowerCase() + '_' + os.toLowerCase()
1109 baseName = architecture.toLowerCase() + '_cross_' + configuration.toLowerCase() + '_' + os.toLowerCase()
1113 baseName = architecture.toLowerCase() + '_cross_' + configuration.toLowerCase() + '_' + os.toLowerCase()
1116 case 'x86_arm_altjit':
1117 case 'x64_arm64_altjit':
1118 baseName = architecture.toLowerCase() + '_' + configuration.toLowerCase() + '_' + os.toLowerCase()
1121 println("Unknown architecture: ${architecture}");
1126 return baseName + suffix
1129 def static addNonPRTriggers(def job, def branch, def isPR, def architecture, def os, def configuration, def scenario, def isFlowJob, def isWindowsBuildOnlyJob, def bidailyCrossList) {
1131 // Limited hardware is restricted for non-PR triggers to certain branches.
1132 if (jobRequiresLimitedHardware(architecture, os) && (!(branch in Constants.LimitedHardwareBranches))) {
1136 // No arm64 Ubuntu cron jobs for now: we don't have enough hardware.
1137 if ((architecture == 'arm64') && (os != 'Windows_NT')) {
1146 switch (architecture) {
1149 if (isFlowJob && architecture == 'x86' && os == 'Ubuntu') {
1150 addPeriodicTriggerHelper(job, '@daily')
1152 else if (isFlowJob || os == 'Windows_NT' || !(os in Constants.crossList)) {
1153 addGithubPushTriggerHelper(job)
1157 if (os == 'Windows_NT') {
1158 // Only the flow jobs get push triggers; the build and test jobs are triggered by the flow job.
1160 // We would normally want a per-push trigger, but with limited hardware we can't keep up.
1161 // Do the builds daily.
1162 addPeriodicTriggerHelper(job, '@daily')
1166 // Only the flow jobs get push triggers; the build and test jobs are triggered by the flow job.
1168 addPeriodicTriggerHelper(job, '@daily')
1173 if (os == 'Windows_NT') {
1174 // Only the flow jobs get triggers; the build and test jobs are triggered by the flow job.
1176 // We would normally want a push trigger, but with limited hardware we can't keep up.
1177 // Do the builds daily.
1178 addPeriodicTriggerHelper(job, '@daily')
1182 assert os == 'Ubuntu'
1183 // Only the flow jobs get push triggers; the build and test jobs are triggered by the flow job.
1185 // Currently no push triggers, with limited arm Linux hardware.
1186 // TODO: If we have enough machine capacity, add some arm Linux push triggers.
1187 addPeriodicTriggerHelper(job, '@daily')
1192 addGithubPushTriggerHelper(job)
1194 case 'x86_arm_altjit':
1195 case 'x64_arm64_altjit':
1196 // Only do altjit push triggers for Checked; don't waste time on Debug or Release.
1197 if (configuration == 'Checked') {
1198 addGithubPushTriggerHelper(job)
1202 println("Unknown architecture: ${architecture}");
1208 assert !(os in bidailyCrossList)
1209 // r2r gets a push trigger for checked/release
1210 if (configuration == 'Checked' || configuration == 'Release') {
1211 assert (os == 'Windows_NT') || (os in Constants.crossList)
1212 if (architecture == 'x64' && os != 'OSX10.12') {
1213 //Flow jobs should be Windows, Ubuntu, OSX0.12, or CentOS
1214 if (isFlowJob || os == 'Windows_NT') {
1215 addGithubPushTriggerHelper(job)
1217 // OSX10.12 r2r jobs should only run every 12 hours, not daily.
1218 } else if (architecture == 'x64' && os == 'OSX10.12'){
1220 addPeriodicTriggerHelper(job, 'H H/12 * * *')
1223 // For x86, only add per-commit jobs for Windows
1224 else if (architecture == 'x86') {
1225 if (os == 'Windows_NT') {
1226 addGithubPushTriggerHelper(job)
1229 // arm64 r2r jobs should only run weekly.
1230 // arm64 r2r jobs are only run on Windows (Q: should they run on non-Windows?)
1231 else if (architecture == 'arm64') {
1232 if (os == 'Windows_NT') {
1234 addPeriodicTriggerHelper(job, '@weekly')
1238 // arm r2r jobs should only run weekly.
1239 else if (architecture == 'arm') {
1241 addPeriodicTriggerHelper(job, '@weekly')
1246 case 'r2r_jitstress1':
1247 case 'r2r_jitstress2':
1248 case 'r2r_jitstressregs1':
1249 case 'r2r_jitstressregs2':
1250 case 'r2r_jitstressregs3':
1251 case 'r2r_jitstressregs4':
1252 case 'r2r_jitstressregs8':
1253 case 'r2r_jitstressregs0x10':
1254 case 'r2r_jitstressregs0x80':
1255 case 'r2r_jitstressregs0x1000':
1256 case 'r2r_jitminopts':
1257 case 'r2r_jitforcerelocs':
1258 case 'r2r_gcstress15':
1259 assert !(os in bidailyCrossList)
1261 // GCStress=C is currently not supported on OS X
1262 if (os == 'OSX10.12' && isGCStressRelatedTesting(scenario)) {
1266 // GC Stress 15 r2r gets a push trigger for checked/release
1267 if (configuration == 'Checked' || configuration == 'Release') {
1268 assert (os == 'Windows_NT') || (os in Constants.crossList)
1269 if (architecture == 'x64') {
1270 //Flow jobs should be Windows, Ubuntu, OSX10.12, or CentOS
1271 if (isFlowJob || os == 'Windows_NT') {
1272 // Add a weekly periodic trigger
1273 addPeriodicTriggerHelper(job, 'H H * * 3,6') // some time every Wednesday and Saturday
1276 // For x86, only add periodic jobs for Windows
1277 else if (architecture == 'x86') {
1278 if (os == 'Windows_NT') {
1279 addPeriodicTriggerHelper(job, 'H H * * 3,6') // some time every Wednesday and Saturday
1282 // arm64 r2r jobs are only run on Windows (Q: should they run on non-Windows?)
1283 else if (architecture == 'arm64') {
1284 if (os == 'Windows_NT') {
1286 addPeriodicTriggerHelper(job, '@weekly')
1290 else if (architecture == 'arm') {
1292 addPeriodicTriggerHelper(job, '@weekly')
1298 assert (os == 'Ubuntu' || os == 'Windows_NT' || os == 'OSX10.12')
1299 assert configuration == 'Release'
1300 assert architecture == 'x64'
1301 addPeriodicTriggerHelper(job, '@daily')
1302 // TODO: Add once external email sending is available again
1303 // addEmailPublisher(job, 'dotnetgctests@microsoft.com')
1306 assert (os == 'Ubuntu' || os == 'Windows_NT' || os == 'OSX10.12')
1307 assert configuration == 'Release'
1308 assert architecture == 'x64'
1309 addPeriodicTriggerHelper(job, 'H H * * 3,6') // some time every Wednesday and Saturday
1310 // TODO: Add once external email sending is available again
1311 // addEmailPublisher(job, 'dotnetgctests@microsoft.com')
1313 case 'standalone_gc':
1314 assert (os == 'Ubuntu' || os == 'Windows_NT' || os == 'OSX10.12')
1315 assert (configuration == 'Release' || configuration == 'Checked')
1316 // TODO: Add once external email sending is available again
1317 // addEmailPublisher(job, 'dotnetgctests@microsoft.com')
1318 addPeriodicTriggerHelper(job, '@daily')
1320 case 'gc_reliability_framework':
1321 assert (os == 'Ubuntu' || os == 'Windows_NT' || os == 'OSX10.12')
1322 assert (configuration == 'Release' || configuration == 'Checked')
1323 // Only triggered by phrase.
1326 assert !(os in bidailyCrossList)
1327 // ILASM/ILDASM roundtrip one gets a daily build, and only for release
1328 if (architecture == 'x64' && configuration == 'Release') {
1329 // We don't expect to see a job generated except in these scenarios
1330 assert (os == 'Windows_NT') || (os in Constants.crossList)
1331 if (isFlowJob || os == 'Windows_NT') {
1332 addPeriodicTriggerHelper(job, '@daily')
1337 assert (os == 'Ubuntu' || os == 'Windows_NT' || os == 'OSX10.12')
1338 assert configuration == 'Checked'
1339 assert (architecture == 'x64' || architecture == 'x86')
1340 addGithubPushTriggerHelper(job)
1343 assert (os == 'Windows_NT' || os == "Ubuntu")
1344 assert architecture == 'x64'
1345 addGithubPushTriggerHelper(job)
1347 case 'jitstressregs1':
1348 case 'jitstressregs2':
1349 case 'jitstressregs3':
1350 case 'jitstressregs4':
1351 case 'jitstressregs8':
1352 case 'jitstressregs0x10':
1353 case 'jitstressregs0x80':
1354 case 'jitstressregs0x1000':
1359 case 'jitstress2_jitstressregs1':
1360 case 'jitstress2_jitstressregs2':
1361 case 'jitstress2_jitstressregs3':
1362 case 'jitstress2_jitstressregs4':
1363 case 'jitstress2_jitstressregs8':
1364 case 'jitstress2_jitstressregs0x10':
1365 case 'jitstress2_jitstressregs0x80':
1366 case 'jitstress2_jitstressregs0x1000':
1367 case 'tailcallstress':
1370 case 'jitnox86hwintrinsic':
1371 case 'jitincompletehwintrinsic':
1372 case 'jitx86hwintrinsicnoavx':
1373 case 'jitx86hwintrinsicnoavx2':
1374 case 'jitx86hwintrinsicnosimd':
1375 case 'corefx_baseline':
1376 case 'corefx_minopts':
1377 case 'corefx_jitstress1':
1378 case 'corefx_jitstress2':
1379 case 'corefx_jitstressregs1':
1380 case 'corefx_jitstressregs2':
1381 case 'corefx_jitstressregs3':
1382 case 'corefx_jitstressregs4':
1383 case 'corefx_jitstressregs8':
1384 case 'corefx_jitstressregs0x10':
1385 case 'corefx_jitstressregs0x80':
1386 case 'corefx_jitstressregs0x1000':
1388 if (os == 'CentOS7.1') {
1391 if (os in bidailyCrossList) {
1394 // ARM corefx testing uses non-flow jobs to provide the configuration-specific
1395 // build for the flow job. We don't need cron jobs for these. Note that the
1396 // Windows ARM jobs depend on a Windows "build only" job that exits the trigger
1397 // function very early, so only non-Windows gets here.
1398 if ((architecture == 'arm') && isCoreFxScenario(scenario) && !isFlowJob) {
1401 if ((architecture == 'arm64') && isCoreFxScenario(scenario) && !isFlowJob) {
1404 assert (os == 'Windows_NT') || (os in Constants.crossList)
1405 if (jobRequiresLimitedHardware(architecture, os)) {
1406 addPeriodicTriggerHelper(job, '@weekly')
1409 addPeriodicTriggerHelper(job, '@daily')
1414 if (os == 'CentOS7.1') {
1417 if (os in bidailyCrossList) {
1420 if ((architecture == 'arm64') && (os != 'Windows_NT')) {
1421 // TODO: should we have cron jobs for arm64 Linux GCStress?
1424 assert (os == 'Windows_NT') || (os in Constants.crossList)
1425 addPeriodicTriggerHelper(job, '@weekly')
1428 case 'gcstress0xc_zapdisable':
1429 case 'gcstress0xc_zapdisable_jitstress2':
1430 case 'gcstress0xc_zapdisable_heapverify1':
1431 case 'gcstress0xc_jitstress1':
1432 case 'gcstress0xc_jitstress2':
1433 case 'gcstress0xc_minopts_heapverify1':
1434 if (os == 'CentOS7.1') {
1437 if (os == 'OSX10.12') {
1438 // GCStress=C is currently not supported on OS X
1441 if (os in bidailyCrossList) {
1444 if ((architecture == 'arm64') && (os != 'Windows_NT')) {
1445 // TODO: should we have cron jobs for arm64 Linux GCStress?
1448 assert (os == 'Windows_NT') || (os in Constants.crossList)
1449 addPeriodicTriggerHelper(job, '@weekly')
1453 // Testing on other operating systems TBD
1454 assert (os == 'Windows_NT' || os == 'Ubuntu')
1455 if (architecture == 'x64' || architecture == 'x86') {
1456 if (configuration == 'Checked') {
1457 addPeriodicTriggerHelper(job, '@daily')
1462 case 'tieredcompilation':
1463 case 'corefx_tieredcompilation':
1464 // No periodic jobs just yet, still testing
1468 println("Unknown scenario: ${scenario}");
1475 // **************************
1476 // Define the basic inner loop builds for PR and commit. This is basically just the set
1477 // of coreclr builds over linux/osx 10.12/windows and debug/release/checked. In addition, the windows
1478 // builds will do a couple extra steps.
1479 // **************************
1481 // Adds a trigger for the PR build if one is needed. If isFlowJob is true, then this is the
1482 // flow job that rolls up the build and test for non-windows OS's. // If the job is a windows build only job,
1483 // it's just used for internal builds
1484 // If you add a job with a trigger phrase, please add that phrase to coreclr/Documentation/project-docs/ci-trigger-phrases.md
1485 def static addTriggers(def job, def branch, def isPR, def architecture, def os, def configuration, def scenario, def isFlowJob, def isWindowsBuildOnlyJob) {
1486 def isNormalOrInnerloop = (scenario == "normal" || scenario == "innerloop")
1488 if (isWindowsBuildOnlyJob) {
1492 def bidailyCrossList = ['RHEL7.2', 'Debian8.4']
1493 // Non pull request builds.
1495 addNonPRTriggers(job, branch, isPR, architecture, os, configuration, scenario, isFlowJob, isWindowsBuildOnlyJob, bidailyCrossList)
1522 // Pull request builds. Generally these fall into two categories: default triggers and on-demand triggers
1523 // We generally only have a distinct set of default triggers but a bunch of on-demand ones.
1524 def osGroup = getOSGroup(os)
1525 switch (architecture) {
1526 case 'x64': // editor brace matching: {
1527 if (scenario == 'formatting') {
1528 assert configuration == 'Checked'
1529 if (os == 'Windows_NT' || os == 'Ubuntu') {
1530 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} Formatting")
1537 // OpenSUSE, Debian & RedHat get trigger phrases for pri 0 build, and pri 1 build & test
1540 if (scenario == 'innerloop') {
1542 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Innerloop Build")
1544 else if (scenario == 'normal') {
1545 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build", "(?i).*test\\W+${os}\\W+${architecture}.*")
1551 assert scenario != 'innerloop'
1552 // Distinguish with the other architectures (arm and x86)
1553 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build", "(?i).*test\\W+${os}\\W+${architecture}.*")
1559 assert scenario != 'innerloop'
1560 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build", "(?i).*test\\W+${os}\\W+.*")
1564 if (scenario == 'illink') {
1565 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} via ILLink", "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
1571 // Triggers on the non-flow jobs aren't necessary here
1572 // Corefx testing uses non-flow jobs.
1573 if (!isFlowJob && !isCoreFxScenario(scenario)) {
1578 // PR Triggered jobs. These jobs will run pri0 tests.
1579 if (configuration == 'Checked') {
1580 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Innerloop Build and Test")
1585 // OSX uses checked for default PR tests
1586 if (configuration == 'Checked') {
1588 assert !job.name.contains("centos")
1589 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test", "(?i).*test\\W+${os}\\W+${architecture}\\W+Build and Test.*")
1594 if (configuration == 'Checked') {
1595 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Jit Diff Build and Test", "(?i).*test\\W+${os}\\W+${scenario}.*")
1600 if (configuration == 'Release') {
1601 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} IL RoundTrip Build and Test", "(?i).*test\\W+${os}\\W+${scenario}.*")
1606 if (configuration == 'Release') {
1607 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Long-Running GC Build & Test", "(?i).*test\\W+${os}\\W+${configuration}\\W+${scenario}.*")
1612 if (configuration == 'Release') {
1613 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} GC Simulator", "(?i).*test\\W+${os}\\W+${configuration}\\W+${scenario}.*")
1617 case 'standalone_gc':
1618 if (configuration == 'Release' || configuration == 'Checked') {
1619 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Standalone GC", "(?i).*test\\W+${os}\\W+${configuration}\\W+${scenario}.*")
1623 case 'gc_reliability_framework':
1624 if (configuration == 'Release' || configuration == 'Checked') {
1625 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} GC Reliability Framework", "(?i).*test\\W+${os}\\W+${configuration}\\W+${scenario}.*")
1630 if (isJitStressScenario(scenario)) {
1631 def displayStr = getStressModeDisplayName(scenario)
1632 assert (os == 'Windows_NT') || (os in Constants.crossList)
1633 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test (Jit - ${displayStr})",
1634 "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
1636 else if (isR2RScenario(scenario)) {
1637 if (configuration == 'Release' || configuration == 'Checked') {
1638 def displayStr = getR2RDisplayName(scenario)
1639 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} ${displayStr} Build and Test",
1640 "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
1644 println("Unknown scenario: ${scenario}");
1655 // CentOS uses checked for default PR tests while debug is build only
1656 if (configuration == 'Debug') {
1658 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Innerloop Build")
1661 // Make sure this is a flow job to get build and test.
1662 if (configuration == 'Checked' && isFlowJob) {
1663 assert job.name.contains("flow")
1665 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Innerloop Build and Test")
1670 // Make sure this is a flow job to get build and test.
1671 if (configuration == 'Checked' && isFlowJob) {
1672 assert job.name.contains("flow")
1674 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test", "(?i).*test\\W+${os}\\W+${architecture}\\W+Build and Test.*")
1679 if (isR2RScenario(scenario)) {
1680 if (configuration == 'Release' || configuration == 'Checked') {
1681 def displayStr = getR2RDisplayName(scenario)
1682 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} ${displayStr} Build & Test",
1683 "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
1695 if (configuration == 'Checked' || configuration == 'Release') {
1696 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Innerloop Build and Test")
1701 if (configuration == 'Checked') {
1702 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test", "(?i).*test\\W+${os}\\W+${architecture}\\W+Build and Test.*")
1707 if (configuration == 'Checked') {
1708 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Jit Diff Build and Test", "(?i).*test\\W+${os}\\W+${scenario}.*")
1713 if (configuration == 'Release') {
1714 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} IL RoundTrip Build and Test", "(?i).*test\\W+${os}\\W+${scenario}.*")
1719 if (configuration == 'Release') {
1720 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Long-Running GC Build & Test", "(?i).*test\\W+${os}\\W+${configuration}\\W+${scenario}.*")
1725 if (configuration == 'Release') {
1726 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} GC Simulator", "(?i).*test\\W+${os}\\W+${configuration}\\W+${scenario}.*")
1730 case 'standalone_gc':
1731 if (configuration == 'Release' || configuration == 'Checked') {
1732 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Standalone GC", "(?i).*test\\W+${os}\\W+${configuration}\\W+${scenario}.*")
1736 case 'gc_reliability_framework':
1737 if (configuration == 'Release' || configuration == 'Checked') {
1738 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} GC Reliability Framework", "(?i).*test\\W+${os}\\W+${configuration}\\W+${scenario}.*")
1743 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} via ILLink", "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
1745 case 'corefx_innerloop':
1746 if (configuration == 'Release' || configuration == 'Checked') {
1747 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} CoreFX Tests")
1752 if (isJitStressScenario(scenario)) {
1753 def displayStr = getStressModeDisplayName(scenario)
1754 assert (os == 'Windows_NT') || (os in Constants.crossList)
1755 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test (Jit - ${displayStr})",
1756 "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
1758 else if (isR2RScenario(scenario)) {
1759 if (configuration == 'Release' || configuration == 'Checked') {
1760 def displayStr = getR2RDisplayName(scenario)
1761 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} ${displayStr} Build & Test",
1762 "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
1766 println("Unknown scenario: ${scenario}");
1775 println("Unknown os: ${os}");
1782 // editor brace matching: }
1784 case 'armem': // editor brace matching: {
1787 azureVMAgentPostBuildAction {
1788 agentPostBuildAction('Delete agent if the build was not successful (when idle).')
1796 assert scenario != 'innerloop'
1797 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} Cross ${configuration} Build",
1798 "(?i).*test\\W+${os}\\W+${architecture}\\W+Cross\\W+${configuration}\\W+Build.*")
1802 architecture = 'armel'
1804 if (scenario == 'innerloop') {
1805 if (configuration == 'Checked') {
1806 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} Cross ${configuration} Innerloop Build and Test")
1810 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} Cross ${configuration} Build",
1811 "(?i).*test\\W+${os}\\W+${architecture}\\W+Cross\\W+${configuration}\\W+Build.*")
1817 // editor brace matching: }
1819 case 'arm': // editor brace matching: {
1821 // Triggers on the non-flow jobs aren't necessary
1826 // Set up a private trigger
1827 def contextString = "${os} ${architecture} Cross ${configuration}"
1828 def triggerString = "(?i).*test\\W+${os}\\W+${architecture}\\W+Cross\\W+${configuration}"
1829 if (scenario == 'innerloop') {
1830 contextString += " Innerloop"
1831 triggerString += "\\W+Innerloop"
1834 contextString += " ${scenario}"
1835 triggerString += "\\W+${scenario}"
1838 if (configuration == 'Debug') {
1839 contextString += " Build"
1840 triggerString += "\\W+Build"
1842 contextString += " Build and Test"
1843 triggerString += "\\W+Build and Test"
1846 triggerString += ".*"
1850 if (scenario == 'innerloop') {
1851 if (configuration == 'Checked') {
1852 Utilities.addGithubPRTriggerForBranch(job, branch, contextString)
1856 Utilities.addGithubPRTriggerForBranch(job, branch, contextString, triggerString)
1863 // Only Checked is an innerloop trigger.
1864 if (configuration == 'Checked')
1866 Utilities.addDefaultPrivateGithubPRTriggerForBranch(job, branch, contextString, null, arm64Users)
1870 Utilities.addPrivateGithubPRTriggerForBranch(job, branch, contextString, triggerString, null, arm64Users)
1873 // Stress jobs will use this code path.
1874 if (isArmWindowsScenario(scenario)) {
1875 Utilities.addPrivateGithubPRTriggerForBranch(job, branch, contextString, triggerString, null, arm64Users)
1881 println("NYI os: ${os}");
1886 // editor brace matching: }
1887 case 'arm64': // editor brace matching: {
1888 // Set up a private trigger
1889 def contextString = "${os} ${architecture} Cross ${configuration}"
1890 def triggerString = "(?i).*test\\W+${os}\\W+${architecture}\\W+Cross\\W+${configuration}"
1892 if (scenario == 'innerloop') {
1893 contextString += " Innerloop"
1894 triggerString += "\\W+Innerloop"
1897 contextString += " ${scenario}"
1898 triggerString += "\\W+${scenario}"
1901 if (configuration == 'Debug') {
1902 contextString += " Build"
1903 triggerString += "\\W+Build"
1905 contextString += " Build and Test"
1906 triggerString += "\\W+Build and Test"
1909 triggerString += ".*"
1916 if (configuration == 'Debug' && !isFlowJob) {
1917 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} Cross ${configuration} Innerloop Build")
1922 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test", triggerString)
1925 if (isR2RScenario(scenario)) {
1926 if (configuration == 'Checked' || configuration == 'Release') {
1927 def displayStr = getR2RDisplayName(scenario)
1928 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} ${displayStr} Build and Test", triggerString)
1936 // Triggers on the non-flow jobs aren't necessary here
1941 assert isArmWindowsScenario(scenario)
1944 if (configuration == 'Checked') {
1945 Utilities.addDefaultPrivateGithubPRTriggerForBranch(job, branch, contextString, null, arm64Users)
1950 Utilities.addPrivateGithubPRTriggerForBranch(job, branch, contextString, triggerString, null, arm64Users)
1953 // Stress jobs will use this code path.
1954 if (isArmWindowsScenario(scenario)) {
1955 Utilities.addPrivateGithubPRTriggerForBranch(job, branch, contextString, triggerString, null, arm64Users)
1961 println("NYI os: ${os}");
1967 // editor brace matching: }
1968 case 'x86': // editor brace matching: {
1969 assert ((os == 'Windows_NT') || ((os == 'Ubuntu') && isNormalOrInnerloop))
1970 if (os == 'Ubuntu') {
1971 // Triggers on the non-flow jobs aren't necessary here
1976 // on-demand only for ubuntu x86
1977 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build",
1978 "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}.*")
1984 if (configuration == 'Checked' || configuration == 'Release') {
1985 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Innerloop Build and Test")
1990 if (configuration == 'Checked') {
1991 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test",
1992 "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+Build and Test.*")
1997 if (configuration == 'Release') {
1998 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} IL RoundTrip Build and Test",
1999 "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
2004 if (configuration == 'Release') {
2005 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Long-Running GC Build & Test",
2006 "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
2011 if (configuration == 'Release') {
2012 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} GC Simulator",
2013 "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
2017 case 'standalone_gc':
2018 if (configuration == 'Release' || configuration == 'Checked') {
2019 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Standalone GC",
2020 "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
2025 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} via ILLink", "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
2029 if (isJitStressScenario(scenario)) {
2030 def displayStr = getStressModeDisplayName(scenario)
2031 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test (Jit - ${displayStr})",
2032 "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
2034 else if (isR2RScenario(scenario)) {
2035 if (configuration == 'Release' || configuration == 'Checked') {
2036 def displayStr = getR2RDisplayName(scenario)
2037 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} ${displayStr} Build & Test",
2038 "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
2042 println("Unknown scenario: ${os} ${architecture} ${scenario}");
2050 // editor brace matching: }
2051 case 'x64_arm64_altjit':
2052 case 'x86_arm_altjit': // editor brace matching: {
2053 assert (os == 'Windows_NT')
2056 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test",
2057 "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+Build and Test.*")
2060 Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} ${scenario}",
2061 "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*")
2066 // editor brace matching: }
2068 println("Unknown architecture: ${architecture}");
2074 def static calculateBuildCommands(def newJob, def scenario, def branch, def isPR, def architecture, def configuration, def os, def isBuildOnly) {
2075 def buildCommands = []
2076 def osGroup = getOSGroup(os)
2077 def lowerConfiguration = configuration.toLowerCase()
2080 if (scenario == 'innerloop') {
2084 def doCoreFxTesting = isCoreFxScenario(scenario)
2086 // Calculate the build steps, archival, and xunit results
2088 case 'Windows_NT': // editor brace matching: {
2089 switch (architecture) {
2092 case 'x86_arm_altjit':
2093 case 'x64_arm64_altjit':
2094 def arch = architecture
2096 if (architecture == 'x86_arm_altjit') {
2099 else if (architecture == 'x64_arm64_altjit') {
2103 if (scenario == 'formatting') {
2104 buildCommands += "python -u tests\\scripts\\format.py -c %WORKSPACE% -o Windows_NT -a ${arch}"
2105 Utilities.addArchival(newJob, "format.patch", "", true, false)
2109 if (scenario == 'illink') {
2110 buildCommands += "tests\\scripts\\build_illink.cmd clone ${arch}"
2113 // If it is a release build for Windows, ensure PGO is used, else fail the build.
2114 if ((lowerConfiguration == 'release') &&
2115 (scenario in Constants.basicScenarios) &&
2116 (architecture != 'x86_arm_altjit') &&
2117 (architecture != 'x64_arm64_altjit')) {
2119 buildOpts += ' -enforcepgo'
2122 if (doCoreFxTesting) {
2123 buildOpts += ' skiptests';
2125 buildOpts += " -priority=${priority}"
2128 // Set __TestIntermediateDir to something short. If __TestIntermediateDir is already set, build-test.cmd will
2129 // output test binaries to that directory. If it is not set, the binaries are sent to a default directory whose name is about
2130 // 35 characters long.
2132 buildCommands += "set __TestIntermediateDir=int&&build.cmd ${lowerConfiguration} ${arch} ${buildOpts}"
2135 def runtestArguments = ''
2136 def testOpts = 'collectdumps'
2138 if (isR2RScenario(scenario)) {
2140 // If this is a ReadyToRun scenario, pass 'crossgen' or 'crossgenaltjit'
2141 // to cause framework assemblies to be crossgen'ed. Pass 'runcrossgentests'
2142 // to cause the tests to be crossgen'ed.
2144 if ((architecture == 'x86_arm_altjit') || (architecture == 'x64_arm64_altjit')) {
2145 testOpts += ' crossgenaltjit protononjit.dll'
2147 testOpts += ' crossgen'
2150 testOpts += ' runcrossgentests'
2152 else if (scenario == 'jitdiff') {
2153 testOpts += ' jitdisasm crossgen'
2155 else if (scenario == 'ilrt') {
2156 testOpts += ' ilasmroundtrip'
2158 else if (isLongGc(scenario)) {
2159 testOpts += " ${scenario} sequential"
2161 else if (scenario == 'standalone_gc') {
2162 testOpts += ' gcname clrgc.dll'
2164 else if (scenario == 'illink') {
2165 testOpts += " link %WORKSPACE%\\linker\\linker\\bin\\netcore_Release\\netcoreapp2.0\\win10-${arch}\\publish\\illink.exe"
2168 // Default per-test timeout is 10 minutes. For stress modes and Debug scenarios, increase this
2169 // to 30 minutes (30 * 60 * 1000 = 180000). The "timeout" argument to runtest.cmd sets this, by
2170 // taking a timeout value in milliseconds. (Note that it sets the __TestTimeout environment variable,
2171 // which is read by the xunit harness.)
2172 if (isJitStressScenario(scenario) || isR2RStressScenario(scenario) || (lowerConfiguration == 'debug'))
2174 def timeout = 1800000
2175 testOpts += " timeout ${timeout}"
2178 // If we are running a stress mode, we should write out the set of key
2179 // value env pairs to a file at this point and then we'll pass that to runtest.cmd
2181 def envScriptPath = ''
2182 if (isJitStressScenario(scenario) || isR2RStressScenario(scenario)) {
2183 def buildCommandsStr = ''
2184 envScriptPath = "%WORKSPACE%\\SetStressModes.bat"
2185 buildCommandsStr += envScriptCreate(os, envScriptPath)
2187 if (isJitStressScenario(scenario)) {
2188 buildCommandsStr += envScriptSetStressModeVariables(os, Constants.jitStressModeScenarios[scenario], envScriptPath)
2190 else if (isR2RStressScenario(scenario)) {
2191 buildCommandsStr += envScriptSetStressModeVariables(os, Constants.r2rStressScenarios[scenario], envScriptPath)
2194 if (architecture == 'x86_arm_altjit') {
2195 buildCommandsStr += envScriptAppendExistingScript(os, "%WORKSPACE%\\tests\\x86_arm_altjit.cmd", envScriptPath)
2197 else if (architecture == 'x64_arm64_altjit') {
2198 buildCommandsStr += envScriptAppendExistingScript(os, "%WORKSPACE%\\tests\\x64_arm64_altjit.cmd", envScriptPath)
2201 envScriptFinalize(os, envScriptPath)
2203 // Note that buildCommands is an array of individually executed commands; we want all the commands used to
2204 // create the SetStressModes.bat script to be executed together, hence we accumulate them as strings
2205 // into a single script.
2206 buildCommands += buildCommandsStr
2208 else if (architecture == 'x86_arm_altjit') {
2209 envScriptPath = "%WORKSPACE%\\tests\\x86_arm_altjit.cmd"
2211 else if (architecture == 'x64_arm64_altjit') {
2212 envScriptPath = "%WORKSPACE%\\tests\\x64_arm64_altjit.cmd"
2214 if (envScriptPath != '') {
2215 testOpts += " TestEnv ${envScriptPath}"
2218 runtestArguments = "${lowerConfiguration} ${arch} ${testOpts}"
2220 if (doCoreFxTesting) {
2221 if (scenario == 'corefx_innerloop') {
2222 // Create CORE_ROOT and testhost
2223 buildCommands += "build-test.cmd ${lowerConfiguration} ${arch} buildtesthostonly"
2224 buildCommands += "tests\\runtest.cmd ${runtestArguments} CoreFXTestsAll"
2226 // Archive and process (only) the test results
2227 Utilities.addArchival(newJob, "bin/Logs/**/testResults.xml")
2228 Utilities.addXUnitDotNETResults(newJob, "bin/Logs/**/testResults.xml")
2231 def workspaceRelativeFxRoot = "_/fx"
2232 def absoluteFxRoot = "%WORKSPACE%\\_\\fx"
2233 def fxBranch = getFxBranch(branch)
2235 buildCommands += "python -u %WORKSPACE%\\tests\\scripts\\run-corefx-tests.py -arch ${arch} -ci_arch ${architecture} -build_type ${configuration} -fx_root ${absoluteFxRoot} -fx_branch ${fxBranch} -env_script ${envScriptPath}"
2237 // Archive and process (only) the test results
2238 Utilities.addArchival(newJob, "${workspaceRelativeFxRoot}/bin/**/testResults.xml")
2239 Utilities.addXUnitDotNETResults(newJob, "${workspaceRelativeFxRoot}/bin/**/testResults.xml")
2241 //Archive additional build stuff to diagnose why my attempt at fault injection isn't causing CI to fail
2242 Utilities.addArchival(newJob, "SetStressModes.bat", "", true, false)
2243 Utilities.addArchival(newJob, "${workspaceRelativeFxRoot}/bin/testhost/**", "", true, false)
2246 else if (isGcReliabilityFramework(scenario)) {
2247 buildCommands += "tests\\runtest.cmd ${runtestArguments} GenerateLayoutOnly"
2248 buildCommands += "tests\\scripts\\run-gc-reliability-framework.cmd ${arch} ${configuration}"
2251 buildCommands += "tests\\runtest.cmd ${runtestArguments}"
2253 } // end if (!isBuildOnly)
2255 if (!doCoreFxTesting) {
2256 // Run the rest of the build
2257 // Build the mscorlib for the other OS's
2258 buildCommands += "build.cmd ${lowerConfiguration} ${arch} linuxmscorlib"
2259 buildCommands += "build.cmd ${lowerConfiguration} ${arch} osxmscorlib"
2261 if (arch == 'x64') {
2262 buildCommands += "build.cmd ${lowerConfiguration} arm64 linuxmscorlib"
2265 // Zip up the tests directory so that we don't use so much space/time copying
2266 // 10s of thousands of files around.
2267 buildCommands += "powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('.\\bin\\tests\\${osGroup}.${arch}.${configuration}', '.\\bin\\tests\\tests.zip')\"";
2269 if (!isJitStressScenario(scenario)) {
2270 // For Windows, pull full test results and test drops for x86/x64.
2271 // No need to pull for stress mode scenarios (downstream builds use the default scenario)
2272 Utilities.addArchival(newJob, "bin/Product/**,bin/tests/tests.zip", "bin/Product/**/.nuget/**")
2275 if (scenario == 'jitdiff') {
2276 // retrieve jit-dasm output for base commit, and run jit-diff
2278 // if this is a build only job, we want to keep the default (build) artifacts for the flow job
2279 Utilities.addArchival(newJob, "bin/tests/${osGroup}.${arch}.${configuration}/dasm/**")
2284 Utilities.addXUnitDotNETResults(newJob, 'bin/**/TestRun*.xml', true)
2289 assert isArmWindowsScenario(scenario)
2291 def buildArchitecture = 'arm'
2294 if (doCoreFxTesting) {
2295 // We shouldn't need to build the tests. However, run-corefx-tests.py currently depends on having the restored corefx
2296 // package available, to determine the correct corefx version git commit hash, and we need to build the tests before
2297 // running "tests\\runtest.cmd GenerateLayoutOnly". So build the pri-0 tests to make this happen.
2299 // buildOpts += ' skiptests';
2300 buildOpts += " -priority=0"
2302 buildOpts += " -priority=${priority}"
2305 // This is now a build only job. Do not run tests. Use the flow job.
2306 buildCommands += "set __TestIntermediateDir=int&&build.cmd ${lowerConfiguration} ${buildArchitecture} ${buildOpts}"
2308 if (doCoreFxTesting) {
2310 assert architecture == 'arm'
2312 // Generate the test layout because it restores the corefx package which allows run-corefx-tests.py
2313 // to determine the correct matching corefx version git commit hash.
2314 buildCommands += "tests\\runtest.cmd ${lowerConfiguration} ${architecture} GenerateLayoutOnly"
2316 // Set the stress mode variables; this is incorporated into the generated CoreFx RunTests.cmd files.
2317 def envScriptPath = ''
2318 def buildCommandsStr = ''
2319 envScriptPath = "%WORKSPACE%\\SetStressModes.bat"
2320 buildCommandsStr += envScriptCreate(os, envScriptPath)
2321 buildCommandsStr += envScriptSetStressModeVariables(os, Constants.jitStressModeScenarios[scenario], envScriptPath)
2322 envScriptFinalize(os, envScriptPath)
2323 buildCommands += buildCommandsStr
2325 def workspaceRelativeFxRootLinux = "_/fx"
2326 def workspaceRelativeFxRootWin = "_\\fx"
2327 def absoluteFxRoot = "%WORKSPACE%\\_\\fx"
2328 def fxBranch = getFxBranch(branch)
2330 buildCommands += "python -u %WORKSPACE%\\tests\\scripts\\run-corefx-tests.py -arch ${architecture} -ci_arch ${architecture} -build_type ${configuration} -fx_root ${absoluteFxRoot} -fx_branch ${fxBranch} -env_script ${envScriptPath} -no_run_tests"
2332 // Zip up the CoreFx runtime and tests. We don't need the CoreCLR binaries; they have been copied to the CoreFX tree.
2333 buildCommands += "powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('${workspaceRelativeFxRootWin}\\bin\\testhost\\netcoreapp-Windows_NT-Release-arm', '${workspaceRelativeFxRootWin}\\fxruntime.zip')\"";
2334 buildCommands += "powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('${workspaceRelativeFxRootWin}\\bin\\tests', '${workspaceRelativeFxRootWin}\\fxtests.zip')\"";
2336 Utilities.addArchival(newJob, "${workspaceRelativeFxRootLinux}/fxruntime.zip")
2337 Utilities.addArchival(newJob, "${workspaceRelativeFxRootLinux}/fxtests.zip")
2339 // Zip up the tests directory so that we don't use so much space/time copying
2340 // 10s of thousands of files around.
2341 buildCommands += "powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('.\\bin\\tests\\${osGroup}.${buildArchitecture}.${configuration}', '.\\bin\\tests\\tests.zip')\"";
2344 Utilities.addArchival(newJob, "bin/Product/**,bin/tests/tests.zip", "bin/Product/**/.nuget/**")
2348 assert isArmWindowsScenario(scenario)
2350 // This is now a build only job. Do not run tests. Use the flow job.
2351 buildCommands += "set __TestIntermediateDir=int&&build.cmd ${lowerConfiguration} ${architecture} toolset_dir C:\\ats2 -priority=${priority}"
2353 // Zip up the tests directory so that we don't use so much space/time copying
2354 // 10s of thousands of files around.
2355 buildCommands += "powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('.\\bin\\tests\\${osGroup}.${architecture}.${configuration}', '.\\bin\\tests\\tests.zip')\"";
2358 Utilities.addArchival(newJob, "bin/Product/**,bin/tests/tests.zip", "bin/Product/**/.nuget/**")
2361 println("Unknown architecture: ${architecture}");
2366 // end case 'Windows_NT'; editor brace matching: }
2375 case 'Fedora24': // editor brace matching: {
2376 switch (architecture) {
2379 if (architecture == 'x86' && os == 'Ubuntu') {
2380 // build and PAL test
2381 def dockerImage = getDockerImageName(architecture, os, true)
2382 buildCommands += "docker run -i --rm -v \${WORKSPACE}:/opt/code -w /opt/code -e ROOTFS_DIR=/crossrootfs/x86 ${dockerImage} ./build.sh ${architecture} cross ${lowerConfiguration}"
2383 dockerImage = getDockerImageName(architecture, os, false)
2384 buildCommands += "docker run -i --rm -v \${WORKSPACE}:/opt/code -w /opt/code ${dockerImage} ./src/pal/tests/palsuite/runpaltests.sh /opt/code/bin/obj/${osGroup}.${architecture}.${configuration} /opt/code/bin/paltestout"
2385 Utilities.addArchival(newJob, "bin/Product/**,bin/obj/*/tests/**/*.so", "bin/Product/**/.nuget/**")
2386 Utilities.addXUnitDotNETResults(newJob, '**/pal_tests.xml')
2390 if (scenario == 'formatting') {
2391 buildCommands += "python tests/scripts/format.py -c \${WORKSPACE} -o Linux -a ${architecture}"
2392 Utilities.addArchival(newJob, "format.patch", "", true, false)
2396 if (scenario == 'illink') {
2397 assert(os == 'Ubuntu')
2398 buildCommands += "./tests/scripts/build_illink.sh --clone --arch=${architecture}"
2401 if (!doCoreFxTesting) {
2402 // We run pal tests on all OS but generate mscorlib (and thus, nuget packages)
2403 // only on supported OS platforms.
2404 def bootstrapRid = Utilities.getBoostrapPublishRid(os)
2405 def bootstrapRidEnv = bootstrapRid != null ? "__PUBLISH_RID=${bootstrapRid} " : ''
2407 buildCommands += "${bootstrapRidEnv}./build.sh ${lowerConfiguration} ${architecture}"
2408 buildCommands += "src/pal/tests/palsuite/runpaltests.sh \${WORKSPACE}/bin/obj/${osGroup}.${architecture}.${configuration} \${WORKSPACE}/bin/paltestout"
2410 // Basic archiving of the build
2411 Utilities.addArchival(newJob, "bin/Product/**,bin/obj/*/tests/**/*.dylib,bin/obj/*/tests/**/*.so", "bin/Product/**/.nuget/**")
2413 Utilities.addXUnitDotNETResults(newJob, '**/pal_tests.xml')
2416 // Corefx stress testing
2417 assert os == 'Ubuntu'
2418 assert architecture == 'x64'
2419 assert lowerConfiguration == 'checked'
2420 assert isJitStressScenario(scenario)
2423 buildCommands += "./build.sh ${lowerConfiguration} ${architecture}"
2425 def scriptFileName = "\$WORKSPACE/set_stress_test_env.sh"
2427 def envScriptCmds = envScriptCreate(os, scriptFileName)
2428 envScriptCmds += envScriptSetStressModeVariables(os, Constants.jitStressModeScenarios[scenario], scriptFileName)
2429 envScriptCmds += envScriptFinalize(os, scriptFileName)
2430 buildCommands += envScriptCmds
2432 // Build and text corefx
2433 def workspaceRelativeFxRoot = "_/fx"
2434 def absoluteFxRoot = "\$WORKSPACE/${workspaceRelativeFxRoot}"
2435 def fxBranch = getFxBranch(branch)
2437 buildCommands += "python -u \$WORKSPACE/tests/scripts/run-corefx-tests.py -arch ${architecture} -ci_arch ${architecture} -build_type ${configuration} -fx_root ${absoluteFxRoot} -fx_branch ${fxBranch} -env_script ${scriptFileName}"
2439 // Archive and process (only) the test results
2440 Utilities.addArchival(newJob, "${workspaceRelativeFxRoot}/bin/**/testResults.xml")
2441 Utilities.addXUnitDotNETResults(newJob, "${workspaceRelativeFxRoot}/bin/**/testResults.xml")
2445 // Emulator cross builds for ARM runs on Ubuntu, Ubuntu16.04 and Tizen currently
2446 assert (os == 'Ubuntu') || (os == 'Ubuntu16.04') || (os == 'Tizen')
2448 // default values for Ubuntu
2450 def linuxCodeName = "trusty"
2451 if (os == 'Ubuntu16.04') {
2452 linuxCodeName = "xenial"
2454 else if (os == 'Tizen') {
2456 linuxCodeName = "tizen"
2459 // Unzip the Windows test binaries first. Exit with 0
2460 buildCommands += "unzip -q -o ./bin/tests/tests.zip -d ./bin/tests/Windows_NT.x64.${configuration} || exit 0"
2462 // Unpack the corefx binaries
2463 buildCommands += "mkdir ./bin/CoreFxBinDir"
2464 buildCommands += "tar -xf ./bin/build.tar.gz -C ./bin/CoreFxBinDir"
2465 if (os != 'Tizen') {
2466 buildCommands += "chmod a+x ./bin/CoreFxBinDir/corerun"
2468 // Test environment emulation using docker and qemu has some problem to use lttng library.
2469 // We should remove libcoreclrtraceptprovider.so to avoid test hang.
2470 if (os == 'Ubuntu') {
2471 buildCommands += "rm -f -v ./bin/CoreFxBinDir/libcoreclrtraceptprovider.so"
2474 // Call the ARM CI script to cross build and test using docker
2475 buildCommands += """./tests/scripts/arm32_ci_script.sh \\
2478 --linuxCodeName=${linuxCodeName} \\
2479 --buildConfig=${lowerConfiguration} \\
2480 --testRootDir=./bin/tests/Windows_NT.x64.${configuration} \\
2481 --coreFxBinDir=./bin/CoreFxBinDir \\
2482 --testDirFile=./tests/testsRunningInsideARM.txt"""
2484 // Basic archiving of the build, no pal tests
2485 Utilities.addArchival(newJob, "bin/Product/**,bin/obj/*/tests/**/*.dylib,bin/obj/*/tests/**/*.so", "bin/Product/**/.nuget/**")
2489 // Non-Windows ARM cross builds on hardware run on Ubuntu only
2490 assert (os == 'Ubuntu')
2492 // Add some useful information to the log file. Ignore return codes.
2493 buildCommands += "uname -a || true"
2495 def additionalOpts = ""
2496 if (architecture == 'arm') {
2497 additionalOpts = "-e CAC_ROOTFS_DIR=/crossrootfs/x86"
2500 // Cross build the Ubuntu/arm product using docker with a docker image that contains the correct
2501 // Ubuntu cross-compilation toolset (running on a Ubuntu x64 host).
2502 // For CoreFX testing, we only need the product build; we don't need to generate the layouts. The product
2503 // build is then copied into the corefx layout by the run-corefx-test.py script. For CoreFX testing, we
2504 // ZIP up the generated CoreFX runtime and tests.
2506 def dockerImage = getDockerImageName(architecture, os, true)
2507 def dockerCmd = "docker run -i --rm -v \${WORKSPACE}:\${WORKSPACE} -w \${WORKSPACE} -e ROOTFS_DIR=/crossrootfs/${architecture} ${additionalOpts} ${dockerImage} "
2509 buildCommands += "${dockerCmd}\${WORKSPACE}/build.sh ${lowerConfiguration} ${architecture} cross crosscomponent"
2511 if (doCoreFxTesting) {
2512 def scriptFileName = "\$WORKSPACE/set_stress_test_env.sh"
2514 def envScriptCmds = envScriptCreate(os, scriptFileName)
2515 envScriptCmds += envScriptSetStressModeVariables(os, Constants.jitStressModeScenarios[scenario], scriptFileName)
2516 envScriptCmds += envScriptFinalize(os, scriptFileName)
2517 buildCommands += envScriptCmds
2519 // Build and text corefx
2520 def workspaceRelativeFxRootLinux = "_/fx"
2521 def absoluteFxRoot = "\$WORKSPACE/${workspaceRelativeFxRootLinux}"
2522 def fxBranch = getFxBranch(branch)
2524 buildCommands += "${dockerCmd}python -u \$WORKSPACE/tests/scripts/run-corefx-tests.py -arch ${architecture} -ci_arch ${architecture} -build_type ${configuration} -fx_root ${absoluteFxRoot} -fx_branch ${fxBranch} -env_script ${scriptFileName} -no_run_tests"
2526 // Docker creates files with root permission, so we need to zip in docker also, or else we'll get permission errors.
2527 buildCommands += "${dockerCmd}zip -r ${workspaceRelativeFxRootLinux}/fxruntime.zip ${workspaceRelativeFxRootLinux}/bin/testhost/netcoreapp-Linux-Release-${architecture}"
2528 buildCommands += "${dockerCmd}zip -r ${workspaceRelativeFxRootLinux}/fxtests.zip ${workspaceRelativeFxRootLinux}/bin/tests"
2530 Utilities.addArchival(newJob, "${workspaceRelativeFxRootLinux}/fxruntime.zip")
2531 Utilities.addArchival(newJob, "${workspaceRelativeFxRootLinux}/fxtests.zip")
2532 Utilities.addArchival(newJob, "${workspaceRelativeFxRootLinux}/run-test.sh")
2535 // Then, using the same docker image, generate the CORE_ROOT layout using build-test.sh to
2536 // download the appropriate CoreFX packages.
2537 // Note that docker should not be necessary here, for the "generatelayoutonly" case, but we use it
2538 // just to be consistent with the "build.sh" case -- so both are run with the same environment.
2540 buildCommands += "${dockerCmd}\${WORKSPACE}/build-test.sh ${lowerConfiguration} ${architecture} cross generatelayoutonly"
2542 // ZIP up for the test job (created in the flow job code):
2543 // (1) the built CORE_ROOT, /home/user/coreclr/bin/tests/Linux.arm.Checked/Tests/Core_Root,
2544 // used by runtest.sh as the "--coreOverlayDir" argument.
2545 // (2) the native parts of the test build: /home/user/coreclr/bin/obj/Linux.arm.Checked/tests,
2546 // used by runtest.sh as the "--testNativeBinDir" argument.
2548 // These commands are assumed to be run from the root of the workspace.
2549 buildCommands += "zip -r coreroot.${lowerConfiguration}.zip ./bin/tests/Linux.${architecture}.${configuration}/Tests/Core_Root"
2550 buildCommands += "zip -r testnativebin.${lowerConfiguration}.zip ./bin/obj/Linux.${architecture}.${configuration}/tests"
2552 Utilities.addArchival(newJob, "coreroot.${lowerConfiguration}.zip,testnativebin.${lowerConfiguration}.zip", "")
2555 // We need to clean up the build machines; the docker build leaves newly built files with root permission, which
2556 // the cleanup task in Jenkins can't remove.
2559 azureVMAgentPostBuildAction {
2560 agentPostBuildAction('Delete agent after build execution (when idle).')
2566 println("Unknown architecture: ${architecture}");
2571 // editor brace matching: }
2573 println("Unknown os: ${os}");
2578 return buildCommands
2581 // Determine if we should generate a job for the given parameters. This is for non-flow jobs: either build and test, or build only.
2582 // Returns true if the job should be generated.
2583 def static shouldGenerateJob(def scenario, def isPR, def architecture, def configuration, def os, def isBuildOnly)
2585 // The "innerloop" (Pri-0 testing) scenario is only available as PR triggered.
2586 // All other scenarios do Pri-1 testing.
2587 if (scenario == 'innerloop' && !isPR) {
2591 // Run basic corefx tests only on PR-triggered jobs
2592 // Runs under Release and Checked
2593 if (scenario == 'corefx_innerloop' && !isPR) {
2597 // Tizen is only supported for armem architecture
2598 if (os == 'Tizen' && architecture != 'armem') {
2602 // Filter based on architecture.
2604 switch (architecture) {
2607 if ((os != 'Windows_NT') && (os != 'Ubuntu')) {
2612 if ((os != 'Ubuntu') && (os != 'Ubuntu16.04') && (os != 'Tizen')) {
2616 case 'x86_arm_altjit':
2617 case 'x64_arm64_altjit':
2618 if (os != 'Windows_NT') {
2623 if ((os != 'Windows_NT') && (os != 'Ubuntu')) {
2628 // Everything implemented
2631 println("Unknown architecture: ${architecture}")
2636 // Which (Windows) build only jobs are required?
2638 def isNormalOrInnerloop = (scenario == 'innerloop' || scenario == 'normal')
2641 switch (architecture) {
2643 // We use build only jobs for Windows arm cross-compilation corefx testing, so we need to generate builds for that.
2644 if (!isCoreFxScenario(scenario)) {
2650 if (!isNormalOrInnerloop) {
2659 // Filter based on scenario.
2661 if (isJitStressScenario(scenario)) {
2662 if (configuration != 'Checked') {
2666 def isEnabledOS = (os == 'Windows_NT') || (os == 'Ubuntu' && (isCoreFxScenario(scenario) || architecture == 'arm' || architecture == 'arm64'))
2671 switch (architecture) {
2673 case 'x86_arm_altjit':
2674 case 'x64_arm64_altjit':
2678 // x86 ubuntu: no stress modes
2679 if (os == 'Ubuntu') {
2685 // We use build only jobs for Windows arm cross-compilation corefx testing, so we need to generate builds for that.
2686 // No "regular" Windows arm corefx jobs, e.g.
2687 // For Ubuntu arm corefx testing, we use regular jobs (not "build only" since only Windows has "build only", and
2688 // the Ubuntu arm "regular" jobs don't run tests anyway).
2689 if (os == 'Windows_NT') {
2690 if (! (isBuildOnly && isCoreFxScenario(scenario)) ) {
2695 if (!isCoreFxScenario(scenario)) {
2702 if (os == 'Windows_NT') {
2706 if (!isCoreFxScenario(scenario)) {
2713 // arm64: stress is handled through flow jobs.
2714 // armem: no stress jobs for ARM emulator.
2718 else if (isR2RScenario(scenario)) {
2719 if (os != 'Windows_NT') {
2722 // Stress scenarios only run with Checked builds, not Release (they would work with Debug, but be slow).
2723 if ((configuration != 'Checked') && isR2RStressScenario(scenario)) {
2731 // The ilrt build isn't necessary except for Windows_NT2003. Non-Windows NT uses
2732 // the default scenario build
2733 if (os != 'Windows_NT') {
2737 if (architecture != 'x64') {
2741 if (configuration != 'Release') {
2746 if (os != 'Windows_NT' && os != 'Ubuntu' && os != 'OSX10.12') {
2749 if (architecture != 'x64') {
2752 if (configuration != 'Checked') {
2758 if (os != 'Windows_NT' && os != 'Ubuntu' && os != 'OSX10.12') {
2761 if (architecture != 'x64') {
2764 if (configuration != 'Release') {
2768 case 'gc_reliability_framework':
2769 case 'standalone_gc':
2770 if (os != 'Windows_NT' && os != 'Ubuntu' && os != 'OSX10.12') {
2774 if (architecture != 'x64') {
2778 if (configuration != 'Release' && configuration != 'Checked') {
2782 // We only run Windows and Ubuntu x64 Checked for formatting right now
2784 if (os != 'Windows_NT' && os != 'Ubuntu') {
2787 if (architecture != 'x64') {
2790 if (configuration != 'Checked') {
2795 if (os != 'Windows_NT' && (os != 'Ubuntu' || architecture != 'x64')) {
2798 if (architecture != 'x64' && architecture != 'x86') {
2806 if (!isValidPrTriggeredInnerLoopJob(os, architecture, configuration, isBuildOnly)) {
2810 case 'corefx_innerloop':
2811 if (os != 'Windows_NT'|| architecture != 'x64') {
2814 if(configuration != 'Release' && configuration != 'Checked') {
2819 println("Unknown scenario: ${scenario}")
2825 // For altjit, don't do any scenarios that don't change compilation. That is, scenarios that only change
2826 // runtime behavior, not compile-time behavior, are not interesting.
2827 switch (architecture) {
2828 case 'x86_arm_altjit':
2829 case 'x64_arm64_altjit':
2830 if (isGCStressRelatedTesting(scenario)) {
2838 // The job was not filtered out, so we should generate it!
2842 Constants.allScenarios.each { scenario ->
2843 [true, false].each { isPR ->
2844 Constants.architectureList.each { architecture ->
2845 Constants.configurationList.each { configuration ->
2846 Constants.osList.each { os ->
2847 // If the OS is Windows_NT_BuildOnly, set the isBuildOnly flag to true
2848 // and reset the os to Windows_NT
2849 def isBuildOnly = false
2850 if (os == 'Windows_NT_BuildOnly') {
2855 if (!shouldGenerateJob(scenario, isPR, architecture, configuration, os, isBuildOnly)) {
2860 def jobName = getJobName(configuration, architecture, os, scenario, isBuildOnly)
2861 def folderName = getJobFolder(scenario)
2863 // Create the new job
2864 def newJob = job(Utilities.getFullJobName(project, jobName, isPR, folderName)) {}
2866 // We don't want to include in view any job that is only used by a flow job (because we want the views to have only the
2867 // "top-level" jobs. Build only jobs are such jobs.
2870 addToViews(newJob, isPR, architecture, os)
2873 setJobMachineAffinity(architecture, os, true, false, false, newJob) // isBuildJob = true, isTestJob = false, isFlowJob = false
2875 Utilities.standardJobSetup(newJob, project, isPR, "*/${branch}")
2876 addTriggers(newJob, branch, isPR, architecture, os, configuration, scenario, false, isBuildOnly) // isFlowJob==false
2877 setJobTimeout(newJob, isPR, architecture, configuration, scenario, isBuildOnly)
2879 // Copy Windows build test binaries and corefx build artifacts for Linux cross build for armem.
2880 // We don't use a flow job for this, but we do depend on there being existing builds with these
2881 // artifacts produced.
2882 if (architecture == 'armem' && (os == 'Ubuntu' || os == 'Ubuntu16.04' || os == 'Tizen')) {
2883 // Define the Windows Tests and Corefx build job names
2884 def lowerConfiguration = configuration.toLowerCase()
2885 def WindowsTestsName = projectFolder + '/' +
2886 Utilities.getFullJobName(project,
2887 getJobName(lowerConfiguration, 'x64' , 'windows_nt', 'normal', true),
2889 def fxBranch = getFxBranch(branch)
2890 def corefxFolder = Utilities.getFolderName('dotnet/corefx') + '/' +
2891 Utilities.getFolderName(fxBranch)
2894 def corefx_os = 'linux'
2895 if (os == 'Tizen') {
2900 // Let's use release CoreFX to test checked CoreCLR,
2901 // because we do not generate checked CoreFX in CoreFX CI yet.
2902 def corefx_lowerConfiguration = lowerConfiguration
2903 if (lowerConfiguration == 'checked') {
2904 corefx_lowerConfiguration = 'release'
2907 // Copy the Windows test binaries and the Corefx build binaries
2910 copyArtifacts(WindowsTestsName) {
2911 includePatterns('bin/tests/tests.zip')
2913 latestSuccessful(true)
2916 copyArtifacts("${corefxFolder}/${corefx_os}_${arm_abi}_cross_${corefx_lowerConfiguration}") {
2917 includePatterns('bin/build.tar.gz')
2919 latestSuccessful(true)
2926 def buildCommands = calculateBuildCommands(newJob, scenario, branch, isPR, architecture, configuration, os, isBuildOnly)
2930 if (os == 'Windows_NT') {
2931 buildCommands.each { buildCommand ->
2932 batchFile(buildCommand)
2936 buildCommands.each { buildCommand ->
2949 // Create a Windows ARM/ARM64 test job that will be used by a flow job.
2950 // Returns the newly created job.
2951 def static CreateWindowsArmTestJob(def dslFactory, def project, def architecture, def os, def configuration, def scenario, def isPR, def inputCoreCLRBuildName)
2953 def osGroup = getOSGroup(os)
2954 def jobName = getJobName(configuration, architecture, os, scenario, false) + "_tst"
2956 def jobFolder = getJobFolder(scenario)
2957 def newJob = dslFactory.job(Utilities.getFullJobName(project, jobName, isPR, jobFolder)) {
2959 stringParam('CORECLR_BUILD', '', "Build number to copy CoreCLR ${osGroup} binaries from")
2963 // Set up the copies
2965 // Coreclr build we are trying to test
2967 // ** NOTE ** This will, correctly, overwrite the CORE_ROOT from the Windows test archive
2969 copyArtifacts(inputCoreCLRBuildName) {
2970 excludePatterns('**/testResults.xml', '**/*.ni.dll')
2972 buildNumber('${CORECLR_BUILD}')
2976 if (isCoreFxScenario(scenario)) {
2978 // Only arm supported for corefx testing now.
2979 assert architecture == 'arm'
2981 // Unzip CoreFx runtime
2982 batchFile("powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::ExtractToDirectory('_\\fx\\fxruntime.zip', '_\\fx\\bin\\testhost\\netcoreapp-Windows_NT-Release-arm')\"")
2984 // Unzip CoreFx tests.
2985 batchFile("powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::ExtractToDirectory('_\\fx\\fxtests.zip', '_\\fx\\bin\\tests')\"")
2987 // Add the script to run the corefx tests
2988 def corefx_runtime_path = "%WORKSPACE%\\_\\fx\\bin\\testhost\\netcoreapp-Windows_NT-Release-arm"
2989 def corefx_tests_dir = "%WORKSPACE%\\_\\fx\\bin\\tests"
2990 def corefx_exclusion_file = "%WORKSPACE%\\tests\\arm\\corefx_test_exclusions.txt"
2991 batchFile("call %WORKSPACE%\\tests\\scripts\\run-corefx-tests.bat ${corefx_runtime_path} ${corefx_tests_dir} ${corefx_exclusion_file}")
2993 } else { // !isCoreFxScenario(scenario)
2996 batchFile("powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::ExtractToDirectory('bin\\tests\\tests.zip', 'bin\\tests\\${osGroup}.${architecture}.${configuration}')\"")
2998 def buildCommands = ""
3000 def coreRootLocation = "%WORKSPACE%\\bin\\tests\\Windows_NT.${architecture}.${configuration}\\Tests\\Core_Root"
3001 def addEnvVariable = { variable, value -> buildCommands += "set ${variable}=${value}\r\n"}
3002 def addCommand = { cmd -> buildCommands += "${cmd}\r\n"}
3004 // Make sure Command Extensions are enabled. Used so %ERRORLEVEL% is available.
3005 addCommand("SETLOCAL ENABLEEXTENSIONS")
3008 addEnvVariable("CORE_ROOT", coreRootLocation)
3009 addEnvVariable("COMPlus_NoGuiOnAssert", "1")
3010 addEnvVariable("COMPlus_ContinueOnAssert", "0")
3012 // If we are running a stress mode, we'll set those variables as well
3013 if (isJitStressScenario(scenario) || isR2RStressScenario(scenario)) {
3014 def stressValues = null
3015 if (isJitStressScenario(scenario)) {
3016 stressValues = Constants.jitStressModeScenarios[scenario]
3019 stressValues = Constants.r2rStressScenarios[scenario]
3022 stressValues.each { key, value ->
3023 addEnvVariable(key, value)
3027 if (isR2RScenario(scenario)) {
3028 // Crossgen the framework assemblies.
3029 buildCommands += """
3030 @for %%F in (%CORE_ROOT%\\*.dll) do @call :PrecompileAssembly "%CORE_ROOT%" "%%F" %%~nxF
3031 @goto skip_PrecompileAssembly
3034 @REM Skip mscorlib since it is already precompiled.
3035 @if /I "%3" == "mscorlib.dll" exit /b 0
3036 @if /I "%3" == "mscorlib.ni.dll" exit /b 0
3038 "%CORE_ROOT%\\crossgen.exe" /Platform_Assemblies_Paths "%CORE_ROOT%" %2 >nul 2>nul
3039 @if "%errorlevel%" == "-2146230517" (
3040 echo %2 is not a managed assembly.
3041 ) else if "%errorlevel%" == "-2146234344" (
3042 echo %2 is not a managed assembly.
3043 ) else if %errorlevel% neq 0 (
3044 echo Unable to precompile %2
3050 :skip_PrecompileAssembly
3053 // Set RunCrossGen variable to cause test wrappers to invoke their logic to run
3054 // crossgen on tests before running them.
3055 addEnvVariable("RunCrossGen", "true")
3056 } // isR2RScenario(scenario)
3058 // Create the smarty command
3059 def smartyCommand = "C:\\Tools\\Smarty.exe /noecid /noie /workers 9 /inc EXPECTED_PASS "
3060 def addSmartyFlag = { flag -> smartyCommand += flag + " "}
3061 def addExclude = { exclude -> addSmartyFlag("/exc " + exclude)}
3062 def addArchSpecificExclude = { architectureToExclude, exclude -> addExclude(exclude) }
3064 // Exclude tests based on scenario.
3065 Constants.validArmWindowsScenarios[scenario].each { excludeTag ->
3066 addArchSpecificExclude(architecture, excludeTag)
3069 // Innerloop jobs run Pri-0 tests; everyone else runs Pri-1.
3070 if (scenario == 'innerloop') {
3074 // Exclude any test marked LONG_RUNNING; these often exceed the standard timeout and fail as a result.
3075 // TODO: We should create a "long running" job that runs these with a longer timeout.
3076 addExclude("LONG_RUNNING")
3078 smartyCommand += "/lstFile Tests.lst"
3080 def testListArch = [
3085 def archLocation = testListArch[architecture]
3087 addCommand("copy %WORKSPACE%\\tests\\${archLocation}\\Tests.lst bin\\tests\\${osGroup}.${architecture}.${configuration}")
3089 if (architecture == "arm64") {
3090 addCommand("copy C:\\Jenkins\\vcruntime140.dll bin\\tests\\${osGroup}.${architecture}.${configuration}\\Tests\\Core_Root")
3091 addCommand("copy C:\\Jenkins\\vcruntime140d.dll bin\\tests\\${osGroup}.${architecture}.${configuration}\\Tests\\Core_Root")
3094 addCommand("pushd bin\\tests\\${osGroup}.${architecture}.${configuration}")
3095 addCommand("${smartyCommand}")
3097 // Save the errorlevel from the smarty command to be used as the errorlevel of this batch file.
3098 // However, we also need to remove all the variables that were set during this batch file, so we
3099 // can run the ZIP powershell command (below) in a clean environment. (We can't run the powershell
3100 // command with the COMPlus_AltJit variables set, for example.) To do that, we do ENDLOCAL as well
3101 // as save the current errorlevel on the same line. This works because CMD evaluates the %errorlevel%
3102 // variable expansion (or any variable expansion on the line) BEFORE it executes the ENDLOCAL command.
3103 // Note that the ENDLOCAL also undoes the pushd command, but we add the popd here for clarity.
3104 addCommand("popd & ENDLOCAL & set __save_smarty_errorlevel=%errorlevel%")
3106 // ZIP up the smarty output, no matter what the smarty result.
3107 addCommand("powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('.\\bin\\tests\\${osGroup}.${architecture}.${configuration}\\Smarty.run.0', '.\\bin\\tests\\${osGroup}.${architecture}.${configuration}\\Smarty.run.0.zip')\"")
3109 addCommand("echo %errorlevel%")
3110 addCommand("dir .\\bin\\tests\\${osGroup}.${architecture}.${configuration}")
3112 // Use the smarty errorlevel as the script errorlevel.
3113 addCommand("exit /b %__save_smarty_errorlevel%")
3115 batchFile(buildCommands)
3116 } // non-corefx testing
3120 if (!isCoreFxScenario(scenario)) {
3121 Utilities.addArchival(newJob, "bin/tests/${osGroup}.${architecture}.${configuration}/Smarty.run.0/*.smrt", '', true, false)
3123 // Archive a ZIP file of the entire Smarty.run.0 directory. This is possibly a little too much,
3124 // but there is no easy way to only archive the HTML/TXT files of the failing tests, so we get
3125 // all the passing test info as well. Not necessarily a bad thing, but possibly somewhat large.
3126 Utilities.addArchival(newJob, "bin/tests/${osGroup}.${architecture}.${configuration}/Smarty.run.0.zip", '', true, false)
3132 // Create a test job not covered by the "Windows ARM" case that will be used by a flow job.
3133 // E.g., non-Windows tests.
3134 // Returns the newly created job.
3135 def static CreateOtherTestJob(def dslFactory, def project, def branch, def architecture, def os, def configuration, def scenario, def isPR, def inputCoreCLRBuildName, def inputTestsBuildName)
3137 def isUbuntuArmJob = (os == "Ubuntu") && ((architecture == 'arm') || (architecture == 'arm64')) // ARM Ubuntu running on hardware (not emulator)
3138 def doCoreFxTesting = isCoreFxScenario(scenario)
3140 def workspaceRelativeFxRootLinux = "_/fx" // only used for CoreFX testing
3142 def osGroup = getOSGroup(os)
3143 def jobName = getJobName(configuration, architecture, os, scenario, false) + "_tst"
3146 def useServerGC = false
3148 // Enable Server GC for Ubuntu PR builds
3149 // REVIEW: why? Does this apply to all architectures? Why only PR?
3150 if (os == 'Ubuntu' && isPR) {
3151 testOpts += ' --useServerGC'
3155 if (isR2RScenario(scenario)) {
3157 testOpts += ' --crossgen --runcrossgentests'
3159 if (scenario == 'r2r_jitstress1') {
3160 testOpts += ' --jitstress=1'
3162 else if (scenario == 'r2r_jitstress2') {
3163 testOpts += ' --jitstress=2'
3165 else if (scenario == 'r2r_jitstressregs1') {
3166 testOpts += ' --jitstressregs=1'
3168 else if (scenario == 'r2r_jitstressregs2') {
3169 testOpts += ' --jitstressregs=2'
3171 else if (scenario == 'r2r_jitstressregs3') {
3172 testOpts += ' --jitstressregs=3'
3174 else if (scenario == 'r2r_jitstressregs4') {
3175 testOpts += ' --jitstressregs=4'
3177 else if (scenario == 'r2r_jitstressregs8') {
3178 testOpts += ' --jitstressregs=8'
3180 else if (scenario == 'r2r_jitstressregs0x10') {
3181 testOpts += ' --jitstressregs=0x10'
3183 else if (scenario == 'r2r_jitstressregs0x80') {
3184 testOpts += ' --jitstressregs=0x80'
3186 else if (scenario == 'r2r_jitstressregs0x1000') {
3187 testOpts += ' --jitstressregs=0x1000'
3189 else if (scenario == 'r2r_jitminopts') {
3190 testOpts += ' --jitminopts'
3192 else if (scenario == 'r2r_jitforcerelocs') {
3193 testOpts += ' --jitforcerelocs'
3195 else if (scenario == 'r2r_gcstress15') {
3196 testOpts += ' --gcstresslevel=0xF'
3199 else if (scenario == 'jitdiff') {
3200 testOpts += ' --jitdisasm --crossgen'
3202 else if (scenario == 'illink') {
3203 testOpts += ' --link=\$WORKSPACE/linker/linker/bin/netcore_Release/netcoreapp2.0/ubuntu-x64/publish/illink'
3205 else if (isLongGc(scenario)) {
3206 // Long GC tests behave very poorly when they are not
3207 // the only test running (many of them allocate until OOM).
3208 testOpts += ' --sequential'
3210 // A note - runtest.sh does have "--long-gc" and "--gcsimulator" options
3211 // for running long GC and GCSimulator tests, respectively. We don't use them
3212 // here because using a playlist file produces much more readable output on the CI machines
3213 // and reduces running time.
3215 // The Long GC playlist contains all of the tests that are
3216 // going to be run. The GCSimulator playlist contains all of
3217 // the GC simulator tests.
3218 if (scenario == 'longgc') {
3219 testOpts += ' --long-gc --playlist=./tests/longRunningGcTests.txt'
3221 else if (scenario == 'gcsimulator') {
3222 testOpts += ' --gcsimulator --playlist=./tests/gcSimulatorTests.txt'
3225 else if (isGcReliabilityFramework(scenario)) {
3226 testOpts += ' --build-overlay-only'
3228 else if (scenario == 'standalone_gc') {
3229 if (osGroup == 'OSX') {
3230 testOpts += ' --gcname=libclrgc.dylib'
3232 else if (osGroup == 'Linux') {
3233 testOpts += ' --gcname=libclrgc.so'
3236 println("Unexpected OS group: ${osGroup} for os ${os}")
3241 // The ARM Ubuntu corefx test job doesn't depend on a Windows test build, and hence inputTestsBuildName
3242 // will be null in this case.
3244 def jobFolder = getJobFolder(scenario)
3245 def newJob = dslFactory.job(Utilities.getFullJobName(project, jobName, isPR, jobFolder)) {
3247 if (inputTestsBuildName != null) {
3248 stringParam('CORECLR_WINDOWS_BUILD', '', 'Build number to copy CoreCLR Windows test binaries from')
3250 stringParam('CORECLR_BUILD', '', "Build number to copy CoreCLR ${osGroup} binaries from")
3254 // Set up the copies
3256 // Coreclr build containing the tests and mscorlib
3257 // pri1 jobs still need to copy windows_nt built tests
3258 if (inputTestsBuildName != null) {
3259 copyArtifacts(inputTestsBuildName) {
3260 excludePatterns('**/testResults.xml', '**/*.ni.dll')
3262 buildNumber('${CORECLR_WINDOWS_BUILD}')
3267 // Coreclr build we are trying to test
3269 // ** NOTE ** This will, correctly, overwrite the CORE_ROOT from the Windows test archive
3271 copyArtifacts(inputCoreCLRBuildName) {
3272 excludePatterns('**/testResults.xml', '**/*.ni.dll')
3274 buildNumber('${CORECLR_BUILD}')
3278 if (isUbuntuArmJob) {
3279 // Add some useful information to the log file. Ignore return codes.
3280 shell("uname -a || true")
3283 if (architecture == 'x86') {
3284 shell("mkdir ./bin/CoreFxNative")
3286 def fxBranch = getFxBranch(branch)
3287 def corefxFolder = Utilities.getFolderName('dotnet/corefx') + '/' + Utilities.getFolderName(fxBranch)
3289 copyArtifacts("${corefxFolder}/ubuntu16.04_x86_release") {
3290 includePatterns('bin/build.tar.gz')
3291 targetDirectory('bin/CoreFxNative')
3293 latestSuccessful(true)
3297 shell("tar -xf ./bin/CoreFxNative/bin/build.tar.gz -C ./bin/CoreFxBinDir")
3300 // CoreFX testing downloads the CoreFX tests, not the coreclr tests. Also, unzip the built CoreFX layout/runtime directories.
3301 if (doCoreFxTesting) {
3302 shell("unzip -o ${workspaceRelativeFxRootLinux}/fxtests.zip || exit 0")
3303 shell("unzip -o ${workspaceRelativeFxRootLinux}/fxruntime.zip || exit 0")
3306 // Unzip the tests first. Exit with 0
3307 shell("unzip -q -o ./bin/tests/tests.zip -d ./bin/tests/${osGroup}.${architecture}.${configuration} || exit 0")
3308 shell("rm -r ./bin/tests/${osGroup}.${architecture}.${configuration}/Tests/Core_Root || exit 0")
3311 // For arm Ubuntu (on hardware), we do the "build-test" step on the build machine, not on the test
3312 // machine. The arm Ubuntu test machines do no building -- they have no CLI, for example.
3313 // We should probably do the "generatelayoutonly" step on the build machine for all architectures.
3314 // However, it's believed that perhaps there's an issue with executable permission bits not getting
3315 // copied correctly.
3316 if (!doCoreFxTesting) {
3317 if (isUbuntuArmJob) {
3318 def lowerConfiguration = configuration.toLowerCase()
3319 shell("unzip -o ./coreroot.${lowerConfiguration}.zip || exit 0") // unzips to ./bin/tests/Linux.${architecture}.${configuration}/Tests/Core_Root
3320 shell("unzip -o ./testnativebin.${lowerConfiguration}.zip || exit 0") // unzips to ./bin/obj/Linux.${architecture}.${configuration}/tests
3323 shell("./build-test.sh ${architecture} ${configuration} generatelayoutonly")
3327 // Execute the tests
3328 def runDocker = isNeedDocker(architecture, os, false)
3329 def dockerPrefix = ""
3332 def dockerImage = getDockerImageName(architecture, os, false)
3333 dockerPrefix = "docker run -i --rm -v \${WORKSPACE}:\${WORKSPACE} -w \${WORKSPACE} "
3334 dockerCmd = dockerPrefix + "${dockerImage} "
3337 // If we are running a stress mode, we'll set those variables first.
3338 // For CoreFX, the stress variables are already built into the CoreFX test build per-test wrappers.
3339 if (!doCoreFxTesting && isJitStressScenario(scenario)) {
3340 def scriptFileName = "\${WORKSPACE}/set_stress_test_env.sh"
3341 def envScriptCmds = envScriptCreate(os, scriptFileName)
3342 envScriptCmds += envScriptSetStressModeVariables(os, Constants.jitStressModeScenarios[scenario], scriptFileName)
3343 envScriptCmds += envScriptFinalize(os, scriptFileName)
3344 shell("${envScriptCmds}")
3345 testOpts += " --test-env=${scriptFileName}"
3348 // setup-stress-dependencies.sh, invoked by runtest.sh to download the coredistools package, depends on the "dotnet"
3349 // tool downloaded by the "init-tools.sh" script. However, it only invokes setup-stress-dependencies.sh for x64. The
3350 // coredistools package is used by GCStress on x86 and x64 to disassemble code to determine instruction boundaries.
3351 // On arm/arm64, it is not required as determining instruction boundaries is trivial.
3352 if (isGCStressRelatedTesting(scenario)) {
3353 if (architecture == 'x64') {
3354 shell('./init-tools.sh')
3358 if (doCoreFxTesting) {
3360 \${WORKSPACE}/${workspaceRelativeFxRootLinux}/run-test.sh --sequential --test-exclude-file \${WORKSPACE}/tests/${architecture}/corefx_linux_test_exclusions.txt --runtime \${WORKSPACE}/${workspaceRelativeFxRootLinux}/bin/testhost/netcoreapp-Linux-Release-${architecture} --arch ${architecture} --corefx-tests \${WORKSPACE}/${workspaceRelativeFxRootLinux}/bin --configurationGroup Release""")
3363 def runScript = "${dockerCmd}./tests/runtest.sh"
3367 --testRootDir=\"\${WORKSPACE}/bin/tests/${osGroup}.${architecture}.${configuration}\" \\
3368 --coreOverlayDir=\"\${WORKSPACE}/bin/tests/${osGroup}.${architecture}.${configuration}/Tests/Core_Root\" \\
3369 --testNativeBinDir=\"\${WORKSPACE}/bin/obj/${osGroup}.${architecture}.${configuration}/tests\" \\
3370 --copyNativeTestBin --limitedDumpGeneration ${testOpts}""")
3373 if (isGcReliabilityFramework(scenario)) {
3374 // runtest.sh doesn't actually execute the reliability framework - do it here.
3377 dockerCmd = dockerPrefix + "-e COMPlus_gcServer=1 ${dockerImage} "
3380 shell("export COMPlus_gcServer=1")
3384 shell("${dockerCmd}./tests/scripts/run-gc-reliability-framework.sh ${architecture} ${configuration}")
3389 // Experimental: If on Ubuntu 14.04, then attempt to pull in crash dump links
3390 if (os in ['Ubuntu']) {
3391 SummaryBuilder summaries = new SummaryBuilder()
3392 summaries.addLinksSummaryFromFile('Crash dumps from this run:', 'dumplings.txt')
3393 summaries.emit(newJob)
3396 if (doCoreFxTesting) {
3397 Utilities.addArchival(newJob, "${workspaceRelativeFxRootLinux}/bin/**/testResults.xml")
3398 Utilities.addXUnitDotNETResults(newJob, "${workspaceRelativeFxRootLinux}/bin/**/testResults.xml")
3401 Utilities.addArchival(newJob, "bin/tests/${osGroup}.${architecture}.${configuration}/coreclrtests.*.txt")
3402 Utilities.addXUnitDotNETResults(newJob, '**/coreclrtests.xml')
3408 // Create a test job that will be used by a flow job.
3409 // Returns the newly created job.
3410 // Note that we don't add tests jobs to the various views, since they are always used by a flow job, which is in the views,
3411 // and we want the views to be the minimal set of "top-level" jobs that represent all work.
3412 def static CreateTestJob(def dslFactory, def project, def branch, def architecture, def os, def configuration, def scenario, def isPR, def inputCoreCLRBuildName, def inputTestsBuildName)
3414 def windowsArmJob = ((os == "Windows_NT") && (architecture in Constants.armWindowsCrossArchitectureList))
3417 if (windowsArmJob) {
3418 assert inputTestsBuildName == null
3419 newJob = CreateWindowsArmTestJob(dslFactory, project, architecture, os, configuration, scenario, isPR, inputCoreCLRBuildName)
3421 newJob = CreateOtherTestJob(dslFactory, project, branch, architecture, os, configuration, scenario, isPR, inputCoreCLRBuildName, inputTestsBuildName)
3424 setJobMachineAffinity(architecture, os, false, true, false, newJob) // isBuildJob = false, isTestJob = true, isFlowJob = false
3426 if (scenario == 'jitdiff') {
3427 def osGroup = getOSGroup(os)
3428 Utilities.addArchival(newJob, "bin/tests/${osGroup}.${architecture}.${configuration}/dasm/**")
3431 Utilities.standardJobSetup(newJob, project, isPR, "*/${branch}")
3432 setJobTimeout(newJob, isPR, architecture, configuration, scenario, false)
3437 // Create a flow job to tie together a build job with the given test job.
3438 // The 'inputTestsBuildName' argument might be null if the flow job doesn't depend on a Windows build job.
3439 // Returns the new flow job.
3440 def static CreateFlowJob(def dslFactory, def project, def branch, def architecture, def os, def configuration, def scenario, def isPR, def fullTestJobName, def inputCoreCLRBuildName, def inputTestsBuildName)
3442 // Windows CoreCLR build and Linux CoreCLR build (in parallel) ->
3443 // Linux CoreCLR test
3444 def flowJobName = getJobName(configuration, architecture, os, scenario, false) + "_flow"
3445 def jobFolder = getJobFolder(scenario)
3447 def newFlowJob = null
3449 if (inputTestsBuildName == null) {
3450 newFlowJob = dslFactory.buildFlowJob(Utilities.getFullJobName(project, flowJobName, isPR, jobFolder)) {
3452 coreclrBuildJob = build(params, '${inputCoreCLRBuildName}')
3454 // And then build the test build
3455 build(params + [CORECLR_BUILD: coreclrBuildJob.build.number], '${fullTestJobName}')
3458 JobReport.Report.addReference(inputCoreCLRBuildName)
3459 JobReport.Report.addReference(fullTestJobName)
3462 newFlowJob = dslFactory.buildFlowJob(Utilities.getFullJobName(project, flowJobName, isPR, jobFolder)) {
3464 // Build the input jobs in parallel
3466 { coreclrBuildJob = build(params, '${inputCoreCLRBuildName}') },
3467 { windowsBuildJob = build(params, '${inputTestsBuildName}') }
3470 // And then build the test build
3471 build(params + [CORECLR_BUILD: coreclrBuildJob.build.number,
3472 CORECLR_WINDOWS_BUILD: windowsBuildJob.build.number], '${fullTestJobName}')
3475 JobReport.Report.addReference(inputCoreCLRBuildName)
3476 JobReport.Report.addReference(inputTestsBuildName)
3477 JobReport.Report.addReference(fullTestJobName)
3480 addToViews(newFlowJob, isPR, architecture, os)
3482 setJobMachineAffinity(architecture, os, false, false, true, newFlowJob) // isBuildJob = false, isTestJob = false, isFlowJob = true
3484 Utilities.standardJobSetup(newFlowJob, project, isPR, "*/${branch}")
3485 addTriggers(newFlowJob, branch, isPR, architecture, os, configuration, scenario, true, false) // isFlowJob==true, isWindowsBuildOnlyJob==false
3490 // Determine if we should generate a flow job for the given parameters.
3491 // Returns true if the job should be generated.
3492 def static shouldGenerateFlowJob(def scenario, def isPR, def architecture, def configuration, def os)
3494 // The "innerloop" (Pri-0 testing) scenario is only available as PR triggered.
3495 // All other scenarios do Pri-1 testing.
3496 if (scenario == 'innerloop' && !isPR) {
3500 if (scenario == 'corefx_innerloop') {
3504 // Filter based on OS and architecture.
3506 switch (architecture) {
3508 if (os != "Ubuntu" && os != "Windows_NT") {
3513 if (os != "Ubuntu" && os != "Windows_NT") {
3518 if (os != "Ubuntu") {
3523 if (!(os in Constants.crossList)) {
3526 if (os == "Windows_NT") {
3531 case 'x86_arm_altjit':
3532 case 'x64_arm64_altjit':
3536 println("Unknown architecture: ${architecture}")
3541 def isNormalOrInnerloop = (scenario == 'innerloop' || scenario == 'normal')
3543 // Filter based on scenario in OS.
3545 if (os == 'Windows_NT') {
3546 if (!isArmWindowsScenario(scenario)) {
3552 if (architecture == 'arm64') {
3553 if (!(scenario in Constants.validLinuxArmScenarios)) {
3557 else if (architecture == 'arm') {
3558 if (!(scenario in Constants.validLinuxArmScenarios)) {
3562 else if (architecture == 'x86') {
3563 // Linux/x86 only want innerloop and default test
3564 if (!isNormalOrInnerloop) {
3568 else if (architecture == 'x64') {
3569 // Linux/x64 corefx testing doesn't need a flow job; the "build" job runs run-corefx-tests.py which
3570 // builds and runs the corefx tests. Other Linux/x64 flow jobs are required to get the test
3571 // build from a Windows machine.
3572 if (isCoreFxScenario(scenario)) {
3578 // For CentOS, we only want Checked/Release builds.
3579 if (os == 'CentOS7.1') {
3580 if (configuration != 'Checked' && configuration != 'Release') {
3583 if (!isNormalOrInnerloop && !isR2RScenario(scenario) && !isJitStressScenario(scenario)) {
3588 // For RedHat and Debian, we only do Release builds.
3589 else if (os == 'RHEL7.2' || os == 'Debian8.4') {
3590 if (configuration != 'Release') {
3593 if (!isNormalOrInnerloop) {
3598 // Next, filter based on scenario.
3600 if (isJitStressScenario(scenario)) {
3601 if (configuration != 'Checked') {
3605 // On Windows, CoreFx tests currently not implemented for ARM64.
3606 if (isCoreFxScenario(scenario) && (os == 'Windows_NT') && (architecture == 'arm64')) {
3610 else if (isR2RBaselineScenario(scenario)) {
3611 if (configuration != 'Checked' && configuration != 'Release') {
3615 else if (isR2RStressScenario(scenario)) {
3616 if (configuration != 'Checked') {
3626 // Long GC tests take a long time on non-Release builds
3627 // ilrt is also Release only
3628 if (configuration != 'Release') {
3634 if (configuration != 'Checked') {
3639 case 'gc_reliability_framework':
3640 case 'standalone_gc':
3641 if (configuration != 'Release' && configuration != 'Checked') {
3649 if (os != 'Windows_NT' && os != 'Ubuntu') {
3660 if (!isValidPrTriggeredInnerLoopJob(os, architecture, configuration, false)) {
3666 println("Unknown scenario: ${scenario}")
3672 // The job was not filtered out, so we should generate it!
3676 // Create jobs requiring flow jobs. This includes x64 non-Windows, arm/arm64 Ubuntu, and arm/arm64 Windows.
3677 Constants.allScenarios.each { scenario ->
3678 [true, false].each { isPR ->
3679 Constants.architectureList.each { architecture ->
3680 Constants.configurationList.each { configuration ->
3681 Constants.osList.each { os ->
3683 if (!shouldGenerateFlowJob(scenario, isPR, architecture, configuration, os)) {
3687 def windowsArmJob = ((os == "Windows_NT") && (architecture in Constants.armWindowsCrossArchitectureList))
3688 def doCoreFxTesting = isCoreFxScenario(scenario)
3690 // Figure out the job name of the CoreCLR build the test will depend on.
3692 def inputCoreCLRBuildScenario = scenario == 'innerloop' ? 'innerloop' : 'normal'
3693 def inputCoreCLRBuildIsBuildOnly = false
3694 if (doCoreFxTesting) {
3695 // Every CoreFx test depends on its own unique build.
3696 inputCoreCLRBuildScenario = scenario
3697 if (windowsArmJob) {
3698 // Only Windows ARM corefx jobs use "build only" jobs. Others, such as Ubuntu ARM corefx, use "regular" jobs.
3699 inputCoreCLRBuildIsBuildOnly = true
3702 def inputCoreCLRFolderName = getJobFolder(inputCoreCLRBuildScenario)
3703 def inputCoreCLRBuildName = projectFolder + '/' +
3704 Utilities.getFullJobName(project, getJobName(configuration, architecture, os, inputCoreCLRBuildScenario, inputCoreCLRBuildIsBuildOnly), isPR, inputCoreCLRFolderName)
3706 // Figure out the name of the build job that the test job will depend on.
3707 // For Windows ARM tests, this is not used, as the CoreCLR build creates the tests. For other
3708 // tests (e.g., Linux ARM), we depend on a Windows build to get the tests.
3709 // For CoreFX tests, however, Linux doesn't need the Windows build for the tests, since the
3710 // CoreFX build creates the tests.
3712 def inputTestsBuildName = null
3714 if (!windowsArmJob && !doCoreFxTesting) {
3715 def testBuildScenario = scenario == 'innerloop' ? 'innerloop' : 'normal'
3717 def inputTestsBuildArch = architecture
3718 if (architecture == "arm64") {
3719 // Use the x64 test build for arm64 unix
3720 inputTestsBuildArch = "x64"
3722 else if (architecture == "arm") {
3723 // Use the x86 test build for arm unix
3724 inputTestsBuildArch = "x86"
3727 def inputTestsBuildIsBuildOnly = true
3729 inputTestsBuildName = projectFolder + '/' +
3730 Utilities.getFullJobName(project, getJobName(configuration, inputTestsBuildArch, 'windows_nt', testBuildScenario, inputTestsBuildIsBuildOnly), isPR)
3733 // =============================================================================================
3734 // Create the test job
3735 // =============================================================================================
3737 def testJob = CreateTestJob(this, project, branch, architecture, os, configuration, scenario, isPR, inputCoreCLRBuildName, inputTestsBuildName)
3739 // =============================================================================================
3740 // Create a build flow to join together the build and tests required to run this test.
3741 // =============================================================================================
3743 if (os == 'RHEL7.2' || os == 'Debian8.4') {
3744 // Do not create the flow job for RHEL jobs.
3748 def fullTestJobName = projectFolder + '/' + testJob.name
3749 def flowJob = CreateFlowJob(this, project, branch, architecture, os, configuration, scenario, isPR, fullTestJobName, inputCoreCLRBuildName, inputTestsBuildName)
3757 JobReport.Report.generateJobReport(out)
3759 // Make the call to generate the help job
3760 Utilities.createHelperJob(this, project, branch,
3761 "Welcome to the ${project} Repository", // This is prepended to the help message
3762 "Have a nice day!") // This is appended to the help message. You might put known issues here.
3764 Utilities.addCROSSCheck(this, project, branch)