diff --git a/.forgejo/workflows/grade.yml b/.forgejo/workflows/grade.yml index 9e4d6c2..7b6bf4d 100644 --- a/.forgejo/workflows/grade.yml +++ b/.forgejo/workflows/grade.yml @@ -1,19 +1,18 @@ name: grade on: [push] -# Production wiring (gitea-runner on ghost, docker mode): -# - job container = gitea/runner-images (has docker CLI) + the host docker -# socket, so docker_grade.sh drives the host daemon exactly as designed +# Production wiring (forgejo-runner on ghost): +# - forgejo-runner v13 config sets docker_host: automount (host socket into +# the job container), so docker_grade.sh drives the host daemon as designed # - hidden tests mount from the runner host (/opt/grade-hidden) — never in # this repo # - GRADE_HMAC_SECRET mounts from /opt/grade/grade.env on the runner host jobs: grade: - runs-on: ubuntu-latest + runs-on: docker container: image: gitea/runner-images:ubuntu-22.04 options: >- - -v /var/run/docker.sock:/var/run/docker.sock -v /opt/grade/grade.env:/run/secrets/grade.env:ro -v /opt/grade-hidden:/opt/grade-hidden:ro steps: diff --git a/hidden/__pycache__/test_hidden.cpython-314-pytest-9.1.1.pyc b/hidden/__pycache__/test_hidden.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..a257e42 Binary files /dev/null and b/hidden/__pycache__/test_hidden.cpython-314-pytest-9.1.1.pyc differ diff --git a/hidden/test_hidden.py b/hidden/test_hidden.py new file mode 100644 index 0000000..9b7e0c8 --- /dev/null +++ b/hidden/test_hidden.py @@ -0,0 +1,44 @@ +"""Hidden interface test for the Record Manager (blank must fail, solved must pass). + +Runs with pytest's cwd = the assembled submission (/work/submission). +Blank (M1 starter) fails because `save`/`load` are unimplemented ("not yet"); +the full reference implements the store round-trip. +""" + +import pathlib +import subprocess + + +def _root() -> pathlib.Path: + return pathlib.Path.cwd() + + +def _run(cmd, timeout=180, **kw): + return subprocess.run(cmd, capture_output=True, text=True, timeout=timeout, **kw) + + +def test_record_manager_interface(): + root = _root() + + build = _run(["make", "-C", str(root), "-j2"]) + assert build.returncode == 0, "BUILD FAILED:\n" + build.stdout + build.stderr + recman = root / "build" / "recman" + assert recman.exists(), "build/recman missing after make" + + # add two records, save to a file + session1 = ( + "add\nAda Lovelace\nada@x\n555-0100\n" + "add\nGrace Hopper\ngrace@x\n444-0200\n" + "save\n/tmp/rm_hidden.txt\nquit\n" + ) + r = _run([str(recman)], input=session1) + assert "added: Ada Lovelace" in r.stdout, "add failed:\n" + r.stdout + assert "added: Grace Hopper" in r.stdout, "add failed:\n" + r.stdout + assert "saved" in r.stdout, "save did not persist (blank starter prints 'not yet'):\n" + r.stdout + + # load back in a fresh session and confirm the round-trip + session2 = "load\n/tmp/rm_hidden.txt\nlist\nquit\n" + r2 = _run([str(recman)], input=session2) + assert "Ada Lovelace" in r2.stdout and "Grace Hopper" in r2.stdout, ( + "save/load round-trip failed:\n" + r2.stdout + )