Skip to content

0.4.0: the argument vector is passed unaltered, and the suite observe… #8

0.4.0: the argument vector is passed unaltered, and the suite observe…

0.4.0: the argument vector is passed unaltered, and the suite observe… #8

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
jobs:
build:
name: conformance
runs-on: ubuntu-24.04
timeout-minutes: 30
env:
# A version verified to build this package, not a measured minimum. The
# package uses modules, exported extern "C" declarations and ordinary
# dependencies, none of which is recent; the pin exists for reproducibility
# rather than because an older mcpp is known to fail.
MCPP_VERSION: 2026.8.19.4
XLINGS_VERSION: v2026.8.17.2
XLINGS_NON_INTERACTIVE: '1'
steps:
- uses: actions/checkout@v4
- name: Install xlings
run: |
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh \
| bash -s "$XLINGS_VERSION"
echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH"
- name: Install mcpp
run: |
xlings update
xlings install "mcpp@$MCPP_VERSION" -y -g
mcpp --version
mcpp self config --mirror GLOBAL
# The version of the specification this implementation is written against
# is stated once, in the manifest, and read from there. Stating it a second
# time in this file is what allowed the two to drift: the manifest moved to
# 0.3.0 and this file compared against the 0.2.0 surface, so four names
# this implementation is required to export were reported as unspecified.
- name: Read the specification version from the manifest
run: |
v="$(sed -n 's/^openkal[[:space:]]*=[[:space:]]*"\([^"]*\)".*/\1/p' mcpp.toml | head -1)"
test -n "$v" || { echo "the manifest does not name openkal" >&2; exit 1; }
echo "OPENKAL_VERSION=$v" >> "$GITHUB_ENV"
echo "written against openkal $v"
- name: Conformance
run: |
mcpp test 2>&1 | tee conformance.log
# A suite that discovered nothing reports success, so every suite is
# asserted to have run. The list is derived from the files present
# rather than written out here: a hand-written list names the suites
# that existed when it was written, and a suite added afterwards
# escapes the assertion silently. This assertion named two of five.
missing=0
for f in tests/*.cpp; do
name="$(basename "$f" .cpp)"
if ! grep -q "^$name \.\.\. ok" conformance.log; then
echo "suite did not run, or did not pass: $name" >&2
missing=1
fi
done
test "$missing" -eq 0
- name: The specification, at the version the manifest names
uses: actions/checkout@v4
with:
repository: mcpplibs/openkal
ref: ${{ env.OPENKAL_VERSION }}
path: .spec
- name: The exported surface matches the specification
run: |
# Clause 9.3. The list and the checker come from the specification
# itself rather than from a copy kept here, so that the comparison has
# one source. --complete because this implementation claims every
# interface: a name it fails to export is a failure, not an interface
# it declines to provide.
bash .spec/tools/check-surface.sh --complete .spec/SURFACE.txt \
$(find target -name '*.o' | tr '\n' ' ')
# The program is taken from the specification rather than copied here. A
# copy in each implementation is a copy that can diverge, and the value of
# the program is precisely that every implementation runs the same one.
#
# The manifest is written here because naming the implementation is the
# manifest's job and not the program's, which is the arrangement the
# program exists to demonstrate.
- name: The portable program runs
run: |
sed -i 's|^openkal = ".*"$|openkal = { path = ".spec" }|' mcpp.toml
cat > .spec/examples/portable/mcpp.toml <<'TOML'
[package]
name = "portable"
version = "0.1.0"
[dependencies]
openkal = { path = "../.." }
openkal-linux = { path = "../../.." }
TOML
cd .spec/examples/portable
mcpp run 2>&1 | tee run.log
# Both directions: that the program reported, and that nothing it
# observed failed to hold. Asserting only the first would pass for a
# program that printed its failures.
grep -q 'openkal: the portable program, above eight interfaces' run.log
grep -q 'openkal: observations that did not hold: 0' run.log
! grep -q 'NOT HELD' run.log