package api import ( "go/ast" "go/parser" "go/token" "testing" ) // TestDecisionEffectsListsEveryConstant parses canonical.go so that adding a // DecisionEffect constant without listing it in DecisionEffects fails here. func TestDecisionEffectsListsEveryConstant(t *testing.T) { file, err := parser.ParseFile(token.NewFileSet(), "canonical.go", nil, 0) if err != nil { t.Fatal(err) } declared := map[string]bool{} ast.Inspect(file, func(node ast.Node) bool { spec, ok := node.(*ast.ValueSpec) if !ok { return true } if ident, ok := spec.Type.(*ast.Ident); !ok || ident.Name != "DecisionEffect" { return true } for _, value := range spec.Values { if lit, ok := value.(*ast.BasicLit); ok { declared[lit.Value[1:len(lit.Value)-1]] = true } } return true }) listed := map[string]bool{} for _, effect := range DecisionEffects() { listed[string(effect)] = true } if len(declared) == 0 { t.Fatal("found no DecisionEffect constants in canonical.go") } for effect := range declared { if !listed[effect] { t.Errorf("DecisionEffect %q is declared but missing from DecisionEffects()", effect) } } if len(listed) != len(declared) { t.Errorf("DecisionEffects() lists %d effects, canonical.go declares %d", len(listed), len(declared)) } } func TestRestrictsSplitsByDirection(t *testing.T) { want := map[DecisionEffect]bool{ DecisionEffectAllow: false, DecisionEffectAuditOnly: false, DecisionEffectDeny: true, DecisionEffectRedact: true, DecisionEffectNotApplicable: true, } for _, effect := range DecisionEffects() { expected, ok := want[effect] if !ok { t.Fatalf("effect %q has no stated direction; decide it under FLEX-DEC-2026-018", effect) } if effect.Restricts() != expected { t.Errorf("%q.Restricts() = %v, want %v", effect, effect.Restricts(), expected) } } }