blob: 6fd631d860c8fc63e0279ed817e1941f2597e162 [file] [log] [blame]
Feng Xiaoe96ff302015-06-15 18:21:48 -07001// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc. All rights reserved.
3// https://developers.google.com/protocol-buffers/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15// * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31// Author: ksroka@google.com (Krzysztof Sroka)
32
33#include <google/protobuf/util/field_comparator.h>
34
35#include <google/protobuf/unittest.pb.h>
36#include <google/protobuf/descriptor.h>
Jisi Liu46e8ff62015-10-05 11:59:43 -070037#include <google/protobuf/stubs/mathutil.h>
Feng Xiaoe841bac2015-12-11 17:09:20 -080038// This gtest header is put after mathutil.h intentionally. We have to do
39// this because mathutil.h includes mathlimits.h which requires cmath not
40// being included to compile on some versions of gcc:
41// https://github.com/google/protobuf/blob/818c5eee08840355d70d2f3bdf1a2f17986a5e70/src/google/protobuf/stubs/mathlimits.h#L48
42// and the opensource version gtest.h header includes cmath transitively
43// somehow.
Feng Xiao9659ea92015-11-02 12:39:27 -080044#include <gtest/gtest.h>
Feng Xiaoe96ff302015-06-15 18:21:48 -070045namespace google {
46namespace protobuf {
47namespace util {
48namespace {
49
50using protobuf_unittest::TestAllTypes;
51
52class DefaultFieldComparatorTest : public ::testing::Test {
53 protected:
54 void SetUp() {
55 descriptor_ = TestAllTypes::descriptor();
56 }
57
58 const Descriptor* descriptor_;
59 DefaultFieldComparator comparator_;
60 TestAllTypes message_1_;
61 TestAllTypes message_2_;
62};
63
64TEST_F(DefaultFieldComparatorTest, RecursesIntoGroup) {
65 const FieldDescriptor* field =
66 descriptor_->FindFieldByName("optionalgroup");
67 EXPECT_EQ(FieldComparator::RECURSE,
68 comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
69}
70
71TEST_F(DefaultFieldComparatorTest, RecursesIntoNestedMessage) {
72 const FieldDescriptor* field =
73 descriptor_->FindFieldByName("optional_nested_message");
74 EXPECT_EQ(FieldComparator::RECURSE,
75 comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
76}
77
78TEST_F(DefaultFieldComparatorTest, RecursesIntoForeignMessage) {
79 const FieldDescriptor* field =
80 descriptor_->FindFieldByName("optional_foreign_message");
81 EXPECT_EQ(FieldComparator::RECURSE,
82 comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
83}
84
85TEST_F(DefaultFieldComparatorTest, Int32Comparison) {
86 const FieldDescriptor* field = descriptor_->FindFieldByName("optional_int32");
87 message_1_.set_optional_int32(1);
88 message_2_.set_optional_int32(1);
89
90 EXPECT_EQ(FieldComparator::SAME,
91 comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
92
93 message_2_.set_optional_int32(-1);
94 EXPECT_EQ(FieldComparator::DIFFERENT,
95 comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
96}
97
98TEST_F(DefaultFieldComparatorTest, Int64Comparison) {
99 const FieldDescriptor* field = descriptor_->FindFieldByName("optional_int64");
100 message_1_.set_optional_int64(1L);
101 message_2_.set_optional_int64(1L);
102
103 EXPECT_EQ(FieldComparator::SAME,
104 comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
105
106 message_2_.set_optional_int64(-1L);
107 EXPECT_EQ(FieldComparator::DIFFERENT,
108 comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
109}
110
111TEST_F(DefaultFieldComparatorTest, UInt32Comparison) {
112 const FieldDescriptor* field =
113 descriptor_->FindFieldByName("optional_uint32");
114 message_1_.set_optional_uint32(1);
115 message_2_.set_optional_uint32(1);
116
117 EXPECT_EQ(FieldComparator::SAME,
118 comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
119
120 message_2_.set_optional_uint32(2);
121 EXPECT_EQ(FieldComparator::DIFFERENT,
122 comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
123}
124
125TEST_F(DefaultFieldComparatorTest, UInt64Comparison) {
126 const FieldDescriptor* field =
127 descriptor_->FindFieldByName("optional_uint64");
128 message_1_.set_optional_uint64(1L);
129 message_2_.set_optional_uint64(1L);
130
131 EXPECT_EQ(FieldComparator::SAME,
132 comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
133
134 message_2_.set_optional_uint64(2L);
135 EXPECT_EQ(FieldComparator::DIFFERENT,
136 comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
137}
138
139TEST_F(DefaultFieldComparatorTest, BooleanComparison) {
140 const FieldDescriptor* field =
141 descriptor_->FindFieldByName("optional_bool");
142 message_1_.set_optional_bool(true);
143 message_2_.set_optional_bool(true);
144
145 EXPECT_EQ(FieldComparator::SAME,
146 comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
147
148 message_2_.set_optional_bool(false);
149 EXPECT_EQ(FieldComparator::DIFFERENT,
150 comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
151}
152
153TEST_F(DefaultFieldComparatorTest, EnumComparison) {
154 const FieldDescriptor* field =
155 descriptor_->FindFieldByName("optional_nested_enum");
156 message_1_.set_optional_nested_enum(TestAllTypes::BAR);
157 message_2_.set_optional_nested_enum(TestAllTypes::BAR);
158
159 EXPECT_EQ(FieldComparator::SAME,
160 comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
161
162 message_2_.set_optional_nested_enum(TestAllTypes::BAZ);
163 EXPECT_EQ(FieldComparator::DIFFERENT,
164 comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
165}
166
167TEST_F(DefaultFieldComparatorTest, StringComparison) {
168 const FieldDescriptor* field =
169 descriptor_->FindFieldByName("optional_string");
170 message_1_.set_optional_string("foo");
171 message_2_.set_optional_string("foo");
172
173 EXPECT_EQ(FieldComparator::SAME,
174 comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
175
176 message_2_.set_optional_string("bar");
177 EXPECT_EQ(FieldComparator::DIFFERENT,
178 comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
179}
180
181TEST_F(DefaultFieldComparatorTest, FloatingPointComparisonExact) {
182 const FieldDescriptor* field_float =
183 descriptor_->FindFieldByName("optional_float");
184 const FieldDescriptor* field_double =
185 descriptor_->FindFieldByName("optional_double");
186
187 message_1_.set_optional_float(0.1f);
188 message_2_.set_optional_float(0.1f);
189 message_1_.set_optional_double(0.1);
190 message_2_.set_optional_double(0.1);
191
192 EXPECT_EQ(FieldComparator::SAME,
193 comparator_.Compare(message_1_, message_2_,
194 field_float, -1, -1, NULL));
195 EXPECT_EQ(FieldComparator::SAME,
196 comparator_.Compare(message_1_, message_2_,
197 field_double, -1, -1, NULL));
198
199 message_2_.set_optional_float(0.2f);
200 message_2_.set_optional_double(0.2);
201
202 EXPECT_EQ(FieldComparator::DIFFERENT,
203 comparator_.Compare(message_1_, message_2_,
204 field_float, -1, -1, NULL));
205 EXPECT_EQ(FieldComparator::DIFFERENT,
206 comparator_.Compare(message_1_, message_2_,
207 field_double, -1, -1, NULL));
208}
209
210TEST_F(DefaultFieldComparatorTest, FloatingPointComparisonApproximate) {
211 const FieldDescriptor* field_float =
212 descriptor_->FindFieldByName("optional_float");
213 const FieldDescriptor* field_double =
214 descriptor_->FindFieldByName("optional_double");
215
216 message_1_.set_optional_float(2.300005f);
217 message_2_.set_optional_float(2.300006f);
218 message_1_.set_optional_double(2.3000000000000003);
219 message_2_.set_optional_double(2.3000000000000007);
220
221 // Approximate comparison depends on MathUtil, so we assert on MathUtil
222 // results first to check if that's where the failure was introduced.
223 ASSERT_NE(message_1_.optional_float(), message_2_.optional_float());
224 ASSERT_NE(message_1_.optional_double(), message_2_.optional_double());
225 ASSERT_TRUE(MathUtil::AlmostEquals(message_1_.optional_float(),
226 message_2_.optional_float()));
227 ASSERT_TRUE(MathUtil::AlmostEquals(message_1_.optional_double(),
228 message_2_.optional_double()));
229
230 // DefaultFieldComparator's default float comparison mode is EXACT.
231 ASSERT_EQ(DefaultFieldComparator::EXACT, comparator_.float_comparison());
232 EXPECT_EQ(FieldComparator::DIFFERENT,
233 comparator_.Compare(message_1_, message_2_,
234 field_float, -1, -1, NULL));
235 EXPECT_EQ(FieldComparator::DIFFERENT,
236 comparator_.Compare(message_1_, message_2_,
237 field_double, -1, -1, NULL));
238
239 comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE);
240
241 EXPECT_EQ(FieldComparator::SAME,
242 comparator_.Compare(message_1_, message_2_,
243 field_float, -1, -1, NULL));
244 EXPECT_EQ(FieldComparator::SAME,
245 comparator_.Compare(message_1_, message_2_,
246 field_double, -1, -1, NULL));
247}
248
249TEST_F(DefaultFieldComparatorTest, FloatingPointComparisonTreatNaNsAsEqual) {
250 const FieldDescriptor* field_float =
251 descriptor_->FindFieldByName("optional_float");
252 const FieldDescriptor* field_double =
253 descriptor_->FindFieldByName("optional_double");
254
255 message_1_.set_optional_float(MathLimits<float>::kNaN);
256 message_2_.set_optional_float(MathLimits<float>::kNaN);
257 message_1_.set_optional_double(MathLimits<double>::kNaN);
258 message_2_.set_optional_double(MathLimits<double>::kNaN);
259
260 // DefaultFieldComparator's default float comparison mode is EXACT with
261 // treating NaNs as different.
262 ASSERT_EQ(DefaultFieldComparator::EXACT, comparator_.float_comparison());
263 ASSERT_EQ(false, comparator_.treat_nan_as_equal());
264 EXPECT_EQ(FieldComparator::DIFFERENT,
265 comparator_.Compare(message_1_, message_2_,
266 field_float, -1, -1, NULL));
267 EXPECT_EQ(FieldComparator::DIFFERENT,
268 comparator_.Compare(message_1_, message_2_,
269 field_double, -1, -1, NULL));
270 comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE);
271 EXPECT_EQ(FieldComparator::DIFFERENT,
272 comparator_.Compare(message_1_, message_2_,
273 field_float, -1, -1, NULL));
274 EXPECT_EQ(FieldComparator::DIFFERENT,
275 comparator_.Compare(message_1_, message_2_,
276 field_double, -1, -1, NULL));
277
278 comparator_.set_treat_nan_as_equal(true);
279 ASSERT_EQ(true, comparator_.treat_nan_as_equal());
280 comparator_.set_float_comparison(DefaultFieldComparator::EXACT);
281 EXPECT_EQ(FieldComparator::SAME,
282 comparator_.Compare(message_1_, message_2_,
283 field_float, -1, -1, NULL));
284 EXPECT_EQ(FieldComparator::SAME,
285 comparator_.Compare(message_1_, message_2_,
286 field_double, -1, -1, NULL));
287 comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE);
288 EXPECT_EQ(FieldComparator::SAME,
289 comparator_.Compare(message_1_, message_2_,
290 field_float, -1, -1, NULL));
291 EXPECT_EQ(FieldComparator::SAME,
292 comparator_.Compare(message_1_, message_2_,
293 field_double, -1, -1, NULL));
294}
295
296TEST_F(DefaultFieldComparatorTest,
297 FloatingPointComparisonWithinFractionOrMargin) {
298 const FieldDescriptor* field_float =
299 descriptor_->FindFieldByName("optional_float");
300 const FieldDescriptor* field_double =
301 descriptor_->FindFieldByName("optional_double");
302
303 message_1_.set_optional_float(100.0f);
304 message_2_.set_optional_float(109.9f);
305 message_1_.set_optional_double(100.0);
306 message_2_.set_optional_double(109.9);
307
308 comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE);
309 EXPECT_EQ(FieldComparator::DIFFERENT,
310 comparator_.Compare(message_1_, message_2_,
311 field_float, -1, -1, NULL));
312 EXPECT_EQ(FieldComparator::DIFFERENT,
313 comparator_.Compare(message_1_, message_2_,
314 field_double, -1, -1, NULL));
315
316 // Should fail since the fraction is too low.
317 comparator_.SetFractionAndMargin(field_float, 0.01, 0.0);
318 comparator_.SetFractionAndMargin(field_double, 0.01, 0.0);
319
320 EXPECT_EQ(FieldComparator::DIFFERENT,
321 comparator_.Compare(message_1_, message_2_,
322 field_float, -1, -1, NULL));
323 EXPECT_EQ(FieldComparator::DIFFERENT,
324 comparator_.Compare(message_1_, message_2_,
325 field_double, -1, -1, NULL));
326
327 // Should fail since the margin is too low.
328 comparator_.SetFractionAndMargin(field_float, 0.0, 9.0);
329 comparator_.SetFractionAndMargin(field_double, 0.0, 9.0);
330 EXPECT_EQ(FieldComparator::DIFFERENT,
331 comparator_.Compare(message_1_, message_2_,
332 field_float, -1, -1, NULL));
333 EXPECT_EQ(FieldComparator::DIFFERENT,
334 comparator_.Compare(message_1_, message_2_,
335 field_double, -1, -1, NULL));
336
337 // Should succeed since the fraction is high enough.
338 comparator_.SetFractionAndMargin(field_float, 0.2, 0.0);
339 comparator_.SetFractionAndMargin(field_double, 0.2, 0.0);
340 EXPECT_EQ(FieldComparator::SAME,
341 comparator_.Compare(message_1_, message_2_,
342 field_float, -1, -1, NULL));
343 EXPECT_EQ(FieldComparator::SAME,
344 comparator_.Compare(message_1_, message_2_,
345 field_double, -1, -1, NULL));
346
347 // Should succeed since the margin is high enough.
348 comparator_.SetFractionAndMargin(field_float, 0.0, 10.0);
349 comparator_.SetFractionAndMargin(field_double, 0.0, 10.0);
350 EXPECT_EQ(FieldComparator::SAME,
351 comparator_.Compare(message_1_, message_2_,
352 field_float, -1, -1, NULL));
353 EXPECT_EQ(FieldComparator::SAME,
354 comparator_.Compare(message_1_, message_2_,
355 field_double, -1, -1, NULL));
356
357 // Setting values for one of the fields should not affect the other.
358 comparator_.SetFractionAndMargin(field_double, 0.0, 0.0);
359 EXPECT_EQ(FieldComparator::SAME,
360 comparator_.Compare(message_1_, message_2_,
361 field_float, -1, -1, NULL));
362 EXPECT_EQ(FieldComparator::DIFFERENT,
363 comparator_.Compare(message_1_, message_2_,
364 field_double, -1, -1, NULL));
365
366 // +inf should be equal even though they are not technically within margin or
367 // fraction.
368 message_1_.set_optional_float(numeric_limits<float>::infinity());
369 message_2_.set_optional_float(numeric_limits<float>::infinity());
370 message_1_.set_optional_double(numeric_limits<double>::infinity());
371 message_2_.set_optional_double(numeric_limits<double>::infinity());
372 comparator_.SetFractionAndMargin(field_float, 0.0, 0.0);
373 comparator_.SetFractionAndMargin(field_double, 0.0, 0.0);
374 EXPECT_EQ(FieldComparator::SAME,
375 comparator_.Compare(message_1_, message_2_,
376 field_float, -1, -1, NULL));
377 EXPECT_EQ(FieldComparator::SAME,
378 comparator_.Compare(message_1_, message_2_,
379 field_double, -1, -1, NULL));
380
381 // -inf should be equal even though they are not technically within margin or
382 // fraction.
383 message_1_.set_optional_float(-numeric_limits<float>::infinity());
384 message_2_.set_optional_float(-numeric_limits<float>::infinity());
385 message_1_.set_optional_double(-numeric_limits<double>::infinity());
386 message_2_.set_optional_double(-numeric_limits<double>::infinity());
387 comparator_.SetFractionAndMargin(field_float, 0.0, 0.0);
388 comparator_.SetFractionAndMargin(field_double, 0.0, 0.0);
389 EXPECT_EQ(FieldComparator::SAME,
390 comparator_.Compare(message_1_, message_2_,
391 field_float, -1, -1, NULL));
392 EXPECT_EQ(FieldComparator::SAME,
393 comparator_.Compare(message_1_, message_2_,
394 field_double, -1, -1, NULL));
395}
396
397TEST_F(DefaultFieldComparatorTest,
398 FloatingPointComparisonWithinDefaultFractionOrMargin) {
399 const FieldDescriptor* field_float =
400 descriptor_->FindFieldByName("optional_float");
401 const FieldDescriptor* field_double =
402 descriptor_->FindFieldByName("optional_double");
403
404 message_1_.set_optional_float(100.0f);
405 message_2_.set_optional_float(109.9f);
406 message_1_.set_optional_double(100.0);
407 message_2_.set_optional_double(109.9);
408
409 comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE);
410 EXPECT_EQ(FieldComparator::DIFFERENT,
411 comparator_.Compare(message_1_, message_2_,
412 field_float, -1, -1, NULL));
413 EXPECT_EQ(FieldComparator::DIFFERENT,
414 comparator_.Compare(message_1_, message_2_,
415 field_double, -1, -1, NULL));
416
417 // Set default fraction and margin.
418 comparator_.SetDefaultFractionAndMargin(0.01, 0.0);
419
420 // Float comparisons should fail since the fraction is too low.
421 EXPECT_EQ(FieldComparator::DIFFERENT,
422 comparator_.Compare(message_1_, message_2_,
423 field_float, -1, -1, NULL));
424 EXPECT_EQ(FieldComparator::DIFFERENT,
425 comparator_.Compare(message_1_, message_2_,
426 field_double, -1, -1, NULL));
427
428 // Set field-specific fraction and margin for one field (field_float) but not
429 // the other (field_double)
430 comparator_.SetFractionAndMargin(field_float, 0.2, 0.0);
431
432 // The field with the override should succeed, since its field-specific
433 // fraction is high enough.
434 EXPECT_EQ(FieldComparator::SAME,
435 comparator_.Compare(message_1_, message_2_,
436 field_float, -1, -1, NULL));
437 // The field with no override should fail, since the default fraction is too
438 // low
439 EXPECT_EQ(FieldComparator::DIFFERENT,
440 comparator_.Compare(message_1_, message_2_,
441 field_double, -1, -1, NULL));
442
443 // Set the default fraction and margin high enough so that fields that use
444 // the default should succeed
445 comparator_.SetDefaultFractionAndMargin(0.2, 0.0);
446 EXPECT_EQ(FieldComparator::SAME,
447 comparator_.Compare(message_1_, message_2_,
448 field_double, -1, -1, NULL));
449
450 // The field with an override should still be OK
451 EXPECT_EQ(FieldComparator::SAME,
452 comparator_.Compare(message_1_, message_2_,
453 field_float, -1, -1, NULL));
454
455 // Set fraction and margin for the field with an override to be too low
456 comparator_.SetFractionAndMargin(field_float, 0.01, 0.0);
457
458 // Now our default is high enough but field_float's override is too low.
459 EXPECT_EQ(FieldComparator::DIFFERENT,
460 comparator_.Compare(message_1_, message_2_,
461 field_float, -1, -1, NULL));
462 EXPECT_EQ(FieldComparator::SAME,
463 comparator_.Compare(message_1_, message_2_,
464 field_double, -1, -1, NULL));
465}
466
467// Simple test checking whether we compare values at correct indices.
468TEST_F(DefaultFieldComparatorTest, RepeatedFieldComparison) {
469 const FieldDescriptor* field =
470 descriptor_->FindFieldByName("repeated_string");
471
472 message_1_.add_repeated_string("foo");
473 message_1_.add_repeated_string("bar");
474 message_2_.add_repeated_string("bar");
475 message_2_.add_repeated_string("baz");
476
477 EXPECT_EQ(FieldComparator::DIFFERENT,
478 comparator_.Compare(message_1_, message_2_, field, 0, 0, NULL));
479 EXPECT_EQ(FieldComparator::DIFFERENT,
480 comparator_.Compare(message_1_, message_2_, field, 1, 1, NULL));
481 EXPECT_EQ(FieldComparator::SAME,
482 comparator_.Compare(message_1_, message_2_, field, 1, 0, NULL));
483}
484
485} // namespace util
486} // namespace protobuf
487} // namespace
488} // namespace google