blob: bd5afcb3a618674bc21807fe9cb091cc0e2fe47d [file] [log] [blame]
#[cfg(test)]
mod tests {
use std::path::Path;
use backtrace::Backtrace;
use libc::c_void;
pub type Callback = extern "C" fn(data: *mut c_void);
extern "C" {
fn foo(cb: Callback, data: *mut c_void);
}
extern "C" fn store_backtrace(data: *mut c_void) {
let bt = backtrace::Backtrace::new();
unsafe { *(data as *mut Option<Backtrace>) = Some(bt) };
}
fn assert_contains(backtrace: &Backtrace,
expected_name: &str,
expected_file: &str,
expected_line: u32) {
let expected_file = Path::new(expected_file);
for frame in backtrace.frames() {
for symbol in frame.symbols() {
if let Some(name) = symbol.name() {
if name.as_bytes() == expected_name.as_bytes() {
assert!(symbol.filename().unwrap().ends_with(expected_file));
assert_eq!(symbol.lineno(), Some(expected_line));
return;
}
}
}
}
panic!("symbol {:?} not found in backtrace: {:?}", expected_name, backtrace);
}
/// Verifies that when debug info includes only lines tables the generated
/// backtrace is still generated successfully. The test exercises behaviour
/// that failed previously when compiling with clang -g1.
///
/// The test case uses C rather than rust, since at that time when it was
/// written the debug info generated at level 1 in rustc was essentially
/// the same as at level 2.
#[test]
#[cfg_attr(windows, ignore)]
fn backtrace_works_with_line_tables_only() {
let mut backtrace: Option<Backtrace> = None;
unsafe { foo(store_backtrace, &mut backtrace as *mut _ as *mut c_void) };
let backtrace = backtrace.expect("backtrace");
assert_contains(&backtrace, "foo", "src/callback.c", 13);
assert_contains(&backtrace, "bar", "src/callback.c", 9);
assert_contains(&backtrace, "baz", "src/callback.c", 5);
}
}