I'm writing some Rust code that manipulates raw pointers. These raw pointers are then exposed to users through structures that use ContravariantLifetime to tie the lifetime of the struct to my object.
I'd like to be able to write tests that validate that the user-facing structures cannot live longer than my object. I have code like the following:
fn element_cannot_outlive_parts() {
let mut z = {
let p = Package::new();
p.create() // returns an object that cannot live longer than p
};
}
This fails to compile, which is exactly what I want. However, I'd like to have some automated check that this behavior is true even after whatever refactoring I do to the code.
My best idea at the moment is to write one-off Rust files with this code and rig up bash scripts to attempt to compile them and look for specific error messages, which all feels pretty hacky.
The Rust project has a special set of tests called "compile-fail" tests that do exactly what you want.
The compiletest crate is an extraction of this idea that allows other libraries to do the same thing:
fn main() {
let x: (u64, bool) = (true, 42u64);
//~^ ERROR mismatched types
//~^^ ERROR mismatched types
}
One idea that gets halfway there is to use Cargo's "features".
Specify tests with a feature flag:
#[test]
#[cfg(feature = "compile_failure")]
fn bogus_test() {}
Add this to Cargo.toml:
[features]
compile_failure = []
And run tests as
cargo test --features compile_failure
The obvious thing missing from this is the automatic checking of "was it the right failure". If nothing else, this allows me to have tests that are semi-living in my codebase.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With