Skip to content

Commit 641fec2

Browse files
authored
Merge pull request #609 from TYPO3/lolli-5
runTests.sh and nullable fix
2 parents ca8c648 + 5fcbb3b commit 641fec2

File tree

17 files changed

+179
-226
lines changed

17 files changed

+179
-226
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@ jobs:
1616
php: [ '7.2', '7.3', '7.4', '8.0', '8.1', '8.2' ]
1717
steps:
1818
- name: Checkout
19-
uses: actions/checkout@v3
19+
uses: actions/checkout@v4
2020

2121
- name: Composer install
2222
run: Build/Scripts/runTests.sh -p ${{ matrix.php }} -s composerUpdate
2323

2424
- name: CGL
25-
if: ${{ matrix.php <= '8.1' }}
25+
if: startsWith(matrix.php, '7.4')
2626
run: Build/Scripts/runTests.sh -p ${{ matrix.php }} -s cgl -n
2727

2828
- name: Lint PHP

Build/Scripts/runTests.sh

Lines changed: 138 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,13 @@
11
#!/usr/bin/env bash
22

3-
#
4-
# Test runner based on docker and docker-compose.
5-
#
6-
7-
# Function to write a .env file in Build/testing-docker/local
8-
# This is read by docker-compose and vars defined here are
9-
# used in Build/testing-docker/docker-compose.yml
10-
setUpDockerComposeDotEnv() {
11-
# Delete possibly existing local .env file if exists
12-
[ -e .env ] && rm .env
13-
# Set up a new .env file for docker-compose
14-
echo "COMPOSE_PROJECT_NAME=local" >> .env
15-
# To prevent access rights of files created by the testing, the docker image later
16-
# runs with the same user that is currently executing the script. docker-compose can't
17-
# use $UID directly itself since it is a shell variable and not an env variable, so
18-
# we have to set it explicitly here.
19-
echo "HOST_UID=`id -u`" >> .env
20-
# Your local home directory for composer and npm caching
21-
echo "HOST_HOME=${HOME}" >> .env
22-
# Your local user
23-
echo "ROOT_DIR"=${ROOT_DIR} >> .env
24-
echo "HOST_USER=${USER}" >> .env
25-
echo "PHP_XDEBUG_ON=${PHP_XDEBUG_ON}" >> .env
26-
echo "DOCKER_PHP_IMAGE=${DOCKER_PHP_IMAGE}" >> .env
27-
echo "SCRIPT_VERBOSE=${SCRIPT_VERBOSE}" >> .env
28-
echo "CGLCHECK_DRY_RUN=${CGLCHECK_DRY_RUN}" >> .env
29-
echo "IMAGE_PREFIX=${IMAGE_PREFIX}" >> .env
3+
cleanUp() {
4+
ATTACHED_CONTAINERS=$(${CONTAINER_BIN} ps --filter network=${NETWORK} --format='{{.Names}} 2>/dev/null')
5+
if [[ -n $ATTACHED_CONTAINERS ]]; then
6+
for ATTACHED_CONTAINER in ${ATTACHED_CONTAINERS}; do
7+
${CONTAINER_BIN} kill ${ATTACHED_CONTAINER} >/dev/null
8+
done
9+
${CONTAINER_BIN} network rm ${NETWORK} >/dev/null
10+
fi
3011
}
3112

3213
# Load help text into $HELP
@@ -49,14 +30,22 @@ Options:
4930
- phpstanGenerateBaseline: regenerate phpstan baseline, handy after phpstan updates
5031
- unit (default): PHP unit tests
5132
52-
-p <7.2|7.3|7.4|8.0|8.1|8.2>
33+
-b <docker|podman>
34+
Container environment:
35+
- podman
36+
- docker
37+
38+
If not provided, podman will be used first if both are installed.
39+
40+
-p <7.2|7.3|7.4|8.0|8.1|8.2|8.3>
5341
Specifies the PHP minor version to be used
5442
- 7.2 (default): use PHP 7.2
5543
- 7.3: use PHP 7.3
5644
- 7.4: use PHP 7.4
5745
- 8.0: use PHP 8.0
5846
- 8.1: use PHP 8.1
5947
- 8.2: use PHP 8.2
48+
- 8.3: use PHP 8.3
6049
6150
-x
6251
Only with -s cgl|unit
@@ -68,56 +57,68 @@ Options:
6857
Only with -s cgl
6958
Activate dry-run in CGL check that does not actively change files and only prints broken ones.
7059
71-
-v
72-
Enable verbose script output. Shows variables and docker commands.
73-
7460
-h
7561
Show this help.
7662
7763
Examples:
7864
# Run unit tests using default PHP version
7965
./Build/Scripts/runTests.sh
8066
81-
# Run unit tests using PHP 7.4
82-
./Build/Scripts/runTests.sh -p 7.4
67+
# Run unit tests using PHP 8.1
68+
./Build/Scripts/runTests.sh -p 8.1
8369
EOF
8470

85-
# Test if docker-compose exists, else exit out with error
86-
if ! type "docker-compose" > /dev/null; then
87-
echo "This script relies on docker and docker-compose. Please install" >&2
88-
exit 1
71+
# Test if docker exists, else exit out with error
72+
if ! type "docker" >/dev/null 2>&1 && ! type "podman" >/dev/null 2>&1; then
73+
echo "This script relies on docker or podman. Please install" >&2
74+
exit 1
8975
fi
9076

9177
# Go to the directory this script is located, so everything else is relative
9278
# to this dir, no matter from where this script is called.
9379
THIS_SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
9480
cd "$THIS_SCRIPT_DIR" || exit 1
95-
96-
# Go to directory that contains the local docker-compose.yml file
97-
cd ../testing-docker || exit 1
81+
cd ../../ || exit 1
9882

9983
# Option defaults
100-
ROOT_DIR=`readlink -f ${PWD}/../../`
84+
ROOT_DIR=`readlink -f ${PWD}`
10185
TEST_SUITE="unit"
10286
PHP_VERSION="7.2"
10387
PHP_XDEBUG_ON=0
10488
SCRIPT_VERBOSE=0
10589
CGLCHECK_DRY_RUN=""
106-
IMAGE_PREFIX="ghcr.io/typo3/"
90+
CONTAINER_BIN=""
91+
CONTAINER_INTERACTIVE="-it --init"
92+
HOST_UID=$(id -u)
93+
HOST_PID=$(id -g)
94+
USERSET=""
95+
SUFFIX=$(echo $RANDOM)
96+
NETWORK="testing-framework-${SUFFIX}"
97+
CI_PARAMS=""
98+
CONTAINER_HOST="host.docker.internal"
10799

108100
# Option parsing
109101
# Reset in case getopts has been used previously in the shell
110102
OPTIND=1
111103
# Array for invalid options
112104
INVALID_OPTIONS=();
113105
# Simple option parsing based on getopts (! not getopt)
114-
while getopts ":s:p:hxnv" OPT; do
106+
while getopts ":b:s:p:hxn" OPT; do
115107
case ${OPT} in
116108
s)
117109
TEST_SUITE=${OPTARG}
118110
;;
111+
b)
112+
if ! [[ ${OPTARG} =~ ^(docker|podman)$ ]]; then
113+
INVALID_OPTIONS+=("${OPTARG}")
114+
fi
115+
CONTAINER_BIN=${OPTARG}
116+
;;
119117
p)
120118
PHP_VERSION=${OPTARG}
119+
if ! [[ ${PHP_VERSION} =~ ^(7.2|7.3|7.4|8.0|8.1|8.2|8.3)$ ]]; then
120+
INVALID_OPTIONS+=("${OPTARG}")
121+
fi
121122
;;
122123
h)
123124
echo "${HELP}"
@@ -126,9 +127,6 @@ while getopts ":s:p:hxnv" OPT; do
126127
n)
127128
CGLCHECK_DRY_RUN="-n"
128129
;;
129-
v)
130-
SCRIPT_VERBOSE=1
131-
;;
132130
x)
133131
PHP_XDEBUG_ON=1
134132
;;
@@ -148,15 +146,62 @@ if [ ${#INVALID_OPTIONS[@]} -ne 0 ]; then
148146
echo "-"${I} >&2
149147
done
150148
echo >&2
151-
echo "${HELP}" >&2
149+
echo "Use \".Build/Scripts/runTests.sh -h\" to display help and valid options" >&2
150+
exit 1
151+
fi
152+
153+
# ENV var "CI" is set by gitlab-ci. Use it to force some CI details.
154+
if [ "${CI}" == "true" ]; then
155+
CONTAINER_INTERACTIVE=""
156+
# @todo Enforce pull-never once we have cached image folder similar to Core CI runner image caches.
157+
# CI_PARAMS="--pull=never"
158+
fi
159+
160+
# determine default container binary to use: 1. podman 2. docker
161+
if [[ -z "${CONTAINER_BIN}" ]]; then
162+
if type "podman" >/dev/null 2>&1; then
163+
CONTAINER_BIN="podman"
164+
elif type "docker" >/dev/null 2>&1; then
165+
CONTAINER_BIN="docker"
166+
fi
167+
fi
168+
169+
if [ $(uname) != "Darwin" ] && [ ${CONTAINER_BIN} = "docker" ]; then
170+
# Run docker jobs as current user to prevent permission issues. Not needed with podman.
171+
USERSET="--user $HOST_UID"
172+
fi
173+
174+
if ! type ${CONTAINER_BIN} >/dev/null 2>&1; then
175+
echo "Selected container environment \"${CONTAINER_BIN}\" not found. Please install or use -b option to select one." >&2
152176
exit 1
153177
fi
154178

155-
# Move "7.2" to "php72", the latter is the docker container name
156-
DOCKER_PHP_IMAGE=`echo "php${PHP_VERSION}" | sed -e 's/\.//'`
179+
IMAGE_PHP="ghcr.io/typo3/core-testing-$(echo "php${PHP_VERSION}" | sed -e 's/\.//'):latest"
180+
181+
if [[ -d "../../Build/testing-docker" ]]; then
182+
rm -rf ../../Build/testing-docker
183+
fi
184+
185+
# Remove handled options and leaving the rest in the line, so it can be passed raw to commands
186+
shift $((OPTIND - 1))
157187

158-
if [ ${SCRIPT_VERBOSE} -eq 1 ]; then
159-
set -x
188+
${CONTAINER_BIN} network create ${NETWORK} >/dev/null
189+
190+
if [ ${CONTAINER_BIN} = "docker" ]; then
191+
# docker needs the add-host for xdebug remote debugging. podman has host.container.internal built in
192+
CONTAINER_COMMON_PARAMS="${CONTAINER_INTERACTIVE} --rm --network ${NETWORK} --add-host "${CONTAINER_HOST}:host-gateway" ${USERSET} -v ${ROOT_DIR}:${ROOT_DIR} -w ${ROOT_DIR}"
193+
else
194+
# podman
195+
CONTAINER_HOST="host.containers.internal"
196+
CONTAINER_COMMON_PARAMS="${CONTAINER_INTERACTIVE} ${CI_PARAMS} --rm --network ${NETWORK} -v ${ROOT_DIR}:${ROOT_DIR} -w ${ROOT_DIR}"
197+
fi
198+
199+
if [ ${PHP_XDEBUG_ON} -eq 0 ]; then
200+
XDEBUG_MODE="-e XDEBUG_MODE=off"
201+
XDEBUG_CONFIG=" "
202+
else
203+
XDEBUG_MODE="-e XDEBUG_MODE=debug -e XDEBUG_TRIGGER=foo"
204+
XDEBUG_CONFIG="client_port=${PHP_XDEBUG_PORT} client_host=${CONTAINER_HOST}"
160205
fi
161206

162207
# Suite execution
@@ -166,43 +211,36 @@ case ${TEST_SUITE} in
166211
if [[ ! -z ${CGLCHECK_DRY_RUN} ]]; then
167212
CGLCHECK_DRY_RUN="--dry-run --diff"
168213
fi
169-
setUpDockerComposeDotEnv
170-
docker-compose run cgl
214+
COMMAND="php -dxdebug.mode=off .Build/bin/php-cs-fixer fix -v ${CGLCHECK_DRY_RUN} --path-mode intersection --config=Build/php-cs-fixer/config.php"
215+
${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name cgl-${SUFFIX} ${IMAGE_PHP} ${COMMAND}
171216
SUITE_EXIT_CODE=$?
172-
docker-compose down
173217
;;
174218
clean)
175219
rm -rf ../../composer.lock ../../.Build/ ../../public
176220
;;
177221
composerUpdate)
178-
setUpDockerComposeDotEnv
179-
docker-compose run composer_update
222+
COMMAND=(composer update --no-progress --no-interaction)
223+
${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name composer-update-${SUFFIX} -e COMPOSER_CACHE_DIR=.Build/.cache/composer ${IMAGE_PHP} "${COMMAND[@]}"
180224
SUITE_EXIT_CODE=$?
181-
docker-compose down
182225
;;
183226
lint)
184-
setUpDockerComposeDotEnv
185-
docker-compose run lint
227+
COMMAND="php -v | grep '^PHP'; find . -name '*.php' ! -path './.Build/*' ! -path './public/*' -print0 | xargs -0 -n1 -P4 php -dxdebug.mode=off -l >/dev/null"
228+
${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name lint-php-${SUFFIX} ${IMAGE_PHP} /bin/sh -c "${COMMAND}"
186229
SUITE_EXIT_CODE=$?
187-
docker-compose down
188230
;;
189231
phpstan)
190-
setUpDockerComposeDotEnv
191-
docker-compose run phpstan
232+
COMMAND=(php -dxdebug.mode=off .Build/bin/phpstan analyse -c Build/phpstan/phpstan.neon --no-progress --no-interaction --memory-limit 4G "$@")
233+
${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name phpstan-${SUFFIX} ${IMAGE_PHP} "${COMMAND[@]}"
192234
SUITE_EXIT_CODE=$?
193-
docker-compose down
194235
;;
195236
phpstanGenerateBaseline)
196-
setUpDockerComposeDotEnv
197-
docker-compose run phpstan_generate_baseline
237+
COMMAND="php -dxdebug.mode=off .Build/bin/phpstan analyse -c Build/phpstan/phpstan.neon --no-progress --no-interaction --memory-limit 4G --generate-baseline=Build/phpstan/phpstan-baseline.neon"
238+
${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name phpstan-baseline-${SUFFIX} ${IMAGE_PHP} /bin/sh -c "${COMMAND}"
198239
SUITE_EXIT_CODE=$?
199-
docker-compose down
200240
;;
201241
unit)
202-
setUpDockerComposeDotEnv
203-
docker-compose run unit
242+
${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name unit-${SUFFIX} ${XDEBUG_MODE} -e XDEBUG_CONFIG="${XDEBUG_CONFIG}" ${IMAGE_PHP} .Build/bin/phpunit Tests/Unit/ "$@"
204243
SUITE_EXIT_CODE=$?
205-
docker-compose down
206244
;;
207245
*)
208246
echo "Invalid -s option argument ${TEST_SUITE}" >&2
@@ -211,4 +249,35 @@ case ${TEST_SUITE} in
211249
exit 1
212250
esac
213251

252+
cleanUp
253+
254+
# Print summary
255+
echo "" >&2
256+
echo "###########################################################################" >&2
257+
echo "Result of ${TEST_SUITE}" >&2
258+
echo "Container runtime: ${CONTAINER_BIN}" >&2
259+
echo "PHP: ${PHP_VERSION}" >&2
260+
if [[ ${TEST_SUITE} =~ ^(functional|functionalDeprecated|acceptance|acceptanceInstall)$ ]]; then
261+
case "${DBMS}" in
262+
mariadb|mysql|postgres)
263+
echo "DBMS: ${DBMS} version ${DBMS_VERSION} driver ${DATABASE_DRIVER}" >&2
264+
;;
265+
sqlite)
266+
echo "DBMS: ${DBMS}" >&2
267+
;;
268+
esac
269+
fi
270+
if [[ -n ${EXTRA_TEST_OPTIONS} ]]; then
271+
echo " Note: Using -e is deprecated. Simply add the options at the end of the command."
272+
echo " Instead of: Build/Scripts/runTests.sh -s ${TEST_SUITE} -e '${EXTRA_TEST_OPTIONS}' $@"
273+
echo " use: Build/Scripts/runTests.sh -s ${TEST_SUITE} -- ${EXTRA_TEST_OPTIONS} $@"
274+
fi
275+
if [[ ${SUITE_EXIT_CODE} -eq 0 ]]; then
276+
echo "SUCCESS" >&2
277+
else
278+
echo "FAILURE" >&2
279+
fi
280+
echo "###########################################################################" >&2
281+
echo "" >&2
282+
214283
exit $SUITE_EXIT_CODE

