Add lint coverage tests

This commit is contained in:
Snider 2026-04-16 06:52:34 +01:00
parent fb307db690
commit 9bde4dbe74
4 changed files with 148 additions and 1 deletions

View file

@ -29,6 +29,34 @@ func TestDetect_Good_ProjectMarkersAndFiles(t *testing.T) {
)
}
func TestDetect_Good_MarkerCoverage(t *testing.T) {
dir := t.TempDir()
files := map[string]string{
"go.mod": "module example.com/test\n",
"composer.json": "{}\n",
"package.json": "{}\n",
"tsconfig.json": "{}\n",
"requirements.txt": "ruff\n",
"pyproject.toml": "[tool.ruff]\n",
"Cargo.toml": "[package]\nname = \"test\"\n",
"Dockerfile.dev": "FROM scratch\n",
"run.sh": "#!/bin/sh\n",
"main.cpp": "int main() { return 0; }\n",
"config.yaml": "kind: Config\n",
"config.yml": "kind: Config\n",
}
for name, content := range files {
require.NoError(t, os.WriteFile(filepath.Join(dir, name), []byte(content), 0o644))
}
assert.Equal(t,
[]string{"cpp", "dockerfile", "go", "js", "php", "python", "rust", "shell", "ts", "yaml"},
Detect(dir),
)
}
func TestDetectFromFiles_Good(t *testing.T) {
files := []string{
"main.go",
@ -45,7 +73,7 @@ func TestDetectFromFiles_Good(t *testing.T) {
)
}
func TestDetect_MissingPathReturnsEmptySlice(t *testing.T) {
func TestDetect_Bad_MissingPathReturnsEmptySlice(t *testing.T) {
assert.Equal(t, []string{}, Detect(filepath.Join(t.TempDir(), "missing")))
}
@ -57,3 +85,17 @@ func TestDetect_Good_SkipsHiddenRootDirectory(t *testing.T) {
assert.Equal(t, []string{}, Detect(hiddenDir))
}
func TestDetect_Ugly_SkipsNestedHiddenAndExcludedDirectories(t *testing.T) {
dir := t.TempDir()
require.NoError(t, os.WriteFile(filepath.Join(dir, "root.go"), []byte("package main\n"), 0o644))
require.NoError(t, os.MkdirAll(filepath.Join(dir, "vendor"), 0o755))
require.NoError(t, os.WriteFile(filepath.Join(dir, "vendor", "ignored.go"), []byte("package ignored\n"), 0o644))
require.NoError(t, os.MkdirAll(filepath.Join(dir, ".core"), 0o755))
require.NoError(t, os.WriteFile(filepath.Join(dir, ".core", "ignored.go"), []byte("package ignored\n"), 0o644))
require.NoError(t, os.MkdirAll(filepath.Join(dir, "services", ".generated"), 0o755))
require.NoError(t, os.WriteFile(filepath.Join(dir, "services", ".generated", "ignored.go"), []byte("package ignored\n"), 0o644))
assert.Equal(t, []string{"go"}, Detect(dir))
}

View file

@ -62,3 +62,26 @@ func TestResolveRunOutputFormat_Good_ExplicitOutputBypassesConfigLoading(t *test
require.NoError(t, err)
assert.Equal(t, "sarif", format)
}
func TestResolveRunOutputFormat_Bad_BrokenConfig(t *testing.T) {
dir := t.TempDir()
require.NoError(t, os.MkdirAll(filepath.Join(dir, ".core"), 0o755))
require.NoError(t, os.WriteFile(filepath.Join(dir, ".core", "lint.yaml"), []byte("{not: yaml"), 0o644))
_, err := ResolveRunOutputFormat(RunInput{
Path: dir,
})
assert.Error(t, err)
}
func TestResolveRunOutputFormat_Ugly_MissingSchedule(t *testing.T) {
dir := t.TempDir()
require.NoError(t, os.MkdirAll(filepath.Join(dir, ".core"), 0o755))
require.NoError(t, os.WriteFile(filepath.Join(dir, ".core", "lint.yaml"), []byte("output: text\n"), 0o644))
_, err := ResolveRunOutputFormat(RunInput{
Path: dir,
Schedule: "nightly",
})
assert.Error(t, err)
}

View file

@ -58,6 +58,19 @@ func TestSummarise_Good_Empty(t *testing.T) {
assert.Empty(t, summary.BySeverity)
}
func TestSummarise_Bad_BlankSeverityDefaultsToWarning(t *testing.T) {
summary := Summarise([]Finding{
{Severity: ""},
{Severity: "info"},
})
assert.Equal(t, 2, summary.Total)
assert.Equal(t, 1, summary.Warnings)
assert.Equal(t, 1, summary.Info)
assert.Equal(t, 0, summary.Errors)
assert.True(t, summary.Passed)
}
func TestWriteJSON_Good_Roundtrip(t *testing.T) {
findings := sampleFindings()
var buf bytes.Buffer
@ -116,6 +129,11 @@ func TestWriteJSONL_Good_Empty(t *testing.T) {
assert.Empty(t, buf.String())
}
func TestWriteJSONL_Bad_PropagatesWriterErrors(t *testing.T) {
err := WriteJSONL(failingWriter{}, sampleFindings())
require.Error(t, err)
}
func TestWriteText_Good(t *testing.T) {
findings := sampleFindings()
var buf bytes.Buffer

View file

@ -29,6 +29,9 @@ func TestDetectLanguage_Good(t *testing.T) {
{"noextension", ""},
{"file.py", "python"},
{"Dockerfile", "dockerfile"},
{"services/Dockerfile.prod", "dockerfile"},
{"configs/settings.yaml", "yaml"},
{"configs/settings.yml", "yaml"},
}
for _, tt := range tests {
@ -39,6 +42,15 @@ func TestDetectLanguage_Good(t *testing.T) {
}
}
func TestDetectLanguage_Bad_UnknownExtension(t *testing.T) {
assert.Equal(t, "", DetectLanguage("notes.txt"))
assert.Equal(t, "", DetectLanguage("README"))
}
func TestDetectLanguage_Ugly_DockerfileVariant(t *testing.T) {
assert.Equal(t, "dockerfile", DetectLanguage("nested/Dockerfile.test"))
}
func TestScanDir_Good_FindsMatches(t *testing.T) {
dir := t.TempDir()
@ -209,6 +221,58 @@ func TestScanFile_Good_Python(t *testing.T) {
assert.Equal(t, "python", DetectLanguage(file))
}
func TestScanFile_Bad_NoMatchingLanguageRules(t *testing.T) {
dir := t.TempDir()
file := filepath.Join(dir, "app.go")
err := os.WriteFile(file, []byte("package main\n"), 0o644)
require.NoError(t, err)
rules := []Rule{
{
ID: "php-only",
Title: "PHP TODO",
Severity: "low",
Languages: []string{"php"},
Pattern: `TODO`,
Fix: "Remove TODO",
Detection: "regex",
},
}
s, err := NewScanner(rules)
require.NoError(t, err)
findings, err := s.ScanFile(file)
require.NoError(t, err)
assert.Empty(t, findings)
}
func TestScanFile_Ugly_UnsupportedExtension(t *testing.T) {
dir := t.TempDir()
file := filepath.Join(dir, "notes.txt")
err := os.WriteFile(file, []byte("TODO: this is not a recognised source file\n"), 0o644)
require.NoError(t, err)
rules := []Rule{
{
ID: "go-only",
Title: "Go TODO",
Severity: "low",
Languages: []string{"go"},
Pattern: `TODO`,
Fix: "Remove TODO",
Detection: "regex",
},
}
s, err := NewScanner(rules)
require.NoError(t, err)
findings, err := s.ScanFile(file)
require.NoError(t, err)
assert.Nil(t, findings)
}
func TestScanDir_Good_Subdirectories(t *testing.T) {
dir := t.TempDir()