8000 Search CTest output for failure locations (#4418) by malsyned · Pull Request #4420 · microsoft/vscode-cmake-tools · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Search CTest output for failure locations (#4418) #4420

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

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

malsyned
Copy link
Contributor

This change addresses item #4418

This changes visible behavior

The following changes are proposed:

Adds configuration setting cmake.ctest.failurePatterns, a list of regular expressions and capture group indices for matching file, line, message, expected output, and actual output from failing tests.

The purpose of this change

Populate TestMessage objects with more specific information about test failures than is available through the DEF_SOURCE_LINE property.

Other Notes/Information

I based the design of this feature around the design of Task Problem Matchers. It lacks some of the advanced features of Problem Matchers, like named patterns, pattern inheritance, multi-regexp patterns, and loops. I'm happy to add those to the implementation if needed, but I thought it better to start with the simplest thing that could work and grow it in response to feedback.

Screenshots

image

image

image

malsyned added a commit to malsyned/vscode-cmake-tools that referenced this pull request Apr 18, 2025
@gcampbell-msft
Copy link
Collaborator

@malsyned I think that this is a useful PR and is an interesting additive feature. There is also minimal risk for regression, as by default this will not perform any additional computation because the default is without this.

Before spending time reviewing, could you fix the merge conflicts?

Copy link
Collaborator
@gcampbell-msft gcampbell-msft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we use a more strict type than Object when defining the settings/emitters?

@malsyned
Copy link
Contributor Author

Could we use a more strict type than Object when defining the settings/emitters?

Fixed. I tightened up the corresponding schema in package.json while I was at it.

malsyned added 6 commits May 19, 2025 17:53
Adds configuration setting `cmake.ctest.failurePatterns`, a list of
regular expressions and capture group indices for matching file, line,
message, expected output, and actual output from failing tests. Pattern
matches are used to populate `TestMessage` objects with more specific
information than is available through the `DEF_SOURCE_LINE` property.
The string passed into `searchOutputForFailure()` has been normalized to
CRLF, so make sure the substrings produced from it also have CRLF line
endings.

https://code.visualstudio.com/api/extension-guides/testing#test-output
The package.json schema for `cmake.ctest.failurePattens` was more
lenient in some ways than the corresponding `FailurePatternsConfig`
TypeScript type. Bring them in line with each other.
@malsyned malsyned force-pushed the failure-patterns branch from ce9c88f to 58a6a64 Compare May 19, 2025 21:55
@malsyned
Copy link
Contributor Author
malsyned commented May 19, 2025

I have been doing some work to make sure that this feature is powerful enough to match GoogleTest and GoogleMock failure patterns. I think it is. I went in thinking it might be challenging to match the fairly complicated set of expected vs. actual patterns, but actually, GoogleTest and GoogleMock provide so much additional info in their messages that would be hidden if TestMessage.actual and .expected were filled in, that I don't think I want to match them anyway.

The regexp for GoogleTest/GoogleMock is (.+?):((?:\\d|#)+): *(?:[Ff]ailure|[Ee]rror)\n+((?:.+\n)*), and it is able to match multiple failures in the same test if they are reported:
image

So, that's increased my confidence in this with its current feature set.


const testMessage = new vscode.TestMessage(normalizeCRLF(message));
testMessage.location = new vscode.Location(
vscode.Uri.file(file), new vscode.Position(line, 0)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gcampbell-msft I have a small hesitation about this line, I would love for you to weigh in on it. It's assuming that the output file name matched by the regex is an absolute path suitable for passing to Uri.file(). It always has been in my testing, and I think due to the fact that CMake tends to generate build systems that operate exclusively on absolute paths, I'm guessing it's likely that it always will.

However, if you think otherwise, and you think there's a reasonable directory to resolve relative paths against, I would be happy to add something to this PR.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have any concerns, as the behavior when there are no patterns defined should be the same, correct?

With it being a new feature, I'm okay with the assmption that Uri.file() will work, again, as long as it still works the same if this feature isn't being used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, with no patterns defined, we'll never get to this line of code.

My concern is that the string being passed to Uri.file() is extracted from ctest output that probably originates in some unit test framework code that uses __FILE__. That's how CppUTest and GoogleTest do it, for example. GCC-like compilers generally don't absolute-ize relative paths passed on the command line, so in general it's possible for the output of these test executables to contain relative paths, which aren't handled well by Uri.file().

However, this isn't the general case, this is in the context of CMake, which generally ensures compilers are passed absolute paths, and uses absolute paths in its output messages. That's why I think we can get away with passing the file path directly to Uri.file() without worrying about trying to make it an absolute path first, but also why I wanted a second opinion.

@malsyned
Copy link
Contributor Author
malsyned commented Jun 9, 2025

@paulmaybee @gcampbell-msft Is there anything else you all would like on this PR before you'd consider merging it?

gcampbell-msft
gcampbell-msft previously approved these changes Jun 11, 2025
Copy link
Collaborator
@gcampbell-msft gcampbell-msft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a cool feature! It seems to present very little risk for regressions of other features and is purely additive, so I think this looks good, and it seems you have done good testing.

I left just a comment or two, but overall I think this looks great!


const testMessage = new vscode.TestMessage(normalizeCRLF(message));
testMessage.location = new vscode.Location(
vscode.Uri.file(file), new vscode.Position(line, 0)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have any concerns, as the behavior when there are no patterns defined should be the same, correct?

With it being a new feature, I'm okay with the assmption that Uri.file() will work, again, as long as it still works the same if this feature isn't being used.

@malsyned
Copy link
Contributor Author

I think this is a cool feature! It seems to present very little risk for regressions of other features and is purely additive, so I think this looks good, and it seems you have done good testing.

I left just a comment or two, but overall I think this looks great!

I'm glad you like it! Thanks for the review. I'll work on your comments today.

"type": "string"
}
],
"default": [
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gcampbell-msft in a few comments on this PR you've said some variation of

There is also minimal risk for regression, as by default this will not perform any additional computation because the default is without this

But this PR does add a couple of default regular expressions that will be tried against test output, so it would potentially change behavior in the absence of intentional user configuration. Should I empty out the default so that this feature is disabled by default?


const testMessage = new vscode.TestMessage(normalizeCRLF(message));
testMessage.location = new vscode.Location(
vscode.Uri.file(file), new vscode.Position(line, 0)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, with no patterns defined, we'll never get to this line of code.

My concern is that the string being passed to Uri.file() is extracted from ctest output that probably originates in some unit test framework code that uses __FILE__. That's how CppUTest and GoogleTest do it, for example. GCC-like compilers generally don't absolute-ize relative paths passed on the command line, so in general it's possible for the output of these test executables to contain relative paths, which aren't handled well by Uri.file().

However, this isn't the general case, this is in the context of CMake, which generally ensures compilers are passed absolute paths, and uses absolute paths in its output messages. That's why I think we can get away with passing the file path directly to Uri.file() without worrying about trying to make it an absolute path first, but also why I wanted a second opinion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
0