save progress

This commit is contained in:
StellaOps Bot
2026-01-03 15:27:15 +02:00
parent d486d41a48
commit bc4dd4f377
70 changed files with 8531 additions and 653 deletions

View File

@@ -0,0 +1,195 @@
# VexLens Testing Strategy
## Overview
This document describes the testing strategy for VexLens module, covering determinism verification, regression testing, and golden corpus validation.
## Test Categories
### 1. Unit Tests (`Category=Unit`)
Standard unit tests for individual components:
- **Location:** `src/VexLens/StellaOps.VexLens/__Tests/StellaOps.VexLens.Tests/`
- **Coverage:** Models, builders, serializers, individual consensus components
- **Run frequency:** Every PR, every commit
### 2. Determinism Tests (`Category=Determinism`)
Tests that verify VexLens produces identical outputs for identical inputs:
- **Location:** `src/VexLens/StellaOps.VexLens/__Tests/StellaOps.VexLens.Tests/Determinism/`
- **Key tests:**
- `VexProofShuffleDeterminismTests` - Verifies statement order doesn't affect consensus
- `VexLensPipelineDeterminismTests` - E2E pipeline structural determinism
- **Run frequency:** Nightly regression suite
- **Requirements:** Fixed `TimeProvider` injection for reproducible timestamps
#### Known Limitations
The `VexProofBuilder.GenerateProofId()` method currently uses `Guid.NewGuid()` which introduces non-determinism in the ProofId (and consequently the Digest). This is tracked as risk R-003 and violates AGENTS.md Rule 8.2 (Inject TimeProvider / ID generators). Until `IGuidGenerator` injection is added, determinism tests validate structural determinism rather than byte-identical outputs.
### 3. Regression Tests (`Category=Regression`)
Tests that validate known scenarios produce expected verdicts:
- **Location:** `src/VexLens/StellaOps.VexLens/__Tests/StellaOps.VexLens.Tests/Regression/`
- **Key tests:**
- Fixed package verdict validation
- Not_affected with justification
- Conflict resolution via lattice precedence
- Backport scenario handling
- Under_investigation status preservation
- Signature verification confidence bonus
- Same-issuer temporal precedence
- **Run frequency:** Nightly regression suite
### 4. Golden Corpus Tests (`Category=Golden`)
Tests using curated real-world backport scenarios:
- **Location:** `src/VexLens/StellaOps.VexLens/__Tests/StellaOps.VexLens.Tests/GoldenCorpus/`
- **Data location:** `src/__Tests/__Datasets/GoldenBackports/`
- **Coverage:** 20 backport cases across 8 distributions (Debian, Ubuntu, RHEL, SUSE, CentOS, Alpine, Fedora, Rocky/Alma, Amazon Linux, Oracle Linux)
- **Run frequency:** Nightly regression suite
## Test Infrastructure
### Golden Corpus Structure
```
src/__Tests/__Datasets/GoldenBackports/
├── index.json # Corpus index with case metadata
├── CVE-YYYY-XXXXX-distro-package/
│ └── case.json # Individual test case
└── ...
```
### Case Schema
```json
{
"id": "case identifier",
"cve": "CVE-YYYY-XXXXX",
"distro": {
"name": "debian|rhel|...",
"version": "7|8|...",
"family": "debian|rpm|..."
},
"package": {
"name": "package-name",
"binary": "binary-name",
"vulnerableEvr": "vulnerable EVR",
"patchedEvr": "patched EVR"
},
"upstream": {
"vulnerableRange": "SemVer constraint",
"fixedVersion": "upstream fix version"
},
"expectedVerdict": {
"status": "fixed|not_affected|affected",
"reason": "backport_detected|...",
"upstreamWouldSay": "affected|..."
},
"evidence": {
"advisoryUrl": "URL to advisory",
"patchCommit": "optional commit hash",
"notes": "explanation"
}
}
```
### Test Runner Components
1. **GoldenCorpusLoader** - Loads and filters corpus cases
2. **GoldenCorpusTestRunner** - Executes evaluator against corpus
3. **GoldenCorpusTests** - xUnit test class for corpus validation
## CI Integration
### Nightly Regression (`.gitea/workflows/nightly-regression.yml`)
Test categories run nightly:
- Unit
- Architecture
- Contract
- Integration
- Security
- Golden
- **Determinism**
- **Regression**
### PR Gating
Quick tests run on every PR:
- Unit tests only
- Build determinism check
## Test Best Practices
### 1. Use FakeTimeProvider
Always inject `Microsoft.Extensions.Time.Testing.FakeTimeProvider` to ensure deterministic timestamps:
```csharp
private readonly FakeTimeProvider _timeProvider;
private readonly DateTimeOffset _fixedTime = new(2026, 1, 3, 12, 0, 0, TimeSpan.Zero);
public MyTests()
{
_timeProvider = new FakeTimeProvider(_fixedTime);
}
```
### 2. Set Confidence Explicitly
The `VexProofBuilder` calculates confidence from explicit weight values. For predictable test assertions, set all confidence-affecting properties:
```csharp
builder
.WithWeightSpread(0.95m)
.WithConditionCoverage(1.0m)
.WithSignatureBonus(0.10m)
.WithFreshnessBonus(0.05m);
```
### 3. Set Justification with Status
When testing `not_affected` status, pass justification to `WithFinalStatus`:
```csharp
.WithFinalStatus(VexStatus.NotAffected, VexJustification.VulnerableCodeNotPresent)
```
### 4. Use Correct Types
The `AddStatement` method requires proper types:
- `VexProofIssuer` - Not a string
- `VexProofWeight` with `VexProofWeightFactors` - Not a decimal
```csharp
builder.AddStatement(
id: "stmt-001",
source: "vendor-csaf",
issuer: new VexProofIssuer("Vendor", IssuerCategory.Vendor, TrustTier.Authoritative),
status: VexStatus.Fixed,
justification: null,
weight: new VexProofWeight(0.95m, new VexProofWeightFactors(0.95m, 1.0m, 0.9m, 1.0m, 0.8m)),
timestamp: _fixedTime,
signatureVerified: true);
```
### 5. IssuerCategory and TrustTier Values
Valid `IssuerCategory` values:
- `Unknown`, `Vendor`, `Distributor`, `Community`, `Internal`, `Aggregator`
Valid `TrustTier` values:
- `Authoritative`, `Trusted`, `Untrusted`, `Unknown`
## Future Improvements
1. **Inject IGuidGenerator** - Enable full digest determinism (R-003)
2. **Expand golden corpus** - Add more edge cases and distributions
3. **Property-based testing** - Use FsCheck for fuzzing VEX inputs
4. **Mutation testing** - Use Stryker.NET to validate test coverage quality