• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 // Author: ksroka@google.com (Krzysztof Sroka)
9 
10 #include "google/protobuf/util/field_comparator.h"
11 
12 #include <limits>
13 
14 #include <gtest/gtest.h>
15 #include "google/protobuf/descriptor.h"
16 #include "google/protobuf/unittest.pb.h"
17 
18 namespace google {
19 namespace protobuf {
20 namespace util {
21 namespace {
22 
23 using protobuf_unittest::TestAllTypes;
24 
25 class DefaultFieldComparatorTest : public ::testing::Test {
26  protected:
SetUp()27   void SetUp() override { descriptor_ = TestAllTypes::descriptor(); }
28 
29   const Descriptor* descriptor_;
30   DefaultFieldComparator comparator_;
31   TestAllTypes message_1_;
32   TestAllTypes message_2_;
33 };
34 
TEST_F(DefaultFieldComparatorTest,RecursesIntoGroup)35 TEST_F(DefaultFieldComparatorTest, RecursesIntoGroup) {
36   const FieldDescriptor* field = descriptor_->FindFieldByName("optionalgroup");
37   EXPECT_EQ(
38       FieldComparator::RECURSE,
39       comparator_.Compare(message_1_, message_2_, field, -1, -1, nullptr));
40 }
41 
TEST_F(DefaultFieldComparatorTest,RecursesIntoNestedMessage)42 TEST_F(DefaultFieldComparatorTest, RecursesIntoNestedMessage) {
43   const FieldDescriptor* field =
44       descriptor_->FindFieldByName("optional_nested_message");
45   EXPECT_EQ(
46       FieldComparator::RECURSE,
47       comparator_.Compare(message_1_, message_2_, field, -1, -1, nullptr));
48 }
49 
TEST_F(DefaultFieldComparatorTest,RecursesIntoForeignMessage)50 TEST_F(DefaultFieldComparatorTest, RecursesIntoForeignMessage) {
51   const FieldDescriptor* field =
52       descriptor_->FindFieldByName("optional_foreign_message");
53   EXPECT_EQ(
54       FieldComparator::RECURSE,
55       comparator_.Compare(message_1_, message_2_, field, -1, -1, nullptr));
56 }
57 
TEST_F(DefaultFieldComparatorTest,Int32Comparison)58 TEST_F(DefaultFieldComparatorTest, Int32Comparison) {
59   const FieldDescriptor* field = descriptor_->FindFieldByName("optional_int32");
60   message_1_.set_optional_int32(1);
61   message_2_.set_optional_int32(1);
62 
63   EXPECT_EQ(FieldComparator::SAME, comparator_.Compare(message_1_, message_2_,
64                                                        field, -1, -1, nullptr));
65 
66   message_2_.set_optional_int32(-1);
67   EXPECT_EQ(
68       FieldComparator::DIFFERENT,
69       comparator_.Compare(message_1_, message_2_, field, -1, -1, nullptr));
70 }
71 
TEST_F(DefaultFieldComparatorTest,Int64Comparison)72 TEST_F(DefaultFieldComparatorTest, Int64Comparison) {
73   const FieldDescriptor* field = descriptor_->FindFieldByName("optional_int64");
74   message_1_.set_optional_int64(1L);
75   message_2_.set_optional_int64(1L);
76 
77   EXPECT_EQ(FieldComparator::SAME, comparator_.Compare(message_1_, message_2_,
78                                                        field, -1, -1, nullptr));
79 
80   message_2_.set_optional_int64(-1L);
81   EXPECT_EQ(
82       FieldComparator::DIFFERENT,
83       comparator_.Compare(message_1_, message_2_, field, -1, -1, nullptr));
84 }
85 
TEST_F(DefaultFieldComparatorTest,UInt32Comparison)86 TEST_F(DefaultFieldComparatorTest, UInt32Comparison) {
87   const FieldDescriptor* field =
88       descriptor_->FindFieldByName("optional_uint32");
89   message_1_.set_optional_uint32(1);
90   message_2_.set_optional_uint32(1);
91 
92   EXPECT_EQ(FieldComparator::SAME, comparator_.Compare(message_1_, message_2_,
93                                                        field, -1, -1, nullptr));
94 
95   message_2_.set_optional_uint32(2);
96   EXPECT_EQ(
97       FieldComparator::DIFFERENT,
98       comparator_.Compare(message_1_, message_2_, field, -1, -1, nullptr));
99 }
100 
TEST_F(DefaultFieldComparatorTest,UInt64Comparison)101 TEST_F(DefaultFieldComparatorTest, UInt64Comparison) {
102   const FieldDescriptor* field =
103       descriptor_->FindFieldByName("optional_uint64");
104   message_1_.set_optional_uint64(1L);
105   message_2_.set_optional_uint64(1L);
106 
107   EXPECT_EQ(FieldComparator::SAME, comparator_.Compare(message_1_, message_2_,
108                                                        field, -1, -1, nullptr));
109 
110   message_2_.set_optional_uint64(2L);
111   EXPECT_EQ(
112       FieldComparator::DIFFERENT,
113       comparator_.Compare(message_1_, message_2_, field, -1, -1, nullptr));
114 }
115 
TEST_F(DefaultFieldComparatorTest,BooleanComparison)116 TEST_F(DefaultFieldComparatorTest, BooleanComparison) {
117   const FieldDescriptor* field = descriptor_->FindFieldByName("optional_bool");
118   message_1_.set_optional_bool(true);
119   message_2_.set_optional_bool(true);
120 
121   EXPECT_EQ(FieldComparator::SAME, comparator_.Compare(message_1_, message_2_,
122                                                        field, -1, -1, nullptr));
123 
124   message_2_.set_optional_bool(false);
125   EXPECT_EQ(
126       FieldComparator::DIFFERENT,
127       comparator_.Compare(message_1_, message_2_, field, -1, -1, nullptr));
128 }
129 
TEST_F(DefaultFieldComparatorTest,EnumComparison)130 TEST_F(DefaultFieldComparatorTest, EnumComparison) {
131   const FieldDescriptor* field =
132       descriptor_->FindFieldByName("optional_nested_enum");
133   message_1_.set_optional_nested_enum(TestAllTypes::BAR);
134   message_2_.set_optional_nested_enum(TestAllTypes::BAR);
135 
136   EXPECT_EQ(FieldComparator::SAME, comparator_.Compare(message_1_, message_2_,
137                                                        field, -1, -1, nullptr));
138 
139   message_2_.set_optional_nested_enum(TestAllTypes::BAZ);
140   EXPECT_EQ(
141       FieldComparator::DIFFERENT,
142       comparator_.Compare(message_1_, message_2_, field, -1, -1, nullptr));
143 }
144 
TEST_F(DefaultFieldComparatorTest,StringComparison)145 TEST_F(DefaultFieldComparatorTest, StringComparison) {
146   const FieldDescriptor* field =
147       descriptor_->FindFieldByName("optional_string");
148   message_1_.set_optional_string("foo");
149   message_2_.set_optional_string("foo");
150 
151   EXPECT_EQ(FieldComparator::SAME, comparator_.Compare(message_1_, message_2_,
152                                                        field, -1, -1, nullptr));
153 
154   message_2_.set_optional_string("bar");
155   EXPECT_EQ(
156       FieldComparator::DIFFERENT,
157       comparator_.Compare(message_1_, message_2_, field, -1, -1, nullptr));
158 }
159 
TEST_F(DefaultFieldComparatorTest,FloatingPointComparisonExact)160 TEST_F(DefaultFieldComparatorTest, FloatingPointComparisonExact) {
161   const FieldDescriptor* field_float =
162       descriptor_->FindFieldByName("optional_float");
163   const FieldDescriptor* field_double =
164       descriptor_->FindFieldByName("optional_double");
165 
166   message_1_.set_optional_float(0.1f);
167   message_2_.set_optional_float(0.1f);
168   message_1_.set_optional_double(0.1);
169   message_2_.set_optional_double(0.1);
170 
171   EXPECT_EQ(FieldComparator::SAME,
172             comparator_.Compare(message_1_, message_2_, field_float, -1, -1,
173                                 nullptr));
174   EXPECT_EQ(FieldComparator::SAME,
175             comparator_.Compare(message_1_, message_2_, field_double, -1, -1,
176                                 nullptr));
177 
178   message_2_.set_optional_float(0.2f);
179   message_2_.set_optional_double(0.2);
180 
181   EXPECT_EQ(FieldComparator::DIFFERENT,
182             comparator_.Compare(message_1_, message_2_, field_float, -1, -1,
183                                 nullptr));
184   EXPECT_EQ(FieldComparator::DIFFERENT,
185             comparator_.Compare(message_1_, message_2_, field_double, -1, -1,
186                                 nullptr));
187 }
188 
TEST_F(DefaultFieldComparatorTest,FloatingPointComparisonApproximate)189 TEST_F(DefaultFieldComparatorTest, FloatingPointComparisonApproximate) {
190   const FieldDescriptor* field_float =
191       descriptor_->FindFieldByName("optional_float");
192   const FieldDescriptor* field_double =
193       descriptor_->FindFieldByName("optional_double");
194 
195   message_1_.set_optional_float(2.300005f);
196   message_2_.set_optional_float(2.300006f);
197   message_1_.set_optional_double(2.3000000000000003);
198   message_2_.set_optional_double(2.3000000000000007);
199 
200   // Approximate comparison depends on MathUtil, so we assert on MathUtil
201   // results first to check if that's where the failure was introduced.
202   ASSERT_NE(message_1_.optional_float(), message_2_.optional_float());
203   ASSERT_NE(message_1_.optional_double(), message_2_.optional_double());
204   ASSERT_FLOAT_EQ(message_1_.optional_float(), message_2_.optional_float());
205   ASSERT_DOUBLE_EQ(message_1_.optional_double(), message_2_.optional_double());
206 
207   // DefaultFieldComparator's default float comparison mode is EXACT.
208   ASSERT_EQ(DefaultFieldComparator::EXACT, comparator_.float_comparison());
209   EXPECT_EQ(FieldComparator::DIFFERENT,
210             comparator_.Compare(message_1_, message_2_, field_float, -1, -1,
211                                 nullptr));
212   EXPECT_EQ(FieldComparator::DIFFERENT,
213             comparator_.Compare(message_1_, message_2_, field_double, -1, -1,
214                                 nullptr));
215 
216   comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE);
217 
218   EXPECT_EQ(FieldComparator::SAME,
219             comparator_.Compare(message_1_, message_2_, field_float, -1, -1,
220                                 nullptr));
221   EXPECT_EQ(FieldComparator::SAME,
222             comparator_.Compare(message_1_, message_2_, field_double, -1, -1,
223                                 nullptr));
224 }
225 
TEST_F(DefaultFieldComparatorTest,FloatingPointComparisonTreatNaNsAsEqual)226 TEST_F(DefaultFieldComparatorTest, FloatingPointComparisonTreatNaNsAsEqual) {
227   const FieldDescriptor* field_float =
228       descriptor_->FindFieldByName("optional_float");
229   const FieldDescriptor* field_double =
230       descriptor_->FindFieldByName("optional_double");
231 
232   message_1_.set_optional_float(std::numeric_limits<float>::quiet_NaN());
233   message_2_.set_optional_float(std::numeric_limits<float>::quiet_NaN());
234   message_1_.set_optional_double(std::numeric_limits<double>::quiet_NaN());
235   message_2_.set_optional_double(std::numeric_limits<double>::quiet_NaN());
236 
237   // DefaultFieldComparator's default float comparison mode is EXACT with
238   // treating NaNs as different.
239   ASSERT_EQ(DefaultFieldComparator::EXACT, comparator_.float_comparison());
240   ASSERT_EQ(false, comparator_.treat_nan_as_equal());
241   EXPECT_EQ(FieldComparator::DIFFERENT,
242             comparator_.Compare(message_1_, message_2_, field_float, -1, -1,
243                                 nullptr));
244   EXPECT_EQ(FieldComparator::DIFFERENT,
245             comparator_.Compare(message_1_, message_2_, field_double, -1, -1,
246                                 nullptr));
247   comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE);
248   EXPECT_EQ(FieldComparator::DIFFERENT,
249             comparator_.Compare(message_1_, message_2_, field_float, -1, -1,
250                                 nullptr));
251   EXPECT_EQ(FieldComparator::DIFFERENT,
252             comparator_.Compare(message_1_, message_2_, field_double, -1, -1,
253                                 nullptr));
254 
255   comparator_.set_treat_nan_as_equal(true);
256   ASSERT_EQ(true, comparator_.treat_nan_as_equal());
257   comparator_.set_float_comparison(DefaultFieldComparator::EXACT);
258   EXPECT_EQ(FieldComparator::SAME,
259             comparator_.Compare(message_1_, message_2_, field_float, -1, -1,
260                                 nullptr));
261   EXPECT_EQ(FieldComparator::SAME,
262             comparator_.Compare(message_1_, message_2_, field_double, -1, -1,
263                                 nullptr));
264   comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE);
265   EXPECT_EQ(FieldComparator::SAME,
266             comparator_.Compare(message_1_, message_2_, field_float, -1, -1,
267                                 nullptr));
268   EXPECT_EQ(FieldComparator::SAME,
269             comparator_.Compare(message_1_, message_2_, field_double, -1, -1,
270                                 nullptr));
271 }
272 
TEST_F(DefaultFieldComparatorTest,FloatingPointComparisonWithinFractionOrMargin)273 TEST_F(DefaultFieldComparatorTest,
274        FloatingPointComparisonWithinFractionOrMargin) {
275   const FieldDescriptor* field_float =
276       descriptor_->FindFieldByName("optional_float");
277   const FieldDescriptor* field_double =
278       descriptor_->FindFieldByName("optional_double");
279 
280   message_1_.set_optional_float(100.0f);
281   message_2_.set_optional_float(109.9f);
282   message_1_.set_optional_double(100.0);
283   message_2_.set_optional_double(109.9);
284 
285   comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE);
286   EXPECT_EQ(FieldComparator::DIFFERENT,
287             comparator_.Compare(message_1_, message_2_, field_float, -1, -1,
288                                 nullptr));
289   EXPECT_EQ(FieldComparator::DIFFERENT,
290             comparator_.Compare(message_1_, message_2_, field_double, -1, -1,
291                                 nullptr));
292 
293   // Should fail since the fraction is too low.
294   comparator_.SetFractionAndMargin(field_float, 0.01, 0.0);
295   comparator_.SetFractionAndMargin(field_double, 0.01, 0.0);
296 
297   EXPECT_EQ(FieldComparator::DIFFERENT,
298             comparator_.Compare(message_1_, message_2_, field_float, -1, -1,
299                                 nullptr));
300   EXPECT_EQ(FieldComparator::DIFFERENT,
301             comparator_.Compare(message_1_, message_2_, field_double, -1, -1,
302                                 nullptr));
303 
304   // Should fail since the margin is too low.
305   comparator_.SetFractionAndMargin(field_float, 0.0, 9.0);
306   comparator_.SetFractionAndMargin(field_double, 0.0, 9.0);
307   EXPECT_EQ(FieldComparator::DIFFERENT,
308             comparator_.Compare(message_1_, message_2_, field_float, -1, -1,
309                                 nullptr));
310   EXPECT_EQ(FieldComparator::DIFFERENT,
311             comparator_.Compare(message_1_, message_2_, field_double, -1, -1,
312                                 nullptr));
313 
314   // Should succeed since the fraction is high enough.
315   comparator_.SetFractionAndMargin(field_float, 0.2, 0.0);
316   comparator_.SetFractionAndMargin(field_double, 0.2, 0.0);
317   EXPECT_EQ(FieldComparator::SAME,
318             comparator_.Compare(message_1_, message_2_, field_float, -1, -1,
319                                 nullptr));
320   EXPECT_EQ(FieldComparator::SAME,
321             comparator_.Compare(message_1_, message_2_, field_double, -1, -1,
322                                 nullptr));
323 
324   // Should succeed since the margin is high enough.
325   comparator_.SetFractionAndMargin(field_float, 0.0, 10.0);
326   comparator_.SetFractionAndMargin(field_double, 0.0, 10.0);
327   EXPECT_EQ(FieldComparator::SAME,
328             comparator_.Compare(message_1_, message_2_, field_float, -1, -1,
329                                 nullptr));
330   EXPECT_EQ(FieldComparator::SAME,
331             comparator_.Compare(message_1_, message_2_, field_double, -1, -1,
332                                 nullptr));
333 
334   // Setting values for one of the fields should not affect the other.
335   comparator_.SetFractionAndMargin(field_double, 0.0, 0.0);
336   EXPECT_EQ(FieldComparator::SAME,
337             comparator_.Compare(message_1_, message_2_, field_float, -1, -1,
338                                 nullptr));
339   EXPECT_EQ(FieldComparator::DIFFERENT,
340             comparator_.Compare(message_1_, message_2_, field_double, -1, -1,
341                                 nullptr));
342 
343   // +inf should be equal even though they are not technically within margin or
344   // fraction.
345   message_1_.set_optional_float(std::numeric_limits<float>::infinity());
346   message_2_.set_optional_float(std::numeric_limits<float>::infinity());
347   message_1_.set_optional_double(std::numeric_limits<double>::infinity());
348   message_2_.set_optional_double(std::numeric_limits<double>::infinity());
349   comparator_.SetFractionAndMargin(field_float, 0.0, 0.0);
350   comparator_.SetFractionAndMargin(field_double, 0.0, 0.0);
351   EXPECT_EQ(FieldComparator::SAME,
352             comparator_.Compare(message_1_, message_2_, field_float, -1, -1,
353                                 nullptr));
354   EXPECT_EQ(FieldComparator::SAME,
355             comparator_.Compare(message_1_, message_2_, field_double, -1, -1,
356                                 nullptr));
357 
358   // -inf should be equal even though they are not technically within margin or
359   // fraction.
360   message_1_.set_optional_float(-std::numeric_limits<float>::infinity());
361   message_2_.set_optional_float(-std::numeric_limits<float>::infinity());
362   message_1_.set_optional_double(-std::numeric_limits<double>::infinity());
363   message_2_.set_optional_double(-std::numeric_limits<double>::infinity());
364   comparator_.SetFractionAndMargin(field_float, 0.0, 0.0);
365   comparator_.SetFractionAndMargin(field_double, 0.0, 0.0);
366   EXPECT_EQ(FieldComparator::SAME,
367             comparator_.Compare(message_1_, message_2_, field_float, -1, -1,
368                                 nullptr));
369   EXPECT_EQ(FieldComparator::SAME,
370             comparator_.Compare(message_1_, message_2_, field_double, -1, -1,
371                                 nullptr));
372 
373   // Finite values and inf should not be equal, even for a positive fraction.
374   message_1_.set_optional_float(std::numeric_limits<float>::infinity());
375   message_2_.set_optional_float(0.0f);
376   message_1_.set_optional_double(std::numeric_limits<double>::infinity());
377   message_2_.set_optional_double(0.0);
378   comparator_.SetFractionAndMargin(field_float, 0.1, 0.0);
379   comparator_.SetFractionAndMargin(field_double, 0.1, 0.0);
380   EXPECT_EQ(FieldComparator::DIFFERENT,
381             comparator_.Compare(message_1_, message_2_, field_float, -1, -1,
382                                 nullptr));
383   EXPECT_EQ(FieldComparator::DIFFERENT,
384             comparator_.Compare(message_1_, message_2_, field_double, -1, -1,
385                                 nullptr));
386 }
387 
TEST_F(DefaultFieldComparatorTest,FloatingPointComparisonWithinDefaultFractionOrMargin)388 TEST_F(DefaultFieldComparatorTest,
389        FloatingPointComparisonWithinDefaultFractionOrMargin) {
390   const FieldDescriptor* field_float =
391       descriptor_->FindFieldByName("optional_float");
392   const FieldDescriptor* field_double =
393       descriptor_->FindFieldByName("optional_double");
394 
395   message_1_.set_optional_float(100.0f);
396   message_2_.set_optional_float(109.9f);
397   message_1_.set_optional_double(100.0);
398   message_2_.set_optional_double(109.9);
399 
400   comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE);
401   EXPECT_EQ(FieldComparator::DIFFERENT,
402             comparator_.Compare(message_1_, message_2_, field_float, -1, -1,
403                                 nullptr));
404   EXPECT_EQ(FieldComparator::DIFFERENT,
405             comparator_.Compare(message_1_, message_2_, field_double, -1, -1,
406                                 nullptr));
407 
408   // Set default fraction and margin.
409   comparator_.SetDefaultFractionAndMargin(0.01, 0.0);
410 
411   // Float comparisons should fail since the fraction is too low.
412   EXPECT_EQ(FieldComparator::DIFFERENT,
413             comparator_.Compare(message_1_, message_2_, field_float, -1, -1,
414                                 nullptr));
415   EXPECT_EQ(FieldComparator::DIFFERENT,
416             comparator_.Compare(message_1_, message_2_, field_double, -1, -1,
417                                 nullptr));
418 
419   // Set field-specific fraction and margin for one field (field_float) but not
420   // the other (field_double)
421   comparator_.SetFractionAndMargin(field_float, 0.2, 0.0);
422 
423   // The field with the override should succeed, since its field-specific
424   // fraction is high enough.
425   EXPECT_EQ(FieldComparator::SAME,
426             comparator_.Compare(message_1_, message_2_, field_float, -1, -1,
427                                 nullptr));
428   // The field with no override should fail, since the default fraction is too
429   // low
430   EXPECT_EQ(FieldComparator::DIFFERENT,
431             comparator_.Compare(message_1_, message_2_, field_double, -1, -1,
432                                 nullptr));
433 
434   // Set the default fraction and margin high enough so that fields that use
435   // the default should succeed
436   comparator_.SetDefaultFractionAndMargin(0.2, 0.0);
437   EXPECT_EQ(FieldComparator::SAME,
438             comparator_.Compare(message_1_, message_2_, field_double, -1, -1,
439                                 nullptr));
440 
441   // The field with an override should still be OK
442   EXPECT_EQ(FieldComparator::SAME,
443             comparator_.Compare(message_1_, message_2_, field_float, -1, -1,
444                                 nullptr));
445 
446   // Set fraction and margin for the field with an override to be too low
447   comparator_.SetFractionAndMargin(field_float, 0.01, 0.0);
448 
449   // Now our default is high enough but field_float's override is too low.
450   EXPECT_EQ(FieldComparator::DIFFERENT,
451             comparator_.Compare(message_1_, message_2_, field_float, -1, -1,
452                                 nullptr));
453   EXPECT_EQ(FieldComparator::SAME,
454             comparator_.Compare(message_1_, message_2_, field_double, -1, -1,
455                                 nullptr));
456 }
457 
458 // Simple test checking whether we compare values at correct indices.
TEST_F(DefaultFieldComparatorTest,RepeatedFieldComparison)459 TEST_F(DefaultFieldComparatorTest, RepeatedFieldComparison) {
460   const FieldDescriptor* field =
461       descriptor_->FindFieldByName("repeated_string");
462 
463   message_1_.add_repeated_string("foo");
464   message_1_.add_repeated_string("bar");
465   message_2_.add_repeated_string("bar");
466   message_2_.add_repeated_string("baz");
467 
468   EXPECT_EQ(FieldComparator::DIFFERENT,
469             comparator_.Compare(message_1_, message_2_, field, 0, 0, nullptr));
470   EXPECT_EQ(FieldComparator::DIFFERENT,
471             comparator_.Compare(message_1_, message_2_, field, 1, 1, nullptr));
472   EXPECT_EQ(FieldComparator::SAME,
473             comparator_.Compare(message_1_, message_2_, field, 1, 0, nullptr));
474 }
475 
476 }  // namespace
477 }  // namespace util
478 }  // namespace protobuf
479 }  // namespace google
480