]> git.proxmox.com Git - rustc.git/blame - src/vendor/backtrace/tests/smoke.rs
New upstream version 1.23.0+dfsg1
[rustc.git] / src / vendor / backtrace / tests / smoke.rs
CommitLineData
7cac9316
XL
1extern crate backtrace;
2
3use std::os::raw::c_void;
4use std::thread;
5
6static LIBUNWIND: bool = cfg!(all(unix, feature = "libunwind"));
7static UNIX_BACKTRACE: bool = cfg!(all(unix, feature = "unix-backtrace"));
8static LIBBACKTRACE: bool = cfg!(all(unix, feature = "libbacktrace")) &&
abe05a73
XL
9 !cfg!(target_os = "fuchsia") && !cfg!(target_os = "macos") &&
10 !cfg!(target_os = "ios");
041b39d2 11static CORESYMBOLICATION: bool = cfg!(all(any(target_os = "macos", target_os = "ios"),
7cac9316 12 feature = "coresymbolication"));
abe05a73 13static DLADDR: bool = cfg!(all(unix, feature = "dladdr")) && !cfg!(target_os = "fuchsia");
7cac9316
XL
14static DBGHELP: bool = cfg!(all(windows, feature = "dbghelp"));
15static MSVC: bool = cfg!(target_env = "msvc");
ea8adc8c
XL
16static GIMLI_SYMBOLIZE: bool = cfg!(all(feature = "gimli-symbolize",
17 unix,
18 target_os = "linux"));
7cac9316
XL
19
20#[test]
21fn smoke_test_frames() {
22 frame_1(line!());
23 #[inline(never)] fn frame_1(start_line: u32) { frame_2(start_line) }
24 #[inline(never)] fn frame_2(start_line: u32) { frame_3(start_line) }
25 #[inline(never)] fn frame_3(start_line: u32) { frame_4(start_line) }
26 #[inline(never)] fn frame_4(start_line: u32) {
27 let mut v = Vec::new();
28 backtrace::trace(|cx| {
29 v.push((cx.ip(), cx.symbol_address()));
30 true
31 });
32
33 if v.len() < 5 {
34 assert!(!LIBUNWIND);
35 assert!(!UNIX_BACKTRACE);
36 assert!(!DBGHELP);
37 return
38 }
39
40 // On 32-bit windows apparently the first frame isn't our backtrace
41 // frame but it's actually this frame. I'm not entirely sure why, but at
42 // least it seems consistent?
43 let o = if cfg!(all(windows, target_pointer_width = "32")) {1} else {0};
44 // frame offset 0 is the `backtrace::trace` function, but that's generic
45 assert_frame(&v, o, 1, frame_4 as usize, "frame_4",
46 "tests/smoke.rs", start_line + 6);
47 assert_frame(&v, o, 2, frame_3 as usize, "frame_3", "tests/smoke.rs",
48 start_line + 3);
49 assert_frame(&v, o, 3, frame_2 as usize, "frame_2", "tests/smoke.rs",
50 start_line + 2);
51 assert_frame(&v, o, 4, frame_1 as usize, "frame_1", "tests/smoke.rs",
52 start_line + 1);
53 assert_frame(&v, o, 5, smoke_test_frames as usize,
54 "smoke_test_frames", "", 0);
55 }
56
57 fn assert_frame(syms: &[(*mut c_void, *mut c_void)],
58 offset: usize,
59 idx: usize,
60 actual_fn_pointer: usize,
61 expected_name: &str,
62 expected_file: &str,
63 expected_line: u32) {
64 if offset > idx { return }
65 let (ip, sym) = syms[idx - offset];
66 let ip = ip as usize;
67 let sym = sym as usize;
68 assert!(ip >= sym);
69 assert!(sym >= actual_fn_pointer);
70
71 // windows dbghelp is *quite* liberal (and wrong) in many of its reports
72 // right now...
73 if !DBGHELP {
74 assert!(sym - actual_fn_pointer < 1024);
75 }
76
77 let mut resolved = 0;
ea8adc8c 78 let can_resolve = DLADDR || LIBBACKTRACE || CORESYMBOLICATION || DBGHELP || GIMLI_SYMBOLIZE;
7cac9316
XL
79
80 let mut name = None;
81 let mut addr = None;
82 let mut line = None;
83 let mut file = None;
84 backtrace::resolve(ip as *mut c_void, |sym| {
85 resolved += 1;
86 name = sym.name().map(|v| v.to_string());
87 addr = sym.addr();
88 line = sym.lineno();
89 file = sym.filename().map(|v| v.to_path_buf());
90 });
91
92 // dbghelp doesn't always resolve symbols right now
93 match resolved {
94 0 => return assert!(!can_resolve || DBGHELP),
95 _ => {}
96 }
97
98 // * linux dladdr doesn't work (only consults local symbol table)
99 // * windows dbghelp isn't great for GNU
100 if can_resolve &&
101 !(cfg!(target_os = "linux") && DLADDR) &&
102 !(DBGHELP && !MSVC)
103 {
104 let name = name.expect("didn't find a name");
105 assert!(name.contains(expected_name),
106 "didn't find `{}` in `{}`", expected_name, name);
107 }
108
109 if can_resolve {
110 addr.expect("didn't find a symbol");
111 }
112
113 if (LIBBACKTRACE || CORESYMBOLICATION || (DBGHELP && MSVC)) && cfg!(debug_assertions) {
114 let line = line.expect("didn't find a line number");
115 let file = file.expect("didn't find a line number");
116 if !expected_file.is_empty() {
117 assert!(file.ends_with(expected_file),
118 "{:?} didn't end with {:?}", file, expected_file);
119 }
120 if expected_line != 0 {
121 assert!(line == expected_line,
122 "bad line number on frame for `{}`: {} != {}",
123 expected_name, line, expected_line);
124 }
125 }
126 }
127}
128
129#[test]
130fn many_threads() {
131 let threads = (0..16).map(|_| {
132 thread::spawn(|| {
133 for _ in 0..16 {
134 backtrace::trace(|frame| {
135 backtrace::resolve(frame.ip(), |symbol| {
136 let _s = symbol.name().map(|s| s.to_string());
137 });
138 true
139 });
140 }
141 })
142 }).collect::<Vec<_>>();
143
144 for t in threads {
145 t.join().unwrap()
146 }
147}
148
149#[test]
150#[cfg(feature = "rustc-serialize")]
151fn is_rustc_serialize() {
152 extern crate rustc_serialize;
153
154 fn is_encode<T: rustc_serialize::Encodable>() {}
155 fn is_decode<T: rustc_serialize::Decodable>() {}
156
157 is_encode::<backtrace::Backtrace>();
158 is_decode::<backtrace::Backtrace>();
159}
160
161#[test]
162#[cfg(feature = "serde")]
163fn is_serde() {
164 extern crate serde;
165
166 fn is_serialize<T: serde::ser::Serialize>() {}
041b39d2 167 fn is_deserialize<T: serde::de::DeserializeOwned>() {}
7cac9316
XL
168
169 is_serialize::<backtrace::Backtrace>();
170 is_deserialize::<backtrace::Backtrace>();
171}