runTests.sh 30.9 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
# Load help text into $HELP
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.

114
115
Recommended docker version is >=20.10 for xdebug break pointing to work reliably, and
a recent docker-compose (tested >=1.21.2) is needed.
116
117
118

Usage: $0 [options] [file]

119
No arguments: Run all unit tests with PHP 8.1
120
121
122
123

Options:
    -s <...>
        Specifies which test suite to run
124
            - acceptance: main application acceptance tests
125
            - acceptanceInstall: installation acceptance tests, only with -d mariadb|postgres|sqlite
126
127
            - buildCss: execute scss to css builder
            - buildJavascript: execute typescript to javascript builder
128
            - cgl: test and fix all core php files
129
130
            - cglGit: test and fix latest committed patch for CGL compliance
            - checkAnnotations: check php code for allowed annotations
131
            - checkBom: check UTF-8 files do not contain BOM
132
133
134
135
136
            - 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
137
            - checkGruntClean: Verify "grunt build" is clean. Warning: Executes git commands! Usually used in CI only.
138
139
            - checkPermissions: test some core files for correct executable bits
            - checkRst: test .rst files for integrity
140
            - checkTestMethodsPrefix: check tests methods do not start with "test"
141
142
143
144
            - 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
            - cleanTests: clean up test related files and folders
145
146
147
            - 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.
148
            - composerTestDistribution: "composer update" in Build/composer to verify core dependencies
149
            - composerValidate: "composer validate"
150
151
            - functional: PHP functional tests
            - functionalDeprecated: deprecated PHP functional tests
152
            - lintPhp: PHP linting
153
154
            - lintScss: SCSS linting
            - lintTypescript: TS linting
155
            - lintHtml: HTML linting
156
            - listExceptionCodes: list core exception codes in JSON format
157
            - phpstan: phpstan tests
158
            - phpstanGenerateBaseline: regenerate phpstan baseline, handy after phpstan updates
159
160
161
162
163
            - 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

164
    -a <mysqli|pdo_mysql>
165
        Only with -s functional|functionalDeprecated
166
167
168
169
170
171
172
173
        Specifies to use another driver, following combinations are available:
            - mysql
                - mysqli (default)
                - pdo_mysql
            - mariadb
                - mysqli (default)
                - pdo_mysql

174
    -d <sqlite|mariadb|mysql|postgres>
175
        Only with -s functional|functionalDeprecated|acceptance|acceptanceInstall
176
        Specifies on which DBMS tests are performed
177
178
            - sqlite: (default): use sqlite
            - mariadb use mariadb
179
            - mysql: use MySQL server
180
181
            - postgres: use postgres

182
    -i <10.3|10.4|10.5|10.6|10.7>
183
184
185
186
187
        Only with -d mariadb
        Specifies on which version of mariadb tests are performed
            - 10.3 (default)
            - 10.4
            - 10.5
188
189
            - 10.6
            - 10.7
190

191
    -j <8.0>
192
193
        Only with -d mysql
        Specifies on which version of mysql tests are performed
194
            - 8.0 (default)
195

196
    -k <10|11|12|13|14>
197
198
199
200
201
        Only with -d postgres
        Specifies on which version of postgres tests are performed
            - 10 (default)
            - 11
            - 12
202
203
            - 13
            - 14
204

205
206
207
208
209
    -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

210
    -p <8.1>
211
        Specifies the PHP minor version to be used
212
            - 8.1 (default): use PHP 8.1
213

214
    -e "<phpunit options>"
215
        Only with -s functional|functionalDeprecated|unit|unitDeprecated|unitRandom|acceptance
216
217
218
219
220
221
        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
222
        Only with -s functional|functionalDeprecated|unit|unitDeprecated|unitRandom|acceptance|acceptanceInstall
223
        Send information to host instance for test or system under test break points. This is especially
Christian Kuhn's avatar
Christian Kuhn committed
224
        useful if a local PhpStorm instance is listening on default xdebug port 9003. A different port
225
226
227
        can be selected with -y

    -y <port>
Christian Kuhn's avatar
Christian Kuhn committed
228
        Send xdebug information to a different port than default 9003 if an IDE like PhpStorm
