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 "GPBCodedInputStream.h" 34*1b3f573fSAndroid Build Coastguard Worker#import "GPBMessage_PackagePrivate.h" 35*1b3f573fSAndroid Build Coastguard Worker#import "GPBUnknownField_PackagePrivate.h" 36*1b3f573fSAndroid Build Coastguard Worker#import "google/protobuf/Unittest.pbobjc.h" 37*1b3f573fSAndroid Build Coastguard Worker#import "google/protobuf/UnittestMset.pbobjc.h" 38*1b3f573fSAndroid Build Coastguard Worker#import "google/protobuf/UnittestMsetWireFormat.pbobjc.h" 39*1b3f573fSAndroid Build Coastguard Worker 40*1b3f573fSAndroid Build Coastguard Worker@interface WireFormatTests : GPBTestCase 41*1b3f573fSAndroid Build Coastguard Worker@end 42*1b3f573fSAndroid Build Coastguard Worker 43*1b3f573fSAndroid Build Coastguard Worker@implementation WireFormatTests 44*1b3f573fSAndroid Build Coastguard Worker 45*1b3f573fSAndroid Build Coastguard Worker- (void)testSerialization { 46*1b3f573fSAndroid Build Coastguard Worker TestAllTypes* message = [self allSetRepeatedCount:kGPBDefaultRepeatCount]; 47*1b3f573fSAndroid Build Coastguard Worker 48*1b3f573fSAndroid Build Coastguard Worker NSData* rawBytes = message.data; 49*1b3f573fSAndroid Build Coastguard Worker [self assertFieldsInOrder:rawBytes]; 50*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual(message.serializedSize, (size_t)rawBytes.length); 51*1b3f573fSAndroid Build Coastguard Worker 52*1b3f573fSAndroid Build Coastguard Worker TestAllTypes* message2 = [TestAllTypes parseFromData:rawBytes error:NULL]; 53*1b3f573fSAndroid Build Coastguard Worker 54*1b3f573fSAndroid Build Coastguard Worker [self assertAllFieldsSet:message2 repeatedCount:kGPBDefaultRepeatCount]; 55*1b3f573fSAndroid Build Coastguard Worker} 56*1b3f573fSAndroid Build Coastguard Worker 57*1b3f573fSAndroid Build Coastguard Worker- (void)testSerializationPacked { 58*1b3f573fSAndroid Build Coastguard Worker TestPackedTypes* message = 59*1b3f573fSAndroid Build Coastguard Worker [self packedSetRepeatedCount:kGPBDefaultRepeatCount]; 60*1b3f573fSAndroid Build Coastguard Worker 61*1b3f573fSAndroid Build Coastguard Worker NSData* rawBytes = message.data; 62*1b3f573fSAndroid Build Coastguard Worker [self assertFieldsInOrder:rawBytes]; 63*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual(message.serializedSize, (size_t)rawBytes.length); 64*1b3f573fSAndroid Build Coastguard Worker 65*1b3f573fSAndroid Build Coastguard Worker TestPackedTypes* message2 = 66*1b3f573fSAndroid Build Coastguard Worker [TestPackedTypes parseFromData:rawBytes error:NULL]; 67*1b3f573fSAndroid Build Coastguard Worker 68*1b3f573fSAndroid Build Coastguard Worker [self assertPackedFieldsSet:message2 repeatedCount:kGPBDefaultRepeatCount]; 69*1b3f573fSAndroid Build Coastguard Worker} 70*1b3f573fSAndroid Build Coastguard Worker 71*1b3f573fSAndroid Build Coastguard Worker- (void)testSerializeExtensions { 72*1b3f573fSAndroid Build Coastguard Worker // TestAllTypes and TestAllExtensions should have compatible wire formats, 73*1b3f573fSAndroid Build Coastguard Worker // so if we serealize a TestAllExtensions then parse it as TestAllTypes 74*1b3f573fSAndroid Build Coastguard Worker // it should work. 75*1b3f573fSAndroid Build Coastguard Worker 76*1b3f573fSAndroid Build Coastguard Worker TestAllExtensions* message = 77*1b3f573fSAndroid Build Coastguard Worker [self allExtensionsSetRepeatedCount:kGPBDefaultRepeatCount]; 78*1b3f573fSAndroid Build Coastguard Worker NSData* rawBytes = message.data; 79*1b3f573fSAndroid Build Coastguard Worker [self assertFieldsInOrder:rawBytes]; 80*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual(message.serializedSize, (size_t)rawBytes.length); 81*1b3f573fSAndroid Build Coastguard Worker 82*1b3f573fSAndroid Build Coastguard Worker TestAllTypes* message2 = [TestAllTypes parseFromData:rawBytes error:NULL]; 83*1b3f573fSAndroid Build Coastguard Worker 84*1b3f573fSAndroid Build Coastguard Worker [self assertAllFieldsSet:message2 repeatedCount:kGPBDefaultRepeatCount]; 85*1b3f573fSAndroid Build Coastguard Worker} 86*1b3f573fSAndroid Build Coastguard Worker 87*1b3f573fSAndroid Build Coastguard Worker- (void)testSerializePackedExtensions { 88*1b3f573fSAndroid Build Coastguard Worker // TestPackedTypes and TestPackedExtensions should have compatible wire 89*1b3f573fSAndroid Build Coastguard Worker // formats; check that they serialize to the same string. 90*1b3f573fSAndroid Build Coastguard Worker TestPackedExtensions* message = 91*1b3f573fSAndroid Build Coastguard Worker [self packedExtensionsSetRepeatedCount:kGPBDefaultRepeatCount]; 92*1b3f573fSAndroid Build Coastguard Worker NSData* rawBytes = message.data; 93*1b3f573fSAndroid Build Coastguard Worker [self assertFieldsInOrder:rawBytes]; 94*1b3f573fSAndroid Build Coastguard Worker 95*1b3f573fSAndroid Build Coastguard Worker TestPackedTypes* message2 = 96*1b3f573fSAndroid Build Coastguard Worker [self packedSetRepeatedCount:kGPBDefaultRepeatCount]; 97*1b3f573fSAndroid Build Coastguard Worker NSData* rawBytes2 = message2.data; 98*1b3f573fSAndroid Build Coastguard Worker 99*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqualObjects(rawBytes, rawBytes2); 100*1b3f573fSAndroid Build Coastguard Worker} 101*1b3f573fSAndroid Build Coastguard Worker 102*1b3f573fSAndroid Build Coastguard Worker- (void)testParseExtensions { 103*1b3f573fSAndroid Build Coastguard Worker // TestAllTypes and TestAllExtensions should have compatible wire formats, 104*1b3f573fSAndroid Build Coastguard Worker // so if we serialize a TestAllTypes then parse it as TestAllExtensions 105*1b3f573fSAndroid Build Coastguard Worker // it should work. 106*1b3f573fSAndroid Build Coastguard Worker 107*1b3f573fSAndroid Build Coastguard Worker TestAllTypes* message = [self allSetRepeatedCount:kGPBDefaultRepeatCount]; 108*1b3f573fSAndroid Build Coastguard Worker NSData* rawBytes = message.data; 109*1b3f573fSAndroid Build Coastguard Worker [self assertFieldsInOrder:rawBytes]; 110*1b3f573fSAndroid Build Coastguard Worker 111*1b3f573fSAndroid Build Coastguard Worker GPBExtensionRegistry* registry = [self extensionRegistry]; 112*1b3f573fSAndroid Build Coastguard Worker 113*1b3f573fSAndroid Build Coastguard Worker TestAllExtensions* message2 = [TestAllExtensions parseFromData:rawBytes 114*1b3f573fSAndroid Build Coastguard Worker extensionRegistry:registry 115*1b3f573fSAndroid Build Coastguard Worker error:NULL]; 116*1b3f573fSAndroid Build Coastguard Worker 117*1b3f573fSAndroid Build Coastguard Worker [self assertAllExtensionsSet:message2 repeatedCount:kGPBDefaultRepeatCount]; 118*1b3f573fSAndroid Build Coastguard Worker} 119*1b3f573fSAndroid Build Coastguard Worker 120*1b3f573fSAndroid Build Coastguard Worker 121*1b3f573fSAndroid Build Coastguard Worker- (void)testExtensionsSerializedSize { 122*1b3f573fSAndroid Build Coastguard Worker size_t allSet = [self allSetRepeatedCount:kGPBDefaultRepeatCount].serializedSize; 123*1b3f573fSAndroid Build Coastguard Worker size_t extensionSet = [self allExtensionsSetRepeatedCount:kGPBDefaultRepeatCount].serializedSize; 124*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual(allSet, extensionSet); 125*1b3f573fSAndroid Build Coastguard Worker} 126*1b3f573fSAndroid Build Coastguard Worker 127*1b3f573fSAndroid Build Coastguard Worker- (void)testParsePackedExtensions { 128*1b3f573fSAndroid Build Coastguard Worker // Ensure that packed extensions can be properly parsed. 129*1b3f573fSAndroid Build Coastguard Worker TestPackedExtensions* message = 130*1b3f573fSAndroid Build Coastguard Worker [self packedExtensionsSetRepeatedCount:kGPBDefaultRepeatCount]; 131*1b3f573fSAndroid Build Coastguard Worker NSData* rawBytes = message.data; 132*1b3f573fSAndroid Build Coastguard Worker [self assertFieldsInOrder:rawBytes]; 133*1b3f573fSAndroid Build Coastguard Worker 134*1b3f573fSAndroid Build Coastguard Worker GPBExtensionRegistry* registry = [self extensionRegistry]; 135*1b3f573fSAndroid Build Coastguard Worker 136*1b3f573fSAndroid Build Coastguard Worker TestPackedExtensions* message2 = [TestPackedExtensions parseFromData:rawBytes 137*1b3f573fSAndroid Build Coastguard Worker extensionRegistry:registry 138*1b3f573fSAndroid Build Coastguard Worker error:NULL]; 139*1b3f573fSAndroid Build Coastguard Worker 140*1b3f573fSAndroid Build Coastguard Worker [self assertPackedExtensionsSet:message2 141*1b3f573fSAndroid Build Coastguard Worker repeatedCount:kGPBDefaultRepeatCount]; 142*1b3f573fSAndroid Build Coastguard Worker} 143*1b3f573fSAndroid Build Coastguard Worker 144*1b3f573fSAndroid Build Coastguard Workerconst int kUnknownTypeId = 1550055; 145*1b3f573fSAndroid Build Coastguard Worker 146*1b3f573fSAndroid Build Coastguard Worker- (void)testSerializeMessageSet { 147*1b3f573fSAndroid Build Coastguard Worker // Set up a TestMessageSet with two known messages and an unknown one. 148*1b3f573fSAndroid Build Coastguard Worker TestMessageSet* message_set = [TestMessageSet message]; 149*1b3f573fSAndroid Build Coastguard Worker [[message_set getExtension:[TestMessageSetExtension1 messageSetExtension]] 150*1b3f573fSAndroid Build Coastguard Worker setI:123]; 151*1b3f573fSAndroid Build Coastguard Worker [[message_set getExtension:[TestMessageSetExtension2 messageSetExtension]] 152*1b3f573fSAndroid Build Coastguard Worker setStr:@"foo"]; 153*1b3f573fSAndroid Build Coastguard Worker GPBUnknownField* unknownField = 154*1b3f573fSAndroid Build Coastguard Worker [[[GPBUnknownField alloc] initWithNumber:kUnknownTypeId] autorelease]; 155*1b3f573fSAndroid Build Coastguard Worker [unknownField addLengthDelimited:[NSData dataWithBytes:"bar" length:3]]; 156*1b3f573fSAndroid Build Coastguard Worker GPBUnknownFieldSet* unknownFieldSet = 157*1b3f573fSAndroid Build Coastguard Worker [[[GPBUnknownFieldSet alloc] init] autorelease]; 158*1b3f573fSAndroid Build Coastguard Worker [unknownFieldSet addField:unknownField]; 159*1b3f573fSAndroid Build Coastguard Worker [message_set setUnknownFields:unknownFieldSet]; 160*1b3f573fSAndroid Build Coastguard Worker 161*1b3f573fSAndroid Build Coastguard Worker NSData* data = [message_set data]; 162*1b3f573fSAndroid Build Coastguard Worker 163*1b3f573fSAndroid Build Coastguard Worker // Parse back using RawMessageSet and check the contents. 164*1b3f573fSAndroid Build Coastguard Worker RawMessageSet* raw = [RawMessageSet parseFromData:data error:NULL]; 165*1b3f573fSAndroid Build Coastguard Worker 166*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual([raw.unknownFields countOfFields], (NSUInteger)0); 167*1b3f573fSAndroid Build Coastguard Worker 168*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual(raw.itemArray.count, (NSUInteger)3); 169*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual((uint32_t)[raw.itemArray[0] typeId], 170*1b3f573fSAndroid Build Coastguard Worker [TestMessageSetExtension1 messageSetExtension].fieldNumber); 171*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual((uint32_t)[raw.itemArray[1] typeId], 172*1b3f573fSAndroid Build Coastguard Worker [TestMessageSetExtension2 messageSetExtension].fieldNumber); 173*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual([raw.itemArray[2] typeId], kUnknownTypeId); 174*1b3f573fSAndroid Build Coastguard Worker 175*1b3f573fSAndroid Build Coastguard Worker TestMessageSetExtension1* message1 = 176*1b3f573fSAndroid Build Coastguard Worker [TestMessageSetExtension1 parseFromData:[((RawMessageSet_Item*)raw.itemArray[0]) message] 177*1b3f573fSAndroid Build Coastguard Worker error:NULL]; 178*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual(message1.i, 123); 179*1b3f573fSAndroid Build Coastguard Worker 180*1b3f573fSAndroid Build Coastguard Worker TestMessageSetExtension2* message2 = 181*1b3f573fSAndroid Build Coastguard Worker [TestMessageSetExtension2 parseFromData:[((RawMessageSet_Item*)raw.itemArray[1]) message] 182*1b3f573fSAndroid Build Coastguard Worker error:NULL]; 183*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqualObjects(message2.str, @"foo"); 184*1b3f573fSAndroid Build Coastguard Worker 185*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqualObjects([raw.itemArray[2] message], 186*1b3f573fSAndroid Build Coastguard Worker [NSData dataWithBytes:"bar" length:3]); 187*1b3f573fSAndroid Build Coastguard Worker} 188*1b3f573fSAndroid Build Coastguard Worker 189*1b3f573fSAndroid Build Coastguard Worker- (void)testParseMessageSet { 190*1b3f573fSAndroid Build Coastguard Worker // Set up a RawMessageSet with two known messages and an unknown one. 191*1b3f573fSAndroid Build Coastguard Worker RawMessageSet* raw = [RawMessageSet message]; 192*1b3f573fSAndroid Build Coastguard Worker 193*1b3f573fSAndroid Build Coastguard Worker { 194*1b3f573fSAndroid Build Coastguard Worker RawMessageSet_Item* item = [RawMessageSet_Item message]; 195*1b3f573fSAndroid Build Coastguard Worker item.typeId = [TestMessageSetExtension1 messageSetExtension].fieldNumber; 196*1b3f573fSAndroid Build Coastguard Worker TestMessageSetExtension1* message = [TestMessageSetExtension1 message]; 197*1b3f573fSAndroid Build Coastguard Worker message.i = 123; 198*1b3f573fSAndroid Build Coastguard Worker item.message = [message data]; 199*1b3f573fSAndroid Build Coastguard Worker [raw.itemArray addObject:item]; 200*1b3f573fSAndroid Build Coastguard Worker } 201*1b3f573fSAndroid Build Coastguard Worker 202*1b3f573fSAndroid Build Coastguard Worker { 203*1b3f573fSAndroid Build Coastguard Worker RawMessageSet_Item* item = [RawMessageSet_Item message]; 204*1b3f573fSAndroid Build Coastguard Worker item.typeId = [TestMessageSetExtension2 messageSetExtension].fieldNumber; 205*1b3f573fSAndroid Build Coastguard Worker TestMessageSetExtension2* message = [TestMessageSetExtension2 message]; 206*1b3f573fSAndroid Build Coastguard Worker message.str = @"foo"; 207*1b3f573fSAndroid Build Coastguard Worker item.message = [message data]; 208*1b3f573fSAndroid Build Coastguard Worker [raw.itemArray addObject:item]; 209*1b3f573fSAndroid Build Coastguard Worker } 210*1b3f573fSAndroid Build Coastguard Worker 211*1b3f573fSAndroid Build Coastguard Worker { 212*1b3f573fSAndroid Build Coastguard Worker RawMessageSet_Item* item = [RawMessageSet_Item message]; 213*1b3f573fSAndroid Build Coastguard Worker item.typeId = kUnknownTypeId; 214*1b3f573fSAndroid Build Coastguard Worker item.message = [NSData dataWithBytes:"bar" length:3]; 215*1b3f573fSAndroid Build Coastguard Worker [raw.itemArray addObject:item]; 216*1b3f573fSAndroid Build Coastguard Worker } 217*1b3f573fSAndroid Build Coastguard Worker 218*1b3f573fSAndroid Build Coastguard Worker NSData* data = [raw data]; 219*1b3f573fSAndroid Build Coastguard Worker 220*1b3f573fSAndroid Build Coastguard Worker // Parse as a TestMessageSet and check the contents. 221*1b3f573fSAndroid Build Coastguard Worker TestMessageSet* messageSet = 222*1b3f573fSAndroid Build Coastguard Worker [TestMessageSet parseFromData:data 223*1b3f573fSAndroid Build Coastguard Worker extensionRegistry:[UnittestMsetRoot extensionRegistry] 224*1b3f573fSAndroid Build Coastguard Worker error:NULL]; 225*1b3f573fSAndroid Build Coastguard Worker 226*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual( 227*1b3f573fSAndroid Build Coastguard Worker [[messageSet 228*1b3f573fSAndroid Build Coastguard Worker getExtension:[TestMessageSetExtension1 messageSetExtension]] i], 229*1b3f573fSAndroid Build Coastguard Worker 123); 230*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqualObjects( 231*1b3f573fSAndroid Build Coastguard Worker [[messageSet 232*1b3f573fSAndroid Build Coastguard Worker getExtension:[TestMessageSetExtension2 messageSetExtension]] str], 233*1b3f573fSAndroid Build Coastguard Worker @"foo"); 234*1b3f573fSAndroid Build Coastguard Worker 235*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual([messageSet.unknownFields countOfFields], (NSUInteger)1); 236*1b3f573fSAndroid Build Coastguard Worker GPBUnknownField* unknownField = [messageSet.unknownFields getField:kUnknownTypeId]; 237*1b3f573fSAndroid Build Coastguard Worker XCTAssertNotNil(unknownField); 238*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqual(unknownField.lengthDelimitedList.count, (NSUInteger)1); 239*1b3f573fSAndroid Build Coastguard Worker XCTAssertEqualObjects(unknownField.lengthDelimitedList[0], 240*1b3f573fSAndroid Build Coastguard Worker [NSData dataWithBytes:"bar" length:3]); 241*1b3f573fSAndroid Build Coastguard Worker} 242*1b3f573fSAndroid Build Coastguard Worker 243*1b3f573fSAndroid Build Coastguard Worker- (void)assertFieldsInOrder:(NSData*)data { 244*1b3f573fSAndroid Build Coastguard Worker GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data]; 245*1b3f573fSAndroid Build Coastguard Worker int32_t previousTag = 0; 246*1b3f573fSAndroid Build Coastguard Worker 247*1b3f573fSAndroid Build Coastguard Worker while (YES) { 248*1b3f573fSAndroid Build Coastguard Worker int32_t tag = [input readTag]; 249*1b3f573fSAndroid Build Coastguard Worker if (tag == 0) { 250*1b3f573fSAndroid Build Coastguard Worker break; 251*1b3f573fSAndroid Build Coastguard Worker } 252*1b3f573fSAndroid Build Coastguard Worker 253*1b3f573fSAndroid Build Coastguard Worker XCTAssertGreaterThan(tag, previousTag); 254*1b3f573fSAndroid Build Coastguard Worker [input skipField:tag]; 255*1b3f573fSAndroid Build Coastguard Worker } 256*1b3f573fSAndroid Build Coastguard Worker} 257*1b3f573fSAndroid Build Coastguard Worker 258*1b3f573fSAndroid Build Coastguard Worker@end 259