Build/php-cs-fixer/config.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@
5151
'no_useless_else' => true,
5252
'no_whitespace_in_blank_line' => true,
5353
'ordered_imports' => true,
54+
'nullable_type_declaration' => [
55+
'syntax' => 'question_mark',
56+
],
57+
'nullable_type_declaration_for_default_null_value' => true,
5458
'php_unit_construct' => ['assertions' => ['assertEquals', 'assertSame', 'assertNotEquals', 'assertNotSame']],
5559
'php_unit_mock_short_will_return' => true,
5660
'php_unit_test_case_static_method_calls' => ['call_type' => 'self'],

Build/phpstan/phpstan-baseline.neon

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,13 @@ parameters:
3131
path: ../../Classes/Composer/ExtensionTestEnvironment.php
3232

3333
-
34-
message: "#^Cannot access offset string on int\\.$#"
34+
message: "#^Strict comparison using \\=\\=\\= between class\\-string\\<T of object\\> and '' will always evaluate to false\\.$#"
3535
count: 2
36+
path: ../../Classes/Core/BaseTestCase.php
37+
38+
-
39+
message: "#^Cannot access offset string on int\\.$#"
40+
count: 1
3641
path: ../../Classes/Core/Functional/Framework/DataHandling/Scenario/DataHandlerFactory.php
3742

3843
-

0 commit comments

Comments
 (0)