1package analyzer
2
3import (
4 "path/filepath"
5 "testing"
6
7 "github.com/bnema/hexcheck/config"
8 "golang.org/x/tools/go/analysis/analysistest"
9)
10
11func TestAnalyzer(t *testing.T) {
12 tests := []struct {
13 name string
14 patterns []string
15 }{
16 {
17 name: "boundary imports",
18 patterns: []string{
19 "example.com/project/internal/domain",
20 "example.com/project/internal/application/usecase",
21 },
22 },
23 {
24 name: "heuristics",
25 patterns: []string{
26 "example.com/project/internal/infrastructure/http",
27 },
28 },
29 {
30 name: "type leaks",
31 patterns: []string{
32 "example.com/project/internal/application/port",
33 },
34 },
35 }
36
37 for _, tt := range tests {
38 t.Run(tt.name, func(t *testing.T) {
39 analysistest.Run(t, analysistest.TestData(), New(Options{Config: testConfig(), ModulePath: "example.com/project"}), tt.patterns...)
40 })
41 }
42}
43
44func testIntPtr(v int) *int { return &v }
45
46func testConfig() *config.Config {
47 cfg := &config.Config{
48 Root: filepath.Join(analysistest.TestData(), "src/example.com/project"),
49 Version: 1,
50 Components: map[string]config.Component{
51 "domain": {Role: config.RoleCore, Paths: []string{"internal/domain/**", "internal/policy/**"}},
52 "usecase": {Role: config.RoleUsecase, Paths: []string{"internal/application/usecase/**"}},
53 "ports": {Role: config.RolePorts, Paths: []string{"internal/application/port/**"}},
54 "http": {Role: config.RoleAdapter, Paths: []string{"internal/infrastructure/http/**"}},
55 "sql": {Role: config.RoleAdapter, Paths: []string{"internal/infrastructure/sql/**", "internal/sqlbad/**"}},
56 },
57 Rules: config.DefaultRuleSeverities(),
58 Heuristics: config.Heuristics{
59 BusinessLogicThreshold: testIntPtr(8),
60 BusinessLogicMinStrongSignals: testIntPtr(2),
61 BusinessLogicMinWeakSignals: testIntPtr(2),
62 BusinessLogicMaxFunctionNodes: testIntPtr(2000),
63 BusinessLogicMaxDiagnosticsPerPackage: testIntPtr(10),
64 BusinessKeywords: []string{"Validate", "Authorize", "Compute", "Calculate", "Apply", "Transition", "Can", "Detect", "Migrate", "Resolve", "Profile", "Score", "Ranking", "Restore", "Purge", "Update", "Performance", "Selected"},
65 },
66 ExternalTypes: config.ExternalTypes{
67 FrameworkPackages: []string{"example.com/framework"},
68 },
69 Mocking: config.Mocking{
70 GeneratedMockPaths: []string{"internal/application/port/mocks/**"},
71 },
72 Allow: []config.Allow{
73 {Rule: "no-infra-imports-in-usecase", Path: "internal/application/usecase/*_test.go", Reason: "test architecture rule has a more specific diagnostic"},
74 },
75 }
76 if err := cfg.Validate(); err != nil {
77 panic(err)
78 }
79 return cfg
80}