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',
21 'Ubuntu16.04' : 'Linux',
22 'Ubuntu16.10' : 'Linux',
24 'Debian8.4' : 'Linux',
26 'CentOS7.1' : 'Linux',
29 'Windows_NT' : 'Windows_NT']
30 def osGroup = osGroupMap.get(os, null)
31 assert osGroup != null : "Could not find os group for ${os}"
35 def static getCrossArchitectures(def os, def architecture, def scenario) {
36 switch (architecture) {
47 // We use this class (vs variables) so that the static functions can access data here.
50 // We have very limited Windows ARM64 hardware (used for ARM/ARM64 testing) and Linux/arm32 and Linux/arm64 hardware.
51 // So only allow certain branches to use it.
52 def static LimitedHardwareBranches = [
55 // Innerloop build OS's
56 // The Windows_NT_BuildOnly OS is a way to speed up the Non-Windows builds by avoiding
57 // test execution in the build flow runs. It generates the exact same build
58 // as Windows_NT but without running the tests.
64 'Windows_NT_BuildOnly',
72 def static crossList = [
80 // This is a set of JIT stress modes combined with the set of variables that
81 // need to be set to actually enable that stress mode. The key of the map is the stress mode and
82 // the values are the environment variables
83 def static jitStressModeScenarios = [
84 'minopts' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JITMinOpts' : '1'],
85 'tieredcompilation' : ['COMPlus_TieredCompilation' : '1'], // this can be removed once tiered compilation is on by default
86 'no_tiered_compilation' : ['COMPlus_TieredCompilation' : '0'],
87 'no_tiered_compilation_innerloop': ['COMPlus_TieredCompilation' : '0'],
88 'forcerelocs' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_ForceRelocs' : '1'],
89 'jitstress1' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStress' : '1'],
90 'jitstress2' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStress' : '2'],
91 'jitstress1_tiered' : ['COMPlus_TieredCompilation' : '1', 'COMPlus_JitStress' : '1'],
92 'jitstress2_tiered' : ['COMPlus_TieredCompilation' : '1', 'COMPlus_JitStress' : '2'],
93 'jitstressregs1' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '1'],
94 'jitstressregs2' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '2'],
95 'jitstressregs3' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '3'],
96 'jitstressregs4' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '4'],
97 'jitstressregs8' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '8'],
98 'jitstressregs0x10' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '0x10'],
99 'jitstressregs0x80' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '0x80'],
100 'jitstressregs0x1000' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '0x1000'],
101 'jitstress2_jitstressregs1' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '1'],
102 'jitstress2_jitstressregs2' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '2'],
103 'jitstress2_jitstressregs3' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '3'],
104 'jitstress2_jitstressregs4' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '4'],
105 'jitstress2_jitstressregs8' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '8'],
106 'jitstress2_jitstressregs0x10' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '0x10'],
107 'jitstress2_jitstressregs0x80' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '0x80'],
108 'jitstress2_jitstressregs0x1000' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '0x1000'],
109 'tailcallstress' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_TailcallStress' : '1'],
110 'jitsse2only' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_EnableAVX' : '0', 'COMPlus_EnableSSE3_4' : '0'],
111 'jitnosimd' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_FeatureSIMD' : '0'],
112 'jitincompletehwintrinsic' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_EnableIncompleteISAClass' : '1'],
113 'jitx86hwintrinsicnoavx' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_EnableIncompleteISAClass' : '1', 'COMPlus_EnableAVX' : '0'], // testing the legacy SSE encoding
114 'jitx86hwintrinsicnoavx2' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_EnableIncompleteISAClass' : '1', 'COMPlus_EnableAVX2' : '0'], // testing SNB/IVB
115 'jitx86hwintrinsicnosimd' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_EnableIncompleteISAClass' : '1', 'COMPlus_FeatureSIMD' : '0'], // match "jitnosimd", may need to remove after decoupling HW intrinsic from FeatureSIMD
116 'jitnox86hwintrinsic' : ['COMPlus_TieredCompilation' : '0', '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'],
117 'corefx_baseline' : ['COMPlus_TieredCompilation' : '0'], // corefx baseline
118 'corefx_minopts' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JITMinOpts' : '1'],
119 'corefx_tieredcompilation' : ['COMPlus_TieredCompilation' : '1'], // this can be removed once tiered compilation is on by default
120 'corefx_jitstress1' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStress' : '1'],
121 'corefx_jitstress2' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStress' : '2'],
122 'corefx_jitstressregs1' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '1'],
123 'corefx_jitstressregs2' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '2'],
124 'corefx_jitstressregs3' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '3'],
125 'corefx_jitstressregs4' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '4'],
126 'corefx_jitstressregs8' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '8'],
127 'corefx_jitstressregs0x10' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '0x10'],
128 'corefx_jitstressregs0x80' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '0x80'],
129 'corefx_jitstressregs0x1000' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '0x1000'],
130 'gcstress0x3' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_GCStress' : '0x3'],
131 'gcstress0xc' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_GCStress' : '0xC'],
132 'zapdisable' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_ZapDisable' : '1', 'COMPlus_ReadyToRun' : '0'],
133 'heapverify1' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_HeapVerify' : '1'],
134 'gcstress0xc_zapdisable' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_GCStress' : '0xC', 'COMPlus_ZapDisable' : '1', 'COMPlus_ReadyToRun' : '0'],
135 'gcstress0xc_zapdisable_jitstress2' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_GCStress' : '0xC', 'COMPlus_ZapDisable' : '1', 'COMPlus_ReadyToRun' : '0', 'COMPlus_JitStress' : '2'],
136 'gcstress0xc_zapdisable_heapverify1' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_GCStress' : '0xC', 'COMPlus_ZapDisable' : '1', 'COMPlus_ReadyToRun' : '0', 'COMPlus_HeapVerify' : '1'],
137 'gcstress0xc_jitstress1' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_GCStress' : '0xC', 'COMPlus_JitStress' : '1'],
138 'gcstress0xc_jitstress2' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_GCStress' : '0xC', 'COMPlus_JitStress' : '2'],
139 'gcstress0xc_minopts_heapverify1' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_GCStress' : '0xC', 'COMPlus_JITMinOpts' : '1', 'COMPlus_HeapVerify' : '1']
142 // This is a set of ReadyToRun stress scenarios
143 def static r2rStressScenarios = [
144 'r2r_jitstress1' : ['COMPlus_TieredCompilation' : '0', "COMPlus_JitStress": "1"],
145 'r2r_jitstress2' : ['COMPlus_TieredCompilation' : '0', "COMPlus_JitStress": "2"],
146 'r2r_jitstress1_tiered' : ['COMPlus_TieredCompilation' : '1', "COMPlus_JitStress": "1"],
147 'r2r_jitstress2_tiered' : ['COMPlus_TieredCompilation' : '1', "COMPlus_JitStress": "2"],
148 'r2r_jitstressregs1' : ['COMPlus_TieredCompilation' : '0', "COMPlus_JitStressRegs": "1"],
149 'r2r_jitstressregs2' : ['COMPlus_TieredCompilation' : '0', "COMPlus_JitStressRegs": "2"],
150 'r2r_jitstressregs3' : ['COMPlus_TieredCompilation' : '0', "COMPlus_JitStressRegs": "3"],
151 'r2r_jitstressregs4' : ['COMPlus_TieredCompilation' : '0', "COMPlus_JitStressRegs": "4"],
152 'r2r_jitstressregs8' : ['COMPlus_TieredCompilation' : '0', "COMPlus_JitStressRegs": "8"],
153 'r2r_jitstressregs0x10' : ['COMPlus_TieredCompilation' : '0', "COMPlus_JitStressRegs": "0x10"],
154 'r2r_jitstressregs0x80' : ['COMPlus_TieredCompilation' : '0', "COMPlus_JitStressRegs": "0x80"],
155 'r2r_jitstressregs0x1000' : ['COMPlus_TieredCompilation' : '0', "COMPlus_JitStressRegs": "0x1000"],
156 'r2r_jitminopts' : ['COMPlus_TieredCompilation' : '0', "COMPlus_JITMinOpts": "1"],
157 'r2r_jitforcerelocs' : ['COMPlus_TieredCompilation' : '0', "COMPlus_ForceRelocs": "1"],
158 'r2r_gcstress15' : ['COMPlus_TieredCompilation' : '0', "COMPlus_GCStress": "0xF"],
159 'r2r_no_tiered_compilation' : ['COMPlus_TieredCompilation' : '0'],
162 // This is the basic set of scenarios
163 def static basicScenarios = [
171 // 'jitdiff', // jitdiff is currently disabled, until someone spends the effort to make it fully work
173 'gc_reliability_framework',
176 'crossgen_comparison',
179 def static allScenarios = basicScenarios + r2rStressScenarios.keySet() + jitStressModeScenarios.keySet()
181 // Valid PR trigger combinations.
182 def static prTriggeredValidInnerLoopCombos = [
200 'Windows_NT_BuildOnly': [
244 // A set of scenarios that are valid for arm/arm64 tests run on hardware. This is a map from valid scenario name
245 // to Tests.lst file categories to exclude.
247 // This list should contain a subset of the scenarios from `allScenarios`. Please keep this in the same order as that,
248 // and with the same values, with some commented out, for easier maintenance.
250 // Note that some scenarios that are commented out should be enabled, but haven't yet been.
252 def static validArmWindowsScenarios = [
262 // 'gc_reliability_framework'
264 // 'corefx_innerloop'
265 // 'crossgen_comparison'
269 'r2r_jitstress1_tiered',
270 'r2r_jitstress2_tiered',
271 'r2r_jitstressregs1',
272 'r2r_jitstressregs2',
273 'r2r_jitstressregs3',
274 'r2r_jitstressregs4',
275 'r2r_jitstressregs8',
276 'r2r_jitstressregs0x10',
277 'r2r_jitstressregs0x80',
278 'r2r_jitstressregs0x1000',
280 'r2r_jitforcerelocs',
282 'r2r_no_tiered_compilation',
285 'no_tiered_compilation',
286 'no_tiered_compilation_innerloop',
299 'jitstressregs0x1000',
300 'jitstress2_jitstressregs1',
301 'jitstress2_jitstressregs2',
302 'jitstress2_jitstressregs3',
303 'jitstress2_jitstressregs4',
304 'jitstress2_jitstressregs8',
305 'jitstress2_jitstressregs0x10',
306 'jitstress2_jitstressregs0x80',
307 'jitstress2_jitstressregs0x1000',
309 // 'jitsse2only' // Only relevant to xarch
310 'jitnosimd', // Only interesting on platforms where SIMD support exists.
311 // 'jitincompletehwintrinsic'
312 // 'jitx86hwintrinsicnoavx'
313 // 'jitx86hwintrinsicnoavx2'
314 // 'jitx86hwintrinsicnosimd'
315 // 'jitnox86hwintrinsic'
316 'corefx_baseline', // corefx tests don't use smarty
317 'corefx_minopts', // corefx tests don't use smarty
318 'corefx_tieredcompilation', // corefx tests don't use smarty
319 'corefx_jitstress1', // corefx tests don't use smarty
320 'corefx_jitstress2', // corefx tests don't use smarty
321 'corefx_jitstressregs1', // corefx tests don't use smarty
322 'corefx_jitstressregs2', // corefx tests don't use smarty
323 'corefx_jitstressregs3', // corefx tests don't use smarty
324 'corefx_jitstressregs4', // corefx tests don't use smarty
325 'corefx_jitstressregs8', // corefx tests don't use smarty
326 'corefx_jitstressregs0x10', // corefx tests don't use smarty
327 'corefx_jitstressregs0x80', // corefx tests don't use smarty
328 'corefx_jitstressregs0x1000', // corefx tests don't use smarty
333 'gcstress0xc_zapdisable',
334 'gcstress0xc_zapdisable_jitstress2',
335 'gcstress0xc_zapdisable_heapverify1',
336 'gcstress0xc_jitstress1',
337 'gcstress0xc_jitstress2',
338 'gcstress0xc_minopts_heapverify1',
341 // NOTE: the following scenarios are not defined in the 'allScenarios' list! Is this a bug?
344 'minopts_zapdisable',
345 'gcstress0x3_jitstress1',
346 'gcstress0x3_jitstress2',
347 'gcstress0x3_jitstressregs1',
348 'gcstress0x3_jitstressregs2',
349 'gcstress0x3_jitstressregs3',
350 'gcstress0x3_jitstressregs4',
351 'gcstress0x3_jitstressregs8',
352 'gcstress0x3_jitstressregs0x10',
353 'gcstress0x3_jitstressregs0x80',
354 'gcstress0x3_jitstressregs0x1000',
355 'gcstress0xc_jitstressregs1',
356 'gcstress0xc_jitstressregs2',
357 'gcstress0xc_jitstressregs3',
358 'gcstress0xc_jitstressregs4',
359 'gcstress0xc_jitstressregs8',
360 'gcstress0xc_jitstressregs0x10',
361 'gcstress0xc_jitstressregs0x80',
362 'gcstress0xc_jitstressregs0x1000'
365 def static validLinuxArmScenarios = [
375 // 'gc_reliability_framework'
377 // 'corefx_innerloop'
378 'crossgen_comparison',
382 'r2r_jitstress1_tiered',
383 'r2r_jitstress2_tiered',
384 'r2r_jitstressregs1',
385 'r2r_jitstressregs2',
386 'r2r_jitstressregs3',
387 'r2r_jitstressregs4',
388 'r2r_jitstressregs8',
389 'r2r_jitstressregs0x10',
390 'r2r_jitstressregs0x80',
391 'r2r_jitstressregs0x1000',
393 'r2r_jitforcerelocs',
395 'r2r_no_tiered_compilation',
398 'no_tiered_compilation',
399 'no_tiered_compilation_innerloop',
412 'jitstressregs0x1000',
413 'jitstress2_jitstressregs1',
414 'jitstress2_jitstressregs2',
415 'jitstress2_jitstressregs3',
416 'jitstress2_jitstressregs4',
417 'jitstress2_jitstressregs8',
418 'jitstress2_jitstressregs0x10',
419 'jitstress2_jitstressregs0x80',
420 'jitstress2_jitstressregs0x1000',
422 // 'jitsse2only' // Only relevant to xarch
423 // 'jitnosimd' // Only interesting on platforms where SIMD support exists.
424 // 'jitincompletehwintrinsic'
425 // 'jitx86hwintrinsicnoavx'
426 // 'jitx86hwintrinsicnoavx2'
427 // 'jitx86hwintrinsicnosimd'
428 // 'jitnox86hwintrinsic'
431 'corefx_tieredcompilation',
434 'corefx_jitstressregs1',
435 'corefx_jitstressregs2',
436 'corefx_jitstressregs3',
437 'corefx_jitstressregs4',
438 'corefx_jitstressregs8',
439 'corefx_jitstressregs0x10',
440 'corefx_jitstressregs0x80',
441 'corefx_jitstressregs0x1000',
446 'gcstress0xc_zapdisable',
447 'gcstress0xc_zapdisable_jitstress2',
448 'gcstress0xc_zapdisable_heapverify1',
449 'gcstress0xc_jitstress1',
450 'gcstress0xc_jitstress2',
451 'gcstress0xc_minopts_heapverify1'
454 def static validLinuxArm64Scenarios = [
464 // 'gc_reliability_framework'
466 // 'corefx_innerloop'
467 // 'crossgen_comparison'
471 'r2r_jitstress1_tiered',
472 'r2r_jitstress2_tiered',
473 'r2r_jitstressregs1',
474 'r2r_jitstressregs2',
475 'r2r_jitstressregs3',
476 'r2r_jitstressregs4',
477 'r2r_jitstressregs8',
478 'r2r_jitstressregs0x10',
479 'r2r_jitstressregs0x80',
480 'r2r_jitstressregs0x1000',
482 'r2r_jitforcerelocs',
484 'r2r_no_tiered_compilation',
487 'no_tiered_compilation',
488 'no_tiered_compilation_innerloop',
501 'jitstressregs0x1000',
502 'jitstress2_jitstressregs1',
503 'jitstress2_jitstressregs2',
504 'jitstress2_jitstressregs3',
505 'jitstress2_jitstressregs4',
506 'jitstress2_jitstressregs8',
507 'jitstress2_jitstressregs0x10',
508 'jitstress2_jitstressregs0x80',
509 'jitstress2_jitstressregs0x1000',
511 // 'jitsse2only' // Only relevant to xarch
512 'jitnosimd', // Only interesting on platforms where SIMD support exists.
513 // 'jitincompletehwintrinsic'
514 // 'jitx86hwintrinsicnoavx'
515 // 'jitx86hwintrinsicnoavx2'
516 // 'jitx86hwintrinsicnosimd'
517 // 'jitnox86hwintrinsic'
520 'corefx_tieredcompilation',
523 'corefx_jitstressregs1',
524 'corefx_jitstressregs2',
525 'corefx_jitstressregs3',
526 'corefx_jitstressregs4',
527 'corefx_jitstressregs8',
528 'corefx_jitstressregs0x10',
529 'corefx_jitstressregs0x80',
530 'corefx_jitstressregs0x1000',
535 'gcstress0xc_zapdisable',
536 'gcstress0xc_zapdisable_jitstress2',
537 'gcstress0xc_zapdisable_heapverify1',
538 'gcstress0xc_jitstress1',
539 'gcstress0xc_jitstress2',
540 'gcstress0xc_minopts_heapverify1'
543 def static configurationList = ['Debug', 'Checked', 'Release']
545 // This is the set of architectures
546 // Some of these are pseudo-architectures:
547 // armem -- ARM builds/runs using an emulator. Used for Tizen runs.
548 // x86_arm_altjit -- ARM runs on x86 using the ARM altjit
549 // x64_arm64_altjit -- ARM64 runs on x64 using the ARM64 altjit
550 def static architectureList = ['arm', 'armem', 'x86_arm_altjit', 'x64_arm64_altjit', 'arm64', 'x64', 'x86']
552 // This set of architectures that cross build on Windows and run on Windows ARM64 hardware.
553 def static armWindowsCrossArchitectureList = ['arm', 'arm64']
556 // **************************************************************
557 // Create some specific views
559 // These aren't using the Utilities.addStandardFolderView() function, because that creates
560 // views based on a single regular expression. These views will be generated by adding a
561 // specific set of jobs to them.
563 // Utilities.addStandardFolderView() also creates a lot of additional stuff around the
564 // view, like "Build Statistics", "Job Statistics", "Unstable Jobs". Until it is determined
565 // those are required, don't add them (which simplifies the view pages, as well).
566 // **************************************************************
569 def static MergeJobView = null
570 def static PeriodicJobView = null
571 def static ArchitectureViews = [:]
572 def static OSViews = [:]
575 // MergeJobView: include all jobs that execute when a PR change is merged.
576 Views.MergeJobView = listView('Merge') {
589 // PeriodicJobView: include all jobs that execute on a schedule
590 Views.PeriodicJobView = listView('Periodic') {
603 // Create a view for non-PR jobs for each architecture.
604 Constants.architectureList.each { architecture ->
605 Views.ArchitectureViews[architecture] = listView(architecture) {
619 // Create a view for non-PR jobs for each OS.
620 Constants.osList.each { os ->
621 // Don't create one for the special 'Windows_NT_BuildOnly'
622 if (os == 'Windows_NT_BuildOnly') {
625 Views.OSViews[os] = listView(os) {
639 def static addToMergeView(def job) {
640 Views.MergeJobView.with {
647 def static addToPeriodicView(def job) {
648 Views.PeriodicJobView.with {
655 def static addToViews(def job, def isFlowJob, def isPR, def architecture, def os, def configuration, def scenario) {
657 // No views want PR jobs currently.
661 // 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
662 // "top-level" jobs. Build only jobs are such jobs.
663 if (os == 'Windows_NT_BuildOnly') {
668 // For non-flow jobs, which ones are only used by flow jobs?
669 if ((architecture == 'arm') || (architecture == 'arm64')) {
670 if (isCoreFxScenario(scenario)) {
671 // We have corefx-specific scenario builds for each of the runs, but these are driven by flow jobs.
675 // We're left with the basic normal/innerloop builds. We might want to remove these from the views also, if desired.
676 // However, there are a few, like the Debug Build, that is build only, not "Build and Test", that we should leave.
680 // Add to architecture view.
681 Views.ArchitectureViews[architecture].with {
688 Views.OSViews[os].with {
695 def static addPeriodicTriggerHelper(def job, String cronString, boolean alwaysRuns = false) {
696 addToPeriodicView(job)
697 Utilities.addPeriodicTrigger(job, cronString, alwaysRuns)
700 def static addGithubPushTriggerHelper(def job) {
702 Utilities.addGithubPushTrigger(job)
706 def static setMachineAffinity(def job, def os, def architecture, def options = null) {
707 assert os instanceof String
708 assert architecture instanceof String
710 def armArches = ['arm', 'armem', 'arm64']
712 if (!(architecture in armArches)) {
713 assert options == null
714 Utilities.setMachineAffinity(job, os, 'latest-or-auto')
719 // This is an arm(64) job.
721 // There are several options.
725 // Arm32 (Build) -> latest-arm64
726 // |-> os == "Windows_NT" && (architecture == "arm") && options['use_arm64_build_machine'] == true
727 // Arm32 (Test) -> arm64-windows_nt
728 // |-> os == "Windows_NT" && (architecture == "arm") && options['use_arm64_build_machine'] == false
730 // Arm64 (Build) -> latest-arm64
731 // |-> os == "Windows_NT" && architecture == "arm64" && options['use_arm64_build_machine'] == true
732 // Arm64 (Test) -> arm64-windows_nt
733 // |-> os == "Windows_NT" && architecture == "arm64" && options['use_arm64_build_machine'] == false
737 // Arm32 emulator (Build, Test) -> arm-cross-latest
738 // |-> os == "Tizen" && (architecture == "armem")
740 // Arm32 hardware (Flow) -> Ubuntu 16.04 latest-or-auto (don't use limited arm hardware)
741 // |-> os == "Ubuntu" && (architecture == "arm") && options['is_flow_job'] == true
742 // Arm32 hardware (Build) -> Ubuntu 16.04 latest-or-auto
743 // |-> os == "Ubuntu" && (architecture == "arm") && options['is_build_job'] == true
744 // Arm32 hardware (Test) -> Helix ubuntu.1404.arm32.open queue
745 // |-> os == "Ubuntu" && (architecture == "arm")
747 // Arm64 (Build) -> arm64-cross-latest
748 // |-> os != "Windows_NT" && architecture == "arm64" && options['is_build_job'] == true
749 // Arm64 (Test) -> Helix Ubuntu.1604.Arm64.Open queue
750 // |-> os != "Windows_NT" && architecture == "arm64"
752 // Note: we are no longer using Jenkins tags "arm64-huge-page-size", "arm64-small-page-size".
753 // Support for Linux arm64 large page size has been removed for now, as it wasn't being used.
755 // Note: we are no longer using Jenkins tag 'latest-arm64' for arm/arm64 Windows build machines. Instead,
756 // we are using public VS2017 arm/arm64 tools in a VM from Helix.
758 // This has to be a arm arch
759 assert architecture in armArches
760 if (os == "Windows_NT") {
761 // arm32/arm64 Windows jobs share the same machines for now
762 def isBuild = options['use_arm64_build_machine'] == true
764 if (isBuild == true) {
766 label('Windows.10.Amd64.ClientRS4.DevEx.Open')
769 Utilities.setMachineAffinity(job, 'windows.10.arm64.open')
772 assert os != 'Windows_NT'
774 if (architecture == 'armem') {
775 // arm emulator (Tizen). Build and test on same machine,
778 Utilities.setMachineAffinity(job, 'Ubuntu', 'arm-cross-latest')
781 // arm/arm64 Ubuntu on hardware.
782 assert architecture == 'arm' || architecture == 'arm64'
783 def isFlow = (options != null) && (options['is_flow_job'] == true)
784 def isBuild = (options != null) && (options['is_build_job'] == true)
785 if (isFlow || isBuild) {
786 // arm/arm64 Ubuntu build machine. Build uses docker, so the actual host OS is not
787 // very important. Therefore, use latest or auto. Flow jobs don't need to use arm hardware.
788 Utilities.setMachineAffinity(job, 'Ubuntu16.04', 'latest-or-auto')
790 // arm/arm64 Ubuntu test machine. Specify the Helix queue name here.
791 if (architecture == 'arm64') {
792 assert os == 'Ubuntu16.04'
794 label('Ubuntu.1604.Arm64.Open')
798 assert os == 'Ubuntu'
800 label('ubuntu.1404.arm32.open')
808 // setJobMachineAffinity: compute the machine affinity options for a job,
809 // then set the job with those affinity options.
810 def static setJobMachineAffinity(def architecture, def os, def isBuildJob, def isTestJob, def isFlowJob, def job)
812 assert (isBuildJob && !isTestJob && !isFlowJob) ||
813 (!isBuildJob && isTestJob && !isFlowJob) ||
814 (!isBuildJob && !isTestJob && isFlowJob)
816 def affinityOptions = null
817 def affinityArchitecture = architecture
819 if (os == "Windows_NT") {
820 if (architecture in Constants.armWindowsCrossArchitectureList) {
822 affinityOptions = [ "use_arm64_build_machine" : true ]
823 } else if (isTestJob) {
824 affinityOptions = [ "use_arm64_build_machine" : false ]
825 } else if (isFlowJob) {
826 // For the flow jobs set the machine affinity as x64
827 affinityArchitecture = 'x64'
832 if ((architecture == 'arm64') || (architecture == 'arm')) {
834 affinityOptions = ['is_build_job': true]
835 } else if (isFlowJob) {
836 affinityOptions = ['is_flow_job': true]
841 setMachineAffinity(job, os, affinityArchitecture, affinityOptions)
844 def static isGCStressRelatedTesting(def scenario) {
845 // The 'r2r_gcstress15' scenario is a basic scenario.
846 // Detect it and make it a GCStress related.
847 if (scenario == 'r2r_gcstress15')
852 def gcStressTestEnvVars = [ 'COMPlus_GCStress', 'COMPlus_ZapDisable', 'COMPlus_HeapVerify']
853 def scenarioName = scenario.toLowerCase()
854 def isGCStressTesting = false
855 Constants.jitStressModeScenarios[scenario].each{ k, v ->
856 if (k in gcStressTestEnvVars) {
857 isGCStressTesting = true;
860 return isGCStressTesting
863 def static isCoreFxScenario(def scenario) {
864 def corefx_prefix = 'corefx_'
865 if (scenario.length() < corefx_prefix.length()) {
868 return scenario.substring(0,corefx_prefix.length()) == corefx_prefix
871 def static isR2RBaselineScenario(def scenario) {
872 return (scenario == 'r2r')
875 def static isR2RStressScenario(def scenario) {
876 return Constants.r2rStressScenarios.containsKey(scenario)
879 def static isR2RScenario(def scenario) {
880 return isR2RBaselineScenario(scenario) || isR2RStressScenario(scenario)
883 def static isJitStressScenario(def scenario) {
884 return Constants.jitStressModeScenarios.containsKey(scenario)
887 def static isLongGc(def scenario) {
888 return (scenario == 'longgc' || scenario == 'gcsimulator')
891 def static isJitDiff(def scenario) {
892 return (scenario == 'jitdiff')
895 def static isGcReliabilityFramework(def scenario) {
896 return (scenario == 'gc_reliability_framework')
899 def static isArmWindowsScenario(def scenario) {
900 return Constants.validArmWindowsScenarios.contains(scenario)
903 def static isValidPrTriggeredInnerLoopJob(os, architecture, configuration, isBuildOnly) {
904 if (isBuildOnly == true) {
905 os = 'Windows_NT_BuildOnly'
908 def validOsPrTriggerArchConfigs = Constants.prTriggeredValidInnerLoopCombos[os]
909 if (validOsPrTriggerArchConfigs != null) {
910 def validOsPrTriggerConfigs = validOsPrTriggerArchConfigs[architecture]
911 if (validOsPrTriggerConfigs != null) {
912 if (configuration in validOsPrTriggerConfigs) {
921 // This means the job builds and runs the 'innerloop' test set. This does not mean the job is
922 // scheduled with a default PR trigger despite the correlation being true at the moment.
923 def static isInnerloopTestScenario(def scenario) {
924 return (scenario == 'innerloop' || scenario == 'no_tiered_compilation_innerloop')
927 def static isCrossGenComparisonScenario(def scenario) {
928 return (scenario == 'crossgen_comparison')
931 def static shouldGenerateCrossGenComparisonJob(def os, def architecture, def configuration, def scenario) {
932 assert isCrossGenComparisonScenario(scenario)
933 return (os == 'Ubuntu' && architecture == 'arm' && (configuration == 'Checked' || configuration == 'Release'))
936 def static getFxBranch(def branch) {
937 def fxBranch = branch
938 // Map 'dev/unix_test_workflow' to 'master' so we can test CoreFX jobs in the CoreCLR dev/unix_test_workflow
939 // branch even though CoreFX doesn't have such a branch.
940 if (branch == 'dev/unix_test_workflow') {
946 def static setJobTimeout(newJob, isPR, architecture, configuration, scenario, isBuildOnly) {
947 // 2 hours (120 minutes) is the default timeout
950 if (!isInnerloopTestScenario(scenario)) {
951 // Pri-1 test builds take a long time (see calculateBuildCommands()). So up the Pri-1 build jobs timeout.
956 // Note that these can only increase, never decrease, the Pri-1 timeout possibly set above.
957 if (isGCStressRelatedTesting(scenario)) {
960 else if (isCoreFxScenario(scenario)) {
963 else if (isJitStressScenario(scenario)) {
966 else if (isR2RBaselineScenario(scenario)) {
969 else if (isLongGc(scenario)) {
972 else if (isJitDiff(scenario)) {
975 else if (isGcReliabilityFramework(scenario)) {
978 else if (architecture == 'armem' || architecture == 'arm64') {
982 if (architecture == 'arm') {
983 // ARM32 machines are particularly slow.
988 if (configuration == 'Debug') {
989 // Debug runs can be very slow. Add an hour.
993 if (architecture == 'x86_arm_altjit' || architecture == 'x64_arm64_altjit') {
994 // AltJit runs compile all methods twice.
998 // If we've changed the timeout from the default, set it in the job.
1000 if (timeout != 120) {
1001 Utilities.setJobTimeout(newJob, timeout)
1005 def static getJobFolder(def scenario) {
1006 if (isJitStressScenario(scenario) || isR2RStressScenario(scenario)) {
1009 if (scenario == 'illink') {
1015 def static getStressModeDisplayName(def scenario) {
1017 Constants.jitStressModeScenarios[scenario].each{ k, v ->
1018 def prefixLength = 'COMPlus_'.length()
1019 if (k.length() >= prefixLength) {
1020 def modeName = k.substring(prefixLength, k.length())
1021 if (displayStr != '') {
1022 // Separate multiple variables with a space.
1025 displayStr += modeName + '=' + v
1029 if (isCoreFxScenario(scenario)) {
1030 displayStr = ('CoreFx ' + displayStr).trim()
1036 def static getR2RDisplayName(def scenario) {
1037 // Assume the scenario name is one from the r2rStressScenarios dict, and remove its "r2r_" prefix.
1038 def displayStr = scenario
1039 def prefixLength = 'r2r_'.length()
1040 if (displayStr.length() >= prefixLength) {
1041 displayStr = "R2R " + displayStr.substring(prefixLength, displayStr.length())
1042 } else if (scenario == 'r2r') {
1048 def static getScenarioDisplayString(def scenario) {
1051 return "Innerloop Build and Test"
1053 case 'no_tiered_compilation_innerloop':
1054 def displayStr = getStressModeDisplayName(scenario)
1055 return "Innerloop Build and Test (Jit - ${displayStr})"
1057 case 'corefx_innerloop':
1058 return "CoreFX Tests"
1061 return "Build and Test"
1064 return "Jit Diff Build and Test"
1067 return "IL RoundTrip Build and Test"
1070 return "Long-Running GC Build & Test"
1073 return "GC Simulator"
1075 case 'standalone_gc':
1076 return "Standalone GC"
1078 case 'gc_reliability_framework':
1079 return "GC Reliability Framework"
1085 if (isJitStressScenario(scenario)) {
1086 def displayStr = getStressModeDisplayName(scenario)
1087 return "Build and Test (Jit - ${displayStr})"
1089 else if (isR2RScenario(scenario)) {
1090 def displayStr = getR2RDisplayName(scenario)
1091 return "${displayStr} Build and Test"
1094 return "${scenario}"
1099 println("Unknown scenario: ${scenario}");
1104 // Functions to create an environment script.
1105 // envScriptCreate -- initialize the script (call first)
1106 // envScriptFinalize -- finalize the script (call last)
1107 // envScriptSetStressModeVariables -- set stress mode variables in the env script
1108 // envScriptAppendExistingScript -- append an existing script to the generated script
1110 // Each script returns a string of commands. Concatenate all the strings together before
1111 // adding them to the builds commands, to make sure they get executed as one Jenkins script.
1114 // Initialize the environment setting script.
1115 def static envScriptCreate(def os, def stepScriptLocation) {
1117 if (os == 'Windows_NT') {
1118 stepScript += "echo Creating TestEnv script\r\n"
1119 stepScript += "if exist ${stepScriptLocation} del ${stepScriptLocation}\r\n"
1121 // Create at least an empty script.
1122 stepScript += "echo. > ${stepScriptLocation}\r\n"
1125 stepScript += "echo Creating environment setting script\n"
1126 stepScript += "echo \\#\\!/usr/bin/env bash > ${stepScriptLocation}\n"
1132 // Generates the string for setting stress mode variables.
1133 def static envScriptSetStressModeVariables(def os, def stressModeVars, def stepScriptLocation) {
1135 if (os == 'Windows_NT') {
1136 stressModeVars.each{ k, v ->
1137 // Write out what we are writing to the script file
1138 stepScript += "echo Setting ${k}=${v}\r\n"
1139 // Write out the set itself to the script file`
1140 stepScript += "echo set ${k}=${v} >> ${stepScriptLocation}\r\n"
1144 stressModeVars.each{ k, v ->
1145 // Write out what we are writing to the script file
1146 stepScript += "echo Setting ${k}=${v}\n"
1147 // Write out the set itself to the script file`
1148 stepScript += "echo export ${k}=${v} >> ${stepScriptLocation}\n"
1155 // Append an existing script to an environment script.
1156 // Returns string of commands to do this.
1157 def static envScriptAppendExistingScript(def os, def appendScript, def stepScriptLocation) {
1158 assert (os == 'Windows_NT')
1161 stepScript += "echo Appending ${appendScript} to ${stepScriptLocation}\r\n"
1162 stepScript += "type ${appendScript} >> ${stepScriptLocation}\r\n"
1167 // Finalize an environment setting script.
1168 // Returns string of commands to do this.
1169 def static envScriptFinalize(def os, def stepScriptLocation) {
1172 if (os == 'Windows_NT') {
1173 // Display the resulting script. This is useful when looking at the output log file.
1174 stepScript += "echo Display the total script ${stepScriptLocation}\r\n"
1175 stepScript += "type ${stepScriptLocation}\r\n"
1178 stepScript += "chmod +x ${stepScriptLocation}\n"
1184 def static isNeedDocker(def architecture, def os, def isBuild) {
1186 if (architecture == 'x86' && os == 'Ubuntu') {
1189 else if (architecture == 'armem') {
1192 else if (architecture == 'arm') {
1193 if (os == 'Ubuntu') {
1197 else if (architecture == 'arm64') {
1198 if (os == 'Ubuntu16.04') {
1204 if (architecture == 'x86' && os == 'Ubuntu') {
1211 def static getDockerImageName(def architecture, def os, def isBuild) {
1212 // We must change some docker private images to official later
1214 if (architecture == 'x86' && os == 'Ubuntu') {
1215 return "hseok82/dotnet-buildtools-prereqs:ubuntu-16.04-crossx86-ef0ac75-20175511035548"
1217 else if (architecture == 'armem') {
1218 if (os == 'Tizen') {
1219 return "tizendotnet/dotnet-buildtools-prereqs:ubuntu-16.04-cross-e435274-20180426002255-tizen-rootfs-5.0m1"
1222 else if (architecture == 'arm') {
1223 if (os == 'Ubuntu') {
1224 return "microsoft/dotnet-buildtools-prereqs:ubuntu-14.04-cross-e435274-20180426002420"
1227 else if (architecture == 'arm64') {
1228 if (os == 'Ubuntu16.04') {
1229 return "microsoft/dotnet-buildtools-prereqs:ubuntu-16.04-cross-arm64-a3ae44b-20180315221921"
1234 if (architecture == 'x86' && os == 'Ubuntu') {
1235 return "hseok82/dotnet-buildtools-prereqs:ubuntu1604_x86_test"
1238 println("Unknown architecture to use docker: ${architecture} ${os}");
1243 // We have a limited amount of some hardware. For these, scale back the periodic testing we do,
1244 // and only allowing using this hardware in some specific branches.
1245 def static jobRequiresLimitedHardware(def architecture, def os) {
1246 if (architecture == 'arm') {
1247 // arm Windows and Linux hardware is limited.
1250 else if (architecture == 'arm64') {
1251 // arm64 Windows and Linux hardware is limited.
1259 // Calculates the name of the build job based on some typical parameters.
1261 def static getJobName(def configuration, def architecture, def os, def scenario, def isBuildOnly) {
1262 // If the architecture is x64, do not add that info into the build name.
1263 // Need to change around some systems and other builds to pick up the right builds
1266 def suffix = scenario != 'normal' ? "_${scenario}" : '';
1271 switch (architecture) {
1273 if (scenario == 'normal') {
1274 // For now we leave x64 off of the name for compatibility with other jobs
1275 baseName = configuration.toLowerCase() + '_' + os.toLowerCase()
1277 else if (scenario == 'formatting') {
1278 // we don't care about the configuration for the formatting job. It runs all configs
1279 baseName = architecture.toLowerCase() + '_' + os.toLowerCase()
1282 baseName = architecture.toLowerCase() + '_' + configuration.toLowerCase() + '_' + os.toLowerCase()
1286 // These are cross builds
1287 assert os == 'Tizen'
1288 baseName = 'armel_cross_' + configuration.toLowerCase() + '_' + os.toLowerCase()
1292 // These are cross builds
1293 baseName = architecture.toLowerCase() + '_cross_' + configuration.toLowerCase() + '_' + os.toLowerCase()
1296 case 'x86_arm_altjit':
1297 case 'x64_arm64_altjit':
1298 baseName = architecture.toLowerCase() + '_' + configuration.toLowerCase() + '_' + os.toLowerCase()
1301 println("Unknown architecture: ${architecture}");
1306 return baseName + suffix
1309 def static addNonPRTriggers(def job, def branch, def isPR, def architecture, def os, def configuration, def scenario, def isFlowJob, def isWindowsBuildOnlyJob, def bidailyCrossList) {
1310 def isNormalOrInnerloop = (scenario == "normal" || scenario == "innerloop")
1312 // Limited hardware is restricted for non-PR triggers to certain branches.
1313 if (jobRequiresLimitedHardware(architecture, os) && (!(branch in Constants.LimitedHardwareBranches))) {
1317 // Ubuntu x86 CI jobs are failing. Disable non-PR triggered jobs to avoid these constant failures
1318 // until this is fixed. Tracked by https://github.com/dotnet/coreclr/issues/19003.
1319 if (architecture == 'x86' && os == 'Ubuntu') {
1325 case 'crossgen_comparison':
1326 if (isFlowJob && os == 'Ubuntu' && architecture == 'arm' && (configuration == 'Checked' || configuration == 'Release')) {
1327 addPeriodicTriggerHelper(job, '@daily')
1331 case 'pmi_asm_diffs':
1332 // No non-PR triggers for now.
1336 switch (architecture) {
1339 if (isFlowJob && architecture == 'x86' && os == 'Ubuntu') {
1340 addPeriodicTriggerHelper(job, '@daily')
1342 else if (isFlowJob || os == 'Windows_NT' || (architecture == 'x64' && !(os in Constants.crossList))) {
1343 addGithubPushTriggerHelper(job)
1347 if (os == 'Windows_NT') {
1348 if (isFlowJob || (isNormalOrInnerloop && (configuration == 'Debug'))) {
1349 // We would normally want a per-push trigger, but with limited hardware we can't keep up.
1350 // Do the builds daily.
1351 addPeriodicTriggerHelper(job, '@daily')
1355 // Only the flow jobs get push triggers; the build and test jobs are triggered by the flow job.
1357 addPeriodicTriggerHelper(job, '@daily')
1362 if (os == 'Windows_NT') {
1363 if (isFlowJob || (isNormalOrInnerloop && (configuration == 'Debug'))) {
1364 // We would normally want a push trigger, but with limited hardware we can't keep up.
1365 // Do the builds daily.
1366 addPeriodicTriggerHelper(job, '@daily')
1370 assert os == 'Ubuntu'
1371 // Only the flow jobs get push triggers; the build and test jobs are triggered by the flow job.
1373 // Currently no push triggers, with limited arm Linux hardware.
1374 // TODO: If we have enough machine capacity, add some arm Linux push triggers.
1375 addPeriodicTriggerHelper(job, '@daily')
1380 addGithubPushTriggerHelper(job)
1382 case 'x86_arm_altjit':
1383 case 'x64_arm64_altjit':
1384 // Only do altjit push triggers for Checked; don't waste time on Debug or Release.
1385 if (configuration == 'Checked') {
1386 addGithubPushTriggerHelper(job)
1390 println("Unknown architecture: ${architecture}");
1396 assert !(os in bidailyCrossList)
1397 // r2r gets a push trigger for checked/release
1398 if (configuration == 'Checked' || configuration == 'Release') {
1399 if (architecture == 'x64' && os != 'OSX10.12') {
1400 //Flow jobs should be Windows, Ubuntu, OSX0.12, or CentOS
1401 if (isFlowJob || os == 'Windows_NT') {
1402 addGithubPushTriggerHelper(job)
1404 // OSX10.12 r2r jobs should only run every 12 hours, not daily.
1405 } else if (architecture == 'x64' && os == 'OSX10.12'){
1407 addPeriodicTriggerHelper(job, 'H H/12 * * *')
1410 // For x86, only add per-commit jobs for Windows
1411 else if (architecture == 'x86') {
1412 if (os == 'Windows_NT') {
1413 addGithubPushTriggerHelper(job)
1416 // arm r2r jobs should only run weekly.
1417 else if (architecture == 'arm') {
1419 addPeriodicTriggerHelper(job, '@weekly')
1422 // arm64 r2r jobs should only run weekly.
1423 else if (architecture == 'arm64') {
1425 addPeriodicTriggerHelper(job, '@weekly')
1430 case 'r2r_jitstress1':
1431 case 'r2r_jitstress2':
1432 case 'r2r_jitstress1_tiered':
1433 case 'r2r_jitstress2_tiered':
1434 case 'r2r_jitstressregs1':
1435 case 'r2r_jitstressregs2':
1436 case 'r2r_jitstressregs3':
1437 case 'r2r_jitstressregs4':
1438 case 'r2r_jitstressregs8':
1439 case 'r2r_jitstressregs0x10':
1440 case 'r2r_jitstressregs0x80':
1441 case 'r2r_jitstressregs0x1000':
1442 case 'r2r_jitminopts':
1443 case 'r2r_jitforcerelocs':
1444 case 'r2r_gcstress15':
1445 case 'r2r_no_tiered_compilation':
1446 assert !(os in bidailyCrossList)
1448 // GCStress=C is currently not supported on OS X
1449 if (os == 'OSX10.12' && isGCStressRelatedTesting(scenario)) {
1453 if (configuration == 'Checked' || configuration == 'Release') {
1454 if (architecture == 'x64') {
1455 //Flow jobs should be Windows, Ubuntu, OSX10.12, or CentOS
1456 if (isFlowJob || os == 'Windows_NT') {
1457 addPeriodicTriggerHelper(job, 'H H * * 3,6') // some time every Wednesday and Saturday
1460 // For x86, only add periodic jobs for Windows
1461 else if (architecture == 'x86') {
1462 if (os == 'Windows_NT') {
1463 addPeriodicTriggerHelper(job, 'H H * * 3,6') // some time every Wednesday and Saturday
1466 else if (architecture == 'arm') {
1468 addPeriodicTriggerHelper(job, '@weekly')
1471 else if (architecture == 'arm64') {
1473 addPeriodicTriggerHelper(job, '@weekly')
1479 assert (os == 'Ubuntu' || os == 'Windows_NT' || os == 'OSX10.12')
1480 assert configuration == 'Release'
1481 assert architecture == 'x64'
1482 addPeriodicTriggerHelper(job, '@daily')
1483 // TODO: Add once external email sending is available again
1484 // addEmailPublisher(job, 'dotnetgctests@microsoft.com')
1487 assert (os == 'Ubuntu' || os == 'Windows_NT' || os == 'OSX10.12')
1488 assert configuration == 'Release'
1489 assert architecture == 'x64'
1490 addPeriodicTriggerHelper(job, 'H H * * 3,6') // some time every Wednesday and Saturday
1491 // TODO: Add once external email sending is available again
1492 // addEmailPublisher(job, 'dotnetgctests@microsoft.com')
1494 case 'standalone_gc':
1495 assert (os == 'Ubuntu' || os == 'Windows_NT' || os == 'OSX10.12')
1496 assert (configuration == 'Release' || configuration == 'Checked')
1497 // TODO: Add once external email sending is available again
1498 // addEmailPublisher(job, 'dotnetgctests@microsoft.com')
1499 addPeriodicTriggerHelper(job, '@daily')
1501 case 'gc_reliability_framework':
1502 assert (os == 'Ubuntu' || os == 'Windows_NT' || os == 'OSX10.12')
1503 assert (configuration == 'Release' || configuration == 'Checked')
1504 // Only triggered by phrase.
1507 assert !(os in bidailyCrossList)
1508 // ILASM/ILDASM roundtrip one gets a daily build, and only for release
1509 if (architecture == 'x64' && configuration == 'Release') {
1510 if (isFlowJob || os == 'Windows_NT') {
1511 addPeriodicTriggerHelper(job, '@daily')
1516 assert (os == 'Ubuntu' || os == 'Windows_NT' || os == 'OSX10.12')
1517 assert configuration == 'Checked'
1518 assert (architecture == 'x64' || architecture == 'x86')
1519 addGithubPushTriggerHelper(job)
1522 assert (os == 'Windows_NT' || os == "Ubuntu")
1523 assert architecture == 'x64'
1524 addGithubPushTriggerHelper(job)
1526 case 'jitstressregs1':
1527 case 'jitstressregs2':
1528 case 'jitstressregs3':
1529 case 'jitstressregs4':
1530 case 'jitstressregs8':
1531 case 'jitstressregs0x10':
1532 case 'jitstressregs0x80':
1533 case 'jitstressregs0x1000':
1535 case 'tieredcompilation':
1536 case 'no_tiered_compilation':
1540 case 'jitstress1_tiered':
1541 case 'jitstress2_tiered':
1542 case 'jitstress2_jitstressregs1':
1543 case 'jitstress2_jitstressregs2':
1544 case 'jitstress2_jitstressregs3':
1545 case 'jitstress2_jitstressregs4':
1546 case 'jitstress2_jitstressregs8':
1547 case 'jitstress2_jitstressregs0x10':
1548 case 'jitstress2_jitstressregs0x80':
1549 case 'jitstress2_jitstressregs0x1000':
1550 case 'tailcallstress':
1553 case 'jitnox86hwintrinsic':
1554 case 'jitincompletehwintrinsic':
1555 case 'jitx86hwintrinsicnoavx':
1556 case 'jitx86hwintrinsicnoavx2':
1557 case 'jitx86hwintrinsicnosimd':
1558 case 'corefx_baseline':
1559 case 'corefx_minopts':
1560 case 'corefx_tieredcompilation':
1561 case 'corefx_jitstress1':
1562 case 'corefx_jitstress2':
1563 case 'corefx_jitstressregs1':
1564 case 'corefx_jitstressregs2':
1565 case 'corefx_jitstressregs3':
1566 case 'corefx_jitstressregs4':
1567 case 'corefx_jitstressregs8':
1568 case 'corefx_jitstressregs0x10':
1569 case 'corefx_jitstressregs0x80':
1570 case 'corefx_jitstressregs0x1000':
1572 if (os == 'CentOS7.1') {
1575 if (os in bidailyCrossList) {
1578 // ARM corefx testing uses non-flow jobs to provide the configuration-specific
1579 // build for the flow job. We don't need cron jobs for these. Note that the
1580 // Windows ARM jobs depend on a Windows "build only" job that exits the trigger
1581 // function very early, so only non-Windows gets here.
1582 if ((architecture == 'arm') && isCoreFxScenario(scenario) && !isFlowJob) {
1585 if ((architecture == 'arm64') && isCoreFxScenario(scenario) && !isFlowJob) {
1588 if (jobRequiresLimitedHardware(architecture, os)) {
1589 if ((architecture == 'arm64') && (os == 'Ubuntu16.04')) {
1590 // These jobs are very fast on Linux/arm64 hardware, so run them daily.
1591 addPeriodicTriggerHelper(job, '@daily')
1594 addPeriodicTriggerHelper(job, '@weekly')
1598 addPeriodicTriggerHelper(job, '@daily')
1603 if (os == 'CentOS7.1') {
1606 if (os in bidailyCrossList) {
1609 addPeriodicTriggerHelper(job, '@weekly')
1612 case 'gcstress0xc_zapdisable':
1613 case 'gcstress0xc_zapdisable_jitstress2':
1614 case 'gcstress0xc_zapdisable_heapverify1':
1615 case 'gcstress0xc_jitstress1':
1616 case 'gcstress0xc_jitstress2':
1617 case 'gcstress0xc_minopts_heapverify1':
1618 if (os == 'OSX10.12') {
1619 // GCStress=C is currently not supported on OS X
1622 if (os == 'CentOS7.1') {
1625 if (os in bidailyCrossList) {
1628 addPeriodicTriggerHelper(job, '@weekly')
1632 // Testing on other operating systems TBD
1633 assert (os == 'Windows_NT' || os == 'Ubuntu')
1634 if (architecture == 'x64' || architecture == 'x86') {
1635 if (configuration == 'Checked') {
1636 addPeriodicTriggerHelper(job, '@daily')
1642 println("Unknown scenario: ${scenario}");
1649 // **************************
1650 // Define the basic inner loop builds for PR and commit. This is basically just the set
1651 // of coreclr builds over linux/osx 10.12/windows and debug/release/checked. In addition, the windows
1652 // builds will do a couple extra steps.
1653 // **************************
1655 // Adds a trigger for the PR build if one is needed. If isFlowJob is true, then this is the
1656 // flow job that rolls up the build and test for non-windows OS's. // If the job is a windows build only job,
1657 // it's just used for internal builds
1658 // If you add a job with a trigger phrase, please add that phrase to coreclr/Documentation/project-docs/ci-trigger-phrases.md
1659 def static addTriggers(def job, def branch, def isPR, def architecture, def os, def configuration, def scenario, def isFlowJob, def isWindowsBuildOnlyJob) {
1660 def isNormalOrInnerloop = (scenario == "normal" || scenario == "innerloop")
1662 if (isWindowsBuildOnlyJob) {
1666 def bidailyCrossList = ['RHEL7.2', 'Debian8.4']
1667 // Non pull request builds.
1669 addNonPRTriggers(job, branch, isPR, architecture, os, configuration, scenario, isFlowJob, isWindowsBuildOnlyJob, bidailyCrossList)
1694 // Pull request builds. Generally these fall into two categories: default triggers and on-demand triggers
1695 // We generally only have a distinct set of default triggers but a bunch of on-demand ones.
1697 def contextString = ""
1698 def triggerString = ""
1699 def needsTrigger = true
1700 def isDefaultTrigger = false
1701 def isArm64PrivateJob = false
1702 def scenarioString = ""
1704 // Set up default context string and trigger phrases. This is overridden in places, sometimes just to keep
1705 // the existing non-standard descriptions and phrases. In some cases, the scenarios are asymmetric, as for
1706 // some jobs where the Debug configuration just does builds, no tests.
1708 // Some configurations, like arm32/arm64, always use the exact scenario name as part of the context string.
1709 // This makes it possible to copy/paste the displayed context string as "@dotnet-bot test <context-string>"
1710 // to invoke the trigger. Any "fancy" context string makes that impossible, requiring the user to either
1711 // remember the mapping from context string to trigger string, or use "@dotnet-bot help" to look it up.
1713 if (architecture == 'armem') {
1714 assert os == 'Tizen'
1715 architecture = 'armel'
1718 switch (architecture) {
1719 case 'x64_arm64_altjit':
1720 case 'x86_arm_altjit':
1721 // TODO: for consistency, add "Build and Test" at end.
1722 contextString = "${os} ${architecture} ${configuration} ${scenario}"
1723 triggerString = "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*"
1729 contextString = "${os} ${architecture} Cross ${configuration}"
1730 triggerString = "(?i).*test\\W+${os}\\W+${architecture}\\W+Cross\\W+${configuration}"
1732 if (scenario == 'innerloop') {
1733 contextString += " Innerloop"
1734 triggerString += "\\W+Innerloop"
1737 contextString += " ${scenario}"
1738 triggerString += "\\W+${scenario}"
1741 if (scenario == 'pmi_asm_diffs') {
1742 // Don't add the "Build and Test" part
1744 else if (configuration == 'Debug') {
1745 contextString += " Build"
1746 triggerString += "\\W+Build"
1749 contextString += " Build and Test"
1750 triggerString += "\\W+Build and Test"
1753 triggerString += ".*"
1757 scenarioString = getScenarioDisplayString(scenario)
1758 contextString = "${os} ${architecture} ${configuration} ${scenarioString}"
1759 triggerString = "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}"
1763 triggerString += "\\W+Build and Test.*"
1766 case 'corefx_innerloop': // maintain this asymmetry
1767 triggerString += "\\W+CoreFX Tests.*"
1771 triggerString += "\\W+${scenario}.*"
1775 triggerString += ".*"
1779 // Now determine what kind of trigger this job needs, if any. Any job should be triggerable, except for
1780 // non-flow jobs that are only used as part of flow jobs.
1782 switch (architecture) {
1783 case 'x64': // editor brace matching: {
1784 if (scenario == 'formatting') {
1785 assert configuration == 'Checked'
1786 if (os == 'Windows_NT' || os == 'Ubuntu') {
1787 isDefaultTrigger = true
1788 contextString = "${os} ${architecture} Formatting"
1794 // OpenSUSE, Debian & RedHat get trigger phrases for pri 0 build, and pri 1 build & test
1797 if (scenario == 'innerloop') {
1799 contextString = "${os} ${architecture} ${configuration} Innerloop Build"
1800 isDefaultTrigger = true
1810 assert scenario != 'innerloop'
1811 contextString = "${os} ${architecture} ${configuration} Build"
1812 triggerString = "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+Build.*"
1816 if (scenario == 'illink') {
1819 else if (scenario == 'corefx_innerloop') {
1820 if (configuration == 'Checked') {
1821 isDefaultTrigger = true
1829 // Triggers on the non-flow jobs aren't necessary here
1830 // Corefx testing uses non-flow jobs.
1831 if (!isFlowJob && !isCoreFxScenario(scenario)) {
1832 needsTrigger = false
1837 isDefaultTrigger = true
1840 case 'no_tiered_compilation_innerloop':
1841 if (os == 'Ubuntu') {
1842 isDefaultTrigger = true
1854 // CentOS uses checked for default PR tests while debug is build only
1855 if (configuration == 'Debug') {
1856 isDefaultTrigger = true
1857 contextString = "${os} ${architecture} ${configuration} Innerloop Build"
1861 // Make sure this is a flow job to get build and test.
1863 needsTrigger = false
1867 if (configuration == 'Checked') {
1868 assert job.name.contains("flow")
1869 isDefaultTrigger = true
1870 contextString = "${os} ${architecture} ${configuration} Innerloop Build and Test"
1875 // Make sure this is a flow job to get build and test.
1877 needsTrigger = false
1890 case 'no_tiered_compilation_innerloop':
1891 isDefaultTrigger = true
1894 case 'corefx_innerloop':
1895 if (configuration == 'Checked' || configuration == 'Release') {
1896 isDefaultTrigger = true
1906 println("Unknown os: ${os}");
1913 // editor brace matching: }
1915 case 'armel': // editor brace matching: {
1918 azureVMAgentPostBuildAction {
1919 agentPostBuildAction('Delete agent if the build was not successful (when idle).')
1926 if (scenario == 'innerloop') {
1927 if (configuration == 'Checked') {
1928 isDefaultTrigger = true
1935 // editor brace matching: }
1938 case 'arm64': // editor brace matching: {
1944 // Triggers on the non-flow jobs aren't necessary
1946 needsTrigger = false
1952 case 'no_tiered_compilation_innerloop':
1953 if (configuration == 'Checked') {
1954 isDefaultTrigger = true
1957 case 'crossgen_comparison':
1958 if (os == 'Ubuntu' && architecture == 'arm' && (configuration == 'Checked' || configuration == 'Release')) {
1959 isDefaultTrigger = true
1966 assert isArmWindowsScenario(scenario)
1968 // For Debug normal/innerloop scenario, we don't do test runs, so we don't use flow jobs. That means we need a trigger for
1969 // the non-flow Build job. All others need a trigger on the flow job.
1970 def needsFlowJobTrigger = !(isNormalOrInnerloop && (configuration == 'Debug'))
1971 if (isFlowJob != needsFlowJobTrigger) {
1972 needsTrigger = false
1978 if (configuration == 'Debug') {
1979 // Add default PR trigger for Windows arm64 Debug builds. This is a build only -- no tests are run --
1980 // so the private test hardware is not used. Thus, it can be run by all users, not just arm64Users.
1981 // People in arm64Users will get both this and the Checked Build and Test job.
1982 isDefaultTrigger = true
1983 } else if (configuration == 'Checked') {
1984 isDefaultTrigger = true
1985 isArm64PrivateJob = true
1989 isArm64PrivateJob = true
1994 println("NYI os: ${os}");
2000 // editor brace matching: }
2001 case 'x86': // editor brace matching: {
2002 assert ((os == 'Windows_NT') || ((os == 'Ubuntu') && isNormalOrInnerloop))
2003 if (os == 'Ubuntu') {
2004 // Triggers on the non-flow jobs aren't necessary here
2006 needsTrigger = false
2010 // on-demand only for ubuntu x86
2011 contextString = "${os} ${architecture} ${configuration} Build"
2012 triggerString = "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}.*"
2017 case 'no_tiered_compilation_innerloop':
2018 isDefaultTrigger = true
2025 // editor brace matching: }
2026 case 'x64_arm64_altjit':
2027 case 'x86_arm_altjit':
2028 // Everything default
2032 println("Unknown architecture: ${architecture}");
2038 if (isArm64PrivateJob) {
2039 if (isDefaultTrigger) {
2040 Utilities.addDefaultPrivateGithubPRTriggerForBranch(job, branch, contextString, null, arm64Users)
2043 Utilities.addPrivateGithubPRTriggerForBranch(job, branch, contextString, triggerString, null, arm64Users)
2047 if (isDefaultTrigger) {
2048 Utilities.addGithubPRTriggerForBranch(job, branch, contextString)
2051 Utilities.addGithubPRTriggerForBranch(job, branch, contextString, triggerString)
2057 def static calculateBuildCommands(def newJob, def scenario, def branch, def isPR, def architecture, def configuration, def os, def isBuildOnly) {
2058 def buildCommands = []
2059 def osGroup = getOSGroup(os)
2060 def lowerConfiguration = configuration.toLowerCase()
2062 // Which set of tests to build? Innerloop tests build Pri-0.
2063 // Currently, we only generate asm diffs on Pri-0 tests, if we generate asm diffs on tests at all.
2064 // CoreFX testing skipts building tests altogether (done below).
2065 // All other scenarios build Pri-1 tests.
2067 if (isInnerloopTestScenario(scenario)) {
2071 def doCoreFxTesting = isCoreFxScenario(scenario)
2073 def buildCoreclrTests = true
2074 if (doCoreFxTesting || (scenario == 'pmi_asm_diffs')) {
2075 // These scenarios don't need the coreclr tests build.
2076 buildCoreclrTests = false
2079 // Calculate the build steps, archival, and xunit results
2081 case 'Windows_NT': // editor brace matching: {
2082 switch (architecture) {
2085 case 'x86_arm_altjit':
2086 case 'x64_arm64_altjit':
2087 def arch = architecture
2089 if (architecture == 'x86_arm_altjit') {
2092 else if (architecture == 'x64_arm64_altjit') {
2096 if (scenario == 'formatting') {
2097 buildCommands += "python -u tests\\scripts\\format.py -c %WORKSPACE% -o Windows_NT -a ${arch}"
2098 Utilities.addArchival(newJob, "format.patch", "", true, false)
2102 if (scenario == 'illink') {
2103 buildCommands += "tests\\scripts\\build_illink.cmd clone ${arch}"
2106 // If it is a release build for Windows, ensure PGO is used, else fail the build.
2107 if ((lowerConfiguration == 'release') &&
2108 (scenario in Constants.basicScenarios) &&
2109 (architecture != 'x86_arm_altjit') &&
2110 (architecture != 'x64_arm64_altjit')) {
2112 buildOpts += ' -enforcepgo'
2115 if (buildCoreclrTests) {
2116 buildOpts += " -priority=${priority}"
2118 buildOpts += ' skiptests';
2121 // Set __TestIntermediateDir to something short. If __TestIntermediateDir is already set, build-test.cmd will
2122 // output test binaries to that directory. If it is not set, the binaries are sent to a default directory whose name is about
2123 // 35 characters long.
2125 buildCommands += "set __TestIntermediateDir=int&&build.cmd ${lowerConfiguration} ${arch} ${buildOpts}"
2127 if (scenario == 'pmi_asm_diffs') {
2128 // Now, generate the layout. We don't have any tests, so we need to do some annoying magic before calling runtest.cmd.
2129 buildCommands += "run.cmd build -Project=\"tests\\build.proj\" -BuildOS=Windows_NT -BuildType=${lowerConfiguration} -BuildArch=${arch} -BatchRestorePackages"
2130 buildCommands += "tests\\runtest.cmd ${lowerConfiguration} ${arch} GenerateLayoutOnly"
2132 // TODO: Add -target_branch and -commit_hash arguments based on GitHub variables.
2133 buildCommands += "python -u %WORKSPACE%\\tests\\scripts\\run-pmi-diffs.py -arch ${arch} -ci_arch ${architecture} -build_type ${configuration}"
2136 buildCommands += "powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('_\\_asm', '.\\dasm.${os}.${architecture}.${configuration}.zip')\"";
2139 Utilities.addArchival(newJob, "dasm.${os}.${architecture}.${configuration}.zip")
2144 def runtestArguments = ''
2145 def testOpts = 'collectdumps'
2147 if (isR2RScenario(scenario)) {
2149 // If this is a ReadyToRun scenario, pass 'crossgen' or 'crossgenaltjit'
2150 // to cause framework assemblies to be crossgen'ed. Pass 'runcrossgentests'
2151 // to cause the tests to be crossgen'ed.
2153 if ((architecture == 'x86_arm_altjit') || (architecture == 'x64_arm64_altjit')) {
2154 testOpts += ' crossgenaltjit protononjit.dll'
2156 testOpts += ' crossgen'
2159 testOpts += ' runcrossgentests'
2161 else if (scenario == 'jitdiff') {
2162 testOpts += ' jitdisasm crossgen'
2164 else if (scenario == 'ilrt') {
2165 testOpts += ' ilasmroundtrip'
2167 else if (isLongGc(scenario)) {
2168 testOpts += " ${scenario} sequential"
2170 else if (scenario == 'standalone_gc') {
2171 testOpts += ' gcname clrgc.dll'
2173 else if (scenario == 'illink') {
2174 testOpts += " link %WORKSPACE%\\linker\\linker\\bin\\netcore_Release\\netcoreapp2.0\\win10-${arch}\\publish\\illink.exe"
2177 // Default per-test timeout is 10 minutes. For stress modes and Debug scenarios, increase this
2178 // to 30 minutes (30 * 60 * 1000 = 180000). The "timeout" argument to runtest.cmd sets this, by
2179 // taking a timeout value in milliseconds. (Note that it sets the __TestTimeout environment variable,
2180 // which is read by the xunit harness.)
2181 if (isJitStressScenario(scenario) || isR2RStressScenario(scenario) || (lowerConfiguration == 'debug'))
2183 def timeout = 1800000
2184 testOpts += " timeout ${timeout}"
2187 // If we are running a stress mode, we should write out the set of key
2188 // value env pairs to a file at this point and then we'll pass that to runtest.cmd
2190 def envScriptPath = ''
2191 if (isJitStressScenario(scenario) || isR2RStressScenario(scenario)) {
2192 def buildCommandsStr = ''
2193 envScriptPath = "%WORKSPACE%\\SetStressModes.bat"
2194 buildCommandsStr += envScriptCreate(os, envScriptPath)
2196 if (isJitStressScenario(scenario)) {
2197 buildCommandsStr += envScriptSetStressModeVariables(os, Constants.jitStressModeScenarios[scenario], envScriptPath)
2199 else if (isR2RStressScenario(scenario)) {
2200 buildCommandsStr += envScriptSetStressModeVariables(os, Constants.r2rStressScenarios[scenario], envScriptPath)
2203 if (architecture == 'x86_arm_altjit') {
2204 buildCommandsStr += envScriptAppendExistingScript(os, "%WORKSPACE%\\tests\\x86_arm_altjit.cmd", envScriptPath)
2206 else if (architecture == 'x64_arm64_altjit') {
2207 buildCommandsStr += envScriptAppendExistingScript(os, "%WORKSPACE%\\tests\\x64_arm64_altjit.cmd", envScriptPath)
2210 envScriptFinalize(os, envScriptPath)
2212 // Note that buildCommands is an array of individually executed commands; we want all the commands used to
2213 // create the SetStressModes.bat script to be executed together, hence we accumulate them as strings
2214 // into a single script.
2215 buildCommands += buildCommandsStr
2217 else if (architecture == 'x86_arm_altjit') {
2218 envScriptPath = "%WORKSPACE%\\tests\\x86_arm_altjit.cmd"
2220 else if (architecture == 'x64_arm64_altjit') {
2221 envScriptPath = "%WORKSPACE%\\tests\\x64_arm64_altjit.cmd"
2223 if (envScriptPath != '') {
2224 testOpts += " TestEnv ${envScriptPath}"
2227 runtestArguments = "${lowerConfiguration} ${arch} ${testOpts}"
2229 if (doCoreFxTesting) {
2230 if (scenario == 'corefx_innerloop') {
2231 // Create CORE_ROOT and testhost
2232 buildCommands += "build-test.cmd ${lowerConfiguration} ${arch} buildtesthostonly"
2233 buildCommands += "tests\\runtest.cmd ${runtestArguments} CoreFXTestsAll"
2235 // Archive and process (only) the test results
2236 Utilities.addArchival(newJob, "bin/Logs/**/testResults.xml")
2237 Utilities.addXUnitDotNETResults(newJob, "bin/Logs/**/testResults.xml")
2240 def workspaceRelativeFxRoot = "_/fx"
2241 def absoluteFxRoot = "%WORKSPACE%\\_\\fx"
2242 def fxBranch = getFxBranch(branch)
2244 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}"
2246 // Archive and process (only) the test results
2247 Utilities.addArchival(newJob, "${workspaceRelativeFxRoot}/bin/**/testResults.xml")
2248 Utilities.addXUnitDotNETResults(newJob, "${workspaceRelativeFxRoot}/bin/**/testResults.xml")
2250 //Archive additional build stuff to diagnose why my attempt at fault injection isn't causing CI to fail
2251 Utilities.addArchival(newJob, "SetStressModes.bat", "", true, false)
2252 Utilities.addArchival(newJob, "${workspaceRelativeFxRoot}/bin/testhost/**", "", true, false)
2255 else if (isGcReliabilityFramework(scenario)) {
2256 buildCommands += "tests\\runtest.cmd ${runtestArguments} GenerateLayoutOnly"
2257 buildCommands += "tests\\scripts\\run-gc-reliability-framework.cmd ${arch} ${configuration}"
2260 buildCommands += "tests\\runtest.cmd ${runtestArguments}"
2262 } // end if (!isBuildOnly)
2264 if (!doCoreFxTesting) {
2265 // Run the rest of the build
2266 // Build the mscorlib for the other OS's
2267 buildCommands += "build.cmd ${lowerConfiguration} ${arch} linuxmscorlib"
2268 buildCommands += "build.cmd ${lowerConfiguration} ${arch} osxmscorlib"
2270 if (arch == 'x64') {
2271 buildCommands += "build.cmd ${lowerConfiguration} arm64 linuxmscorlib"
2274 // Zip up the tests directory so that we don't use so much space/time copying
2275 // 10s of thousands of files around.
2276 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')\"";
2278 if (!isJitStressScenario(scenario)) {
2279 // For Windows, pull full test results and test drops for x86/x64.
2280 // No need to pull for stress mode scenarios (downstream builds use the default scenario)
2281 Utilities.addArchival(newJob, "bin/Product/**,bin/tests/tests.zip", "bin/Product/**/.nuget/**")
2284 if (scenario == 'jitdiff') {
2285 // retrieve jit-dasm output for base commit, and run jit-diff
2287 // if this is a build only job, we want to keep the default (build) artifacts for the flow job
2288 Utilities.addArchival(newJob, "bin/tests/${osGroup}.${arch}.${configuration}/dasm/**")
2293 Utilities.addXUnitDotNETResults(newJob, 'bin/**/TestRun*.xml', true)
2299 assert isArmWindowsScenario(scenario)
2303 if (buildCoreclrTests) {
2304 buildOpts += " -priority=${priority}"
2306 buildOpts += ' skiptests'
2309 // This is now a build only job. Do not run tests. Use the flow job.
2310 buildCommands += "set __TestIntermediateDir=int&&build.cmd ${lowerConfiguration} ${architecture} ${buildOpts}"
2312 if (doCoreFxTesting) {
2315 // Set the stress mode variables; this is incorporated into the generated CoreFx RunTests.cmd files.
2316 def envScriptPath = ''
2317 def buildCommandsStr = ''
2318 envScriptPath = "%WORKSPACE%\\SetStressModes.bat"
2319 buildCommandsStr += envScriptCreate(os, envScriptPath)
2320 buildCommandsStr += envScriptSetStressModeVariables(os, Constants.jitStressModeScenarios[scenario], envScriptPath)
2321 envScriptFinalize(os, envScriptPath)
2322 buildCommands += buildCommandsStr
2324 def workspaceRelativeFxRootLinux = "_/fx"
2325 def workspaceRelativeFxRootWin = "_\\fx"
2326 def absoluteFxRoot = "%WORKSPACE%\\_\\fx"
2327 def fxBranch = getFxBranch(branch)
2329 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"
2331 // Zip up the CoreFx runtime and tests. We don't need the CoreCLR binaries; they have been copied to the CoreFX tree.
2332 buildCommands += "powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('${workspaceRelativeFxRootWin}\\bin\\testhost\\netcoreapp-Windows_NT-Release-${architecture}', '${workspaceRelativeFxRootWin}\\fxruntime.zip')\"";
2333 buildCommands += "powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('${workspaceRelativeFxRootWin}\\bin\\tests', '${workspaceRelativeFxRootWin}\\fxtests.zip')\"";
2335 Utilities.addArchival(newJob, "${workspaceRelativeFxRootLinux}/fxruntime.zip")
2336 Utilities.addArchival(newJob, "${workspaceRelativeFxRootLinux}/fxtests.zip")
2338 // Zip up the tests directory so that we don't use so much space/time copying
2339 // 10s of thousands of files around.
2340 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')\"";
2343 Utilities.addArchival(newJob, "bin/Product/**,bin/tests/tests.zip", "bin/Product/**/.nuget/**")
2347 println("Unknown architecture: ${architecture}");
2352 // end case 'Windows_NT'; editor brace matching: }
2361 case 'Fedora24': // editor brace matching: {
2362 switch (architecture) {
2365 if (architecture == 'x86' && os == 'Ubuntu') {
2366 // build and PAL test
2367 def dockerImage = getDockerImageName(architecture, os, true)
2368 buildCommands += "docker run -i --rm -v \${WORKSPACE}:/opt/code -w /opt/code -e ROOTFS_DIR=/crossrootfs/x86 ${dockerImage} ./build.sh ${architecture} cross ${lowerConfiguration}"
2369 dockerImage = getDockerImageName(architecture, os, false)
2370 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"
2371 Utilities.addArchival(newJob, "bin/Product/**,bin/obj/*/tests/**/*.so", "bin/Product/**/.nuget/**")
2372 Utilities.addXUnitDotNETResults(newJob, '**/pal_tests.xml')
2376 if (scenario == 'formatting') {
2377 buildCommands += "python tests/scripts/format.py -c \${WORKSPACE} -o Linux -a ${architecture}"
2378 Utilities.addArchival(newJob, "format.patch", "", true, false)
2382 if (scenario == 'pmi_asm_diffs') {
2383 buildCommands += "./build.sh ${lowerConfiguration} ${architecture} skiptests skipbuildpackages"
2384 buildCommands += "./build-test.sh ${lowerConfiguration} ${architecture} generatelayoutonly"
2386 // TODO: Add -target_branch and -commit_hash arguments based on GitHub variables.
2387 buildCommands += "python -u \${WORKSPACE}/tests/scripts/run-pmi-diffs.py -arch ${architecture} -ci_arch ${architecture} -build_type ${configuration}"
2390 buildCommands += "zip -r dasm.${os}.${architecture}.${configuration}.zip ./_/_asm"
2393 Utilities.addArchival(newJob, "dasm.${os}.${architecture}.${configuration}.zip")
2397 if (scenario == 'illink') {
2398 assert(os == 'Ubuntu')
2399 buildCommands += "./tests/scripts/build_illink.sh --clone --arch=${architecture}"
2402 if (!doCoreFxTesting) {
2403 // We run pal tests on all OS but generate mscorlib (and thus, nuget packages)
2404 // only on supported OS platforms.
2405 def bootstrapRid = Utilities.getBoostrapPublishRid(os)
2406 def bootstrapRidEnv = bootstrapRid != null ? "__PUBLISH_RID=${bootstrapRid} " : ''
2408 buildCommands += "${bootstrapRidEnv}./build.sh ${lowerConfiguration} ${architecture}"
2409 buildCommands += "src/pal/tests/palsuite/runpaltests.sh \${WORKSPACE}/bin/obj/${osGroup}.${architecture}.${configuration} \${WORKSPACE}/bin/paltestout"
2411 // Basic archiving of the build
2412 Utilities.addArchival(newJob, "bin/Product/**,bin/obj/*/tests/**/*.dylib,bin/obj/*/tests/**/*.so", "bin/Product/**/.nuget/**")
2414 Utilities.addXUnitDotNETResults(newJob, '**/pal_tests.xml')
2417 if (scenario == 'corefx_innerloop') {
2418 assert os == 'Ubuntu' || 'OSX10.12'
2419 assert architecture == 'x64'
2421 buildCommands += "./build.sh ${lowerConfiguration} ${architecture} skiptests"
2422 buildCommands += "./build-test.sh ${lowerConfiguration} ${architecture} generatetesthostonly"
2423 buildCommands += "./tests/runtest.sh ${lowerConfiguration} --corefxtestsall --testHostDir=\${WORKSPACE}/bin/tests/${osGroup}.${architecture}.${configuration}/testhost/ --coreclr-src=\${WORKSPACE}"
2426 // Archive and process (only) the test results
2427 Utilities.addArchival(newJob, "bin/Logs/**/testResults.xml")
2428 Utilities.addXUnitDotNETResults(newJob, "bin/Logs/**/testResults.xml")
2431 // Corefx stress testing
2432 assert os == 'Ubuntu'
2433 assert architecture == 'x64'
2434 assert lowerConfiguration == 'checked'
2435 assert isJitStressScenario(scenario)
2438 buildCommands += "./build.sh ${lowerConfiguration} ${architecture}"
2440 def scriptFileName = "\$WORKSPACE/set_stress_test_env.sh"
2442 def envScriptCmds = envScriptCreate(os, scriptFileName)
2443 envScriptCmds += envScriptSetStressModeVariables(os, Constants.jitStressModeScenarios[scenario], scriptFileName)
2444 envScriptCmds += envScriptFinalize(os, scriptFileName)
2445 buildCommands += envScriptCmds
2447 // Build and text corefx
2448 def workspaceRelativeFxRoot = "_/fx"
2449 def absoluteFxRoot = "\$WORKSPACE/${workspaceRelativeFxRoot}"
2450 def fxBranch = getFxBranch(branch)
2452 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}"
2454 // Archive and process (only) the test results
2455 Utilities.addArchival(newJob, "${workspaceRelativeFxRoot}/bin/**/testResults.xml")
2456 Utilities.addXUnitDotNETResults(newJob, "${workspaceRelativeFxRoot}/bin/**/testResults.xml")
2461 // Emulator cross builds for ARM runs on Tizen currently
2462 assert os == 'Tizen'
2464 def arm_abi = "armel"
2465 def linuxCodeName = "tizen"
2467 // Unzip the Windows test binaries first. Exit with 0
2468 buildCommands += "unzip -q -o ./bin/tests/tests.zip -d ./bin/tests/Windows_NT.x64.${configuration} || exit 0"
2470 // Unpack the corefx binaries
2471 buildCommands += "mkdir ./bin/CoreFxBinDir"
2472 buildCommands += "tar -xf ./bin/build.tar.gz -C ./bin/CoreFxBinDir"
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') || (os == 'Ubuntu16.04')
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")
2533 else if (isCrossGenComparisonScenario(scenario)) {
2534 buildCommands += "${dockerCmd}\${WORKSPACE}/build-test.sh ${lowerConfiguration} ${architecture} cross generatelayoutonly"
2536 def workspaceRelativeProductBinDir = "bin/Product/${osGroup}.${architecture}.${configuration}"
2537 def workspaceRelativeCoreLib = "${workspaceRelativeProductBinDir}/IL/System.Private.CoreLib.dll"
2538 def workspaceRelativeCoreRootDir = "bin/tests/${osGroup}.${architecture}.${configuration}/Tests/Core_Root"
2539 def workspaceRelativeCrossGenComparisonScript = "tests/scripts/crossgen_comparison.py"
2540 def workspaceRelativeResultsDir = "_"
2541 def workspaceRelativeArtifactsArchive = "${os}.${architecture}.${configuration}.${scenario}.zip"
2542 def crossGenComparisonCmd = "python -u \${WORKSPACE}/${workspaceRelativeCrossGenComparisonScript} "
2543 getCrossArchitectures(os, architecture, scenario).each{ crossArch ->
2544 def crossGenExecutable = "\${WORKSPACE}/${workspaceRelativeProductBinDir}/${crossArch}/crossgen"
2545 def workspaceRelativeCrossArchResultDir = "${workspaceRelativeResultsDir}/${osGroup}.${crossArch}_${architecture}.${configuration}"
2547 buildCommands += "${dockerCmd}mkdir -p \${WORKSPACE}/${workspaceRelativeCrossArchResultDir}"
2548 buildCommands += "${dockerCmd}${crossGenComparisonCmd}crossgen_corelib --crossgen ${crossGenExecutable} --il_corelib \${WORKSPACE}/${workspaceRelativeCoreLib} --result_dir \${WORKSPACE}/${workspaceRelativeCrossArchResultDir}"
2549 buildCommands += "${dockerCmd}${crossGenComparisonCmd}crossgen_framework --crossgen ${crossGenExecutable} --core_root \${WORKSPACE}/${workspaceRelativeCoreRootDir} --result_dir \${WORKSPACE}/${workspaceRelativeCrossArchResultDir}"
2551 buildCommands += "${dockerCmd}zip -r ${workspaceRelativeArtifactsArchive} ${workspaceRelativeCoreLib} ${workspaceRelativeCoreRootDir} ${workspaceRelativeCrossGenComparisonScript} ${workspaceRelativeResultsDir}"
2552 Utilities.addArchival(newJob, "${workspaceRelativeArtifactsArchive}")
2554 else if (scenario == 'pmi_asm_diffs') {
2555 buildCommands += "${dockerCmd}\${WORKSPACE}/build-test.sh ${lowerConfiguration} ${architecture} cross generatelayoutonly"
2557 // Pass `-skip_diffs` -- the actual diffs will be done on an arm machine in the test job. This is the build job.
2558 // TODO: Add -target_branch and -commit_hash arguments based on GitHub variables.
2559 buildCommands += "python -u \${WORKSPACE}/tests/scripts/run-pmi-diffs.py -arch ${architecture} -ci_arch ${architecture} -build_type ${configuration} -skip_diffs True"
2561 // ZIP what we created.
2562 buildCommands += "zip -r coreroot.${os}.${architecture}.${lowerConfiguration}.zip ./bin/tests/Linux.${architecture}.${configuration}/Tests/Core_Root"
2563 buildCommands += "zip -r coreroot.baseline.${os}.${architecture}.${lowerConfiguration}.zip ./_/_c/bin/tests/Linux.${architecture}.${configuration}/Tests/Core_Root"
2565 // Archive the built artifacts
2566 Utilities.addArchival(newJob, "coreroot.${os}.${architecture}.${lowerConfiguration}.zip,coreroot.baseline.${os}.${architecture}.${lowerConfiguration}.zip")
2568 else if (architecture == 'arm') {
2569 // Then, using the same docker image, generate the CORE_ROOT layout using build-test.sh to
2570 // download the appropriate CoreFX packages.
2571 // Note that docker should not be necessary here, for the "generatelayoutonly" case, but we use it
2572 // just to be consistent with the "build.sh" case -- so both are run with the same environment.
2574 buildCommands += "${dockerCmd}\${WORKSPACE}/build-test.sh ${lowerConfiguration} ${architecture} cross generatelayoutonly"
2576 // ZIP up for the test job (created in the flow job code):
2577 // (1) the built CORE_ROOT, /home/user/coreclr/bin/tests/Linux.arm.Checked/Tests/Core_Root,
2578 // used by runtest.sh as the "--coreOverlayDir" argument.
2579 // (2) the native parts of the test build: /home/user/coreclr/bin/obj/Linux.arm.Checked/tests,
2580 // used by runtest.sh as the "--testNativeBinDir" argument.
2582 // These commands are assumed to be run from the root of the workspace.
2583 buildCommands += "zip -r coreroot.${lowerConfiguration}.zip ./bin/tests/Linux.${architecture}.${configuration}/Tests/Core_Root"
2584 buildCommands += "zip -r testnativebin.${lowerConfiguration}.zip ./bin/obj/Linux.${architecture}.${configuration}/tests"
2586 Utilities.addArchival(newJob, "coreroot.${lowerConfiguration}.zip,testnativebin.${lowerConfiguration}.zip", "")
2589 assert architecture == 'arm64'
2591 // Then, using the same docker image, build the tests and generate the CORE_ROOT layout.
2592 // Linux/arm64 does not use Windows-built tests.
2594 def testBuildOpts = ""
2595 if (priority == '1') {
2596 testBuildOpts = "priority1"
2599 buildCommands += "${dockerCmd}\${WORKSPACE}/build-test.sh ${lowerConfiguration} ${architecture} cross ${testBuildOpts}"
2601 // ZIP up the built tests (including CORE_ROOT and native test components copied to the CORE_ROOT) for the test job (created in the flow job code)
2602 buildCommands += "zip -r tests.${lowerConfiguration}.zip ./bin/tests/Linux.${architecture}.${configuration}"
2604 // We still use the testnativebin files until they get placed properly in the tests directory (next to their respective tests).
2605 // With https://github.com/dotnet/coreclr/pull/19918 this shouldn't be needed anymore.
2606 buildCommands += "zip -r testnativebin.${lowerConfiguration}.zip ./bin/obj/Linux.${architecture}.${configuration}/tests"
2608 Utilities.addArchival(newJob, "tests.${lowerConfiguration}.zip,testnativebin.${lowerConfiguration}.zip", "")
2611 // Archive the build logs from both product and test builds.
2612 Utilities.addArchival(newJob, "bin/Logs/*.log,bin/Logs/*.wrn,bin/Logs/*.err", "")
2614 // We need to clean up the build machines; the docker build leaves newly built files with root permission, which
2615 // the cleanup task in Jenkins can't remove.
2618 azureVMAgentPostBuildAction {
2619 agentPostBuildAction('Delete agent after build execution (when idle).')
2625 println("Unknown architecture: ${architecture}");
2630 // editor brace matching: }
2632 println("Unknown os: ${os}");
2637 return buildCommands
2640 // Determine if we should generate a job for the given parameters. This is for non-flow jobs: either build and test, or build only.
2641 // Returns true if the job should be generated.
2642 def static shouldGenerateJob(def scenario, def isPR, def architecture, def configuration, def os, def isBuildOnly)
2644 // The various "innerloop" jobs are only available as PR triggered.
2647 if (isInnerloopTestScenario(scenario)) {
2651 if (scenario == 'corefx_innerloop') {
2656 // Tizen is only supported for armem architecture
2657 if (os == 'Tizen' && architecture != 'armem') {
2661 // Filter based on architecture.
2663 switch (architecture) {
2665 if ((os != 'Windows_NT') && (os != 'Ubuntu')) {
2670 if ((os != 'Windows_NT') && (os != 'Ubuntu16.04')) {
2675 if (os != 'Tizen') {
2679 case 'x86_arm_altjit':
2680 case 'x64_arm64_altjit':
2681 if (os != 'Windows_NT') {
2686 if ((os != 'Windows_NT') && (os != 'Ubuntu')) {
2691 // Everything implemented
2694 println("Unknown architecture: ${architecture}")
2699 // Which (Windows) build only jobs are required?
2701 def isNormalOrInnerloop = (scenario == 'innerloop' || scenario == 'normal')
2704 switch (architecture) {
2707 // We use build only jobs for Windows arm/arm64 cross-compilation corefx testing, so we need to generate builds for that.
2708 if (!isCoreFxScenario(scenario)) {
2714 if (!isNormalOrInnerloop) {
2723 // Filter based on scenario.
2725 if (isJitStressScenario(scenario)) {
2726 if (configuration != 'Checked') {
2730 def isEnabledOS = (os == 'Windows_NT') ||
2731 (os == 'Ubuntu' && (architecture == 'x64') && isCoreFxScenario(scenario)) ||
2732 (os == 'Ubuntu' && architecture == 'arm') ||
2733 (os == 'Ubuntu16.04' && architecture == 'arm64')
2738 switch (architecture) {
2740 case 'x86_arm_altjit':
2741 case 'x64_arm64_altjit':
2745 // x86 ubuntu: no stress modes
2746 if (os == 'Ubuntu') {
2753 // We use build only jobs for Windows arm/arm64 cross-compilation corefx testing, so we need to generate builds for that.
2754 // No "regular" Windows arm corefx jobs, e.g.
2755 // For Ubuntu arm corefx testing, we use regular jobs (not "build only" since only Windows has "build only", and
2756 // the Ubuntu arm "regular" jobs don't run tests anyway).
2757 if (os == 'Windows_NT') {
2758 if (! (isBuildOnly && isCoreFxScenario(scenario)) ) {
2763 if (!isCoreFxScenario(scenario)) {
2770 // armem: no stress jobs for ARM emulator.
2774 else if (isR2RScenario(scenario)) {
2775 if (os != 'Windows_NT') {
2779 if (isR2RBaselineScenario(scenario)) {
2780 // no need for Debug scenario; Checked is sufficient
2781 if (configuration != 'Checked' && configuration != 'Release') {
2785 else if (isR2RStressScenario(scenario)) {
2786 // Stress scenarios only run with Checked builds, not Release (they would work with Debug, but be slow).
2787 if (configuration != 'Checked') {
2792 switch (architecture) {
2795 // Windows arm/arm64 ready-to-run jobs use flow jobs and test jobs, but depend on "normal" (not R2R specific) build jobs.
2802 else if (isCrossGenComparisonScenario(scenario)) {
2803 return shouldGenerateCrossGenComparisonJob(os, architecture, configuration, scenario)
2809 // The ilrt build isn't necessary except for Windows_NT2003. Non-Windows NT uses
2810 // the default scenario build
2811 if (os != 'Windows_NT') {
2815 if (architecture != 'x64') {
2819 if (configuration != 'Release') {
2824 if (os != 'Windows_NT' && os != 'Ubuntu' && os != 'OSX10.12') {
2827 if (architecture != 'x64') {
2830 if (configuration != 'Checked') {
2836 if (os != 'Windows_NT' && os != 'Ubuntu' && os != 'OSX10.12') {
2839 if (architecture != 'x64') {
2842 if (configuration != 'Release') {
2846 case 'gc_reliability_framework':
2847 case 'standalone_gc':
2848 if (os != 'Windows_NT' && os != 'Ubuntu' && os != 'OSX10.12') {
2852 if (architecture != 'x64') {
2856 if (configuration != 'Release' && configuration != 'Checked') {
2860 // We only run Windows and Ubuntu x64 Checked for formatting right now
2862 if (os != 'Windows_NT' && os != 'Ubuntu') {
2865 if (architecture != 'x64') {
2868 if (configuration != 'Checked') {
2873 if (os != 'Windows_NT' && (os != 'Ubuntu' || architecture != 'x64')) {
2876 if (architecture != 'x64' && architecture != 'x86') {
2884 if (!isValidPrTriggeredInnerLoopJob(os, architecture, configuration, isBuildOnly)) {
2888 case 'corefx_innerloop':
2889 if (os != 'Windows_NT' && os != 'Ubuntu' && os != 'OSX10.12') {
2892 if (architecture != 'x64') {
2896 case 'pmi_asm_diffs':
2897 if (configuration != 'Checked') {
2900 if (architecture == 'armem') {
2903 // Currently, we don't support pmi_asm_diffs for Windows arm/arm64. Is is not in validArmWindowsScenarios.
2904 if ((os == 'Windows_NT') && (architecture == 'arm' || architecture == 'arm64')) {
2907 // Currently, no support for Linux x86.
2908 if ((os != 'Windows_NT') && (architecture == 'x86')) {
2913 println("Unknown scenario: ${scenario}")
2919 // For altjit, don't do any scenarios that don't change compilation. That is, scenarios that only change
2920 // runtime behavior, not compile-time behavior, are not interesting.
2921 switch (architecture) {
2922 case 'x86_arm_altjit':
2923 case 'x64_arm64_altjit':
2924 if (isGCStressRelatedTesting(scenario)) {
2932 // The job was not filtered out, so we should generate it!
2936 Constants.allScenarios.each { scenario ->
2937 [true, false].each { isPR ->
2938 Constants.architectureList.each { architecture ->
2939 Constants.configurationList.each { configuration ->
2940 Constants.osList.each { os ->
2941 // If the OS is Windows_NT_BuildOnly, set the isBuildOnly flag to true
2942 // and reset the os to Windows_NT
2943 def isBuildOnly = false
2944 if (os == 'Windows_NT_BuildOnly') {
2949 if (!shouldGenerateJob(scenario, isPR, architecture, configuration, os, isBuildOnly)) {
2954 def jobName = getJobName(configuration, architecture, os, scenario, isBuildOnly)
2955 def folderName = getJobFolder(scenario)
2957 // Create the new job
2958 def newJob = job(Utilities.getFullJobName(project, jobName, isPR, folderName)) {}
2960 addToViews(newJob, false, isPR, architecture, os, configuration, scenario) // isFlowJob == false
2962 setJobMachineAffinity(architecture, os, true, false, false, newJob) // isBuildJob = true, isTestJob = false, isFlowJob = false
2964 Utilities.standardJobSetup(newJob, project, isPR, "*/${branch}")
2965 addTriggers(newJob, branch, isPR, architecture, os, configuration, scenario, false, isBuildOnly) // isFlowJob==false
2966 setJobTimeout(newJob, isPR, architecture, configuration, scenario, isBuildOnly)
2968 // Copy Windows build test binaries and corefx build artifacts for Linux cross build for armem.
2969 // We don't use a flow job for this, but we do depend on there being existing builds with these
2970 // artifacts produced.
2971 if ((architecture == 'armem') && (os == 'Tizen')) {
2972 // Define the Windows Tests and Corefx build job names
2973 def lowerConfiguration = configuration.toLowerCase()
2974 def WindowsTestsName = projectFolder + '/' +
2975 Utilities.getFullJobName(project,
2976 getJobName(lowerConfiguration, 'x64' , 'windows_nt', 'normal', true),
2978 def fxBranch = getFxBranch(branch)
2979 def corefxFolder = Utilities.getFolderName('dotnet/corefx') + '/' +
2980 Utilities.getFolderName(fxBranch)
2982 def arm_abi = 'armel'
2983 def corefx_os = 'tizen'
2985 // Let's use release CoreFX to test checked CoreCLR,
2986 // because we do not generate checked CoreFX in CoreFX CI yet.
2987 def corefx_lowerConfiguration = lowerConfiguration
2988 if (lowerConfiguration == 'checked') {
2989 corefx_lowerConfiguration = 'release'
2992 // Copy the Windows test binaries and the Corefx build binaries
2995 copyArtifacts(WindowsTestsName) {
2996 includePatterns('bin/tests/tests.zip')
2998 latestSuccessful(true)
3001 copyArtifacts("${corefxFolder}/${corefx_os}_${arm_abi}_cross_${corefx_lowerConfiguration}") {
3002 includePatterns('bin/build.tar.gz')
3004 latestSuccessful(true)
3011 def buildCommands = calculateBuildCommands(newJob, scenario, branch, isPR, architecture, configuration, os, isBuildOnly)
3015 if (os == 'Windows_NT') {
3016 buildCommands.each { buildCommand ->
3017 batchFile(buildCommand)
3021 buildCommands.each { buildCommand ->
3034 // Create a Windows ARM/ARM64 test job that will be used by a flow job.
3035 // Returns the newly created job.
3036 def static CreateWindowsArmTestJob(def dslFactory, def project, def architecture, def os, def configuration, def scenario, def isPR, def inputCoreCLRBuildName)
3038 def osGroup = getOSGroup(os)
3039 def jobName = getJobName(configuration, architecture, os, scenario, false) + "_tst"
3041 def jobFolder = getJobFolder(scenario)
3042 def newJob = dslFactory.job(Utilities.getFullJobName(project, jobName, isPR, jobFolder)) {
3044 stringParam('CORECLR_BUILD', '', "Build number to copy CoreCLR ${osGroup} binaries from")
3048 // Set up the copies
3050 // Coreclr build we are trying to test
3052 // ** NOTE ** This will, correctly, overwrite the CORE_ROOT from the Windows test archive
3054 copyArtifacts(inputCoreCLRBuildName) {
3055 excludePatterns('**/testResults.xml', '**/*.ni.dll')
3057 buildNumber('${CORECLR_BUILD}')
3061 if (isCoreFxScenario(scenario)) {
3063 // Only arm/arm64 supported for corefx testing now.
3064 assert architecture == 'arm' || architecture == 'arm64'
3066 // Unzip CoreFx runtime
3067 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-${architecture}')\"")
3069 // Unzip CoreFx tests.
3070 batchFile("powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::ExtractToDirectory('_\\fx\\fxtests.zip', '_\\fx\\bin\\tests')\"")
3072 // Add the script to run the corefx tests
3073 def corefx_runtime_path = "%WORKSPACE%\\_\\fx\\bin\\testhost\\netcoreapp-Windows_NT-Release-${architecture}"
3074 def corefx_tests_dir = "%WORKSPACE%\\_\\fx\\bin\\tests"
3075 def corefx_exclusion_file = "%WORKSPACE%\\tests\\${architecture}\\corefx_test_exclusions.txt"
3076 batchFile("call %WORKSPACE%\\tests\\scripts\\run-corefx-tests.bat ${corefx_runtime_path} ${corefx_tests_dir} ${corefx_exclusion_file} ${architecture}")
3078 } else { // !isCoreFxScenario(scenario)
3081 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}')\"")
3083 def buildCommands = ""
3085 def coreRootLocation = "%WORKSPACE%\\bin\\tests\\Windows_NT.${architecture}.${configuration}\\Tests\\Core_Root"
3086 def addEnvVariable = { variable, value -> buildCommands += "set ${variable}=${value}\r\n"}
3087 def addCommand = { cmd -> buildCommands += "${cmd}\r\n"}
3089 // Make sure Command Extensions are enabled. Used so %ERRORLEVEL% is available.
3090 addCommand("SETLOCAL ENABLEEXTENSIONS")
3093 addEnvVariable("CORE_ROOT", coreRootLocation)
3094 addEnvVariable("COMPlus_NoGuiOnAssert", "1")
3095 addEnvVariable("COMPlus_ContinueOnAssert", "0")
3097 // If we are running a stress mode, we'll set those variables as well
3098 if (isJitStressScenario(scenario) || isR2RStressScenario(scenario)) {
3099 def stressValues = null
3100 if (isJitStressScenario(scenario)) {
3101 stressValues = Constants.jitStressModeScenarios[scenario]
3104 stressValues = Constants.r2rStressScenarios[scenario]
3107 stressValues.each { key, value ->
3108 addEnvVariable(key, value)
3112 if (isR2RScenario(scenario)) {
3113 // Crossgen the framework assemblies.
3114 buildCommands += """
3115 @for %%F in (%CORE_ROOT%\\*.dll) do @call :PrecompileAssembly "%CORE_ROOT%" "%%F" %%~nxF
3116 @goto skip_PrecompileAssembly
3119 @REM Skip mscorlib since it is already precompiled.
3120 @if /I "%3" == "mscorlib.dll" exit /b 0
3121 @if /I "%3" == "mscorlib.ni.dll" exit /b 0
3123 "%CORE_ROOT%\\crossgen.exe" /Platform_Assemblies_Paths "%CORE_ROOT%" %2 >nul 2>nul
3124 @if "%errorlevel%" == "-2146230517" (
3125 echo %2 is not a managed assembly.
3126 ) else if "%errorlevel%" == "-2146234344" (
3127 echo %2 is not a managed assembly.
3128 ) else if %errorlevel% neq 0 (
3129 echo Unable to precompile %2
3135 :skip_PrecompileAssembly
3138 // Set RunCrossGen variable to cause test wrappers to invoke their logic to run
3139 // crossgen on tests before running them.
3140 addEnvVariable("RunCrossGen", "true")
3141 } // isR2RScenario(scenario)
3144 // Do not run generate layout. It will delete the correct CORE_ROOT, and we do not have a correct product
3145 // dir to copy from.
3146 def runtestCommand = "%WORKSPACE%\\tests\\runtest.cmd ${architecture} ${configuration} skipgeneratelayout"
3148 addCommand("${runtestCommand}")
3150 // Use the smarty errorlevel as the script errorlevel.
3151 addCommand("exit /b %errorlevel%")
3153 batchFile(buildCommands)
3154 } // non-corefx testing
3158 if (!isCoreFxScenario(scenario)) {
3159 Utilities.addXUnitDotNETResults(newJob, 'bin/**/TestRun*.xml', true)
3165 // Create a test job not covered by the "Windows ARM" case that will be used by a flow job.
3166 // E.g., non-Windows tests.
3167 // Returns the newly created job.
3168 def static CreateOtherTestJob(def dslFactory, def project, def branch, def architecture, def os, def configuration, def scenario, def isPR, def inputCoreCLRBuildName, def inputTestsBuildName)
3170 def lowerConfiguration = configuration.toLowerCase()
3172 def isUbuntuArm64Job = ((os == "Ubuntu16.04") && (architecture == 'arm64'))
3173 def isUbuntuArm32Job = ((os == "Ubuntu") && (architecture == 'arm'))
3174 def isUbuntuArmJob = isUbuntuArm32Job || isUbuntuArm64Job
3176 def doCoreFxTesting = isCoreFxScenario(scenario)
3177 def isPmiAsmDiffsScenario = (scenario == 'pmi_asm_diffs')
3179 def workspaceRelativeFxRootLinux = "_/fx" // only used for CoreFX testing
3181 def osGroup = getOSGroup(os)
3182 def jobName = getJobName(configuration, architecture, os, scenario, false) + "_tst"
3185 def useServerGC = false
3187 // Enable Server GC for Ubuntu PR builds
3188 // REVIEW: why? Does this apply to all architectures? Why only PR?
3189 if (os == 'Ubuntu' && isPR) {
3190 testOpts += ' --useServerGC'
3194 if (isR2RScenario(scenario)) {
3196 testOpts += ' --crossgen --runcrossgentests'
3198 if (scenario == 'r2r_jitstress1') {
3199 testOpts += ' --jitstress=1'
3201 else if (scenario == 'r2r_jitstress2') {
3202 testOpts += ' --jitstress=2'
3204 else if (scenario == 'r2r_jitstress1_tiered') {
3205 testOpts += ' --jitstress=1'
3207 else if (scenario == 'r2r_jitstress2_tiered') {
3208 testOpts += ' --jitstress=2'
3210 else if (scenario == 'r2r_jitstressregs1') {
3211 testOpts += ' --jitstressregs=1'
3213 else if (scenario == 'r2r_jitstressregs2') {
3214 testOpts += ' --jitstressregs=2'
3216 else if (scenario == 'r2r_jitstressregs3') {
3217 testOpts += ' --jitstressregs=3'
3219 else if (scenario == 'r2r_jitstressregs4') {
3220 testOpts += ' --jitstressregs=4'
3222 else if (scenario == 'r2r_jitstressregs8') {
3223 testOpts += ' --jitstressregs=8'
3225 else if (scenario == 'r2r_jitstressregs0x10') {
3226 testOpts += ' --jitstressregs=0x10'
3228 else if (scenario == 'r2r_jitstressregs0x80') {
3229 testOpts += ' --jitstressregs=0x80'
3231 else if (scenario == 'r2r_jitstressregs0x1000') {
3232 testOpts += ' --jitstressregs=0x1000'
3234 else if (scenario == 'r2r_jitminopts') {
3235 testOpts += ' --jitminopts'
3237 else if (scenario == 'r2r_jitforcerelocs') {
3238 testOpts += ' --jitforcerelocs'
3240 else if (scenario == 'r2r_gcstress15') {
3241 testOpts += ' --gcstresslevel=0xF'
3244 else if (scenario == 'jitdiff') {
3245 testOpts += ' --jitdisasm --crossgen'
3247 else if (scenario == 'illink') {
3248 testOpts += ' --link=\$WORKSPACE/linker/linker/bin/netcore_Release/netcoreapp2.0/ubuntu-x64/publish/illink'
3250 else if (isLongGc(scenario)) {
3251 // Long GC tests behave very poorly when they are not
3252 // the only test running (many of them allocate until OOM).
3253 testOpts += ' --sequential'
3255 // A note - runtest.sh does have "--long-gc" and "--gcsimulator" options
3256 // for running long GC and GCSimulator tests, respectively. We don't use them
3257 // here because using a playlist file produces much more readable output on the CI machines
3258 // and reduces running time.
3260 // The Long GC playlist contains all of the tests that are
3261 // going to be run. The GCSimulator playlist contains all of
3262 // the GC simulator tests.
3263 if (scenario == 'longgc') {
3264 testOpts += ' --long-gc --playlist=./tests/longRunningGcTests.txt'
3266 else if (scenario == 'gcsimulator') {
3267 testOpts += ' --gcsimulator --playlist=./tests/gcSimulatorTests.txt'
3270 else if (isGcReliabilityFramework(scenario)) {
3271 testOpts += ' --build-overlay-only'
3273 else if (scenario == 'standalone_gc') {
3274 if (osGroup == 'OSX') {
3275 testOpts += ' --gcname=libclrgc.dylib'
3277 else if (osGroup == 'Linux') {
3278 testOpts += ' --gcname=libclrgc.so'
3281 println("Unexpected OS group: ${osGroup} for os ${os}")
3286 // The ARM Ubuntu corefx test job doesn't depend on a Windows test build, and hence inputTestsBuildName
3287 // will be null in this case.
3289 def jobFolder = getJobFolder(scenario)
3290 def newJob = dslFactory.job(Utilities.getFullJobName(project, jobName, isPR, jobFolder)) {
3292 if (inputTestsBuildName != null) {
3293 stringParam('CORECLR_WINDOWS_BUILD', '', 'Build number to copy CoreCLR Windows test binaries from')
3295 stringParam('CORECLR_BUILD', '', "Build number to copy CoreCLR ${osGroup} binaries from")
3299 // Set up the copies
3301 // Coreclr build containing the tests and mscorlib
3302 // pri1 jobs still need to copy windows_nt built tests
3303 if (inputTestsBuildName != null) {
3304 copyArtifacts(inputTestsBuildName) {
3305 excludePatterns('**/testResults.xml', '**/*.ni.dll')
3307 buildNumber('${CORECLR_WINDOWS_BUILD}')
3312 // Coreclr build we are trying to test
3314 // ** NOTE ** This will, correctly, overwrite the CORE_ROOT from the Windows test archive
3316 // HACK: the Ubuntu arm64 copyArtifacts Jenkins plug-in is ridiculously slow (45 minutes to
3317 // 1.5 hours for this step). Instead, directly use wget, which is fast (1 minute).
3319 if (!isUbuntuArm64Job) {
3320 copyArtifacts(inputCoreCLRBuildName) {
3321 excludePatterns('**/testResults.xml', '**/*.ni.dll')
3323 buildNumber('${CORECLR_BUILD}')
3328 if (isUbuntuArmJob) {
3329 // Add some useful information to the log file. Ignore return codes.
3330 shell("uname -a || true")
3333 if (isUbuntuArm64Job) {
3334 // Copy the required artifacts directly, using wget, e.g.:
3336 // https://ci.dot.net/job/dotnet_coreclr/job/master/job/arm64_cross_checked_ubuntu16.04_innerloop_prtest/16/artifact/testnativebin.checked.zip
3337 // https://ci.dot.net/job/dotnet_coreclr/job/master/job/arm64_cross_checked_ubuntu16.04_innerloop_prtest/16/artifact/tests.checked.zip
3339 // parameterized as:
3341 // https://ci.dot.net/job/${mungedProjectName}/job/${mungedBranchName}/job/${inputJobName}/${CORECLR_BUILD}/artifact/testnativebin.checked.zip
3342 // https://ci.dot.net/job/${mungedProjectName}/job/${mungedBranchName}/job/${inputJobName}/${CORECLR_BUILD}/artifact/tests.checked.zip
3344 // CoreFX example artifact URLs:
3346 // https://ci.dot.net/job/dotnet_coreclr/job/dev_unix_test_workflow/job/jitstress/job/arm64_cross_checked_ubuntu16.04_corefx_baseline_prtest/1/artifact/_/fx/fxruntime.zip
3347 // https://ci.dot.net/job/dotnet_coreclr/job/dev_unix_test_workflow/job/jitstress/job/arm64_cross_checked_ubuntu16.04_corefx_baseline_prtest/1/artifact/_/fx/fxtests.zip
3349 // Note that the source might be in a "jitstress" folder.
3351 // Use `--progress=dot:giga` to display some progress output, but limit it in the log file.
3353 // Use `--directory-prefix=_/fx` to specify where to put the corefx files (to match what other platforms do). Use this instead of `-O`.
3355 shell("echo \"Using wget instead of the Jenkins copy artifacts plug-in to copy artifacts from ${inputCoreCLRBuildName}\"")
3357 def mungedProjectName = Utilities.getFolderName(project)
3358 def mungedBranchName = Utilities.getFolderName(branch)
3360 def doCrossGenComparison = isCrossGenComparisonScenario(scenario)
3361 def inputCoreCLRBuildScenario = isInnerloopTestScenario(scenario) ? 'innerloop' : 'normal'
3362 if (isPmiAsmDiffsScenario || doCoreFxTesting || doCrossGenComparison) {
3363 // These depend on unique builds for each scenario
3364 inputCoreCLRBuildScenario = scenario
3366 def sourceJobName = getJobName(configuration, architecture, os, inputCoreCLRBuildScenario, false)
3367 def inputJobName = Utilities.getFullJobName(sourceJobName, isPR)
3369 // Need to add the sub-folder if necessary.
3370 def inputJobPath = "job/${inputJobName}"
3371 def folderName = getJobFolder(inputCoreCLRBuildScenario)
3372 if (folderName != '') {
3373 inputJobPath = "job/${folderName}/job/${inputJobName}"
3376 def inputUrlRoot = "https://ci.dot.net/job/${mungedProjectName}/job/${mungedBranchName}/${inputJobPath}/\${CORECLR_BUILD}/artifact"
3378 if (isPmiAsmDiffsScenario) {
3379 def workspaceRelativeRootLinux = "_"
3380 shell("mkdir -p ${workspaceRelativeRootLinux}")
3381 shell("wget --progress=dot:giga ${inputUrlRoot}/coreroot.${os}.${architecture}.${lowerConfiguration}.zip")
3382 shell("wget --progress=dot:giga ${inputUrlRoot}/coreroot.baseline.${os}.${architecture}.${lowerConfiguration}.zip")
3384 else if (doCoreFxTesting) {
3385 shell("mkdir -p ${workspaceRelativeFxRootLinux}")
3386 shell("wget --progress=dot:giga --directory-prefix=${workspaceRelativeFxRootLinux} ${inputUrlRoot}/${workspaceRelativeFxRootLinux}/fxtests.zip")
3387 shell("wget --progress=dot:giga --directory-prefix=${workspaceRelativeFxRootLinux} ${inputUrlRoot}/${workspaceRelativeFxRootLinux}/fxruntime.zip")
3390 shell("wget --progress=dot:giga ${inputUrlRoot}/testnativebin.${lowerConfiguration}.zip")
3391 shell("wget --progress=dot:giga ${inputUrlRoot}/tests.${lowerConfiguration}.zip")
3395 if (architecture == 'x86') {
3396 shell("mkdir ./bin/CoreFxNative")
3398 def fxBranch = getFxBranch(branch)
3399 def corefxFolder = Utilities.getFolderName('dotnet/corefx') + '/' + Utilities.getFolderName(fxBranch)
3401 copyArtifacts("${corefxFolder}/ubuntu16.04_x86_release") {
3402 includePatterns('bin/build.tar.gz')
3403 targetDirectory('bin/CoreFxNative')
3405 latestSuccessful(true)
3409 shell("mkdir ./bin/CoreFxBinDir")
3410 shell("tar -xf ./bin/CoreFxNative/bin/build.tar.gz -C ./bin/CoreFxBinDir")
3413 if (isPmiAsmDiffsScenario) {
3414 // TODO: add back "-q" when we know it works
3415 shell("unzip -o ./coreroot.${os}.${architecture}.${lowerConfiguration}.zip || exit 0")
3416 shell("unzip -o ./coreroot.baseline.${os}.${architecture}.${lowerConfiguration}.zip || exit 0")
3418 // CoreFX testing downloads the CoreFX tests, not the coreclr tests. Also, unzip the built CoreFX layout/runtime directories.
3419 else if (doCoreFxTesting) {
3420 shell("unzip -q -o ${workspaceRelativeFxRootLinux}/fxtests.zip || exit 0")
3421 shell("unzip -q -o ${workspaceRelativeFxRootLinux}/fxruntime.zip || exit 0")
3423 else if (architecture != 'arm64') {
3424 // ARM64 copies the tests from the build machine; this is for unzip'ing tests copied from a Windows build.
3426 // Unzip the tests first. Exit with 0
3427 shell("unzip -q -o ./bin/tests/tests.zip -d ./bin/tests/${osGroup}.${architecture}.${configuration} || exit 0")
3428 shell("rm -r ./bin/tests/${osGroup}.${architecture}.${configuration}/Tests/Core_Root || exit 0")
3431 // For arm Ubuntu (on hardware), we do the "build-test" step on the build machine, not on the test
3432 // machine. The arm Ubuntu test machines do no building -- they have no CLI, for example.
3433 // We should probably do the "generatelayoutonly" step on the build machine for all architectures.
3434 // However, it's believed that perhaps there's an issue with executable permission bits not getting
3435 // copied correctly.
3436 if (!doCoreFxTesting) {
3437 if (isUbuntuArmJob) {
3438 if (!isPmiAsmDiffsScenario) {
3439 if (architecture == 'arm') {
3440 shell("unzip -q -o ./coreroot.${lowerConfiguration}.zip || exit 0") // unzips to ./bin/tests/Linux.${architecture}.${configuration}/Tests/Core_Root
3441 shell("unzip -q -o ./testnativebin.${lowerConfiguration}.zip || exit 0") // unzips to ./bin/obj/Linux.${architecture}.${configuration}/tests
3444 assert architecture == 'arm64'
3445 shell("unzip -q -o ./tests.${lowerConfiguration}.zip || exit 0") // unzips to ./bin/tests/Linux.${architecture}.${configuration}
3447 // We still the testnativebin files until they get placed properly in the tests directory (next to their respective tests).
3448 shell("unzip -q -o ./testnativebin.${lowerConfiguration}.zip || exit 0") // unzips to ./bin/obj/Linux.${architecture}.${configuration}/tests
3453 shell("./build-test.sh ${architecture} ${configuration} generatelayoutonly")
3457 // Execute the tests
3458 def runDocker = isNeedDocker(architecture, os, false)
3459 def dockerPrefix = ""
3462 def dockerImage = getDockerImageName(architecture, os, false)
3463 dockerPrefix = "docker run -i --rm -v \${WORKSPACE}:\${WORKSPACE} -w \${WORKSPACE} "
3464 dockerCmd = dockerPrefix + "${dockerImage} "
3467 // If we are running a stress mode, we'll set those variables first.
3468 // For CoreFX, the stress variables are already built into the CoreFX test build per-test wrappers.
3469 if (!doCoreFxTesting && isJitStressScenario(scenario)) {
3470 def scriptFileName = "\${WORKSPACE}/set_stress_test_env.sh"
3471 def envScriptCmds = envScriptCreate(os, scriptFileName)
3472 envScriptCmds += envScriptSetStressModeVariables(os, Constants.jitStressModeScenarios[scenario], scriptFileName)
3473 envScriptCmds += envScriptFinalize(os, scriptFileName)
3474 shell("${envScriptCmds}")
3475 testOpts += " --test-env=${scriptFileName}"
3478 // setup-stress-dependencies.sh, invoked by runtest.sh to download the coredistools package, depends on the "dotnet"
3479 // tool downloaded by the "init-tools.sh" script. However, it only invokes setup-stress-dependencies.sh for x64. The
3480 // coredistools package is used by GCStress on x86 and x64 to disassemble code to determine instruction boundaries.
3481 // On arm/arm64, it is not required as determining instruction boundaries is trivial.
3482 if (isGCStressRelatedTesting(scenario)) {
3483 if (architecture == 'x64') {
3484 shell('./init-tools.sh')
3488 if (isPmiAsmDiffsScenario) {
3490 python -u \${WORKSPACE}/tests/scripts/run-pmi-diffs.py -arch ${architecture} -ci_arch ${architecture} -build_type ${configuration} -skip_baseline_build True""")
3492 shell("zip -r dasm.${os}.${architecture}.${configuration}.zip ./_/_asm")
3494 else if (doCoreFxTesting) {
3496 \${WORKSPACE}/tests/scripts/run-corefx-tests.sh --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""")
3499 def runScript = "${dockerCmd}./tests/runtest.sh"
3501 // TODO: the testNativeBinDir shouldn't be necessary if the native test binaries are placed properly with their corresponding managed test code.
3505 ${lowerConfiguration} \\
3506 --testRootDir=\"\${WORKSPACE}/bin/tests/${osGroup}.${architecture}.${configuration}\" \\
3507 --coreOverlayDir=\"\${WORKSPACE}/bin/tests/${osGroup}.${architecture}.${configuration}/Tests/Core_Root\" \\
3508 --testNativeBinDir=\"\${WORKSPACE}/bin/obj/${osGroup}.${architecture}.${configuration}/tests\" \\
3509 --copyNativeTestBin --limitedDumpGeneration ${testOpts}""")
3512 if (isGcReliabilityFramework(scenario)) {
3513 // runtest.sh doesn't actually execute the reliability framework - do it here.
3516 dockerCmd = dockerPrefix + "-e COMPlus_gcServer=1 ${dockerImage} "
3519 shell("export COMPlus_gcServer=1")
3523 shell("${dockerCmd}./tests/scripts/run-gc-reliability-framework.sh ${architecture} ${configuration}")
3528 // Experimental: If on Ubuntu 14.04, then attempt to pull in crash dump links
3529 if (os in ['Ubuntu']) {
3530 SummaryBuilder summaries = new SummaryBuilder()
3531 summaries.addLinksSummaryFromFile('Crash dumps from this run:', 'dumplings.txt')
3532 summaries.emit(newJob)
3535 if (isPmiAsmDiffsScenario) {
3537 Utilities.addArchival(newJob, "dasm.${os}.${architecture}.${configuration}.zip")
3539 else if (doCoreFxTesting) {
3540 Utilities.addArchival(newJob, "${workspaceRelativeFxRootLinux}/bin/**/testResults.xml")
3541 if ((os == "Ubuntu") && (architecture == 'arm')) {
3542 // We have a problem with the xunit plug-in, where it is consistently failing on Ubuntu arm32 test result uploading with this error:
3544 // [xUnit] [ERROR] - The plugin hasn't been performed correctly: remote file operation failed: /ssd/j/workspace/dotnet_coreclr/master/jitstress/arm_cross_checked_ubuntu_corefx_baseline_tst at hudson.remoting.Channel@3697f46d:JNLP4-connect connection from 131.107.159.149/131.107.159.149:58529: java.io.IOException: Remote call on JNLP4-connect connection from 131.107.159.149/131.107.159.149:58529 failed
3546 // We haven't been able to identify the reason. So, do not add xunit parsing of the test data in this scenario.
3547 // This is tracked by: https://github.com/dotnet/coreclr/issues/19447.
3550 Utilities.addXUnitDotNETResults(newJob, "${workspaceRelativeFxRootLinux}/bin/**/testResults.xml")
3554 Utilities.addXUnitDotNETResults(newJob, '**/coreclrtests.xml')
3560 def static CreateNonWindowsCrossGenComparisonTestJob(def dslFactory, def project, def architecture, def os, def configuration, def scenario, def isPR, def inputCoreCLRBuildName)
3562 assert isCrossGenComparisonScenario(scenario)
3564 def osGroup = getOSGroup(os)
3565 def jobName = getJobName(configuration, architecture, os, scenario, false) + "_tst"
3567 def workspaceRelativeResultsDir = "_"
3568 def workspaceRelativeNativeArchResultDir = "${workspaceRelativeResultsDir}/${osGroup}.${architecture}_${architecture}.${configuration}"
3570 def jobFolder = getJobFolder(scenario)
3571 def newJob = dslFactory.job(Utilities.getFullJobName(project, jobName, isPR, jobFolder)) {
3573 stringParam('CORECLR_BUILD', '', "Build number to copy CoreCLR ${osGroup} binaries from")
3576 def workspaceRelativeArtifactsArchive = "${os}.${architecture}.${configuration}.${scenario}.zip"
3579 copyArtifacts(inputCoreCLRBuildName) {
3580 includePatterns("${workspaceRelativeArtifactsArchive}")
3582 buildNumber('${CORECLR_BUILD}')
3586 shell("unzip -o ${workspaceRelativeArtifactsArchive} || exit 0")
3588 def workspaceRelativeCoreLib = "bin/Product/${osGroup}.${architecture}.${configuration}/IL/System.Private.CoreLib.dll"
3589 def workspaceRelativeCoreRootDir = "bin/tests/${osGroup}.${architecture}.${configuration}/Tests/Core_Root"
3590 def workspaceRelativeCrossGenComparisonScript = "tests/scripts/crossgen_comparison.py"
3591 def workspaceRelativeCrossGenExecutable = "${workspaceRelativeCoreRootDir}/crossgen"
3593 def crossGenComparisonCmd = "python -u \${WORKSPACE}/${workspaceRelativeCrossGenComparisonScript} "
3594 def crossGenExecutable = "\${WORKSPACE}/${workspaceRelativeCrossGenExecutable}"
3596 shell("mkdir -p ${workspaceRelativeNativeArchResultDir}")
3597 shell("${crossGenComparisonCmd}crossgen_corelib --crossgen ${crossGenExecutable} --il_corelib \${WORKSPACE}/${workspaceRelativeCoreLib} --result_dir \${WORKSPACE}/${workspaceRelativeNativeArchResultDir}")
3598 shell("${crossGenComparisonCmd}crossgen_framework --crossgen ${crossGenExecutable} --core_root \${WORKSPACE}/${workspaceRelativeCoreRootDir} --result_dir \${WORKSPACE}/${workspaceRelativeNativeArchResultDir}")
3600 getCrossArchitectures(os, architecture, scenario).each{ crossArch ->
3601 def workspaceRelativeCrossArchResultDir = "${workspaceRelativeResultsDir}/${osGroup}.${crossArch}_${architecture}.${configuration}"
3602 shell("${crossGenComparisonCmd}compare --base_dir \${WORKSPACE}/${workspaceRelativeNativeArchResultDir} --diff_dir \${WORKSPACE}/${workspaceRelativeCrossArchResultDir}")
3607 Utilities.addArchival(newJob, "${workspaceRelativeNativeArchResultDir}/**")
3608 getCrossArchitectures(os, architecture, scenario).each{ crossArch ->
3609 def workspaceRelativeCrossArchResultDir = "${workspaceRelativeResultsDir}/${osGroup}.${crossArch}_${architecture}.${configuration}"
3610 Utilities.addArchival(newJob, "${workspaceRelativeCrossArchResultDir}/**")
3616 // Create a test job that will be used by a flow job.
3617 // Returns the newly created job.
3618 // 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,
3619 // and we want the views to be the minimal set of "top-level" jobs that represent all work.
3620 def static CreateTestJob(def dslFactory, def project, def branch, def architecture, def os, def configuration, def scenario, def isPR, def inputCoreCLRBuildName, def inputTestsBuildName)
3622 def windowsArmJob = ((os == "Windows_NT") && (architecture in Constants.armWindowsCrossArchitectureList))
3625 if (windowsArmJob) {
3626 assert inputTestsBuildName == null
3627 newJob = CreateWindowsArmTestJob(dslFactory, project, architecture, os, configuration, scenario, isPR, inputCoreCLRBuildName)
3629 else if (isCrossGenComparisonScenario(scenario)) {
3630 assert inputTestsBuildName == null
3631 newJob = CreateNonWindowsCrossGenComparisonTestJob(dslFactory, project, architecture, os, configuration, scenario, isPR, inputCoreCLRBuildName)
3634 newJob = CreateOtherTestJob(dslFactory, project, branch, architecture, os, configuration, scenario, isPR, inputCoreCLRBuildName, inputTestsBuildName)
3637 setJobMachineAffinity(architecture, os, false, true, false, newJob) // isBuildJob = false, isTestJob = true, isFlowJob = false
3639 if (scenario == 'jitdiff') {
3640 def osGroup = getOSGroup(os)
3641 Utilities.addArchival(newJob, "bin/tests/${osGroup}.${architecture}.${configuration}/dasm/**")
3644 Utilities.standardJobSetup(newJob, project, isPR, "*/${branch}")
3645 setJobTimeout(newJob, isPR, architecture, configuration, scenario, false)
3650 // Create a flow job to tie together a build job with the given test job.
3651 // The 'inputTestsBuildName' argument might be null if the flow job doesn't depend on a Windows build job.
3652 // Returns the new flow job.
3653 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)
3655 // Windows CoreCLR build and Linux CoreCLR build (in parallel) ->
3656 // Linux CoreCLR test
3657 def flowJobName = getJobName(configuration, architecture, os, scenario, false) + "_flow"
3658 def jobFolder = getJobFolder(scenario)
3660 def newFlowJob = null
3662 if (inputTestsBuildName == null) {
3663 newFlowJob = dslFactory.buildFlowJob(Utilities.getFullJobName(project, flowJobName, isPR, jobFolder)) {
3665 coreclrBuildJob = build(params, '${inputCoreCLRBuildName}')
3667 // And then build the test build
3668 build(params + [CORECLR_BUILD: coreclrBuildJob.build.number], '${fullTestJobName}')
3671 JobReport.Report.addReference(inputCoreCLRBuildName)
3672 JobReport.Report.addReference(fullTestJobName)
3675 newFlowJob = dslFactory.buildFlowJob(Utilities.getFullJobName(project, flowJobName, isPR, jobFolder)) {
3677 // Build the input jobs in parallel
3679 { coreclrBuildJob = build(params, '${inputCoreCLRBuildName}') },
3680 { windowsBuildJob = build(params, '${inputTestsBuildName}') }
3683 // And then build the test build
3684 build(params + [CORECLR_BUILD: coreclrBuildJob.build.number,
3685 CORECLR_WINDOWS_BUILD: windowsBuildJob.build.number], '${fullTestJobName}')
3688 JobReport.Report.addReference(inputCoreCLRBuildName)
3689 JobReport.Report.addReference(inputTestsBuildName)
3690 JobReport.Report.addReference(fullTestJobName)
3693 addToViews(newFlowJob, true, isPR, architecture, os, configuration, scenario) // isFlowJob = true
3695 setJobMachineAffinity(architecture, os, false, false, true, newFlowJob) // isBuildJob = false, isTestJob = false, isFlowJob = true
3697 Utilities.standardJobSetup(newFlowJob, project, isPR, "*/${branch}")
3698 addTriggers(newFlowJob, branch, isPR, architecture, os, configuration, scenario, true, false) // isFlowJob==true, isWindowsBuildOnlyJob==false
3703 // Determine if we should generate a flow job for the given parameters.
3704 // Returns true if the job should be generated.
3705 def static shouldGenerateFlowJob(def scenario, def isPR, def architecture, def configuration, def os)
3707 // The various "innerloop" jobs are only available as PR triggered.
3710 if (isInnerloopTestScenario(scenario)) {
3714 if (scenario == 'corefx_innerloop') {
3719 // Filter based on OS and architecture.
3721 switch (architecture) {
3723 if (os != "Ubuntu" && os != "Windows_NT") {
3728 if (os != "Ubuntu16.04" && os != "Windows_NT") {
3733 if (os != "Ubuntu") {
3738 if (!(os in Constants.crossList)) {
3741 if (os == "Windows_NT") {
3746 case 'x86_arm_altjit':
3747 case 'x64_arm64_altjit':
3751 println("Unknown architecture: ${architecture}")
3756 def isNormalOrInnerloop = (scenario == 'innerloop' || scenario == 'normal')
3758 // Filter based on scenario in OS.
3760 if (os == 'Windows_NT') {
3761 assert architecture == 'arm' || architecture == 'arm64'
3762 if (!isArmWindowsScenario(scenario)) {
3765 if (isNormalOrInnerloop && (configuration == 'Debug')) {
3766 // The arm32/arm64 Debug configuration for innerloop/normal scenario is a special case: it does a build only, and no test run.
3767 // To do that, it doesn't require a flow job.
3773 if (architecture == 'arm') {
3774 if (!(scenario in Constants.validLinuxArmScenarios)) {
3778 else if (architecture == 'arm64') {
3779 if (!(scenario in Constants.validLinuxArm64Scenarios)) {
3783 else if (architecture == 'x86') {
3784 // Linux/x86 only want innerloop and default test
3785 if (!isNormalOrInnerloop) {
3789 else if (architecture == 'x64') {
3790 // Linux/x64 corefx testing doesn't need a flow job; the "build" job runs run-corefx-tests.py which
3791 // builds and runs the corefx tests. Other Linux/x64 flow jobs are required to get the test
3792 // build from a Windows machine.
3793 if (isCoreFxScenario(scenario)) {
3799 // For CentOS, we only want Checked/Release builds.
3800 if (os == 'CentOS7.1') {
3801 if (configuration != 'Checked' && configuration != 'Release') {
3804 if (!isNormalOrInnerloop && !isR2RScenario(scenario)) {
3809 // For RedHat and Debian, we only do Release builds.
3810 else if (os == 'RHEL7.2' || os == 'Debian8.4') {
3811 if (configuration != 'Release') {
3814 if (!isNormalOrInnerloop) {
3819 // Next, filter based on scenario.
3821 if (isJitStressScenario(scenario)) {
3822 if (configuration != 'Checked') {
3826 else if (isR2RBaselineScenario(scenario)) {
3827 if (configuration != 'Checked' && configuration != 'Release') {
3831 else if (isR2RStressScenario(scenario)) {
3832 if (configuration != 'Checked') {
3836 else if (isCrossGenComparisonScenario(scenario)) {
3837 return shouldGenerateCrossGenComparisonJob(os, architecture, configuration, scenario)
3845 // Long GC tests take a long time on non-Release builds
3846 // ilrt is also Release only
3847 if (configuration != 'Release') {
3853 if (configuration != 'Checked') {
3858 case 'gc_reliability_framework':
3859 case 'standalone_gc':
3860 if (configuration != 'Release' && configuration != 'Checked') {
3869 if (os != 'Windows_NT' && os != 'Ubuntu') {
3879 if (!isValidPrTriggeredInnerLoopJob(os, architecture, configuration, false)) {
3884 case 'pmi_asm_diffs':
3885 if (configuration != 'Checked') {
3888 // No need for flow job except for Linux arm/arm64
3889 if ((os != 'Windows_NT') && (architecture != 'arm') && (architecture != 'arm64')) {
3894 case 'corefx_innerloop':
3895 // No flow job needed
3899 println("Unknown scenario: ${scenario}")
3905 // The job was not filtered out, so we should generate it!
3909 // Create jobs requiring flow jobs. This includes x64 non-Windows, arm/arm64 Ubuntu, and arm/arm64 Windows.
3910 Constants.allScenarios.each { scenario ->
3911 [true, false].each { isPR ->
3912 Constants.architectureList.each { architecture ->
3913 Constants.configurationList.each { configuration ->
3914 Constants.osList.each { os ->
3916 if (!shouldGenerateFlowJob(scenario, isPR, architecture, configuration, os)) {
3920 def windowsArmJob = ((os == "Windows_NT") && (architecture in Constants.armWindowsCrossArchitectureList))
3921 def doCoreFxTesting = isCoreFxScenario(scenario)
3922 def doCrossGenComparison = isCrossGenComparisonScenario(scenario)
3923 def isPmiAsmDiffsScenario = (scenario == 'pmi_asm_diffs')
3925 // Figure out the job name of the CoreCLR build the test will depend on.
3927 def inputCoreCLRBuildScenario = isInnerloopTestScenario(scenario) ? 'innerloop' : 'normal'
3928 def inputCoreCLRBuildIsBuildOnly = false
3929 if (doCoreFxTesting || isPmiAsmDiffsScenario) {
3930 // Every CoreFx test depends on its own unique build.
3931 inputCoreCLRBuildScenario = scenario
3932 if (windowsArmJob) {
3933 // Only Windows ARM corefx jobs use "build only" jobs. Others, such as Ubuntu ARM corefx, use "regular" jobs.
3934 inputCoreCLRBuildIsBuildOnly = true
3937 else if (doCrossGenComparison) {
3938 inputCoreCLRBuildScenario = scenario
3941 def inputCoreCLRFolderName = getJobFolder(inputCoreCLRBuildScenario)
3942 def inputCoreCLRBuildName = projectFolder + '/' +
3943 Utilities.getFullJobName(project, getJobName(configuration, architecture, os, inputCoreCLRBuildScenario, inputCoreCLRBuildIsBuildOnly), isPR, inputCoreCLRFolderName)
3945 // Figure out the name of the build job that the test job will depend on.
3946 // For Windows ARM tests, this is not used, as the CoreCLR build creates the tests. For other
3947 // tests (e.g., Linux ARM), we depend on a Windows build to get the tests.
3948 // For CoreFX tests, however, Linux doesn't need the Windows build for the tests, since the
3949 // CoreFX build creates the tests.
3951 def inputTestsBuildName = null
3953 // Ubuntu Arm64 jobs do the test build on the build machine, and thus don't depend on a Windows build.
3954 def isUbuntuArm64Job = ((os == "Ubuntu16.04") && (architecture == 'arm64'))
3956 if (!windowsArmJob && !doCoreFxTesting & !doCrossGenComparison && !isUbuntuArm64Job && !isPmiAsmDiffsScenario) {
3957 def testBuildScenario = isInnerloopTestScenario(scenario) ? 'innerloop' : 'normal'
3959 def inputTestsBuildArch = architecture
3960 if (architecture == "arm") {
3961 // Use the x86 test build for arm unix
3962 inputTestsBuildArch = "x86"
3965 def inputTestsBuildIsBuildOnly = true
3967 inputTestsBuildName = projectFolder + '/' +
3968 Utilities.getFullJobName(project, getJobName(configuration, inputTestsBuildArch, 'windows_nt', testBuildScenario, inputTestsBuildIsBuildOnly), isPR)
3971 // =============================================================================================
3972 // Create the test job
3973 // =============================================================================================
3975 def testJob = CreateTestJob(this, project, branch, architecture, os, configuration, scenario, isPR, inputCoreCLRBuildName, inputTestsBuildName)
3977 // =============================================================================================
3978 // Create a build flow to join together the build and tests required to run this test.
3979 // =============================================================================================
3981 if (os == 'RHEL7.2' || os == 'Debian8.4') {
3982 // Do not create the flow job for RHEL jobs.
3986 def fullTestJobName = projectFolder + '/' + testJob.name
3987 def flowJob = CreateFlowJob(this, project, branch, architecture, os, configuration, scenario, isPR, fullTestJobName, inputCoreCLRBuildName, inputTestsBuildName)
3995 JobReport.Report.generateJobReport(out)
3997 // Make the call to generate the help job
3998 Utilities.createHelperJob(this, project, branch,
3999 "Welcome to the ${project} Repository", // This is prepended to the help message
4000 "Have a nice day!") // This is appended to the help message. You might put known issues here.
4002 Utilities.addCROSSCheck(this, project, branch)