From fad7b78e1a09e90f5387ff414fa8cf3d6844772e Mon Sep 17 00:00:00 2001 From: Thomas Van Lenten Date: Mon, 22 Jul 2024 12:42:06 -0700 Subject: [PATCH] [ObjC] Add test around enum unknown values. PiperOrigin-RevId: 654858735 --- objectivec/Tests/GPBMessageTests.m | 52 +++++++- objectivec/Tests/unittest_objc.proto | 187 +++++++++++++++------------ 2 files changed, 152 insertions(+), 87 deletions(-) diff --git a/objectivec/Tests/GPBMessageTests.m b/objectivec/Tests/GPBMessageTests.m index d598a48b60..e70f898e3e 100644 --- a/objectivec/Tests/GPBMessageTests.m +++ b/objectivec/Tests/GPBMessageTests.m @@ -5,14 +5,14 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#import "GPBTestUtilities.h" - #import +#import "GPBArray.h" #import "GPBArray_PackagePrivate.h" #import "GPBDescriptor.h" #import "GPBDictionary_PackagePrivate.h" #import "GPBMessage_PackagePrivate.h" +#import "GPBTestUtilities.h" #import "GPBUnknownFieldSet_PackagePrivate.h" #import "GPBUnknownField_PackagePrivate.h" #import "objectivec/Tests/Unittest.pbobjc.h" @@ -2022,6 +2022,54 @@ XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:4], EnumTestMsg_MyEnum_NegTwo); } +- (void)testCloseEnumsValuesOutOfRange { + // The unknown values should all make it into the unknown fields. + EnumTestMsg *msg1 = [EnumTestMsg message]; + msg1.bar = EnumTestMsg_MyEnum_NegTwo; + msg1.baz = EnumTestMsg_MyEnum_Two; + [msg1.mumbleArray addValue:EnumTestMsg_MyEnum_Two]; + [msg1.mumbleArray addValue:EnumTestMsg_MyEnum_NegTwo]; + + NSData *data = [msg1 data]; + XCTAssertNotNil(data); + + EnumTestMsgPrime *msg2 = [EnumTestMsgPrime parseFromData:data error:NULL]; + XCTAssertNotNil(msg2); + XCTAssertEqualObjects(data, [msg2 data]); + XCTAssertFalse(msg2.hasBar); + XCTAssertFalse(msg2.hasBaz); + XCTAssertEqual(msg2.mumbleArray_Count, 0U); + + GPBUnknownFields *ufs = [[[GPBUnknownFields alloc] initFromMessage:msg2] autorelease]; + XCTAssertEqual(ufs.count, 4U); + uint64_t varint; + XCTAssertTrue([ufs getFirst:EnumTestMsg_FieldNumber_Bar varint:&varint]); + XCTAssertEqual(varint, (uint64_t)EnumTestMsg_MyEnum_NegTwo); + XCTAssertTrue([ufs getFirst:EnumTestMsg_FieldNumber_Baz varint:&varint]); + XCTAssertEqual(varint, (uint64_t)EnumTestMsg_MyEnum_Two); + NSArray *fields = [ufs fields:EnumTestMsg_FieldNumber_MumbleArray]; + XCTAssertEqual(fields.count, 2U); + XCTAssertEqual(fields[0].varint, (uint64_t)EnumTestMsg_MyEnum_Two); + XCTAssertEqual(fields[1].varint, (uint64_t)EnumTestMsg_MyEnum_NegTwo); + + GPBUnknownFieldSet *unknownFields = msg2.unknownFields; + XCTAssertNotNil(unknownFields); + XCTAssertEqual(unknownFields.countOfFields, 3U); + XCTAssertTrue([unknownFields hasField:EnumTestMsg_FieldNumber_Bar]); + XCTAssertTrue([unknownFields hasField:EnumTestMsg_FieldNumber_Baz]); + XCTAssertTrue([unknownFields hasField:EnumTestMsg_FieldNumber_MumbleArray]); + GPBUnknownField *field = [unknownFields getField:EnumTestMsg_FieldNumber_Bar]; + XCTAssertEqual(field.varintList.count, 1U); + XCTAssertEqual([field.varintList valueAtIndex:0], (uint64_t)EnumTestMsg_MyEnum_NegTwo); + field = [unknownFields getField:EnumTestMsg_FieldNumber_Baz]; + XCTAssertEqual(field.varintList.count, 1U); + XCTAssertEqual([field.varintList valueAtIndex:0], (uint64_t)EnumTestMsg_MyEnum_Two); + field = [unknownFields getField:EnumTestMsg_FieldNumber_MumbleArray]; + XCTAssertEqual(field.varintList.count, 2U); + XCTAssertEqual([field.varintList valueAtIndex:0], (uint64_t)EnumTestMsg_MyEnum_Two); + XCTAssertEqual([field.varintList valueAtIndex:1], (uint64_t)EnumTestMsg_MyEnum_NegTwo); +} + - (void)testReservedWordNaming { // names.cc has some special handing to make sure that some "reserved" objc // names get renamed in a way so they don't conflict. diff --git a/objectivec/Tests/unittest_objc.proto b/objectivec/Tests/unittest_objc.proto index 4f0e348569..b7b67fc372 100644 --- a/objectivec/Tests/unittest_objc.proto +++ b/objectivec/Tests/unittest_objc.proto @@ -7,11 +7,11 @@ syntax = "proto2"; +package objc.protobuf.tests; + import "google/protobuf/any.proto"; import "objectivec/Tests/unittest.proto"; -package objc.protobuf.tests; - // Explicit empty prefix, tests some validations code paths also. option objc_class_prefix = ""; @@ -78,143 +78,142 @@ message self { } enum autorelease { - retain = 1; - release = 2; + retain = 1; + release = 2; retainCount = 3; } // Singular // Objective C Keywords - optional bool id = 1; - optional bool _cmd = 2; + optional bool id = 1; + optional bool _cmd = 2; // super is used as submessage above - optional bool in = 4; - optional bool out = 5; - optional bool inout = 6; - optional bool bycopy = 7; - optional bool byref = 8; - optional bool oneway = 9; - optional bool self = 10; - optional bool instancetype = 11; - optional bool nullable = 12; - optional bool nonnull = 13; - optional bool nil = 14; + optional bool in = 4; + optional bool out = 5; + optional bool inout = 6; + optional bool bycopy = 7; + optional bool byref = 8; + optional bool oneway = 9; + optional bool self = 10; + optional bool instancetype = 11; + optional bool nullable = 12; + optional bool nonnull = 13; + optional bool nil = 14; // Nil and nil can't be in the same message - optional bool YES = 16; - optional bool NO = 17; - optional bool weak = 18; + optional bool YES = 16; + optional bool NO = 17; + optional bool weak = 18; // Some C/C++ Keywords - optional bool case = 30; - optional bool if = 31; - optional bool and_eq = 32; - optional bool public = 33; - optional bool private = 34; - optional bool typename = 35; - optional bool static_cast = 36; - optional bool typeof = 37; - optional bool restrict = 38; - optional bool NULL = 39; + optional bool case = 30; + optional bool if = 31; + optional bool and_eq = 32; + optional bool public = 33; + optional bool private = 34; + optional bool typename = 35; + optional bool static_cast = 36; + optional bool typeof = 37; + optional bool restrict = 38; + optional bool NULL = 39; // Some NSObject Methods - optional bool dealloc = 110; - optional bool isProxy = 111; - optional bool copy = 112; - optional bool description = 113; - optional bool zone = 114; - optional bool className = 115; - optional bool __retain_OA = 116; - optional bool CAMLType = 117; - optional bool isNSDictionary__ = 118; + optional bool dealloc = 110; + optional bool isProxy = 111; + optional bool copy = 112; + optional bool description = 113; + optional bool zone = 114; + optional bool className = 115; + optional bool __retain_OA = 116; + optional bool CAMLType = 117; + optional bool isNSDictionary__ = 118; optional bool accessibilityLabel = 119; // Some Objc "keywords" that we shouldn't // have to worry about because they // can only appear in specialized areas. - optional bool assign = 200; - optional bool getter = 201; - optional bool setter = 202; - optional bool atomic = 203; - optional bool nonatomic = 204; - optional bool strong = 205; - optional bool null_resettable = 206; - optional bool readonly = 207; + optional bool assign = 200; + optional bool getter = 201; + optional bool setter = 202; + optional bool atomic = 203; + optional bool nonatomic = 204; + optional bool strong = 205; + optional bool null_resettable = 206; + optional bool readonly = 207; // Some GPBMessage methods - optional bool clear = 300; - optional bool data = 301; - optional bool descriptor = 302; - optional bool delimitedData = 303; + optional bool clear = 300; + optional bool data = 301; + optional bool descriptor = 302; + optional bool delimitedData = 303; // Some MacTypes - optional bool Fixed = 400; - optional bool Point = 401; - optional bool FixedPoint = 402; - optional bool Style = 403; + optional bool Fixed = 400; + optional bool Point = 401; + optional bool FixedPoint = 402; + optional bool Style = 403; // C/C++ reserved identifiers - optional bool _Generic = 500; - optional bool __block = 501; + optional bool _Generic = 500; + optional bool __block = 501; // Try a keyword as a type - optional autorelease SubEnum = 1000; + optional autorelease SubEnum = 1000; optional group New = 2000 { - optional string copy = 1; + optional string copy = 1; } optional group MutableCopy = 2001 { optional int32 extensionRegistry = 1; } extensions 3000 to 3999; - } enum retain { - count = 4; - initialized = 5; + count = 4; + initialized = 5; serializedSize = 6; } message ObjCPropertyNaming { // Test that the properties properly get things all caps. - optional string url = 1; + optional string url = 1; optional string thumbnail_url = 2; - optional string url_foo = 3; + optional string url_foo = 3; optional string some_url_blah = 4; - optional string http = 5; - optional string https = 6; + optional string http = 5; + optional string https = 6; // This one doesn't. - repeated string urls = 7; + repeated string urls = 7; } // EnumValueShortName: The short names shouldn't get suffixes/prefixes. enum Foo { SERIALIZED_SIZE = 1; - SIZE = 2; - OTHER = 3; + SIZE = 2; + OTHER = 3; } // EnumValueShortName: The enum name gets a prefix. enum Category { - RED = 1; + RED = 1; BLUE = 2; } // EnumValueShortName: Twist case, full name gets PB, but the short names // should still end up correct. enum Time { - BASE = 1; - RECORD = 2; - SOMETHING_ELSE = 3; + BASE = 1; + RECORD = 2; + SOMETHING_ELSE = 3; } extend self { - repeated int32 debugDescription = 3000 [packed = true]; - repeated int64 finalize = 3001 [packed = true]; - repeated uint32 hash = 3002 [packed = true]; - repeated uint64 classForCoder = 3003 [packed = true]; - repeated sint32 byref = 3004 [packed = true]; + repeated int32 debugDescription = 3000 [packed = true]; + repeated int64 finalize = 3001 [packed = true]; + repeated uint32 hash = 3002 [packed = true]; + repeated uint64 classForCoder = 3003 [packed = true]; + repeated sint32 byref = 3004 [packed = true]; } // Test handing of fields that start with init*. @@ -700,13 +699,17 @@ message JustToScopeExtensions { repeated string mutableCopy_val_lower_complex_repeated = 2711; repeated string mutableCopy_Val_upper_complex_repeated = 2712; - repeated string mutableCopyvalue_lower_no_underscore_complex_repeated = 2713; - repeated string mutableCopyValue_upper_no_underscore_complex_repeated = 2714; + repeated string mutableCopyvalue_lower_no_underscore_complex_repeated = + 2713; + repeated string mutableCopyValue_upper_no_underscore_complex_repeated = + 2714; repeated int32 mutableCopy_val_lower_primitive_repeated = 2715; repeated int32 mutableCopy_Val_upper_primitive_repeated = 2716; - repeated int32 mutableCopyvalue_lower_no_underscore_primitive_repeated = 2717; - repeated int32 mutableCopyValue_upper_no_underscore_primitive_repeated = 2718; + repeated int32 mutableCopyvalue_lower_no_underscore_primitive_repeated = + 2717; + repeated int32 mutableCopyValue_upper_no_underscore_primitive_repeated = + 2718; repeated self mutableCopy_val_lower_message_repeated = 2719; repeated self mutableCopy_Val_upper_message_repeated = 2720; @@ -781,9 +784,9 @@ message ObjcWeirdDefaults { // Used to confirm negative enum values work as expected. message EnumTestMsg { enum MyEnum { - ZERO = 0; - ONE = 1; - TWO = 2; + ZERO = 0; + ONE = 1; + TWO = 2; NEG_ONE = -1; NEG_TWO = -2; } @@ -794,6 +797,20 @@ message EnumTestMsg { repeated MyEnum mumble = 4; } +message EnumTestMsgPrime { + enum MyEnumPrime { + ZERO = 0; + ONE = 1; + NEG_ONE = -1; + // Lacks 2, -2. + } + optional MyEnumPrime foo = 1; + optional MyEnumPrime bar = 2 [default = ONE]; + optional MyEnumPrime baz = 3 [default = NEG_ONE]; + + repeated MyEnumPrime mumble = 4; +} + // Test case for https://github.com/protocolbuffers/protobuf/issues/1453 // Message with no explicit defaults, but a non zero default for an enum. message MessageWithOneBasedEnum {