Skip to content

Commit

Permalink
Make it possible to create SdkError context structs for tests (smit…
Browse files Browse the repository at this point in the history
  • Loading branch information
jdisanti committed Mar 3, 2023
1 parent 818343e commit 7ce8032
Show file tree
Hide file tree
Showing 2 changed files with 192 additions and 0 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.next.toml
Expand Up @@ -227,3 +227,15 @@ match client.some_operation().send().await {
references = ["smithy-rs#2398"]
meta = { "breaking" = false, "tada" = true, "bug" = false }
author = "ysaito1001"

[[aws-sdk-rust]]
message = "`SdkError` variants can now be constructed for easier unit testing."
references = ["smithy-rs#2428", "smithy-rs#2208"]
meta = { "breaking" = false, "tada" = true, "bug" = false }
author = "jdisanti"

[[smithy-rs]]
message = "`SdkError` variants can now be constructed for easier unit testing."
references = ["smithy-rs#2428", "smithy-rs#2208"]
meta = { "breaking" = false, "tada" = true, "bug" = false, "target" = "client" }
author = "jdisanti"
180 changes: 180 additions & 0 deletions rust-runtime/aws-smithy-http/src/result.rs
Expand Up @@ -32,25 +32,195 @@ pub struct SdkSuccess<O> {
pub parsed: O,
}

/// Builders for `SdkError` variant context.
pub mod builders {
use super::*;

macro_rules! source_only_error_builder {
($errorName:ident, $builderName:ident, $sourceType:ident) => {
#[doc = concat!("Builder for [`", stringify!($errorName), "`](super::", stringify!($errorName), ").")]
#[derive(Debug, Default)]
pub struct $builderName {
source: Option<$sourceType>,
}

impl $builderName {
#[doc = "Creates a new builder."]
pub fn new() -> Self { Default::default() }

#[doc = "Sets the error source."]
pub fn source(mut self, source: impl Into<$sourceType>) -> Self {
self.source = Some(source.into());
self
}

#[doc = "Sets the error source."]
pub fn set_source(&mut self, source: Option<$sourceType>) -> &mut Self {
self.source = source;
self
}

#[doc = "Builds the error context."]
pub fn build(self) -> $errorName {
$errorName { source: self.source.expect("source is required") }
}
}
};
}

source_only_error_builder!(ConstructionFailure, ConstructionFailureBuilder, BoxError);
source_only_error_builder!(TimeoutError, TimeoutErrorBuilder, BoxError);
source_only_error_builder!(DispatchFailure, DispatchFailureBuilder, ConnectorError);

/// Builder for [`ResponseError`](super::ResponseError).
#[derive(Debug)]
pub struct ResponseErrorBuilder<R> {
source: Option<BoxError>,
raw: Option<R>,
}

impl<R> Default for ResponseErrorBuilder<R> {
fn default() -> Self {
Self {
source: None,
raw: None,
}
}
}

impl<R> ResponseErrorBuilder<R> {
/// Creates a new builder.
pub fn new() -> Self {
Default::default()
}

/// Sets the error source.
pub fn source(mut self, source: impl Into<BoxError>) -> Self {
self.source = Some(source.into());
self
}

/// Sets the error source.
pub fn set_source(&mut self, source: Option<BoxError>) -> &mut Self {
self.source = source;
self
}

/// Sets the raw response.
pub fn raw(mut self, raw: R) -> Self {
self.raw = Some(raw);
self
}

/// Sets the raw response.
pub fn set_raw(&mut self, raw: Option<R>) -> &mut Self {
self.raw = raw;
self
}

/// Builds the error context.
pub fn build(self) -> ResponseError<R> {
ResponseError {
source: self.source.expect("source is required"),
raw: self.raw.expect("a raw response is required"),
}
}
}

/// Builder for [`ServiceError`](super::ServiceError).
#[derive(Debug)]
pub struct ServiceErrorBuilder<E, R> {
source: Option<E>,
raw: Option<R>,
}

impl<E, R> Default for ServiceErrorBuilder<E, R> {
fn default() -> Self {
Self {
source: None,
raw: None,
}
}
}

impl<E, R> ServiceErrorBuilder<E, R> {
/// Creates a new builder.
pub fn new() -> Self {
Default::default()
}

/// Sets the error source.
pub fn source(mut self, source: impl Into<E>) -> Self {
self.source = Some(source.into());
self
}

/// Sets the error source.
pub fn set_source(&mut self, source: Option<E>) -> &mut Self {
self.source = source;
self
}

/// Sets the raw response.
pub fn raw(mut self, raw: R) -> Self {
self.raw = Some(raw);
self
}

/// Sets the raw response.
pub fn set_raw(&mut self, raw: Option<R>) -> &mut Self {
self.raw = raw;
self
}

/// Builds the error context.
pub fn build(self) -> ServiceError<E, R> {
ServiceError {
source: self.source.expect("source is required"),
raw: self.raw.expect("a raw response is required"),
}
}
}
}

/// Error context for [`SdkError::ConstructionFailure`]
#[derive(Debug)]
pub struct ConstructionFailure {
source: BoxError,
}

impl ConstructionFailure {
/// Creates a builder for this error context type.
pub fn builder() -> builders::ConstructionFailureBuilder {
builders::ConstructionFailureBuilder::new()
}
}

/// Error context for [`SdkError::TimeoutError`]
#[derive(Debug)]
pub struct TimeoutError {
source: BoxError,
}

impl TimeoutError {
/// Creates a builder for this error context type.
pub fn builder() -> builders::TimeoutErrorBuilder {
builders::TimeoutErrorBuilder::new()
}
}

/// Error context for [`SdkError::DispatchFailure`]
#[derive(Debug)]
pub struct DispatchFailure {
source: ConnectorError,
}

impl DispatchFailure {
/// Creates a builder for this error context type.
pub fn builder() -> builders::DispatchFailureBuilder {
builders::DispatchFailureBuilder::new()
}

/// Returns true if the error is an IO error
pub fn is_io(&self) -> bool {
self.source.is_io()
Expand Down Expand Up @@ -82,6 +252,11 @@ pub struct ResponseError<R> {
}

impl<R> ResponseError<R> {
/// Creates a builder for this error context type.
pub fn builder() -> builders::ResponseErrorBuilder<R> {
builders::ResponseErrorBuilder::new()
}

/// Returns a reference to the raw response
pub fn raw(&self) -> &R {
&self.raw
Expand All @@ -103,6 +278,11 @@ pub struct ServiceError<E, R> {
}

impl<E, R> ServiceError<E, R> {
/// Creates a builder for this error context type.
pub fn builder() -> builders::ServiceErrorBuilder<E, R> {
builders::ServiceErrorBuilder::new()
}

/// Returns the underlying error of type `E`
pub fn err(&self) -> &E {
&self.source
Expand Down

0 comments on commit 7ce8032

Please sign in to comment.