• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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