package main import ( "go/ast" "go/importer" "go/parser" "go/token" "go/types" "strings" "testing" ) func TestExportedContractBoundaries(t *testing.T) { tests := []struct { name string source string wantError string }{ { name: "leaked implementation type", source: `package facade import "example.com/implementation" func New() *implementation.State { return nil } `, wantError: "exposes named type example.com/implementation.State", }, { name: "alias to implementation type", source: `package facade import "example.com/implementation" type Alias = implementation.State `, wantError: "exposes named type example.com/implementation.State", }, { name: "callback leaks implementation type", source: `package facade import "example.com/implementation" type Callback func() *implementation.State `, wantError: "exposes named type example.com/implementation.State", }, { name: "generic constraint leaks implementation type", source: `package facade import "example.com/implementation" type Box[T interface{ Value() *implementation.State }] struct { value T } `, wantError: "exposes named type example.com/implementation.State", }, { name: "generic instantiation leaks implementation type", source: `package facade import "example.com/implementation" type Box[T any] struct { value T } func New() Box[implementation.State] { return Box[implementation.State]{} } `, wantError: "exposes named type example.com/implementation.State", }, { name: "promoted implementation method", source: `package facade import "example.com/implementation" type state = implementation.State type Handle struct { state } `, wantError: "promotes method Promoted from example.com/implementation", }, { name: "promoted pointer implementation method", source: `package facade import "example.com/implementation" type state = implementation.State type Handle struct { state } `, wantError: "promotes method PointerPromoted from example.com/implementation", }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { violations := checkFixture(t, test.source) if !strings.Contains(strings.Join(violations, "\n"), test.wantError) { t.Fatalf("checkExports() = %v, want an error containing %q", violations, test.wantError) } }) } } func TestPrivateImplementationFieldAndSelectedStandardTypes(t *testing.T) { source := `package facade import ( "context" "example.com/implementation" ) type Handle struct { state *implementation.State } func Open(context.Context) *Handle { return nil } ` if violations := checkFixture(t, source); len(violations) != 0 { t.Fatalf("private implementation field and selected standard type were rejected: %v", violations) } } func TestValidationDiagnosticTypesBelongToFacade(t *testing.T) { valid := `package facade type ValidationCheck string type ValidationFinding struct{} type FileSizeMeasurement struct{} type ValidationError struct { Check ValidationCheck Findings []ValidationFinding Measurement *FileSizeMeasurement Cause error } ` pkg := typecheck(t, token.NewFileSet(), modulePath, valid) if violations := checkValidationTypes(pkg); len(violations) != 0 { t.Fatalf("checkValidationTypes() = %v, want facade-owned diagnostics", violations) } implementation := typecheck(t, token.NewFileSet(), "example.com/implementation", `package implementation type State string `) fset := token.NewFileSet() fixtureImporter := singlePackageImporter{path: "example.com/implementation", pkg: implementation} invalid := strings.Replace(valid, "type ValidationCheck string", "import \"example.com/implementation\"\ntype ValidationCheck = implementation.State", 1) pkg = typecheckWithImporter(t, fset, modulePath, invalid, fixtureImporter) if violations := checkValidationTypes(pkg); !strings.Contains(strings.Join(violations, "\n"), "ValidationCheck is not a facade-owned named type") { t.Fatalf("checkValidationTypes() = %v, want ownership violation", violations) } } func TestActualRepositoryBoundaries(t *testing.T) { if err := checkRepository(t.Context(), "../.."); err != nil { t.Fatal(err) } } func TestInternalPackagesCannotImportPublicFacades(t *testing.T) { packages := []listedPackage{ {ImportPath: modulePath + "/internal/operations", Imports: []string{modulePath}}, {ImportPath: modulePath + "/cmd/releasekit/internal/cli", Imports: []string{modulePath + "/buildinfo"}}, {ImportPath: modulePath}, {ImportPath: modulePath + "/buildinfo"}, } err := checkImportDirections(packages) if err == nil || !strings.Contains(err.Error(), "internal package "+modulePath+"/internal/operations imports public or command package "+modulePath) || !strings.Contains(err.Error(), "internal package "+modulePath+"/cmd/releasekit/internal/cli imports public or command package "+modulePath+"/buildinfo") { t.Fatalf("checkImportDirections() error = %v, want internal-to-facade violation", err) } } func TestRuntimeFacadeCannotDependOnExternalPackages(t *testing.T) { packages := []listedPackage{ {ImportPath: modulePath + "/buildinfo", Imports: []string{"example.com/runtime"}}, {ImportPath: "example.com/runtime"}, } err := checkImportDirections(packages) if err == nil || !strings.Contains(err.Error(), "buildinfo depends on non-runtime package example.com/runtime") { t.Fatalf("checkImportDirections() error = %v, want runtime dependency violation", err) } } func checkFixture(t *testing.T, facadeSource string) []string { t.Helper() fset := token.NewFileSet() implementation := typecheck(t, fset, "example.com/implementation", `package implementation type State struct{} func (State) Promoted() {} func (*State) PointerPromoted() {} `) fixtureImporter := singlePackageImporter{path: "example.com/implementation", pkg: implementation} facade := typecheckWithImporter(t, fset, "example.com/facade", facadeSource, fixtureImporter) return checkExports(facade) } type singlePackageImporter struct { path string pkg *types.Package } func (i singlePackageImporter) Import(path string) (*types.Package, error) { if path == i.path { return i.pkg, nil } return importer.Default().Import(path) } func typecheck(t *testing.T, fset *token.FileSet, path, source string) *types.Package { t.Helper() return typecheckWithImporter(t, fset, path, source, importer.Default()) } func typecheckWithImporter(t *testing.T, fset *token.FileSet, path, source string, imports types.Importer) *types.Package { t.Helper() file, err := parser.ParseFile(fset, path+".go", source, 0) if err != nil { t.Fatal(err) } var errors []error config := types.Config{ Importer: imports, Error: func(err error) { errors = append(errors, err) }, } pkg, err := config.Check(path, fset, []*ast.File{file}, nil) if err != nil { t.Fatalf("typecheck %s: %v (%v)", path, err, errors) } return pkg } func TestCommandInternalCompositionPreservesLibraryBoundaries(t *testing.T) { for _, test := range []struct { name, from, to string reject bool }{ {"command helpers", "/cmd/releasekit/internal/cli/parser", "/cmd/releasekit/internal/cli/settings", false}, {"other executable helpers", "/cmd/future/internal/parser", "/cmd/future/internal/settings", false}, {"helper root", "/cmd/releasekit/internal", "/cmd/releasekit/internal/cli", false}, {"controller uses facade", "/cmd/releasekit", "", false}, {"library imports controller", "/internal/build", "/cmd/releasekit", true}, {"library imports helper", "/internal/build", "/cmd/releasekit/internal/cli", true}, {"helper imports facade", "/cmd/releasekit/internal/cli", "", true}, {"helper imports runtime facade", "/cmd/releasekit/internal/cli", "/buildinfo", true}, {"helper imports controller", "/cmd/releasekit/internal/cli", "/cmd/releasekit", true}, } { t.Run(test.name, func(t *testing.T) { err := checkImportDirections([]listedPackage{{ImportPath: modulePath + test.from, Imports: []string{modulePath + test.to}}}) if (err != nil) != test.reject { t.Fatalf("dependency %s -> %s: %v", test.from, test.to, err) } }) } }