229
230
231
232
233
        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
234
        outputs the used seed at the end (in gitlab core testing logs, too). Use that number to
235
236
237
        replay the unit tests in that order.

    -n
238
        Only with -s cgl|cglGit
239
240
241
        Activate dry-run in CGL check that does not actively change files and only prints broken ones.

    -u
242
243
244
245
        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-*.
246
247
248
249
250
251
252
253

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

    -h
        Show this help.

Examples:
254
    # Run all core unit tests using PHP 8.1
255
256
257
    ./Build/Scripts/runTests.sh
    ./Build/Scripts/runTests.sh -s unit

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

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

264
265
266
267
    # 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

268
269
    # Run unit tests with PHP 8.1 and have xdebug enabled
    ./Build/Scripts/runTests.sh -x -p 8.1
270

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

274
275
276
277
    # Run functional tests on mariadb 10.5
    ./Build/Scripts/runTests.sh -d mariadb -i 10.5

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

280
281
    # Run restricted set of application acceptance tests
    ./Build/Scripts/runTests.sh -s acceptance typo3/sysext/core/Tests/Acceptance/Application/Login/BackendLoginCest.php:loginButtonMouseOver
282
283

    # Run installer tests of a new instance on sqlite
284
    ./Build/Scripts/runTests.sh -s acceptanceInstall -d sqlite
285
286
287
288
EOF

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

293
294
# 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.
295
296
297
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
298
    echo "docker-compose $DOCKER_COMPOSE_VERSION is currently broken and not supported by runTests.sh."
299
    echo "If you are running Docker Desktop for MacOS/Windows disable 'Use Docker Compose V2' (Preferences > General)"
300
301
302
    exit 1
fi

303
304
# Go to the directory this script is located, so everything else is relative
# to this dir, no matter from where this script is called.
305
THIS_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
306
307
308
309
310
cd "$THIS_SCRIPT_DIR" || exit 1

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

311
312
# Set core root path by checking whether realpath exists
if ! command -v realpath &> /dev/null; then
313
314
    echo "Consider installing realpath for properly resolving symlinks" >&2
    CORE_ROOT="${PWD}/../../../"
315
else
316
    CORE_ROOT=$(realpath "${PWD}/../../../")
317
318
fi

319
320
# Option defaults
TEST_SUITE="unit"
321
DBMS="sqlite"
322
PHP_VERSION="8.1"
323
PHP_XDEBUG_ON=0
Christian Kuhn's avatar
Christian Kuhn committed
324
PHP_XDEBUG_PORT=9003
325
326
EXTRA_TEST_OPTIONS=""
SCRIPT_VERBOSE=0
Christian Kuhn's avatar
Christian Kuhn committed
327
PHPUNIT_RANDOM=""
328
CGLCHECK_DRY_RUN=""
329
DATABASE_DRIVER=""
330
MARIADB_VERSION="10.3"
331
MYSQL_VERSION="8.0"
332
POSTGRES_VERSION="10"
333
334
CHUNKS=0
THISCHUNK=0
335
DOCKER_SELENIUM_IMAGE="selenium/standalone-chrome:4.0.0-20211102"
336
337
338
339
340
341
342
343
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
344
345
346
347
348
349
350
351
352

# 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
353
354
355
356
357
358
359

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

# 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
445
    echo "call \".Build/Scripts/runTests.sh -h\" to display help and valid options"
446
447
448
    exit 1
fi

449
# Move "7.4" to "php74", the latter is the docker container name
450
DOCKER_PHP_IMAGE=$(echo "php${PHP_VERSION}" | sed -e 's/\.//')
451
452
453
454
455
456
457
458
459
460
461
462

# 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)
463
        handleDbmsAndDriverOptions
464
        setUpDockerComposeDotEnv
465
        if [ "${CHUNKS}" -gt 1 ]; then
466
467
            docker-compose run acceptance_split
        fi
468
469
        case ${DBMS} in
            mysql)
470
                echo "Using driver: ${DATABASE_DRIVER}"
471
472
                docker-compose run prepare_acceptance_application_mysql
                docker-compose run acceptance_application_mysql
