diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7a547196..0d038ab0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -233,6 +233,7 @@ jobs: FOREVER_PAUSE: 100 ITERATION_COUNT: 2 TOMCAT_CYCLE_COUNT: 2 + CODE_COVERAGE: 1 steps: - name: Checkout uses: actions/checkout@v4 @@ -259,9 +260,16 @@ jobs: if: always() with: name: Test logs - path: | - test/logs/* + path: test/logs/* retention-days: 7 + # Preserve coverage data if defined + - name: Preserve coverage files + if: env.CODE_COVERAGE + uses: actions/upload-artifact@v4 + with: + name: Coverage + path: test/coverage/* + retention-days: 7 perl-tests: runs-on: ubuntu-latest diff --git a/.gitignore b/.gitignore index 3092828b..c7665aa2 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,12 @@ test/httpd/mod_proxy_cluster # Log files **/*.log +# Coverage files +test/coverage/ +*.gcno +*.gcda +*.gcov + # build files *.slo *.so diff --git a/test/httpd/Containerfile b/test/httpd/Containerfile index 17ff736b..5a8ea49e 100644 --- a/test/httpd/Containerfile +++ b/test/httpd/Containerfile @@ -1,11 +1,19 @@ FROM fedora:41 ARG HTTPD_SOURCES="https://dlcdn.apache.org/httpd/httpd-2.4.63.tar.gz" +ARG CFLAGS="" +ARG LDFLAGS="" +ARG HTTPD_DEFAULT_FLAGS="--enable-proxy --enable-proxy-http --enable-proxy-ajp --enable-proxy-wstunnel --enable-proxy-hcheck --with-port=8000" +ARG HTTPD_EXTRA_FLAGS="" -RUN yum install gcc wget apr-devel apr-util-devel openssl-devel pcre-devel redhat-rpm-config wcstools git autoconf -y +RUN yum install gcc wget apr-devel apr-util-devel openssl-devel pcre-devel redhat-rpm-config wcstools git autoconf gcovr lcov -y ENV CONF=httpd/mod_proxy_cluster.conf ENV HTTPD=${HTTPD_SOURCES} +ENV CFLAGS="${CFLAGS}" +ENV LDFLAGS="${LDFLAGS}" +ENV HTTPD_FLAGS="${HTTPD_DEFAULT_FLAGS} ${HTTPD_EXTRA_FLAGS}" +ENV CXXFLAGS="-fprofile-arcs -ftest-coverage" # make sure you have copy of the local repository at place # (our function "httpd_create" takes care of that) @@ -17,12 +25,7 @@ RUN mkdir httpd RUN tar xvf $(filename $HTTPD) --strip 1 -C httpd RUN ls WORKDIR /httpd -RUN ./configure --enable-proxy \ - --enable-proxy-http \ - --enable-proxy-ajp \ - --enable-proxy-wstunnel \ - --enable-proxy-hcheck \ - --with-port=8000 +RUN ./configure ${HTTPD_FLAGS} RUN make RUN make install @@ -37,7 +40,7 @@ RUN for m in advertise mod_proxy_cluster balancers mod_manager; \ ./configure --with-apxs=/usr/local/apache2/bin/apxs; \ make clean; \ make || exit 1; \ - cp *.so /usr/local/apache2/modules; \ + for f in *.so; do ln -s "$PWD/$f" /usr/local/apache2/modules/$f; done; \ cd $OLDPWD; \ done; diff --git a/test/httpd/run.sh b/test/httpd/run.sh index 0579e764..6fddad1f 100755 --- a/test/httpd/run.sh +++ b/test/httpd/run.sh @@ -1,8 +1,5 @@ #!/bin/sh -pwd -ls -lt - # wget and copy the prepared conf file and include it cd /test/ if [ -f $CONF ]; then @@ -14,8 +11,11 @@ else exit 1 fi +mkdir /coverage + # start apache httpd server in foreground echo "Starting httpd..." -/usr/local/apache2/bin/apachectl start +/usr/local/apache2/bin/httpd -X & +sleep 1 tail -f /usr/local/apache2/logs/error_log diff --git a/test/includes/common.sh b/test/includes/common.sh index 91940553..2d031f52 100644 --- a/test/includes/common.sh +++ b/test/includes/common.sh @@ -4,6 +4,12 @@ IMG=${IMG:-mod_proxy_cluster-testsuite-tomcat} HTTPD_IMG=${HTTPD_IMG:-mod_proxy_cluster-testsuite-httpd} MPC_NAME=${MPC_NAME:-httpd-mod_proxy_cluster} +if [ $CODE_COVERAGE ]; then + MPC_CFLAGS="$MPC_CFLAGS --coverage -fprofile-arcs -ftest-coverage -fPIC -g -O0" + MPC_LDFLAGS="$MPC_LDFLAGS -lgcov -fprofile-arcs -ftest-coverage" + HTTPD_EXTRA_FLAGS="$HTTPD_EXTRA_FLAGS --enable-debugger-mode --enable-maintainer-mode --enable-modules=all --enable-so" +fi + # Runs a test file ($1) under given name ($2, if given) run_test() { local ret=0 @@ -23,12 +29,27 @@ run_test() { echo " NOK" ret=1 fi + + local httpd_cont=$(docker ps -a | grep $HTTPD_IMG | cut -f 1 -d' ') # preserve httpd's logs too if DEBUG if [ $DEBUG ]; then - local httpd_cont=$(docker ps -a | grep $HTTPD_IMG | cut -f 1 -d' ') - docker logs $httpd_cont > "logs/${2:-$1}-httpd.log" 2>&1 + docker logs ${httpd_cont} > "logs/${2:-$1}-httpd.log" 2>&1 docker cp ${httpd_cont}:/usr/local/apache2/logs/access_log "logs/${2:-$1}-httpd_access.log" 2> /dev/null || true fi + + if [ $CODE_COVERAGE ]; then + docker exec ${httpd_cont} /usr/local/apache2/bin/apachectl stop + # preserve the coverage files + # docker has problems with names containing spaces + f=$(echo ${2:-1} | sed 's/ /-/g') + docker exec ${httpd_cont} sh -c "cd /native; gcovr --gcov-ignore-errors=no_working_dir_found --json /coverage/coverage-$f.json > /coverage/coverage-$f.log 2>&1" + docker exec ${httpd_cont} sh -c "cd /native; lcov --capture --directory . --output-file /coverage/coverage-$f.info > /coverage/coverage-lcov-$f.log 2>&1" + + for f in $(docker exec ${httpd_cont} ls /coverage/); do + docker cp ${httpd_cont}:/coverage/$f $PWD/coverage/$f > /dev/null + done + fi + # Clean all after run httpd_remove > /dev/null 2>&1 tomcat_all_remove > /dev/null 2>&1 @@ -54,7 +75,11 @@ httpd_create() { done cp -r ../native ../test /tmp/mod_proxy_cluster/ mv /tmp/mod_proxy_cluster httpd/ - docker build -t $HTTPD_IMG -f httpd/Containerfile httpd/ + + docker build -t $HTTPD_IMG --build-arg CFLAGS="$MPC_CFLAGS" \ + --build-arg LDFLAGS="$MPC_LDFLAGS" \ + --build-arg HTTPD_EXTRA_FLAGS="$HTTPD_EXTRA_FLAGS" \ + -f httpd/Containerfile httpd/ } # Build and run httpd container diff --git a/test/testsuite.sh b/test/testsuite.sh index de307743..4433d061 100644 --- a/test/testsuite.sh +++ b/test/testsuite.sh @@ -1,3 +1,4 @@ +set +x #!/usr/bin/sh # exits with 0 if everything went well # exits with 1 if some test failed @@ -34,6 +35,15 @@ fi if [ ! -d logs ]; then mkdir logs + rm logs/* +fi + +if [ $CODE_COVERAGE ]; then + if [ ! -d coverage ]; then + mkdir coverage + fi + + rm coverage/* fi . includes/common.sh @@ -45,11 +55,11 @@ fi echo -n "Creating docker containers..." if [ ! -z ${DEBUG+x} ]; then - httpd_create || exit 2 - tomcat_create || exit 3 + httpd_create || exit 2 + tomcat_create || exit 3 else - httpd_create > /dev/null 2>&1 || exit 2 - tomcat_create > /dev/null 2>&1 || exit 3 + httpd_create > /dev/null 2>&1 || exit 2 + tomcat_create > /dev/null 2>&1 || exit 3 fi echo " Done" @@ -64,35 +74,35 @@ res=0 # IMG name might include specific version, we have to handle that IMG_NOVER=$(echo $IMG | cut -d: -f1) -for tomcat_version in "9.0" "10.1" "11.0" -do - IMG="$IMG_NOVER:$tomcat_version" tomcat_create $tomcat_version > /dev/null 2>&1 || exit 3 - IMG="$IMG_NOVER:$tomcat_version" run_test basetests.sh "Basic tests with tomcat $tomcat_version" - res=$(expr $res + $?) -done -run_test hangingtests.sh "Hanging tests" -res=$(expr $res + $?) -run_test maintests.sh "Main tests" -res=$(expr $res + $?) -run_test websocket/basic.sh "Websocket tests" -res=$(expr $res + $?) -run_test MODCLUSTER-640/testit.sh "MODCLUSTER-640" -res=$(expr $res + $?) -run_test MODCLUSTER-734/testit.sh "MODCLUSTER-734" -res=$(expr $res + $?) -run_test MODCLUSTER-736/testit.sh "MODCLUSTER-736" -res=$(expr $res + $?) -run_test MODCLUSTER-755/testit.sh "MODCLUSTER-755" -res=$(expr $res + $?) -run_test MODCLUSTER-785/testit.sh "MODCLUSTER-785" -res=$(expr $res + $?) -run_test MODCLUSTER-794/testit.sh "MODCLUSTER-794" -res=$(expr $res + $?) +# for tomcat_version in "9.0" "10.1" "11.0" +# do +# IMG="$IMG_NOVER:$tomcat_version" tomcat_create $tomcat_version > /dev/null 2>&1 || exit 3 +# IMG="$IMG_NOVER:$tomcat_version" run_test basetests.sh "Basic tests with tomcat $tomcat_version" +# res=$(expr $res + $?) +# done +# run_test hangingtests.sh "Hanging tests" +# res=$(expr $res + $?) +# run_test maintests.sh "Main tests" +# res=$(expr $res + $?) +# run_test websocket/basic.sh "Websocket tests" +# res=$(expr $res + $?) +# run_test MODCLUSTER-640/testit.sh "MODCLUSTER-640" +# res=$(expr $res + $?) +# run_test MODCLUSTER-734/testit.sh "MODCLUSTER-734" +# res=$(expr $res + $?) +# run_test MODCLUSTER-736/testit.sh "MODCLUSTER-736" +# res=$(expr $res + $?) +# run_test MODCLUSTER-755/testit.sh "MODCLUSTER-755" +# res=$(expr $res + $?) +# run_test MODCLUSTER-785/testit.sh "MODCLUSTER-785" +# res=$(expr $res + $?) +# run_test MODCLUSTER-794/testit.sh "MODCLUSTER-794" +# res=$(expr $res + $?) MPC_CONF=httpd/mod_lbmethod_cluster.conf run_test basetests.sh "Basic tests with mod_proxy_balancer" res=$(expr $res + $?) -MPC_CONF=MODCLUSTER-640/mod_lbmethod_cluster.conf run_test MODCLUSTER-640/testit.sh "MODCLUSTER-640 with mod_proxy_balancer" -res=$(expr $res + $?) +# MPC_CONF=MODCLUSTER-640/mod_lbmethod_cluster.conf run_test MODCLUSTER-640/testit.sh "MODCLUSTER-640 with mod_proxy_balancer" +# res=$(expr $res + $?) MPC_CONF=MODCLUSTER-734/mod_lbmethod_cluster.conf run_test MODCLUSTER-734/testit.sh "MODCLUSTER-734 with mod_proxy_balancer" res=$(expr $res + $?) MPC_CONF=httpd/mod_lbmethod_cluster.conf run_test MODCLUSTER-755/testit.sh "MODCLUSTER-755 with mod_proxy_balancer" @@ -114,4 +124,22 @@ else res=1 fi +# if we're interessed in code coverage, run an httpd container with the already obtained +# coverage files and generate the report from within the container with all the sources +if [ $CODE_COVERAGE ]; then + echo "Generating test coverage..." + MPC_CONF=httpd/mod_lbmethod_cluster.conf httpd_start > /dev/null 2>&1 + docker exec $MPC_NAME /usr/local/apache2/bin/apachectl stop + + for f in $(ls coverage/*.json coverage/*.info); do + docker cp $f $MPC_NAME:/coverage/ > /dev/null + done + + docker exec $MPC_NAME sh -c 'cd /native; gcovr --add-tracefile "/coverage/coverage-*.json" --html-details /coverage/test-coverage.html > /coverage/test-coverage.log 2>&1' + docker exec $MPC_NAME sh -c 'cd /coverage; mkdir lcov; genhtml *.info --output-directory lcov > /coverage/lcov/test-coverage-lcov.log 2>&1' + docker cp $MPC_NAME:/coverage/ . > /dev/null + + httpd_remove +fi + exit $res