package lint import ( "go/parser" "go/token" "strings" "testing" ) // The lint, over this repository (novox/hq to-be 45 Phase 2, ADR 0227 rule 4 "how it is checked"): every // error branch that answers an empty collection says why that is the truth, or the build fails naming it. func TestNoReaderAnswersEmptyForAnError(t *testing.T) { found, err := EmptyOnError("../..") if err != nil { t.Fatal(err) } allowed := 0 for _, f := range found { if f.Allowed != "" { allowed++ continue } t.Errorf("%s answers an empty collection and no error when it could not read: refuse by name "+ "(return the error), or say at the return why empty is the truth (// %s )", f, Allow) } t.Logf("%d error branch(es) answer empty, each saying why", allowed) } // The lint itself: what it finds, and what it does not. func TestTheLintFindsEmptyOnError(t *testing.T) { const src = `package x func readContributions() []string { raw, err := read() if err != nil { return nil } return parse(raw) } func consumers() ([]string, error) { if err := load(); err != nil { return []string{}, nil } return nil, nil } func byName() (map[string]int, error) { if err := load(); err != nil { return nil, err } return map[string]int{}, nil } func allowed() ([]string, error) { if err := load(); err != nil { // empty-on-error: a store not yet seeded holds no seats, and the caller keeps its defaults return nil, nil } return nil, nil } func notFound() ([]string, error) { if errors.Is(err, ErrNoRows) { return nil, nil } return nil, nil } func inside() { f := func() []int { if readErr != nil { return nil } return []int{1} } _ = f } ` fset := token.NewFileSet() file, err := parser.ParseFile(fset, "x.go", src, parser.ParseComments) if err != nil { t.Fatal(err) } var failing, allowedFns []string for _, f := range inFile(fset, file, "x.go") { if f.Allowed != "" { allowedFns = append(allowedFns, f.Func) continue } failing = append(failing, f.Func) } want := "readContributions consumers inside (a function inside it)" if strings.Join(failing, " ") != want { t.Fatalf("the lint found %q, want %q", failing, want) } if strings.Join(allowedFns, " ") != "allowed" { t.Fatalf("the allowance was not read: %q", allowedFns) } }