guildhouse-spire-plugins/docs/testing.md
Tyler King 420a4e2ea0 Remediate all 17 audit findings from AUDIT.md
Critical fixes:
- F-01: SatScope array form support (single pointer → slice with polymorphic JSON)
- F-02: Add governance-intent@guildhouse.dev as 10th Shellstream extension
- F-06: Replace os.Exit(1) stubs with go-plugin Serve() boilerplate in all cmd/
- F-13: Validate SatScope.ResourcePattern is non-empty

High priority:
- F-03: Add normative Accord policy syntax note to credential-governance.md §8.2
- F-04: Replace OID XXXXX placeholder with explicit PEN reference and IANA TODO
- F-05: Document CredentialComposer hook mapping in spec and plugin-types.md
- F-07/F-08: Commit CI pipeline (.github/workflows/ci.yaml)
- F-09: Add hashicorp/go-plugin v1.6.3 to go.mod

Medium priority:
- F-10: Wire sample-ssh-cert-extensions.json fixture into shellstream tests
- F-11: Cross-reference merkle proof depth limit (256 leaves) in governance spec
- F-12: Add YAML format clarification headers to deploy configs
- F-14: Expand README with project status, docs links, and quick-start

Low priority:
- F-15: Standardize "SSH SVID" → "SSH-SVID" terminology across docs
- F-16: Add GovernanceEpochSeconds to PluginConfig and deploy configs
- F-17: Add troubleshooting section to deployment.md, error handling to OIDC docs

Global: Rename all extension keys from @guildhouse.io to @guildhouse.dev

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 11:45:33 -05:00

105 lines
3.5 KiB
Markdown

# Testing Strategy
How to test the Guildhouse SPIRE plugins.
## Running Tests
```bash
make test # Run all tests
make lint # Run go vet
# Verbose output
go test -v ./...
# Single package
go test -v ./pkg/shellstream/...
# With coverage
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out
```
## Test Structure
### Unit Tests (`pkg/`)
Each package has `*_test.go` files with unit tests:
| Package | Tests | Coverage Focus |
|---------|-------|---------------|
| `pkg/shellstream` | ~28 tests | Encode/decode round-trips, validation rules, format constraints, co-occurrence rules |
| `pkg/oidc` | 2 tests | Config validation (scaffolded) |
| `pkg/governance` | 2 tests | Client construction (scaffolded) |
| `pkg/sshcert` | 3 tests | Builder config validation (scaffolded) |
| `pkg/config` | 2 tests | Plugin config validation (scaffolded) |
### `pkg/shellstream` Tests (Fully Implemented)
The shellstream package has comprehensive tests covering:
- **Round-trip**: Encode → Decode produces identical values (full and minimal)
- **Required fields**: Missing tenant-id, missing roles produce validation errors
- **Format validation**: Invalid UUID, wrong hex length, uppercase hex, invalid base64
- **Co-occurrence**: sat-scope without sat-hash, ceremony-id without ceremony-type, merkle-proof without merkle-root
- **Parsing**: JSON sat-scope, comma-separated roles, base64 merkle proof, uint64 governance epoch
- **Edge cases**: Epoch value 0, nil extensions, unknown extensions ignored
- **Enum validation**: Unknown ceremony-type rejected
### Integration Test Approach (Future)
When plugin implementations are complete, integration tests will use mock gRPC servers:
```go
// Example mock GovernanceService
type mockGovernanceServer struct {
quartermasterv1.UnimplementedGovernanceServiceServer
intents map[string]*Intent
}
func (s *mockGovernanceServer) CreateIntent(ctx context.Context, req *quartermasterv1.CreateIntentRequest) (*quartermasterv1.CreateIntentResponse, error) {
// Return predictable responses for testing
}
```
Integration tests will:
1. Start mock gRPC servers for GovernanceService, CeremonyService, NotaryService
2. Create plugin instances pointed at the mock servers
3. Invoke plugin methods (Attest, Compose, Notify)
4. Verify the plugin made expected gRPC calls with correct parameters
5. Verify the plugin handled error conditions (unreachable service, denied intent, ceremony timeout)
## Test Fixtures
Test fixture files in `test/fixtures/`:
| File | Purpose |
|------|---------|
| `sample-oidc-token.json` | Example OIDC token payload for oidc-attestor testing |
| `sample-sat-scope.json` | Example SatScope for governance client testing |
| `sample-ssh-cert-extensions.json` | Example Shellstream extensions map for shellstream package testing |
| `spire-test-config.hcl` | Example SPIRE plugin configuration for config package testing |
Load fixtures in tests:
```go
func loadFixture(t *testing.T, name string) []byte {
t.Helper()
data, err := os.ReadFile(filepath.Join("../../test/fixtures", name))
if err != nil {
t.Fatalf("load fixture %s: %v", name, err)
}
return data
}
```
## CI Pipeline
The CI pipeline is defined in `.github/workflows/ci.yaml`. It runs on every push and pull request to `master`:
1. Checks out the repository
2. Sets up Go 1.23
3. Runs `make test` (all unit tests)
4. Runs `make lint` (`go vet`)
5. Runs `make build` (compiles all 4 plugin binaries)
See [`.github/workflows/ci.yaml`](../.github/workflows/ci.yaml) for the full workflow definition.