Harden the runner contract

This commit is contained in:
2026-07-03 08:26:51 -05:00
parent ccecc630e4
commit 32be4ee85e
2 changed files with 39 additions and 1 deletions

View File

@@ -56,6 +56,9 @@ func (r *Runner) Run(ctx context.Context, input RunInput) (RunOutput, error) {
if err != nil {
return output, fmt.Errorf("build extractor %q: %w", extractorKey, err)
}
if extractor == nil {
return output, fmt.Errorf("build extractor %q: returned nil extractor", extractorKey)
}
result, err := extractor.Extract(ctx, contracts.ExtractionRequest{
Source: input.Source,
@@ -121,7 +124,10 @@ func runValidators(ctx context.Context, extractor contracts.Extractor, doc *sour
var rejected []artifacts.RejectedArtifact
var warnings []contracts.Warning
for _, validator := range extractor.Validators() {
for validatorIndex, validator := range extractor.Validators() {
if validator == nil {
return nil, rejected, warnings, fmt.Errorf("extractor %q validator[%d] must not be nil", extractor.Key(), validatorIndex)
}
result, err := validator.Validate(ctx, contracts.ValidationRequest{
Source: doc,
Candidates: eligible,

View File

@@ -83,6 +83,19 @@ func TestRunRejectsInvalidSetup(t *testing.T) {
}
}
func TestRunRejectsNilExtractorFromFactory(t *testing.T) {
factory := fakeFactory{extractors: map[string]contracts.Extractor{
"generic-extractor": nil,
}}
_, err := New(factory).Run(context.Background(), RunInput{
Source: validSourceDocument(),
ExtractorKeys: []string{"generic-extractor"},
})
assertRunError(t, err, "returned nil extractor")
}
func TestRunUsesConfiguredExtractorOrderAndAssignsGlobalIndices(t *testing.T) {
var order []string
var seenIndices []int
@@ -251,6 +264,25 @@ func TestRunSurfacesValidatorCardinalityError(t *testing.T) {
assertRunError(t, err, "0 decisions for 1 candidates")
}
func TestRunRejectsNilValidator(t *testing.T) {
factory := fakeFactory{extractors: map[string]contracts.Extractor{
"generic-extractor": fakeExtractor{
key: "generic-extractor",
artifactType: "generic-artifact",
schemaVersion: "v1",
candidateCount: 1,
validators: []contracts.Validator{nil},
},
}}
_, err := New(factory).Run(context.Background(), RunInput{
Source: validSourceDocument(),
ExtractorKeys: []string{"generic-extractor"},
})
assertRunError(t, err, "validator[0] must not be nil")
}
func TestRunCollectsExtractorAndValidatorWarnings(t *testing.T) {
validator := fakeValidator{
name: "generic-validator",