Skip to content

Commit eaeff36

Browse files
authored
test(common): add an IsProtoApproximatelyEqual matcher (#13873)
Add a proto-message matcher that supports approximate equality checks on floating-point fields.
1 parent c1be3cb commit eaeff36

2 files changed

Lines changed: 64 additions & 1 deletion

File tree

google/cloud/testing_util/is_proto_equal.cc

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,39 @@ absl::optional<std::string> CompareProtos(
2727
google::protobuf::util::MessageDifferencer differencer;
2828
differencer.ReportDifferencesToString(&delta);
2929
auto const result = differencer.Compare(arg, value);
30-
if (result) return {};
30+
if (result) return absl::nullopt;
31+
return delta;
32+
}
33+
34+
absl::optional<std::string> CompareProtosApproximately(
35+
google::protobuf::Message const& arg,
36+
google::protobuf::Message const& value) {
37+
std::string delta;
38+
google::protobuf::util::DefaultFieldComparator comparator;
39+
comparator.set_float_comparison(
40+
google::protobuf::util::DefaultFieldComparator::APPROXIMATE);
41+
// Keep the comparator's default fraction and margin.
42+
google::protobuf::util::MessageDifferencer differencer;
43+
differencer.set_field_comparator(&comparator);
44+
differencer.ReportDifferencesToString(&delta);
45+
auto const result = differencer.Compare(arg, value);
46+
if (result) return absl::nullopt;
47+
return delta;
48+
}
49+
50+
absl::optional<std::string> CompareProtosApproximately(
51+
google::protobuf::Message const& arg,
52+
google::protobuf::Message const& value, double fraction, double margin) {
53+
std::string delta;
54+
google::protobuf::util::DefaultFieldComparator comparator;
55+
comparator.set_float_comparison(
56+
google::protobuf::util::DefaultFieldComparator::APPROXIMATE);
57+
comparator.SetDefaultFractionAndMargin(fraction, margin);
58+
google::protobuf::util::MessageDifferencer differencer;
59+
differencer.set_field_comparator(&comparator);
60+
differencer.ReportDifferencesToString(&delta);
61+
auto const result = differencer.Compare(arg, value);
62+
if (result) return absl::nullopt;
3163
return delta;
3264
}
3365

google/cloud/testing_util/is_proto_equal.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,37 @@ MATCHER_P(IsProtoEqual, value, "Checks whether protos are equal") {
3838
return !delta.has_value();
3939
}
4040

41+
// Compares float and double fields approximately, using the default
42+
// google::protobuf::MessageDifferencer tolerances.
43+
absl::optional<std::string> CompareProtosApproximately(
44+
google::protobuf::Message const& arg,
45+
google::protobuf::Message const& value);
46+
47+
MATCHER_P(IsProtoApproximatelyEqual, value,
48+
"Checks whether protos are approximately equal") {
49+
absl::optional<std::string> delta = CompareProtosApproximately(arg, value);
50+
if (delta.has_value()) {
51+
*result_listener << "\n" << *delta;
52+
}
53+
return !delta.has_value();
54+
}
55+
56+
// Compares float and double fields approximately, using the given
57+
// @p fraction and @p margin.
58+
absl::optional<std::string> CompareProtosApproximately(
59+
google::protobuf::Message const& arg,
60+
google::protobuf::Message const& value, double fraction, double margin);
61+
62+
MATCHER_P3(IsProtoApproximatelyEqual, value, fraction, margin,
63+
"Checks whether protos are approximately equal") {
64+
absl::optional<std::string> delta =
65+
CompareProtosApproximately(arg, value, fraction, margin);
66+
if (delta.has_value()) {
67+
*result_listener << "\n" << *delta;
68+
}
69+
return !delta.has_value();
70+
}
71+
4172
} // namespace testing_util
4273
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
4374
} // namespace cloud

0 commit comments

Comments
 (0)