From: Remi Gacogne Date: Mon, 29 Sep 2025 13:04:39 +0000 (+0200) Subject: build-and-test-all: Fix code coverage generation from meson dist tarball X-Git-Tag: rec-5.4.0-alpha1~226^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ada2257104537d3dfd939e9c05efe3c3396e8b1d;p=thirdparty%2Fpdns.git build-and-test-all: Fix code coverage generation from meson dist tarball Signed-off-by: Remi Gacogne --- diff --git a/.github/scripts/normalize_paths_in_coverage.py b/.github/scripts/normalize_paths_in_coverage.py index 78475acc6e..95092c1e08 100755 --- a/.github/scripts/normalize_paths_in_coverage.py +++ b/.github/scripts/normalize_paths_in_coverage.py @@ -2,15 +2,68 @@ import os import sys +from pathlib import Path -if __name__ == '__main__': +DEBUG = False + +def debug_print(string): + if DEBUG: + print(string) + +def get_relative_to_product_source_dir(product, target): + if product == 'auth': + # authoritative or tool + return target + if product == 'recursor': + return os.path.join('pdns', 'recursordist', target) + if product == 'dnsdist': + return os.path.join('pdns', 'dnsdistdist', target) + return None + +def remove_meson_dist_path(product, target): + # target looks like this: /tmp/dnsdist-meson-dist-build/meson-dist/dnsdist-0.0.0-git1/xsk.hh + path = Path(target) + index = path.parts.index('meson-dist') + # skip up to meson-dist and the directory below that, + # so we now have: xsk.hh + relevant = str(path.relative_to(path.parents[len(path.parts) - (index + 3)])) + return get_relative_to_product_source_dir(product, relevant) + + +def remove_dist_dir_path(repositoryRoot, version, target): + # get rid of the distdir path, to get file paths as they are in the repository + # if we are building from meson, it might look like this: + # /__w/pdns/pdns/pdns/dnsdistdist/dnsdist-0.0.0-git1/config.h + if f'pdns-{version}' in target: + # authoritative or tool + authPath = os.path.join(repositoryRoot, f'pdns-{version}') + relativeToAuth = os.path.relpath(target, authPath) + target = get_relative_to_product_source_dir('auth', relativeToAuth) + return target + if f'pdns-recursor-{version}' in target: + recPath = os.path.join(repositoryRoot, 'pdns', 'recursordist', f'pdns-recursor-{version}') + relativeToRec = os.path.relpath(target, recPath) + return get_relative_to_product_source_dir('recursor', relativeToRec) + if f'dnsdist-{version}' in target: + distPath = os.path.join(repositoryRoot, 'pdns', 'dnsdistdist', f'dnsdist-{version}') + relativeToDist = os.path.relpath(target, distPath) + target = get_relative_to_product_source_dir('dnsdist', relativeToDist) + return target + + # let's assume we already have a full path to the repository, like + # /__w/pdns/pdns/pdns/auth-catalogzone.hh + distPath = os.path.join(repositoryRoot) + relativeToDist = os.path.relpath(target, distPath) + return relativeToDist + +def process(): repositoryRoot = os.path.realpath(sys.argv[1]) - version = sys.argv[2] - inputFile = sys.argv[3] - outputFile = sys.argv[4] - fromDistDir = sys.argv[5] - with open(inputFile, mode='r') as inputFilePtr: - with open(outputFile, mode='w') as outputFilePtr: + product = sys.argv[2] + version = sys.argv[3] + inputFile = sys.argv[4] + outputFile = sys.argv[5] + with open(inputFile, mode='r', encoding='utf-8') as inputFilePtr: + with open(outputFile, mode='w', encoding='utf-8') as outputFilePtr: for line in inputFilePtr: if not line.startswith('SF:'): outputFilePtr.write(line) @@ -24,31 +77,30 @@ if __name__ == '__main__': source_file = parts[1].rstrip() # get rid of symbolic links target = os.path.realpath(source_file) + debug_print(f'- Got source_file={source_file}, target={target}') + + if '/meson-dist/' in target: + # this is a file that comes from a meson dist tarball + target = remove_meson_dist_path(product, target) + debug_print(f'meson-dist -> target={target}') + else: + target = remove_dist_dir_path(repositoryRoot, version, target) + debug_print(f'dist dir -> target={target}') - # get rid of the distdir path, to get file paths as they are in the repository - if f'pdns-{version}' in target: - # authoritative or tool - authPath = os.path.join(repositoryRoot, f'pdns-{version}') - relativeToAuth = os.path.relpath(target, authPath) - target = relativeToAuth - elif f'pdns-recursor-{version}' in target: - recPath = os.path.join(repositoryRoot, 'pdns', 'recursordist', f'pdns-recursor-{version}') - relativeToRec = os.path.relpath(target, recPath) - target = os.path.join('pdns', 'recursordist', relativeToRec) - elif f'dnsdist-{version}' in target: - distPath = os.path.join(repositoryRoot, 'pdns', 'dnsdistdist', f'dnsdist-{version}') - relativeToDist = os.path.relpath(target, distPath) - target = os.path.join('pdns', 'dnsdistdist', relativeToDist) - elif fromDistDir == '1': - print(f'Ignoring {target} that we could not map to a distdir', file=sys.stderr) + if target is None: continue # we need to properly map symbolic links fullPath = os.path.join(repositoryRoot, target) + debug_print(f'fullPath is {fullPath}') if os.path.islink(fullPath): # get the link target realPath = os.path.realpath(fullPath) # and make it relative again target = os.path.relpath(realPath, repositoryRoot) + debug_print(f'=> final target is {target}') outputFilePtr.write(f"SF:{target}\n") + +if __name__ == '__main__': + process() diff --git a/.github/workflows/build-and-test-all.yml b/.github/workflows/build-and-test-all.yml index 4bf9604ee7..aefdf80036 100644 --- a/.github/workflows/build-and-test-all.yml +++ b/.github/workflows/build-and-test-all.yml @@ -111,7 +111,7 @@ jobs: - run: ${{ env.INV_CMD }} ci-auth-run-unit-tests ${{ matrix.builder == 'meson' && '--meson' || '' }} env: PDNS_BUILD_PATH: ../pdns-${{ env.BUILDER_VERSION }} - - run: ${{ env.INV_CMD }} generate-coverage-info ./pdns-auth-testrunner $GITHUB_WORKSPACE + - run: ${{ env.INV_CMD }} generate-coverage-info ./pdns-auth-testrunner 'auth' $GITHUB_WORKSPACE if: ${{ env.COVERAGE == 'yes' && matrix.builder == 'meson' }} - name: Coveralls Parallel auth unit if: ${{ env.COVERAGE == 'yes' && matrix.builder == 'meson' }} @@ -199,7 +199,7 @@ jobs: working-directory: ./pdns/recursordist/ - run: ${{ env.INV_CMD }} ci-rec-build ${{ matrix.builder == 'meson' && '--meson' || '' }} - run: ${{ env.INV_CMD }} ci-rec-run-unit-tests ${{ matrix.builder == 'meson' && '--meson' || '' }} - - run: ${{ env.INV_CMD }} generate-coverage-info ./testrunner $GITHUB_WORKSPACE + - run: ${{ env.INV_CMD }} generate-coverage-info ./testrunner 'recursor' $GITHUB_WORKSPACE if: ${{ env.COVERAGE == 'yes' && matrix.sanitizers != 'tsan' && matrix.builder == 'meson' }} - name: Coveralls Parallel rec unit if: ${{ env.COVERAGE == 'yes' && matrix.sanitizers != 'tsan' && matrix.builder == 'meson' }} @@ -298,7 +298,7 @@ jobs: if: ${{ matrix.builder == 'autotools' }} - run: ${{ env.INV_CMD }} ci-dnsdist-make-bear ${{ matrix.builder }} - run: ${{ env.INV_CMD }} ci-dnsdist-run-unit-tests ${{ matrix.builder }} - - run: ${{ env.INV_CMD }} generate-coverage-info ./testrunner $GITHUB_WORKSPACE + - run: ${{ env.INV_CMD }} generate-coverage-info ./testrunner 'dnsdist' $GITHUB_WORKSPACE if: ${{ env.COVERAGE == 'yes' && matrix.sanitizers != 'tsan' && matrix.builder == 'meson'}} - name: Coveralls Parallel dnsdist unit if: ${{ env.COVERAGE == 'yes' && matrix.sanitizers != 'tsan' && matrix.builder == 'meson' }} @@ -384,7 +384,7 @@ jobs: - run: ${{ env.INV_CMD }} install-clang-runtime - run: ${{ env.INV_CMD }} install-auth-test-deps -b ${{ matrix.backend }} - run: ${{ env.INV_CMD }} test-api auth -b ${{ matrix.backend }} - - run: ${{ env.INV_CMD }} generate-coverage-info /opt/pdns-auth/sbin/pdns-auth $GITHUB_WORKSPACE + - run: ${{ env.INV_CMD }} generate-coverage-info /opt/pdns-auth/sbin/pdns-auth 'auth' $GITHUB_WORKSPACE if: ${{ env.COVERAGE == 'yes' }} - name: Coveralls Parallel auth API ${{ matrix.backend }} if: ${{ env.COVERAGE == 'yes' }} @@ -516,7 +516,7 @@ jobs: - run: ${{ env.INV_CMD }} install-clang-runtime - run: ${{ env.INV_CMD }} install-auth-test-deps -b ${{ matrix.backend }} - run: ${{ env.INV_CMD }} test-auth-backend -b ${{ matrix.backend }} - - run: ${{ env.INV_CMD }} generate-coverage-info /opt/pdns-auth/sbin/pdns-auth $GITHUB_WORKSPACE + - run: ${{ env.INV_CMD }} generate-coverage-info /opt/pdns-auth/sbin/pdns-auth 'auth' $GITHUB_WORKSPACE if: ${{ env.COVERAGE == 'yes' }} - name: Coveralls Parallel auth backend ${{ matrix.backend }} if: ${{ env.COVERAGE == 'yes' }} @@ -559,7 +559,7 @@ jobs: - run: ${{ env.INV_CMD }} install-clang-runtime - run: ${{ env.INV_CMD }} install-auth-test-deps - run: ${{ env.INV_CMD }} test-ixfrdist - - run: ${{ env.INV_CMD }} generate-coverage-info /opt/pdns-auth/bin/ixfrdist $GITHUB_WORKSPACE + - run: ${{ env.INV_CMD }} generate-coverage-info /opt/pdns-auth/bin/ixfrdist 'auth' $GITHUB_WORKSPACE if: ${{ env.COVERAGE == 'yes' }} - name: Coveralls Parallel ixfrdist if: ${{ env.COVERAGE == 'yes' }} @@ -611,7 +611,7 @@ jobs: - run: ${{ env.INV_CMD }} install-clang-runtime - run: ${{ env.INV_CMD }} install-rec-test-deps - run: ${{ env.INV_CMD }} test-api recursor - - run: ${{ env.INV_CMD }} generate-coverage-info /opt/pdns-recursor/sbin/pdns_recursor $GITHUB_WORKSPACE + - run: ${{ env.INV_CMD }} generate-coverage-info /opt/pdns-recursor/sbin/pdns_recursor 'recursor' $GITHUB_WORKSPACE if: ${{ env.COVERAGE == 'yes' && matrix.sanitizers != 'tsan' }} - name: Coveralls Parallel recursor API if: ${{ env.COVERAGE == 'yes' && matrix.sanitizers != 'tsan' }} @@ -665,7 +665,7 @@ jobs: - run: ${{ env.INV_CMD }} install-clang-runtime - run: ${{ env.INV_CMD }} install-rec-test-deps - run: ${{ env.INV_CMD }} test-regression-recursor - - run: ${{ env.INV_CMD }} generate-coverage-info /opt/pdns-recursor/sbin/pdns_recursor $GITHUB_WORKSPACE + - run: ${{ env.INV_CMD }} generate-coverage-info /opt/pdns-recursor/sbin/pdns_recursor 'recursor' $GITHUB_WORKSPACE if: ${{ env.COVERAGE == 'yes' && matrix.sanitizers != 'tsan' }} - name: Coveralls Parallel recursor regression if: ${{ env.COVERAGE == 'yes' && matrix.sanitizers != 'tsan' }} @@ -718,7 +718,7 @@ jobs: - run: ${{ env.INV_CMD }} install-clang-runtime - run: ${{ env.INV_CMD }} install-rec-bulk-deps - run: ${{ env.INV_CMD }} test-bulk-recursor 100 ${{ matrix.threads }} ${{ matrix.mthreads }} ${{ matrix.shards }} ${{ matrix.IPv6 }} - - run: ${{ env.INV_CMD }} generate-coverage-info /opt/pdns-recursor/sbin/pdns_recursor $GITHUB_WORKSPACE + - run: ${{ env.INV_CMD }} generate-coverage-info /opt/pdns-recursor/sbin/pdns_recursor 'recursor' $GITHUB_WORKSPACE if: ${{ env.COVERAGE == 'yes' && matrix.sanitizers != 'tsan' }} - name: Coveralls Parallel recursor bulk if: ${{ env.COVERAGE == 'yes' && matrix.sanitizers != 'tsan' }} @@ -769,7 +769,7 @@ jobs: ASAN_OPTIONS: detect_leaks=0 TSAN_OPTIONS: "halt_on_error=1:suppressions=${{ github.workspace }}/pdns/recursordist/recursor-tsan.supp" # Disabled, it gives us: "/bin/bash: line 1: llvm-profdata-13: command not found" due to mismatch between deb and ubuntu versions - #- run: . ${{ github.workspace }}/.venv/bin/activate && inv generate-coverage-info /opt/pdns-recursor/sbin/pdns_recursor $GITHUB_WORKSPACE + #- run: . ${{ github.workspace }}/.venv/bin/activate && inv generate-coverage-info 'recursor' /opt/pdns-recursor/sbin/pdns_recursor $GITHUB_WORKSPACE # if: ${{ env.COVERAGE == 'yes' && matrix.sanitizers != 'tsan' }} #- name: Coveralls Parallel recursor bulk # if: ${{ env.COVERAGE == 'yes' && matrix.sanitizers != 'tsan' }} @@ -825,7 +825,7 @@ jobs: - run: ${{ env.INV_CMD }} install-clang-runtime - run: ${{ env.INV_CMD }} install-dnsdist-test-deps $([ "$(. /etc/os-release && echo $VERSION_CODENAME)" = "bullseye" ] && echo "--skipXDP=True") - run: ${{ env.INV_CMD }} test-dnsdist $([ "$(. /etc/os-release && echo $VERSION_CODENAME)" = "bullseye" ] && echo "--skipXDP=True") - - run: ${{ env.INV_CMD }} generate-coverage-info /opt/dnsdist/bin/dnsdist $GITHUB_WORKSPACE + - run: ${{ env.INV_CMD }} generate-coverage-info /opt/dnsdist/bin/dnsdist 'dnsdist' $GITHUB_WORKSPACE if: ${{ env.COVERAGE == 'yes' && matrix.sanitizers != 'tsan' }} - name: Coveralls Parallel dnsdist regression if: ${{ env.COVERAGE == 'yes' && matrix.sanitizers != 'tsan' }} diff --git a/tasks.py b/tasks.py index 34df1980d2..719240f206 100644 --- a/tasks.py +++ b/tasks.py @@ -232,12 +232,12 @@ def install_coverage_deps(c): c.sudo(f'apt-get install -y --no-install-recommends llvm-{clang_version}') @task -def generate_coverage_info(c, binary, outputDir): +def generate_coverage_info(c, binary, product, outputDir): if is_coverage_enabled(): version = os.getenv('BUILDER_VERSION') c.run(f'llvm-profdata-{clang_version} merge -sparse -o {outputDir}/temp.profdata /tmp/code-*.profraw') c.run(f'llvm-cov-{clang_version} export --format=lcov --ignore-filename-regex=\'^/usr/\' -instr-profile={outputDir}/temp.profdata -object {binary} > {outputDir}/coverage.lcov') - c.run(f'{outputDir}/.github/scripts/normalize_paths_in_coverage.py {outputDir} {version} {outputDir}/coverage.lcov {outputDir}/normalized_coverage.lcov 0') + c.run(f'{outputDir}/.github/scripts/normalize_paths_in_coverage.py {outputDir} {product} {version} {outputDir}/coverage.lcov {outputDir}/normalized_coverage.lcov 0') c.run(f'mv {outputDir}/normalized_coverage.lcov {outputDir}/coverage.lcov') def setup_authbind(c):