xref: /aosp_15_r20/external/protobuf/objectivec/Tests/GPBWireFormatTests.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 "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