From d2f44101070c8c13fcd8d9d157bd8fa0e8bb25c3 Mon Sep 17 00:00:00 2001 From: Martin Geisler Date: Fri, 1 Nov 2024 08:51:40 -0700 Subject: [PATCH] Also implement `MessageMatcher` for `T: Copy` This makes it possible to match views by value: ```rust expect_that!( response.clients(), unordered_elements_are![ proto_eq(proto!(Client { name: "Alice" }).as_view()), proto_eq(proto!(Client { name: "Bob" }).as_view()) ] ); ``` where `clients()` return an iterator over `ClientView` values. PiperOrigin-RevId: 692192744 --- rust/gtest_matchers_impl.rs | 16 ++++++++++++++++ rust/test/shared/gtest_matchers_test.rs | 24 ++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/rust/gtest_matchers_impl.rs b/rust/gtest_matchers_impl.rs index 0dc833a758..c52f98b231 100644 --- a/rust/gtest_matchers_impl.rs +++ b/rust/gtest_matchers_impl.rs @@ -30,6 +30,22 @@ where } } +impl Matcher for MessageMatcher +where + T: MatcherEq + Copy, +{ + fn matches(&self, actual: T) -> MatcherResult { + actual.matches(&self.expected).into() + } + + fn describe(&self, matcher_result: MatcherResult) -> Description { + match matcher_result { + MatcherResult::Match => format!("is equal to {:?}", self.expected).into(), + MatcherResult::NoMatch => format!("is not equal to {:?}", self.expected).into(), + } + } +} + pub fn proto_eq(expected: T) -> MessageMatcher { MessageMatcher { expected } } diff --git a/rust/test/shared/gtest_matchers_test.rs b/rust/test/shared/gtest_matchers_test.rs index a74add5726..0cd09d260b 100644 --- a/rust/test/shared/gtest_matchers_test.rs +++ b/rust/test/shared/gtest_matchers_test.rs @@ -11,7 +11,9 @@ google3::import! { use googletest::prelude::*; use paste::paste; +use protobuf::proto; use protobuf_gtest_matchers::proto_eq; +use unittest_proto3_rust_proto::test_all_types::NestedMessage; use unittest_proto3_rust_proto::TestAllTypes as TestAllTypesProto3; use unittest_rust_proto::TestAllTypes; @@ -52,3 +54,25 @@ macro_rules! generate_not_eq_msgs_tests { generate_eq_msgs_tests!((TestAllTypes, editions), (TestAllTypesProto3, proto3)); generate_not_eq_msgs_tests!((TestAllTypes, editions), (TestAllTypesProto3, proto3)); + +#[gtest] +fn proto_eq_works_on_view() { + // This exercises the `impl Matcher for MessageMatcher + // where T: MatcherEq + Copy` implementation. + let msg = proto!(TestAllTypesProto3 { + repeated_nested_message: [ + NestedMessage { bb: 10 }, + NestedMessage { bb: 20 }, + NestedMessage { bb: 30 } + ] + }); + + expect_that!( + msg.repeated_nested_message(), + unordered_elements_are![ + proto_eq(proto!(NestedMessage { bb: 10 }).as_view()), + proto_eq(proto!(NestedMessage { bb: 20 }).as_view()), + proto_eq(proto!(NestedMessage { bb: 30 }).as_view()), + ] + ); +}