Skip to content

Commit db3c48b

Browse files
test: add Hypothesis fuzz coverage and macos-latest CI matrix (#75)
* test: add Hypothesis fuzz coverage and macos-latest CI matrix Add tests/test_parser_fuzz.py with strategies for malformed/truncated JSONL, unknown record types, missing/extra fields, deep nesting, long lines, empty lines, and null bytes. Harden parse_session against adversarial inputs found by fuzz (non-dict JSON values, unhashable type keys, non-str metadata fields). Extend CI matrix to macos-latest for pytest, integration-tests, js-tests, and lint-and-audit. Document Ubuntu + Windows + macOS CI in CONTRIBUTING. * fix: macOS js-tests rollup install and fuzz tmp_path cleanup Install platform Rollup binary after npm ci; drop Linux-only optionalDep. Use pytest tmp_path in test_parser_fuzz.py instead of leaking mkdtemp dirs. * fix(test): guard dict() cast in structured_entry to fix mypy arg-type error * fix(parser,test): harden token arithmetic and wire fuzz CI profile Add _safe_int() so non-numeric usage fields coerce to 0 instead of raising TypeError during token accumulation; apply to all token fields. Drop max_examples/deadline from the test decorator so the conftest ci/dev profile actually governs fuzz runtime. Inline _fuzz_jsonl_path, tighten truncation model and unknown-type assertion, simplify ALLOWED_EXCEPTIONS, and note macOS in the CONTRIBUTING PR checklist. * fix(parser): coerce non-finite usage tokens and tidy review nits Guard _safe_int against NaN/Infinity (json.loads accepts these literals; int(nan)/int(inf) raise), broaden fuzz floats to cover them, and add an explicit non-finite regression test. Revert entry_counts to truthiness so empty-string types stay skipped, wrap service_tier in the message payload, and drop the no-op [tool.hypothesis] block from pyproject.toml. * fix(parser): clamp _safe_int to non-negative for token accounting Negative usage token values from adversarial JSONL must not reduce session metadata totals; apply max(0, ...) in _safe_int and add regression test.
1 parent 8083f3e commit db3c48b

8 files changed

Lines changed: 385 additions & 39 deletions

File tree

.github/workflows/ci.yml

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ jobs:
4949
strategy:
5050
fail-fast: false
5151
matrix:
52-
os: [ubuntu-latest, windows-latest]
52+
os: [ubuntu-latest, windows-latest, macos-latest]
5353
permissions:
5454
contents: read
5555
steps:
@@ -83,7 +83,7 @@ jobs:
8383
strategy:
8484
fail-fast: false
8585
matrix:
86-
os: [ubuntu-latest, windows-latest]
86+
os: [ubuntu-latest, windows-latest, macos-latest]
8787
permissions:
8888
contents: read
8989
steps:
@@ -138,7 +138,7 @@ jobs:
138138
strategy:
139139
fail-fast: false
140140
matrix:
141-
os: [ubuntu-latest, windows-latest]
141+
os: [ubuntu-latest, windows-latest, macos-latest]
142142
permissions:
143143
contents: read
144144
actions: write
@@ -174,7 +174,7 @@ jobs:
174174
strategy:
175175
fail-fast: false
176176
matrix:
177-
os: [ubuntu-latest, windows-latest]
177+
os: [ubuntu-latest, windows-latest, macos-latest]
178178
permissions:
179179
contents: read
180180
steps:
@@ -188,4 +188,19 @@ jobs:
188188
cache: npm
189189

190190
- run: npm ci
191+
# npm optional-deps bug: platform rollup binaries are sometimes skipped after npm ci
192+
# (https://github.com/npm/cli/issues/4828). Install the native package explicitly.
193+
- name: Ensure Rollup native binary
194+
shell: bash
195+
run: |
196+
ROLLUP_VERSION=$(node -p "require('./node_modules/rollup/package.json').version")
197+
case "$(node -p "process.platform + '-' + process.arch")" in
198+
darwin-arm64) PKG="@rollup/rollup-darwin-arm64" ;;
199+
darwin-x64) PKG="@rollup/rollup-darwin-x64" ;;
200+
linux-x64) PKG="@rollup/rollup-linux-x64-gnu" ;;
201+
win32-x64) PKG="@rollup/rollup-win32-x64-msvc" ;;
202+
win32-arm64) PKG="@rollup/rollup-win32-arm64-msvc" ;;
203+
*) echo "Unsupported Node platform: $(node -p "process.platform + '-' + process.arch")"; exit 1 ;;
204+
esac
205+
npm install --no-save "${PKG}@${ROLLUP_VERSION}"
191206
- run: npm test

