Skip to content

Commit 268cdb1

Browse files
committed
PBC -> test framework, move folder specification to framework Cargo.toml
1 parent 37a7ed8 commit 268cdb1

File tree

1 file changed

+83
-104
lines changed

1 file changed

+83
-104
lines changed

text/0000-erfc-post-build-contexts.md

Lines changed: 83 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
- Feature Name: post_build_contexts
1+
- Feature Name: custom_test_frameworks
22
- Start Date: 2018-01-25
33
- RFC PR: (leave this empty)
44
- Rust Issue: (leave this empty)
55

66
# Summary
77
[summary]: #summary
88

9-
This is an *experimental RFC* for adding the ability to integrate custom test/bench/etc frameworks ("post-build frameworks") in Rust.
9+
This is an *experimental RFC* for adding the ability to integrate custom test/bench/etc frameworks ("test frameworks") in Rust.
1010

1111
# Motivation
1212
[motivation]: #motivation
@@ -46,8 +46,8 @@ The main two features proposed are:
4646

4747
- An API for crates that generate custom binaries, including
4848
introspection into the target crate.
49-
- A mechanism for `cargo` integration so that custom post-build
50-
contexts are at the same level of integration as `test` or `bench` as
49+
- A mechanism for `cargo` integration so that custom test frameworks
50+
are at the same level of integration as `test` or `bench` as
5151
far as build processes are concerned.
5252

5353
[cargo-fuzz]: https://github.com/rust-fuzz/cargo-fuzz
@@ -60,28 +60,27 @@ The main two features proposed are:
6060
(As an eRFC I'm merging the "guide-level/reference-level" split for now; when we have more concrete
6161
ideas we can figure out how to frame it and then the split will make more sense)
6262

63-
The basic idea is that crates can define post-build contexts, which specify
63+
The basic idea is that crates can define test frameworks, which specify
6464
how to transform collected test functions and construct a `main()` function,
6565
and then crates using these can declare them in their Cargo.toml, which will let
66-
crate developers invoke various test-like post-build steps using the post-build
67-
context.
66+
crate developers invoke various test-like steps using the framework.
6867

6968

70-
## Procedural macro for a new post-build context
69+
## Procedural macro for a new test framework
7170

72-
A custom post-build context is like a whole-crate procedural
71+
A test framework is like a whole-crate procedural
7372
macro that is evaluated after all other macros in the target crate have
7473
been evaluated. It is passed the `TokenStream` for every element in the
75-
target crate that has a set of attributes the post-build context has
76-
registered interest in. For example, to declare a post-build context
74+
target crate that has a set of attributes the test framework has
75+
registered interest in. For example, to declare a test framework
7776
called `mytest`:
7877

7978
```rust
8079
extern crate proc_macro;
8180
use proc_macro::TokenStream;
8281

8382
// attributes() is optional
84-
#[post_build_context(attributes(foo, bar))]
83+
#[test_framework(attributes(foo, bar))]
8584
pub fn mytest(items: &[AnnotatedItem]) -> TokenStream {
8685
// ...
8786
}
@@ -100,17 +99,17 @@ struct AnnotatedItem
10099

101100
`items` here contains an `AnnotatedItem` for every item in the
102101
target crate that has one of the attributes declared in `attributes`
103-
along with attributes sharing the name of the context (`mytest`, here).
102+
along with attributes sharing the name of the framework (`mytest`, here).
104103

105-
A post-build context could declare that it reacts to multiple different
104+
A test framework could declare that it reacts to multiple different
106105
attributes, in which case it would get all items with any of the
107106
listed attributes. These items be modules, functions, structs,
108-
statics, or whatever else the post-build context wants to support. Note
109-
that the post-build context function can only see all the annotated
107+
statics, or whatever else the test framework wants to support. Note
108+
that the test framework function can only see all the annotated
110109
items, not modify them; modification would have to happen with regular
111110
procedural macros. The returned `TokenStream` must declare the `main()`
112111
that is to become the entry-point for the binary produced when this
113-
post-build context is used.
112+
test framework is used.
114113

115114
So an example transformation would be to take something like this:
116115

@@ -143,99 +142,109 @@ fn main() {
143142
```
144143

