From a6aa516270225f387e9e615dcfa6eebca71f5475 Mon Sep 17 00:00:00 2001 From: Jeff Waugh Date: Wed, 16 Nov 2016 02:58:01 +1100 Subject: [PATCH] Generate a separate test function for every header - Header tests can now be run selectively, e.g. `cargo test union` will test all headers with 'union' in the file name. - The list of test functions is generated by `build.rs`, so never needs to be updated. - Clever approach suggested by @fitzgen. --- libbindgen/build.rs | 39 ++++++++++++++++++++++++-- libbindgen/tests/tests.rs | 58 ++++++++++----------------------------- 2 files changed, 51 insertions(+), 46 deletions(-) diff --git a/libbindgen/build.rs b/libbindgen/build.rs index b9cf3e6045..228a7f2212 100644 --- a/libbindgen/build.rs +++ b/libbindgen/build.rs @@ -1,10 +1,9 @@ mod codegen { extern crate quasi_codegen; use std::path::Path; - use std::env; pub fn main() { - let out_dir = env::var_os("OUT_DIR").unwrap(); + let out_dir = Path::new(env!("OUT_DIR")); let src = Path::new("src/codegen/mod.rs"); let dst = Path::new(&out_dir).join("codegen.rs"); @@ -14,6 +13,42 @@ mod codegen { } } +mod testgen { + use std::char; + use std::ffi::OsStr; + use std::fs::{self, File}; + use std::io::Write; + use std::path::Path; + + pub fn main() { + let out_dir = Path::new(env!("OUT_DIR")); + let mut dst = File::create(Path::new(&out_dir).join("tests.rs")).unwrap(); + + let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); + let headers_dir = manifest_dir.join("tests").join("headers"); + + let entries = fs::read_dir(headers_dir) + .expect("Couldn't read headers dir") + .map(|result| result.expect("Couldn't read header file")); + + for entry in entries { + match entry.path().extension().and_then(OsStr::to_str) { + Some("h") | Some("hpp") => { + let func = entry.file_name().to_str().unwrap() + .replace(|c| !char::is_alphanumeric(c), "_") + .replace("__", "_") + .to_lowercase(); + let _ = writeln!(dst, "test_header!(header_{}, {:?});", + func, entry.path()); + } + _ => {} + } + } + let _ = dst.flush(); + } +} + fn main() { codegen::main(); + testgen::main(); } diff --git a/libbindgen/tests/tests.rs b/libbindgen/tests/tests.rs index c98262608e..c07864062b 100644 --- a/libbindgen/tests/tests.rs +++ b/libbindgen/tests/tests.rs @@ -6,10 +6,9 @@ extern crate libbindgen; extern crate log; extern crate shlex; -use std::env; use std::fs; use std::io::{BufRead, BufReader, Error, ErrorKind, Read}; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; #[path="../../src/options.rs"] mod options; @@ -93,46 +92,17 @@ fn create_bindgen_builder(header: &PathBuf) builder_from_flags(args).map(|(builder, _)| builder.no_unstable_rust()) } -#[test] -fn run_bindgen_tests() { - log::set_logger(|max_log_level| { - use env_logger::Logger; - let env_logger = Logger::new(); - max_log_level.set(env_logger.filter()); - Box::new(env_logger) - }) - .expect("Failed to set logger."); - - let manifest_env = env::var("CARGO_MANIFEST_DIR") - .expect("CARGO_MANIFEST_DIR not set!"); - let manifest_dir = Path::new(&manifest_env); - let headers_dir = manifest_dir.join("tests").join("headers"); - - let entries = fs::read_dir(&headers_dir) - .expect("Couldn't read headers dir") - .map(|result| result.expect("Couldn't read header file")); - - let headers: Vec<_> = entries.filter_map(|entry| { - match entry.path().extension().and_then(|s| s.to_str()) { - Some("h") | Some("hpp") => Some(entry.path()), - _ => None, - } - }) - .collect(); - - let failures: Vec<_> = headers.iter() - .filter_map(|header| { - create_bindgen_builder(header) - .and_then(|builder| compare_generated_header(header, builder)) - .err() - }) - .collect(); - - let num_failures = failures.len(); - - if num_failures > 0 { - panic!("{} test{} failed!", - num_failures, - if num_failures > 1 {"s"} else {""}); - } +macro_rules! test_header { + ($function:ident, $header:expr) => ( + #[test] + fn $function() { + let header = PathBuf::from($header); + let _ = create_bindgen_builder(&header) + .and_then(|builder| compare_generated_header(&header, builder)) + .map_err(|err| panic!(format!("{}", err)) ); + } + ) } + +// This file is generated by build.rs +include!(concat!(env!("OUT_DIR"), "/tests.rs"));