Skip to content

Commit

Permalink
added more unit tests for tls, di and error handling logic (#88)
Browse files Browse the repository at this point in the history
  • Loading branch information
RomanEmreis authored Feb 23, 2025
1 parent f8cc8fb commit a516ce9
Show file tree
Hide file tree
Showing 4 changed files with 337 additions and 0 deletions.
41 changes: 41 additions & 0 deletions src/di.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,44 @@ impl App {
self
}
}

#[cfg(test)]
mod tests {
use super::App;

#[derive(Default)]
struct TestDependency;

#[tokio::test]
async fn it_adds_singleton() {
let mut app = App::new();
app.add_singleton(TestDependency);

let container = app.container.build();
let dep = container.resolve_shared::<TestDependency>().await;

assert!(dep.is_ok());
}

#[tokio::test]
async fn it_adds_scoped() {
let mut app = App::new();
app.add_scoped::<TestDependency>();

let container = app.container.build();
let dep = container.resolve_shared::<TestDependency>().await;

assert!(dep.is_ok());
}

#[tokio::test]
async fn it_adds_transient() {
let mut app = App::new();
app.add_transient::<TestDependency>();

let container = app.container.build();
let dep = container.resolve_shared::<TestDependency>().await;

assert!(dep.is_ok());
}
}
20 changes: 20 additions & 0 deletions src/di/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,4 +390,24 @@ mod tests {

assert!(container.is_ok());
}

#[tokio::test]
async fn it_returns_error_when_resolve_unregistered() {
let container = ContainerBuilder::new().build();

let cache = container.resolve::<CacheWrapper>().await;

assert!(cache.is_err());
}

#[tokio::test]
async fn it_returns_error_when_resolve_unregistered_from_scope() {
let container = ContainerBuilder::new()
.build()
.create_scope();

let cache = container.resolve::<CacheWrapper>().await;

assert!(cache.is_err());
}
}
142 changes: 142 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,145 @@ impl App {
self
}
}

