pkgsrc-Changes archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
CVS commit: pkgsrc/pkgtools/pkglint
Module Name: pkgsrc
Committed By: rillig
Date: Tue Nov 19 06:51:39 UTC 2019
Modified Files:
pkgsrc/pkgtools/pkglint: Makefile
pkgsrc/pkgtools/pkglint/files: alternatives.go alternatives_test.go
mktypes.go pkgsrc.go pkgsrc_test.go testnames_test.go
pkgsrc/pkgtools/pkglint/files/getopt: getopt_test.go
pkgsrc/pkgtools/pkglint/files/histogram: histogram_test.go
pkgsrc/pkgtools/pkglint/files/intqa: testnames.go testnames_test.go
pkgsrc/pkgtools/pkglint/files/licenses: licenses_test.go
pkgsrc/pkgtools/pkglint/files/pkgver: vercmp_test.go
pkgsrc/pkgtools/pkglint/files/textproc: lexer_test.go
pkgsrc/pkgtools/pkglint/files/trace: tracing_test.go
Log Message:
pkgtools/pkglint: update to 19.3.9
Changes since 19.3.8:
Match man pages in ALTERNATIVES with their counterparts in PLIST. In
PLIST files, ${PKGMANDIR} may be abbreviated as a simple "man", but not
in ALTERNATIVES.
To generate a diff of this commit:
cvs rdiff -u -r1.608 -r1.609 pkgsrc/pkgtools/pkglint/Makefile
cvs rdiff -u -r1.15 -r1.16 pkgsrc/pkgtools/pkglint/files/alternatives.go
cvs rdiff -u -r1.16 -r1.17 pkgsrc/pkgtools/pkglint/files/alternatives_test.go
cvs rdiff -u -r1.19 -r1.20 pkgsrc/pkgtools/pkglint/files/mktypes.go
cvs rdiff -u -r1.40 -r1.41 pkgsrc/pkgtools/pkglint/files/pkgsrc.go
cvs rdiff -u -r1.34 -r1.35 pkgsrc/pkgtools/pkglint/files/pkgsrc_test.go
cvs rdiff -u -r1.7 -r1.8 pkgsrc/pkgtools/pkglint/files/testnames_test.go
cvs rdiff -u -r1.11 -r1.12 \
pkgsrc/pkgtools/pkglint/files/getopt/getopt_test.go
cvs rdiff -u -r1.2 -r1.3 \
pkgsrc/pkgtools/pkglint/files/histogram/histogram_test.go
cvs rdiff -u -r1.5 -r1.6 pkgsrc/pkgtools/pkglint/files/intqa/testnames.go
cvs rdiff -u -r1.2 -r1.3 \
pkgsrc/pkgtools/pkglint/files/intqa/testnames_test.go
cvs rdiff -u -r1.6 -r1.7 \
pkgsrc/pkgtools/pkglint/files/licenses/licenses_test.go
cvs rdiff -u -r1.6 -r1.7 pkgsrc/pkgtools/pkglint/files/pkgver/vercmp_test.go
cvs rdiff -u -r1.7 -r1.8 pkgsrc/pkgtools/pkglint/files/textproc/lexer_test.go
cvs rdiff -u -r1.4 -r1.5 pkgsrc/pkgtools/pkglint/files/trace/tracing_test.go
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: pkgsrc/pkgtools/pkglint/Makefile
diff -u pkgsrc/pkgtools/pkglint/Makefile:1.608 pkgsrc/pkgtools/pkglint/Makefile:1.609
--- pkgsrc/pkgtools/pkglint/Makefile:1.608 Sun Nov 17 02:06:01 2019
+++ pkgsrc/pkgtools/pkglint/Makefile Tue Nov 19 06:51:38 2019
@@ -1,6 +1,6 @@
-# $NetBSD: Makefile,v 1.608 2019/11/17 02:06:01 rillig Exp $
+# $NetBSD: Makefile,v 1.609 2019/11/19 06:51:38 rillig Exp $
-PKGNAME= pkglint-19.3.8
+PKGNAME= pkglint-19.3.9
CATEGORIES= pkgtools
DISTNAME= tools
MASTER_SITES= ${MASTER_SITE_GITHUB:=golang/}
Index: pkgsrc/pkgtools/pkglint/files/alternatives.go
diff -u pkgsrc/pkgtools/pkglint/files/alternatives.go:1.15 pkgsrc/pkgtools/pkglint/files/alternatives.go:1.16
--- pkgsrc/pkgtools/pkglint/files/alternatives.go:1.15 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/alternatives.go Tue Nov 19 06:51:38 2019
@@ -28,6 +28,9 @@ func CheckFileAlternatives(filename stri
if plist.Files[plistName] != nil || G.Pkg.vars.IsDefined("ALTERNATIVES_SRC") {
return
}
+ if plist.Files[strings.Replace(plistName, "${PKGMANDIR}", "man", 1)] != nil {
+ return
+ }
switch {
Index: pkgsrc/pkgtools/pkglint/files/alternatives_test.go
diff -u pkgsrc/pkgtools/pkglint/files/alternatives_test.go:1.16 pkgsrc/pkgtools/pkglint/files/alternatives_test.go:1.17
--- pkgsrc/pkgtools/pkglint/files/alternatives_test.go:1.16 Sun Jul 14 21:25:47 2019
+++ pkgsrc/pkgtools/pkglint/files/alternatives_test.go Tue Nov 19 06:51:38 2019
@@ -106,3 +106,25 @@ func (s *Suite) Test_CheckFileAlternativ
t.CheckOutputEmpty()
}
+
+// When a man page is mentioned in the ALTERNATIVES file, it must use the
+// PKGMANDIR variable. In the PLIST files though, there is some magic
+// in the pkgsrc infrastructure that maps man/ to ${PKGMANDIR}, which
+// leads to a bit less typing.
+//
+// Seen in graphics/py-blockdiag.
+func (s *Suite) Test_CheckFileAlternatives__PLIST_man(c *check.C) {
+ t := s.Init(c)
+
+ t.SetUpPackage("category/package")
+ t.CreateFileLines("category/package/ALTERNATIVES",
+ "@PKGMANDIR@/man1/blockdiag @PREFIX@/@PKGMANDIR@/man1/blockdiag-@PYVERSSUFFIX@.1")
+ t.CreateFileLines("category/package/PLIST",
+ PlistCvsID,
+ "man/man1/blockdiag-${PYVERSSUFFIX}.1")
+ t.FinishSetUp()
+
+ G.Check(t.File("category/package"))
+
+ t.CheckOutputEmpty()
+}
Index: pkgsrc/pkgtools/pkglint/files/mktypes.go
diff -u pkgsrc/pkgtools/pkglint/files/mktypes.go:1.19 pkgsrc/pkgtools/pkglint/files/mktypes.go:1.20
--- pkgsrc/pkgtools/pkglint/files/mktypes.go:1.19 Fri Nov 1 19:56:53 2019
+++ pkgsrc/pkgtools/pkglint/files/mktypes.go Tue Nov 19 06:51:38 2019
@@ -110,7 +110,7 @@ func (m MkVarUseModifier) IsToLower() bo
func (m MkVarUseModifier) ChangesWords() bool {
text := m.Text
- // See MkParser.VarUseModifiers for the meaning of these modifiers.
+ // See MkParser.varUseModifier for the meaning of these modifiers.
switch text[0] {
case 'E', 'H', 'M', 'N', 'O', 'R', 'T':
Index: pkgsrc/pkgtools/pkglint/files/pkgsrc.go
diff -u pkgsrc/pkgtools/pkglint/files/pkgsrc.go:1.40 pkgsrc/pkgtools/pkglint/files/pkgsrc.go:1.41
--- pkgsrc/pkgtools/pkglint/files/pkgsrc.go:1.40 Sun Nov 17 02:55:56 2019
+++ pkgsrc/pkgtools/pkglint/files/pkgsrc.go Tue Nov 19 06:51:38 2019
@@ -219,7 +219,7 @@ func (src *Pkgsrc) loadDocChangesFromFil
continue
}
- if year != "" && len(change.Date) >= 4 && change.Date[0:4] != year {
+ if year != "" && change.Date[0:4] != year {
line.Warnf("Year %q for %s does not match the filename %s.",
change.Date[0:4], change.Pkgpath, filename)
}
Index: pkgsrc/pkgtools/pkglint/files/pkgsrc_test.go
diff -u pkgsrc/pkgtools/pkglint/files/pkgsrc_test.go:1.34 pkgsrc/pkgtools/pkglint/files/pkgsrc_test.go:1.35
--- pkgsrc/pkgtools/pkglint/files/pkgsrc_test.go:1.34 Sun Nov 17 02:55:56 2019
+++ pkgsrc/pkgtools/pkglint/files/pkgsrc_test.go Tue Nov 19 06:51:38 2019
@@ -368,6 +368,10 @@ func (s *Suite) Test_Pkgsrc_parseDocChan
test("\t Too large indentation",
"WARN: doc/CHANGES-2019:123: Package changes should be indented using a single tab, not \"\\t \".")
+ test("\t",
+ "WARN: doc/CHANGES-2019:123: Invalid doc/CHANGES line: \t")
+ test("\t1",
+ "WARN: doc/CHANGES-2019:123: Invalid doc/CHANGES line: \t1")
test("\t1 2 3 4",
"WARN: doc/CHANGES-2019:123: Invalid doc/CHANGES line: \t1 2 3 4")
test("\t1 2 3 4 5",
@@ -387,25 +391,25 @@ func (s *Suite) Test_Pkgsrc_parseDocChan
nil...)
// "to" is wrong
- test("\tAdded pkgpath to 1.0 [author date]",
+ test("\tAdded pkgpath to 1.0 [author 2019-01-01]",
"WARN: doc/CHANGES-2019:123: Invalid doc/CHANGES line: "+
- "\tAdded pkgpath to 1.0 [author date]")
+ "\tAdded pkgpath to 1.0 [author 2019-01-01]")
test("\tUpdated pkgpath to 1.0 [author 2019-01-01]",
nil...)
// "from" is wrong
- test("\tUpdated pkgpath from 1.0 [author date]",
+ test("\tUpdated pkgpath from 1.0 [author 2019-01-01]",
"WARN: doc/CHANGES-2019:123: Invalid doc/CHANGES line: "+
- "\tUpdated pkgpath from 1.0 [author date]")
+ "\tUpdated pkgpath from 1.0 [author 2019-01-01]")
test("\tDowngraded pkgpath to 1.0 [author 2019-01-01]",
nil...)
// "from" is wrong
- test("\tDowngraded pkgpath from 1.0 [author date]",
+ test("\tDowngraded pkgpath from 1.0 [author 2019-01-01]",
"WARN: doc/CHANGES-2019:123: Invalid doc/CHANGES line: "+
- "\tDowngraded pkgpath from 1.0 [author date]")
+ "\tDowngraded pkgpath from 1.0 [author 2019-01-01]")
test("\tRemoved pkgpath [author 2019-01-01]",
nil...)
@@ -414,30 +418,30 @@ func (s *Suite) Test_Pkgsrc_parseDocChan
nil...)
// "and" is wrong
- test("\tRemoved pkgpath and pkgpath [author date]",
+ test("\tRemoved pkgpath and pkgpath [author 2019-01-01]",
"WARN: doc/CHANGES-2019:123: Invalid doc/CHANGES line: "+
- "\tRemoved pkgpath and pkgpath [author date]")
+ "\tRemoved pkgpath and pkgpath [author 2019-01-01]")
test("\tRenamed pkgpath to other [author 2019-01-01]",
nil...)
// "from" is wrong
- test("\tRenamed pkgpath from previous [author date]",
+ test("\tRenamed pkgpath from previous [author 2019-01-01]",
"WARN: doc/CHANGES-2019:123: Invalid doc/CHANGES line: "+
- "\tRenamed pkgpath from previous [author date]")
+ "\tRenamed pkgpath from previous [author 2019-01-01]")
test("\tMoved pkgpath to other [author 2019-01-01]",
nil...)
// "from" is wrong
- test("\tMoved pkgpath from previous [author date]",
+ test("\tMoved pkgpath from previous [author 2019-01-01]",
"WARN: doc/CHANGES-2019:123: Invalid doc/CHANGES line: "+
- "\tMoved pkgpath from previous [author date]")
+ "\tMoved pkgpath from previous [author 2019-01-01]")
// "Split" is wrong
- test("\tSplit pkgpath into a and b [author date]",
+ test("\tSplit pkgpath into a and b [author 2019-01-01]",
"WARN: doc/CHANGES-2019:123: Invalid doc/CHANGES line: "+
- "\tSplit pkgpath into a and b [author date]")
+ "\tSplit pkgpath into a and b [author 2019-01-01]")
// Entries ending in a colon are used for infrastructure changes.
test("\tmk: remove support for USE_CROSSBASE [author 2016-06-19]",
Index: pkgsrc/pkgtools/pkglint/files/testnames_test.go
diff -u pkgsrc/pkgtools/pkglint/files/testnames_test.go:1.7 pkgsrc/pkgtools/pkglint/files/testnames_test.go:1.8
--- pkgsrc/pkgtools/pkglint/files/testnames_test.go:1.7 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/testnames_test.go Tue Nov 19 06:51:38 2019
@@ -10,7 +10,7 @@ import (
// Test_${Type}_${Method}__${description_using_underscores}
func (s *Suite) Test__test_names(c *check.C) {
ck := intqa.NewTestNameChecker(c.Errorf)
- ck.IgnoreFiles("*yacc.go")
- ck.Enable(intqa.EAll, -intqa.EMissingTest)
+ ck.Configure("*", "*", "*", -intqa.EMissingTest)
+ ck.Configure("*yacc.go", "*", "*", intqa.ENone)
ck.Check()
}
Index: pkgsrc/pkgtools/pkglint/files/getopt/getopt_test.go
diff -u pkgsrc/pkgtools/pkglint/files/getopt/getopt_test.go:1.11 pkgsrc/pkgtools/pkglint/files/getopt/getopt_test.go:1.12
--- pkgsrc/pkgtools/pkglint/files/getopt/getopt_test.go:1.11 Sun Nov 17 01:26:26 2019
+++ pkgsrc/pkgtools/pkglint/files/getopt/getopt_test.go Tue Nov 19 06:51:38 2019
@@ -411,6 +411,6 @@ func (s *Suite) Test_Options_Help__with_
func (s *Suite) Test__test_names(c *check.C) {
ck := intqa.NewTestNameChecker(c.Errorf)
- ck.Enable(intqa.EAll, -intqa.EMissingTest)
+ ck.Configure("*", "*", "*", -intqa.EMissingTest)
ck.Check()
}
Index: pkgsrc/pkgtools/pkglint/files/histogram/histogram_test.go
diff -u pkgsrc/pkgtools/pkglint/files/histogram/histogram_test.go:1.2 pkgsrc/pkgtools/pkglint/files/histogram/histogram_test.go:1.3
--- pkgsrc/pkgtools/pkglint/files/histogram/histogram_test.go:1.2 Sun Nov 17 01:26:26 2019
+++ pkgsrc/pkgtools/pkglint/files/histogram/histogram_test.go Tue Nov 19 06:51:38 2019
@@ -30,6 +30,6 @@ func (s *Suite) Test_Histogram(c *check.
func (s *Suite) Test__test_names(c *check.C) {
ck := intqa.NewTestNameChecker(c.Errorf)
- ck.Enable(intqa.EAll, -intqa.EMissingTest)
+ ck.Configure("*", "*", "*", -intqa.EMissingTest)
ck.Check()
}
Index: pkgsrc/pkgtools/pkglint/files/intqa/testnames.go
diff -u pkgsrc/pkgtools/pkglint/files/intqa/testnames.go:1.5 pkgsrc/pkgtools/pkglint/files/intqa/testnames.go:1.6
--- pkgsrc/pkgtools/pkglint/files/intqa/testnames.go:1.5 Sun Nov 17 01:26:26 2019
+++ pkgsrc/pkgtools/pkglint/files/intqa/testnames.go Tue Nov 19 06:51:38 2019
@@ -8,7 +8,8 @@ import (
"go/token"
"io"
"os"
- "path/filepath"
+ "path"
+ "reflect"
"sort"
"strings"
"unicode"
@@ -17,7 +18,7 @@ import (
type Error int
const (
- ENone Error = iota
+ ENone Error = iota + 1
EAll
// A function or method does not have a corresponding test.
@@ -45,43 +46,47 @@ const (
type TestNameChecker struct {
errorf func(format string, args ...interface{})
- ignoredFiles []string
- order int
+ filters []filter
+ order int
testees []*testee
tests []*test
- errorsMask uint64
- errors []string
- out io.Writer
+ errors []string
+ out io.Writer
}
// NewTestNameChecker creates a new checker.
-// By default, all errors are disabled; call Enable to enable them.
+// By default, all errors are enabled;
+// call Configure to disable them selectively.
func NewTestNameChecker(errorf func(format string, args ...interface{})) *TestNameChecker {
- return &TestNameChecker{errorf: errorf, out: os.Stderr}
-}
+ ck := TestNameChecker{errorf: errorf, out: os.Stderr}
-func (ck *TestNameChecker) IgnoreFiles(fileGlob string) {
- ck.ignoredFiles = append(ck.ignoredFiles, fileGlob)
-}
-
-func (ck *TestNameChecker) Enable(errors ...Error) {
- for _, err := range errors {
- if err == ENone {
- ck.errorsMask = 0
- } else if err == EAll {
- ck.errorsMask = ^uint64(0)
- } else if err < 0 {
- ck.errorsMask &= ^(uint64(1) << -uint(err))
- } else {
- ck.errorsMask |= uint64(1) << uint(err)
- }
- }
+ // For test fixtures from https://gopkg.in/check/v1.
+ ck.Configure("*_test.go", "*", "SetUpTest", -EMissingTest)
+ ck.Configure("*_test.go", "*", "TearDownTest", -EMissingTest)
+
+ // See https://github.com/rillig/gobco.
+ ck.Configure("gobco_*.go", "gobco*", "*", -EMissingTest)
+ ck.Configure("gobco_*.go", "", "gobco*", -EMissingTest)
+
+ return &ck
+}
+
+// Configure sets the errors that are activated for the given code,
+// specified by shell patterns like in path.Match.
+//
+// All rules are applied in order. Later rules overwrite earlier rules.
+//
+// Individual errors can be enabled by giving their constant and disabled
+// by negating them, such as -EMissingTestee. To reset everything, use
+// either EAll or ENone.
+func (ck *TestNameChecker) Configure(filenames, typeNames, funcNames string, errors ...Error) {
+ ck.filters = append(ck.filters, filter{filenames, typeNames, funcNames, errors})
}
func (ck *TestNameChecker) Check() {
- ck.load()
+ ck.load(".")
ck.checkTestees()
ck.checkTests()
ck.checkOrder()
@@ -89,29 +94,18 @@ func (ck *TestNameChecker) Check() {
}
// load loads all type, function and method names from the current package.
-func (ck *TestNameChecker) load() {
+func (ck *TestNameChecker) load(dir string) {
+
fileSet := token.NewFileSet()
- pkgs, err := parser.ParseDir(fileSet, ".", nil, 0)
+ pkgs, err := parser.ParseDir(fileSet, dir, nil, 0)
if err != nil {
panic(err)
}
- var pkgnames []string
- for pkgname := range pkgs {
- pkgnames = append(pkgnames, pkgname)
- }
- sort.Strings(pkgnames)
-
- for _, pkgname := range pkgnames {
+ for _, pkgname := range sortedKeys(pkgs) {
files := pkgs[pkgname].Files
- var filenames []string
- for filename := range files {
- filenames = append(filenames, filename)
- }
- sort.Strings(filenames)
-
- for _, filename := range filenames {
+ for _, filename := range sortedKeys(files) {
file := files[filename]
for _, decl := range file.Decls {
ck.loadDecl(decl, filename)
@@ -131,7 +125,7 @@ func (ck *TestNameChecker) loadDecl(decl
switch spec := spec.(type) {
case *ast.TypeSpec:
typeName := spec.Name.Name
- ck.addCode(code{filename, typeName, "", ck.nextOrder()})
+ ck.addCode(code{filename, typeName, "", 0})
}
}
@@ -145,16 +139,28 @@ func (ck *TestNameChecker) loadDecl(decl
typeName = typeExpr.(*ast.Ident).Name
}
}
- ck.addCode(code{filename, typeName, decl.Name.Name, ck.nextOrder()})
+ funcName := decl.Name.Name
+ ck.addCode(code{filename, typeName, funcName, 0})
}
}
func (ck *TestNameChecker) addCode(code code) {
- isTest := strings.HasSuffix(code.file, "_test.go") &&
- code.Type != "" &&
- strings.HasPrefix(code.Func, "Test")
+ if code.isTestScope() && code.isFunc() && code.Func == "TestMain" {
+ // This is not a test for Main, but a wrapper function of the test.
+ // Therefore it is completely ignored.
+ // See https://golang.org/pkg/testing/#hdr-Main.
+ //
+ // Among others, this function is created by
+ // https://github.com/rillig/gobco when measuring the branch
+ // coverage of a package.
+ return
+ }
- if isTest {
+ if !ck.isRelevant(code.file, code.Type, code.Func, EAll) {
+ return
+ }
+
+ if code.isTest() {
ck.addTest(code)
} else {
ck.addTestee(code)
@@ -162,15 +168,19 @@ func (ck *TestNameChecker) addCode(code
}
func (ck *TestNameChecker) addTestee(code code) {
+ code.order = ck.nextOrder()
ck.testees = append(ck.testees, &testee{code})
}
func (ck *TestNameChecker) addTest(code code) {
- if !strings.HasPrefix(code.Func, "Test_") {
+ if !strings.HasPrefix(code.Func, "Test_") &&
+ code.Func != "Test" &&
ck.addError(
EName,
+ code,
"Test %q must start with %q.",
- code.fullName(), "Test_")
+ code.fullName(), "Test_") {
+
return
}
@@ -178,16 +188,18 @@ func (ck *TestNameChecker) addTest(code
testeeName := strings.TrimPrefix(strings.TrimPrefix(parts[0], "Test"), "_")
descr := ""
if len(parts) > 1 {
- if parts[1] == "" {
+ if parts[1] == "" &&
ck.addError(
EName,
- "Test %q must not have a nonempty description.",
- code.fullName())
+ code,
+ "Test %q must have a nonempty description.",
+ code.fullName()) {
return
}
descr = parts[1]
}
+ code.order = ck.nextOrder()
ck.tests = append(ck.tests, &test{code, testeeName, descr, nil})
}
@@ -213,8 +225,8 @@ func (ck *TestNameChecker) relate() {
func (ck *TestNameChecker) checkTests() {
for _, test := range ck.tests {
ck.checkTestFile(test)
- ck.checkTestName(test)
ck.checkTestTestee(test)
+ ck.checkTestDescr(test)
}
}
@@ -225,12 +237,15 @@ func (ck *TestNameChecker) checkTestFile
}
correctTestFile := strings.TrimSuffix(testee.file, ".go") + "_test.go"
- if correctTestFile != test.file {
- ck.addError(
- EFile,
- "Test %q for %q must be in %s instead of %s.",
- test.fullName(), testee.fullName(), correctTestFile, test.file)
+ if correctTestFile == test.file {
+ return
}
+
+ ck.addError(
+ EFile,
+ test.code,
+ "Test %q for %q must be in %s instead of %s.",
+ test.fullName(), testee.fullName(), correctTestFile, test.file)
}
func (ck *TestNameChecker) checkTestTestee(test *test) {
@@ -242,27 +257,23 @@ func (ck *TestNameChecker) checkTestTest
testeeName := strings.Replace(test.testeeName, "_", ".", -1)
ck.addError(
EMissingTestee,
+ test.code,
"Missing testee %q for test %q.",
testeeName, test.fullName())
}
-// checkTestName ensures that the method name does not accidentally
-// end up in the description of the test. This could happen if there is a
-// double underscore instead of a single underscore.
-func (ck *TestNameChecker) checkTestName(test *test) {
+// checkTestDescr ensures that the type or function name of the testee
+// does not accidentally end up in the description of the test. This could
+// happen if there is a double underscore instead of a single underscore.
+func (ck *TestNameChecker) checkTestDescr(test *test) {
testee := test.testee
- if testee == nil {
- return
- }
- if testee.Type != "" && testee.Func != "" {
- return
- }
- if !isCamelCase(test.descr) {
+ if testee == nil || testee.isMethod() || !isCamelCase(test.descr) {
return
}
ck.addError(
EName,
+ testee.code,
"%s: Test description %q must not use CamelCase in the first word.",
test.fullName(), test.descr)
}
@@ -274,29 +285,49 @@ func (ck *TestNameChecker) checkTestees(
}
for _, testee := range ck.testees {
- if tested[testee] || testee.Func == "" {
- continue
- }
+ ck.checkTesteeTest(testee, tested)
+ }
+}
- testName := "Test_" + join(testee.Type, "_", testee.Func)
- ck.addError(
- EMissingTest,
- "Missing unit test %q for %q.",
- testName, testee.fullName())
+func (ck *TestNameChecker) checkTesteeTest(testee *testee, tested map[*testee]bool) {
+ if tested[testee] || testee.isType() {
+ return
}
+
+ testName := "Test_" + join(testee.Type, "_", testee.Func)
+ ck.addError(
+ EMissingTest,
+ testee.code,
+ "Missing unit test %q for %q.",
+ testName, testee.fullName())
}
-func (ck *TestNameChecker) isIgnored(filename string) bool {
- for _, mask := range ck.ignoredFiles {
- ok, err := filepath.Match(mask, filename)
- if err != nil {
- panic(err)
+// isRelevant checks whether the given error is enabled.
+func (ck *TestNameChecker) isRelevant(filename, typeName, funcName string, e Error) bool {
+ mask := ^uint64(0)
+ for _, filter := range ck.filters {
+ if matches(filename, filter.filenames) &&
+ matches(typeName, filter.typeNames) &&
+ matches(funcName, filter.funcNames) {
+ mask = ck.errorsMask(mask, filter.errors...)
}
- if ok {
- return true
+ }
+ return mask&ck.errorsMask(0, e) != 0
+}
+
+func (ck *TestNameChecker) errorsMask(mask uint64, errors ...Error) uint64 {
+ for _, err := range errors {
+ if err == ENone {
+ mask = 0
+ } else if err == EAll {
+ mask = ^uint64(0)
+ } else if err < 0 {
+ mask &= ^(uint64(1) << -uint(err))
+ } else {
+ mask |= uint64(1) << uint(err)
}
}
- return false
+ return mask
}
// checkOrder ensures that the tests appear in the same order as their
@@ -323,18 +354,22 @@ func (ck *TestNameChecker) checkOrder()
break
}
}
+
ck.addError(
EOrder,
- "Test %q should be ordered before %q.",
+ test.code,
+ "Test %q must be ordered before %q.",
test.fullName(), insertBefore.fullName())
}
}
}
-func (ck *TestNameChecker) addError(e Error, format string, args ...interface{}) {
- if ck.errorsMask&(uint64(1)<<uint(e)) != 0 {
+func (ck *TestNameChecker) addError(e Error, c code, format string, args ...interface{}) bool {
+ relevant := ck.isRelevant(c.file, c.Type, c.Func, e)
+ if relevant {
ck.errors = append(ck.errors, fmt.Sprintf(format, args...))
}
+ return relevant
}
func (ck *TestNameChecker) print() {
@@ -342,23 +377,22 @@ func (ck *TestNameChecker) print() {
_, _ = fmt.Fprintln(ck.out, msg)
}
- errors := plural(len(ck.errors), "error", "errors")
- if len(ck.errors) > 0 {
- ck.errorf("%s.", errors)
+ n := len(ck.errors)
+ if n > 1 {
+ ck.errorf("%d errors.", n)
+ } else if n == 1 {
+ ck.errorf("%d error.", n)
}
}
-type code struct {
- file string // The file containing the code
- Type string // The type, e.g. MkLine
- Func string // The function or method name, e.g. Warnf
- order int // The relative order in the file
+type filter struct {
+ filenames string
+ typeNames string
+ funcNames string
+ errors []Error
}
-func (c *code) fullName() string { return join(c.Type, ".", c.Func) }
-
// testee is an element of the source code that can be tested.
-// It is either a type, a function or a method.
type testee struct {
code
}
@@ -371,15 +405,24 @@ type test struct {
testee *testee
}
-func plural(n int, sg, pl string) string {
- if n == 0 {
- return ""
- }
- form := pl
- if n == 1 {
- form = sg
- }
- return fmt.Sprintf("%d %s", n, form)
+// code is either a type, a function or a method.
+type code struct {
+ file string // the file containing the code
+ Type string // the type, e.g. MkLine
+ Func string // the function or method name, e.g. Warnf
+ order int // the relative order in the file
+}
+
+func (c *code) fullName() string { return join(c.Type, ".", c.Func) }
+func (c *code) isFunc() bool { return c.Type == "" }
+func (c *code) isType() bool { return c.Func == "" }
+func (c *code) isMethod() bool { return c.Type != "" && c.Func != "" }
+
+func (c *code) isTest() bool {
+ return c.isTestScope() && strings.HasPrefix(c.Func, "Test")
+}
+func (c *code) isTestScope() bool {
+ return strings.HasSuffix(c.file, "_test.go")
}
func isCamelCase(str string) bool {
@@ -400,3 +443,21 @@ func join(a, sep, b string) string {
}
return a + sep + b
}
+
+func matches(subj string, pattern string) bool {
+ ok, err := path.Match(pattern, subj)
+ if err != nil {
+ panic(err)
+ }
+ return ok
+}
+
+// sortedKeys returns the sorted keys from an arbitrary map.
+func sortedKeys(m interface{}) []string {
+ var keys []string
+ for _, key := range reflect.ValueOf(m).MapKeys() {
+ keys = append(keys, key.Interface().(string))
+ }
+ sort.Strings(keys)
+ return keys
+}
Index: pkgsrc/pkgtools/pkglint/files/intqa/testnames_test.go
diff -u pkgsrc/pkgtools/pkglint/files/intqa/testnames_test.go:1.2 pkgsrc/pkgtools/pkglint/files/intqa/testnames_test.go:1.3
--- pkgsrc/pkgtools/pkglint/files/intqa/testnames_test.go:1.2 Sun Nov 17 02:06:01 2019
+++ pkgsrc/pkgtools/pkglint/files/intqa/testnames_test.go Tue Nov 19 06:51:38 2019
@@ -3,8 +3,10 @@ package intqa
import (
"bytes"
"fmt"
+ "go/ast"
"gopkg.in/check.v1"
"io/ioutil"
+ "path"
"testing"
)
@@ -26,7 +28,6 @@ func (s *Suite) Init(c *check.C) *TestNa
s.c = c
s.ck = NewTestNameChecker(errorf)
- s.ck.Enable(EAll)
s.ck.out = ioutil.Discard
return s.ck
}
@@ -37,6 +38,25 @@ func (s *Suite) TearDownTest(c *check.C)
s.CheckSummary("")
}
+func (s *Suite) CheckTestees(testees ...*testee) {
+ s.c.Check(s.ck.testees, check.DeepEquals, testees)
+ s.ck.testees = nil
+}
+
+func (*Suite) newTestee(filename, typeName, funcName string, order int) *testee {
+ return &testee{code{filename, typeName, funcName, order}}
+}
+
+func (s *Suite) CheckTests(tests ...*test) {
+ s.c.Check(s.ck.tests, check.DeepEquals, tests)
+ s.ck.tests = nil
+}
+
+func (*Suite) newTest(filename, typeName, funcName string, order int, testeeName, descr string, testee *testee) *test {
+ c := code{filename, typeName, funcName, order}
+ return &test{c, testeeName, descr, testee}
+}
+
func (s *Suite) CheckErrors(errors ...string) {
s.c.Check(s.ck.errors, check.DeepEquals, errors)
s.ck.errors = nil
@@ -47,51 +67,169 @@ func (s *Suite) CheckSummary(summary str
s.summary = ""
}
-func (s *Suite) Test_TestNameChecker_Enable(c *check.C) {
+func (s *Suite) Test_NewTestNameChecker(c *check.C) {
+ ck := s.Init(c)
+
+ c.Check(ck.isRelevant("*_test.go", "Suite", "SetUpTest", EAll), check.Equals, true)
+ c.Check(ck.isRelevant("*_test.go", "Suite", "SetUpTest", EMissingTest), check.Equals, false)
+
+ c.Check(ck.isRelevant("*_test.go", "Suite", "TearDownTest", EAll), check.Equals, true)
+ c.Check(ck.isRelevant("*_test.go", "Suite", "TearDownTest", EMissingTest), check.Equals, false)
+}
+
+func (s *Suite) Test_TestNameChecker_Configure(c *check.C) {
ck := s.Init(c)
- ck.Enable(ENone) // overwrite initialization from Suite.Init
+ ck.Configure("*", "*", "*", ENone) // overwrite initialization from Suite.Init
+
+ c.Check(ck.isRelevant("", "", "", EAll), check.Equals, false)
+ c.Check(ck.isRelevant("", "", "", EMissingTestee), check.Equals, false)
+ c.Check(ck.isRelevant("", "", "", EMissingTest), check.Equals, false)
+
+ ck.Configure("*", "*", "*", EAll)
- c.Check(ck.errorsMask, check.Equals, uint64(0))
+ c.Check(ck.isRelevant("", "", "", EAll), check.Equals, true)
+ c.Check(ck.isRelevant("", "", "", EMissingTestee), check.Equals, true)
+ c.Check(ck.isRelevant("", "", "", EMissingTest), check.Equals, true)
- ck.Enable(EAll)
+ ck.Configure("*", "*", "*", -EMissingTestee)
- c.Check(ck.errorsMask, check.Equals, ^uint64(0))
+ c.Check(ck.isRelevant("", "", "", EAll), check.Equals, true)
+ c.Check(ck.isRelevant("", "", "", EMissingTestee), check.Equals, false)
+ c.Check(ck.isRelevant("", "", "", EMissingTest), check.Equals, true)
+
+ ck.Configure("*", "*", "*", ENone, EMissingTest)
+
+ c.Check(ck.isRelevant("", "", "", EAll), check.Equals, true)
+ c.Check(ck.isRelevant("", "", "", EMissingTestee), check.Equals, false)
+ c.Check(ck.isRelevant("", "", "", EMissingTest), check.Equals, true)
+
+ ck.Configure("*", "*", "*", EAll, -EMissingTest)
+
+ c.Check(ck.isRelevant("", "", "", EAll), check.Equals, true)
+ c.Check(ck.isRelevant("", "", "", EMissingTestee), check.Equals, true)
+ c.Check(ck.isRelevant("", "", "", EMissingTest), check.Equals, false)
+}
- ck.Enable(ENone, EMissingTest)
+func (s *Suite) Test_TestNameChecker_Configure__ignore_single_function(c *check.C) {
+ ck := s.Init(c)
- c.Check(ck.errorsMask, check.Equals, uint64(4))
+ ck.Configure("*", "*", "*", EAll)
- ck.Enable(EAll, -EMissingTest)
+ // The intention of this rule is that this particular function is ignored.
+ // Everything else from that file is still processed.
+ ck.Configure("*_test.go", "", "TestMain", ENone)
- c.Check(ck.errorsMask, check.Equals, ^uint64(0)^4)
+ c.Check(ck.isRelevant("file_test.go", "", "", EAll), check.Equals, true)
+ c.Check(ck.isRelevant("file_test.go", "*", "*", EAll), check.Equals, true)
+ c.Check(ck.isRelevant("file_test.go", "*", "Other", EAll), check.Equals, true)
+ c.Check(ck.isRelevant("file_test.go", "", "TestMain", EAll), check.Equals, false)
+ c.Check(ck.isRelevant("file_test.go", "*", "TestMain", EAll), check.Equals, true)
}
func (s *Suite) Test_TestNameChecker_Check(c *check.C) {
ck := s.Init(c)
+ ck.Configure("*", "Suite", "*", -EMissingTest)
+
ck.Check()
s.CheckErrors(
- "Missing unit test \"Test_NewTestNameChecker\" for \"NewTestNameChecker\".",
- "Missing unit test \"Test_TestNameChecker_IgnoreFiles\" for \"TestNameChecker.IgnoreFiles\".",
- "Missing unit test \"Test_TestNameChecker_load\" for \"TestNameChecker.load\".",
- "Missing unit test \"Test_TestNameChecker_loadDecl\" for \"TestNameChecker.loadDecl\".",
"Missing unit test \"Test_TestNameChecker_addCode\" for \"TestNameChecker.addCode\".",
- "Missing unit test \"Test_TestNameChecker_addTestee\" for \"TestNameChecker.addTestee\".",
- "Missing unit test \"Test_TestNameChecker_nextOrder\" for \"TestNameChecker.nextOrder\".",
"Missing unit test \"Test_TestNameChecker_relate\" for \"TestNameChecker.relate\".",
- "Missing unit test \"Test_TestNameChecker_checkTests\" for \"TestNameChecker.checkTests\".",
- "Missing unit test \"Test_TestNameChecker_checkTestees\" for \"TestNameChecker.checkTestees\".",
- "Missing unit test \"Test_TestNameChecker_isIgnored\" for \"TestNameChecker.isIgnored\".",
- "Missing unit test \"Test_TestNameChecker_addError\" for \"TestNameChecker.addError\".",
- "Missing unit test \"Test_Test\" for \"Test\".",
- "Missing unit test \"Test_Suite_Init\" for \"Suite.Init\".",
- "Missing unit test \"Test_Suite_TearDownTest\" for \"Suite.TearDownTest\".",
- "Missing unit test \"Test_Suite_CheckErrors\" for \"Suite.CheckErrors\".",
- "Missing unit test \"Test_Suite_CheckSummary\" for \"Suite.CheckSummary\".",
- "Missing unit test \"Test_Value_Method\" for \"Value.Method\".")
- s.CheckSummary("18 errors.")
+ "Missing unit test \"Test_TestNameChecker_isRelevant\" for \"TestNameChecker.isRelevant\".")
+ s.CheckSummary("3 errors.")
+}
+
+func (s *Suite) Test_TestNameChecker_load__filtered_nothing(c *check.C) {
+ ck := s.Init(c)
+
+ ck.Configure("*", "*", "*", ENone)
+
+ ck.load(".")
+
+ c.Check(ck.testees, check.IsNil)
+ c.Check(ck.tests, check.IsNil)
+}
+
+func (s *Suite) Test_TestNameChecker_load__filtered_only_Value(c *check.C) {
+ ck := s.Init(c)
+
+ ck.Configure("*", "*", "*", ENone)
+ ck.Configure("*", "Value", "*", EAll)
+
+ ck.load(".")
+
+ c.Check(ck.testees, check.DeepEquals, []*testee{
+ {code{"testnames_test.go", "Value", "", 0}},
+ {code{"testnames_test.go", "Value", "Method", 1}}})
+ c.Check(ck.tests, check.IsNil)
+}
+
+func (s *Suite) Test_TestNameChecker_load__panic(c *check.C) {
+ ck := s.Init(c)
+
+ c.Check(
+ func() { ck.load("does-not-exist") },
+ check.PanicMatches,
+ `^open does-not-exist\b.*`)
+}
+
+func (s *Suite) Test_TestNameChecker_loadDecl(c *check.C) {
+ ck := s.Init(c)
+
+ typeDecl := func(name string) *ast.GenDecl {
+ return &ast.GenDecl{Specs: []ast.Spec{&ast.TypeSpec{Name: &ast.Ident{Name: name}}}}
+ }
+ funcDecl := func(name string) *ast.FuncDecl {
+ return &ast.FuncDecl{Name: &ast.Ident{Name: name}}
+ }
+ methodDecl := func(typeName, methodName string) *ast.FuncDecl {
+ return &ast.FuncDecl{
+ Name: &ast.Ident{Name: methodName},
+ Recv: &ast.FieldList{List: []*ast.Field{{Type: &ast.Ident{Name: typeName}}}}}
+ }
+
+ ck.loadDecl(typeDecl("TypeName"), "file_test.go")
+
+ s.CheckTestees(
+ s.newTestee("file_test.go", "TypeName", "", 0))
+
+ // The freestanding TestMain function is ignored by a hardcoded rule,
+ // independently of the configuration.
+ ck.loadDecl(funcDecl("TestMain"), "file_test.go")
+
+ // The TestMain method on a type is relevant, but violates the naming rule.
+ // Therefore it is ignored.
+ ck.loadDecl(methodDecl("Suite", "TestMain"), "file_test.go")
+
+ s.CheckTests(
+ nil...)
+ s.CheckErrors(
+ "Test \"Suite.TestMain\" must start with \"Test_\".")
+
+ // The above error can be disabled, and then the method is handled
+ // like any other test method.
+ ck.Configure("*", "Suite", "*", -EName)
+ ck.loadDecl(methodDecl("Suite", "TestMain"), "file_test.go")
+
+ s.CheckTests(
+ s.newTest("file_test.go", "Suite", "TestMain", 1, "Main", "", nil))
+
+ // There is no special handling for TestMain method with a description.
+ ck.loadDecl(methodDecl("Suite", "TestMain__descr"), "file_test.go")
+
+ s.CheckTests(
+ s.newTest("file_test.go", "Suite", "TestMain__descr", 2, "Main", "descr", nil))
+}
+
+func (s *Suite) Test_TestNameChecker_addTestee(c *check.C) {
+ ck := s.Init(c)
+
+ code := code{"filename.go", "Type", "Method", 0}
+ ck.addTestee(code)
+
+ c.Check(ck.testees, check.DeepEquals, []*testee{{code}})
}
func (s *Suite) Test_TestNameChecker_addTest(c *check.C) {
@@ -99,6 +237,7 @@ func (s *Suite) Test_TestNameChecker_add
ck.addTest(code{"filename.go", "Type", "Method", 0})
+ c.Check(ck.tests, check.IsNil)
s.CheckErrors(
"Test \"Type.Method\" must start with \"Test_\".")
}
@@ -106,10 +245,56 @@ func (s *Suite) Test_TestNameChecker_add
func (s *Suite) Test_TestNameChecker_addTest__empty_description(c *check.C) {
ck := s.Init(c)
- ck.addTest(code{"filename.go", "Suite", "Test_Method__", 0})
+ ck.addTest(code{"f_test.go", "Suite", "Test_Method__", 0})
+
+ s.CheckErrors(
+ "Test \"Suite.Test_Method__\" must have a nonempty description.")
+
+ // The test is not registered and thus cannot complain about its missing
+ // testee.
+ ck.checkTests()
+
+ s.CheckErrors(
+ nil...)
+}
+
+func (s *Suite) Test_TestNameChecker_addTest__suppressed_empty_description(c *check.C) {
+ ck := s.Init(c)
+
+ ck.Configure("*", "*", "*", -EName)
+ ck.addTest(code{"f_test.go", "Suite", "Test_Method__", 0})
+
+ s.CheckErrors(
+ nil...)
+
+ // Since there was no error above, the test is added normally
+ // and can complain about its missing testee.
+ ck.checkTests()
+
+ s.CheckErrors(
+ "Missing testee \"Method\" for test \"Suite.Test_Method__\".")
+}
+
+func (s *Suite) Test_TestNameChecker_nextOrder(c *check.C) {
+ ck := s.Init(c)
+
+ c.Check(ck.nextOrder(), check.Equals, 0)
+ c.Check(ck.nextOrder(), check.Equals, 1)
+ c.Check(ck.nextOrder(), check.Equals, 2)
+}
+
+func (s *Suite) Test_TestNameChecker_checkTests(c *check.C) {
+ ck := s.Init(c)
+
+ ck.tests = append(ck.tests,
+ s.newTest("wrong_test.go", "", "Test_Func", 0, "Func", "",
+ s.newTestee("source.go", "", "Func", 1)))
+
+ ck.checkTests()
s.CheckErrors(
- "Test \"Suite.Test_Method__\" must not have a nonempty description.")
+ "Test \"Test_Func\" for \"Func\" " +
+ "must be in source_test.go instead of wrong_test.go.")
}
func (s *Suite) Test_TestNameChecker_checkTestFile__global(c *check.C) {
@@ -165,10 +350,10 @@ func (s *Suite) Test_TestNameChecker_che
nil...)
}
-func (s *Suite) Test_TestNameChecker_checkTestName__camel_case(c *check.C) {
+func (s *Suite) Test_TestNameChecker_checkTestDescr__camel_case(c *check.C) {
ck := s.Init(c)
- ck.checkTestName(&test{
+ ck.checkTestDescr(&test{
code{"demo_test.go", "Suite", "Test_Missing__CamelCase", 0},
"Missing",
"CamelCase",
@@ -179,6 +364,45 @@ func (s *Suite) Test_TestNameChecker_che
"must not use CamelCase in the first word.")
}
+func (s *Suite) Test_TestNameChecker_checkTestees(c *check.C) {
+ ck := s.Init(c)
+
+ ck.testees = []*testee{s.newTestee("s.go", "", "Func", 0)}
+ ck.tests = nil // force an error
+
+ ck.checkTestees()
+
+ s.CheckErrors(
+ "Missing unit test \"Test_Func\" for \"Func\".")
+}
+
+func (s *Suite) Test_TestNameChecker_checkTesteeTest(c *check.C) {
+ ck := s.Init(c)
+
+ ck.checkTesteeTest(
+ &testee{code{"demo.go", "Type", "", 0}},
+ nil)
+ ck.checkTesteeTest(
+ &testee{code{"demo.go", "", "Func", 0}},
+ nil)
+ ck.checkTesteeTest(
+ &testee{code{"demo.go", "Type", "Method", 0}},
+ nil)
+
+ s.CheckErrors(
+ "Missing unit test \"Test_Func\" for \"Func\".",
+ "Missing unit test \"Test_Type_Method\" for \"Type.Method\".")
+}
+
+func (s *Suite) Test_TestNameChecker_errorsMask(c *check.C) {
+ ck := s.Init(c)
+
+ c.Check(ck.errorsMask(0, EAll), check.Equals, ^uint64(0))
+ c.Check(ck.errorsMask(12345, ENone), check.Equals, uint64(0))
+ c.Check(ck.errorsMask(12345, ENone, EMissingTest), check.Equals, uint64(8))
+ c.Check(ck.errorsMask(2, EMissingTest), check.Equals, uint64(10))
+}
+
func (s *Suite) Test_TestNameChecker_checkOrder(c *check.C) {
ck := s.Init(c)
@@ -186,6 +410,8 @@ func (s *Suite) Test_TestNameChecker_che
ck.addTestee(code{"f.go", "T", "M1", 11})
ck.addTestee(code{"f.go", "T", "M2", 12})
ck.addTestee(code{"f.go", "T", "M3", 13})
+ ck.addTest(code{"a_test.go", "S", "Test_A", 98}) // different file, is skipped
+ ck.addTest(code{"f_test.go", "S", "Test_Missing", 99}) // missing testee, is skipped
ck.addTest(code{"f_test.go", "S", "Test_T_M1", 100}) // maxTestee = 11
ck.addTest(code{"f_test.go", "S", "Test_T_M2", 101}) // maxTestee = 12
ck.addTest(code{"f_test.go", "S", "Test_T", 102}) // testee 10 < maxTestee 12: insert before first [.testee > testee 10] == T_M1
@@ -198,10 +424,23 @@ func (s *Suite) Test_TestNameChecker_che
ck.checkOrder()
s.CheckErrors(
- "Test \"S.Test_T\" should be ordered before \"S.Test_T_M1\".",
- "Test \"S.Test_T__1\" should be ordered before \"S.Test_T_M1\".",
- "Test \"S.Test_T__2\" should be ordered before \"S.Test_T_M1\".",
- "Test \"S.Test_T_M2__1\" should be ordered before \"S.Test_T_M3\".")
+ "Test \"S.Test_T\" must be ordered before \"S.Test_T_M1\".",
+ "Test \"S.Test_T__1\" must be ordered before \"S.Test_T_M1\".",
+ "Test \"S.Test_T__2\" must be ordered before \"S.Test_T_M1\".",
+ "Test \"S.Test_T_M2__1\" must be ordered before \"S.Test_T_M3\".")
+}
+
+func (s *Suite) Test_TestNameChecker_addError(c *check.C) {
+ ck := s.Init(c)
+
+ ck.Configure("ignored*", "*", "*", -EName)
+ ok1 := ck.addError(EName, code{"ignored.go", "", "Func", 0}, "E1")
+ ok2 := ck.addError(EName, code{"reported.go", "", "Func", 0}, "E2")
+
+ c.Check(ok1, check.Equals, false)
+ c.Check(ok2, check.Equals, true)
+ s.CheckErrors(
+ "E2")
}
func (s *Suite) Test_TestNameChecker_print__empty(c *check.C) {
@@ -214,12 +453,12 @@ func (s *Suite) Test_TestNameChecker_pri
c.Check(out.String(), check.Equals, "")
}
-func (s *Suite) Test_TestNameChecker_print__errors(c *check.C) {
+func (s *Suite) Test_TestNameChecker_print__1_error(c *check.C) {
var out bytes.Buffer
ck := s.Init(c)
ck.out = &out
+ ck.addError(EName, code{}, "1")
- ck.addError(EName, "1")
ck.print()
c.Check(out.String(), check.Equals, "1\n")
@@ -227,6 +466,20 @@ func (s *Suite) Test_TestNameChecker_pri
s.CheckSummary("1 error.")
}
+func (s *Suite) Test_TestNameChecker_print__2_errors(c *check.C) {
+ var out bytes.Buffer
+ ck := s.Init(c)
+ ck.out = &out
+ ck.addError(EName, code{}, "1")
+ ck.addError(EName, code{}, "2")
+
+ ck.print()
+
+ c.Check(out.String(), check.Equals, "1\n2\n")
+ s.CheckErrors("1", "2")
+ s.CheckSummary("2 errors.")
+}
+
func (s *Suite) Test_code_fullName(c *check.C) {
_ = s.Init(c)
@@ -240,13 +493,77 @@ func (s *Suite) Test_code_fullName(c *ch
test("Type", "Method", "Type.Method")
}
-func (s *Suite) Test_plural(c *check.C) {
+func (s *Suite) Test_code_isFunc(c *check.C) {
_ = s.Init(c)
- c.Check(plural(0, "singular", "plural"), check.Equals, "")
- c.Check(plural(1, "singular", "plural"), check.Equals, "1 singular")
- c.Check(plural(2, "singular", "plural"), check.Equals, "2 plural")
- c.Check(plural(1000, "singular", "plural"), check.Equals, "1000 plural")
+ test := func(typeName, funcName string, isFunc bool) {
+ code := code{"filename", typeName, funcName, 0}
+ c.Check(code.isFunc(), check.Equals, isFunc)
+ }
+
+ test("Type", "", false)
+ test("", "Func", true)
+ test("Type", "Method", false)
+}
+
+func (s *Suite) Test_code_isType(c *check.C) {
+ _ = s.Init(c)
+
+ test := func(typeName, funcName string, isType bool) {
+ code := code{"filename", typeName, funcName, 0}
+ c.Check(code.isType(), check.Equals, isType)
+ }
+
+ test("Type", "", true)
+ test("", "Func", false)
+ test("Type", "Method", false)
+}
+
+func (s *Suite) Test_code_isMethod(c *check.C) {
+ _ = s.Init(c)
+
+ test := func(typeName, funcName string, isMethod bool) {
+ code := code{"filename", typeName, funcName, 0}
+ c.Check(code.isMethod(), check.Equals, isMethod)
+ }
+
+ test("Type", "", false)
+ test("", "Func", false)
+ test("Type", "Method", true)
+}
+
+func (s *Suite) Test_code_isTest(c *check.C) {
+ _ = s.Init(c)
+
+ test := func(filename, typeName, funcName string, isTest bool) {
+ code := code{filename, typeName, funcName, 0}
+ c.Check(code.isTest(), check.Equals, isTest)
+ }
+
+ test("f.go", "Type", "", false)
+ test("f.go", "", "Func", false)
+ test("f.go", "Type", "Method", false)
+ test("f.go", "Type", "Test", false)
+ test("f.go", "Type", "Test_Type_Method", false)
+ test("f.go", "", "Test_Type_Method", false)
+ test("f_test.go", "Type", "Test", true)
+ test("f_test.go", "Type", "Test_Type_Method", true)
+ test("f_test.go", "", "Test_Type_Method", true)
+}
+
+func (s *Suite) Test_code_isTestScope(c *check.C) {
+ _ = s.Init(c)
+
+ test := func(filename string, isTestScope bool) {
+ code := code{filename, "", "", 0}
+ c.Check(code.isTestScope(), check.Equals, isTestScope)
+ }
+
+ test("f.go", false)
+ test("test.go", false)
+ test("_test.go", true)
+ test("file_test.go", true)
+ test("file_linux_test.go", true)
}
func (s *Suite) Test_isCamelCase(c *check.C) {
@@ -273,6 +590,37 @@ func (s *Suite) Test_join(c *check.C) {
c.Check(join("one", " and ", "two"), check.Equals, "one and two")
}
+func (s *Suite) Test_matches(c *check.C) {
+ _ = s.Init(c)
+
+ c.Check(matches("*", "*"), check.Equals, true)
+ c.Check(matches("anything", "*"), check.Equals, true)
+ c.Check(matches("*", "anything"), check.Equals, false)
+ c.Check(func() { matches("any", "[") }, check.Panics, path.ErrBadPattern)
+}
+
+func (s *Suite) Test_sortedKeys(c *check.C) {
+ _ = s.Init(c)
+
+ m := make(map[string]uint8)
+ m["first"] = 1
+ m["second"] = 2
+ m["third"] = 3
+ m["fourth"] = 4
+
+ c.Check(
+ sortedKeys(m),
+ check.DeepEquals,
+ []string{"first", "fourth", "second", "third"})
+}
+
+func (s *Suite) Test_Value_Method(c *check.C) {
+ _ = s.Init(c)
+
+ // Just for code coverage of checkTestFile, to have a piece of code
+ // that lives in the same file as its test.
+}
+
type Value struct{}
// Method has no star on the receiver,
Index: pkgsrc/pkgtools/pkglint/files/licenses/licenses_test.go
diff -u pkgsrc/pkgtools/pkglint/files/licenses/licenses_test.go:1.6 pkgsrc/pkgtools/pkglint/files/licenses/licenses_test.go:1.7
--- pkgsrc/pkgtools/pkglint/files/licenses/licenses_test.go:1.6 Sun Nov 17 01:26:26 2019
+++ pkgsrc/pkgtools/pkglint/files/licenses/licenses_test.go Tue Nov 19 06:51:38 2019
@@ -133,6 +133,6 @@ func Test(t *testing.T) {
func (s *Suite) Test__test_names(c *check.C) {
ck := intqa.NewTestNameChecker(c.Errorf)
- ck.Enable(intqa.EAll, -intqa.EMissingTest)
+ ck.Configure("*", "*", "*", -intqa.EMissingTest)
ck.Check()
}
Index: pkgsrc/pkgtools/pkglint/files/pkgver/vercmp_test.go
diff -u pkgsrc/pkgtools/pkglint/files/pkgver/vercmp_test.go:1.6 pkgsrc/pkgtools/pkglint/files/pkgver/vercmp_test.go:1.7
--- pkgsrc/pkgtools/pkglint/files/pkgver/vercmp_test.go:1.6 Sun Nov 17 01:26:26 2019
+++ pkgsrc/pkgtools/pkglint/files/pkgver/vercmp_test.go Tue Nov 19 06:51:38 2019
@@ -95,6 +95,6 @@ func (s *Suite) Test_newVersion(c *check
func (s *Suite) Test__test_names(c *check.C) {
ck := intqa.NewTestNameChecker(c.Errorf)
- ck.Enable(intqa.EAll, -intqa.EMissingTest)
+ ck.Configure("*", "*", "*", -intqa.EMissingTest)
ck.Check()
}
Index: pkgsrc/pkgtools/pkglint/files/textproc/lexer_test.go
diff -u pkgsrc/pkgtools/pkglint/files/textproc/lexer_test.go:1.7 pkgsrc/pkgtools/pkglint/files/textproc/lexer_test.go:1.8
--- pkgsrc/pkgtools/pkglint/files/textproc/lexer_test.go:1.7 Sun Nov 17 01:26:26 2019
+++ pkgsrc/pkgtools/pkglint/files/textproc/lexer_test.go Tue Nov 19 06:51:39 2019
@@ -415,6 +415,6 @@ func (s *Suite) Test__Alpha(c *check.C)
func (s *Suite) Test__test_names(c *check.C) {
ck := intqa.NewTestNameChecker(c.Errorf)
- ck.Enable(intqa.EAll, -intqa.EMissingTest)
+ ck.Configure("*", "*", "*", -intqa.EMissingTest)
ck.Check()
}
Index: pkgsrc/pkgtools/pkglint/files/trace/tracing_test.go
diff -u pkgsrc/pkgtools/pkglint/files/trace/tracing_test.go:1.4 pkgsrc/pkgtools/pkglint/files/trace/tracing_test.go:1.5
--- pkgsrc/pkgtools/pkglint/files/trace/tracing_test.go:1.4 Sun Nov 17 01:26:26 2019
+++ pkgsrc/pkgtools/pkglint/files/trace/tracing_test.go Tue Nov 19 06:51:39 2019
@@ -145,6 +145,6 @@ func (str) String() string {
func (s *Suite) Test__test_names(c *check.C) {
ck := intqa.NewTestNameChecker(c.Errorf)
- ck.Enable(intqa.EAll, -intqa.EMissingTest)
+ ck.Configure("*", "*", "*", -intqa.EMissingTest)
ck.Check()
}
Home |
Main Index |
Thread Index |
Old Index