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>
3.5 KiB
3.5 KiB
Testing Strategy
How to test the Guildhouse SPIRE plugins.
Running Tests
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:
// 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:
- Start mock gRPC servers for GovernanceService, CeremonyService, NotaryService
- Create plugin instances pointed at the mock servers
- Invoke plugin methods (Attest, Compose, Notify)
- Verify the plugin made expected gRPC calls with correct parameters
- 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:
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:
- Checks out the repository
- Sets up Go 1.23
- Runs
make test(all unit tests) - Runs
make lint(go vet) - Runs
make build(compiles all 4 plugin binaries)
See .github/workflows/ci.yaml for the full workflow definition.