Skip to content

test(family): check that a clocked part's reset chains #85

test(family): check that a clocked part's reset chains

test(family): check that a clocked part's reset chains #85

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
env:
PYTHON_VERSION: "3.12"
jobs:
lint:
name: Format and lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install ruff
run: pipx install ruff==0.16.3
- name: Check formatting
run: ruff format --check .
- name: Lint
run: ruff check --output-format=github .
- uses: pnpm/action-setup@v6
- uses: actions/setup-node@v7
with:
node-version: 22
cache: pnpm
- name: Install the formatter
run: pnpm install --frozen-lockfile --ignore-scripts
- name: Check that every JSON file is formatted
run: pnpm run format:check
# The workflows are the one thing here nothing else checks, and a mistake
# in them is only visible once a run has already gone wrong. The archive
# is verified by digest before anything in it runs, for the same reason
# every image this project loads is.
- name: Check the workflows themselves
run: |
curl -fsSL -o actionlint.tar.gz \
"https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz"
echo "${ACTIONLINT_SHA256} actionlint.tar.gz" | sha256sum -c -
tar -xzf actionlint.tar.gz actionlint
./actionlint -color
rm -f actionlint actionlint.tar.gz
shell: bash
env:
ACTIONLINT_VERSION: "1.7.12"
ACTIONLINT_SHA256: "8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8"
types:
name: Types
runs-on: ubuntu-latest
steps:
# The processor is reached through a submodule, and the checker follows the
# import to type it. Without the checkout it would report the whole backend
# as missing rather than as wrong, which is a different and useless answer.
- uses: actions/checkout@v7
with:
submodules: recursive
- uses: actions/setup-python@v7
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install the type checker
run: pipx install mypy==1.14.1
# Strict, with every optional error class the version offers turned on. The
# settings live in pyproject.toml so a local run and this one agree; a gate
# that only holds in CI teaches people to push and find out.
- name: Every annotation has to hold
run: mypy
test:
name: Tests on Python ${{ matrix.python }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python: ["3.12", "3.13", "3.14"]
steps:
# The package reaches the processor through this submodule, and without it
# the microcode backend cannot be built at all. Checking it out here does
# not supply any firmware, so the runner still exercises the path a user
# without an image takes.
- uses: actions/checkout@v7
with:
submodules: recursive
- uses: actions/setup-python@v7
with:
python-version: ${{ matrix.python }}
- name: Install coverage
run: python -m pip install --disable-pip-version-check coverage==7.6.10
- name: Run every test file, under coverage
run: |
python -m coverage erase
status=0
while IFS= read -r file; do
echo "::group::${file}"
python -m coverage run -a "${file}" || status=1
echo "::endgroup::"
done < <(find snesdsp conformance -name '*.test.py' | sort)
exit "${status}"
shell: bash
- name: Coverage must be total
run: python -m coverage report
speed:
name: Throughput
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
submodules: recursive
- uses: actions/setup-python@v7
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: The part must still run faster than the floor
run: python -m conformance.speed
quotes:
name: Every quoted sentence, against the document it came from
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: ${{ env.PYTHON_VERSION }}
# No document is redistributable, so none is here and this checks nothing
# on a runner. It says so rather than reporting a pass: the value is that
# somebody running it with the data sheet on disk gets a real answer, and
# that a run without it cannot be mistaken for one.
- name: Every quoted sentence, against the document it came from
run: python -m conformance.quotes
firmware:
name: Against the parts, when any microcode is present
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
submodules: recursive
- uses: actions/setup-python@v7
with:
python-version: ${{ env.PYTHON_VERSION }}
# This runs the program a cartridge carries, which belongs to whoever
# wrote it, so on a machine without one it says so and stops rather than
# reporting a pass. Everything a machine without one can check runs in the
# test job above: this package has no behaviour of its own to get wrong.
# Exit 2 is the runner saying it had nothing to run, which is the honest
# answer to a person who asked it to drive a part and holds no image. It is
# not a failure of this build, so it is caught here rather than by making
# the tool lie about it.
- name: Drive the parts with the exchanges real cartridges make
run: |
set +e
status=0
for part in dsp1 dsp2 dsp3 dsp4; do
echo "::group::${part}"
python -m conformance.against_cartridges "${part}" | tee -a report.txt
here=${PIPESTATUS[0]}
echo "::endgroup::"
[ "${here}" -eq 0 ] || status="${here}"
done
set -e
if [ "${status}" -eq 2 ]; then
echo "::notice title=No microcode present::The checks that run a part's own program did not run. They are not failures; they had nothing to run."
exit 0
fi
exit "${status}"
shell: bash
# What each part answers, re-derived and compared against what it answered
# when the corpus was taken. The microcode makes the values right; this
# catches the layers around it changing them, which nothing else would.
- name: Every part still answers what it answered
run: |
set +e
python -m conformance.answers
status=$?
set -e
if [ "${status}" -eq 2 ]; then
echo "::notice title=No microcode present::The recorded answers were not re-derived. They are not failures; there was nothing to run."
exit 0
fi
exit "${status}"
shell: bash
# The DSP-1B corrected an arithmetic fault in the DSP-1. That is a claim
# with a consequence, and this re-derives the inputs where the two masks
# actually part company rather than taking the claim on trust.
- name: The DSP-1B correction is still where it was
run: |
set +e
python -m conformance.masks
status=$?
set -e
if [ "${status}" -eq 2 ]; then
echo "::notice title=Both DSP-1 masks not present::The mask comparison needs an image for the DSP-1 and the DSP-1B. It did not run."
exit 0
fi
exit "${status}"
shell: bash
# Every snippet the README prints, run against the parts it names. A
# number in a document is a claim about the code, and this is what keeps
# the two from drifting apart. Same exit 2 rule as above.
- name: Every example in the README still gives what it says
run: |
set +e
python -m conformance.documented
status=$?
set -e
if [ "${status}" -eq 2 ]; then
echo "::notice title=No microcode present::The README examples were not run. They are not failures; they had nothing to run."
exit 0
fi
exit "${status}"
shell: bash