473
474
475
                SUITE_EXIT_CODE=$?
                ;;
            mariadb)
476
                echo "Using driver: ${DATABASE_DRIVER}"
477
478
                docker-compose run prepare_acceptance_application_mariadb
                docker-compose run acceptance_application_mariadb
479
480
481
                SUITE_EXIT_CODE=$?
                ;;
            postgres)
482
483
                docker-compose run prepare_acceptance_application_postgres
                docker-compose run acceptance_application_postgres
484
485
                SUITE_EXIT_CODE=$?
                ;;
486
487
488
489
490
            sqlite)
                docker-compose run prepare_acceptance_application_sqlite
                docker-compose run acceptance_application_sqlite
                SUITE_EXIT_CODE=$?
                ;;
491
492
493
            *)
                echo "Acceptance tests don't run with DBMS ${DBMS}" >&2
                echo >&2
494
                echo "call \".Build/Scripts/runTests.sh -h\" to display help and valid options" >&2
495
496
                exit 1
        esac
497
498
        docker-compose down
        ;;
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
    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
528
                echo "call \".Build/Scripts/runTests.sh -h\" to display help and valid options" >&2
529
530
531
532
                exit 1
        esac
        docker-compose down
        ;;
533
534
535
536
537
538
539
540
541
542
543
544
    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
        ;;
545
546
    cgl)
        # Active dry-run for cgl needs not "-n" but specific options
547
        if [ -n "${CGLCHECK_DRY_RUN}" ]; then
548
            CGLCHECK_DRY_RUN="--dry-run --diff"
549
550
551
552
553
554
        fi
        setUpDockerComposeDotEnv
        docker-compose run cgl_all
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
555
556
557
558
559
560
    cglGit)
        setUpDockerComposeDotEnv
        docker-compose run cgl_git
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
561
562
563
564
565
566
    checkAnnotations)
        setUpDockerComposeDotEnv
        docker-compose run check_annotations
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
567
568
569
570
571
572
    checkTestMethodsPrefix)
        setUpDockerComposeDotEnv
        docker-compose run check_test_methods_prefix
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
573
574
575
576
577
578
    checkBom)
        setUpDockerComposeDotEnv
        docker-compose run check_bom
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
    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
        ;;
609
610
611
612
613
614
    checkGruntClean)
        setUpDockerComposeDotEnv
        docker-compose run check_grunt_clean
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
615
616
617
618
619
620
621
622
623
624
625
626
    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
        ;;
627
628
629
630
631
632
633
634
635
636
637
638
639
640
    clean)
        cleanBuildFiles
        cleanCacheFiles
        cleanTestFiles
        ;;
    cleanBuild)
        cleanBuildFiles
        ;;
    cleanCache)
        cleanCacheFiles
        ;;
    cleanTests)
        cleanTestFiles
        ;;
641
642
643
644
645
646
    composerInstall)
        setUpDockerComposeDotEnv
        docker-compose run composer_install
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
647
648
649
650
651
652
653
654
655
656
657
658
    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
        ;;
659
660
661
662
663
664
    composerTestDistribution)
        setUpDockerComposeDotEnv
        docker-compose run composer_test_distribution
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
665
666
667
668
669
670
671
    composerValidate)
        setUpDockerComposeDotEnv
        docker-compose run composer_validate
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
    functional)
672
        handleDbmsAndDriverOptions
673
        setUpDockerComposeDotEnv
674
        if [ "${CHUNKS}" -gt 0 ]; then
675
676
            docker-compose run functional_split
        fi
677
678
        case ${DBMS} in
            mariadb)
679
                echo "Using driver: ${DATABASE_DRIVER}"
680
681
                docker-compose run prepare_functional_mariadb
                docker-compose run functional_mariadb
682
683
                SUITE_EXIT_CODE=$?
                ;;
684
            mysql)
685
                echo "Using driver: ${DATABASE_DRIVER}"
686
687
                docker-compose run prepare_functional_mysql
                docker-compose run functional_mysql
688
689
                SUITE_EXIT_CODE=$?
                ;;
690
            postgres)
