diff options
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | docs/third_party.md | 1 | ||||
-rwxr-xr-x | objectivec/DevTools/full_mac_build.sh | 8 | ||||
-rw-r--r-- | objectivec/GPBArray.m | 4 | ||||
-rw-r--r-- | objectivec/GPBDictionary.m | 8 | ||||
-rw-r--r-- | objectivec/GPBMessage.m | 16 | ||||
-rw-r--r-- | objectivec/GPBUtilities.m | 16 | ||||
-rw-r--r-- | objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj | 4 | ||||
-rw-r--r-- | objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj | 4 | ||||
-rw-r--r-- | objectivec/Tests/GPBArrayTests.m | 173 | ||||
-rw-r--r-- | objectivec/Tests/GPBDictionaryTests.m | 186 | ||||
-rw-r--r-- | objectivec/Tests/GPBMessageTests.m | 31 | ||||
-rw-r--r-- | src/google/protobuf/arena_nc.cc | 45 | ||||
-rw-r--r-- | src/google/protobuf/arena_nc_test.py | 61 | ||||
-rw-r--r-- | src/google/protobuf/compiler/js/embed.cc | 2 |
15 files changed, 437 insertions, 123 deletions
diff --git a/Makefile.am b/Makefile.am index 4ece5217..5ade9d2b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -525,6 +525,7 @@ objectivec_EXTRA_DIST= \ objectivec/Tests/GPBDictionaryTests+String.m \ objectivec/Tests/GPBDictionaryTests+UInt32.m \ objectivec/Tests/GPBDictionaryTests+UInt64.m \ + objectivec/Tests/GPBDictionaryTests.m \ objectivec/Tests/GPBDictionaryTests.pddm \ objectivec/Tests/GPBMessageTests+Merge.m \ objectivec/Tests/GPBMessageTests+Runtime.m \ diff --git a/docs/third_party.md b/docs/third_party.md index 0bbde914..160090ce 100644 --- a/docs/third_party.md +++ b/docs/third_party.md @@ -32,6 +32,7 @@ These are projects we know about implementing Protocol Buffers for other program * Delphi: http://sourceforge.net/projects/protobuf-delphi/ * Delphi: http://fundementals.sourceforge.net/dl.html * Elixir: https://github.com/jeremyong/exprotoc +* Elm: https://github.com/tiziano88/elm-protobuf * Erlang: http://github.com/ngerakines/erlang_protobuffs/tree/master * Erlang: http://piqi.org/ * Erlang: https://code.google.com/p/protoc-gen-erl/ diff --git a/objectivec/DevTools/full_mac_build.sh b/objectivec/DevTools/full_mac_build.sh index ef8fb740..ea9fd273 100755 --- a/objectivec/DevTools/full_mac_build.sh +++ b/objectivec/DevTools/full_mac_build.sh @@ -265,6 +265,14 @@ if [[ "${DO_XCODE_IOS_TESTS}" == "yes" ]] ; then -destination "platform=iOS Simulator,name=iPad Pro (9.7 inch),OS=10.1" # 64bit ) ;; + 8.2* ) + XCODEBUILD_TEST_BASE_IOS+=( + -destination "platform=iOS Simulator,name=iPhone 4s,OS=8.1" # 32bit + -destination "platform=iOS Simulator,name=iPhone 7,OS=10.2" # 64bit + -destination "platform=iOS Simulator,name=iPad 2,OS=8.1" # 32bit + -destination "platform=iOS Simulator,name=iPad Pro (9.7 inch),OS=10.2" # 64bit + ) + ;; * ) echo "Time to update the simulator targets for Xcode ${XCODE_VERSION}" exit 2 diff --git a/objectivec/GPBArray.m b/objectivec/GPBArray.m index ae57747d..f401631d 100644 --- a/objectivec/GPBArray.m +++ b/objectivec/GPBArray.m @@ -2519,14 +2519,14 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { - (id)copyWithZone:(NSZone *)zone { if (_array == nil) { - _array = [[NSMutableArray alloc] init]; + return [[NSMutableArray allocWithZone:zone] init]; } return [_array copyWithZone:zone]; } - (id)mutableCopyWithZone:(NSZone *)zone { if (_array == nil) { - _array = [[NSMutableArray alloc] init]; + return [[NSMutableArray allocWithZone:zone] init]; } return [_array mutableCopyWithZone:zone]; } diff --git a/objectivec/GPBDictionary.m b/objectivec/GPBDictionary.m index fd8bd1ce..1c67c680 100644 --- a/objectivec/GPBDictionary.m +++ b/objectivec/GPBDictionary.m @@ -13579,22 +13579,26 @@ void GPBDictionaryReadEntry(id mapDictionary, - (id)copyWithZone:(NSZone *)zone { if (_dictionary == nil) { - _dictionary = [[NSMutableDictionary alloc] init]; + return [[NSMutableDictionary allocWithZone:zone] init]; } return [_dictionary copyWithZone:zone]; } - (id)mutableCopyWithZone:(NSZone *)zone { if (_dictionary == nil) { - _dictionary = [[NSMutableDictionary alloc] init]; + return [[NSMutableDictionary allocWithZone:zone] init]; } return [_dictionary mutableCopyWithZone:zone]; } +// Not really needed, but subscripting is likely common enough it doesn't hurt +// to ensure it goes directly to the real NSMutableDictionary. - (id)objectForKeyedSubscript:(id)key { return [_dictionary objectForKeyedSubscript:key]; } +// Not really needed, but subscripting is likely common enough it doesn't hurt +// to ensure it goes directly to the real NSMutableDictionary. - (void)setObject:(id)obj forKeyedSubscript:(id<NSCopying>)key { if (_dictionary == nil) { _dictionary = [[NSMutableDictionary alloc] init]; diff --git a/objectivec/GPBMessage.m b/objectivec/GPBMessage.m index 4a6f0612..9660f1ed 100644 --- a/objectivec/GPBMessage.m +++ b/objectivec/GPBMessage.m @@ -1023,9 +1023,11 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { if (arrayOrMap) { if (field.fieldType == GPBFieldTypeRepeated) { if (GPBFieldDataTypeIsObject(field)) { - GPBAutocreatedArray *autoArray = arrayOrMap; - if (autoArray->_autocreator == self) { - autoArray->_autocreator = nil; + if ([arrayOrMap isKindOfClass:[GPBAutocreatedArray class]]) { + GPBAutocreatedArray *autoArray = arrayOrMap; + if (autoArray->_autocreator == self) { + autoArray->_autocreator = nil; + } } } else { // Type doesn't matter, it is a GPB*Array. @@ -1037,9 +1039,11 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { } else { if ((field.mapKeyDataType == GPBDataTypeString) && GPBFieldDataTypeIsObject(field)) { - GPBAutocreatedDictionary *autoDict = arrayOrMap; - if (autoDict->_autocreator == self) { - autoDict->_autocreator = nil; + if ([arrayOrMap isKindOfClass:[GPBAutocreatedDictionary class]]) { + GPBAutocreatedDictionary *autoDict = arrayOrMap; + if (autoDict->_autocreator == self) { + autoDict->_autocreator = nil; + } } } else { // Type doesn't matter, it is a GPB*Dictionary. diff --git a/objectivec/GPBUtilities.m b/objectivec/GPBUtilities.m index d4538598..68aadb77 100644 --- a/objectivec/GPBUtilities.m +++ b/objectivec/GPBUtilities.m @@ -408,9 +408,11 @@ void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, if (field.fieldType == GPBFieldTypeRepeated) { // If the old array was autocreated by us, then clear it. if (GPBDataTypeIsObject(fieldType)) { - GPBAutocreatedArray *autoArray = oldValue; - if (autoArray->_autocreator == self) { - autoArray->_autocreator = nil; + if ([oldValue isKindOfClass:[GPBAutocreatedArray class]]) { + GPBAutocreatedArray *autoArray = oldValue; + if (autoArray->_autocreator == self) { + autoArray->_autocreator = nil; + } } } else { // Type doesn't matter, it is a GPB*Array. @@ -423,9 +425,11 @@ void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, // If the old map was autocreated by us, then clear it. if ((field.mapKeyDataType == GPBDataTypeString) && GPBDataTypeIsObject(fieldType)) { - GPBAutocreatedDictionary *autoDict = oldValue; - if (autoDict->_autocreator == self) { - autoDict->_autocreator = nil; + if ([oldValue isKindOfClass:[GPBAutocreatedDictionary class]]) { + GPBAutocreatedDictionary *autoDict = oldValue; + if (autoDict->_autocreator == self) { + autoDict->_autocreator = nil; + } } } else { // Type doesn't matter, it is a GPB*Dictionary. diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj index 7ce5d54f..919d0076 100644 --- a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj +++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj @@ -57,6 +57,7 @@ F47476E51D21A524007C7B1A /* Duration.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B4248D41A92826400BC1EC6 /* Duration.pbobjc.m */; }; F47476E61D21A524007C7B1A /* Timestamp.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B4248D61A92826400BC1EC6 /* Timestamp.pbobjc.m */; }; F4B51B1E1BBC610700744318 /* GPBObjectiveCPlusPlusTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4B51B1D1BBC610700744318 /* GPBObjectiveCPlusPlusTest.mm */; }; + F4C4B9E41E1D976300D3B61D /* GPBDictionaryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F4C4B9E21E1D974F00D3B61D /* GPBDictionaryTests.m */; }; F4E675971B21D0000054530B /* Any.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675871B21D0000054530B /* Any.pbobjc.m */; }; F4E675991B21D0000054530B /* Api.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675891B21D0000054530B /* Api.pbobjc.m */; }; F4E6759B1B21D0000054530B /* Empty.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E6758B1B21D0000054530B /* Empty.pbobjc.m */; }; @@ -187,6 +188,7 @@ F4B6B8B21A9CCBDA00892426 /* GPBUnknownFieldSet_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFieldSet_PackagePrivate.h; sourceTree = "<group>"; }; F4B6B8B61A9CD1DE00892426 /* GPBExtensionInternals.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBExtensionInternals.h; sourceTree = "<group>"; }; F4B6B8B81A9CD1DE00892426 /* GPBRootObject_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRootObject_PackagePrivate.h; sourceTree = "<group>"; }; + F4C4B9E21E1D974F00D3B61D /* GPBDictionaryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDictionaryTests.m; sourceTree = "<group>"; }; F4CF31701B162ED800BD9B06 /* unittest_objc_startup.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_objc_startup.proto; sourceTree = "<group>"; }; F4E675861B21D0000054530B /* Any.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Any.pbobjc.h; path = google/protobuf/Any.pbobjc.h; sourceTree = "<group>"; }; F4E675871B21D0000054530B /* Any.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Any.pbobjc.m; path = google/protobuf/Any.pbobjc.m; sourceTree = "<group>"; }; @@ -393,6 +395,7 @@ 7461B69D0F94FDF800A0C422 /* GPBCodedOuputStreamTests.m */, 5102DABB1891A052002037B6 /* GPBConcurrencyTests.m */, F4353D1C1AB8822D005A6198 /* GPBDescriptorTests.m */, + F4C4B9E21E1D974F00D3B61D /* GPBDictionaryTests.m */, F4353D2C1AC06F10005A6198 /* GPBDictionaryTests.pddm */, F4353D2D1AC06F10005A6198 /* GPBDictionaryTests+Bool.m */, F4353D2E1AC06F10005A6198 /* GPBDictionaryTests+Int32.m */, @@ -677,6 +680,7 @@ F4353D371AC06F10005A6198 /* GPBDictionaryTests+String.m in Sources */, F4353D381AC06F10005A6198 /* GPBDictionaryTests+UInt32.m in Sources */, 8BBEA4B7147C727D00C4ADB7 /* GPBUtilitiesTests.m in Sources */, + F4C4B9E41E1D976300D3B61D /* GPBDictionaryTests.m in Sources */, 8BBEA4B8147C727D00C4ADB7 /* GPBWireFormatTests.m in Sources */, 8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */, 8B8B615D17DF7056002EE618 /* GPBARCUnittestProtos.m in Sources */, diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj index 5f599719..64fc45c0 100644 --- a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj +++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj @@ -65,6 +65,7 @@ F47476E91D21A537007C7B1A /* Duration.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B4248DE1A929C7D00BC1EC6 /* Duration.pbobjc.m */; }; F47476EA1D21A537007C7B1A /* Timestamp.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B4248E01A929C7D00BC1EC6 /* Timestamp.pbobjc.m */; }; F4B51B1C1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4B51B1B1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm */; }; + F4C4B9E71E1D97BF00D3B61D /* GPBDictionaryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F4C4B9E51E1D97BB00D3B61D /* GPBDictionaryTests.m */; }; F4E675D01B21D1620054530B /* Any.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675B71B21D1440054530B /* Any.pbobjc.m */; }; F4E675D11B21D1620054530B /* Api.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675B91B21D1440054530B /* Api.pbobjc.m */; }; F4E675D21B21D1620054530B /* Empty.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675BC1B21D1440054530B /* Empty.pbobjc.m */; }; @@ -209,6 +210,7 @@ F4B6B8B11A9CCBBB00892426 /* GPBUnknownFieldSet_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFieldSet_PackagePrivate.h; sourceTree = "<group>"; }; F4B6B8B31A9CD1C600892426 /* GPBExtensionInternals.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBExtensionInternals.h; sourceTree = "<group>"; }; F4B6B8B51A9CD1C600892426 /* GPBRootObject_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRootObject_PackagePrivate.h; sourceTree = "<group>"; }; + F4C4B9E51E1D97BB00D3B61D /* GPBDictionaryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDictionaryTests.m; sourceTree = "<group>"; }; F4CF31711B162EF500BD9B06 /* unittest_objc_startup.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_objc_startup.proto; sourceTree = "<group>"; }; F4E675B61B21D1440054530B /* Any.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Any.pbobjc.h; path = google/protobuf/Any.pbobjc.h; sourceTree = "<group>"; }; F4E675B71B21D1440054530B /* Any.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Any.pbobjc.m; path = google/protobuf/Any.pbobjc.m; sourceTree = "<group>"; }; @@ -431,6 +433,7 @@ 7461B69D0F94FDF800A0C422 /* GPBCodedOuputStreamTests.m */, 5102DABB1891A052002037B6 /* GPBConcurrencyTests.m */, F4353D1E1AB88243005A6198 /* GPBDescriptorTests.m */, + F4C4B9E51E1D97BB00D3B61D /* GPBDictionaryTests.m */, F4353D3A1AC06F31005A6198 /* GPBDictionaryTests.pddm */, F4353D3B1AC06F31005A6198 /* GPBDictionaryTests+Bool.m */, F4353D3C1AC06F31005A6198 /* GPBDictionaryTests+Int32.m */, @@ -773,6 +776,7 @@ F4353D451AC06F31005A6198 /* GPBDictionaryTests+String.m in Sources */, F4353D461AC06F31005A6198 /* GPBDictionaryTests+UInt32.m in Sources */, 8BBEA4B7147C727D00C4ADB7 /* GPBUtilitiesTests.m in Sources */, + F4C4B9E71E1D97BF00D3B61D /* GPBDictionaryTests.m in Sources */, 8BBEA4B8147C727D00C4ADB7 /* GPBWireFormatTests.m in Sources */, 8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */, 8B8B615D17DF7056002EE618 /* GPBARCUnittestProtos.m in Sources */, diff --git a/objectivec/Tests/GPBArrayTests.m b/objectivec/Tests/GPBArrayTests.m index 0fb15e40..31f75501 100644 --- a/objectivec/Tests/GPBArrayTests.m +++ b/objectivec/Tests/GPBArrayTests.m @@ -32,6 +32,7 @@ #import <XCTest/XCTest.h> #import "GPBArray.h" +#import "GPBArray_PackagePrivate.h" #import "GPBTestUtilities.h" @@ -3436,3 +3437,175 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { } @end + +#pragma mark - GPBAutocreatedArray Tests + +// These are hand written tests to double check some behaviors of the +// GPBAutocreatedArray. + +// NOTE: GPBAutocreatedArray is private to the library, users of the library +// should never have to directly deal with this class. + +@interface GPBAutocreatedArrayTests : XCTestCase +@end + +@implementation GPBAutocreatedArrayTests + +- (void)testEquality { + GPBAutocreatedArray *array = [[GPBAutocreatedArray alloc] init]; + + XCTAssertTrue([array isEqual:@[]]); + XCTAssertTrue([array isEqualToArray:@[]]); + + XCTAssertFalse([array isEqual:@[ @"foo" ]]); + XCTAssertFalse([array isEqualToArray:@[ @"foo" ]]); + + [array addObject:@"foo"]; + + XCTAssertFalse([array isEqual:@[]]); + XCTAssertFalse([array isEqualToArray:@[]]); + XCTAssertTrue([array isEqual:@[ @"foo" ]]); + XCTAssertTrue([array isEqualToArray:@[ @"foo" ]]); + XCTAssertFalse([array isEqual:@[ @"bar" ]]); + XCTAssertFalse([array isEqualToArray:@[ @"bar" ]]); + + GPBAutocreatedArray *array2 = [[GPBAutocreatedArray alloc] init]; + + XCTAssertFalse([array isEqual:array2]); + XCTAssertFalse([array isEqualToArray:array2]); + + [array2 addObject:@"bar"]; + XCTAssertFalse([array isEqual:array2]); + XCTAssertFalse([array isEqualToArray:array2]); + + [array2 replaceObjectAtIndex:0 withObject:@"foo"]; + XCTAssertTrue([array isEqual:array2]); + XCTAssertTrue([array isEqualToArray:array2]); + + [array2 release]; + [array release]; +} + +- (void)testCopy { + { + GPBAutocreatedArray *array = [[GPBAutocreatedArray alloc] init]; + + NSArray *cpy = [array copy]; + XCTAssertTrue(cpy != array); // Ptr compare + XCTAssertTrue([cpy isKindOfClass:[NSArray class]]); + XCTAssertFalse([cpy isKindOfClass:[GPBAutocreatedArray class]]); + XCTAssertEqual(cpy.count, (NSUInteger)0); + + NSArray *cpy2 = [array copy]; + XCTAssertTrue(cpy2 != array); // Ptr compare + // Can't compare cpy and cpy2 because NSArray has a singleton empty + // array it uses, so the ptrs are the same. + XCTAssertTrue([cpy2 isKindOfClass:[NSArray class]]); + XCTAssertFalse([cpy2 isKindOfClass:[GPBAutocreatedArray class]]); + XCTAssertEqual(cpy2.count, (NSUInteger)0); + + [cpy2 release]; + [cpy release]; + [array release]; + } + + { + GPBAutocreatedArray *array = [[GPBAutocreatedArray alloc] init]; + + NSMutableArray *cpy = [array mutableCopy]; + XCTAssertTrue(cpy != array); // Ptr compare + XCTAssertTrue([cpy isKindOfClass:[NSMutableArray class]]); + XCTAssertFalse([cpy isKindOfClass:[GPBAutocreatedArray class]]); + XCTAssertEqual(cpy.count, (NSUInteger)0); + + NSMutableArray *cpy2 = [array mutableCopy]; + XCTAssertTrue(cpy2 != array); // Ptr compare + XCTAssertTrue(cpy2 != cpy); // Ptr compare + XCTAssertTrue([cpy2 isKindOfClass:[NSMutableArray class]]); + XCTAssertFalse([cpy2 isKindOfClass:[GPBAutocreatedArray class]]); + XCTAssertEqual(cpy2.count, (NSUInteger)0); + + [cpy2 release]; + [cpy release]; + [array release]; + } + + { + GPBAutocreatedArray *array = [[GPBAutocreatedArray alloc] init]; + [array addObject:@"foo"]; + [array addObject:@"bar"]; + + NSArray *cpy = [array copy]; + XCTAssertTrue(cpy != array); // Ptr compare + XCTAssertTrue([cpy isKindOfClass:[NSArray class]]); + XCTAssertFalse([cpy isKindOfClass:[GPBAutocreatedArray class]]); + XCTAssertEqual(cpy.count, (NSUInteger)2); + XCTAssertEqualObjects(cpy[0], @"foo"); + XCTAssertEqualObjects(cpy[1], @"bar"); + + NSArray *cpy2 = [array copy]; + XCTAssertTrue(cpy2 != array); // Ptr compare + XCTAssertTrue(cpy2 != cpy); // Ptr compare + XCTAssertTrue([cpy2 isKindOfClass:[NSArray class]]); + XCTAssertFalse([cpy2 isKindOfClass:[GPBAutocreatedArray class]]); + XCTAssertEqual(cpy2.count, (NSUInteger)2); + XCTAssertEqualObjects(cpy2[0], @"foo"); + XCTAssertEqualObjects(cpy2[1], @"bar"); + + [cpy2 release]; + [cpy release]; + [array release]; + } + + { + GPBAutocreatedArray *array = [[GPBAutocreatedArray alloc] init]; + [array addObject:@"foo"]; + [array addObject:@"bar"]; + + NSMutableArray *cpy = [array mutableCopy]; + XCTAssertTrue(cpy != array); // Ptr compare + XCTAssertTrue([cpy isKindOfClass:[NSArray class]]); + XCTAssertFalse([cpy isKindOfClass:[GPBAutocreatedArray class]]); + XCTAssertEqual(cpy.count, (NSUInteger)2); + XCTAssertEqualObjects(cpy[0], @"foo"); + XCTAssertEqualObjects(cpy[1], @"bar"); + + NSMutableArray *cpy2 = [array mutableCopy]; + XCTAssertTrue(cpy2 != array); // Ptr compare + XCTAssertTrue(cpy2 != cpy); // Ptr compare + XCTAssertTrue([cpy2 isKindOfClass:[NSArray class]]); + XCTAssertFalse([cpy2 isKindOfClass:[GPBAutocreatedArray class]]); + XCTAssertEqual(cpy2.count, (NSUInteger)2); + XCTAssertEqualObjects(cpy2[0], @"foo"); + XCTAssertEqualObjects(cpy2[1], @"bar"); + + [cpy2 release]; + [cpy release]; + [array release]; + } +} + +- (void)testIndexedSubscriptSupport { + // The base NSArray/NSMutableArray behaviors for *IndexedSubscript methods + // should still work via the methods that one has to override to make an + // NSMutableArray subclass. i.e. - this should "just work" and if these + // crash/fail, then something is wrong in how NSMutableArray is subclassed. + + GPBAutocreatedArray *array = [[GPBAutocreatedArray alloc] init]; + + [array addObject:@"foo"]; + [array addObject:@"bar"]; + XCTAssertEqual(array.count, (NSUInteger)2); + XCTAssertEqualObjects(array[0], @"foo"); + XCTAssertEqualObjects(array[1], @"bar"); + array[0] = @"foo2"; + array[2] = @"baz"; + XCTAssertEqual(array.count, (NSUInteger)3); + XCTAssertEqualObjects(array[0], @"foo2"); + XCTAssertEqualObjects(array[1], @"bar"); + XCTAssertEqualObjects(array[2], @"baz"); + + [array release]; +} + +@end diff --git a/objectivec/Tests/GPBDictionaryTests.m b/objectivec/Tests/GPBDictionaryTests.m new file mode 100644 index 00000000..52b4b328 --- /dev/null +++ b/objectivec/Tests/GPBDictionaryTests.m @@ -0,0 +1,186 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2017 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import <Foundation/Foundation.h> +#import <XCTest/XCTest.h> + +#import "GPBDictionary.h" +#import "GPBDictionary_PackagePrivate.h" + +#import "GPBTestUtilities.h" + +#pragma mark - GPBAutocreatedDictionary Tests + +// These are hand written tests to double check some behaviors of the +// GPBAutocreatedDictionary. The GPBDictionary+[type]Tests files are generate +// tests. + +// NOTE: GPBAutocreatedDictionary is private to the library, users of the +// library should never have to directly deal with this class. + +@interface GPBAutocreatedDictionaryTests : XCTestCase +@end + +@implementation GPBAutocreatedDictionaryTests + +- (void)testEquality { + GPBAutocreatedDictionary *dict = [[GPBAutocreatedDictionary alloc] init]; + + XCTAssertTrue([dict isEqual:@{}]); + XCTAssertTrue([dict isEqualToDictionary:@{}]); + + XCTAssertFalse([dict isEqual:@{ @"foo" : @"bar" }]); + XCTAssertFalse([dict isEqualToDictionary:@{ @"foo" : @"bar" }]); + + [dict setObject:@"bar" forKey:@"foo"]; + + XCTAssertFalse([dict isEqual:@{}]); + XCTAssertFalse([dict isEqualToDictionary:@{}]); + XCTAssertTrue([dict isEqual:@{ @"foo" : @"bar" }]); + XCTAssertTrue([dict isEqualToDictionary:@{ @"foo" : @"bar" }]); + XCTAssertFalse([dict isEqual:@{ @"bar" : @"baz" }]); + XCTAssertFalse([dict isEqualToDictionary:@{ @"bar" : @"baz" }]); + + GPBAutocreatedDictionary *dict2 = [[GPBAutocreatedDictionary alloc] init]; + + XCTAssertFalse([dict isEqual:dict2]); + XCTAssertFalse([dict isEqualToDictionary:dict2]); + + [dict2 setObject:@"mumble" forKey:@"foo"]; + XCTAssertFalse([dict isEqual:dict2]); + XCTAssertFalse([dict isEqualToDictionary:dict2]); + + [dict2 setObject:@"bar" forKey:@"foo"]; + XCTAssertTrue([dict isEqual:dict2]); + XCTAssertTrue([dict isEqualToDictionary:dict2]); + + [dict2 release]; + [dict release]; +} + +- (void)testCopy { + { + GPBAutocreatedDictionary *dict = [[GPBAutocreatedDictionary alloc] init]; + + NSDictionary *cpy = [dict copy]; + XCTAssertTrue(cpy != dict); // Ptr compare + XCTAssertTrue([cpy isKindOfClass:[NSDictionary class]]); + XCTAssertFalse([cpy isKindOfClass:[GPBAutocreatedDictionary class]]); + XCTAssertEqual(cpy.count, (NSUInteger)0); + + NSDictionary *cpy2 = [dict copy]; + XCTAssertTrue(cpy2 != dict); // Ptr compare + XCTAssertTrue(cpy2 != cpy); // Ptr compare + XCTAssertTrue([cpy2 isKindOfClass:[NSDictionary class]]); + XCTAssertFalse([cpy2 isKindOfClass:[GPBAutocreatedDictionary class]]); + XCTAssertEqual(cpy2.count, (NSUInteger)0); + + [cpy2 release]; + [cpy release]; + [dict release]; + } + + { + GPBAutocreatedDictionary *dict = [[GPBAutocreatedDictionary alloc] init]; + + NSMutableDictionary *cpy = [dict mutableCopy]; + XCTAssertTrue(cpy != dict); // Ptr compare + XCTAssertTrue([cpy isKindOfClass:[NSMutableDictionary class]]); + XCTAssertFalse([cpy isKindOfClass:[GPBAutocreatedDictionary class]]); + XCTAssertEqual(cpy.count, (NSUInteger)0); + + NSMutableDictionary *cpy2 = [dict mutableCopy]; + XCTAssertTrue(cpy2 != dict); // Ptr compare + XCTAssertTrue(cpy2 != cpy); // Ptr compare + XCTAssertTrue([cpy2 isKindOfClass:[NSMutableDictionary class]]); + XCTAssertFalse([cpy2 isKindOfClass:[GPBAutocreatedDictionary class]]); + XCTAssertEqual(cpy2.count, (NSUInteger)0); + + [cpy2 release]; + [cpy release]; + [dict release]; + } + + { + GPBAutocreatedDictionary *dict = [[GPBAutocreatedDictionary alloc] init]; + dict[@"foo"] = @"bar"; + dict[@"baz"] = @"mumble"; + + NSDictionary *cpy = [dict copy]; + XCTAssertTrue(cpy != dict); // Ptr compare + XCTAssertTrue([cpy isKindOfClass:[NSDictionary class]]); + XCTAssertFalse([cpy isKindOfClass:[GPBAutocreatedDictionary class]]); + XCTAssertEqual(cpy.count, (NSUInteger)2); + XCTAssertEqualObjects(cpy[@"foo"], @"bar"); + XCTAssertEqualObjects(cpy[@"baz"], @"mumble"); + + NSDictionary *cpy2 = [dict copy]; + XCTAssertTrue(cpy2 != dict); // Ptr compare + XCTAssertTrue(cpy2 != cpy); // Ptr compare + XCTAssertTrue([cpy2 isKindOfClass:[NSDictionary class]]); + XCTAssertFalse([cpy2 isKindOfClass:[GPBAutocreatedDictionary class]]); + XCTAssertEqual(cpy2.count, (NSUInteger)2); + XCTAssertEqualObjects(cpy2[@"foo"], @"bar"); + XCTAssertEqualObjects(cpy2[@"baz"], @"mumble"); + + [cpy2 release]; + [cpy release]; + [dict release]; + } + + { + GPBAutocreatedDictionary *dict = [[GPBAutocreatedDictionary alloc] init]; + dict[@"foo"] = @"bar"; + dict[@"baz"] = @"mumble"; + + NSMutableDictionary *cpy = [dict mutableCopy]; + XCTAssertTrue(cpy != dict); // Ptr compare + XCTAssertTrue([cpy isKindOfClass:[NSMutableDictionary class]]); + XCTAssertFalse([cpy isKindOfClass:[GPBAutocreatedDictionary class]]); + XCTAssertEqual(cpy.count, (NSUInteger)2); + XCTAssertEqualObjects(cpy[@"foo"], @"bar"); + XCTAssertEqualObjects(cpy[@"baz"], @"mumble"); + + NSMutableDictionary *cpy2 = [dict mutableCopy]; + XCTAssertTrue(cpy2 != dict); // Ptr compare + XCTAssertTrue(cpy2 != cpy); // Ptr compare + XCTAssertTrue([cpy2 isKindOfClass:[NSMutableDictionary class]]); + XCTAssertFalse([cpy2 isKindOfClass:[GPBAutocreatedDictionary class]]); + XCTAssertEqual(cpy2.count, (NSUInteger)2); + XCTAssertEqualObjects(cpy2[@"foo"], @"bar"); + XCTAssertEqualObjects(cpy2[@"baz"], @"mumble"); + + [cpy2 release]; + [cpy release]; + [dict release]; + } +} + +@end diff --git a/objectivec/Tests/GPBMessageTests.m b/objectivec/Tests/GPBMessageTests.m index a3c5a6b4..c15535c5 100644 --- a/objectivec/Tests/GPBMessageTests.m +++ b/objectivec/Tests/GPBMessageTests.m @@ -1082,6 +1082,20 @@ [repeatedStringArray release]; } +- (void)testSetOverAutocreatedArrayAndSetAgain { + // Ensure when dealing with replacing an array it is handled being either + // an autocreated one or a straight NSArray. + + // The real test here is that nothing crashes while doing the work. + TestAllTypes *message = [TestAllTypes message]; + [message.repeatedStringArray addObject:@"foo"]; + XCTAssertEqual(message.repeatedStringArray_Count, (NSUInteger)1); + message.repeatedStringArray = [NSMutableArray arrayWithObjects:@"bar", @"bar2", nil]; + XCTAssertEqual(message.repeatedStringArray_Count, (NSUInteger)2); + message.repeatedStringArray = [NSMutableArray arrayWithObject:@"baz"]; + XCTAssertEqual(message.repeatedStringArray_Count, (NSUInteger)1); +} + - (void)testReplaceAutocreatedArray { // Replacing array should orphan the old one and cause its creator to become // visible. @@ -1281,6 +1295,23 @@ [strToStr release]; } +- (void)testSetOverAutocreatedMapAndSetAgain { + // Ensure when dealing with replacing a map it is handled being either + // an autocreated one or a straight NSDictionary. + + // The real test here is that nothing crashes while doing the work. + TestRecursiveMessageWithRepeatedField *message = + [TestRecursiveMessageWithRepeatedField message]; + message.strToStr[@"foo"] = @"bar"; + XCTAssertEqual(message.strToStr_Count, (NSUInteger)1); + message.strToStr = + [NSMutableDictionary dictionaryWithObjectsAndKeys:@"bar", @"key1", @"baz", @"key2", nil]; + XCTAssertEqual(message.strToStr_Count, (NSUInteger)2); + message.strToStr = + [NSMutableDictionary dictionaryWithObject:@"baz" forKey:@"mumble"]; + XCTAssertEqual(message.strToStr_Count, (NSUInteger)1); +} + - (void)testReplaceAutocreatedMap { // Replacing map should orphan the old one and cause its creator to become // visible. diff --git a/src/google/protobuf/arena_nc.cc b/src/google/protobuf/arena_nc.cc deleted file mode 100644 index f2f08427..00000000 --- a/src/google/protobuf/arena_nc.cc +++ /dev/null @@ -1,45 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Negative compilation test for arena usage. - -#include <google/protobuf/arena.h> -#include <google/protobuf/unittest.pb.h> - -#ifdef TEST_ARENA_PRIVATE_CONSTRUCTOR - -namespace google { -void ArenaPrivateConstructor() { - google::protobuf::Arena arena; - protobuf_unittest::TestAllTypes message(&arena); -} - -#endif -} // namespace google diff --git a/src/google/protobuf/arena_nc_test.py b/src/google/protobuf/arena_nc_test.py deleted file mode 100644 index 56a7dd05..00000000 --- a/src/google/protobuf/arena_nc_test.py +++ /dev/null @@ -1,61 +0,0 @@ -#! /usr/bin/env python -# -# Protocol Buffers - Google's data interchange format -# Copyright 2008 Google Inc. All rights reserved. -# https://developers.google.com/protocol-buffers/ -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Negative compilation unit tests for arena API.""" - -import unittest - -from google3.testing.pybase import fake_target_util -from google3.testing.pybase import unittest - - -class ArenaNcTest(unittest.TestCase): - - def testCompilerErrors(self): - """Runs a list of tests to verify compiler error messages.""" - - # Defines a list of test specs, where each element is a tuple - # (test name, list of regexes for matching the compiler errors). - test_specs = [ - ('ARENA_PRIVATE_CONSTRUCTOR', - [r'calling a protected constructor']), - ('SANITY', None)] - - fake_target_util.AssertCcCompilerErrors( - self, # The current test case. - 'google3/google/protobuf/arena_nc', # The fake target file. - 'arena_nc.o', # The sub-target to build. - test_specs # List of test specifications. - ) - -if __name__ == '__main__': - unittest.main() diff --git a/src/google/protobuf/compiler/js/embed.cc b/src/google/protobuf/compiler/js/embed.cc index a725b62e..57d38237 100644 --- a/src/google/protobuf/compiler/js/embed.cc +++ b/src/google/protobuf/compiler/js/embed.cc @@ -98,7 +98,7 @@ static void AddFile(const char* name, std::basic_ostream<char>* out) { int main(int argc, char *argv[]) { std::cout << "#include " - "\"google/protobuf/compiler/js/well_known_types_embed.h\"\n"; + "<google/protobuf/compiler/js/well_known_types_embed.h>\n"; std::cout << "struct FileToc well_known_types_js[] = {\n"; for (int i = 1; i < argc; i++) { |