Skip to content

Commit cd47892

Browse files
committed
Add unit tests + fix integration tests
1 parent df85e55 commit cd47892

File tree

4 files changed

+106
-30
lines changed

4 files changed

+106
-30
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bin_tests/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ libc = "0.2"
2323
nix = { version = "0.29", features = ["signal", "socket"] }
2424
hex = "0.4"
2525
os_info = "3.7.0"
26+
regex = "1.0"
2627

2728
[dev-dependencies]
2829
serial_test = "3.2"

bin_tests/tests/crashtracker_bin_test.rs

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -360,17 +360,18 @@ fn test_crash_tracking_app(crash_type: &str) {
360360
#[cfg_attr(miri, ignore)]
361361
#[cfg(not(target_os = "macos"))] // Same restriction as other panic tests
362362
fn test_crash_tracking_bin_panic_hook_after_fork() {
363-
test_panic_hook_mode("panic_hook_after_fork", "child panicked after fork");
363+
test_panic_hook_mode(
364+
"panic_hook_after_fork",
365+
"message",
366+
Some("child panicked after fork"),
367+
);
364368
}
365369

366370
#[test]
367371
#[cfg_attr(miri, ignore)]
368372
#[cfg(not(target_os = "macos"))] // Same restriction as other panic tests
369373
fn test_crash_tracking_bin_panic_hook_string() {
370-
test_panic_hook_mode(
371-
"panic_hook_string",
372-
"Process panicked with message: Panic with value: 42",
373-
);
374+
test_panic_hook_mode("panic_hook_string", "message", Some("Panic with value: 42"));
374375
}
375376

376377
#[test]
@@ -379,12 +380,14 @@ fn test_crash_tracking_bin_panic_hook_string() {
379380
fn test_crash_tracking_bin_panic_hook_unknown_type() {
380381
test_panic_hook_mode(
381382
"panic_hook_unknown_type",
382-
"Process panicked with unknown type",
383+
"unknown type",
384+
None, // no panic message for unknown type
383385
);
384386
}
385387

386-
/// Helper function to run panic hook tests with different payload types
387-
fn test_panic_hook_mode(mode: &str, expected_message_substring: &str) {
388+
/// Helper function to run panic hook tests with different payload types.
389+
/// Note: Since tests are built with Debug profile, location is always expected.
390+
fn test_panic_hook_mode(mode: &str, expected_category: &str, expected_panic_message: Option<&str>) {
388391
use bin_tests::test_runner::run_custom_crash_test;
389392

390393
// Set up custom artifacts: receiver + crashtracker_bin_test
@@ -393,15 +396,38 @@ fn test_panic_hook_mode(mode: &str, expected_message_substring: &str) {
393396

394397
let artifacts_map = build_artifacts(&[&crashtracker_receiver, &crashtracker_bin_test]).unwrap();
395398

396-
let expected_msg = expected_message_substring.to_owned();
399+
let expected_category = expected_category.to_owned();
400+
let expected_panic_message = expected_panic_message.map(|s| s.to_owned());
397401
let validator: ValidatorFn = Box::new(move |payload, _fixtures| {
398402
// Verify the panic message is captured
399403
let error = &payload["error"];
400404
let message = error["message"].as_str().unwrap();
405+
406+
// Check the message starts with "Process panicked with <category>"
407+
let expected_prefix = format!("Process panicked with {}", expected_category);
408+
assert!(
409+
message.starts_with(&expected_prefix),
410+
"Expected panic message to start with '{}', got: {}",
411+
expected_prefix,
412+
message
413+
);
414+
415+
// Check the panic message if expected (the message passed to panic! macro)
416+
if let Some(ref panic_msg) = expected_panic_message {
417+
assert!(
418+
message.contains(panic_msg),
419+
"Expected panic message to contain '{}', got: {}",
420+
panic_msg,
421+
message
422+
);
423+
}
424+
425+
// Check for location format (file:line:column) - always present in Debug builds
426+
// Location should end with pattern like " (path/file.rs:123:45)"
427+
let location_regex = regex::Regex::new(r" \(.+?:\d+:\d+\)$").unwrap();
401428
assert!(
402-
message.contains(&expected_msg),
403-
"Expected panic message to contain '{}', got: {}",
404-
expected_msg,
429+
location_regex.is_match(message),
430+
"Expected panic message to end with location ' (file:line:column)', got: {}",
405431
message
406432
);
407433

libdd-crashtracker/src/collector/crash_handler.rs

Lines changed: 66 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -79,26 +79,20 @@ pub fn update_metadata(metadata: Metadata) -> anyhow::Result<()> {
7979
}
8080

8181
/// Format a panic message with optional location information.
82-
fn format_panic_message(
82+
fn format_message(
8383
category: &str,
84-
description: &str,
84+
panic_message: &str,
8585
location: Option<&panic::Location>,
8686
) -> String {
87-
let base = match location {
88-
Some(loc) => format!(
89-
"Process panicked with {} ({}:{}:{})",
90-
category,
91-
loc.file(),
92-
loc.line(),
93-
loc.column()
94-
),
95-
None => format!("Process panicked with {}", category),
87+
let base = if panic_message.is_empty() {
88+
format!("Process panicked with {}", category)
89+
} else {
90+
format!("Process panicked with {} \"{}\"", category, panic_message)
9691
};
9792

98-
if description.is_empty() {
99-
base
100-
} else {
101-
format!("{}: {}", base, description)
93+
match location {
94+
Some(loc) => format!("{} ({}:{}:{})", base, loc.file(), loc.line(), loc.column()),
95+
None => base,
10296
}
10397
}
10498

@@ -124,12 +118,12 @@ pub fn register_panic_hook() -> anyhow::Result<()> {
124118
panic::set_hook(Box::new(|panic_info| {
125119
// Extract panic message from payload (supports &str and String)
126120
let message = if let Some(&s) = panic_info.payload().downcast_ref::<&str>() {
127-
format_panic_message("message", s, panic_info.location())
121+
format_message("message", s, panic_info.location())
128122
} else if let Some(s) = panic_info.payload().downcast_ref::<String>() {
129-
format_panic_message("message", s.as_str(), panic_info.location())
123+
format_message("message", s.as_str(), panic_info.location())
130124
} else {
131125
// For non-string types, use a generic message
132-
format_panic_message("unknown type", "", panic_info.location())
126+
format_message("unknown type", "", panic_info.location())
133127
};
134128

135129
// Store the message, cleaning up any old message
@@ -394,4 +388,58 @@ mod tests {
394388
assert_eq!(stored_metadata.library_name, "test");
395389
}
396390
}
391+
392+
#[test]
393+
fn test_format_message_with_message_and_location() {
394+
let location = panic::Location::caller();
395+
let result = format_message("message", "test panic", Some(location));
396+
397+
assert!(result.starts_with("Process panicked with message \"test panic\" ("));
398+
assert!(result.contains(&format!("{}:", location.file())));
399+
assert!(result.contains(&format!(":{}", location.line())));
400+
assert!(result.ends_with(&format!("{})", location.column())));
401+
}
402+
403+
#[test]
404+
fn test_format_message_with_message_no_location() {
405+
let result = format_message("message", "test panic", None);
406+
assert_eq!(result, "Process panicked with message \"test panic\"");
407+
}
408+
409+
#[test]
410+
fn test_format_message_empty_message_with_location() {
411+
let location = panic::Location::caller();
412+
let result = format_message("unknown type", "", Some(location));
413+
414+
assert!(result.starts_with("Process panicked with unknown type ("));
415+
assert!(result.contains(&format!("{}:", location.file())));
416+
assert!(result.ends_with(&format!("{})", location.column())));
417+
}
418+
419+
#[test]
420+
fn test_format_message_empty_message_no_location() {
421+
let result = format_message("unknown type", "", None);
422+
assert_eq!(result, "Process panicked with unknown type");
423+
}
424+
425+
#[test]
426+
fn test_format_message_different_categories() {
427+
let result1 = format_message("message", "test", None);
428+
assert_eq!(result1, "Process panicked with message \"test\"");
429+
430+
let result2 = format_message("unknown type", "", None);
431+
assert_eq!(result2, "Process panicked with unknown type");
432+
433+
let result3 = format_message("custom category", "content", None);
434+
assert_eq!(result3, "Process panicked with custom category \"content\"");
435+
}
436+
437+
#[test]
438+
fn test_format_message_with_special_characters() {
439+
let result = format_message("message", "test \"quoted\" 'text'", None);
440+
assert_eq!(
441+
result,
442+
"Process panicked with message \"test \"quoted\" 'text'\""
443+
);
444+
}
397445
}

0 commit comments

Comments
 (0)