summaryrefslogtreecommitdiffstats
path: root/library/backtrace/crates/line-tables-only/src/lib.rs
blob: bd5afcb3a618674bc21807fe9cb091cc0e2fe47d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#[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);
    }
}