-
Notifications
You must be signed in to change notification settings - Fork 17.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
testing: panic in Init if flag.Parse has already been called #31859
Comments
What was the behavior with Go 1.12? (Is this a regression?) |
go test
fails if flag.Parse() called in init
I see this issue as a regression, |
I think this is likely happening due to changed |
go test
fails if flag.Parse() called in initgo test
fails if flag.Parse() called in init
CC @bradfitz |
OK, so if that is an intended behavior I can fix my code by adding a |
I don't think that a breaking change was intended. This seems like something that should be fixed before Go 1.13 is released. |
We knew that fbc6a97 was going to break some people. It's arguably on the fence on whether it's inside the go1compat umbrella (it's half API, half tooling) and we guessed it would affect very few people. (generally more advanced people who could read the docs/release notes & work around) That said, I haven't looked at this particular issue yet. I'll let @cespare have a look first. |
It seems possible to fix this by putting the call to If I understand correctly, the |
Fun. I'll take a look today. |
What we (or at least I) intended with #21051 / CL 173722 was:
So @vearutop this means that you shouldn't need to use As @bcmills alluded to, the problem is that code which calls flag.Parse during initialization won't get the test flags. The initialization of the user's test package ("ptest"/"pxtest" in the go tool internal parlance) happens before the package main test runner initialization ("testmain") so there's nothing we can do in the generated testmain code to fix this. The workaround that makes sense to me, which is what I think @bcmills is suggesting, is that we can insert a bit of code into the ptest/pxtest packages before we build them:
(Putting this in a variable declaration expression means that it happens before I think this is pretty straightforward. I'll send a CL soon.
Yeah, and same for variable declarations, modulo initialization dependencies. I'll ensure that the synthesized file is passed to the compiler first. |
Change https://golang.org/cl/176098 mentions this issue: |
@cespare I'm afraid this is still broken. Given package somewhere
import (
"flag"
)
var StopOnFailure bool
func init() {
flag.BoolVar(&StopOnFailure, "stop-on-failure", false,
"Stop processing on first failed scenario.")
flag.Parse()
} And package my_test
import (
"fmt"
"testing"
"path/to/somewhere"
)
func TestSomething(t *testing.T) {
_ = somewhere.StopOnFailure
}
func BenchmarkSomething(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_ = fmt.Sprintf("%d", i)
}
}
|
@vearutop thanks for bringing it to my attention. It turns out that this particular repro code relies on undefined behavior: it assumes that the
(And if I run with However, this all kind of doesn't matter because you could fix your repro code by making To state it more generally, the "testinginit" workaround I did over in https://golang.org/cl/176098 ensures that testing.Init is called before the package under test is initialized. It does not ensure that testing.Init is called before that package's dependencies are initialized, so if they call flag.Parse during initialization they may not see the testing flags. I think that a solution is to move the testinginit workaround from the package under test into the
(This would be very simple with a @bcmills thoughts? |
Not sure to understand:
With |
Sorry, I meant to say that there are some changes on tip (that will be in Go 1.13). I updated my comment. |
And also I tried adding package somewhere
import (
"flag"
_ "testing"
)
var StopOnFailure bool
func init() {
flag.BoolVar(&StopOnFailure, "stop-on-failure", false,
"Stop processing on first failed scenario.")
flag.Parse()
} but it did not help, same failure on |
Right, I'm saying that without the By adding the So:
|
It's hard to understand why code would call |
This allows tests to be run against functions in Main without conflicting between test flags and application flags. More info: golang/go#31859
This allows tests to be run against functions in Main without conflicting between test flags and application flags. More info: golang/go#31859
When flag.Parse is in main, it is _only_ called in the command binary. When flag.Parse is in init, it is _also_ called in the test binary. The test binary, however, likes to register its own flags, which due to init ordering usually happens after the command's inits. In Go 1.13, flag registration was delayed to be later in the init process, which is how this issue came up. See also golang/go#31859 Signed-off-by: Chris Koch <[email protected]>
When flag.Parse is in main, it is _only_ called in the command binary. When flag.Parse is in init, it is _also_ called in the test binary. The test binary, however, likes to register its own flags, which due to init ordering usually happens after the command's inits. In Go 1.13, flag registration was delayed to be later in the init process, which is how this issue came up. See also golang/go#31859 Signed-off-by: Chris Koch <[email protected]>
When flag.Parse is in main, it is _only_ called in the command binary. When flag.Parse is in init, it is _also_ called in the test binary. The test binary, however, likes to register its own flags, which due to init ordering usually happens after the command's inits. In Go 1.13, flag registration was delayed to be later in the init process, which is how this issue came up. See also golang/go#31859 Signed-off-by: Chris Koch <[email protected]>
See golang/go#31859 for more information.
Go 1.13 introduces a Testing.Init function for handling test flags. https://tip.golang.org/doc/go1.13#testing This has the unfortunate consequence of panicking if flags are parsed before testing.Init is called (for instance, in init). We therefore update the code to parse flags in the Testing Main override such that tests may be run in Go 1.11-1.14. Related: golang/go#31859 Co-authored-by: Andrew Pinkham <[email protected]> PR #3 [close ch1056]
Hello,
|
@GreatSnoopy this change shipped two releases ago, over a year ago - I think if you have further suggestions or bugs, you should file a new issue. |
Sorry for that, not trying to reopen the issue, just to ask a question that is closely related to this particular issue and I thought this would be the most appropriate place. I will create a new issue. |
Adds go.mod file to project root. Fixes go_test's inoperability with go1.13+. In go1.13+, invoking `flag.Parse()` in a test file's `init()` does not work. See https://golang.org/pkg/testing/#hdr-Main and golang/go#31859
This allows tests to be run against functions in Main without conflicting between test flags and application flags. More info: golang/go#31859
This allows tests to be run against functions in Main without conflicting between test flags and application flags. More info: golang/go#31859
This allows tests to be run against functions in Main without conflicting between test flags and application flags. More info: golang/go#31859
This allows tests to be run against functions in Main without conflicting between test flags and application flags. More info: golang/go#31859
Tests failed with "flag provided but not defined: -test.testlogfile" See golang/go#31859
This hopefully fixes the issue we were seeing in CI, related to golang/go#31859.
Calling flags.Parse() within init() races with other packages which register flags in their init(), and in particular with the testing package itself. It is more reliable to call flags.Parse() from a TestMain implementation. See golang/go#31859, golang/go#33869.
#6388) * tests/GoTest.sh: Fix flags.Parse location to work on new go SDKs. Calling flags.Parse() within init() races with other packages which register flags in their init(), and in particular with the testing package itself. It is more reliable to call flags.Parse() from a TestMain implementation. See golang/go#31859, golang/go#33869. * .github: Enable build-go action in build.yaml workflow.
Why ? |
@Wang-Kai This issue was closed a year and a half ago. Closed issues are not a good place for discussions. Thanks. |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
Ran test having custom command line flags, minimal example:
What did you expect to see?
What did you see instead?
The text was updated successfully, but these errors were encountered: