github.com/pankona/gometalinter@v2.0.11+incompatible/regressiontests/support.go (about)

     1  package regressiontests
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"os"
     9  	"os/exec"
    10  	"path/filepath"
    11  	"strings"
    12  	"testing"
    13  
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/require"
    16  	"gotest.tools/fs"
    17  )
    18  
    19  type Issue struct {
    20  	Linter   string `json:"linter"`
    21  	Severity string `json:"severity"`
    22  	Path     string `json:"path"`
    23  	Line     int    `json:"line"`
    24  	Col      int    `json:"col"`
    25  	Message  string `json:"message"`
    26  }
    27  
    28  func (i *Issue) String() string {
    29  	col := ""
    30  	if i.Col != 0 {
    31  		col = fmt.Sprintf("%d", i.Col)
    32  	}
    33  	return fmt.Sprintf("%s:%d:%s:%s: %s (%s)", strings.TrimSpace(i.Path), i.Line, col, i.Severity, strings.TrimSpace(i.Message), i.Linter)
    34  }
    35  
    36  type Issues []Issue
    37  
    38  // ExpectIssues runs gometalinter and expects it to generate exactly the
    39  // issues provided.
    40  func ExpectIssues(t *testing.T, linter string, source string, expected Issues, extraFlags ...string) {
    41  	// Write source to temporary directory.
    42  	dir, err := ioutil.TempDir(".", "gometalinter-")
    43  	require.NoError(t, err)
    44  	defer os.RemoveAll(dir)
    45  
    46  	testFile := filepath.Join(dir, "test.go")
    47  	err = ioutil.WriteFile(testFile, []byte(source), 0644)
    48  	require.NoError(t, err)
    49  
    50  	actual := RunLinter(t, linter, dir, extraFlags...)
    51  	assert.Equal(t, expected, actual)
    52  }
    53  
    54  // RunLinter runs the gometalinter as a binary against the files at path and
    55  // returns the issues it encountered
    56  func RunLinter(t *testing.T, linter string, path string, extraFlags ...string) Issues {
    57  	binary, cleanup := buildBinary(t)
    58  	defer cleanup()
    59  
    60  	args := []string{
    61  		"-d", "--no-config", "--disable-all", "--enable", linter, "--json",
    62  		"--sort=path", "--sort=line", "--sort=column", "--sort=message",
    63  		"./...",
    64  	}
    65  	args = append(args, extraFlags...)
    66  	cmd := exec.Command(binary, args...)
    67  	cmd.Dir = path
    68  
    69  	errBuffer := new(bytes.Buffer)
    70  	cmd.Stderr = errBuffer
    71  
    72  	output, _ := cmd.Output()
    73  
    74  	var actual Issues
    75  	err := json.Unmarshal(output, &actual)
    76  	if !assert.NoError(t, err) {
    77  		fmt.Printf("Stderr: %s\n", errBuffer)
    78  		fmt.Printf("Output: %s\n", output)
    79  		return nil
    80  	}
    81  	return filterIssues(actual, linter, path)
    82  }
    83  
    84  func buildBinary(t *testing.T) (string, func()) {
    85  	tmpdir := fs.NewDir(t, "regression-test-binary")
    86  	path := tmpdir.Join("gometalinter")
    87  	cmd := exec.Command("go", "build", "-o", path, "..")
    88  	require.NoError(t, cmd.Run())
    89  	return path, tmpdir.Remove
    90  }
    91  
    92  // filterIssues to just the issues relevant for the current linter and normalize
    93  // the error message by removing the directory part of the path from both Path
    94  // and Message
    95  func filterIssues(issues Issues, linterName string, dir string) Issues {
    96  	filtered := Issues{}
    97  	for _, issue := range issues {
    98  		if issue.Linter == linterName || linterName == "" {
    99  			issue.Path = strings.Replace(issue.Path, dir+string(os.PathSeparator), "", -1)
   100  			issue.Message = strings.Replace(issue.Message, dir+string(os.PathSeparator), "", -1)
   101  			issue.Message = strings.Replace(issue.Message, dir, "", -1)
   102  			filtered = append(filtered, issue)
   103  		}
   104  	}
   105  	return filtered
   106  }