runTests.sh 32 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/env bash

#
# TYPO3 core test runner based on docker and docker-compose.
#

# Function to write a .env file in Build/testing-docker/local
# This is read by docker-compose and vars defined here are
# used in Build/testing-docker/local/docker-compose.yml
setUpDockerComposeDotEnv() {
    # Delete possibly existing local .env file if exists
    [ -e .env ] && rm .env
    # Set up a new .env file for docker-compose
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
    {
        echo "COMPOSE_PROJECT_NAME=local"
        # To prevent access rights of files created by the testing, the docker image later
        # runs with the same user that is currently executing the script. docker-compose can't
        # use $UID directly itself since it is a shell variable and not an env variable, so
        # we have to set it explicitly here.
        echo "HOST_UID=$(id -u)"
        # Your local user
        echo "CORE_ROOT=${CORE_ROOT}"
        echo "HOST_USER=${USER}"
        echo "TEST_FILE=${TEST_FILE}"
        echo "PHP_XDEBUG_ON=${PHP_XDEBUG_ON}"
        echo "PHP_XDEBUG_PORT=${PHP_XDEBUG_PORT}"
        echo "DOCKER_PHP_IMAGE=${DOCKER_PHP_IMAGE}"
        echo "EXTRA_TEST_OPTIONS=${EXTRA_TEST_OPTIONS}"
        echo "SCRIPT_VERBOSE=${SCRIPT_VERBOSE}"
        echo "PHPUNIT_RANDOM=${PHPUNIT_RANDOM}"
        echo "CGLCHECK_DRY_RUN=${CGLCHECK_DRY_RUN}"
        echo "DATABASE_DRIVER=${DATABASE_DRIVER}"
        echo "MARIADB_VERSION=${MARIADB_VERSION}"
        echo "MYSQL_VERSION=${MYSQL_VERSION}"
        echo "POSTGRES_VERSION=${POSTGRES_VERSION}"
        echo "PHP_VERSION=${PHP_VERSION}"
        echo "CHUNKS=${CHUNKS}"
        echo "THISCHUNK=${THISCHUNK}"
39
        echo "DOCKER_SELENIUM_IMAGE=${DOCKER_SELENIUM_IMAGE}"
40
41
        echo "IS_CORE_CI=${IS_CORE_CI}"
        echo "PHPSTAN_CONFIG_FILE=${PHPSTAN_CONFIG_FILE}"
42
    } > .env
43
}
44

45
46
47
48
# Options -a and -d depend on each other. The function
# validates input combinations and sets defaults.
handleDbmsAndDriverOptions() {
    case ${DBMS} in
49
        mysql|mariadb)
50
            [ -z "${DATABASE_DRIVER}" ] && DATABASE_DRIVER="mysqli"
51
52
53
            if [ "${DATABASE_DRIVER}" != "mysqli" ] && [ "${DATABASE_DRIVER}" != "pdo_mysql" ]; then
                echo "Invalid option -a ${DATABASE_DRIVER} with -d ${DBMS}" >&2
                echo >&2
54
                echo "call \".Build/Scripts/runTests.sh -h\" to display help and valid options" >&2
55
56
57
                exit 1
            fi
            ;;
58
        postgres|sqlite)
59
            if [ -n "${DATABASE_DRIVER}" ]; then
60
61
                echo "Invalid option -a ${DATABASE_DRIVER} with -d ${DBMS}" >&2
                echo >&2
62
                echo "call \".Build/Scripts/runTests.sh -h\" to display help and valid options" >&2
63
64
65
66
                exit 1
            fi
            ;;
    esac
67
68
}

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
cleanBuildFiles() {
    # > builds
    echo -n "Clean builds ... " ; rm -rf \
        ../../../Build/JavaScript \
        ../../../Build/node_modules ; \
        echo "done"
}

cleanCacheFiles() {
    # > caches
    echo -n "Clean caches ... " ; rm -rf \
        ../../../.cache \
        ../../../Build/.cache \
        ../../../Build/composer/.cache/ \
        ../../../.php-cs-fixer.cache ; \
        echo "done"
}

cleanTestFiles() {
    # > composer distribution test
    echo -n "Clean composer distribution test ... " ; rm -rf \
        ../../../Build/composer/composer.json \
        ../../../Build/composer/composer.lock \
        ../../../Build/composer/public/index.php \
        ../../../Build/composer/public/typo3 \
        ../../../Build/composer/public/typo3conf/ext \
        ../../../Build/composer/var/ \
        ../../../Build/composer/vendor/ ; \
       echo "done"

    # > test related
    echo -n "Clean test related files ... " ; rm -rf \
        ../../../Build/phpunit/FunctionalTests-Job-*.xml \
        ../../../typo3/sysext/core/Tests/Acceptance/AcceptanceTests-Job-* \
        ../../../typo3/sysext/core/Tests/Acceptance/Support/_generated \
        ../../../typo3temp/var/tests/ ; \
        echo "done"
}

