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 <XCTest/XCTest.h> 32*1b3f573fSAndroid Build Coastguard Worker 33*1b3f573fSAndroid Build Coastguard Worker#import "GPBUtilities_PackagePrivate.h" 34*1b3f573fSAndroid Build Coastguard Worker 35*1b3f573fSAndroid Build Coastguard Worker#import <objc/runtime.h> 36*1b3f573fSAndroid Build Coastguard Worker 37*1b3f573fSAndroid Build Coastguard Worker#import "GPBTestUtilities.h" 38*1b3f573fSAndroid Build Coastguard Worker 39*1b3f573fSAndroid Build Coastguard Worker#import "GPBDescriptor.h" 40*1b3f573fSAndroid Build Coastguard Worker#import "GPBDescriptor_PackagePrivate.h" 41*1b3f573fSAndroid Build Coastguard Worker#import "GPBMessage.h" 42*1b3f573fSAndroid Build Coastguard Worker#import "GPBUnknownField_PackagePrivate.h" 43*1b3f573fSAndroid Build Coastguard Worker 44*1b3f573fSAndroid Build Coastguard Worker#import "google/protobuf/MapUnittest.pbobjc.h" 45*1b3f573fSAndroid Build Coastguard Worker#import "google/protobuf/Unittest.pbobjc.h" 46*1b3f573fSAndroid Build Coastguard Worker#import "google/protobuf/UnittestObjc.pbobjc.h" 47*1b3f573fSAndroid Build Coastguard Worker 48*1b3f573fSAndroid Build Coastguard Worker@interface UtilitiesTests : GPBTestCase 49*1b3f573fSAndroid Build Coastguard Worker@end 50*1b3f573fSAndroid Build Coastguard Worker 51*1b3f573fSAndroid Build Coastguard Worker@implementation UtilitiesTests 52*1b3f573fSAndroid Build Coastguard Worker 53*1b3f573fSAndroid Build Coastguard Worker- (void)testRightShiftFunctions { 54*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual((1UL << 31) >> 31, 1UL); 55*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual((int32_t)(1U << 31) >> 31, -1); 56*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual((1ULL << 63) >> 63, 1ULL); 57*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual((int64_t)(1ULL << 63) >> 63, -1LL); 58*1b3f573fSAndroid Build Coastguard Worker 59*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual(GPBLogicalRightShift32((1U << 31), 31), 1); 60*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual(GPBLogicalRightShift64((1ULL << 63), 63), 1LL); 61*1b3f573fSAndroid Build Coastguard Worker} 62*1b3f573fSAndroid Build Coastguard Worker 63*1b3f573fSAndroid Build Coastguard Worker- (void)testGPBDecodeTextFormatName { 64*1b3f573fSAndroid Build Coastguard Worker uint8_t decodeData[] = { 65*1b3f573fSAndroid Build Coastguard Worker 0x6, 66*1b3f573fSAndroid Build Coastguard Worker // An inlined string (first to make sure the leading null is handled 67*1b3f573fSAndroid Build Coastguard Worker // correctly, and with a key of zero to check that). 68*1b3f573fSAndroid Build Coastguard Worker 0x0, 0x0, 'z', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 'J', 0x0, 69*1b3f573fSAndroid Build Coastguard Worker // All as is (00 op) 70*1b3f573fSAndroid Build Coastguard Worker 0x1, 0x0A, 0x0, 71*1b3f573fSAndroid Build Coastguard Worker // Underscore, upper + 9 (10 op) 72*1b3f573fSAndroid Build Coastguard Worker 0x3, 0xCA, 0x0, 73*1b3f573fSAndroid Build Coastguard Worker // Upper + 3 (10 op), underscore, upper + 5 (10 op) 74*1b3f573fSAndroid Build Coastguard Worker 0x2, 0x44, 0xC6, 0x0, 75*1b3f573fSAndroid Build Coastguard Worker // All Upper for 4 (11 op), underscore, underscore, upper + 5 (10 op), 76*1b3f573fSAndroid Build Coastguard Worker // underscore, lower + 0 (01 op) 77*1b3f573fSAndroid Build Coastguard Worker 0x4, 0x64, 0x80, 0xC5, 0xA1, 0x0, 78*1b3f573fSAndroid Build Coastguard Worker // 2 byte key: as is + 3 (00 op), underscore, lower + 4 (01 op), 79*1b3f573fSAndroid Build Coastguard Worker // underscore, lower + 3 (01 op), underscore, lower + 1 (01 op), 80*1b3f573fSAndroid Build Coastguard Worker // underscore, lower + 30 (01 op), as is + 30 (00 op), as is + 13 (00 op), 81*1b3f573fSAndroid Build Coastguard Worker // underscore, as is + 3 (00 op) 82*1b3f573fSAndroid Build Coastguard Worker 0xE8, 0x07, 0x04, 0xA5, 0xA4, 0xA2, 0xBF, 0x1F, 0x0E, 0x84, 0x0, 83*1b3f573fSAndroid Build Coastguard Worker }; 84*1b3f573fSAndroid Build Coastguard Worker NSString *inputStr = @"abcdefghIJ"; 85*1b3f573fSAndroid Build Coastguard Worker 86*1b3f573fSAndroid Build Coastguard Worker // Empty inputs 87*1b3f573fSAndroid Build Coastguard Worker 88*1b3f573fSAndroid Build Coastguard Worker XCTAssertNil(GPBDecodeTextFormatName(nil, 1, NULL)); 89*1b3f573fSAndroid Build Coastguard Worker XCTAssertNil(GPBDecodeTextFormatName(decodeData, 1, NULL)); 90*1b3f573fSAndroid Build Coastguard Worker XCTAssertNil(GPBDecodeTextFormatName(nil, 1, inputStr)); 91*1b3f573fSAndroid Build Coastguard Worker 92*1b3f573fSAndroid Build Coastguard Worker // Keys not found. 93*1b3f573fSAndroid Build Coastguard Worker 94*1b3f573fSAndroid Build Coastguard Worker XCTAssertNil(GPBDecodeTextFormatName(decodeData, 5, inputStr)); 95*1b3f573fSAndroid Build Coastguard Worker XCTAssertNil(GPBDecodeTextFormatName(decodeData, -1, inputStr)); 96*1b3f573fSAndroid Build Coastguard Worker 97*1b3f573fSAndroid Build Coastguard Worker // Some name decodes. 98*1b3f573fSAndroid Build Coastguard Worker 99*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 1, inputStr), @"abcdefghIJ"); 100*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 2, inputStr), @"Abcd_EfghIJ"); 101*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 3, inputStr), @"_AbcdefghIJ"); 102*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 4, inputStr), @"ABCD__EfghI_j"); 103*1b3f573fSAndroid Build Coastguard Worker 104*1b3f573fSAndroid Build Coastguard Worker // An inlined string (and key of zero). 105*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 0, inputStr), @"zbcdefghIJ"); 106*1b3f573fSAndroid Build Coastguard Worker 107*1b3f573fSAndroid Build Coastguard Worker // Long name so multiple decode ops are needed. 108*1b3f573fSAndroid Build Coastguard Worker inputStr = @"longFieldNameIsLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1000"; 109*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 1000, inputStr), 110*1b3f573fSAndroid Build Coastguard Worker @"long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000"); 111*1b3f573fSAndroid Build Coastguard Worker} 112*1b3f573fSAndroid Build Coastguard Worker 113*1b3f573fSAndroid Build Coastguard Worker- (void)testTextFormat { 114*1b3f573fSAndroid Build Coastguard Worker TestAllTypes *message = [TestAllTypes message]; 115*1b3f573fSAndroid Build Coastguard Worker 116*1b3f573fSAndroid Build Coastguard Worker // Not kGPBDefaultRepeatCount because we are comparing to golden master file 117*1b3f573fSAndroid Build Coastguard Worker // which was generated with 2. 118*1b3f573fSAndroid Build Coastguard Worker [self setAllFields:message repeatedCount:2]; 119*1b3f573fSAndroid Build Coastguard Worker 120*1b3f573fSAndroid Build Coastguard Worker NSString *result = GPBTextFormatForMessage(message, nil); 121*1b3f573fSAndroid Build Coastguard Worker 122*1b3f573fSAndroid Build Coastguard Worker NSString *fileName = @"text_format_unittest_data.txt"; 123*1b3f573fSAndroid Build Coastguard Worker NSData *resultData = [result dataUsingEncoding:NSUTF8StringEncoding]; 124*1b3f573fSAndroid Build Coastguard Worker NSData *expectedData = 125*1b3f573fSAndroid Build Coastguard Worker [self getDataFileNamed:fileName dataToWrite:resultData]; 126*1b3f573fSAndroid Build Coastguard Worker NSString *expected = [[NSString alloc] initWithData:expectedData 127*1b3f573fSAndroid Build Coastguard Worker encoding:NSUTF8StringEncoding]; 128*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqualObjects(expected, result); 129*1b3f573fSAndroid Build Coastguard Worker [expected release]; 130*1b3f573fSAndroid Build Coastguard Worker} 131*1b3f573fSAndroid Build Coastguard Worker 132*1b3f573fSAndroid Build Coastguard Worker- (void)testTextFormatExtra { 133*1b3f573fSAndroid Build Coastguard Worker // -testTextFormat uses all protos with fields that don't require special 134*1b3f573fSAndroid Build Coastguard Worker // handing for figuring out the names. The ObjC proto has a bunch of oddball 135*1b3f573fSAndroid Build Coastguard Worker // field and enum names that require the decode info to get right, so this 136*1b3f573fSAndroid Build Coastguard Worker // confirms they generated and decoded correctly. 137*1b3f573fSAndroid Build Coastguard Worker 138*1b3f573fSAndroid Build Coastguard Worker self_Class *message = [self_Class message]; 139*1b3f573fSAndroid Build Coastguard Worker message.cmd = YES; 140*1b3f573fSAndroid Build Coastguard Worker message.isProxy_p = YES; 141*1b3f573fSAndroid Build Coastguard Worker message.subEnum = self_autorelease_RetainCount; 142*1b3f573fSAndroid Build Coastguard Worker message.new_p.copy_p = @"foo"; 143*1b3f573fSAndroid Build Coastguard Worker 144*1b3f573fSAndroid Build Coastguard Worker NSString *expected = @"_cmd: true\n" 145*1b3f573fSAndroid Build Coastguard Worker @"isProxy: true\n" 146*1b3f573fSAndroid Build Coastguard Worker @"SubEnum: retainCount\n" 147*1b3f573fSAndroid Build Coastguard Worker @"New {\n" 148*1b3f573fSAndroid Build Coastguard Worker @" copy: \"foo\"\n" 149*1b3f573fSAndroid Build Coastguard Worker @"}\n"; 150*1b3f573fSAndroid Build Coastguard Worker NSString *result = GPBTextFormatForMessage(message, nil); 151*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqualObjects(expected, result); 152*1b3f573fSAndroid Build Coastguard Worker} 153*1b3f573fSAndroid Build Coastguard Worker 154*1b3f573fSAndroid Build Coastguard Worker- (void)testTextFormatMaps { 155*1b3f573fSAndroid Build Coastguard Worker TestMap *message = [TestMap message]; 156*1b3f573fSAndroid Build Coastguard Worker 157*1b3f573fSAndroid Build Coastguard Worker // Map iteration order doesn't have to be stable, so use only one entry. 158*1b3f573fSAndroid Build Coastguard Worker [self setAllMapFields:message numEntries:1]; 159*1b3f573fSAndroid Build Coastguard Worker 160*1b3f573fSAndroid Build Coastguard Worker NSString *result = GPBTextFormatForMessage(message, nil); 161*1b3f573fSAndroid Build Coastguard Worker 162*1b3f573fSAndroid Build Coastguard Worker NSString *fileName = @"text_format_map_unittest_data.txt"; 163*1b3f573fSAndroid Build Coastguard Worker NSData *resultData = [result dataUsingEncoding:NSUTF8StringEncoding]; 164*1b3f573fSAndroid Build Coastguard Worker NSData *expectedData = 165*1b3f573fSAndroid Build Coastguard Worker [self getDataFileNamed:fileName dataToWrite:resultData]; 166*1b3f573fSAndroid Build Coastguard Worker NSString *expected = [[NSString alloc] initWithData:expectedData 167*1b3f573fSAndroid Build Coastguard Worker encoding:NSUTF8StringEncoding]; 168*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqualObjects(expected, result); 169*1b3f573fSAndroid Build Coastguard Worker [expected release]; 170*1b3f573fSAndroid Build Coastguard Worker} 171*1b3f573fSAndroid Build Coastguard Worker 172*1b3f573fSAndroid Build Coastguard Worker- (void)testTextFormatExtensions { 173*1b3f573fSAndroid Build Coastguard Worker TestAllExtensions *message = [TestAllExtensions message]; 174*1b3f573fSAndroid Build Coastguard Worker 175*1b3f573fSAndroid Build Coastguard Worker // Not kGPBDefaultRepeatCount because we are comparing to golden master file 176*1b3f573fSAndroid Build Coastguard Worker // which was generated with 2. 177*1b3f573fSAndroid Build Coastguard Worker [self setAllExtensions:message repeatedCount:2]; 178*1b3f573fSAndroid Build Coastguard Worker 179*1b3f573fSAndroid Build Coastguard Worker NSString *result = GPBTextFormatForMessage(message, nil); 180*1b3f573fSAndroid Build Coastguard Worker 181*1b3f573fSAndroid Build Coastguard Worker // NOTE: ObjC TextFormat doesn't have the proper extension names so it 182*1b3f573fSAndroid Build Coastguard Worker // uses comments for the ObjC name and raw numbers for the fields instead 183*1b3f573fSAndroid Build Coastguard Worker // of the bracketed extension name. 184*1b3f573fSAndroid Build Coastguard Worker NSString *fileName = @"text_format_extensions_unittest_data.txt"; 185*1b3f573fSAndroid Build Coastguard Worker NSData *resultData = [result dataUsingEncoding:NSUTF8StringEncoding]; 186*1b3f573fSAndroid Build Coastguard Worker NSData *expectedData = 187*1b3f573fSAndroid Build Coastguard Worker [self getDataFileNamed:fileName dataToWrite:resultData]; 188*1b3f573fSAndroid Build Coastguard Worker NSString *expected = [[NSString alloc] initWithData:expectedData 189*1b3f573fSAndroid Build Coastguard Worker encoding:NSUTF8StringEncoding]; 190*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqualObjects(expected, result); 191*1b3f573fSAndroid Build Coastguard Worker [expected release]; 192*1b3f573fSAndroid Build Coastguard Worker} 193*1b3f573fSAndroid Build Coastguard Worker 194*1b3f573fSAndroid Build Coastguard Worker- (void)testSetRepeatedFields { 195*1b3f573fSAndroid Build Coastguard Worker TestAllTypes *message = [TestAllTypes message]; 196*1b3f573fSAndroid Build Coastguard Worker 197*1b3f573fSAndroid Build Coastguard Worker NSDictionary *repeatedFieldValues = @{ 198*1b3f573fSAndroid Build Coastguard Worker @"repeatedStringArray" : [@[@"foo", @"bar"] mutableCopy], 199*1b3f573fSAndroid Build Coastguard Worker @"repeatedBoolArray" : [GPBBoolArray arrayWithValue:YES], 200*1b3f573fSAndroid Build Coastguard Worker @"repeatedInt32Array" : [GPBInt32Array arrayWithValue:14], 201*1b3f573fSAndroid Build Coastguard Worker @"repeatedInt64Array" : [GPBInt64Array arrayWithValue:15], 202*1b3f573fSAndroid Build Coastguard Worker @"repeatedUint32Array" : [GPBUInt32Array arrayWithValue:16], 203*1b3f573fSAndroid Build Coastguard Worker @"repeatedUint64Array" : [GPBUInt64Array arrayWithValue:16], 204*1b3f573fSAndroid Build Coastguard Worker @"repeatedFloatArray" : [GPBFloatArray arrayWithValue:16], 205*1b3f573fSAndroid Build Coastguard Worker @"repeatedDoubleArray" : [GPBDoubleArray arrayWithValue:16], 206*1b3f573fSAndroid Build Coastguard Worker @"repeatedNestedEnumArray" : 207*1b3f573fSAndroid Build Coastguard Worker [GPBEnumArray arrayWithValidationFunction:TestAllTypes_NestedEnum_IsValidValue 208*1b3f573fSAndroid Build Coastguard Worker rawValue:TestAllTypes_NestedEnum_Foo], 209*1b3f573fSAndroid Build Coastguard Worker }; 210*1b3f573fSAndroid Build Coastguard Worker for (NSString *fieldName in repeatedFieldValues) { 211*1b3f573fSAndroid Build Coastguard Worker GPBFieldDescriptor *field = 212*1b3f573fSAndroid Build Coastguard Worker [message.descriptor fieldWithName:fieldName]; 213*1b3f573fSAndroid Build Coastguard Worker XCTAssertNotNil(field, @"No field with name: %@", fieldName); 214*1b3f573fSAndroid Build Coastguard Worker id expectedValues = repeatedFieldValues[fieldName]; 215*1b3f573fSAndroid Build Coastguard Worker GPBSetMessageRepeatedField(message, field, expectedValues); 216*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqualObjects(expectedValues, 217*1b3f573fSAndroid Build Coastguard Worker [message valueForKeyPath:fieldName]); 218*1b3f573fSAndroid Build Coastguard Worker } 219*1b3f573fSAndroid Build Coastguard Worker} 220*1b3f573fSAndroid Build Coastguard Worker 221*1b3f573fSAndroid Build Coastguard Worker// Helper to make an unknown field set with something in it. 222*1b3f573fSAndroid Build Coastguard Workerstatic GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) { 223*1b3f573fSAndroid Build Coastguard Worker GPBUnknownFieldSet *result = 224*1b3f573fSAndroid Build Coastguard Worker [[[GPBUnknownFieldSet alloc] init] autorelease]; 225*1b3f573fSAndroid Build Coastguard Worker 226*1b3f573fSAndroid Build Coastguard Worker GPBUnknownField *field = 227*1b3f573fSAndroid Build Coastguard Worker [[[GPBUnknownField alloc] initWithNumber:num] autorelease]; 228*1b3f573fSAndroid Build Coastguard Worker [field addVarint:num]; 229*1b3f573fSAndroid Build Coastguard Worker [result addField:field]; 230*1b3f573fSAndroid Build Coastguard Worker 231*1b3f573fSAndroid Build Coastguard Worker return result; 232*1b3f573fSAndroid Build Coastguard Worker} 233*1b3f573fSAndroid Build Coastguard Worker 234*1b3f573fSAndroid Build Coastguard Worker- (void)testDropMessageUnknownFieldsRecursively { 235*1b3f573fSAndroid Build Coastguard Worker TestAllExtensions *message = [TestAllExtensions message]; 236*1b3f573fSAndroid Build Coastguard Worker 237*1b3f573fSAndroid Build Coastguard Worker // Give it unknownFields. 238*1b3f573fSAndroid Build Coastguard Worker message.unknownFields = UnknownFieldsSetHelper(777); 239*1b3f573fSAndroid Build Coastguard Worker 240*1b3f573fSAndroid Build Coastguard Worker // Given it extensions that include a message with unknown fields of its own. 241*1b3f573fSAndroid Build Coastguard Worker { 242*1b3f573fSAndroid Build Coastguard Worker // Int 243*1b3f573fSAndroid Build Coastguard Worker [message setExtension:[UnittestRoot optionalInt32Extension] value:@5]; 244*1b3f573fSAndroid Build Coastguard Worker 245*1b3f573fSAndroid Build Coastguard Worker // Group 246*1b3f573fSAndroid Build Coastguard Worker OptionalGroup_extension *optionalGroup = [OptionalGroup_extension message]; 247*1b3f573fSAndroid Build Coastguard Worker optionalGroup.a = 123; 248*1b3f573fSAndroid Build Coastguard Worker optionalGroup.unknownFields = UnknownFieldsSetHelper(779); 249*1b3f573fSAndroid Build Coastguard Worker [message setExtension:[UnittestRoot optionalGroupExtension] 250*1b3f573fSAndroid Build Coastguard Worker value:optionalGroup]; 251*1b3f573fSAndroid Build Coastguard Worker 252*1b3f573fSAndroid Build Coastguard Worker // Message 253*1b3f573fSAndroid Build Coastguard Worker TestAllTypes_NestedMessage *nestedMessage = 254*1b3f573fSAndroid Build Coastguard Worker [TestAllTypes_NestedMessage message]; 255*1b3f573fSAndroid Build Coastguard Worker nestedMessage.bb = 456; 256*1b3f573fSAndroid Build Coastguard Worker nestedMessage.unknownFields = UnknownFieldsSetHelper(778); 257*1b3f573fSAndroid Build Coastguard Worker [message setExtension:[UnittestRoot optionalNestedMessageExtension] 258*1b3f573fSAndroid Build Coastguard Worker value:nestedMessage]; 259*1b3f573fSAndroid Build Coastguard Worker 260*1b3f573fSAndroid Build Coastguard Worker // Repeated Group 261*1b3f573fSAndroid Build Coastguard Worker RepeatedGroup_extension *repeatedGroup = 262*1b3f573fSAndroid Build Coastguard Worker [[RepeatedGroup_extension alloc] init]; 263*1b3f573fSAndroid Build Coastguard Worker repeatedGroup.a = 567; 264*1b3f573fSAndroid Build Coastguard Worker repeatedGroup.unknownFields = UnknownFieldsSetHelper(780); 265*1b3f573fSAndroid Build Coastguard Worker [message addExtension:[UnittestRoot repeatedGroupExtension] 266*1b3f573fSAndroid Build Coastguard Worker value:repeatedGroup]; 267*1b3f573fSAndroid Build Coastguard Worker [repeatedGroup release]; 268*1b3f573fSAndroid Build Coastguard Worker 269*1b3f573fSAndroid Build Coastguard Worker // Repeated Message 270*1b3f573fSAndroid Build Coastguard Worker nestedMessage = [[TestAllTypes_NestedMessage alloc] init]; 271*1b3f573fSAndroid Build Coastguard Worker nestedMessage.bb = 678; 272*1b3f573fSAndroid Build Coastguard Worker nestedMessage.unknownFields = UnknownFieldsSetHelper(781); 273*1b3f573fSAndroid Build Coastguard Worker [message addExtension:[UnittestRoot repeatedNestedMessageExtension] 274*1b3f573fSAndroid Build Coastguard Worker value:nestedMessage]; 275*1b3f573fSAndroid Build Coastguard Worker [nestedMessage release]; 276*1b3f573fSAndroid Build Coastguard Worker } 277*1b3f573fSAndroid Build Coastguard Worker 278*1b3f573fSAndroid Build Coastguard Worker // Confirm everything is there. 279*1b3f573fSAndroid Build Coastguard Worker 280*1b3f573fSAndroid Build Coastguard Worker XCTAssertNotNil(message); 281*1b3f573fSAndroid Build Coastguard Worker XCTAssertNotNil(message.unknownFields); 282*1b3f573fSAndroid Build Coastguard Worker XCTAssertTrue([message hasExtension:[UnittestRoot optionalInt32Extension]]); 283*1b3f573fSAndroid Build Coastguard Worker 284*1b3f573fSAndroid Build Coastguard Worker { 285*1b3f573fSAndroid Build Coastguard Worker XCTAssertTrue([message hasExtension:[UnittestRoot optionalGroupExtension]]); 286*1b3f573fSAndroid Build Coastguard Worker OptionalGroup_extension *optionalGroup = 287*1b3f573fSAndroid Build Coastguard Worker [message getExtension:[UnittestRoot optionalGroupExtension]]; 288*1b3f573fSAndroid Build Coastguard Worker XCTAssertNotNil(optionalGroup); 289*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual(optionalGroup.a, 123); 290*1b3f573fSAndroid Build Coastguard Worker XCTAssertNotNil(optionalGroup.unknownFields); 291*1b3f573fSAndroid Build Coastguard Worker } 292*1b3f573fSAndroid Build Coastguard Worker 293*1b3f573fSAndroid Build Coastguard Worker { 294*1b3f573fSAndroid Build Coastguard Worker XCTAssertTrue([message hasExtension:[UnittestRoot optionalNestedMessageExtension]]); 295*1b3f573fSAndroid Build Coastguard Worker TestAllTypes_NestedMessage *nestedMessage = 296*1b3f573fSAndroid Build Coastguard Worker [message getExtension:[UnittestRoot optionalNestedMessageExtension]]; 297*1b3f573fSAndroid Build Coastguard Worker XCTAssertNotNil(nestedMessage); 298*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual(nestedMessage.bb, 456); 299*1b3f573fSAndroid Build Coastguard Worker XCTAssertNotNil(nestedMessage.unknownFields); 300*1b3f573fSAndroid Build Coastguard Worker } 301*1b3f573fSAndroid Build Coastguard Worker 302*1b3f573fSAndroid Build Coastguard Worker { 303*1b3f573fSAndroid Build Coastguard Worker XCTAssertTrue([message hasExtension:[UnittestRoot repeatedGroupExtension]]); 304*1b3f573fSAndroid Build Coastguard Worker NSArray *repeatedGroups = [message getExtension:[UnittestRoot repeatedGroupExtension]]; 305*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual(repeatedGroups.count, (NSUInteger)1); 306*1b3f573fSAndroid Build Coastguard Worker RepeatedGroup_extension *repeatedGroup = repeatedGroups.firstObject; 307*1b3f573fSAndroid Build Coastguard Worker XCTAssertNotNil(repeatedGroup); 308*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual(repeatedGroup.a, 567); 309*1b3f573fSAndroid Build Coastguard Worker XCTAssertNotNil(repeatedGroup.unknownFields); 310*1b3f573fSAndroid Build Coastguard Worker } 311*1b3f573fSAndroid Build Coastguard Worker 312*1b3f573fSAndroid Build Coastguard Worker { 313*1b3f573fSAndroid Build Coastguard Worker XCTAssertTrue([message hasExtension:[UnittestRoot repeatedNestedMessageExtension]]); 314*1b3f573fSAndroid Build Coastguard Worker NSArray *repeatedNestedMessages = [message getExtension:[UnittestRoot repeatedNestedMessageExtension]]; 315*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual(repeatedNestedMessages.count, (NSUInteger)1); 316*1b3f573fSAndroid Build Coastguard Worker TestAllTypes_NestedMessage *repeatedNestedMessage = repeatedNestedMessages.firstObject; 317*1b3f573fSAndroid Build Coastguard Worker XCTAssertNotNil(repeatedNestedMessage); 318*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual(repeatedNestedMessage.bb, 678); 319*1b3f573fSAndroid Build Coastguard Worker XCTAssertNotNil(repeatedNestedMessage.unknownFields); 320*1b3f573fSAndroid Build Coastguard Worker } 321*1b3f573fSAndroid Build Coastguard Worker 322*1b3f573fSAndroid Build Coastguard Worker // Drop them. 323*1b3f573fSAndroid Build Coastguard Worker GPBMessageDropUnknownFieldsRecursively(message); 324*1b3f573fSAndroid Build Coastguard Worker 325*1b3f573fSAndroid Build Coastguard Worker // Confirm unknowns are gone from within the messages. 326*1b3f573fSAndroid Build Coastguard Worker 327*1b3f573fSAndroid Build Coastguard Worker XCTAssertNotNil(message); 328*1b3f573fSAndroid Build Coastguard Worker XCTAssertNil(message.unknownFields); 329*1b3f573fSAndroid Build Coastguard Worker XCTAssertTrue([message hasExtension:[UnittestRoot optionalInt32Extension]]); 330*1b3f573fSAndroid Build Coastguard Worker 331*1b3f573fSAndroid Build Coastguard Worker { 332*1b3f573fSAndroid Build Coastguard Worker XCTAssertTrue([message hasExtension:[UnittestRoot optionalGroupExtension]]); 333*1b3f573fSAndroid Build Coastguard Worker OptionalGroup_extension *optionalGroup = 334*1b3f573fSAndroid Build Coastguard Worker [message getExtension:[UnittestRoot optionalGroupExtension]]; 335*1b3f573fSAndroid Build Coastguard Worker XCTAssertNotNil(optionalGroup); 336*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual(optionalGroup.a, 123); 337*1b3f573fSAndroid Build Coastguard Worker XCTAssertNil(optionalGroup.unknownFields); 338*1b3f573fSAndroid Build Coastguard Worker } 339*1b3f573fSAndroid Build Coastguard Worker 340*1b3f573fSAndroid Build Coastguard Worker { 341*1b3f573fSAndroid Build Coastguard Worker XCTAssertTrue([message hasExtension:[UnittestRoot optionalNestedMessageExtension]]); 342*1b3f573fSAndroid Build Coastguard Worker TestAllTypes_NestedMessage *nestedMessage = 343*1b3f573fSAndroid Build Coastguard Worker [message getExtension:[UnittestRoot optionalNestedMessageExtension]]; 344*1b3f573fSAndroid Build Coastguard Worker XCTAssertNotNil(nestedMessage); 345*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual(nestedMessage.bb, 456); 346*1b3f573fSAndroid Build Coastguard Worker XCTAssertNil(nestedMessage.unknownFields); 347*1b3f573fSAndroid Build Coastguard Worker } 348*1b3f573fSAndroid Build Coastguard Worker 349*1b3f573fSAndroid Build Coastguard Worker { 350*1b3f573fSAndroid Build Coastguard Worker XCTAssertTrue([message hasExtension:[UnittestRoot repeatedGroupExtension]]); 351*1b3f573fSAndroid Build Coastguard Worker NSArray *repeatedGroups = [message getExtension:[UnittestRoot repeatedGroupExtension]]; 352*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual(repeatedGroups.count, (NSUInteger)1); 353*1b3f573fSAndroid Build Coastguard Worker RepeatedGroup_extension *repeatedGroup = repeatedGroups.firstObject; 354*1b3f573fSAndroid Build Coastguard Worker XCTAssertNotNil(repeatedGroup); 355*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual(repeatedGroup.a, 567); 356*1b3f573fSAndroid Build Coastguard Worker XCTAssertNil(repeatedGroup.unknownFields); 357*1b3f573fSAndroid Build Coastguard Worker } 358*1b3f573fSAndroid Build Coastguard Worker 359*1b3f573fSAndroid Build Coastguard Worker { 360*1b3f573fSAndroid Build Coastguard Worker XCTAssertTrue([message hasExtension:[UnittestRoot repeatedNestedMessageExtension]]); 361*1b3f573fSAndroid Build Coastguard Worker NSArray *repeatedNestedMessages = [message getExtension:[UnittestRoot repeatedNestedMessageExtension]]; 362*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual(repeatedNestedMessages.count, (NSUInteger)1); 363*1b3f573fSAndroid Build Coastguard Worker TestAllTypes_NestedMessage *repeatedNestedMessage = repeatedNestedMessages.firstObject; 364*1b3f573fSAndroid Build Coastguard Worker XCTAssertNotNil(repeatedNestedMessage); 365*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual(repeatedNestedMessage.bb, 678); 366*1b3f573fSAndroid Build Coastguard Worker XCTAssertNil(repeatedNestedMessage.unknownFields); 367*1b3f573fSAndroid Build Coastguard Worker } 368*1b3f573fSAndroid Build Coastguard Worker 369*1b3f573fSAndroid Build Coastguard Worker} 370*1b3f573fSAndroid Build Coastguard Worker 371*1b3f573fSAndroid Build Coastguard Worker- (void)testDropMessageUnknownFieldsRecursively_Maps { 372*1b3f573fSAndroid Build Coastguard Worker TestMap *message = [TestMap message]; 373*1b3f573fSAndroid Build Coastguard Worker 374*1b3f573fSAndroid Build Coastguard Worker { 375*1b3f573fSAndroid Build Coastguard Worker ForeignMessage *foreignMessage = [ForeignMessage message]; 376*1b3f573fSAndroid Build Coastguard Worker foreignMessage.unknownFields = UnknownFieldsSetHelper(100); 377*1b3f573fSAndroid Build Coastguard Worker [message.mapInt32ForeignMessage setObject:foreignMessage forKey:100]; 378*1b3f573fSAndroid Build Coastguard Worker 379*1b3f573fSAndroid Build Coastguard Worker foreignMessage = [ForeignMessage message]; 380*1b3f573fSAndroid Build Coastguard Worker foreignMessage.unknownFields = UnknownFieldsSetHelper(101); 381*1b3f573fSAndroid Build Coastguard Worker [message.mapStringForeignMessage setObject:foreignMessage forKey:@"101"]; 382*1b3f573fSAndroid Build Coastguard Worker } 383*1b3f573fSAndroid Build Coastguard Worker 384*1b3f573fSAndroid Build Coastguard Worker // Confirm everything is there. 385*1b3f573fSAndroid Build Coastguard Worker 386*1b3f573fSAndroid Build Coastguard Worker XCTAssertNotNil(message); 387*1b3f573fSAndroid Build Coastguard Worker 388*1b3f573fSAndroid Build Coastguard Worker { 389*1b3f573fSAndroid Build Coastguard Worker ForeignMessage *foreignMessage = [message.mapInt32ForeignMessage objectForKey:100]; 390*1b3f573fSAndroid Build Coastguard Worker XCTAssertNotNil(foreignMessage); 391*1b3f573fSAndroid Build Coastguard Worker XCTAssertNotNil(foreignMessage.unknownFields); 392*1b3f573fSAndroid Build Coastguard Worker } 393*1b3f573fSAndroid Build Coastguard Worker 394*1b3f573fSAndroid Build Coastguard Worker { 395*1b3f573fSAndroid Build Coastguard Worker ForeignMessage *foreignMessage = [message.mapStringForeignMessage objectForKey:@"101"]; 396*1b3f573fSAndroid Build Coastguard Worker XCTAssertNotNil(foreignMessage); 397*1b3f573fSAndroid Build Coastguard Worker XCTAssertNotNil(foreignMessage.unknownFields); 398*1b3f573fSAndroid Build Coastguard Worker } 399*1b3f573fSAndroid Build Coastguard Worker 400*1b3f573fSAndroid Build Coastguard Worker GPBMessageDropUnknownFieldsRecursively(message); 401*1b3f573fSAndroid Build Coastguard Worker 402*1b3f573fSAndroid Build Coastguard Worker // Confirm unknowns are gone from within the messages. 403*1b3f573fSAndroid Build Coastguard Worker 404*1b3f573fSAndroid Build Coastguard Worker XCTAssertNotNil(message); 405*1b3f573fSAndroid Build Coastguard Worker 406*1b3f573fSAndroid Build Coastguard Worker { 407*1b3f573fSAndroid Build Coastguard Worker ForeignMessage *foreignMessage = [message.mapInt32ForeignMessage objectForKey:100]; 408*1b3f573fSAndroid Build Coastguard Worker XCTAssertNotNil(foreignMessage); 409*1b3f573fSAndroid Build Coastguard Worker XCTAssertNil(foreignMessage.unknownFields); 410*1b3f573fSAndroid Build Coastguard Worker } 411*1b3f573fSAndroid Build Coastguard Worker 412*1b3f573fSAndroid Build Coastguard Worker { 413*1b3f573fSAndroid Build Coastguard Worker ForeignMessage *foreignMessage = [message.mapStringForeignMessage objectForKey:@"101"]; 414*1b3f573fSAndroid Build Coastguard Worker XCTAssertNotNil(foreignMessage); 415*1b3f573fSAndroid Build Coastguard Worker XCTAssertNil(foreignMessage.unknownFields); 416*1b3f573fSAndroid Build Coastguard Worker } 417*1b3f573fSAndroid Build Coastguard Worker 418*1b3f573fSAndroid Build Coastguard Worker} 419*1b3f573fSAndroid Build Coastguard Worker 420*1b3f573fSAndroid Build Coastguard Worker@end 421