diff --git a/testing/hygiene/hygiene_test.go b/testing/hygiene/hygiene_test.go index 86f57af..025fd14 100644 --- a/testing/hygiene/hygiene_test.go +++ b/testing/hygiene/hygiene_test.go @@ -17,6 +17,12 @@ import ( const maxGoFileLOC = 500 var goFileNamePattern = regexp.MustCompile(`^[a-z0-9]+(_[a-z0-9]+)*(_test)?\.go$`) +var genericFileNameTokens = map[string]struct{}{ + "chunk": {}, + "part": {}, + "piece": {}, + "split": {}, +} func repoRoot(tb testing.TB) string { tb.Helper() @@ -61,13 +67,16 @@ func collectGoFiles(tb testing.TB, roots ...string) []string { func TestHygieneContracts(t *testing.T) { root := repoRoot(t) files := collectGoFiles(t, filepath.Join(root, "cmd"), filepath.Join(root, "internal")) + namingFiles := append([]string{}, files...) + namingFiles = append(namingFiles, collectGoFiles(t, filepath.Join(root, "testing"))...) sort.Strings(files) + sort.Strings(namingFiles) t.Run("doc_contract", func(t *testing.T) { checkDocContracts(t, files) }) t.Run("naming_contract", func(t *testing.T) { - checkNamingContracts(t, files) + checkNamingContracts(t, namingFiles) }) t.Run("loc_limit", func(t *testing.T) { checkFileLOCLimits(t, files) @@ -121,9 +130,19 @@ func checkNamingContracts(t *testing.T, files []string) { if !goFileNamePattern.MatchString(base) { t.Errorf("%s: filename %q violates naming contract %s", file, base, goFileNamePattern.String()) } + for _, token := range filenameTokens(base) { + if _, ok := genericFileNameTokens[token]; ok { + t.Errorf("%s: filename %q uses generic split-file token %q", file, base, token) + } + } } } +func filenameTokens(name string) []string { + trimmed := strings.TrimSuffix(strings.TrimSuffix(name, ".go"), "_test") + return strings.Split(trimmed, "_") +} + // checkFileLOCLimits runs one orchestration or CLI step. // Signature: checkFileLOCLimits(t *testing.T, files []string). // Why: A strict LOC cap forces focused files and keeps refactors manageable.