212 lines
5.2 KiB
Markdown
212 lines
5.2 KiB
Markdown
# eBPF Reachability Test Fixtures
|
|
|
|
This directory contains frozen test fixtures for determinism validation of the eBPF evidence collection system.
|
|
|
|
## Directory Structure
|
|
|
|
```
|
|
fixtures/ebpf/
|
|
├── README.md # This file
|
|
├── proc/ # Mock /proc filesystem data
|
|
│ ├── {pid}-maps.txt # Memory map files
|
|
│ └── {pid}-cgroup.txt # Cgroup membership
|
|
├── elf/ # Mock ELF symbol data
|
|
│ └── *-symbols.json # Symbol tables in JSON format
|
|
├── events/ # Simulated eBPF events
|
|
│ └── *-events.json # Event sequences by type
|
|
└── golden/ # Expected NDJSON output
|
|
└── *-golden.ndjson # Canonical output for comparison
|
|
```
|
|
|
|
## Fixture Types
|
|
|
|
### /proc Filesystem Fixtures (`proc/`)
|
|
|
|
Mock `/proc/{pid}/maps` and `/proc/{pid}/cgroup` files for testing symbol resolution and container identification.
|
|
|
|
**Format for maps:**
|
|
```
|
|
start-end permissions offset device inode pathname
|
|
7f0000000000-7f0000001000 r--p 00000000 fd:01 12345678 /lib/libc.so.6
|
|
```
|
|
|
|
**Format for cgroup:**
|
|
```
|
|
0::/system.slice/containerd.service/container-id
|
|
```
|
|
|
|
### ELF Symbol Fixtures (`elf/`)
|
|
|
|
JSON representation of ELF symbol tables for testing address resolution.
|
|
|
|
**Schema:**
|
|
```json
|
|
{
|
|
"path": "/path/to/binary",
|
|
"format": "ELF64",
|
|
"symbols": [
|
|
{ "name": "symbol_name", "address": "0x1000", "size": 256, "type": "FUNC" }
|
|
],
|
|
"buildId": "hexstring"
|
|
}
|
|
```
|
|
|
|
### Event Fixtures (`events/`)
|
|
|
|
JSON arrays of simulated eBPF events with binary-compatible structures.
|
|
|
|
**Event Types:**
|
|
- `1` - File access (sys_enter_openat)
|
|
- `2` - Process exec (sched_process_exec)
|
|
- `3` - TCP state (inet_sock_set_state)
|
|
- `4` - Network op (uprobe connect/accept)
|
|
- `5` - SSL op (uprobe SSL_read/SSL_write)
|
|
- `6` - Symbol call (uprobe function)
|
|
|
|
### Golden Output Fixtures (`golden/`)
|
|
|
|
Canonical NDJSON files representing expected output when processing event fixtures with enrichment.
|
|
|
|
**Requirements:**
|
|
- Sorted JSON keys (alphabetical)
|
|
- No trailing whitespace
|
|
- Single newline per record
|
|
- No pretty-printing
|
|
|
|
## Determinism Testing
|
|
|
|
### Running Tests
|
|
|
|
```bash
|
|
# Run determinism tests
|
|
dotnet test --filter "Category=Determinism"
|
|
|
|
# Verify against golden files
|
|
dotnet test --filter "FullyQualifiedName~GoldenFileTests"
|
|
```
|
|
|
|
### Updating Golden Files
|
|
|
|
**IMPORTANT:** Only update golden files when schema changes are intentional.
|
|
|
|
1. Set environment variable to enable updates:
|
|
```bash
|
|
export STELLAOPS_UPDATE_FIXTURES=true
|
|
```
|
|
|
|
2. Run the test that generates output:
|
|
```bash
|
|
dotnet test --filter "FullyQualifiedName~GenerateGoldenOutput"
|
|
```
|
|
|
|
3. Review changes carefully:
|
|
```bash
|
|
git diff tests/reachability/fixtures/ebpf/golden/
|
|
```
|
|
|
|
4. Commit with explanation:
|
|
```bash
|
|
git add tests/reachability/fixtures/ebpf/golden/
|
|
git commit -m "Update golden files: <reason for change>"
|
|
```
|
|
|
|
### CI Integration
|
|
|
|
The CI workflow runs determinism tests automatically:
|
|
|
|
```yaml
|
|
# .gitea/workflows/test.yaml
|
|
- name: Determinism Tests
|
|
run: dotnet test --filter "Category=Determinism"
|
|
env:
|
|
STELLAOPS_UPDATE_FIXTURES: "false" # Never auto-update in CI
|
|
```
|
|
|
|
If tests fail:
|
|
1. Check if schema changes were intentional
|
|
2. If intentional, update golden files locally and commit
|
|
3. If unintentional, fix the determinism bug
|
|
|
|
## Adding New Fixtures
|
|
|
|
### Adding a New Event Type
|
|
|
|
1. Create input fixture in `events/`:
|
|
```json
|
|
// events/new-type-events.json
|
|
[
|
|
{
|
|
"event_type": 7,
|
|
"timestamp_ns": 1000000000000,
|
|
...
|
|
}
|
|
]
|
|
```
|
|
|
|
2. Generate golden output:
|
|
```bash
|
|
STELLAOPS_UPDATE_FIXTURES=true dotnet test --filter "GenerateNewTypeGolden"
|
|
```
|
|
|
|
3. Verify output is deterministic:
|
|
```bash
|
|
# Run multiple times, output should be identical
|
|
for i in {1..3}; do
|
|
dotnet test --filter "NewTypeGolden" 2>/dev/null
|
|
sha256sum golden/new-type-golden.ndjson
|
|
done
|
|
```
|
|
|
|
### Adding a New Process Fixture
|
|
|
|
1. Create mock `/proc` files:
|
|
```bash
|
|
# proc/{pid}-maps.txt
|
|
# proc/{pid}-cgroup.txt
|
|
```
|
|
|
|
2. Create corresponding ELF symbols if needed:
|
|
```bash
|
|
# elf/{binary}-symbols.json
|
|
```
|
|
|
|
3. Update container mapping in test setup
|
|
|
|
## Validation
|
|
|
|
Golden files must satisfy these constraints:
|
|
|
|
1. **Byte-identical output**: Same input always produces same output
|
|
2. **Sorted keys**: JSON keys in alphabetical order
|
|
3. **No floating point**: Use integers for all numeric values
|
|
4. **UTF-8 NFC**: All strings in NFC normalization form
|
|
5. **No null values**: Omit fields with null values
|
|
6. **Consistent timestamps**: Use nanoseconds since boot
|
|
|
|
Run validation:
|
|
```bash
|
|
# Validate golden file format
|
|
stella evidence validate tests/reachability/fixtures/ebpf/golden/*.ndjson
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Test Fails: "Output differs from golden file"
|
|
|
|
1. Check for unintended schema changes
|
|
2. Verify timestamp handling is deterministic
|
|
3. Check for locale-dependent formatting
|
|
4. Ensure random values aren't leaking into output
|
|
|
|
### Test Fails: "Cannot load fixture"
|
|
|
|
1. Verify fixture file exists and is valid JSON
|
|
2. Check file permissions
|
|
3. Ensure no BOM in JSON files
|
|
|
|
### Test Fails: "Symbol resolution failed"
|
|
|
|
1. Verify mock maps file has correct format
|
|
2. Check address ranges don't overlap
|
|
3. Ensure symbol addresses are within mapped regions
|