[ObjC] Parsing helper and tests around unknown fields.

Make a new internal api for collecting up the unknown group fields
that will be used in a future change.

Add testing for the new api and for unknown field parsing of groups in
general.

PiperOrigin-RevId: 654875605
pull/17563/head
Thomas Van Lenten 4 months ago committed by Copybara-Service
parent af794965f9
commit d44c0d577c
  1. 54
      objectivec/GPBCodedInputStream.m
  2. 3
      objectivec/GPBCodedInputStream_PackagePrivate.h
  3. 102
      objectivec/Tests/GPBCodedInputStreamTests.m
  4. 175
      objectivec/Tests/GPBUnknownFieldSetTest.m
  5. 160
      objectivec/Tests/GPBUnknownFieldsTest.m

@ -267,6 +267,60 @@ NSData *GPBCodedInputStreamReadRetainedBytesNoCopy(GPBCodedInputStreamState *sta
return result;
}
static void SkipToEndGroupInternal(GPBCodedInputStreamState *state, uint32_t endGroupTag) {
CheckRecursionLimit(state);
++state->recursionDepth;
while (YES) {
uint32_t tag = GPBCodedInputStreamReadTag(state);
if (tag == endGroupTag || tag == 0) {
GPBCodedInputStreamCheckLastTagWas(state, endGroupTag); // Will fail for end of input.
--state->recursionDepth;
return;
}
switch (GPBWireFormatGetTagWireType(tag)) {
case GPBWireFormatVarint:
(void)ReadRawVarint64(state);
break;
case GPBWireFormatFixed64:
SkipRawData(state, sizeof(uint64_t));
break;
case GPBWireFormatLengthDelimited: {
uint64_t size = ReadRawVarint64(state);
CheckFieldSize(size);
size_t size2 = (size_t)size; // Cast safe on 32bit because of CheckFieldSize() above.
SkipRawData(state, size2);
break;
}
case GPBWireFormatStartGroup:
SkipToEndGroupInternal(state, GPBWireFormatMakeTag(GPBWireFormatGetTagFieldNumber(tag),
GPBWireFormatEndGroup));
break;
case GPBWireFormatEndGroup:
GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidTag, @"Unmatched end group");
break;
case GPBWireFormatFixed32:
SkipRawData(state, sizeof(uint32_t));
break;
}
}
}
// This doesn't include the start group, but it collects all bytes until the end group including
// the end group tag.
NSData *GPBCodedInputStreamReadRetainedBytesToEndGroupNoCopy(GPBCodedInputStreamState *state,
int32_t fieldNumber) {
// Better have just read the start of the group.
GPBCodedInputStreamCheckLastTagWas(state,
GPBWireFormatMakeTag(fieldNumber, GPBWireFormatStartGroup));
const uint8_t *start = state->bytes + state->bufferPos;
SkipToEndGroupInternal(state, GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup));
// This will be after the end group tag.
const uint8_t *end = state->bytes + state->bufferPos;
return [[NSData alloc] initWithBytesNoCopy:(void *)start
length:(NSUInteger)(end - start)
freeWhenDone:NO];
}
size_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state, size_t byteLimit) {
byteLimit += state->bufferPos;
size_t oldLimit = state->currentLimit;

@ -76,6 +76,9 @@ NSData *GPBCodedInputStreamReadRetainedBytes(GPBCodedInputStreamState *state)
__attribute((ns_returns_retained));
NSData *GPBCodedInputStreamReadRetainedBytesNoCopy(GPBCodedInputStreamState *state)
__attribute((ns_returns_retained));
NSData *GPBCodedInputStreamReadRetainedBytesToEndGroupNoCopy(GPBCodedInputStreamState *state,
int32_t fieldNumber)
__attribute((ns_returns_retained));
size_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state, size_t byteLimit);
void GPBCodedInputStreamPopLimit(GPBCodedInputStreamState *state, size_t oldLimit);

