From f1de08e5a52518f054e27d75c6868250dd671dfc Mon Sep 17 00:00:00 2001 From: daxpedda Date: Sat, 17 Aug 2024 23:57:20 +0200 Subject: [PATCH] Add test coverage --- .github/workflows/coverage-documentation.yaml | 238 ++++++++++++++++++ .github/workflows/documentation.yaml | 56 ----- .github/workflows/merge.yaml | 2 +- README.md | 3 +- 4 files changed, 241 insertions(+), 58 deletions(-) create mode 100644 .github/workflows/coverage-documentation.yaml delete mode 100644 .github/workflows/documentation.yaml diff --git a/.github/workflows/coverage-documentation.yaml b/.github/workflows/coverage-documentation.yaml new file mode 100644 index 0000000..5e86c70 --- /dev/null +++ b/.github/workflows/coverage-documentation.yaml @@ -0,0 +1,238 @@ +name: Coverage & Documentation + +on: + push: + branches: ["main"] + pull_request: + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref_name }} + cancel-in-progress: true + +env: + CARGO_TERM_COLOR: always + +jobs: + coverage: + name: Test Coverage ${{ matrix.mt.description }} + + runs-on: ubuntu-24.04 + + timeout-minutes: 10 + + strategy: + matrix: + mt: + - { id: 0 } + - { + id: 1, + description: with Atomics, + component: ",rust-src", + cflags: -matomics -mbulk-memory, + flags: "-Ctarget-feature=+atomics,+bulk-memory", + args: "-Zbuild-std=panic_abort,std", + } + + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install `wasm-bindgen-cli` + uses: taiki-e/cache-cargo-install-action@v2 + with: + tool: wasm-bindgen-cli + - name: Install LLVM v18 + run: sudo apt-get install llvm-18 + - name: Install Rust nightly + run: | + rustup toolchain install nightly --profile minimal --target wasm32-unknown-unknown --component llvm-tools-preview${{ matrix.mt.component }} + rustup default nightly + - name: Test + env: + CHROMEDRIVER: chromedriver + CFLAGS_wasm32_unknown_unknown: ${{ matrix.mt.cflags }} + CARGO_HOST_RUSTFLAGS: --cfg=wasm_bindgen_unstable_test_coverage + RUSTFLAGS: + -Cinstrument-coverage -Zno-profiler-runtime --emit=llvm-ir + --cfg=wasm_bindgen_unstable_test_coverage ${{ matrix.mt.flags }} + WASM_BINDGEN_UNSTABLE_TEST_PROFRAW_OUT: coverage-input + run: | + mkdir coverage-input + cargo test --all-features --target wasm32-unknown-unknown -Ztarget-applies-to-host -Zhost-config ${{ matrix.mt.args }} --tests + - name: Prepare Object Files + env: + CFLAGS_wasm32_unknown_unknown: ${{ matrix.mt.cflags }} + CARGO_HOST_RUSTFLAGS: --cfg=wasm_bindgen_unstable_test_coverage + RUSTFLAGS: + -Cinstrument-coverage -Zno-profiler-runtime --emit=llvm-ir + --cfg=wasm_bindgen_unstable_test_coverage ${{ matrix.mt.flags }} + run: | + mkdir coverage-output + crate_name=web_time + IFS=$'\n' + for file in $( + cargo test --all-features --target wasm32-unknown-unknown -Ztarget-applies-to-host -Zhost-config ${{ matrix.mt.args }} --tests --no-run --message-format=json | \ + jq -r "select(.reason == \"compiler-artifact\") | (select(.target.kind == [\"test\"]) // select(.target.name == \"$crate_name\")) | .filenames[0]" + ) + do + if [[ ${file##*.} == "rlib" ]]; then + base=$(basename $file .rlib) + file=$(dirname $file)/${base#"lib"}.ll + else + file=$(dirname $file)/$(basename $file .wasm).ll + fi + + input=coverage-input/$(basename $file) + cp $file $input + + perl -i -p0e 's/(^define.*?$).*?^}/$1\nstart:\n unreachable\n}/gms' $input + counter=1 + while (( counter != 0 )); do + counter=$(perl -i -p0e '$c+= s/(^(define|declare)(,? [^\n ]+)*),? range\(.*?\)/$1/gm; END{print "$c"}' $input) + done + + clang-18 $input -Wno-override-module -c -o coverage-output/$(basename $input .ll).o + done + - name: Merge Profile Data + run: + llvm-profdata-18 merge -sparse coverage-input/*.profraw -o + coverage-output/coverage.profdata + - name: Upload Test Coverage Artifact + uses: actions/upload-artifact@v4 + with: + name: test-coverage-${{ matrix.mt.id }} + path: coverage-output + retention-days: 1 + if-no-files-found: error + + collect-coverage: + name: Collect Test Coverage + + needs: coverage + + runs-on: ubuntu-24.04 + + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install LLVM v18 + run: sudo apt-get install llvm-18 + - name: Install `rustfilt` + uses: taiki-e/cache-cargo-install-action@v2 + with: + tool: rustfilt + - name: Download Test Coverage + uses: actions/download-artifact@v4 + with: + pattern: test-coverage-* + path: coverage-input + - name: Merge Profile Data + run: + llvm-profdata-18 merge -sparse coverage-input/**/coverage.profdata -o + coverage-input/coverage.profdata + - name: Export Code Coverage Report + run: | + mkdir coverage-output + objects=() + for file in $(ls coverage-input/**/*.o) + do + objects+=(-object $file) + done + llvm-cov-18 show -show-instantiations=false -Xdemangler=rustfilt -output-dir coverage-output -format=html -instr-profile=coverage-input/coverage.profdata ${objects[@]} -sources src + llvm-cov-18 export -format=lcov -skip-functions -instr-profile=coverage-input/coverage.profdata ${objects[@]} -sources src > coverage-output/coverage.lcov + llvm-cov-18 export -format=text -summary-only -instr-profile=coverage-input/coverage.profdata ${objects[@]} -sources src | \ + printf '{ "coverage": "%.2f%%" }' $(jq '.data[0].totals.functions.percent') > coverage-output/coverage.json + - name: Download Previous Coverage Report + run: wget https://daxpedda.github.io/wasm-worker/coverage/coverage.lcov + - name: Report Coverage in Job Summary + # See + uses: 06393993/lcov-reporter-action@24d48ff28930b87e67d0df34283153b04a76f166 + with: + lcov-file: coverage-output/coverage.lcov + lcov-base: coverage.lcov + filter-changed-files: true + title: Test Coverage + post-to: job-summary + - name: Upload Test Coverage Artifact + uses: actions/upload-artifact@v4 + with: + name: test-coverage + path: coverage-output + retention-days: 1 + if-no-files-found: error + + document: + name: Document + + runs-on: ubuntu-latest + + if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' + + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install Rust nightly + run: | + rustup toolchain install nightly --profile minimal --target wasm32-unknown-unknown + rustup default nightly + - name: Run Rustdoc + env: + RUSTDOCFLAGS: --crate-version main --cfg=docsrs + run: + cargo doc --no-deps -Z rustdoc-map -Z rustdoc-scrape-examples --target + wasm32-unknown-unknown --all-features + - name: Setup Pages + uses: actions/configure-pages@v5 + - name: Fix permissions + run: | + chmod -c -R +rX "target/wasm32-unknown-unknown/doc" | while read line; do + echo "::warning title=Invalid file permissions automatically fixed::$line" + done + - name: Upload + uses: actions/upload-artifact@v4 + with: + name: documentation + path: target/wasm32-unknown-unknown/doc + retention-days: 1 + if-no-files-found: error + + deploy: + name: Deploy + + needs: [collect-coverage, document] + + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }}doc/web_time + + runs-on: ubuntu-latest + + if: + github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.ref_name == + 'main') + + permissions: + contents: read + pages: write + id-token: write + + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Download Test Coverage + uses: actions/download-artifact@v4 + with: + name: test-coverage + path: page/coverage + - name: Download Documentation + uses: actions/download-artifact@v4 + with: + name: documentation + path: page/doc + - name: Upload Page Artifact + uses: actions/upload-pages-artifact@v3 + with: + path: page + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.github/workflows/documentation.yaml b/.github/workflows/documentation.yaml deleted file mode 100644 index fefb6ee..0000000 --- a/.github/workflows/documentation.yaml +++ /dev/null @@ -1,56 +0,0 @@ -name: Documentation - -on: - push: - branches: ["main"] - workflow_dispatch: - -concurrency: - group: "pages" - cancel-in-progress: true - -env: - CARGO_TERM_COLOR: always - -jobs: - document-deploy: - name: Document & Deploy - - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }}web_time - - runs-on: ubuntu-latest - - permissions: - contents: read - pages: write - id-token: write - - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Install Rust nightly - run: | - rustup toolchain install nightly --profile minimal --target wasm32-unknown-unknown - rustup default nightly - - name: Run Rustdoc - env: - RUSTDOCFLAGS: --crate-version main --cfg=docsrs - run: - cargo doc --no-deps -Z rustdoc-map -Z rustdoc-scrape-examples --target - wasm32-unknown-unknown --all-features - - name: Setup Pages - uses: actions/configure-pages@v5 - - name: Fix permissions - run: | - chmod -c -R +rX "target/wasm32-unknown-unknown/doc" | while read line; do - echo "::warning title=Invalid file permissions automatically fixed::$line" - done - - name: Upload artifact - uses: actions/upload-pages-artifact@v3 - with: - path: target/wasm32-unknown-unknown/doc - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v4 diff --git a/.github/workflows/merge.yaml b/.github/workflows/merge.yaml index 5b2be2f..cfe80cf 100644 --- a/.github/workflows/merge.yaml +++ b/.github/workflows/merge.yaml @@ -69,4 +69,4 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - gh workflow run Documentation -r ${{ fromJSON(steps.pr.outputs.base_ref).baseRefName }} + gh workflow run "Coverage & Documentation" -r ${{ fromJSON(steps.pr.outputs.base_ref).baseRefName }} diff --git a/README.md b/README.md index cd20280..aef2e66 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,8 @@ [![Crates.io Version](https://img.shields.io/crates/v/web-time.svg)](https://crates.io/crates/web-time) [![Live Build Status](https://img.shields.io/github/check-runs/daxpedda/web-time/main?label=CI)](https://github.com/daxpedda/web-time/actions?query=branch%3Amain) [![Docs.rs Documentation](https://img.shields.io/docsrs/web-time?label=docs.rs)](https://docs.rs/crate/web-time) -[![Main Documentation](https://img.shields.io/github/actions/workflow/status/daxpedda/web-time/documentation.yaml?branch=main&label=main%20docs)](https://daxpedda.github.io/web-time/web_time/index.html) +[![Main Documentation](https://img.shields.io/github/actions/workflow/status/daxpedda/web-time/coverage-documentation.yaml?branch=main&label=main%20docs)](https://daxpedda.github.io/web-time/doc/web_time) +[![Test Coverage](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fdaxpedda.github.io%2Fweb-time%2Fcoverage%2Fcoverage.json&query=%24.coverage&label=Test%20Coverage)](https://daxpedda.github.io/web-time/coverage) ## Description