108
109
110
111
112
113
114
cleanRenderedDocumentationFiles() {
    # > caches
    echo -n "Clean rendered documentation files ... " ; rm -rf \
        ../../../typo3/sysext/*/Documentation-GENERATED-temp ; \
        echo "done"
}

115
# Load help text into $HELP
116
# @todo Remove xdebug / php8.2 note after PHP8.2 image contains working xdebug.
117
118
119
120
121
read -r -d '' HELP <<EOF
TYPO3 core test runner. Execute acceptance, unit, functional and other test suites in
a docker based test environment. Handles execution of single test files, sending
xdebug information to a local IDE and more.

122
123
Recommended docker version is >=20.10 for xdebug break pointing to work reliably, and
a recent docker-compose (tested >=1.21.2) is needed.
124
125
126

Usage: $0 [options] [file]

127
No arguments: Run all unit tests with PHP 8.1
128
129
130
131

Options:
    -s <...>
        Specifies which test suite to run
132
            - acceptance: main application acceptance tests
133
            - acceptanceInstall: installation acceptance tests, only with -d mariadb|postgres|sqlite
134
135
            - buildCss: execute scss to css builder
            - buildJavascript: execute typescript to javascript builder
136
            - cgl: test and fix all core php files
137
138
            - cglGit: test and fix latest committed patch for CGL compliance
            - checkAnnotations: check php code for allowed annotations
139
            - checkBom: check UTF-8 files do not contain BOM
140
141
142
143
144
            - checkComposer: check composer.json files for version integrity
            - checkExceptionCodes: test core for duplicate exception codes
            - checkExtensionScannerRst: test all .rst files referenced by extension scanner exist
            - checkFilePathLength: test core file paths do not exceed maximum length
            - checkGitSubmodule: test core git has no sub modules defined
145
            - checkGruntClean: Verify "grunt build" is clean. Warning: Executes git commands! Usually used in CI only.
146
            - checkNamespaceIntegrity: Verify namespace integrity in class and test code files are in good shape.
147
148
            - checkPermissions: test some core files for correct executable bits
            - checkRst: test .rst files for integrity
149
            - checkTestMethodsPrefix: check tests methods do not start with "test"
150
151
152
            - clean: clean up build, cache and testing related files and folders
            - cleanBuild: clean up build related files and folders
            - cleanCache: clean up cache related files and folders
153
            - cleanRenderedDocumentation: clean up rendered documentation files and folders (Documentation-GENERATED-temp)
154
            - cleanTests: clean up test related files and folders
155
156
157
            - composerInstall: "composer install"
            - composerInstallMax: "composer update", with no platform.php config.
            - composerInstallMin: "composer update --prefer-lowest", with platform.php set to PHP version x.x.0.
158
            - composerTestDistribution: "composer update" in Build/composer to verify core dependencies
159
            - composerValidate: "composer validate"
160
161
            - functional: PHP functional tests
            - functionalDeprecated: deprecated PHP functional tests
162
            - lintPhp: PHP linting
163
164
            - lintScss: SCSS linting
            - lintTypescript: TS linting
165
            - lintHtml: HTML linting
166
            - listExceptionCodes: list core exception codes in JSON format
167
            - phpstan: phpstan tests
168
            - phpstanGenerateBaseline: regenerate phpstan baseline, handy after phpstan updates
169
170
171
172
173
            - unit (default): PHP unit tests
            - unitDeprecated: deprecated PHP unit tests
            - unitJavascript: JavaScript unit tests
            - unitRandom: PHP unit tests in random order, add -o <number> to use specific seed

174
    -a <mysqli|pdo_mysql>
175
        Only with -s functional|functionalDeprecated
176
177
178
179
180
181
182
183
        Specifies to use another driver, following combinations are available:
            - mysql
                - mysqli (default)
                - pdo_mysql
            - mariadb
                - mysqli (default)
                - pdo_mysql

184
    -d <sqlite|mariadb|mysql|postgres>
185
        Only with -s functional|functionalDeprecated|acceptance|acceptanceInstall
186
        Specifies on which DBMS tests are performed
187
188
            - sqlite: (default): use sqlite
            - mariadb use mariadb
189
            - mysql: use MySQL server
190
191
            - postgres: use postgres

192
    -i <10.3|10.4|10.5|10.6|10.7>
193
194
195
196
197
        Only with -d mariadb
        Specifies on which version of mariadb tests are performed
            - 10.3 (default)
            - 10.4
            - 10.5
198
199
            - 10.6
            - 10.7
200

201
    -j <8.0>
202
203
        Only with -d mysql
        Specifies on which version of mysql tests are performed
204
            - 8.0 (default)
205

206
    -k <10|11|12|13|14>
207
208
209
210
211
        Only with -d postgres
        Specifies on which version of postgres tests are performed
            - 10 (default)
            - 11
            - 12
212
213
            - 13
            - 14
214

215
216
217
218
219
    -c <chunk/numberOfChunks>
        Only with -s functional|acceptance
        Hack functional or acceptance tests into #numberOfChunks pieces and run tests of #chunk.
        Example -c 3/13

220
    -p <8.1|8.2>
221
        Specifies the PHP minor version to be used
222
            - 8.1 (default): use PHP 8.1
223
            - 8.2: use PHP 8.2 (note that xdebug is currently not available for PHP8.2)
224

225
    -e "<phpunit options>"
226
        Only with -s functional|functionalDeprecated|unit|unitDeprecated|unitRandom|acceptance
227
228
229
230
231
232
        Additional options to send to phpunit (unit & functional tests) or codeception (acceptance
        tests). For phpunit, options starting with "--" must be added after options starting with "-".
        Example -e "-v --filter canRetrieveValueWithGP" to enable verbose output AND filter tests
        named "canRetrieveValueWithGP"

    -x
233
        Only with -s functional|functionalDeprecated|unit|unitDeprecated|unitRandom|acceptance|acceptanceInstall
234
        Send information to host instance for test or system under test break points. This is especially
Christian Kuhn's avatar
Christian Kuhn committed
235
        useful if a local PhpStorm instance is listening on default xdebug port 9003. A different port
236
237
238
        can be selected with -y

    -y <port>
Christian Kuhn's avatar
Christian Kuhn committed
239
        Send xdebug information to a different port than default 9003 if an IDE like PhpStorm
240
241
242
243
244
        is not listening on default port.

    -o <number>
        Only with -s unitRandom
        Set specific random seed to replay a random run in this order again. The phpunit randomizer
Christian Kuhn's avatar
Christian Kuhn committed
245
        outputs the used seed at the end (in gitlab core testing logs, too). Use that number to
246
247
248
        replay the unit tests in that order.

    -n
249
        Only with -s cgl|cglGit
250
251
252
        Activate dry-run in CGL check that does not actively change files and only prints broken ones.

    -u
253
254
255
256
        Update existing typo3/core-testing-*:latest docker images and remove dangling local docker volumes.
        Maintenance call to docker pull latest versions of the main php images. The images are updated once
        in a while and only the latest ones are supported by core testing. Use this if weird test errors occur.
        Also removes obsolete image versions of typo3/core-testing-*.
257
258
259
260
261
262
263
264

    -v
        Enable verbose script output. Shows variables and docker commands.

    -h
        Show this help.

Examples:
265
    # Run all core unit tests using PHP 8.1
266
267
268
    ./Build/Scripts/runTests.sh
    ./Build/Scripts/runTests.sh -s unit

Christian Kuhn's avatar
Christian Kuhn committed
269
    # Run all core units tests and enable xdebug (have a PhpStorm listening on port 9003!)
270
271
    ./Build/Scripts/runTests.sh -x

272
    # Run unit tests in phpunit verbose mode with xdebug on PHP 8.1 and filter for test canRetrieveValueWithGP
273
    ./Build/Scripts/runTests.sh -x -p 8.1 -e "-v --filter canRetrieveValueWithGP"
274

275
276
277
278
    # Run functional tests in phpunit with a filtered test method name in a specified file
    # example will currently execute two tests, both of which start with the search term
    ./Build/Scripts/runTests.sh -s functional -e "--filter deleteContent" typo3/sysext/core/Tests/Functional/DataHandling/Regular/Modify/ActionTest.php

279
280
    # Run unit tests with PHP 8.1 and have xdebug enabled
    ./Build/Scripts/runTests.sh -x -p 8.1
281

282
    # Run functional tests on postgres with xdebug, php 8.1 and execute a restricted set of tests
283
    ./Build/Scripts/runTests.sh -x -p 8.1 -s functional -d postgres typo3/sysext/core/Tests/Functional/Authentication
284

285
286
287
288
    # Run functional tests on mariadb 10.5
    ./Build/Scripts/runTests.sh -d mariadb -i 10.5

    # Run functional tests on postgres 11
289
    ./Build/Scripts/runTests.sh -s functional -d postgres -k 11
290

291
292
    # Run restricted set of application acceptance tests
    ./Build/Scripts/runTests.sh -s acceptance typo3/sysext/core/Tests/Acceptance/Application/Login/BackendLoginCest.php:loginButtonMouseOver
293
294

    # Run installer tests of a new instance on sqlite
295
    ./Build/Scripts/runTests.sh -s acceptanceInstall -d sqlite
296
297
298
299
EOF

# Test if docker-compose exists, else exit out with error
if ! type "docker-compose" > /dev/null; then
300
301
    echo "This script relies on docker and docker-compose. Please install" >&2
    exit 1
302
303
fi

304
305
# docker-compose v2 is enabled by docker for mac as experimental feature without
# asking the user. v2 is currently broken. Detect the version and error out.
306
307
308
DOCKER_COMPOSE_VERSION=$(docker-compose version --short)
DOCKER_COMPOSE_MAJOR=$(echo "$DOCKER_COMPOSE_VERSION" | cut -d'.' -f1 | tr -d 'v')
if [ "$DOCKER_COMPOSE_MAJOR" -gt "1" ]; then
309
    echo "docker-compose $DOCKER_COMPOSE_VERSION is currently broken and not supported by runTests.sh."
310
    echo "If you are running Docker Desktop for MacOS/Windows disable 'Use Docker Compose V2' (Preferences > General)"
311
312
313
    exit 1
fi

314
315
# Go to the directory this script is located, so everything else is relative
# to this dir, no matter from where this script is called.
316
THIS_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
317
318
319
320
321
cd "$THIS_SCRIPT_DIR" || exit 1

# Go to directory that contains the local docker-compose.yml file
cd ../testing-docker/local || exit 1

322
323
# Set core root path by checking whether realpath exists
if ! command -v realpath &> /dev/null; then
324
325
    echo "Consider installing realpath for properly resolving symlinks" >&2
    CORE_ROOT="${PWD}/../../../"
326
else
327
    CORE_ROOT=$(realpath "${PWD}/../../../")
328
329
fi

330
331
# Option defaults
TEST_SUITE="unit"
332
DBMS="sqlite"
333
PHP_VERSION="8.1"
334
PHP_XDEBUG_ON=0
Christian Kuhn's avatar
Christian Kuhn committed
335
PHP_XDEBUG_PORT=9003
336
337
EXTRA_TEST_OPTIONS=""
SCRIPT_VERBOSE=0
Christian Kuhn's avatar
Christian Kuhn committed
338
PHPUNIT_RANDOM=""
339
CGLCHECK_DRY_RUN=""
340
DATABASE_DRIVER=""
341
MARIADB_VERSION="10.3"
342
MYSQL_VERSION="8.0"
343
POSTGRES_VERSION="10"
344
345
CHUNKS=0
THISCHUNK=0
346
DOCKER_SELENIUM_IMAGE="selenium/standalone-chrome:4.0.0-20211102"
347
348
349
350
351
352
353
354
IS_CORE_CI=0
PHPSTAN_CONFIG_FILE="phpstan.local.neon"

# ENV var "CI" is set by gitlab-ci. We use it here to distinct 'local' and 'CI' environment.
if [ "$CI" == "true" ]; then
    IS_CORE_CI=1
    PHPSTAN_CONFIG_FILE="phpstan.ci.neon"
fi
355
356
357
358
359
360
361
362
363

# Detect arm64 and use a seleniarm image.
# In a perfect world selenium would have a arm64 integrated, but that is not on the horizon.
# So for the time being we have to use seleniarm image.
ARCH=$(uname -m)
if [ $ARCH = "arm64" ]; then
    DOCKER_SELENIUM_IMAGE="seleniarm/standalone-chromium:4.1.2-20220227"
    echo "Architecture" $ARCH "requires" $DOCKER_SELENIUM_IMAGE "to run acceptance tests."
fi
364
365
366
367
368
369
370

# Option parsing
# Reset in case getopts has been used previously in the shell
OPTIND=1
# Array for invalid options
INVALID_OPTIONS=();
# Simple option parsing based on getopts (! not getopt)
371
while getopts ":a:s:c:d:i:j:k:p:e:xy:o:nhuv" OPT; do
372
    case ${OPT} in
373
374
375
        s)
            TEST_SUITE=${OPTARG}
            ;;
376
377
378
        a)
            DATABASE_DRIVER=${OPTARG}
            ;;
379
380
        c)
            if ! [[ ${OPTARG} =~ ^([0-9]+\/[0-9]+)$ ]]; then
381
                INVALID_OPTIONS+=("${OPTARG}")
382
383
            else
                # Split "2/13" - run chunk 2 of 13 chunks
384
385
                THISCHUNK=$(echo "${OPTARG}" | cut -d '/' -f1)
                CHUNKS=$(echo "${OPTARG}" | cut -d '/' -f2)
386
            fi
387
388
389
390
            ;;
        d)
            DBMS=${OPTARG}
            ;;
391
392
        i)
            MARIADB_VERSION=${OPTARG}
393
            if ! [[ ${MARIADB_VERSION} =~ ^(10.3|10.4|10.5|10.6|10.7)$ ]]; then
394
                INVALID_OPTIONS+=("${OPTARG}")
395
396
397
398
            fi
            ;;
        j)
            MYSQL_VERSION=${OPTARG}
399
            if ! [[ ${MYSQL_VERSION} =~ ^(8.0)$ ]]; then
400
                INVALID_OPTIONS+=("${OPTARG}")
401
402
403
404
            fi
            ;;
        k)
            POSTGRES_VERSION=${OPTARG}
405
            if ! [[ ${POSTGRES_VERSION} =~ ^(10|11|12|13|14)$ ]]; then
406
                INVALID_OPTIONS+=("${OPTARG}")
407
408
            fi
            ;;
409
410
        p)
            PHP_VERSION=${OPTARG}
411
            if ! [[ ${PHP_VERSION} =~ ^(8.1|8.2)$ ]]; then
412
                INVALID_OPTIONS+=("${OPTARG}")
413
            fi
414
415
416
417
418
419
420
421
422
423
424
            ;;
        e)
            EXTRA_TEST_OPTIONS=${OPTARG}
            ;;
        x)
            PHP_XDEBUG_ON=1
            ;;
        y)
            PHP_XDEBUG_PORT=${OPTARG}
            ;;
        o)
Christian Kuhn's avatar
Christian Kuhn committed
425
            PHPUNIT_RANDOM="--random-order-seed=${OPTARG}"
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
            ;;
        n)
            CGLCHECK_DRY_RUN="-n"
            ;;
        h)
            echo "${HELP}"
            exit 0
            ;;
        u)
            TEST_SUITE=update
            ;;
        v)
            SCRIPT_VERBOSE=1
            ;;
        \?)
441
            INVALID_OPTIONS+=("${OPTARG}")
442
443
            ;;
        :)
444
            INVALID_OPTIONS+=("${OPTARG}")
445
446
447
448
            ;;
    esac
done

449
450
451
452
453
454
# @todo Remove this check after PHP8.2 image contains xdebug
if [ "${PHP_VERSION}" == "8.2" -a ${PHP_XDEBUG_ON} -eq 1 ]; then
    echo "xdebug not available for PHP 8.2; either use other PHP version or do not use -x"
    exit 1
fi

455
456
457
458
459
460
461
# Exit on invalid options
if [ ${#INVALID_OPTIONS[@]} -ne 0 ]; then
    echo "Invalid option(s):" >&2
    for I in "${INVALID_OPTIONS[@]}"; do
        echo "-"${I} >&2
    done
    echo >&2
462
    echo "call \".Build/Scripts/runTests.sh -h\" to display help and valid options"
463
464
465
    exit 1
fi

466
# Move "7.4" to "php74", the latter is the docker container name
467
DOCKER_PHP_IMAGE=$(echo "php${PHP_VERSION}" | sed -e 's/\.//')
468
469
470
471
472
473
474
475
476
477
478
479

# Set $1 to first mass argument, this is the optional test file or test directory to execute
shift $((OPTIND - 1))
TEST_FILE=${1}

if [ ${SCRIPT_VERBOSE} -eq 1 ]; then
    set -x
fi

# Suite execution
case ${TEST_SUITE} in
    acceptance)
480
        handleDbmsAndDriverOptions
481
        setUpDockerComposeDotEnv
482
        if [ "${CHUNKS}" -gt 1 ]; then
483
484
            docker-compose run acceptance_split
        fi
485
486
        case ${DBMS} in
            mysql)
487
                echo "Using driver: ${DATABASE_DRIVER}"
488
489
                docker-compose run prepare_acceptance_application_mysql
                docker-compose run acceptance_application_mysql
490
491
492
                SUITE_EXIT_CODE=$?
                ;;
            mariadb)
493
                echo "Using driver: ${DATABASE_DRIVER}"
494
495
                docker-compose run prepare_acceptance_application_mariadb
                docker-compose run acceptance_application_mariadb
496
497
498
                SUITE_EXIT_CODE=$?
                ;;
            postgres)
499
500
                docker-compose run prepare_acceptance_application_postgres
                docker-compose run acceptance_application_postgres
501
502
                SUITE_EXIT_CODE=$?
                ;;
503
504
505
506
507
            sqlite)
                docker-compose run prepare_acceptance_application_sqlite
                docker-compose run acceptance_application_sqlite
                SUITE_EXIT_CODE=$?
                ;;
508
509
510
            *)
                echo "Acceptance tests don't run with DBMS ${DBMS}" >&2
                echo >&2
511
                echo "call \".Build/Scripts/runTests.sh -h\" to display help and valid options" >&2
512
513
                exit 1
        esac
514
515
        docker-compose down
        ;;
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
    acceptanceInstall)
        handleDbmsAndDriverOptions
        setUpDockerComposeDotEnv
        case ${DBMS} in
            mysql)
                echo "Using driver: ${DATABASE_DRIVER}"
                docker-compose run prepare_acceptance_install_mysql
                docker-compose run acceptance_install_mysql
                SUITE_EXIT_CODE=$?
                ;;
            mariadb)
                echo "Using driver: ${DATABASE_DRIVER}"
                docker-compose run prepare_acceptance_install_mariadb
                docker-compose run acceptance_install_mariadb
                SUITE_EXIT_CODE=$?
                ;;
            postgres)
                docker-compose run prepare_acceptance_install_postgres
                docker-compose run acceptance_install_postgres
                SUITE_EXIT_CODE=$?
                ;;
            sqlite)
                docker-compose run prepare_acceptance_install_sqlite
                docker-compose run acceptance_install_sqlite
                SUITE_EXIT_CODE=$?
                ;;
            *)
                echo "Acceptance install tests don't run with DBMS ${DBMS}" >&2
                echo >&2
545
                echo "call \".Build/Scripts/runTests.sh -h\" to display help and valid options" >&2
546
547
548
549
                exit 1
        esac
        docker-compose down
        ;;
550
551
552
553
554
555
556
557
558
559
560
561
    buildCss)
        setUpDockerComposeDotEnv
        docker-compose run build_css
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
    buildJavascript)
        setUpDockerComposeDotEnv
        docker-compose run build_javascript
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
562
563
    cgl)
        # Active dry-run for cgl needs not "-n" but specific options
564
        if [ -n "${CGLCHECK_DRY_RUN}" ]; then
565
            CGLCHECK_DRY_RUN="--dry-run --diff"
566
567
568
569
570
571
        fi
        setUpDockerComposeDotEnv
        docker-compose run cgl_all
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
572
573
574
575
576
577
    cglGit)
        setUpDockerComposeDotEnv
        docker-compose run cgl_git
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
578
579
580
581
582
583
    checkAnnotations)
        setUpDockerComposeDotEnv
        docker-compose run check_annotations
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
584
585
586
587
588
589
    checkTestMethodsPrefix)
        setUpDockerComposeDotEnv
        docker-compose run check_test_methods_prefix
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
590
591
592
593
594
595
    checkBom)
        setUpDockerComposeDotEnv
        docker-compose run check_bom
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
    checkComposer)
        setUpDockerComposeDotEnv
        docker-compose run check_composer
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
    checkExceptionCodes)
        setUpDockerComposeDotEnv
        docker-compose run check_exception_codes
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
    checkExtensionScannerRst)
        setUpDockerComposeDotEnv
        docker-compose run check_extension_scanner_rst
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
    checkFilePathLength)
        setUpDockerComposeDotEnv
        docker-compose run check_file_path_length
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
    checkGitSubmodule)
        setUpDockerComposeDotEnv
        docker-compose run check_git_submodule
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
626
627
628
629
630
631
    checkGruntClean)
        setUpDockerComposeDotEnv
        docker-compose run check_grunt_clean
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
632
633
634
635
636
637
    checkNamespaceIntegrity)
        setUpDockerComposeDotEnv
        docker-compose run check_namespace_integrity
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
638
639
640
641
642
643
644
645
646
647
648
649
    checkPermissions)
        setUpDockerComposeDotEnv
        docker-compose run check_permissions
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
    checkRst)
        setUpDockerComposeDotEnv
        docker-compose run check_rst
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
650
651
652
    clean)
        cleanBuildFiles
        cleanCacheFiles
653
        cleanRenderedDocumentationFiles
654
655
656
657
658
659
660
661
        cleanTestFiles
        ;;
    cleanBuild)
        cleanBuildFiles
        ;;
    cleanCache)
        cleanCacheFiles
        ;;
662
663
664
    cleanRenderedDocumentation)
        cleanRenderedDocumentationFiles
        ;;
665
666
667
    cleanTests)
        cleanTestFiles
        ;;
668
669
670
671
672
673
    composerInstall)
        setUpDockerComposeDotEnv
        docker-compose run composer_install
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
674
675
676
677
678
679
680
681
682
683
684
685
    composerInstallMax)
        setUpDockerComposeDotEnv
        docker-compose run composer_install_max
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
    composerInstallMin)
        setUpDockerComposeDotEnv
        docker-compose run composer_install_min
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
686
687
688
689
690
691
    composerTestDistribution)
        setUpDockerComposeDotEnv
        docker-compose run composer_test_distribution
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
692
693
694
695
696
697
698
    composerValidate)
        setUpDockerComposeDotEnv
        docker-compose run composer_validate
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
    functional)
699
        handleDbmsAndDriverOptions
700
        setUpDockerComposeDotEnv
701
        if [ "${CHUNKS}" -gt 0 ]; then
702
703
            docker-compose run functional_split
        fi
704
705
        case ${DBMS} in
            mariadb)
706
                echo "Using driver: ${DATABASE_DRIVER}"
707
708
                docker-compose run prepare_functional_mariadb
                docker-compose run functional_mariadb
709
710
                SUITE_EXIT_CODE=$?
                ;;
711
            mysql)
712
                echo "Using driver: ${DATABASE_DRIVER}"
713
714
                docker-compose run prepare_functional_mysql
                docker-compose run functional_mysql
715
716
                SUITE_EXIT_CODE=$?
                ;;
717
            postgres)
718
719
                docker-compose run prepare_functional_postgres
                docker-compose run functional_postgres
720
721
722
                SUITE_EXIT_CODE=$?
                ;;
            sqlite)
723
724
725
726
                # sqlite has a tmpfs as typo3temp/var/tests/functional-sqlite-dbs/
                # Since docker is executed as root (yay!), the path to this dir is owned by
                # root if docker creates it. Thank you, docker. We create the path beforehand
                # to avoid permission issues on host filesystem after execution.
727
                mkdir -p "${CORE_ROOT}/typo3temp/var/tests/functional-sqlite-dbs/"
728
729
730
731
732
                docker-compose run prepare_functional_sqlite
                docker-compose run functional_sqlite
                SUITE_EXIT_CODE=$?
                ;;
            *)
733
                echo "Functional tests don't run with DBMS ${DBMS}" >&2
734
                echo >&2
735
                echo "call \".Build/Scripts/runTests.sh -h\" to display help and valid options" >&2
736
737
738
739
                exit 1
        esac
        docker-compose down
        ;;
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
    functionalDeprecated)
        handleDbmsAndDriverOptions
        setUpDockerComposeDotEnv
        case ${DBMS} in
            mariadb)
                echo "Using driver: ${DATABASE_DRIVER}"
                docker-compose run prepare_functional_mariadb
                docker-compose run functional_deprecated_mariadb
                SUITE_EXIT_CODE=$?
                ;;
            mysql)
                echo "Using driver: ${DATABASE_DRIVER}"
                docker-compose run prepare_functional_mysql
                docker-compose run functional_deprecated_mysql
                SUITE_EXIT_CODE=$?
                ;;
            postgres)
                docker-compose run prepare_functional_postgres
                docker-compose run functional_deprecated_postgres
                SUITE_EXIT_CODE=$?
                ;;
            sqlite)
                # sqlite has a tmpfs as typo3temp/var/tests/functional-sqlite-dbs/
                # Since docker is executed as root (yay!), the path to this dir is owned by
                # root if docker creates it. Thank you, docker. We create the path beforehand
                # to avoid permission issues on host filesystem after execution.
766
                mkdir -p "${CORE_ROOT}/typo3temp/var/tests/functional-sqlite-dbs/"
767
768
769
770
771
772
773
                docker-compose run prepare_functional_sqlite
                docker-compose run functional_deprecated_sqlite
                SUITE_EXIT_CODE=$?
                ;;
            *)
                echo "Deprecated functional tests don't run with DBMS ${DBMS}" >&2
                echo >&2
774
                echo "call \".Build/Scripts/runTests.sh -h\" to display help and valid options" >&2
775
776
777
778
                exit 1
        esac
        docker-compose down
        ;;
779
    lintPhp)
780
        setUpDockerComposeDotEnv
781
        docker-compose run lint_php
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
    lintScss)
        setUpDockerComposeDotEnv
        docker-compose run lint_scss
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
    lintTypescript)
        setUpDockerComposeDotEnv
        docker-compose run lint_typescript
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
797
798
799
800
801
802
    lintHtml)
        setUpDockerComposeDotEnv
        docker-compose run lint_html
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
803
804
805
806
807
808
    listExceptionCodes)
        setUpDockerComposeDotEnv
        docker-compose run list_exception_codes
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
809
810
811
812
813
814
    phpstan)
        setUpDockerComposeDotEnv
        docker-compose run phpstan
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
815
816
817
818
819
820
    phpstanGenerateBaseline)
        setUpDockerComposeDotEnv
        docker-compose run phpstan_generate_baseline
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
    unit)
        setUpDockerComposeDotEnv
        docker-compose run unit
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
    unitDeprecated)
        setUpDockerComposeDotEnv
        docker-compose run unitDeprecated
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
    unitJavascript)
        setUpDockerComposeDotEnv
        docker-compose run unitJavascript
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
    unitRandom)
        setUpDockerComposeDotEnv
        docker-compose run unitRandom
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
    update)
846
847
848
849
        # prune unused, dangling local volumes
        echo "> prune unused, dangling local volumes"
        docker volume ls -q -f driver=local -f dangling=true | awk '$0 ~ /^[0-9a-f]{64}$/ { print }' | xargs -I {} docker volume rm {}
        echo ""
850
        # pull typo3/core-testing-*:latest versions of those ones that exist locally
851
        echo "> pull typo3/core-testing-*:latest versions of those ones that exist locally"
852
        docker images typo3/core-testing-*:latest --format "{{.Repository}}:latest" | xargs -I {} docker pull {}
853
        echo ""
854
        # remove "dangling" typo3/core-testing-* images (those tagged as <none>)
855
        echo "> remove \"dangling\" typo3/core-testing-* images (those tagged as <none>)"
856
        docker images typo3/core-testing-* --filter "dangling=true" --format "{{.ID}}" | xargs -I {} docker rmi {}
857
        echo ""
858
859
860
861
862
863
864
865
        ;;
    *)
        echo "Invalid -s option argument ${TEST_SUITE}" >&2
        echo >&2
        echo "${HELP}" >&2
        exit 1
esac

866
867
case ${DBMS} in
    mariadb)
868
        DBMS_OUTPUT="DBMS: ${DBMS}  version ${MARIADB_VERSION}  driver ${DATABASE_DRIVER}"
869
870
        ;;
    mysql)
871
        DBMS_OUTPUT="DBMS: ${DBMS}  version ${MYSQL_VERSION}  driver ${DATABASE_DRIVER}"
872
873
874
875
876
877
878
879
880
881
882
        ;;
    postgres)
        DBMS_OUTPUT="DBMS: ${DBMS}  version ${POSTGRES_VERSION}"
        ;;
    sqlite)
        DBMS_OUTPUT="DBMS: ${DBMS}"
        ;;
    *)
        DBMS_OUTPUT="DBMS not recognized: $DBMS"
        exit 1
esac
883
884
885
886
887
888

# Print summary
if [ ${SCRIPT_VERBOSE} -eq 1 ]; then
    # Turn off verbose mode for the script summary
    set +x
fi
889
890
echo "" >&2
echo "###########################################################################" >&2
891
892
893
894
895
896
897
echo "Result of ${TEST_SUITE}" >&2
if [[ ${IS_CORE_CI} -eq 1 ]]; then
    echo "Environment: CI" >&2
else
    echo "Environment: local" >&2
fi
echo "PHP: ${PHP_VERSION}" >&2
898
if [[ ${TEST_SUITE} =~ ^(functional|acceptance|acceptanceInstall)$ ]]; then
899
900
901
902
903
904
905
906
907
908
909
    echo "${DBMS_OUTPUT}" >&2
fi

if [[ ${SUITE_EXIT_CODE} -eq 0 ]]; then
    echo "SUCCESS" >&2
else
    echo "FAILURE" >&2
fi
echo "###########################################################################" >&2
echo "" >&2

910
# Exit with code of test suite - This script return non-zero if the executed test failed.
911
exit $SUITE_EXIT_CODE