Skip to content

Commit

Permalink
Move backtraces into StdError
Browse files Browse the repository at this point in the history
  • Loading branch information
webmaster128 committed Apr 1, 2021
1 parent fd4f9f4 commit bb0224e
Showing 1 changed file with 102 additions and 35 deletions.
137 changes: 102 additions & 35 deletions packages/std/src/errors/std_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,18 @@ pub enum StdError {
#[cfg(feature = "backtraces")]
backtrace: Backtrace,
},
#[error(transparent)]
Overflow(#[from] OverflowError),
#[error(transparent)]
DivideByZero(#[from] DivideByZeroError),
#[error("Overflow: {source}")]
Overflow {
source: OverflowError,
#[cfg(feature = "backtraces")]
backtrace: Backtrace,
},
#[error("Divide by zero: {source}")]
DivideByZero {
source: DivideByZeroError,
#[cfg(feature = "backtraces")]
backtrace: Backtrace,
},
}

impl StdError {
Expand Down Expand Up @@ -165,6 +173,22 @@ impl StdError {
backtrace: Backtrace::capture(),
}
}

pub fn overflow(source: OverflowError) -> Self {
StdError::Overflow {
source,
#[cfg(feature = "backtraces")]
backtrace: Backtrace::capture(),
}
}

pub fn divide_by_zero(source: DivideByZeroError) -> Self {
StdError::DivideByZero {
source,
#[cfg(feature = "backtraces")]
backtrace: Backtrace::capture(),
}
}
}

impl PartialEq<StdError> for StdError {
Expand Down Expand Up @@ -320,16 +344,34 @@ impl PartialEq<StdError> for StdError {
false
}
}
StdError::Overflow(err) => {
if let StdError::Overflow(rhs_err) = rhs {
err == rhs_err
StdError::Overflow {
source,
#[cfg(feature = "backtraces")]
backtrace: _,
} => {
if let StdError::Overflow {
source: rhs_source,
#[cfg(feature = "backtraces")]
backtrace: _,
} = rhs
{
source == rhs_source
} else {
false
}
}
StdError::DivideByZero(err) => {
if let StdError::DivideByZero(rhs_err) = rhs {
err == rhs_err
StdError::DivideByZero {
source,
#[cfg(feature = "backtraces")]
backtrace: _,
} => {
if let StdError::DivideByZero {
source: rhs_source,
#[cfg(feature = "backtraces")]
backtrace: _,
} = rhs
{
source == rhs_source
} else {
false
}
Expand Down Expand Up @@ -362,6 +404,18 @@ impl From<RecoverPubkeyError> for StdError {
}
}

impl From<OverflowError> for StdError {
fn from(source: OverflowError) -> Self {
Self::overflow(source)
}
}

impl From<DivideByZeroError> for StdError {
fn from(source: DivideByZeroError) -> Self {
Self::divide_by_zero(source)
}
}

/// The return type for init, execute and query. Since the error type cannot be serialized to JSON,
/// this is only available within the contract and its unit tests.
///
Expand Down Expand Up @@ -389,8 +443,6 @@ pub struct OverflowError {
pub operation: OverflowOperation,
pub operand1: String,
pub operand2: String,
#[cfg(feature = "backtraces")]
backtrace: Backtrace,
}

impl OverflowError {
Expand All @@ -399,8 +451,6 @@ impl OverflowError {
operation,
operand1: operand1.to_string(),
operand2: operand2.to_string(),
#[cfg(feature = "backtraces")]
backtrace: Backtrace::capture(),
}
}
}
Expand All @@ -409,16 +459,12 @@ impl OverflowError {
#[error("Cannot devide {operand} by zero")]
pub struct DivideByZeroError {
pub operand: String,
#[cfg(feature = "backtraces")]
backtrace: Backtrace,
}

impl DivideByZeroError {
pub fn new<U: ToString>(operand: U) -> Self {
Self {
operand: operand.to_string(),
#[cfg(feature = "backtraces")]
backtrace: Backtrace::capture(),
}
}
}
Expand Down Expand Up @@ -552,14 +598,19 @@ mod tests {

#[test]
fn underflow_works_for_u128() {
let error = StdError::from(OverflowError::new(OverflowOperation::Sub, 123u128, 456u128));
let error =
StdError::overflow(OverflowError::new(OverflowOperation::Sub, 123u128, 456u128));
match error {
StdError::Overflow(OverflowError {
operation: OverflowOperation::Sub,
operand1,
operand2,
StdError::Overflow {
source:
OverflowError {
operation,
operand1,
operand2,
},
..
}) => {
} => {
assert_eq!(operation, OverflowOperation::Sub);
assert_eq!(operand1, "123");
assert_eq!(operand2, "456");
}
Expand All @@ -568,37 +619,53 @@ mod tests {
}

#[test]
fn underflow_works_for_i64() {
let error = StdError::from(OverflowError::new(OverflowOperation::Sub, 777i64, 1234i64));
fn overflow_works_for_i64() {
let error = StdError::overflow(OverflowError::new(OverflowOperation::Sub, 777i64, 1234i64));
match error {
StdError::Overflow(OverflowError {
operation: OverflowOperation::Sub,
operand1,
operand2,
StdError::Overflow {
source:
OverflowError {
operation,
operand1,
operand2,
},
..
}) => {
} => {
assert_eq!(operation, OverflowOperation::Sub);
assert_eq!(operand1, "777");
assert_eq!(operand2, "1234");
}
_ => panic!("expect different error"),
}
}

#[test]
fn divide_by_zero_works() {
let error = StdError::divide_by_zero(DivideByZeroError::new(123u128));
match error {
StdError::DivideByZero {
source: DivideByZeroError { operand },
..
} => assert_eq!(operand, "123"),
_ => panic!("expect different error"),
}
}

#[test]
fn implements_debug() {
let error: StdError = StdError::from(OverflowError::new(OverflowOperation::Sub, 3, 5));
let embedded = format!("Debug message: {:?}", error);
let embedded = format!("Debug: {:?}", error);
assert_eq!(
embedded,
r#"Debug message: Overflow(OverflowError { operation: Sub, operand1: "3", operand2: "5" })"#
r#"Debug: Overflow { source: OverflowError { operation: Sub, operand1: "3", operand2: "5" } }"#
);
}

#[test]
fn implements_display() {
let error: StdError = StdError::from(OverflowError::new(OverflowOperation::Sub, 3, 5));
let embedded = format!("Display message: {}", error);
assert_eq!(embedded, "Display message: Cannot Sub with 3 and 5");
let embedded = format!("Display: {}", error);
assert_eq!(embedded, "Display: Overflow: Cannot Sub with 3 and 5");
}

#[test]
Expand Down

0 comments on commit bb0224e

Please sign in to comment.