Skip to content

Commit 600e567

Browse files
tbdyereinauer
authored andcommitted
ci: add GitHub Actions workflow and update TESTING.md
1 parent 94f5382 commit 600e567

5 files changed

Lines changed: 215 additions & 7 deletions

File tree

.github/workflows/ci.yml

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
unit-tests:
11+
name: Unit Tests (Python ${{ matrix.python-version }}, ${{ matrix.os }})
12+
runs-on: ${{ matrix.os }}
13+
strategy:
14+
fail-fast: false
15+
matrix:
16+
os: [ubuntu-latest, macos-latest, windows-latest]
17+
python-version: ["3.11", "3.12", "3.13"]
18+
steps:
19+
- uses: actions/checkout@v4
20+
with:
21+
submodules: true
22+
23+
- name: Set up Python ${{ matrix.python-version }}
24+
uses: actions/setup-python@v5
25+
with:
26+
python-version: ${{ matrix.python-version }}
27+
cache: 'pip'
28+
29+
- name: Install dependencies
30+
run: |
31+
python -m pip install --upgrade pip
32+
pip install -e "./amitools[vamos]"
33+
pip install "pytest>=7.0" "pytest-cov>=4.0" "pytest-timeout>=2.0"
34+
pip install -e "." --no-deps
35+
36+
- name: Run unit tests
37+
run: pytest tests/unit/ -v --timeout=30
38+
39+
integration-tests:
40+
name: Integration Tests (${{ matrix.os }})
41+
runs-on: ${{ matrix.os }}
42+
needs: unit-tests
43+
strategy:
44+
fail-fast: false
45+
matrix:
46+
# Windows excluded: machine68k segfaults due to opcode table
47+
# over-read (cnvogelg/machine68k#8) and JMP/CAS collision (#9).
48+
os: [ubuntu-latest, macos-latest]
49+
steps:
50+
- uses: actions/checkout@v4
51+
with:
52+
submodules: true
53+
54+
- name: Set up Python 3.13
55+
uses: actions/setup-python@v5
56+
with:
57+
python-version: "3.13"
58+
cache: 'pip'
59+
60+
- name: Clone AmiFUSE-testing fixtures
61+
# Clones to sibling directory of workspace checkout.
62+
# Workspace is typically /home/runner/work/<repo>/<repo>.
63+
run: |
64+
git clone --depth 1 https://github.com/reinauer/AmiFUSE-testing.git ../AmiFUSE-testing
65+
continue-on-error: true
66+
67+
- name: Install dependencies
68+
run: |
69+
python -m pip install --upgrade pip
70+
pip install -e "./amitools[vamos]"
71+
pip install "pytest>=7.0" "pytest-cov>=4.0" "pytest-timeout>=2.0"
72+
pip install -e "." --no-deps
73+
74+
- name: Verify machine68k
75+
run: |
76+
python -c "import machine68k; print(f'machine68k {machine68k.__version__}')"
77+
python -c "import machine68k; machine68k.CPU(1); print('CPU probe OK')"
78+
continue-on-error: true
79+
80+
- name: Run integration tests
81+
env:
82+
AMIFUSE_FIXTURE_ROOT: ${{ github.workspace }}/../AmiFUSE-testing
83+
run: pytest tests/integration/ -v --timeout=60
84+
85+
tools-smoke:
86+
name: Tools Smoke (${{ matrix.os }})
87+
runs-on: ${{ matrix.os }}
88+
needs: unit-tests
89+
strategy:
90+
fail-fast: false
91+
matrix:
92+
os: [ubuntu-latest, macos-latest]
93+
steps:
94+
- uses: actions/checkout@v4
95+
with:
96+
submodules: true
97+
98+
- name: Set up Python 3.13
99+
uses: actions/setup-python@v5
100+
with:
101+
python-version: "3.13"
102+
cache: 'pip'
103+
104+
- name: Clone AmiFUSE-testing fixtures
105+
# Clones to sibling directory of workspace checkout.
106+
# Workspace is typically /home/runner/work/<repo>/<repo>.
107+
run: |
108+
git clone --depth 1 https://github.com/reinauer/AmiFUSE-testing.git ../AmiFUSE-testing
109+
continue-on-error: true
110+
111+
- name: Install dependencies
112+
run: |
113+
python -m pip install --upgrade pip
114+
pip install -e "./amitools[vamos]"
115+
pip install -e "." --no-deps
116+
117+
- name: Run amifuse_matrix smoke
118+
env:
119+
AMIFUSE_FIXTURE_ROOT: ${{ github.workspace }}/../AmiFUSE-testing
120+
run: python tools/amifuse_matrix.py --fixtures pfs3 sfs ofs --runs 1 --json
121+
122+
- name: Run image_format_smoke
123+
env:
124+
AMIFUSE_FIXTURE_ROOT: ${{ github.workspace }}/../AmiFUSE-testing
125+
run: python tools/image_format_smoke.py --case direct-rdb-pfs3 --json

