// This is a smoke test for pre-generated `src/ittapi-bindings.rs` and // `src/jitprofiling-bindings.rs` files to see that they don't need to be // updated. We check in a generated version so downstream consumers don't // have to get `bindgen` working themselves. // // If bindgen or ittapi.h or jitprofiling.h change you can run tests with // `BLESS=1` (inspired by a similar patch for binaryen) to regenerate the // source files, otherwise this can test on CI that the file doesn't need // to be regenerated. #![allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] #![allow(unused)] const INCLUDE_PATH: &'static str = "./c-library/include"; #[cfg(target_os = "linux")] const BINDINGS_PATH: &'static str = "src/linux"; #[cfg(target_os = "macos")] const BINDINGS_PATH: &'static str = "src/macos"; #[cfg(target_os = "windows")] const BINDINGS_PATH: &'static str = "src/windows"; #[cfg(target_os = "freebsd")] const BINDINGS_PATH: &'static str = "src/freebsd"; #[cfg(target_os = "openbsd")] const BINDINGS_PATH: &'static str = "src/openbsd"; #[test] fn test_ittnotify_bindings_up_to_date() { // When generating the `ittnotify`, we exclude non-ITT constants (see `allowlist_var`) to avoid // `libc` differences. let mut expected = bindgen::Builder::default() .formatter(bindgen::Formatter::Rustfmt) .allowlist_var("ITT.*") .allowlist_var("__itt.*") .header(concat(INCLUDE_PATH, "/ittnotify.h")) .generate() .expect("Unable to generate ittnotify bindings.") .to_string(); let bindings_file = concat(BINDINGS_PATH, "/ittnotify_bindings.rs"); if std::env::var("BLESS").is_ok() { std::fs::write(bindings_file, expected).unwrap(); } else { let expected = normalize(expected); let actual = normalize(std::fs::read_to_string(bindings_file).unwrap()); if expected == actual { return; } for diff in diff::lines(&expected, &actual) { match diff { diff::Result::Both(_, s) => println!(" {}", s), diff::Result::Left(s) => println!("-{}", s), diff::Result::Right(s) => println!("+{}", s), } } panic!("differences found, need to regenerate ittnotify bindings"); } } #[test] fn test_jitprofiling_bindings_up_to_date() { let mut expected = bindgen::Builder::default() .formatter(bindgen::Formatter::Rustfmt) .header(concat(INCLUDE_PATH, "/jitprofiling.h")) .generate() .expect("Unable to generate jitprofiling bindings") .to_string(); let bindings_file = concat(BINDINGS_PATH, "/jitprofiling_bindings.rs"); if std::env::var("BLESS").is_ok() { std::fs::write(bindings_file, expected).unwrap(); } else { let expected = normalize(expected); let actual = normalize(std::fs::read_to_string(bindings_file).unwrap()); if expected == actual { return; } for diff in diff::lines(&expected, &actual) { match diff { diff::Result::Both(_, s) => println!(" {}", s), diff::Result::Left(s) => println!("-{}", s), diff::Result::Right(s) => println!("+{}", s), } } panic!("differences found, need to regenerate jitprofiling bindings"); } } /// Concatenate two strings; `concat!` only works with literals. fn concat(a: &str, b: &str) -> String { format!("{}{}", a, b) } /// Normalize the line endings of a string; this removes Windows' carriage returns. fn normalize(str: String) -> String { if cfg!(target_os = "windows") { str.replace("\r", "") } else { str } }