@ -6,12 +6,14 @@
// https://developers.google.com/open-source/licenses/bsd
#import <Foundation/Foundation.h>
#import "GPBTestUtilities.h"
#import "GPBCodedInputStream.h"
#import "GPBCodedInputStream_PackagePrivate.h"
#import "GPBCodedOutputStream.h"
#import "GPBTestUtilities.h"
#import "GPBUnknownFieldSet_PackagePrivate.h"
#import "GPBUtilities_PackagePrivate.h"
#import "GPBWireFormat.h"
#import "objectivec/Tests/Unittest.pbobjc.h"
@interface CodedInputStreamTests : GPBTestCase
@ -444,4 +446,102 @@
}
}
- (void)assertReadByteToEndGroupFails:(NSData*)data {
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
uint32_t tag = [input readTag];
XCTAssertThrows(GPBCodedInputStreamReadRetainedBytesToEndGroupNoCopy(
&input->state_, GPBWireFormatGetTagFieldNumber(tag)));
}
- (void)assertReadByteToEndGroup:(NSData*)data value:(NSData*)value {
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
uint32_t tag = [input readTag];
NSData* readValue = GPBCodedInputStreamReadRetainedBytesToEndGroupNoCopy(
&input->state_, GPBWireFormatGetTagFieldNumber(tag));
XCTAssertNotNil(readValue);
XCTAssertEqualObjects(readValue, value);
[readValue release];
}
static NSData* DataForGroupsOfDepth(NSUInteger depth) {
NSMutableData* data = [NSMutableData dataWithCapacity:0];
uint32_t byte = 35; // 35 = 0b100011 -> field 4/start group
for (NSUInteger i = 0; i < depth; ++i) {
[data appendBytes:&byte length:1];
}
byte = 8; // 8 = 0b1000, -> field 1/varint
[data appendBytes:&byte length:1];
byte = 1; // 1 -> varint value of 1
[data appendBytes:&byte length:1];
byte = 36; // 36 = 0b100100 -> field 4/end group
for (NSUInteger i = 0; i < depth; ++i) {
[data appendBytes:&byte length:1];
}
return data;
}
- (void)testBytesToEndGroup {
// 35 = 0b100011 -> field 4/start group
// 36 = 0b100100 -> field 4/end group
// 43 = 0b101011 -> field 5/end group
// 44 = 0b101100 -> field 5/end group
// 8 = 0b1000, 1 -> field 1/varint, value of 1
// 21 = 0b10101, 0x78, 0x56, 0x34, 0x12 -> field 2/fixed32, value of 0x12345678
// 25 = 0b11001, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12 -> field 3/fixed64,
// value of 0x123456789abcdef0LL
// 50 = 0b110010, 0x0 -> field 6/length delimited, length 0
// 50 = 0b110010, 0x1, 42 -> field 6/length delimited, length 1, byte 42
// 0 -> field 0 which is invalid/varint
// 15 = 0b1111 -> field 1, wire type 7 which is invalid
[self assertReadByteToEndGroup:bytes(35, 36) value:bytes(36)]; // empty group
[self assertReadByteToEndGroup:bytes(35, 8, 1, 36) value:bytes(8, 1, 36)]; // varint
[self assertReadByteToEndGroup:bytes(35, 21, 0x78, 0x56, 0x34, 0x12, 36) // fixed32
value:bytes(21, 0x78, 0x56, 0x34, 0x12, 36)];
[self assertReadByteToEndGroup:bytes(35, 25, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
36) // fixed64
value:bytes(25, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12, 36)];
[self assertReadByteToEndGroup:bytes(35, 50, 0, 36)
value:bytes(50, 0, 36)]; // length delimited, length 0
[self assertReadByteToEndGroup:bytes(35, 50, 1, 42, 36)
value:bytes(50, 1, 42, 36)]; // length delimited, length 1, byte 42
[self assertReadByteToEndGroup:bytes(35, 43, 44, 36) value:bytes(43, 44, 36)]; // Sub group
[self assertReadByteToEndGroup:bytes(35, 8, 1, 43, 8, 1, 44,
36) // varint and sub group with varint
value:bytes(8, 1, 43, 8, 1, 44, 36)];
[self assertReadByteToEndGroupFails:bytes(35, 0, 36)]; // Invalid field number
[self assertReadByteToEndGroupFails:bytes(35, 15, 36)]; // Invalid wire type
[self assertReadByteToEndGroupFails:bytes(35, 21, 0x78, 0x56, 0x34)]; // truncated fixed32
[self assertReadByteToEndGroupFails:bytes(35, 25, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56,
0x34)]; // truncated fixed64
// Mising end group
[self assertReadByteToEndGroupFails:bytes(35)];
[self assertReadByteToEndGroupFails:bytes(35, 8, 1)];
[self assertReadByteToEndGroupFails:bytes(35, 43)];
[self assertReadByteToEndGroupFails:bytes(35, 43, 8, 1)];
// Wrong end group
[self assertReadByteToEndGroupFails:bytes(35, 44)];
[self assertReadByteToEndGroupFails:bytes(35, 8, 1, 44)];
[self assertReadByteToEndGroupFails:bytes(35, 43, 36)];
[self assertReadByteToEndGroupFails:bytes(35, 43, 8, 1, 36)];
[self assertReadByteToEndGroupFails:bytes(35, 43, 44, 44)];
[self assertReadByteToEndGroupFails:bytes(35, 43, 8, 1, 44, 44)];
// This is the same limit as within GPBCodedInputStream.
const NSUInteger kDefaultRecursionLimit = 100;
// That depth parses.
NSData* testData = DataForGroupsOfDepth(kDefaultRecursionLimit);
[self assertReadByteToEndGroup:testData
value:[testData subdataWithRange:NSMakeRange(1, testData.length - 1)]];
// One more level deep fails.
testData = DataForGroupsOfDepth(kDefaultRecursionLimit + 1);
[self assertReadByteToEndGroupFails:testData];
}
@end