TESTING.md

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ python3 tools/amifuse_matrix.py \
271271

272272
Then compare the results with:
273273

274-
[PERFORMANCE.md](/Users/stepan/git/AmiFuse-codex/PERFORMANCE.md)
274+
[PERFORMANCE.md](PERFORMANCE.md)
275275

276276
Important interpretation rules:
277277

@@ -293,7 +293,7 @@ the matrix is the main current performance harness.
293293

294294
The `amitools` submodule has its own test tree and README:
295295

296-
[amitools/test/README.md](/Users/stepan/git/AmiFuse-codex/amitools/test/README.md)
296+
[amitools/test/README.md](amitools/test/README.md)
297297

298298
The important buckets there are:
299299

@@ -341,6 +341,85 @@ In practice:
341341
- `readme smoke` catches CLI and docs drift
342342
- `amitools` tests catch lower-level runtime semantics
343343

344+
## Pytest Test Suite
345+
346+
The repo has a structured pytest test suite alongside the legacy tools/
347+
scripts. Tests are organized into two layers:
348+
349+
| Layer | Location | Marker | Requires |
350+
|-------|----------|--------|----------|
351+
| Unit | `tests/unit/` | _(none)_ | Python + amifuse installed |
352+
| Integration | `tests/integration/` | `integration` | machine68k + external fixtures |
353+
354+
### Quick Start
355+
356+
```sh
357+
# Unit tests (all platforms, no external dependencies)
358+
pytest tests/unit/ -v --timeout=30
359+
360+
# Integration tests (Linux/macOS, needs fixtures)
361+
pytest tests/integration/ -v --timeout=60
362+
363+
# All tests
364+
pytest tests/ -v --timeout=60
365+
```
366+
367+
### Fixture Resolution
368+
369+
Integration tests need handler binaries and disk images. They resolve
370+
the fixture directory through a cascade:
371+
372+
1. `AMIFUSE_FIXTURE_ROOT` env var — point this at any directory containing
373+
`drivers/` (handler binaries) and `fixtures/readonly/` (disk images)
374+
2. `../AmiFUSE-testing` sibling directory (relative to repo root)
375+
3. `~/AmigaOS/AmiFuse` (default local path)
376+
4. `None` → tests skip gracefully with a clear message
377+
378+
The fixture directory must contain at minimum:
379+
380+
```
381+
<fixture-root>/
382+
├── drivers/
383+
│ ├── pfs3aio # PFS3 handler binary
384+
│ └── FastFileSystem # FFS/OFS handler binary
385+
└── fixtures/
386+
└── readonly/
387+
├── pfs.hdf # PFS3 hard drive image
388+
└── ofs.adf # OFS floppy image
389+
```
390+
391+
Set the env var to point at your fixture directory:
392+
393+
```sh
394+
export AMIFUSE_FIXTURE_ROOT=/path/to/your/fixtures
395+
pytest tests/integration/ -v
396+
```
397+
398+
### Markers
399+
400+
| Marker | Meaning |
401+
|--------|---------|
402+
| `slow` | Slow tests (deselect with `-m "not slow"`) |
403+
| `fuse` | Requires FUSE/WinFSP kernel driver |
404+
| `integration` | Requires external fixtures and machine68k |
405+
| `windows` / `macos` / `linux` | Platform-specific tests |
406+
407+
### CI (GitHub Actions)
408+
409+
The CI workflow (`.github/workflows/ci.yml`) runs three jobs:
410+
411+
| Job | Platforms | Python | What |
412+
|-----|-----------|--------|------|
413+
| `unit-tests` | Linux, macOS, Windows | 3.11, 3.12, 3.13 | `pytest tests/unit/` |
414+
| `integration-tests` | Linux, macOS | 3.13 | `pytest tests/integration/` with external fixtures |
415+
| `tools-smoke` | Linux, macOS | 3.13 | `amifuse_matrix.py` + `image_format_smoke.py` |
416+
417+
Windows is excluded from integration and tools-smoke because machine68k
418+
segfaults on Windows due to opcode table over-read
419+
([cnvogelg/machine68k#8](https://github.com/cnvogelg/machine68k/issues/8))
420+
and JMP/CAS collision
421+
([cnvogelg/machine68k#9](https://github.com/cnvogelg/machine68k/issues/9)).
422+
344423
## Current Gaps
345424

346425
The following are still planned, not fully documented as standalone test
@@ -349,4 +428,8 @@ entry points yet:
349428
- far-end file I/O coverage inside a filesystem that spans a partition
350429
larger than `4GiB`
351430
- fuller long-run generated benchmark recipes
352-
- fixture-layout cleanup for `~/AmigaOS/AmiFuse/`
431+
- ~~fixture-layout cleanup for `~/AmigaOS/AmiFuse/`~~ (resolved:
432+
`AMIFUSE_FIXTURE_ROOT` env var + fixture cascade in `tests/fixtures/paths.py`)
433+
- Windows integration tests pending machine68k upstream fixes
434+
([cnvogelg/machine68k#8](https://github.com/cnvogelg/machine68k/issues/8),
435+
[cnvogelg/machine68k#9](https://github.com/cnvogelg/machine68k/issues/9))

tests/fixtures/paths.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Resolves external fixture paths through a cascade:
44
1. AMIFUSE_FIXTURE_ROOT env var
55
2. ../AmiFUSE-testing sibling directory (relative to repo root)
6-
3. ~/AmigaOS/AmiFuse (Stefan's default)
6+
3. ~/AmigaOS/AmiFuse (default local path)
77
4. None (tests skip gracefully)
88
99
This module does NOT import from tools/fixture_paths.py.
@@ -31,7 +31,7 @@ def _resolve_fixture_root() -> Path | None:
3131
if sibling.is_dir() and (sibling / "drivers").is_dir():
3232
return sibling
3333

34-
# 3. Stefan's default local path
34+
# 3. Default local path
3535
default = Path.home() / "AmigaOS" / "AmiFuse"
3636
if default.is_dir() and (default / "drivers").is_dir():
3737
return default

tests/integration/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def pytest_collection_modifyitems(config, items):
4040

4141
if FIXTURE_ROOT is None:
4242
skip = pytest.mark.skip(
43-
reason="No fixture root found (set AMIFUSE_FIXTURE_ROOT or clone AmiFUSE-testing)"
43+
reason="No fixture root found (set AMIFUSE_FIXTURE_ROOT or place fixtures in ~/AmigaOS/AmiFuse)"
4444
)
4545
for item in items:
4646
if item.get_closest_marker("integration") is not None:

tests/integration/test_handler_bridge_write.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""HandlerBridge write-path integration tests.
22
33
Uses temporary copies of fixture images to test write operations
4-
without modifying committed fixtures.
4+
without modifying source fixture images.
55
66
HandlerBridge write API (verified against fuse_fs.py):
77
open_file(path, flags) -> Optional[Tuple[fh_addr, dir_lock]]

0 commit comments

Comments
 (0)