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 // We use this class (vs variables) so that the static functions can access data here.
38 // We have very limited Windows ARM64 hardware (used for ARM/ARM64 testing) and Linux/arm32 and Linux/arm64 hardware.
39 // So only allow certain branches to use it.
40 def static LimitedHardwareBranches = [
43 // Innerloop build OS's
44 // The Windows_NT_BuildOnly OS is a way to speed up the Non-Windows builds by avoiding
45 // test execution in the build flow runs. It generates the exact same build
46 // as Windows_NT but without running the tests.
52 'Windows_NT_BuildOnly',
60 def static crossList = [
68 // This is a set of JIT stress modes combined with the set of variables that
69 // need to be set to actually enable that stress mode. The key of the map is the stress mode and
70 // the values are the environment variables
71 def static jitStressModeScenarios = [
72 'minopts' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JITMinOpts' : '1'],
73 'tieredcompilation' : ['COMPlus_TieredCompilation' : '1'], // this can be removed once tiered compilation is on by default
74 'no_tiered_compilation' : ['COMPlus_TieredCompilation' : '0'],
75 'no_tiered_compilation_innerloop': ['COMPlus_TieredCompilation' : '0'],
76 'forcerelocs' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_ForceRelocs' : '1'],
77 'jitstress1' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStress' : '1'],
78 'jitstress2' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStress' : '2'],
79 'jitstress1_tiered' : ['COMPlus_TieredCompilation' : '1', 'COMPlus_JitStress' : '1'],
80 'jitstress2_tiered' : ['COMPlus_TieredCompilation' : '1', 'COMPlus_JitStress' : '2'],
81 'jitstressregs1' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '1'],
82 'jitstressregs2' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '2'],
83 'jitstressregs3' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '3'],
84 'jitstressregs4' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '4'],
85 'jitstressregs8' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '8'],
86 'jitstressregs0x10' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '0x10'],
87 'jitstressregs0x80' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '0x80'],
88 'jitstressregs0x1000' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '0x1000'],
89 'jitstress2_jitstressregs1' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '1'],
90 'jitstress2_jitstressregs2' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '2'],
91 'jitstress2_jitstressregs3' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '3'],
92 'jitstress2_jitstressregs4' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '4'],
93 'jitstress2_jitstressregs8' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '8'],
94 'jitstress2_jitstressregs0x10' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '0x10'],
95 'jitstress2_jitstressregs0x80' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '0x80'],
96 'jitstress2_jitstressregs0x1000' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '0x1000'],
97 'tailcallstress' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_TailcallStress' : '1'],
98 'jitsse2only' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_EnableAVX' : '0', 'COMPlus_EnableSSE3_4' : '0'],
99 'jitnosimd' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_FeatureSIMD' : '0'],
100 'jitincompletehwintrinsic' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_EnableIncompleteISAClass' : '1'],
101 'jitx86hwintrinsicnoavx' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_EnableIncompleteISAClass' : '1', 'COMPlus_EnableAVX' : '0'], // testing the legacy SSE encoding
102 'jitx86hwintrinsicnoavx2' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_EnableIncompleteISAClass' : '1', 'COMPlus_EnableAVX2' : '0'], // testing SNB/IVB
103 'jitx86hwintrinsicnosimd' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_EnableIncompleteISAClass' : '1', 'COMPlus_FeatureSIMD' : '0'], // match "jitnosimd", may need to remove after decoupling HW intrinsic from FeatureSIMD
104 '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'],
105 'corefx_baseline' : ['COMPlus_TieredCompilation' : '0'], // corefx baseline
106 'corefx_minopts' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JITMinOpts' : '1'],
107 'corefx_tieredcompilation' : ['COMPlus_TieredCompilation' : '1'], // this can be removed once tiered compilation is on by default
108 'corefx_jitstress1' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStress' : '1'],
109 'corefx_jitstress2' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStress' : '2'],
110 'corefx_jitstressregs1' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '1'],
111 'corefx_jitstressregs2' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '2'],
112 'corefx_jitstressregs3' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '3'],
113 'corefx_jitstressregs4' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '4'],
114 'corefx_jitstressregs8' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '8'],
115 'corefx_jitstressregs0x10' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '0x10'],
116 'corefx_jitstressregs0x80' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '0x80'],
117 'corefx_jitstressregs0x1000' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_JitStressRegs' : '0x1000'],
118 'gcstress0x3' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_GCStress' : '0x3'],
119 'gcstress0xc' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_GCStress' : '0xC'],
120 'zapdisable' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_ZapDisable' : '1', 'COMPlus_ReadyToRun' : '0'],
121 'heapverify1' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_HeapVerify' : '1'],
122 'gcstress0xc_zapdisable' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_GCStress' : '0xC', 'COMPlus_ZapDisable' : '1', 'COMPlus_ReadyToRun' : '0'],
123 'gcstress0xc_zapdisable_jitstress2' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_GCStress' : '0xC', 'COMPlus_ZapDisable' : '1', 'COMPlus_ReadyToRun' : '0', 'COMPlus_JitStress' : '2'],
124 'gcstress0xc_zapdisable_heapverify1' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_GCStress' : '0xC', 'COMPlus_ZapDisable' : '1', 'COMPlus_ReadyToRun' : '0', 'COMPlus_HeapVerify' : '1'],
125 'gcstress0xc_jitstress1' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_GCStress' : '0xC', 'COMPlus_JitStress' : '1'],
126 'gcstress0xc_jitstress2' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_GCStress' : '0xC', 'COMPlus_JitStress' : '2'],
127 'gcstress0xc_minopts_heapverify1' : ['COMPlus_TieredCompilation' : '0', 'COMPlus_GCStress' : '0xC', 'COMPlus_JITMinOpts' : '1', 'COMPlus_HeapVerify' : '1']
130 // This is a set of ReadyToRun stress scenarios
131 def static r2rStressScenarios = [
132 'r2r_jitstress1' : ['COMPlus_TieredCompilation' : '0', "COMPlus_JitStress": "1"],
133 'r2r_jitstress2' : ['COMPlus_TieredCompilation' : '0', "COMPlus_JitStress": "2"],
134 'r2r_jitstress1_tiered' : ['COMPlus_TieredCompilation' : '1', "COMPlus_JitStress": "1"],
135 'r2r_jitstress2_tiered' : ['COMPlus_TieredCompilation' : '1', "COMPlus_JitStress": "2"],
136 'r2r_jitstressregs1' : ['COMPlus_TieredCompilation' : '0', "COMPlus_JitStressRegs": "1"],
137 'r2r_jitstressregs2' : ['COMPlus_TieredCompilation' : '0', "COMPlus_JitStressRegs": "2"],
138 'r2r_jitstressregs3' : ['COMPlus_TieredCompilation' : '0', "COMPlus_JitStressRegs": "3"],
139 'r2r_jitstressregs4' : ['COMPlus_TieredCompilation' : '0', "COMPlus_JitStressRegs": "4"],
140 'r2r_jitstressregs8' : ['COMPlus_TieredCompilation' : '0', "COMPlus_JitStressRegs": "8"],
141 'r2r_jitstressregs0x10' : ['COMPlus_TieredCompilation' : '0', "COMPlus_JitStressRegs": "0x10"],
142 'r2r_jitstressregs0x80' : ['COMPlus_TieredCompilation' : '0', "COMPlus_JitStressRegs": "0x80"],
143 'r2r_jitstressregs0x1000' : ['COMPlus_TieredCompilation' : '0', "COMPlus_JitStressRegs": "0x1000"],
144 'r2r_jitminopts' : ['COMPlus_TieredCompilation' : '0', "COMPlus_JITMinOpts": "1"],
145 'r2r_jitforcerelocs' : ['COMPlus_TieredCompilation' : '0', "COMPlus_ForceRelocs": "1"],
146 'r2r_gcstress15' : ['COMPlus_TieredCompilation' : '0', "COMPlus_GCStress": "0xF"],
147 'r2r_no_tiered_compilation' : ['COMPlus_TieredCompilation' : '0'],
150 // This is the basic set of scenarios
151 def static basicScenarios = [
158 // 'jitdiff', // jitdiff is currently disabled, until someone spends the effort to make it fully work
160 'gc_reliability_framework',
163 'crossgen_comparison',
166 def static allScenarios = basicScenarios + r2rStressScenarios.keySet() + jitStressModeScenarios.keySet()
168 // Valid PR trigger combinations.
169 def static prTriggeredValidInnerLoopCombos = [
178 'Windows_NT_BuildOnly': [
185 // A set of scenarios that are valid for arm/arm64 tests run on hardware. This is a map from valid scenario name
186 // to Tests.lst file categories to exclude.
188 // This list should contain a subset of the scenarios from `allScenarios`. Please keep this in the same order as that,
189 // and with the same values, with some commented out, for easier maintenance.
191 // Note that some scenarios that are commented out should be enabled, but haven't yet been.
193 def static validArmWindowsScenarios = [
203 // 'gc_reliability_framework'
205 // 'corefx_innerloop'
206 // 'crossgen_comparison'
210 'r2r_jitstress1_tiered',
211 'r2r_jitstress2_tiered',
212 'r2r_jitstressregs1',
213 'r2r_jitstressregs2',
214 'r2r_jitstressregs3',
215 'r2r_jitstressregs4',
216 'r2r_jitstressregs8',
217 'r2r_jitstressregs0x10',
218 'r2r_jitstressregs0x80',
219 'r2r_jitstressregs0x1000',
221 'r2r_jitforcerelocs',
223 'r2r_no_tiered_compilation',
226 'no_tiered_compilation',
227 'no_tiered_compilation_innerloop',
240 'jitstressregs0x1000',
241 'jitstress2_jitstressregs1',
242 'jitstress2_jitstressregs2',
243 'jitstress2_jitstressregs3',
244 'jitstress2_jitstressregs4',
245 'jitstress2_jitstressregs8',
246 'jitstress2_jitstressregs0x10',
247 'jitstress2_jitstressregs0x80',
248 'jitstress2_jitstressregs0x1000',
250 // 'jitsse2only' // Only relevant to xarch
251 'jitnosimd', // Only interesting on platforms where SIMD support exists.
252 // 'jitincompletehwintrinsic'
253 // 'jitx86hwintrinsicnoavx'
254 // 'jitx86hwintrinsicnoavx2'
255 // 'jitx86hwintrinsicnosimd'
256 // 'jitnox86hwintrinsic'
257 'corefx_baseline', // corefx tests don't use smarty
258 'corefx_minopts', // corefx tests don't use smarty
259 'corefx_tieredcompilation', // corefx tests don't use smarty
260 'corefx_jitstress1', // corefx tests don't use smarty
261 'corefx_jitstress2', // corefx tests don't use smarty
262 'corefx_jitstressregs1', // corefx tests don't use smarty
263 'corefx_jitstressregs2', // corefx tests don't use smarty
264 'corefx_jitstressregs3', // corefx tests don't use smarty
265 'corefx_jitstressregs4', // corefx tests don't use smarty
266 'corefx_jitstressregs8', // corefx tests don't use smarty
267 'corefx_jitstressregs0x10', // corefx tests don't use smarty
268 'corefx_jitstressregs0x80', // corefx tests don't use smarty
269 'corefx_jitstressregs0x1000', // corefx tests don't use smarty
274 'gcstress0xc_zapdisable',
275 'gcstress0xc_zapdisable_jitstress2',
276 'gcstress0xc_zapdisable_heapverify1',
277 'gcstress0xc_jitstress1',
278 'gcstress0xc_jitstress2',
279 'gcstress0xc_minopts_heapverify1',
282 // NOTE: the following scenarios are not defined in the 'allScenarios' list! Is this a bug?
285 'minopts_zapdisable',
286 'gcstress0x3_jitstress1',
287 'gcstress0x3_jitstress2',
288 'gcstress0x3_jitstressregs1',
289 'gcstress0x3_jitstressregs2',
290 'gcstress0x3_jitstressregs3',
291 'gcstress0x3_jitstressregs4',
292 'gcstress0x3_jitstressregs8',
293 'gcstress0x3_jitstressregs0x10',
294 'gcstress0x3_jitstressregs0x80',
295 'gcstress0x3_jitstressregs0x1000',
296 'gcstress0xc_jitstressregs1',
297 'gcstress0xc_jitstressregs2',
298 'gcstress0xc_jitstressregs3',
299 'gcstress0xc_jitstressregs4',
300 'gcstress0xc_jitstressregs8',
301 'gcstress0xc_jitstressregs0x10',
302 'gcstress0xc_jitstressregs0x80',
303 'gcstress0xc_jitstressregs0x1000'
306 def static validLinuxArmScenarios = [
316 // 'gc_reliability_framework'
318 // 'corefx_innerloop'
319 'crossgen_comparison',
323 'r2r_jitstress1_tiered',
324 'r2r_jitstress2_tiered',
325 'r2r_jitstressregs1',
326 'r2r_jitstressregs2',
327 'r2r_jitstressregs3',
328 'r2r_jitstressregs4',
329 'r2r_jitstressregs8',
330 'r2r_jitstressregs0x10',
331 'r2r_jitstressregs0x80',
332 'r2r_jitstressregs0x1000',
334 'r2r_jitforcerelocs',
336 'r2r_no_tiered_compilation',
339 'no_tiered_compilation',
340 'no_tiered_compilation_innerloop',
353 'jitstressregs0x1000',
354 'jitstress2_jitstressregs1',
355 'jitstress2_jitstressregs2',
356 'jitstress2_jitstressregs3',
357 'jitstress2_jitstressregs4',
358 'jitstress2_jitstressregs8',
359 'jitstress2_jitstressregs0x10',
360 'jitstress2_jitstressregs0x80',
361 'jitstress2_jitstressregs0x1000',
363 // 'jitsse2only' // Only relevant to xarch
364 // 'jitnosimd' // Only interesting on platforms where SIMD support exists.
365 // 'jitincompletehwintrinsic'
366 // 'jitx86hwintrinsicnoavx'
367 // 'jitx86hwintrinsicnoavx2'
368 // 'jitx86hwintrinsicnosimd'
369 // 'jitnox86hwintrinsic'
372 'corefx_tieredcompilation',
375 'corefx_jitstressregs1',
376 'corefx_jitstressregs2',
377 'corefx_jitstressregs3',
378 'corefx_jitstressregs4',
379 'corefx_jitstressregs8',
380 'corefx_jitstressregs0x10',
381 'corefx_jitstressregs0x80',
382 'corefx_jitstressregs0x1000',
387 'gcstress0xc_zapdisable',
388 'gcstress0xc_zapdisable_jitstress2',
389 'gcstress0xc_zapdisable_heapverify1',
390 'gcstress0xc_jitstress1',
391 'gcstress0xc_jitstress2',
392 'gcstress0xc_minopts_heapverify1'
395 def static validLinuxArm64Scenarios = [
405 // 'gc_reliability_framework'
407 // 'corefx_innerloop'
408 'crossgen_comparison',
412 'r2r_jitstress1_tiered',
413 'r2r_jitstress2_tiered',
414 'r2r_jitstressregs1',
415 'r2r_jitstressregs2',
416 'r2r_jitstressregs3',
417 'r2r_jitstressregs4',
418 'r2r_jitstressregs8',
419 'r2r_jitstressregs0x10',
420 'r2r_jitstressregs0x80',
421 'r2r_jitstressregs0x1000',
423 'r2r_jitforcerelocs',
425 'r2r_no_tiered_compilation',
428 'no_tiered_compilation',
429 'no_tiered_compilation_innerloop',
442 'jitstressregs0x1000',
443 'jitstress2_jitstressregs1',
444 'jitstress2_jitstressregs2',
445 'jitstress2_jitstressregs3',
446 'jitstress2_jitstressregs4',
447 'jitstress2_jitstressregs8',
448 'jitstress2_jitstressregs0x10',
449 'jitstress2_jitstressregs0x80',
450 'jitstress2_jitstressregs0x1000',
452 // 'jitsse2only' // Only relevant to xarch
453 'jitnosimd', // Only interesting on platforms where SIMD support exists.
454 // 'jitincompletehwintrinsic'
455 // 'jitx86hwintrinsicnoavx'
456 // 'jitx86hwintrinsicnoavx2'
457 // 'jitx86hwintrinsicnosimd'
458 // 'jitnox86hwintrinsic'
461 'corefx_tieredcompilation',
464 'corefx_jitstressregs1',
465 'corefx_jitstressregs2',
466 'corefx_jitstressregs3',
467 'corefx_jitstressregs4',
468 'corefx_jitstressregs8',
469 'corefx_jitstressregs0x10',
470 'corefx_jitstressregs0x80',
471 'corefx_jitstressregs0x1000',
476 'gcstress0xc_zapdisable',
477 'gcstress0xc_zapdisable_jitstress2',
478 'gcstress0xc_zapdisable_heapverify1',
479 'gcstress0xc_jitstress1',
480 'gcstress0xc_jitstress2',
481 'gcstress0xc_minopts_heapverify1'
484 def static configurationList = ['Debug', 'Checked', 'Release']
486 // This is the set of architectures
487 // Some of these are pseudo-architectures:
488 // armem -- ARM builds/runs using an emulator. Used for Tizen runs.
489 def static architectureList = ['arm', 'armem', 'arm64', 'x64', 'x86']
491 // This set of architectures that cross build on Windows and run on Windows ARM64 hardware.
492 def static armWindowsCrossArchitectureList = ['arm', 'arm64']
495 // **************************************************************
496 // Create some specific views
498 // These aren't using the Utilities.addStandardFolderView() function, because that creates
499 // views based on a single regular expression. These views will be generated by adding a
500 // specific set of jobs to them.
502 // Utilities.addStandardFolderView() also creates a lot of additional stuff around the
503 // view, like "Build Statistics", "Job Statistics", "Unstable Jobs". Until it is determined
504 // those are required, don't add them (which simplifies the view pages, as well).
505 // **************************************************************
508 def static MergeJobView = null
509 def static PeriodicJobView = null
510 def static ArchitectureViews = [:]
511 def static OSViews = [:]
514 // MergeJobView: include all jobs that execute when a PR change is merged.
515 Views.MergeJobView = listView('Merge') {
528 // PeriodicJobView: include all jobs that execute on a schedule
529 Views.PeriodicJobView = listView('Periodic') {
542 // Create a view for non-PR jobs for each architecture.
543 Constants.architectureList.each { architecture ->
544 Views.ArchitectureViews[architecture] = listView(architecture) {
558 // Create a view for non-PR jobs for each OS.
559 Constants.osList.each { os ->
560 // Don't create one for the special 'Windows_NT_BuildOnly'
561 if (os == 'Windows_NT_BuildOnly') {
564 Views.OSViews[os] = listView(os) {
578 def static addToMergeView(def job) {
579 Views.MergeJobView.with {
586 def static addToPeriodicView(def job) {
587 Views.PeriodicJobView.with {
594 def static addToViews(def job, def isFlowJob, def isPR, def architecture, def os, def configuration, def scenario) {
596 // No views want PR jobs currently.
600 // 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
601 // "top-level" jobs. Build only jobs are such jobs.
602 if (os == 'Windows_NT_BuildOnly') {
607 // For non-flow jobs, which ones are only used by flow jobs?
608 if ((architecture == 'arm') || (architecture == 'arm64')) {
609 if (isCoreFxScenario(scenario)) {
610 // We have corefx-specific scenario builds for each of the runs, but these are driven by flow jobs.
614 // We're left with the basic normal/innerloop builds. We might want to remove these from the views also, if desired.
615 // However, there are a few, like the Debug Build, that is build only, not "Build and Test", that we should leave.
619 // Add to architecture view.
620 Views.ArchitectureViews[architecture].with {
627 Views.OSViews[os].with {
634 def static addPeriodicTriggerHelper(def job, String cronString, boolean alwaysRuns = false) {
635 addToPeriodicView(job)
636 Utilities.addPeriodicTrigger(job, cronString, alwaysRuns)
639 def static addGithubPushTriggerHelper(def job) {
640 // Disable all Push trigger jobs. All jobs will need to be requested.
641 // addToMergeView(job)
642 // Utilities.addGithubPushTrigger(job)
646 def static setMachineAffinity(def job, def os, def architecture, def options = null) {
647 assert os instanceof String
648 assert architecture instanceof String
650 def armArches = ['arm', 'armem', 'arm64']
652 if (!(architecture in armArches)) {
653 assert options == null
654 Utilities.setMachineAffinity(job, os, 'latest-or-auto')
659 // This is an arm(64) job.
661 // There are several options.
665 // Arm32 (Build) -> latest-arm64
666 // |-> os == "Windows_NT" && (architecture == "arm") && options['use_arm64_build_machine'] == true
667 // Arm32 (Test) -> arm64-windows_nt
668 // |-> os == "Windows_NT" && (architecture == "arm") && options['use_arm64_build_machine'] == false
670 // Arm64 (Build) -> latest-arm64
671 // |-> os == "Windows_NT" && architecture == "arm64" && options['use_arm64_build_machine'] == true
672 // Arm64 (Test) -> arm64-windows_nt
673 // |-> os == "Windows_NT" && architecture == "arm64" && options['use_arm64_build_machine'] == false
677 // Arm32 emulator (Build, Test) -> arm-cross-latest
678 // |-> os == "Tizen" && (architecture == "armem")
680 // Arm32 hardware (Flow) -> Ubuntu 16.04 latest-or-auto (don't use limited arm hardware)
681 // |-> os == "Ubuntu" && (architecture == "arm") && options['is_flow_job'] == true
682 // Arm32 hardware (Build) -> Ubuntu 16.04 latest-or-auto
683 // |-> os == "Ubuntu" && (architecture == "arm") && options['is_build_job'] == true
684 // Arm32 hardware (Test) -> Helix ubuntu.1404.arm32.open queue
685 // |-> os == "Ubuntu" && (architecture == "arm")
687 // Arm64 (Build) -> arm64-cross-latest
688 // |-> os != "Windows_NT" && architecture == "arm64" && options['is_build_job'] == true
689 // Arm64 (Test) -> Helix Ubuntu.1604.Arm64.Iron.Open queue
690 // |-> os != "Windows_NT" && architecture == "arm64"
692 // Note: we are no longer using Jenkins tags "arm64-huge-page-size", "arm64-small-page-size".
693 // Support for Linux arm64 large page size has been removed for now, as it wasn't being used.
695 // Note: we are no longer using Jenkins tag 'latest-arm64' for arm/arm64 Windows build machines. Instead,
696 // we are using public VS2017 arm/arm64 tools in a VM from Helix.
698 // This has to be a arm arch
699 assert architecture in armArches
700 if (os == "Windows_NT") {
701 // arm32/arm64 Windows jobs share the same machines for now
702 def isBuild = options['use_arm64_build_machine'] == true
704 if (isBuild == true) {
706 label('Windows.10.Amd64.ClientRS4.DevEx.Open')
709 Utilities.setMachineAffinity(job, 'windows.10.arm64.open')
712 assert os != 'Windows_NT'
714 if (architecture == 'armem') {
715 // arm emulator (Tizen). Build and test on same machine,
718 Utilities.setMachineAffinity(job, 'Ubuntu', 'arm-cross-latest')
721 // arm/arm64 Ubuntu on hardware.
722 assert architecture == 'arm' || architecture == 'arm64'
723 def isFlow = (options != null) && (options['is_flow_job'] == true)
724 def isBuild = (options != null) && (options['is_build_job'] == true)
725 if (isFlow || isBuild) {
726 // arm/arm64 Ubuntu build machine. Build uses docker, so the actual host OS is not
727 // very important. Therefore, use latest or auto. Flow jobs don't need to use arm hardware.
728 Utilities.setMachineAffinity(job, 'Ubuntu16.04', 'latest-or-auto')
730 // arm/arm64 Ubuntu test machine. Specify the Helix queue name here.
731 if (architecture == 'arm64') {
732 assert os == 'Ubuntu16.04'
734 label('Ubuntu.1604.Arm64.Iron.Open')
738 assert os == 'Ubuntu'
740 label('ubuntu.1404.arm32.open')
748 // setJobMachineAffinity: compute the machine affinity options for a job,
749 // then set the job with those affinity options.
750 def static setJobMachineAffinity(def architecture, def os, def isBuildJob, def isTestJob, def isFlowJob, def job)
752 assert (isBuildJob && !isTestJob && !isFlowJob) ||
753 (!isBuildJob && isTestJob && !isFlowJob) ||
754 (!isBuildJob && !isTestJob && isFlowJob)
756 def affinityOptions = null
757 def affinityArchitecture = architecture
759 if (os == "Windows_NT") {
760 if (architecture in Constants.armWindowsCrossArchitectureList) {
762 affinityOptions = [ "use_arm64_build_machine" : true ]
763 } else if (isTestJob) {
764 affinityOptions = [ "use_arm64_build_machine" : false ]
765 } else if (isFlowJob) {
766 // For the flow jobs set the machine affinity as x64
767 affinityArchitecture = 'x64'
772 if ((architecture == 'arm64') || (architecture == 'arm')) {
774 affinityOptions = ['is_build_job': true]
775 } else if (isFlowJob) {
776 affinityOptions = ['is_flow_job': true]
781 setMachineAffinity(job, os, affinityArchitecture, affinityOptions)
784 def static isGCStressRelatedTesting(def scenario) {
785 // The 'r2r_gcstress15' scenario is a basic scenario.
786 // Detect it and make it a GCStress related.
787 if (scenario == 'r2r_gcstress15')
792 def gcStressTestEnvVars = [ 'COMPlus_GCStress', 'COMPlus_ZapDisable', 'COMPlus_HeapVerify']
793 def scenarioName = scenario.toLowerCase()
794 def isGCStressTesting = false
795 Constants.jitStressModeScenarios[scenario].each{ k, v ->
796 if (k in gcStressTestEnvVars) {
797 isGCStressTesting = true;
800 return isGCStressTesting
803 def static isCoreFxScenario(def scenario) {
804 def corefx_prefix = 'corefx_'
805 if (scenario.length() < corefx_prefix.length()) {
808 return scenario.substring(0,corefx_prefix.length()) == corefx_prefix
811 def static isR2RBaselineScenario(def scenario) {
812 return (scenario == 'r2r')
815 def static isR2RStressScenario(def scenario) {
816 return Constants.r2rStressScenarios.containsKey(scenario)
819 def static isR2RScenario(def scenario) {
820 return isR2RBaselineScenario(scenario) || isR2RStressScenario(scenario)
823 def static isJitStressScenario(def scenario) {
824 return Constants.jitStressModeScenarios.containsKey(scenario)
827 def static isLongGc(def scenario) {
828 return (scenario == 'longgc' || scenario == 'gcsimulator')
831 def static isJitDiff(def scenario) {
832 return (scenario == 'jitdiff')
835 def static isGcReliabilityFramework(def scenario) {
836 return (scenario == 'gc_reliability_framework')
839 def static isArmWindowsScenario(def scenario) {
840 return Constants.validArmWindowsScenarios.contains(scenario)
843 def static isValidPrTriggeredInnerLoopJob(os, architecture, configuration, isBuildOnly) {
844 if (isBuildOnly == true) {
845 os = 'Windows_NT_BuildOnly'
848 def validOsPrTriggerArchConfigs = Constants.prTriggeredValidInnerLoopCombos[os]
849 if (validOsPrTriggerArchConfigs != null) {
850 def validOsPrTriggerConfigs = validOsPrTriggerArchConfigs[architecture]
851 if (validOsPrTriggerConfigs != null) {
852 if (configuration in validOsPrTriggerConfigs) {
861 // This means the job builds and runs the 'innerloop' test set. This does not mean the job is
862 // scheduled with a default PR trigger despite the correlation being true at the moment.
863 def static isInnerloopTestScenario(def scenario) {
864 return (scenario == 'innerloop' || scenario == 'no_tiered_compilation_innerloop')
867 def static isCrossGenComparisonScenario(def scenario) {
868 return (scenario == 'crossgen_comparison')
871 def static shouldGenerateCrossGenComparisonJob(def os, def architecture, def configuration, def scenario) {
872 assert isCrossGenComparisonScenario(scenario)
873 return ((os == 'Ubuntu' && architecture == 'arm') || (os == 'Ubuntu16.04' && architecture == 'arm64')) && (configuration == 'Checked' || configuration == 'Release')
876 def static getFxBranch(def branch) {
877 def fxBranch = branch
878 // Map 'dev/unix_test_workflow' to 'master' so we can test CoreFX jobs in the CoreCLR dev/unix_test_workflow
879 // branch even though CoreFX doesn't have such a branch.
880 if (branch == 'dev/unix_test_workflow') {
886 def static setJobTimeout(newJob, isPR, architecture, configuration, scenario, isBuildOnly) {
887 // 2 hours (120 minutes) is the default timeout
890 if (!isInnerloopTestScenario(scenario)) {
891 // Pri-1 test builds take a long time (see calculateBuildCommands()). So up the Pri-1 build jobs timeout.
896 // Note that these can only increase, never decrease, the Pri-1 timeout possibly set above.
897 if (isGCStressRelatedTesting(scenario)) {
900 else if (isCoreFxScenario(scenario)) {
903 else if (isJitStressScenario(scenario)) {
906 else if (isR2RBaselineScenario(scenario)) {
909 else if (isLongGc(scenario)) {
912 else if (isJitDiff(scenario)) {
915 else if (isGcReliabilityFramework(scenario)) {
918 else if (architecture == 'armem' || architecture == 'arm64') {
922 if (architecture == 'arm') {
923 // ARM32 machines are particularly slow.
928 if (configuration == 'Debug') {
929 // Debug runs can be very slow. Add an hour.
933 // If we've changed the timeout from the default, set it in the job.
935 if (timeout != 120) {
936 Utilities.setJobTimeout(newJob, timeout)
940 def static getJobFolder(def scenario) {
941 if (isJitStressScenario(scenario) || isR2RStressScenario(scenario)) {
944 if (scenario == 'illink') {
950 def static getStressModeDisplayName(def scenario) {
952 Constants.jitStressModeScenarios[scenario].each{ k, v ->
953 def prefixLength = 'COMPlus_'.length()
954 if (k.length() >= prefixLength) {
955 def modeName = k.substring(prefixLength, k.length())
956 if (displayStr != '') {
957 // Separate multiple variables with a space.
960 displayStr += modeName + '=' + v
964 if (isCoreFxScenario(scenario)) {
965 displayStr = ('CoreFx ' + displayStr).trim()
971 def static getR2RDisplayName(def scenario) {
972 // Assume the scenario name is one from the r2rStressScenarios dict, and remove its "r2r_" prefix.
973 def displayStr = scenario
974 def prefixLength = 'r2r_'.length()
975 if (displayStr.length() >= prefixLength) {
976 displayStr = "R2R " + displayStr.substring(prefixLength, displayStr.length())
977 } else if (scenario == 'r2r') {
983 def static getScenarioDisplayString(def scenario) {
986 return "Innerloop Build and Test"
988 case 'no_tiered_compilation_innerloop':
989 def displayStr = getStressModeDisplayName(scenario)
990 return "Innerloop Build and Test (Jit - ${displayStr})"
992 case 'corefx_innerloop':
993 return "CoreFX Tests"
996 return "Build and Test"
999 return "Jit Diff Build and Test"
1002 return "IL RoundTrip Build and Test"
1005 return "Long-Running GC Build & Test"
1008 return "GC Simulator"
1010 case 'standalone_gc':
1011 return "Standalone GC"
1013 case 'gc_reliability_framework':
1014 return "GC Reliability Framework"
1020 if (isJitStressScenario(scenario)) {
1021 def displayStr = getStressModeDisplayName(scenario)
1022 return "Build and Test (Jit - ${displayStr})"
1024 else if (isR2RScenario(scenario)) {
1025 def displayStr = getR2RDisplayName(scenario)
1026 return "${displayStr} Build and Test"
1029 return "${scenario}"
1034 println("Unknown scenario: ${scenario}");
1039 // Functions to create an environment script.
1040 // envScriptCreate -- initialize the script (call first)
1041 // envScriptFinalize -- finalize the script (call last)
1042 // envScriptSetStressModeVariables -- set stress mode variables in the env script
1043 // envScriptAppendExistingScript -- append an existing script to the generated script
1045 // Each script returns a string of commands. Concatenate all the strings together before
1046 // adding them to the builds commands, to make sure they get executed as one Jenkins script.
1049 // Initialize the environment setting script.
1050 def static envScriptCreate(def os, def stepScriptLocation) {
1052 if (os == 'Windows_NT') {
1053 stepScript += "echo Creating TestEnv script\r\n"
1054 stepScript += "if exist ${stepScriptLocation} del ${stepScriptLocation}\r\n"
1056 // Create at least an empty script.
1057 stepScript += "echo. > ${stepScriptLocation}\r\n"
1060 stepScript += "echo Creating environment setting script\n"
1061 stepScript += "echo \\#\\!/usr/bin/env bash > ${stepScriptLocation}\n"
1067 // Generates the string for setting stress mode variables.
1068 def static envScriptSetStressModeVariables(def os, def stressModeVars, def stepScriptLocation) {
1070 if (os == 'Windows_NT') {
1071 stressModeVars.each{ k, v ->
1072 // Write out what we are writing to the script file
1073 stepScript += "echo Setting ${k}=${v}\r\n"
1074 // Write out the set itself to the script file`
1075 stepScript += "echo set ${k}=${v} >> ${stepScriptLocation}\r\n"
1079 stressModeVars.each{ k, v ->
1080 // Write out what we are writing to the script file
1081 stepScript += "echo Setting ${k}=${v}\n"
1082 // Write out the set itself to the script file`
1083 stepScript += "echo export ${k}=${v} >> ${stepScriptLocation}\n"
1090 // Append an existing script to an environment script.
1091 // Returns string of commands to do this.
1092 def static envScriptAppendExistingScript(def os, def appendScript, def stepScriptLocation) {
1093 assert (os == 'Windows_NT')
1096 stepScript += "echo Appending ${appendScript} to ${stepScriptLocation}\r\n"
1097 stepScript += "type ${appendScript} >> ${stepScriptLocation}\r\n"
1102 // Finalize an environment setting script.
1103 // Returns string of commands to do this.
1104 def static envScriptFinalize(def os, def stepScriptLocation) {
1107 if (os == 'Windows_NT') {
1108 // Display the resulting script. This is useful when looking at the output log file.
1109 stepScript += "echo Display the total script ${stepScriptLocation}\r\n"
1110 stepScript += "type ${stepScriptLocation}\r\n"
1113 stepScript += "chmod +x ${stepScriptLocation}\n"
1119 def static isNeedDocker(def architecture, def os, def isBuild) {
1121 if (architecture == 'x86' && os == 'Ubuntu') {
1124 else if (architecture == 'armem') {
1127 else if (architecture == 'arm') {
1128 if (os == 'Ubuntu') {
1132 else if (architecture == 'arm64') {
1133 if (os == 'Ubuntu16.04') {
1139 if (architecture == 'x86' && os == 'Ubuntu') {
1146 def static getDockerImageName(def architecture, def os, def isBuild) {
1147 // We must change some docker private images to official later
1149 if (architecture == 'x86' && os == 'Ubuntu') {
1150 return "hseok82/dotnet-buildtools-prereqs:ubuntu-16.04-crossx86-ef0ac75-20175511035548"
1152 else if (architecture == 'armem') {
1153 if (os == 'Tizen') {
1154 return "tizendotnet/dotnet-buildtools-prereqs:ubuntu-16.04-cross-e435274-20180426002255-tizen-rootfs-5.0m1"
1157 else if (architecture == 'arm') {
1158 if (os == 'Ubuntu') {
1159 return "mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-14.04-cross-e435274-20180426002420"
1162 else if (architecture == 'arm64') {
1163 if (os == 'Ubuntu16.04') {
1164 return "mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-16.04-cross-arm64-a3ae44b-20180315221921"
1169 if (architecture == 'x86' && os == 'Ubuntu') {
1170 return "hseok82/dotnet-buildtools-prereqs:ubuntu1604_x86_test"
1173 println("Unknown architecture to use docker: ${architecture} ${os}");
1177 def static getTestArtifactsTgzFileName(def osGroup, def architecture, def configuration) {
1178 return "bin-tests-${osGroup}.${architecture}.${configuration}.tgz"
1181 // We have a limited amount of some hardware. For these, scale back the periodic testing we do,
1182 // and only allowing using this hardware in some specific branches.
1183 def static jobRequiresLimitedHardware(def architecture, def os) {
1184 if (architecture == 'arm') {
1185 // arm Windows and Linux hardware is limited.
1188 else if (architecture == 'arm64') {
1189 // arm64 Windows and Linux hardware is limited.
1197 // Calculates the name of the build job based on some typical parameters.
1199 def static getJobName(def configuration, def architecture, def os, def scenario, def isBuildOnly) {
1200 // If the architecture is x64, do not add that info into the build name.
1201 // Need to change around some systems and other builds to pick up the right builds
1204 def suffix = scenario != 'normal' ? "_${scenario}" : '';
1209 switch (architecture) {
1211 if (scenario == 'normal') {
1212 // For now we leave x64 off of the name for compatibility with other jobs
1213 baseName = configuration.toLowerCase() + '_' + os.toLowerCase()
1215 else if (scenario == 'formatting') {
1216 // we don't care about the configuration for the formatting job. It runs all configs
1217 baseName = architecture.toLowerCase() + '_' + os.toLowerCase()
1220 baseName = architecture.toLowerCase() + '_' + configuration.toLowerCase() + '_' + os.toLowerCase()
1224 // These are cross builds
1225 assert os == 'Tizen'
1226 baseName = 'armel_cross_' + configuration.toLowerCase() + '_' + os.toLowerCase()
1230 // These are cross builds
1231 baseName = architecture.toLowerCase() + '_cross_' + configuration.toLowerCase() + '_' + os.toLowerCase()
1234 baseName = architecture.toLowerCase() + '_' + configuration.toLowerCase() + '_' + os.toLowerCase()
1237 println("Unknown architecture: ${architecture}");
1242 return baseName + suffix
1245 def static addNonPRTriggers(def job, def branch, def isPR, def architecture, def os, def configuration, def scenario, def isFlowJob, def isWindowsBuildOnlyJob, def bidailyCrossList) {
1247 // The dev/unix_test_workflow branch is used for Jenkins CI testing. We generally do not need any non-PR
1248 // triggers in the branch, because that would use machine resources unnecessarily.
1249 if (branch == 'dev/unix_test_workflow') {
1253 // Limited hardware is restricted for non-PR triggers to certain branches.
1254 if (jobRequiresLimitedHardware(architecture, os) && (!(branch in Constants.LimitedHardwareBranches))) {
1258 // Ubuntu x86 CI jobs are failing. Disable non-PR triggered jobs to avoid these constant failures
1259 // until this is fixed. Tracked by https://github.com/dotnet/coreclr/issues/19003.
1260 if (architecture == 'x86' && os == 'Ubuntu') {
1264 def isNormalOrInnerloop = (scenario == "normal" || scenario == "innerloop")
1268 case 'crossgen_comparison':
1269 if (isFlowJob && (configuration == 'Checked' || configuration == 'Release')) {
1270 if (os == 'Ubuntu' && architecture == 'arm') {
1271 // Not enough Linux/arm32 hardware for this.
1272 // addPeriodicTriggerHelper(job, '@daily')
1274 if (os == 'Ubuntu16.04' && architecture == 'arm64') {
1275 addPeriodicTriggerHelper(job, '@daily')
1280 case 'pmi_asm_diffs':
1281 // No non-PR triggers for now.
1285 switch (architecture) {
1288 if (isFlowJob && architecture == 'x86' && os == 'Ubuntu') {
1289 addPeriodicTriggerHelper(job, '@daily')
1291 else if (isFlowJob || os == 'Windows_NT' || (architecture == 'x64' && !(os in Constants.crossList))) {
1292 addGithubPushTriggerHelper(job)
1296 if (os == 'Windows_NT') {
1297 if (isFlowJob || (isNormalOrInnerloop && (configuration == 'Debug'))) {
1298 // We would normally want a per-push trigger, but with limited hardware we can't keep up.
1299 // Do the builds daily.
1300 addPeriodicTriggerHelper(job, '@daily')
1304 // Only the flow jobs get push triggers; the build and test jobs are triggered by the flow job.
1306 addPeriodicTriggerHelper(job, '@daily')
1311 if (os == 'Windows_NT') {
1312 if (isFlowJob || (isNormalOrInnerloop && (configuration == 'Debug'))) {
1313 // We would normally want a push trigger, but with limited hardware we can't keep up.
1314 // Do the builds daily.
1315 addPeriodicTriggerHelper(job, '@daily')
1319 assert os == 'Ubuntu'
1320 // Only the flow jobs get push triggers; the build and test jobs are triggered by the flow job.
1322 // Currently no push triggers, with limited arm Linux hardware.
1323 // TODO: If we have enough machine capacity, add some arm Linux push triggers.
1325 // Duplicated by AzDO
1326 // addPeriodicTriggerHelper(job, '@daily')
1331 addGithubPushTriggerHelper(job)
1334 println("Unknown architecture: ${architecture}");
1340 assert !(os in bidailyCrossList)
1341 // r2r gets a push trigger for checked/release
1342 if (configuration == 'Checked' || configuration == 'Release') {
1343 if (architecture == 'x64' && os != 'OSX10.12') {
1344 //Flow jobs should be Windows, Ubuntu, OSX0.12, or CentOS
1345 if (isFlowJob || os == 'Windows_NT') {
1346 addGithubPushTriggerHelper(job)
1348 // OSX10.12 r2r jobs should only run every 12 hours, not daily.
1349 } else if (architecture == 'x64' && os == 'OSX10.12'){
1351 addPeriodicTriggerHelper(job, 'H H/12 * * *')
1354 // For x86, only add per-commit jobs for Windows
1355 else if (architecture == 'x86') {
1356 if (os == 'Windows_NT') {
1357 addGithubPushTriggerHelper(job)
1360 // arm r2r jobs should only run weekly.
1361 else if (architecture == 'arm') {
1363 // Linux arm32 done in AzDO
1364 if (os == 'Windows_NT') {
1365 addPeriodicTriggerHelper(job, '@weekly')
1369 // arm64 r2r jobs should only run weekly.
1370 else if (architecture == 'arm64') {
1372 addPeriodicTriggerHelper(job, '@weekly')
1377 case 'r2r_jitstress1':
1378 case 'r2r_jitstress2':
1379 case 'r2r_jitstress1_tiered':
1380 case 'r2r_jitstress2_tiered':
1381 case 'r2r_jitstressregs1':
1382 case 'r2r_jitstressregs2':
1383 case 'r2r_jitstressregs3':
1384 case 'r2r_jitstressregs4':
1385 case 'r2r_jitstressregs8':
1386 case 'r2r_jitstressregs0x10':
1387 case 'r2r_jitstressregs0x80':
1388 case 'r2r_jitstressregs0x1000':
1389 case 'r2r_jitminopts':
1390 case 'r2r_jitforcerelocs':
1391 case 'r2r_gcstress15':
1392 case 'r2r_no_tiered_compilation':
1393 assert !(os in bidailyCrossList)
1395 // GCStress=C is currently not supported on OS X
1396 if (os == 'OSX10.12' && isGCStressRelatedTesting(scenario)) {
1400 if (configuration == 'Checked' || configuration == 'Release') {
1401 if (architecture == 'x64') {
1402 //Flow jobs should be Windows, Ubuntu, OSX10.12, or CentOS
1403 if (isFlowJob || os == 'Windows_NT') {
1404 addPeriodicTriggerHelper(job, 'H H * * 3,6') // some time every Wednesday and Saturday
1407 // For x86, only add periodic jobs for Windows
1408 else if (architecture == 'x86') {
1409 if (os == 'Windows_NT') {
1410 addPeriodicTriggerHelper(job, 'H H * * 3,6') // some time every Wednesday and Saturday
1413 else if (architecture == 'arm') {
1415 // Linux arm32 duplicated by AzDO
1416 if (os == 'Windows_NT') {
1417 addPeriodicTriggerHelper(job, '@weekly')
1421 else if (architecture == 'arm64') {
1423 addPeriodicTriggerHelper(job, '@weekly')
1429 assert (os == 'Ubuntu' || os == 'Windows_NT' || os == 'OSX10.12')
1430 assert configuration == 'Release'
1431 assert architecture == 'x64'
1432 addPeriodicTriggerHelper(job, '@daily')
1433 // TODO: Add once external email sending is available again
1434 // addEmailPublisher(job, 'dotnetgctests@microsoft.com')
1437 assert (os == 'Ubuntu' || os == 'Windows_NT' || os == 'OSX10.12')
1438 assert configuration == 'Release'
1439 assert architecture == 'x64'
1440 addPeriodicTriggerHelper(job, 'H H * * 3,6') // some time every Wednesday and Saturday
1441 // TODO: Add once external email sending is available again
1442 // addEmailPublisher(job, 'dotnetgctests@microsoft.com')
1444 case 'standalone_gc':
1445 assert (os == 'Ubuntu' || os == 'Windows_NT' || os == 'OSX10.12')
1446 assert (configuration == 'Release' || configuration == 'Checked')
1447 // TODO: Add once external email sending is available again
1448 // addEmailPublisher(job, 'dotnetgctests@microsoft.com')
1449 addPeriodicTriggerHelper(job, '@daily')
1451 case 'gc_reliability_framework':
1452 assert (os == 'Ubuntu' || os == 'Windows_NT' || os == 'OSX10.12')
1453 assert (configuration == 'Release' || configuration == 'Checked')
1454 // Only triggered by phrase.
1457 assert !(os in bidailyCrossList)
1458 // ILASM/ILDASM roundtrip one gets a daily build, and only for release
1459 if (architecture == 'x64' && configuration == 'Release') {
1460 if (isFlowJob || os == 'Windows_NT') {
1461 addPeriodicTriggerHelper(job, '@daily')
1466 assert (os == 'Ubuntu' || os == 'Windows_NT' || os == 'OSX10.12')
1467 assert configuration == 'Checked'
1468 assert (architecture == 'x64' || architecture == 'x86')
1469 addGithubPushTriggerHelper(job)
1472 assert (os == 'Windows_NT' || os == "Ubuntu")
1473 assert architecture == 'x64'
1474 addGithubPushTriggerHelper(job)
1476 case 'jitstressregs1':
1477 case 'jitstressregs2':
1478 case 'jitstressregs3':
1479 case 'jitstressregs4':
1480 case 'jitstressregs8':
1481 case 'jitstressregs0x10':
1482 case 'jitstressregs0x80':
1483 case 'jitstressregs0x1000':
1485 case 'tieredcompilation':
1486 case 'no_tiered_compilation':
1490 case 'jitstress1_tiered':
1491 case 'jitstress2_tiered':
1492 case 'jitstress2_jitstressregs1':
1493 case 'jitstress2_jitstressregs2':
1494 case 'jitstress2_jitstressregs3':
1495 case 'jitstress2_jitstressregs4':
1496 case 'jitstress2_jitstressregs8':
1497 case 'jitstress2_jitstressregs0x10':
1498 case 'jitstress2_jitstressregs0x80':
1499 case 'jitstress2_jitstressregs0x1000':
1500 case 'tailcallstress':
1503 case 'jitnox86hwintrinsic':
1504 case 'jitincompletehwintrinsic':
1505 case 'jitx86hwintrinsicnoavx':
1506 case 'jitx86hwintrinsicnoavx2':
1507 case 'jitx86hwintrinsicnosimd':
1508 case 'corefx_baseline':
1509 case 'corefx_minopts':
1510 case 'corefx_tieredcompilation':
1511 case 'corefx_jitstress1':
1512 case 'corefx_jitstress2':
1513 case 'corefx_jitstressregs1':
1514 case 'corefx_jitstressregs2':
1515 case 'corefx_jitstressregs3':
1516 case 'corefx_jitstressregs4':
1517 case 'corefx_jitstressregs8':
1518 case 'corefx_jitstressregs0x10':
1519 case 'corefx_jitstressregs0x80':
1520 case 'corefx_jitstressregs0x1000':
1522 if (os == 'CentOS7.1') {
1525 if (os in bidailyCrossList) {
1528 if ((os == 'Ubuntu') && (architecture == 'arm') && !isCoreFxScenario(scenario)) {
1529 // Linux arm32 duplicated by AzDO
1532 // ARM corefx testing uses non-flow jobs to provide the configuration-specific
1533 // build for the flow job. We don't need cron jobs for these. Note that the
1534 // Windows ARM jobs depend on a Windows "build only" job that exits the trigger
1535 // function very early, so only non-Windows gets here.
1536 if ((architecture == 'arm') && isCoreFxScenario(scenario) && !isFlowJob) {
1539 if ((architecture == 'arm64') && isCoreFxScenario(scenario) && !isFlowJob) {
1542 if (jobRequiresLimitedHardware(architecture, os)) {
1543 if ((architecture == 'arm64') && (os == 'Ubuntu16.04')) {
1544 // These jobs are very fast on Linux/arm64 hardware, so run them daily.
1545 addPeriodicTriggerHelper(job, '@daily')
1547 else if (scenario == 'corefx_baseline') {
1548 addPeriodicTriggerHelper(job, '@daily')
1551 addPeriodicTriggerHelper(job, '@weekly')
1555 addPeriodicTriggerHelper(job, '@daily')
1560 if (os == 'CentOS7.1') {
1563 if (os in bidailyCrossList) {
1566 if ((os == 'Ubuntu') && (architecture == 'arm')) {
1567 // Linux arm32 duplicated by AzDO
1570 addPeriodicTriggerHelper(job, '@weekly')
1573 case 'gcstress0xc_zapdisable':
1574 case 'gcstress0xc_zapdisable_jitstress2':
1575 case 'gcstress0xc_zapdisable_heapverify1':
1576 case 'gcstress0xc_jitstress1':
1577 case 'gcstress0xc_jitstress2':
1578 case 'gcstress0xc_minopts_heapverify1':
1579 if (os == 'OSX10.12') {
1580 // GCStress=C is currently not supported on OS X
1583 if (os == 'CentOS7.1') {
1586 if (os in bidailyCrossList) {
1589 if ((os == 'Ubuntu') && (architecture == 'arm')) {
1590 // Linux arm32 duplicated by AzDO
1593 addPeriodicTriggerHelper(job, '@weekly')
1597 // Testing on other operating systems TBD
1598 assert (os == 'Windows_NT' || os == 'Ubuntu')
1599 if (architecture == 'x64' || architecture == 'x86') {
1600 if (configuration == 'Checked') {
1601 addPeriodicTriggerHelper(job, '@daily')
1607 println("Unknown scenario: ${scenario}");
1614 // **************************
1615 // Define the basic inner loop builds for PR and commit. This is basically just the set
1616 // of coreclr builds over linux/osx 10.12/windows and debug/release/checked. In addition, the windows
1617 // builds will do a couple extra steps.
1618 // **************************
1620 // Adds a trigger for the PR build if one is needed. If isFlowJob is true, then this is the
1621 // flow job that rolls up the build and test for non-windows OS's. // If the job is a windows build only job,
1622 // it's just used for internal builds
1623 // If you add a job with a trigger phrase, please add that phrase to coreclr/Documentation/project-docs/ci-trigger-phrases.md
1624 def static addTriggers(def job, def branch, def isPR, def architecture, def os, def configuration, def scenario, def isFlowJob, def isWindowsBuildOnlyJob) {
1625 def isNormalOrInnerloop = (scenario == "normal" || scenario == "innerloop")
1627 if (isWindowsBuildOnlyJob) {
1631 def bidailyCrossList = ['RHEL7.2', 'Debian8.4']
1632 // Non pull request builds.
1634 addNonPRTriggers(job, branch, isPR, architecture, os, configuration, scenario, isFlowJob, isWindowsBuildOnlyJob, bidailyCrossList)
1659 // Pull request builds. Generally these fall into two categories: default triggers and on-demand triggers
1660 // We generally only have a distinct set of default triggers but a bunch of on-demand ones.
1662 def contextString = ""
1663 def triggerString = ""
1664 def needsTrigger = true
1665 def isDefaultTrigger = false
1666 def isArm64PrivateJob = false
1667 def scenarioString = ""
1669 // Set up default context string and trigger phrases. This is overridden in places, sometimes just to keep
1670 // the existing non-standard descriptions and phrases. In some cases, the scenarios are asymmetric, as for
1671 // some jobs where the Debug configuration just does builds, no tests.
1673 // Some configurations, like arm32/arm64, always use the exact scenario name as part of the context string.
1674 // This makes it possible to copy/paste the displayed context string as "@dotnet-bot test <context-string>"
1675 // to invoke the trigger. Any "fancy" context string makes that impossible, requiring the user to either
1676 // remember the mapping from context string to trigger string, or use "@dotnet-bot help" to look it up.
1678 if (architecture == 'armem') {
1679 assert os == 'Tizen'
1680 architecture = 'armel'
1683 switch (architecture) {
1687 contextString = "${os} ${architecture} Cross ${configuration}"
1688 triggerString = "(?i).*test\\W+${os}\\W+${architecture}\\W+Cross\\W+${configuration}"
1690 if (scenario == 'innerloop') {
1691 contextString += " Innerloop"
1692 triggerString += "\\W+Innerloop"
1695 contextString += " ${scenario}"
1696 triggerString += "\\W+${scenario}"
1699 if (scenario == 'pmi_asm_diffs') {
1700 // Don't add the "Build and Test" part
1702 else if (configuration == 'Debug') {
1703 contextString += " Build"
1704 triggerString += "\\W+Build"
1707 contextString += " Build and Test"
1708 triggerString += "\\W+Build and Test"
1711 triggerString += ".*"
1715 scenarioString = getScenarioDisplayString(scenario)
1716 contextString = "${os} ${architecture} ${configuration} ${scenarioString}"
1717 triggerString = "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}"
1721 triggerString += "\\W+Build and Test.*"
1724 case 'corefx_innerloop': // maintain this asymmetry
1725 triggerString += "\\W+CoreFX Tests.*"
1729 triggerString += "\\W+${scenario}.*"
1733 triggerString += ".*"
1737 // Now determine what kind of trigger this job needs, if any. Any job should be triggerable, except for
1738 // non-flow jobs that are only used as part of flow jobs.
1740 switch (architecture) {
1741 case 'x64': // editor brace matching: {
1742 if (scenario == 'formatting') {
1743 assert configuration == 'Checked'
1744 if (os == 'Windows_NT' || os == 'Ubuntu') {
1745 isDefaultTrigger = true
1746 contextString = "${os} ${architecture} Formatting"
1751 if (scenario == 'pmi_asm_diffs') {
1752 // Everything is already set.
1753 // No default triggers.
1758 // OpenSUSE, Debian & RedHat get trigger phrases for pri 0 build, and pri 1 build & test
1761 if (scenario == 'innerloop') {
1763 contextString = "${os} ${architecture} ${configuration} Innerloop Build"
1764 isDefaultTrigger = true
1774 assert scenario != 'innerloop'
1775 contextString = "${os} ${architecture} ${configuration} Build"
1776 triggerString = "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+Build.*"
1780 if (scenario == 'illink') {
1783 else if (scenario == 'corefx_innerloop') {
1784 if (configuration == 'Checked') {
1785 isDefaultTrigger = true
1793 // Triggers on the non-flow jobs aren't necessary here
1794 // Corefx testing uses non-flow jobs.
1795 if (!isFlowJob && !isCoreFxScenario(scenario)) {
1796 needsTrigger = false
1801 isDefaultTrigger = true
1804 case 'no_tiered_compilation_innerloop':
1805 if (os == 'Ubuntu') {
1806 isDefaultTrigger = true
1818 // CentOS uses checked for default PR tests while debug is build only
1819 if (configuration == 'Debug') {
1820 isDefaultTrigger = true
1821 contextString = "${os} ${architecture} ${configuration} Innerloop Build"
1825 // Make sure this is a flow job to get build and test.
1827 needsTrigger = false
1831 if (configuration == 'Checked') {
1832 assert job.name.contains("flow")
1833 isDefaultTrigger = true
1834 contextString = "${os} ${architecture} ${configuration} Innerloop Build and Test"
1839 // Make sure this is a flow job to get build and test.
1841 needsTrigger = false
1854 case 'no_tiered_compilation_innerloop':
1855 isDefaultTrigger = true
1858 case 'corefx_innerloop':
1859 if (configuration == 'Checked' || configuration == 'Release') {
1860 isDefaultTrigger = true
1870 println("Unknown os: ${os}");
1877 // editor brace matching: }
1879 case 'armel': // editor brace matching: {
1882 azureVMAgentPostBuildAction {
1883 agentPostBuildAction('Delete agent if the build was not successful (when idle).')
1890 if (scenario == 'innerloop') {
1891 if (configuration == 'Checked') {
1892 isDefaultTrigger = true
1899 // editor brace matching: }
1902 case 'arm64': // editor brace matching: {
1908 // Triggers on the non-flow jobs aren't necessary
1910 needsTrigger = false
1913 if (os == 'Ubuntu' && architecture == 'arm') {
1916 case 'no_tiered_compilation_innerloop':
1917 if (configuration == 'Checked') {
1918 isDefaultTrigger = true
1921 case 'crossgen_comparison':
1922 if (configuration == 'Checked' || configuration == 'Release') {
1923 isDefaultTrigger = true
1931 assert isArmWindowsScenario(scenario)
1933 // 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
1934 // the non-flow Build job. All others need a trigger on the flow job.
1935 def needsFlowJobTrigger = !(isNormalOrInnerloop && (configuration == 'Debug'))
1936 if (isFlowJob != needsFlowJobTrigger) {
1937 needsTrigger = false
1943 if (configuration == 'Checked') {
1944 isDefaultTrigger = true
1945 isArm64PrivateJob = true
1949 isArm64PrivateJob = true
1954 println("NYI os: ${os}");
1960 // editor brace matching: }
1961 case 'x86': // editor brace matching: {
1962 assert ((os == 'Windows_NT') || ((os == 'Ubuntu') && isNormalOrInnerloop))
1963 if (os == 'Ubuntu') {
1964 // Triggers on the non-flow jobs aren't necessary here
1966 needsTrigger = false
1970 // on-demand only for ubuntu x86
1971 contextString = "${os} ${architecture} ${configuration} Build"
1972 triggerString = "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}.*"
1977 case 'no_tiered_compilation_innerloop':
1978 isDefaultTrigger = true
1985 // editor brace matching: }
1988 println("Unknown architecture: ${architecture}");
1994 if (isArm64PrivateJob) {
1995 // ignore isDefaultTrigger to disable Jenkins by default
1997 Utilities.addDefaultPrivateGithubPRTriggerForBranch(job, branch, contextString, null, arm64Users)
2000 Utilities.addPrivateGithubPRTriggerForBranch(job, branch, contextString, triggerString, null, arm64Users)
2004 // ignore isDefaultTrigger to disable Jenkins by default
2006 Utilities.addGithubPRTriggerForBranch(job, branch, contextString)
2009 Utilities.addGithubPRTriggerForBranch(job, branch, contextString, triggerString)
2015 def static calculateBuildCommands(def newJob, def scenario, def branch, def isPR, def architecture, def configuration, def os, def isBuildOnly) {
2016 def buildCommands = []
2017 def osGroup = getOSGroup(os)
2018 def lowerConfiguration = configuration.toLowerCase()
2020 // Which set of tests to build? Innerloop tests build Pri-0.
2021 // Currently, we only generate asm diffs on Pri-0 tests, if we generate asm diffs on tests at all.
2022 // CoreFX testing skipts building tests altogether (done below).
2023 // All other scenarios build Pri-1 tests.
2025 if (isInnerloopTestScenario(scenario)) {
2029 def doCoreFxTesting = isCoreFxScenario(scenario)
2031 def buildCoreclrTests = true
2032 if (doCoreFxTesting || (scenario == 'pmi_asm_diffs')) {
2033 // These scenarios don't need the coreclr tests build.
2034 buildCoreclrTests = false
2037 // Calculate the build steps, archival, and xunit results
2039 case 'Windows_NT': // editor brace matching: {
2040 switch (architecture) {
2043 def arch = architecture
2046 if (scenario == 'formatting') {
2047 buildCommands += "python -u tests\\scripts\\format.py -c %WORKSPACE% -o Windows_NT -a ${arch}"
2048 Utilities.addArchival(newJob, "format.patch", "", true, false)
2052 if (scenario == 'illink') {
2053 buildCommands += "tests\\scripts\\build_illink.cmd clone ${arch}"
2056 // If it is a release build for Windows, ensure PGO is used, else fail the build.
2057 if ((lowerConfiguration == 'release') &&
2058 (scenario in Constants.basicScenarios)) {
2060 buildOpts += ' -enforcepgo'
2063 if (buildCoreclrTests) {
2064 buildOpts += " -priority=${priority}"
2066 buildOpts += ' skiptests';
2069 // Set __TestIntermediateDir to something short. If __TestIntermediateDir is already set, build-test.cmd will
2070 // output test binaries to that directory. If it is not set, the binaries are sent to a default directory whose name is about
2071 // 35 characters long.
2073 buildCommands += "set __TestIntermediateDir=int&&build.cmd ${lowerConfiguration} ${arch} ${buildOpts}"
2075 if (scenario == 'pmi_asm_diffs') {
2076 // Now, generate the layout. We don't have any tests, but we need to restore the packages before calling runtest.cmd.
2077 // Call build-test.cmd to do this. It will do a little more than we need, but that's ok.
2078 buildCommands += "build-test.cmd ${lowerConfiguration} ${arch} skipmanaged skipnative"
2079 buildCommands += "tests\\runtest.cmd ${lowerConfiguration} ${arch} GenerateLayoutOnly"
2081 // TODO: Add -target_branch and -commit_hash arguments based on GitHub variables.
2082 buildCommands += "python -u %WORKSPACE%\\tests\\scripts\\run-pmi-diffs.py -arch ${arch} -ci_arch ${architecture} -build_type ${configuration}"
2085 buildCommands += "powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('_\\pmi\\asm', '.\\dasm.${os}.${architecture}.${configuration}.zip')\"";
2088 Utilities.addArchival(newJob, "dasm.${os}.${architecture}.${configuration}.zip")
2093 def runtestArguments = ''
2094 def testOpts = 'collectdumps'
2096 if (isR2RScenario(scenario)) {
2098 // If this is a ReadyToRun scenario, pass 'crossgen'
2099 // to cause framework assemblies to be crossgen'ed. Pass 'runcrossgentests'
2100 // to cause the tests to be crossgen'ed.
2102 testOpts += ' crossgen runcrossgentests'
2104 else if (scenario == 'jitdiff') {
2105 testOpts += ' jitdisasm crossgen'
2107 else if (scenario == 'ilrt') {
2108 testOpts += ' ilasmroundtrip'
2110 else if (isLongGc(scenario)) {
2111 testOpts += " ${scenario} sequential"
2113 else if (scenario == 'standalone_gc') {
2114 testOpts += ' gcname clrgc.dll'
2116 else if (scenario == 'illink') {
2117 testOpts += " link %WORKSPACE%\\linker\\linker\\bin\\netcore_Release\\netcoreapp2.0\\win10-${arch}\\publish\\illink.exe"
2120 // Default per-test timeout is 10 minutes. For stress modes and Debug scenarios, increase this
2121 // to 30 minutes (30 * 60 * 1000 = 180000). The "timeout" argument to runtest.cmd sets this, by
2122 // taking a timeout value in milliseconds. (Note that it sets the __TestTimeout environment variable,
2123 // which is read by the xunit harness.)
2124 if (isJitStressScenario(scenario) || isR2RStressScenario(scenario) || (lowerConfiguration == 'debug'))
2126 def timeout = 1800000
2127 testOpts += " timeout ${timeout}"
2130 // If we are running a stress mode, we should write out the set of key
2131 // value env pairs to a file at this point and then we'll pass that to runtest.cmd
2133 def envScriptPath = ''
2134 if (isJitStressScenario(scenario) || isR2RStressScenario(scenario)) {
2135 def buildCommandsStr = ''
2136 envScriptPath = "%WORKSPACE%\\SetStressModes.bat"
2137 buildCommandsStr += envScriptCreate(os, envScriptPath)
2139 if (isJitStressScenario(scenario)) {
2140 buildCommandsStr += envScriptSetStressModeVariables(os, Constants.jitStressModeScenarios[scenario], envScriptPath)
2142 else if (isR2RStressScenario(scenario)) {
2143 buildCommandsStr += envScriptSetStressModeVariables(os, Constants.r2rStressScenarios[scenario], envScriptPath)
2146 envScriptFinalize(os, envScriptPath)
2148 // Note that buildCommands is an array of individually executed commands; we want all the commands used to
2149 // create the SetStressModes.bat script to be executed together, hence we accumulate them as strings
2150 // into a single script.
2151 buildCommands += buildCommandsStr
2153 if (envScriptPath != '') {
2154 testOpts += " TestEnv ${envScriptPath}"
2157 runtestArguments = "${lowerConfiguration} ${arch} ${testOpts}"
2159 if (doCoreFxTesting) {
2160 if (scenario == 'corefx_innerloop') {
2161 // Create CORE_ROOT and testhost
2162 buildCommands += "build-test.cmd ${lowerConfiguration} ${arch} buildtesthostonly"
2163 buildCommands += "tests\\runtest.cmd ${runtestArguments} CoreFXTestsAll"
2165 // Archive and process (only) the test results
2166 Utilities.addArchival(newJob, "bin/Logs/**/testResults.xml", "", /* doNotFailIfNothingArchived */ true, /* archiveOnlyIfSuccessful */ false)
2167 Utilities.addXUnitDotNETResults(newJob, "bin/Logs/**/testResults.xml")
2170 def workspaceRelativeFxRoot = "_/fx"
2171 def absoluteFxRoot = "%WORKSPACE%\\_\\fx"
2172 def fxBranch = getFxBranch(branch)
2173 def exclusionRspPath = "%WORKSPACE%\\tests\\scripts\\run-corefx-tests-exclusions.txt"
2175 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} -exclusion_rsp_file ${exclusionRspPath}"
2177 // Archive and process (only) the test results
2178 Utilities.addArchival(newJob, "${workspaceRelativeFxRoot}/artifacts/bin/**/testResults.xml", "", /* doNotFailIfNothingArchived */ true, /* archiveOnlyIfSuccessful */ false)
2179 Utilities.addXUnitDotNETResults(newJob, "${workspaceRelativeFxRoot}/artifacts/bin/**/testResults.xml")
2181 //Archive additional build stuff to diagnose why my attempt at fault injection isn't causing CI to fail
2182 Utilities.addArchival(newJob, "SetStressModes.bat", "", true, false)
2183 Utilities.addArchival(newJob, "${workspaceRelativeFxRoot}/artifacts/bin/testhost/**", "", true, false)
2186 else if (isGcReliabilityFramework(scenario)) {
2187 buildCommands += "tests\\runtest.cmd ${runtestArguments} GenerateLayoutOnly"
2188 buildCommands += "tests\\scripts\\run-gc-reliability-framework.cmd ${arch} ${configuration}"
2191 def buildCommandsStr = "call tests\\runtest.cmd ${runtestArguments}\r\n"
2193 // If we ran the tests, collect the test logs collected by xunit. We want to do this even if the tests fail, so we
2194 // must do it in the same batch file as the test run.
2196 buildCommandsStr += "echo on\r\n" // Show the following commands in the log. "echo" doesn't alter the errorlevel.
2197 buildCommandsStr += "set saved_errorlevel=%errorlevel%\r\n"
2198 buildCommandsStr += "powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('.\\bin\\tests\\${osGroup}.${arch}.${configuration}\\Reports', '.\\bin\\tests\\testReports.zip')\"\r\n";
2199 buildCommandsStr += "exit /b %saved_errorlevel%\r\n"
2201 def doNotFailIfNothingArchived = true
2202 def archiveOnlyIfSuccessful = false
2203 Utilities.addArchival(newJob, "bin/tests/testReports.zip", "", doNotFailIfNothingArchived, archiveOnlyIfSuccessful)
2205 buildCommands += buildCommandsStr
2207 } // end if (!isBuildOnly)
2209 if (!doCoreFxTesting) {
2210 // Run the rest of the build
2211 // Build the mscorlib for the other OS's
2212 buildCommands += "build.cmd ${lowerConfiguration} ${arch} linuxmscorlib"
2213 buildCommands += "build.cmd ${lowerConfiguration} ${arch} osxmscorlib"
2215 if (arch == 'x64') {
2216 buildCommands += "build.cmd ${lowerConfiguration} arm64 linuxmscorlib"
2219 if (!isJitStressScenario(scenario)) {
2220 // Zip up the tests directory so that we don't use so much space/time copying
2221 // 10s of thousands of files around.
2222 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')\"";
2224 // For Windows, pull full test results and test drops for x86/x64.
2225 // No need to pull for stress mode scenarios (downstream builds use the default scenario)
2226 Utilities.addArchival(newJob, "bin/Product/**,bin/tests/tests.zip", "bin/Product/**/.nuget/**")
2229 if (scenario == 'jitdiff') {
2230 // retrieve jit-dasm output for base commit, and run jit-diff
2232 // if this is a build only job, we want to keep the default (build) artifacts for the flow job
2233 Utilities.addArchival(newJob, "bin/tests/${osGroup}.${arch}.${configuration}/dasm/**")
2238 Utilities.addXUnitDotNETResults(newJob, 'bin/**/TestRun*.xml', true)
2242 // Archive the logs, even if the build failed (which is when they are most interesting).
2243 Utilities.addArchival(newJob, "bin/Logs/*.log,bin/Logs/*.wrn,bin/Logs/*.err,bin/Logs/MsbuildDebugLogs/*", "", /* doNotFailIfNothingArchived */ true, /* archiveOnlyIfSuccessful */ false)
2247 assert isArmWindowsScenario(scenario)
2251 if (buildCoreclrTests) {
2252 buildOpts += " -priority=${priority}"
2254 buildOpts += ' skiptests'
2257 // This is now a build only job. Do not run tests. Use the flow job.
2258 buildCommands += "set __TestIntermediateDir=int&&build.cmd ${lowerConfiguration} ${architecture} ${buildOpts}"
2260 if (doCoreFxTesting) {
2263 // Set the stress mode variables; this is incorporated into the generated CoreFx RunTests.cmd files.
2264 def envScriptPath = ''
2265 def buildCommandsStr = ''
2266 envScriptPath = "%WORKSPACE%\\SetStressModes.bat"
2267 buildCommandsStr += envScriptCreate(os, envScriptPath)
2268 buildCommandsStr += envScriptSetStressModeVariables(os, Constants.jitStressModeScenarios[scenario], envScriptPath)
2269 envScriptFinalize(os, envScriptPath)
2270 buildCommands += buildCommandsStr
2272 def workspaceRelativeFxRootLinux = "_/fx"
2273 def workspaceRelativeFxRootWin = "_\\fx"
2274 def absoluteFxRoot = "%WORKSPACE%\\_\\fx"
2275 def fxBranch = getFxBranch(branch)
2277 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"
2279 // Zip up the CoreFx runtime and tests. We don't need the CoreCLR binaries; they have been copied to the CoreFX tree.
2280 buildCommands += "powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('${workspaceRelativeFxRootWin}\\artifacts\\bin\\testhost\\netcoreapp-Windows_NT-Release-${architecture}', '${workspaceRelativeFxRootWin}\\fxruntime.zip')\"";
2281 buildCommands += "powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('${workspaceRelativeFxRootWin}\\artifacts\\bin\\tests', '${workspaceRelativeFxRootWin}\\fxtests.zip')\"";
2283 Utilities.addArchival(newJob, "${workspaceRelativeFxRootLinux}/fxruntime.zip")
2284 Utilities.addArchival(newJob, "${workspaceRelativeFxRootLinux}/fxtests.zip")
2286 // Zip up the tests directory so that we don't use so much space/time copying
2287 // 10s of thousands of files around.
2288 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')\"";
2291 Utilities.addArchival(newJob, "bin/Product/**,bin/tests/tests.zip", "bin/Product/**/.nuget/**")
2294 // Archive the logs, even if the build failed (which is when they are most interesting).
2295 Utilities.addArchival(newJob, "bin/Logs/*.log,bin/Logs/*.wrn,bin/Logs/*.err,bin/Logs/MsbuildDebugLogs/*", "", /* doNotFailIfNothingArchived */ true, /* archiveOnlyIfSuccessful */ false)
2298 println("Unknown architecture: ${architecture}");
2303 // end case 'Windows_NT'; editor brace matching: }
2312 case 'Fedora24': // editor brace matching: {
2313 switch (architecture) {
2315 if (os == 'Ubuntu') {
2316 // build and PAL test
2317 def dockerImage = getDockerImageName(architecture, os, true)
2318 buildCommands += "docker run -i --rm -v \${WORKSPACE}:/opt/code -w /opt/code -e ROOTFS_DIR=/crossrootfs/x86 ${dockerImage} ./build.sh ${architecture} cross ${lowerConfiguration}"
2319 dockerImage = getDockerImageName(architecture, os, false)
2320 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"
2321 Utilities.addArchival(newJob, "bin/Product/**,bin/obj/*/tests/**/*.so", "bin/Product/**/.nuget/**")
2322 Utilities.addXUnitDotNETResults(newJob, '**/pal_tests.xml')
2327 if (scenario == 'formatting') {
2328 buildCommands += "python tests/scripts/format.py -c \${WORKSPACE} -o Linux -a ${architecture}"
2329 Utilities.addArchival(newJob, "format.patch", "", true, false)
2333 if (scenario == 'pmi_asm_diffs') {
2334 buildCommands += "./build.sh ${lowerConfiguration} ${architecture} skiptests skipbuildpackages"
2335 buildCommands += "./build-test.sh ${lowerConfiguration} ${architecture} generatelayoutonly"
2337 // TODO: Add -target_branch and -commit_hash arguments based on GitHub variables.
2338 buildCommands += "python -u \${WORKSPACE}/tests/scripts/run-pmi-diffs.py -arch ${architecture} -ci_arch ${architecture} -build_type ${configuration}"
2341 buildCommands += "tar -czf dasm.${os}.${architecture}.${configuration}.tgz ./_/pmi/asm"
2342 Utilities.addArchival(newJob, "dasm.${os}.${architecture}.${configuration}.tgz")
2346 if (scenario == 'illink') {
2347 assert(os == 'Ubuntu')
2348 buildCommands += "./tests/scripts/build_illink.sh --clone --arch=${architecture}"
2351 if (!doCoreFxTesting) {
2352 // We run pal tests on all OS but generate mscorlib (and thus, nuget packages)
2353 // only on supported OS platforms.
2354 def bootstrapRid = Utilities.getBoostrapPublishRid(os)
2355 def bootstrapRidEnv = bootstrapRid != null ? "__PUBLISH_RID=${bootstrapRid} " : ''
2357 buildCommands += "${bootstrapRidEnv}./build.sh ${lowerConfiguration} ${architecture}"
2359 def testBuildOpts = ""
2360 if (priority == '1') {
2361 testBuildOpts = "priority1"
2364 buildCommands += "./build-test.sh ${lowerConfiguration} ${architecture} ${testBuildOpts}"
2365 buildCommands += "src/pal/tests/palsuite/runpaltests.sh \${WORKSPACE}/bin/obj/${osGroup}.${architecture}.${configuration} \${WORKSPACE}/bin/paltestout"
2367 // Archive the bin/tests folder for *_tst jobs
2368 def testArtifactsTgzFileName = getTestArtifactsTgzFileName(osGroup, architecture, configuration)
2369 buildCommands += "tar -czf ${testArtifactsTgzFileName} bin/tests/${osGroup}.${architecture}.${configuration}"
2370 Utilities.addArchival(newJob, "${testArtifactsTgzFileName}", "")
2372 Utilities.addXUnitDotNETResults(newJob, '**/pal_tests.xml')
2375 if (scenario == 'corefx_innerloop') {
2376 assert os == 'Ubuntu' || 'OSX10.12'
2377 assert architecture == 'x64'
2379 buildCommands += "./build.sh ${lowerConfiguration} ${architecture} skiptests"
2380 buildCommands += "./build-test.sh ${lowerConfiguration} ${architecture} generatetesthostonly"
2381 buildCommands += "./tests/runtest.sh ${lowerConfiguration} --corefxtestsall --testHostDir=\${WORKSPACE}/bin/tests/${osGroup}.${architecture}.${configuration}/testhost/ --coreclr-src=\${WORKSPACE}"
2383 // Archive and process (only) the test results
2384 Utilities.addArchival(newJob, "bin/Logs/**/testResults.xml", "", /* doNotFailIfNothingArchived */ true, /* archiveOnlyIfSuccessful */ false)
2385 Utilities.addXUnitDotNETResults(newJob, "bin/Logs/**/testResults.xml")
2388 // Corefx stress testing
2389 assert os == 'Ubuntu'
2390 assert architecture == 'x64'
2391 assert lowerConfiguration == 'checked'
2392 assert isJitStressScenario(scenario)
2395 buildCommands += "./build.sh ${lowerConfiguration} ${architecture}"
2397 def scriptFileName = "\$WORKSPACE/set_stress_test_env.sh"
2399 def envScriptCmds = envScriptCreate(os, scriptFileName)
2400 envScriptCmds += envScriptSetStressModeVariables(os, Constants.jitStressModeScenarios[scenario], scriptFileName)
2401 envScriptCmds += envScriptFinalize(os, scriptFileName)
2402 buildCommands += envScriptCmds
2404 // Build and text corefx
2405 def workspaceRelativeFxRoot = "_/fx"
2406 def absoluteFxRoot = "\$WORKSPACE/${workspaceRelativeFxRoot}"
2407 def fxBranch = getFxBranch(branch)
2408 def exclusionRspPath = "\$WORKSPACE/tests/scripts/run-corefx-tests-exclusions.txt"
2410 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} -exclusion_rsp_file ${exclusionRspPath}"
2412 // Archive and process (only) the test results
2413 Utilities.addArchival(newJob, "${workspaceRelativeFxRoot}/artifacts/bin/**/testResults.xml", "", /* doNotFailIfNothingArchived */ true, /* archiveOnlyIfSuccessful */ false)
2414 Utilities.addXUnitDotNETResults(newJob, "${workspaceRelativeFxRoot}/artifacts/bin/**/testResults.xml")
2418 // Archive the logs, even if the build failed (which is when they are most interesting).
2419 Utilities.addArchival(newJob, "bin/Logs/*.log,bin/Logs/*.wrn,bin/Logs/*.err,bin/Logs/MsbuildDebugLogs/*", "", /* doNotFailIfNothingArchived */ true, /* archiveOnlyIfSuccessful */ false)
2422 // Emulator cross builds for ARM runs on Tizen currently
2423 assert os == 'Tizen'
2425 def arm_abi = "armel"
2426 def linuxCodeName = "tizen"
2428 // Unzip the Windows test binaries first. Exit with 0
2429 buildCommands += "unzip -q -o ./bin/tests/tests.zip -d ./bin/tests/Windows_NT.x64.${configuration} || exit 0"
2431 // Unpack the corefx binaries
2432 buildCommands += "mkdir ./bin/CoreFxBinDir"
2433 buildCommands += "tar -xf ./artifacts/bin/build.tar.gz -C ./bin/CoreFxBinDir"
2435 // Call the ARM CI script to cross build and test using docker
2436 buildCommands += """./tests/scripts/arm32_ci_script.sh \\
2439 --linuxCodeName=${linuxCodeName} \\
2440 --buildConfig=${lowerConfiguration} \\
2441 --testRootDir=./bin/tests/Windows_NT.x64.${configuration} \\
2442 --coreFxBinDir=./bin/CoreFxBinDir \\
2443 --testDirFile=./tests/testsRunningInsideARM.txt"""
2445 // Basic archiving of the build, no pal tests
2446 Utilities.addArchival(newJob, "bin/Product/**,bin/obj/*/tests/**/*.dylib,bin/obj/*/tests/**/*.so", "bin/Product/**/.nuget/**")
2450 // Non-Windows ARM cross builds on hardware run on Ubuntu only
2451 assert (os == 'Ubuntu') || (os == 'Ubuntu16.04')
2453 // Add some useful information to the log file. Ignore return codes.
2454 buildCommands += "uname -a || true"
2456 // Cross build the Ubuntu/arm product using docker with a docker image that contains the correct
2457 // Ubuntu cross-compilation toolset (running on a Ubuntu x64 host).
2458 // For CoreFX testing, we only need the product build; we don't need to generate the layouts. The product
2459 // build is then copied into the corefx layout by the run-corefx-test.py script. For CoreFX testing, we
2460 // ZIP up the generated CoreFX runtime and tests.
2462 def dockerImage = getDockerImageName(architecture, os, true)
2463 def dockerCmd = "docker run -i --rm -v \${WORKSPACE}:\${WORKSPACE} -w \${WORKSPACE} -e ROOTFS_DIR=/crossrootfs/${architecture} ${dockerImage} "
2465 buildCommands += "${dockerCmd}\${WORKSPACE}/build.sh ${lowerConfiguration} ${architecture} cross"
2467 if (doCoreFxTesting) {
2468 def scriptFileName = "\$WORKSPACE/set_stress_test_env.sh"
2470 def envScriptCmds = envScriptCreate(os, scriptFileName)
2471 envScriptCmds += envScriptSetStressModeVariables(os, Constants.jitStressModeScenarios[scenario], scriptFileName)
2472 envScriptCmds += envScriptFinalize(os, scriptFileName)
2473 buildCommands += envScriptCmds
2475 // Build and text corefx
2476 def workspaceRelativeFxRootLinux = "_/fx"
2477 def absoluteFxRoot = "\$WORKSPACE/${workspaceRelativeFxRootLinux}"
2478 def fxBranch = getFxBranch(branch)
2480 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"
2482 // Docker creates files with root permission, so we need to zip in docker also, or else we'll get permission errors.
2483 buildCommands += "${dockerCmd}zip -r ${workspaceRelativeFxRootLinux}/fxruntime.zip ${workspaceRelativeFxRootLinux}/artifacts/bin/testhost/netcoreapp-Linux-Release-${architecture}"
2484 buildCommands += "${dockerCmd}zip -r ${workspaceRelativeFxRootLinux}/fxtests.zip ${workspaceRelativeFxRootLinux}/artifacts/bin/tests"
2486 Utilities.addArchival(newJob, "${workspaceRelativeFxRootLinux}/fxruntime.zip")
2487 Utilities.addArchival(newJob, "${workspaceRelativeFxRootLinux}/fxtests.zip")
2489 else if (isCrossGenComparisonScenario(scenario)) {
2490 buildCommands += "${dockerCmd}\${WORKSPACE}/build-test.sh ${lowerConfiguration} ${architecture} cross generatelayoutonly"
2492 def workspaceRelativeProductBinDir = "bin/Product/${osGroup}.${architecture}.${configuration}"
2493 def workspaceRelativeCoreLib = "${workspaceRelativeProductBinDir}/IL/System.Private.CoreLib.dll"
2494 def workspaceRelativeCoreRootDir = "bin/tests/${osGroup}.${architecture}.${configuration}/Tests/Core_Root"
2495 def workspaceRelativeCrossGenComparisonScript = "tests/scripts/crossgen_comparison.py"
2496 def workspaceRelativeResultsDir = "_"
2497 def workspaceRelativeArtifactsArchive = "${os}.${architecture}.${configuration}.${scenario}.zip"
2498 def crossGenComparisonCmd = "python -u \${WORKSPACE}/${workspaceRelativeCrossGenComparisonScript} "
2499 def crossArch = "x64"
2500 def crossGenExecutable = "\${WORKSPACE}/${workspaceRelativeProductBinDir}/${crossArch}/crossgen"
2501 def workspaceRelativeCrossArchResultDir = "${workspaceRelativeResultsDir}/${osGroup}.${crossArch}_${architecture}.${configuration}"
2503 buildCommands += "${dockerCmd}mkdir -p \${WORKSPACE}/${workspaceRelativeCrossArchResultDir}"
2504 buildCommands += "${dockerCmd}${crossGenComparisonCmd}crossgen_corelib --crossgen ${crossGenExecutable} --il_corelib \${WORKSPACE}/${workspaceRelativeCoreLib} --result_dir \${WORKSPACE}/${workspaceRelativeCrossArchResultDir}"
2505 buildCommands += "${dockerCmd}${crossGenComparisonCmd}crossgen_framework --crossgen ${crossGenExecutable} --core_root \${WORKSPACE}/${workspaceRelativeCoreRootDir} --result_dir \${WORKSPACE}/${workspaceRelativeCrossArchResultDir}"
2507 buildCommands += "${dockerCmd}zip -r ${workspaceRelativeArtifactsArchive} ${workspaceRelativeCoreLib} ${workspaceRelativeCoreRootDir} ${workspaceRelativeCrossGenComparisonScript} ${workspaceRelativeResultsDir}"
2508 Utilities.addArchival(newJob, "${workspaceRelativeArtifactsArchive}")
2510 else if (scenario == 'pmi_asm_diffs') {
2511 buildCommands += "${dockerCmd}\${WORKSPACE}/build-test.sh ${lowerConfiguration} ${architecture} cross generatelayoutonly"
2513 // Pass `--skip_diffs` -- the actual diffs will be done on an arm machine in the test job. This is the build job.
2514 // TODO: Add -target_branch and -commit_hash arguments based on GitHub variables.
2515 buildCommands += "python -u \${WORKSPACE}/tests/scripts/run-pmi-diffs.py -arch ${architecture} -ci_arch ${architecture} -build_type ${configuration} --skip_diffs"
2517 // Archive what we created.
2518 buildCommands += "tar -czf product.${os}.${architecture}.${lowerConfiguration}.tgz ./bin/Product/Linux.${architecture}.${configuration}"
2519 buildCommands += "tar -czf product.baseline.${os}.${architecture}.${lowerConfiguration}.tgz ./_/pmi/base/bin/Product/Linux.${architecture}.${configuration}"
2520 buildCommands += "tar -czf coreroot.${os}.${architecture}.${lowerConfiguration}.tgz ./bin/tests/Linux.${architecture}.${configuration}/Tests/Core_Root"
2521 buildCommands += "tar -czf coreroot.baseline.${os}.${architecture}.${lowerConfiguration}.tgz ./_/pmi/base/bin/tests/Linux.${architecture}.${configuration}/Tests/Core_Root"
2523 // Archive the built artifacts
2524 Utilities.addArchival(newJob, "product.${os}.${architecture}.${lowerConfiguration}.tgz,product.baseline.${os}.${architecture}.${lowerConfiguration}.tgz,coreroot.${os}.${architecture}.${lowerConfiguration}.tgz,coreroot.baseline.${os}.${architecture}.${lowerConfiguration}.tgz")
2527 // Then, using the same docker image, build the tests and generate the CORE_ROOT layout.
2529 def testBuildOpts = ""
2530 if (priority == '1') {
2531 testBuildOpts = "priority1"
2534 buildCommands += "${dockerCmd}\${WORKSPACE}/build-test.sh ${lowerConfiguration} ${architecture} cross ${testBuildOpts}"
2536 // 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)
2537 def testArtifactsTgzFileName = getTestArtifactsTgzFileName(osGroup, architecture, configuration)
2538 buildCommands += "tar -czf ${testArtifactsTgzFileName} bin/tests/${osGroup}.${architecture}.${configuration}"
2540 Utilities.addArchival(newJob, "${testArtifactsTgzFileName}", "")
2543 // Archive the logs, even if the build failed (which is when they are most interesting).
2544 Utilities.addArchival(newJob, "bin/Logs/*.log,bin/Logs/*.wrn,bin/Logs/*.err,bin/Logs/MsbuildDebugLogs/*", "", /* doNotFailIfNothingArchived */ true, /* archiveOnlyIfSuccessful */ false)
2546 // We need to clean up the build machines; the docker build leaves newly built files with root permission, which
2547 // the cleanup task in Jenkins can't remove.
2550 azureVMAgentPostBuildAction {
2551 agentPostBuildAction('Delete agent after build execution (when idle).')
2557 println("Unknown architecture: ${architecture}");
2562 // editor brace matching: }
2564 println("Unknown os: ${os}");
2569 return buildCommands
2572 // Determine if we should generate a job for the given parameters. This is for non-flow jobs: either build and test, or build only.
2573 // Returns true if the job should be generated.
2574 def static shouldGenerateJob(def scenario, def isPR, def architecture, def configuration, def os, def isBuildOnly)
2576 def windowsArmJob = ((os == "Windows_NT") && (architecture in Constants.armWindowsCrossArchitectureList))
2578 // Innerloop jobs (except corefx_innerloop) are no longer created in Jenkins
2579 // The only exception is windows arm(64)
2580 if (isInnerloopTestScenario(scenario) && isPR && !windowsArmJob) {
2581 assert scenario != 'corefx_innerloop'
2586 if (isInnerloopTestScenario(scenario)) {
2590 if (scenario == 'corefx_innerloop') {
2595 // Tizen is only supported for armem architecture
2596 if (os == 'Tizen' && architecture != 'armem') {
2600 // Filter based on architecture.
2602 switch (architecture) {
2604 if ((os != 'Windows_NT') && (os != 'Ubuntu')) {
2609 if ((os != 'Windows_NT') && (os != 'Ubuntu16.04')) {
2614 if (os != 'Tizen') {
2619 if ((os != 'Windows_NT') && (os != 'Ubuntu')) {
2624 // Everything implemented
2627 println("Unknown architecture: ${architecture}")
2632 // Which (Windows) build only jobs are required?
2634 def isNormalOrInnerloop = (scenario == 'innerloop' || scenario == 'normal')
2637 switch (architecture) {
2640 // We use build only jobs for Windows arm/arm64 cross-compilation corefx testing, so we need to generate builds for that.
2641 if (!isCoreFxScenario(scenario)) {
2647 if (!isNormalOrInnerloop) {
2656 // Filter based on scenario.
2658 if (isJitStressScenario(scenario)) {
2659 if (configuration != 'Checked') {
2663 def isEnabledOS = (os == 'Windows_NT') ||
2664 (os == 'Ubuntu' && (architecture == 'x64') && isCoreFxScenario(scenario)) ||
2665 (os == 'Ubuntu' && architecture == 'arm') ||
2666 (os == 'Ubuntu16.04' && architecture == 'arm64')
2671 switch (architecture) {
2676 // x86 ubuntu: no stress modes
2677 if (os == 'Ubuntu') {
2684 // We use build only jobs for Windows arm/arm64 cross-compilation corefx testing, so we need to generate builds for that.
2685 // No "regular" Windows arm corefx jobs, e.g.
2686 // For Ubuntu arm corefx testing, we use regular jobs (not "build only" since only Windows has "build only", and
2687 // the Ubuntu arm "regular" jobs don't run tests anyway).
2688 if (os == 'Windows_NT') {
2689 if (! (isBuildOnly && isCoreFxScenario(scenario)) ) {
2694 if (!isCoreFxScenario(scenario)) {
2701 // armem: no stress jobs for ARM emulator.
2705 else if (isR2RScenario(scenario)) {
2706 if (os != 'Windows_NT') {
2710 if (isR2RBaselineScenario(scenario)) {
2711 // no need for Debug scenario; Checked is sufficient
2712 if (configuration != 'Checked' && configuration != 'Release') {
2716 else if (isR2RStressScenario(scenario)) {
2717 // Stress scenarios only run with Checked builds, not Release (they would work with Debug, but be slow).
2718 if (configuration != 'Checked') {
2723 switch (architecture) {
2726 // Windows arm/arm64 ready-to-run jobs use flow jobs and test jobs, but depend on "normal" (not R2R specific) build jobs.
2733 else if (isCrossGenComparisonScenario(scenario)) {
2734 return shouldGenerateCrossGenComparisonJob(os, architecture, configuration, scenario)
2740 // The ilrt build isn't necessary except for Windows_NT2003. Non-Windows NT uses
2741 // the default scenario build
2742 if (os != 'Windows_NT') {
2746 if (architecture != 'x64') {
2750 if (configuration != 'Release') {
2755 if (os != 'Windows_NT' && os != 'Ubuntu' && os != 'OSX10.12') {
2758 if (architecture != 'x64') {
2761 if (configuration != 'Checked') {
2767 if (os != 'Windows_NT' && os != 'Ubuntu' && os != 'OSX10.12') {
2770 if (architecture != 'x64') {
2773 if (configuration != 'Release') {
2777 case 'gc_reliability_framework':
2778 case 'standalone_gc':
2779 if (os != 'Windows_NT' && os != 'Ubuntu' && os != 'OSX10.12') {
2783 if (architecture != 'x64') {
2787 if (configuration != 'Release' && configuration != 'Checked') {
2791 // We only run Windows and Ubuntu x64 Checked for formatting right now
2793 if (os != 'Windows_NT' && os != 'Ubuntu') {
2796 if (architecture != 'x64') {
2799 if (configuration != 'Checked') {
2804 if (os != 'Windows_NT' && (os != 'Ubuntu' || architecture != 'x64')) {
2807 if (architecture != 'x64' && architecture != 'x86') {
2815 if (!isValidPrTriggeredInnerLoopJob(os, architecture, configuration, isBuildOnly)) {
2819 case 'corefx_innerloop':
2820 if (os != 'Windows_NT' && os != 'Ubuntu' && os != 'OSX10.12') {
2823 if (architecture != 'x64') {
2827 case 'pmi_asm_diffs':
2828 if (configuration != 'Checked') {
2831 if (architecture == 'armem') {
2834 // Currently, we don't support pmi_asm_diffs for Windows arm/arm64. We don't have a dotnet CLI available to
2835 // build jitutils. The jobs are not in validArmWindowsScenarios.
2836 if ((os == 'Windows_NT') && (architecture == 'arm' || architecture == 'arm64')) {
2839 // Currently, no support for Linux x86.
2840 if ((os != 'Windows_NT') && (architecture == 'x86')) {
2845 println("Unknown scenario: ${scenario}")
2851 // The job was not filtered out, so we should generate it!
2855 Constants.allScenarios.each { scenario ->
2856 [true, false].each { isPR ->
2857 Constants.architectureList.each { architecture ->
2858 Constants.configurationList.each { configuration ->
2859 Constants.osList.each { os ->
2860 // If the OS is Windows_NT_BuildOnly, set the isBuildOnly flag to true
2861 // and reset the os to Windows_NT
2862 def isBuildOnly = false
2863 if (os == 'Windows_NT_BuildOnly') {
2868 if (!shouldGenerateJob(scenario, isPR, architecture, configuration, os, isBuildOnly)) {
2873 def jobName = getJobName(configuration, architecture, os, scenario, isBuildOnly)
2874 def folderName = getJobFolder(scenario)
2876 // Create the new job
2877 def newJob = job(Utilities.getFullJobName(project, jobName, isPR, folderName)) {}
2879 addToViews(newJob, false, isPR, architecture, os, configuration, scenario) // isFlowJob == false
2881 setJobMachineAffinity(architecture, os, true, false, false, newJob) // isBuildJob = true, isTestJob = false, isFlowJob = false
2883 Utilities.standardJobSetup(newJob, project, isPR, "*/${branch}")
2884 addTriggers(newJob, branch, isPR, architecture, os, configuration, scenario, false, isBuildOnly) // isFlowJob==false
2885 setJobTimeout(newJob, isPR, architecture, configuration, scenario, isBuildOnly)
2887 // Copy Windows build test binaries and corefx build artifacts for Linux cross build for armem.
2888 // We don't use a flow job for this, but we do depend on there being existing builds with these
2889 // artifacts produced.
2890 if ((architecture == 'armem') && (os == 'Tizen')) {
2891 // Define the Windows Tests and Corefx build job names
2892 def lowerConfiguration = configuration.toLowerCase()
2893 def WindowsTestsName = projectFolder + '/' +
2894 Utilities.getFullJobName(project,
2895 getJobName(lowerConfiguration, 'x64' , 'windows_nt', 'normal', true),
2897 def fxBranch = getFxBranch(branch)
2898 def corefxFolder = Utilities.getFolderName('dotnet/corefx') + '/' +
2899 Utilities.getFolderName(fxBranch)
2901 def arm_abi = 'armel'
2902 def corefx_os = 'tizen'
2904 // Let's use release CoreFX to test checked CoreCLR,
2905 // because we do not generate checked CoreFX in CoreFX CI yet.
2906 def corefx_lowerConfiguration = lowerConfiguration
2907 if (lowerConfiguration == 'checked') {
2908 corefx_lowerConfiguration = 'release'
2911 // Copy the Windows test binaries and the Corefx build binaries
2914 copyArtifacts(WindowsTestsName) {
2915 includePatterns('bin/tests/tests.zip')
2917 latestSuccessful(true)
2920 copyArtifacts("${corefxFolder}/${corefx_os}_${arm_abi}_cross_${corefx_lowerConfiguration}") {
2921 includePatterns('artifacts/bin/build.tar.gz')
2923 latestSuccessful(true)
2930 def buildCommands = calculateBuildCommands(newJob, scenario, branch, isPR, architecture, configuration, os, isBuildOnly)
2934 if (os == 'Windows_NT') {
2935 buildCommands.each { buildCommand ->
2936 batchFile(buildCommand)
2940 buildCommands.each { buildCommand ->
2953 // Create a Windows ARM/ARM64 test job that will be used by a flow job.
2954 // Returns the newly created job.
2955 def static CreateWindowsArmTestJob(def dslFactory, def project, def architecture, def os, def configuration, def scenario, def isPR, def inputCoreCLRBuildName)
2957 def osGroup = getOSGroup(os)
2958 def jobName = getJobName(configuration, architecture, os, scenario, false) + "_tst"
2960 def jobFolder = getJobFolder(scenario)
2961 def newJob = dslFactory.job(Utilities.getFullJobName(project, jobName, isPR, jobFolder)) {
2963 stringParam('CORECLR_BUILD', '', "Build number to copy CoreCLR ${osGroup} binaries from")
2967 // Set up the copies
2969 // Coreclr build we are trying to test
2971 // ** NOTE ** This will, correctly, overwrite the CORE_ROOT from the Windows test archive
2973 copyArtifacts(inputCoreCLRBuildName) {
2974 excludePatterns('**/testResults.xml', '**/*.ni.dll')
2976 buildNumber('${CORECLR_BUILD}')
2980 if (isCoreFxScenario(scenario)) {
2982 // Only arm/arm64 supported for corefx testing now.
2983 assert architecture == 'arm' || architecture == 'arm64'
2985 // Unzip CoreFx runtime
2986 batchFile("powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::ExtractToDirectory('_\\fx\\fxruntime.zip', '_\\fx\\artifacts\\bin\\testhost\\netcoreapp-Windows_NT-Release-${architecture}')\"")
2988 // Unzip CoreFx tests.
2989 batchFile("powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::ExtractToDirectory('_\\fx\\fxtests.zip', '_\\fx\\artifacts\\bin\\tests')\"")
2991 // Add the script to run the corefx tests
2992 def corefx_runtime_path = "%WORKSPACE%\\_\\fx\\artifacts\\bin\\testhost\\netcoreapp-Windows_NT-Release-${architecture}"
2993 def corefx_tests_dir = "%WORKSPACE%\\_\\fx\\artifacts\\bin\\tests"
2994 def corefx_exclusion_file = "%WORKSPACE%\\tests\\${architecture}\\corefx_test_exclusions.txt"
2995 def exclusionRspPath = "%WORKSPACE%\\tests\\scripts\\run-corefx-tests-exclusions.txt"
2996 batchFile("call %WORKSPACE%\\tests\\scripts\\run-corefx-tests.bat ${corefx_runtime_path} ${corefx_tests_dir} ${corefx_exclusion_file} ${architecture} ${exclusionRspPath}")
2998 } else { // !isCoreFxScenario(scenario)
3001 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}')\"")
3003 def buildCommands = ""
3005 def coreRootLocation = "%WORKSPACE%\\bin\\tests\\Windows_NT.${architecture}.${configuration}\\Tests\\Core_Root"
3006 def addEnvVariable = { variable, value -> buildCommands += "set ${variable}=${value}\r\n"}
3007 def addCommand = { cmd -> buildCommands += "${cmd}\r\n"}
3009 // Make sure Command Extensions are enabled. Used so %ERRORLEVEL% is available.
3010 addCommand("SETLOCAL ENABLEEXTENSIONS")
3013 addEnvVariable("CORE_ROOT", coreRootLocation)
3014 addEnvVariable("COMPlus_NoGuiOnAssert", "1")
3015 addEnvVariable("COMPlus_ContinueOnAssert", "0")
3017 // If we are running a stress mode, we'll set those variables as well
3018 if (isJitStressScenario(scenario) || isR2RStressScenario(scenario)) {
3019 def stressValues = null
3020 if (isJitStressScenario(scenario)) {
3021 stressValues = Constants.jitStressModeScenarios[scenario]
3024 stressValues = Constants.r2rStressScenarios[scenario]
3027 stressValues.each { key, value ->
3028 addEnvVariable(key, value)
3032 if (isR2RScenario(scenario)) {
3033 // Crossgen the framework assemblies.
3034 buildCommands += """
3035 @for %%F in (%CORE_ROOT%\\*.dll) do @call :PrecompileAssembly "%CORE_ROOT%" "%%F" %%~nxF
3036 @goto skip_PrecompileAssembly
3039 @REM Skip mscorlib since it is already precompiled.
3040 @if /I "%3" == "mscorlib.dll" exit /b 0
3041 @if /I "%3" == "mscorlib.ni.dll" exit /b 0
3043 "%CORE_ROOT%\\crossgen.exe" /Platform_Assemblies_Paths "%CORE_ROOT%" %2 >nul 2>nul
3044 @if "%errorlevel%" == "-2146230517" (
3045 echo %2 is not a managed assembly.
3046 ) else if "%errorlevel%" == "-2146234344" (
3047 echo %2 is not a managed assembly.
3048 ) else if %errorlevel% neq 0 (
3049 echo Unable to precompile %2
3055 :skip_PrecompileAssembly
3058 // Set RunCrossGen variable to cause test wrappers to invoke their logic to run
3059 // crossgen on tests before running them.
3060 addEnvVariable("RunCrossGen", "true")
3061 } // isR2RScenario(scenario)
3064 // Do not run generate layout. It will delete the correct CORE_ROOT, and we do not have a correct product
3065 // dir to copy from.
3066 def runtestCommand = "call %WORKSPACE%\\tests\\runtest.cmd ${architecture} ${configuration} skipgeneratelayout"
3068 addCommand("${runtestCommand}")
3069 addCommand("echo on") // Show the following commands in the log. "echo" doesn't alter the errorlevel.
3070 addCommand("set saved_errorlevel=%errorlevel%")
3072 // Collect the test logs collected by xunit. Ignore errors here. We want to collect these even if the run
3073 // failed for some reason, so it needs to be in this batch file.
3075 addCommand("powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('.\\bin\\tests\\${osGroup}.${architecture}.${configuration}\\Reports', '.\\bin\\tests\\testReports.zip')\"");
3077 // Use the runtest.cmd errorlevel as the script errorlevel.
3078 addCommand("exit /b %saved_errorlevel%")
3080 batchFile(buildCommands)
3081 } // non-corefx testing
3085 if (!isCoreFxScenario(scenario)) {
3086 def doNotFailIfNothingArchived = true
3087 def archiveOnlyIfSuccessful = false
3088 Utilities.addArchival(newJob, "bin/tests/testReports.zip", "", doNotFailIfNothingArchived, archiveOnlyIfSuccessful)
3090 Utilities.addXUnitDotNETResults(newJob, 'bin/**/TestRun*.xml', true)
3096 // Create a test job not covered by the "Windows ARM" case that will be used by a flow job.
3097 // E.g., non-Windows tests.
3098 // Returns the newly created job.
3099 def static CreateOtherTestJob(def dslFactory, def project, def branch, def architecture, def os, def configuration, def scenario, def isPR, def inputCoreCLRBuildName)
3101 def lowerConfiguration = configuration.toLowerCase()
3103 def isUbuntuArm64Job = ((os == "Ubuntu16.04") && (architecture == 'arm64'))
3104 def isUbuntuArm32Job = ((os == "Ubuntu") && (architecture == 'arm'))
3105 def isUbuntuArmJob = isUbuntuArm32Job || isUbuntuArm64Job
3107 def doCoreFxTesting = isCoreFxScenario(scenario)
3108 def isPmiAsmDiffsScenario = (scenario == 'pmi_asm_diffs')
3110 def workspaceRelativeFxRootLinux = "_/fx" // only used for CoreFX testing
3112 def osGroup = getOSGroup(os)
3113 def jobName = getJobName(configuration, architecture, os, scenario, false) + "_tst"
3116 def useServerGC = false
3118 // Enable Server GC for Ubuntu PR builds
3119 // REVIEW: why? Does this apply to all architectures? Why only PR?
3120 if (os == 'Ubuntu' && isPR) {
3121 testOpts += ' --useServerGC'
3125 if (isR2RScenario(scenario)) {
3127 testOpts += ' --crossgen --runcrossgentests'
3129 if (scenario == 'r2r_jitstress1') {
3130 testOpts += ' --jitstress=1'
3132 else if (scenario == 'r2r_jitstress2') {
3133 testOpts += ' --jitstress=2'
3135 else if (scenario == 'r2r_jitstress1_tiered') {
3136 testOpts += ' --jitstress=1'
3138 else if (scenario == 'r2r_jitstress2_tiered') {
3139 testOpts += ' --jitstress=2'
3141 else if (scenario == 'r2r_jitstressregs1') {
3142 testOpts += ' --jitstressregs=1'
3144 else if (scenario == 'r2r_jitstressregs2') {
3145 testOpts += ' --jitstressregs=2'
3147 else if (scenario == 'r2r_jitstressregs3') {
3148 testOpts += ' --jitstressregs=3'
3150 else if (scenario == 'r2r_jitstressregs4') {
3151 testOpts += ' --jitstressregs=4'
3153 else if (scenario == 'r2r_jitstressregs8') {
3154 testOpts += ' --jitstressregs=8'
3156 else if (scenario == 'r2r_jitstressregs0x10') {
3157 testOpts += ' --jitstressregs=0x10'
3159 else if (scenario == 'r2r_jitstressregs0x80') {
3160 testOpts += ' --jitstressregs=0x80'
3162 else if (scenario == 'r2r_jitstressregs0x1000') {
3163 testOpts += ' --jitstressregs=0x1000'
3165 else if (scenario == 'r2r_jitminopts') {
3166 testOpts += ' --jitminopts'
3168 else if (scenario == 'r2r_jitforcerelocs') {
3169 testOpts += ' --jitforcerelocs'
3171 else if (scenario == 'r2r_gcstress15') {
3172 testOpts += ' --gcstresslevel=0xF'
3175 else if (scenario == 'jitdiff') {
3176 testOpts += ' --jitdisasm --crossgen'
3178 else if (scenario == 'illink') {
3179 testOpts += ' --link=\$WORKSPACE/linker/linker/bin/netcore_Release/netcoreapp2.0/ubuntu-x64/publish/illink'
3181 else if (isLongGc(scenario)) {
3182 // Long GC tests behave very poorly when they are not
3183 // the only test running (many of them allocate until OOM).
3184 testOpts += ' --sequential'
3186 // A note - runtest.sh does have "--long-gc" and "--gcsimulator" options
3187 // for running long GC and GCSimulator tests, respectively. We don't use them
3188 // here because using a playlist file produces much more readable output on the CI machines
3189 // and reduces running time.
3191 // The Long GC playlist contains all of the tests that are
3192 // going to be run. The GCSimulator playlist contains all of
3193 // the GC simulator tests.
3194 if (scenario == 'longgc') {
3195 testOpts += ' --long-gc --playlist=./tests/longRunningGcTests.txt'
3197 else if (scenario == 'gcsimulator') {
3198 testOpts += ' --gcsimulator --playlist=./tests/gcSimulatorTests.txt'
3201 else if (isGcReliabilityFramework(scenario)) {
3202 testOpts += ' --build-overlay-only'
3204 else if (scenario == 'standalone_gc') {
3205 if (osGroup == 'OSX') {
3206 testOpts += ' --gcname=libclrgc.dylib'
3208 else if (osGroup == 'Linux') {
3209 testOpts += ' --gcname=libclrgc.so'
3212 println("Unexpected OS group: ${osGroup} for os ${os}")
3217 def jobFolder = getJobFolder(scenario)
3218 def newJob = dslFactory.job(Utilities.getFullJobName(project, jobName, isPR, jobFolder)) {
3220 stringParam('CORECLR_BUILD', '', "Build number to copy CoreCLR ${osGroup} binaries from")
3224 // Set up the copies
3226 // Coreclr build we are trying to test
3228 // HACK: the Ubuntu arm64 copyArtifacts Jenkins plug-in is ridiculously slow (45 minutes to
3229 // 1.5 hours for this step). Instead, directly use wget, which is fast (1 minute).
3231 if (!isUbuntuArm64Job) {
3232 copyArtifacts(inputCoreCLRBuildName) {
3233 excludePatterns('**/testResults.xml', '**/*.ni.dll')
3235 buildNumber('${CORECLR_BUILD}')
3240 if (isUbuntuArmJob) {
3241 // Add some useful information to the log file. Ignore return codes.
3242 shell("uname -a || true")
3245 if (isUbuntuArm64Job) {
3246 // Copy the required artifacts directly, using wget, e.g.:
3248 // https://ci.dot.net/job/dotnet_coreclr/job/master/job/arm64_cross_checked_ubuntu16.04_innerloop_prtest/16/artifact/testnativebin.checked.zip
3249 // https://ci.dot.net/job/dotnet_coreclr/job/master/job/arm64_cross_checked_ubuntu16.04_innerloop_prtest/16/artifact/tests.checked.zip
3251 // parameterized as:
3253 // https://ci.dot.net/job/${mungedProjectName}/job/${mungedBranchName}/job/${inputJobName}/${CORECLR_BUILD}/artifact/testnativebin.checked.zip
3254 // https://ci.dot.net/job/${mungedProjectName}/job/${mungedBranchName}/job/${inputJobName}/${CORECLR_BUILD}/artifact/tests.checked.zip
3256 // CoreFX example artifact URLs:
3258 // 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
3259 // 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
3261 // Note that the source might be in a "jitstress" folder.
3263 // Use `--progress=dot:giga` to display some progress output, but limit it in the log file.
3265 // Use `--directory-prefix=_/fx` to specify where to put the corefx files (to match what other platforms do). Use this instead of `-O`.
3267 shell("echo \"Using wget instead of the Jenkins copy artifacts plug-in to copy artifacts from ${inputCoreCLRBuildName}\"")
3269 def mungedProjectName = Utilities.getFolderName(project)
3270 def mungedBranchName = Utilities.getFolderName(branch)
3272 def doCrossGenComparison = isCrossGenComparisonScenario(scenario)
3273 def inputCoreCLRBuildScenario = isInnerloopTestScenario(scenario) ? 'innerloop' : 'normal'
3274 if (isPmiAsmDiffsScenario || doCoreFxTesting || doCrossGenComparison) {
3275 // These depend on unique builds for each scenario
3276 inputCoreCLRBuildScenario = scenario
3278 def sourceJobName = getJobName(configuration, architecture, os, inputCoreCLRBuildScenario, false)
3279 def inputJobName = Utilities.getFullJobName(sourceJobName, isPR)
3281 // Need to add the sub-folder if necessary.
3282 def inputJobPath = "job/${inputJobName}"
3283 def folderName = getJobFolder(inputCoreCLRBuildScenario)
3284 if (folderName != '') {
3285 inputJobPath = "job/${folderName}/job/${inputJobName}"
3288 def inputUrlRoot = "https://ci.dot.net/job/${mungedProjectName}/job/${mungedBranchName}/${inputJobPath}/\${CORECLR_BUILD}/artifact"
3290 if (isPmiAsmDiffsScenario) {
3291 def workspaceRelativeRootLinux = "_/pmi"
3292 shell("mkdir -p ${workspaceRelativeRootLinux}")
3293 shell("wget --progress=dot:giga ${inputUrlRoot}/product.${os}.${architecture}.${lowerConfiguration}.tgz")
3294 shell("wget --progress=dot:giga ${inputUrlRoot}/product.baseline.${os}.${architecture}.${lowerConfiguration}.tgz")
3295 shell("wget --progress=dot:giga ${inputUrlRoot}/coreroot.${os}.${architecture}.${lowerConfiguration}.tgz")
3296 shell("wget --progress=dot:giga ${inputUrlRoot}/coreroot.baseline.${os}.${architecture}.${lowerConfiguration}.tgz")
3298 else if (doCoreFxTesting) {
3299 shell("mkdir -p ${workspaceRelativeFxRootLinux}")
3300 shell("wget --progress=dot:giga --directory-prefix=${workspaceRelativeFxRootLinux} ${inputUrlRoot}/${workspaceRelativeFxRootLinux}/fxtests.zip")
3301 shell("wget --progress=dot:giga --directory-prefix=${workspaceRelativeFxRootLinux} ${inputUrlRoot}/${workspaceRelativeFxRootLinux}/fxruntime.zip")
3304 def testArtifactsTgzFileName = getTestArtifactsTgzFileName(osGroup, architecture, configuration)
3305 shell("wget --progress=dot:giga ${inputUrlRoot}/${testArtifactsTgzFileName}")
3309 if (architecture == 'x86') {
3310 shell("mkdir ./bin/CoreFxNative")
3312 def fxBranch = getFxBranch(branch)
3313 def corefxFolder = Utilities.getFolderName('dotnet/corefx') + '/' + Utilities.getFolderName(fxBranch)
3315 copyArtifacts("${corefxFolder}/ubuntu16.04_x86_release") {
3316 includePatterns('artifacts/bin/build.tar.gz')
3317 targetDirectory('bin/CoreFxNative')
3319 latestSuccessful(true)
3323 shell("mkdir ./bin/CoreFxBinDir")
3324 shell("tar -xf ./bin/CoreFxNative/artifacts/bin/build.tar.gz -C ./bin/CoreFxBinDir")
3327 if (isPmiAsmDiffsScenario) {
3328 shell("tar -xzf ./product.${os}.${architecture}.${lowerConfiguration}.tgz || exit 0")
3329 shell("tar -xzf ./product.baseline.${os}.${architecture}.${lowerConfiguration}.tgz || exit 0")
3330 shell("tar -xzf ./coreroot.${os}.${architecture}.${lowerConfiguration}.tgz || exit 0")
3331 shell("tar -xzf ./coreroot.baseline.${os}.${architecture}.${lowerConfiguration}.tgz || exit 0")
3333 // CoreFX testing downloads the CoreFX tests, not the coreclr tests. Also, unzip the built CoreFX layout/runtime directories.
3334 else if (doCoreFxTesting) {
3335 shell("unzip -q -o ${workspaceRelativeFxRootLinux}/fxtests.zip || exit 0")
3336 shell("unzip -q -o ${workspaceRelativeFxRootLinux}/fxruntime.zip || exit 0")
3339 def testArtifactsTgzFileName = getTestArtifactsTgzFileName(osGroup, architecture, configuration)
3340 shell("tar -xzf ./${testArtifactsTgzFileName} || exit 0") // extracts to ./bin/tests/${osGroup}.${architecture}.${configuration}
3343 // Execute the tests
3344 def runDocker = isNeedDocker(architecture, os, false)
3345 def dockerPrefix = ""
3348 def dockerImage = getDockerImageName(architecture, os, false)
3349 dockerPrefix = "docker run -i --rm -v \${WORKSPACE}:\${WORKSPACE} -w \${WORKSPACE} "
3350 dockerCmd = dockerPrefix + "${dockerImage} "
3353 // If we are running a stress mode, we'll set those variables first.
3354 // For CoreFX, the stress variables are already built into the CoreFX test build per-test wrappers.
3355 if (!doCoreFxTesting && isJitStressScenario(scenario)) {
3356 def scriptFileName = "\${WORKSPACE}/set_stress_test_env.sh"
3357 def envScriptCmds = envScriptCreate(os, scriptFileName)
3358 envScriptCmds += envScriptSetStressModeVariables(os, Constants.jitStressModeScenarios[scenario], scriptFileName)
3359 envScriptCmds += envScriptFinalize(os, scriptFileName)
3360 shell("${envScriptCmds}")
3361 testOpts += " --test-env=${scriptFileName}"
3364 // setup-stress-dependencies.sh, invoked by runtest.sh to download the coredistools package, depends on the "dotnet"
3365 // tool downloaded by the "init-tools.sh" script. However, it only invokes setup-stress-dependencies.sh for x64. The
3366 // coredistools package is used by GCStress on x86 and x64 to disassemble code to determine instruction boundaries.
3367 // On arm/arm64, it is not required as determining instruction boundaries is trivial.
3368 if (isGCStressRelatedTesting(scenario)) {
3369 if (architecture == 'x64') {
3370 shell('./init-tools.sh')
3374 if (isPmiAsmDiffsScenario) {
3376 python -u \${WORKSPACE}/tests/scripts/run-pmi-diffs.py -arch ${architecture} -ci_arch ${architecture} -build_type ${configuration} --skip_baseline_build""")
3378 shell("tar -czf dasm.${os}.${architecture}.${configuration}.tgz ./_/pmi/asm")
3380 else if (doCoreFxTesting) {
3381 def exclusionRspPath = "\${WORKSPACE}/tests/scripts/run-corefx-tests-exclusions.txt"
3383 \${WORKSPACE}/tests/scripts/run-corefx-tests.sh --test-exclude-file \${WORKSPACE}/tests/${architecture}/corefx_linux_test_exclusions.txt --runtime \${WORKSPACE}/${workspaceRelativeFxRootLinux}/artifacts/bin/testhost/netcoreapp-Linux-Release-${architecture} --arch ${architecture} --corefx-tests \${WORKSPACE}/${workspaceRelativeFxRootLinux}/artifacts/bin --configurationGroup Release --exclusion-rsp-file ${exclusionRspPath}""")
3386 def runScript = "${dockerCmd}./tests/runtest.sh"
3390 ${lowerConfiguration} \\
3391 --testRootDir=\"\${WORKSPACE}/bin/tests/${osGroup}.${architecture}.${configuration}\" \\
3392 --coreOverlayDir=\"\${WORKSPACE}/bin/tests/${osGroup}.${architecture}.${configuration}/Tests/Core_Root\" \\
3393 --limitedDumpGeneration ${testOpts}""")
3396 if (isGcReliabilityFramework(scenario)) {
3397 // runtest.sh doesn't actually execute the reliability framework - do it here.
3400 dockerCmd = dockerPrefix + "-e COMPlus_gcServer=1 ${dockerImage} "
3403 shell("export COMPlus_gcServer=1")
3407 shell("${dockerCmd}./tests/scripts/run-gc-reliability-framework.sh ${architecture} ${configuration}")
3412 // Experimental: If on Ubuntu 14.04, then attempt to pull in crash dump links
3413 if (os in ['Ubuntu']) {
3414 SummaryBuilder summaries = new SummaryBuilder()
3415 summaries.addLinksSummaryFromFile('Crash dumps from this run:', 'dumplings.txt')
3416 summaries.emit(newJob)
3419 if (isPmiAsmDiffsScenario) {
3421 Utilities.addArchival(newJob, "dasm.${os}.${architecture}.${configuration}.tgz")
3423 else if (doCoreFxTesting) {
3424 Utilities.addArchival(newJob, "${workspaceRelativeFxRootLinux}/artifacts/bin/**/testResults.xml", "", /* doNotFailIfNothingArchived */ true, /* archiveOnlyIfSuccessful */ false)
3425 if ((os == "Ubuntu") && (architecture == 'arm')) {
3426 // We have a problem with the xunit plug-in, where it is consistently failing on Ubuntu arm32 test result uploading with this error:
3428 // [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
3430 // We haven't been able to identify the reason. So, do not add xunit parsing of the test data in this scenario.
3431 // This is tracked by: https://github.com/dotnet/coreclr/issues/19447.
3434 Utilities.addXUnitDotNETResults(newJob, "${workspaceRelativeFxRootLinux}/artifacts/bin/**/testResults.xml")
3438 Utilities.addXUnitDotNETResults(newJob, '**/coreclrtests.xml')
3444 def static CreateNonWindowsCrossGenComparisonTestJob(def dslFactory, def project, def architecture, def os, def configuration, def scenario, def isPR, def inputCoreCLRBuildName)
3446 assert isCrossGenComparisonScenario(scenario)
3448 def osGroup = getOSGroup(os)
3449 def jobName = getJobName(configuration, architecture, os, scenario, false) + "_tst"
3451 def workspaceRelativeResultsDir = "_"
3452 def workspaceRelativeNativeArchResultDir = "${workspaceRelativeResultsDir}/${osGroup}.${architecture}_${architecture}.${configuration}"
3454 def crossArch = "x64"
3455 def workspaceRelativeCrossArchResultDir = "${workspaceRelativeResultsDir}/${osGroup}.${crossArch}_${architecture}.${configuration}"
3457 def jobFolder = getJobFolder(scenario)
3458 def newJob = dslFactory.job(Utilities.getFullJobName(project, jobName, isPR, jobFolder)) {
3460 stringParam('CORECLR_BUILD', '', "Build number to copy CoreCLR ${osGroup} binaries from")
3463 def workspaceRelativeArtifactsArchive = "${os}.${architecture}.${configuration}.${scenario}.zip"
3466 copyArtifacts(inputCoreCLRBuildName) {
3467 includePatterns("${workspaceRelativeArtifactsArchive}")
3469 buildNumber('${CORECLR_BUILD}')
3473 shell("unzip -o ${workspaceRelativeArtifactsArchive} || exit 0")
3475 def workspaceRelativeCoreLib = "bin/Product/${osGroup}.${architecture}.${configuration}/IL/System.Private.CoreLib.dll"
3476 def workspaceRelativeCoreRootDir = "bin/tests/${osGroup}.${architecture}.${configuration}/Tests/Core_Root"
3477 def workspaceRelativeCrossGenComparisonScript = "tests/scripts/crossgen_comparison.py"
3478 def workspaceRelativeCrossGenExecutable = "${workspaceRelativeCoreRootDir}/crossgen"
3480 def crossGenComparisonCmd = "python -u \${WORKSPACE}/${workspaceRelativeCrossGenComparisonScript} "
3481 def crossGenExecutable = "\${WORKSPACE}/${workspaceRelativeCrossGenExecutable}"
3483 shell("mkdir -p ${workspaceRelativeNativeArchResultDir}")
3484 shell("${crossGenComparisonCmd}crossgen_corelib --crossgen ${crossGenExecutable} --il_corelib \${WORKSPACE}/${workspaceRelativeCoreLib} --result_dir \${WORKSPACE}/${workspaceRelativeNativeArchResultDir}")
3485 shell("${crossGenComparisonCmd}crossgen_framework --crossgen ${crossGenExecutable} --core_root \${WORKSPACE}/${workspaceRelativeCoreRootDir} --result_dir \${WORKSPACE}/${workspaceRelativeNativeArchResultDir}")
3487 shell("${crossGenComparisonCmd}compare --base_dir \${WORKSPACE}/${workspaceRelativeNativeArchResultDir} --diff_dir \${WORKSPACE}/${workspaceRelativeCrossArchResultDir}")
3491 Utilities.addArchival(newJob, "${workspaceRelativeNativeArchResultDir}/**", "", /* doNotFailIfNothingArchived */ true, /* archiveOnlyIfSuccessful */ false)
3492 Utilities.addArchival(newJob, "${workspaceRelativeCrossArchResultDir}/**", "", /* doNotFailIfNothingArchived */ true, /* archiveOnlyIfSuccessful */ false)
3497 // Create a test job that will be used by a flow job.
3498 // Returns the newly created job.
3499 // 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,
3500 // and we want the views to be the minimal set of "top-level" jobs that represent all work.
3501 def static CreateTestJob(def dslFactory, def project, def branch, def architecture, def os, def configuration, def scenario, def isPR, def inputCoreCLRBuildName)
3503 def windowsArmJob = ((os == "Windows_NT") && (architecture in Constants.armWindowsCrossArchitectureList))
3506 if (windowsArmJob) {
3507 newJob = CreateWindowsArmTestJob(dslFactory, project, architecture, os, configuration, scenario, isPR, inputCoreCLRBuildName)
3509 else if (isCrossGenComparisonScenario(scenario)) {
3510 newJob = CreateNonWindowsCrossGenComparisonTestJob(dslFactory, project, architecture, os, configuration, scenario, isPR, inputCoreCLRBuildName)
3513 newJob = CreateOtherTestJob(dslFactory, project, branch, architecture, os, configuration, scenario, isPR, inputCoreCLRBuildName)
3516 setJobMachineAffinity(architecture, os, false, true, false, newJob) // isBuildJob = false, isTestJob = true, isFlowJob = false
3518 if (scenario == 'jitdiff') {
3519 def osGroup = getOSGroup(os)
3520 Utilities.addArchival(newJob, "bin/tests/${osGroup}.${architecture}.${configuration}/dasm/**")
3523 Utilities.standardJobSetup(newJob, project, isPR, "*/${branch}")
3524 setJobTimeout(newJob, isPR, architecture, configuration, scenario, false)
3529 // Create a flow job to tie together a build job with the given test job.
3530 // Returns the new flow job.
3531 def static CreateFlowJob(def dslFactory, def project, def branch, def architecture, def os, def configuration, def scenario, def isPR, def fullTestJobName, def inputCoreCLRBuildName)
3533 // Windows CoreCLR build and Linux CoreCLR build (in parallel) ->
3534 // Linux CoreCLR test
3535 def flowJobName = getJobName(configuration, architecture, os, scenario, false) + "_flow"
3536 def jobFolder = getJobFolder(scenario)
3538 def newFlowJob = dslFactory.buildFlowJob(Utilities.getFullJobName(project, flowJobName, isPR, jobFolder)) {
3540 coreclrBuildJob = build(params, '${inputCoreCLRBuildName}')
3542 // And then build the test build
3543 build(params + [CORECLR_BUILD: coreclrBuildJob.build.number], '${fullTestJobName}')
3546 JobReport.Report.addReference(inputCoreCLRBuildName)
3547 JobReport.Report.addReference(fullTestJobName)
3549 addToViews(newFlowJob, true, isPR, architecture, os, configuration, scenario) // isFlowJob = true
3551 setJobMachineAffinity(architecture, os, false, false, true, newFlowJob) // isBuildJob = false, isTestJob = false, isFlowJob = true
3553 Utilities.standardJobSetup(newFlowJob, project, isPR, "*/${branch}")
3554 addTriggers(newFlowJob, branch, isPR, architecture, os, configuration, scenario, true, false) // isFlowJob==true, isWindowsBuildOnlyJob==false
3559 // Determine if we should generate a flow job for the given parameters.
3560 // Returns true if the job should be generated.
3561 def static shouldGenerateFlowJob(def scenario, def isPR, def architecture, def configuration, def os)
3563 // The various "innerloop" jobs are only available as PR triggered.
3566 if (isInnerloopTestScenario(scenario)) {
3570 if (scenario == 'corefx_innerloop') {
3575 // Disable flow jobs for innerloop pr.
3577 // The only exception is windows arm(64)
3578 if (isInnerloopTestScenario(scenario) && isPR && os != 'Windows_NT') {
3579 assert scenario != 'corefx_innerloop'
3584 // Filter based on OS and architecture.
3586 switch (architecture) {
3588 if (os != "Ubuntu" && os != "Windows_NT") {
3593 if (os != "Ubuntu16.04" && os != "Windows_NT") {
3598 if (os != "Ubuntu") {
3603 if (!(os in Constants.crossList)) {
3606 if (os == "Windows_NT") {
3614 println("Unknown architecture: ${architecture}")
3619 def isNormalOrInnerloop = (scenario == 'innerloop' || scenario == 'normal')
3621 // Filter based on scenario in OS.
3623 if (os == 'Windows_NT') {
3624 assert architecture == 'arm' || architecture == 'arm64'
3625 if (!isArmWindowsScenario(scenario)) {
3628 if (isNormalOrInnerloop && (configuration == 'Debug')) {
3629 // The arm32/arm64 Debug configuration for innerloop/normal scenario is a special case: it does a build only, and no test run.
3630 // To do that, it doesn't require a flow job.
3636 if (architecture == 'arm') {
3637 if (!(scenario in Constants.validLinuxArmScenarios)) {
3641 else if (architecture == 'arm64') {
3642 if (!(scenario in Constants.validLinuxArm64Scenarios)) {
3646 else if (architecture == 'x86') {
3647 // Linux/x86 only want innerloop and default test
3648 if (!isNormalOrInnerloop) {
3652 else if (architecture == 'x64') {
3653 // Linux/x64 corefx testing doesn't need a flow job; the "build" job runs run-corefx-tests.py which
3654 // builds and runs the corefx tests. Other Linux/x64 flow jobs are required to get the test
3655 // build from a Windows machine.
3656 if (isCoreFxScenario(scenario)) {
3662 // For CentOS, we only want Checked/Release builds.
3663 if (os == 'CentOS7.1') {
3664 if (configuration != 'Checked' && configuration != 'Release') {
3667 if (!isNormalOrInnerloop && !isR2RScenario(scenario)) {
3672 // For RedHat and Debian, we only do Release builds.
3673 else if (os == 'RHEL7.2' || os == 'Debian8.4') {
3674 if (configuration != 'Release') {
3677 if (!isNormalOrInnerloop) {
3682 // Next, filter based on scenario.
3684 if (isJitStressScenario(scenario)) {
3685 if (configuration != 'Checked') {
3689 else if (isR2RBaselineScenario(scenario)) {
3690 if (configuration != 'Checked' && configuration != 'Release') {
3694 else if (isR2RStressScenario(scenario)) {
3695 if (configuration != 'Checked') {
3699 else if (isCrossGenComparisonScenario(scenario)) {
3700 return shouldGenerateCrossGenComparisonJob(os, architecture, configuration, scenario)
3708 // Long GC tests take a long time on non-Release builds
3709 // ilrt is also Release only
3710 if (configuration != 'Release') {
3716 if (configuration != 'Checked') {
3721 case 'gc_reliability_framework':
3722 case 'standalone_gc':
3723 if (configuration != 'Release' && configuration != 'Checked') {
3732 if (os != 'Windows_NT' && os != 'Ubuntu') {
3742 if (!isValidPrTriggeredInnerLoopJob(os, architecture, configuration, false)) {
3747 case 'pmi_asm_diffs':
3748 if (configuration != 'Checked') {
3751 // No need for flow job except for Linux arm/arm64
3752 if ((os != 'Windows_NT') && (architecture != 'arm') && (architecture != 'arm64')) {
3757 case 'corefx_innerloop':
3758 // No flow job needed
3762 println("Unknown scenario: ${scenario}")
3768 // The job was not filtered out, so we should generate it!
3772 // Create jobs requiring flow jobs. This includes x64 non-Windows, arm/arm64 Ubuntu, and arm/arm64 Windows.
3773 Constants.allScenarios.each { scenario ->
3774 [true, false].each { isPR ->
3775 Constants.architectureList.each { architecture ->
3776 Constants.configurationList.each { configuration ->
3777 Constants.osList.each { os ->
3779 if (!shouldGenerateFlowJob(scenario, isPR, architecture, configuration, os)) {
3783 def windowsArmJob = ((os == "Windows_NT") && (architecture in Constants.armWindowsCrossArchitectureList))
3784 def doCoreFxTesting = isCoreFxScenario(scenario)
3785 def doCrossGenComparison = isCrossGenComparisonScenario(scenario)
3786 def isPmiAsmDiffsScenario = (scenario == 'pmi_asm_diffs')
3788 // Figure out the job name of the CoreCLR build the test will depend on.
3790 def inputCoreCLRBuildScenario = isInnerloopTestScenario(scenario) ? 'innerloop' : 'normal'
3791 def inputCoreCLRBuildIsBuildOnly = false
3792 if (doCoreFxTesting || isPmiAsmDiffsScenario) {
3793 // Every CoreFx test depends on its own unique build.
3794 inputCoreCLRBuildScenario = scenario
3795 if (windowsArmJob) {
3796 // Only Windows ARM corefx jobs use "build only" jobs. Others, such as Ubuntu ARM corefx, use "regular" jobs.
3797 inputCoreCLRBuildIsBuildOnly = true
3800 else if (doCrossGenComparison) {
3801 inputCoreCLRBuildScenario = scenario
3804 def inputCoreCLRFolderName = getJobFolder(inputCoreCLRBuildScenario)
3805 def inputCoreCLRBuildName = projectFolder + '/' +
3806 Utilities.getFullJobName(project, getJobName(configuration, architecture, os, inputCoreCLRBuildScenario, inputCoreCLRBuildIsBuildOnly), isPR, inputCoreCLRFolderName)
3808 // =============================================================================================
3809 // Create the test job
3810 // =============================================================================================
3812 def testJob = CreateTestJob(this, project, branch, architecture, os, configuration, scenario, isPR, inputCoreCLRBuildName)
3814 // =============================================================================================
3815 // Create a build flow to join together the build and tests required to run this test.
3816 // =============================================================================================
3818 if (os == 'RHEL7.2' || os == 'Debian8.4') {
3819 // Do not create the flow job for RHEL jobs.
3823 def fullTestJobName = projectFolder + '/' + testJob.name
3824 def flowJob = CreateFlowJob(this, project, branch, architecture, os, configuration, scenario, isPR, fullTestJobName, inputCoreCLRBuildName)
3832 JobReport.Report.generateJobReport(out)
3834 // Make the call to generate the help job
3835 Utilities.createHelperJob(this, project, branch,
3836 "Welcome to the ${project} Repository", // This is prepended to the help message
3837 "Have a nice day!") // This is appended to the help message. You might put known issues here.
3839 Utilities.addCROSSCheck(this, project, branch)