@ -6,6 +6,7 @@
// https://developers.google.com/open-source/licenses/bsd
#import "GPBTestUtilities.h"
#import "GPBUnknownFieldSet.h"
#import "GPBUnknownFieldSet_PackagePrivate.h"
#import "GPBUnknownField_PackagePrivate.h"
@ -376,6 +377,180 @@
XCTAssertEqual(0x7FFFFFFFFFFFFFFFULL, [field2.varintList valueAtIndex:0]);
}
static NSData* DataForGroupsOfDepth(NSUInteger depth) {
NSMutableData* data = [NSMutableData dataWithCapacity:0];
uint32_t byte = 35; // 35 = 0b100011 -> field 4/start group
for (NSUInteger i = 0; i < depth; ++i) {
[data appendBytes:&byte length:1];
}
byte = 8; // 8 = 0b1000, -> field 1/varint
[data appendBytes:&byte length:1];
byte = 1; // 1 -> varint value of 1
[data appendBytes:&byte length:1];
byte = 36; // 36 = 0b100100 -> field 4/end group
for (NSUInteger i = 0; i < depth; ++i) {
[data appendBytes:&byte length:1];
}
return data;
}
- (void)testParsingNestingGroupData {
// 35 = 0b100011 -> field 4/start group
// 36 = 0b100100 -> field 4/end group
// 43 = 0b101011 -> field 5/end group
// 44 = 0b101100 -> field 5/end group
// 8 = 0b1000, 1 -> field 1/varint, value of 1
// 21 = 0b10101, 0x78, 0x56, 0x34, 0x12 -> field 2/fixed32, value of 0x12345678
// 25 = 0b11001, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12 -> field 3/fixed64,
// value of 0x123456789abcdef0LL
// 50 = 0b110010, 0x0 -> field 6/length delimited, length 0
// 50 = 0b110010, 0x1, 42 -> field 6/length delimited, length 1, byte 42
// 0 -> field 0 which is invalid/varint
// 15 = 0b1111 -> field 1, wire type 7 which is invalid
TestEmptyMessage* m = [TestEmptyMessage parseFromData:DataFromBytes(35, 36)
error:NULL]; // empty group
XCTAssertEqual(m.unknownFields.countOfFields, (NSUInteger)1);
GPBUnknownField* field = [m.unknownFields getField:4];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
GPBUnknownFieldSet* group = field.groupList[0];
XCTAssertEqual(group.countOfFields, (NSUInteger)0);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1, 36) error:NULL]; // varint
XCTAssertEqual(m.unknownFields.countOfFields, (NSUInteger)1);
field = [m.unknownFields getField:4];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
field = [group getField:1];
XCTAssertEqual(field.varintList.count, (NSUInteger)1);
XCTAssertEqual([field.varintList valueAtIndex:0], 1);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 21, 0x78, 0x56, 0x34, 0x12, 36)
error:NULL]; // fixed32
XCTAssertEqual(m.unknownFields.countOfFields, (NSUInteger)1);
field = [m.unknownFields getField:4];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
field = [group getField:2];
XCTAssertEqual(field.fixed32List.count, (NSUInteger)1);
XCTAssertEqual([field.fixed32List valueAtIndex:0], 0x12345678);
m = [TestEmptyMessage
parseFromData:DataFromBytes(35, 25, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
36)
error:NULL]; // fixed64
XCTAssertEqual(m.unknownFields.countOfFields, (NSUInteger)1);
field = [m.unknownFields getField:4];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
field = [group getField:3];
XCTAssertEqual(field.fixed64List.count, (NSUInteger)1);
XCTAssertEqual([field.fixed64List valueAtIndex:0], 0x123456789abcdef0LL);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 50, 0, 36)
error:NULL]; // length delimited, length 0
XCTAssertEqual(m.unknownFields.countOfFields, (NSUInteger)1);
field = [m.unknownFields getField:4];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
field = [group getField:6];
XCTAssertEqual(field.lengthDelimitedList.count, (NSUInteger)1);
XCTAssertEqualObjects(field.lengthDelimitedList[0], [NSData data]);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 50, 1, 42, 36)
error:NULL]; // length delimited, length 1, byte 42
XCTAssertEqual(m.unknownFields.countOfFields, (NSUInteger)1);
field = [m.unknownFields getField:4];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
field = [group getField:6];
XCTAssertEqual(field.lengthDelimitedList.count, (NSUInteger)1);
XCTAssertEqualObjects(field.lengthDelimitedList[0], DataFromBytes(42));
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 43, 44, 36) error:NULL]; // Sub group
field = [m.unknownFields getField:4];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
XCTAssertEqual(group.countOfFields, (NSUInteger)1);
field = [group getField:5];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
XCTAssertEqual(group.countOfFields, (NSUInteger)0);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1, 43, 8, 2, 44, 36)
error:NULL]; // varint and sub group with varint
XCTAssertEqual(m.unknownFields.countOfFields, (NSUInteger)1);
field = [m.unknownFields getField:4];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
XCTAssertEqual(group.countOfFields, (NSUInteger)2);
field = [group getField:1];
XCTAssertEqual(field.varintList.count, (NSUInteger)1);
XCTAssertEqual([field.varintList valueAtIndex:0], 1);
field = [group getField:5];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
field = [group getField:1];
XCTAssertEqual(field.varintList.count, (NSUInteger)1);
XCTAssertEqual([field.varintList valueAtIndex:0], 2);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 0, 36)
error:NULL]); // Invalid field number
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 15, 36)
error:NULL]); // Invalid wire type
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 21, 0x78, 0x56, 0x34)
error:NULL]); // truncated fixed32
XCTAssertNil([TestEmptyMessage
parseFromData:DataFromBytes(35, 25, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56,
0x34)
error:NULL]); // truncated fixed64
// Mising end group
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 8, 1) error:NULL]);
// Wrong end group
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 44) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1, 44) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 36) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 8, 1, 36) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 44, 44) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 8, 1, 44, 44) error:NULL]);
// This is the same limit as within GPBCodedInputStream.
const NSUInteger kDefaultRecursionLimit = 100;
// That depth parses.
NSData* testData = DataForGroupsOfDepth(kDefaultRecursionLimit);
m = [TestEmptyMessage parseFromData:testData error:NULL];
XCTAssertEqual(m.unknownFields.countOfFields, (NSUInteger)1);
field = [m.unknownFields getField:4];
for (NSUInteger i = 0; i < kDefaultRecursionLimit; ++i) {
XCTAssertEqual(field.varintList.count, (NSUInteger)0);
XCTAssertEqual(field.fixed32List.count, (NSUInteger)0);
XCTAssertEqual(field.fixed64List.count, (NSUInteger)0);
XCTAssertEqual(field.lengthDelimitedList.count, (NSUInteger)0);
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
XCTAssertEqual(group.countOfFields, (NSUInteger)1);
field = [group getField:(i < (kDefaultRecursionLimit - 1) ? 4 : 1)];
}
// field is of the inner most group
XCTAssertEqual(field.varintList.count, (NSUInteger)1);
XCTAssertEqual([field.varintList valueAtIndex:0], (NSUInteger)1);
XCTAssertEqual(field.fixed32List.count, (NSUInteger)0);
XCTAssertEqual(field.fixed64List.count, (NSUInteger)0);
XCTAssertEqual(field.lengthDelimitedList.count, (NSUInteger)0);
XCTAssertEqual(field.groupList.count, (NSUInteger)0);
// One more level deep fails.
testData = DataForGroupsOfDepth(kDefaultRecursionLimit + 1);
XCTAssertNil([TestEmptyMessage parseFromData:testData error:NULL]);
}
#pragma mark - Field tests
// Some tests directly on fields since the dictionary in FieldSet can gate
// testing some of these.

