Skip to content

Commit eb89558

Browse files
committed
Port backtrace dylib-dep test to a ui test
1 parent c3b05c6 commit eb89558

File tree

3 files changed

+147
-0
lines changed

3 files changed

+147
-0
lines changed

Diff for: tests/ui/debuginfo/auxiliary/dylib-dep-helper-aux.rs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//@ compile-flags: -g -Cstrip=none
2+
3+
#[inline(never)]
4+
pub fn callback<F>(f: F)
5+
where
6+
F: FnOnce((&'static str, u32)),
7+
{
8+
f((file!(), line!()))
9+
}
10+
11+
#[inline(always)]
12+
pub fn callback_inlined<F>(f: F)
13+
where
14+
F: FnOnce((&'static str, u32)),
15+
{
16+
f((file!(), line!()))
17+
}

Diff for: tests/ui/debuginfo/auxiliary/dylib-dep-helper.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//@ compile-flags: -g -Cstrip=none
2+
3+
#![crate_type = "cdylib"]
4+
#![crate_type = "rlib"]
5+
6+
#![allow(improper_ctypes_definitions)]
7+
8+
type Pos = (&'static str, u32);
9+
10+
macro_rules! pos {
11+
() => {
12+
(file!(), line!())
13+
};
14+
}
15+
16+
#[no_mangle]
17+
pub extern "C" fn foo(outer: Pos, inner: fn(Pos, Pos)) {
18+
inner(outer, pos!());
19+
}

Diff for: tests/ui/debuginfo/backtrace-dylib-dep.rs

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// Check that backtrace info is correctly generated for dynamic libraries and is usable by a
2+
// rust binary.
3+
// Part of porting some backtrace tests to rustc: <https://github.com/rust-lang/rust/issues/122899>.
4+
// Original test:
5+
// <https://github.com/rust-lang/backtrace-rs/tree/6fa4b85b9962c3e1be8c2e5cc605cd078134152b/crates/dylib-dep>
6+
// ignore-tidy-linelength
7+
//@ compile-flags: -g -Copt-level=0 -Cstrip=none
8+
//@ aux-crate: dylib_dep_helper=dylib-dep-helper.rs
9+
//@ aux-crate: auxiliary=dylib-dep-helper-aux.rs
10+
//@ ignore-musl musl doesn't support dynamic libraries (at least when the original test was written).
11+
//@ run-pass
12+
13+
#![allow(improper_ctypes)]
14+
#![allow(improper_ctypes_definitions)]
15+
16+
extern crate dylib_dep_helper;
17+
extern crate auxiliary;
18+
19+
use std::backtrace::Backtrace;
20+
21+
macro_rules! pos {
22+
() => {
23+
(file!(), line!())
24+
};
25+
}
26+
27+
macro_rules! check {
28+
($($pos:expr),*) => ({
29+
verify(&[$($pos,)* pos!()]);
30+
})
31+
}
32+
33+
fn verify(filelines: &[Pos]) {
34+
let trace = Backtrace::capture();
35+
eprintln!("-----------------------------------");
36+
eprintln!("looking for:");
37+
for (file, line) in filelines.iter().rev() {
38+
eprintln!("\t{file}:{line}");
39+
}
40+
eprintln!("found:\n{trace:#?}");
41+
let mut iter = filelines.iter().rev();
42+
// FIXME(jieyouxu): use proper `BacktraceFrame` accessors when it becomes available. Right now,
43+
// this depends on the debug format of `Backtrace` which is of course fragile.
44+
let backtrace = format!("{:#?}", trace);
45+
while let Some((file, line)) = iter.next() {
46+
// FIXME(jieyouxu): make this test use proper accessors on `BacktraceFrames` once it has
47+
// them.
48+
assert!(backtrace.contains(file), "expected backtrace to contain {}", file);
49+
assert!(backtrace.contains(&line.to_string()), "expected backtrace to contain {}", line);
50+
}
51+
}
52+
53+
type Pos = (&'static str, u32);
54+
55+
extern "C" {
56+
#[link_name = "foo"]
57+
fn foo(p: Pos, cb: fn(Pos, Pos));
58+
}
59+
60+
fn main() {
61+
std::env::set_var("RUST_BACKTRACE", "1");
62+
63+
unsafe {
64+
foo(pos!(), |a, b| {
65+
check!(a, b)
66+
})
67+
}
68+
69+
outer(pos!());
70+
}
71+
72+
#[inline(never)]
73+
fn outer(main_pos: Pos) {
74+
inner(main_pos, pos!());
75+
inner_inlined(main_pos, pos!());
76+
}
77+
78+
#[inline(never)]
79+
fn inner(main_pos: Pos, outer_pos: Pos) {
80+
check!(main_pos, outer_pos);
81+
check!(main_pos, outer_pos);
82+
let inner_pos = pos!(); auxiliary::callback(|aux_pos| {
83+
check!(main_pos, outer_pos, inner_pos, aux_pos);
84+
});
85+
let inner_pos = pos!(); auxiliary::callback_inlined(|aux_pos| {
86+
check!(main_pos, outer_pos, inner_pos, aux_pos);
87+
});
88+
}
89+
90+
#[inline(always)]
91+
fn inner_inlined(main_pos: Pos, outer_pos: Pos) {
92+
check!(main_pos, outer_pos);
93+
check!(main_pos, outer_pos);
94+
95+
#[inline(always)]
96+
fn inner_further_inlined(main_pos: Pos, outer_pos: Pos, inner_pos: Pos) {
97+
check!(main_pos, outer_pos, inner_pos);
98+
}
99+
inner_further_inlined(main_pos, outer_pos, pos!());
100+
101+
let inner_pos = pos!(); auxiliary::callback(|aux_pos| {
102+
check!(main_pos, outer_pos, inner_pos, aux_pos);
103+
});
104+
let inner_pos = pos!(); auxiliary::callback_inlined(|aux_pos| {
105+
check!(main_pos, outer_pos, inner_pos, aux_pos);
106+
});
107+
108+
// this tests a distinction between two independent calls to the inlined function.
109+
// (un)fortunately, LLVM somehow merges two consecutive such calls into one node.
110+
inner_further_inlined(main_pos, outer_pos, pos!());
111+
}

0 commit comments

Comments
 (0)