Skip to content

Commit

Permalink
tests: Check that command_line_args round-trips.
Browse files Browse the repository at this point in the history
Fixes #1818.
  • Loading branch information
emilio committed Jul 1, 2020
1 parent 243359c commit d794a08
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 23 deletions.
6 changes: 5 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,13 @@ You may set the `BINDGEN_OVERWRITE_EXPECTED` environment variable to overwrite
the expected bindings with `bindgen`'s current output:

```
$BINDGEN_OVERWRITE_EXPECTED=1 cargo test
$ BINDGEN_OVERWRITE_EXPECTED=1 cargo test
```

If you're not changing command line arguments, you may want to set
`BINDGEN_DISABLE_ROUNDTRIP_TEST` to avoid a lot of tests for round-tripping of
those.

### Testing Generated Bindings

If your local changes are introducing expected modifications in the
Expand Down
63 changes: 41 additions & 22 deletions tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ use std::sync::Once;
mod options;
use crate::options::builder_from_flags;

/// The environment variable that determines if test expectations are overwritten.
static OVERWRITE_ENV_VAR: &str = "BINDGEN_OVERWRITE_EXPECTED";

// Run `rustfmt` on the given source string and return a tuple of the formatted
// bindings, and rustfmt's stderr.
fn rustfmt(source: String) -> (String, String) {
Expand Down Expand Up @@ -119,6 +116,7 @@ The latest `rustfmt` is required to run the `bindgen` test suite. Install
fn compare_generated_header(
header: &PathBuf,
builder: Builder,
check_roundtrip: bool,
) -> Result<(), Error> {
let file_name = header.file_name().ok_or(Error::new(
ErrorKind::Other,
Expand Down Expand Up @@ -194,6 +192,14 @@ fn compare_generated_header(
),
};

let flags = if check_roundtrip {
let mut flags = builder.command_line_flags();
flags.insert(0, "bindgen".into());
flags
} else {
vec![]
};

// We skip the generate() error here so we get a full diff below
let (actual, rustfmt_stderr) = match builder.generate() {
Ok(bindings) => {
Expand All @@ -207,37 +213,48 @@ fn compare_generated_header(
let (expected, rustfmt_stderr) = rustfmt(expected);
println!("{}", rustfmt_stderr);

if actual == expected {
if !actual.is_empty() {
return Ok(());
}
if actual.is_empty() {
return Err(Error::new(
ErrorKind::Other,
"Something's gone really wrong!",
));
}

println!("{}", rustfmt_stderr);
if actual != expected {
println!("{}", rustfmt_stderr);

println!("diff expected generated");
println!("--- expected: {:?}", looked_at.last().unwrap());
println!("+++ generated from: {:?}", header);
println!("diff expected generated");
println!("--- expected: {:?}", looked_at.last().unwrap());
println!("+++ generated from: {:?}", header);

for diff in diff::lines(&expected, &actual) {
match diff {
diff::Result::Left(l) => println!("-{}", l),
diff::Result::Both(l, _) => println!(" {}", l),
diff::Result::Right(r) => println!("+{}", r),
for diff in diff::lines(&expected, &actual) {
match diff {
diff::Result::Left(l) => println!("-{}", l),
diff::Result::Both(l, _) => println!(" {}", l),
diff::Result::Right(r) => println!("+{}", r),
}
}

// Overwrite the expectation with actual output.
if env::var_os("BINDGEN_OVERWRITE_EXPECTED").is_some() {
let mut expectation_file =
fs::File::create(looked_at.last().unwrap())?;
expectation_file.write_all(actual.as_bytes())?;
}

return Err(Error::new(ErrorKind::Other, "Header and binding differ! Run with BINDGEN_OVERWRITE_EXPECTED=1 in the environment to automatically overwrite the expectation."));
}

// Overwrite the expectation with actual output.
if env::var_os(OVERWRITE_ENV_VAR).is_some() {
let mut expectation_file = fs::File::create(looked_at.last().unwrap())?;
expectation_file.write_all(actual.as_bytes())?;
if check_roundtrip {
let roundtrip_builder = builder_from_flags(flags.into_iter())?.0;
if let Err(e) =
compare_generated_header(&header, roundtrip_builder, false)
{
return Err(Error::new(ErrorKind::Other, format!("Checking CLI flags roundtrip errored! You probably need to fix Builder::command_line_args. {}", e)));
}
}

Err(Error::new(ErrorKind::Other, "Header and binding differ! Run with BINDGEN_OVERWRITE_EXPECTED=1 in the environment to automatically overwrite the expectation."))
Ok(())
}

fn builder() -> Builder {
Expand Down Expand Up @@ -328,7 +345,9 @@ macro_rules! test_header {
fn $function() {
let header = PathBuf::from($header);
let result = create_bindgen_builder(&header).and_then(|builder| {
compare_generated_header(&header, builder)
let check_roundtrip =
env::var_os("BINDGEN_DISABLE_ROUNDTRIP_TEST").is_none();
compare_generated_header(&header, builder, check_roundtrip)
});

if let Err(err) = result {
Expand Down

0 comments on commit d794a08

Please sign in to comment.