Skip to content

Commit 9cb48fd

Browse files
committed
Run the unit tests
We'll need to play around with the unit test upload features (https://github.com/EnricoMi/publish-unit-test-result-action#configuration) what works best. This is based on what we do for the integration test. Most shared code is handled by baseinstall.sh. We can now also install a database with a different name as the unit tests use that locally. As side-effect we directly test this in CI. The CI ran on GitLab before and needed extra steps to push the result to GitHub. As everything is in GitHub Actions now we can remove those extra steps. (cherry picked from commit 5530189)
1 parent e900c21 commit 9cb48fd

File tree

4 files changed

+190
-30
lines changed

4 files changed

+190
-30
lines changed

.github/jobs/baseinstall.sh

+64-22
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ alias section_start='trace_off ; section_start_internal '
1818
alias section_end='trace_off ; section_end_internal '
1919

2020
export version="$1"
21+
db=${2:-install}
22+
phpversion="${3:-8.1}"
23+
# If this script is called from unit-tests.sh, we use the test environment
24+
export APP_ENV="${4:-prod}"
25+
26+
# In the test environment, we need to use a different database
27+
[ "$APP_ENV" = "prod" ] && DATABASE_NAME=domjudge || DATABASE_NAME=domjudge_test
2128

2229
MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-root}
2330

@@ -38,8 +45,11 @@ sudo apt install -y acl zip unzip nginx php php-fpm php-gd \
3845
python3-yaml latexmk curl
3946
section_end
4047

41-
PHPVERSION=$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION."\n";')
42-
export PHPVERSION
48+
if [ -z "$phpversion" ]; then
49+
phpversion=$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION."\n";')
50+
fi
51+
52+
show_phpinfo "$phpversion"
4353

4454
section_start "Install composer"
4555
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
@@ -60,18 +70,41 @@ section_end
6070

6171
section_start "Install domserver"
6272
make configure
63-
./configure --with-baseurl='https://localhost/domjudge/' --enable-doc-build=no --prefix="/opt/domjudge"
64-
65-
make domserver
66-
sudo make install-domserver
73+
if [ "$version" = "all" ]; then
74+
# Note that we use http instead of https here as python requests doesn't
75+
# like our self-signed cert. We should fix this separately.
76+
./configure \
77+
--with-baseurl='http://localhost/domjudge/' \
78+
--with-domjudge-user=domjudge \
79+
--with-judgehost-chrootdir=/chroot/domjudge | tee "$ARTIFACTS"/configure.txt
80+
make build-scripts domserver judgehost docs
81+
make install-domserver install-judgehost install-docs
82+
else
83+
./configure \
84+
--with-baseurl='https://localhost/domjudge/' \
85+
--with-domjudge-user=root \
86+
--enable-doc-build=no \
87+
--enable-judgehost-build=no | tee "$ARTIFACTS"/configure.txt
88+
make domserver
89+
make install-domserver
90+
rm -rf /opt/domjudge/domserver/webapp/public/doc
91+
cp -r doc /opt/domjudge/domserver/webapp/public/
92+
find /opt/domjudge/domserver -name DOMjudgelogo.pdf
93+
fi
6794
section_end
6895

69-
section_start "Explicit start mysql + install DB"
70-
sudo /etc/init.d/mysql start
96+
section_start "SQL settings"
97+
cat > ~/.my.cnf <<EOF
98+
[client]
99+
host=sqlserver
100+
user=root
101+
password=${MYSQL_ROOT_PASSWORD}
102+
EOF
103+
cat ~/.my.cnf
71104

72-
mysql_root "CREATE DATABASE IF NOT EXISTS \`domjudge\` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
105+
mysql_root "CREATE DATABASE IF NOT EXISTS \`$DATABASE_NAME\` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
73106
mysql_root "CREATE USER IF NOT EXISTS \`domjudge\`@'%' IDENTIFIED BY 'domjudge';"
74-
mysql_root "GRANT SELECT, INSERT, UPDATE, DELETE ON \`domjudge\`.* TO 'domjudge'@'%';"
107+
mysql_root "GRANT SELECT, INSERT, UPDATE, DELETE ON \`$DATABASE_NAME\`.* TO 'domjudge'@'%';"
75108
mysql_root "FLUSH PRIVILEGES;"
76109

