-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
Correctly parse nested go tests #16817
Correctly parse nested go tests #16817
Conversation
bcb4e0e
to
af44e17
Compare
/test integration |
Where's a flake when you need one. |
af44e17
to
309eb38
Compare
/test integration |
/test all |
309eb38
to
76aa972
Compare
/test integration
|
1 similar comment
/test integration |
Ready for review. Biggest change is that integration runner now only returns the last 20k of any successful job. I also ended up doing a bit of a hack to split the output since there's no perfect way to nest the results for consumption by the calling go test. |
/test integration |
76aa972
to
03c848d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have no idea what most of this does 😄
} | ||
return err | ||
} | ||
|
||
if testing.Verbose() { | ||
t.Log(string(out)) | ||
if len(out) < 20000 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought you wanted the last 20k lines - this seems to ignore anything longer than 20k.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can change but last is only slightly better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we please factor this to be a net-new parser that doesn't support nested output?
} | ||
return nil | ||
} | ||
|
||
func transformOutput(out string) string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a test for this? It's a little dense without test or explanatory comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed and documented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's tested in 17.txt
// The first submatch of this regex is the result of the test (PASS, FAIL, or SKIP) | ||
// The second submatch of this regex is the name of the test | ||
// The third submatch of this regex is the time taken in seconds for the test to finish | ||
var testResultPattern = regexp.MustCompile(`^(\s*)--- (PASS|FAIL|SKIP):\s+([^\s]+)\s+\((\d+\.\d+)(s| seconds)\)$`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment isn't valid anymore, since the first sub-match is the leading whitespace?
testStartPattern *regexp.Regexp | ||
testResultPattern *regexp.Regexp | ||
} | ||
var testOutputPattern = regexp.MustCompile(`^(\s*)(.*)$`) | ||
|
||
// MarksBeginning determines if the line marks the beginning of a test case |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Godoc drift?
return matches[3] + "s", true | ||
func ExtractOutput(line string) (string, int, bool) { | ||
if matches := testOutputPattern.FindStringSubmatch(line); len(matches) > 1 { | ||
return matches[2], len(matches[1]) / 4, true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not clear what the int
returned here is ... or why we divide it by four
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will clarify but it's go indentation
func (p *testDataParser) ExtractResult(line string) (api.TestResult, bool) { | ||
if matches := p.testResultPattern.FindStringSubmatch(line); len(matches) > 1 && len(matches[1]) > 0 { | ||
switch matches[1] { | ||
func ExtractResult(line string) (r api.TestResult, name string, depth int, duration string, ok bool) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An internal type to bind this data together may be less unwieldy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not worth it
tests[name] = test | ||
} | ||
orderedTests = append(orderedTests, name) | ||
currentTestName = []string{name} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this a slice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stack
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed
test.SkipMessage = &api.SkipMessage{} | ||
} | ||
if err := test.SetDuration(duration); err != nil { | ||
return nil, fmt.Errorf("unexpected duration on line %d: %s", count, duration) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isnt this a parser failure, not unexpected duration?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what you mean - the duration is wrog
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not unexpected that we found the duration, it just doesn't parse
name := currentTestName[len(currentTestName)-1] | ||
test := tests[name] | ||
switch { | ||
case test.FailureOutput != nil, test.SkipMessage != nil: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Switch is idiomatic for more than one condition
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's only one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are two conditions
if err := test.SetDuration(duration); err != nil { | ||
return nil, fmt.Errorf("unexpected duration on line %d: %s", count, duration) | ||
} | ||
switch { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we hide this behind a stack library so it's easier to read?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it will help.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean, it took me a million and a half years to figure it out ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I renamed it.
@@ -6,6 +6,8 @@ import ( | |||
"reflect" | |||
"testing" | |||
|
|||
"k8s.io/apimachinery/pkg/util/diff" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please let's not do this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
diff.ObjectReflectDiff is the most useful piece of code I have ever written.
Use a stateful parser approach to process each section of the test output independently. Correctly handles nested tests and nested output and puts any stdout/err into the SystemOut field of the generated test result. Note: this breaks --suite=nested, but was not able to find any users.
Allows junitreport to parse output correctly for nested integration tests.
03c848d
to
5c502e3
Compare
Updated |
/retest Flakes, unit verified that test output is correct. |
/retest |
1 similar comment
/retest |
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: smarterclayton, stevekuznetsov The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these OWNERS Files:
You can indicate your approval by writing |
Automatic merge from submit-queue (batch tested with PRs 16068, 16817). |
Use a stateful parser approach to process each section of the test
output independently. Correctly handles nested tests and nested output
and puts any stdout/err into the SystemOut field of the generated test
result.
Note: this breaks --suite=nested, but was not able to find any users.
@liggitt @stevekuznetsov tests are updated but want to soak this a bit