CONTRIBUTING.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Thanks for considering a patch. This repo is a small Flask app plus a hash-route
99
- **Python 3.12** (matches CI)
1010
- **Node 20+** (only if you change `static/js/` or run frontend unit tests)
1111

12-
CI runs **`ruff check`**, **`ruff format --check`**, **`pip-audit`**, **`pytest`**, **integration tests**, and **Vitest** on **ubuntu-latest** and **windows-latest** (Python 3.12, Node 20). Type-check (`mypy`) and production install smoke run on Ubuntu only.
12+
CI runs **`ruff check`**, **`ruff format --check`**, **`pip-audit`**, **`pytest`**, **integration tests**, and **Vitest** on **Ubuntu, Windows, and macOS** (`ubuntu-latest`, `windows-latest`, `macos-latest`; Python 3.12, Node 20). Type-check (`mypy`) and production install smoke run on Ubuntu only.
1313

1414
### Bootstrap (Windows PowerShell)
1515

@@ -112,7 +112,7 @@ npm run test:coverage # optional
112112
- [ ] `ruff check .` and `ruff format --check .` green locally
113113
- [ ] `pytest -q` green locally
114114
- [ ] `npm test` green if JS changed
115-
- [ ] CI jobs green (`lint-and-audit`, `pytest`, `integration-tests`, `js-tests` on Ubuntu + Windows; `mypy`, `prod-install-smoke` on Ubuntu)
115+
- [ ] CI jobs green (`lint-and-audit`, `pytest`, `integration-tests`, `js-tests` on Ubuntu + Windows + macOS; `mypy`, `prod-install-smoke` on Ubuntu)
116116
- [ ] PR description includes a **Test plan** section
117117
- [ ] API changes update [`docs/api-reference.md`](docs/api-reference.md) if behavior or errors change
118118

package-lock.json

Lines changed: 1 addition & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,5 @@
1212
"jsdom": "^26.1.0",
1313
"marked": "^12.0.1",
1414
"vitest": "^3.2.4"
15-
},
16-
"optionalDependencies": {
17-
"@rollup/rollup-linux-x64-gnu": "4.60.4"
1815
}
1916
}

requirements-dev.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ types-Flask==1.1.6
55
pytest-cov>=5.0
66
ruff>=0.9.0
77
pip-audit>=2.7.0
8+
hypothesis>=6.100.0

tests/conftest.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,22 @@
22

33
from __future__ import annotations
44

5+
import os
56
import shutil
67
from collections.abc import Mapping
78
from pathlib import Path
89

910
import pytest
11+
from hypothesis import settings
1012

1113
from app import create_app
1214

15+
# Hypothesis profiles drive fuzz example counts/deadlines (deadline disabled to
16+
# avoid timing flakiness on slow/CI runners). CI runs fewer examples for speed.
17+
settings.register_profile("dev", max_examples=200, deadline=None)
18+
settings.register_profile("ci", max_examples=100, deadline=None)
19+
settings.load_profile("ci" if os.environ.get("CI") else "dev")
20+
1321
FIXTURES = Path(__file__).parent / "fixtures"
1422

1523

0 commit comments

Comments
 (0)