2026-10-05 17:07:17 +00:00
package main
import (
"go/ast"
"go/importer"
"go/parser"
"go/token"
"go/types"
"strings"
"testing"
)
2026-11-01 19:25:15 +00:00
func TestRuntimeFacadeCannotDependOnForge ( t * testing . T ) {
for _ , indirect := range [ ] bool { false , true } {
name := "direct"
dependency := modulePath + "/internal/forge"
packages := [ ] listedPackage { { ImportPath : dependency } }
if indirect {
name = "transitive"
packages = append ( packages , listedPackage { ImportPath : modulePath + "/internal/runtime" , Imports : [ ] string { dependency } } )
dependency = modulePath + "/internal/runtime"
}
packages = append ( packages , listedPackage { ImportPath : modulePath + "/buildinfo" , Imports : [ ] string { dependency } } )
t . Run ( name , func ( t * testing . T ) {
err := checkImportDirections ( packages )
if err == nil || ! strings . Contains ( err . Error ( ) , "buildinfo" ) || ! strings . Contains ( err . Error ( ) , "/internal/forge" ) {
t . Fatalf ( "dependency check = %v, want excluded forge runtime dependency" , err )
}
} )
}
}
2026-10-05 17:07:17 +00:00
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 )
2026-10-07 18:34:34 +00:00
}
}
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 )
2026-10-05 17:07:17 +00:00
}
}
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 } } ,
2026-10-05 17:25:11 +00:00
{ ImportPath : modulePath + "/cmd/releasekit/internal/cli" , Imports : [ ] string { modulePath + "/buildinfo" } } ,
2026-10-05 17:07:17 +00:00
{ ImportPath : modulePath } ,
2026-10-05 17:25:11 +00:00
{ ImportPath : modulePath + "/buildinfo" } ,
2026-10-05 17:07:17 +00:00
}
err := checkImportDirections ( packages )
2026-10-05 17:25:11 +00:00
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" ) {
2026-10-05 17:07:17 +00:00
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 )
}
}
2026-11-01 18:30:52 +00:00
func TestSharedDeliveryPackagesCannotDependOnGitea ( t * testing . T ) {
allowed := [ ] listedPackage {
{ ImportPath : modulePath + "/internal/delivery" , Imports : [ ] string { modulePath + "/internal/forge" , modulePath + "/internal/artifact" } } ,
{ ImportPath : modulePath + "/internal/forge" } ,
{ ImportPath : modulePath + "/internal/artifact" } ,
{ ImportPath : modulePath + "/internal/gitea" } ,
}
if err := checkImportDirections ( allowed ) ; err != nil {
t . Fatalf ( "shared delivery boundary rejected neutral dependencies: %v" , err )
}
violating := [ ] listedPackage {
{ ImportPath : modulePath + "/internal/delivery" , Imports : [ ] string { modulePath + "/internal/policy" } } ,
{ ImportPath : modulePath + "/internal/policy" , Imports : [ ] string { modulePath + "/internal/gitea" } } ,
{ ImportPath : modulePath + "/internal/forge" } ,
{ ImportPath : modulePath + "/internal/artifact" } ,
{ ImportPath : modulePath + "/internal/gitea" } ,
}
err := checkImportDirections ( violating )
if err == nil || ! strings . Contains ( err . Error ( ) , "shared package " + modulePath + "/internal/delivery depends on Gitea adapter" ) {
t . Fatalf ( "checkImportDirections() error = %v, want transitive shared-delivery violation" , err )
}
}
2026-10-05 17:07:17 +00:00
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
}
2026-10-06 01:08:34 +00:00
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 )
}
} )
}
}