145144
Because this procedural macro is only loaded when it is used as the
146-
post-build context, the `#[mytest]` annotation should probably be kept
145+
test framework, the `#[mytest]` annotation should probably be kept
147146
behind `#[cfg(mytest)]` (which is automatically set when we are currently running
148-
with the `mytest` context, i.e. `cargo post-build mytest` is being run)
147+
with the `mytest` framework, i.e. `cargo test --framework mytest` is being run)
149148
so that you don't get unknown attribute warnings
150-
whilst loading, and to avoid conflicts with other post-build contexts
149+
whilst loading, and to avoid conflicts with other frameworks
151150
that may use the same attributes. (We could change this by asking
152151
attributes to be registered in Cargo.toml, but we don't find this
153152
necessary)
154153

155154

156-
A crate may only define a single post-build context.
155+
A crate may only define a single framework.
157156

158157
## Cargo integration
159158

160-
Alternative post-build contexts need to integrate with cargo.
159+
Alternative frameworks need to integrate with cargo.
161160
In particular, when crate `a` uses a crate `b` which provides an
162-
post-build context, `a` needs to be able to specify when `b`'s post-build
163-
context should be used. Furthermore, cargo needs to understand that when
164-
`b`'s post-build context is used, `b`'s dependencies must also be linked.
165-
Note that `b` could potentially provide multiple post-build contexts ---
166-
these are named according to the name of their `#[post_build_context]`
167-
function.
161+
framework, `a` needs to be able to specify when `b`'s framework
162+
should be used. Furthermore, cargo needs to understand that when
163+
`b`'s framework is used, `b`'s dependencies must also be linked.
168164

169-
Crates which define a post-build context must have an `post-build-context = true`
170-
key in their `Cargo.toml`. They cannot be used as regular dependencies. It can also specify
165+
Crates which define a test framework must have a `[testing.framework]`
166+
key in their `Cargo.toml`. They cannot be used as regular dependencies.
167+
This section works like this:
171168

172169
```rust
170+
[testing.framework]
171+
name = "bench" # mandatory
172+
folders = ["bench/"]
173+
lib = true # true by default
173174
single-target = true # false by default
174175
```
175176

