diff --git a/Cargo.lock b/Cargo.lock index b3e81ac..ce820dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -515,9 +515,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.1" +version = "4.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ed2379f8603fa2b7509891660e802b88c70a79a6427a70abb5968054de2c28" +checksum = "401a4694d2bf92537b6867d94de48c4842089645fdcdf6c71865b175d836e9c2" dependencies = [ "clap_builder", ] @@ -872,9 +872,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" dependencies = [ "percent-encoding", ] @@ -1022,9 +1022,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", @@ -1282,9 +1282,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -1465,9 +1465,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.145" +version = "0.2.146" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc86cde3ff845662b8f4ef6cb50ea0e20c524eb3d29ae048287e06a1b3fa6a81" +checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" [[package]] name = "libgit2-sys" @@ -1501,9 +1501,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "lock_api" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" dependencies = [ "autocfg", "scopeguard", @@ -1764,9 +1764,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.30.3" +version = "0.30.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" dependencies = [ "memchr", ] @@ -1865,7 +1865,7 @@ dependencies = [ [[package]] name = "pact-protobuf-plugin" -version = "0.3.2" +version = "0.3.3" dependencies = [ "ansi_term", "anyhow", @@ -1924,9 +1924,9 @@ dependencies = [ [[package]] name = "pact_consumer" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016334b4a70ecb22f448267fd817003f7c09ffda5165aa31e9fe4ede5091aa07" +checksum = "c91a29624a59437715e7209ad86e63f194b344a77368b3dea401dae424f5fdfc" dependencies = [ "anyhow", "async-trait", @@ -2110,15 +2110,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.7" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.2.16", + "redox_syscall", "smallvec", - "windows-sys 0.45.0", + "windows-targets 0.48.0", ] [[package]] @@ -2178,9 +2178,9 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "peresil" @@ -2458,15 +2458,6 @@ dependencies = [ "num_cpus", ] -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.3.5" @@ -2498,9 +2489,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.8.3" +version = "1.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81ca098a9821bd52d6b24fd8b10bd081f47d39c22778cafaa75a2857a62c6390" +checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" dependencies = [ "aho-corasick", "memchr", @@ -3081,15 +3072,16 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.5.0" +version = "3.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" +checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" dependencies = [ + "autocfg", "cfg-if", "fastrand", - "redox_syscall 0.3.5", + "redox_syscall", "rustix", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -3634,9 +3626,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" dependencies = [ "form_urlencoded", "idna", diff --git a/src/lib.rs b/src/lib.rs index 2bc27ed..86298b2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,7 +6,7 @@ mod protobuf; mod message_builder; pub mod message_decoder; pub mod utils; -mod matching; +pub mod matching; pub mod mock_server; pub mod tcp; pub mod dynamic_message; diff --git a/src/matching.rs b/src/matching.rs index 9182194..363fe03 100644 --- a/src/matching.rs +++ b/src/matching.rs @@ -128,7 +128,7 @@ pub(crate) fn compare( skip_all, fields(%path) )] -fn compare_message( +pub fn compare_message( path: DocPath, expected_message_fields: &[ProtobufField], actual_message_fields: &[ProtobufField], diff --git a/src/utils.rs b/src/utils.rs index 046cb26..204fd70 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -318,7 +318,7 @@ pub(crate) fn parse_pact_from_request_json(pact_json: &str, source: &str) -> any } /// Lookup up the interaction in the Pact file, given the ID -pub(crate) fn lookup_interaction_by_id<'a>( +pub fn lookup_interaction_by_id<'a>( interaction_key: &str, pact: &'a V4Pact ) -> Option<&'a Box> { @@ -326,7 +326,7 @@ pub(crate) fn lookup_interaction_by_id<'a>( .find(|i| i.unique_key() == interaction_key) } -pub(crate) fn lookup_interaction_config(interaction: &dyn V4Interaction) -> Option> { +pub fn lookup_interaction_config(interaction: &dyn V4Interaction) -> Option> { interaction.plugin_config().iter() .find_map(|(key, value)| { if key.as_str() == "protobuf" { @@ -372,7 +372,7 @@ pub(crate) fn lookup_service_descriptors_for_interaction( } /// Get the encoded Protobuf descriptors from the Pact level configuration for the message key -pub(crate) fn get_descriptors_for_interaction( +pub fn get_descriptors_for_interaction( message_key: &str, plugin_config: &BTreeMap ) -> anyhow::Result { diff --git a/tests/enum.proto b/tests/enum.proto new file mode 100644 index 0000000..b3ec414 --- /dev/null +++ b/tests/enum.proto @@ -0,0 +1,20 @@ +syntax = "proto3"; + +enum Values { + NONE = 0; + A = 1; + B = 2; + C = 3; +} + +message MessageIn { + repeated Values in = 1; +} + +message MessageOut { + repeated Values out = 1; +} + +service Test { + rpc GetTest(MessageIn) returns (MessageOut) {} +} diff --git a/tests/enum_tests.rs b/tests/enum_tests.rs new file mode 100644 index 0000000..23ac93a --- /dev/null +++ b/tests/enum_tests.rs @@ -0,0 +1,90 @@ +use std::path::Path; + +use expectest::prelude::*; +use maplit::hashmap; +use pact_consumer::builders::PactBuilderAsync; +use pact_matching::{BodyMatchResult, CoreMatchingContext, DiffConfig}; +use pact_models::json_utils::json_to_string; +use pact_models::path_exp::DocPath; +use prost::encoding::WireType; +use serde_json::json; +use pact_protobuf_plugin::matching::compare_message; +use pact_protobuf_plugin::message_decoder::{ProtobufField, ProtobufFieldData}; +use pact_protobuf_plugin::utils::{find_message_type_by_name, get_descriptors_for_interaction, lookup_interaction_config}; + +#[test_log::test(tokio::test(flavor = "multi_thread"))] +async fn repeated_enum_test() { + let mut pact_builder = PactBuilderAsync::new_v4("repeated_enum", "protobuf-plugin"); + pact_builder + .using_plugin("protobuf", None).await + .message_interaction("get a list of enums", |mut i| async move { + let proto_file = Path::new("tests/enum.proto") + .canonicalize().unwrap().to_string_lossy().to_string(); + i.contents_from(json!({ + "pact:proto": proto_file, + "pact:message-type": "MessageIn", + "pact:content-type": "application/protobuf", + + "in": [ + "matching(equalTo, 'A')" + ] + })).await; + i + }) + .await; + + let pact = pact_builder.build().as_v4_pact().unwrap(); + let plugin_config = pact.plugin_data.iter() + .find(|data| data.name == "protobuf") + .map(|data| &data.configuration) + .unwrap() + .iter() + .map(|(k, v)| (k.clone(), v.clone())) + .collect(); + + for message in pact_builder.messages() { + let interaction_config = lookup_interaction_config(&message).unwrap(); + let descriptor_key = interaction_config.get("descriptorKey") + .map(json_to_string).unwrap(); + let fds = get_descriptors_for_interaction(descriptor_key.as_str(), + &plugin_config).unwrap(); + let path = DocPath::root(); + let context = CoreMatchingContext::new(DiffConfig::NoUnexpectedKeys, + &message.contents.matching_rules.rules_for_category("body").unwrap(), &hashmap!{}); + let (message_descriptor, fs) = find_message_type_by_name("MessageIn", &fds).unwrap(); + let enum_descriptor = fs.enum_type.first().unwrap(); + let expected = vec![ + ProtobufField { + field_num: 1, + field_name: "in".to_string(), + wire_type: WireType::LengthDelimited, + data: ProtobufFieldData::Enum(1, enum_descriptor.clone()) + } + ]; + let actual = vec![ + ProtobufField { + field_num: 1, + field_name: "in".to_string(), + wire_type: WireType::LengthDelimited, + data: ProtobufFieldData::Enum(1, enum_descriptor.clone()) + }, + // ProtobufField { + // field_num: 1, + // field_name: "in".to_string(), + // wire_type: WireType::LengthDelimited, + // data: ProtobufFieldData::Enum(1, enum_descriptor.clone()) + // } + ]; + + let result = compare_message( + path, + &expected, + &actual, + &context, + &message_descriptor, + &fds, + ).unwrap(); + + expect!(result).to(be_equal_to(BodyMatchResult::Ok)); + } +} diff --git a/tests/mock_server_tests.rs b/tests/mock_server_tests.rs index 262cc10..9b8990d 100644 --- a/tests/mock_server_tests.rs +++ b/tests/mock_server_tests.rs @@ -93,7 +93,7 @@ fn mock_server_with_no_requests() { } } -#[test_log::test(tokio::test(flavor = "multi_thread", worker_threads = 2))] +#[test_log::test(tokio::test(flavor = "multi_thread"))] async fn each_value_matcher() { let mut pact_builder = PactBuilderAsync::new_v4("each-value", "protobuf-plugin"); pact_builder @@ -164,3 +164,4 @@ async fn each_value_matcher() { let path = http::uri::PathAndQuery::try_from("/Test/GetValues").unwrap(); grpc.unary(Request::new(message), path, codec).await.unwrap(); } +