pkgsrc/pkgtools/pkglint/files/check_test.go
rillig 31a3a6b80c pkglint: Update to 5.5.1
Changes since 5.5:

* Allow filtering log messages by keyword (--only)
* In --autofix and --show-autofix mode, show only fixable diagnostics
* When called with --source, show the source below the diagnostics
* Don't warn about USE_LANGUAGES in ../../mk/compiler.mk
* Fix autofix for .gz in PLIST
2018-01-13 23:56:14 +00:00

254 lines
6.4 KiB
Go

package main
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"strings"
"testing"
"gopkg.in/check.v1"
"netbsd.org/pkglint/textproc"
"netbsd.org/pkglint/trace"
)
var equals = check.Equals
var deepEquals = check.DeepEquals
type Suite struct {
stdout bytes.Buffer
stderr bytes.Buffer
tmpdir string
checkC *check.C
}
// Init initializes the suite with the check.C instance for the actual
// test run. See https://github.com/go-check/check/issues/22
func (s *Suite) Init(c *check.C) {
if s.checkC != nil {
panic("Suite.Init must only be called once.")
}
s.checkC = c
}
func (s *Suite) c() *check.C {
if s.checkC == nil {
panic("Suite.Init must be called before accessing check.C.")
}
return s.checkC
}
func (s *Suite) Stdout() string {
defer s.stdout.Reset()
return s.stdout.String()
}
func (s *Suite) Stderr() string {
defer s.stderr.Reset()
return s.stderr.String()
}
// Returns and consumes the output from both stdout and stderr.
// The temporary directory is replaced with a tilde (~).
func (s *Suite) Output() string {
output := s.Stdout() + s.Stderr()
if s.tmpdir != "" {
output = strings.Replace(output, s.tmpdir, "~", -1)
}
return output
}
func (s *Suite) CheckOutputEmpty() {
s.c().Check(s.Output(), equals, "")
}
func (s *Suite) CheckOutputLines(expectedLines ...string) {
expectedOutput := ""
for _, expectedLine := range expectedLines {
expectedOutput += expectedLine + "\n"
}
s.c().Check(s.Output(), equals, expectedOutput)
}
func (s *Suite) BeginDebugToStdout() {
G.logOut = NewSeparatorWriter(os.Stdout)
trace.Out = os.Stdout
trace.Tracing = true
}
func (s *Suite) EndDebugToStdout() {
G.logOut = NewSeparatorWriter(&s.stdout)
trace.Out = &s.stdout
trace.Tracing = false
}
// UseCommandLine simulates a command line for the remainder of the test.
// See Pkglint.ParseCommandLine
func (s *Suite) UseCommandLine(args ...string) {
exitcode := new(Pkglint).ParseCommandLine(append([]string{"pkglint"}, args...))
if exitcode != nil && *exitcode != 0 {
s.CheckOutputEmpty()
s.c().Fatalf("Cannot parse command line: %#v", args)
}
G.opts.LogVerbose = true // See SetUpTest
}
func (s *Suite) RegisterMasterSite(varname string, urls ...string) {
name2url := &G.globalData.MasterSiteVarToURL
url2name := &G.globalData.MasterSiteURLToVar
if *name2url == nil {
*name2url = make(map[string]string)
*url2name = make(map[string]string)
}
(*name2url)[varname] = urls[0]
for _, url := range urls {
(*url2name)[url] = varname
}
}
func (s *Suite) RegisterTool(tool *Tool) {
reg := G.globalData.Tools
if len(reg.byName) == 0 && len(reg.byVarname) == 0 {
reg = NewToolRegistry()
G.globalData.Tools = reg
}
if tool.Name != "" {
reg.byName[tool.Name] = tool
}
if tool.Varname != "" {
reg.byVarname[tool.Varname] = tool
}
}
func (s *Suite) CreateTmpFile(relFname, content string) (absFname string) {
c := s.c()
absFname = s.TmpDir() + "/" + relFname
err := os.MkdirAll(path.Dir(absFname), 0777)
c.Assert(err, check.IsNil)
err = ioutil.WriteFile(absFname, []byte(content), 0666)
c.Check(err, check.IsNil)
return
}
func (s *Suite) CreateTmpFileLines(relFname string, rawTexts ...string) (absFname string) {
text := ""
for _, rawText := range rawTexts {
text += rawText + "\n"
}
return s.CreateTmpFile(relFname, text)
}
func (s *Suite) LoadTmpFile(relFname string) (absFname string) {
c := s.c()
bytes, err := ioutil.ReadFile(s.TmpDir() + "/" + relFname)
c.Assert(err, check.IsNil)
return string(bytes)
}
func (s *Suite) TmpDir() string {
if s.tmpdir == "" {
s.tmpdir = filepath.ToSlash(s.c().MkDir())
}
return s.tmpdir
}
func (s *Suite) ExpectFatalError(action func()) {
if r := recover(); r != nil {
if _, ok := r.(pkglintFatal); ok {
action()
return
}
panic(r)
}
}
func (s *Suite) SetUpTest(c *check.C) {
G = GlobalVars{Testing: true}
textproc.Testing = true
G.logOut, G.logErr, trace.Out = NewSeparatorWriter(&s.stdout), NewSeparatorWriter(&s.stderr), &s.stdout
s.checkC = c
s.UseCommandLine( /* no arguments */ )
s.checkC = nil
G.opts.LogVerbose = true // To detect duplicate work being done
}
func (s *Suite) TearDownTest(c *check.C) {
G = GlobalVars{}
textproc.Testing = false
if out := s.Output(); out != "" {
fmt.Fprintf(os.Stderr, "Unchecked output in %q; check with: c.Check(s.Output(), equals, %q)", c.TestName(), out)
}
s.tmpdir = ""
}
var _ = check.Suite(new(Suite))
func Test(t *testing.T) { check.TestingT(t) }
var T TestObjectCreator
type TestObjectCreator struct{}
// Arguments are either (lineno, orignl) or (lineno, orignl, textnl).
func (t TestObjectCreator) NewRawLines(args ...interface{}) []*RawLine {
rawlines := make([]*RawLine, len(args)/2)
j := 0
for i := 0; i < len(args); i += 2 {
lineno := args[i].(int)
orignl := args[i+1].(string)
textnl := orignl
if i+2 < len(args) {
if s, ok := args[i+2].(string); ok {
textnl = s
i++
}
}
rawlines[j] = &RawLine{lineno, orignl, textnl}
j++
}
return rawlines[:j]
}
func (t TestObjectCreator) NewLine(filename string, lineno int, text string) Line {
textnl := text + "\n"
rawLine := RawLine{lineno, textnl, textnl}
return NewLine(filename, lineno, text, []*RawLine{&rawLine})
}
func (t TestObjectCreator) NewMkLine(fileName string, lineno int, text string) MkLine {
return NewMkLine(t.NewLine(fileName, lineno, text))
}
func (t TestObjectCreator) NewShellLine(fileName string, lineno int, text string) *ShellLine {
return NewShellLine(t.NewMkLine(fileName, lineno, text))
}
// NewLines generates a slice of simple lines,
// i.e. each logical line has exactly one physical line.
// To work with line continuations like in Makefiles,
// use Suite.CreateTmpFileLines together with Suite.LoadExistingLines.
func (t TestObjectCreator) NewLines(fname string, texts ...string) []Line {
return t.NewLinesAt(fname, 1, texts...)
}
func (t TestObjectCreator) NewMkLines(fname string, lines ...string) *MkLines {
return NewMkLines(t.NewLines(fname, lines...))
}
// NewLinesAt generates a slice of simple lines,
// i.e. each logical line has exactly one physical line.
// To work with line continuations like in Makefiles,
// use Suite.CreateTmpFileLines together with Suite.LoadExistingLines.
func (t TestObjectCreator) NewLinesAt(fname string, firstLine int, texts ...string) []Line {
result := make([]Line, len(texts))
for i, text := range texts {
textnl := text + "\n"
result[i] = NewLine(fname, i+firstLine, text, t.NewRawLines(i+firstLine, textnl))
}
return result
}