1 // 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 (at) 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> 37 #include <google/protobuf/stubs/mathutil.h> 38 // 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. 44 #include <gtest/gtest.h> 45 namespace google { 46 namespace protobuf { 47 namespace util { 48 namespace { 49 50 using protobuf_unittest::TestAllTypes; 51 52 class 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 64 TEST_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 71 TEST_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 78 TEST_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 85 TEST_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 98 TEST_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 111 TEST_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 125 TEST_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 139 TEST_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 153 TEST_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 167 TEST_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 181 TEST_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 210 TEST_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 249 TEST_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 296 TEST_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 397 TEST_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. 468 TEST_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 489