/src/test/run-pass/backtrace.rs

https://github.com/avr-rust/rust · Rust · 123 lines · 88 code · 15 blank · 20 comment · 15 complexity · dd37df6d2fe8dd316d89d09d2e5196bc MD5 · raw file

  1. // ignore-android FIXME #17520
  2. // ignore-cloudabi spawning processes is not supported
  3. // ignore-emscripten spawning processes is not supported
  4. // ignore-openbsd no support for libbacktrace without filename
  5. // ignore-sgx no processes
  6. // compile-flags:-g
  7. use std::env;
  8. use std::process::{Command, Stdio};
  9. use std::str;
  10. #[inline(never)]
  11. fn foo() {
  12. let _v = vec![1, 2, 3];
  13. if env::var_os("IS_TEST").is_some() {
  14. panic!()
  15. }
  16. }
  17. #[inline(never)]
  18. fn double() {
  19. struct Double;
  20. impl Drop for Double {
  21. fn drop(&mut self) { panic!("twice") }
  22. }
  23. let _d = Double;
  24. panic!("once");
  25. }
  26. fn template(me: &str) -> Command {
  27. let mut m = Command::new(me);
  28. m.env("IS_TEST", "1")
  29. .stdout(Stdio::piped())
  30. .stderr(Stdio::piped());
  31. return m;
  32. }
  33. fn expected(fn_name: &str) -> String {
  34. format!(" backtrace::{}", fn_name)
  35. }
  36. fn contains_verbose_expected(s: &str, fn_name: &str) -> bool {
  37. // HACK(eddyb) work around the fact that verbosely demangled stack traces
  38. // (from `RUST_BACKTRACE=full`, or, as is the case here, panic-in-panic)
  39. // may contain symbols with hashes in them, i.e. `backtrace[...]::`.
  40. let prefix = " backtrace";
  41. let suffix = &format!("::{}", fn_name);
  42. s.match_indices(prefix).any(|(i, _)| {
  43. s[i + prefix.len()..]
  44. .trim_start_matches('[')
  45. .trim_start_matches(char::is_alphanumeric)
  46. .trim_start_matches(']')
  47. .starts_with(suffix)
  48. })
  49. }
  50. fn runtest(me: &str) {
  51. // Make sure that the stack trace is printed
  52. let p = template(me).arg("fail").env("RUST_BACKTRACE", "1").spawn().unwrap();
  53. let out = p.wait_with_output().unwrap();
  54. assert!(!out.status.success());
  55. let s = str::from_utf8(&out.stderr).unwrap();
  56. assert!(s.contains("stack backtrace") && s.contains(&expected("foo")),
  57. "bad output: {}", s);
  58. assert!(s.contains(" 0:"), "the frame number should start at 0");
  59. // Make sure the stack trace is *not* printed
  60. // (Remove RUST_BACKTRACE from our own environment, in case developer
  61. // is running `make check` with it on.)
  62. let p = template(me).arg("fail").env_remove("RUST_BACKTRACE").spawn().unwrap();
  63. let out = p.wait_with_output().unwrap();
  64. assert!(!out.status.success());
  65. let s = str::from_utf8(&out.stderr).unwrap();
  66. assert!(!s.contains("stack backtrace") && !s.contains(&expected("foo")),
  67. "bad output2: {}", s);
  68. // Make sure the stack trace is *not* printed
  69. // (RUST_BACKTRACE=0 acts as if it were unset from our own environment,
  70. // in case developer is running `make check` with it set.)
  71. let p = template(me).arg("fail").env("RUST_BACKTRACE","0").spawn().unwrap();
  72. let out = p.wait_with_output().unwrap();
  73. assert!(!out.status.success());
  74. let s = str::from_utf8(&out.stderr).unwrap();
  75. assert!(!s.contains("stack backtrace") && !s.contains(" - foo"),
  76. "bad output3: {}", s);
  77. // Make sure a stack trace is printed
  78. let p = template(me).arg("double-fail").spawn().unwrap();
  79. let out = p.wait_with_output().unwrap();
  80. assert!(!out.status.success());
  81. let s = str::from_utf8(&out.stderr).unwrap();
  82. // loosened the following from double::h to double:: due to
  83. // spurious failures on mac, 32bit, optimized
  84. assert!(s.contains("stack backtrace") && contains_verbose_expected(s, "double"),
  85. "bad output3: {}", s);
  86. // Make sure a stack trace isn't printed too many times
  87. let p = template(me).arg("double-fail")
  88. .env("RUST_BACKTRACE", "1").spawn().unwrap();
  89. let out = p.wait_with_output().unwrap();
  90. assert!(!out.status.success());
  91. let s = str::from_utf8(&out.stderr).unwrap();
  92. let mut i = 0;
  93. for _ in 0..2 {
  94. i += s[i + 10..].find("stack backtrace").unwrap() + 10;
  95. }
  96. assert!(s[i + 10..].find("stack backtrace").is_none(),
  97. "bad output4: {}", s);
  98. }
  99. fn main() {
  100. let args: Vec<String> = env::args().collect();
  101. if args.len() >= 2 && args[1] == "fail" {
  102. foo();
  103. } else if args.len() >= 2 && args[1] == "double-fail" {
  104. double();
  105. } else {
  106. runtest(&args[0]);
  107. }
  108. }