// Package archtest innehåller arkitekturtester: regler om vilka paket som // får bero på vad. Körs som vanliga tester med `go test ./...`. package archtest import ( "os/exec" "strings" "testing" ) // Paket (relativt modulroten) som får importera Ebitengine. All annan kod // under internal/ ska gå att testa utan fönster. var mayUseEbitengine = map[string]bool{ "internal/game": true, "internal/ui": true, "internal/audio": true, } const ebitengine = "github.com/hajimehoshi/ebiten/" func TestOnlyPresentationPackagesImportEbitengine(t *testing.T) { root := goList(t, "-m", "-f", "{{.Dir}}") module := goList(t, "-m", "-f", "{{.Path}}") out := goListIn(t, root, "-f", "{{.ImportPath}}|{{join .Deps \",\"}}", "./...") for _, line := range strings.Split(out, "\n") { pkg, deps, ok := strings.Cut(line, "|") if !ok { continue } rel := strings.TrimPrefix(strings.TrimPrefix(pkg, module), "/") if strings.HasPrefix(rel, "cmd/") || mayUseEbitengine[rel] { continue } for _, d := range strings.Split(deps, ",") { if strings.HasPrefix(d, ebitengine) { t.Errorf("%s får inte bero på Ebitengine (via %s) – flytta logiken till ett rent paket eller lägg till paketet i mayUseEbitengine", rel, d) break } } } } func goList(t *testing.T, args ...string) string { t.Helper() return goListIn(t, "", args...) } func goListIn(t *testing.T, dir string, args ...string) string { t.Helper() cmd := exec.Command("go", append([]string{"list"}, args...)...) cmd.Dir = dir out, err := cmd.Output() if err != nil { t.Fatalf("go list %v: %v", args, err) } return strings.TrimSpace(string(out)) }