From 9ba09214b257d23935e9f7ae49e483b86b848477 Mon Sep 17 00:00:00 2001 From: ndefokou Date: Tue, 19 Nov 2024 14:49:05 +0100 Subject: [PATCH] Adding test on manager.rs --- crates/plugin-api/src/lib.rs | 1 + .../web-plugins/didcomm-messaging/Cargo.toml | 17 ++- .../didcomm-messaging/message-api/src/lib.rs | 6 +- .../didcomm-messaging/src/manager.rs | 125 ++++++++++++++++++ .../didcomm-messaging/src/plugin.rs | 9 +- .../didcomm-messaging/src/web/dispatcher.rs | 6 +- 6 files changed, 146 insertions(+), 18 deletions(-) diff --git a/crates/plugin-api/src/lib.rs b/crates/plugin-api/src/lib.rs index 726ef506..878e1da1 100644 --- a/crates/plugin-api/src/lib.rs +++ b/crates/plugin-api/src/lib.rs @@ -8,6 +8,7 @@ use axum::Router; #[derive(Debug, PartialEq)] pub enum PluginError { InitError, + DidcommMessagContainerError, } pub trait Plugin: Sync + Send { diff --git a/crates/web-plugins/didcomm-messaging/Cargo.toml b/crates/web-plugins/didcomm-messaging/Cargo.toml index 3adbbdc6..7fe26b55 100644 --- a/crates/web-plugins/didcomm-messaging/Cargo.toml +++ b/crates/web-plugins/didcomm-messaging/Cargo.toml @@ -11,10 +11,10 @@ keystore.workspace = true shared.workspace = true plugin-api.workspace = true filesystem.workspace = true -forward.workspace = true -pickup.workspace = true -trust-ping.workspace = true -mediator-coordination.workspace = true +forward = { workspace = true, optional = true } +pickup = { workspace = true, optional = true } +trust-ping = { workspace = true, optional = true } +mediator-coordination = { workspace = true, optional = true } message-api.workspace = true @@ -31,11 +31,10 @@ serde = { version = "1.0", features = ["derive"] } [features] -default = ["routing", "pickup", "trust-ping", "mediator-coordination"] -routing = [] -pickup = [] -trust-ping = [] -mediator-coordination = [] +routing = ["dep:forward"] +pickup = ["dep:pickup"] +trust-ping = ["dep:trust-ping"] +mediator-coordination = ["dep:mediator-coordination"] [dev-dependencies] diff --git a/crates/web-plugins/didcomm-messaging/message-api/src/lib.rs b/crates/web-plugins/didcomm-messaging/message-api/src/lib.rs index 613fabdb..db81d679 100644 --- a/crates/web-plugins/didcomm-messaging/message-api/src/lib.rs +++ b/crates/web-plugins/didcomm-messaging/message-api/src/lib.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, sync::Arc}; +use std::{collections::HashMap, fmt::Debug, sync::Arc}; use async_trait::async_trait; use axum::response::Response; @@ -6,12 +6,12 @@ use didcomm::Message; use shared::state::AppState; #[async_trait] -pub trait MessageHandler: Send + Sync { +pub trait MessageHandler: Send + Sync + Debug{ async fn handle(&self, state: Arc, msg: Message) -> Result, Response>; } -#[derive(Default, Clone)] +#[derive(Default, Clone, Debug)] pub struct MessageRouter { handlers: HashMap>, } diff --git a/crates/web-plugins/didcomm-messaging/src/manager.rs b/crates/web-plugins/didcomm-messaging/src/manager.rs index 9f34fcf6..b9a918d1 100644 --- a/crates/web-plugins/didcomm-messaging/src/manager.rs +++ b/crates/web-plugins/didcomm-messaging/src/manager.rs @@ -81,3 +81,128 @@ impl<'a> MessagePluginContainer<'a> { })) } } + +#[cfg(test)] +mod tests { + use super::*; + use std::sync::Arc; + + // Real plugin implementations + struct FirstPlugin; + impl MessagePlugin for FirstPlugin { + fn name(&self) -> &'static str { + "first" + } + + fn didcomm_routes(&self) -> MessageRouter { + MessageRouter::new() + } + } + + struct SecondPlugin; + impl MessagePlugin for SecondPlugin { + fn name(&self) -> &'static str { + "second" + } + + fn didcomm_routes(&self) -> MessageRouter { + MessageRouter::new() + } + } + + #[test] + fn test_loading_plugins() { + let plugins: Vec> = + vec![Arc::new(FirstPlugin {}), Arc::new(SecondPlugin {})]; + + let mut container = MessagePluginContainer { + loaded: false, + collected_routes: vec![], + message_plugins: &plugins, + }; + + assert!(container.load().is_ok()); + assert!(container.loaded); + + assert_eq!(container.collected_routes.len(), 2); + + assert!(container.find_handler("first").is_some()); + assert!(container.find_handler("second").is_some()); + assert!(container.find_handler("non-existent").is_none()); + } + + #[test] + fn test_loading_duplicate_plugins() { + let plugins: Vec> = vec![ + Arc::new(FirstPlugin {}), + Arc::new(SecondPlugin {}), + Arc::new(SecondPlugin {}), + ]; + + let mut container = MessagePluginContainer { + loaded: false, + collected_routes: vec![], + message_plugins: &plugins, + }; + + assert_eq!( + container.load().unwrap_err(), + MessageContainerError::DuplicateEntry + ); + + assert_eq!(container.collected_routes.len(), 0); + } + + #[test] + fn test_double_loading() { + let plugins: Vec> = + vec![Arc::new(FirstPlugin {}), Arc::new(SecondPlugin {})]; + + let mut container = MessagePluginContainer { + loaded: false, + collected_routes: vec![], + message_plugins: &plugins, + }; + + assert!(container.load().is_ok()); + assert!(container.load().is_ok()); + } + + #[test] + fn test_unloading_plugins() { + let plugins: Vec> = + vec![Arc::new(FirstPlugin {}), Arc::new(SecondPlugin {})]; + + let mut container = MessagePluginContainer { + loaded: false, + collected_routes: vec![], + message_plugins: &plugins, + }; + + assert!(container.load().is_ok()); + assert_eq!(container.collected_routes.len(), 2); + + assert!(container.unload().is_ok()); + assert!(!container.loaded); + + assert_eq!(container.collected_routes.len(), 0); + } + + #[test] + fn test_routes_without_loading() { + let plugins: Vec> = + vec![Arc::new(FirstPlugin {}), Arc::new(SecondPlugin {})]; + + let container = MessagePluginContainer { + loaded: false, + collected_routes: vec![], + message_plugins: &plugins, + }; + + // Attempt to access routes without loading + assert_eq!( + container.didcomm_routes().unwrap_err(), + MessageContainerError::Unloaded + ); + } +} diff --git a/crates/web-plugins/didcomm-messaging/src/plugin.rs b/crates/web-plugins/didcomm-messaging/src/plugin.rs index 6efc66fc..999b2a2a 100644 --- a/crates/web-plugins/didcomm-messaging/src/plugin.rs +++ b/crates/web-plugins/didcomm-messaging/src/plugin.rs @@ -1,7 +1,8 @@ -use crate::web; +use crate::{manager::MessagePluginContainer, web}; use axum::Router; use filesystem::StdFileSystem; use mongodb::Database; +use plugin_api::PluginError::DidcommMessagContainerError; use plugin_api::{Plugin, PluginError}; use shared::{ repository::{MongoConnectionRepository, MongoMessagesRepository}, @@ -23,6 +24,12 @@ struct DidcommMessagingPluginEnv { /// Loads environment variables required for this plugin fn load_plugin_env() -> Result { + let mut container = MessagePluginContainer::new(); + if container.load().is_err() { + tracing::error!("failed to load DIDComm protocols container"); + return Err(DidcommMessagContainerError); + } + let public_domain = std::env::var("SERVER_PUBLIC_DOMAIN").map_err(|_| { tracing::error!("SERVER_PUBLIC_DOMAIN env variable required"); PluginError::InitError diff --git a/crates/web-plugins/didcomm-messaging/src/web/dispatcher.rs b/crates/web-plugins/didcomm-messaging/src/web/dispatcher.rs index 9a6afa12..dc300872 100644 --- a/crates/web-plugins/didcomm-messaging/src/web/dispatcher.rs +++ b/crates/web-plugins/didcomm-messaging/src/web/dispatcher.rs @@ -14,11 +14,7 @@ pub(crate) async fn process_didcomm_message( State(state): State>, Extension(message): Extension, ) -> Response { - let mut container = MessagePluginContainer::new(); - if container.load().is_err() { - tracing::error!("failed to load DIDComm protocols container"); - return StatusCode::INTERNAL_SERVER_ERROR.into_response(); - } + let container = MessagePluginContainer::new(); if let Some(handler) = container .didcomm_routes()