# 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 ```yaml # .github/workflows/test.yaml name: Test on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: '1.23' - run: make test - run: make lint - run: make build ```