Coordinate separate full vet pass
This commit is contained in:
@@ -11,6 +11,8 @@ type Check string
|
||||
const (
|
||||
// GoTest identifies the base Go test suite.
|
||||
GoTest Check = "go-test"
|
||||
// GoVet identifies the separate full vet pass.
|
||||
GoVet Check = "go-vet"
|
||||
)
|
||||
|
||||
// Finding describes a validation observation at an optional source location.
|
||||
|
||||
@@ -11,31 +11,41 @@ import (
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestRunUsesOneSuiteWithSelectedRaceSetting(t *testing.T) {
|
||||
func TestRunUsesOneSuiteWithGoValidationSettings(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
race bool
|
||||
name string
|
||||
race bool
|
||||
fullVet bool
|
||||
}{
|
||||
{name: "default"},
|
||||
{name: "race", race: true},
|
||||
{name: "full vet", fullVet: true},
|
||||
{name: "race and full vet", race: true, fullVet: true},
|
||||
} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
logPath := installGoShim(t, false)
|
||||
logPath := installGoShim(t, "", false)
|
||||
err := Run(context.Background(), Request{
|
||||
RepositoryDir: t.TempDir(),
|
||||
Settings: Settings{Race: test.race},
|
||||
Settings: Settings{Race: test.race, FullVet: test.fullVet},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Run() error = %v", err)
|
||||
}
|
||||
|
||||
commands := readGoShimLog(t, logPath)
|
||||
var tests []string
|
||||
for _, command := range commands {
|
||||
var tests, vets []string
|
||||
var testPosition, vetPosition int
|
||||
for i, command := range commands {
|
||||
if strings.HasPrefix(command, "test ") {
|
||||
tests = append(tests, command)
|
||||
testPosition = i
|
||||
}
|
||||
if strings.HasPrefix(command, "vet ") {
|
||||
vets = append(vets, command)
|
||||
vetPosition = i
|
||||
}
|
||||
}
|
||||
if len(tests) != 1 {
|
||||
@@ -50,12 +60,33 @@ func TestRunUsesOneSuiteWithSelectedRaceSetting(t *testing.T) {
|
||||
if got := strings.Contains(command, " -race "); got != test.race {
|
||||
t.Errorf("Go test command %q has race=%t, want %t", tests[0], got, test.race)
|
||||
}
|
||||
if got := strings.Contains(command, " -vet=off "); got != test.fullVet {
|
||||
t.Errorf("Go test command %q disables test-time vet=%t, want %t", tests[0], got, test.fullVet)
|
||||
}
|
||||
wantVets := 0
|
||||
if test.fullVet {
|
||||
wantVets = 1
|
||||
}
|
||||
if len(vets) != wantVets {
|
||||
t.Fatalf("Go vet invocations = %q, want %d", vets, wantVets)
|
||||
}
|
||||
if test.fullVet {
|
||||
vetCommand := " " + vets[0] + " "
|
||||
for _, argument := range []string{"vet", "-mod=readonly", "./..."} {
|
||||
if !strings.Contains(vetCommand, " "+argument+" ") {
|
||||
t.Errorf("Go vet command %q does not contain %q", vets[0], argument)
|
||||
}
|
||||
}
|
||||
if vetPosition <= testPosition {
|
||||
t.Errorf("Go vet command %q did not follow the test suite %q", vets[0], tests[0])
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunReportsRacePrerequisiteFailureWithoutFallback(t *testing.T) {
|
||||
logPath := installGoShim(t, true)
|
||||
logPath := installGoShim(t, "race", false)
|
||||
err := Run(context.Background(), Request{
|
||||
RepositoryDir: t.TempDir(),
|
||||
Settings: Settings{Race: true},
|
||||
@@ -80,6 +111,69 @@ func TestRunReportsRacePrerequisiteFailureWithoutFallback(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunStopsAfterGoTestFailure(t *testing.T) {
|
||||
logPath := installGoShim(t, "test", false)
|
||||
err := Run(context.Background(), Request{
|
||||
RepositoryDir: t.TempDir(),
|
||||
Settings: Settings{FullVet: true},
|
||||
})
|
||||
var failure *Failure
|
||||
if !errors.As(err, &failure) || failure.Check != GoTest {
|
||||
t.Fatalf("Run() error = %v, want a go-test validation failure", err)
|
||||
}
|
||||
for _, command := range readGoShimLog(t, logPath) {
|
||||
if strings.HasPrefix(command, "vet ") {
|
||||
t.Fatalf("Go vet ran after Go test failed: %q", command)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunAttributesFullVetFailure(t *testing.T) {
|
||||
logPath := installGoShim(t, "vet", false)
|
||||
err := Run(context.Background(), Request{
|
||||
RepositoryDir: t.TempDir(),
|
||||
Settings: Settings{FullVet: true},
|
||||
})
|
||||
var failure *Failure
|
||||
if !errors.As(err, &failure) || failure.Check != GoVet {
|
||||
t.Fatalf("Run() error = %v, want a go-vet validation failure", err)
|
||||
}
|
||||
var exitError *exec.ExitError
|
||||
if !errors.As(err, &exitError) {
|
||||
t.Fatalf("Run() error = %v, want the command failure preserved", err)
|
||||
}
|
||||
commands := readGoShimLog(t, logPath)
|
||||
var validationCommands []string
|
||||
for _, command := range commands {
|
||||
if strings.HasPrefix(command, "test ") || strings.HasPrefix(command, "vet ") {
|
||||
validationCommands = append(validationCommands, command)
|
||||
}
|
||||
}
|
||||
if len(validationCommands) != 2 || !strings.HasPrefix(validationCommands[0], "test ") || !strings.HasPrefix(validationCommands[1], "vet ") {
|
||||
t.Fatalf("validation command sequence = %q, want test followed by vet", validationCommands)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunPreservesFullVetCancellation(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("the controlled Go command fixture uses a POSIX shell")
|
||||
}
|
||||
installGoShim(t, "", true)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
defer cancel()
|
||||
err := Run(ctx, Request{
|
||||
RepositoryDir: t.TempDir(),
|
||||
Settings: Settings{FullVet: true},
|
||||
})
|
||||
var failure *Failure
|
||||
if !errors.As(err, &failure) || failure.Check != GoVet {
|
||||
t.Fatalf("Run() error = %v, want a go-vet validation failure", err)
|
||||
}
|
||||
if !errors.Is(err, context.DeadlineExceeded) {
|
||||
t.Fatalf("Run() error = %v, want deadline cause preserved", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunExecutesRaceEnabledSuiteOnHost(t *testing.T) {
|
||||
if !raceSupported(runtime.GOOS, runtime.GOARCH) {
|
||||
t.Skipf("Go race detector is not supported on %s/%s", runtime.GOOS, runtime.GOARCH)
|
||||
@@ -112,7 +206,7 @@ func TestRaceFixture(t *testing.T) {}
|
||||
}
|
||||
}
|
||||
|
||||
func installGoShim(t *testing.T, failRace bool) string {
|
||||
func installGoShim(t *testing.T, failure string, delayVet bool) string {
|
||||
t.Helper()
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("the controlled Go command fixture uses a POSIX shell")
|
||||
@@ -131,17 +225,33 @@ func installGoShim(t *testing.T, failRace bool) string {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
failBlock := ""
|
||||
if failRace {
|
||||
failBlock = `
|
||||
vetDelay := ""
|
||||
if delayVet {
|
||||
vetDelay = `
|
||||
if [ "${1-}" = "vet" ]; then
|
||||
exec sleep 5
|
||||
fi
|
||||
`
|
||||
}
|
||||
failBlock := fmt.Sprintf(`
|
||||
if [ "${1-}" = "test" ]; then
|
||||
for argument in "$@"; do
|
||||
if [ "$argument" = "-race" ]; then
|
||||
if [ "%s" = "race" ] && [ "$argument" = "-race" ]; then
|
||||
echo "race detector prerequisite unavailable" >&2
|
||||
exit 2
|
||||
fi
|
||||
done
|
||||
`
|
||||
}
|
||||
if [ "%s" = "test" ]; then
|
||||
echo "Go test failed" >&2
|
||||
exit 2
|
||||
fi
|
||||
fi
|
||||
if [ "${1-}" = "vet" ] && [ "%s" = "vet" ]; then
|
||||
echo "Go vet failed" >&2
|
||||
exit 2
|
||||
fi
|
||||
%s
|
||||
`, failure, failure, failure, vetDelay)
|
||||
script := fmt.Sprintf(`#!/bin/sh
|
||||
set -eu
|
||||
printf '%%s\n' "$*" >> "$RELEASEKIT_GO_LOG"
|
||||
|
||||
@@ -10,7 +10,8 @@ import (
|
||||
|
||||
// Settings selects shared validation behavior.
|
||||
type Settings struct {
|
||||
Race bool
|
||||
Race bool
|
||||
FullVet bool
|
||||
}
|
||||
|
||||
// Request identifies the captured source and output used by shared validation.
|
||||
@@ -37,10 +38,19 @@ func Run(ctx context.Context, request Request) error {
|
||||
if request.Settings.Race {
|
||||
args = append(args, "-race")
|
||||
}
|
||||
if request.Settings.FullVet {
|
||||
args = append(args, "-vet=off")
|
||||
}
|
||||
args = append(args, "./...")
|
||||
_, err = tool.Run(ctx, request.RepositoryDir, gotool.Native, gotool.Target{}, request.Output, args...)
|
||||
if err != nil {
|
||||
return &Failure{Check: GoTest, Cause: err}
|
||||
}
|
||||
if request.Settings.FullVet {
|
||||
_, err = tool.Run(ctx, request.RepositoryDir, gotool.Native, gotool.Target{}, request.Output, "vet", "-mod=readonly", "./...")
|
||||
if err != nil {
|
||||
return &Failure{Check: GoVet, Cause: err}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user