Skip to content
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

libtest: add glob support to test name filters #46417

Closed
wants to merge 3 commits into from

Conversation

jonhoo
Copy link
Contributor

@jonhoo jonhoo commented Dec 1, 2017

Tests can currently only be filtered by substring or exact match. This makes it difficult to have finer-grained control over which tests to run (#46408), such as running only tests with a given suffix in a module, all tests without a given suffix, etc.

This PR adds support for glob patterns in test name filters. When at least one of the special glob characters (*, ?, or [) are present, the pattern is interpreted as a glob, and used to match against test names. These characters cannot appear in ordinary test names, so this should not cause unexpected results. This allows commands such as:

mymod::*_fast

or

foo --skip *_slow

Fixes #46408.

@rust-highfive
Copy link
Collaborator

r? @bluss

(rust_highfive has picked a reviewer for you, use r? to override)

@jonhoo
Copy link
Contributor Author

jonhoo commented Dec 1, 2017

One question that should probably be resolved: currently, globbing is enabled either if --glob is passed, or if the pattern includes a glob special character. But, consider an invocation like:

foo --skip *_slow

With the tests foo, foo_slow, and foo_fast. The user probably expects foo and foo_fast to be run, but this will actually run all three tests. foo doesn't contain any globbing characters, to globbing isn't enabled, and substring matching is used instead. This means that the skip patterns will also not use globbing, and will match the literal string *_slow, which doesn't match the name of any test. Worse yet, this isn't fixed by adding --glob; that would cause foo to be treated as a globbing pattern (not a substring match), and so only foo (and not foo_fast or foo_slow) would be matched. This suggests that to really fix this issue, we'd need to track whether each individual pattern should be a glob, which becomes overly complex.

All this taken together, I suggest we keep things the way they are currently (only infer from main pattern or presence of --glob) I believe that that's the behaviour that is least surprising and most intuitive. But I'm open to suggestions.

@jonhoo jonhoo force-pushed the glob-test-pattern branch from 432a38b to 6775588 Compare December 1, 2017 07:13
Tests can currently only be filtered by substring or exact match. This
makes it difficult to have finer-grained control over which tests to
run, such as running only tests with a given suffix in a module, all
tests without a given suffix, etc.

This PR adds a `--glob` flag to make test name filters use glob patterns
instead of string substring matching. This allows commands such as:

    --glob mymod::*_fast

or

    --glob --skip *_slow

The `--glob` flag can normally be omitted, as it is inferred whenever a
pattern includes one of the glob special characters (`*`, `?`, or `[`).
These characters cannot appear in ordinary test names, so this should
not cause unexpected results.

If both `--exact` *and* `--glob` are given, `--exact` takes precedence.

Fixes rust-lang#46408.
@jonhoo jonhoo force-pushed the glob-test-pattern branch from 6775588 to 9813b49 Compare December 1, 2017 07:57
@jonhoo
Copy link
Contributor Author

jonhoo commented Dec 1, 2017

I changed my mind. Latest commit interprets patterns independently, so the example given before

foo --skip *_slow

will now work correctly (it'll include foo_fast and foo, but not foo_slow). I think that's more intuitive. --glob and --exact apply to all patterns.

@kennytm kennytm added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Dec 1, 2017
@jonhoo jonhoo force-pushed the glob-test-pattern branch 2 times, most recently from 17c28f6 to 0a122f0 Compare December 1, 2017 16:43
The filter and each skip rule are now all interpreted as test name
patterns separately. This means that, unless `--glob` is passed, only
patterns containing glob characters are considered glob patterns. For
example:

    foo --skip *_slow

Will consider `foo` a substring pattern, and `*_slow` a glob pattern.
Similarly

    *_fast --skip bar

Will run `foo_fast`, but not `bar_fast`.
@jonhoo jonhoo force-pushed the glob-test-pattern branch from 0a122f0 to 0b83c56 Compare December 1, 2017 18:27
@jonhoo
Copy link
Contributor Author

jonhoo commented Dec 1, 2017

This PR should probably also be tagged with relnotes if accepted.

@jonhoo
Copy link
Contributor Author

jonhoo commented Dec 1, 2017

Surprisingly tricky to figure out who the right person for review on libtest is :p Neither #rust-dev-tools, #rustc, or #rust-libs seems to know. Based on past PRs to libtest, let's try:
r? @Mark-Simulacrum

@Mark-Simulacrum Mark-Simulacrum added the relnotes Marks issues that should be documented in the release notes of the next release. label Dec 1, 2017
@Mark-Simulacrum
Copy link
Member

Code looks good in general. However, I'm not sure why we need the --glob flag -- it seems to do nothing, as we already infer globs in all cases when they could have an effect based on the documentation: https://docs.rs/glob/0.2.11/glob/struct.Pattern.html.

Could you explain that?

In terms of review, it seems like we may want to make this unstable, but I don't know if that's possible for libtest parameters. If we can't make it unstable then we should get all of libs team to sign off on it at least.

@jonhoo
Copy link
Contributor Author

jonhoo commented Dec 2, 2017

Good point -- I removed the flag. Technically the flag changes the behaviour of strings that do not contain the special characters, since globs required a complete match. Non-glob matches are substring matches by default. But I think you're right that in practice the --glob flag wouldn't be used.

I don't know of a way to make libtest parameters unstable, except by manually adding eprintln! to the code, but that doesn't seem right. Sign-off from the libs teams seems like a good idea!

@Mark-Simulacrum
Copy link
Member

@rust-lang/libs thoughts? This seems good but I'd want sign off from everyone since it'll probably be insta-stable.

@BurntSushi
Copy link
Member

This seems like a fine idea in principle. I think my only concern here would be the stabilization of the glob syntax itself. Aside from the fact that the glob crate isn't 1.0 yet, one key piece of common syntax that the current glob crate doesn't support is the curly bracket syntax, e.g., {foo,bar} to mean foo or bar. For example, today, the following program prints true for both matches, but I'd expect different results with a crate that supported curly bracket syntax:

extern crate glob;

use glob::Pattern;

fn main() {
    let pat = Pattern::new("{*").unwrap();
    println!("{:?}", pat.matches("{foo"));
    
    let pat = Pattern::new("{foo}").unwrap();
    println!("{:?}", pat.matches("{foo}"));
}

Would we consider this an acceptable breaking change? If so, then I suppose it seems fine to move forward. (In the sense that I can't think of any other concerns with the public facing interface.)

@jonhoo jonhoo force-pushed the glob-test-pattern branch from 2871364 to 2482c58 Compare December 2, 2017 06:02
@jonhoo
Copy link
Contributor Author

jonhoo commented Dec 2, 2017

@BurntSushi I'm not too concerned about that for the same reason I'm not concerned about introducing automatic interpretation of strings as globs in general: test names cannot contain {, and so no existing patterns that are used to match test names should stop working because of such a change.

@alexcrichton
Copy link
Member

Historically the test crate actually had support for full-blown regexes and that was just removed in the lead-up to 1.0 where we moved the regex crate to crates.io instead of in the standard library/libextra. In that sense there's definitely desire for this!

That being said I'm wary of using the glob crate as I think it can be difficult to specify what's happening (glob is quite old and somewhat unmaintained at this point). I'd personally be much more comfortable with the regex crate, but I'm also not sure we'd want to pull that into the distribution. I know long-term we've always wanted custom test frameworks to be a thing but we've been saying that for years now...

So I guess tl;dr; I'd ideally prefer for the extra support we add here to be specifyable (aka have documentation and be supported) which I think rules out glob but leaves open regex perhaps? Ideally though I'd still hold off on adding regex and instead add support for custom test frameworks, but that thought may be a bit of a pipe dream at this point!

@jonhoo
Copy link
Contributor Author

jonhoo commented Dec 4, 2017

I'd love having full regex support (similar to go test), but share your concern with folding in regex. glob presented a nice alternative given that it is already used elsewhere, and probably won't go away for a while. The syntax is also pretty simple and straightforward.

Custom test runners would be nice, I agree, but as you say we have been wanting that for a long time, and it doesn't seem like much is changing any time soon. It's also nice for the default thing that is run with cargo test to support something beyond just substring matching. And I think glob fits that nicely.

I think glob is a fairly familiar, and widely-documented (outside of Rust) format for these kinds of tasks. The fact that the crate is not maintained and not super well-documented is a problem, I agree, but something that could (and should) probably be fixed separately from this.

@jonhoo
Copy link
Contributor Author

jonhoo commented Dec 7, 2017

Gentle ping @alexcrichton

@alexcrichton
Copy link
Member

Ah sorry about that. I definitely understand where you're coming from but for me maintainability of a crate like libtest trumps almost all else, so the fact that glob isn't actually specified and is barely maintained (afaik) is a serious mark against it. The current libtest is very minimal and we've ended up getting pretty far with it. In that sense I would still personally prefer to not land major new features to libtest and continue to hold out for custom test frameworks. I realize that it's still pretty far out, but my hope is that we can add fuel to the fire of designing it instead of getting into an unfortunately unmaintainable state of libtest in a few years time.

@jonhoo
Copy link
Contributor Author

jonhoo commented Dec 7, 2017

Hmm, that's unfortunate, but I understand the reasoning. Is there any particular place to monitor the progress of custom test runners, and potentially to contribute/discuss directions going forward?

@alexcrichton
Copy link
Member

For posterity, the conversation here was resumed on IRC

@carols10cents
Copy link
Member

Also relevant: https://internals.rust-lang.org/t/past-present-and-future-for-rust-testing/6354/18

Putting this in the libs team's court for triage purposes :)

@carols10cents carols10cents added S-waiting-on-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Dec 12, 2017
@jonhoo
Copy link
Contributor Author

jonhoo commented Dec 12, 2017

@carols10cents hehe, yes, that was the follow-up to the IRC follow-up. @steveklabnik mentioned that he wanted to bring it up during the work week, so hopefully we'll see some further discussion coming out of that.

@alexcrichton
Copy link
Member

Ok I'm going to close this for no in favor of @jonhoo's thread on internals

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
relnotes Marks issues that should be documented in the release notes of the next release. S-waiting-on-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Test name filtering does not allow disambiguating tests with overlapping names
8 participants