Skip to content

Commit 1d555dd

Browse files
r41k0uCopilot
andcommitted
Tests: Add tests/README.md
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent ee44444 commit 1d555dd

File tree

1 file changed

+116
-0
lines changed

1 file changed

+116
-0
lines changed

tests/README.md

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# PythonBPF Test Suite
2+
3+
## Quick start
4+
5+
```bash
6+
# Activate the venv and install test deps (once)
7+
source .venv/bin/activate
8+
uv pip install -e ".[test]"
9+
10+
# Run the full suite (IR + LLC levels, no sudo required)
11+
make test
12+
13+
# Run with coverage report
14+
make test-cov
15+
```
16+
17+
## Test levels
18+
19+
Tests are split into three levels, each in a separate file:
20+
21+
| Level | File | What it checks | Needs sudo? |
22+
|---|---|---|---|
23+
| 1 — IR generation | `test_ir_generation.py` | `compile_to_ir()` completes without exception or `logging.ERROR` | No |
24+
| 2 — LLC compilation | `test_llc_compilation.py` | Level 1 + `llc` produces a non-empty `.o` file | No |
25+
| 3 — Kernel verifier | `test_verifier.py` | `bpftool prog load -d` exits 0 | Yes |
26+
27+
Levels 1 and 2 run together with `make test`. Level 3 is opt-in:
28+
29+
```bash
30+
make test-verifier # requires bpftool and sudo
31+
```
32+
33+
## Running a single test
34+
35+
Tests are parametrized by file path. Use `-k` to filter:
36+
37+
```bash
38+
# By file name
39+
pytest tests/ -v -k "and.py" -m "not verifier"
40+
41+
# By category
42+
pytest tests/ -v -k "conditionals" -m "not verifier"
43+
44+
# One specific level only
45+
pytest tests/test_ir_generation.py -v -k "hash_map.py"
46+
```
47+
48+
## Coverage report
49+
50+
```bash
51+
make test-cov
52+
```
53+
54+
- **Terminal**: shows per-file coverage with missing lines after the test run.
55+
- **HTML**: written to `htmlcov/index.html` — open in a browser for line-by-line detail.
56+
57+
```bash
58+
xdg-open htmlcov/index.html
59+
```
60+
61+
`htmlcov/` and `.coverage` are excluded from git (listed in `.gitignore` if not already).
62+
63+
## Expected failures (`test_config.toml`)
64+
65+
Known-broken tests are declared in `tests/test_config.toml`:
66+
67+
```toml
68+
[xfail]
69+
"failing_tests/my_test.py" = {reason = "...", level = "ir"}
70+
```
71+
72+
- `level = "ir"` — fails during IR generation; both IR and LLC tests are marked xfail.
73+
- `level = "llc"` — IR generates fine but `llc` rejects it; only the LLC test is marked xfail.
74+
75+
All xfails use `strict = True`: if a test starts **passing** it shows up as **XPASS** and is treated as a test failure. This is intentional — it means the bug was fixed and the test should be promoted to `passing_tests/`.
76+
77+
## Adding a new test
78+
79+
1. Create a `.py` file in `tests/passing_tests/<category>/` with the usual `@bpf` decorators and a `compile()` call at the bottom.
80+
2. Run `make test` — the file is discovered and tested automatically at all levels.
81+
3. If the test is expected to fail, add it to `tests/test_config.toml` instead of `passing_tests/`.
82+
83+
## Directory structure
84+
85+
```
86+
tests/
87+
├── README.md ← you are here
88+
├── conftest.py ← pytest config: discovery, xfail/skip injection, fixtures
89+
├── test_config.toml ← expected-failure list
90+
├── test_ir_generation.py ← Level 1
91+
├── test_llc_compilation.py ← Level 2
92+
├── test_verifier.py ← Level 3 (opt-in, sudo)
93+
├── framework/
94+
│ ├── bpf_test_case.py ← BpfTestCase dataclass
95+
│ ├── collector.py ← discovers test files, reads test_config.toml
96+
│ ├── compiler.py ← wrappers around compile_to_ir() + _run_llc()
97+
│ └── verifier.py ← bpftool subprocess wrapper
98+
├── passing_tests/ ← programs that should compile and verify cleanly
99+
└── failing_tests/ ← programs with known issues (declared in test_config.toml)
100+
```
101+
102+
## Known regressions (as of compilation-context PR merge)
103+
104+
Three tests in `passing_tests/` currently fail — these are bugs to fix, not xfails:
105+
106+
| Test | Error |
107+
|---|---|
108+
| `passing_tests/assign/comprehensive.py` | `TypeError: cannot store i64* to i64*` |
109+
| `passing_tests/helpers/bpf_probe_read.py` | `ValueError: 'ctx' not in local symbol table` |
110+
| `passing_tests/vmlinux/register_state_dump.py` | `KeyError: 'cs'` |
111+
112+
Nine tests in `failing_tests/` were fixed by the compilation-context PR (they show as XPASS). They can be moved to `passing_tests/` when convenient:
113+
114+
`assign/retype.py`, `conditionals/helper_cond.py`, `conditionals/oneline.py`,
115+
`direct_assign.py`, `globals.py`, `if.py`, `license.py` (IR only), `named_arg.py`,
116+
`xdp/xdp_test_1.py`

0 commit comments

Comments
 (0)