summaryrefslogtreecommitdiffstats
path: root/third_party/rust/minidump-writer/tests
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/minidump-writer/tests')
-rw-r--r--third_party/rust/minidump-writer/tests/common/mod.rs67
-rw-r--r--third_party/rust/minidump-writer/tests/linux_minidump_writer.rs106
-rw-r--r--third_party/rust/minidump-writer/tests/ptrace_dumper.rs21
3 files changed, 97 insertions, 97 deletions
diff --git a/third_party/rust/minidump-writer/tests/common/mod.rs b/third_party/rust/minidump-writer/tests/common/mod.rs
index bbb6abf35c..1d5497b3ba 100644
--- a/third_party/rust/minidump-writer/tests/common/mod.rs
+++ b/third_party/rust/minidump-writer/tests/common/mod.rs
@@ -8,21 +8,27 @@ type Error = Box<dyn error::Error + std::marker::Send + std::marker::Sync>;
#[allow(unused)]
pub type Result<T> = result::Result<T, Error>;
+fn build_command() -> Command {
+ let mut cmd = Command::new("cargo");
+
+ cmd.env("RUST_BACKTRACE", "1")
+ .args(["run", "-q", "--bin", "test"]);
+
+ // In normal cases where the host and target are the same this won't matter,
+ // but tests will fail if you are eg running in a cross container which will
+ // likely be x86_64 but may be targetting aarch64 or i686, which will result
+ // in tests failing, or at the least not testing what you think
+ cmd.args(["--target", current_platform::CURRENT_PLATFORM, "--"]);
+
+ cmd
+}
+
#[allow(unused)]
pub fn spawn_child(command: &str, args: &[&str]) {
- let mut cmd_object = Command::new("cargo");
- let mut cmd_ref = cmd_object
- .env("RUST_BACKTRACE", "1")
- .arg("run")
- .arg("-q")
- .arg("--bin")
- .arg("test")
- .arg("--")
- .arg(command);
- for arg in args {
- cmd_ref = cmd_ref.arg(arg);
- }
- let child = cmd_ref.output().expect("failed to execute child");
+ let mut cmd = build_command();
+ cmd.arg(command).args(args);
+
+ let child = cmd.output().expect("failed to execute child");
println!("Child output:");
std::io::stdout().write_all(&child.stdout).unwrap();
@@ -30,20 +36,12 @@ pub fn spawn_child(command: &str, args: &[&str]) {
assert_eq!(child.status.code().expect("No return value"), 0);
}
-fn start_child_and_wait_for_threads_helper(cmd: &str, num: usize) -> Child {
- let mut child = Command::new("cargo")
- .env("RUST_BACKTRACE", "1")
- .arg("run")
- .arg("-q")
- .arg("--bin")
- .arg("test")
- .arg("--")
- .arg(cmd)
- .arg(format!("{}", num))
- .stdout(Stdio::piped())
- .spawn()
- .expect("failed to execute child");
+fn start_child_and_wait_for_threads_helper(command: &str, num: usize) -> Child {
+ let mut cmd = build_command();
+ cmd.arg(command).arg(num.to_string());
+ cmd.stdout(Stdio::piped());
+ let mut child = cmd.spawn().expect("failed to spawn cargo");
wait_for_threads(&mut child, num);
child
}
@@ -84,17 +82,10 @@ pub fn wait_for_threads(child: &mut Child, num: usize) {
#[allow(unused)]
pub fn start_child_and_return(args: &[&str]) -> Child {
- let mut child = Command::new("cargo")
- .env("RUST_BACKTRACE", "1")
- .arg("run")
- .arg("-q")
- .arg("--bin")
- .arg("test")
- .arg("--")
- .args(args)
- .stdout(Stdio::piped())
- .spawn()
- .expect("failed to execute child");
+ let mut cmd = build_command();
+ cmd.args(args);
- child
+ cmd.stdout(Stdio::piped())
+ .spawn()
+ .expect("failed to execute child")
}
diff --git a/third_party/rust/minidump-writer/tests/linux_minidump_writer.rs b/third_party/rust/minidump-writer/tests/linux_minidump_writer.rs
index d9864bae13..c8458b1583 100644
--- a/third_party/rust/minidump-writer/tests/linux_minidump_writer.rs
+++ b/third_party/rust/minidump-writer/tests/linux_minidump_writer.rs
@@ -72,31 +72,31 @@ fn get_crash_context(tid: Pid) -> CrashContext {
}
}
-macro_rules! contextual_tests {
- () => {};
- ( fn $name:ident ($ctx:ident : Context) $body:block $($rest:tt)* ) => {
+macro_rules! contextual_test {
+ ( $(#[$attr:meta])? fn $name:ident ($ctx:ident : Context) $body:block ) => {
mod $name {
use super::*;
fn test($ctx: Context) $body
#[test]
- fn run() {
+ $(#[$attr])?
+ fn without_context() {
test(Context::Without)
}
#[cfg(not(target_arch = "mips"))]
#[test]
- fn run_with_context() {
+ $(#[$attr])?
+ fn with_context() {
test(Context::With)
}
}
- contextual_tests! { $($rest)* }
}
}
-contextual_tests! {
- fn test_write_dump(context: Context) {
+contextual_test! {
+ fn write_dump(context: Context) {
let num_of_threads = 3;
let mut child = start_child_and_wait_for_threads(num_of_threads);
let pid = child.id() as i32;
@@ -123,8 +123,11 @@ contextual_tests! {
assert_eq!(mem_slice.len(), in_memory_buffer.len());
assert_eq!(mem_slice, in_memory_buffer);
}
+}
- fn test_write_and_read_dump_from_parent(context: Context) {
+contextual_test! {
+ #[ignore]
+ fn write_and_read_dump_from_parent(context: Context) {
let mut child = start_child_and_return(&["spawn_mmap_wait"]);
let pid = child.id() as i32;
@@ -228,8 +231,10 @@ contextual_tests! {
.get_raw_stream(MozLinuxLimits as u32)
.expect("Couldn't find MozLinuxLimits");
}
+}
- fn test_write_with_additional_memory(context: Context) {
+contextual_test! {
+ fn write_with_additional_memory(context: Context) {
let mut child = start_child_and_return(&["spawn_alloc_wait"]);
let pid = child.id() as i32;
@@ -289,8 +294,10 @@ contextual_tests! {
// Verify memory contents.
assert_eq!(region.bytes, values);
}
+}
- fn test_skip_if_requested(context: Context) {
+contextual_test! {
+ fn skip_if_requested(context: Context) {
let num_of_threads = 1;
let mut child = start_child_and_wait_for_threads(num_of_threads);
let pid = child.id() as i32;
@@ -325,8 +332,10 @@ contextual_tests! {
assert!(res.is_err());
}
+}
- fn test_sanitized_stacks(context: Context) {
+contextual_test! {
+ fn sanitized_stacks(context: Context) {
if context == Context::With {
// FIXME the context's stack pointer very often doesn't lie in mapped memory, resulting
// in the stack memory having 0 size (so no slice will match `defaced` in the
@@ -378,8 +387,10 @@ contextual_tests! {
assert!(slice.windows(defaced.len()).any(|window| window == defaced));
}
}
+}
- fn test_write_early_abort(context: Context) {
+contextual_test! {
+ fn write_early_abort(context: Context) {
let mut child = start_child_and_return(&["spawn_alloc_wait"]);
let pid = child.id() as i32;
@@ -434,8 +445,10 @@ contextual_tests! {
// Should be missing:
assert!(dump.get_stream::<MinidumpMemoryList>().is_err());
}
+}
- fn test_named_threads(context: Context) {
+contextual_test! {
+ fn named_threads(context: Context) {
let num_of_threads = 5;
let mut child = start_child_and_wait_for_named_threads(num_of_threads);
let pid = child.id() as i32;
@@ -476,10 +489,11 @@ contextual_tests! {
expected.insert(format!("thread_{}", id));
}
assert_eq!(expected, names);
-
}
+}
- fn test_file_descriptors(context: Context) {
+contextual_test! {
+ fn file_descriptors(context: Context) {
let num_of_files = 5;
let mut child = start_child_and_wait_for_create_files(num_of_files);
let pid = child.id() as i32;
@@ -520,7 +534,7 @@ contextual_tests! {
}
#[test]
-fn test_minidump_size_limit() {
+fn minidump_size_limit() {
let num_of_threads = 40;
let mut child = start_child_and_wait_for_threads(num_of_threads);
let pid = child.id() as i32;
@@ -662,7 +676,7 @@ fn test_minidump_size_limit() {
}
#[test]
-fn test_with_deleted_binary() {
+fn with_deleted_binary() {
let num_of_threads = 1;
let binary_copy_dir = tempfile::Builder::new()
.prefix("deleted_binary")
@@ -686,36 +700,9 @@ fn test_with_deleted_binary() {
let pid = child.id() as i32;
- let build_id = PtraceDumper::elf_file_identifier_from_mapped_file(&mem_slice)
+ let mut build_id = PtraceDumper::elf_file_identifier_from_mapped_file(&mem_slice)
.expect("Failed to get build_id");
- let guid = GUID {
- data1: u32::from_ne_bytes(build_id[0..4].try_into().unwrap()),
- data2: u16::from_ne_bytes(build_id[4..6].try_into().unwrap()),
- data3: u16::from_ne_bytes(build_id[6..8].try_into().unwrap()),
- data4: build_id[8..16].try_into().unwrap(),
- };
-
- // guid_to_string() is not public in minidump, so copied it here
- // And append a zero, because module IDs include an "age" field
- // which is always zero on Linux.
- let filtered = format!(
- "{:08X}{:04X}{:04X}{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}0",
- guid.data1,
- guid.data2,
- guid.data3,
- guid.data4[0],
- guid.data4[1],
- guid.data4[2],
- guid.data4[3],
- guid.data4[4],
- guid.data4[5],
- guid.data4[6],
- guid.data4[7],
- );
- // Strip out dashes
- //let mut filtered: String = identifier.chars().filter(|x| *x != '-').collect();
-
std::fs::remove_file(&binary_copy).expect("Failed to remove binary");
let mut tmpfile = tempfile::Builder::new()
@@ -747,11 +734,34 @@ fn test_with_deleted_binary() {
.main_module()
.expect("Could not get main module");
assert_eq!(main_module.code_file(), binary_copy.to_string_lossy());
- assert_eq!(main_module.debug_identifier(), filtered.parse().ok());
+
+ let did = main_module
+ .debug_identifier()
+ .expect("expected value debug id");
+ {
+ let uuid = did.uuid();
+ let uuid = uuid.as_bytes();
+
+ // Swap bytes in the original to match the expected uuid
+ if cfg!(target_endian = "little") {
+ build_id[..4].reverse();
+ build_id[4..6].reverse();
+ build_id[6..8].reverse();
+ }
+
+ // The build_id from the binary can be as little as 8 bytes, eg LLD uses
+ // xxhash to calculate the build_id by default from 10+
+ build_id.resize(16, 0);
+
+ assert_eq!(uuid.as_slice(), &build_id);
+ }
+
+ // The 'age'/appendix, always 0 on non-windows targets
+ assert_eq!(did.appendix(), 0);
}
#[test]
-fn test_memory_info_list_stream() {
+fn memory_info_list_stream() {
let mut child = start_child_and_wait_for_threads(1);
let pid = child.id() as i32;
diff --git a/third_party/rust/minidump-writer/tests/ptrace_dumper.rs b/third_party/rust/minidump-writer/tests/ptrace_dumper.rs
index 1be27f0809..6b62a4f6f3 100644
--- a/third_party/rust/minidump-writer/tests/ptrace_dumper.rs
+++ b/third_party/rust/minidump-writer/tests/ptrace_dumper.rs
@@ -7,7 +7,6 @@ use nix::sys::signal::Signal;
use std::convert::TryInto;
use std::io::{BufRead, BufReader};
use std::mem::size_of;
-use std::os::unix::io::AsFd;
use std::os::unix::process::ExitStatusExt;
mod common;
@@ -29,7 +28,8 @@ fn test_thread_list_from_parent() {
let num_of_threads = 5;
let mut child = start_child_and_wait_for_threads(num_of_threads);
let pid = child.id() as i32;
- let mut dumper = PtraceDumper::new(pid).expect("Couldn't init dumper");
+ let mut dumper = PtraceDumper::new(pid, minidump_writer::minidump_writer::STOP_TIMEOUT)
+ .expect("Couldn't init dumper");
assert_eq!(dumper.threads.len(), num_of_threads);
dumper.suspend_threads().expect("Could not suspend threads");
@@ -129,20 +129,22 @@ fn test_merged_mappings() {
map_size,
ProtFlags::PROT_READ,
MapFlags::MAP_SHARED,
- Some(file.as_fd()),
+ &file,
0,
)
.unwrap()
};
+ let mapped = mapped_mem.as_ptr() as usize;
+
// Carve a page out of the first mapping with different permissions.
let _inside_mapping = unsafe {
mmap(
- std::num::NonZeroUsize::new(mapped_mem as usize + 2 * page_size.get()),
+ std::num::NonZeroUsize::new(mapped + 2 * page_size.get()),
page_size,
ProtFlags::PROT_NONE,
MapFlags::MAP_SHARED | MapFlags::MAP_FIXED,
- Some(file.as_fd()),
+ &file,
// Map a different offset just to
// better test real-world conditions.
page_size.get().try_into().unwrap(), // try_into() in order to work for 32 and 64 bit
@@ -151,11 +153,7 @@ fn test_merged_mappings() {
spawn_child(
"merged_mappings",
- &[
- path,
- &format!("{}", mapped_mem as usize),
- &format!("{map_size}"),
- ],
+ &[path, &format!("{mapped}"), &format!("{map_size}")],
);
}
@@ -209,7 +207,8 @@ fn test_sanitize_stack_copy() {
let heap_addr = usize::from_str_radix(output.next().unwrap().trim_start_matches("0x"), 16)
.expect("unable to parse mmap_addr");
- let mut dumper = PtraceDumper::new(pid).expect("Couldn't init dumper");
+ let mut dumper = PtraceDumper::new(pid, minidump_writer::minidump_writer::STOP_TIMEOUT)
+ .expect("Couldn't init dumper");
assert_eq!(dumper.threads.len(), num_of_threads);
dumper.suspend_threads().expect("Could not suspend threads");
let thread_info = dumper