Add framework composition runner
This commit is contained in:
105
internal/framework/validators/validators_test.go
Normal file
105
internal/framework/validators/validators_test.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package validators
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gitea.maximumdirect.net/eric/notarius/internal/core/artifacts"
|
||||
"gitea.maximumdirect.net/eric/notarius/internal/framework/contracts"
|
||||
)
|
||||
|
||||
func TestApproved(t *testing.T) {
|
||||
decision := Approved(7)
|
||||
|
||||
if decision.CandidateIndex != 7 {
|
||||
t.Fatalf("CandidateIndex = %d, want 7", decision.CandidateIndex)
|
||||
}
|
||||
if !decision.Approved {
|
||||
t.Fatal("Approved = false, want true")
|
||||
}
|
||||
if decision.ReasonCode != ReasonApproved {
|
||||
t.Fatalf("ReasonCode = %q, want %q", decision.ReasonCode, ReasonApproved)
|
||||
}
|
||||
if decision.Message != "approved" {
|
||||
t.Fatalf("Message = %q, want approved", decision.Message)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRejectedTrimsReasonAndMessage(t *testing.T) {
|
||||
decision := Rejected(3, " invalid ", "\tmessage\n")
|
||||
|
||||
if decision.CandidateIndex != 3 {
|
||||
t.Fatalf("CandidateIndex = %d, want 3", decision.CandidateIndex)
|
||||
}
|
||||
if decision.Approved {
|
||||
t.Fatal("Approved = true, want false")
|
||||
}
|
||||
if decision.ReasonCode != "invalid" {
|
||||
t.Fatalf("ReasonCode = %q, want invalid", decision.ReasonCode)
|
||||
}
|
||||
if decision.Message != "message" {
|
||||
t.Fatalf("Message = %q, want message", decision.Message)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnforceDecisionCardinalityAllowsNonZeroCandidateIndices(t *testing.T) {
|
||||
candidates := []artifacts.Candidate{{Index: 4}, {Index: 8}}
|
||||
decisions := []contracts.ValidationDecision{Approved(8), Approved(4)}
|
||||
|
||||
if err := EnforceDecisionCardinality(candidates, decisions); err != nil {
|
||||
t.Fatalf("EnforceDecisionCardinality() error = %v, want nil", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnforceDecisionCardinalityAllowsEmptyInputs(t *testing.T) {
|
||||
if err := EnforceDecisionCardinality(nil, nil); err != nil {
|
||||
t.Fatalf("EnforceDecisionCardinality() error = %v, want nil", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnforceDecisionCardinalityRejectsUnknownDecisionIndex(t *testing.T) {
|
||||
err := EnforceDecisionCardinality(
|
||||
[]artifacts.Candidate{{Index: 1}},
|
||||
[]contracts.ValidationDecision{Approved(2)},
|
||||
)
|
||||
|
||||
assertCardinalityError(t, err, "unknown candidate index 2")
|
||||
}
|
||||
|
||||
func TestEnforceDecisionCardinalityRejectsDuplicateDecisionIndex(t *testing.T) {
|
||||
err := EnforceDecisionCardinality(
|
||||
[]artifacts.Candidate{{Index: 1}, {Index: 2}},
|
||||
[]contracts.ValidationDecision{Approved(1), Approved(1)},
|
||||
)
|
||||
|
||||
assertCardinalityError(t, err, "duplicate decision")
|
||||
}
|
||||
|
||||
func TestEnforceDecisionCardinalityRejectsMissingDecisionIndex(t *testing.T) {
|
||||
err := EnforceDecisionCardinality(
|
||||
[]artifacts.Candidate{{Index: 1}, {Index: 2}},
|
||||
[]contracts.ValidationDecision{Approved(1)},
|
||||
)
|
||||
|
||||
assertCardinalityError(t, err, "1 decisions for 2 candidates")
|
||||
}
|
||||
|
||||
func TestEnforceDecisionCardinalityRejectsDuplicateCandidateIndex(t *testing.T) {
|
||||
err := EnforceDecisionCardinality(
|
||||
[]artifacts.Candidate{{Index: 1}, {Index: 1}},
|
||||
[]contracts.ValidationDecision{Approved(1), Approved(1)},
|
||||
)
|
||||
|
||||
assertCardinalityError(t, err, "candidate index 1 is duplicated")
|
||||
}
|
||||
|
||||
func assertCardinalityError(t *testing.T, err error, want string) {
|
||||
t.Helper()
|
||||
|
||||
if err == nil {
|
||||
t.Fatal("EnforceDecisionCardinality() error = nil, want error")
|
||||
}
|
||||
if !strings.Contains(err.Error(), want) {
|
||||
t.Fatalf("EnforceDecisionCardinality() error = %q, want substring %q", err.Error(), want)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user