Files
go-admin/tools/checksilent/main_test.go
zhangwenjian b836945eea feat: add checksilent, for the failures that do not report themselves
Six checks, five at ERROR and one - the cross-repository menu-name comparison -
at WARN, because it can only match by regular expression across two modules and
a false positive that fails CI teaches people to silence the tool.

The summary names which contract roots were actually scanned: core/ is a
separate module with no directory here, and a check that quietly covers less
than it claims is worse than no check.
2026-09-01 17:45:41 +08:00

139 lines
3.7 KiB
Go

package main
import (
"bytes"
"encoding/json"
"strings"
"testing"
)
// Acceptance 14b, second half: the WARN check on its own leaves the exit code
// at zero. If it did not, the first person it misjudged would silence it, and a
// silenced check is worse than none - it looks like coverage.
func TestOnlyWarningsExitZero(t *testing.T) {
root, ui := menuNameFixture(t, "DemoProduct", "Product")
var buf bytes.Buffer
code, err := run(&buf, root, options{UIDir: ui}, false)
if err != nil {
t.Fatal(err)
}
if code != 0 {
t.Errorf("exit code = %d, want 0:\n%s", code, buf.String())
}
out := buf.String()
if !strings.Contains(out, "[WARN]") {
t.Errorf("the warning was not printed:\n%s", out)
}
if !strings.Contains(out, "0 error(s), 1 warning(s)") {
t.Errorf("summary = %s", out)
}
if !strings.Contains(out, "Warnings do not affect the exit code.") {
t.Errorf("output must say warnings are not fatal:\n%s", out)
}
}
// Acceptance 14b, first half: any of the other five fails the run.
func TestAnyErrorExitsNonZero(t *testing.T) {
root := fixture(t, map[string]string{
"app/admin/models/user.go": "package models\n\ntype SysUser struct{}\n",
"common/middleware/auth.go": `package middleware
import "go-admin/app/admin/models"
var _ = models.SysUser{}
`,
})
var buf bytes.Buffer
code, err := run(&buf, root, options{}, false)
if err != nil {
t.Fatal(err)
}
if code != 1 {
t.Errorf("exit code = %d, want 1:\n%s", code, buf.String())
}
if !strings.Contains(buf.String(), "[ERROR]") {
t.Errorf("output = %s", buf.String())
}
}
func TestCleanTreeExitsZero(t *testing.T) {
root := fixture(t, map[string]string{
"common/models/by.go": "package models\n\ntype ControlBy struct{}\n",
})
var buf bytes.Buffer
code, err := run(&buf, root, options{}, false)
if err != nil {
t.Fatal(err)
}
if code != 0 {
t.Errorf("exit code = %d, want 0:\n%s", code, buf.String())
}
if !strings.Contains(buf.String(), "0 error(s), 0 warning(s)") {
t.Errorf("output = %s", buf.String())
}
}
// Every message has to name a file and a line, or the report is a puzzle rather
// than a finding.
func TestTextOutputLocatesEveryFinding(t *testing.T) {
root := fixture(t, map[string]string{
"app/admin/models/user.go": "package models\n\ntype SysUser struct{}\n",
"common/middleware/auth.go": `package middleware
import "go-admin/app/admin/models"
var _ = models.SysUser{}
`,
})
var buf bytes.Buffer
if _, err := run(&buf, root, options{}, false); err != nil {
t.Fatal(err)
}
line := strings.SplitN(buf.String(), "\n", 2)[0]
if !strings.HasPrefix(line, "common/middleware/auth.go:3:") {
t.Errorf("first line does not locate the finding: %q", line)
}
}
func TestJSONOutput(t *testing.T) {
root := fixture(t, map[string]string{
"app/admin/models/user.go": "package models\n\ntype SysUser struct{}\n",
"common/middleware/auth.go": `package middleware
import "go-admin/app/admin/models"
var _ = models.SysUser{}
`,
})
var buf bytes.Buffer
code, err := run(&buf, root, options{}, true)
if err != nil {
t.Fatal(err)
}
if code != 1 {
t.Errorf("exit code = %d", code)
}
var findings []Finding
if err = json.Unmarshal(buf.Bytes(), &findings); err != nil {
t.Fatalf("output is not JSON: %v\n%s", err, buf.String())
}
if len(findings) != 1 || findings[0].Check != checkImportBoundary || findings[0].Severity != "ERROR" {
t.Errorf("findings = %+v", findings)
}
}
// The tool runs on this repository in CI, so it has to be clean here. This also
// covers acceptance 13b: nothing under common/ imports app/ any more.
func TestThisRepositoryIsClean(t *testing.T) {
var buf bytes.Buffer
code, err := run(&buf, "../..", options{}, false)
if err != nil {
t.Fatal(err)
}
if code != 0 {
t.Errorf("checksilent reports problems in this repository:\n%s", buf.String())
}
}