177+
`lib` specifies if the `--lib` mode exists for this framework by default,
178+
and `folders` specifies which folders the framework applies to. Both can be overridden
179+
by consumers.
180+
176181
`single-target` indicates that only a single target can be run with this
177-
context at once (some tools, like cargo-fuzz, run forever, and so it
182+
framework at once (some tools, like cargo-fuzz, run forever, and so it
178183
does not make sense to specify multiple targets).
179184

180-
Crates that wish to *use* a custom post-build context, do so by defining
181-
a new post-build context under a new `build-context` section in their
185+
Crates that wish to *use* a custom test framework, do so by including a framework
186+
under a new `[[testing.frameworks]]` section in their
182187
`Cargo.toml`:
183188

184189
```toml
185-
[post-build.context.fuzz]
190+
[[testing.frameworks]]
186191
provider = { rust-fuzz = "1.0" }
187-
folders = ["fuzz/"]
192+
name = "fuzz" # optional, overrides `name` on framework crate
193+
folders = ["fuzz/"] # optional, overrides `folders` on framework crate
194+
lib = false # optional, overrides `lib` on framework crate
188195
```
189196

190-
This defines a post-build context named `fuzz`, which uses the
197+
This pulls in the framework named "fuzz", which uses the
191198
implementation provided by the `rust-fuzz` crate. When run, it will be
192199
applied to all files in the `fuzz` directory. By default, the following
193-
contexts are defined:
200+
frameworks are defined:
194201

195202
```toml
196-
[post-build.context.test]
203+
[[testing.frameworks]]
204+
name = "test"
197205
provider = { test = "1.0" }
198206
folders = ["tests/"]
199207

200-
[post-build.context.bench]
208+
[[testing.frameworks]]
209+
name = "bench"
201210
provider = { ?? = "1.0" }
202211
folders = ["benches/"]
203212

204-
[post-build.context.examples]
213+
[[testing.frameworks]]
214+
name = "example"
205215
provider = { ?? = "1.0" }
206216
folders = ["examples/"]
207217
```
208218

209-
There's also an `example` context defined that just runs the `main()` of
210-
any files given.
211-
212-
These can be overridden by a crate's `Cargo.toml`.
219+
Whereas having two frameworks of the same name is an error, if you define
220+
a framework named "test", "bench", or "example", it will override the implicitly
221+
defined builtin frameworks.
213222

214-
To invoke a particular post-build context, a user invokes `cargo context
215-
<context>`. `cargo test` and `cargo bench` are aliases for `cargo
216-
context test` and `cargo context bench` respectively. Any additional
217-
arguments are passed to the post-build context binary. By convention, the
223+
To invoke a particular framework, a user invokes `cargo test --framework
224+
<name>`. `cargo bench` is an alias for `cargo
225+
test --framework bench`. Any additional
226+
arguments are passed to the testing binary. By convention, the
218227
first position argument should allow filtering which targets
219228
(tests/benchmarks/etc.) are run.
220229

221-
To run multiple contexts at once, a crate can declare post-build context
222-
*sets*. One such example is the `test` post-build context set, which
223-
will run doctests and the `test` and `examples` context. This can be
230+
To run multiple frameworks at once, a crate can declare testing
231+
*sets*. One such example is the `test` testing set, which
232+
will run doctests and the `test` and `examples` framework. This can be
224233
customized:
225234

226235
```toml
227-
[post-build.set.test]
228-
contexts = [test, quickcheck, examples]
236+
[testing.set.test]
237+
frameworks = [test, quickcheck, examples]
229238
```
230239

231240
This means that `cargo test` will, aside from doctests, run `cargo
232-
context test`, `cargo context quickcheck`, and `cargo context examples`
241+
test --framework test`, `cargo test --framework quickcheck`, and `cargo test --framework examples`
233242
(and similar stuff for `cargo bench`). It is not possible to make `cargo
234-
test` _not_ run doctests. If both a context and a set exists with a
243+
test` _not_ run doctests. If both a framework and a set exists with a
235244
given name, the set takes precedence.
236245

237-
`[[test]]` and `[[example]]` in a crate's `Cargo.toml` add files to the
238-
`test` and `example` contexts respectively.
246+
`[[test]]` and `[[example]]` in a crate's `Cargo.toml` add targets to the
247+
`test` and `example` frameworks respectively.
239248

240249
## To be designed
241250

@@ -255,9 +264,9 @@ like json output and whatnot.
255264

256265
- This adds more sections to `Cargo.toml`.
257266
- This complicates the execution path for cargo, in that it now needs
258-
to know about post-build contexts and sets.
267+
to know about testing frameworks and sets.
259268
- Flags and command-line parameters for test and bench will now vary
260-
between post-build contexts, which may confuse users as they move
269+
between testing frameworks, which may confuse users as they move
261270
between crates.
262271

263272
# Rationale and alternatives
@@ -273,7 +282,7 @@ forms of testing or benchmarking.
273282
An alternative proposal was to expose an extremely general whole-crate proc macro:
274283

275284
```rust
276-
#[post_build_context(attributes(foo, bar))]
285+
#[test_framework(attributes(foo, bar))]
277286
pub fn mytest(crate: TokenStream) -> TokenStream {
278287
// ...
279288
}
@@ -318,7 +327,7 @@ compiler already has)
318327
Test crates are now simply proc macro attributes:
319328

320329
```rust
321-
#[proc_macro_attr(attributes(test, foo, bar))]
330+
#[test_framework(attributes(test, foo, bar))]
322331
pub fn harness(crate: TokenStream) -> TokenStream {
323332
// ...
324333
}
@@ -339,31 +348,15 @@ there's consensus on some of these we can move them into the main RFC.
339348

340349
Documentation tests are somewhat special, in that they cannot easily be
341350
expressed as `TokenStream` manipulations. In the first instance, the
342-
right thing to do is probably to have an implicitly defined post-build
343-
context called `doctest` which is included in the post-build context set
351+
right thing to do is probably to have an implicitly defined framework
352+
called `doctest` which is included in the testing set
344353
`test` by default (as proposed above).
345354

346355
Another argument for punting on doctests is that they are intended to
347356
demonstrate code that the user of a library would write. They're there
348357
to document *how* something should be used, and it then makes somewhat
349358
less sense to have different "ways" of running them.
350359

351-
## Translating existing cargo test flags
352-
353-
Today, `cargo test` takes a number of flags such as `--lib`, `--test
354-
foo`, and `--doc`. As it would be a breaking change to change these,
355-
cargo should recognize them and map to the appropriate post-build
356-
contexts.
357-
358-
Furthermore, `cargo test` lets you pick a single testing target via `--test`,
359-
and `cargo bench` via `--bench`. We'll need to create an agnostic flag
360-
for `cargo context` (we cannot use `--target` because it is already used for
361-
the target architecture, and `--test` is too specific for tests). `--post-build-target`
362-
is one rather verbose suggestion.
363-
364-
We also need to settle on a command name, `cargo context` and `cargo post-build`
365-
don't quite capture what's going on.
366-
367360
## Standardizing the output
368361

369362
We should probably provide a crate with useful output formatters and
@@ -373,27 +366,27 @@ to standardize things like json output and whatnot.
373366

374367
## Namespacing
375368

376-
Currently, two post-build contexts can both declare interest in the same
369+
Currently, two frameworks can both declare interest in the same
377370
attributes. How do we deal with collisions (e.g., most test crates will
378371
want the attribute `#[test]`). Do we namespace the attributes by the
379-
context name (e.g., `#[mytest::test]`)? Do we require them to be behind
372+
framework name (e.g., `#[mytest::test]`)? Do we require them to be behind
380373
`#[cfg(mytest)]`?
381374

382375
## Runtime dependencies and flags
383376

384-
The code generated by the post-build context may itself have dependencies.
385-
Currently there's no way for the post-build context to specify this. One
377+
The code generated by the framework may itself have dependencies.
378+
Currently there's no way for the framework to specify this. One
386379
proposal is for the crate to specify _runtime_ dependencies of the
387-
post-build context via:
380+
framework via:
388381

389382
```toml
390-
[context-dependencies]
383+
[testing.framework.dependencies]
391384
libfuzzer-sys = ...
392385
```
393386

394-
If a crate is currently running this post-build context, its
395-
dev-dependencies will be semver-merged with the post-build context's
396-
`context-dependencies`. However, this may not be strictly necessary.
387+
If a crate is currently running this framework, its
388+
dev-dependencies will be semver-merged with the frameworks's
389+
`framework.dependencies`. However, this may not be strictly necessary.
397390
Custom derives have a similar problem and they solve it by just asking
398391
users to import the correct crate.
399392

@@ -402,27 +395,13 @@ users to import the correct crate.
402395
The general syntax and toml stuff should be approximately settled on before this eRFC merges, but
403396
iterated on later. Naming the feature is hard, some candidates are:
404397

405-
- test framework
398+
- testing framework
399+
- post-build context
406400
- build context
407401
- execution context
408402

409403
None of these are particularly great, ideas would be nice.
410404

411-
## Default folders and sets
412-
413-
Should a post-build context be able to declare "defaults" for what folders and post-build sets it
414-
should be added to? This might save users from some boilerplate in a large number of situations.
415-
416-
This could be done in the Cargo.toml as:
417-
418-
```toml
419-
[post-build.defaults]
420-
folders = ["tests/"]
421-
set = "test" # will automatically be added to the `test` set
422-
```
423-
424-
This is useful if a crate wishes to standardize things.
425-
426405
## Bencher
427406

428407
Should we be shipping a bencher by default at all (i.e., in libtest)? Could we instead default

0 commit comments

Comments
 (0)