1 /* 2 * Copyright (c) 2016 Google, Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.google.common.truth.extensions.proto; 17 18 import static com.google.common.base.Preconditions.checkNotNull; 19 import static com.google.common.truth.Truth.assertThat; 20 import static org.junit.Assert.fail; 21 22 import com.google.common.collect.ImmutableMap; 23 import com.google.protobuf.Any; 24 import com.google.protobuf.Descriptors.Descriptor; 25 import com.google.protobuf.Descriptors.FieldDescriptor; 26 import com.google.protobuf.DynamicMessage; 27 import com.google.protobuf.ExtensionRegistry; 28 import com.google.protobuf.InvalidProtocolBufferException; 29 import com.google.protobuf.Message; 30 import com.google.protobuf.UnknownFieldSet; 31 import java.util.Collection; 32 import java.util.Map; 33 import org.junit.Test; 34 import org.junit.runner.RunWith; 35 import org.junit.runners.Parameterized; 36 import org.junit.runners.Parameterized.Parameters; 37 38 /** Unit tests for {@link ProtoSubject}. */ 39 @RunWith(Parameterized.class) 40 public class ProtoSubjectTest extends ProtoSubjectTestBase { 41 42 @Parameters(name = "{0}") parameters()43 public static Collection<Object[]> parameters() { 44 return ProtoSubjectTestBase.parameters(); 45 } 46 ProtoSubjectTest(TestType testType)47 public ProtoSubjectTest(TestType testType) { 48 super(testType); 49 } 50 51 @Test testDifferentClasses()52 public void testDifferentClasses() throws InvalidProtocolBufferException { 53 Message message = parse("o_int: 3"); 54 DynamicMessage dynamicMessage = 55 DynamicMessage.parseFrom(message.getDescriptorForType(), message.toByteString()); 56 57 expectThat(message).isEqualTo(dynamicMessage); 58 expectThat(dynamicMessage).isEqualTo(message); 59 } 60 61 @Test testDifferentDynamicDescriptors()62 public void testDifferentDynamicDescriptors() throws InvalidProtocolBufferException { 63 // Only test once. 64 if (!isProto3()) { 65 return; 66 } 67 68 DynamicMessage message1 = 69 DynamicMessage.parseFrom( 70 TestMessage2.getDescriptor(), 71 TestMessage2.newBuilder().setOInt(43).build().toByteString()); 72 DynamicMessage message2 = 73 DynamicMessage.parseFrom( 74 TestMessage3.getDescriptor(), 75 TestMessage3.newBuilder().setOInt(43).build().toByteString()); 76 77 expectFailureWhenTesting().that(message1).isEqualTo(message2); 78 expectThatFailure().hasMessageThat().contains("different descriptors"); 79 } 80 81 @Test testFullDiffOnlyWhenRelevant()82 public void testFullDiffOnlyWhenRelevant() { 83 // There are no matches, so 'Full diff' should not be printed. 84 expectFailureWhenTesting().that(parse("o_int: 3")).isEqualTo(parse("o_int: 4")); 85 expectThatFailure().hasMessageThat().doesNotContain("Full diff"); 86 87 // r_string is matched, so the 'Full diff' contains extra information. 88 expectFailureWhenTesting() 89 .that(parse("o_int: 3 r_string: 'abc'")) 90 .isEqualTo(parse("o_int: 4 r_string: 'abc'")); 91 expectThatFailure().hasMessageThat().contains("Full diff"); 92 } 93 94 @Test testIgnoringFieldAbsence()95 public void testIgnoringFieldAbsence() { 96 Message message = parse("o_int: 3"); 97 Message diffMessage = parse("o_int: 3 o_enum: DEFAULT"); 98 99 // Make sure the implementation is reflexive. 100 if (isProto3()) { 101 expectThat(diffMessage).isEqualTo(message); 102 expectThat(message).isEqualTo(diffMessage); 103 } else { 104 expectThat(diffMessage).isNotEqualTo(message); 105 expectThat(message).isNotEqualTo(diffMessage); 106 } 107 expectThat(diffMessage).ignoringFieldAbsence().isEqualTo(message); 108 expectThat(message).ignoringFieldAbsence().isEqualTo(diffMessage); 109 110 if (!isProto3()) { 111 Message customDefaultMessage = parse("o_int: 3"); 112 Message diffCustomDefaultMessage = parse("o_int: 3 o_long_defaults_to_42: 42"); 113 114 expectThat(diffCustomDefaultMessage).isNotEqualTo(customDefaultMessage); 115 expectThat(diffCustomDefaultMessage).ignoringFieldAbsence().isEqualTo(customDefaultMessage); 116 expectThat(customDefaultMessage).isNotEqualTo(diffCustomDefaultMessage); 117 expectThat(customDefaultMessage).ignoringFieldAbsence().isEqualTo(diffCustomDefaultMessage); 118 } 119 120 if (!isProto3()) { 121 expectFailureWhenTesting().that(diffMessage).isEqualTo(message); 122 expectIsEqualToFailed(); 123 expectThatFailure().hasMessageThat().contains("added: o_enum: DEFAULT"); 124 } 125 126 expectFailureWhenTesting().that(diffMessage).ignoringFieldAbsence().isNotEqualTo(message); 127 expectIsNotEqualToFailed(); 128 expectThatFailure().hasMessageThat().contains("matched: o_int: 3"); 129 if (!isProto3()) { 130 // Proto 3 doesn't cover the field at all when it's not set. 131 expectThatFailure().hasMessageThat().contains("matched: o_enum: DEFAULT"); 132 } 133 } 134 135 @Test testIgnoringFieldAbsence_anyMessage()136 public void testIgnoringFieldAbsence_anyMessage() { 137 Message message = parse("o_int: 3"); 138 Message diffMessage = parse("o_int: 3 o_any_message: {}"); 139 140 expectThat(diffMessage).ignoringFieldAbsence().isEqualTo(message); 141 expectThat(message).ignoringFieldAbsence().isEqualTo(diffMessage); 142 143 expectFailureWhenTesting().that(diffMessage).isEqualTo(message); 144 expectIsEqualToFailed(); 145 expectThatFailure().hasMessageThat().contains("added: o_any_message:"); 146 147 expectFailureWhenTesting().that(diffMessage).ignoringFieldAbsence().isNotEqualTo(message); 148 expectIsNotEqualToFailed(); 149 expectThatFailure().hasMessageThat().contains("matched: o_int: 3"); 150 expectThatFailure().hasMessageThat().contains("matched: o_any_message"); 151 } 152 153 @Test testIgnoringFieldAbsence_scoped()154 public void testIgnoringFieldAbsence_scoped() { 155 Message message = parse("o_sub_test_message: { o_test_message: {} }"); 156 Message emptyMessage = parse(""); 157 Message partialMessage = parse("o_sub_test_message: {}"); 158 159 // All three are equal if we ignore field absence entirely. 160 expectThat(emptyMessage).ignoringFieldAbsence().isEqualTo(message); 161 expectThat(partialMessage).ignoringFieldAbsence().isEqualTo(message); 162 163 // If we ignore only o_sub_test_message.o_test_message, only the partial message is equal. 164 FieldDescriptor subTestMessageField = getFieldDescriptor("o_sub_test_message"); 165 FieldDescriptor subTestMessageTestMessageField = 166 checkNotNull(subTestMessageField.getMessageType().findFieldByName("o_test_message")); 167 expectThat(partialMessage) 168 .ignoringFieldAbsenceOfFieldDescriptors(subTestMessageTestMessageField) 169 .isEqualTo(message); 170 expectFailureWhenTesting() 171 .that(emptyMessage) 172 .ignoringFieldAbsenceOfFieldDescriptors(subTestMessageTestMessageField) 173 .isEqualTo(message); 174 expectIsEqualToFailed(); 175 expectThatFailure().hasMessageThat().contains("deleted: o_sub_test_message"); 176 177 // But, we can ignore both. 178 expectThat(partialMessage) 179 .ignoringFieldAbsenceOfFieldDescriptors(subTestMessageField) 180 .ignoringFieldAbsenceOfFieldDescriptors(subTestMessageTestMessageField) 181 .isEqualTo(message); 182 expectThat(partialMessage) 183 .ignoringFieldAbsenceOfFieldDescriptors(subTestMessageField, subTestMessageTestMessageField) 184 .isEqualTo(message); 185 expectThat(emptyMessage) 186 .ignoringFieldAbsenceOfFieldDescriptors(subTestMessageField) 187 .ignoringFieldAbsenceOfFieldDescriptors(subTestMessageTestMessageField) 188 .isEqualTo(message); 189 expectThat(emptyMessage) 190 .ignoringFieldAbsenceOfFieldDescriptors(subTestMessageField, subTestMessageTestMessageField) 191 .isEqualTo(message); 192 193 try { 194 expectThat(message) 195 .ignoringFieldAbsenceOfFieldDescriptors(getFieldDescriptor("r_string")) 196 .isEqualTo(message); 197 fail("Expected failure."); 198 } catch (Exception e) { 199 assertThat(e).hasMessageThat().contains("r_string"); 200 assertThat(e).hasMessageThat().contains("repeated fields cannot be absent"); 201 } 202 203 if (isProto3()) { 204 try { 205 expectThat(message) 206 .ignoringFieldAbsenceOfFieldDescriptors(getFieldDescriptor("o_double")) 207 .isEqualTo(message); 208 fail("Expected failure."); 209 } catch (Exception e) { 210 assertThat(e).hasMessageThat().contains("o_double"); 211 assertThat(e).hasMessageThat().contains("is a field without presence"); 212 } 213 } else { 214 expectThat(message) 215 .ignoringFieldAbsenceOfFieldDescriptors(getFieldDescriptor("o_double")) 216 .isEqualTo(message); 217 } 218 } 219 220 @Test testUnknownFields()221 public void testUnknownFields() throws InvalidProtocolBufferException { 222 Message message = 223 fromUnknownFields( 224 UnknownFieldSet.newBuilder() 225 .addField(99, UnknownFieldSet.Field.newBuilder().addVarint(42).build()) 226 .build()); 227 Message diffMessage = 228 fromUnknownFields( 229 UnknownFieldSet.newBuilder() 230 .addField(93, UnknownFieldSet.Field.newBuilder().addVarint(42).build()) 231 .build()); 232 233 expectThat(diffMessage).isNotEqualTo(message); 234 expectThat(diffMessage).ignoringFieldAbsence().isEqualTo(message); 235 236 expectFailureWhenTesting().that(diffMessage).isEqualTo(message); 237 expectIsEqualToFailed(); 238 expectThatFailure().hasMessageThat().contains("added: 93[0]: 42"); 239 expectThatFailure().hasMessageThat().contains("deleted: 99[0]: 42"); 240 241 expectFailureWhenTesting().that(diffMessage).ignoringFieldAbsence().isNotEqualTo(message); 242 expectIsNotEqualToFailed(); 243 } 244 245 @Test testRepeatedFieldOrder()246 public void testRepeatedFieldOrder() { 247 Message message = parse("r_string: \"foo\" r_string: \"bar\""); 248 Message eqMessage = parse("r_string: \"bar\" r_string: \"foo\""); 249 Message diffMessage = parse("r_string: \"foo\" r_string: \"foo\" r_string: \"bar\""); 250 251 expectThat(message).isEqualTo(clone(message)); 252 expectThat(message).ignoringRepeatedFieldOrder().isEqualTo(clone(message)); 253 expectThat(diffMessage).isNotEqualTo(message); 254 expectThat(diffMessage).ignoringRepeatedFieldOrder().isNotEqualTo(message); 255 expectThat(eqMessage).isNotEqualTo(message); 256 expectThat(eqMessage).ignoringRepeatedFieldOrder().isEqualTo(message); 257 258 Message nestedMessage = 259 parse( 260 "r_test_message: { o_int: 33 r_string: \"foo\" r_string: \"bar\" } " 261 + "r_test_message: { o_int: 44 r_string: \"baz\" r_string: \"qux\" } "); 262 Message diffNestedMessage = 263 parse( 264 "r_test_message: { o_int: 33 r_string: \"qux\" r_string: \"baz\" } " 265 + "r_test_message: { o_int: 44 r_string: \"bar\" r_string: \"foo\" } "); 266 Message eqNestedMessage = 267 parse( 268 "r_test_message: { o_int: 44 r_string: \"qux\" r_string: \"baz\" } " 269 + "r_test_message: { o_int: 33 r_string: \"bar\" r_string: \"foo\" } "); 270 271 expectThat(nestedMessage).isEqualTo(clone(nestedMessage)); 272 expectThat(nestedMessage).ignoringRepeatedFieldOrder().isEqualTo(clone(nestedMessage)); 273 expectThat(diffNestedMessage).isNotEqualTo(nestedMessage); 274 expectThat(diffNestedMessage).ignoringRepeatedFieldOrder().isNotEqualTo(nestedMessage); 275 expectThat(eqNestedMessage).isNotEqualTo(nestedMessage); 276 expectThat(eqNestedMessage).ignoringRepeatedFieldOrder().isEqualTo(nestedMessage); 277 278 expectFailureWhenTesting().that(eqMessage).isEqualTo(message); 279 expectIsEqualToFailed(); 280 expectThatFailure().hasMessageThat().contains("modified: r_string[0]: \"foo\" -> \"bar\""); 281 expectThatFailure().hasMessageThat().contains("modified: r_string[1]: \"bar\" -> \"foo\""); 282 283 expectFailureWhenTesting().that(eqMessage).ignoringRepeatedFieldOrder().isNotEqualTo(message); 284 expectIsNotEqualToFailed(); 285 expectThatFailure().hasMessageThat().contains("moved: r_string[0] -> r_string[1]: \"foo\""); 286 expectThatFailure().hasMessageThat().contains("moved: r_string[1] -> r_string[0]: \"bar\""); 287 288 expectFailureWhenTesting().that(diffMessage).ignoringRepeatedFieldOrder().isEqualTo(message); 289 expectIsEqualToFailed(); 290 expectThatFailure().hasMessageThat().contains("matched: r_string[0]: \"foo\""); 291 expectThatFailure().hasMessageThat().contains("moved: r_string[1] -> r_string[2]: \"bar\""); 292 expectThatFailure().hasMessageThat().contains("added: r_string[1]: \"foo\""); 293 } 294 295 @Test testRepeatedFieldOrder_scoped()296 public void testRepeatedFieldOrder_scoped() { 297 Message message = 298 parse("r_string: 'a' r_string: 'b' o_sub_test_message: { r_string: 'c' r_string: 'd' }"); 299 Message diffSubMessage = 300 parse("r_string: 'a' r_string: 'b' o_sub_test_message: { r_string: 'd' r_string: 'c' }"); 301 Message diffAll = 302 parse("r_string: 'b' r_string: 'a' o_sub_test_message: { r_string: 'd' r_string: 'c' }"); 303 304 FieldDescriptor rootMessageRepeatedfield = getFieldDescriptor("r_string"); 305 FieldDescriptor subMessageRepeatedField = 306 checkNotNull( 307 getFieldDescriptor("o_sub_test_message").getMessageType().findFieldByName("r_string")); 308 309 // Ignoring all repeated field order tests pass. 310 expectThat(diffSubMessage).ignoringRepeatedFieldOrder().isEqualTo(message); 311 expectThat(diffAll).ignoringRepeatedFieldOrder().isEqualTo(message); 312 313 // Ignoring only some results in failures. 314 // 315 // TODO(user): Whether we check failure message substrings or not is currently ad-hoc on a 316 // per-test basis, and not especially maintainable. We should make the tests consistent 317 // according to some reasonable rule in this regard. 318 expectFailureWhenTesting() 319 .that(diffSubMessage) 320 .ignoringRepeatedFieldOrderOfFieldDescriptors(rootMessageRepeatedfield) 321 .isEqualTo(message); 322 expectIsEqualToFailed(); 323 expectThatFailure() 324 .hasMessageThat() 325 .contains("modified: o_sub_test_message.r_string[0]: \"c\" -> \"d\""); 326 expectThat(diffSubMessage) 327 .ignoringRepeatedFieldOrderOfFieldDescriptors(subMessageRepeatedField) 328 .isEqualTo(message); 329 330 expectThat(diffAll) 331 .ignoringRepeatedFieldOrderOfFieldDescriptors(rootMessageRepeatedfield) 332 .isNotEqualTo(message); 333 expectThat(diffAll) 334 .ignoringRepeatedFieldOrderOfFieldDescriptors(subMessageRepeatedField) 335 .isNotEqualTo(message); 336 expectThat(diffAll) 337 .ignoringRepeatedFieldOrderOfFieldDescriptors( 338 rootMessageRepeatedfield, subMessageRepeatedField) 339 .isEqualTo(message); 340 341 try { 342 expectThat(message) 343 .ignoringRepeatedFieldOrderOfFields(getFieldNumber("o_int")) 344 .isEqualTo(message); 345 fail("Expected failure."); 346 } catch (Exception e) { 347 assertThat(e).hasMessageThat().contains("o_int"); 348 assertThat(e).hasMessageThat().contains("is not a repeated field"); 349 } 350 } 351 352 @Test testDoubleTolerance()353 public void testDoubleTolerance() { 354 Message message = parse("o_double: 1.0"); 355 Message diffMessage = parse("o_double: 1.1"); 356 357 expectThat(diffMessage).isNotEqualTo(message); 358 expectThat(diffMessage).usingDoubleTolerance(0.2).isEqualTo(message); 359 expectThat(diffMessage).usingDoubleTolerance(0.05).isNotEqualTo(message); 360 expectThat(diffMessage).usingFloatTolerance(0.2f).isNotEqualTo(message); 361 } 362 363 @Test testDoubleTolerance_defaultValue()364 public void testDoubleTolerance_defaultValue() { 365 Message message = parse("o_double: 0.0"); 366 Message defaultInstance = parse(""); 367 Message diffMessage = parse("o_double: 0.01"); 368 369 expectThat(diffMessage).isNotEqualTo(message); 370 371 if (isProto3()) { 372 // The default value is ignored and treated as unset. 373 // We treat is as equivalent to being set to 0.0 because there is no distinction in Proto 3. 374 expectThat(message).isEqualTo(defaultInstance); 375 expectThat(diffMessage).usingDoubleTolerance(0.1).isEqualTo(message); 376 expectThat(diffMessage).usingDoubleTolerance(0.1).ignoringFieldAbsence().isEqualTo(message); 377 } else { 378 // The default value can be set or unset, so we respect it. 379 expectThat(message).isNotEqualTo(defaultInstance); 380 381 expectThat(diffMessage).usingDoubleTolerance(0.1).isEqualTo(message); 382 expectThat(diffMessage).usingDoubleTolerance(0.1).isNotEqualTo(defaultInstance); 383 expectThat(diffMessage).usingDoubleTolerance(0.1).ignoringFieldAbsence().isEqualTo(message); 384 expectThat(diffMessage) 385 .usingDoubleTolerance(0.1) 386 .ignoringFieldAbsence() 387 .isEqualTo(defaultInstance); 388 389 // The same logic applies for a specified default; not available in Proto 3. 390 Message message2 = parse("o_double_defaults_to_42: 42.0"); 391 Message diffMessage2 = parse("o_double_defaults_to_42: 42.01"); 392 393 expectThat(diffMessage2).usingDoubleTolerance(0.1).isEqualTo(message2); 394 expectThat(diffMessage2).usingDoubleTolerance(0.1).isNotEqualTo(defaultInstance); 395 expectThat(diffMessage2).usingDoubleTolerance(0.1).ignoringFieldAbsence().isEqualTo(message2); 396 expectThat(diffMessage2) 397 .usingDoubleTolerance(0.1) 398 .ignoringFieldAbsence() 399 .isEqualTo(defaultInstance); 400 } 401 } 402 403 @Test testDoubleTolerance_scoped()404 public void testDoubleTolerance_scoped() { 405 Message message = parse("o_double: 1.0 o_double2: 1.0"); 406 Message diffMessage = parse("o_double: 1.1 o_double2: 1.5"); 407 408 int doubleFieldNumber = getFieldNumber("o_double"); 409 int double2FieldNumber = getFieldNumber("o_double2"); 410 411 expectThat(diffMessage).usingDoubleTolerance(0.6).isEqualTo(message); 412 expectThat(diffMessage).usingDoubleTolerance(0.2).isNotEqualTo(message); 413 414 // usingDoubleTolerance*() statements override all previous statements. 415 expectThat(diffMessage) 416 .usingDoubleTolerance(0.2) 417 .usingDoubleToleranceForFields(0.6, double2FieldNumber) 418 .isEqualTo(message); 419 expectThat(diffMessage) 420 .usingDoubleToleranceForFields(0.6, doubleFieldNumber, double2FieldNumber) 421 .usingDoubleToleranceForFields(0.2, doubleFieldNumber) 422 .isEqualTo(message); 423 424 expectThat(diffMessage) 425 .usingDoubleTolerance(0.2) 426 .usingDoubleToleranceForFields(0.6, doubleFieldNumber) 427 .isNotEqualTo(message); 428 expectThat(diffMessage) 429 .usingDoubleToleranceForFields(0.6, double2FieldNumber) 430 .usingDoubleTolerance(0.2) 431 .isNotEqualTo(message); 432 expectThat(diffMessage) 433 .usingDoubleToleranceForFields(0.6, doubleFieldNumber, double2FieldNumber) 434 .usingDoubleToleranceForFields(0.2, double2FieldNumber) 435 .isNotEqualTo(message); 436 437 try { 438 expectThat(message) 439 .usingDoubleToleranceForFields(3.14159, getFieldNumber("o_int")) 440 .isEqualTo(message); 441 fail("Expected failure."); 442 } catch (Exception e) { 443 assertThat(e).hasMessageThat().contains("o_int"); 444 assertThat(e).hasMessageThat().contains("is not a double field"); 445 } 446 } 447 448 @Test testFloatTolerance()449 public void testFloatTolerance() { 450 Message message = parse("o_float: 1.0"); 451 Message diffMessage = parse("o_float: 1.1"); 452 453 expectThat(diffMessage).isNotEqualTo(message); 454 expectThat(diffMessage).usingFloatTolerance(0.2f).isEqualTo(message); 455 expectThat(diffMessage).usingFloatTolerance(0.05f).isNotEqualTo(message); 456 expectThat(diffMessage).usingDoubleTolerance(0.2).isNotEqualTo(message); 457 } 458 459 @Test testFloatTolerance_defaultValue()460 public void testFloatTolerance_defaultValue() { 461 Message message = parse("o_float: 0.0"); 462 Message defaultInstance = parse(""); 463 Message diffMessage = parse("o_float: 0.01"); 464 465 expectThat(diffMessage).isNotEqualTo(message); 466 467 if (isProto3()) { 468 // The default value is ignored and treated as unset. 469 // We treat is as equivalent to being set to 0.0f because there is no distinction in Proto 3. 470 expectThat(message).isEqualTo(defaultInstance); 471 expectThat(diffMessage).usingFloatTolerance(0.1f).isEqualTo(message); 472 expectThat(diffMessage).usingFloatTolerance(0.1f).ignoringFieldAbsence().isEqualTo(message); 473 } else { 474 // The default value can be set or unset, so we respect it. 475 expectThat(message).isNotEqualTo(defaultInstance); 476 477 expectThat(diffMessage).usingFloatTolerance(0.1f).isEqualTo(message); 478 expectThat(diffMessage).usingFloatTolerance(0.1f).isNotEqualTo(defaultInstance); 479 expectThat(diffMessage).usingFloatTolerance(0.1f).ignoringFieldAbsence().isEqualTo(message); 480 expectThat(diffMessage) 481 .usingFloatTolerance(0.1f) 482 .ignoringFieldAbsence() 483 .isEqualTo(defaultInstance); 484 485 // The same logic applies for a specified default; not available in Proto 3. 486 Message message2 = parse("o_float_defaults_to_42: 42.0"); 487 Message diffMessage2 = parse("o_float_defaults_to_42: 42.01"); 488 489 expectThat(diffMessage2).usingFloatTolerance(0.1f).isEqualTo(message2); 490 expectThat(diffMessage2).usingFloatTolerance(0.1f).isNotEqualTo(defaultInstance); 491 expectThat(diffMessage2).usingFloatTolerance(0.1f).ignoringFieldAbsence().isEqualTo(message2); 492 expectThat(diffMessage2) 493 .usingFloatTolerance(0.1f) 494 .ignoringFieldAbsence() 495 .isEqualTo(defaultInstance); 496 } 497 } 498 499 @Test testFloatTolerance_scoped()500 public void testFloatTolerance_scoped() { 501 Message message = parse("o_float: 1.0 o_float2: 1.0"); 502 Message diffMessage = parse("o_float: 1.1 o_float2: 1.5"); 503 504 int floatFieldNumber = getFieldNumber("o_float"); 505 int float2FieldNumber = getFieldNumber("o_float2"); 506 507 expectThat(diffMessage).usingFloatTolerance(0.6f).isEqualTo(message); 508 expectThat(diffMessage).usingFloatTolerance(0.2f).isNotEqualTo(message); 509 510 // usingFloatTolerance*() statements override all previous statements. 511 expectThat(diffMessage) 512 .usingFloatTolerance(0.2f) 513 .usingFloatToleranceForFields(0.6f, float2FieldNumber) 514 .isEqualTo(message); 515 expectThat(diffMessage) 516 .usingFloatTolerance(0.2f) 517 .usingFloatToleranceForFields(0.6f, floatFieldNumber) 518 .isNotEqualTo(message); 519 expectThat(diffMessage) 520 .usingFloatToleranceForFields(0.6f, float2FieldNumber) 521 .usingFloatTolerance(0.2f) 522 .isNotEqualTo(message); 523 expectThat(diffMessage) 524 .usingFloatToleranceForFields(0.6f, floatFieldNumber, float2FieldNumber) 525 .usingFloatToleranceForFields(0.2f, floatFieldNumber) 526 .isEqualTo(message); 527 expectThat(diffMessage) 528 .usingFloatToleranceForFields(0.6f, floatFieldNumber, float2FieldNumber) 529 .usingFloatToleranceForFields(0.2f, float2FieldNumber) 530 .isNotEqualTo(message); 531 532 try { 533 expectThat(message) 534 .usingFloatToleranceForFields(3.1416f, getFieldNumber("o_int")) 535 .isEqualTo(message); 536 fail("Expected failure."); 537 } catch (Exception e) { 538 assertThat(e).hasMessageThat().contains("o_int"); 539 assertThat(e).hasMessageThat().contains("is not a float field"); 540 } 541 } 542 543 @Test testComparingExpectedFieldsOnly()544 public void testComparingExpectedFieldsOnly() { 545 Message message = parse("o_int: 3 r_string: 'foo'"); 546 Message narrowMessage = parse("o_int: 3"); 547 548 expectThat(message).comparingExpectedFieldsOnly().isEqualTo(narrowMessage); 549 expectThat(narrowMessage).comparingExpectedFieldsOnly().isNotEqualTo(message); 550 551 expectFailureWhenTesting() 552 .that(message) 553 .comparingExpectedFieldsOnly() 554 .isNotEqualTo(narrowMessage); 555 expectThatFailure().hasMessageThat().contains("ignored: r_string"); 556 } 557 558 @Test testIgnoringExtraRepeatedFieldElements_respectingOrder()559 public void testIgnoringExtraRepeatedFieldElements_respectingOrder() { 560 Message message = parse("r_string: 'foo' r_string: 'bar'"); 561 Message eqMessage = parse("r_string: 'foo' r_string: 'foobar' r_string: 'bar'"); 562 Message diffMessage = parse("r_string: 'bar' r_string: 'foobar' r_string: 'foo'"); 563 564 expectThat(eqMessage).ignoringExtraRepeatedFieldElements().isEqualTo(message); 565 expectThat(diffMessage).ignoringExtraRepeatedFieldElements().isNotEqualTo(message); 566 567 expectFailureWhenTesting() 568 .that(eqMessage) 569 .ignoringExtraRepeatedFieldElements() 570 .isNotEqualTo(message); 571 expectThatFailure() 572 .hasMessageThat() 573 .contains("ignored: r_string[?] -> r_string[1]: \"foobar\""); 574 575 expectFailureWhenTesting() 576 .that(diffMessage) 577 .ignoringExtraRepeatedFieldElements() 578 .isEqualTo(message); 579 expectThatFailure() 580 .hasMessageThat() 581 .contains("out_of_order: r_string[1] -> r_string[0]: \"bar\""); 582 expectThatFailure().hasMessageThat().contains("moved: r_string[0] -> r_string[2]: \"foo\""); 583 } 584 585 @Test testIgnoringExtraRepeatedFieldElements_ignoringOrder()586 public void testIgnoringExtraRepeatedFieldElements_ignoringOrder() { 587 Message message = parse("r_string: 'foo' r_string: 'bar'"); 588 Message eqMessage = parse("r_string: 'baz' r_string: 'bar' r_string: 'qux' r_string: 'foo'"); 589 Message diffMessage = parse("r_string: 'abc' r_string: 'foo' r_string: 'xyz'"); 590 591 expectThat(eqMessage) 592 .ignoringExtraRepeatedFieldElements() 593 .ignoringRepeatedFieldOrder() 594 .isEqualTo(message); 595 expectThat(diffMessage) 596 .ignoringExtraRepeatedFieldElements() 597 .ignoringRepeatedFieldOrder() 598 .isNotEqualTo(message); 599 600 expectFailureWhenTesting() 601 .that(diffMessage) 602 .ignoringExtraRepeatedFieldElements() 603 .ignoringRepeatedFieldOrder() 604 .isEqualTo(message); 605 expectThatFailure().hasMessageThat().contains("moved: r_string[0] -> r_string[1]: \"foo\""); 606 expectThatFailure().hasMessageThat().contains("deleted: r_string[1]: \"bar\""); 607 } 608 609 @Test testIgnoringExtraRepeatedFieldElements_empty()610 public void testIgnoringExtraRepeatedFieldElements_empty() { 611 Message message = parse("o_int: 2"); 612 Message diffMessage = parse("o_int: 2 r_string: 'error'"); 613 614 expectThat(diffMessage).ignoringExtraRepeatedFieldElements().isNotEqualTo(message); 615 expectThat(diffMessage) 616 .ignoringExtraRepeatedFieldElements() 617 .ignoringRepeatedFieldOrder() 618 .isNotEqualTo(message); 619 620 expectThat(diffMessage) 621 .comparingExpectedFieldsOnly() 622 .ignoringExtraRepeatedFieldElements() 623 .isEqualTo(message); 624 expectThat(diffMessage) 625 .comparingExpectedFieldsOnly() 626 .ignoringExtraRepeatedFieldElements() 627 .ignoringRepeatedFieldOrder() 628 .isEqualTo(message); 629 } 630 631 @Test testIgnoringExtraRepeatedFieldElements_scoped()632 public void testIgnoringExtraRepeatedFieldElements_scoped() { 633 Message message = parse("r_string: 'a' o_sub_test_message: { r_string: 'c' }"); 634 Message diffMessage = 635 parse("r_string: 'a' o_sub_test_message: { r_string: 'b' r_string: 'c' }"); 636 637 FieldDescriptor rootRepeatedField = getFieldDescriptor("r_string"); 638 FieldDescriptor subMessageRepeatedField = 639 checkNotNull( 640 getFieldDescriptor("o_sub_test_message").getMessageType().findFieldByName("r_string")); 641 642 expectThat(diffMessage).ignoringExtraRepeatedFieldElements().isEqualTo(message); 643 expectThat(diffMessage) 644 .ignoringExtraRepeatedFieldElementsOfFieldDescriptors(rootRepeatedField) 645 .isNotEqualTo(message); 646 expectThat(diffMessage) 647 .ignoringExtraRepeatedFieldElementsOfFieldDescriptors(subMessageRepeatedField) 648 .isEqualTo(message); 649 expectThat(diffMessage) 650 .ignoringExtraRepeatedFieldElementsOfFieldDescriptors( 651 rootRepeatedField, subMessageRepeatedField) 652 .isEqualTo(message); 653 654 try { 655 expectThat(message) 656 .ignoringExtraRepeatedFieldElementsOfFields(getFieldNumber("o_int")) 657 .isEqualTo(message); 658 fail("Expected failure."); 659 } catch (Exception e) { 660 assertThat(e).hasMessageThat().contains("o_int"); 661 assertThat(e).hasMessageThat().contains("it cannot contain extra elements"); 662 } 663 } 664 665 // Utility which fills a proto map field, based on the java.util.Map. makeProtoMap(Map<String, Integer> map)666 private Message makeProtoMap(Map<String, Integer> map) { 667 StringBuilder textProto = new StringBuilder(); 668 for (String key : map.keySet()) { 669 int value = map.get(key); 670 textProto 671 .append("test_message_map { key: '") 672 .append(key) 673 .append("' value { o_int: ") 674 .append(value) 675 .append(" } } "); 676 } 677 return parse(textProto.toString()); 678 } 679 680 @Test testIgnoringExtraRepeatedFieldElements_map()681 public void testIgnoringExtraRepeatedFieldElements_map() { 682 Message message = makeProtoMap(ImmutableMap.of("foo", 2, "bar", 3)); 683 Message eqMessage = makeProtoMap(ImmutableMap.of("bar", 3, "qux", 4, "foo", 2)); 684 Message diffMessage = makeProtoMap(ImmutableMap.of("quz", 5, "foo", 2)); 685 Message emptyMessage = parse(""); 686 687 expectThat(eqMessage).ignoringExtraRepeatedFieldElements().isEqualTo(message); 688 expectThat(eqMessage) 689 .ignoringRepeatedFieldOrder() 690 .ignoringExtraRepeatedFieldElements() 691 .isEqualTo(message); 692 expectThat(diffMessage).ignoringExtraRepeatedFieldElements().isNotEqualTo(message); 693 expectThat(diffMessage) 694 .ignoringExtraRepeatedFieldElements() 695 .ignoringRepeatedFieldOrder() 696 .isNotEqualTo(message); 697 698 expectThat(message).ignoringExtraRepeatedFieldElements().isNotEqualTo(emptyMessage); 699 700 expectFailureWhenTesting() 701 .that(diffMessage) 702 .ignoringExtraRepeatedFieldElements() 703 .isEqualTo(message); 704 expectThatFailure().hasMessageThat().contains("matched: test_message_map[\"foo\"].o_int: 2"); 705 expectThatFailure().hasMessageThat().contains("ignored: test_message_map[\"quz\"]"); 706 expectThatFailure().hasMessageThat().contains("deleted: test_message_map[\"bar\"]"); 707 } 708 709 @Test testReportingMismatchesOnly_isEqualTo()710 public void testReportingMismatchesOnly_isEqualTo() { 711 Message message = parse("r_string: \"foo\" r_string: \"bar\""); 712 Message diffMessage = parse("r_string: \"foo\" r_string: \"not_bar\""); 713 714 expectFailureWhenTesting().that(diffMessage).isEqualTo(message); 715 expectIsEqualToFailed(); 716 expectThatFailure().hasMessageThat().contains("foo"); 717 expectThatFailure().hasMessageThat().contains("bar"); 718 expectThatFailure().hasMessageThat().contains("not_bar"); 719 720 expectFailureWhenTesting().that(diffMessage).reportingMismatchesOnly().isEqualTo(message); 721 expectIsEqualToFailed(); 722 expectThatFailure().hasMessageThat().doesNotContain("foo"); 723 expectThatFailure().hasMessageThat().contains("bar"); 724 expectThatFailure().hasMessageThat().contains("not_bar"); 725 } 726 727 @Test testReportingMismatchesOnly_isNotEqualTo()728 public void testReportingMismatchesOnly_isNotEqualTo() { 729 Message message = parse("o_int: 33 r_string: \"foo\" r_string: \"bar\""); 730 Message diffMessage = parse("o_int: 33 r_string: \"bar\" r_string: \"foo\""); 731 732 expectFailureWhenTesting().that(diffMessage).ignoringRepeatedFieldOrder().isNotEqualTo(message); 733 expectIsNotEqualToFailed(); 734 expectThatFailure().hasMessageThat().contains("33"); 735 expectThatFailure().hasMessageThat().contains("foo"); 736 expectThatFailure().hasMessageThat().contains("bar"); 737 738 expectFailureWhenTesting() 739 .that(diffMessage) 740 .ignoringRepeatedFieldOrder() 741 .reportingMismatchesOnly() 742 .isNotEqualTo(message); 743 expectIsNotEqualToFailed(); 744 expectThatFailure().hasMessageThat().doesNotContain("33"); 745 expectThatFailure().hasMessageThat().doesNotContain("foo"); 746 expectThatFailure().hasMessageThat().doesNotContain("bar"); 747 } 748 749 @Test testHasAllRequiredFields()750 public void testHasAllRequiredFields() { 751 // Proto 3 doesn't have required fields. 752 if (isProto3()) { 753 return; 754 } 755 756 expectThat(parsePartial("")).hasAllRequiredFields(); 757 expectThat(parsePartial("o_required_string_message: { required_string: \"foo\" }")) 758 .hasAllRequiredFields(); 759 760 expectFailureWhenTesting() 761 .that(parsePartial("o_required_string_message: {}")) 762 .hasAllRequiredFields(); 763 expectThatFailure() 764 .factKeys() 765 .containsExactly( 766 "expected to have all required fields set", "but was missing", "proto was"); 767 expectThatFailure() 768 .factValue("but was missing") 769 .isEqualTo("[o_required_string_message.required_string]"); 770 771 expectFailureWhenTesting() 772 .that(parsePartial("r_required_string_message: {} r_required_string_message: {}")) 773 .hasAllRequiredFields(); 774 expectThatFailure() 775 .factKeys() 776 .containsExactly( 777 "expected to have all required fields set", "but was missing", "proto was"); 778 expectThatFailure() 779 .factValue("but was missing") 780 .contains("r_required_string_message[0].required_string"); 781 expectThatFailure() 782 .factValue("but was missing") 783 .contains("r_required_string_message[1].required_string"); 784 } 785 786 @Test testAnyMessage_notEqual_diffPrintsExpandedAny()787 public void testAnyMessage_notEqual_diffPrintsExpandedAny() { 788 String typeUrl = 789 isProto3() 790 ? "type.googleapis.com/com.google.common.truth.extensions.proto.SubTestMessage3" 791 : "type.googleapis.com/com.google.common.truth.extensions.proto.SubTestMessage2"; 792 Message msgWithAny = 793 parse("" + "o_int: 42 " + "o_any_message: { [" + typeUrl + "]: {r_string: \"foo\"} }"); 794 Message msgWithoutAny = parse("o_int: 42"); 795 796 expectFailureWhenTesting() 797 .that(msgWithAny) 798 .unpackingAnyUsing(getTypeRegistry(), getExtensionRegistry()) 799 .isEqualTo(msgWithoutAny); 800 expectThatFailure() 801 .hasMessageThat() 802 .contains( 803 "added: o_any_message: \n" + "[" + typeUrl + "] {\n" + " r_string: \"foo\"\n" + "}\n"); 804 805 expectFailureWhenTesting() 806 .that(msgWithoutAny) 807 .unpackingAnyUsing(getTypeRegistry(), getExtensionRegistry()) 808 .isEqualTo(msgWithAny); 809 expectThatFailure() 810 .hasMessageThat() 811 .contains( 812 "deleted: o_any_message: \n" 813 + "[" 814 + typeUrl 815 + "] {\n" 816 + " r_string: \"foo\"\n" 817 + "}\n"); 818 } 819 820 @Test testRepeatedAnyMessage_notEqual_diffPrintsExpandedAny()821 public void testRepeatedAnyMessage_notEqual_diffPrintsExpandedAny() { 822 String typeUrl = 823 isProto3() 824 ? "type.googleapis.com/com.google.common.truth.extensions.proto.SubTestMessage3" 825 : "type.googleapis.com/com.google.common.truth.extensions.proto.SubTestMessage2"; 826 String fooSubMessage = "{ [" + typeUrl + "]: {r_string: \"foo\"} }"; 827 String barSubMessage = "{ [" + typeUrl + "]: {r_string: \"bar\"} }"; 828 String bazSubMessage = "{ [" + typeUrl + "]: {r_string: \"baz\"} }"; 829 Message msgWithFooBar = 830 parse( 831 "" 832 + "o_int: 42 " 833 + "r_any_message: " 834 + fooSubMessage 835 + "r_any_message: " 836 + barSubMessage); 837 Message msgWithBazFoo = 838 parse( 839 "" 840 + "o_int: 42 " 841 + "r_any_message: " 842 + bazSubMessage 843 + "r_any_message: " 844 + fooSubMessage); 845 846 expectFailureWhenTesting() 847 .that(msgWithFooBar) 848 .unpackingAnyUsing(getTypeRegistry(), getExtensionRegistry()) 849 .ignoringRepeatedFieldOrder() 850 .isEqualTo(msgWithBazFoo); 851 852 expectThatFailure() 853 .hasMessageThat() 854 .contains( 855 "" 856 + "moved: r_any_message[1] -> r_any_message[0]:\n" 857 + "added: r_any_message[1]: \n" 858 + "[" 859 + typeUrl 860 + "] {\n" 861 + " r_string: \"bar\"\n" 862 + "}\n" 863 + "deleted: r_any_message[0]: \n" 864 + "[" 865 + typeUrl 866 + "] {\n" 867 + " r_string: \"baz\"\n" 868 + "}"); 869 } 870 871 @Test testAnyMessagesWithDifferentTypes()872 public void testAnyMessagesWithDifferentTypes() { 873 String typeUrl = 874 isProto3() 875 ? "type.googleapis.com/com.google.common.truth.extensions.proto.SubTestMessage3" 876 : "type.googleapis.com/com.google.common.truth.extensions.proto.SubTestMessage2"; 877 String diffTypeUrl = 878 isProto3() 879 ? "type.googleapis.com/com.google.common.truth.extensions.proto.SubSubTestMessage3" 880 : "type.googleapis.com/com.google.common.truth.extensions.proto.SubSubTestMessage2"; 881 882 Message message = parse("o_any_message: { [" + typeUrl + "]: {r_string: \"foo\"} }"); 883 Message diffMessage = parse("o_any_message: { [" + diffTypeUrl + "]: {r_string: \"bar\"} }"); 884 885 expectThat(message) 886 .unpackingAnyUsing(getTypeRegistry(), getExtensionRegistry()) 887 .isNotEqualTo(diffMessage); 888 889 expectFailureWhenTesting() 890 .that(message) 891 .unpackingAnyUsing(getTypeRegistry(), getExtensionRegistry()) 892 .isEqualTo(diffMessage); 893 expectThatFailure().hasMessageThat().contains("modified: o_any_message.type_url"); 894 expectThatFailure() 895 .hasMessageThat() 896 .containsMatch("modified: o_any_message.value:.*bar.*->.*foo.*"); 897 } 898 899 @Test testAnyMessageCompareWithEmptyAnyMessage()900 public void testAnyMessageCompareWithEmptyAnyMessage() { 901 String typeUrl = 902 isProto3() 903 ? "type.googleapis.com/com.google.common.truth.extensions.proto.SubTestMessage3" 904 : "type.googleapis.com/com.google.common.truth.extensions.proto.SubTestMessage2"; 905 906 Message messageWithAny = parse("o_any_message: { [" + typeUrl + "]: {o_int: 1} }"); 907 Message messageWithEmptyAny = parse("o_any_message: { }"); 908 909 expectThat(messageWithAny) 910 .unpackingAnyUsing(getTypeRegistry(), getExtensionRegistry()) 911 .isNotEqualTo(messageWithEmptyAny); 912 expectThat(messageWithEmptyAny) 913 .unpackingAnyUsing(getTypeRegistry(), getExtensionRegistry()) 914 .isNotEqualTo(messageWithAny); 915 916 expectFailureWhenTesting() 917 .that(messageWithAny) 918 .unpackingAnyUsing(getTypeRegistry(), getExtensionRegistry()) 919 .isEqualTo(messageWithEmptyAny); 920 expectThatFailure().hasMessageThat().contains("modified: o_any_message.type_url"); 921 expectThatFailure().hasMessageThat().contains("modified: o_any_message.value"); 922 923 expectFailureWhenTesting() 924 .that(messageWithEmptyAny) 925 .unpackingAnyUsing(getTypeRegistry(), getExtensionRegistry()) 926 .isEqualTo(messageWithAny); 927 expectThatFailure().hasMessageThat().contains("modified: o_any_message.type_url"); 928 expectThatFailure().hasMessageThat().contains("modified: o_any_message.value"); 929 } 930 931 @Test testAnyMessageComparedWithDynamicMessage()932 public void testAnyMessageComparedWithDynamicMessage() throws InvalidProtocolBufferException { 933 String typeUrl = 934 isProto3() 935 ? "type.googleapis.com/com.google.common.truth.extensions.proto.SubTestMessage3" 936 : "type.googleapis.com/com.google.common.truth.extensions.proto.SubTestMessage2"; 937 938 Message messageWithAny = parse("o_any_message: { [" + typeUrl + "]: {o_int: 1} }"); 939 FieldDescriptor fieldDescriptor = getFieldDescriptor("o_any_message"); 940 Any message = (Any) messageWithAny.getField(fieldDescriptor); 941 DynamicMessage dynamicMessage = 942 DynamicMessage.parseFrom( 943 Any.getDescriptor(), message.toByteString(), ExtensionRegistry.getEmptyRegistry()); 944 945 expectThat(dynamicMessage) 946 .unpackingAnyUsing(getTypeRegistry(), getExtensionRegistry()) 947 .isEqualTo(message); 948 expectThat(message) 949 .unpackingAnyUsing(getTypeRegistry(), getExtensionRegistry()) 950 .isEqualTo(dynamicMessage); 951 } 952 953 @Test testMapWithDefaultKeysAndValues()954 public void testMapWithDefaultKeysAndValues() throws InvalidProtocolBufferException { 955 Descriptor descriptor = getFieldDescriptor("o_int").getContainingType(); 956 String defaultString = ""; 957 int defaultInt32 = 0; 958 Message message = makeProtoMap(ImmutableMap.of(defaultString, 1, "foo", defaultInt32)); 959 Message dynamicMessage = 960 DynamicMessage.parseFrom( 961 descriptor, message.toByteString(), ExtensionRegistry.getEmptyRegistry()); 962 expectThat(message).isEqualTo(dynamicMessage); 963 } 964 } 965