ordeal 0.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ordeal-0.0.0/.github/ISSUE_TEMPLATE/bug_report.yml +48 -0
- ordeal-0.0.0/.github/ISSUE_TEMPLATE/config.yml +1 -0
- ordeal-0.0.0/.github/ISSUE_TEMPLATE/feature_request.yml +24 -0
- ordeal-0.0.0/.github/PULL_REQUEST_TEMPLATE.md +11 -0
- ordeal-0.0.0/.github/dependabot.yml +17 -0
- ordeal-0.0.0/.github/workflows/ci.yml +51 -0
- ordeal-0.0.0/.github/workflows/release.yml +79 -0
- ordeal-0.0.0/.gitignore +211 -0
- ordeal-0.0.0/.python-version +1 -0
- ordeal-0.0.0/AGENTS.md +46 -0
- ordeal-0.0.0/CHANGELOG.md +20 -0
- ordeal-0.0.0/CLAUDE.md +108 -0
- ordeal-0.0.0/CONTRIBUTING.md +42 -0
- ordeal-0.0.0/LICENSE +201 -0
- ordeal-0.0.0/PKG-INFO +352 -0
- ordeal-0.0.0/README.md +314 -0
- ordeal-0.0.0/docs/api-reference.md +130 -0
- ordeal-0.0.0/docs/cli.md +54 -0
- ordeal-0.0.0/docs/configuration.md +78 -0
- ordeal-0.0.0/docs/core-concepts.md +82 -0
- ordeal-0.0.0/docs/explorer.md +81 -0
- ordeal-0.0.0/docs/getting-started.md +92 -0
- ordeal-0.0.0/docs/index.md +25 -0
- ordeal-0.0.0/docs/integrations.md +66 -0
- ordeal-0.0.0/docs/mutations.md +43 -0
- ordeal-0.0.0/docs/simulate.md +69 -0
- ordeal-0.0.0/ordeal/__init__.py +96 -0
- ordeal-0.0.0/ordeal/assertions.py +161 -0
- ordeal-0.0.0/ordeal/buggify.py +81 -0
- ordeal-0.0.0/ordeal/chaos.py +111 -0
- ordeal-0.0.0/ordeal/cli.py +269 -0
- ordeal-0.0.0/ordeal/config.py +205 -0
- ordeal-0.0.0/ordeal/explore.py +614 -0
- ordeal-0.0.0/ordeal/faults/__init__.py +158 -0
- ordeal-0.0.0/ordeal/faults/io.py +177 -0
- ordeal-0.0.0/ordeal/faults/numerical.py +138 -0
- ordeal-0.0.0/ordeal/faults/timing.py +118 -0
- ordeal-0.0.0/ordeal/integrations/__init__.py +5 -0
- ordeal-0.0.0/ordeal/integrations/atheris_engine.py +172 -0
- ordeal-0.0.0/ordeal/integrations/schemathesis_ext.py +184 -0
- ordeal-0.0.0/ordeal/invariants.py +179 -0
- ordeal-0.0.0/ordeal/mutations.py +435 -0
- ordeal-0.0.0/ordeal/plugin.py +129 -0
- ordeal-0.0.0/ordeal/py.typed +0 -0
- ordeal-0.0.0/ordeal/quickcheck.py +340 -0
- ordeal-0.0.0/ordeal/simulate.py +172 -0
- ordeal-0.0.0/ordeal/strategies.py +103 -0
- ordeal-0.0.0/ordeal/trace.py +331 -0
- ordeal-0.0.0/ordeal.egg-info/PKG-INFO +352 -0
- ordeal-0.0.0/ordeal.egg-info/SOURCES.txt +72 -0
- ordeal-0.0.0/ordeal.egg-info/dependency_links.txt +1 -0
- ordeal-0.0.0/ordeal.egg-info/entry_points.txt +5 -0
- ordeal-0.0.0/ordeal.egg-info/requires.txt +17 -0
- ordeal-0.0.0/ordeal.egg-info/top_level.txt +1 -0
- ordeal-0.0.0/ordeal.toml.example +63 -0
- ordeal-0.0.0/pyproject.toml +76 -0
- ordeal-0.0.0/setup.cfg +4 -0
- ordeal-0.0.0/tests/__init__.py +0 -0
- ordeal-0.0.0/tests/_explore_target.py +54 -0
- ordeal-0.0.0/tests/_mutation_target.py +19 -0
- ordeal-0.0.0/tests/test_assertions.py +159 -0
- ordeal-0.0.0/tests/test_battle.py +709 -0
- ordeal-0.0.0/tests/test_buggify.py +66 -0
- ordeal-0.0.0/tests/test_chaos.py +118 -0
- ordeal-0.0.0/tests/test_cli.py +45 -0
- ordeal-0.0.0/tests/test_config.py +96 -0
- ordeal-0.0.0/tests/test_explore.py +225 -0
- ordeal-0.0.0/tests/test_faults.py +262 -0
- ordeal-0.0.0/tests/test_invariants.py +154 -0
- ordeal-0.0.0/tests/test_quickcheck.py +230 -0
- ordeal-0.0.0/tests/test_simulate.py +171 -0
- ordeal-0.0.0/tests/test_strategies.py +68 -0
- ordeal-0.0.0/tests/test_trace.py +202 -0
- ordeal-0.0.0/uv.lock +959 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
name: Bug Report
|
|
2
|
+
description: Report a bug in ordeal
|
|
3
|
+
labels: [bug]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: description
|
|
7
|
+
attributes:
|
|
8
|
+
label: Description
|
|
9
|
+
description: What happened?
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
|
|
13
|
+
- type: textarea
|
|
14
|
+
id: reproduction
|
|
15
|
+
attributes:
|
|
16
|
+
label: Minimal reproduction
|
|
17
|
+
description: Smallest code snippet or steps that trigger the bug.
|
|
18
|
+
render: python
|
|
19
|
+
|
|
20
|
+
- type: textarea
|
|
21
|
+
id: expected
|
|
22
|
+
attributes:
|
|
23
|
+
label: Expected behavior
|
|
24
|
+
description: What should have happened instead?
|
|
25
|
+
|
|
26
|
+
- type: input
|
|
27
|
+
id: ordeal-version
|
|
28
|
+
attributes:
|
|
29
|
+
label: ordeal version
|
|
30
|
+
placeholder: "0.1.0"
|
|
31
|
+
|
|
32
|
+
- type: input
|
|
33
|
+
id: python-version
|
|
34
|
+
attributes:
|
|
35
|
+
label: Python version
|
|
36
|
+
placeholder: "3.12.0"
|
|
37
|
+
|
|
38
|
+
- type: input
|
|
39
|
+
id: os
|
|
40
|
+
attributes:
|
|
41
|
+
label: Operating system
|
|
42
|
+
placeholder: "Ubuntu 24.04 / macOS 15 / Windows 11"
|
|
43
|
+
|
|
44
|
+
- type: textarea
|
|
45
|
+
id: logs
|
|
46
|
+
attributes:
|
|
47
|
+
label: Relevant log output
|
|
48
|
+
render: text
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
blank_issues_enabled: true
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: Feature Request
|
|
2
|
+
description: Suggest a new feature or improvement
|
|
3
|
+
labels: [enhancement]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: problem
|
|
7
|
+
attributes:
|
|
8
|
+
label: Problem or use case
|
|
9
|
+
description: What are you trying to do? Why does ordeal not solve it today?
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
|
|
13
|
+
- type: textarea
|
|
14
|
+
id: solution
|
|
15
|
+
attributes:
|
|
16
|
+
label: Proposed solution
|
|
17
|
+
description: How should ordeal solve this? Include example API if applicable.
|
|
18
|
+
render: python
|
|
19
|
+
|
|
20
|
+
- type: textarea
|
|
21
|
+
id: alternatives
|
|
22
|
+
attributes:
|
|
23
|
+
label: Alternatives considered
|
|
24
|
+
description: What other approaches did you consider?
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: "pip"
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: "weekly"
|
|
7
|
+
groups:
|
|
8
|
+
dependencies:
|
|
9
|
+
patterns: ["*"]
|
|
10
|
+
|
|
11
|
+
- package-ecosystem: "github-actions"
|
|
12
|
+
directory: "/"
|
|
13
|
+
schedule:
|
|
14
|
+
interval: "weekly"
|
|
15
|
+
groups:
|
|
16
|
+
actions:
|
|
17
|
+
patterns: ["*"]
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
lint:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- uses: astral-sh/setup-uv@v4
|
|
18
|
+
|
|
19
|
+
- run: uv python install 3.13
|
|
20
|
+
|
|
21
|
+
- run: uv sync --extra dev
|
|
22
|
+
|
|
23
|
+
- name: Ruff check
|
|
24
|
+
run: uv run ruff check .
|
|
25
|
+
|
|
26
|
+
- name: Ruff format
|
|
27
|
+
run: uv run ruff format --check .
|
|
28
|
+
|
|
29
|
+
test:
|
|
30
|
+
runs-on: ${{ matrix.os }}
|
|
31
|
+
strategy:
|
|
32
|
+
fail-fast: false
|
|
33
|
+
matrix:
|
|
34
|
+
os: [ubuntu-latest]
|
|
35
|
+
python-version: ["3.12", "3.13"]
|
|
36
|
+
include:
|
|
37
|
+
- os: macos-latest
|
|
38
|
+
python-version: "3.13"
|
|
39
|
+
- os: windows-latest
|
|
40
|
+
python-version: "3.13"
|
|
41
|
+
steps:
|
|
42
|
+
- uses: actions/checkout@v4
|
|
43
|
+
|
|
44
|
+
- uses: astral-sh/setup-uv@v4
|
|
45
|
+
|
|
46
|
+
- run: uv python install ${{ matrix.python-version }}
|
|
47
|
+
|
|
48
|
+
- run: uv sync --extra dev
|
|
49
|
+
|
|
50
|
+
- name: Run tests
|
|
51
|
+
run: uv run pytest --tb=short -q
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
tags: ["v*"]
|
|
7
|
+
|
|
8
|
+
permissions: {}
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
# ── Auto-tag: bump patch on every push to main ──────────────────────
|
|
12
|
+
auto-tag:
|
|
13
|
+
if: github.ref == 'refs/heads/main'
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
permissions:
|
|
16
|
+
contents: write
|
|
17
|
+
outputs:
|
|
18
|
+
new_tag: ${{ steps.bump.outputs.new_tag }}
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
with:
|
|
22
|
+
fetch-depth: 0
|
|
23
|
+
|
|
24
|
+
- name: Bump patch version
|
|
25
|
+
id: bump
|
|
26
|
+
run: |
|
|
27
|
+
# If HEAD already carries a version tag, skip (manual tag push).
|
|
28
|
+
if git tag --points-at HEAD | grep -qE '^v[0-9]'; then
|
|
29
|
+
echo "new_tag=" >> "$GITHUB_OUTPUT"
|
|
30
|
+
exit 0
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
# Find the latest clean semver tag (ignore pre-release suffixes).
|
|
34
|
+
LATEST=$(git tag -l 'v*' --sort=-v:refname \
|
|
35
|
+
| grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -1)
|
|
36
|
+
|
|
37
|
+
if [ -z "$LATEST" ]; then
|
|
38
|
+
NEW_TAG="v0.0.1"
|
|
39
|
+
else
|
|
40
|
+
VERSION=${LATEST#v}
|
|
41
|
+
IFS='.' read -r MAJOR MINOR PATCH <<< "$VERSION"
|
|
42
|
+
NEW_TAG="v${MAJOR}.${MINOR}.$((PATCH + 1))"
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
git tag "$NEW_TAG"
|
|
46
|
+
git push origin "$NEW_TAG"
|
|
47
|
+
echo "new_tag=$NEW_TAG" >> "$GITHUB_OUTPUT"
|
|
48
|
+
|
|
49
|
+
# ── Publish to PyPI ─────────────────────────────────────────────────
|
|
50
|
+
publish:
|
|
51
|
+
needs: [auto-tag]
|
|
52
|
+
# Run when: (a) triggered by a manual tag push, OR
|
|
53
|
+
# (b) auto-tag just created a new tag.
|
|
54
|
+
if: >-
|
|
55
|
+
always() && (
|
|
56
|
+
startsWith(github.ref, 'refs/tags/v') ||
|
|
57
|
+
needs.auto-tag.outputs.new_tag != ''
|
|
58
|
+
)
|
|
59
|
+
runs-on: ubuntu-latest
|
|
60
|
+
environment: pypi
|
|
61
|
+
permissions:
|
|
62
|
+
id-token: write # OIDC for PyPI trusted publisher
|
|
63
|
+
steps:
|
|
64
|
+
- uses: actions/checkout@v4
|
|
65
|
+
with:
|
|
66
|
+
fetch-depth: 0 # setuptools-scm needs full history + tags
|
|
67
|
+
|
|
68
|
+
- uses: actions/setup-python@v5
|
|
69
|
+
with:
|
|
70
|
+
python-version: "3.12"
|
|
71
|
+
|
|
72
|
+
- name: Install build tools
|
|
73
|
+
run: pip install build setuptools-scm
|
|
74
|
+
|
|
75
|
+
- name: Build sdist + wheel
|
|
76
|
+
run: python -m build
|
|
77
|
+
|
|
78
|
+
- name: Publish to PyPI
|
|
79
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
ordeal-0.0.0/.gitignore
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[codz]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py.cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
#Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# UV
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
#uv.lock
|
|
102
|
+
|
|
103
|
+
# poetry
|
|
104
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
105
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
106
|
+
# commonly ignored for libraries.
|
|
107
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
108
|
+
#poetry.lock
|
|
109
|
+
#poetry.toml
|
|
110
|
+
|
|
111
|
+
# pdm
|
|
112
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
113
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
114
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
115
|
+
#pdm.lock
|
|
116
|
+
#pdm.toml
|
|
117
|
+
.pdm-python
|
|
118
|
+
.pdm-build/
|
|
119
|
+
|
|
120
|
+
# pixi
|
|
121
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
122
|
+
#pixi.lock
|
|
123
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
124
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
125
|
+
.pixi
|
|
126
|
+
|
|
127
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
128
|
+
__pypackages__/
|
|
129
|
+
|
|
130
|
+
# Celery stuff
|
|
131
|
+
celerybeat-schedule
|
|
132
|
+
celerybeat.pid
|
|
133
|
+
|
|
134
|
+
# SageMath parsed files
|
|
135
|
+
*.sage.py
|
|
136
|
+
|
|
137
|
+
# Environments
|
|
138
|
+
.env
|
|
139
|
+
.envrc
|
|
140
|
+
.venv
|
|
141
|
+
env/
|
|
142
|
+
venv/
|
|
143
|
+
ENV/
|
|
144
|
+
env.bak/
|
|
145
|
+
venv.bak/
|
|
146
|
+
|
|
147
|
+
# Spyder project settings
|
|
148
|
+
.spyderproject
|
|
149
|
+
.spyproject
|
|
150
|
+
|
|
151
|
+
# Rope project settings
|
|
152
|
+
.ropeproject
|
|
153
|
+
|
|
154
|
+
# mkdocs documentation
|
|
155
|
+
/site
|
|
156
|
+
|
|
157
|
+
# mypy
|
|
158
|
+
.mypy_cache/
|
|
159
|
+
.dmypy.json
|
|
160
|
+
dmypy.json
|
|
161
|
+
|
|
162
|
+
# Pyre type checker
|
|
163
|
+
.pyre/
|
|
164
|
+
|
|
165
|
+
# pytype static type analyzer
|
|
166
|
+
.pytype/
|
|
167
|
+
|
|
168
|
+
# Cython debug symbols
|
|
169
|
+
cython_debug/
|
|
170
|
+
|
|
171
|
+
# PyCharm
|
|
172
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
173
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
174
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
175
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
176
|
+
#.idea/
|
|
177
|
+
|
|
178
|
+
# Abstra
|
|
179
|
+
# Abstra is an AI-powered process automation framework.
|
|
180
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
181
|
+
# Learn more at https://abstra.io/docs
|
|
182
|
+
.abstra/
|
|
183
|
+
|
|
184
|
+
# Visual Studio Code
|
|
185
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
|
186
|
+
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
187
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
|
188
|
+
# you could uncomment the following to ignore the entire vscode folder
|
|
189
|
+
# .vscode/
|
|
190
|
+
|
|
191
|
+
# Ruff stuff:
|
|
192
|
+
.ruff_cache/
|
|
193
|
+
|
|
194
|
+
# PyPI configuration file
|
|
195
|
+
.pypirc
|
|
196
|
+
|
|
197
|
+
# Cursor
|
|
198
|
+
# Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
|
|
199
|
+
# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
|
|
200
|
+
# refer to https://docs.cursor.com/context/ignore-files
|
|
201
|
+
.cursorignore
|
|
202
|
+
.cursorindexingignore
|
|
203
|
+
|
|
204
|
+
# Marimo
|
|
205
|
+
marimo/_static/
|
|
206
|
+
marimo/_lsp/
|
|
207
|
+
__marimo__/
|
|
208
|
+
|
|
209
|
+
# Ordeal
|
|
210
|
+
.ordeal/
|
|
211
|
+
ordeal-report.json
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
ordeal-0.0.0/AGENTS.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
Conventions for AI agents working on ordeal.
|
|
4
|
+
|
|
5
|
+
## Build & test
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
uv sync # install deps
|
|
9
|
+
uv run pytest tests/ -q # run all 205 tests (~7s)
|
|
10
|
+
uv run pytest tests/ --chaos # with property reporting
|
|
11
|
+
uv run ordeal explore -c demo.toml # run explorer (needs PYTHONPATH if tests/ is target)
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Project structure
|
|
15
|
+
|
|
16
|
+
- `ordeal/` — library source (14 modules + faults/ + integrations/)
|
|
17
|
+
- `tests/` — 13 test files, includes `test_battle.py` (ordeal testing itself)
|
|
18
|
+
- `docs/` — 9 markdown docs, `index.md` is the hub
|
|
19
|
+
- `ordeal.toml.example` — annotated config reference
|
|
20
|
+
|
|
21
|
+
## Rules
|
|
22
|
+
|
|
23
|
+
- Python 3.12+. Use `match/case`, `type | None` syntax, `from __future__ import annotations`.
|
|
24
|
+
- Every public function has a docstring. Every parameter is typed. No untyped `Any` except at system boundaries (wrapping unknown functions, JSON codecs, optional deps).
|
|
25
|
+
- Tests go in `tests/test_<module>.py`. Battle tests (ordeal testing itself) go in `tests/test_battle.py`.
|
|
26
|
+
- Faults are in `ordeal/faults/{io,numerical,timing}.py`. New fault types go in the matching file or a new one.
|
|
27
|
+
- No emojis in code or docs.
|
|
28
|
+
- Keep docs under 130 lines each. Example-first, minimal prose.
|
|
29
|
+
|
|
30
|
+
## Architecture decisions
|
|
31
|
+
|
|
32
|
+
- `ChaosTest` extends Hypothesis's `RuleBasedStateMachine`. The nemesis rule is auto-injected.
|
|
33
|
+
- The Explorer is separate from Hypothesis — it drives rules manually with coverage feedback.
|
|
34
|
+
- `buggify()` is zero-cost in production (thread-local `_state.active` check).
|
|
35
|
+
- Assertions use a global `PropertyTracker` — thread-safe, activated by `--chaos` flag or `auto_configure()`.
|
|
36
|
+
- TOML config (`ordeal.toml`) is the interface between humans/agents and the Explorer.
|
|
37
|
+
- Traces are JSON. Replay uses recorded param values, not re-drawing from strategies.
|
|
38
|
+
|
|
39
|
+
## When adding a new feature
|
|
40
|
+
|
|
41
|
+
1. Write the module in `ordeal/`.
|
|
42
|
+
2. Add tests in `tests/test_<module>.py`.
|
|
43
|
+
3. Add a battle test in `tests/test_battle.py` if the feature has interesting state.
|
|
44
|
+
4. Export from `ordeal/__init__.py` if it's public API.
|
|
45
|
+
5. Add a doc in `docs/` (under 130 lines).
|
|
46
|
+
6. Update `docs/api-reference.md`.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0
|
|
4
|
+
|
|
5
|
+
Initial release.
|
|
6
|
+
|
|
7
|
+
- **ChaosTest** — stateful chaos testing with auto-injected nemesis, swarm mode
|
|
8
|
+
- **Faults** — io, numerical, timing fault primitives + PatchFault/LambdaFault base
|
|
9
|
+
- **Assertions** — always/sometimes/reachable/unreachable (Antithesis model)
|
|
10
|
+
- **Invariants** — composable named checks (no_nan & bounded(0,1))
|
|
11
|
+
- **Buggify** — FoundationDB-style inline fault injection
|
|
12
|
+
- **QuickCheck** — @quickcheck decorator with boundary-biased generation
|
|
13
|
+
- **Simulate** — Clock and FileSystem for no-mock testing
|
|
14
|
+
- **Mutations** — AST-based mutation testing (arithmetic, comparison, negate, return_none)
|
|
15
|
+
- **Explorer** — coverage-guided exploration with checkpointing, energy scheduling, shrinking
|
|
16
|
+
- **Traces** — JSON recording, replay, delta-debugging shrinking
|
|
17
|
+
- **CLI** — `ordeal explore` and `ordeal replay`
|
|
18
|
+
- **Config** — `ordeal.toml` driven configuration
|
|
19
|
+
- **Plugin** — pytest integration (--chaos, --chaos-seed, @pytest.mark.chaos)
|
|
20
|
+
- **Integrations** — Atheris (coverage-guided fuzzing), Schemathesis (API chaos)
|
ordeal-0.0.0/CLAUDE.md
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
## Project
|
|
4
|
+
|
|
5
|
+
ordeal — Automated chaos testing for Python. Fault injection, property assertions, coverage-guided exploration, and stateful testing in one library.
|
|
6
|
+
|
|
7
|
+
Built on ideas from Antithesis (deterministic exploration), FoundationDB (BUGGIFY inline faults), Jepsen (nemesis interleaving), Hypothesis (stateful property testing), Jane Street QuickCheck (boundary-biased generation), and Meta ACH (mutation validation).
|
|
8
|
+
|
|
9
|
+
## Commands
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
uv sync # install dependencies
|
|
13
|
+
uv run pytest # run all tests (~205 tests)
|
|
14
|
+
uv run pytest tests/test_X.py # single module
|
|
15
|
+
uv run pytest -x # stop on first failure
|
|
16
|
+
uv run pytest --chaos # enable chaos mode in tests
|
|
17
|
+
uv run pytest --chaos-seed 42 # reproducible chaos
|
|
18
|
+
uv run ruff check . # lint
|
|
19
|
+
uv run ruff format --check . # check formatting
|
|
20
|
+
uv run ruff format . # auto-format
|
|
21
|
+
uv run ordeal explore # run coverage-guided explorer (reads ordeal.toml)
|
|
22
|
+
uv run ordeal replay <trace> # replay a failure trace
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Architecture
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
ordeal/
|
|
29
|
+
├── __init__.py Public API: ChaosTest, rule, invariant, always, sometimes, buggify, etc.
|
|
30
|
+
├── chaos.py ChaosTest base class (extends Hypothesis RuleBasedStateMachine)
|
|
31
|
+
├── explore.py Coverage-guided explorer — AFL-style edge hashing, energy scheduling
|
|
32
|
+
├── assertions.py always / sometimes / reachable / unreachable (Antithesis model)
|
|
33
|
+
├── buggify.py Inline fault injection (FoundationDB BUGGIFY model)
|
|
34
|
+
├── quickcheck.py @quickcheck decorator with boundary-biased type-driven strategies
|
|
35
|
+
├── simulate.py Deterministic simulation primitives: Clock, FileSystem
|
|
36
|
+
├── invariants.py Composable invariants with & operator: no_nan & bounded(0, 1)
|
|
37
|
+
├── mutations.py AST-based mutation testing with 4 operators
|
|
38
|
+
├── trace.py Trace recording, JSON serialization, replay, delta-debugging shrink
|
|
39
|
+
├── config.py ordeal.toml loader with strict validation
|
|
40
|
+
├── cli.py CLI entry point: ordeal explore / ordeal replay
|
|
41
|
+
├── plugin.py Pytest plugin: --chaos, --chaos-seed, --buggify-prob flags
|
|
42
|
+
├── strategies.py Adversarial Hypothesis strategies for fuzzing
|
|
43
|
+
├── faults/
|
|
44
|
+
│ ├── __init__.py Fault / PatchFault / LambdaFault base abstractions
|
|
45
|
+
│ ├── io.py error_on_call, disk_full, permission_denied, corrupt/truncate output
|
|
46
|
+
│ ├── numerical.py nan_injection, inf_injection, wrong_shape, corrupted_floats
|
|
47
|
+
│ └── timing.py timeout, slow, intermittent_crash, jitter
|
|
48
|
+
└── integrations/
|
|
49
|
+
├── atheris_engine.py Coverage-guided fuzzing bridge (optional: atheris)
|
|
50
|
+
└── schemathesis_ext.py API chaos testing bridge (optional: schemathesis)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Key design decisions
|
|
54
|
+
|
|
55
|
+
- **ChaosTest** extends `hypothesis.stateful.RuleBasedStateMachine`. A **nemesis rule** is auto-injected to toggle faults during exploration. Hypothesis explores rule interleavings + fault schedules.
|
|
56
|
+
- **Swarm mode**: Each test run uses a random subset of faults. Better aggregate coverage than all-faults-always-on.
|
|
57
|
+
- **Energy scheduling**: Checkpoints that led to new edge coverage get higher selection probability. Constants: reward=2.0, decay=0.95, min=0.01.
|
|
58
|
+
- **Assertions**: `always`/`unreachable` raise immediately (triggers Hypothesis shrinking). `sometimes`/`reachable` are deferred — checked at session end via PropertyTracker.
|
|
59
|
+
- **buggify()**: No-op when chaos mode is inactive. Thread-local RNG, seed-controlled, zero overhead in production.
|
|
60
|
+
- **PatchFault**: Resolves a dotted path (e.g. `"myapp.api.call"`) and wraps the target function with fault behavior. Activate/deactivate cycle managed by ChaosTest.
|
|
61
|
+
- **Optional deps**: atheris, schemathesis, numpy are behind try/except imports with helpful error messages.
|
|
62
|
+
|
|
63
|
+
## Conventions
|
|
64
|
+
|
|
65
|
+
- Python >= 3.12. Type hints throughout.
|
|
66
|
+
- `ruff` for lint and format. Line length 99. Rules: E, F, I, W.
|
|
67
|
+
- Tests in `tests/`. Test files prefixed `test_*.py`. Helper modules prefixed `_*.py`.
|
|
68
|
+
- Configuration via `ordeal.toml` — see `ordeal.toml.example` for full schema.
|
|
69
|
+
- Hypothesis stateful API (`rule`, `invariant`, `initialize`, `precondition`, `Bundle`) is re-exported from `ordeal.__init__`.
|
|
70
|
+
- Version derived from git tags via `setuptools-scm`.
|
|
71
|
+
|
|
72
|
+
## Dependencies
|
|
73
|
+
|
|
74
|
+
- **Required**: hypothesis >= 6.100.0, pytest >= 8.0.0
|
|
75
|
+
- **Optional extras**:
|
|
76
|
+
- `ordeal[atheris]` — coverage-guided fuzzing via Google Atheris
|
|
77
|
+
- `ordeal[api]` — API chaos testing via Schemathesis
|
|
78
|
+
- `ordeal[all]` — everything including numpy
|
|
79
|
+
- **Dev**: ruff, pytest-cov (`pip install ordeal[dev]`)
|
|
80
|
+
|
|
81
|
+
## Common tasks
|
|
82
|
+
|
|
83
|
+
### Add a new fault type
|
|
84
|
+
|
|
85
|
+
1. Add a function in the appropriate `ordeal/faults/*.py` module that returns a `PatchFault` or `LambdaFault`.
|
|
86
|
+
2. The function takes a `target` dotted path and fault-specific parameters.
|
|
87
|
+
3. Add tests in `tests/test_faults.py`.
|
|
88
|
+
4. Document in `docs/api-reference.md`.
|
|
89
|
+
|
|
90
|
+
### Add a new assertion
|
|
91
|
+
|
|
92
|
+
1. Add the function in `ordeal/assertions.py`.
|
|
93
|
+
2. If deferred (like `sometimes`), register with the global `tracker: PropertyTracker`.
|
|
94
|
+
3. Export from `ordeal/__init__.py` and add to `__all__`.
|
|
95
|
+
4. Add tests in `tests/test_assertions.py`.
|
|
96
|
+
|
|
97
|
+
### Add a new invariant
|
|
98
|
+
|
|
99
|
+
1. Add a function in `ordeal/invariants.py` that returns an `Invariant` instance.
|
|
100
|
+
2. Invariants compose with `&`. Numpy support is optional — guard with try/except.
|
|
101
|
+
3. Add tests in `tests/test_invariants.py`.
|
|
102
|
+
|
|
103
|
+
### Add a new mutation operator
|
|
104
|
+
|
|
105
|
+
1. Create an AST `NodeTransformer` subclass in `ordeal/mutations.py`.
|
|
106
|
+
2. Register it in `_APPLICATORS` dict with a string key.
|
|
107
|
+
3. The applicator yields `Mutant` objects with location and description.
|
|
108
|
+
4. Add tests in `tests/test_battle.py` or a dedicated test file.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Contributing to ordeal
|
|
2
|
+
|
|
3
|
+
## Setup
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
git clone https://github.com/teilomillet/ordeal
|
|
7
|
+
cd ordeal
|
|
8
|
+
uv sync --extra dev
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Development workflow
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
uv run pytest # run tests
|
|
15
|
+
uv run pytest tests/test_X.py # single module
|
|
16
|
+
uv run pytest -x # stop on first failure
|
|
17
|
+
uv run ruff check . # lint
|
|
18
|
+
uv run ruff format . # format
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Submitting changes
|
|
22
|
+
|
|
23
|
+
1. Fork the repo and create a branch from `main`.
|
|
24
|
+
2. Write tests for your changes.
|
|
25
|
+
3. Ensure `uv run pytest` and `uv run ruff check .` pass.
|
|
26
|
+
4. Open a pull request.
|
|
27
|
+
|
|
28
|
+
## Project structure
|
|
29
|
+
|
|
30
|
+
See [CLAUDE.md](CLAUDE.md) for architecture, conventions, and common contribution recipes.
|
|
31
|
+
|
|
32
|
+
## Adding a new fault type
|
|
33
|
+
|
|
34
|
+
1. Create a function in `ordeal/faults/` that returns a `PatchFault` or `LambdaFault`.
|
|
35
|
+
2. Add tests in `tests/test_faults.py`.
|
|
36
|
+
3. Document in `docs/api-reference.md`.
|
|
37
|
+
|
|
38
|
+
## Adding a new assertion
|
|
39
|
+
|
|
40
|
+
1. Add the function in `ordeal/assertions.py`.
|
|
41
|
+
2. Export from `ordeal/__init__.py` and add to `__all__`.
|
|
42
|
+
3. Add tests in `tests/test_assertions.py`.
|