77110
# Show some MySQL debugging
@@ -80,7 +113,9 @@ mysql_root "SELECT CURRENT_USER();"
80113
mysql_root "SELECT USER();"
81114
mysql_root "SELECT user,host FROM mysql.user"
82115
mysql_root "SET GLOBAL max_allowed_packet=1073741824"
83-
echo "unused:sqlserver:domjudge:domjudge:domjudge:3306" > /opt/domjudge/domserver/etc/dbpasswords.secret
116+
mysql_root "SHOW GLOBAL STATUS LIKE 'Connection_errors_%'"
117+
mysql_root "SHOW VARIABLES LIKE '%_timeout'"
118+
echo "unused:sqlserver:$DATABASE_NAME:domjudge:domjudge:3306" > /opt/domjudge/domserver/etc/dbpasswords.secret
84119
mysql_user "SELECT CURRENT_USER();"
85120
mysql_user "SELECT USER();"
86121
section_end
@@ -107,7 +142,7 @@ cp /proc/cmdline "$ARTIFACTS"/cmdline.txt
107142
section_end
108143

109144
section_start "Setup webserver"
110-
sudo cp /opt/domjudge/domserver/etc/domjudge-fpm.conf /etc/php/$PHPVERSION/fpm/pool.d/domjudge.conf
145+
cp /opt/domjudge/domserver/etc/domjudge-fpm.conf /etc/php/"$phpversion"/fpm/pool.d/domjudge.conf
111146

