Testing macros for accidental leaks


#1

Current test framework only tests success or panics. With macros, they aren’t always fully hygienic, so sometimes you wanna test your own hygiene.

Take for example eventbus. This shouldn’t compile:

#[macro_use]
extern crate eventbus;

use eventbus::{Event, EventBus};

struct MyEvent {
    i: i32
}

impl Event for MyEvent {
}

#[test]
fn test_hygiene() {
    let bus = [EventBus::new()];
    let mut event = MyEvent { i: 3 };
    post_event!(&bus[EVENT_ID.load(::std::sync::atomic::Ordering::Relaxed)], MyEvent, &mut event);
}

And (as of eventbus 0.4.0) it doesn’t, but there’s no way to automatically test it.


#2

There’s two options I know of for testing whether something doesn’t compile:

  1. compile_fail doc test
  2. compiletest_rs

#3

The former is uh, how would I even use that?

The latter doesn’t work on stable.


#4

compiletest_rs does actually have a stable feature to run on stable, the PR is the only sort of documentation of it I can find: https://github.com/laumann/compiletest-rs/pull/107


#5

It builds on stable, but I’d hardly say it works on stable.


#6

I am very confused about that comment. For your use case it would work exactly the same on stable.


#7

compiletest-rs’s compile-fail tests don’t work on stable. I tried it.


#8

I can’t guess what you did wrong, but I can assure you that it does work on stable. :laughing:

For example try running cargo +stable test against this directory of ref-cast, or cargo +stable test --features compiletest against this directory of indoc.


#9

wait, those aren’t testing the parent crate directly…

they aren’t using src/lib.rs and tests/…

I guess that’s what I did wrong, yeah? (edit: nope, still doesn’t work)

anyway, would still be nicer if they were built-in.


#10

I still can’t guess what you are doing, but that’s not it either. It works exactly the same if you move those tests directly into the main crate. :smiley: You can see this PR passing in CI against stable, beta, and nightly: https://github.com/dtolnay/ref-cast/pull/6

I prefer to keep them separate only because it is not possible to have optional dev-dependencies at the moment (this is tracked in rust-lang/cargo#1596). If I need to run my crate’s tests against an older version of rustc than the one required by compiletest_rs, this way makes it easier.


#11

maybe I’m accidentally using an older rustc? .-.


#12

The perfect solution would be a #[should_not_compile] attribute with a optional rustc error code.

It would probably require cargo test to generate for each of these test a rs file with all the other tests removed (so the failing test can be identified) and try to compile them. It would probably slow down test a lot, even if code generation can be skipped.