Files
story/internal/cisupplychainconformance/conformance_test.go
T

62 lines
3.1 KiB
Go

package cisupplychainconformance
import (
"strings"
"testing"
"time"
)
func TestRemoteManagedCICompleteEvidencePasses(t *testing.T) {
t.Parallel()
capture := ciFixture("REMOTE_MANAGED_CI")
report := Evaluate(capture, capture.CandidateVersion, capture.BuildDigest, capture.SourceCommit, time.Now())
if report.Result != "PASS" || report.EvidenceScope != "REMOTE_CI_SUPPLY_CHAIN" || report.ExternalValidationRequired || len(report.CompletedChecks) != len(RequiredChecks) {
t.Fatalf("unexpected report: %+v", report)
}
}
func TestMissingRequiredArtifactFails(t *testing.T) {
t.Parallel()
capture := ciFixture("REMOTE_MANAGED_CI")
capture.SBOMs = capture.SBOMs[:2]
report := Evaluate(capture, capture.CandidateVersion, capture.BuildDigest, capture.SourceCommit, time.Now())
if report.Result != "FAIL" || !report.ExternalValidationRequired {
t.Fatalf("expected failed report: %+v", report)
}
}
func TestLocalToolchainCannotCompleteExternalValidation(t *testing.T) {
t.Parallel()
capture := ciFixture("LOCAL_TOOLCHAIN")
capture.Provider = "LOCAL_GO_TEST"
report := Evaluate(capture, capture.CandidateVersion, capture.BuildDigest, capture.SourceCommit, time.Now())
if report.Result != "PASS" || report.EvidenceScope != "LOCAL_CI_TOOLCHAIN" || !report.ExternalValidationRequired {
t.Fatalf("unexpected local report: %+v", report)
}
}
func ciFixture(source string) Capture {
started := time.Date(2026, 8, 25, 9, 0, 0, 0, time.UTC)
digest := "sha256:" + strings.Repeat("a", 64)
checks := make([]CheckResult, 0, len(RequiredChecks))
for _, code := range RequiredChecks {
checks = append(checks, CheckResult{Code: code, Status: "PASS", EvidenceRef: "artifact:checks/" + strings.ToLower(code)})
}
images := make([]ImageArtifact, 0, len(RequiredImages))
for position, subject := range RequiredImages {
images = append(images, ImageArtifact{Subject: subject, Reference: "registry.example.com/voice/" + strings.ToLower(subject), Digest: "sha256:" + strings.Repeat(string(rune('b'+position)), 64), EvidenceRef: "artifact:images/" + strings.ToLower(subject)})
}
sboms := make([]SBOMArtifact, 0, len(RequiredSBOMs))
for position, subject := range RequiredSBOMs {
sboms = append(sboms, SBOMArtifact{Subject: subject, Format: "CYCLONEDX_JSON", Digest: "sha256:" + strings.Repeat(string(rune('d'+position)), 64), EvidenceRef: "artifact:sbom/" + strings.ToLower(subject)})
}
return Capture{
SchemaVersion: CaptureSchema, EvidenceSource: source, CandidateVersion: "0.64.0-rc.1", BuildDigest: digest,
SourceCommit: strings.Repeat("1", 40), Provider: "GITHUB_ACTIONS", RepositoryRef: "github:example/voice-platform",
WorkflowRef: ".github/workflows/ci.yml@refs/tags/v0.64.0-rc.1", RunID: "123456789", RunURL: "https://github.com/example/voice-platform/actions/runs/123456789",
Trigger: "RELEASE", Ref: "refs/tags/v0.64.0-rc.1", Attempt: 1, Conclusion: "SUCCESS", StartedAt: started, CompletedAt: started.Add(20 * time.Minute),
CollectedAt: started.Add(25 * time.Minute), ExecutedByRef: "release-engineer", ReviewedByRef: "security-reviewer", ReviewRef: "approval:SEC-2026-081",
Checks: checks, Images: images, SBOMs: sboms,
}
}