From f8df7bee3e194d1fef8f2919c32d8eb0d2de5929 Mon Sep 17 00:00:00 2001 From: Ronald Holshausen Date: Tue, 28 May 2024 14:57:56 +1000 Subject: [PATCH] chore: Fix broken unit tests --- drivers/rust/driver/Cargo.lock | 17 +++ drivers/rust/driver/Cargo.toml | 1 + drivers/rust/driver/src/catalogue_manager.rs | 60 +++++--- drivers/rust/driver/src/grpc_plugin.rs | 139 ++++++++++++++++++- drivers/rust/driver/src/plugin_manager.rs | 4 +- 5 files changed, 196 insertions(+), 25 deletions(-) diff --git a/drivers/rust/driver/Cargo.lock b/drivers/rust/driver/Cargo.lock index 28dda4b8..8ada1052 100644 --- a/drivers/rust/driver/Cargo.lock +++ b/drivers/rust/driver/Cargo.lock @@ -549,6 +549,12 @@ dependencies = [ "syn", ] +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + [[package]] name = "digest" version = "0.10.7" @@ -1662,6 +1668,7 @@ dependencies = [ "mlua", "os_info", "pact_models", + "pretty_assertions", "prost", "prost-types", "rand 0.8.5", @@ -1913,6 +1920,16 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "pretty_assertions" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" +dependencies = [ + "diff", + "yansi", +] + [[package]] name = "prettyplease" version = "0.2.20" diff --git a/drivers/rust/driver/Cargo.toml b/drivers/rust/driver/Cargo.toml index 26fe0b78..279f03e2 100644 --- a/drivers/rust/driver/Cargo.toml +++ b/drivers/rust/driver/Cargo.toml @@ -62,6 +62,7 @@ base64 = "0.21.7" [dev-dependencies] env_logger = "0.11.3" expectest = "0.12.0" +pretty_assertions = "1.4.0" tempdir = "0.3.7" test-log = "0.2.15" diff --git a/drivers/rust/driver/src/catalogue_manager.rs b/drivers/rust/driver/src/catalogue_manager.rs index b87b088f..c4117934 100644 --- a/drivers/rust/driver/src/catalogue_manager.rs +++ b/drivers/rust/driver/src/catalogue_manager.rs @@ -122,6 +122,18 @@ pub struct CatalogueEntry { pub values: HashMap } +impl Default for CatalogueEntry { + fn default() -> Self { + CatalogueEntry { + entry_type: CatalogueEntryType::CONTENT_MATCHER, + provider_type: CatalogueEntryProviderType::CORE, + plugin: None, + key: "".to_string(), + values: Default::default(), + } + } +} + /// Register the entries in the global catalogue pub fn register_plugin_entries(plugin: &PactPluginManifest, catalogue_list: Vec) { trace!("register_plugin_entries({:?}, {:?})", plugin, catalogue_list); @@ -251,10 +263,8 @@ pub fn all_entries() -> Vec { #[cfg(test)] mod tests { - use expectest::prelude::*; use maplit::hashmap; - - use crate::proto::catalogue_entry; + use pretty_assertions::assert_eq; use super::*; @@ -266,25 +276,31 @@ mod tests { .. PactPluginManifest::default() }; let entries = vec![ - ProtoCatalogueEntry { - r#type: catalogue_entry::EntryType::ContentMatcher as i32, + CatalogueEntry { + entry_type: CatalogueEntryType::CONTENT_MATCHER, + provider_type: CatalogueEntryProviderType::PLUGIN, key: "protobuf".to_string(), - values: hashmap!{ "content-types".to_string() => "application/protobuf;application/grpc".to_string() } + values: hashmap!{ "content-types".to_string() => "application/protobuf;application/grpc".to_string() }, + .. CatalogueEntry::default() }, - ProtoCatalogueEntry { - r#type: catalogue_entry::EntryType::ContentGenerator as i32, + CatalogueEntry { + entry_type: CatalogueEntryType::CONTENT_GENERATOR, + provider_type: CatalogueEntryProviderType::PLUGIN, key: "protobuf".to_string(), - values: hashmap!{ "content-types".to_string() => "application/protobuf;application/grpc".to_string() } + values: hashmap!{ "content-types".to_string() => "application/protobuf;application/grpc".to_string() }, + .. CatalogueEntry::default() }, - ProtoCatalogueEntry { - r#type: catalogue_entry::EntryType::Transport as i32, + CatalogueEntry { + entry_type: CatalogueEntryType::TRANSPORT, + provider_type: CatalogueEntryProviderType::PLUGIN, key: "grpc".to_string(), - values: hashmap!{} + values: hashmap!{}, + .. CatalogueEntry::default() } ]; // When - register_plugin_entries(&manifest, &entries); + register_plugin_entries(&manifest, entries); // Then let matcher_entry = lookup_entry("content-matcher/protobuf"); @@ -293,26 +309,26 @@ mod tests { remove_plugin_entries("sets_plugin_catalogue_entries_correctly"); - expect!(matcher_entry).to(be_some().value(CatalogueEntry { + assert_eq!(matcher_entry.unwrap(), CatalogueEntry { entry_type: CatalogueEntryType::CONTENT_MATCHER, provider_type: CatalogueEntryProviderType::PLUGIN, - plugin: Some(manifest.clone()), + plugin: None, key: "protobuf".to_string(), values: hashmap!{ "content-types".to_string() => "application/protobuf;application/grpc".to_string() } - })); - expect!(generator_entry).to(be_some().value(CatalogueEntry { + }); + assert_eq!(generator_entry.unwrap(), CatalogueEntry { entry_type: CatalogueEntryType::CONTENT_GENERATOR, provider_type: CatalogueEntryProviderType::PLUGIN, - plugin: Some(manifest.clone()), + plugin: None, key: "protobuf".to_string(), values: hashmap!{ "content-types".to_string() => "application/protobuf;application/grpc".to_string() } - })); - expect!(transport_entry).to(be_some().value(CatalogueEntry { + }); + assert_eq!(transport_entry.unwrap(), CatalogueEntry { entry_type: CatalogueEntryType::TRANSPORT, provider_type: CatalogueEntryProviderType::PLUGIN, - plugin: Some(manifest.clone()), + plugin: None, key: "grpc".to_string(), values: hashmap!{} - })); + }); } } diff --git a/drivers/rust/driver/src/grpc_plugin.rs b/drivers/rust/driver/src/grpc_plugin.rs index 0af69683..c7084d68 100644 --- a/drivers/rust/driver/src/grpc_plugin.rs +++ b/drivers/rust/driver/src/grpc_plugin.rs @@ -2,8 +2,8 @@ use std::collections::HashMap; use std::path::PathBuf; -use std::process::Stdio; #[cfg(windows)] use std::process::Command; +use std::process::Stdio; use std::str::from_utf8; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; @@ -828,5 +828,142 @@ pub(crate) async fn start_plugin_process(manifest: &PactPluginManifest) -> anyho #[cfg(test)] pub(crate) mod tests { + use async_trait::async_trait; + use expectest::prelude::*; + use maplit::hashmap; + + use crate::catalogue_manager::{CatalogueEntry, CatalogueEntryProviderType, CatalogueEntryType, lookup_entry, remove_plugin_entries}; + use crate::grpc_plugin::{init_handshake, PactPluginRpc}; + use crate::plugin_models::PactPluginManifest; + use crate::proto::{ + Catalogue, + catalogue_entry, + CatalogueEntry as ProtoCatalogueEntry, + CompareContentsRequest, + CompareContentsResponse, + ConfigureInteractionRequest, + ConfigureInteractionResponse, + GenerateContentRequest, + GenerateContentResponse, + InitPluginRequest, + InitPluginResponse, + MockServerRequest, + MockServerResults, + ShutdownMockServerRequest, + ShutdownMockServerResponse, + StartMockServerRequest, + StartMockServerResponse, + VerificationPreparationRequest, + VerificationPreparationResponse, + VerifyInteractionRequest, + VerifyInteractionResponse + }; + + #[derive(Default, Debug, Clone)] + struct MockPlugin {} + + #[async_trait] + impl PactPluginRpc for MockPlugin { + async fn init_plugin(&mut self, request: InitPluginRequest) -> anyhow::Result { + let entries = vec![ + ProtoCatalogueEntry { + r#type: catalogue_entry::EntryType::ContentMatcher as i32, + key: "protobuf".to_string(), + values: hashmap!{ "content-types".to_string() => "application/protobuf;application/grpc".to_string() } + }, + ProtoCatalogueEntry { + r#type: catalogue_entry::EntryType::ContentGenerator as i32, + key: "protobuf".to_string(), + values: hashmap!{ "content-types".to_string() => "application/protobuf;application/grpc".to_string() } + }, + ProtoCatalogueEntry { + r#type: catalogue_entry::EntryType::Transport as i32, + key: "grpc".to_string(), + values: hashmap!{} + } + ]; + Ok(InitPluginResponse { + catalogue: entries + }) + } + + async fn compare_contents(&self, _request: CompareContentsRequest) -> anyhow::Result { + todo!() + } + + async fn configure_interaction(&self, _request: ConfigureInteractionRequest) -> anyhow::Result { + todo!() + } + + async fn generate_content(&self, _request: GenerateContentRequest) -> anyhow::Result { + todo!() + } + + async fn start_mock_server(&self, _request: StartMockServerRequest) -> anyhow::Result { + todo!() + } + async fn shutdown_mock_server(&self, _request: ShutdownMockServerRequest) -> anyhow::Result { + todo!() + } + + async fn get_mock_server_results(&self, _request: MockServerRequest) -> anyhow::Result { + todo!() + } + + async fn prepare_interaction_for_verification(&self, _request: VerificationPreparationRequest) -> anyhow::Result { + todo!() + } + + async fn verify_interaction(&self, _request: VerifyInteractionRequest) -> anyhow::Result { + todo!() + } + + async fn update_catalogue(&self, _request: Catalogue) -> anyhow::Result<()> { + todo!() + } + } + + #[tokio::test] + async fn init_handshake_sets_plugin_catalogue_entries_correctly() { + // Given + let manifest = PactPluginManifest { + name: "init_handshake_sets_plugin_catalogue_entries_correctly".to_string(), + .. PactPluginManifest::default() + }; + + let mut mock_plugin = MockPlugin {}; + + // When + init_handshake(&manifest, &mut mock_plugin).await.unwrap(); + + // Then + let matcher_entry = lookup_entry("content-matcher/protobuf"); + let generator_entry = lookup_entry("content-generator/protobuf"); + let transport_entry = lookup_entry("transport/grpc"); + + remove_plugin_entries("init_handshake_sets_plugin_catalogue_entries_correctly"); + + expect!(matcher_entry).to(be_some().value(CatalogueEntry { + entry_type: CatalogueEntryType::CONTENT_MATCHER, + provider_type: CatalogueEntryProviderType::PLUGIN, + plugin: Some(manifest.clone()), + key: "protobuf".to_string(), + values: hashmap!{ "content-types".to_string() => "application/protobuf;application/grpc".to_string() } + })); + expect!(generator_entry).to(be_some().value(CatalogueEntry { + entry_type: CatalogueEntryType::CONTENT_GENERATOR, + provider_type: CatalogueEntryProviderType::PLUGIN, + plugin: Some(manifest.clone()), + key: "protobuf".to_string(), + values: hashmap!{ "content-types".to_string() => "application/protobuf;application/grpc".to_string() } + })); + expect!(transport_entry).to(be_some().value(CatalogueEntry { + entry_type: CatalogueEntryType::TRANSPORT, + provider_type: CatalogueEntryProviderType::PLUGIN, + plugin: Some(manifest.clone()), + key: "grpc".to_string(), + values: hashmap!{} + })); + } } diff --git a/drivers/rust/driver/src/plugin_manager.rs b/drivers/rust/driver/src/plugin_manager.rs index 5a2028b1..8ff1882e 100644 --- a/drivers/rust/driver/src/plugin_manager.rs +++ b/drivers/rust/driver/src/plugin_manager.rs @@ -237,12 +237,12 @@ async fn initialise_plugin<'a>( } "lua" => { #[cfg(feature = "lua")] { - let mut plugin = start_lua_plugin(manifest)?; + let plugin = start_lua_plugin(manifest)?; debug!("Plugin started OK ({:?}), sending init message", plugin); plugin.init()?; - // This causes a deadlock + // TODO: This causes a deadlock //publish_updated_catalogue(); let arc = Arc::new(plugin);