diff --git a/Makefile b/Makefile index e177fef95..78c1691fb 100644 --- a/Makefile +++ b/Makefile @@ -58,6 +58,17 @@ build: @$(SWIFT) --version @$(SWIFT) build -c $(BUILD_CONFIGURATION) $(SWIFT_CONFIGURATION) +.PHONY: coverage-build +coverage-build: + @echo Building container binaries with coverage instrumentation... + @$(SWIFT) --version + @$(SWIFT) build -c $(BUILD_CONFIGURATION) $(SWIFT_CONFIGURATION) --enable-code-coverage + +.PHONY: coverage-all +coverage-all: coverage-build + @"$(MAKE)" BUILD_CONFIGURATION=$(BUILD_CONFIGURATION) DEST_DIR="$(ROOT_DIR)/" SUDO= install + @"$(MAKE)" init-block + .PHONY: cli cli: @echo Building container CLI... @@ -160,6 +171,15 @@ COV_DATA_DIR = $(shell $(SWIFT) test --show-coverage-path | xargs dirname) COV_REPORT_FILE = $(ROOT_DIR)/code-coverage-report COVERAGE_OUTPUT_DIR := $(ROOT_DIR)/coverage-reports TEST_BINARY = $(BUILD_BIN_DIR)/containerPackageTests.xctest/Contents/MacOS/containerPackageTests +# All product binaries that may be instrumented for coverage. +# Used as additional -object args to llvm-cov for integration/combined reports. +COV_BINARIES := \ + $(BUILD_BIN_DIR)/container \ + $(BUILD_BIN_DIR)/container-apiserver \ + $(BUILD_BIN_DIR)/container-runtime-linux \ + $(BUILD_BIN_DIR)/container-network-vmnet \ + $(BUILD_BIN_DIR)/container-core-images +COV_OBJECT_FLAGS := $(patsubst %,-object %,$(COV_BINARIES)) # Set of files we do not want to get caught in the coverage generation LLVM_COV_IGNORE := \ --ignore-filename-regex=".build/" \ @@ -168,19 +188,19 @@ LLVM_COV_IGNORE := \ --ignore-filename-regex=".grpc.swift" # Generate JSON + HTML coverage reports and a coverage-percent.txt from a profdata file. -# $(1) = profdata path, $(2) = tier name (unit/integration/combined) +# $(1) = profdata path, $(2) = tier name (unit/integration/combined), $(3) = additional -object flags (optional) define GENERATE_COV_REPORTS @echo Exporting $(2) coverage JSON... @xcrun llvm-cov export --compilation-dir=`pwd` \ -instr-profile=$(1) \ $(LLVM_COV_IGNORE) \ - $(TEST_BINARY) > $(COVERAGE_OUTPUT_DIR)/$(2)/coverage-summary.json + $(TEST_BINARY) $(3) > $(COVERAGE_OUTPUT_DIR)/$(2)/coverage-summary.json @echo Generating $(2) coverage HTML report... @xcrun llvm-cov show --compilation-dir=`pwd` --format=html \ -instr-profile=$(1) \ $(LLVM_COV_IGNORE) \ -output-dir=$(COVERAGE_OUTPUT_DIR)/$(2)/html \ - $(TEST_BINARY) + $(TEST_BINARY) $(3) @echo Extracting $(2) coverage percentages... @jq -r '"line coverage: \(.data[0].totals.lines.percent | . * 100 | round | . / 100)%\nfunction coverage: \(.data[0].totals.functions.percent | . * 100 | round | . / 100)%"' \ $(COVERAGE_OUTPUT_DIR)/$(2)/coverage-summary.json > $(COVERAGE_OUTPUT_DIR)/$(2)/coverage-percent.txt @@ -231,7 +251,7 @@ coverage: coverage-build coverage-unit coverage-integration $(COVERAGE_OUTPUT_DIR)/unit/default.profdata \ $(COVERAGE_OUTPUT_DIR)/integration/default.profdata \ -o $(COVERAGE_OUTPUT_DIR)/combined/default.profdata - $(call GENERATE_COV_REPORTS,$(COVERAGE_OUTPUT_DIR)/combined/default.profdata,combined) + $(call GENERATE_COV_REPORTS,$(COVERAGE_OUTPUT_DIR)/combined/default.profdata,combined,$(COV_OBJECT_FLAGS)) .PHONY: coverage-unit coverage-unit: @@ -244,13 +264,14 @@ coverage-unit: $(call GENERATE_COV_REPORTS,$(COVERAGE_OUTPUT_DIR)/unit/default.profdata,unit) .PHONY: coverage-integration -coverage-integration: all +coverage-integration: coverage-all @echo Ensuring apiserver stopped before the coverage integration tests... @bin/container system stop && sleep 3 && scripts/ensure-container-stopped.sh @echo Running integration test coverage... @rm -f $(COV_DATA_DIR)/*.profraw @mkdir -p $(COVERAGE_OUTPUT_DIR)/integration - @bin/container --debug system start --timeout 60 $(SYSTEM_START_OPTS) && \ + @LLVM_PROFILE_FILE=$(COVERAGE_OUTPUT_DIR)/integration/%p-%m%c.profraw \ + bin/container --debug system start --timeout 60 $(SYSTEM_START_OPTS) && \ echo "Starting CLI integration tests with coverage" && \ { \ export CLITEST_LOG_ROOT=$(LOG_ROOT) ; \ @@ -263,7 +284,7 @@ coverage-integration: all } @echo Merging integration coverage profdata... @xcrun llvm-profdata merge -sparse $(COVERAGE_OUTPUT_DIR)/integration/*.profraw -o $(COVERAGE_OUTPUT_DIR)/integration/default.profdata - $(call GENERATE_COV_REPORTS,$(COVERAGE_OUTPUT_DIR)/integration/default.profdata,integration) + $(call GENERATE_COV_REPORTS,$(COVERAGE_OUTPUT_DIR)/integration/default.profdata,integration,$(COV_OBJECT_FLAGS)) .PHONY: integration integration: init-block diff --git a/Sources/ContainerPlugin/PluginLoader.swift b/Sources/ContainerPlugin/PluginLoader.swift index 0c156a5a0..38eeefc2b 100644 --- a/Sources/ContainerPlugin/PluginLoader.swift +++ b/Sources/ContainerPlugin/PluginLoader.swift @@ -205,6 +205,8 @@ extension PluginLoader { "http_proxy", "HTTP_PROXY", "https_proxy", "HTTPS_PROXY", "no_proxy", "NO_PROXY", + // Allows LLVM coverage profiling data to be written by launchd-managed helper processes. + "LLVM_PROFILE_FILE", ]) public func registerWithLaunchd(