https://github.com/andyholmes/actuary
An opinionated test runner for C projects
https://github.com/andyholmes/actuary
Last synced: 11 months ago
JSON representation
An opinionated test runner for C projects
- Host: GitHub
- URL: https://github.com/andyholmes/actuary
- Owner: andyholmes
- License: gpl-3.0
- Created: 2022-11-28T00:45:52.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2025-06-23T23:42:08.000Z (12 months ago)
- Last Synced: 2025-06-26T16:17:09.368Z (12 months ago)
- Language: Shell
- Size: 102 KB
- Stars: 0
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Actuary
**An opinionated test runner for C projects**
Actuary is a test runner and GitHub Action, specifically for programs written in
C that use the `meson` build system, with an emphasis on GLib-based projects.
It's common, and wise, to run tests under various conditions (e.g. [sanitizers])
and employ static analysis tools (e.g. [cppcheck]). Actuary is really just a
series of shell scripts that makes it simpler to run a set of suites, both in a
GitHub [job matrix] and on your local workstation.
Actuary includes a CI image and a `toolbox` image, with all required tools
pre-installed, intended to be used as base images for a project.
[sanitizers]: https://github.com/google/sanitizers
[cppcheck]: https://cppcheck.sourceforge.io/
[job matrix]: https://docs.github.com/actions/using-jobs/using-a-matrix-for-your-jobs
## Complete Example
```yml
name: Actuary
on:
pull_request:
branches:
- main
jobs:
test:
name: Tests
runs-on: ubuntu-latest
# See "Containers" below
container:
image: ghcr.io/${{ github.repository }}:${{ github.base_ref }}
# Setup a job matrix (compiler x suite), with inputs for each job
strategy:
matrix:
compiler: [gcc, llvm]
suite: [test, asan, tsan, analyzer]
include:
- suite: test
setup-args: -Dtests=true
test-args: --repeat=3
- suite: asan
setup-args: -Dtests=true
- suite: tsan
setup-args: -Dtests=true
- suite: analyzer
setup-args: -Dtests=false
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@v3
with:
submodules: true
# Run each test suite
- name: Test
id: test
uses: andyholmes/actuary@main
with:
suite: ${{ matrix.suite }}
compiler: ${{ matrix.compiler }}
setup-args: ${{ matrix.setup-args }}
test-args: ${{ matrix.test-args }}
# Enable coverage generation for one suite
test-coverage: ${{ matrix.compiler == 'gcc' && matrix.suite == 'test' }}
# Upload test log as an artifact
- name: Test Report
if: ${{ failure() }}
uses: actions/upload-artifact@v3
with:
name: Tests (${{ matrix.compiler }}, ${{ matrix.suite }})
path: ${{ steps.test.outputs.log }}
# Upload coverage HTML as an artifact
- name: Coverage (html)
if: ${{ matrix.compiler == 'gcc' && matrix.suite == 'test' }}
uses: actions/upload-artifact@v3
with:
name: Tests (coverage)
path: ${{ steps.test.outputs.coverage-html }}
```
## Configuration
Actuary is really intended to be used in a job matrix, so the two driving inputs
are `suite` and `compiler`.
| Name | Description |
|-------------------------|----------------------------------------------------|
| `suite` | Test suite (default: `test`) |
| `compiler` | Compiler (default: system) |
The `suite` input determines which test suite will be run. Additional suites can
be added to `/usr/share/actuary/suites/`.
The `compiler` input determines which compiler to use. Actuary includes two
presets (`gcc` and `llvm`), but will fallback to the system default if not set.
### test
Standard `meson test` runner.
This suite, and suites based on it, respect the following inputs:
| Input | Description |
|-------------------------|----------------------------------------------------|
| `setup-args` | Options for `meson setup` |
| `test-args` | Options for `meson test` |
| `test-coverage` | Enable or disable coverage generation |
| `lcov-include` | Path glob of directories to include in coverage |
| `lcov-exclude` | Path glob of directories to exclude from coverage |
The `setup-args` input is passed to `meson setup`, overriding any default
arguments or options.
The `test-args` input is passed to `meson test`, overriding any default
arguments or options.
The `test-coverage` input enables coverage generation with [LCOV], and will
result in an LCOV `.info` file and an HTML report.
This suite, and suites based on it, generate the following outputs:
| Output | Description |
|-------------------------|----------------------------------------------------|
| `log` | Path to `testlog.txt` file (`meson test`) |
| `coverage` | Path to `coverage.info` file (LCOV) |
| `coverage-html` | Path to `coverage-html` directory (HTML) |
[lcov]: https://github.com/linux-test-project/lcov
### asan
Run tests with AddressSanitizer.
This suite is based on the [`test` suite](#test) and will respect any inputs it
accepts.
### tsan
Run tests with ThreadSanitizer.
This suite is based on the [`test` suite](#test) and will respect any inputs it
accepts.
### analyzer
Run the compiler's static analysis tool (e.g. LLVM scan-build).
This suite is not based on the `test` suite, but will respect the `setup-args`
input.
This suite generates the following outputs:
| Output | Description |
|-------------------------|----------------------------------------------------|
| `log` | Path to logfile |
### abidiff
Test for API breakage in changes.
This suite respects the following inputs:
| Input | Description |
|-------------------------|----------------------------------------------------|
| `setup-args` | Options for `meson setup` |
| `abidiff-args` | Options for `abidiff` |
| `abidiff-lib` | Shared Object (e.g. `libfoobar-1.0.so`) |
This suite is will respect the `setup-args` input.
This suite generates the following outputs:
| Output | Description |
|-------------------------|----------------------------------------------------|
| `log` | Path to logfile |
### cppcheck
Run cppcheck static analyzer
This suite respects the following inputs:
| Input | Description |
|-------------------------|----------------------------------------------------|
| `cppcheck-args` | Options for `cppcheck` |
| `cppcheck-path` | Path to the source directory |
## Containers
Actuary provides containers with pre-installed packages for the included suites
and a companion `toolbox` image for local development.
| Image Name | Notes |
|-------------------------|----------------------------------------------------|
| `actuary` | |
| `actuary-toolbox` | Includes `gdb` |
Most projects will want to include additional build dependencies, which can be
done by adding a stage on top of Actuary's base images:
```dockerfile
FROM ghcr.io/andyholmes/actuary:latest
RUN dnf install -y --enablerepo=fedora-debuginfo,updates-debuginfo \
gi-docgen graphviz \
glib2-devel glib2-debuginfo \
gtk4-devel gtk4-debuginfo \
libadwaita-devel libadwaita-debuginfo && \
dnf clean all && rm -rf /var/cache/dnf
```
You can copy-paste the [`cr.yml`][cr] workflow from Actuary to build and push
the image to your project's container registry. Then use your project's CI image
with Actuary:
```yml
name: Continuous Integration
on:
pull_request:
jobs:
actuary:
name: Actuary
runs-on: ubuntu-latest
container:
image: ghcr.io/username/project:latest
steps:
- name: Test
uses: andyholmes/actuary@main
with:
suite: test
setup-args: -Dtests=true
```
[cr]: https://github.com/andyholmes/actuary/blob/main/.github/workflows/cr.yml