From 5331d044c4c1e04a540a58f64f90590f9c19bb5f Mon Sep 17 00:00:00 2001 From: jackctj117 Date: Thu, 2 Oct 2025 15:58:13 -0600 Subject: [PATCH 1/5] Addition of code coverage feature --- .gitignore | 5 ++++ test/Makefile | 31 ++++++++++++++++++++-- test/README.md | 64 +++++++++++++++++++++++++++++++++++++++++++++ wolfhsm/wh_client.h | 6 ++--- wolfhsm/wh_server.h | 6 +---- 5 files changed, 102 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 6b0bb108c..37f572851 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,8 @@ compile_commands.json tools/static-analysis/reports/ *.xml *.html + +# Code coverage +*.gcda +*.gcno +coverage/ diff --git a/test/Makefile b/test/Makefile index 051212dcb..2f7fb7749 100644 --- a/test/Makefile +++ b/test/Makefile @@ -77,6 +77,12 @@ ifeq ($(ASAN),1) LDFLAGS += -fsanitize=address endif +# Add code coverage option +ifeq ($(COVERAGE),1) + CFLAGS += --coverage + LDFLAGS += --coverage +endif + ## wolfSSL defines ifeq ($(DEBUG_WOLFSSL),1) DEF += -DDEBUG_WOLFSSL @@ -190,7 +196,7 @@ vpath %.s $(dir $(SRC_ASM)) ## Makefile Targets -.PHONY: build_app build_hex build_static clean run +.PHONY: build_app build_hex build_static clean run coverage build_app: $(BUILD_DIR) $(BUILD_DIR)/$(BIN).elf @echo Build complete. @@ -238,7 +244,9 @@ clean: $(BUILD_DIR)/*.o \ $(BUILD_DIR)/*.a \ $(BUILD_DIR)/*.sym \ - $(BUILD_DIR)/*.disasm + $(BUILD_DIR)/*.disasm \ + $(BUILD_DIR)/*.gcda \ + $(BUILD_DIR)/*.gcno # No prereq's here to stop from rebuilding with different options run: @@ -247,3 +255,22 @@ ifeq (,$(wildcard $(BUILD_DIR)/$(BIN).elf)) else $(BUILD_DIR)/$(BIN).elf endif + +# Coverage target: build with coverage, run tests, and generate report +coverage: + @echo "Building with coverage enabled..." + $(MAKE) clean + $(MAKE) COVERAGE=1 DEBUG=1 + @echo "Running tests..." + @if [ ! -f $(BUILD_DIR)/$(BIN).elf ]; then \ + echo "Error: $(BUILD_DIR)/$(BIN).elf not found. Build failed."; \ + exit 1; \ + fi + $(BUILD_DIR)/$(BIN).elf + @echo "Generating coverage report..." + gcovr --root .. \ + --filter 'src/.*' \ + --filter 'wolfhsm/.*' \ + --html-details $(BUILD_DIR)/coverage.html \ + --print-summary + @echo "Coverage report generated at $(BUILD_DIR)/coverage.html" diff --git a/test/README.md b/test/README.md index 4d1e56a6d..4fea8b979 100644 --- a/test/README.md +++ b/test/README.md @@ -97,3 +97,67 @@ IMG_MGR ECC P256 Test completed successfully! IMG_MGR AES128 CMAC Test completed successfully! IMG_MGR RSA2048 Test completed successfully! ``` + +## Code Coverage + +The test suite supports code coverage analysis using gcovr. To generate coverage reports: + +**Note**: The coverage directory must exist before generating reports. The `make coverage` target creates this automatically, but if running gcovr manually, create it first with: +```bash +mkdir -p ../coverage +``` + +### Running Coverage + +Use the convenient coverage target: +```bash +make coverage +``` + +This will: +1. Clean previous build artifacts +2. Rebuild with coverage instrumentation enabled +3. Run the test suite +4. Generate an HTML coverage report + +The coverage report will be generated at `../coverage/index.html`. + +### Manual Coverage Workflow + +Alternatively, you can run coverage manually: + +```bash +# Build with coverage enabled +make clean +make COVERAGE=1 DEBUG=1 + +# Run tests +make run + +# Create coverage directory and generate report (from repository root) +cd .. +mkdir -p coverage +gcovr --root . \ + --filter 'src/.*' \ + --filter 'wolfhsm/.*' \ + --html-details coverage/index.html \ + --print-summary +``` + +### Coverage Options + +You can customize the coverage report generation: + +```bash +# Generate XML format (for CI/CD) +gcovr --root . --filter 'src/.*' --filter 'wolfhsm/.*' --xml coverage.xml + +# Generate JSON format +gcovr --root . --filter 'src/.*' --filter 'wolfhsm/.*' --json coverage.json + +# Include branch coverage +gcovr --root . --filter 'src/.*' --filter 'wolfhsm/.*' --branches --print-summary + +# Set minimum coverage threshold (fails if below 80%) +gcovr --root . --filter 'src/.*' --filter 'wolfhsm/.*' --fail-under-line 80 +``` diff --git a/wolfhsm/wh_client.h b/wolfhsm/wh_client.h index 786f15732..f8b3897a2 100644 --- a/wolfhsm/wh_client.h +++ b/wolfhsm/wh_client.h @@ -1047,9 +1047,9 @@ int wh_Client_KeyUnwrapAndCacheRequest(whClientContext* ctx, * key. * @return int Returns 0 on success, or a negative error code on failure. */ -int wh_Client_UnrapKeyAndCacheResponse(whClientContext* ctx, - enum wc_CipherType cipherType, - uint16_t* keyIdOut); +int wh_Client_KeyUnwrapAndCacheResponse(whClientContext* ctx, + enum wc_CipherType cipherType, + uint16_t* keyIdOut); /* Counter functions */ int wh_Client_CounterInitRequest(whClientContext* c, whNvmId counterId, diff --git a/wolfhsm/wh_server.h b/wolfhsm/wh_server.h index ab67bbf56..664fcd993 100644 --- a/wolfhsm/wh_server.h +++ b/wolfhsm/wh_server.h @@ -120,12 +120,8 @@ typedef whDmaOper whServerDmaOper; typedef whDmaFlags whServerDmaFlags; typedef whDmaAddr whServerDmaAddr; typedef whDmaAddrList whServerDmaAddrList; - #ifdef WOLFHSM_CFG_DMA_CUSTOM_CLIENT_COPY -typedef enum { - WH_DMA_COPY_OPER_CLIENT_READ = 0, - WH_DMA_COPY_OPER_CLIENT_WRITE = 1, -} whServerDmaCopyOper; +typedef whDmaCopyOper whServerDmaCopyOper; #endif /* WOLFHSM_CFG_DMA_CUSTOM_CLIENT_COPY */ /* DMA callbacks invoked internally by wolfHSM before and after every client From bf81f24bf179f71c7bd2a5159e717a6ea723b364 Mon Sep 17 00:00:00 2001 From: jackctj117 Date: Thu, 9 Oct 2025 14:36:17 -0600 Subject: [PATCH 2/5] Allow passing of arguments after coverage --- test/Makefile | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/test/Makefile b/test/Makefile index 2f7fb7749..065978532 100644 --- a/test/Makefile +++ b/test/Makefile @@ -260,7 +260,7 @@ endif coverage: @echo "Building with coverage enabled..." $(MAKE) clean - $(MAKE) COVERAGE=1 DEBUG=1 + $(MAKE) COVERAGE=1 $(filter-out coverage,$(MAKECMDGOALS)) @echo "Running tests..." @if [ ! -f $(BUILD_DIR)/$(BIN).elf ]; then \ echo "Error: $(BUILD_DIR)/$(BIN).elf not found. Build failed."; \ @@ -268,9 +268,13 @@ coverage: fi $(BUILD_DIR)/$(BIN).elf @echo "Generating coverage report..." - gcovr --root .. \ + cd .. && mkdir -p coverage && gcovr --root . \ --filter 'src/.*' \ --filter 'wolfhsm/.*' \ - --html-details $(BUILD_DIR)/coverage.html \ + --html-details coverage/index.html \ --print-summary - @echo "Coverage report generated at $(BUILD_DIR)/coverage.html" + @echo "Coverage report generated at ../coverage/index.html" + +# Prevent make from trying to build these as targets +%: + @: From 6c8bae9cc35b656df2eea63feb3dba1e1902ab49 Mon Sep 17 00:00:00 2001 From: jackctj117 Date: Fri, 10 Oct 2025 14:42:52 -0600 Subject: [PATCH 3/5] Compatibility for gcov 11.4 and up --- test/Makefile | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/Makefile b/test/Makefile index 065978532..8201f1510 100644 --- a/test/Makefile +++ b/test/Makefile @@ -260,7 +260,7 @@ endif coverage: @echo "Building with coverage enabled..." $(MAKE) clean - $(MAKE) COVERAGE=1 $(filter-out coverage,$(MAKECMDGOALS)) + $(MAKE) COVERAGE=1 build_app @echo "Running tests..." @if [ ! -f $(BUILD_DIR)/$(BIN).elf ]; then \ echo "Error: $(BUILD_DIR)/$(BIN).elf not found. Build failed."; \ @@ -268,10 +268,12 @@ coverage: fi $(BUILD_DIR)/$(BIN).elf @echo "Generating coverage report..." - cd .. && mkdir -p coverage && gcovr --root . \ - --filter 'src/.*' \ - --filter 'wolfhsm/.*' \ - --html-details coverage/index.html \ + mkdir -p ../coverage && gcovr Build \ + --root .. \ + --gcov-executable gcov \ + --filter '\.\./src/.*' \ + --filter '\.\./wolfhsm/.*' \ + --html-details ../coverage/index.html \ --print-summary @echo "Coverage report generated at ../coverage/index.html" From 7cd533e7703543dc0e35bc95e10e17a595670ca8 Mon Sep 17 00:00:00 2001 From: jackctj117 Date: Fri, 10 Oct 2025 14:46:02 -0600 Subject: [PATCH 4/5] Allow to pass in arguments after coverage --- test/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/Makefile b/test/Makefile index 8201f1510..25b40cf88 100644 --- a/test/Makefile +++ b/test/Makefile @@ -260,7 +260,8 @@ endif coverage: @echo "Building with coverage enabled..." $(MAKE) clean - $(MAKE) COVERAGE=1 build_app + $(eval COVERAGE_TARGETS := $(filter-out coverage,$(MAKECMDGOALS))) + $(MAKE) COVERAGE=1 $(if $(COVERAGE_TARGETS),$(COVERAGE_TARGETS),build_app) @echo "Running tests..." @if [ ! -f $(BUILD_DIR)/$(BIN).elf ]; then \ echo "Error: $(BUILD_DIR)/$(BIN).elf not found. Build failed."; \ From cf3384e426405176385a3acd4dd40cfe8d0df14e Mon Sep 17 00:00:00 2001 From: jackctj117 Date: Fri, 10 Oct 2025 15:14:27 -0600 Subject: [PATCH 5/5] added code coverage to github actions --- .github/workflows/code-coverage.yml | 53 +++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 .github/workflows/code-coverage.yml diff --git a/.github/workflows/code-coverage.yml b/.github/workflows/code-coverage.yml new file mode 100644 index 000000000..0b9037c4d --- /dev/null +++ b/.github/workflows/code-coverage.yml @@ -0,0 +1,53 @@ +name: Code Coverage + +on: + push: + branches: [ 'master', 'main', 'release/**' ] + pull_request: + branches: [ '*' ] + +jobs: + coverage: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + # List compiler version + - name: List compiler and gcov version + run: | + gcc --version + gcov --version + + # Install gcovr for coverage report generation + - name: Install gcovr + run: | + sudo apt-get update + sudo apt-get install -y gcovr + + # Checkout wolfssl + - name: Checkout wolfssl + uses: actions/checkout@v4 + with: + repository: wolfssl/wolfssl + path: wolfssl + + # Run coverage + - name: Build and run tests with coverage + run: cd test && make coverage WOLFSSL_DIR=../wolfssl + + # Display coverage summary in the action log + - name: Display coverage summary + run: | + echo "=== Coverage Summary ===" + cd test + gcovr Build --root .. --filter '\.\./src/.*' --filter '\.\./wolfhsm/.*' --print-summary + + # Upload coverage report as artifact + - name: Upload coverage report + uses: actions/upload-artifact@v4 + with: + name: coverage-report + path: coverage/ + retention-days: 30 +