-
Notifications
You must be signed in to change notification settings - Fork 1
231 lines (207 loc) · 9.04 KB
/
Copy pathunit-tests-cpp.yml
File metadata and controls
231 lines (207 loc) · 9.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# =============================================================================
# C++ Unit Tests with Coverage Workflow for Axon
# =============================================================================
# Runs unit tests with coverage for standalone C++ libraries:
# - axon_mcap
# - axon_uploader
# - axon_logging
#
# These libraries don't require ROS and can run in a simpler environment.
# Coverage is uploaded to Codecov with the "cpp" flag.
# =============================================================================
name: C++ Unit Tests
on:
# Called by ci.yml orchestrator
workflow_call:
# Allow standalone runs
workflow_dispatch:
jobs:
# ===========================================================================
# Run unit tests with coverage for each library in PARALLEL
# ===========================================================================
cpp-unit-tests:
name: ${{ matrix.library }}
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
include:
- library: axon_mcap
cmake_flag: AXON_MCAP
extra_packages: ""
needs_aws_sdk: false
- library: axon_uploader
cmake_flag: AXON_UPLOADER
extra_packages: "libsqlite3-dev libcurl4-openssl-dev"
needs_aws_sdk: true
- library: axon_logging
cmake_flag: AXON_LOGGING
extra_packages: ""
needs_aws_sdk: false
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Cache apt packages
uses: awalsh128/cache-apt-pkgs-action@latest
with:
packages: build-essential cmake pkg-config ccache libgtest-dev libgmock-dev libyaml-cpp-dev liblz4-dev libzstd-dev libre2-dev libturbojpeg0-dev libboost-dev libboost-system-dev libboost-log-dev libboost-thread-dev libboost-filesystem-dev libcurl4-openssl-dev libssl-dev lcov
version: 1.1
- name: Install extra packages for ${{ matrix.library }}
if: matrix.extra_packages != ''
run: |
sudo apt-get update
sudo apt-get install -y ${{ matrix.extra_packages }}
# =========================================================================
# AWS SDK for C++ (built from source - no apt packages available)
# =========================================================================
- name: Cache AWS SDK
if: matrix.needs_aws_sdk
uses: actions/cache@v4
id: aws-sdk-cache
with:
path: ~/aws-sdk-cpp-install
key: aws-sdk-cpp-1.11.458-ubuntu22-s3-transfer-v1
- name: Build AWS SDK from source
if: matrix.needs_aws_sdk && steps.aws-sdk-cache.outputs.cache-hit != 'true'
run: |
echo "Building AWS SDK from source (this will be cached for future runs)..."
git clone --recurse-submodules --depth 1 --branch 1.11.458 \
https://github.com/aws/aws-sdk-cpp.git ~/aws-sdk-cpp-src
cd ~/aws-sdk-cpp-src
cmake -B build \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=~/aws-sdk-cpp-install \
-DBUILD_ONLY="s3;transfer" \
-DENABLE_TESTING=OFF \
-DAUTORUN_UNIT_TESTS=OFF \
-DBUILD_SHARED_LIBS=ON
cmake --build build -j$(nproc)
cmake --install build
# Cleanup source to save space
rm -rf ~/aws-sdk-cpp-src
- name: Cache ccache
uses: actions/cache@v4
with:
path: ~/.ccache
key: ccache-coverage-${{ matrix.library }}-${{ runner.os }}-${{ hashFiles('core/**/*.cpp', 'core/**/*.hpp') }}
restore-keys: |
ccache-coverage-${{ matrix.library }}-${{ runner.os }}-
ccache-cpp-${{ runner.os }}-
- name: Configure ccache
run: |
ccache --set-config=max_size=500M
ccache --set-config=compression=true
ccache -z
- name: Build GTest from source
run: |
if [ -d /usr/src/googletest ]; then
cd /usr/src/googletest
sudo cmake -B build
sudo cmake --build build
sudo cmake --install build
fi
- name: Build and test with coverage
run: |
# Set ccache for faster builds
export CCACHE_DIR=~/.ccache
ccache -z
# Build with make
if [ "${{ matrix.library }}" = "axon_uploader" ]; then
make build-uploader \
BUILD_TYPE=Debug \
AXON_ENABLE_COVERAGE=ON \
AXON_BUILD_UPLOADER=ON \
CMAKE_PREFIX_PATH=~/aws-sdk-cpp-install
elif [ "${{ matrix.library }}" = "axon_mcap" ]; then
make build-mcap \
BUILD_TYPE=Debug \
AXON_ENABLE_COVERAGE=ON
elif [ "${{ matrix.library }}" = "axon_logging" ]; then
make build-logging \
BUILD_TYPE=Debug \
AXON_ENABLE_COVERAGE=ON
fi
# Run tests
if [ "${{ matrix.library }}" = "axon_uploader" ]; then
cd build/axon_uploader && ctest --output-on-failure
elif [ "${{ matrix.library }}" = "axon_mcap" ]; then
cd build/axon_mcap && ctest --output-on-failure
elif [ "${{ matrix.library }}" = "axon_logging" ]; then
cd build/axon_logging && ctest --output-on-failure
fi
ccache -s
- name: Generate coverage report
run: |
if [ "${{ matrix.library }}" = "axon_uploader" ]; then
cd build/axon_uploader
elif [ "${{ matrix.library }}" = "axon_mcap" ]; then
cd build/axon_mcap
elif [ "${{ matrix.library }}" = "axon_logging" ]; then
cd build/axon_logging
fi
# Detect lcov version for compatibility flags
LCOV_VERSION=$(lcov --version 2>&1 | grep -oP 'LCOV version \K[0-9.]+' || echo "1.0")
LCOV_MAJOR=$(echo "${LCOV_VERSION}" | cut -d. -f1)
echo "lcov version: ${LCOV_VERSION}"
# Error types to ignore (lcov 2.0+):
# mismatch - mismatched exception tags (C++ std lib differences)
# unused - unused coverage data
# negative - negative branch counts (compiler/gcov compatibility issue)
# gcov - unexecuted blocks on non-branch lines
LCOV_IGNORE_FLAGS=""
if [ "${LCOV_MAJOR}" -ge 2 ]; then
LCOV_IGNORE_FLAGS="--ignore-errors mismatch,unused,negative,gcov"
fi
# Generate coverage (filtering only - path normalization done in merge step)
lcov --capture --directory . --output-file coverage_raw.info \
--rc lcov_branch_coverage=1 ${LCOV_IGNORE_FLAGS} || {
echo "Warning: lcov capture had issues, trying with more permissive flags..."
if [ "${LCOV_MAJOR}" -ge 2 ]; then
lcov --capture --directory . --output-file coverage_raw.info \
--rc lcov_branch_coverage=1 --ignore-errors mismatch,unused,negative,gcov,source || true
else
lcov --capture --directory . --output-file coverage_raw.info \
--rc lcov_branch_coverage=1 || true
fi
}
lcov --remove coverage_raw.info \
'/usr/*' '/opt/*' '*/_deps/*' '*/test/*' '*/c++/*' \
--output-file coverage.info --rc lcov_branch_coverage=1 ${LCOV_IGNORE_FLAGS} || {
echo "Warning: lcov filtering had issues, using raw coverage..."
cp coverage_raw.info coverage.info
}
# Debug: show sample paths before normalization
echo "Sample paths in coverage file (before normalization):"
grep "^SF:" coverage.info | head -5 || true
- name: Normalize coverage paths
run: |
cd build/${{ matrix.library }}
chmod +x ${{ github.workspace }}/.github/scripts/normalize_coverage_paths.sh
${{ github.workspace }}/.github/scripts/normalize_coverage_paths.sh coverage.info
echo "Sample paths after normalization:"
grep "^SF:" coverage.info | head -5 || true
- name: Copy coverage to root for artifact upload
run: cp build/${{ matrix.library }}/coverage.info coverage.info
- name: Upload coverage to Codecov with flag
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: coverage.info
flags: cpp-unit
name: cpp-unit-${{ matrix.library }}
fail_ci_if_error: false
verbose: true
disable_search: true
disable_file_fixes: true
override_commit: ${{ github.event.pull_request.head.sha || github.sha }}
override_branch: ${{ github.head_ref || github.ref_name }}
override_build: ${{ github.run_id }}
override_pr: ${{ github.event.pull_request.number }}
- name: Upload coverage artifact
uses: actions/upload-artifact@v4
with:
name: coverage-cpp-${{ matrix.library }}
path: coverage.info
retention-days: 7