package internal_test import ( "go/ast" "go/parser" "go/token" "os" "strconv" "strings" "testing" ) func TestArchitecture_ModelAndServiceAreProtocolNeutral(t *testing.T) { for _, dir := range []string{"model", "service"} { imports := packageImports(t, dir) for _, forbidden := range []string{ "net/http", "github.com/gin-gonic/gin", "github.com/dhao2001/mygo/internal/api", } { if imports[forbidden] { t.Fatalf("internal/%s imports forbidden package %q", dir, forbidden) } } } } func TestArchitecture_HTTPDoesNotImportRepositories(t *testing.T) { for _, dir := range []string{"handler", "middleware"} { imports := packageImports(t, dir) if imports["github.com/dhao2001/mygo/internal/repository"] { t.Fatalf("internal/%s imports internal/repository; use service boundaries instead", dir) } } } func packageImports(t *testing.T, dir string) map[string]bool { t.Helper() imports := map[string]bool{} pkgs := parsePackage(t, dir) for _, pkg := range pkgs { for _, file := range pkg.Files { for _, spec := range file.Imports { path, err := strconv.Unquote(spec.Path.Value) if err != nil { t.Fatalf("unquote import path %s: %v", spec.Path.Value, err) } imports[path] = true } } } return imports } func parsePackage(t *testing.T, dir string) map[string]*ast.Package { t.Helper() fset := token.NewFileSet() pkgs, err := parser.ParseDir(fset, dir, func(info os.FileInfo) bool { name := info.Name() return !strings.HasSuffix(name, "_test.go") }, parser.ParseComments) if err != nil { t.Fatalf("parse internal/%s: %v", dir, err) } return pkgs }