Skip to content

Commit 282941b

Browse files
committed
Port backtrace-rs's cpp_smoke_test to rustc repo
1 parent 5e55679 commit 282941b

File tree

5 files changed

+130
-0
lines changed

5 files changed

+130
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[package]
2+
name = "cpp_smoke_test"
3+
version = "0.1.0"
4+
authors = ["Nick Fitzgerald <[email protected]>"]
5+
edition = "2021"
6+
build = "build.rs"
7+
8+
[build-dependencies]
9+
cc = "1.0"
10+
11+
[dependencies]
12+
backtrace = { version = "0.3.74", features = ["cpp_demangle"] }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
fn main() {
2+
compile_cpp();
3+
}
4+
5+
fn compile_cpp() {
6+
println!("cargo:rerun-if-changed=cpp/trampoline.cpp");
7+
8+
cc::Build::new()
9+
.cpp(true)
10+
.debug(true)
11+
.opt_level(0)
12+
.file("cpp/trampoline.cpp")
13+
.compile("libcpptrampoline.a");
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#include <stdio.h>
2+
3+
namespace space {
4+
template <typename FuncT>
5+
void templated_trampoline(FuncT func) {
6+
func();
7+
}
8+
}
9+
10+
typedef void (*FuncPtr)();
11+
12+
extern "C" void cpp_trampoline(FuncPtr func) {
13+
space::templated_trampoline(func);
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
use std::sync::atomic::{AtomicBool, Ordering};
2+
3+
extern "C" {
4+
fn cpp_trampoline(func: extern "C" fn()) -> ();
5+
}
6+
7+
#[test]
8+
fn smoke_test_cpp() {
9+
static RAN_ASSERTS: AtomicBool = AtomicBool::new(false);
10+
11+
extern "C" fn assert_cpp_frames() {
12+
let mut physical_frames = Vec::new();
13+
backtrace::trace(|cx| {
14+
physical_frames.push(cx.ip());
15+
16+
// We only want to capture this closure's frame, assert_cpp_frames,
17+
// space::templated_trampoline, and cpp_trampoline. Those are
18+
// logical frames, which might be inlined into fewer physical
19+
// frames, so we may end up with extra logical frames after
20+
// resolving these.
21+
physical_frames.len() < 5
22+
});
23+
24+
let names: Vec<_> = physical_frames
25+
.into_iter()
26+
.flat_map(|ip| {
27+
let mut logical_frame_names = vec![];
28+
29+
backtrace::resolve(ip, |sym| {
30+
let sym_name = sym.name().expect("Should have a symbol name");
31+
let demangled = sym_name.to_string();
32+
logical_frame_names.push(demangled);
33+
});
34+
35+
assert!(
36+
!logical_frame_names.is_empty(),
37+
"Should have resolved at least one symbol for the physical frame"
38+
);
39+
40+
logical_frame_names
41+
})
42+
// Skip the backtrace::trace closure and assert_cpp_frames, and then
43+
// take the two C++ frame names.
44+
.skip_while(|name| !name.contains("trampoline"))
45+
.take(2)
46+
.collect();
47+
48+
println!("actual names = {names:#?}");
49+
50+
let expected =
51+
["void space::templated_trampoline<void (*)()>(void (*)())", "cpp_trampoline"];
52+
println!("expected names = {expected:#?}");
53+
54+
assert_eq!(names.len(), expected.len());
55+
for (actual, expected) in names.iter().zip(expected.iter()) {
56+
assert_eq!(actual, expected);
57+
}
58+
59+
RAN_ASSERTS.store(true, Ordering::SeqCst);
60+
}
61+
62+
assert!(!RAN_ASSERTS.load(Ordering::SeqCst));
63+
unsafe {
64+
cpp_trampoline(assert_cpp_frames);
65+
}
66+
assert!(RAN_ASSERTS.load(Ordering::SeqCst));
67+
}

Diff for: tests/run-make/backtrace-cpp-smoke-test/rmake.rs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Part of porting backtrace-rs tests to rustc repo:
2+
// Original test: <https://github.com/rust-lang/rust/issues/122899>
3+
// <https://github.com/rust-lang/backtrace-rs/tree/6fa4b85b9962c3e1be8c2e5cc605cd078134152b/crates/cpp_smoke_test>
4+
// Issue: https://github.com/rust-lang/rust/issues/122899
5+
// ignore-tidy-linelength
6+
7+
use std::path::PathBuf;
8+
9+
use run_make_support::{cargo, cmd, env_var, path, target};
10+
11+
const CRATE: &str = "cpp_smoke_test";
12+
13+
fn main() {
14+
std::env::set_current_dir(CRATE).unwrap();
15+
16+
let target_dir = path("target");
17+
18+
cargo()
19+
.args(&["test", "--target", &target()])
20+
.env("CARGO_TARGET_DIR", &target_dir)
21+
.run()
22+
.assert_exit_code(0);
23+
}

0 commit comments

Comments
 (0)