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