b4c073dec89b76493a909578ddea34b7558e158c
[Packages/TYPO3.CMS.git] / Build / bamboo / src / main / java / core / AbstractCoreSpec.java
1 package core;
2
3 /*
4 * This file is part of the TYPO3 CMS project.
5 *
6 * It is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License, either version 2
8 * of the License, or any later version.
9 *
10 * For the full copyright and license information, please read the
11 * LICENSE.txt file that was distributed with this source code.
12 *
13 * The TYPO3 project - inspiring people to share!
14 */
15
16 import java.util.ArrayList;
17
18 import com.atlassian.bamboo.specs.api.builders.BambooKey;
19 import com.atlassian.bamboo.specs.api.builders.plan.Job;
20 import com.atlassian.bamboo.specs.api.builders.plan.artifact.Artifact;
21 import com.atlassian.bamboo.specs.api.builders.requirement.Requirement;
22 import com.atlassian.bamboo.specs.api.builders.task.Task;
23 import com.atlassian.bamboo.specs.builders.task.CheckoutItem;
24 import com.atlassian.bamboo.specs.builders.task.CommandTask;
25 import com.atlassian.bamboo.specs.builders.task.NpmTask;
26 import com.atlassian.bamboo.specs.builders.task.ScriptTask;
27 import com.atlassian.bamboo.specs.builders.task.TestParserTask;
28 import com.atlassian.bamboo.specs.builders.task.VcsCheckoutTask;
29 import com.atlassian.bamboo.specs.model.task.ScriptTaskProperties;
30 import com.atlassian.bamboo.specs.model.task.TestParserTaskProperties;
31
32 /**
33 * Abstract class with common methods of pre-merge and nightly plan
34 */
35 abstract public class AbstractCoreSpec {
36
37 protected String composerRootVersionEnvironment = "COMPOSER_ROOT_VERSION=9.0.0";
38
39 protected String testingFrameworkBuildPath = "vendor/typo3/testing-framework/Resources/Core/Build/";
40
41 protected String credentialsMysql =
42 "typo3DatabaseName=\"func\"" +
43 " typo3DatabaseUsername=\"funcu\"" +
44 " typo3DatabasePassword=\"funcp\"" +
45 " typo3DatabaseHost=\"localhost\"" +
46 " typo3InstallToolPassword=\"klaus\"";
47
48 protected String credentialsMssql =
49 "typo3DatabaseDriver=\"sqlsrv\"" +
50 " typo3DatabaseName=\"func\"" +
51 " typo3DatabasePassword='Test1234!'" +
52 " typo3DatabaseUsername=\"SA\"" +
53 " typo3DatabaseHost=\"localhost\"" +
54 " typo3DatabasePort=\"1433\"" +
55 " typo3DatabaseCharset=\"utf-8\"" +
56 " typo3InstallToolPassword=\"klaus\"";
57
58 protected String credentialsPgsql =
59 "typo3DatabaseDriver=\"pdo_pgsql\"" +
60 " typo3DatabaseName=\"func\"" +
61 " typo3DatabaseUsername=\"bamboo\"" +
62 " typo3DatabaseHost=\"localhost\"" +
63 " typo3InstallToolPassword=\"klaus\"";
64
65 /**
66 * Job composer validate
67 */
68 protected Job getJobComposerValidate() {
69 return new Job("Validate composer.json", new BambooKey("VC"))
70 .description("Validate composer.json before actual tests are executed")
71 .tasks(
72 this.getTaskGitCloneRepository(),
73 this.getTaskGitCherryPick(),
74 new CommandTask()
75 .description("composer validate")
76 .executable("composer").argument("validate")
77 .environmentVariables(this.composerRootVersionEnvironment)
78 );
79 }
80
81 /**
82 * Job acceptance test installs system on mysql
83 *
84 * @param Requirement requirement
85 * @param String requirementIdentfier
86 */
87 protected Job getJobAcceptanceTestInstallMysql(Requirement requirement, String requirementIdentifier) {
88 return new Job("Accept inst my " + requirementIdentifier, new BambooKey("ACINSTMY" + requirementIdentifier))
89 .description("Install TYPO3 on mysql and create empty frontend page " + requirementIdentifier)
90 .tasks(
91 this.getTaskGitCloneRepository(),
92 this.getTaskGitCherryPick(),
93 this.getTaskComposerInstall(),
94 this.getTaskPrepareAcceptanceTest(),
95 new CommandTask()
96 .description("Execute codeception AcceptanceInstallMysql suite")
97 .executable("codecept")
98 .argument("run AcceptanceInstallMysql -d -c " + this.testingFrameworkBuildPath + "AcceptanceTestsInstallMysql.yml --xml reports.xml --html reports.html")
99 .environmentVariables(this.credentialsMysql)
100 )
101 .finalTasks(
102 new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
103 .resultDirectories("typo3temp/var/tests/AcceptanceReportsInstallMysql/reports.xml"),
104 this.getTaskDeleteMysqlDatabases(),
105 this.getTaskTearDownAcceptanceTestSetup()
106 )
107 .requirements(
108 requirement
109 )
110 .artifacts(new Artifact()
111 .name("Test Report")
112 .copyPattern("typo3temp/var/tests/AcceptanceReportsInstallMysql/")
113 .shared(false));
114 }
115
116 /**
117 * Job acceptance test installs system and introduction package on pgsql
118 *
119 * @param Requirement requirement
120 * @param String requirementIdentfier
121 */
122 protected Job getJobAcceptanceTestInstallPgsql(Requirement requirement, String requirementIdentifier) {
123 return new Job("Accept inst pg " + requirementIdentifier, new BambooKey("ACINSTPG" + requirementIdentifier))
124 .description("Install TYPO3 on pgsql and load introduction package " + requirementIdentifier)
125 .tasks(
126 this.getTaskGitCloneRepository(),
127 this.getTaskGitCherryPick(),
128 this.getTaskComposerInstall(),
129 this.getTaskPrepareAcceptanceTest(),
130 new CommandTask()
131 .description("Execute codeception AcceptanceInstallPgsql suite")
132 .executable("codecept")
133 .argument("run AcceptanceInstallPgsql -d -c " + this.testingFrameworkBuildPath + "AcceptanceTestsInstallPgsql.yml --xml reports.xml --html reports.html")
134 .environmentVariables(this.credentialsPgsql)
135 )
136 .finalTasks(
137 new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
138 .resultDirectories("typo3temp/var/tests/AcceptanceReportsInstallPgsql/reports.xml"),
139 this.getTaskDeletePgsqlDatabases(),
140 this.getTaskTearDownAcceptanceTestSetup()
141 )
142 .requirements(
143 requirement
144 )
145 .artifacts(new Artifact()
146 .name("Test Report")
147 .copyPattern("typo3temp/var/tests/AcceptanceReportsInstallPgsql/")
148 .shared(false));
149 }
150
151 /**
152 * Jobs for mysql based acceptance tests
153 *
154 * @param int numberOfChunks
155 * @param Requirement requirement
156 * @param String requirementIdentifier
157 */
158 protected ArrayList<Job> getJobsAcceptanceTestsMysql(int numberOfChunks, Requirement requirement, String requirementIdentifier) {
159 ArrayList<Job> jobs = new ArrayList<Job>();
160
161 for (int i=1; i<=numberOfChunks; i++) {
162 jobs.add(new Job("Accept my " + requirementIdentifier + " 0" + i, new BambooKey("ACMY" + requirementIdentifier + "0" + i))
163 .description("Run acceptance tests" + requirementIdentifier)
164 .tasks(
165 this.getTaskGitCloneRepository(),
166 this.getTaskGitCherryPick(),
167 this.getTaskComposerInstall(),
168 this.getTaskPrepareAcceptanceTest(),
169 new ScriptTask()
170 .description("Split acceptance tests")
171 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
172 .inlineBody(
173 this.getScriptTaskBashInlineBody() +
174 "./" + this.testingFrameworkBuildPath + "Scripts/splitAcceptanceTests.sh " + numberOfChunks + "\n"
175 ),
176 new CommandTask()
177 .description("Execute codeception acceptance suite group " + i)
178 .executable("codecept")
179 .argument("run Acceptance -d -g AcceptanceTests-Job-" + i + " -c " + this.testingFrameworkBuildPath + "AcceptanceTests.yml --xml reports.xml --html reports.html")
180 .environmentVariables(this.credentialsMysql)
181 )
182 .finalTasks(
183 new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
184 .resultDirectories("typo3temp/var/tests/AcceptanceReports/reports.xml"),
185 this.getTaskDeleteMysqlDatabases(),
186 this.getTaskTearDownAcceptanceTestSetup()
187 )
188 .requirements(
189 requirement
190 )
191 .artifacts(new Artifact()
192 .name("Test Report")
193 .copyPattern("typo3temp/var/tests/AcceptanceReports/")
194 .shared(false)
195 )
196 );
197 }
198
199 return jobs;
200 }
201
202 /**
203 * Jobs for mysql based functional tests
204 *
205 * @param int numberOfChunks
206 * @param Requirement requirement
207 * @param String requirementIdentifier
208 */
209 protected ArrayList<Job> getJobsFunctionalTestsMysql(int numberOfChunks, Requirement requirement, String requirementIdentifier) {
210 ArrayList<Job> jobs = new ArrayList<Job>();
211
212 for (int i=0; i<numberOfChunks; i++) {
213 jobs.add(new Job("Func mysql " + requirementIdentifier + " 0" + i, new BambooKey("FMY" + requirementIdentifier + "0" + i))
214 .description("Run functional tests on mysql DB " + requirementIdentifier)
215 .tasks(
216 this.getTaskGitCloneRepository(),
217 this.getTaskGitCherryPick(),
218 this.getTaskComposerInstall(),
219 this.getTaskSplitFunctionalJobs(numberOfChunks),
220 new ScriptTask()
221 .description("Run phpunit with functional chunk 0" + i)
222 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
223 .inlineBody(
224 this.getScriptTaskBashInlineBody() +
225 "./bin/phpunit --log-junit test-reports/phpunit.xml -c " + this.testingFrameworkBuildPath + "FunctionalTests-Job-" + i + ".xml"
226 )
227 .environmentVariables(this.credentialsMysql)
228 )
229 .finalTasks(
230 this.getTaskDeleteMysqlDatabases(),
231 new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
232 .resultDirectories("test-reports/phpunit.xml")
233 )
234 .requirements(
235 requirement
236 )
237 );
238 }
239
240 return jobs;
241 }
242
243 /**
244 * Jobs for mssql based functional tests
245 *
246 * @param int numberOfChunks
247 * @param Requirement requirement
248 * @param String requirementIdentifier
249 */
250 protected ArrayList<Job> getJobsFunctionalTestsMssql(int numberOfChunks, Requirement requirement, String requirementIdentifier) {
251 ArrayList<Job> jobs = new ArrayList<Job>();
252
253 for (int i=0; i<numberOfChunks; i++) {
254 jobs.add(new Job("Func mssql " + requirementIdentifier + " 0" + i, new BambooKey("FMS" + requirementIdentifier + "0" + i))
255 .description("Run functional tests on mysql DB " + requirementIdentifier)
256 .tasks(
257 this.getTaskGitCloneRepository(),
258 this.getTaskGitCherryPick(),
259 this.getTaskComposerInstall(),
260 this.getTaskSplitFunctionalJobs(numberOfChunks),
261 new ScriptTask()
262 .description("Run phpunit with functional chunk 0" + i)
263 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
264 .inlineBody(
265 this.getScriptTaskBashInlineBody() +
266 "./bin/phpunit --exclude-group not-mssql --log-junit test-reports/phpunit.xml -c " + this.testingFrameworkBuildPath + "FunctionalTests-Job-" + i + ".xml"
267 )
268 .environmentVariables(this.credentialsMssql)
269 )
270 .finalTasks(
271 this.getTaskDeleteMssqlDatabases(),
272 new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
273 .resultDirectories("test-reports/phpunit.xml")
274 )
275 .requirements(
276 requirement
277 )
278 );
279 }
280
281 return jobs;
282 }
283
284 /**
285 * Jobs for pgsql based functional tests
286 *
287 * @param int numberOfChunks
288 * @param Requirement requirement
289 * @param String requirementIdentifier
290 */
291 protected ArrayList<Job> getJobsFunctionalTestsPgsql(int numberOfChunks, Requirement requirement, String requirementIdentifier) {
292 ArrayList<Job> jobs = new ArrayList<Job>();
293
294 for (int i=0; i<numberOfChunks; i++) {
295 jobs.add(new Job("Func pgsql " + requirementIdentifier + " 0" + i, new BambooKey("FPG" + requirementIdentifier + "0" + i))
296 .description("Run functional tests on pgsql DB " + requirementIdentifier)
297 .tasks(
298 this.getTaskGitCloneRepository(),
299 this.getTaskGitCherryPick(),
300 this.getTaskComposerInstall(),
301 this.getTaskSplitFunctionalJobs(numberOfChunks),
302 new ScriptTask()
303 .description("Run phpunit with functional chunk 0" + i)
304 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
305 .inlineBody(
306 this.getScriptTaskBashInlineBody() +
307 "./bin/phpunit --exclude-group not-postgres --log-junit test-reports/phpunit.xml -c " + this.testingFrameworkBuildPath + "FunctionalTests-Job-" + i + ".xml"
308 )
309 .environmentVariables(this.credentialsPgsql)
310 )
311 .finalTasks(
312 this.getTaskDeletePgsqlDatabases(),
313 new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
314 .resultDirectories("test-reports/phpunit.xml")
315 )
316 .requirements(
317 requirement
318 )
319 );
320 }
321
322 return jobs;
323 }
324
325 /**
326 * Job with various smaller script tests
327 */
328 protected Job getJobIntegrationVarious() {
329 // Exception code checker, xlf, permissions, rst file check
330 return new Job("Integration various", new BambooKey("CDECC"))
331 .description("Checks duplicate exceptions, git submodules, xlf files, permissions, rst")
332 .tasks(
333 this.getTaskGitCloneRepository(),
334 this.getTaskGitCherryPick(),
335 this.getTaskComposerInstall(),
336 new ScriptTask()
337 .description("Run duplicate exception code check script")
338 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
339 .inlineBody(
340 this.getScriptTaskBashInlineBody() +
341 "./Build/Scripts/duplicateExceptionCodeCheck.sh\n"
342 ),
343 new ScriptTask()
344 .description("Run git submodule status and verify there are none")
345 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
346 .inlineBody(
347 this.getScriptTaskBashInlineBody() +
348 "if [[ `git submodule status 2>&1 | wc -l` -ne 0 ]]; then\n" +
349 " echo \\\"Found a submodule definition in repository\\\";\n" +
350 " exit 99;\n" +
351 "fi\n"
352 ),
353 new ScriptTask()
354 .description("Run permission check script")
355 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
356 .inlineBody(
357 this.getScriptTaskBashInlineBody() +
358 "./Build/Scripts/checkFilePermissions.sh\n"
359 ),
360 new ScriptTask()
361 .description("Run xlf check")
362 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
363 .inlineBody(
364 this.getScriptTaskBashInlineBody() +
365 "./Build/Scripts/xlfcheck.sh"
366 ),
367 new ScriptTask()
368 .description("Run rst check")
369 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
370 .inlineBody(
371 this.getScriptTaskBashInlineBody() +
372 "./Build/Scripts/validateRstFiles.sh"
373 ),
374 new ScriptTask()
375 .description("Run path length check")
376 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
377 .inlineBody(
378 this.getScriptTaskBashInlineBody() +
379 "./Build/Scripts/maxFilePathLength.sh"
380 ),
381 new ScriptTask()
382 .description("Run extension scanner ReST file reference tester")
383 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
384 .inlineBody(
385 this.getScriptTaskBashInlineBody() +
386 "./Build/Scripts/extensionScannerRstFileReferences.php"
387 )
388 )
389 .requirements(
390 new Requirement("system.phpVersion")
391 .matchValue("7\\.0|7\\.1")
392 .matchType(Requirement.MatchType.MATCHES)
393 );
394 }
395
396 /**
397 * Job for javascript unit tests
398 */
399 protected Job getJobUnitJavaScript() {
400 return new Job("Unit JavaScript", new BambooKey("JSUT"))
401 .description("Run JavaScript unit tests")
402 .tasks(
403 this.getTaskGitCloneRepository(),
404 this.getTaskGitCherryPick(),
405 this.getTaskComposerInstall(),
406 new NpmTask()
407 .description("npm install in Build/ dir")
408 .nodeExecutable("Node.js")
409 .workingSubdirectory("Build/")
410 .command("install"),
411 new ScriptTask()
412 .description("Run tests")
413 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
414 .inlineBody(
415 this.getScriptTaskBashInlineBody() +
416 "./Build/node_modules/karma/bin/karma start " + this.testingFrameworkBuildPath + "Configuration/JSUnit/karma.conf.js --single-run"
417 )
418 )
419 .finalTasks(
420 new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
421 .resultDirectories("typo3temp/var/tests/*")
422 )
423 .requirements(
424 new Requirement("system.phpVersion")
425 .matchValue("7\\.0|7\\.1")
426 .matchType(Requirement.MatchType.MATCHES)
427 )
428 .artifacts(
429 new Artifact()
430 .name("Clover Report (System)")
431 .copyPattern("**/*.*")
432 .location("Build/target/site/clover")
433 .shared(false)
434 );
435 }
436
437 /**
438 * Job for PHP lint
439 *
440 * @param Requirement requirement
441 * @param String requirementIdentfier
442 */
443 protected Job getJobLintPhp(Requirement requirement, String requirementIdentifier) {
444 return new Job("Lint " + requirementIdentifier, new BambooKey("L" + requirementIdentifier))
445 .description("Run php -l on source files for linting " + requirementIdentifier)
446 .tasks(
447 this.getTaskGitCloneRepository(),
448 this.getTaskGitCherryPick(),
449 new ScriptTask()
450 .description("Run php lint")
451 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
452 .inlineBody(
453 this.getScriptTaskBashInlineBody() +
454 "find . -name \\*.php -print0 | xargs -0 -n1 -P2 php -l >/dev/null\n"
455 )
456 )
457 .requirements(
458 requirement
459 );
460 }
461
462 /**
463 * Job for lint npm scss and typescript
464 */
465 protected Job getJobLintScssTs() {
466 return new Job("Lint scss ts", new BambooKey("LSTS"))
467 .description("Run npm lint in Build/ dir")
468 .tasks(
469 this.getTaskGitCloneRepository(),
470 this.getTaskGitCherryPick(),
471 new NpmTask()
472 .description("npm install in Build/ dir")
473 .nodeExecutable("Node.js")
474 .workingSubdirectory("Build/")
475 .command("install"),
476 new NpmTask()
477 .description("Run npm lint")
478 .nodeExecutable("Node.js")
479 .workingSubdirectory("Build/")
480 .command("run lint")
481 )
482 .requirements(
483 new Requirement("system.imageVersion")
484 );
485 }
486
487 /**
488 * Job for unit testing PHP
489 *
490 * @param Requirement requirement
491 * @param String requirementIdentfier
492 */
493 protected Job getJobUnitPhp(Requirement requirement, String requirementIdentifier) {
494 return new Job("Unit " + requirementIdentifier, new BambooKey("UT" + requirementIdentifier))
495 .description("Run unit tests " + requirementIdentifier)
496 .tasks(
497 this.getTaskGitCloneRepository(),
498 this.getTaskGitCherryPick(),
499 this.getTaskComposerInstall(),
500 new ScriptTask()
501 .description("Run phpunit")
502 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
503 .inlineBody(
504 this.getScriptTaskBashInlineBody() +
505 this.getScriptTaskBashPhpNoXdebug() +
506 "php_no_xdebug bin/phpunit --log-junit test-reports/phpunit.xml -c " + this.testingFrameworkBuildPath + "UnitTests.xml"
507 )
508 )
509 .finalTasks(
510 new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
511 .resultDirectories("test-reports/phpunit.xml")
512 )
513 .requirements(
514 requirement
515 );
516 }
517
518 /**
519 * Jobs for unit testing PHP in random test order
520 *
521 * @param int numberOfRuns
522 * @param Requirement requirement
523 * @param String requirementIdentfier
524 */
525 protected ArrayList<Job> getJobUnitPhpRandom(int numberOfRuns, Requirement requirement, String requirementIdentifier) {
526 ArrayList<Job> jobs = new ArrayList<Job>();
527
528 for (int i=0; i<numberOfRuns; i++) {
529 jobs.add(new Job("Unit " + requirementIdentifier + " random 0" + i, new BambooKey("UTR" + requirementIdentifier + "0" + i))
530 .description("Run unit tests on " + requirementIdentifier + " in random order 0" + i)
531 .tasks(
532 this.getTaskGitCloneRepository(),
533 this.getTaskGitCherryPick(),
534 this.getTaskComposerInstall(),
535 new ScriptTask()
536 .description("Run phpunit-randomizer")
537 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
538 .inlineBody(
539 this.getScriptTaskBashInlineBody() +
540 this.getScriptTaskBashPhpNoXdebug() +
541 "php_no_xdebug bin/phpunit-randomizer --log-junit test-reports/phpunit.xml -c " + this.testingFrameworkBuildPath + "UnitTests.xml --order rand"
542 )
543 )
544 .finalTasks(
545 new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
546 .resultDirectories("test-reports/phpunit.xml")
547 )
548 .requirements(
549 requirement
550 )
551 );
552 }
553
554 return jobs;
555 }
556
557 /**
558 * Task definition for basic core clone of linked default repository
559 */
560 protected Task getTaskGitCloneRepository() {
561 return new VcsCheckoutTask()
562 .description("Checkout git core")
563 .checkoutItems(new CheckoutItem().defaultRepository())
564 .cleanCheckout(true);
565 }
566
567 /**
568 * Task definition to cherry pick a patch set from gerrit on top of cloned core
569 */
570 protected Task getTaskGitCherryPick() {
571 return new ScriptTask()
572 .description("Gerrit cherry pick")
573 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
574 .inlineBody(
575 this.getScriptTaskBashInlineBody() +
576 "CHANGEURL=${bamboo.changeUrl}\n" +
577 "CHANGEURLID=${CHANGEURL#https://review.typo3.org/}\n" +
578 "PATCHSET=${bamboo.patchset}\n" +
579 "\n" +
580 "if [[ $CHANGEURL ]]; then\n" +
581 " gerrit-cherry-pick https://review.typo3.org/Packages/TYPO3.CMS $CHANGEURLID/$PATCHSET || exit 1\n" +
582 "fi\n"
583 );
584 }
585
586 /**
587 * Task definition to execute composer install
588 */
589 protected Task getTaskComposerInstall() {
590 return new CommandTask()
591 .description("composer install")
592 .executable("composer")
593 .argument("install -n")
594 .environmentVariables(this.composerRootVersionEnvironment);
595 }
596
597 /**
598 * Task to prepare an acceptance test starting selenium and others
599 */
600 protected Task getTaskPrepareAcceptanceTest() {
601 return new ScriptTask()
602 .description("Start xvfb, selenium, php web server, prepare chrome environment")
603 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
604 .inlineBody(
605 this.getScriptTaskBashInlineBody() +
606 "# start xvfb until chrome headless can be used\n" +
607 "/sbin/start-stop-daemon --start --quiet --pidfile xvfb.pid --make-pidfile --background --exec /usr/bin/Xvfb :99\n" +
608 "\n" +
609 "# the display chrome should render to (xvfb)\n" +
610 "export DISPLAY=\":99\"\n" +
611 "\n" +
612 "PATH=$PATH:./bin DBUS_SESSION_BUS_ADDRESS=/dev/null ./bin/selenium-server-standalone >/dev/null 2>&1 & \n" +
613 "echo $! > selenium.pid\n" +
614 "\n" +
615 "# Wait for selenium server to load\n" +
616 "until $(curl --output /dev/null --silent --head --fail http://localhost:4444/wd/hub); do\n" +
617 " printf '.'\n sleep 1\n" +
618 "done\n" +
619 "\n" +
620 "php -S localhost:8000 >/dev/null 2>&1 &\n" +
621 "echo $! > phpserver.pid\n" +
622 "\n" +
623 "mkdir -p typo3temp/var/tests/\n"
624 );
625 }
626
627 /**
628 * Task to delete any created mysql test databases, used as final task
629 */
630 protected Task getTaskDeleteMysqlDatabases() {
631 return new ScriptTask()
632 .description("Delete mysql test dbs")
633 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
634 .inlineBody(
635 this.getScriptTaskBashInlineBody() +
636 "DB_STARTS_WITH=\"func_\"\n" +
637 "MUSER=\"funcu\"\n" +
638 "MPWD=\"funcp\"\n" +
639 "MYSQL=\"mysql\"\n" +
640 "DBS=\"$($MYSQL -u $MUSER -p\"$MPWD\" -Bse 'show databases')\"\n" +
641 "\n" +
642 "for db in $DBS; do\n" +
643 " if [[ \"$db\" == $DB_STARTS_WITH* ]]; then\n" +
644 " echo \"Deleting $db\"\n" +
645 " $MYSQL -u $MUSER -p\"$MPWD\" -Bse \"drop database $db\"\n" +
646 " fi\n" +
647 "done\n"
648 );
649 }
650
651 /**
652 * Task to delete any created mssql test databases, used as final task
653 */
654 protected Task getTaskDeleteMssqlDatabases() {
655 return new ScriptTask()
656 .description("Delete mssql test dbs")
657 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
658 .inlineBody(
659 this.getScriptTaskBashInlineBody() +
660 "DBS=`/opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P 'Test1234!' -Q 'select name from sys.databases' | grep '^func_'`\n" +
661 "\n" +
662 "for db in $DBS; do\n" +
663 " echo \"Deleteing $db\"\n" +
664 " /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P 'Test1234!' -Q \"drop database $db\"\n" +
665 "done\n"
666 );
667 }
668
669 /**
670 * Task to delete any created pgsql test databases, used as final task
671 */
672 protected Task getTaskDeletePgsqlDatabases() {
673 return new ScriptTask()
674 .description("Delete pgsql test dbs")
675 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
676 .inlineBody(
677 this.getScriptTaskBashInlineBody() +
678 "DB_STARTS_WITH=\"func_\"\n" +
679 "PGUSER=\"bamboo\"\n" +
680 "DBS=\"$(/usr/bin/psql -qtA -c 'SELECT datname FROM pg_database WHERE datistemplate = false;' postgres)\"\n" +
681 "\n" +
682 "for db in $DBS; do\n" +
683 " if [[ \"$db\" == $DB_STARTS_WITH* ]]; then\n" +
684 " echo \"Deleting $db\"\n" +
685 " /usr/bin/psql -qtA -c \"DROP DATABASE $db\" postgres\n" +
686 " fi\n" +
687 "done\n"
688 );
689 }
690
691 /**
692 * Task to stop selenium and friends, opposite of getTaskPrepareAcceptanceTest, used as final task
693 */
694 protected Task getTaskTearDownAcceptanceTestSetup() {
695 return new ScriptTask()
696 .description("Stop acceptance test services like selenium and friends")
697 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
698 .inlineBody(
699 this.getScriptTaskBashInlineBody() +
700 "kill `cat phpserver.pid`\n" +
701 "kill `cat selenium.pid`\n" +
702 "kill `cat xvfb.pid`\n"
703 );
704 }
705
706 /**
707 * Task to split functional jobs into chunks
708 */
709 protected Task getTaskSplitFunctionalJobs(int numberOfJobs) {
710 return new ScriptTask()
711 .description("Create list of test files to execute per job")
712 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
713 .inlineBody(
714 this.getScriptTaskBashInlineBody() +
715 "./" + this.testingFrameworkBuildPath + "Scripts/splitFunctionalTests.sh " + numberOfJobs
716 );
717 }
718
719 /**
720 * Requirement for php 7.0
721 */
722 protected Requirement getRequirementPhpVersion70() {
723 return new Requirement("system.phpVersion")
724 .matchValue("7.0")
725 .matchType(Requirement.MatchType.EQUALS);
726 }
727
728 /**
729 * Requirement for php 7.1
730 */
731 protected Requirement getRequirementPhpVersion71() {
732 return new Requirement("system.phpVersion")
733 .matchValue("7.1")
734 .matchType(Requirement.MatchType.EQUALS);
735 }
736
737 /**
738 * Requirement for php 7.0 or 7.1
739 */
740 protected Requirement getRequirementPhpVersion70Or71() {
741 return new Requirement("system.phpVersion")
742 .matchValue("7\\.0|7\\.1")
743 .matchType(Requirement.MatchType.MATCHES);
744 }
745
746 /**
747 * A bash header for script tasks forking a bash if needed
748 */
749 protected String getScriptTaskBashInlineBody() {
750 return
751 "#!/bin/bash\n" +
752 "\n" +
753 "if [ \"$(ps -p \"$$\" -o comm=)\" != \"bash\" ]; then\n" +
754 " bash \"$0\" \"$@\"\n" +
755 " exit \"$?\"\n" +
756 "fi\n" +
757 "\n";
758 }
759
760 /**
761 * A bash function providing a php bin without xdebug
762 */
763 protected String getScriptTaskBashPhpNoXdebug() {
764 return
765 "php_no_xdebug () {\n" +
766 " temporaryPath=\"$(mktemp -t php.XXXX).ini\"\n" +
767 " php -i | grep \"\\.ini\" | grep -o -e '\\(/[A-Za-z0-9._-]\\+\\)\\+\\.ini' | grep -v xdebug | xargs awk 'FNR==1{print \"\"}1' > \"${temporaryPath}\"\n" +
768 " php -n -c \"${temporaryPath}\" \"$@\"\n" +
769 " RETURN=$?\n" +
770 " rm -f \"${temporaryPath}\"\n" +
771 " exit $RETURN\n" +
772 "}\n" +
773 "\n";
774 }
775 }