@ -847,4 +847,164 @@
XCTAssertEqual(varint, 0x7FFFFFFFFFFFFFFFL);
}
static NSData* DataForGroupsOfDepth(NSUInteger depth) {
NSMutableData* data = [NSMutableData dataWithCapacity:0];
uint32_t byte = 35; // 35 = 0b100011 -> field 4/start group
for (NSUInteger i = 0; i < depth; ++i) {
[data appendBytes:&byte length:1];
}
byte = 8; // 8 = 0b1000, -> field 1/varint
[data appendBytes:&byte length:1];
byte = 1; // 1 -> varint value of 1
[data appendBytes:&byte length:1];
byte = 36; // 36 = 0b100100 -> field 4/end group
for (NSUInteger i = 0; i < depth; ++i) {
[data appendBytes:&byte length:1];
}
return data;
}
- (void)testParsingNestingGroupData {
// 35 = 0b100011 -> field 4/start group
// 36 = 0b100100 -> field 4/end group
// 43 = 0b101011 -> field 5/end group
// 44 = 0b101100 -> field 5/end group
// 8 = 0b1000, 1 -> field 1/varint, value of 1
// 21 = 0b10101, 0x78, 0x56, 0x34, 0x12 -> field 2/fixed32, value of 0x12345678
// 25 = 0b11001, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12 -> field 3/fixed64,
// value of 0x123456789abcdef0LL
// 50 = 0b110010, 0x0 -> field 6/length delimited, length 0
// 50 = 0b110010, 0x1, 42 -> field 6/length delimited, length 1, byte 42
// 0 -> field 0 which is invalid/varint
// 15 = 0b1111 -> field 1, wire type 7 which is invalid
TestEmptyMessage* m = [TestEmptyMessage parseFromData:DataFromBytes(35, 36)
error:NULL]; // empty group
GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
GPBUnknownFields* group = [ufs firstGroup:4];
XCTAssertTrue(group.empty);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1, 36) error:NULL]; // varint
ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
group = [ufs firstGroup:4];
XCTAssertEqual(group.count, (NSUInteger)1);
uint64_t varint = 0;
XCTAssertTrue([group getFirst:1 varint:&varint]);
XCTAssertEqual(varint, 1);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 21, 0x78, 0x56, 0x34, 0x12, 36)
error:NULL]; // fixed32
ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
group = [ufs firstGroup:4];
XCTAssertEqual(group.count, (NSUInteger)1);
uint32_t fixed32 = 0;
XCTAssertTrue([group getFirst:2 fixed32:&fixed32]);
XCTAssertEqual(fixed32, 0x12345678);
m = [TestEmptyMessage
parseFromData:DataFromBytes(35, 25, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
36)
error:NULL]; // fixed64
ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
group = [ufs firstGroup:4];
XCTAssertEqual(group.count, (NSUInteger)1);
uint64_t fixed64 = 0;
XCTAssertTrue([group getFirst:3 fixed64:&fixed64]);
XCTAssertEqual(fixed64, 0x123456789abcdef0LL);
XCTAssertEqual(m.unknownFields.countOfFields, (NSUInteger)1);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 50, 0, 36)
error:NULL]; // length delimited, length 0
ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
group = [ufs firstGroup:4];
XCTAssertEqual(group.count, (NSUInteger)1);
NSData* lengthDelimited = [group firstLengthDelimited:6];
XCTAssertEqualObjects(lengthDelimited, [NSData data]);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 50, 1, 42, 36)
error:NULL]; // length delimited, length 1, byte 42
ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
group = [ufs firstGroup:4];
XCTAssertEqual(group.count, (NSUInteger)1);
lengthDelimited = [group firstLengthDelimited:6];
XCTAssertEqualObjects(lengthDelimited, DataFromBytes(42));
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 43, 44, 36) error:NULL]; // Sub group
ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
group = [ufs firstGroup:4];
XCTAssertEqual(group.count, (NSUInteger)1);
group = [group firstGroup:5];
XCTAssertTrue(group.empty);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1, 43, 8, 2, 44, 36)
error:NULL]; // varint and sub group with varint
ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
group = [ufs firstGroup:4];
XCTAssertEqual(group.count, (NSUInteger)2);
varint = 0;
XCTAssertTrue([group getFirst:1 varint:&varint]);
XCTAssertEqual(varint, 1);
group = [group firstGroup:5];
XCTAssertEqual(group.count, (NSUInteger)1);
XCTAssertTrue([group getFirst:1 varint:&varint]);
XCTAssertEqual(varint, 2);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 0, 36)
error:NULL]); // Invalid field number
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 15, 36)
error:NULL]); // Invalid wire type
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 21, 0x78, 0x56, 0x34)
error:NULL]); // truncated fixed32
XCTAssertNil([TestEmptyMessage
parseFromData:DataFromBytes(35, 25, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56,
0x34)
error:NULL]); // truncated fixed64
// Mising end group
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 8, 1) error:NULL]);
// Wrong end group
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 44) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1, 44) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 36) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 8, 1, 36) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 44, 44) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 8, 1, 44, 44) error:NULL]);
// This is the same limit as within GPBCodedInputStream.
const NSUInteger kDefaultRecursionLimit = 100;
// That depth parses.
NSData* testData = DataForGroupsOfDepth(kDefaultRecursionLimit);
m = [TestEmptyMessage parseFromData:testData error:NULL];
ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
group = [ufs firstGroup:4];
for (NSUInteger i = 1; i < kDefaultRecursionLimit; ++i) {
XCTAssertEqual(group.count, (NSUInteger)1);
group = [group firstGroup:4];
}
// group is now the inner most group.
XCTAssertEqual(group.count, (NSUInteger)1);
varint = 0;
XCTAssertTrue([group getFirst:1 varint:&varint]);
XCTAssertEqual(varint, 1);
// One more level deep fails.
testData = DataForGroupsOfDepth(kDefaultRecursionLimit + 1);
XCTAssertNil([TestEmptyMessage parseFromData:testData error:NULL]);
}
@end

Loading…
Cancel
Save