mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-05-29 19:30:37 +00:00
refactor: Refactor usage of BoxedError (#48)
* feat: Define a general boxed error * refactor: common_function use Error in common_query * feat: Add tests to define_opaque_error macro * refactor: Refactor table and table engine error * refactor: recordbatch remove arrow dev-dependency * refactor: datanode crate use common_error::BoxedError * chore: Fix clippy * feat: Returning source status code when using BoxedError * test: Fix opaque error test * test: Add tests for table::Error & table_engine::Error * test: Add test for RecordBatch::new() * test: Remove generated tests from define_opaque_error * chore: Address cr comment
This commit is contained in:
@@ -83,101 +83,64 @@ macro_rules! define_opaque_error {
|
||||
};
|
||||
}
|
||||
|
||||
// Define a general boxed error.
|
||||
define_opaque_error!(BoxedError);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::error::Error as StdError;
|
||||
use std::error::Error;
|
||||
|
||||
use snafu::ErrorCompat;
|
||||
|
||||
use super::*;
|
||||
use crate::prelude::*;
|
||||
use crate::format::DebugFormat;
|
||||
use crate::mock::MockError;
|
||||
|
||||
define_opaque_error!(Error);
|
||||
#[test]
|
||||
fn test_opaque_error_without_backtrace() {
|
||||
let err = BoxedError::new(MockError::new(StatusCode::Internal));
|
||||
assert!(err.backtrace_opt().is_none());
|
||||
assert_eq!(StatusCode::Internal, err.status_code());
|
||||
assert!(err.as_any().downcast_ref::<MockError>().is_some());
|
||||
assert!(err.source().is_none());
|
||||
|
||||
#[derive(Debug, Snafu)]
|
||||
enum InnerError {
|
||||
#[snafu(display("This is a leaf error, val: {}", val))]
|
||||
Leaf { val: i32, backtrace: Backtrace },
|
||||
|
||||
#[snafu(display("This is an internal error"))]
|
||||
Internal {
|
||||
source: std::io::Error,
|
||||
backtrace: Backtrace,
|
||||
},
|
||||
}
|
||||
|
||||
impl ErrorExt for InnerError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
StatusCode::Internal
|
||||
}
|
||||
|
||||
fn backtrace_opt(&self) -> Option<&snafu::Backtrace> {
|
||||
ErrorCompat::backtrace(self)
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl From<InnerError> for Error {
|
||||
fn from(err: InnerError) -> Self {
|
||||
Self::new(err)
|
||||
}
|
||||
}
|
||||
|
||||
fn throw_leaf() -> std::result::Result<(), InnerError> {
|
||||
LeafSnafu { val: 10 }.fail()
|
||||
}
|
||||
|
||||
fn throw_io() -> std::result::Result<(), std::io::Error> {
|
||||
Err(std::io::Error::new(std::io::ErrorKind::Other, "oh no!"))
|
||||
}
|
||||
|
||||
fn throw_internal() -> std::result::Result<(), InnerError> {
|
||||
throw_io().context(InternalSnafu)
|
||||
assert!(ErrorCompat::backtrace(&err).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inner_error() {
|
||||
let leaf = throw_leaf().err().unwrap();
|
||||
assert!(leaf.backtrace_opt().is_some());
|
||||
assert!(leaf.source().is_none());
|
||||
fn test_opaque_error_with_backtrace() {
|
||||
let err = BoxedError::new(MockError::with_backtrace(StatusCode::Internal));
|
||||
assert!(err.backtrace_opt().is_some());
|
||||
assert_eq!(StatusCode::Internal, err.status_code());
|
||||
assert!(err.as_any().downcast_ref::<MockError>().is_some());
|
||||
assert!(err.source().is_none());
|
||||
|
||||
let internal = throw_internal().err().unwrap();
|
||||
assert!(internal.backtrace_opt().is_some());
|
||||
assert!(internal.source().is_some());
|
||||
}
|
||||
assert!(ErrorCompat::backtrace(&err).is_some());
|
||||
|
||||
#[test]
|
||||
fn test_opaque_error() {
|
||||
// Test leaf error.
|
||||
let err: Error = throw_leaf().map_err(Into::into).err().unwrap();
|
||||
let msg = format!("{:?}", err);
|
||||
assert!(msg.contains("\nBacktrace:\n"));
|
||||
|
||||
let fmt_msg = format!("{:?}", DebugFormat::new(&err));
|
||||
assert_eq!(msg, fmt_msg);
|
||||
|
||||
assert!(ErrorCompat::backtrace(&err).is_some());
|
||||
let msg = err.to_string();
|
||||
msg.contains("Internal");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_opaque_error_with_source() {
|
||||
let leaf_err = MockError::with_backtrace(StatusCode::Internal);
|
||||
let internal_err = MockError::with_source(leaf_err);
|
||||
let err = BoxedError::new(internal_err);
|
||||
|
||||
assert!(err.backtrace_opt().is_some());
|
||||
assert_eq!("This is a leaf error, val: 10", err.to_string());
|
||||
assert_eq!(StatusCode::Internal, err.status_code());
|
||||
assert!(err.as_any().downcast_ref::<MockError>().is_some());
|
||||
assert!(err.source().is_some());
|
||||
|
||||
err.as_any().downcast_ref::<InnerError>().unwrap();
|
||||
|
||||
// Test internal error.
|
||||
let err: Error = throw_internal().map_err(Into::into).err().unwrap();
|
||||
let msg = format!("{:?}", err);
|
||||
assert!(msg.contains("\nBacktrace:\n"));
|
||||
assert!(msg.contains("Caused by"));
|
||||
|
||||
let fmt_msg = format!("{:?}", DebugFormat::new(&err));
|
||||
assert_eq!(msg, fmt_msg);
|
||||
|
||||
assert!(ErrorCompat::backtrace(&err).is_some());
|
||||
assert!(err.backtrace_opt().is_some());
|
||||
assert_eq!("This is an internal error", err.to_string());
|
||||
assert_eq!(StatusCode::Internal, err.status_code());
|
||||
|
||||
err.as_any().downcast_ref::<InnerError>().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ pub mod status_code;
|
||||
pub mod prelude {
|
||||
pub use snafu::{prelude::*, Backtrace, ErrorCompat};
|
||||
|
||||
pub use crate::ext::ErrorExt;
|
||||
pub use crate::ext::{BoxedError, ErrorExt};
|
||||
pub use crate::format::DebugFormat;
|
||||
pub use crate::status_code::StatusCode;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user