`GPBUnknownFields` will be the eventually replacement for `GPBUnknownFieldSet`. This introduces the type and the changes to `GPBUnknownField`. The new api will preserve the wire ordering of unknown fields. This is now checked in conformance tests. While this adds the type changes and tests them, it does not yet wire the changes in to the rest of the Runtime, so the conformance tests still done pass. `GPBUnknownFieldSet` also hasn't been deprecated yet, that will come in later with the wiring in to the runtime. PiperOrigin-RevId: 648361455pull/17276/head
parent
a4f9ddd8fc
commit
47f633eae6
13 changed files with 1374 additions and 129 deletions
@ -0,0 +1,155 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2024 Google Inc. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
#import <Foundation/Foundation.h> |
||||
|
||||
@class GPBUnknownField; |
||||
|
||||
NS_ASSUME_NONNULL_BEGIN |
||||
|
||||
/**
|
||||
* A collection of unknown field numbers and their values. |
||||
* |
||||
* Note: `NSFastEnumeration` is supported to iterate over the `GPBUnknownFields` |
||||
* in order. |
||||
* |
||||
* Reminder: Any field number can occur multiple times. For example, if a .proto |
||||
* file were updated to a have a new (unpacked) repeated field, then each value |
||||
* would appear independently. Likewise, it is possible that a number appears |
||||
* multiple times with different data types, i.e. - unpacked vs. package repeated |
||||
* fields from concatenating binary blobs of data. |
||||
*/ |
||||
__attribute__((objc_subclassing_restricted)) |
||||
@interface GPBUnknownFields : NSObject<NSCopying, NSFastEnumeration> |
||||
|
||||
/**
|
||||
* Initializes a new empty instance. |
||||
**/ |
||||
- (instancetype)init; |
||||
|
||||
/**
|
||||
* The number of fields in this set. A single field number can appear in |
||||
* multiple `GPBUnknownField` values as it might be a repeated field (it is |
||||
* also possible that they have different `type` values (for example package vs |
||||
* unpacked repeated fields). |
||||
* |
||||
* Note: `NSFastEnumeration` is supported to iterate over the fields in order. |
||||
**/ |
||||
@property(nonatomic, readonly, assign) NSUInteger count; |
||||
|
||||
/** If the set is empty or not. */ |
||||
@property(nonatomic, readonly, assign) BOOL empty; |
||||
|
||||
/**
|
||||
* Removes all the fields current in the set. |
||||
**/ |
||||
- (void)clear; |
||||
|
||||
/**
|
||||
* Fetches the subset of all the unknown fields that are for the given field |
||||
* number. |
||||
* |
||||
* @returns An `NSArray` of `GPBUnknownField`s or `nil` if there were none. |
||||
*/ |
||||
- (nullable NSArray<GPBUnknownField *> *)fields:(int32_t)fieldNumber; |
||||
|
||||
/**
|
||||
* Add a new varint unknown field. |
||||
* |
||||
* @param fieldNumber The field number to use. |
||||
* @param value The value to add. |
||||
**/ |
||||
- (void)addFieldNumber:(int32_t)fieldNumber varint:(uint64_t)value; |
||||
|
||||
/**
|
||||
* Add a new fixed32 unknown field. |
||||
* |
||||
* @param fieldNumber The field number to use. |
||||
* @param value The value to add. |
||||
**/ |
||||
- (void)addFieldNumber:(int32_t)fieldNumber fixed32:(uint32_t)value; |
||||
|
||||
/**
|
||||
* Add a new fixed64 unknown field. |
||||
* |
||||
* @param fieldNumber The field number to use. |
||||
* @param value The value to add. |
||||
**/ |
||||
- (void)addFieldNumber:(int32_t)fieldNumber fixed64:(uint64_t)value; |
||||
|
||||
/**
|
||||
* Add a new length delimited (length prefixed) unknown field. |
||||
* |
||||
* @param fieldNumber The field number to use. |
||||
* @param value The value to add. |
||||
**/ |
||||
- (void)addFieldNumber:(int32_t)fieldNumber lengthDelimited:(nonnull NSData *)value; |
||||
|
||||
/**
|
||||
* Add a group (tag delimited) unknown field. |
||||
* |
||||
* @param fieldNumber The field number to use. |
||||
* |
||||
* @return A new `GPBUnknownFields` to set the field of the group too. |
||||
**/ |
||||
- (nonnull GPBUnknownFields *)addGroupWithFieldNumber:(int32_t)fieldNumber; |
||||
|
||||
@end |
||||
|
||||
@interface GPBUnknownFields (AccessHelpers) |
||||
|
||||
/**
|
||||
* Fetches the first varint for the given field number. |
||||
* |
||||
* @param fieldNumber The field number to look for. |
||||
* @param outValue A pointer to receive the value if found |
||||
* |
||||
* @returns YES/NO on if there was a matching unknown field. |
||||
**/ |
||||
- (BOOL)getFirst:(int32_t)fieldNumber varint:(nonnull uint64_t *)outValue; |
||||
|
||||
/**
|
||||
* Fetches the first fixed32 for the given field number. |
||||
* |
||||
* @param fieldNumber The field number to look for. |
||||
* @param outValue A pointer to receive the value if found |
||||
* |
||||
* @returns YES/NO on if there was a matching unknown field. |
||||
**/ |
||||
- (BOOL)getFirst:(int32_t)fieldNumber fixed32:(nonnull uint32_t *)outValue; |
||||
|
||||
/**
|
||||
* Fetches the first fixed64 for the given field number. |
||||
* |
||||
* @param fieldNumber The field number to look for. |
||||
* @param outValue A pointer to receive the value if found |
||||
* |
||||
* @returns YES/NO on if there was a matching unknown field. |
||||
**/ |
||||
- (BOOL)getFirst:(int32_t)fieldNumber fixed64:(nonnull uint64_t *)outValue; |
||||
|
||||
/**
|
||||
* Fetches the first length delimited (length prefixed) for the given field number. |
||||
* |
||||
* @param fieldNumber The field number to look for. |
||||
* |
||||
* @returns The first length delimited value for the given field number. |
||||
**/ |
||||
- (nullable NSData *)firstLengthDelimited:(int32_t)fieldNumber; |
||||
|
||||
/**
|
||||
* Fetches the first group (tag delimited) field for the given field number. |
||||
* |
||||
* @param fieldNumber The field number to look for. |
||||
* |
||||
* @returns The first group for the given field number. |
||||
**/ |
||||
- (nullable GPBUnknownFields *)firstGroup:(int32_t)fieldNumber; |
||||
|
||||
@end |
||||
|
||||
NS_ASSUME_NONNULL_END |
@ -0,0 +1,199 @@ |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2024 Google Inc. All rights reserved. |
||||
// |
||||
// Use of this source code is governed by a BSD-style |
||||
// license that can be found in the LICENSE file or at |
||||
// https://developers.google.com/open-source/licenses/bsd |
||||
|
||||
#import "GPBUnknownFields.h" |
||||
#import "GPBUnknownField_PackagePrivate.h" |
||||
|
||||
#define CHECK_FIELD_NUMBER(number) \ |
||||
if (number <= 0) { \ |
||||
[NSException raise:NSInvalidArgumentException format:@"Not a valid field number."]; \ |
||||
} |
||||
|
||||
@implementation GPBUnknownFields { |
||||
@package |
||||
NSMutableArray<GPBUnknownField *> *fields_; |
||||
} |
||||
|
||||
// Direct access is use for speed, to avoid even internally declaring things |
||||
// read/write, etc. The warning is enabled in the project to ensure code calling |
||||
// protos can turn on -Wdirect-ivar-access without issues. |
||||
#pragma clang diagnostic push |
||||
#pragma clang diagnostic ignored "-Wdirect-ivar-access" |
||||
|
||||
- (instancetype)init { |
||||
self = [super init]; |
||||
if (self) { |
||||
fields_ = [[NSMutableArray alloc] init]; |
||||
} |
||||
return self; |
||||
} |
||||
|
||||
- (id)copyWithZone:(NSZone *)zone { |
||||
GPBUnknownFields *copy = [[GPBUnknownFields alloc] init]; |
||||
// Fields are r/o in this api, so just copy the array. |
||||
copy->fields_ = [fields_ mutableCopyWithZone:zone]; |
||||
return copy; |
||||
} |
||||
|
||||
- (void)dealloc { |
||||
[fields_ release]; |
||||
[super dealloc]; |
||||
} |
||||
|
||||
- (BOOL)isEqual:(id)object { |
||||
if (![object isKindOfClass:[GPBUnknownFields class]]) { |
||||
return NO; |
||||
} |
||||
GPBUnknownFields *ufs = (GPBUnknownFields *)object; |
||||
// The type is defined with order of fields mattering, so just compare the arrays. |
||||
return [fields_ isEqual:ufs->fields_]; |
||||
} |
||||
|
||||
- (NSUInteger)hash { |
||||
return [fields_ hash]; |
||||
} |
||||
|
||||
- (NSString *)description { |
||||
return [NSString |
||||
stringWithFormat:@"<%@ %p>: %lu fields", [self class], self, (unsigned long)fields_.count]; |
||||
} |
||||
|
||||
#pragma mark - Public Methods |
||||
|
||||
- (NSUInteger)count { |
||||
return fields_.count; |
||||
} |
||||
|
||||
- (BOOL)empty { |
||||
return fields_.count == 0; |
||||
} |
||||
|
||||
- (void)clear { |
||||
[fields_ removeAllObjects]; |
||||
} |
||||
|
||||
- (NSArray<GPBUnknownField *> *)fields:(int32_t)fieldNumber { |
||||
CHECK_FIELD_NUMBER(fieldNumber); |
||||
NSMutableArray<GPBUnknownField *> *result = [[NSMutableArray alloc] init]; |
||||
for (GPBUnknownField *field in fields_) { |
||||
if (field.number == fieldNumber) { |
||||
[result addObject:field]; |
||||
} |
||||
} |
||||
if (result.count == 0) { |
||||
[result release]; |
||||
return nil; |
||||
} |
||||
return [result autorelease]; |
||||
} |
||||
|
||||
- (void)addFieldNumber:(int32_t)fieldNumber varint:(uint64_t)value { |
||||
CHECK_FIELD_NUMBER(fieldNumber); |
||||
GPBUnknownField *field = [[GPBUnknownField alloc] initWithNumber:fieldNumber varint:value]; |
||||
[fields_ addObject:field]; |
||||
[field release]; |
||||
} |
||||
|
||||
- (void)addFieldNumber:(int32_t)fieldNumber fixed32:(uint32_t)value { |
||||
CHECK_FIELD_NUMBER(fieldNumber); |
||||
GPBUnknownField *field = [[GPBUnknownField alloc] initWithNumber:fieldNumber fixed32:value]; |
||||
[fields_ addObject:field]; |
||||
[field release]; |
||||
} |
||||
|
||||
- (void)addFieldNumber:(int32_t)fieldNumber fixed64:(uint64_t)value { |
||||
CHECK_FIELD_NUMBER(fieldNumber); |
||||
GPBUnknownField *field = [[GPBUnknownField alloc] initWithNumber:fieldNumber fixed64:value]; |
||||
[fields_ addObject:field]; |
||||
[field release]; |
||||
} |
||||
|
||||
- (void)addFieldNumber:(int32_t)fieldNumber lengthDelimited:(NSData *)value { |
||||
CHECK_FIELD_NUMBER(fieldNumber); |
||||
GPBUnknownField *field = [[GPBUnknownField alloc] initWithNumber:fieldNumber |
||||
lengthDelimited:value]; |
||||
[fields_ addObject:field]; |
||||
[field release]; |
||||
} |
||||
|
||||
- (GPBUnknownFields *)addGroupWithFieldNumber:(int32_t)fieldNumber { |
||||
CHECK_FIELD_NUMBER(fieldNumber); |
||||
GPBUnknownFields *group = [[GPBUnknownFields alloc] init]; |
||||
GPBUnknownField *field = [[GPBUnknownField alloc] initWithNumber:fieldNumber group:group]; |
||||
[fields_ addObject:field]; |
||||
[field release]; |
||||
return [group autorelease]; |
||||
} |
||||
|
||||
#pragma mark - NSFastEnumeration protocol |
||||
|
||||
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state |
||||
objects:(__unsafe_unretained id _Nonnull *)stackbuf |
||||
count:(NSUInteger)len { |
||||
return [fields_ countByEnumeratingWithState:state objects:stackbuf count:len]; |
||||
} |
||||
|
||||
@end |
||||
|
||||
@implementation GPBUnknownFields (AccessHelpers) |
||||
|
||||
- (BOOL)getFirst:(int32_t)fieldNumber varint:(nonnull uint64_t *)outValue { |
||||
CHECK_FIELD_NUMBER(fieldNumber); |
||||
for (GPBUnknownField *field in fields_) { |
||||
if (field.number == fieldNumber && field.type == GPBUnknownFieldTypeVarint) { |
||||
*outValue = field.varint; |
||||
return YES; |
||||
} |
||||
} |
||||
return NO; |
||||
} |
||||
|
||||
- (BOOL)getFirst:(int32_t)fieldNumber fixed32:(nonnull uint32_t *)outValue { |
||||
CHECK_FIELD_NUMBER(fieldNumber); |
||||
for (GPBUnknownField *field in fields_) { |
||||
if (field.number == fieldNumber && field.type == GPBUnknownFieldTypeFixed32) { |
||||
*outValue = field.fixed32; |
||||
return YES; |
||||
} |
||||
} |
||||
return NO; |
||||
} |
||||
|
||||
- (BOOL)getFirst:(int32_t)fieldNumber fixed64:(nonnull uint64_t *)outValue { |
||||
CHECK_FIELD_NUMBER(fieldNumber); |
||||
for (GPBUnknownField *field in fields_) { |
||||
if (field.number == fieldNumber && field.type == GPBUnknownFieldTypeFixed64) { |
||||
*outValue = field.fixed64; |
||||
return YES; |
||||
} |
||||
} |
||||
return NO; |
||||
} |
||||
|
||||
- (nullable NSData *)firstLengthDelimited:(int32_t)fieldNumber { |
||||
CHECK_FIELD_NUMBER(fieldNumber); |
||||
for (GPBUnknownField *field in fields_) { |
||||
if (field.number == fieldNumber && field.type == GPBUnknownFieldTypeLengthDelimited) { |
||||
return field.lengthDelimited; |
||||
} |
||||
} |
||||
return nil; |
||||
} |
||||
|
||||
- (nullable GPBUnknownFields *)firstGroup:(int32_t)fieldNumber { |
||||
CHECK_FIELD_NUMBER(fieldNumber); |
||||
for (GPBUnknownField *field in fields_) { |
||||
if (field.number == fieldNumber && field.type == GPBUnknownFieldTypeGroup) { |
||||
return field.group; |
||||
} |
||||
} |
||||
return nil; |
||||
} |
||||
|
||||
#pragma clang diagnostic pop |
||||
|
||||
@end |
@ -0,0 +1,15 @@ |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2024 Google Inc. All rights reserved. |
||||
// |
||||
// Use of this source code is governed by a BSD-style |
||||
// license that can be found in the LICENSE file or at |
||||
// https://developers.google.com/open-source/licenses/bsd |
||||
|
||||
// This is a test including a single public header to ensure things build. |
||||
// It helps test that imports are complete/ordered correctly. |
||||
|
||||
#import "GPBUnknownFields.h" |
||||
|
||||
// Something in the body of this file so the compiler/linker won't complain |
||||
// about an empty .o file. |
||||
__attribute__((visibility("default"))) char dummy_symbol_25 = 0; |
@ -0,0 +1,514 @@ |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2024 Google Inc. All rights reserved. |
||||
// |
||||
// Use of this source code is governed by a BSD-style |
||||
// license that can be found in the LICENSE file or at |
||||
// https://developers.google.com/open-source/licenses/bsd |
||||
|
||||
#import "GPBTestUtilities.h" |
||||
#import "GPBUnknownField.h" |
||||
#import "GPBUnknownFields.h" |
||||
#import "objectivec/Tests/Unittest.pbobjc.h" |
||||
|
||||
@interface UnknownFieldsTest : GPBTestCase |
||||
@end |
||||
|
||||
@implementation UnknownFieldsTest |
||||
|
||||
- (void)testEmptyAndClear { |
||||
GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; |
||||
XCTAssertTrue(ufs.empty); |
||||
|
||||
[ufs addFieldNumber:1 varint:1]; |
||||
XCTAssertFalse(ufs.empty); |
||||
[ufs clear]; |
||||
XCTAssertTrue(ufs.empty); |
||||
|
||||
[ufs addFieldNumber:1 fixed32:1]; |
||||
XCTAssertFalse(ufs.empty); |
||||
[ufs clear]; |
||||
XCTAssertTrue(ufs.empty); |
||||
|
||||
[ufs addFieldNumber:1 fixed64:1]; |
||||
XCTAssertFalse(ufs.empty); |
||||
[ufs clear]; |
||||
XCTAssertTrue(ufs.empty); |
||||
|
||||
[ufs addFieldNumber:1 lengthDelimited:[NSData data]]; |
||||
XCTAssertFalse(ufs.empty); |
||||
[ufs clear]; |
||||
XCTAssertTrue(ufs.empty); |
||||
|
||||
GPBUnknownFields* group = [ufs addGroupWithFieldNumber:1]; |
||||
XCTAssertNotNil(group); |
||||
XCTAssertFalse(ufs.empty); |
||||
} |
||||
|
||||
- (void)testEqualityAndHash { |
||||
// Empty |
||||
|
||||
GPBUnknownFields* ufs1 = [[[GPBUnknownFields alloc] init] autorelease]; |
||||
XCTAssertTrue([ufs1 isEqual:ufs1]); |
||||
XCTAssertFalse([ufs1 isEqual:@"foo"]); |
||||
GPBUnknownFields* ufs2 = [[[GPBUnknownFields alloc] init] autorelease]; |
||||
XCTAssertEqualObjects(ufs1, ufs2); |
||||
XCTAssertEqual([ufs1 hash], [ufs2 hash]); |
||||
|
||||
// Varint |
||||
|
||||
[ufs1 addFieldNumber:1 varint:1]; |
||||
XCTAssertNotEqualObjects(ufs1, ufs2); |
||||
[ufs2 addFieldNumber:1 varint:1]; |
||||
XCTAssertEqualObjects(ufs1, ufs2); |
||||
XCTAssertEqual([ufs1 hash], [ufs2 hash]); |
||||
|
||||
// Fixed32 |
||||
|
||||
[ufs1 addFieldNumber:2 fixed32:1]; |
||||
XCTAssertNotEqualObjects(ufs1, ufs2); |
||||
[ufs2 addFieldNumber:2 fixed32:1]; |
||||
XCTAssertEqualObjects(ufs1, ufs2); |
||||
XCTAssertEqual([ufs1 hash], [ufs2 hash]); |
||||
|
||||
// Fixed64 |
||||
|
||||
[ufs1 addFieldNumber:3 fixed64:1]; |
||||
XCTAssertNotEqualObjects(ufs1, ufs2); |
||||
[ufs2 addFieldNumber:3 fixed64:1]; |
||||
XCTAssertEqualObjects(ufs1, ufs2); |
||||
XCTAssertEqual([ufs1 hash], [ufs2 hash]); |
||||
|
||||
// LengthDelimited |
||||
|
||||
[ufs1 addFieldNumber:4 lengthDelimited:DataFromCStr("foo")]; |
||||
XCTAssertNotEqualObjects(ufs1, ufs2); |
||||
[ufs2 addFieldNumber:4 lengthDelimited:DataFromCStr("foo")]; |
||||
XCTAssertEqualObjects(ufs1, ufs2); |
||||
XCTAssertEqual([ufs1 hash], [ufs2 hash]); |
||||
|
||||
// Group |
||||
|
||||
GPBUnknownFields* group1 = [ufs1 addGroupWithFieldNumber:5]; |
||||
[group1 addFieldNumber:10 varint:10]; |
||||
XCTAssertNotEqualObjects(ufs1, ufs2); |
||||
GPBUnknownFields* group2 = [ufs2 addGroupWithFieldNumber:5]; |
||||
[group2 addFieldNumber:10 varint:10]; |
||||
XCTAssertEqualObjects(ufs1, ufs2); |
||||
XCTAssertEqual([ufs1 hash], [ufs2 hash]); |
||||
} |
||||
|
||||
- (void)testInequality_Values { |
||||
// Same field number and type, different values. |
||||
|
||||
GPBUnknownFields* ufs1 = [[[GPBUnknownFields alloc] init] autorelease]; |
||||
GPBUnknownFields* ufs2 = [[[GPBUnknownFields alloc] init] autorelease]; |
||||
|
||||
[ufs1 addFieldNumber:1 varint:1]; |
||||
[ufs2 addFieldNumber:1 varint:2]; |
||||
XCTAssertNotEqualObjects(ufs1, ufs2); |
||||
|
||||
[ufs1 clear]; |
||||
[ufs2 clear]; |
||||
XCTAssertEqualObjects(ufs1, ufs2); |
||||
|
||||
[ufs1 addFieldNumber:1 fixed32:1]; |
||||
[ufs2 addFieldNumber:1 fixed32:2]; |
||||
XCTAssertNotEqualObjects(ufs1, ufs2); |
||||
|
||||
[ufs1 clear]; |
||||
[ufs2 clear]; |
||||
XCTAssertEqualObjects(ufs1, ufs2); |
||||
|
||||
[ufs1 addFieldNumber:1 fixed64:1]; |
||||
[ufs2 addFieldNumber:1 fixed64:2]; |
||||
XCTAssertNotEqualObjects(ufs1, ufs2); |
||||
|
||||
[ufs1 clear]; |
||||
[ufs2 clear]; |
||||
XCTAssertEqualObjects(ufs1, ufs2); |
||||
|
||||
[ufs1 addFieldNumber:1 lengthDelimited:DataFromCStr("foo")]; |
||||
[ufs2 addFieldNumber:1 lengthDelimited:DataFromCStr("bar")]; |
||||
XCTAssertNotEqualObjects(ufs1, ufs2); |
||||
|
||||
[ufs1 clear]; |
||||
[ufs2 clear]; |
||||
XCTAssertEqualObjects(ufs1, ufs2); |
||||
|
||||
GPBUnknownFields* group1 = [ufs1 addGroupWithFieldNumber:1]; |
||||
GPBUnknownFields* group2 = [ufs2 addGroupWithFieldNumber:1]; |
||||
[group1 addFieldNumber:10 varint:10]; |
||||
[group2 addFieldNumber:10 varint:20]; |
||||
XCTAssertNotEqualObjects(ufs1, ufs2); |
||||
XCTAssertNotEqualObjects(group1, group2); |
||||
} |
||||
|
||||
- (void)testInequality_FieldNumbers { |
||||
// Same type and value, different field numbers. |
||||
|
||||
GPBUnknownFields* ufs1 = [[[GPBUnknownFields alloc] init] autorelease]; |
||||
GPBUnknownFields* ufs2 = [[[GPBUnknownFields alloc] init] autorelease]; |
||||
|
||||
[ufs1 addFieldNumber:1 varint:1]; |
||||
[ufs2 addFieldNumber:2 varint:1]; |
||||
XCTAssertNotEqualObjects(ufs1, ufs2); |
||||
|
||||
[ufs1 clear]; |
||||
[ufs2 clear]; |
||||
XCTAssertEqualObjects(ufs1, ufs2); |
||||
|
||||
[ufs1 addFieldNumber:1 fixed32:1]; |
||||
[ufs2 addFieldNumber:2 fixed32:1]; |
||||
XCTAssertNotEqualObjects(ufs1, ufs2); |
||||
|
||||
[ufs1 clear]; |
||||
[ufs2 clear]; |
||||
XCTAssertEqualObjects(ufs1, ufs2); |
||||
|
||||
[ufs1 addFieldNumber:1 fixed64:1]; |
||||
[ufs2 addFieldNumber:2 fixed64:1]; |
||||
XCTAssertNotEqualObjects(ufs1, ufs2); |
||||
|
||||
[ufs1 clear]; |
||||
[ufs2 clear]; |
||||
XCTAssertEqualObjects(ufs1, ufs2); |
||||
|
||||
[ufs1 addFieldNumber:1 lengthDelimited:DataFromCStr("foo")]; |
||||
[ufs2 addFieldNumber:2 lengthDelimited:DataFromCStr("fod")]; |
||||
XCTAssertNotEqualObjects(ufs1, ufs2); |
||||
|
||||
[ufs1 clear]; |
||||
[ufs2 clear]; |
||||
XCTAssertEqualObjects(ufs1, ufs2); |
||||
|
||||
GPBUnknownFields* group1 = [ufs1 addGroupWithFieldNumber:1]; |
||||
GPBUnknownFields* group2 = [ufs2 addGroupWithFieldNumber:2]; |
||||
[group1 addFieldNumber:10 varint:10]; |
||||
[group2 addFieldNumber:10 varint:10]; |
||||
XCTAssertNotEqualObjects(ufs1, ufs2); |
||||
XCTAssertEqualObjects(group1, group2); |
||||
} |
||||
|
||||
- (void)testInequality_Types { |
||||
// Same field number and value when possible, different types. |
||||
|
||||
GPBUnknownFields* ufs1 = [[[GPBUnknownFields alloc] init] autorelease]; |
||||
GPBUnknownFields* ufs2 = [[[GPBUnknownFields alloc] init] autorelease]; |
||||
|
||||
[ufs1 addFieldNumber:1 varint:1]; |
||||
[ufs2 addFieldNumber:1 fixed32:1]; |
||||
XCTAssertNotEqualObjects(ufs1, ufs2); |
||||
|
||||
[ufs1 clear]; |
||||
[ufs2 clear]; |
||||
XCTAssertEqualObjects(ufs1, ufs2); |
||||
|
||||
[ufs1 addFieldNumber:1 fixed32:1]; |
||||
[ufs2 addFieldNumber:1 fixed64:1]; |
||||
XCTAssertNotEqualObjects(ufs1, ufs2); |
||||
|
||||
[ufs1 clear]; |
||||
[ufs2 clear]; |
||||
XCTAssertEqualObjects(ufs1, ufs2); |
||||
|
||||
[ufs1 addFieldNumber:1 fixed64:1]; |
||||
[ufs2 addFieldNumber:1 varint:1]; |
||||
XCTAssertNotEqualObjects(ufs1, ufs2); |
||||
|
||||
[ufs1 clear]; |
||||
[ufs2 clear]; |
||||
XCTAssertEqualObjects(ufs1, ufs2); |
||||
|
||||
[ufs1 addFieldNumber:1 lengthDelimited:DataFromCStr("foo")]; |
||||
[ufs2 addFieldNumber:1 varint:1]; |
||||
XCTAssertNotEqualObjects(ufs1, ufs2); |
||||
|
||||
[ufs1 clear]; |
||||
[ufs2 clear]; |
||||
XCTAssertEqualObjects(ufs1, ufs2); |
||||
|
||||
GPBUnknownFields* group1 = [ufs1 addGroupWithFieldNumber:1]; |
||||
[group1 addFieldNumber:10 varint:10]; |
||||
[ufs2 addFieldNumber:1 varint:1]; |
||||
XCTAssertNotEqualObjects(ufs1, ufs2); |
||||
} |
||||
|
||||
- (void)testGetFirst { |
||||
GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; |
||||
XCTAssertEqual(0U, ufs.count); |
||||
[ufs addFieldNumber:1 varint:1]; |
||||
XCTAssertEqual(1U, ufs.count); |
||||
[ufs addFieldNumber:1 varint:2]; |
||||
XCTAssertEqual(2U, ufs.count); |
||||
[ufs addFieldNumber:1 fixed32:3]; |
||||
XCTAssertEqual(3U, ufs.count); |
||||
[ufs addFieldNumber:1 fixed32:4]; |
||||
XCTAssertEqual(4U, ufs.count); |
||||
[ufs addFieldNumber:1 fixed64:5]; |
||||
XCTAssertEqual(5U, ufs.count); |
||||
[ufs addFieldNumber:1 fixed64:6]; |
||||
XCTAssertEqual(6U, ufs.count); |
||||
[ufs addFieldNumber:1 lengthDelimited:DataFromCStr("foo")]; |
||||
XCTAssertEqual(7U, ufs.count); |
||||
[ufs addFieldNumber:1 lengthDelimited:DataFromCStr("bar")]; |
||||
XCTAssertEqual(8U, ufs.count); |
||||
GPBUnknownFields* group1 = [ufs addGroupWithFieldNumber:1]; |
||||
XCTAssertNotNil(group1); |
||||
XCTAssertEqual(9U, ufs.count); |
||||
GPBUnknownFields* group2 = [ufs addGroupWithFieldNumber:1]; |
||||
XCTAssertNotNil(group2); |
||||
XCTAssertTrue(group1 != group2); // Different objects |
||||
XCTAssertEqual(10U, ufs.count); |
||||
|
||||
[ufs addFieldNumber:11 varint:11]; |
||||
[ufs addFieldNumber:12 fixed32:12]; |
||||
[ufs addFieldNumber:13 fixed64:13]; |
||||
[ufs addFieldNumber:14 lengthDelimited:DataFromCStr("foo2")]; |
||||
GPBUnknownFields* group3 = [ufs addGroupWithFieldNumber:15]; |
||||
XCTAssertNotNil(group3); |
||||
XCTAssertTrue(group3 != group1); // Different objects |
||||
XCTAssertTrue(group3 != group2); // Different objects |
||||
XCTAssertEqual(15U, ufs.count); |
||||
|
||||
uint64_t varint = 0; |
||||
XCTAssertTrue([ufs getFirst:1 varint:&varint]); |
||||
XCTAssertEqual(1U, varint); |
||||
XCTAssertTrue([ufs getFirst:11 varint:&varint]); |
||||
XCTAssertEqual(11U, varint); |
||||
XCTAssertFalse([ufs getFirst:12 varint:&varint]); // Different type |
||||
XCTAssertFalse([ufs getFirst:99 varint:&varint]); // Not present |
||||
|
||||
uint32_t fixed32 = 0; |
||||
XCTAssertTrue([ufs getFirst:1 fixed32:&fixed32]); |
||||
XCTAssertEqual(3U, fixed32); |
||||
XCTAssertTrue([ufs getFirst:12 fixed32:&fixed32]); |
||||
XCTAssertEqual(12U, fixed32); |
||||
XCTAssertFalse([ufs getFirst:11 fixed32:&fixed32]); // Different type |
||||
XCTAssertFalse([ufs getFirst:99 fixed32:&fixed32]); // Not present |
||||
|
||||
uint64_t fixed64 = 0; |
||||
XCTAssertTrue([ufs getFirst:1 fixed64:&fixed64]); |
||||
XCTAssertEqual(5U, fixed64); |
||||
XCTAssertTrue([ufs getFirst:13 fixed64:&fixed64]); |
||||
XCTAssertEqual(13U, fixed64); |
||||
XCTAssertFalse([ufs getFirst:11 fixed64:&fixed64]); // Different type |
||||
XCTAssertFalse([ufs getFirst:99 fixed64:&fixed64]); // Not present |
||||
|
||||
XCTAssertEqualObjects(DataFromCStr("foo"), [ufs firstLengthDelimited:1]); |
||||
XCTAssertEqualObjects(DataFromCStr("foo2"), [ufs firstLengthDelimited:14]); |
||||
XCTAssertNil([ufs firstLengthDelimited:11]); // Different type |
||||
XCTAssertNil([ufs firstLengthDelimited:99]); // Not present |
||||
|
||||
XCTAssertTrue(group1 == [ufs firstGroup:1]); // Testing ptr, exact object |
||||
XCTAssertTrue(group3 == [ufs firstGroup:15]); // Testing ptr, exact object |
||||
XCTAssertNil([ufs firstGroup:11]); // Different type |
||||
XCTAssertNil([ufs firstGroup:99]); // Not present |
||||
} |
||||
|
||||
- (void)testGetFields { |
||||
GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; |
||||
[ufs addFieldNumber:1 varint:1]; |
||||
[ufs addFieldNumber:2 varint:2]; |
||||
[ufs addFieldNumber:1 fixed32:3]; |
||||
[ufs addFieldNumber:2 fixed32:4]; |
||||
[ufs addFieldNumber:1 fixed64:5]; |
||||
[ufs addFieldNumber:3 fixed64:6]; |
||||
[ufs addFieldNumber:1 lengthDelimited:DataFromCStr("foo")]; |
||||
[ufs addFieldNumber:2 lengthDelimited:DataFromCStr("bar")]; |
||||
GPBUnknownFields* group1 = [ufs addGroupWithFieldNumber:1]; |
||||
GPBUnknownFields* group2 = [ufs addGroupWithFieldNumber:3]; |
||||
|
||||
NSArray<GPBUnknownField*>* fields1 = [ufs fields:1]; |
||||
XCTAssertEqual(fields1.count, 5); |
||||
GPBUnknownField* field = fields1[0]; |
||||
XCTAssertEqual(field.number, 1); |
||||
XCTAssertEqual(field.type, GPBUnknownFieldTypeVarint); |
||||
XCTAssertEqual(field.varint, 1); |
||||
field = fields1[1]; |
||||
XCTAssertEqual(field.number, 1); |
||||
XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed32); |
||||
XCTAssertEqual(field.fixed32, 3); |
||||
field = fields1[2]; |
||||
XCTAssertEqual(field.number, 1); |
||||
XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed64); |
||||
XCTAssertEqual(field.fixed64, 5); |
||||
field = fields1[3]; |
||||
XCTAssertEqual(field.number, 1); |
||||
XCTAssertEqual(field.type, GPBUnknownFieldTypeLengthDelimited); |
||||
XCTAssertEqualObjects(field.lengthDelimited, DataFromCStr("foo")); |
||||
field = fields1[4]; |
||||
XCTAssertEqual(field.number, 1); |
||||
XCTAssertEqual(field.type, GPBUnknownFieldTypeGroup); |
||||
XCTAssertTrue(field.group == group1); // Exact object. |
||||
|
||||
NSArray<GPBUnknownField*>* fields2 = [ufs fields:2]; |
||||
XCTAssertEqual(fields2.count, 3); |
||||
field = fields2[0]; |
||||
XCTAssertEqual(field.number, 2); |
||||
XCTAssertEqual(field.type, GPBUnknownFieldTypeVarint); |
||||
XCTAssertEqual(field.varint, 2); |
||||
field = fields2[1]; |
||||
XCTAssertEqual(field.number, 2); |
||||
XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed32); |
||||
XCTAssertEqual(field.fixed32, 4); |
||||
field = fields2[2]; |
||||
XCTAssertEqual(field.number, 2); |
||||
XCTAssertEqual(field.type, GPBUnknownFieldTypeLengthDelimited); |
||||
XCTAssertEqualObjects(field.lengthDelimited, DataFromCStr("bar")); |
||||
|
||||
NSArray<GPBUnknownField*>* fields3 = [ufs fields:3]; |
||||
XCTAssertEqual(fields3.count, 2); |
||||
field = fields3[0]; |
||||
XCTAssertEqual(field.number, 3); |
||||
XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed64); |
||||
XCTAssertEqual(field.fixed64, 6); |
||||
field = fields3[1]; |
||||
XCTAssertEqual(field.number, 3); |
||||
XCTAssertEqual(field.type, GPBUnknownFieldTypeGroup); |
||||
XCTAssertTrue(field.group == group2); // Exact object. |
||||
|
||||
XCTAssertNil([ufs fields:99]); // Not present |
||||
} |
||||
|
||||
- (void)testFastEnumeration { |
||||
GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; |
||||
[ufs addFieldNumber:1 varint:1]; |
||||
[ufs addFieldNumber:2 varint:2]; |
||||
[ufs addFieldNumber:1 fixed32:3]; |
||||
[ufs addFieldNumber:2 fixed32:4]; |
||||
[ufs addFieldNumber:1 fixed64:5]; |
||||
[ufs addFieldNumber:3 fixed64:6]; |
||||
[ufs addFieldNumber:1 lengthDelimited:DataFromCStr("foo")]; |
||||
[ufs addFieldNumber:2 lengthDelimited:DataFromCStr("bar")]; |
||||
GPBUnknownFields* group1 = [ufs addGroupWithFieldNumber:1]; |
||||
GPBUnknownFields* group2 = [ufs addGroupWithFieldNumber:3]; |
||||
|
||||
// The order added nothing to do with field numbers. |
||||
NSInteger loop = 0; |
||||
for (GPBUnknownField* field in ufs) { |
||||
++loop; |
||||
switch (loop) { |
||||
case 1: |
||||
XCTAssertEqual(field.number, 1); |
||||
XCTAssertEqual(field.type, GPBUnknownFieldTypeVarint); |
||||
XCTAssertEqual(field.varint, 1); |
||||
break; |
||||
case 2: |
||||
XCTAssertEqual(field.number, 2); |
||||
XCTAssertEqual(field.type, GPBUnknownFieldTypeVarint); |
||||
XCTAssertEqual(field.varint, 2); |
||||
break; |
||||
case 3: |
||||
XCTAssertEqual(field.number, 1); |
||||
XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed32); |
||||
XCTAssertEqual(field.fixed32, 3); |
||||
break; |
||||
case 4: |
||||
XCTAssertEqual(field.number, 2); |
||||
XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed32); |
||||
XCTAssertEqual(field.fixed32, 4); |
||||
break; |
||||
case 5: |
||||
XCTAssertEqual(field.number, 1); |
||||
XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed64); |
||||
XCTAssertEqual(field.fixed64, 5); |
||||
break; |
||||
case 6: |
||||
XCTAssertEqual(field.number, 3); |
||||
XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed64); |
||||
XCTAssertEqual(field.fixed64, 6); |
||||
break; |
||||
case 7: |
||||
XCTAssertEqual(field.number, 1); |
||||
XCTAssertEqual(field.type, GPBUnknownFieldTypeLengthDelimited); |
||||
XCTAssertEqualObjects(field.lengthDelimited, DataFromCStr("foo")); |
||||
break; |
||||
case 8: |
||||
XCTAssertEqual(field.number, 2); |
||||
XCTAssertEqual(field.type, GPBUnknownFieldTypeLengthDelimited); |
||||
XCTAssertEqualObjects(field.lengthDelimited, DataFromCStr("bar")); |
||||
break; |
||||
case 9: |
||||
XCTAssertEqual(field.number, 1); |
||||
XCTAssertEqual(field.type, GPBUnknownFieldTypeGroup); |
||||
XCTAssertTrue(field.group == group1); // Exact object. |
||||
break; |
||||
case 10: |
||||
XCTAssertEqual(field.number, 3); |
||||
XCTAssertEqual(field.type, GPBUnknownFieldTypeGroup); |
||||
XCTAssertTrue(field.group == group2); // Exact object. |
||||
break; |
||||
default: |
||||
XCTFail(@"Unexpected"); |
||||
break; |
||||
} |
||||
} |
||||
XCTAssertEqual(loop, 10); |
||||
} |
||||
|
||||
- (void)testDescriptions { |
||||
// Exercise description for completeness. |
||||
GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; |
||||
[ufs addFieldNumber:1 varint:1]; |
||||
[ufs addFieldNumber:2 fixed32:1]; |
||||
[ufs addFieldNumber:1 fixed64:1]; |
||||
[ufs addFieldNumber:4 lengthDelimited:DataFromCStr("foo")]; |
||||
[[ufs addGroupWithFieldNumber:5] addFieldNumber:10 varint:10]; |
||||
XCTAssertTrue(ufs.description.length > 10); |
||||
for (GPBUnknownField* field in ufs) { |
||||
XCTAssertTrue(field.description.length > 10); |
||||
} |
||||
} |
||||
|
||||
- (void)testInvalidFieldNumbers { |
||||
GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; |
||||
|
||||
XCTAssertThrowsSpecificNamed([ufs addFieldNumber:0 varint:1], NSException, |
||||
NSInvalidArgumentException); |
||||
XCTAssertThrowsSpecificNamed([ufs addFieldNumber:0 fixed32:1], NSException, |
||||
NSInvalidArgumentException); |
||||
XCTAssertThrowsSpecificNamed([ufs addFieldNumber:0 fixed64:1], NSException, |
||||
NSInvalidArgumentException); |
||||
XCTAssertThrowsSpecificNamed([ufs addFieldNumber:0 lengthDelimited:[NSData data]], NSException, |
||||
NSInvalidArgumentException); |
||||
XCTAssertThrowsSpecificNamed([ufs addGroupWithFieldNumber:0], NSException, |
||||
NSInvalidArgumentException); |
||||
|
||||
XCTAssertThrowsSpecificNamed([ufs addFieldNumber:-1 varint:1], NSException, |
||||
NSInvalidArgumentException); |
||||
XCTAssertThrowsSpecificNamed([ufs addFieldNumber:-1 fixed32:1], NSException, |
||||
NSInvalidArgumentException); |
||||
XCTAssertThrowsSpecificNamed([ufs addFieldNumber:-1 fixed64:1], NSException, |
||||
NSInvalidArgumentException); |
||||
XCTAssertThrowsSpecificNamed([ufs addFieldNumber:-1 lengthDelimited:[NSData data]], NSException, |
||||
NSInvalidArgumentException); |
||||
XCTAssertThrowsSpecificNamed([ufs addGroupWithFieldNumber:-1], NSException, |
||||
NSInvalidArgumentException); |
||||
|
||||
uint64_t varint; |
||||
uint32_t fixed32; |
||||
uint64_t fixed64; |
||||
XCTAssertThrowsSpecificNamed([ufs getFirst:0 varint:&varint], NSException, |
||||
NSInvalidArgumentException); |
||||
XCTAssertThrowsSpecificNamed([ufs getFirst:0 fixed32:&fixed32], NSException, |
||||
NSInvalidArgumentException); |
||||
XCTAssertThrowsSpecificNamed([ufs getFirst:0 fixed64:&fixed64], NSException, |
||||
NSInvalidArgumentException); |
||||
XCTAssertThrowsSpecificNamed([ufs firstLengthDelimited:0], NSException, |
||||
NSInvalidArgumentException); |
||||
XCTAssertThrowsSpecificNamed([ufs firstGroup:0], NSException, NSInvalidArgumentException); |
||||
|
||||
XCTAssertThrowsSpecificNamed([ufs getFirst:-1 varint:&varint], NSException, |
||||
NSInvalidArgumentException); |
||||
XCTAssertThrowsSpecificNamed([ufs getFirst:-1 fixed32:&fixed32], NSException, |
||||
NSInvalidArgumentException); |
||||
XCTAssertThrowsSpecificNamed([ufs getFirst:-1 fixed64:&fixed64], NSException, |
||||
NSInvalidArgumentException); |
||||
XCTAssertThrowsSpecificNamed([ufs firstLengthDelimited:-1], NSException, |
||||
NSInvalidArgumentException); |
||||
XCTAssertThrowsSpecificNamed([ufs firstGroup:-1], NSException, NSInvalidArgumentException); |
||||
XCTAssertThrowsSpecificNamed([ufs fields:0], NSException, NSInvalidArgumentException); |
||||
XCTAssertThrowsSpecificNamed([ufs fields:-1], NSException, NSInvalidArgumentException); |
||||
} |
||||
|
||||
@end |
Loading…
Reference in new issue