}
}
+// Used by panicking::default_hook
+#[cfg(test)]
+/// This impl is only used by printing logic, so any error returned is always
+/// of kind `Other`, and should be ignored.
+impl Write for Box<dyn (::realstd::io::Write) + Send> {
+ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+ (**self).write(buf).map_err(|_| ErrorKind::Other.into())
+ }
+
+ fn flush(&mut self) -> io::Result<()> {
+ (**self).flush().map_err(|_| ErrorKind::Other.into())
+ }
+}
+
// =============================================================================
// In-memory buffer implementations
+#![cfg_attr(test, allow(unused))]
+
use crate::io::prelude::*;
use crate::cell::RefCell;
}
}
+/// Stderr used by eprint! and eprintln! macros, and panics
+thread_local! {
+ static LOCAL_STDERR: RefCell<Option<Box<dyn Write + Send>>> = {
+ RefCell::new(None)
+ }
+}
+
/// A handle to a raw instance of the standard input stream of this process.
///
/// This handle is not synchronized or buffered in any fashion. Constructed via
issue = "0")]
#[doc(hidden)]
pub fn set_panic(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write + Send>> {
- use crate::panicking::LOCAL_STDERR;
use crate::mem;
LOCAL_STDERR.with(move |slot| {
mem::replace(&mut *slot.borrow_mut(), sink)
reason = "implementation detail which may disappear or be replaced at any time",
issue = "0")]
#[doc(hidden)]
+#[cfg(not(test))]
pub fn _print(args: fmt::Arguments) {
print_to(args, &LOCAL_STDOUT, stdout, "stdout");
}
reason = "implementation detail which may disappear or be replaced at any time",
issue = "0")]
#[doc(hidden)]
+#[cfg(not(test))]
pub fn _eprint(args: fmt::Arguments) {
- use crate::panicking::LOCAL_STDERR;
print_to(args, &LOCAL_STDERR, stderr, "stderr");
}
+#[cfg(test)]
+pub use realstd::io::{_eprint, _print};
+
#[cfg(test)]
mod tests {
use crate::panic::{UnwindSafe, RefUnwindSafe};
// std may use features in a platform-specific way
#![allow(unused_features)]
-#![cfg_attr(test, feature(test, update_panic_count))]
+#![cfg_attr(test, feature(print_internals, set_stdio, test, update_panic_count))]
#![cfg_attr(all(target_vendor = "fortanix", target_env = "sgx"),
feature(global_asm, range_contains, slice_index_methods,
decl_macro, coerce_unsized, sgx_platform, ptr_wrapping_offset_from))]
//! * Executing a panic up to doing the actual implementation
//! * Shims around "try"
-use core::panic::BoxMeUp;
-use core::panic::{PanicInfo, Location};
-
-use crate::io::prelude::*;
+use core::panic::{BoxMeUp, PanicInfo, Location};
use crate::any::Any;
-use crate::cell::RefCell;
use crate::fmt;
use crate::intrinsics;
use crate::mem;
use crate::sys_common::util;
use crate::thread;
-thread_local! {
- pub static LOCAL_STDERR: RefCell<Option<Box<dyn Write + Send>>> = {
- RefCell::new(None)
- }
-}
+#[cfg(not(test))]
+use crate::io::set_panic;
+// make sure to use the stderr output configured
+// by libtest in the real copy of std
+#[cfg(test)]
+use realstd::io::set_panic;
// Binary interface to the panic runtime that the standard library depends on.
//
}
};
- if let Some(mut local) = LOCAL_STDERR.with(|s| s.borrow_mut().take()) {
- write(&mut *local);
- let mut s = Some(local);
- LOCAL_STDERR.with(|slot| {
- *slot.borrow_mut() = s.take();
- });
+ if let Some(mut local) = set_panic(None) {
+ // NB. In `cfg(test)` this uses the forwarding impl
+ // for `Box<dyn (::realstd::io::Write) + Send>`.
+ write(&mut local);
+ set_panic(Some(local));
} else if let Some(mut out) = panic_output() {
write(&mut out);
}