blob: 7db83f0022882fd002ec800c81cf1003799d0f5c [file] [log] [blame]
// 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.*")
// Also, note how few functions we allow: if we generate bindings for all the declared
// functions, we run into linking errors. Only some functions are actually defined in
// `libittnotify.a` but most are provided dynamically by the dynamic collection library. See
// the `README.md` for more details.
.allowlist_function("__itt_mark_pt.*")
.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 (`BLESS=1 cargo test`)");
}
}
#[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 (`BLESS=1 cargo test`)"
);
}
}
/// 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
}
}