Skip to content

Commit

Permalink
cmd/go: fail fast across packages
Browse files Browse the repository at this point in the history
Fixes #33038

Change-Id: I0b70c450be1c1cc59ddc1f3fddad227deccc7e14
GitHub-Last-Rev: 302ebd6
GitHub-Pull-Request: #62714
Cq-Include-Trybots: luci.golang.try:gotip-linux-amd64-longtest-race,gotip-windows-amd64-race,gotip-windows-amd64-longtest
Reviewed-on: https://go-review.googlesource.com/c/go/+/529198
LUCI-TryBot-Result: Go LUCI <[email protected]>
Reviewed-by: Dmitri Shuralyov <[email protected]>
Auto-Submit: Bryan Mills <[email protected]>
Reviewed-by: Bryan Mills <[email protected]>
  • Loading branch information
AlexanderYastrebov authored and gopherbot committed Feb 21, 2024
1 parent c07b9b0 commit 806aeb1
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 4 deletions.
18 changes: 15 additions & 3 deletions src/cmd/go/internal/test/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"strconv"
"strings"
"sync"
"sync/atomic"
"time"

"cmd/go/internal/base"
Expand Down Expand Up @@ -540,6 +541,7 @@ var (
testC bool // -c flag
testCoverPkgs []*load.Package // -coverpkg flag
testCoverProfile string // -coverprofile flag
testFailFast bool // -failfast flag
testFuzz string // -fuzz flag
testJSON bool // -json flag
testList string // -list flag
Expand Down Expand Up @@ -589,9 +591,10 @@ var (

testHelp bool // -help option passed to test via -args

testKillTimeout = 100 * 365 * 24 * time.Hour // backup alarm; defaults to about a century if no timeout is set
testWaitDelay time.Duration // how long to wait for output to close after a test binary exits; zero means unlimited
testCacheExpire time.Time // ignore cached test results before this time
testKillTimeout = 100 * 365 * 24 * time.Hour // backup alarm; defaults to about a century if no timeout is set
testWaitDelay time.Duration // how long to wait for output to close after a test binary exits; zero means unlimited
testCacheExpire time.Time // ignore cached test results before this time
testShouldFailFast atomic.Bool // signals pending tests to fail fast

testBlockProfile, testCPUProfile, testMemProfile, testMutexProfile, testTrace string // profiling flag that limits test to one package

Expand Down Expand Up @@ -1355,6 +1358,11 @@ func (r *runTestActor) Act(b *work.Builder, ctx context.Context, a *work.Action)
// Wait for previous test to get started and print its first json line.
select {
case <-r.prev:
// If should fail fast then release next test and exit.
if testShouldFailFast.Load() {
close(r.next)
return nil
}
case <-base.Interrupted:
// We can't wait for the previous test action to complete: we don't start
// new actions after an interrupt, so if that action wasn't already running
Expand Down Expand Up @@ -1631,6 +1639,10 @@ func (r *runTestActor) Act(b *work.Builder, ctx context.Context, a *work.Action)
fmt.Fprintf(cmd.Stdout, "ok \t%s\t%s%s%s\n", a.Package.ImportPath, t, coveragePercentage(out), norun)
r.c.saveOutput(a)
} else {
if testFailFast {
testShouldFailFast.Store(true)
}

base.SetExitStatus(1)
if cancelSignaled {
fmt.Fprintf(cmd.Stdout, "*** Test killed with %v: ran too long (%v).\n", base.SignalTrace, testKillTimeout)
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/go/internal/test/testflag.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func init() {
cf.Int("count", 0, "")
cf.String("cpu", "", "")
cf.StringVar(&testCPUProfile, "cpuprofile", "", "")
cf.Bool("failfast", false, "")
cf.BoolVar(&testFailFast, "failfast", false, "")
cf.StringVar(&testFuzz, "fuzz", "", "")
cf.Bool("fullpath", false, "")
cf.StringVar(&testList, "list", "", "")
Expand Down
33 changes: 33 additions & 0 deletions src/cmd/go/testdata/script/test_fail_fast.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,15 @@ stdout -count=1 'FAIL - '
! go test ./failfast_test.go -run='TestFatal[CD]' -failfast=false
stdout -count=2 'FAIL - '

# cross package failfast
! go test -p 1 -failfast ./a ./b ./c
stdout -count=1 'FAIL - '
stdout -count=1 'FAIL - TestFailingPkgA'

-- go.mod --
module m

go 1.21.0
-- failfast_test.go --
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
Expand Down Expand Up @@ -111,3 +120,27 @@ func TestFatalC(t *testing.T) {
func TestFatalD(t *testing.T) {
t.Fatalf("FAIL - %s", t.Name())
}
-- a/a_test.go --
package a

import "testing"

func TestFailingPkgA(t *testing.T) {
t.Errorf("FAIL - %s", t.Name())
}
-- b/b_test.go --
package b

import "testing"

func TestFailingPkgB(t *testing.T) {
t.Errorf("FAIL - %s", t.Name())
}
-- c/c_test.go --
package c

import "testing"

func TestFailingPkgC(t *testing.T) {
t.Errorf("FAIL - %s", t.Name())
}

0 comments on commit 806aeb1

Please sign in to comment.