This project is an attempt at extracting the compiletest
utility
from the Rust compiler.
The compiletest
utility is useful for library and plugin developers, who want
to include test programs that should fail to compile, issue warnings or
otherwise produce compile-time output.
To use compiletest-rs
in your application, add the following to Cargo.toml
[dev-dependencies]
compiletest_rs = "0.11.0"
By default, compiletest-rs
should be able to run on both stable, beta and
nightly channels of rust. We use the tester
fork of Rust's builtin
test
crate, so that we don't have require nightly. If you are running nightly
and want to use Rust's test
crate directly, you need to have the rustc development
libraries install (which you can get by running rustup component add rustc-dev --toolchain nightly
). Once you have the rustc development libraries installed, you
can use the rustc
feature to make compiletest use them instead of the tester
crate.
[dev-dependencies]
compiletest_rs = { version = "0.11.0", features = [ "rustc" ] }
Create a tests
folder in the root folder of your project. Create a test file
with something like the following:
extern crate compiletest_rs as compiletest;
use std::path::PathBuf;
fn run_mode(mode: &'static str) {
let mut config = compiletest::Config::default();
config.mode = mode.parse().expect("Invalid mode");
config.src_base = PathBuf::from(format!("tests/{}", mode));
config.link_deps(); // Populate config.target_rustcflags with dependencies on the path
config.clean_rmeta(); // If your tests import the parent crate, this helps with E0464
compiletest::run_tests(&config);
}
#[test]
fn compile_test() {
run_mode("compile-fail");
run_mode("run-pass");
}
Each mode corresponds to a folder with the same name in the tests
folder. That
is for the compile-fail
mode the test runner looks for the
tests/compile-fail
folder.
Adding flags to the Rust compiler is a matter of assigning the correct field in
the config. The most common flag to populate is the
target_rustcflags
to include the link dependencies on the path.
// NOTE! This is the manual way of adding flags
config.target_rustcflags = Some("-L target/debug".to_string());
This is useful (and necessary) for library development. Note that other secondary library dependencies may have their build artifacts placed in different (non-obvious) locations and these locations must also be added.
For convenience, Config
provides a link_deps()
method that
populates target_rustcflags
with all the dependencies found in the
PATH
variable (which is OS specific). For most cases, it should be
sufficient to do:
let mut config = compiletest::Config::default();
config.link_deps();
Note that link_deps()
panics if any of the added paths contain spaces, as
these are currently not handled correctly.
See the test-project
folder for a complete working example using the
compiletest-rs
utility. Simply cd test-project
and cargo test
to see the
tests run. The annotation syntax is documented in the rustc-guide.
run-pass
mode is strictly not necessary since it's baked right into
Cargo, but I haven't bothered to take it outThank you for your interest in improving this utility! Please consider submitting your patch to the upstream source instead, as it will be incorporated into this repo in due time. Still, there are some supporting files that are specific to this repo, for example:
If you are unsure, open a pull request anyway and we would be glad to help!