rust/library/core/tests/result.rs

428 lines
12 KiB
Rust
Raw Normal View History

use core::ops::DerefMut;
2019-12-22 16:42:04 -06:00
use core::option::*;
2019-12-22 16:42:04 -06:00
fn op1() -> Result<isize, &'static str> {
Ok(666)
}
fn op2() -> Result<isize, &'static str> {
Err("sadface")
}
#[test]
2015-04-28 23:22:58 -05:00
fn test_and() {
2015-01-25 15:05:03 -06:00
assert_eq!(op1().and(Ok(667)).unwrap(), 667);
2019-12-22 16:42:04 -06:00
assert_eq!(op1().and(Err::<i32, &'static str>("bad")).unwrap_err(), "bad");
2015-01-25 15:05:03 -06:00
assert_eq!(op2().and(Ok(667)).unwrap_err(), "sadface");
2019-12-22 16:42:04 -06:00
assert_eq!(op2().and(Err::<i32, &'static str>("bad")).unwrap_err(), "sadface");
}
#[test]
2015-04-28 23:22:58 -05:00
fn test_and_then() {
assert_eq!(op1().and_then(|i| Ok::<isize, &'static str>(i + 1)).unwrap(), 667);
2019-12-22 16:42:04 -06:00
assert_eq!(op1().and_then(|_| Err::<isize, &'static str>("bad")).unwrap_err(), "bad");
2019-12-22 16:42:04 -06:00
assert_eq!(op2().and_then(|i| Ok::<isize, &'static str>(i + 1)).unwrap_err(), "sadface");
assert_eq!(op2().and_then(|_| Err::<isize, &'static str>("bad")).unwrap_err(), "sadface");
}
#[test]
2015-04-28 23:22:58 -05:00
fn test_or() {
assert_eq!(op1().or(Ok::<_, &'static str>(667)).unwrap(), 666);
assert_eq!(op1().or(Err("bad")).unwrap(), 666);
assert_eq!(op2().or(Ok::<_, &'static str>(667)).unwrap(), 667);
assert_eq!(op2().or(Err("bad")).unwrap_err(), "bad");
}
#[test]
2015-04-28 23:22:58 -05:00
fn test_or_else() {
assert_eq!(op1().or_else(|_| Ok::<isize, &'static str>(667)).unwrap(), 666);
assert_eq!(op1().or_else(|e| Err::<isize, &'static str>(e)).unwrap(), 666);
assert_eq!(op2().or_else(|_| Ok::<isize, &'static str>(667)).unwrap(), 667);
2019-12-22 16:42:04 -06:00
assert_eq!(op2().or_else(|e| Err::<isize, &'static str>(e)).unwrap_err(), "sadface");
}
#[test]
2015-04-28 23:22:58 -05:00
fn test_impl_map() {
assert!(Ok::<isize, isize>(1).map(|x| x + 1) == Ok(2));
assert!(Err::<isize, isize>(1).map(|x| x + 1) == Err(1));
}
#[test]
2015-04-28 23:22:58 -05:00
fn test_impl_map_err() {
assert!(Ok::<isize, isize>(1).map_err(|x| x + 1) == Ok(1));
assert!(Err::<isize, isize>(1).map_err(|x| x + 1) == Err(2));
}
#[test]
fn test_collect() {
let v: Result<Vec<isize>, ()> = (0..0).map(|_| Ok::<isize, ()>(0)).collect();
assert!(v == Ok(vec![]));
let v: Result<Vec<isize>, ()> = (0..3).map(|x| Ok::<isize, ()>(x)).collect();
assert!(v == Ok(vec![0, 1, 2]));
2019-12-22 16:42:04 -06:00
let v: Result<Vec<isize>, isize> = (0..3).map(|x| if x > 1 { Err(x) } else { Ok(x) }).collect();
assert!(v == Err(2));
// test that it does not take more elements than it needs
2018-07-13 00:25:22 -05:00
let mut functions: [Box<dyn Fn() -> Result<(), isize>>; 3] =
2015-01-25 15:05:03 -06:00
[box || Ok(()), box || Err(1), box || panic!()];
let v: Result<Vec<()>, isize> = functions.iter_mut().map(|f| (*f)()).collect();
assert!(v == Err(1));
}
#[test]
2015-04-28 23:22:58 -05:00
fn test_fmt_default() {
let ok: Result<isize, &'static str> = Ok(100);
let err: Result<isize, &'static str> = Err("Err");
let s = format!("{ok:?}");
std: Rename Show/String to Debug/Display This commit is an implementation of [RFC 565][rfc] which is a stabilization of the `std::fmt` module and the implementations of various formatting traits. Specifically, the following changes were performed: [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0565-show-string-guidelines.md * The `Show` trait is now deprecated, it was renamed to `Debug` * The `String` trait is now deprecated, it was renamed to `Display` * Many `Debug` and `Display` implementations were audited in accordance with the RFC and audited implementations now have the `#[stable]` attribute * Integers and floats no longer print a suffix * Smart pointers no longer print details that they are a smart pointer * Paths with `Debug` are now quoted and escape characters * The `unwrap` methods on `Result` now require `Display` instead of `Debug` * The `Error` trait no longer has a `detail` method and now requires that `Display` must be implemented. With the loss of `String`, this has moved into libcore. * `impl<E: Error> FromError<E> for Box<Error>` now exists * `derive(Show)` has been renamed to `derive(Debug)`. This is not currently warned about due to warnings being emitted on stage1+ While backwards compatibility is attempted to be maintained with a blanket implementation of `Display` for the old `String` trait (and the same for `Show`/`Debug`) this is still a breaking change due to primitives no longer implementing `String` as well as modifications such as `unwrap` and the `Error` trait. Most code is fairly straightforward to update with a rename or tweaks of method calls. [breaking-change] Closes #21436
2015-01-20 17:45:07 -06:00
assert_eq!(s, "Ok(100)");
let s = format!("{err:?}");
assert_eq!(s, "Err(\"Err\")");
}
#[test]
2015-04-28 23:22:58 -05:00
fn test_unwrap_or() {
let ok: Result<isize, &'static str> = Ok(100);
let ok_err: Result<isize, &'static str> = Err("Err");
assert_eq!(ok.unwrap_or(50), 100);
assert_eq!(ok_err.unwrap_or(50), 50);
}
#[test]
fn test_ok_or_err() {
let ok: Result<isize, isize> = Ok(100);
let err: Result<isize, isize> = Err(200);
assert_eq!(ok.into_ok_or_err(), 100);
assert_eq!(err.into_ok_or_err(), 200);
}
#[test]
2015-04-28 23:22:58 -05:00
fn test_unwrap_or_else() {
fn handler(msg: &'static str) -> isize {
2019-12-22 16:42:04 -06:00
if msg == "I got this." { 50 } else { panic!("BadBad") }
}
let ok: Result<isize, &'static str> = Ok(100);
let ok_err: Result<isize, &'static str> = Err("I got this.");
assert_eq!(ok.unwrap_or_else(handler), 100);
assert_eq!(ok_err.unwrap_or_else(handler), 50);
}
#[test]
#[should_panic]
pub fn test_unwrap_or_else_panic() {
fn handler(msg: &'static str) -> isize {
2019-12-22 16:42:04 -06:00
if msg == "I got this." { 50 } else { panic!("BadBad") }
}
let bad_err: Result<isize, &'static str> = Err("Unrecoverable mess.");
2019-12-22 16:42:04 -06:00
let _: isize = bad_err.unwrap_or_else(handler);
}
#[test]
fn test_unwrap_unchecked() {
let ok: Result<isize, &'static str> = Ok(100);
assert_eq!(unsafe { ok.unwrap_unchecked() }, 100);
}
#[test]
fn test_unwrap_err_unchecked() {
let ok_err: Result<isize, &'static str> = Err("Err");
assert_eq!(unsafe { ok_err.unwrap_err_unchecked() }, "Err");
}
#[test]
pub fn test_expect_ok() {
let ok: Result<isize, &'static str> = Ok(100);
assert_eq!(ok.expect("Unexpected error"), 100);
}
#[test]
2019-12-22 16:42:04 -06:00
#[should_panic(expected = "Got expected error: \"All good\"")]
pub fn test_expect_err() {
let err: Result<isize, &'static str> = Err("All good");
err.expect("Got expected error");
}
2017-01-10 21:17:47 -06:00
#[test]
pub fn test_expect_err_err() {
let ok: Result<&'static str, isize> = Err(100);
assert_eq!(ok.expect_err("Unexpected ok"), 100);
}
#[test]
2019-12-22 16:42:04 -06:00
#[should_panic(expected = "Got expected ok: \"All good\"")]
2017-01-10 21:17:47 -06:00
pub fn test_expect_err_ok() {
let err: Result<&'static str, isize> = Ok("All good");
err.expect_err("Got expected ok");
}
#[test]
pub fn test_iter() {
let ok: Result<isize, &'static str> = Ok(100);
let mut it = ok.iter();
assert_eq!(it.size_hint(), (1, Some(1)));
assert_eq!(it.next(), Some(&100));
assert_eq!(it.size_hint(), (0, Some(0)));
assert!(it.next().is_none());
assert_eq!((&ok).into_iter().next(), Some(&100));
let err: Result<isize, &'static str> = Err("error");
assert_eq!(err.iter().next(), None);
}
#[test]
pub fn test_iter_mut() {
let mut ok: Result<isize, &'static str> = Ok(100);
for loc in ok.iter_mut() {
*loc = 200;
}
assert_eq!(ok, Ok(200));
for loc in &mut ok {
*loc = 300;
}
assert_eq!(ok, Ok(300));
let mut err: Result<isize, &'static str> = Err("error");
for loc in err.iter_mut() {
*loc = 200;
}
assert_eq!(err, Err("error"));
}
#[test]
pub fn test_unwrap_or_default() {
assert_eq!(op1().unwrap_or_default(), 666);
assert_eq!(op2().unwrap_or_default(), 0);
}
#[test]
pub fn test_into_ok() {
fn infallible_op() -> Result<isize, !> {
Ok(666)
}
assert_eq!(infallible_op().into_ok(), 666);
enum MyNeverToken {}
impl From<MyNeverToken> for ! {
fn from(never: MyNeverToken) -> ! {
match never {}
}
}
fn infallible_op2() -> Result<isize, MyNeverToken> {
Ok(667)
}
assert_eq!(infallible_op2().into_ok(), 667);
}
2021-03-23 15:27:38 -05:00
#[test]
pub fn test_into_err() {
fn until_error_op() -> Result<!, isize> {
Err(666)
}
assert_eq!(until_error_op().into_err(), 666);
enum MyNeverToken {}
impl From<MyNeverToken> for ! {
fn from(never: MyNeverToken) -> ! {
match never {}
}
}
fn until_error_op2() -> Result<MyNeverToken, isize> {
Err(667)
}
assert_eq!(until_error_op2().into_err(), 667);
}
#[test]
fn test_try() {
2021-04-15 03:13:39 -05:00
fn try_result_ok() -> Result<u8, u32> {
2018-05-20 13:52:08 -05:00
let result: Result<u8, u8> = Ok(1);
let val = result?;
Ok(val)
}
assert_eq!(try_result_ok(), Ok(1));
2021-04-15 03:13:39 -05:00
fn try_result_err() -> Result<u8, u32> {
2018-05-20 13:52:08 -05:00
let result: Result<u8, u8> = Err(1);
let val = result?;
Ok(val)
}
assert_eq!(try_result_err(), Err(1));
}
#[test]
fn test_result_as_deref() {
// &Result<T: Deref, E>::Ok(T).as_deref() ->
2018-04-30 14:51:43 -05:00
// Result<&T::Deref::Target, &E>::Ok(&*T)
let ref_ok = &Result::Ok::<&i32, u8>(&42);
let expected_result = Result::Ok::<&i32, &u8>(&42);
assert_eq!(ref_ok.as_deref(), expected_result);
2018-04-30 14:51:43 -05:00
let ref_ok = &Result::Ok::<String, u32>(String::from("a result"));
2018-04-30 14:51:43 -05:00
let expected_result = Result::Ok::<&str, &u32>("a result");
assert_eq!(ref_ok.as_deref(), expected_result);
2018-04-30 14:51:43 -05:00
let ref_ok = &Result::Ok::<Vec<i32>, u32>(vec![1, 2, 3, 4, 5]);
let expected_result = Result::Ok::<&[i32], &u32>([1, 2, 3, 4, 5].as_slice());
assert_eq!(ref_ok.as_deref(), expected_result);
2018-04-30 14:51:43 -05:00
2020-07-30 21:44:29 -05:00
// &Result<T: Deref, E>::Err(T).as_deref() ->
// Result<&T::Deref::Target, &E>::Err(&*E)
let val = 41;
let ref_err = &Result::Err::<&u8, i32>(val);
let expected_result = Result::Err::<&u8, &i32>(&val);
assert_eq!(ref_err.as_deref(), expected_result);
2018-04-30 14:51:43 -05:00
let s = String::from("an error");
let ref_err = &Result::Err::<&u32, String>(s.clone());
let expected_result = Result::Err::<&u32, &String>(&s);
assert_eq!(ref_err.as_deref(), expected_result);
2018-04-30 14:51:43 -05:00
let v = vec![5, 4, 3, 2, 1];
let ref_err = &Result::Err::<&u32, Vec<i32>>(v.clone());
let expected_result = Result::Err::<&u32, &Vec<i32>>(&v);
assert_eq!(ref_err.as_deref(), expected_result);
}
#[test]
fn test_result_as_deref_mut() {
2020-07-30 21:44:29 -05:00
// &mut Result<T: DerefMut, E>::Ok(T).as_deref_mut() ->
// Result<&mut T::DerefMut::Target, &mut E>::Ok(&mut *T)
let mut val = 42;
let mut expected_val = 42;
let mut_ok = &mut Result::Ok::<&mut i32, u8>(&mut val);
let expected_result = Result::Ok::<&mut i32, &mut u8>(&mut expected_val);
assert_eq!(mut_ok.as_deref_mut(), expected_result);
let mut expected_string = String::from("a result");
let mut_ok = &mut Result::Ok::<String, u32>(expected_string.clone());
let expected_result = Result::Ok::<&mut str, &mut u32>(expected_string.deref_mut());
assert_eq!(mut_ok.as_deref_mut(), expected_result);
let mut expected_vec = vec![1, 2, 3, 4, 5];
let mut_ok = &mut Result::Ok::<Vec<i32>, u32>(expected_vec.clone());
let expected_result = Result::Ok::<&mut [i32], &mut u32>(expected_vec.as_mut_slice());
assert_eq!(mut_ok.as_deref_mut(), expected_result);
2020-07-30 21:44:29 -05:00
// &mut Result<T: DerefMut, E>::Err(T).as_deref_mut() ->
// Result<&mut T, &mut E>::Err(&mut *E)
let mut val = 41;
let mut_err = &mut Result::Err::<&mut u8, i32>(val);
let expected_result = Result::Err::<&mut u8, &mut i32>(&mut val);
assert_eq!(mut_err.as_deref_mut(), expected_result);
let mut expected_string = String::from("an error");
let mut_err = &mut Result::Err::<&mut u32, String>(expected_string.clone());
let expected_result = Result::Err::<&mut u32, &mut String>(&mut expected_string);
assert_eq!(mut_err.as_deref_mut(), expected_result);
let mut expected_vec = vec![5, 4, 3, 2, 1];
let mut_err = &mut Result::Err::<&mut u32, Vec<i32>>(expected_vec.clone());
let expected_result = Result::Err::<&mut u32, &mut Vec<i32>>(&mut expected_vec);
assert_eq!(mut_err.as_deref_mut(), expected_result);
}
#[test]
fn result_const() {
// test that the methods of `Result` are usable in a const context
const RESULT: Result<usize, bool> = Ok(32);
const REF: Result<&usize, &bool> = RESULT.as_ref();
assert_eq!(REF, Ok(&32));
const IS_OK: bool = RESULT.is_ok();
assert!(IS_OK);
const IS_ERR: bool = RESULT.is_err();
assert!(!IS_ERR)
}
2021-10-16 11:18:00 -05:00
#[test]
const fn result_const_mut() {
let mut result: Result<usize, bool> = Ok(32);
{
let as_mut = result.as_mut();
match as_mut {
Ok(v) => *v = 42,
Err(_) => unreachable!(),
}
}
let mut result_err: Result<usize, bool> = Err(false);
{
let as_mut = result_err.as_mut();
match as_mut {
Ok(_) => unreachable!(),
Err(v) => *v = true,
}
}
}
#[test]
fn result_opt_conversions() {
#[derive(Copy, Clone, Debug, PartialEq)]
struct BadNumErr;
fn try_num(x: i32) -> Result<i32, BadNumErr> {
if x <= 5 { Ok(x + 1) } else { Err(BadNumErr) }
}
type ResOpt = Result<Option<i32>, BadNumErr>;
type OptRes = Option<Result<i32, BadNumErr>>;
let mut x: ResOpt = Ok(Some(5));
let mut y: OptRes = Some(Ok(5));
assert_eq!(x, y.transpose());
assert_eq!(x.transpose(), y);
x = Ok(None);
y = None;
assert_eq!(x, y.transpose());
assert_eq!(x.transpose(), y);
x = Err(BadNumErr);
y = Some(Err(BadNumErr));
assert_eq!(x, y.transpose());
assert_eq!(x.transpose(), y);
let res: Result<Vec<i32>, BadNumErr> = (0..10)
.map(|x| {
let y = try_num(x)?;
Ok(if y % 2 == 0 { Some(y - 1) } else { None })
})
.filter_map(Result::transpose)
.collect();
assert_eq!(res, Err(BadNumErr))
}
2021-04-15 03:13:39 -05:00
#[test]
fn result_try_trait_v2_branch() {
use core::num::NonZeroU32;
use core::ops::{ControlFlow::*, Try};
assert_eq!(Ok::<i32, i32>(4).branch(), Continue(4));
assert_eq!(Err::<i32, i32>(4).branch(), Break(Err(4)));
let one = NonZeroU32::new(1).unwrap();
assert_eq!(Ok::<(), NonZeroU32>(()).branch(), Continue(()));
assert_eq!(Err::<(), NonZeroU32>(one).branch(), Break(Err(one)));
assert_eq!(Ok::<NonZeroU32, ()>(one).branch(), Continue(one));
assert_eq!(Err::<NonZeroU32, ()>(()).branch(), Break(Err(())));
}