691
692
                docker-compose run prepare_functional_postgres
                docker-compose run functional_postgres
693
694
695
                SUITE_EXIT_CODE=$?
                ;;
            sqlite)
696
697
698
699
                # 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.
700
                mkdir -p "${CORE_ROOT}/typo3temp/var/tests/functional-sqlite-dbs/"
701
702
703
704
705
                docker-compose run prepare_functional_sqlite
                docker-compose run functional_sqlite
                SUITE_EXIT_CODE=$?
                ;;
            *)
706
                echo "Functional tests don't run with DBMS ${DBMS}" >&2
707
                echo >&2
708
                echo "call \".Build/Scripts/runTests.sh -h\" to display help and valid options" >&2
709
710
711
712
                exit 1
        esac
        docker-compose down
        ;;
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
    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.
739
                mkdir -p "${CORE_ROOT}/typo3temp/var/tests/functional-sqlite-dbs/"
740
741
742
743
744
745
746
                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
747
                echo "call \".Build/Scripts/runTests.sh -h\" to display help and valid options" >&2
748
749
750
751
                exit 1
        esac
        docker-compose down
        ;;
752
    lintPhp)
753
        setUpDockerComposeDotEnv
754
        docker-compose run lint_php
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
        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
        ;;
770
771
772
773
774
775
    lintHtml)
        setUpDockerComposeDotEnv
        docker-compose run lint_html
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
776
777
778
779
780
781
    listExceptionCodes)
        setUpDockerComposeDotEnv
        docker-compose run list_exception_codes
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
782
783
784
785
786
787
    phpstan)
        setUpDockerComposeDotEnv
        docker-compose run phpstan
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
788
789
790
791
792
793
    phpstanGenerateBaseline)
        setUpDockerComposeDotEnv
        docker-compose run phpstan_generate_baseline
        SUITE_EXIT_CODE=$?
        docker-compose down
        ;;
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
    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)
819
820
821
822
        # 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 ""
823
        # pull typo3/core-testing-*:latest versions of those ones that exist locally
824
        echo "> pull typo3/core-testing-*:latest versions of those ones that exist locally"
825
        docker images typo3/core-testing-*:latest --format "{{.Repository}}:latest" | xargs -I {} docker pull {}
826
        echo ""
827
        # remove "dangling" typo3/core-testing-* images (those tagged as <none>)
828
        echo "> remove \"dangling\" typo3/core-testing-* images (those tagged as <none>)"
829
        docker images typo3/core-testing-* --filter "dangling=true" --format "{{.ID}}" | xargs -I {} docker rmi {}
830
        echo ""
831
832
833
834
835
836
837
838
        ;;
    *)
        echo "Invalid -s option argument ${TEST_SUITE}" >&2
        echo >&2
        echo "${HELP}" >&2
        exit 1
esac

839
840
case ${DBMS} in
    mariadb)
841
        DBMS_OUTPUT="DBMS: ${DBMS}  version ${MARIADB_VERSION}  driver ${DATABASE_DRIVER}"
842
843
        ;;
    mysql)
844
        DBMS_OUTPUT="DBMS: ${DBMS}  version ${MYSQL_VERSION}  driver ${DATABASE_DRIVER}"
845
846
847
848
849
850
851
852
853
854
855
        ;;
    postgres)
        DBMS_OUTPUT="DBMS: ${DBMS}  version ${POSTGRES_VERSION}"
        ;;
    sqlite)
        DBMS_OUTPUT="DBMS: ${DBMS}"
        ;;
    *)
        DBMS_OUTPUT="DBMS not recognized: $DBMS"
        exit 1
esac
856
857
858
859
860
861

# Print summary
if [ ${SCRIPT_VERBOSE} -eq 1 ]; then
    # Turn off verbose mode for the script summary
    set +x
fi
862
863
echo "" >&2
echo "###########################################################################" >&2
864
865
866
867
868
869
870
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
871
if [[ ${TEST_SUITE} =~ ^(functional|acceptance|acceptanceInstall)$ ]]; then
872
873
874
875
876
877
878
879
880
881
882
    echo "${DBMS_OUTPUT}" >&2
fi

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

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