Files
Assistant/cmd/devctl/architecture_test.go
2026-08-16 15:22:49 +03:00

71 lines
3.1 KiB
Go

package main
import (
"os"
"path/filepath"
"strings"
"testing"
)
func TestArchitectureSentinelNegativeCases(t *testing.T) {
tests := []struct {
name string
importPath string
want string
}{
{"domain infrastructure import", "git.cin.su/m/Assistant/adapters/postgres", "domain imports forbidden /adapters/"},
{"cross-module implementation import", "git.cin.su/m/Assistant/modules/beta/domain", "cross-module implementation import beta"},
{"undeclared contract dependency", "git.cin.su/m/Assistant/contracts/beta", "undeclared contract dependency contracts.beta"},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
root := architectureFixture(t, test.importPath)
err := checkArchitectureAt(root)
if err == nil || !strings.Contains(err.Error(), test.want) {
t.Fatalf("sentinel error = %v", err)
}
})
}
}
func TestArchitectureSentinelAcceptsDeclaredContractDependency(t *testing.T) {
root := architectureFixture(t, "git.cin.su/m/Assistant/contracts/beta")
registry := `{"registry_version":1,"semantic_generation":1,"architecture_generation":1,"modules":{"alpha":{"id":"mod.alpha","owns":[],"database_schema":"alpha","boundary_class":"remote_capable","may_depend_on":["contracts.beta"]},"beta":{"id":"mod.beta","owns":[],"database_schema":"beta","boundary_class":"remote_capable","may_depend_on":[]}}}`
writeFixture(t, filepath.Join(root, "architecture", "architecture-registry.json"), registry)
if err := checkArchitectureAt(root); err != nil {
t.Fatalf("declared dependency rejected: %v", err)
}
}
func TestPreflightRejectsProtectedPathBelowTierE(t *testing.T) {
registry := Registry{ProtectedPaths: []string{"architecture/**", "security/**"}}
taskPacket := TaskPacket{TaskID: "DEV-bad", RiskTier: "C", Intent: "weaken guardrail"}
taskPacket.AllowedChangeScope.Paths = []string{"architecture/architecture-registry.json"}
if err := validateTaskScope(taskPacket, registry); err == nil || !strings.Contains(err.Error(), "protected path") {
t.Fatalf("protected path task error = %v", err)
}
taskPacket.RiskTier = "E"
if err := validateTaskScope(taskPacket, registry); err != nil {
t.Fatalf("Tier E protected path rejected: %v", err)
}
}
func architectureFixture(t *testing.T, importPath string) string {
t.Helper()
root := t.TempDir()
registry := `{"registry_version":1,"semantic_generation":1,"architecture_generation":1,"modules":{"alpha":{"id":"mod.alpha","owns":[],"database_schema":"alpha","boundary_class":"remote_capable","may_depend_on":[]},"beta":{"id":"mod.beta","owns":[],"database_schema":"beta","boundary_class":"remote_capable","may_depend_on":[]}}}`
writeFixture(t, filepath.Join(root, "architecture", "architecture-registry.json"), registry)
writeFixture(t, filepath.Join(root, "modules", "alpha", "domain", "fixture.go"), "package domain\nimport _ \""+importPath+"\"\n")
return root
}
func writeFixture(t *testing.T, path, content string) {
t.Helper()
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(path, []byte(content), 0o644); err != nil {
t.Fatal(err)
}
}