112147
sudo rm -f /etc/nginx/sites-enabled/*
113148
sudo cp /opt/domjudge/domserver/etc/nginx-conf /etc/nginx/sites-enabled/domjudge
@@ -121,34 +156,41 @@ sudo nginx -t
121156
section_end
122157

123158
section_start "Show webserver is up"
124-
for service in nginx php${PHPVERSION}-fpm; do
125-
sudo systemctl restart $service
126-
sudo systemctl status $service
159+
for service in nginx php${phpversion}-fpm; do
160+
service "$service" restart
161+
service "$service" status
127162
done
128163
section_end
129164

130165
if [ "${db}" = "install" ]; then
131166
section_start "Install the example data"
167+
if [ "$version" = "unit" ]; then
168+
# Make sure admin has no team associated so we will not insert submissions during unit tests.
169+
mysql_root "UPDATE user SET teamid=null WHERE userid=1;" $DATABASE_NAME
170+
fi
132171
/opt/domjudge/domserver/bin/dj_setup_database -uroot -p${MYSQL_ROOT_PASSWORD} install-examples | tee -a "$ARTIFACTS/mysql.txt"
133172
section_end
134173
fi
135174

136175
section_start "Setup user"
137176
# We're using the admin user in all possible roles
138-
echo "DELETE FROM userrole WHERE userid=1;" | mysql -uroot -proot domjudge
177+
mysql_root "DELETE FROM userrole WHERE userid=1;" $DATABASE_NAME
139178
if [ "$version" = "team" ]; then
140179
# Add team to admin user
141-
echo "INSERT INTO userrole (userid, roleid) VALUES (1, 3);" | mysql -uroot -proot domjudge
142-
echo "UPDATE user SET teamid = 1 WHERE userid = 1;" | mysql -uroot -proot domjudge
180+
mysql_root "INSERT INTO userrole (userid, roleid) VALUES (1, 3);" $DATABASE_NAME
181+
mysql_root "UPDATE user SET teamid = 1 WHERE userid = 1;" $DATABASE_NAME
143182
elif [ "$version" = "jury" ]; then
144183
# Add jury to admin user
145-
echo "INSERT INTO userrole (userid, roleid) VALUES (1, 2);" | mysql -uroot -proot domjudge
184+
mysql_root "INSERT INTO userrole (userid, roleid) VALUES (1, 2);" $DATABASE_NAME
146185
elif [ "$version" = "balloon" ]; then
147186
# Add balloon to admin user
148-
echo "INSERT INTO userrole (userid, roleid) VALUES (1, 4);" | mysql -uroot -proot domjudge
187+
mysql_root "INSERT INTO userrole (userid, roleid) VALUES (1, 4);" $DATABASE_NAME
149188
elif [ "$version" = "admin" ]; then
150189
# Add admin to admin user
151-
echo "INSERT INTO userrole (userid, roleid) VALUES (1, 1);" | mysql -uroot -proot domjudge
190+
mysql_root "INSERT INTO userrole (userid, roleid) VALUES (1, 1);" $DATABASE_NAME
191+
elif [ "$version" = "all" ] || [ "$version" = "unit" ]; then
192+
mysql_root "INSERT INTO userrole (userid, roleid) VALUES (1, 1);" $DATABASE_NAME
193+
mysql_root "INSERT INTO userrole (userid, roleid) VALUES (1, 3);" $DATABASE_NAME
194+
mysql_root "UPDATE user SET teamid = 1 WHERE userid = 1;" $DATABASE_NAME
152195
fi
153196
section_end
154-

.github/jobs/unit-tests.sh

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#!/bin/bash
2+
3+
. .github/jobs/ci_settings.sh
4+
5+
DIR="$PWD"
6+
7+
export version=$1
8+
unittest=$2
9+
[ "$version" = "8.1" ] && CODECOVERAGE=1 || CODECOVERAGE=0
10+
11+
# Set up
12+
export unit=1
13+
14+
# Add team to admin user
15+
echo "UPDATE user SET teamid = 1 WHERE userid = 1;" | mysql domjudge_test
16+
17+
# Copy the .env.test file, as this is normally not done during
18+
# installation and we need it.
19+
cp webapp/.env.test /opt/domjudge/domserver/webapp/
20+
21+
# We also need the composer.json for PHPunit to detect the correct directory.
22+
cp webapp/composer.json /opt/domjudge/domserver/webapp/
23+
24+
cd /opt/domjudge/domserver
25+
26+
# Run phpunit tests.
27+
pcov=""
28+
phpcov=""
29+
if [ "$CODECOVERAGE" -eq 1 ]; then
30+
phpcov="-dpcov.enabled=1 -dpcov.directory=webapp/src"
31+
pcov="--coverage-html=${DIR}/coverage-html --coverage-clover coverage.xml"
32+
fi
33+
set +e
34+
echo "unused:sqlserver:domjudge:domjudge:domjudge:3306" > /opt/domjudge/domserver/etc/dbpasswords.secret
35+
php $phpcov webapp/bin/phpunit -c webapp/phpunit.xml.dist webapp/tests/$unittest --log-junit ${ARTIFACTS}/unit-tests.xml --colors=never $pcov > "$ARTIFACTS"/phpunit.out
36+
UNITSUCCESS=$?
37+
38+
# Store the unit tests also in the root for the GHA
39+
cp $ARTIFACTS/unit-tests.xml $DIR/
40+
41+
# Make sure the log exists before copy
42+
touch ${DIR}/webapp/var/log/test.log
43+
cp ${DIR}/webapp/var/log/*.log "$ARTIFACTS"/
44+
45+
set -e
46+
CNT=0
47+
THRESHOLD=32
48+
if [ $CODECOVERAGE -eq 1 ]; then
49+
CNT=$(sed -n '/Generating code coverage report/,$p' "$ARTIFACTS"/phpunit.out | grep -v DoctrineTestBundle | grep -cv ^$)
50+
fi
51+
52+
if [ $UNITSUCCESS -ne 0 ] || [ $CNT -gt $THRESHOLD ]; then
53+
exit 1
54+
fi
55+
56+
if [ $CODECOVERAGE -eq 1 ]; then
57+
section_start "Upload code coverage"
58+
# Only upload when we got working unit-tests.
59+
set +u # Uses some variables which are not set
60+
# shellcheck disable=SC1090
61+
. $DIR/.github/jobs/uploadcodecov.sh &>> "$ARTIFACTS"/codecov.log
62+
section_end
63+
fi

.github/workflows/unit-tests.yml

+63
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
name: Unit tests
2+
# We can speedup with: https://github.com/actions/cache
23
on:
34
push:
45
branches:
@@ -19,3 +20,65 @@ jobs:
1920
- name: Detect changes to manually verify
2021
run: diff newcodecov .github/jobs/uploadcodecov.sh
2122

23+
unit-tests:
24+
runs-on: ubuntu-24.04
25+
timeout-minutes: 20
26+
container:
27+
image: domjudge/gitlabci:24.04
28+
services:
29+
sqlserver:
30+
image: mariadb
31+
ports:
32+
- 3306:3306
33+
env:
34+
MYSQL_ROOT_PASSWORD: root
35+
MYSQL_USER: domjudge
36+
MYSQL_PASSWORD: domjudge
37+
options: --health-cmd="healthcheck.sh --connect --innodb_initialized" --health-interval=10s --health-timeout=5s --health-retries=3
38+
strategy:
39+
matrix:
40+
PHPVERSION: [8.1, 8.4]
41+
TEST: [Unit, E2E]
42+
steps:
43+
- uses: actions/checkout@v4
44+
- name: info
45+
run: |
46+
cat /proc/cmdline && echo &&
47+
cat /proc/mounts && echo &&
48+
ls -al /sys/fs/cgroup && echo &&
49+
uname -a && echo &&
50+
stat -fc %T /sys/fs/cgroup && echo &&
51+
cat /proc/self/cgroup && echo &&
52+
cat /proc/cpuinfo
53+
- name: pstree
54+
run: pstree -p
55+
- name: Install DOMjudge
56+
run: .github/jobs/baseinstall.sh unit install ${{ matrix.PHPVERSION }} test
57+
- name: Check nginx
58+
run: curl -v https://localhost/domjudge/
59+
- name: Run the unit-tests
60+
run: .github/jobs/unit-tests.sh ${{ matrix.PHPVERSION }} ${{ matrix.TEST }}
61+
- name: Publish Test Results
62+
uses: EnricoMi/publish-unit-test-result-action@v2
63+
if: ${{ !cancelled() }}
64+
with:
65+
comment_mode: changes in failures
66+
check_name: unit-tests-${{ matrix.PHPVERSION }}-${{ matrix.TEST }}.xml
67+
files: unit-tests-${{ matrix.PHPVERSION }}-${{ matrix.TEST }}.xml
68+
- name: Get SQL logs
69+
run: docker logs "${{ job.services.sqlserver.id }}"
70+
- name: Collect docker logs on failure
71+
if: ${{ !cancelled() }}
72+
uses: jwalton/gh-docker-logs@v1
73+
with:
74+
dest: '/tmp/docker-logs'
75+
- name: Upload all logs/artifacts
76+
if: ${{ !cancelled() }}
77+
uses: actions/upload-artifact@v4
78+
with:
79+
name: Logs-${{ matrix.PHPVERSION }}-${{ matrix.TEST }}
80+
path: |
81+
/var/log/nginx
82+
/opt/domjudge/domserver/webapp/var/log/*.log
83+
/tmp/docker-logs
84+
/tmp/artifacts

gitlab/base.sh

-8
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,6 @@
44

55
lsb_release -a
66

7-
cat > ~/.my.cnf <<EOF
8-
[client]
9-
host=sqlserver
10-
user=root
11-
password=${MYSQL_ROOT_PASSWORD}
12-
EOF
13-
cat ~/.my.cnf
14-
157
# FIXME: This chicken-egg problem is annoying but let us bootstrap for now.
168
echo "CREATE DATABASE IF NOT EXISTS \`domjudge\` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" | mysql
179
echo "CREATE USER 'domjudge'@'%' IDENTIFIED BY 'domjudge';" | mysql

0 commit comments

Comments
 (0)