github.com/snyk/vervet/v3@v3.7.0/internal/linter/sweatercomb/linter_test.go (about)

     1  package sweatercomb
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"os/exec"
     9  	"path/filepath"
    10  	"testing"
    11  
    12  	qt "github.com/frankban/quicktest"
    13  
    14  	"github.com/snyk/vervet/v3/config"
    15  )
    16  
    17  func TestLinter(t *testing.T) {
    18  	c := qt.New(t)
    19  	ctx, cancel := context.WithCancel(context.TODO())
    20  	defer cancel()
    21  
    22  	// Sanity check constructor
    23  	l, err := New(ctx, &config.SweaterCombLinter{
    24  		Image:     "some-image",
    25  		Rules:     []string{"/sweater-comb/rules/rule1", "rule2"},
    26  		ExtraArgs: []string{"--some-flag"},
    27  	})
    28  	c.Assert(err, qt.IsNil)
    29  	c.Assert(l.image, qt.Equals, "some-image")
    30  	c.Assert(l.rules, qt.DeepEquals, []string{"/sweater-comb/rules/rule1", "/sweater-comb/target/rule2"})
    31  	c.Assert(l.extraArgs, qt.DeepEquals, []string{"--some-flag"})
    32  
    33  	// Verify temp ruleset that joins all the rulesets.
    34  	rulesetFile := filepath.Join(l.rulesDir, "ruleset.yaml")
    35  	rulesetContents, err := ioutil.ReadFile(rulesetFile)
    36  	c.Assert(err, qt.IsNil)
    37  	c.Assert(string(rulesetContents), qt.Equals, `
    38  extends:
    39  - /sweater-comb/rules/rule1
    40  - /sweater-comb/target/rule2
    41  `[1:])
    42  
    43  	// Capture stdout so we can test the output substitution that replaces
    44  	// container paths with the current working directory in spectral's output.
    45  	cwd, err := os.Getwd()
    46  	c.Assert(err, qt.IsNil)
    47  	tempDir := c.TempDir()
    48  	tempFile, err := os.Create(tempDir + "/stdout")
    49  	c.Assert(err, qt.IsNil)
    50  	c.Patch(&os.Stdout, tempFile)
    51  	defer tempFile.Close()
    52  
    53  	// Verify mock runner ran what we'd expect
    54  	runner := &mockRunner{}
    55  	l.runner = runner
    56  	err = l.Run(ctx, "my-api", "my-api/**/*.yaml")
    57  	c.Assert(err, qt.IsNil)
    58  	c.Assert(runner.runs, qt.DeepEquals, [][]string{{
    59  		"docker", "run", "--rm",
    60  		"-v", l.rulesDir + ":/vervet",
    61  		"-v", cwd + ":/sweater-comb/target",
    62  		"some-image",
    63  		"lint",
    64  		"-r", "/vervet/ruleset.yaml",
    65  		"--some-flag",
    66  		"my-api/**/*.yaml",
    67  	}})
    68  
    69  	// Verify captured output was substituted. Mainly a convenience that makes
    70  	// output host-relevant and cmd-clickable if possible.
    71  	c.Assert(tempFile.Sync(), qt.IsNil)
    72  	capturedOutput, err := ioutil.ReadFile(tempFile.Name())
    73  	c.Assert(err, qt.IsNil)
    74  	c.Assert(string(capturedOutput), qt.Equals, cwd+" is the path to things in your project\n")
    75  
    76  	// Command failed.
    77  	runner = &mockRunner{err: fmt.Errorf("nope")}
    78  	l.runner = runner
    79  	err = l.Run(ctx, "my-api", "my-api/**/*.yaml")
    80  	c.Assert(err, qt.ErrorMatches, "nope")
    81  }
    82  
    83  type mockRunner struct {
    84  	runs [][]string
    85  	err  error
    86  }
    87  
    88  func (r *mockRunner) run(cmd *exec.Cmd) error {
    89  	fmt.Fprintln(cmd.Stdout, "/sweater-comb/target is the path to things in your project")
    90  	r.runs = append(r.runs, cmd.Args)
    91  	return r.err
    92  }