#[cfg(test)]
mod tests {
use super::{Error, StatusCode};
use std::io::{ErrorKind, Error as IoError};

#[test]
fn it_converts_from_not_found_io_error() {
let io_error = IoError::new(ErrorKind::NotFound, "not found");
let err = Error::from(io_error);

assert!(err.is_client_error());
assert_eq!(err.status, StatusCode::NOT_FOUND);
}

#[test]
fn it_converts_from_connection_reset_io_error() {
let io_error = IoError::new(ErrorKind::ConnectionReset, "reset");
let err = Error::from(io_error);

assert!(err.is_server_error());
assert_eq!(err.status, StatusCode::BAD_GATEWAY);
}

#[test]
fn it_converts_from_connection_aborted_io_error() {
let io_error = IoError::new(ErrorKind::ConnectionAborted, "aborted");
let err = Error::from(io_error);

assert!(err.is_server_error());
assert_eq!(err.status, StatusCode::BAD_GATEWAY);
}

#[test]
fn it_converts_from_not_connected_io_error() {
let io_error = IoError::new(ErrorKind::NotConnected, "not connected");
let err = Error::from(io_error);

assert!(err.is_server_error());
assert_eq!(err.status, StatusCode::BAD_GATEWAY);
}

#[test]
fn it_converts_from_add_in_use_io_error() {
let io_error = IoError::new(ErrorKind::AddrInUse, "addr in use");
let err = Error::from(io_error);

assert!(err.is_server_error());
assert_eq!(err.status, StatusCode::BAD_GATEWAY);
}

#[test]
fn it_converts_from_addr_not_available_io_error() {
let io_error = IoError::new(ErrorKind::AddrNotAvailable, "addr not available");
let err = Error::from(io_error);

assert!(err.is_server_error());
assert_eq!(err.status, StatusCode::BAD_GATEWAY);
}

#[test]
fn it_converts_from_broken_pipe_io_error() {
let io_error = IoError::new(ErrorKind::BrokenPipe, "broken pipe");
let err = Error::from(io_error);

assert!(err.is_server_error());
assert_eq!(err.status, StatusCode::BAD_GATEWAY);
}

#[test]
fn it_converts_from_already_exists_io_error() {
let io_error = IoError::new(ErrorKind::AlreadyExists, "exists");
let err = Error::from(io_error);

assert!(err.is_client_error());
assert_eq!(err.status, StatusCode::CONFLICT);
}

#[test]
fn it_converts_from_invalid_data_io_error() {
let io_error = IoError::new(ErrorKind::InvalidData, "invalid data");
let err = Error::from(io_error);

assert!(err.is_client_error());
assert_eq!(err.status, StatusCode::BAD_REQUEST);
}

#[test]
fn it_converts_from_timed_out_io_error() {
let io_error = IoError::new(ErrorKind::TimedOut, "timeout");
let err = Error::from(io_error);

assert!(err.is_client_error());
assert_eq!(err.status, StatusCode::REQUEST_TIMEOUT);
}

#[test]
fn it_converts_from_unsupported_io_error() {
let io_error = IoError::new(ErrorKind::Unsupported, "unsupported");
let err = Error::from(io_error);

assert!(err.is_client_error());
assert_eq!(err.status, StatusCode::UNSUPPORTED_MEDIA_TYPE);
}

#[test]
fn it_converts_from_io_error() {
let io_error = IoError::new(ErrorKind::Other, "some error");
let err = Error::from(io_error);

assert!(err.is_server_error());
assert_eq!(err.status, StatusCode::INTERNAL_SERVER_ERROR);
}

#[test]
fn it_converts_error_to_io_error() {
let error = Error::client_error("some error");
let io_error = IoError::from(error);

assert_eq!(io_error.kind(), ErrorKind::Other);
}

#[test]
fn it_splits_into_parts() {
let error = Error::server_error("some error");

let (status, instance, inner) = error.into_parts();

assert_eq!(status, StatusCode::INTERNAL_SERVER_ERROR);
assert!(instance.is_none());
assert_eq!(format!("{}", inner), "some error");
}

#[test]
fn it_unwraps_into_inner() {
let error = Error::server_error("some error");

let inner = error.into_inner();

assert_eq!(format!("{}", inner), "some error");
}
}
134 changes: 134 additions & 0 deletions src/tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,7 @@ impl App {

#[cfg(test)]
mod tests {
use std::path::PathBuf;
use std::time::Duration;
use super::{
TlsConfig,
Expand Down Expand Up @@ -759,6 +760,130 @@ mod tests {
assert_eq!(tls_config.https_redirection_config.http_port, DEFAULT_PORT);
}

#[test]
fn it_creates_tls_config_from_pem() {
let tls_config = TlsConfig::from_pem("tls");

let path = PathBuf::from("tls");

assert_eq!(tls_config.key, path.join(KEY_FILE_NAME));
assert_eq!(tls_config.cert, path.join(CERT_FILE_NAME));
assert_eq!(tls_config.client_auth, ClientAuth::None);

assert_eq!(tls_config.hsts_config.exclude_hosts.len(), 0);
assert_eq!(tls_config.hsts_config.max_age, Duration::from_secs(DEFAULT_MAX_AGE));
assert!(tls_config.hsts_config.preload);
assert!(tls_config.hsts_config.include_sub_domains);

assert!(!tls_config.https_redirection_config.enabled);
assert_eq!(tls_config.https_redirection_config.http_port, DEFAULT_PORT);
}

#[test]
fn it_creates_tls_config_with_hsts() {
let tls_config = TlsConfig::from_pem("tls")
.with_hsts(HstsConfig {
max_age: Duration::from_secs(1),
preload: false,
include_sub_domains: false,
exclude_hosts: vec!["example.com"]
});

let path = PathBuf::from("tls");

assert_eq!(tls_config.key, path.join(KEY_FILE_NAME));
assert_eq!(tls_config.cert, path.join(CERT_FILE_NAME));
assert_eq!(tls_config.client_auth, ClientAuth::None);

assert_eq!(tls_config.hsts_config.exclude_hosts.len(), 1);
assert_eq!(tls_config.hsts_config.max_age, Duration::from_secs(1));
assert!(!tls_config.hsts_config.preload);
assert!(!tls_config.hsts_config.include_sub_domains);

assert!(!tls_config.https_redirection_config.enabled);
assert_eq!(tls_config.https_redirection_config.http_port, DEFAULT_PORT);
}

#[test]
fn it_creates_tls_config_with_hsts_preload() {
let tls_config = TlsConfig::from_pem("tls")
.with_hsts_preload(false);

let path = PathBuf::from("tls");

assert_eq!(tls_config.key, path.join(KEY_FILE_NAME));
assert_eq!(tls_config.cert, path.join(CERT_FILE_NAME));
assert_eq!(tls_config.client_auth, ClientAuth::None);

assert_eq!(tls_config.hsts_config.exclude_hosts.len(), 0);
assert_eq!(tls_config.hsts_config.max_age, Duration::from_secs(DEFAULT_MAX_AGE));
assert!(!tls_config.hsts_config.preload);
assert!(tls_config.hsts_config.include_sub_domains);

assert!(!tls_config.https_redirection_config.enabled);
assert_eq!(tls_config.https_redirection_config.http_port, DEFAULT_PORT);
}

#[test]
fn it_creates_tls_config_with_hsts_sub_domains() {
let tls_config = TlsConfig::from_pem("tls")
.with_hsts_sub_domains(false);

let path = PathBuf::from("tls");

assert_eq!(tls_config.key, path.join(KEY_FILE_NAME));
assert_eq!(tls_config.cert, path.join(CERT_FILE_NAME));
assert_eq!(tls_config.client_auth, ClientAuth::None);

assert_eq!(tls_config.hsts_config.exclude_hosts.len(), 0);
assert_eq!(tls_config.hsts_config.max_age, Duration::from_secs(DEFAULT_MAX_AGE));
assert!(tls_config.hsts_config.preload);
assert!(!tls_config.hsts_config.include_sub_domains);

assert!(!tls_config.https_redirection_config.enabled);
assert_eq!(tls_config.https_redirection_config.http_port, DEFAULT_PORT);
}

#[test]
fn it_creates_tls_config_with_hsts_max_age() {
let tls_config = TlsConfig::from_pem("tls")
.with_hsts_max_age(Duration::from_secs(5));

let path = PathBuf::from("tls");

assert_eq!(tls_config.key, path.join(KEY_FILE_NAME));
assert_eq!(tls_config.cert, path.join(CERT_FILE_NAME));
assert_eq!(tls_config.client_auth, ClientAuth::None);

assert_eq!(tls_config.hsts_config.exclude_hosts.len(), 0);
assert_eq!(tls_config.hsts_config.max_age, Duration::from_secs(5));
assert!(tls_config.hsts_config.preload);
assert!(tls_config.hsts_config.include_sub_domains);

assert!(!tls_config.https_redirection_config.enabled);
assert_eq!(tls_config.https_redirection_config.http_port, DEFAULT_PORT);
}

#[test]
fn it_creates_tls_config_with_hsts_exclude_hosts() {
let tls_config = TlsConfig::from_pem("tls")
.with_hsts_exclude_hosts(&["example.com"]);

let path = PathBuf::from("tls");

assert_eq!(tls_config.key, path.join(KEY_FILE_NAME));
assert_eq!(tls_config.cert, path.join(CERT_FILE_NAME));
assert_eq!(tls_config.client_auth, ClientAuth::None);

assert_eq!(tls_config.hsts_config.exclude_hosts.len(), 1);
assert_eq!(tls_config.hsts_config.max_age, Duration::from_secs(DEFAULT_MAX_AGE));
assert!(tls_config.hsts_config.preload);
assert!(tls_config.hsts_config.include_sub_domains);

assert!(!tls_config.https_redirection_config.enabled);
assert_eq!(tls_config.https_redirection_config.http_port, DEFAULT_PORT);
}

#[test]
fn it_creates_default_hsts_config() {
let hsts_config = HstsConfig::default();
Expand All @@ -776,4 +901,13 @@ mod tests {
assert!(!https_redirection_config.enabled);
assert_eq!(https_redirection_config.http_port, DEFAULT_PORT);
}

#[test]
fn it_displays_hsts_config() {
let hsts_config = HstsConfig::default();

let hsts_string = hsts_config.to_string();

assert_eq!(hsts_string, "max-age=2592000; includeSubDomains; preload");
}
}

0 comments on commit a516ce9

Please sign in to comment.