summaryrefslogtreecommitdiffstats
path: root/library/backtrace/crates/cpp_smoke_test
diff options
context:
space:
mode:
Diffstat (limited to 'library/backtrace/crates/cpp_smoke_test')
-rw-r--r--library/backtrace/crates/cpp_smoke_test/Cargo.toml11
-rw-r--r--library/backtrace/crates/cpp_smoke_test/build.rs14
-rw-r--r--library/backtrace/crates/cpp_smoke_test/cpp/trampoline.cpp14
-rw-r--r--library/backtrace/crates/cpp_smoke_test/src/lib.rs2
-rw-r--r--library/backtrace/crates/cpp_smoke_test/tests/smoke.rs73
5 files changed, 114 insertions, 0 deletions
diff --git a/library/backtrace/crates/cpp_smoke_test/Cargo.toml b/library/backtrace/crates/cpp_smoke_test/Cargo.toml
new file mode 100644
index 000000000..1325d7c04
--- /dev/null
+++ b/library/backtrace/crates/cpp_smoke_test/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "cpp_smoke_test"
+version = "0.1.0"
+authors = ["Nick Fitzgerald <fitzgen@gmail.com>"]
+build = "build.rs"
+
+[build-dependencies]
+cc = "1.0"
+
+[dependencies]
+backtrace = { path = "../..", features = ["cpp_demangle"] }
diff --git a/library/backtrace/crates/cpp_smoke_test/build.rs b/library/backtrace/crates/cpp_smoke_test/build.rs
new file mode 100644
index 000000000..5ddc63d82
--- /dev/null
+++ b/library/backtrace/crates/cpp_smoke_test/build.rs
@@ -0,0 +1,14 @@
+fn main() {
+ compile_cpp();
+}
+
+fn compile_cpp() {
+ println!("cargo:rerun-if-changed=cpp/trampoline.cpp");
+
+ cc::Build::new()
+ .cpp(true)
+ .debug(true)
+ .opt_level(0)
+ .file("cpp/trampoline.cpp")
+ .compile("libcpptrampoline.a");
+}
diff --git a/library/backtrace/crates/cpp_smoke_test/cpp/trampoline.cpp b/library/backtrace/crates/cpp_smoke_test/cpp/trampoline.cpp
new file mode 100644
index 000000000..61e09604c
--- /dev/null
+++ b/library/backtrace/crates/cpp_smoke_test/cpp/trampoline.cpp
@@ -0,0 +1,14 @@
+#include <stdio.h>
+
+namespace space {
+ template <typename FuncT>
+ void templated_trampoline(FuncT func) {
+ func();
+ }
+}
+
+typedef void (*FuncPtr)();
+
+extern "C" void cpp_trampoline(FuncPtr func) {
+ space::templated_trampoline(func);
+}
diff --git a/library/backtrace/crates/cpp_smoke_test/src/lib.rs b/library/backtrace/crates/cpp_smoke_test/src/lib.rs
new file mode 100644
index 000000000..2002ef17d
--- /dev/null
+++ b/library/backtrace/crates/cpp_smoke_test/src/lib.rs
@@ -0,0 +1,2 @@
+#[test]
+fn it_works() {}
diff --git a/library/backtrace/crates/cpp_smoke_test/tests/smoke.rs b/library/backtrace/crates/cpp_smoke_test/tests/smoke.rs
new file mode 100644
index 000000000..b9aef47f5
--- /dev/null
+++ b/library/backtrace/crates/cpp_smoke_test/tests/smoke.rs
@@ -0,0 +1,73 @@
+extern crate backtrace;
+extern crate cpp_smoke_test;
+
+use std::sync::atomic::{AtomicBool, Ordering};
+
+extern "C" {
+ fn cpp_trampoline(func: extern "C" fn()) -> ();
+}
+
+#[test]
+#[ignore] // fixme(fitzgen/cpp_demangle#73)
+fn smoke_test_cpp() {
+ static RAN_ASSERTS: AtomicBool = AtomicBool::new(false);
+
+ extern "C" fn assert_cpp_frames() {
+ let mut physical_frames = Vec::new();
+ backtrace::trace(|cx| {
+ physical_frames.push(cx.ip());
+
+ // We only want to capture this closure's frame, assert_cpp_frames,
+ // space::templated_trampoline, and cpp_trampoline. Those are
+ // logical frames, which might be inlined into fewer physical
+ // frames, so we may end up with extra logical frames after
+ // resolving these.
+ physical_frames.len() < 4
+ });
+
+ let names: Vec<_> = physical_frames
+ .into_iter()
+ .flat_map(|ip| {
+ let mut logical_frame_names = vec![];
+
+ backtrace::resolve(ip, |sym| {
+ let sym_name = sym.name().expect("Should have a symbol name");
+ let demangled = sym_name.to_string();
+ logical_frame_names.push(demangled);
+ });
+
+ assert!(
+ !logical_frame_names.is_empty(),
+ "Should have resolved at least one symbol for the physical frame"
+ );
+
+ logical_frame_names
+ })
+ // Skip the backtrace::trace closure and assert_cpp_frames, and then
+ // take the two C++ frame names.
+ .skip_while(|name| !name.contains("trampoline"))
+ .take(2)
+ .collect();
+
+ println!("actual names = {:#?}", names);
+
+ let expected = [
+ "void space::templated_trampoline<void (*)()>(void (*)())",
+ "cpp_trampoline",
+ ];
+ println!("expected names = {:#?}", expected);
+
+ assert_eq!(names.len(), expected.len());
+ for (actual, expected) in names.iter().zip(expected.iter()) {
+ assert_eq!(actual, expected);
+ }
+
+ RAN_ASSERTS.store(true, Ordering::SeqCst);
+ }
+
+ assert!(!RAN_ASSERTS.load(Ordering::SeqCst));
+ unsafe {
+ cpp_trampoline(assert_cpp_frames);
+ }
+ assert!(RAN_ASSERTS.load(Ordering::SeqCst));
+}