Skip to content

Commit 49b3ab0

Browse files
committed
cmd/go: report all loading errors in tests as "setup failed"
Currently, under *most* circumstances, if there's a package loading error during "go test", that will get reported as a "FAIL p [setup failed]" or "FAIL p [build failed] message and won't prevent running unaffected test packages. However, if there's a loading error from a non-test file in a package listed directly on the "go test" command line, that gets reported as an immediate fatal error, without any "FAIL" line, and without attempting to run other tests listed on the command line. Likewise, certain early build errors (like a package containing no Go files) are currently immediately fatal rather than reporting a test failure. Fix this by eliminating the check that causes that immediate failure. This causes one minor follow-up problem: since load.TestPackagesAndErrors was never passed a top-level package with an error before, it doesn't currently propagate such an error to the packages it synthesizes (even though it will propagate errors in imported packages). Fix this by copying the error from the top-level package into the synthesized test package while we're copying everything else. For #62067. Change-Id: Icd563a3d9912256b53afd998050995e5260ebe5d Reviewed-on: https://go-review.googlesource.com/c/go/+/558637 Reviewed-by: Russ Cox <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Sam Thanawalla <[email protected]>
1 parent 7020759 commit 49b3ab0

File tree

4 files changed

+82
-4
lines changed

4 files changed

+82
-4
lines changed

src/cmd/go/internal/load/test.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,10 @@ func TestPackagesAndErrors(ctx context.Context, done func(), opts PackageOpts, p
176176
if len(p.TestGoFiles) > 0 || p.Name == "main" || cover != nil && cover.Local {
177177
ptest = new(Package)
178178
*ptest = *p
179-
ptest.Error = ptestErr
180-
ptest.Incomplete = incomplete
179+
if ptest.Error == nil {
180+
ptest.Error = ptestErr
181+
}
182+
ptest.Incomplete = ptest.Incomplete || incomplete
181183
ptest.ForTest = p.ImportPath
182184
ptest.GoFiles = nil
183185
ptest.GoFiles = append(ptest.GoFiles, p.GoFiles...)

src/cmd/go/internal/test/test.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,8 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) {
703703

704704
pkgOpts := load.PackageOpts{ModResolveTests: true}
705705
pkgs = load.PackagesAndErrors(ctx, pkgOpts, pkgArgs)
706-
load.CheckPackageErrors(pkgs)
706+
// We *don't* call load.CheckPackageErrors here because we want to report
707+
// loading errors as per-package test setup errors later.
707708
if len(pkgs) == 0 {
708709
base.Fatalf("no packages to test")
709710
}

src/cmd/go/testdata/script/test_flags.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ stdout '\Aok\s+example.com/x\s+[0-9.s]+\n\z'
1515
# Even though ./x looks like a package path, the real package should be
1616
# the implicit '.'.
1717
! go test --answer=42 ./x
18-
stderr '^no Go files in '$PWD'$'
18+
stdout '^FAIL\t. \[build failed\]'
19+
stderr '^\.: no Go files in '$PWD'$'
1920

2021
# However, *flags* that appear after unrecognized flags should still be
2122
# interpreted as flags, under the (possibly-erroneous) assumption that
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
[short] skip
2+
3+
# Test that a loading error in a test file is reported as a "setup failed" error
4+
# and doesn't prevent running other tests.
5+
! go test -o=$devnull ./t1/p ./t
6+
stderr '# m/t1/p\n.*package x is not in std'
7+
stdout 'FAIL m/t1/p \[setup failed\]'
8+
stdout 'ok m/t'
9+
10+
# Test a loading error in a test package, but not in the test file
11+
! go test -o=$devnull ./t2/p ./t
12+
stderr '# m/t2/p\n.*package x is not in std'
13+
stdout 'FAIL m/t2/p \[setup failed\]'
14+
stdout 'ok m/t'
15+
16+
# Test a loading error in a package imported by a test file
17+
! go test -o=$devnull ./t3/p ./t
18+
stderr '# m/t3/p\n.*package x is not in std'
19+
stdout 'FAIL m/t3/p \[setup failed\]'
20+
stdout 'ok m/t'
21+
22+
# Test a loading error in a package imported by a test package
23+
! go test -o=$devnull ./t4/p ./t
24+
stderr '# m/t4/p\n.*package x is not in std'
25+
stdout 'FAIL m/t4/p \[setup failed\]'
26+
stdout 'ok m/t'
27+
28+
# Test that two loading errors are both reported.
29+
! go test -o=$devnull ./t1/p ./t2/p ./t
30+
stderr '# m/t1/p\n.*package x is not in std'
31+
stdout 'FAIL m/t1/p \[setup failed\]'
32+
stderr '# m/t2/p\n.*package x is not in std'
33+
stdout 'FAIL m/t2/p \[setup failed\]'
34+
stdout 'ok m/t'
35+
36+
# Finally, this one is a build error, but produced by cmd/go directly
37+
! go test -o=$devnull . ./t
38+
stderr '^\.: no Go files in '$PWD'$'
39+
stdout 'FAIL . \[build failed\]'
40+
stdout 'ok m/t'
41+
42+
-- go.mod --
43+
module m
44+
go 1.21
45+
-- t/t_test.go --
46+
package t
47+
48+
import "testing"
49+
50+
func TestGood(t *testing.T) {}
51+
-- t1/p/p_test.go --
52+
package p
53+
54+
import "x"
55+
-- t2/p/p_test.go --
56+
package p
57+
-- t2/p/p.go --
58+
package p
59+
60+
import "x"
61+
-- t3/p/p_test.go --
62+
package p
63+
64+
import "m/bad"
65+
-- t4/p/p_test.go --
66+
package p
67+
-- t4/p/p.go --
68+
package p
69+
70+
import "m/bad"
71+
-- bad/bad.go --
72+
package bad
73+
74+
import "x"

0 commit comments

Comments
 (0)