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#import "GPBTestUtilities.h" 32 33#import <objc/runtime.h> 34 35#import "GPBArray_PackagePrivate.h" 36#import "GPBDescriptor.h" 37#import "GPBDictionary_PackagePrivate.h" 38#import "GPBMessage_PackagePrivate.h" 39#import "GPBUnknownField_PackagePrivate.h" 40#import "GPBUnknownFieldSet_PackagePrivate.h" 41#import "google/protobuf/Unittest.pbobjc.h" 42#import "google/protobuf/UnittestObjc.pbobjc.h" 43 44@interface MessageTests : GPBTestCase 45@end 46 47@implementation MessageTests 48 49// TODO(thomasvl): this should get split into a few files of logic junks, it is 50// a jumble of things at the moment (and the testutils have a bunch of the real 51// assertions). 52 53- (TestAllTypes *)mergeSource { 54 TestAllTypes *message = [TestAllTypes message]; 55 [message setOptionalInt32:1]; 56 [message setOptionalString:@"foo"]; 57 [message setOptionalForeignMessage:[ForeignMessage message]]; 58 [message.repeatedStringArray addObject:@"bar"]; 59 return message; 60} 61 62- (TestAllTypes *)mergeDestination { 63 TestAllTypes *message = [TestAllTypes message]; 64 [message setOptionalInt64:2]; 65 [message setOptionalString:@"baz"]; 66 ForeignMessage *foreignMessage = [ForeignMessage message]; 67 [foreignMessage setC:3]; 68 [message setOptionalForeignMessage:foreignMessage]; 69 [message.repeatedStringArray addObject:@"qux"]; 70 return message; 71} 72 73- (TestAllTypes *)mergeDestinationWithoutForeignMessageIvar { 74 TestAllTypes *message = [TestAllTypes message]; 75 [message setOptionalInt64:2]; 76 [message setOptionalString:@"baz"]; 77 [message.repeatedStringArray addObject:@"qux"]; 78 return message; 79} 80 81- (TestAllTypes *)mergeResult { 82 TestAllTypes *message = [TestAllTypes message]; 83 [message setOptionalInt32:1]; 84 [message setOptionalInt64:2]; 85 [message setOptionalString:@"foo"]; 86 ForeignMessage *foreignMessage = [ForeignMessage message]; 87 [foreignMessage setC:3]; 88 [message setOptionalForeignMessage:foreignMessage]; 89 [message.repeatedStringArray addObject:@"qux"]; 90 [message.repeatedStringArray addObject:@"bar"]; 91 return message; 92} 93 94- (TestAllTypes *)mergeResultForDestinationWithoutForeignMessageIvar { 95 TestAllTypes *message = [TestAllTypes message]; 96 [message setOptionalInt32:1]; 97 [message setOptionalInt64:2]; 98 [message setOptionalString:@"foo"]; 99 ForeignMessage *foreignMessage = [ForeignMessage message]; 100 [message setOptionalForeignMessage:foreignMessage]; 101 [message.repeatedStringArray addObject:@"qux"]; 102 [message.repeatedStringArray addObject:@"bar"]; 103 return message; 104} 105 106- (TestAllExtensions *)mergeExtensionsDestination { 107 TestAllExtensions *message = [TestAllExtensions message]; 108 [message setExtension:[UnittestRoot optionalInt32Extension] value:@5]; 109 [message setExtension:[UnittestRoot optionalStringExtension] value:@"foo"]; 110 ForeignMessage *foreignMessage = [ForeignMessage message]; 111 foreignMessage.c = 4; 112 [message setExtension:[UnittestRoot optionalForeignMessageExtension] 113 value:foreignMessage]; 114 TestAllTypes_NestedMessage *nestedMessage = 115 [TestAllTypes_NestedMessage message]; 116 [message setExtension:[UnittestRoot optionalNestedMessageExtension] 117 value:nestedMessage]; 118 return message; 119} 120 121- (TestAllExtensions *)mergeExtensionsSource { 122 TestAllExtensions *message = [TestAllExtensions message]; 123 [message setExtension:[UnittestRoot optionalInt64Extension] value:@6]; 124 [message setExtension:[UnittestRoot optionalStringExtension] value:@"bar"]; 125 ForeignMessage *foreignMessage = [ForeignMessage message]; 126 [message setExtension:[UnittestRoot optionalForeignMessageExtension] 127 value:foreignMessage]; 128 TestAllTypes_NestedMessage *nestedMessage = 129 [TestAllTypes_NestedMessage message]; 130 nestedMessage.bb = 7; 131 [message setExtension:[UnittestRoot optionalNestedMessageExtension] 132 value:nestedMessage]; 133 return message; 134} 135 136- (TestAllExtensions *)mergeExtensionsResult { 137 TestAllExtensions *message = [TestAllExtensions message]; 138 [message setExtension:[UnittestRoot optionalInt32Extension] value:@5]; 139 [message setExtension:[UnittestRoot optionalInt64Extension] value:@6]; 140 [message setExtension:[UnittestRoot optionalStringExtension] value:@"bar"]; 141 ForeignMessage *foreignMessage = [ForeignMessage message]; 142 foreignMessage.c = 4; 143 [message setExtension:[UnittestRoot optionalForeignMessageExtension] 144 value:foreignMessage]; 145 TestAllTypes_NestedMessage *nestedMessage = 146 [TestAllTypes_NestedMessage message]; 147 nestedMessage.bb = 7; 148 [message setExtension:[UnittestRoot optionalNestedMessageExtension] 149 value:nestedMessage]; 150 return message; 151} 152 153- (void)testMergeFrom { 154 TestAllTypes *result = [[self.mergeDestination copy] autorelease]; 155 [result mergeFrom:self.mergeSource]; 156 NSData *resultData = [result data]; 157 NSData *mergeResultData = [self.mergeResult data]; 158 XCTAssertEqualObjects(resultData, mergeResultData); 159 XCTAssertEqualObjects(result, self.mergeResult); 160 161 // Test when destination does not have an Ivar (type is an object) but source 162 // has such Ivar. 163 // The result must has the Ivar which is same as the one in source. 164 result = [[self.mergeDestinationWithoutForeignMessageIvar copy] autorelease]; 165 [result mergeFrom:self.mergeSource]; 166 resultData = [result data]; 167 mergeResultData = 168 [self.mergeResultForDestinationWithoutForeignMessageIvar data]; 169 XCTAssertEqualObjects(resultData, mergeResultData); 170 XCTAssertEqualObjects( 171 result, self.mergeResultForDestinationWithoutForeignMessageIvar); 172 173 // Test when destination is empty. 174 // The result must is same as the source. 175 result = [TestAllTypes message]; 176 [result mergeFrom:self.mergeSource]; 177 resultData = [result data]; 178 mergeResultData = [self.mergeSource data]; 179 XCTAssertEqualObjects(resultData, mergeResultData); 180 XCTAssertEqualObjects(result, self.mergeSource); 181} 182 183- (void)testMergeFromWithExtensions { 184 TestAllExtensions *result = [self mergeExtensionsDestination]; 185 [result mergeFrom:[self mergeExtensionsSource]]; 186 NSData *resultData = [result data]; 187 NSData *mergeResultData = [[self mergeExtensionsResult] data]; 188 XCTAssertEqualObjects(resultData, mergeResultData); 189 XCTAssertEqualObjects(result, [self mergeExtensionsResult]); 190 191 // Test merging from data. 192 result = [self mergeExtensionsDestination]; 193 NSData *data = [[self mergeExtensionsSource] data]; 194 XCTAssertNotNil(data); 195 [result mergeFromData:data 196 extensionRegistry:[UnittestRoot extensionRegistry]]; 197 resultData = [result data]; 198 XCTAssertEqualObjects(resultData, mergeResultData); 199 XCTAssertEqualObjects(result, [self mergeExtensionsResult]); 200} 201 202- (void)testIsEquals { 203 TestAllTypes *result = [[self.mergeDestination copy] autorelease]; 204 [result mergeFrom:self.mergeSource]; 205 XCTAssertEqualObjects(result.data, self.mergeResult.data); 206 XCTAssertEqualObjects(result, self.mergeResult); 207 TestAllTypes *result2 = [[self.mergeDestination copy] autorelease]; 208 XCTAssertNotEqualObjects(result2.data, self.mergeResult.data); 209 XCTAssertNotEqualObjects(result2, self.mergeResult); 210} 211 212// ================================================================= 213// Required-field-related tests. 214 215- (TestRequired *)testRequiredInitialized { 216 TestRequired *message = [TestRequired message]; 217 [message setA:1]; 218 [message setB:2]; 219 [message setC:3]; 220 return message; 221} 222 223- (void)testRequired { 224 TestRequired *message = [TestRequired message]; 225 226 XCTAssertFalse(message.initialized); 227 [message setA:1]; 228 XCTAssertFalse(message.initialized); 229 [message setB:1]; 230 XCTAssertFalse(message.initialized); 231 [message setC:1]; 232 XCTAssertTrue(message.initialized); 233} 234 235- (void)testRequiredForeign { 236 TestRequiredForeign *message = [TestRequiredForeign message]; 237 238 XCTAssertTrue(message.initialized); 239 240 [message setOptionalMessage:[TestRequired message]]; 241 XCTAssertFalse(message.initialized); 242 243 [message setOptionalMessage:self.testRequiredInitialized]; 244 XCTAssertTrue(message.initialized); 245 246 [message.repeatedMessageArray addObject:[TestRequired message]]; 247 XCTAssertFalse(message.initialized); 248 249 [message.repeatedMessageArray removeAllObjects]; 250 [message.repeatedMessageArray addObject:self.testRequiredInitialized]; 251 XCTAssertTrue(message.initialized); 252} 253 254- (void)testRequiredExtension { 255 TestAllExtensions *message = [TestAllExtensions message]; 256 257 XCTAssertTrue(message.initialized); 258 259 [message setExtension:[TestRequired single] value:[TestRequired message]]; 260 XCTAssertFalse(message.initialized); 261 262 [message setExtension:[TestRequired single] 263 value:self.testRequiredInitialized]; 264 XCTAssertTrue(message.initialized); 265 266 [message addExtension:[TestRequired multi] value:[TestRequired message]]; 267 XCTAssertFalse(message.initialized); 268 269 [message setExtension:[TestRequired multi] 270 index:0 271 value:self.testRequiredInitialized]; 272 XCTAssertTrue(message.initialized); 273} 274 275- (void)testDataFromUninitialized { 276 TestRequired *message = [TestRequired message]; 277 NSData *data = [message data]; 278 // In DEBUG, the data generation will fail, but in non DEBUG, it passes 279 // because the check isn't done (for speed). 280#ifdef DEBUG 281 XCTAssertNil(data); 282#else 283 XCTAssertNotNil(data); 284 XCTAssertFalse(message.initialized); 285#endif // DEBUG 286} 287 288- (void)testInitialized { 289 // We're mostly testing that no exception is thrown. 290 TestRequired *message = [TestRequired message]; 291 XCTAssertFalse(message.initialized); 292} 293 294- (void)testDataFromNestedUninitialized { 295 TestRequiredForeign *message = [TestRequiredForeign message]; 296 [message setOptionalMessage:[TestRequired message]]; 297 [message.repeatedMessageArray addObject:[TestRequired message]]; 298 [message.repeatedMessageArray addObject:[TestRequired message]]; 299 NSData *data = [message data]; 300 // In DEBUG, the data generation will fail, but in non DEBUG, it passes 301 // because the check isn't done (for speed). 302#ifdef DEBUG 303 XCTAssertNil(data); 304#else 305 XCTAssertNotNil(data); 306 XCTAssertFalse(message.initialized); 307#endif // DEBUG 308} 309 310- (void)testNestedInitialized { 311 // We're mostly testing that no exception is thrown. 312 313 TestRequiredForeign *message = [TestRequiredForeign message]; 314 [message setOptionalMessage:[TestRequired message]]; 315 [message.repeatedMessageArray addObject:[TestRequired message]]; 316 [message.repeatedMessageArray addObject:[TestRequired message]]; 317 318 XCTAssertFalse(message.initialized); 319} 320 321- (void)testParseUninitialized { 322 NSError *error = nil; 323 TestRequired *msg = 324 [TestRequired parseFromData:GPBEmptyNSData() error:&error]; 325 // In DEBUG, the parse will fail, but in non DEBUG, it passes because 326 // the check isn't done (for speed). 327#ifdef DEBUG 328 XCTAssertNil(msg); 329 XCTAssertNotNil(error); 330 XCTAssertEqualObjects(error.domain, GPBMessageErrorDomain); 331 XCTAssertEqual(error.code, GPBMessageErrorCodeMissingRequiredField); 332#else 333 XCTAssertNotNil(msg); 334 XCTAssertNil(error); 335 XCTAssertFalse(msg.initialized); 336#endif // DEBUG 337} 338 339- (void)testCoding { 340 NSData *data = 341 [NSKeyedArchiver archivedDataWithRootObject:[self mergeResult]]; 342 id unarchivedObject = [NSKeyedUnarchiver unarchiveObjectWithData:data]; 343 344 XCTAssertEqualObjects(unarchivedObject, [self mergeResult]); 345 346 // Intentionally doing a pointer comparison. 347 XCTAssertNotEqual(unarchivedObject, [self mergeResult]); 348} 349 350- (void)testObjectReset { 351 // Tests a failure where clearing out defaults values caused an over release. 352 TestAllTypes *message = [TestAllTypes message]; 353 message.hasOptionalNestedMessage = NO; 354 [message setOptionalNestedMessage:[TestAllTypes_NestedMessage message]]; 355 message.hasOptionalNestedMessage = NO; 356 [message setOptionalNestedMessage:[TestAllTypes_NestedMessage message]]; 357 [message setOptionalNestedMessage:nil]; 358 message.hasOptionalNestedMessage = NO; 359} 360 361- (void)testSettingHasToYes { 362 TestAllTypes *message = [TestAllTypes message]; 363 XCTAssertThrows([message setHasOptionalNestedMessage:YES]); 364} 365 366- (void)testRoot { 367 XCTAssertNotNil([UnittestRoot extensionRegistry]); 368} 369 370- (void)testGPBMessageSize { 371 // See the note in GPBMessage_PackagePrivate.h about why we want to keep the 372 // base instance size pointer size aligned. 373 size_t messageSize = class_getInstanceSize([GPBMessage class]); 374 XCTAssertEqual((messageSize % sizeof(void *)), (size_t)0, 375 @"Base size isn't pointer size aligned"); 376 377 // Since we add storage ourselves (see +allocWithZone: in GPBMessage), confirm 378 // that the size of some generated classes is still the same as the base for 379 // that logic to work as desired. 380 size_t testMessageSize = class_getInstanceSize([TestAllTypes class]); 381 XCTAssertEqual(testMessageSize, messageSize); 382} 383 384- (void)testInit { 385 TestAllTypes *message = [TestAllTypes message]; 386 [self assertClear:message]; 387} 388 389- (void)testAccessors { 390 TestAllTypes *message = [TestAllTypes message]; 391 [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount]; 392 [self assertAllFieldsSet:message repeatedCount:kGPBDefaultRepeatCount]; 393} 394 395- (void)testKVC_ValueForKey { 396 TestAllTypes *message = [TestAllTypes message]; 397 [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount]; 398 [self assertAllFieldsKVCMatch:message]; 399} 400 401- (void)testKVC_SetValue_ForKey { 402 TestAllTypes *message = [TestAllTypes message]; 403 [self setAllFieldsViaKVC:message repeatedCount:kGPBDefaultRepeatCount]; 404 [self assertAllFieldsKVCMatch:message]; 405 [self assertAllFieldsSet:message repeatedCount:kGPBDefaultRepeatCount]; 406 [self assertAllFieldsKVCMatch:message]; 407} 408 409- (void)testDescription { 410 // No real test, just exercise code 411 TestAllTypes *message = [TestAllTypes message]; 412 [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount]; 413 414 GPBUnknownFieldSet *unknownFields = 415 [[[GPBUnknownFieldSet alloc] init] autorelease]; 416 GPBUnknownField *field = 417 [[[GPBUnknownField alloc] initWithNumber:2] autorelease]; 418 [field addVarint:2]; 419 [unknownFields addField:field]; 420 field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease]; 421 [field addVarint:4]; 422 [unknownFields addField:field]; 423 424 [message setUnknownFields:unknownFields]; 425 426 NSString *description = [message description]; 427 XCTAssertGreaterThan([description length], 0U); 428 429 GPBMessage *message2 = [TestAllExtensions message]; 430 [message2 setExtension:[UnittestRoot optionalInt32Extension] value:@1]; 431 432 [message2 addExtension:[UnittestRoot repeatedInt32Extension] value:@2]; 433 434 description = [message2 description]; 435 XCTAssertGreaterThan([description length], 0U); 436} 437 438- (void)testSetter { 439 // Test to make sure that if we set a value that has a default value 440 // with the default, that the has is set, and the value gets put into the 441 // message correctly. 442 TestAllTypes *message = [TestAllTypes message]; 443 GPBDescriptor *descriptor = [[message class] descriptor]; 444 XCTAssertNotNil(descriptor); 445 GPBFieldDescriptor *fieldDescriptor = 446 [descriptor fieldWithName:@"defaultInt32"]; 447 XCTAssertNotNil(fieldDescriptor); 448 GPBGenericValue defaultValue = [fieldDescriptor defaultValue]; 449 [message setDefaultInt32:defaultValue.valueInt32]; 450 XCTAssertTrue(message.hasDefaultInt32); 451 XCTAssertEqual(message.defaultInt32, defaultValue.valueInt32); 452 453 // Do the same thing with an object type. 454 message = [TestAllTypes message]; 455 fieldDescriptor = [descriptor fieldWithName:@"defaultString"]; 456 XCTAssertNotNil(fieldDescriptor); 457 defaultValue = [fieldDescriptor defaultValue]; 458 [message setDefaultString:defaultValue.valueString]; 459 XCTAssertTrue(message.hasDefaultString); 460 XCTAssertEqualObjects(message.defaultString, defaultValue.valueString); 461 462 // Test default string type. 463 message = [TestAllTypes message]; 464 XCTAssertEqualObjects(message.defaultString, @"hello"); 465 XCTAssertFalse(message.hasDefaultString); 466 fieldDescriptor = [descriptor fieldWithName:@"defaultString"]; 467 XCTAssertNotNil(fieldDescriptor); 468 defaultValue = [fieldDescriptor defaultValue]; 469 [message setDefaultString:defaultValue.valueString]; 470 XCTAssertEqualObjects(message.defaultString, @"hello"); 471 XCTAssertTrue(message.hasDefaultString); 472 [message setDefaultString:nil]; 473 XCTAssertEqualObjects(message.defaultString, @"hello"); 474 XCTAssertFalse(message.hasDefaultString); 475 message.hasDefaultString = NO; 476 XCTAssertFalse(message.hasDefaultString); 477 XCTAssertEqualObjects(message.defaultString, @"hello"); 478 479 // Test default bytes type. 480 NSData *defaultBytes = [@"world" dataUsingEncoding:NSUTF8StringEncoding]; 481 XCTAssertEqualObjects(message.defaultBytes, defaultBytes); 482 XCTAssertFalse(message.hasDefaultString); 483 fieldDescriptor = [descriptor fieldWithName:@"defaultBytes"]; 484 XCTAssertNotNil(fieldDescriptor); 485 defaultValue = [fieldDescriptor defaultValue]; 486 [message setDefaultBytes:defaultValue.valueData]; 487 XCTAssertEqualObjects(message.defaultBytes, defaultBytes); 488 XCTAssertTrue(message.hasDefaultBytes); 489 [message setDefaultBytes:nil]; 490 XCTAssertEqualObjects(message.defaultBytes, defaultBytes); 491 XCTAssertFalse(message.hasDefaultBytes); 492 message.hasDefaultBytes = NO; 493 XCTAssertFalse(message.hasDefaultBytes); 494 XCTAssertEqualObjects(message.defaultBytes, defaultBytes); 495 496 // Test optional string. 497 XCTAssertFalse(message.hasOptionalString); 498 XCTAssertEqualObjects(message.optionalString, @""); 499 XCTAssertFalse(message.hasOptionalString); 500 message.optionalString = nil; 501 XCTAssertFalse(message.hasOptionalString); 502 XCTAssertEqualObjects(message.optionalString, @""); 503 NSString *string = @"string"; 504 message.optionalString = string; 505 XCTAssertEqualObjects(message.optionalString, string); 506 XCTAssertTrue(message.hasOptionalString); 507 message.optionalString = nil; 508 XCTAssertFalse(message.hasOptionalString); 509 XCTAssertEqualObjects(message.optionalString, @""); 510 511 // Test optional data. 512 XCTAssertFalse(message.hasOptionalBytes); 513 XCTAssertEqualObjects(message.optionalBytes, GPBEmptyNSData()); 514 XCTAssertFalse(message.hasOptionalBytes); 515 message.optionalBytes = nil; 516 XCTAssertFalse(message.hasOptionalBytes); 517 XCTAssertEqualObjects(message.optionalBytes, GPBEmptyNSData()); 518 NSData *data = [@"bytes" dataUsingEncoding:NSUTF8StringEncoding]; 519 message.optionalBytes = data; 520 XCTAssertEqualObjects(message.optionalBytes, data); 521 XCTAssertTrue(message.hasOptionalBytes); 522 message.optionalBytes = nil; 523 XCTAssertFalse(message.hasOptionalBytes); 524 XCTAssertEqualObjects(message.optionalBytes, GPBEmptyNSData()); 525 526 // Test lazy message setting 527 XCTAssertFalse(message.hasOptionalLazyMessage); 528 XCTAssertNotNil(message.optionalLazyMessage); 529 XCTAssertFalse(message.hasOptionalLazyMessage); 530 message.hasOptionalLazyMessage = NO; 531 XCTAssertFalse(message.hasOptionalLazyMessage); 532 XCTAssertNotNil(message.optionalLazyMessage); 533 XCTAssertFalse(message.hasOptionalLazyMessage); 534 message.optionalLazyMessage = nil; 535 XCTAssertFalse(message.hasOptionalLazyMessage); 536 537 // Test nested messages 538 XCTAssertFalse(message.hasOptionalLazyMessage); 539 message.optionalLazyMessage.bb = 1; 540 XCTAssertTrue(message.hasOptionalLazyMessage); 541 XCTAssertEqual(message.optionalLazyMessage.bb, 1); 542 XCTAssertNotNil(message.optionalLazyMessage); 543 message.optionalLazyMessage = nil; 544 XCTAssertFalse(message.hasOptionalLazyMessage); 545 XCTAssertEqual(message.optionalLazyMessage.bb, 0); 546 XCTAssertFalse(message.hasOptionalLazyMessage); 547 XCTAssertNotNil(message.optionalLazyMessage); 548 549 // -testDefaultSubMessages tests the "defaulting" handling of fields 550 // containing messages. 551} 552 553- (void)testRepeatedSetters { 554 TestAllTypes *message = [TestAllTypes message]; 555 [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount]; 556 [self modifyRepeatedFields:message]; 557 [self assertRepeatedFieldsModified:message 558 repeatedCount:kGPBDefaultRepeatCount]; 559} 560 561- (void)testClear { 562 TestAllTypes *message = [TestAllTypes message]; 563 [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount]; 564 [self clearAllFields:message]; 565 [self assertClear:message]; 566 TestAllTypes *message2 = [TestAllTypes message]; 567 XCTAssertEqualObjects(message, message2); 568} 569 570- (void)testClearKVC { 571 TestAllTypes *message = [TestAllTypes message]; 572 [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount]; 573 [self clearAllFields:message]; 574 [self assertClear:message]; 575 [self assertClearKVC:message]; 576} 577 578- (void)testClearExtension { 579 // clearExtension() is not actually used in TestUtil, so try it manually. 580 GPBMessage *message1 = [TestAllExtensions message]; 581 [message1 setExtension:[UnittestRoot optionalInt32Extension] value:@1]; 582 583 XCTAssertTrue([message1 hasExtension:[UnittestRoot optionalInt32Extension]]); 584 [message1 clearExtension:[UnittestRoot optionalInt32Extension]]; 585 XCTAssertFalse([message1 hasExtension:[UnittestRoot optionalInt32Extension]]); 586 587 GPBMessage *message2 = [TestAllExtensions message]; 588 [message2 addExtension:[UnittestRoot repeatedInt32Extension] value:@1]; 589 590 XCTAssertEqual( 591 [[message2 getExtension:[UnittestRoot repeatedInt32Extension]] count], 592 (NSUInteger)1); 593 [message2 clearExtension:[UnittestRoot repeatedInt32Extension]]; 594 XCTAssertEqual( 595 [[message2 getExtension:[UnittestRoot repeatedInt32Extension]] count], 596 (NSUInteger)0); 597 598 // Clearing an unset extension field shouldn't make the target message 599 // visible. 600 GPBMessage *message3 = [TestAllExtensions message]; 601 GPBMessage *extension_msg = 602 [message3 getExtension:[UnittestObjcRoot recursiveExtension]]; 603 XCTAssertFalse([message3 hasExtension:[UnittestObjcRoot recursiveExtension]]); 604 [extension_msg clearExtension:[UnittestRoot optionalInt32Extension]]; 605 XCTAssertFalse([message3 hasExtension:[UnittestObjcRoot recursiveExtension]]); 606} 607 608- (void)testDefaultingSubMessages { 609 TestAllTypes *message = [TestAllTypes message]; 610 611 // Initially they should all not have values. 612 613 XCTAssertFalse(message.hasOptionalGroup); 614 XCTAssertFalse(message.hasOptionalNestedMessage); 615 XCTAssertFalse(message.hasOptionalForeignMessage); 616 XCTAssertFalse(message.hasOptionalImportMessage); 617 XCTAssertFalse(message.hasOptionalPublicImportMessage); 618 XCTAssertFalse(message.hasOptionalLazyMessage); 619 620 // They should auto create something when fetched. 621 622 TestAllTypes_OptionalGroup *optionalGroup = [message.optionalGroup retain]; 623 TestAllTypes_NestedMessage *optionalNestedMessage = 624 [message.optionalNestedMessage retain]; 625 ForeignMessage *optionalForeignMessage = 626 [message.optionalForeignMessage retain]; 627 ImportMessage *optionalImportMessage = [message.optionalImportMessage retain]; 628 PublicImportMessage *optionalPublicImportMessage = 629 [message.optionalPublicImportMessage retain]; 630 TestAllTypes_NestedMessage *optionalLazyMessage = 631 [message.optionalLazyMessage retain]; 632 633 XCTAssertNotNil(optionalGroup); 634 XCTAssertNotNil(optionalNestedMessage); 635 XCTAssertNotNil(optionalForeignMessage); 636 XCTAssertNotNil(optionalImportMessage); 637 XCTAssertNotNil(optionalPublicImportMessage); 638 XCTAssertNotNil(optionalLazyMessage); 639 640 // Although they were created, they should not respond to hasValue until that 641 // submessage is mutated. 642 643 XCTAssertFalse(message.hasOptionalGroup); 644 XCTAssertFalse(message.hasOptionalNestedMessage); 645 XCTAssertFalse(message.hasOptionalForeignMessage); 646 XCTAssertFalse(message.hasOptionalImportMessage); 647 XCTAssertFalse(message.hasOptionalPublicImportMessage); 648 XCTAssertFalse(message.hasOptionalLazyMessage); 649 650 // And they set that value back in to the message since the value created was 651 // mutable (so a second fetch should give the same object). 652 653 XCTAssertEqual(message.optionalGroup, optionalGroup); 654 XCTAssertEqual(message.optionalNestedMessage, optionalNestedMessage); 655 XCTAssertEqual(message.optionalForeignMessage, optionalForeignMessage); 656 XCTAssertEqual(message.optionalImportMessage, optionalImportMessage); 657 XCTAssertEqual(message.optionalPublicImportMessage, 658 optionalPublicImportMessage); 659 XCTAssertEqual(message.optionalLazyMessage, optionalLazyMessage); 660 661 // And the default objects for a second message should be distinct (again, 662 // since they are mutable, each needs their own copy). 663 664 TestAllTypes *message2 = [TestAllTypes message]; 665 666 // Intentionally doing a pointer comparison. 667 XCTAssertNotEqual(message2.optionalGroup, optionalGroup); 668 XCTAssertNotEqual(message2.optionalNestedMessage, optionalNestedMessage); 669 XCTAssertNotEqual(message2.optionalForeignMessage, optionalForeignMessage); 670 XCTAssertNotEqual(message2.optionalImportMessage, optionalImportMessage); 671 XCTAssertNotEqual(message2.optionalPublicImportMessage, 672 optionalPublicImportMessage); 673 XCTAssertNotEqual(message2.optionalLazyMessage, optionalLazyMessage); 674 675 // Setting the values to nil will clear the has flag, and on next access you 676 // get back new submessages. 677 678 message.optionalGroup = nil; 679 message.optionalNestedMessage = nil; 680 message.optionalForeignMessage = nil; 681 message.optionalImportMessage = nil; 682 message.optionalPublicImportMessage = nil; 683 message.optionalLazyMessage = nil; 684 685 XCTAssertFalse(message.hasOptionalGroup); 686 XCTAssertFalse(message.hasOptionalNestedMessage); 687 XCTAssertFalse(message.hasOptionalForeignMessage); 688 XCTAssertFalse(message.hasOptionalImportMessage); 689 XCTAssertFalse(message.hasOptionalPublicImportMessage); 690 XCTAssertFalse(message.hasOptionalLazyMessage); 691 692 // Intentionally doing a pointer comparison. 693 XCTAssertNotEqual(message.optionalGroup, optionalGroup); 694 XCTAssertNotEqual(message.optionalNestedMessage, optionalNestedMessage); 695 XCTAssertNotEqual(message.optionalForeignMessage, optionalForeignMessage); 696 XCTAssertNotEqual(message.optionalImportMessage, optionalImportMessage); 697 XCTAssertNotEqual(message.optionalPublicImportMessage, 698 optionalPublicImportMessage); 699 XCTAssertNotEqual(message.optionalLazyMessage, optionalLazyMessage); 700 701 [optionalGroup release]; 702 [optionalNestedMessage release]; 703 [optionalForeignMessage release]; 704 [optionalImportMessage release]; 705 [optionalPublicImportMessage release]; 706 [optionalLazyMessage release]; 707} 708 709- (void)testMultiplePointersToAutocreatedMessage { 710 // Multiple objects pointing to the same autocreated message. 711 TestAllTypes *message = [TestAllTypes message]; 712 TestAllTypes *message2 = [TestAllTypes message]; 713 message2.optionalGroup = message.optionalGroup; 714 XCTAssertTrue([message2 hasOptionalGroup]); 715 XCTAssertFalse([message hasOptionalGroup]); 716 message2.optionalGroup.a = 42; 717 XCTAssertTrue([message hasOptionalGroup]); 718 XCTAssertTrue([message2 hasOptionalGroup]); 719} 720 721- (void)testCopyWithAutocreatedMessage { 722 // Mutable copy should not copy autocreated messages. 723 TestAllTypes *message = [TestAllTypes message]; 724 message.optionalGroup.a = 42; 725 XCTAssertNotNil(message.optionalNestedMessage); 726 TestAllTypes *message2 = [[message copy] autorelease]; 727 XCTAssertTrue([message2 hasOptionalGroup]); 728 XCTAssertFalse([message2 hasOptionalNestedMessage]); 729 730 // Intentionally doing a pointer comparison. 731 XCTAssertNotEqual(message.optionalNestedMessage, 732 message2.optionalNestedMessage); 733} 734 735- (void)testClearAutocreatedSubmessage { 736 // Call clear on an intermediate submessage should cause it to get recreated 737 // on the next call. 738 TestRecursiveMessage *message = [TestRecursiveMessage message]; 739 TestRecursiveMessage *message_inner = [message.a.a.a retain]; 740 XCTAssertNotNil(message_inner); 741 XCTAssertTrue(GPBWasMessageAutocreatedBy(message_inner, message.a.a)); 742 [message.a.a clear]; 743 XCTAssertFalse(GPBWasMessageAutocreatedBy(message_inner, message.a.a)); 744 745 // Intentionally doing a pointer comparison. 746 XCTAssertNotEqual(message.a.a.a, message_inner); 747 [message_inner release]; 748} 749 750- (void)testRetainAutocreatedSubmessage { 751 // Should be able to retain autocreated submessage while the creator is 752 // dealloced. 753 TestAllTypes *message = [TestAllTypes message]; 754 755 ForeignMessage *subMessage; 756 @autoreleasepool { 757 TestAllTypes *message2 = [TestAllTypes message]; 758 subMessage = message2.optionalForeignMessage; // Autocreated 759 message.optionalForeignMessage = subMessage; 760 XCTAssertTrue(GPBWasMessageAutocreatedBy(message.optionalForeignMessage, 761 message2)); 762 } 763 764 // Should be the same object, and should still be live. 765 XCTAssertEqual(message.optionalForeignMessage, subMessage); 766 XCTAssertNotNil([subMessage description]); 767} 768 769- (void)testSetNilAutocreatedSubmessage { 770 TestRecursiveMessage *message = [TestRecursiveMessage message]; 771 TestRecursiveMessage *message_inner = [message.a.a retain]; 772 XCTAssertFalse([message hasA]); 773 XCTAssertFalse([message.a hasA]); 774 message.a.a = nil; 775 776 // |message.a| has to be made visible, but |message.a.a| was set to nil so 777 // shouldn't be. 778 XCTAssertTrue([message hasA]); 779 XCTAssertFalse([message.a hasA]); 780 781 // Setting submessage to nil should cause it to lose its creator. 782 XCTAssertFalse(GPBWasMessageAutocreatedBy(message_inner, message.a)); 783 784 // After setting to nil, getting it again should create a new autocreated 785 // message. 786 // Intentionally doing a pointer comparison. 787 XCTAssertNotEqual(message.a.a, message_inner); 788 789 [message_inner release]; 790} 791 792- (void)testSetDoesntHaveAutocreatedSubmessage { 793 // Clearing submessage (set has == NO) should NOT cause it to lose its 794 // creator. 795 TestAllTypes *message = [TestAllTypes message]; 796 TestAllTypes_NestedMessage *nestedMessage = message.optionalNestedMessage; 797 XCTAssertFalse([message hasOptionalNestedMessage]); 798 [message setHasOptionalNestedMessage:NO]; 799 XCTAssertFalse([message hasOptionalNestedMessage]); 800 XCTAssertEqual(message.optionalNestedMessage, nestedMessage); 801} 802 803- (void)testSetAutocreatedMessageBecomesVisible { 804 // Setting a value should cause the submessage to appear to its creator. 805 // Test this several levels deep. 806 TestRecursiveMessage *message = [TestRecursiveMessage message]; 807 message.a.a.a.a.i = 42; 808 XCTAssertTrue([message hasA]); 809 XCTAssertTrue([message.a hasA]); 810 XCTAssertTrue([message.a.a hasA]); 811 XCTAssertTrue([message.a.a.a hasA]); 812 XCTAssertFalse([message.a.a.a.a hasA]); 813 XCTAssertEqual(message.a.a.a.a.i, 42); 814} 815 816- (void)testClearUnsetFieldOfAutocreatedMessage { 817 // Clearing an unset field should not cause the submessage to appear to its 818 // creator. 819 TestRecursiveMessage *message = [TestRecursiveMessage message]; 820 message.a.a.a.a.hasI = NO; 821 XCTAssertFalse([message hasA]); 822 XCTAssertFalse([message.a hasA]); 823 XCTAssertFalse([message.a.a hasA]); 824 XCTAssertFalse([message.a.a.a hasA]); 825} 826 827- (void)testAutocreatedSubmessageAssignSkip { 828 TestRecursiveMessage *message = [TestRecursiveMessage message]; 829 TestRecursiveMessage *messageLevel1 = [message.a retain]; 830 TestRecursiveMessage *messageLevel2 = [message.a.a retain]; 831 TestRecursiveMessage *messageLevel3 = [message.a.a.a retain]; 832 TestRecursiveMessage *messageLevel4 = [message.a.a.a.a retain]; 833 XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel1, message)); 834 XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel2, messageLevel1)); 835 XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel3, messageLevel2)); 836 XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel4, messageLevel3)); 837 838 // Test skipping over an autocreated submessage and ensure it gets unset. 839 message.a = message.a.a; 840 XCTAssertEqual(message.a, messageLevel2); 841 XCTAssertTrue([message hasA]); 842 XCTAssertEqual(message.a.a, messageLevel3); 843 XCTAssertFalse([message.a hasA]); 844 XCTAssertEqual(message.a.a.a, messageLevel4); 845 XCTAssertFalse(GPBWasMessageAutocreatedBy(messageLevel1, 846 message)); // Because it was orphaned. 847 XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel2, messageLevel1)); 848 XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel3, messageLevel2)); 849 850 [messageLevel1 release]; 851 [messageLevel2 release]; 852 [messageLevel3 release]; 853 [messageLevel4 release]; 854} 855 856- (void)testAutocreatedSubmessageAssignLoop { 857 TestRecursiveMessage *message = [TestRecursiveMessage message]; 858 TestRecursiveMessage *messageLevel1 = [message.a retain]; 859 TestRecursiveMessage *messageLevel2 = [message.a.a retain]; 860 TestRecursiveMessage *messageLevel3 = [message.a.a.a retain]; 861 TestRecursiveMessage *messageLevel4 = [message.a.a.a.a retain]; 862 XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel1, message)); 863 XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel2, messageLevel1)); 864 XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel3, messageLevel2)); 865 XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel4, messageLevel3)); 866 867 // Test a property with a loop. You'd never do this but at least ensure the 868 // autocreated submessages behave sanely. 869 message.a.a = message.a; 870 XCTAssertTrue([message hasA]); 871 XCTAssertEqual(message.a, messageLevel1); 872 XCTAssertTrue([message.a hasA]); 873 XCTAssertEqual(message.a.a, messageLevel1); 874 XCTAssertTrue([message.a.a hasA]); 875 XCTAssertEqual(message.a.a.a, messageLevel1); 876 XCTAssertFalse(GPBWasMessageAutocreatedBy(messageLevel1, 877 message)); // Because it was assigned. 878 XCTAssertFalse(GPBWasMessageAutocreatedBy(messageLevel2, 879 messageLevel1)); // Because it was orphaned. 880 XCTAssertFalse([messageLevel2 hasA]); 881 882 // Break the retain loop. 883 message.a.a = nil; 884 XCTAssertTrue([message hasA]); 885 XCTAssertFalse([message.a hasA]); 886 887 [messageLevel1 release]; 888 [messageLevel2 release]; 889 [messageLevel3 release]; 890 [messageLevel4 release]; 891} 892 893- (void)testSetAutocreatedSubmessage { 894 // Setting autocreated submessage to another value should cause the old one to 895 // lose its creator. 896 TestAllTypes *message = [TestAllTypes message]; 897 TestAllTypes_NestedMessage *nestedMessage = 898 [message.optionalNestedMessage retain]; 899 900 message.optionalNestedMessage = [TestAllTypes_NestedMessage message]; 901 XCTAssertTrue([message hasOptionalNestedMessage]); 902 XCTAssertTrue(message.optionalNestedMessage != nestedMessage); 903 XCTAssertFalse(GPBWasMessageAutocreatedBy(nestedMessage, message)); 904 905 [nestedMessage release]; 906} 907 908- (void)testAutocreatedUnknownFields { 909 // Doing anything with (except reading) unknown fields should cause the 910 // submessage to become visible. 911 TestAllTypes *message = [TestAllTypes message]; 912 XCTAssertNotNil(message.optionalNestedMessage); 913 XCTAssertFalse([message hasOptionalNestedMessage]); 914 XCTAssertNil(message.optionalNestedMessage.unknownFields); 915 XCTAssertFalse([message hasOptionalNestedMessage]); 916 917 GPBUnknownFieldSet *unknownFields = 918 [[[GPBUnknownFieldSet alloc] init] autorelease]; 919 message.optionalNestedMessage.unknownFields = unknownFields; 920 XCTAssertTrue([message hasOptionalNestedMessage]); 921 922 message.optionalNestedMessage = nil; 923 XCTAssertFalse([message hasOptionalNestedMessage]); 924 [message.optionalNestedMessage setUnknownFields:unknownFields]; 925 XCTAssertTrue([message hasOptionalNestedMessage]); 926} 927 928- (void)testSetAutocreatedSubmessageToSelf { 929 // Setting submessage to itself should cause it to become visible. 930 TestAllTypes *message = [TestAllTypes message]; 931 XCTAssertNotNil(message.optionalNestedMessage); 932 XCTAssertFalse([message hasOptionalNestedMessage]); 933 message.optionalNestedMessage = message.optionalNestedMessage; 934 XCTAssertTrue([message hasOptionalNestedMessage]); 935} 936 937- (void)testAutocreatedSubmessageMemoryLeaks { 938 // Test for memory leaks with autocreated submessages. 939 TestRecursiveMessage *message; 940 TestRecursiveMessage *messageLevel1; 941 TestRecursiveMessage *messageLevel2; 942 TestRecursiveMessage *messageLevel3; 943 TestRecursiveMessage *messageLevel4; 944 @autoreleasepool { 945 message = [[TestRecursiveMessage alloc] init]; 946 messageLevel1 = [message.a retain]; 947 messageLevel2 = [message.a.a retain]; 948 messageLevel3 = [message.a.a.a retain]; 949 messageLevel4 = [message.a.a.a.a retain]; 950 message.a.i = 1; 951 } 952 953 XCTAssertEqual(message.retainCount, (NSUInteger)1); 954 [message release]; 955 XCTAssertEqual(messageLevel1.retainCount, (NSUInteger)1); 956 [messageLevel1 release]; 957 XCTAssertEqual(messageLevel2.retainCount, (NSUInteger)1); 958 [messageLevel2 release]; 959 XCTAssertEqual(messageLevel3.retainCount, (NSUInteger)1); 960 [messageLevel3 release]; 961 XCTAssertEqual(messageLevel4.retainCount, (NSUInteger)1); 962 [messageLevel4 release]; 963} 964 965- (void)testDefaultingArrays { 966 // Basic tests for default creation of arrays in a message. 967 TestRecursiveMessageWithRepeatedField *message = 968 [TestRecursiveMessageWithRepeatedField message]; 969 TestRecursiveMessageWithRepeatedField *message2 = 970 [TestRecursiveMessageWithRepeatedField message]; 971 972 // Simply accessing the array should not make any fields visible. 973 XCTAssertNotNil(message.a.a.iArray); 974 XCTAssertFalse([message hasA]); 975 XCTAssertFalse([message.a hasA]); 976 XCTAssertNotNil(message2.a.a.strArray); 977 XCTAssertFalse([message2 hasA]); 978 XCTAssertFalse([message2.a hasA]); 979 980 // But adding an element to the array should. 981 [message.a.a.iArray addValue:42]; 982 XCTAssertTrue([message hasA]); 983 XCTAssertTrue([message.a hasA]); 984 XCTAssertEqual([message.a.a.iArray count], (NSUInteger)1); 985 [message2.a.a.strArray addObject:@"foo"]; 986 XCTAssertTrue([message2 hasA]); 987 XCTAssertTrue([message2.a hasA]); 988 XCTAssertEqual([message2.a.a.strArray count], (NSUInteger)1); 989} 990 991- (void)testAutocreatedArrayShared { 992 // Multiple objects pointing to the same array. 993 TestRecursiveMessageWithRepeatedField *message1a = 994 [TestRecursiveMessageWithRepeatedField message]; 995 TestRecursiveMessageWithRepeatedField *message1b = 996 [TestRecursiveMessageWithRepeatedField message]; 997 message1a.a.iArray = message1b.a.iArray; 998 XCTAssertTrue([message1a hasA]); 999 XCTAssertFalse([message1b hasA]); 1000 [message1a.a.iArray addValue:1]; 1001 XCTAssertTrue([message1a hasA]); 1002 XCTAssertTrue([message1b hasA]); 1003 XCTAssertEqual(message1a.a.iArray, message1b.a.iArray); 1004 1005 TestRecursiveMessageWithRepeatedField *message2a = 1006 [TestRecursiveMessageWithRepeatedField message]; 1007 TestRecursiveMessageWithRepeatedField *message2b = 1008 [TestRecursiveMessageWithRepeatedField message]; 1009 message2a.a.strArray = message2b.a.strArray; 1010 XCTAssertTrue([message2a hasA]); 1011 XCTAssertFalse([message2b hasA]); 1012 [message2a.a.strArray addObject:@"bar"]; 1013 XCTAssertTrue([message2a hasA]); 1014 XCTAssertTrue([message2b hasA]); 1015 XCTAssertEqual(message2a.a.strArray, message2b.a.strArray); 1016} 1017 1018- (void)testAutocreatedArrayCopy { 1019 // Copy should not copy autocreated arrays. 1020 TestAllTypes *message = [TestAllTypes message]; 1021 XCTAssertNotNil(message.repeatedStringArray); 1022 XCTAssertNotNil(message.repeatedInt32Array); 1023 TestAllTypes *message2 = [[message copy] autorelease]; 1024 // Pointer conparisions. 1025 XCTAssertNotEqual(message.repeatedStringArray, message2.repeatedStringArray); 1026 XCTAssertNotEqual(message.repeatedInt32Array, message2.repeatedInt32Array); 1027 1028 // Mutable copy should copy empty arrays that were explicitly set (end up 1029 // with different objects that are equal). 1030 TestAllTypes *message3 = [TestAllTypes message]; 1031 message3.repeatedInt32Array = [GPBInt32Array arrayWithValue:42]; 1032 message3.repeatedStringArray = [NSMutableArray arrayWithObject:@"wee"]; 1033 XCTAssertNotNil(message.repeatedInt32Array); 1034 XCTAssertNotNil(message.repeatedStringArray); 1035 TestAllTypes *message4 = [[message3 copy] autorelease]; 1036 XCTAssertNotEqual(message3.repeatedInt32Array, message4.repeatedInt32Array); 1037 XCTAssertEqualObjects(message3.repeatedInt32Array, 1038 message4.repeatedInt32Array); 1039 XCTAssertNotEqual(message3.repeatedStringArray, message4.repeatedStringArray); 1040 XCTAssertEqualObjects(message3.repeatedStringArray, 1041 message4.repeatedStringArray); 1042} 1043 1044- (void)testAutocreatedArrayRetain { 1045 // Should be able to retain autocreated array while the creator is dealloced. 1046 TestAllTypes *message = [TestAllTypes message]; 1047 1048 @autoreleasepool { 1049 TestAllTypes *message2 = [TestAllTypes message]; 1050 message.repeatedInt32Array = message2.repeatedInt32Array; 1051 message.repeatedStringArray = message2.repeatedStringArray; 1052 // Pointer conparision 1053 XCTAssertEqual(message.repeatedInt32Array->_autocreator, message2); 1054 XCTAssertTrue([message.repeatedStringArray 1055 isKindOfClass:[GPBAutocreatedArray class]]); 1056 XCTAssertEqual( 1057 ((GPBAutocreatedArray *)message.repeatedStringArray)->_autocreator, 1058 message2); 1059 } 1060 1061 XCTAssertNil(message.repeatedInt32Array->_autocreator); 1062 XCTAssertTrue( 1063 [message.repeatedStringArray isKindOfClass:[GPBAutocreatedArray class]]); 1064 XCTAssertNil( 1065 ((GPBAutocreatedArray *)message.repeatedStringArray)->_autocreator); 1066} 1067 1068- (void)testSetNilAutocreatedArray { 1069 // Setting array to nil should cause it to lose its delegate. 1070 TestAllTypes *message = [TestAllTypes message]; 1071 GPBInt32Array *repeatedInt32Array = [message.repeatedInt32Array retain]; 1072 GPBAutocreatedArray *repeatedStringArray = 1073 (GPBAutocreatedArray *)[message.repeatedStringArray retain]; 1074 XCTAssertTrue([repeatedStringArray isKindOfClass:[GPBAutocreatedArray class]]); 1075 XCTAssertEqual(repeatedInt32Array->_autocreator, message); 1076 XCTAssertEqual(repeatedStringArray->_autocreator, message); 1077 message.repeatedInt32Array = nil; 1078 message.repeatedStringArray = nil; 1079 XCTAssertNil(repeatedInt32Array->_autocreator); 1080 XCTAssertNil(repeatedStringArray->_autocreator); 1081 [repeatedInt32Array release]; 1082 [repeatedStringArray release]; 1083} 1084 1085- (void)testReplaceAutocreatedArray { 1086 // Replacing array should orphan the old one and cause its creator to become 1087 // visible. 1088 { 1089 TestRecursiveMessageWithRepeatedField *message = 1090 [TestRecursiveMessageWithRepeatedField message]; 1091 XCTAssertNotNil(message.a); 1092 XCTAssertNotNil(message.a.iArray); 1093 XCTAssertFalse([message hasA]); 1094 GPBInt32Array *iArray = [message.a.iArray retain]; 1095 XCTAssertEqual(iArray->_autocreator, message.a); // Pointer comparision 1096 message.a.iArray = [GPBInt32Array arrayWithValue:1]; 1097 XCTAssertTrue([message hasA]); 1098 XCTAssertNotEqual(message.a.iArray, iArray); // Pointer comparision 1099 XCTAssertNil(iArray->_autocreator); 1100 [iArray release]; 1101 } 1102 1103 { 1104 TestRecursiveMessageWithRepeatedField *message = 1105 [TestRecursiveMessageWithRepeatedField message]; 1106 XCTAssertNotNil(message.a); 1107 XCTAssertNotNil(message.a.strArray); 1108 XCTAssertFalse([message hasA]); 1109 GPBAutocreatedArray *strArray = 1110 (GPBAutocreatedArray *)[message.a.strArray retain]; 1111 XCTAssertTrue([strArray isKindOfClass:[GPBAutocreatedArray class]]); 1112 XCTAssertEqual(strArray->_autocreator, message.a); // Pointer comparision 1113 message.a.strArray = [NSMutableArray arrayWithObject:@"foo"]; 1114 XCTAssertTrue([message hasA]); 1115 XCTAssertNotEqual(message.a.strArray, strArray); // Pointer comparision 1116 XCTAssertNil(strArray->_autocreator); 1117 [strArray release]; 1118 } 1119} 1120 1121- (void)testSetAutocreatedArrayToSelf { 1122 // Setting array to itself should cause it to become visible. 1123 { 1124 TestRecursiveMessageWithRepeatedField *message = 1125 [TestRecursiveMessageWithRepeatedField message]; 1126 XCTAssertNotNil(message.a); 1127 XCTAssertNotNil(message.a.iArray); 1128 XCTAssertFalse([message hasA]); 1129 message.a.iArray = message.a.iArray; 1130 XCTAssertTrue([message hasA]); 1131 XCTAssertNil(message.a.iArray->_autocreator); 1132 } 1133 1134 { 1135 TestRecursiveMessageWithRepeatedField *message = 1136 [TestRecursiveMessageWithRepeatedField message]; 1137 XCTAssertNotNil(message.a); 1138 XCTAssertNotNil(message.a.strArray); 1139 XCTAssertFalse([message hasA]); 1140 message.a.strArray = message.a.strArray; 1141 XCTAssertTrue([message hasA]); 1142 XCTAssertTrue([message.a.strArray isKindOfClass:[GPBAutocreatedArray class]]); 1143 XCTAssertNil(((GPBAutocreatedArray *)message.a.strArray)->_autocreator); 1144 } 1145} 1146 1147- (void)testAutocreatedArrayRemoveAllValues { 1148 // Calling removeAllValues on autocreated array should not cause it to be 1149 // visible. 1150 TestRecursiveMessageWithRepeatedField *message = 1151 [TestRecursiveMessageWithRepeatedField message]; 1152 [message.a.iArray removeAll]; 1153 XCTAssertFalse([message hasA]); 1154 [message.a.strArray removeAllObjects]; 1155 XCTAssertFalse([message hasA]); 1156} 1157 1158- (void)testDefaultingMaps { 1159 // Basic tests for default creation of maps in a message. 1160 TestRecursiveMessageWithRepeatedField *message = 1161 [TestRecursiveMessageWithRepeatedField message]; 1162 TestRecursiveMessageWithRepeatedField *message2 = 1163 [TestRecursiveMessageWithRepeatedField message]; 1164 1165 // Simply accessing the map should not make any fields visible. 1166 XCTAssertNotNil(message.a.a.iToI); 1167 XCTAssertFalse([message hasA]); 1168 XCTAssertFalse([message.a hasA]); 1169 XCTAssertNotNil(message2.a.a.strToStr); 1170 XCTAssertFalse([message2 hasA]); 1171 XCTAssertFalse([message2.a hasA]); 1172 1173 // But adding an element to the map should. 1174 [message.a.a.iToI setValue:100 forKey:200]; 1175 XCTAssertTrue([message hasA]); 1176 XCTAssertTrue([message.a hasA]); 1177 XCTAssertEqual([message.a.a.iToI count], (NSUInteger)1); 1178 [message2.a.a.strToStr setObject:@"foo" forKey:@"bar"]; 1179 XCTAssertTrue([message2 hasA]); 1180 XCTAssertTrue([message2.a hasA]); 1181 XCTAssertEqual([message2.a.a.strToStr count], (NSUInteger)1); 1182} 1183 1184- (void)testAutocreatedMapShared { 1185 // Multiple objects pointing to the same map. 1186 TestRecursiveMessageWithRepeatedField *message1a = 1187 [TestRecursiveMessageWithRepeatedField message]; 1188 TestRecursiveMessageWithRepeatedField *message1b = 1189 [TestRecursiveMessageWithRepeatedField message]; 1190 message1a.a.iToI = message1b.a.iToI; 1191 XCTAssertTrue([message1a hasA]); 1192 XCTAssertFalse([message1b hasA]); 1193 [message1a.a.iToI setValue:1 forKey:2]; 1194 XCTAssertTrue([message1a hasA]); 1195 XCTAssertTrue([message1b hasA]); 1196 XCTAssertEqual(message1a.a.iToI, message1b.a.iToI); 1197 1198 TestRecursiveMessageWithRepeatedField *message2a = 1199 [TestRecursiveMessageWithRepeatedField message]; 1200 TestRecursiveMessageWithRepeatedField *message2b = 1201 [TestRecursiveMessageWithRepeatedField message]; 1202 message2a.a.strToStr = message2b.a.strToStr; 1203 XCTAssertTrue([message2a hasA]); 1204 XCTAssertFalse([message2b hasA]); 1205 [message2a.a.strToStr setObject:@"bar" forKey:@"foo"]; 1206 XCTAssertTrue([message2a hasA]); 1207 XCTAssertTrue([message2b hasA]); 1208 XCTAssertEqual(message2a.a.strToStr, message2b.a.strToStr); 1209} 1210 1211- (void)testAutocreatedMapCopy { 1212 // Copy should not copy autocreated maps. 1213 TestRecursiveMessageWithRepeatedField *message = 1214 [TestRecursiveMessageWithRepeatedField message]; 1215 XCTAssertNotNil(message.strToStr); 1216 XCTAssertNotNil(message.iToI); 1217 TestRecursiveMessageWithRepeatedField *message2 = 1218 [[message copy] autorelease]; 1219 // Pointer conparisions. 1220 XCTAssertNotEqual(message.strToStr, message2.strToStr); 1221 XCTAssertNotEqual(message.iToI, message2.iToI); 1222 1223 // Mutable copy should copy empty arrays that were explicitly set (end up 1224 // with different objects that are equal). 1225 TestRecursiveMessageWithRepeatedField *message3 = 1226 [TestRecursiveMessageWithRepeatedField message]; 1227 message3.iToI = [GPBInt32Int32Dictionary dictionaryWithValue:10 forKey:20]; 1228 message3.strToStr = 1229 [NSMutableDictionary dictionaryWithObject:@"abc" forKey:@"123"]; 1230 XCTAssertNotNil(message.iToI); 1231 XCTAssertNotNil(message.iToI); 1232 TestRecursiveMessageWithRepeatedField *message4 = 1233 [[message3 copy] autorelease]; 1234 XCTAssertNotEqual(message3.iToI, message4.iToI); 1235 XCTAssertEqualObjects(message3.iToI, message4.iToI); 1236 XCTAssertNotEqual(message3.strToStr, message4.strToStr); 1237 XCTAssertEqualObjects(message3.strToStr, message4.strToStr); 1238} 1239 1240- (void)testAutocreatedMapRetain { 1241 // Should be able to retain autocreated map while the creator is dealloced. 1242 TestRecursiveMessageWithRepeatedField *message = 1243 [TestRecursiveMessageWithRepeatedField message]; 1244 1245 @autoreleasepool { 1246 TestRecursiveMessageWithRepeatedField *message2 = 1247 [TestRecursiveMessageWithRepeatedField message]; 1248 message.iToI = message2.iToI; 1249 message.strToStr = message2.strToStr; 1250 // Pointer conparision 1251 XCTAssertEqual(message.iToI->_autocreator, message2); 1252 XCTAssertTrue([message.strToStr 1253 isKindOfClass:[GPBAutocreatedDictionary class]]); 1254 XCTAssertEqual( 1255 ((GPBAutocreatedDictionary *)message.strToStr)->_autocreator, 1256 message2); 1257 } 1258 1259 XCTAssertNil(message.iToI->_autocreator); 1260 XCTAssertTrue( 1261 [message.strToStr isKindOfClass:[GPBAutocreatedDictionary class]]); 1262 XCTAssertNil( 1263 ((GPBAutocreatedDictionary *)message.strToStr)->_autocreator); 1264} 1265 1266- (void)testSetNilAutocreatedMap { 1267 // Setting map to nil should cause it to lose its delegate. 1268 TestRecursiveMessageWithRepeatedField *message = 1269 [TestRecursiveMessageWithRepeatedField message]; 1270 GPBInt32Int32Dictionary *iToI = [message.iToI retain]; 1271 GPBAutocreatedDictionary *strToStr = 1272 (GPBAutocreatedDictionary *)[message.strToStr retain]; 1273 XCTAssertTrue([strToStr isKindOfClass:[GPBAutocreatedDictionary class]]); 1274 XCTAssertEqual(iToI->_autocreator, message); 1275 XCTAssertEqual(strToStr->_autocreator, message); 1276 message.iToI = nil; 1277 message.strToStr = nil; 1278 XCTAssertNil(iToI->_autocreator); 1279 XCTAssertNil(strToStr->_autocreator); 1280 [iToI release]; 1281 [strToStr release]; 1282} 1283 1284- (void)testReplaceAutocreatedMap { 1285 // Replacing map should orphan the old one and cause its creator to become 1286 // visible. 1287 { 1288 TestRecursiveMessageWithRepeatedField *message = 1289 [TestRecursiveMessageWithRepeatedField message]; 1290 XCTAssertNotNil(message.a); 1291 XCTAssertNotNil(message.a.iToI); 1292 XCTAssertFalse([message hasA]); 1293 GPBInt32Int32Dictionary *iToI = [message.a.iToI retain]; 1294 XCTAssertEqual(iToI->_autocreator, message.a); // Pointer comparision 1295 message.a.iToI = [GPBInt32Int32Dictionary dictionaryWithValue:6 forKey:7]; 1296 XCTAssertTrue([message hasA]); 1297 XCTAssertNotEqual(message.a.iToI, iToI); // Pointer comparision 1298 XCTAssertNil(iToI->_autocreator); 1299 [iToI release]; 1300 } 1301 1302 { 1303 TestRecursiveMessageWithRepeatedField *message = 1304 [TestRecursiveMessageWithRepeatedField message]; 1305 XCTAssertNotNil(message.a); 1306 XCTAssertNotNil(message.a.strToStr); 1307 XCTAssertFalse([message hasA]); 1308 GPBAutocreatedDictionary *strToStr = 1309 (GPBAutocreatedDictionary *)[message.a.strToStr retain]; 1310 XCTAssertTrue([strToStr isKindOfClass:[GPBAutocreatedDictionary class]]); 1311 XCTAssertEqual(strToStr->_autocreator, message.a); // Pointer comparision 1312 message.a.strToStr = 1313 [NSMutableDictionary dictionaryWithObject:@"abc" forKey:@"def"]; 1314 XCTAssertTrue([message hasA]); 1315 XCTAssertNotEqual(message.a.strToStr, strToStr); // Pointer comparision 1316 XCTAssertNil(strToStr->_autocreator); 1317 [strToStr release]; 1318 } 1319} 1320 1321- (void)testSetAutocreatedMapToSelf { 1322 // Setting map to itself should cause it to become visible. 1323 { 1324 TestRecursiveMessageWithRepeatedField *message = 1325 [TestRecursiveMessageWithRepeatedField message]; 1326 XCTAssertNotNil(message.a); 1327 XCTAssertNotNil(message.a.iToI); 1328 XCTAssertFalse([message hasA]); 1329 message.a.iToI = message.a.iToI; 1330 XCTAssertTrue([message hasA]); 1331 XCTAssertNil(message.a.iToI->_autocreator); 1332 } 1333 1334 { 1335 TestRecursiveMessageWithRepeatedField *message = 1336 [TestRecursiveMessageWithRepeatedField message]; 1337 XCTAssertNotNil(message.a); 1338 XCTAssertNotNil(message.a.strToStr); 1339 XCTAssertFalse([message hasA]); 1340 message.a.strToStr = message.a.strToStr; 1341 XCTAssertTrue([message hasA]); 1342 XCTAssertTrue([message.a.strToStr isKindOfClass:[GPBAutocreatedDictionary class]]); 1343 XCTAssertNil(((GPBAutocreatedDictionary *)message.a.strToStr)->_autocreator); 1344 } 1345} 1346 1347- (void)testAutocreatedMapRemoveAllValues { 1348 // Calling removeAll on autocreated map should not cause it to be visible. 1349 TestRecursiveMessageWithRepeatedField *message = 1350 [TestRecursiveMessageWithRepeatedField message]; 1351 [message.a.iToI removeAll]; 1352 XCTAssertFalse([message hasA]); 1353 [message.a.strToStr removeAllObjects]; 1354 XCTAssertFalse([message hasA]); 1355} 1356 1357- (void)testExtensionAccessors { 1358 TestAllExtensions *message = [TestAllExtensions message]; 1359 [self setAllExtensions:message repeatedCount:kGPBDefaultRepeatCount]; 1360 [self assertAllExtensionsSet:message repeatedCount:kGPBDefaultRepeatCount]; 1361} 1362 1363- (void)testExtensionRepeatedSetters { 1364 TestAllExtensions *message = [TestAllExtensions message]; 1365 [self setAllExtensions:message repeatedCount:kGPBDefaultRepeatCount]; 1366 [self modifyRepeatedExtensions:message]; 1367 [self assertRepeatedExtensionsModified:message 1368 repeatedCount:kGPBDefaultRepeatCount]; 1369} 1370 1371- (void)testExtensionDefaults { 1372 [self assertExtensionsClear:[TestAllExtensions message]]; 1373} 1374 1375- (void)testExtensionIsEquals { 1376 TestAllExtensions *message = [TestAllExtensions message]; 1377 [self setAllExtensions:message repeatedCount:kGPBDefaultRepeatCount]; 1378 [self modifyRepeatedExtensions:message]; 1379 TestAllExtensions *message2 = [TestAllExtensions message]; 1380 [self setAllExtensions:message2 repeatedCount:kGPBDefaultRepeatCount]; 1381 XCTAssertFalse([message isEqual:message2]); 1382 message2 = [TestAllExtensions message]; 1383 [self setAllExtensions:message2 repeatedCount:kGPBDefaultRepeatCount]; 1384 [self modifyRepeatedExtensions:message2]; 1385 XCTAssertEqualObjects(message, message2); 1386} 1387 1388- (void)testExtensionsMergeFrom { 1389 TestAllExtensions *message = [TestAllExtensions message]; 1390 [self setAllExtensions:message repeatedCount:kGPBDefaultRepeatCount]; 1391 [self modifyRepeatedExtensions:message]; 1392 1393 message = [TestAllExtensions message]; 1394 [self setAllExtensions:message repeatedCount:kGPBDefaultRepeatCount]; 1395 TestAllExtensions *message2 = [TestAllExtensions message]; 1396 [self modifyRepeatedExtensions:message2]; 1397 [message2 mergeFrom:message]; 1398 1399 XCTAssertEqualObjects(message, message2); 1400} 1401 1402- (void)testDefaultingExtensionMessages { 1403 TestAllExtensions *message = [TestAllExtensions message]; 1404 1405 // Initially they should all not have values. 1406 1407 XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]); 1408 XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]); 1409 XCTAssertFalse( 1410 [message hasExtension:[UnittestRoot optionalNestedMessageExtension]]); 1411 XCTAssertFalse( 1412 [message hasExtension:[UnittestRoot optionalForeignMessageExtension]]); 1413 XCTAssertFalse( 1414 [message hasExtension:[UnittestRoot optionalImportMessageExtension]]); 1415 XCTAssertFalse([message 1416 hasExtension:[UnittestRoot optionalPublicImportMessageExtension]]); 1417 XCTAssertFalse( 1418 [message hasExtension:[UnittestRoot optionalLazyMessageExtension]]); 1419 1420 // They should auto create something when fetched. 1421 1422 TestAllTypes_OptionalGroup *optionalGroup = 1423 [message getExtension:[UnittestRoot optionalGroupExtension]]; 1424 TestAllTypes_NestedMessage *optionalNestedMessage = 1425 [message getExtension:[UnittestRoot optionalNestedMessageExtension]]; 1426 ForeignMessage *optionalForeignMessage = 1427 [message getExtension:[UnittestRoot optionalForeignMessageExtension]]; 1428 ImportMessage *optionalImportMessage = 1429 [message getExtension:[UnittestRoot optionalImportMessageExtension]]; 1430 PublicImportMessage *optionalPublicImportMessage = [message 1431 getExtension:[UnittestRoot optionalPublicImportMessageExtension]]; 1432 TestAllTypes_NestedMessage *optionalLazyMessage = 1433 [message getExtension:[UnittestRoot optionalLazyMessageExtension]]; 1434 1435 XCTAssertNotNil(optionalGroup); 1436 XCTAssertNotNil(optionalNestedMessage); 1437 XCTAssertNotNil(optionalForeignMessage); 1438 XCTAssertNotNil(optionalImportMessage); 1439 XCTAssertNotNil(optionalPublicImportMessage); 1440 XCTAssertNotNil(optionalLazyMessage); 1441 1442 // Although it auto-created empty messages, it should not show that it has 1443 // them. 1444 1445 XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]); 1446 XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]); 1447 XCTAssertFalse([message hasExtension:[UnittestRoot optionalNestedMessageExtension]]); 1448 XCTAssertFalse([message hasExtension:[UnittestRoot optionalForeignMessageExtension]]); 1449 XCTAssertFalse([message hasExtension:[UnittestRoot optionalImportMessageExtension]]); 1450 XCTAssertFalse([message hasExtension:[UnittestRoot optionalPublicImportMessageExtension]]); 1451 XCTAssertFalse([message hasExtension:[UnittestRoot optionalLazyMessageExtension]]); 1452 1453 // And they set that value back in to the message since the value created was 1454 // mutable (so a second fetch should give the same object). 1455 1456 XCTAssertEqual([message getExtension:[UnittestRoot optionalGroupExtension]], 1457 optionalGroup); 1458 XCTAssertEqual( 1459 [message getExtension:[UnittestRoot optionalNestedMessageExtension]], 1460 optionalNestedMessage); 1461 XCTAssertEqual( 1462 [message getExtension:[UnittestRoot optionalForeignMessageExtension]], 1463 optionalForeignMessage); 1464 XCTAssertEqual( 1465 [message getExtension:[UnittestRoot optionalImportMessageExtension]], 1466 optionalImportMessage); 1467 XCTAssertEqual( 1468 [message getExtension:[UnittestRoot optionalPublicImportMessageExtension]], 1469 optionalPublicImportMessage); 1470 XCTAssertEqual( 1471 [message getExtension:[UnittestRoot optionalLazyMessageExtension]], 1472 optionalLazyMessage); 1473 1474 // And the default objects for a second message should be distinct (again, 1475 // since they are mutable, each needs their own copy). 1476 1477 TestAllExtensions *message2 = [TestAllExtensions message]; 1478 1479 // Intentionally doing a pointer comparison. 1480 XCTAssertNotEqual( 1481 [message2 getExtension:[UnittestRoot optionalGroupExtension]], 1482 optionalGroup); 1483 XCTAssertNotEqual( 1484 [message2 getExtension:[UnittestRoot optionalNestedMessageExtension]], 1485 optionalNestedMessage); 1486 XCTAssertNotEqual( 1487 [message2 getExtension:[UnittestRoot optionalForeignMessageExtension]], 1488 optionalForeignMessage); 1489 XCTAssertNotEqual( 1490 [message2 getExtension:[UnittestRoot optionalImportMessageExtension]], 1491 optionalImportMessage); 1492 XCTAssertNotEqual( 1493 [message2 getExtension:[UnittestRoot optionalPublicImportMessageExtension]], 1494 optionalPublicImportMessage); 1495 XCTAssertNotEqual( 1496 [message2 getExtension:[UnittestRoot optionalLazyMessageExtension]], 1497 optionalLazyMessage); 1498 1499 // Clear values, and on next access you get back new submessages. 1500 1501 [message setExtension:[UnittestRoot optionalGroupExtension] value:nil]; 1502 [message setExtension:[UnittestRoot optionalGroupExtension] value:nil]; 1503 [message setExtension:[UnittestRoot optionalNestedMessageExtension] 1504 value:nil]; 1505 [message setExtension:[UnittestRoot optionalForeignMessageExtension] 1506 value:nil]; 1507 [message setExtension:[UnittestRoot optionalImportMessageExtension] 1508 value:nil]; 1509 [message setExtension:[UnittestRoot optionalPublicImportMessageExtension] 1510 value:nil]; 1511 [message setExtension:[UnittestRoot optionalLazyMessageExtension] value:nil]; 1512 1513 XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]); 1514 XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]); 1515 XCTAssertFalse( 1516 [message hasExtension:[UnittestRoot optionalNestedMessageExtension]]); 1517 XCTAssertFalse( 1518 [message hasExtension:[UnittestRoot optionalForeignMessageExtension]]); 1519 XCTAssertFalse( 1520 [message hasExtension:[UnittestRoot optionalImportMessageExtension]]); 1521 XCTAssertFalse([message 1522 hasExtension:[UnittestRoot optionalPublicImportMessageExtension]]); 1523 XCTAssertFalse( 1524 [message hasExtension:[UnittestRoot optionalLazyMessageExtension]]); 1525 1526 XCTAssertEqual([message getExtension:[UnittestRoot optionalGroupExtension]], 1527 optionalGroup); 1528 XCTAssertEqual( 1529 [message getExtension:[UnittestRoot optionalNestedMessageExtension]], 1530 optionalNestedMessage); 1531 XCTAssertEqual( 1532 [message getExtension:[UnittestRoot optionalForeignMessageExtension]], 1533 optionalForeignMessage); 1534 XCTAssertEqual( 1535 [message getExtension:[UnittestRoot optionalImportMessageExtension]], 1536 optionalImportMessage); 1537 XCTAssertEqual( 1538 [message 1539 getExtension:[UnittestRoot optionalPublicImportMessageExtension]], 1540 optionalPublicImportMessage); 1541 XCTAssertEqual( 1542 [message getExtension:[UnittestRoot optionalLazyMessageExtension]], 1543 optionalLazyMessage); 1544} 1545 1546- (void)testMultiplePointersToAutocreatedExtension { 1547 // 2 objects point to the same auto-created extension. One should "has" it. 1548 // The other should not. 1549 TestAllExtensions *message = [TestAllExtensions message]; 1550 TestAllExtensions *message2 = [TestAllExtensions message]; 1551 GPBExtensionDescriptor *extension = [UnittestRoot optionalGroupExtension]; 1552 [message setExtension:extension value:[message2 getExtension:extension]]; 1553 XCTAssertEqual([message getExtension:extension], 1554 [message2 getExtension:extension]); 1555 XCTAssertFalse([message2 hasExtension:extension]); 1556 XCTAssertTrue([message hasExtension:extension]); 1557 1558 TestAllTypes_OptionalGroup *extensionValue = 1559 [message2 getExtension:extension]; 1560 extensionValue.a = 1; 1561 XCTAssertTrue([message2 hasExtension:extension]); 1562 XCTAssertTrue([message hasExtension:extension]); 1563} 1564 1565- (void)testCopyWithAutocreatedExtension { 1566 // Mutable copy shouldn't copy autocreated extensions. 1567 TestAllExtensions *message = [TestAllExtensions message]; 1568 GPBExtensionDescriptor *optionalGroupExtension = 1569 [UnittestRoot optionalGroupExtension]; 1570 GPBExtensionDescriptor *optionalNestedMessageExtesion = 1571 [UnittestRoot optionalNestedMessageExtension]; 1572 TestAllTypes_OptionalGroup *optionalGroup = 1573 [message getExtension:optionalGroupExtension]; 1574 optionalGroup.a = 42; 1575 XCTAssertNotNil(optionalGroup); 1576 XCTAssertNotNil([message getExtension:optionalNestedMessageExtesion]); 1577 XCTAssertTrue([message hasExtension:optionalGroupExtension]); 1578 XCTAssertFalse([message hasExtension:optionalNestedMessageExtesion]); 1579 1580 TestAllExtensions *message2 = [[message copy] autorelease]; 1581 1582 // message2 should end up with its own copy of the optional group. 1583 XCTAssertTrue([message2 hasExtension:optionalGroupExtension]); 1584 XCTAssertEqualObjects([message getExtension:optionalGroupExtension], 1585 [message2 getExtension:optionalGroupExtension]); 1586 // Intentionally doing a pointer comparison. 1587 XCTAssertNotEqual([message getExtension:optionalGroupExtension], 1588 [message2 getExtension:optionalGroupExtension]); 1589 1590 XCTAssertFalse([message2 hasExtension:optionalNestedMessageExtesion]); 1591 // Intentionally doing a pointer comparison (auto creation should be 1592 // different) 1593 XCTAssertNotEqual([message getExtension:optionalNestedMessageExtesion], 1594 [message2 getExtension:optionalNestedMessageExtesion]); 1595} 1596 1597- (void)testClearMessageAutocreatedExtension { 1598 // Call clear should cause it to recreate its autocreated extensions. 1599 TestAllExtensions *message = [TestAllExtensions message]; 1600 GPBExtensionDescriptor *optionalGroupExtension = 1601 [UnittestRoot optionalGroupExtension]; 1602 TestAllTypes_OptionalGroup *optionalGroup = 1603 [[message getExtension:optionalGroupExtension] retain]; 1604 [message clear]; 1605 TestAllTypes_OptionalGroup *optionalGroupNew = 1606 [message getExtension:optionalGroupExtension]; 1607 1608 // Intentionally doing a pointer comparison. 1609 XCTAssertNotEqual(optionalGroup, optionalGroupNew); 1610 [optionalGroup release]; 1611} 1612 1613- (void)testRetainAutocreatedExtension { 1614 // Should be able to retain autocreated extension while the creator is 1615 // dealloced. 1616 TestAllExtensions *message = [TestAllExtensions message]; 1617 GPBExtensionDescriptor *optionalGroupExtension = 1618 [UnittestRoot optionalGroupExtension]; 1619 1620 @autoreleasepool { 1621 TestAllExtensions *message2 = [TestAllExtensions message]; 1622 [message setExtension:optionalGroupExtension 1623 value:[message2 getExtension:optionalGroupExtension]]; 1624 XCTAssertTrue(GPBWasMessageAutocreatedBy( 1625 [message getExtension:optionalGroupExtension], message2)); 1626 } 1627 1628 XCTAssertFalse(GPBWasMessageAutocreatedBy( 1629 [message getExtension:optionalGroupExtension], message)); 1630} 1631 1632- (void)testClearAutocreatedExtension { 1633 // Clearing autocreated extension should NOT cause it to lose its creator. 1634 TestAllExtensions *message = [TestAllExtensions message]; 1635 GPBExtensionDescriptor *optionalGroupExtension = 1636 [UnittestRoot optionalGroupExtension]; 1637 TestAllTypes_OptionalGroup *optionalGroup = 1638 [[message getExtension:optionalGroupExtension] retain]; 1639 [message clearExtension:optionalGroupExtension]; 1640 TestAllTypes_OptionalGroup *optionalGroupNew = 1641 [message getExtension:optionalGroupExtension]; 1642 XCTAssertEqual(optionalGroup, optionalGroupNew); 1643 XCTAssertFalse([message hasExtension:optionalGroupExtension]); 1644 [optionalGroup release]; 1645 1646 // Clearing autocreated extension should not cause its creator to become 1647 // visible 1648 GPBExtensionDescriptor *recursiveExtension = 1649 [UnittestObjcRoot recursiveExtension]; 1650 TestAllExtensions *message_lvl2 = [message getExtension:recursiveExtension]; 1651 TestAllExtensions *message_lvl3 = 1652 [message_lvl2 getExtension:recursiveExtension]; 1653 [message_lvl3 clearExtension:recursiveExtension]; 1654 XCTAssertFalse([message hasExtension:recursiveExtension]); 1655} 1656 1657- (void)testSetAutocreatedExtensionBecomesVisible { 1658 // Setting an extension should cause the extension to appear to its creator. 1659 // Test this several levels deep. 1660 TestAllExtensions *message = [TestAllExtensions message]; 1661 GPBExtensionDescriptor *recursiveExtension = 1662 [UnittestObjcRoot recursiveExtension]; 1663 TestAllExtensions *message_lvl2 = [message getExtension:recursiveExtension]; 1664 TestAllExtensions *message_lvl3 = 1665 [message_lvl2 getExtension:recursiveExtension]; 1666 TestAllExtensions *message_lvl4 = 1667 [message_lvl3 getExtension:recursiveExtension]; 1668 XCTAssertFalse([message hasExtension:recursiveExtension]); 1669 XCTAssertFalse([message_lvl2 hasExtension:recursiveExtension]); 1670 XCTAssertFalse([message_lvl3 hasExtension:recursiveExtension]); 1671 XCTAssertFalse([message_lvl4 hasExtension:recursiveExtension]); 1672 [message_lvl4 setExtension:[UnittestRoot optionalInt32Extension] value:@(1)]; 1673 XCTAssertTrue([message hasExtension:recursiveExtension]); 1674 XCTAssertTrue([message_lvl2 hasExtension:recursiveExtension]); 1675 XCTAssertTrue([message_lvl3 hasExtension:recursiveExtension]); 1676 XCTAssertFalse([message_lvl4 hasExtension:recursiveExtension]); 1677 XCTAssertFalse(GPBWasMessageAutocreatedBy(message_lvl4, message_lvl3)); 1678 XCTAssertFalse(GPBWasMessageAutocreatedBy(message_lvl3, message_lvl2)); 1679 XCTAssertFalse(GPBWasMessageAutocreatedBy(message_lvl2, message)); 1680} 1681 1682- (void)testSetAutocreatedExtensionToSelf { 1683 // Setting extension to itself should cause it to become visible. 1684 TestAllExtensions *message = [TestAllExtensions message]; 1685 GPBExtensionDescriptor *optionalGroupExtension = 1686 [UnittestRoot optionalGroupExtension]; 1687 XCTAssertNotNil([message getExtension:optionalGroupExtension]); 1688 XCTAssertFalse([message hasExtension:optionalGroupExtension]); 1689 [message setExtension:optionalGroupExtension 1690 value:[message getExtension:optionalGroupExtension]]; 1691 XCTAssertTrue([message hasExtension:optionalGroupExtension]); 1692} 1693 1694- (void)testAutocreatedExtensionMemoryLeaks { 1695 GPBExtensionDescriptor *recursiveExtension = 1696 [UnittestObjcRoot recursiveExtension]; 1697 1698 // Test for memory leaks with autocreated extensions. 1699 TestAllExtensions *message; 1700 TestAllExtensions *message_lvl2; 1701 TestAllExtensions *message_lvl3; 1702 TestAllExtensions *message_lvl4; 1703 @autoreleasepool { 1704 message = [[TestAllExtensions alloc] init]; 1705 message_lvl2 = [[message getExtension:recursiveExtension] retain]; 1706 message_lvl3 = [[message_lvl2 getExtension:recursiveExtension] retain]; 1707 message_lvl4 = [[message_lvl3 getExtension:recursiveExtension] retain]; 1708 [message_lvl2 setExtension:[UnittestRoot optionalInt32Extension] 1709 value:@(1)]; 1710 } 1711 1712 XCTAssertEqual(message.retainCount, (NSUInteger)1); 1713 @autoreleasepool { 1714 [message release]; 1715 } 1716 XCTAssertEqual(message_lvl2.retainCount, (NSUInteger)1); 1717 @autoreleasepool { 1718 [message_lvl2 release]; 1719 } 1720 XCTAssertEqual(message_lvl3.retainCount, (NSUInteger)1); 1721 @autoreleasepool { 1722 [message_lvl3 release]; 1723 } 1724 XCTAssertEqual(message_lvl4.retainCount, (NSUInteger)1); 1725 [message_lvl4 release]; 1726} 1727 1728- (void)testSetExtensionWithAutocreatedValue { 1729 GPBExtensionDescriptor *recursiveExtension = 1730 [UnittestObjcRoot recursiveExtension]; 1731 1732 TestAllExtensions *message; 1733 @autoreleasepool { 1734 message = [[TestAllExtensions alloc] init]; 1735 [message getExtension:recursiveExtension]; 1736 } 1737 1738 // This statements checks that the extension value isn't accidentally 1739 // dealloced when removing it from the autocreated map. 1740 [message setExtension:recursiveExtension 1741 value:[message getExtension:recursiveExtension]]; 1742 XCTAssertTrue([message hasExtension:recursiveExtension]); 1743 [message release]; 1744} 1745 1746- (void)testRecursion { 1747 TestRecursiveMessage *message = [TestRecursiveMessage message]; 1748 XCTAssertNotNil(message.a); 1749 XCTAssertNotNil(message.a.a); 1750 XCTAssertEqual(message.a.a.i, 0); 1751} 1752 1753- (void)testGenerateAndParseUnknownMessage { 1754 GPBUnknownFieldSet *unknowns = 1755 [[[GPBUnknownFieldSet alloc] init] autorelease]; 1756 [unknowns mergeVarintField:123 value:456]; 1757 GPBMessage *message = [GPBMessage message]; 1758 [message setUnknownFields:unknowns]; 1759 NSData *data = [message data]; 1760 GPBMessage *message2 = 1761 [GPBMessage parseFromData:data extensionRegistry:nil error:NULL]; 1762 XCTAssertEqualObjects(message, message2); 1763} 1764 1765- (void)testDelimitedWriteAndParseMultipleMessages { 1766 GPBUnknownFieldSet *unknowns1 = 1767 [[[GPBUnknownFieldSet alloc] init] autorelease]; 1768 [unknowns1 mergeVarintField:123 value:456]; 1769 GPBMessage *message1 = [GPBMessage message]; 1770 [message1 setUnknownFields:unknowns1]; 1771 1772 GPBUnknownFieldSet *unknowns2 = 1773 [[[GPBUnknownFieldSet alloc] init] autorelease]; 1774 [unknowns2 mergeVarintField:789 value:987]; 1775 [unknowns2 mergeVarintField:654 value:321]; 1776 GPBMessage *message2 = [GPBMessage message]; 1777 [message2 setUnknownFields:unknowns2]; 1778 1779 NSMutableData *delimitedData = [NSMutableData data]; 1780 [delimitedData appendData:[message1 delimitedData]]; 1781 [delimitedData appendData:[message2 delimitedData]]; 1782 GPBCodedInputStream *input = 1783 [GPBCodedInputStream streamWithData:delimitedData]; 1784 GPBMessage *message3 = [GPBMessage parseDelimitedFromCodedInputStream:input 1785 extensionRegistry:nil 1786 error:NULL]; 1787 GPBMessage *message4 = [GPBMessage parseDelimitedFromCodedInputStream:input 1788 extensionRegistry:nil 1789 error:NULL]; 1790 XCTAssertEqualObjects(message1, message3); 1791 XCTAssertEqualObjects(message2, message4); 1792} 1793 1794- (void)testDuplicateEnums { 1795 XCTAssertEqual(TestEnumWithDupValue_Foo1, TestEnumWithDupValue_Foo2); 1796} 1797 1798- (void)testWeirdDefaults { 1799 ObjcWeirdDefaults *message = [ObjcWeirdDefaults message]; 1800 GPBDescriptor *descriptor = [[message class] descriptor]; 1801 GPBFieldDescriptor *fieldDesc = [descriptor fieldWithName:@"foo"]; 1802 XCTAssertNotNil(fieldDesc); 1803 XCTAssertTrue(fieldDesc.hasDefaultValue); 1804 XCTAssertFalse(message.hasFoo); 1805 XCTAssertEqualObjects(message.foo, @""); 1806 1807 fieldDesc = [descriptor fieldWithName:@"bar"]; 1808 XCTAssertNotNil(fieldDesc); 1809 XCTAssertTrue(fieldDesc.hasDefaultValue); 1810 XCTAssertFalse(message.hasBar); 1811 XCTAssertEqualObjects(message.bar, GPBEmptyNSData()); 1812} 1813 1814- (void)testEnumDescriptorFromExtensionDescriptor { 1815 GPBExtensionDescriptor *extDescriptor = 1816 [UnittestRoot optionalForeignEnumExtension]; 1817 XCTAssertEqual(extDescriptor.dataType, GPBDataTypeEnum); 1818 GPBEnumDescriptor *enumDescriptor = extDescriptor.enumDescriptor; 1819 GPBEnumDescriptor *expectedDescriptor = ForeignEnum_EnumDescriptor(); 1820 XCTAssertEqualObjects(enumDescriptor, expectedDescriptor); 1821} 1822 1823- (void)testPropertyNaming { 1824 // objectivec_helpers.cc has some special handing to get proper all caps 1825 // for a few cases to meet objc developer expectations. 1826 // 1827 // This "test" confirms that the expected names are generated, otherwise the 1828 // test itself will fail to compile. 1829 ObjCPropertyNaming *msg = [ObjCPropertyNaming message]; 1830 // On their own, at the end, in the middle. 1831 msg.URL = @"good"; 1832 msg.thumbnailURL = @"good"; 1833 msg.URLFoo = @"good"; 1834 msg.someURLBlah = @"good"; 1835 msg.HTTP = @"good"; 1836 msg.HTTPS = @"good"; 1837 // No caps since it was "urls". 1838 [msg.urlsArray addObject:@"good"]; 1839} 1840 1841- (void)testEnumNaming { 1842 // objectivec_helpers.cc has some interesting cases to deal with in 1843 // EnumValueName/EnumValueShortName. Confirm that things generated as 1844 // expected. 1845 1846 // This block just has to compile to confirm we got the expected types/names. 1847 // The *_IsValidValue() calls are just there to keep the projects warnings 1848 // flags happy by providing use of the variables/values. 1849 1850 Foo aFoo = Foo_SerializedSize; 1851 Foo_IsValidValue(aFoo); 1852 aFoo = Foo_Size; 1853 Foo_IsValidValue(aFoo); 1854 1855 Category_Enum aCat = Category_Enum_Red; 1856 Category_Enum_IsValidValue(aCat); 1857 1858 Time aTime = Time_Base; 1859 Time_IsValidValue(aTime); 1860 aTime = Time_SomethingElse; 1861 Time_IsValidValue(aTime); 1862 1863 // This block confirms the names in the decriptors is what we wanted. 1864 1865 GPBEnumDescriptor *descriptor; 1866 NSString *valueName; 1867 1868 descriptor = Foo_EnumDescriptor(); 1869 XCTAssertNotNil(descriptor); 1870 XCTAssertEqualObjects(@"Foo", descriptor.name); 1871 valueName = [descriptor enumNameForValue:Foo_SerializedSize]; 1872 XCTAssertEqualObjects(@"Foo_SerializedSize", valueName); 1873 valueName = [descriptor enumNameForValue:Foo_Size]; 1874 XCTAssertEqualObjects(@"Foo_Size", valueName); 1875 1876 descriptor = Category_Enum_EnumDescriptor(); 1877 XCTAssertNotNil(descriptor); 1878 XCTAssertEqualObjects(@"Category_Enum", descriptor.name); 1879 valueName = [descriptor enumNameForValue:Category_Enum_Red]; 1880 XCTAssertEqualObjects(@"Category_Enum_Red", valueName); 1881 1882 descriptor = Time_EnumDescriptor(); 1883 XCTAssertNotNil(descriptor); 1884 XCTAssertEqualObjects(@"Time", descriptor.name); 1885 valueName = [descriptor enumNameForValue:Time_Base]; 1886 XCTAssertEqualObjects(@"Time_Base", valueName); 1887 valueName = [descriptor enumNameForValue:Time_SomethingElse]; 1888 XCTAssertEqualObjects(@"Time_SomethingElse", valueName); 1889} 1890 1891- (void)testNegativeEnums { 1892 EnumTestMsg *msg = [EnumTestMsg message]; 1893 1894 // Defaults 1895 XCTAssertEqual(msg.foo, EnumTestMsg_MyEnum_Zero); 1896 XCTAssertEqual(msg.bar, EnumTestMsg_MyEnum_One); 1897 XCTAssertEqual(msg.baz, EnumTestMsg_MyEnum_NegOne); 1898 // Bounce to wire and back. 1899 NSData *data = [msg data]; 1900 XCTAssertNotNil(data); 1901 EnumTestMsg *msgPrime = [EnumTestMsg parseFromData:data error:NULL]; 1902 XCTAssertEqualObjects(msgPrime, msg); 1903 XCTAssertEqual(msgPrime.foo, EnumTestMsg_MyEnum_Zero); 1904 XCTAssertEqual(msgPrime.bar, EnumTestMsg_MyEnum_One); 1905 XCTAssertEqual(msgPrime.baz, EnumTestMsg_MyEnum_NegOne); 1906 1907 // Other values 1908 msg.bar = EnumTestMsg_MyEnum_Two; 1909 msg.baz = EnumTestMsg_MyEnum_NegTwo; 1910 XCTAssertEqual(msg.bar, EnumTestMsg_MyEnum_Two); 1911 XCTAssertEqual(msg.baz, EnumTestMsg_MyEnum_NegTwo); 1912 // Bounce to wire and back. 1913 data = [msg data]; 1914 XCTAssertNotNil(data); 1915 msgPrime = [EnumTestMsg parseFromData:data error:NULL]; 1916 XCTAssertEqualObjects(msgPrime, msg); 1917 XCTAssertEqual(msgPrime.foo, EnumTestMsg_MyEnum_Zero); 1918 XCTAssertEqual(msgPrime.bar, EnumTestMsg_MyEnum_Two); 1919 XCTAssertEqual(msgPrime.baz, EnumTestMsg_MyEnum_NegTwo); 1920 1921 // Repeated field (shouldn't ever be an issue since developer has to use the 1922 // right GPBArray methods themselves). 1923 msg.mumbleArray = [GPBEnumArray 1924 arrayWithValidationFunction:EnumTestMsg_MyEnum_IsValidValue]; 1925 [msg.mumbleArray addValue:EnumTestMsg_MyEnum_Zero]; 1926 [msg.mumbleArray addValue:EnumTestMsg_MyEnum_One]; 1927 [msg.mumbleArray addValue:EnumTestMsg_MyEnum_Two]; 1928 [msg.mumbleArray addValue:EnumTestMsg_MyEnum_NegOne]; 1929 [msg.mumbleArray addValue:EnumTestMsg_MyEnum_NegTwo]; 1930 XCTAssertEqual([msg.mumbleArray valueAtIndex:0], EnumTestMsg_MyEnum_Zero); 1931 XCTAssertEqual([msg.mumbleArray valueAtIndex:1], EnumTestMsg_MyEnum_One); 1932 XCTAssertEqual([msg.mumbleArray valueAtIndex:2], EnumTestMsg_MyEnum_Two); 1933 XCTAssertEqual([msg.mumbleArray valueAtIndex:3], EnumTestMsg_MyEnum_NegOne); 1934 XCTAssertEqual([msg.mumbleArray valueAtIndex:4], EnumTestMsg_MyEnum_NegTwo); 1935 // Bounce to wire and back. 1936 data = [msg data]; 1937 XCTAssertNotNil(data); 1938 msgPrime = [EnumTestMsg parseFromData:data error:NULL]; 1939 XCTAssertEqualObjects(msgPrime, msg); 1940 XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:0], 1941 EnumTestMsg_MyEnum_Zero); 1942 XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:1], EnumTestMsg_MyEnum_One); 1943 XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:2], EnumTestMsg_MyEnum_Two); 1944 XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:3], 1945 EnumTestMsg_MyEnum_NegOne); 1946 XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:4], 1947 EnumTestMsg_MyEnum_NegTwo); 1948} 1949 1950- (void)testOneBasedEnumHolder { 1951 // Test case for https://github.com/google/protobuf/issues/1453 1952 // Message with no explicit defaults, but a non zero default for an enum. 1953 MessageWithOneBasedEnum *enumMsg = [MessageWithOneBasedEnum message]; 1954 XCTAssertEqual(enumMsg.enumField, MessageWithOneBasedEnum_OneBasedEnum_One); 1955} 1956 1957- (void)testBoolOffsetUsage { 1958 // Bools use storage within has_bits; this test ensures that this is honored 1959 // in all places where things should crash or fail based on reading out of 1960 // field storage instead. 1961 BoolOnlyMessage *msg1 = [BoolOnlyMessage message]; 1962 BoolOnlyMessage *msg2 = [BoolOnlyMessage message]; 1963 1964 msg1.boolField1 = YES; 1965 msg2.boolField1 = YES; 1966 msg1.boolField3 = YES; 1967 msg2.boolField3 = YES; 1968 msg1.boolField5 = YES; 1969 msg2.boolField5 = YES; 1970 msg1.boolField7 = YES; 1971 msg2.boolField7 = YES; 1972 msg1.boolField9 = YES; 1973 msg2.boolField9 = YES; 1974 msg1.boolField11 = YES; 1975 msg2.boolField11 = YES; 1976 msg1.boolField13 = YES; 1977 msg2.boolField13 = YES; 1978 msg1.boolField15 = YES; 1979 msg2.boolField15 = YES; 1980 msg1.boolField17 = YES; 1981 msg2.boolField17 = YES; 1982 msg1.boolField19 = YES; 1983 msg2.boolField19 = YES; 1984 msg1.boolField21 = YES; 1985 msg2.boolField21 = YES; 1986 msg1.boolField23 = YES; 1987 msg2.boolField23 = YES; 1988 msg1.boolField25 = YES; 1989 msg2.boolField25 = YES; 1990 msg1.boolField27 = YES; 1991 msg2.boolField27 = YES; 1992 msg1.boolField29 = YES; 1993 msg2.boolField29 = YES; 1994 msg1.boolField31 = YES; 1995 msg2.boolField31 = YES; 1996 1997 msg1.boolField32 = YES; 1998 msg2.boolField32 = YES; 1999 2000 XCTAssertTrue(msg1 != msg2); // Different pointers. 2001 XCTAssertEqual([msg1 hash], [msg2 hash]); 2002 XCTAssertEqualObjects(msg1, msg2); 2003 2004 BoolOnlyMessage *msg1Prime = [[msg1 copy] autorelease]; 2005 XCTAssertTrue(msg1Prime != msg1); // Different pointers. 2006 XCTAssertEqual([msg1 hash], [msg1Prime hash]); 2007 XCTAssertEqualObjects(msg1, msg1Prime); 2008 2009 // Field set in one, but not the other means they don't match (even if 2010 // set to default value). 2011 msg1Prime.boolField2 = NO; 2012 XCTAssertNotEqualObjects(msg1Prime, msg1); 2013 // And when set to different values. 2014 msg1.boolField2 = YES; 2015 XCTAssertNotEqualObjects(msg1Prime, msg1); 2016 // And then they match again. 2017 msg1.boolField2 = NO; 2018 XCTAssertEqualObjects(msg1Prime, msg1); 2019 XCTAssertEqual([msg1 hash], [msg1Prime hash]); 2020} 2021 2022@end 2023