126 lines
6.5 KiB
Go
126 lines
6.5 KiB
Go
package validation
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestRunFileChecksUseSelectedInputsAndFullReferenceLookup(t *testing.T) {
|
|
repository := newTreeRepository(t)
|
|
writeTreeFile(t, repository, "go.mod", []byte("module example.com/root\n\ngo 1.25.0\nreplace example.com/rootdep => ./missing\n"))
|
|
writeTreeFile(t, repository, "go.work", []byte("go 1.25.0\n"))
|
|
writeTreeFile(t, repository, "outside.go", []byte("package outside\nfunc broken( ){}\n"))
|
|
writeTreeFile(t, repository, "outside.bin", []byte(strings.Repeat("x", 160)))
|
|
writeTreeFile(t, repository, "nested/go.mod", []byte("module example.com/nested\n\ngo 1.25.0\n"))
|
|
writeTreeFile(t, repository, "nested/source.go", []byte("package nested\n\nfunc ready() {}\n"))
|
|
writeTreeFile(t, repository, "nested/ignored.bin", []byte(strings.Repeat("x", 160)))
|
|
writeTreeFile(t, repository, "nested/docs/guide.md", []byte("# Guide\n\n[details](../../sibling/docs/target.md#details)\n"))
|
|
writeTreeFile(t, repository, "nested/child/go.mod", []byte("module example.com/nested/child\n"))
|
|
writeTreeFile(t, repository, "nested/child/broken.go", []byte("package child\nfunc broken( ){}\n"))
|
|
writeTreeFile(t, repository, "nested/child/go.work", []byte("go 1.25.0\n"))
|
|
writeTreeFile(t, repository, "sibling/go.mod", []byte("module example.com/sibling\n\nreplace example.com/siblingdep => ./missing\n"))
|
|
writeTreeFile(t, repository, "sibling/go.work", []byte("go 1.25.0\n"))
|
|
writeTreeFile(t, repository, "sibling/broken.go", []byte("package sibling\nfunc broken( ){}\n"))
|
|
writeTreeFile(t, repository, "sibling/outside.bin", []byte(strings.Repeat("x", 160)))
|
|
writeTreeFile(t, repository, "sibling/docs/target.md", []byte("# Details\n\n[broken](missing.md)\n"))
|
|
writeTreeFile(t, repository, "shared/broken.go", []byte("package shared\nfunc broken( ){}\n"))
|
|
commit := commitCandidateTree(t, repository)
|
|
installGoShim(t, "", false)
|
|
moduleDir := filepath.Join(repository, "nested")
|
|
settings := Settings{
|
|
GoFormat: true,
|
|
ModuleDistribution: ModuleDistributionSettings{
|
|
WorkspaceFiles: true,
|
|
LocalReplacements: true,
|
|
},
|
|
FileSize: &FileSizeSettings{LimitBytes: int64Pointer(100), Exclusions: []string{"ignored.bin"}},
|
|
Markdown: &MarkdownSettings{EnforceCheckoutBoundary: true},
|
|
}
|
|
request := Request{RepositoryDir: repository, ModuleDir: moduleDir, Commit: commit, Settings: settings}
|
|
if err := Run(context.Background(), request); err != nil {
|
|
t.Fatalf("selected module checks = %v, want out-of-scope violations ignored and cross-module anchor resolved", err)
|
|
}
|
|
|
|
request.Settings.FileSize.Exclusions = nil
|
|
err := Run(context.Background(), request)
|
|
assertScopedFailure(t, err, FileSize, "nested/ignored.bin")
|
|
|
|
writeTreeFile(t, repository, "nested/broken.go", []byte("package nested\nfunc broken( ){}\n"))
|
|
request.Commit = commitCandidateTree(t, repository)
|
|
request.Settings = Settings{GoFormat: true}
|
|
assertScopedFailure(t, Run(context.Background(), request), GoFormat, "nested/broken.go")
|
|
|
|
writeTreeFile(t, repository, "nested/go.work", []byte("go 1.25.0\n"))
|
|
request.Commit = commitCandidateTree(t, repository)
|
|
request.Settings = Settings{ModuleDistribution: ModuleDistributionSettings{WorkspaceFiles: true}}
|
|
assertScopedFailure(t, Run(context.Background(), request), WorkspaceFiles, "nested/go.work")
|
|
|
|
writeTreeFile(t, repository, "nested/go.mod", []byte("module example.com/nested\n\ngo 1.25.0\nreplace example.com/nesteddep => ./missing\n"))
|
|
request.Commit = commitCandidateTree(t, repository)
|
|
request.Settings = Settings{ModuleDistribution: ModuleDistributionSettings{LocalReplacements: true}}
|
|
assertScopedFailure(t, Run(context.Background(), request), LocalReplacements, "nested/go.mod")
|
|
|
|
writeTreeFile(t, repository, "nested/docs/guide.md", []byte("# Guide\n\n[details](../../sibling/docs/target.md#details)\n\n[missing](absent.md)\n"))
|
|
request.Commit = commitCandidateTree(t, repository)
|
|
request.Settings = Settings{Markdown: &MarkdownSettings{}}
|
|
assertScopedFailure(t, Run(context.Background(), request), MarkdownLinks, "nested/docs/guide.md")
|
|
|
|
request.Settings = Settings{GoFormat: true, SharedFiles: []string{"shared/broken.go"}}
|
|
assertScopedFailure(t, Run(context.Background(), request), GoFormat, "shared/broken.go")
|
|
}
|
|
|
|
func assertScopedFailure(t *testing.T, err error, check Check, path string) {
|
|
t.Helper()
|
|
failure, ok := err.(*Failure)
|
|
if !ok || failure.Check != check {
|
|
t.Fatalf("validation error = %v, want %s failure", err, check)
|
|
}
|
|
for _, finding := range failure.Findings {
|
|
if finding.Path == path {
|
|
return
|
|
}
|
|
}
|
|
t.Fatalf("%s findings = %#v, want path %q", check, failure.Findings, path)
|
|
}
|
|
|
|
func TestFileSizeExclusionsAreModuleRelative(t *testing.T) {
|
|
repository := newTreeRepository(t)
|
|
writeTreeFile(t, repository, "nested/go.mod", []byte("module example.com/nested\n"))
|
|
writeTreeFile(t, repository, "nested/dist/output.bin", []byte(strings.Repeat("x", 20)))
|
|
writeTreeFile(t, repository, "nested/dist-old/output.bin", []byte(strings.Repeat("x", 20)))
|
|
commit := commitCandidateTree(t, repository)
|
|
tree, err := ReadCandidateTreeForScope(context.Background(), repository, commit, TreeScope{ModuleDir: filepath.Join(repository, "nested")})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
cleanupCandidateTree(t, tree)
|
|
settings := fileSizeSettingsForModule(&FileSizeSettings{LimitBytes: int64Pointer(10), Exclusions: []string{"./dist/"}}, tree.modulePath)
|
|
err = checkFileSize(t.Context(), tree, settings)
|
|
var failure *Failure
|
|
if !errors.As(err, &failure) || failure.Check != FileSize || len(failure.Findings) != 1 || failure.Findings[0].Path != "nested/dist-old/output.bin" {
|
|
t.Fatalf("module-relative file-size exclusion error = %v, want only nested/dist-old/output.bin", err)
|
|
}
|
|
}
|
|
|
|
func TestSharedFileSelectionFailureCarriesCauseAndPresentation(t *testing.T) {
|
|
repository := newTreeRepository(t)
|
|
writeTreeFile(t, repository, "go.mod", []byte("module example.com/root\n"))
|
|
commit := commitCandidateTree(t, repository)
|
|
installGoShim(t, "", false)
|
|
err := Run(context.Background(), Request{
|
|
RepositoryDir: repository,
|
|
Commit: commit,
|
|
Settings: Settings{SharedFiles: []string{"missing.txt"}},
|
|
})
|
|
var failure *Failure
|
|
if !errors.As(err, &failure) || failure.Check != SharedFiles || failure.Cause == nil || len(failure.Findings) != 1 || failure.Findings[0].Path != "missing.txt" {
|
|
t.Fatalf("shared-file selection error = %#v, want path, cause, and shared-files identity", err)
|
|
}
|
|
if !strings.Contains(err.Error(), "shared-files") || !strings.Contains(err.Error(), "missing.txt") {
|
|
t.Fatalf("shared-file error text = %q, want existing check/path presentation", err)
|
|
}
|
|
}
|