# Testing Guide
This guide explains how to run, extend, and debug the test suites across all
Synta crates and language bindings. For CI configuration see
[Contributing](contribution.md#running-ci-locally); for architecture background
see [System Architecture](system-architecture.md).
---
## Test Suite Overview
| Core DER/BER unit tests | `tests/*.rs` | Decoder, encoder, all ASN.1 types, tag/length, roundtrip, serde, BER indefinite-length |
| Certificate tests | `synta-certificate/tests/` | X.509/CRL/CSR/OCSP parsing, PKCS#7/12, algorithm IDs, owned types |
| Codegen tests | `synta-codegen/tests/` | ASN.1 schema parsing and Rust code generation |
| Kerberos tests | `synta-krb5/tests/` | Kerberos V5 ASN.1 structures |
| MTC tests | `synta-mtc/tests/` | Merkle Tree Certificate validation and property tests |
| x509-limbo | `synta-x509-verification/tests/limbo/` | RFC 5280 path validation compliance (~39 MB harness) |
| Python binding tests | `tests/python/` | Full Python API surface via pytest |
| C FFI tests | `tests/c/` | C API bindings via `make` |
---
## Running Tests
### All tests at once
```bash
./contrib/ci/local-ci.sh test
```
This runs `cargo test --workspace --all-features` on the stable, beta, and
nightly toolchains in sequence.
### Individual crate tests
```bash
# Core ASN.1 parser
cargo test -p synta
# X.509 / PKI
cargo test -p synta-certificate
# Code generator
cargo test -p synta-codegen --all-features
# Kerberos types
cargo test -p synta-krb5
# Merkle Tree Certificates
cargo test -p synta-mtc
# RFC 5280 path validation (x509-limbo)
cargo test -p synta-x509-verification
```
### Python binding tests
The Python binding must be compiled first. Use `maturin develop` (recommended
for development) or the CI build step:
```bash
# Quick development cycle
cd synta-python
uv venv
uv pip install maturin pytest
uv run maturin develop
uv run pytest ../tests/python/ -v
# Or use the CI helper (also builds the release .so)
./contrib/ci/local-ci.sh python-test
```
Alternatively, if you have a compiled `.so` in `python/`:
```bash
PYTHONPATH=python python3 -m pytest tests/python/ -v
```
### C FFI tests
Build the shared library first, then run the C test suite:
```bash
cargo build --release -p synta-ffi
make -C tests/c test
```
For memory-error checking:
```bash
make -C tests/c valgrind
```
### RFC 5280 compliance (x509-limbo)
The x509-limbo test vectors are large (~39 MB). They are checked out
automatically by the test runner if the `tests/limbo/` directory contains the
harness JSON:
```bash
./contrib/ci/local-ci.sh test-limbo
```
---
## Test Vectors
Binary DER/BER test vectors live under `tests/vectors/`. They are organised
by standard:
```
tests/vectors/
├── pkcs/ # PKCS#7, #8, #10, #12 DER binaries
├── cryptography/ # Vectors from the cryptography Python library
├── certs/ # X.509 certificate DER files
└── README.md # Origin and licence notes for each vector set
```
When adding a new vector:
1. Place the raw binary under the appropriate subdirectory.
2. Write a test that decodes it and asserts expected field values.
3. Document the origin and licence in `tests/vectors/README.md`.
---
## Serde Tests
Serde support is feature-gated (`--features serde`). Run serde tests in
isolation to avoid interference from non-serde builds:
```bash
./contrib/ci/local-ci.sh test-serde
# Equivalent to:
cargo test -p synta --features serde
```
---
## Writing New Tests
### Rust unit / integration tests
Place unit tests in a `#[cfg(test)]` module at the bottom of the source file
they test. Integration tests go in `tests/` at the crate root.
```rust
#[cfg(test)]
mod tests {
use super::*;
use synta::{Decoder, Encoding};
#[test]
fn decode_my_type() {
let der = hex::decode("3003020101").unwrap();
let mut dec = Decoder::new(&der, Encoding::Der);
let val = dec.decode::<MyType>().unwrap();
assert_eq!(val.field, 1);
}
}
```
### Python tests
Python tests use `pytest` and live in `tests/python/`. Always set
`PYTHONPATH=python` (or use the `maturin develop` environment):
```python
import synta
def test_decode_certificate(der_bytes):
cert = synta.Certificate.from_der(der_bytes)
assert cert.serial_number is not None
```
### C FFI tests
C tests are small programs in `tests/c/`. Each must link against `libcsynta`
(the Makefile handles this) and follow the OpenSSL-style ownership convention:
- `synta_*_parse_der()` returns an owned handle.
- `synta_*_free()` frees it; call it exactly once.
- `get0_*()` getters return borrowed pointers valid while the parent is alive.
---
## Code Coverage
Coverage reports can be generated with `cargo-llvm-cov`:
```bash
cargo llvm-cov --workspace --html --open
# Or for a lcov report:
cargo llvm-cov --workspace --lcov --output-path coverage/lcov.info
```
Existing `.profraw` files in the repository root and `synta-certificate/` are
from previous coverage runs and can be safely deleted.
---
## Fuzzing
The `synta-fuzz` crate provides a structured ASN.1 fuzzer:
```bash
cargo +nightly fuzz run fuzz_target -- -max_len=65536
```
Seeds for the fuzzer live in `tests/fuzz/corpus/`. Add any DER files that
exercise new code paths to expand the corpus.
---
## Continuous Integration
The full test pipeline is described in [Contributing](contribution.md#running-ci-locally).
Key jobs for testing:
| `test` | `cargo test --workspace` | stable + beta + nightly |
| `test-certificate` | `cargo test -p synta-certificate` | PKI types |
| `test-codegen` | `cargo test -p synta-codegen --all-features` | ASN.1 codegen |
| `test-krb5` | `cargo test -p synta-krb5` | Kerberos types |
| `test-mtc` | `cargo test -p synta-mtc` | MTC validation |
| `test-limbo` | `cargo test -p synta-x509-verification` | x509-limbo RFC 5280 compliance |
| `test-serde` | `cargo test -p synta --features serde` | Serde roundtrip |
| `python-test` | `pytest tests/python/` | Python bindings |
| `c-test` | `make -C tests/c test` | C FFI |
---
## See Also
- [Contributing](contribution.md) — commit conventions, CI setup, code style
- [System Architecture](system-architecture.md) — crate dependency graph
- [Codebase Summary](codebase-summary.md) — file inventory and test suite table
- [Limitations](limitations.md) — known unsupported ASN.1 constructs