aboutsummaryrefslogtreecommitdiffhomepage
path: root/objectivec/Tests
diff options
context:
space:
mode:
authorGravatar Thomas Van Lenten <thomasvl@google.com>2015-05-01 08:57:16 -0400
committerGravatar Thomas Van Lenten <thomasvl@google.com>2015-05-06 13:19:14 -0400
commit30650d81d9baa446dbc8deb784ba53794cafda5b (patch)
tree993f42cbfc871dd25d9273606f48d7c3b520df27 /objectivec/Tests
parentefa666cf0ad77827ac0b15a159e2c85e9991d77c (diff)
Alpha 1 drop of Google's Objective C plugin and runtime support for protobufs.
Diffstat (limited to 'objectivec/Tests')
-rw-r--r--objectivec/Tests/Filter1.txt40
-rw-r--r--objectivec/Tests/Filter2.txt35
-rw-r--r--objectivec/Tests/GPBARCUnittestProtos.m57
-rw-r--r--objectivec/Tests/GPBArrayTests.m3365
-rw-r--r--objectivec/Tests/GPBCodedInputStreamTests.m290
-rw-r--r--objectivec/Tests/GPBCodedOuputStreamTests.m321
-rw-r--r--objectivec/Tests/GPBConcurrencyTests.m157
-rw-r--r--objectivec/Tests/GPBDescriptorTests.m232
-rw-r--r--objectivec/Tests/GPBDictionaryTests+Bool.m2421
-rw-r--r--objectivec/Tests/GPBDictionaryTests+Int32.m3650
-rw-r--r--objectivec/Tests/GPBDictionaryTests+Int64.m3650
-rw-r--r--objectivec/Tests/GPBDictionaryTests+String.m3362
-rw-r--r--objectivec/Tests/GPBDictionaryTests+UInt32.m3650
-rw-r--r--objectivec/Tests/GPBDictionaryTests+UInt64.m3649
-rw-r--r--objectivec/Tests/GPBDictionaryTests.pddm1044
-rw-r--r--objectivec/Tests/GPBFilteredMessageTests.m98
-rw-r--r--objectivec/Tests/GPBMessageTests+Merge.m700
-rw-r--r--objectivec/Tests/GPBMessageTests+Runtime.m1978
-rw-r--r--objectivec/Tests/GPBMessageTests+Serialization.m838
-rw-r--r--objectivec/Tests/GPBMessageTests.m1728
-rw-r--r--objectivec/Tests/GPBPerfTests.m306
-rw-r--r--objectivec/Tests/GPBStringTests.m516
-rw-r--r--objectivec/Tests/GPBSwiftTests.swift405
-rw-r--r--objectivec/Tests/GPBTestUtilities.h87
-rw-r--r--objectivec/Tests/GPBTestUtilities.m2350
-rw-r--r--objectivec/Tests/GPBUnittestProtos.m56
-rw-r--r--objectivec/Tests/GPBUnknownFieldSetTest.m255
-rw-r--r--objectivec/Tests/GPBUtilitiesTests.m363
-rw-r--r--objectivec/Tests/GPBWellKnownTypesTest.m102
-rw-r--r--objectivec/Tests/GPBWireFormatTests.m246
-rw-r--r--objectivec/Tests/UnitTests-Bridging-Header.h6
-rw-r--r--objectivec/Tests/UnitTests-Info.plist20
-rw-r--r--objectivec/Tests/golden_messagebin0 -> 493 bytes
-rw-r--r--objectivec/Tests/golden_packed_fields_messagebin0 -> 493 bytes
-rw-r--r--objectivec/Tests/iOSTestHarness/AppDelegate.m35
-rw-r--r--objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/Contents.json116
-rw-r--r--objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6.pngbin0 -> 8583 bytes
-rw-r--r--objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6@2x.pngbin0 -> 17744 bytes
-rw-r--r--objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7.pngbin0 -> 8969 bytes
-rw-r--r--objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7@2x.pngbin0 -> 18788 bytes
-rw-r--r--objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6.pngbin0 -> 7021 bytes
-rw-r--r--objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6@2x.pngbin0 -> 13348 bytes
-rw-r--r--objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7@2x.pngbin0 -> 11128 bytes
-rw-r--r--objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7@3x.pngbin0 -> 21792 bytes
-rw-r--r--objectivec/Tests/iOSTestHarness/Images.xcassets/LaunchImage.launchimage/Contents.json49
-rw-r--r--objectivec/Tests/iOSTestHarness/Info.plist43
-rw-r--r--objectivec/Tests/iOSTestHarness/LaunchScreen.xib33
-rw-r--r--objectivec/Tests/iOSTestHarness/en.lproj/InfoPlist.strings2
-rw-r--r--objectivec/Tests/text_format_map_unittest_data.txt70
-rw-r--r--objectivec/Tests/text_format_unittest_data.txt116
-rw-r--r--objectivec/Tests/unittest_cycle.proto58
-rw-r--r--objectivec/Tests/unittest_filter.proto71
-rw-r--r--objectivec/Tests/unittest_name_mangling.proto37
-rw-r--r--objectivec/Tests/unittest_objc.proto389
-rw-r--r--objectivec/Tests/unittest_runtime_proto2.proto108
-rw-r--r--objectivec/Tests/unittest_runtime_proto3.proto101
56 files changed, 37205 insertions, 0 deletions
diff --git a/objectivec/Tests/Filter1.txt b/objectivec/Tests/Filter1.txt
new file mode 100644
index 00000000..88a5cac8
--- /dev/null
+++ b/objectivec/Tests/Filter1.txt
@@ -0,0 +1,40 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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.
+
+
+// Test the filter system for the ObjC Protocol Buffer Compiler.
+
+// Class names are matched using file name globbing rules.
+// Whitespace is not allowed at the beginning of a line (except for a line
+// that is a single newline).
+
+Keep
+RemoveEnumMessage_KeepNestedInside
+RemoveJustKidding
diff --git a/objectivec/Tests/Filter2.txt b/objectivec/Tests/Filter2.txt
new file mode 100644
index 00000000..5a2bb0f8
--- /dev/null
+++ b/objectivec/Tests/Filter2.txt
@@ -0,0 +1,35 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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.
+
+
+// Test the filter system for the ObjC Protocol Buffer Compiler to test
+// multiple filter support.
+
+Other
diff --git a/objectivec/Tests/GPBARCUnittestProtos.m b/objectivec/Tests/GPBARCUnittestProtos.m
new file mode 100644
index 00000000..daf4effc
--- /dev/null
+++ b/objectivec/Tests/GPBARCUnittestProtos.m
@@ -0,0 +1,57 @@
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+// 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.
+
+// Makes sure all the generated headers compile with ARC on.
+
+#import "google/protobuf/Unittest.pbobjc.h"
+#import "google/protobuf/UnittestCustomOptions.pbobjc.h"
+#import "google/protobuf/UnittestCycle.pbobjc.h"
+#import "google/protobuf/UnittestDropUnknownFields.pbobjc.h"
+#import "google/protobuf/UnittestEmbedOptimizeFor.pbobjc.h"
+#import "google/protobuf/UnittestEmpty.pbobjc.h"
+#import "google/protobuf/UnittestEnormousDescriptor.pbobjc.h"
+#import "google/protobuf/UnittestFilter.pbobjc.h"
+#import "google/protobuf/UnittestImport.pbobjc.h"
+#import "google/protobuf/UnittestImportLite.pbobjc.h"
+#import "google/protobuf/UnittestImportPublic.pbobjc.h"
+#import "google/protobuf/UnittestImportPublicLite.pbobjc.h"
+#import "google/protobuf/UnittestLite.pbobjc.h"
+#import "google/protobuf/UnittestMset.pbobjc.h"
+#import "google/protobuf/UnittestNameMangling.pbobjc.h"
+#import "google/protobuf/UnittestNoGenericServices.pbobjc.h"
+#import "google/protobuf/UnittestObjc.pbobjc.h"
+#import "google/protobuf/UnittestOptimizeFor.pbobjc.h"
+#import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.h"
+#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+#import "google/protobuf/UnittestRuntimeProto3.pbobjc.h"
diff --git a/objectivec/Tests/GPBArrayTests.m b/objectivec/Tests/GPBArrayTests.m
new file mode 100644
index 00000000..37724c59
--- /dev/null
+++ b/objectivec/Tests/GPBArrayTests.m
@@ -0,0 +1,3365 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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 "GPBArray.h"
+
+#ifndef GPBARRAYSIZE
+#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))))
+#endif // GPBARRAYSIZE
+
+// To let the testing macros work, add some extra methods to simplify things.
+@interface GPBEnumArray (TestingTweak)
++ (instancetype)arrayWithValue:(int32_t)value;
+- (instancetype)initWithValues:(const int32_t [])values
+ count:(NSUInteger)count;
+@end
+
+static BOOL TestingEnum_IsValidValue(int32_t value) {
+ switch (value) {
+ case 71:
+ case 72:
+ case 73:
+ case 74:
+ return YES;
+ default:
+ return NO;
+ }
+}
+
+static BOOL TestingEnum_IsValidValue2(int32_t value) {
+ switch (value) {
+ case 71:
+ case 72:
+ case 73:
+ return YES;
+ default:
+ return NO;
+ }
+}
+
+@implementation GPBEnumArray (TestingTweak)
++ (instancetype)arrayWithValue:(int32_t)value {
+ return [[[self alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:&value
+ count:1] autorelease];
+}
+- (instancetype)initWithValues:(const int32_t [])values
+ count:(NSUInteger)count {
+ return [self initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:values
+ count:count];
+}
+@end
+
+#pragma mark - PDDM Macros
+
+//%PDDM-DEFINE ARRAY_TESTS(NAME, TYPE, VAL1, VAL2, VAL3, VAL4)
+//%ARRAY_TESTS2(NAME, TYPE, VAL1, VAL2, VAL3, VAL4, )
+//%PDDM-DEFINE ARRAY_TESTS2(NAME, TYPE, VAL1, VAL2, VAL3, VAL4, HELPER)
+//%#pragma mark - NAME
+//%
+//%@interface GPB##NAME##ArrayTests : XCTestCase
+//%@end
+//%
+//%@implementation GPB##NAME##ArrayTests
+//%
+//%- (void)testEmpty {
+//% GPB##NAME##Array *array = [[GPB##NAME##Array alloc] init];
+//% XCTAssertNotNil(array);
+//% XCTAssertEqual(array.count, 0U);
+//% XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
+//% [array enumerateValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//% #pragma unused(value, idx, stop)
+//% XCTFail(@"Shouldn't get here!");
+//% }];
+//% [array enumerateValuesWithOptions:NSEnumerationReverse
+//% usingBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//% #pragma unused(value, idx, stop)
+//% XCTFail(@"Shouldn't get here!");
+//% }];
+//% [array release];
+//%}
+//%
+//%- (void)testOne {
+//% GPB##NAME##Array *array = [GPB##NAME##Array arrayWithValue:VAL1];
+//% XCTAssertNotNil(array);
+//% XCTAssertEqual(array.count, 1U);
+//% XCTAssertEqual([array valueAtIndex:0], VAL1);
+//% XCTAssertThrowsSpecificNamed([array valueAtIndex:1], NSException, NSRangeException);
+//% [array enumerateValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//% XCTAssertEqual(idx, 0U);
+//% XCTAssertEqual(value, VAL1);
+//% XCTAssertNotEqual(stop, NULL);
+//% }];
+//% [array enumerateValuesWithOptions:NSEnumerationReverse
+//% usingBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//% XCTAssertEqual(idx, 0U);
+//% XCTAssertEqual(value, VAL1);
+//% XCTAssertNotEqual(stop, NULL);
+//% }];
+//%}
+//%
+//%- (void)testBasics {
+//% static const TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
+//% GPB##NAME##Array *array =
+//% [[GPB##NAME##Array alloc] initWithValues:kValues
+//% NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(array);
+//% XCTAssertEqual(array.count, 4U);
+//% XCTAssertEqual([array valueAtIndex:0], VAL1);
+//% XCTAssertEqual([array valueAtIndex:1], VAL2);
+//% XCTAssertEqual([array valueAtIndex:2], VAL3);
+//% XCTAssertEqual([array valueAtIndex:3], VAL4);
+//% XCTAssertThrowsSpecificNamed([array valueAtIndex:4], NSException, NSRangeException);
+//% __block NSUInteger idx2 = 0;
+//% [array enumerateValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//% XCTAssertEqual(idx, idx2);
+//% XCTAssertEqual(value, kValues[idx]);
+//% XCTAssertNotEqual(stop, NULL);
+//% ++idx2;
+//% }];
+//% idx2 = 0;
+//% [array enumerateValuesWithOptions:NSEnumerationReverse
+//% usingBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//% XCTAssertEqual(idx, (3 - idx2));
+//% XCTAssertEqual(value, kValues[idx]);
+//% XCTAssertNotEqual(stop, NULL);
+//% ++idx2;
+//% }];
+//% // Stopping the enumeration.
+//% idx2 = 0;
+//% [array enumerateValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//% XCTAssertEqual(idx, idx2);
+//% XCTAssertEqual(value, kValues[idx]);
+//% XCTAssertNotEqual(stop, NULL);
+//% if (idx2 == 1) *stop = YES;
+//% XCTAssertNotEqual(idx, 2U);
+//% XCTAssertNotEqual(idx, 3U);
+//% ++idx2;
+//% }];
+//% idx2 = 0;
+//% [array enumerateValuesWithOptions:NSEnumerationReverse
+//% usingBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//% XCTAssertEqual(idx, (3 - idx2));
+//% XCTAssertEqual(value, kValues[idx]);
+//% XCTAssertNotEqual(stop, NULL);
+//% if (idx2 == 1) *stop = YES;
+//% XCTAssertNotEqual(idx, 1U);
+//% XCTAssertNotEqual(idx, 0U);
+//% ++idx2;
+//% }];
+//% [array release];
+//%}
+//%
+//%- (void)testEquality {
+//% const TYPE kValues1[] = { VAL1, VAL2, VAL3 };
+//% const TYPE kValues2[] = { VAL1, VAL4, VAL3 };
+//% const TYPE kValues3[] = { VAL1, VAL2, VAL3, VAL4 };
+//% GPB##NAME##Array *array1 =
+//% [[GPB##NAME##Array alloc] initWithValues:kValues1
+//% NAME$S count:GPBARRAYSIZE(kValues1)];
+//% XCTAssertNotNil(array1);
+//% GPB##NAME##Array *array1prime =
+//% [[GPB##NAME##Array alloc] initWithValues:kValues1
+//% NAME$S count:GPBARRAYSIZE(kValues1)];
+//% XCTAssertNotNil(array1prime);
+//% GPB##NAME##Array *array2 =
+//% [[GPB##NAME##Array alloc] initWithValues:kValues2
+//% NAME$S count:GPBARRAYSIZE(kValues2)];
+//% XCTAssertNotNil(array2);
+//% GPB##NAME##Array *array3 =
+//% [[GPB##NAME##Array alloc] initWithValues:kValues3
+//% NAME$S count:GPBARRAYSIZE(kValues3)];
+//% XCTAssertNotNil(array3);
+//%
+//% // 1/1Prime should be different objects, but equal.
+//% XCTAssertNotEqual(array1, array1prime);
+//% XCTAssertEqualObjects(array1, array1prime);
+//% // Equal, so they must have same hash.
+//% XCTAssertEqual([array1 hash], [array1prime hash]);
+//%
+//% // 1/2/3 shouldn't be equal.
+//% XCTAssertNotEqualObjects(array1, array2);
+//% XCTAssertNotEqualObjects(array1, array3);
+//% XCTAssertNotEqualObjects(array2, array3);
+//%
+//% [array1 release];
+//% [array1prime release];
+//% [array2 release];
+//% [array3 release];
+//%}
+//%
+//%- (void)testCopy {
+//% const TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
+//% GPB##NAME##Array *array =
+//% [[GPB##NAME##Array alloc] initWithValues:kValues
+//% NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(array);
+//%
+//% GPB##NAME##Array *array2 = [array copy];
+//% XCTAssertNotNil(array2);
+//%
+//% // Should be new object but equal.
+//% XCTAssertNotEqual(array, array2);
+//% XCTAssertEqualObjects(array, array2);
+//%}
+//%
+//%- (void)testArrayFromArray {
+//% const TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
+//% GPB##NAME##Array *array =
+//% [[GPB##NAME##Array alloc] initWithValues:kValues
+//% NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(array);
+//%
+//% GPB##NAME##Array *array2 = [GPB##NAME##Array arrayWithValueArray:array];
+//% XCTAssertNotNil(array2);
+//%
+//% // Should be new pointer, but equal objects.
+//% XCTAssertNotEqual(array, array2);
+//% XCTAssertEqualObjects(array, array2);
+//%}
+//%
+//%- (void)testAdds {
+//% GPB##NAME##Array *array = [GPB##NAME##Array array];
+//% XCTAssertNotNil(array);
+//%
+//% XCTAssertEqual(array.count, 0U);
+//% [array addValue:VAL1];
+//% XCTAssertEqual(array.count, 1U);
+//%
+//% const TYPE kValues1[] = { VAL2, VAL3 };
+//% [array addValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+//% XCTAssertEqual(array.count, 3U);
+//%
+//% const TYPE kValues2[] = { VAL4, VAL1 };
+//% GPB##NAME##Array *array2 =
+//% [[GPB##NAME##Array alloc] initWithValues:kValues2
+//% NAME$S count:GPBARRAYSIZE(kValues2)];
+//% XCTAssertNotNil(array2);
+//% [array add##HELPER##ValuesFromArray:array2];
+//% XCTAssertEqual(array.count, 5U);
+//%
+//% XCTAssertEqual([array valueAtIndex:0], VAL1);
+//% XCTAssertEqual([array valueAtIndex:1], VAL2);
+//% XCTAssertEqual([array valueAtIndex:2], VAL3);
+//% XCTAssertEqual([array valueAtIndex:3], VAL4);
+//% XCTAssertEqual([array valueAtIndex:4], VAL1);
+//%}
+//%
+//%- (void)testInsert {
+//% const TYPE kValues[] = { VAL1, VAL2, VAL3 };
+//% GPB##NAME##Array *array =
+//% [[GPB##NAME##Array alloc] initWithValues:kValues
+//% NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(array);
+//% XCTAssertEqual(array.count, 3U);
+//%
+//% // First
+//% [array insertValue:VAL4 atIndex:0];
+//% XCTAssertEqual(array.count, 4U);
+//%
+//% // Middle
+//% [array insertValue:VAL4 atIndex:2];
+//% XCTAssertEqual(array.count, 5U);
+//%
+//% // End
+//% [array insertValue:VAL4 atIndex:5];
+//% XCTAssertEqual(array.count, 6U);
+//%
+//% // Too far.
+//% XCTAssertThrowsSpecificNamed([array insertValue:VAL4 atIndex:7],
+//% NSException, NSRangeException);
+//%
+//% XCTAssertEqual([array valueAtIndex:0], VAL4);
+//% XCTAssertEqual([array valueAtIndex:1], VAL1);
+//% XCTAssertEqual([array valueAtIndex:2], VAL4);
+//% XCTAssertEqual([array valueAtIndex:3], VAL2);
+//% XCTAssertEqual([array valueAtIndex:4], VAL3);
+//% XCTAssertEqual([array valueAtIndex:5], VAL4);
+//%}
+//%
+//%- (void)testRemove {
+//% const TYPE kValues[] = { VAL4, VAL1, VAL2, VAL4, VAL3, VAL4 };
+//% GPB##NAME##Array *array =
+//% [[GPB##NAME##Array alloc] initWithValues:kValues
+//% NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(array);
+//% XCTAssertEqual(array.count, 6U);
+//%
+//% // First
+//% [array removeValueAtIndex:0];
+//% XCTAssertEqual(array.count, 5U);
+//% XCTAssertEqual([array valueAtIndex:0], VAL1);
+//%
+//% // Middle
+//% [array removeValueAtIndex:2];
+//% XCTAssertEqual(array.count, 4U);
+//% XCTAssertEqual([array valueAtIndex:2], VAL3);
+//%
+//% // End
+//% [array removeValueAtIndex:3];
+//% XCTAssertEqual(array.count, 3U);
+//%
+//% XCTAssertEqual([array valueAtIndex:0], VAL1);
+//% XCTAssertEqual([array valueAtIndex:1], VAL2);
+//% XCTAssertEqual([array valueAtIndex:2], VAL3);
+//%
+//% // Too far.
+//% XCTAssertThrowsSpecificNamed([array removeValueAtIndex:3],
+//% NSException, NSRangeException);
+//%
+//% [array removeAll];
+//% XCTAssertEqual(array.count, 0U);
+//% XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0],
+//% NSException, NSRangeException);
+//%}
+//%
+//%- (void)testInplaceMutation {
+//% const TYPE kValues[] = { VAL1, VAL1, VAL3, VAL3 };
+//% GPB##NAME##Array *array =
+//% [[GPB##NAME##Array alloc] initWithValues:kValues
+//% NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(array);
+//%
+//% [array replaceValueAtIndex:1 withValue:VAL2];
+//% [array replaceValueAtIndex:3 withValue:VAL4];
+//% XCTAssertEqual(array.count, 4U);
+//% XCTAssertEqual([array valueAtIndex:0], VAL1);
+//% XCTAssertEqual([array valueAtIndex:1], VAL2);
+//% XCTAssertEqual([array valueAtIndex:2], VAL3);
+//% XCTAssertEqual([array valueAtIndex:3], VAL4);
+//%
+//% XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withValue:VAL4],
+//% NSException, NSRangeException);
+//%
+//% [array exchangeValueAtIndex:1 withValueAtIndex:3];
+//% XCTAssertEqual(array.count, 4U);
+//% XCTAssertEqual([array valueAtIndex:0], VAL1);
+//% XCTAssertEqual([array valueAtIndex:1], VAL4);
+//% XCTAssertEqual([array valueAtIndex:2], VAL3);
+//% XCTAssertEqual([array valueAtIndex:3], VAL2);
+//%
+//% [array exchangeValueAtIndex:2 withValueAtIndex:0];
+//% XCTAssertEqual(array.count, 4U);
+//% XCTAssertEqual([array valueAtIndex:0], VAL3);
+//% XCTAssertEqual([array valueAtIndex:1], VAL4);
+//% XCTAssertEqual([array valueAtIndex:2], VAL1);
+//% XCTAssertEqual([array valueAtIndex:3], VAL2);
+//%
+//% XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:4 withValueAtIndex:1],
+//% NSException, NSRangeException);
+//% XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4],
+//% NSException, NSRangeException);
+//%}
+//%
+//%- (void)testInternalResizing {
+//% const TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
+//% GPB##NAME##Array *array =
+//% [[GPB##NAME##Array alloc] initWithValues:kValues
+//% NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(array);
+//%
+//% // Add/remove to trigger the intneral buffer to grow/shrink.
+//% for (int i = 0; i < 100; ++i) {
+//% [array addValues:kValues count:GPBARRAYSIZE(kValues)];
+//% }
+//% XCTAssertEqual(array.count, 404U);
+//% for (int i = 0; i < 100; ++i) {
+//% [array removeValueAtIndex:(i * 2)];
+//% }
+//% XCTAssertEqual(array.count, 304U);
+//% for (int i = 0; i < 100; ++i) {
+//% [array insertValue:VAL4 atIndex:(i * 3)];
+//% }
+//% XCTAssertEqual(array.count, 404U);
+//% [array removeAll];
+//% XCTAssertEqual(array.count, 0U);
+//%}
+//%
+//%@end
+//%
+//%PDDM-EXPAND ARRAY_TESTS(Int32, int32_t, 1, 2, 3, 4)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Int32
+
+@interface GPBInt32ArrayTests : XCTestCase
+@end
+
+@implementation GPBInt32ArrayTests
+
+- (void)testEmpty {
+ GPBInt32Array *array = [[GPBInt32Array alloc] init];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array release];
+}
+
+- (void)testOne {
+ GPBInt32Array *array = [GPBInt32Array arrayWithValue:1];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 1U);
+ XCTAssertEqual([array valueAtIndex:0], 1);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:1], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 1);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 1);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ static const int32_t kValues[] = { 1, 2, 3, 4 };
+ GPBInt32Array *array =
+ [[GPBInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 1);
+ XCTAssertEqual([array valueAtIndex:1], 2);
+ XCTAssertEqual([array valueAtIndex:2], 3);
+ XCTAssertEqual([array valueAtIndex:3], 4);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:4], NSException, NSRangeException);
+ __block NSUInteger idx2 = 0;
+ [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ // Stopping the enumeration.
+ idx2 = 0;
+ [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ XCTAssertNotEqual(idx, 3U);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 1U);
+ XCTAssertNotEqual(idx, 0U);
+ ++idx2;
+ }];
+ [array release];
+}
+
+- (void)testEquality {
+ const int32_t kValues1[] = { 1, 2, 3 };
+ const int32_t kValues2[] = { 1, 4, 3 };
+ const int32_t kValues3[] = { 1, 2, 3, 4 };
+ GPBInt32Array *array1 =
+ [[GPBInt32Array alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1);
+ GPBInt32Array *array1prime =
+ [[GPBInt32Array alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1prime);
+ GPBInt32Array *array2 =
+ [[GPBInt32Array alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ GPBInt32Array *array3 =
+ [[GPBInt32Array alloc] initWithValues:kValues3
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(array3);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(array1, array1prime);
+ XCTAssertEqualObjects(array1, array1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([array1 hash], [array1prime hash]);
+
+ // 1/2/3 shouldn't be equal.
+ XCTAssertNotEqualObjects(array1, array2);
+ XCTAssertNotEqualObjects(array1, array3);
+ XCTAssertNotEqualObjects(array2, array3);
+
+ [array1 release];
+ [array1prime release];
+ [array2 release];
+ [array3 release];
+}
+
+- (void)testCopy {
+ const int32_t kValues[] = { 1, 2, 3, 4 };
+ GPBInt32Array *array =
+ [[GPBInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBInt32Array *array2 = [array copy];
+ XCTAssertNotNil(array2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testArrayFromArray {
+ const int32_t kValues[] = { 1, 2, 3, 4 };
+ GPBInt32Array *array =
+ [[GPBInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBInt32Array *array2 = [GPBInt32Array arrayWithValueArray:array];
+ XCTAssertNotNil(array2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testAdds {
+ GPBInt32Array *array = [GPBInt32Array array];
+ XCTAssertNotNil(array);
+
+ XCTAssertEqual(array.count, 0U);
+ [array addValue:1];
+ XCTAssertEqual(array.count, 1U);
+
+ const int32_t kValues1[] = { 2, 3 };
+ [array addValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+ XCTAssertEqual(array.count, 3U);
+
+ const int32_t kValues2[] = { 4, 1 };
+ GPBInt32Array *array2 =
+ [[GPBInt32Array alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ [array addValuesFromArray:array2];
+ XCTAssertEqual(array.count, 5U);
+
+ XCTAssertEqual([array valueAtIndex:0], 1);
+ XCTAssertEqual([array valueAtIndex:1], 2);
+ XCTAssertEqual([array valueAtIndex:2], 3);
+ XCTAssertEqual([array valueAtIndex:3], 4);
+ XCTAssertEqual([array valueAtIndex:4], 1);
+}
+
+- (void)testInsert {
+ const int32_t kValues[] = { 1, 2, 3 };
+ GPBInt32Array *array =
+ [[GPBInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 3U);
+
+ // First
+ [array insertValue:4 atIndex:0];
+ XCTAssertEqual(array.count, 4U);
+
+ // Middle
+ [array insertValue:4 atIndex:2];
+ XCTAssertEqual(array.count, 5U);
+
+ // End
+ [array insertValue:4 atIndex:5];
+ XCTAssertEqual(array.count, 6U);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array insertValue:4 atIndex:7],
+ NSException, NSRangeException);
+
+ XCTAssertEqual([array valueAtIndex:0], 4);
+ XCTAssertEqual([array valueAtIndex:1], 1);
+ XCTAssertEqual([array valueAtIndex:2], 4);
+ XCTAssertEqual([array valueAtIndex:3], 2);
+ XCTAssertEqual([array valueAtIndex:4], 3);
+ XCTAssertEqual([array valueAtIndex:5], 4);
+}
+
+- (void)testRemove {
+ const int32_t kValues[] = { 4, 1, 2, 4, 3, 4 };
+ GPBInt32Array *array =
+ [[GPBInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 6U);
+
+ // First
+ [array removeValueAtIndex:0];
+ XCTAssertEqual(array.count, 5U);
+ XCTAssertEqual([array valueAtIndex:0], 1);
+
+ // Middle
+ [array removeValueAtIndex:2];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:2], 3);
+
+ // End
+ [array removeValueAtIndex:3];
+ XCTAssertEqual(array.count, 3U);
+
+ XCTAssertEqual([array valueAtIndex:0], 1);
+ XCTAssertEqual([array valueAtIndex:1], 2);
+ XCTAssertEqual([array valueAtIndex:2], 3);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:3],
+ NSException, NSRangeException);
+
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0],
+ NSException, NSRangeException);
+}
+
+- (void)testInplaceMutation {
+ const int32_t kValues[] = { 1, 1, 3, 3 };
+ GPBInt32Array *array =
+ [[GPBInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ [array replaceValueAtIndex:1 withValue:2];
+ [array replaceValueAtIndex:3 withValue:4];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 1);
+ XCTAssertEqual([array valueAtIndex:1], 2);
+ XCTAssertEqual([array valueAtIndex:2], 3);
+ XCTAssertEqual([array valueAtIndex:3], 4);
+
+ XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withValue:4],
+ NSException, NSRangeException);
+
+ [array exchangeValueAtIndex:1 withValueAtIndex:3];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 1);
+ XCTAssertEqual([array valueAtIndex:1], 4);
+ XCTAssertEqual([array valueAtIndex:2], 3);
+ XCTAssertEqual([array valueAtIndex:3], 2);
+
+ [array exchangeValueAtIndex:2 withValueAtIndex:0];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 3);
+ XCTAssertEqual([array valueAtIndex:1], 4);
+ XCTAssertEqual([array valueAtIndex:2], 1);
+ XCTAssertEqual([array valueAtIndex:3], 2);
+
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:4 withValueAtIndex:1],
+ NSException, NSRangeException);
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4],
+ NSException, NSRangeException);
+}
+
+- (void)testInternalResizing {
+ const int32_t kValues[] = { 1, 2, 3, 4 };
+ GPBInt32Array *array =
+ [[GPBInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ // Add/remove to trigger the intneral buffer to grow/shrink.
+ for (int i = 0; i < 100; ++i) {
+ [array addValues:kValues count:GPBARRAYSIZE(kValues)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ for (int i = 0; i < 100; ++i) {
+ [array removeValueAtIndex:(i * 2)];
+ }
+ XCTAssertEqual(array.count, 304U);
+ for (int i = 0; i < 100; ++i) {
+ [array insertValue:4 atIndex:(i * 3)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_TESTS(UInt32, uint32_t, 11U, 12U, 13U, 14U)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - UInt32
+
+@interface GPBUInt32ArrayTests : XCTestCase
+@end
+
+@implementation GPBUInt32ArrayTests
+
+- (void)testEmpty {
+ GPBUInt32Array *array = [[GPBUInt32Array alloc] init];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array release];
+}
+
+- (void)testOne {
+ GPBUInt32Array *array = [GPBUInt32Array arrayWithValue:11U];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 1U);
+ XCTAssertEqual([array valueAtIndex:0], 11U);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:1], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 11U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 11U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ static const uint32_t kValues[] = { 11U, 12U, 13U, 14U };
+ GPBUInt32Array *array =
+ [[GPBUInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 11U);
+ XCTAssertEqual([array valueAtIndex:1], 12U);
+ XCTAssertEqual([array valueAtIndex:2], 13U);
+ XCTAssertEqual([array valueAtIndex:3], 14U);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:4], NSException, NSRangeException);
+ __block NSUInteger idx2 = 0;
+ [array enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ // Stopping the enumeration.
+ idx2 = 0;
+ [array enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ XCTAssertNotEqual(idx, 3U);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 1U);
+ XCTAssertNotEqual(idx, 0U);
+ ++idx2;
+ }];
+ [array release];
+}
+
+- (void)testEquality {
+ const uint32_t kValues1[] = { 11U, 12U, 13U };
+ const uint32_t kValues2[] = { 11U, 14U, 13U };
+ const uint32_t kValues3[] = { 11U, 12U, 13U, 14U };
+ GPBUInt32Array *array1 =
+ [[GPBUInt32Array alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1);
+ GPBUInt32Array *array1prime =
+ [[GPBUInt32Array alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1prime);
+ GPBUInt32Array *array2 =
+ [[GPBUInt32Array alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ GPBUInt32Array *array3 =
+ [[GPBUInt32Array alloc] initWithValues:kValues3
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(array3);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(array1, array1prime);
+ XCTAssertEqualObjects(array1, array1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([array1 hash], [array1prime hash]);
+
+ // 1/2/3 shouldn't be equal.
+ XCTAssertNotEqualObjects(array1, array2);
+ XCTAssertNotEqualObjects(array1, array3);
+ XCTAssertNotEqualObjects(array2, array3);
+
+ [array1 release];
+ [array1prime release];
+ [array2 release];
+ [array3 release];
+}
+
+- (void)testCopy {
+ const uint32_t kValues[] = { 11U, 12U, 13U, 14U };
+ GPBUInt32Array *array =
+ [[GPBUInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBUInt32Array *array2 = [array copy];
+ XCTAssertNotNil(array2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testArrayFromArray {
+ const uint32_t kValues[] = { 11U, 12U, 13U, 14U };
+ GPBUInt32Array *array =
+ [[GPBUInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBUInt32Array *array2 = [GPBUInt32Array arrayWithValueArray:array];
+ XCTAssertNotNil(array2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testAdds {
+ GPBUInt32Array *array = [GPBUInt32Array array];
+ XCTAssertNotNil(array);
+
+ XCTAssertEqual(array.count, 0U);
+ [array addValue:11U];
+ XCTAssertEqual(array.count, 1U);
+
+ const uint32_t kValues1[] = { 12U, 13U };
+ [array addValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+ XCTAssertEqual(array.count, 3U);
+
+ const uint32_t kValues2[] = { 14U, 11U };
+ GPBUInt32Array *array2 =
+ [[GPBUInt32Array alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ [array addValuesFromArray:array2];
+ XCTAssertEqual(array.count, 5U);
+
+ XCTAssertEqual([array valueAtIndex:0], 11U);
+ XCTAssertEqual([array valueAtIndex:1], 12U);
+ XCTAssertEqual([array valueAtIndex:2], 13U);
+ XCTAssertEqual([array valueAtIndex:3], 14U);
+ XCTAssertEqual([array valueAtIndex:4], 11U);
+}
+
+- (void)testInsert {
+ const uint32_t kValues[] = { 11U, 12U, 13U };
+ GPBUInt32Array *array =
+ [[GPBUInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 3U);
+
+ // First
+ [array insertValue:14U atIndex:0];
+ XCTAssertEqual(array.count, 4U);
+
+ // Middle
+ [array insertValue:14U atIndex:2];
+ XCTAssertEqual(array.count, 5U);
+
+ // End
+ [array insertValue:14U atIndex:5];
+ XCTAssertEqual(array.count, 6U);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array insertValue:14U atIndex:7],
+ NSException, NSRangeException);
+
+ XCTAssertEqual([array valueAtIndex:0], 14U);
+ XCTAssertEqual([array valueAtIndex:1], 11U);
+ XCTAssertEqual([array valueAtIndex:2], 14U);
+ XCTAssertEqual([array valueAtIndex:3], 12U);
+ XCTAssertEqual([array valueAtIndex:4], 13U);
+ XCTAssertEqual([array valueAtIndex:5], 14U);
+}
+
+- (void)testRemove {
+ const uint32_t kValues[] = { 14U, 11U, 12U, 14U, 13U, 14U };
+ GPBUInt32Array *array =
+ [[GPBUInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 6U);
+
+ // First
+ [array removeValueAtIndex:0];
+ XCTAssertEqual(array.count, 5U);
+ XCTAssertEqual([array valueAtIndex:0], 11U);
+
+ // Middle
+ [array removeValueAtIndex:2];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:2], 13U);
+
+ // End
+ [array removeValueAtIndex:3];
+ XCTAssertEqual(array.count, 3U);
+
+ XCTAssertEqual([array valueAtIndex:0], 11U);
+ XCTAssertEqual([array valueAtIndex:1], 12U);
+ XCTAssertEqual([array valueAtIndex:2], 13U);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:3],
+ NSException, NSRangeException);
+
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0],
+ NSException, NSRangeException);
+}
+
+- (void)testInplaceMutation {
+ const uint32_t kValues[] = { 11U, 11U, 13U, 13U };
+ GPBUInt32Array *array =
+ [[GPBUInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ [array replaceValueAtIndex:1 withValue:12U];
+ [array replaceValueAtIndex:3 withValue:14U];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 11U);
+ XCTAssertEqual([array valueAtIndex:1], 12U);
+ XCTAssertEqual([array valueAtIndex:2], 13U);
+ XCTAssertEqual([array valueAtIndex:3], 14U);
+
+ XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withValue:14U],
+ NSException, NSRangeException);
+
+ [array exchangeValueAtIndex:1 withValueAtIndex:3];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 11U);
+ XCTAssertEqual([array valueAtIndex:1], 14U);
+ XCTAssertEqual([array valueAtIndex:2], 13U);
+ XCTAssertEqual([array valueAtIndex:3], 12U);
+
+ [array exchangeValueAtIndex:2 withValueAtIndex:0];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 13U);
+ XCTAssertEqual([array valueAtIndex:1], 14U);
+ XCTAssertEqual([array valueAtIndex:2], 11U);
+ XCTAssertEqual([array valueAtIndex:3], 12U);
+
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:4 withValueAtIndex:1],
+ NSException, NSRangeException);
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4],
+ NSException, NSRangeException);
+}
+
+- (void)testInternalResizing {
+ const uint32_t kValues[] = { 11U, 12U, 13U, 14U };
+ GPBUInt32Array *array =
+ [[GPBUInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ // Add/remove to trigger the intneral buffer to grow/shrink.
+ for (int i = 0; i < 100; ++i) {
+ [array addValues:kValues count:GPBARRAYSIZE(kValues)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ for (int i = 0; i < 100; ++i) {
+ [array removeValueAtIndex:(i * 2)];
+ }
+ XCTAssertEqual(array.count, 304U);
+ for (int i = 0; i < 100; ++i) {
+ [array insertValue:14U atIndex:(i * 3)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_TESTS(Int64, int64_t, 31LL, 32LL, 33LL, 34LL)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Int64
+
+@interface GPBInt64ArrayTests : XCTestCase
+@end
+
+@implementation GPBInt64ArrayTests
+
+- (void)testEmpty {
+ GPBInt64Array *array = [[GPBInt64Array alloc] init];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array release];
+}
+
+- (void)testOne {
+ GPBInt64Array *array = [GPBInt64Array arrayWithValue:31LL];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 1U);
+ XCTAssertEqual([array valueAtIndex:0], 31LL);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:1], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 31LL);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 31LL);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ static const int64_t kValues[] = { 31LL, 32LL, 33LL, 34LL };
+ GPBInt64Array *array =
+ [[GPBInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 31LL);
+ XCTAssertEqual([array valueAtIndex:1], 32LL);
+ XCTAssertEqual([array valueAtIndex:2], 33LL);
+ XCTAssertEqual([array valueAtIndex:3], 34LL);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:4], NSException, NSRangeException);
+ __block NSUInteger idx2 = 0;
+ [array enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ // Stopping the enumeration.
+ idx2 = 0;
+ [array enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ XCTAssertNotEqual(idx, 3U);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 1U);
+ XCTAssertNotEqual(idx, 0U);
+ ++idx2;
+ }];
+ [array release];
+}
+
+- (void)testEquality {
+ const int64_t kValues1[] = { 31LL, 32LL, 33LL };
+ const int64_t kValues2[] = { 31LL, 34LL, 33LL };
+ const int64_t kValues3[] = { 31LL, 32LL, 33LL, 34LL };
+ GPBInt64Array *array1 =
+ [[GPBInt64Array alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1);
+ GPBInt64Array *array1prime =
+ [[GPBInt64Array alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1prime);
+ GPBInt64Array *array2 =
+ [[GPBInt64Array alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ GPBInt64Array *array3 =
+ [[GPBInt64Array alloc] initWithValues:kValues3
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(array3);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(array1, array1prime);
+ XCTAssertEqualObjects(array1, array1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([array1 hash], [array1prime hash]);
+
+ // 1/2/3 shouldn't be equal.
+ XCTAssertNotEqualObjects(array1, array2);
+ XCTAssertNotEqualObjects(array1, array3);
+ XCTAssertNotEqualObjects(array2, array3);
+
+ [array1 release];
+ [array1prime release];
+ [array2 release];
+ [array3 release];
+}
+
+- (void)testCopy {
+ const int64_t kValues[] = { 31LL, 32LL, 33LL, 34LL };
+ GPBInt64Array *array =
+ [[GPBInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBInt64Array *array2 = [array copy];
+ XCTAssertNotNil(array2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testArrayFromArray {
+ const int64_t kValues[] = { 31LL, 32LL, 33LL, 34LL };
+ GPBInt64Array *array =
+ [[GPBInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBInt64Array *array2 = [GPBInt64Array arrayWithValueArray:array];
+ XCTAssertNotNil(array2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testAdds {
+ GPBInt64Array *array = [GPBInt64Array array];
+ XCTAssertNotNil(array);
+
+ XCTAssertEqual(array.count, 0U);
+ [array addValue:31LL];
+ XCTAssertEqual(array.count, 1U);
+
+ const int64_t kValues1[] = { 32LL, 33LL };
+ [array addValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+ XCTAssertEqual(array.count, 3U);
+
+ const int64_t kValues2[] = { 34LL, 31LL };
+ GPBInt64Array *array2 =
+ [[GPBInt64Array alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ [array addValuesFromArray:array2];
+ XCTAssertEqual(array.count, 5U);
+
+ XCTAssertEqual([array valueAtIndex:0], 31LL);
+ XCTAssertEqual([array valueAtIndex:1], 32LL);
+ XCTAssertEqual([array valueAtIndex:2], 33LL);
+ XCTAssertEqual([array valueAtIndex:3], 34LL);
+ XCTAssertEqual([array valueAtIndex:4], 31LL);
+}
+
+- (void)testInsert {
+ const int64_t kValues[] = { 31LL, 32LL, 33LL };
+ GPBInt64Array *array =
+ [[GPBInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 3U);
+
+ // First
+ [array insertValue:34LL atIndex:0];
+ XCTAssertEqual(array.count, 4U);
+
+ // Middle
+ [array insertValue:34LL atIndex:2];
+ XCTAssertEqual(array.count, 5U);
+
+ // End
+ [array insertValue:34LL atIndex:5];
+ XCTAssertEqual(array.count, 6U);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array insertValue:34LL atIndex:7],
+ NSException, NSRangeException);
+
+ XCTAssertEqual([array valueAtIndex:0], 34LL);
+ XCTAssertEqual([array valueAtIndex:1], 31LL);
+ XCTAssertEqual([array valueAtIndex:2], 34LL);
+ XCTAssertEqual([array valueAtIndex:3], 32LL);
+ XCTAssertEqual([array valueAtIndex:4], 33LL);
+ XCTAssertEqual([array valueAtIndex:5], 34LL);
+}
+
+- (void)testRemove {
+ const int64_t kValues[] = { 34LL, 31LL, 32LL, 34LL, 33LL, 34LL };
+ GPBInt64Array *array =
+ [[GPBInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 6U);
+
+ // First
+ [array removeValueAtIndex:0];
+ XCTAssertEqual(array.count, 5U);
+ XCTAssertEqual([array valueAtIndex:0], 31LL);
+
+ // Middle
+ [array removeValueAtIndex:2];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:2], 33LL);
+
+ // End
+ [array removeValueAtIndex:3];
+ XCTAssertEqual(array.count, 3U);
+
+ XCTAssertEqual([array valueAtIndex:0], 31LL);
+ XCTAssertEqual([array valueAtIndex:1], 32LL);
+ XCTAssertEqual([array valueAtIndex:2], 33LL);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:3],
+ NSException, NSRangeException);
+
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0],
+ NSException, NSRangeException);
+}
+
+- (void)testInplaceMutation {
+ const int64_t kValues[] = { 31LL, 31LL, 33LL, 33LL };
+ GPBInt64Array *array =
+ [[GPBInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ [array replaceValueAtIndex:1 withValue:32LL];
+ [array replaceValueAtIndex:3 withValue:34LL];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 31LL);
+ XCTAssertEqual([array valueAtIndex:1], 32LL);
+ XCTAssertEqual([array valueAtIndex:2], 33LL);
+ XCTAssertEqual([array valueAtIndex:3], 34LL);
+
+ XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withValue:34LL],
+ NSException, NSRangeException);
+
+ [array exchangeValueAtIndex:1 withValueAtIndex:3];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 31LL);
+ XCTAssertEqual([array valueAtIndex:1], 34LL);
+ XCTAssertEqual([array valueAtIndex:2], 33LL);
+ XCTAssertEqual([array valueAtIndex:3], 32LL);
+
+ [array exchangeValueAtIndex:2 withValueAtIndex:0];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 33LL);
+ XCTAssertEqual([array valueAtIndex:1], 34LL);
+ XCTAssertEqual([array valueAtIndex:2], 31LL);
+ XCTAssertEqual([array valueAtIndex:3], 32LL);
+
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:4 withValueAtIndex:1],
+ NSException, NSRangeException);
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4],
+ NSException, NSRangeException);
+}
+
+- (void)testInternalResizing {
+ const int64_t kValues[] = { 31LL, 32LL, 33LL, 34LL };
+ GPBInt64Array *array =
+ [[GPBInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ // Add/remove to trigger the intneral buffer to grow/shrink.
+ for (int i = 0; i < 100; ++i) {
+ [array addValues:kValues count:GPBARRAYSIZE(kValues)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ for (int i = 0; i < 100; ++i) {
+ [array removeValueAtIndex:(i * 2)];
+ }
+ XCTAssertEqual(array.count, 304U);
+ for (int i = 0; i < 100; ++i) {
+ [array insertValue:34LL atIndex:(i * 3)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_TESTS(UInt64, uint64_t, 41ULL, 42ULL, 43ULL, 44ULL)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - UInt64
+
+@interface GPBUInt64ArrayTests : XCTestCase
+@end
+
+@implementation GPBUInt64ArrayTests
+
+- (void)testEmpty {
+ GPBUInt64Array *array = [[GPBUInt64Array alloc] init];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array release];
+}
+
+- (void)testOne {
+ GPBUInt64Array *array = [GPBUInt64Array arrayWithValue:41ULL];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 1U);
+ XCTAssertEqual([array valueAtIndex:0], 41ULL);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:1], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 41ULL);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 41ULL);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ static const uint64_t kValues[] = { 41ULL, 42ULL, 43ULL, 44ULL };
+ GPBUInt64Array *array =
+ [[GPBUInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 41ULL);
+ XCTAssertEqual([array valueAtIndex:1], 42ULL);
+ XCTAssertEqual([array valueAtIndex:2], 43ULL);
+ XCTAssertEqual([array valueAtIndex:3], 44ULL);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:4], NSException, NSRangeException);
+ __block NSUInteger idx2 = 0;
+ [array enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ // Stopping the enumeration.
+ idx2 = 0;
+ [array enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ XCTAssertNotEqual(idx, 3U);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 1U);
+ XCTAssertNotEqual(idx, 0U);
+ ++idx2;
+ }];
+ [array release];
+}
+
+- (void)testEquality {
+ const uint64_t kValues1[] = { 41ULL, 42ULL, 43ULL };
+ const uint64_t kValues2[] = { 41ULL, 44ULL, 43ULL };
+ const uint64_t kValues3[] = { 41ULL, 42ULL, 43ULL, 44ULL };
+ GPBUInt64Array *array1 =
+ [[GPBUInt64Array alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1);
+ GPBUInt64Array *array1prime =
+ [[GPBUInt64Array alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1prime);
+ GPBUInt64Array *array2 =
+ [[GPBUInt64Array alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ GPBUInt64Array *array3 =
+ [[GPBUInt64Array alloc] initWithValues:kValues3
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(array3);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(array1, array1prime);
+ XCTAssertEqualObjects(array1, array1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([array1 hash], [array1prime hash]);
+
+ // 1/2/3 shouldn't be equal.
+ XCTAssertNotEqualObjects(array1, array2);
+ XCTAssertNotEqualObjects(array1, array3);
+ XCTAssertNotEqualObjects(array2, array3);
+
+ [array1 release];
+ [array1prime release];
+ [array2 release];
+ [array3 release];
+}
+
+- (void)testCopy {
+ const uint64_t kValues[] = { 41ULL, 42ULL, 43ULL, 44ULL };
+ GPBUInt64Array *array =
+ [[GPBUInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBUInt64Array *array2 = [array copy];
+ XCTAssertNotNil(array2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testArrayFromArray {
+ const uint64_t kValues[] = { 41ULL, 42ULL, 43ULL, 44ULL };
+ GPBUInt64Array *array =
+ [[GPBUInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBUInt64Array *array2 = [GPBUInt64Array arrayWithValueArray:array];
+ XCTAssertNotNil(array2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testAdds {
+ GPBUInt64Array *array = [GPBUInt64Array array];
+ XCTAssertNotNil(array);
+
+ XCTAssertEqual(array.count, 0U);
+ [array addValue:41ULL];
+ XCTAssertEqual(array.count, 1U);
+
+ const uint64_t kValues1[] = { 42ULL, 43ULL };
+ [array addValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+ XCTAssertEqual(array.count, 3U);
+
+ const uint64_t kValues2[] = { 44ULL, 41ULL };
+ GPBUInt64Array *array2 =
+ [[GPBUInt64Array alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ [array addValuesFromArray:array2];
+ XCTAssertEqual(array.count, 5U);
+
+ XCTAssertEqual([array valueAtIndex:0], 41ULL);
+ XCTAssertEqual([array valueAtIndex:1], 42ULL);
+ XCTAssertEqual([array valueAtIndex:2], 43ULL);
+ XCTAssertEqual([array valueAtIndex:3], 44ULL);
+ XCTAssertEqual([array valueAtIndex:4], 41ULL);
+}
+
+- (void)testInsert {
+ const uint64_t kValues[] = { 41ULL, 42ULL, 43ULL };
+ GPBUInt64Array *array =
+ [[GPBUInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 3U);
+
+ // First
+ [array insertValue:44ULL atIndex:0];
+ XCTAssertEqual(array.count, 4U);
+
+ // Middle
+ [array insertValue:44ULL atIndex:2];
+ XCTAssertEqual(array.count, 5U);
+
+ // End
+ [array insertValue:44ULL atIndex:5];
+ XCTAssertEqual(array.count, 6U);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array insertValue:44ULL atIndex:7],
+ NSException, NSRangeException);
+
+ XCTAssertEqual([array valueAtIndex:0], 44ULL);
+ XCTAssertEqual([array valueAtIndex:1], 41ULL);
+ XCTAssertEqual([array valueAtIndex:2], 44ULL);
+ XCTAssertEqual([array valueAtIndex:3], 42ULL);
+ XCTAssertEqual([array valueAtIndex:4], 43ULL);
+ XCTAssertEqual([array valueAtIndex:5], 44ULL);
+}
+
+- (void)testRemove {
+ const uint64_t kValues[] = { 44ULL, 41ULL, 42ULL, 44ULL, 43ULL, 44ULL };
+ GPBUInt64Array *array =
+ [[GPBUInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 6U);
+
+ // First
+ [array removeValueAtIndex:0];
+ XCTAssertEqual(array.count, 5U);
+ XCTAssertEqual([array valueAtIndex:0], 41ULL);
+
+ // Middle
+ [array removeValueAtIndex:2];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:2], 43ULL);
+
+ // End
+ [array removeValueAtIndex:3];
+ XCTAssertEqual(array.count, 3U);
+
+ XCTAssertEqual([array valueAtIndex:0], 41ULL);
+ XCTAssertEqual([array valueAtIndex:1], 42ULL);
+ XCTAssertEqual([array valueAtIndex:2], 43ULL);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:3],
+ NSException, NSRangeException);
+
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0],
+ NSException, NSRangeException);
+}
+
+- (void)testInplaceMutation {
+ const uint64_t kValues[] = { 41ULL, 41ULL, 43ULL, 43ULL };
+ GPBUInt64Array *array =
+ [[GPBUInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ [array replaceValueAtIndex:1 withValue:42ULL];
+ [array replaceValueAtIndex:3 withValue:44ULL];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 41ULL);
+ XCTAssertEqual([array valueAtIndex:1], 42ULL);
+ XCTAssertEqual([array valueAtIndex:2], 43ULL);
+ XCTAssertEqual([array valueAtIndex:3], 44ULL);
+
+ XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withValue:44ULL],
+ NSException, NSRangeException);
+
+ [array exchangeValueAtIndex:1 withValueAtIndex:3];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 41ULL);
+ XCTAssertEqual([array valueAtIndex:1], 44ULL);
+ XCTAssertEqual([array valueAtIndex:2], 43ULL);
+ XCTAssertEqual([array valueAtIndex:3], 42ULL);
+
+ [array exchangeValueAtIndex:2 withValueAtIndex:0];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 43ULL);
+ XCTAssertEqual([array valueAtIndex:1], 44ULL);
+ XCTAssertEqual([array valueAtIndex:2], 41ULL);
+ XCTAssertEqual([array valueAtIndex:3], 42ULL);
+
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:4 withValueAtIndex:1],
+ NSException, NSRangeException);
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4],
+ NSException, NSRangeException);
+}
+
+- (void)testInternalResizing {
+ const uint64_t kValues[] = { 41ULL, 42ULL, 43ULL, 44ULL };
+ GPBUInt64Array *array =
+ [[GPBUInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ // Add/remove to trigger the intneral buffer to grow/shrink.
+ for (int i = 0; i < 100; ++i) {
+ [array addValues:kValues count:GPBARRAYSIZE(kValues)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ for (int i = 0; i < 100; ++i) {
+ [array removeValueAtIndex:(i * 2)];
+ }
+ XCTAssertEqual(array.count, 304U);
+ for (int i = 0; i < 100; ++i) {
+ [array insertValue:44ULL atIndex:(i * 3)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_TESTS(Float, float, 51.f, 52.f, 53.f, 54.f)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Float
+
+@interface GPBFloatArrayTests : XCTestCase
+@end
+
+@implementation GPBFloatArrayTests
+
+- (void)testEmpty {
+ GPBFloatArray *array = [[GPBFloatArray alloc] init];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(float value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array release];
+}
+
+- (void)testOne {
+ GPBFloatArray *array = [GPBFloatArray arrayWithValue:51.f];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 1U);
+ XCTAssertEqual([array valueAtIndex:0], 51.f);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:1], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 51.f);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(float value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 51.f);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ static const float kValues[] = { 51.f, 52.f, 53.f, 54.f };
+ GPBFloatArray *array =
+ [[GPBFloatArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 51.f);
+ XCTAssertEqual([array valueAtIndex:1], 52.f);
+ XCTAssertEqual([array valueAtIndex:2], 53.f);
+ XCTAssertEqual([array valueAtIndex:3], 54.f);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:4], NSException, NSRangeException);
+ __block NSUInteger idx2 = 0;
+ [array enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(float value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ // Stopping the enumeration.
+ idx2 = 0;
+ [array enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ XCTAssertNotEqual(idx, 3U);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(float value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 1U);
+ XCTAssertNotEqual(idx, 0U);
+ ++idx2;
+ }];
+ [array release];
+}
+
+- (void)testEquality {
+ const float kValues1[] = { 51.f, 52.f, 53.f };
+ const float kValues2[] = { 51.f, 54.f, 53.f };
+ const float kValues3[] = { 51.f, 52.f, 53.f, 54.f };
+ GPBFloatArray *array1 =
+ [[GPBFloatArray alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1);
+ GPBFloatArray *array1prime =
+ [[GPBFloatArray alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1prime);
+ GPBFloatArray *array2 =
+ [[GPBFloatArray alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ GPBFloatArray *array3 =
+ [[GPBFloatArray alloc] initWithValues:kValues3
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(array3);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(array1, array1prime);
+ XCTAssertEqualObjects(array1, array1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([array1 hash], [array1prime hash]);
+
+ // 1/2/3 shouldn't be equal.
+ XCTAssertNotEqualObjects(array1, array2);
+ XCTAssertNotEqualObjects(array1, array3);
+ XCTAssertNotEqualObjects(array2, array3);
+
+ [array1 release];
+ [array1prime release];
+ [array2 release];
+ [array3 release];
+}
+
+- (void)testCopy {
+ const float kValues[] = { 51.f, 52.f, 53.f, 54.f };
+ GPBFloatArray *array =
+ [[GPBFloatArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBFloatArray *array2 = [array copy];
+ XCTAssertNotNil(array2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testArrayFromArray {
+ const float kValues[] = { 51.f, 52.f, 53.f, 54.f };
+ GPBFloatArray *array =
+ [[GPBFloatArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBFloatArray *array2 = [GPBFloatArray arrayWithValueArray:array];
+ XCTAssertNotNil(array2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testAdds {
+ GPBFloatArray *array = [GPBFloatArray array];
+ XCTAssertNotNil(array);
+
+ XCTAssertEqual(array.count, 0U);
+ [array addValue:51.f];
+ XCTAssertEqual(array.count, 1U);
+
+ const float kValues1[] = { 52.f, 53.f };
+ [array addValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+ XCTAssertEqual(array.count, 3U);
+
+ const float kValues2[] = { 54.f, 51.f };
+ GPBFloatArray *array2 =
+ [[GPBFloatArray alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ [array addValuesFromArray:array2];
+ XCTAssertEqual(array.count, 5U);
+
+ XCTAssertEqual([array valueAtIndex:0], 51.f);
+ XCTAssertEqual([array valueAtIndex:1], 52.f);
+ XCTAssertEqual([array valueAtIndex:2], 53.f);
+ XCTAssertEqual([array valueAtIndex:3], 54.f);
+ XCTAssertEqual([array valueAtIndex:4], 51.f);
+}
+
+- (void)testInsert {
+ const float kValues[] = { 51.f, 52.f, 53.f };
+ GPBFloatArray *array =
+ [[GPBFloatArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 3U);
+
+ // First
+ [array insertValue:54.f atIndex:0];
+ XCTAssertEqual(array.count, 4U);
+
+ // Middle
+ [array insertValue:54.f atIndex:2];
+ XCTAssertEqual(array.count, 5U);
+
+ // End
+ [array insertValue:54.f atIndex:5];
+ XCTAssertEqual(array.count, 6U);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array insertValue:54.f atIndex:7],
+ NSException, NSRangeException);
+
+ XCTAssertEqual([array valueAtIndex:0], 54.f);
+ XCTAssertEqual([array valueAtIndex:1], 51.f);
+ XCTAssertEqual([array valueAtIndex:2], 54.f);
+ XCTAssertEqual([array valueAtIndex:3], 52.f);
+ XCTAssertEqual([array valueAtIndex:4], 53.f);
+ XCTAssertEqual([array valueAtIndex:5], 54.f);
+}
+
+- (void)testRemove {
+ const float kValues[] = { 54.f, 51.f, 52.f, 54.f, 53.f, 54.f };
+ GPBFloatArray *array =
+ [[GPBFloatArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 6U);
+
+ // First
+ [array removeValueAtIndex:0];
+ XCTAssertEqual(array.count, 5U);
+ XCTAssertEqual([array valueAtIndex:0], 51.f);
+
+ // Middle
+ [array removeValueAtIndex:2];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:2], 53.f);
+
+ // End
+ [array removeValueAtIndex:3];
+ XCTAssertEqual(array.count, 3U);
+
+ XCTAssertEqual([array valueAtIndex:0], 51.f);
+ XCTAssertEqual([array valueAtIndex:1], 52.f);
+ XCTAssertEqual([array valueAtIndex:2], 53.f);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:3],
+ NSException, NSRangeException);
+
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0],
+ NSException, NSRangeException);
+}
+
+- (void)testInplaceMutation {
+ const float kValues[] = { 51.f, 51.f, 53.f, 53.f };
+ GPBFloatArray *array =
+ [[GPBFloatArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ [array replaceValueAtIndex:1 withValue:52.f];
+ [array replaceValueAtIndex:3 withValue:54.f];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 51.f);
+ XCTAssertEqual([array valueAtIndex:1], 52.f);
+ XCTAssertEqual([array valueAtIndex:2], 53.f);
+ XCTAssertEqual([array valueAtIndex:3], 54.f);
+
+ XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withValue:54.f],
+ NSException, NSRangeException);
+
+ [array exchangeValueAtIndex:1 withValueAtIndex:3];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 51.f);
+ XCTAssertEqual([array valueAtIndex:1], 54.f);
+ XCTAssertEqual([array valueAtIndex:2], 53.f);
+ XCTAssertEqual([array valueAtIndex:3], 52.f);
+
+ [array exchangeValueAtIndex:2 withValueAtIndex:0];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 53.f);
+ XCTAssertEqual([array valueAtIndex:1], 54.f);
+ XCTAssertEqual([array valueAtIndex:2], 51.f);
+ XCTAssertEqual([array valueAtIndex:3], 52.f);
+
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:4 withValueAtIndex:1],
+ NSException, NSRangeException);
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4],
+ NSException, NSRangeException);
+}
+
+- (void)testInternalResizing {
+ const float kValues[] = { 51.f, 52.f, 53.f, 54.f };
+ GPBFloatArray *array =
+ [[GPBFloatArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ // Add/remove to trigger the intneral buffer to grow/shrink.
+ for (int i = 0; i < 100; ++i) {
+ [array addValues:kValues count:GPBARRAYSIZE(kValues)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ for (int i = 0; i < 100; ++i) {
+ [array removeValueAtIndex:(i * 2)];
+ }
+ XCTAssertEqual(array.count, 304U);
+ for (int i = 0; i < 100; ++i) {
+ [array insertValue:54.f atIndex:(i * 3)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_TESTS(Double, double, 61., 62., 63., 64.)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Double
+
+@interface GPBDoubleArrayTests : XCTestCase
+@end
+
+@implementation GPBDoubleArrayTests
+
+- (void)testEmpty {
+ GPBDoubleArray *array = [[GPBDoubleArray alloc] init];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(double value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array release];
+}
+
+- (void)testOne {
+ GPBDoubleArray *array = [GPBDoubleArray arrayWithValue:61.];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 1U);
+ XCTAssertEqual([array valueAtIndex:0], 61.);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:1], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 61.);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(double value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 61.);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ static const double kValues[] = { 61., 62., 63., 64. };
+ GPBDoubleArray *array =
+ [[GPBDoubleArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 61.);
+ XCTAssertEqual([array valueAtIndex:1], 62.);
+ XCTAssertEqual([array valueAtIndex:2], 63.);
+ XCTAssertEqual([array valueAtIndex:3], 64.);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:4], NSException, NSRangeException);
+ __block NSUInteger idx2 = 0;
+ [array enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(double value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ // Stopping the enumeration.
+ idx2 = 0;
+ [array enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ XCTAssertNotEqual(idx, 3U);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(double value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 1U);
+ XCTAssertNotEqual(idx, 0U);
+ ++idx2;
+ }];
+ [array release];
+}
+
+- (void)testEquality {
+ const double kValues1[] = { 61., 62., 63. };
+ const double kValues2[] = { 61., 64., 63. };
+ const double kValues3[] = { 61., 62., 63., 64. };
+ GPBDoubleArray *array1 =
+ [[GPBDoubleArray alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1);
+ GPBDoubleArray *array1prime =
+ [[GPBDoubleArray alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1prime);
+ GPBDoubleArray *array2 =
+ [[GPBDoubleArray alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ GPBDoubleArray *array3 =
+ [[GPBDoubleArray alloc] initWithValues:kValues3
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(array3);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(array1, array1prime);
+ XCTAssertEqualObjects(array1, array1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([array1 hash], [array1prime hash]);
+
+ // 1/2/3 shouldn't be equal.
+ XCTAssertNotEqualObjects(array1, array2);
+ XCTAssertNotEqualObjects(array1, array3);
+ XCTAssertNotEqualObjects(array2, array3);
+
+ [array1 release];
+ [array1prime release];
+ [array2 release];
+ [array3 release];
+}
+
+- (void)testCopy {
+ const double kValues[] = { 61., 62., 63., 64. };
+ GPBDoubleArray *array =
+ [[GPBDoubleArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBDoubleArray *array2 = [array copy];
+ XCTAssertNotNil(array2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testArrayFromArray {
+ const double kValues[] = { 61., 62., 63., 64. };
+ GPBDoubleArray *array =
+ [[GPBDoubleArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBDoubleArray *array2 = [GPBDoubleArray arrayWithValueArray:array];
+ XCTAssertNotNil(array2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testAdds {
+ GPBDoubleArray *array = [GPBDoubleArray array];
+ XCTAssertNotNil(array);
+
+ XCTAssertEqual(array.count, 0U);
+ [array addValue:61.];
+ XCTAssertEqual(array.count, 1U);
+
+ const double kValues1[] = { 62., 63. };
+ [array addValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+ XCTAssertEqual(array.count, 3U);
+
+ const double kValues2[] = { 64., 61. };
+ GPBDoubleArray *array2 =
+ [[GPBDoubleArray alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ [array addValuesFromArray:array2];
+ XCTAssertEqual(array.count, 5U);
+
+ XCTAssertEqual([array valueAtIndex:0], 61.);
+ XCTAssertEqual([array valueAtIndex:1], 62.);
+ XCTAssertEqual([array valueAtIndex:2], 63.);
+ XCTAssertEqual([array valueAtIndex:3], 64.);
+ XCTAssertEqual([array valueAtIndex:4], 61.);
+}
+
+- (void)testInsert {
+ const double kValues[] = { 61., 62., 63. };
+ GPBDoubleArray *array =
+ [[GPBDoubleArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 3U);
+
+ // First
+ [array insertValue:64. atIndex:0];
+ XCTAssertEqual(array.count, 4U);
+
+ // Middle
+ [array insertValue:64. atIndex:2];
+ XCTAssertEqual(array.count, 5U);
+
+ // End
+ [array insertValue:64. atIndex:5];
+ XCTAssertEqual(array.count, 6U);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array insertValue:64. atIndex:7],
+ NSException, NSRangeException);
+
+ XCTAssertEqual([array valueAtIndex:0], 64.);
+ XCTAssertEqual([array valueAtIndex:1], 61.);
+ XCTAssertEqual([array valueAtIndex:2], 64.);
+ XCTAssertEqual([array valueAtIndex:3], 62.);
+ XCTAssertEqual([array valueAtIndex:4], 63.);
+ XCTAssertEqual([array valueAtIndex:5], 64.);
+}
+
+- (void)testRemove {
+ const double kValues[] = { 64., 61., 62., 64., 63., 64. };
+ GPBDoubleArray *array =
+ [[GPBDoubleArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 6U);
+
+ // First
+ [array removeValueAtIndex:0];
+ XCTAssertEqual(array.count, 5U);
+ XCTAssertEqual([array valueAtIndex:0], 61.);
+
+ // Middle
+ [array removeValueAtIndex:2];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:2], 63.);
+
+ // End
+ [array removeValueAtIndex:3];
+ XCTAssertEqual(array.count, 3U);
+
+ XCTAssertEqual([array valueAtIndex:0], 61.);
+ XCTAssertEqual([array valueAtIndex:1], 62.);
+ XCTAssertEqual([array valueAtIndex:2], 63.);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:3],
+ NSException, NSRangeException);
+
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0],
+ NSException, NSRangeException);
+}
+
+- (void)testInplaceMutation {
+ const double kValues[] = { 61., 61., 63., 63. };
+ GPBDoubleArray *array =
+ [[GPBDoubleArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ [array replaceValueAtIndex:1 withValue:62.];
+ [array replaceValueAtIndex:3 withValue:64.];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 61.);
+ XCTAssertEqual([array valueAtIndex:1], 62.);
+ XCTAssertEqual([array valueAtIndex:2], 63.);
+ XCTAssertEqual([array valueAtIndex:3], 64.);
+
+ XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withValue:64.],
+ NSException, NSRangeException);
+
+ [array exchangeValueAtIndex:1 withValueAtIndex:3];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 61.);
+ XCTAssertEqual([array valueAtIndex:1], 64.);
+ XCTAssertEqual([array valueAtIndex:2], 63.);
+ XCTAssertEqual([array valueAtIndex:3], 62.);
+
+ [array exchangeValueAtIndex:2 withValueAtIndex:0];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 63.);
+ XCTAssertEqual([array valueAtIndex:1], 64.);
+ XCTAssertEqual([array valueAtIndex:2], 61.);
+ XCTAssertEqual([array valueAtIndex:3], 62.);
+
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:4 withValueAtIndex:1],
+ NSException, NSRangeException);
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4],
+ NSException, NSRangeException);
+}
+
+- (void)testInternalResizing {
+ const double kValues[] = { 61., 62., 63., 64. };
+ GPBDoubleArray *array =
+ [[GPBDoubleArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ // Add/remove to trigger the intneral buffer to grow/shrink.
+ for (int i = 0; i < 100; ++i) {
+ [array addValues:kValues count:GPBARRAYSIZE(kValues)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ for (int i = 0; i < 100; ++i) {
+ [array removeValueAtIndex:(i * 2)];
+ }
+ XCTAssertEqual(array.count, 304U);
+ for (int i = 0; i < 100; ++i) {
+ [array insertValue:64. atIndex:(i * 3)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_TESTS(Bool, BOOL, TRUE, TRUE, FALSE, FALSE)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool
+
+@interface GPBBoolArrayTests : XCTestCase
+@end
+
+@implementation GPBBoolArrayTests
+
+- (void)testEmpty {
+ GPBBoolArray *array = [[GPBBoolArray alloc] init];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array release];
+}
+
+- (void)testOne {
+ GPBBoolArray *array = [GPBBoolArray arrayWithValue:TRUE];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 1U);
+ XCTAssertEqual([array valueAtIndex:0], TRUE);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:1], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, TRUE);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, TRUE);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ static const BOOL kValues[] = { TRUE, TRUE, FALSE, FALSE };
+ GPBBoolArray *array =
+ [[GPBBoolArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], TRUE);
+ XCTAssertEqual([array valueAtIndex:1], TRUE);
+ XCTAssertEqual([array valueAtIndex:2], FALSE);
+ XCTAssertEqual([array valueAtIndex:3], FALSE);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:4], NSException, NSRangeException);
+ __block NSUInteger idx2 = 0;
+ [array enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ // Stopping the enumeration.
+ idx2 = 0;
+ [array enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ XCTAssertNotEqual(idx, 3U);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 1U);
+ XCTAssertNotEqual(idx, 0U);
+ ++idx2;
+ }];
+ [array release];
+}
+
+- (void)testEquality {
+ const BOOL kValues1[] = { TRUE, TRUE, FALSE };
+ const BOOL kValues2[] = { TRUE, FALSE, FALSE };
+ const BOOL kValues3[] = { TRUE, TRUE, FALSE, FALSE };
+ GPBBoolArray *array1 =
+ [[GPBBoolArray alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1);
+ GPBBoolArray *array1prime =
+ [[GPBBoolArray alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1prime);
+ GPBBoolArray *array2 =
+ [[GPBBoolArray alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ GPBBoolArray *array3 =
+ [[GPBBoolArray alloc] initWithValues:kValues3
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(array3);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(array1, array1prime);
+ XCTAssertEqualObjects(array1, array1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([array1 hash], [array1prime hash]);
+
+ // 1/2/3 shouldn't be equal.
+ XCTAssertNotEqualObjects(array1, array2);
+ XCTAssertNotEqualObjects(array1, array3);
+ XCTAssertNotEqualObjects(array2, array3);
+
+ [array1 release];
+ [array1prime release];
+ [array2 release];
+ [array3 release];
+}
+
+- (void)testCopy {
+ const BOOL kValues[] = { TRUE, TRUE, FALSE, FALSE };
+ GPBBoolArray *array =
+ [[GPBBoolArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBBoolArray *array2 = [array copy];
+ XCTAssertNotNil(array2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testArrayFromArray {
+ const BOOL kValues[] = { TRUE, TRUE, FALSE, FALSE };
+ GPBBoolArray *array =
+ [[GPBBoolArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBBoolArray *array2 = [GPBBoolArray arrayWithValueArray:array];
+ XCTAssertNotNil(array2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testAdds {
+ GPBBoolArray *array = [GPBBoolArray array];
+ XCTAssertNotNil(array);
+
+ XCTAssertEqual(array.count, 0U);
+ [array addValue:TRUE];
+ XCTAssertEqual(array.count, 1U);
+
+ const BOOL kValues1[] = { TRUE, FALSE };
+ [array addValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+ XCTAssertEqual(array.count, 3U);
+
+ const BOOL kValues2[] = { FALSE, TRUE };
+ GPBBoolArray *array2 =
+ [[GPBBoolArray alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ [array addValuesFromArray:array2];
+ XCTAssertEqual(array.count, 5U);
+
+ XCTAssertEqual([array valueAtIndex:0], TRUE);
+ XCTAssertEqual([array valueAtIndex:1], TRUE);
+ XCTAssertEqual([array valueAtIndex:2], FALSE);
+ XCTAssertEqual([array valueAtIndex:3], FALSE);
+ XCTAssertEqual([array valueAtIndex:4], TRUE);
+}
+
+- (void)testInsert {
+ const BOOL kValues[] = { TRUE, TRUE, FALSE };
+ GPBBoolArray *array =
+ [[GPBBoolArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 3U);
+
+ // First
+ [array insertValue:FALSE atIndex:0];
+ XCTAssertEqual(array.count, 4U);
+
+ // Middle
+ [array insertValue:FALSE atIndex:2];
+ XCTAssertEqual(array.count, 5U);
+
+ // End
+ [array insertValue:FALSE atIndex:5];
+ XCTAssertEqual(array.count, 6U);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array insertValue:FALSE atIndex:7],
+ NSException, NSRangeException);
+
+ XCTAssertEqual([array valueAtIndex:0], FALSE);
+ XCTAssertEqual([array valueAtIndex:1], TRUE);
+ XCTAssertEqual([array valueAtIndex:2], FALSE);
+ XCTAssertEqual([array valueAtIndex:3], TRUE);
+ XCTAssertEqual([array valueAtIndex:4], FALSE);
+ XCTAssertEqual([array valueAtIndex:5], FALSE);
+}
+
+- (void)testRemove {
+ const BOOL kValues[] = { FALSE, TRUE, TRUE, FALSE, FALSE, FALSE };
+ GPBBoolArray *array =
+ [[GPBBoolArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 6U);
+
+ // First
+ [array removeValueAtIndex:0];
+ XCTAssertEqual(array.count, 5U);
+ XCTAssertEqual([array valueAtIndex:0], TRUE);
+
+ // Middle
+ [array removeValueAtIndex:2];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:2], FALSE);
+
+ // End
+ [array removeValueAtIndex:3];
+ XCTAssertEqual(array.count, 3U);
+
+ XCTAssertEqual([array valueAtIndex:0], TRUE);
+ XCTAssertEqual([array valueAtIndex:1], TRUE);
+ XCTAssertEqual([array valueAtIndex:2], FALSE);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:3],
+ NSException, NSRangeException);
+
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0],
+ NSException, NSRangeException);
+}
+
+- (void)testInplaceMutation {
+ const BOOL kValues[] = { TRUE, TRUE, FALSE, FALSE };
+ GPBBoolArray *array =
+ [[GPBBoolArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ [array replaceValueAtIndex:1 withValue:TRUE];
+ [array replaceValueAtIndex:3 withValue:FALSE];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], TRUE);
+ XCTAssertEqual([array valueAtIndex:1], TRUE);
+ XCTAssertEqual([array valueAtIndex:2], FALSE);
+ XCTAssertEqual([array valueAtIndex:3], FALSE);
+
+ XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withValue:FALSE],
+ NSException, NSRangeException);
+
+ [array exchangeValueAtIndex:1 withValueAtIndex:3];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], TRUE);
+ XCTAssertEqual([array valueAtIndex:1], FALSE);
+ XCTAssertEqual([array valueAtIndex:2], FALSE);
+ XCTAssertEqual([array valueAtIndex:3], TRUE);
+
+ [array exchangeValueAtIndex:2 withValueAtIndex:0];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], FALSE);
+ XCTAssertEqual([array valueAtIndex:1], FALSE);
+ XCTAssertEqual([array valueAtIndex:2], TRUE);
+ XCTAssertEqual([array valueAtIndex:3], TRUE);
+
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:4 withValueAtIndex:1],
+ NSException, NSRangeException);
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4],
+ NSException, NSRangeException);
+}
+
+- (void)testInternalResizing {
+ const BOOL kValues[] = { TRUE, TRUE, FALSE, FALSE };
+ GPBBoolArray *array =
+ [[GPBBoolArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ // Add/remove to trigger the intneral buffer to grow/shrink.
+ for (int i = 0; i < 100; ++i) {
+ [array addValues:kValues count:GPBARRAYSIZE(kValues)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ for (int i = 0; i < 100; ++i) {
+ [array removeValueAtIndex:(i * 2)];
+ }
+ XCTAssertEqual(array.count, 304U);
+ for (int i = 0; i < 100; ++i) {
+ [array insertValue:FALSE atIndex:(i * 3)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_TESTS2(Enum, int32_t, 71, 72, 73, 74, Raw)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Enum
+
+@interface GPBEnumArrayTests : XCTestCase
+@end
+
+@implementation GPBEnumArrayTests
+
+- (void)testEmpty {
+ GPBEnumArray *array = [[GPBEnumArray alloc] init];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array release];
+}
+
+- (void)testOne {
+ GPBEnumArray *array = [GPBEnumArray arrayWithValue:71];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 1U);
+ XCTAssertEqual([array valueAtIndex:0], 71);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:1], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 71);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 71);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ static const int32_t kValues[] = { 71, 72, 73, 74 };
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 71);
+ XCTAssertEqual([array valueAtIndex:1], 72);
+ XCTAssertEqual([array valueAtIndex:2], 73);
+ XCTAssertEqual([array valueAtIndex:3], 74);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:4], NSException, NSRangeException);
+ __block NSUInteger idx2 = 0;
+ [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ // Stopping the enumeration.
+ idx2 = 0;
+ [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ XCTAssertNotEqual(idx, 3U);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 1U);
+ XCTAssertNotEqual(idx, 0U);
+ ++idx2;
+ }];
+ [array release];
+}
+
+- (void)testEquality {
+ const int32_t kValues1[] = { 71, 72, 73 };
+ const int32_t kValues2[] = { 71, 74, 73 };
+ const int32_t kValues3[] = { 71, 72, 73, 74 };
+ GPBEnumArray *array1 =
+ [[GPBEnumArray alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1);
+ GPBEnumArray *array1prime =
+ [[GPBEnumArray alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1prime);
+ GPBEnumArray *array2 =
+ [[GPBEnumArray alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ GPBEnumArray *array3 =
+ [[GPBEnumArray alloc] initWithValues:kValues3
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(array3);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(array1, array1prime);
+ XCTAssertEqualObjects(array1, array1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([array1 hash], [array1prime hash]);
+
+ // 1/2/3 shouldn't be equal.
+ XCTAssertNotEqualObjects(array1, array2);
+ XCTAssertNotEqualObjects(array1, array3);
+ XCTAssertNotEqualObjects(array2, array3);
+
+ [array1 release];
+ [array1prime release];
+ [array2 release];
+ [array3 release];
+}
+
+- (void)testCopy {
+ const int32_t kValues[] = { 71, 72, 73, 74 };
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBEnumArray *array2 = [array copy];
+ XCTAssertNotNil(array2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testArrayFromArray {
+ const int32_t kValues[] = { 71, 72, 73, 74 };
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBEnumArray *array2 = [GPBEnumArray arrayWithValueArray:array];
+ XCTAssertNotNil(array2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testAdds {
+ GPBEnumArray *array = [GPBEnumArray array];
+ XCTAssertNotNil(array);
+
+ XCTAssertEqual(array.count, 0U);
+ [array addValue:71];
+ XCTAssertEqual(array.count, 1U);
+
+ const int32_t kValues1[] = { 72, 73 };
+ [array addValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+ XCTAssertEqual(array.count, 3U);
+
+ const int32_t kValues2[] = { 74, 71 };
+ GPBEnumArray *array2 =
+ [[GPBEnumArray alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ [array addRawValuesFromArray:array2];
+ XCTAssertEqual(array.count, 5U);
+
+ XCTAssertEqual([array valueAtIndex:0], 71);
+ XCTAssertEqual([array valueAtIndex:1], 72);
+ XCTAssertEqual([array valueAtIndex:2], 73);
+ XCTAssertEqual([array valueAtIndex:3], 74);
+ XCTAssertEqual([array valueAtIndex:4], 71);
+}
+
+- (void)testInsert {
+ const int32_t kValues[] = { 71, 72, 73 };
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 3U);
+
+ // First
+ [array insertValue:74 atIndex:0];
+ XCTAssertEqual(array.count, 4U);
+
+ // Middle
+ [array insertValue:74 atIndex:2];
+ XCTAssertEqual(array.count, 5U);
+
+ // End
+ [array insertValue:74 atIndex:5];
+ XCTAssertEqual(array.count, 6U);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array insertValue:74 atIndex:7],
+ NSException, NSRangeException);
+
+ XCTAssertEqual([array valueAtIndex:0], 74);
+ XCTAssertEqual([array valueAtIndex:1], 71);
+ XCTAssertEqual([array valueAtIndex:2], 74);
+ XCTAssertEqual([array valueAtIndex:3], 72);
+ XCTAssertEqual([array valueAtIndex:4], 73);
+ XCTAssertEqual([array valueAtIndex:5], 74);
+}
+
+- (void)testRemove {
+ const int32_t kValues[] = { 74, 71, 72, 74, 73, 74 };
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 6U);
+
+ // First
+ [array removeValueAtIndex:0];
+ XCTAssertEqual(array.count, 5U);
+ XCTAssertEqual([array valueAtIndex:0], 71);
+
+ // Middle
+ [array removeValueAtIndex:2];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:2], 73);
+
+ // End
+ [array removeValueAtIndex:3];
+ XCTAssertEqual(array.count, 3U);
+
+ XCTAssertEqual([array valueAtIndex:0], 71);
+ XCTAssertEqual([array valueAtIndex:1], 72);
+ XCTAssertEqual([array valueAtIndex:2], 73);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:3],
+ NSException, NSRangeException);
+
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0],
+ NSException, NSRangeException);
+}
+
+- (void)testInplaceMutation {
+ const int32_t kValues[] = { 71, 71, 73, 73 };
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ [array replaceValueAtIndex:1 withValue:72];
+ [array replaceValueAtIndex:3 withValue:74];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 71);
+ XCTAssertEqual([array valueAtIndex:1], 72);
+ XCTAssertEqual([array valueAtIndex:2], 73);
+ XCTAssertEqual([array valueAtIndex:3], 74);
+
+ XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withValue:74],
+ NSException, NSRangeException);
+
+ [array exchangeValueAtIndex:1 withValueAtIndex:3];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 71);
+ XCTAssertEqual([array valueAtIndex:1], 74);
+ XCTAssertEqual([array valueAtIndex:2], 73);
+ XCTAssertEqual([array valueAtIndex:3], 72);
+
+ [array exchangeValueAtIndex:2 withValueAtIndex:0];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 73);
+ XCTAssertEqual([array valueAtIndex:1], 74);
+ XCTAssertEqual([array valueAtIndex:2], 71);
+ XCTAssertEqual([array valueAtIndex:3], 72);
+
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:4 withValueAtIndex:1],
+ NSException, NSRangeException);
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4],
+ NSException, NSRangeException);
+}
+
+- (void)testInternalResizing {
+ const int32_t kValues[] = { 71, 72, 73, 74 };
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ // Add/remove to trigger the intneral buffer to grow/shrink.
+ for (int i = 0; i < 100; ++i) {
+ [array addValues:kValues count:GPBARRAYSIZE(kValues)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ for (int i = 0; i < 100; ++i) {
+ [array removeValueAtIndex:(i * 2)];
+ }
+ XCTAssertEqual(array.count, 304U);
+ for (int i = 0; i < 100; ++i) {
+ [array insertValue:74 atIndex:(i * 3)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+}
+
+@end
+
+//%PDDM-EXPAND-END (8 expansions)
+
+#pragma mark - Non macro-based Enum tests
+
+// These are hand written tests to cover the verification and raw methods.
+
+@interface GPBEnumArrayCustomTests : XCTestCase
+@end
+
+@implementation GPBEnumArrayCustomTests
+
+- (void)testRawBasics {
+ static const int32_t kValues[] = { 71, 272, 73, 374 };
+ static const int32_t kValuesFiltered[] = {
+ 71, kGPBUnrecognizedEnumeratorValue, 73, kGPBUnrecognizedEnumeratorValue
+ };
+ XCTAssertEqual(GPBARRAYSIZE(kValues), GPBARRAYSIZE(kValuesFiltered));
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 4U);
+ GPBEnumValidationFunc func = TestingEnum_IsValidValue;
+ XCTAssertEqual(array.validationFunc, func);
+ XCTAssertEqual([array rawValueAtIndex:0], 71);
+ XCTAssertEqual([array rawValueAtIndex:1], 272);
+ XCTAssertEqual([array valueAtIndex:1], kGPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual([array rawValueAtIndex:2], 73);
+ XCTAssertEqual([array rawValueAtIndex:3], 374);
+ XCTAssertEqual([array valueAtIndex:3], kGPBUnrecognizedEnumeratorValue);
+ XCTAssertThrowsSpecificNamed([array rawValueAtIndex:4], NSException, NSRangeException);
+ __block NSUInteger idx2 = 0;
+ [array enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValuesFiltered[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateRawValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValuesFiltered[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ // Stopping the enumeration.
+ idx2 = 0;
+ [array enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ XCTAssertNotEqual(idx, 3U);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateRawValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 1U);
+ XCTAssertNotEqual(idx, 0U);
+ ++idx2;
+ }];
+ [array release];
+}
+
+- (void)testEquality {
+ const int32_t kValues1[] = { 71, 72, 173 }; // With unknown value
+ const int32_t kValues2[] = { 71, 74, 173 }; // With unknown value
+ const int32_t kValues3[] = { 71, 72, 173, 74 }; // With unknown value
+ GPBEnumArray *array1 =
+ [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1);
+ GPBEnumArray *array1prime =
+ [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue2
+ rawValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1prime);
+ GPBEnumArray *array2 =
+ [[GPBEnumArray alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ GPBEnumArray *array3 =
+ [[GPBEnumArray alloc] initWithValues:kValues3
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(array3);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(array1, array1prime);
+ XCTAssertEqualObjects(array1, array1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([array1 hash], [array1prime hash]);
+ // But different validation functions.
+ XCTAssertNotEqual(array1.validationFunc, array1prime.validationFunc);
+
+ // 1/2/3 shouldn't be equal.
+ XCTAssertNotEqualObjects(array1, array2);
+ XCTAssertNotEqualObjects(array1, array3);
+ XCTAssertNotEqualObjects(array2, array3);
+
+ [array1 release];
+ [array1prime release];
+ [array2 release];
+ [array3 release];
+}
+
+- (void)testCopy {
+ const int32_t kValues[] = { 71, 72 };
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ [array addRawValue:1000]; // Unknown
+ XCTAssertEqual(array.count, 3U);
+ XCTAssertEqual([array rawValueAtIndex:0], 71);
+ XCTAssertEqual([array rawValueAtIndex:1], 72);
+ XCTAssertEqual([array rawValueAtIndex:2], 1000);
+ XCTAssertEqual([array valueAtIndex:2], kGPBUnrecognizedEnumeratorValue);
+
+ GPBEnumArray *array2 = [array copy];
+ XCTAssertNotNil(array2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+ XCTAssertEqual(array.validationFunc, array2.validationFunc);
+ XCTAssertTrue([array2 isKindOfClass:[GPBEnumArray class]]);
+ XCTAssertEqual(array2.count, 3U);
+ XCTAssertEqual([array2 rawValueAtIndex:0], 71);
+ XCTAssertEqual([array2 rawValueAtIndex:1], 72);
+ XCTAssertEqual([array2 rawValueAtIndex:2], 1000);
+ XCTAssertEqual([array2 valueAtIndex:2], kGPBUnrecognizedEnumeratorValue);
+}
+
+- (void)testArrayFromArray {
+ const int32_t kValues[] = { 71, 172, 173, 74 }; // Unknowns
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBEnumArray *array2 = [GPBEnumArray arrayWithValueArray:array];
+ XCTAssertNotNil(array2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+ XCTAssertEqual(array.validationFunc, array2.validationFunc);
+}
+
+- (void)testUnknownAdds {
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue];
+ XCTAssertNotNil(array);
+
+ XCTAssertThrowsSpecificNamed([array addValue:172],
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(array.count, 0U);
+
+ const int32_t kValues1[] = { 172, 173 }; // Unknown
+ XCTAssertThrowsSpecificNamed([array addValues:kValues1 count:GPBARRAYSIZE(kValues1)],
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(array.count, 0U);
+
+ [array release];
+}
+
+- (void)testRawAdds {
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue];
+ XCTAssertNotNil(array);
+
+ XCTAssertEqual(array.count, 0U);
+ [array addRawValue:71]; // Valid
+ XCTAssertEqual(array.count, 1U);
+
+ const int32_t kValues1[] = { 172, 173 }; // Unknown
+ [array addRawValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+ XCTAssertEqual(array.count, 3U);
+
+ const int32_t kValues2[] = { 74, 71 };
+ GPBEnumArray *array2 =
+ [[GPBEnumArray alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ [array addRawValuesFromArray:array2];
+ XCTAssertEqual(array.count, 5U);
+
+ XCTAssertEqual([array rawValueAtIndex:0], 71);
+ XCTAssertEqual([array rawValueAtIndex:1], 172);
+ XCTAssertEqual([array valueAtIndex:1], kGPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual([array rawValueAtIndex:2], 173);
+ XCTAssertEqual([array valueAtIndex:2], kGPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual([array rawValueAtIndex:3], 74);
+ XCTAssertEqual([array rawValueAtIndex:4], 71);
+
+ [array release];
+}
+
+- (void)testUnknownInserts {
+ const int32_t kValues[] = { 71, 72, 73 };
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 3U);
+
+ // First
+ XCTAssertThrowsSpecificNamed([array insertValue:174 atIndex:0],
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(array.count, 3U);
+
+ // Middle
+ XCTAssertThrowsSpecificNamed([array insertValue:274 atIndex:1],
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(array.count, 3U);
+
+ // End
+ XCTAssertThrowsSpecificNamed([array insertValue:374 atIndex:3],
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(array.count, 3U);
+}
+
+- (void)testRawInsert {
+ const int32_t kValues[] = { 71, 72, 73 };
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 3U);
+
+ // First
+ [array insertRawValue:174 atIndex:0]; // Unknown
+ XCTAssertEqual(array.count, 4U);
+
+ // Middle
+ [array insertRawValue:274 atIndex:2]; // Unknown
+ XCTAssertEqual(array.count, 5U);
+
+ // End
+ [array insertRawValue:374 atIndex:5]; // Unknown
+ XCTAssertEqual(array.count, 6U);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array insertRawValue:74 atIndex:7],
+ NSException, NSRangeException);
+
+ XCTAssertEqual([array rawValueAtIndex:0], 174);
+ XCTAssertEqual([array valueAtIndex:0], kGPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual([array rawValueAtIndex:1], 71);
+ XCTAssertEqual([array rawValueAtIndex:2], 274);
+ XCTAssertEqual([array valueAtIndex:2], kGPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual([array rawValueAtIndex:3], 72);
+ XCTAssertEqual([array rawValueAtIndex:4], 73);
+ XCTAssertEqual([array rawValueAtIndex:5], 374);
+ XCTAssertEqual([array valueAtIndex:5], kGPBUnrecognizedEnumeratorValue);
+
+ [array release];
+}
+
+- (void)testUnknownInplaceMutation {
+ const int32_t kValues[] = { 71, 72, 73, 74 };
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:1 withValue:172],
+ NSException, NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:3 withValue:274],
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 71);
+ XCTAssertEqual([array valueAtIndex:1], 72);
+ XCTAssertEqual([array valueAtIndex:2], 73);
+ XCTAssertEqual([array valueAtIndex:3], 74);
+}
+
+
+- (void)testRawInplaceMutation {
+ const int32_t kValues[] = { 71, 72, 73, 74 };
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ [array replaceValueAtIndex:1 withRawValue:172]; // Unknown
+ [array replaceValueAtIndex:3 withRawValue:274]; // Unknown
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array rawValueAtIndex:0], 71);
+ XCTAssertEqual([array rawValueAtIndex:1], 172);
+ XCTAssertEqual([array valueAtIndex:1], kGPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual([array rawValueAtIndex:2], 73);
+ XCTAssertEqual([array rawValueAtIndex:3], 274);
+ XCTAssertEqual([array valueAtIndex:3], kGPBUnrecognizedEnumeratorValue);
+
+ XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withRawValue:74],
+ NSException, NSRangeException);
+}
+
+- (void)testRawInternalResizing {
+ const int32_t kValues[] = { 71, 172, 173, 74 }; // Unknown
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ // Add/remove to trigger the intneral buffer to grow/shrink.
+ for (int i = 0; i < 100; ++i) {
+ [array addRawValues:kValues count:GPBARRAYSIZE(kValues)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ for (int i = 0; i < 100; ++i) {
+ [array removeValueAtIndex:(i * 2)];
+ }
+ XCTAssertEqual(array.count, 304U);
+ for (int i = 0; i < 100; ++i) {
+ [array insertRawValue:274 atIndex:(i * 3)]; // Unknown
+ }
+ XCTAssertEqual(array.count, 404U);
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+}
+
+@end
diff --git a/objectivec/Tests/GPBCodedInputStreamTests.m b/objectivec/Tests/GPBCodedInputStreamTests.m
new file mode 100644
index 00000000..0a709cbe
--- /dev/null
+++ b/objectivec/Tests/GPBCodedInputStreamTests.m
@@ -0,0 +1,290 @@
+// 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.
+
+#import "GPBTestUtilities.h"
+
+#import "GPBCodedInputStream.h"
+#import "GPBCodedOutputStream.h"
+#import "GPBUnknownFieldSet_PackagePrivate.h"
+#import "GPBUtilities_PackagePrivate.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+
+@interface CodedInputStreamTests : GPBTestCase
+@end
+
+@implementation CodedInputStreamTests
+
+- (NSData*)bytes_with_sentinel:(int32_t)unused, ... {
+ va_list list;
+ va_start(list, unused);
+
+ NSMutableData* values = [NSMutableData dataWithCapacity:0];
+ int32_t i;
+
+ while ((i = va_arg(list, int32_t)) != 256) {
+ NSAssert(i >= 0 && i < 256, @"");
+ uint8_t u = (uint8_t)i;
+ [values appendBytes:&u length:1];
+ }
+
+ va_end(list);
+
+ return values;
+}
+
+#define bytes(...) [self bytes_with_sentinel:0, __VA_ARGS__, 256]
+
+- (void)testDecodeZigZag {
+ XCTAssertEqual(0, GPBDecodeZigZag32(0));
+ XCTAssertEqual(-1, GPBDecodeZigZag32(1));
+ XCTAssertEqual(1, GPBDecodeZigZag32(2));
+ XCTAssertEqual(-2, GPBDecodeZigZag32(3));
+ XCTAssertEqual((int32_t)0x3FFFFFFF, GPBDecodeZigZag32(0x7FFFFFFE));
+ XCTAssertEqual((int32_t)0xC0000000, GPBDecodeZigZag32(0x7FFFFFFF));
+ XCTAssertEqual((int32_t)0x7FFFFFFF, GPBDecodeZigZag32(0xFFFFFFFE));
+ XCTAssertEqual((int32_t)0x80000000, GPBDecodeZigZag32(0xFFFFFFFF));
+
+ XCTAssertEqual((int64_t)0, GPBDecodeZigZag64(0));
+ XCTAssertEqual((int64_t)-1, GPBDecodeZigZag64(1));
+ XCTAssertEqual((int64_t)1, GPBDecodeZigZag64(2));
+ XCTAssertEqual((int64_t)-2, GPBDecodeZigZag64(3));
+ XCTAssertEqual((int64_t)0x000000003FFFFFFFL,
+ GPBDecodeZigZag64(0x000000007FFFFFFEL));
+ XCTAssertEqual((int64_t)0xFFFFFFFFC0000000L,
+ GPBDecodeZigZag64(0x000000007FFFFFFFL));
+ XCTAssertEqual((int64_t)0x000000007FFFFFFFL,
+ GPBDecodeZigZag64(0x00000000FFFFFFFEL));
+ XCTAssertEqual((int64_t)0xFFFFFFFF80000000L,
+ GPBDecodeZigZag64(0x00000000FFFFFFFFL));
+ XCTAssertEqual((int64_t)0x7FFFFFFFFFFFFFFFL,
+ GPBDecodeZigZag64(0xFFFFFFFFFFFFFFFEL));
+ XCTAssertEqual((int64_t)0x8000000000000000L,
+ GPBDecodeZigZag64(0xFFFFFFFFFFFFFFFFL));
+}
+
+- (void)assertReadVarint:(NSData*)data value:(int64_t)value {
+ {
+ GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
+ XCTAssertEqual((int32_t)value, [input readInt32]);
+ }
+ {
+ GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
+ XCTAssertEqual(value, [input readInt64]);
+ }
+}
+
+- (void)assertReadLittleEndian32:(NSData*)data value:(int32_t)value {
+ GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
+ XCTAssertEqual(value, [input readSFixed32]);
+}
+
+- (void)assertReadLittleEndian64:(NSData*)data value:(int64_t)value {
+ GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
+ XCTAssertEqual(value, [input readSFixed64]);
+}
+
+- (void)assertReadVarintFailure:(NSData*)data {
+ {
+ GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
+ XCTAssertThrows([input readInt32]);
+ }
+ {
+ GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
+ XCTAssertThrows([input readInt64]);
+ }
+}
+
+- (void)testBytes {
+ NSData* data = bytes(0xa2, 0x74);
+ XCTAssertEqual(data.length, (NSUInteger)2);
+ XCTAssertEqual(((uint8_t*)data.bytes)[0], (uint8_t)0xa2);
+ XCTAssertEqual(((uint8_t*)data.bytes)[1], (uint8_t)0x74);
+}
+
+- (void)testReadVarint {
+ [self assertReadVarint:bytes(0x00) value:0];
+ [self assertReadVarint:bytes(0x01) value:1];
+ [self assertReadVarint:bytes(0x7f) value:127];
+ // 14882
+ [self assertReadVarint:bytes(0xa2, 0x74) value:(0x22 << 0) | (0x74 << 7)];
+ // 2961488830
+ [self assertReadVarint:bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b)
+ value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) |
+ (0x04 << 21) | (0x0bLL << 28)];
+
+ // 64-bit
+ // 7256456126
+ [self assertReadVarint:bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b)
+ value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) |
+ (0x04 << 21) | (0x1bLL << 28)];
+ // 41256202580718336
+ [self assertReadVarint:bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49)
+ value:(0x00 << 0) | (0x66 << 7) | (0x6b << 14) |
+ (0x1c << 21) | (0x43LL << 28) | (0x49LL << 35) |
+ (0x24LL << 42) | (0x49LL << 49)];
+ // 11964378330978735131
+ [self
+ assertReadVarint:bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85,
+ 0xa6, 0x01)
+ value:(0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
+ (0x3bLL << 28) | (0x56LL << 35) | (0x00LL << 42) |
+ (0x05LL << 49) | (0x26LL << 56) | (0x01LL << 63)];
+
+ // Failures
+ [self assertReadVarintFailure:bytes(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x00)];
+ [self assertReadVarintFailure:bytes(0x80)];
+}
+
+- (void)testReadLittleEndian {
+ [self assertReadLittleEndian32:bytes(0x78, 0x56, 0x34, 0x12)
+ value:0x12345678];
+ [self assertReadLittleEndian32:bytes(0xf0, 0xde, 0xbc, 0x9a)
+ value:0x9abcdef0];
+
+ [self assertReadLittleEndian64:bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34,
+ 0x12)
+ value:0x123456789abcdef0LL];
+ [self assertReadLittleEndian64:bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc,
+ 0x9a)
+ value:0x9abcdef012345678LL];
+}
+
+- (void)testReadWholeMessage {
+ TestAllTypes* message = [self allSetRepeatedCount:kGPBDefaultRepeatCount];
+
+ NSData* rawBytes = message.data;
+ XCTAssertEqual(message.serializedSize, (size_t)rawBytes.length);
+
+ TestAllTypes* message2 =
+ [TestAllTypes parseFromData:rawBytes extensionRegistry:nil];
+ [self assertAllFieldsSet:message2 repeatedCount:kGPBDefaultRepeatCount];
+}
+
+- (void)testSkipWholeMessage {
+ TestAllTypes* message = [self allSetRepeatedCount:kGPBDefaultRepeatCount];
+ NSData* rawBytes = message.data;
+
+ // Create two parallel inputs. Parse one as unknown fields while using
+ // skipField() to skip each field on the other. Expect the same tags.
+ GPBCodedInputStream* input1 = [GPBCodedInputStream streamWithData:rawBytes];
+ GPBCodedInputStream* input2 = [GPBCodedInputStream streamWithData:rawBytes];
+ GPBUnknownFieldSet* unknownFields =
+ [[[GPBUnknownFieldSet alloc] init] autorelease];
+
+ while (YES) {
+ int32_t tag = [input1 readTag];
+ XCTAssertEqual(tag, [input2 readTag]);
+ if (tag == 0) {
+ break;
+ }
+ [unknownFields mergeFieldFrom:tag input:input1];
+ [input2 skipField:tag];
+ }
+}
+
+- (void)testReadHugeBlob {
+ // Allocate and initialize a 1MB blob.
+ NSMutableData* blob = [NSMutableData dataWithLength:1 << 20];
+ for (NSUInteger i = 0; i < blob.length; i++) {
+ ((uint8_t*)blob.mutableBytes)[i] = (uint8_t)i;
+ }
+
+ // Make a message containing it.
+ TestAllTypes* message = [TestAllTypes message];
+ [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount];
+ [message setOptionalBytes:blob];
+
+ // Serialize and parse it. Make sure to parse from an InputStream, not
+ // directly from a ByteString, so that CodedInputStream uses buffered
+ // reading.
+ GPBCodedInputStream* stream =
+ [GPBCodedInputStream streamWithData:message.data];
+ TestAllTypes* message2 =
+ [TestAllTypes parseFromCodedInputStream:stream extensionRegistry:nil];
+
+ XCTAssertEqualObjects(message.optionalBytes, message2.optionalBytes);
+
+ // Make sure all the other fields were parsed correctly.
+ TestAllTypes* message3 = [[message2 copy] autorelease];
+ TestAllTypes* types = [self allSetRepeatedCount:kGPBDefaultRepeatCount];
+ NSData* data = [types optionalBytes];
+ [message3 setOptionalBytes:data];
+
+ [self assertAllFieldsSet:message3 repeatedCount:kGPBDefaultRepeatCount];
+}
+
+- (void)testReadMaliciouslyLargeBlob {
+ NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+ GPBCodedOutputStream* output =
+ [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+
+ int32_t tag = GPBWireFormatMakeTag(1, GPBWireFormatLengthDelimited);
+ [output writeRawVarint32:tag];
+ [output writeRawVarint32:0x7FFFFFFF];
+ uint8_t bytes[32] = {0};
+ [output writeRawData:[NSData dataWithBytes:bytes length:32]];
+ [output flush];
+
+ NSData* data =
+ [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+ GPBCodedInputStream* input =
+ [GPBCodedInputStream streamWithData:[NSMutableData dataWithData:data]];
+ XCTAssertEqual(tag, [input readTag]);
+
+ XCTAssertThrows([input readData]);
+}
+
+// Verifies fix for b/10315336.
+- (void)testReadMalformedString {
+ NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+ GPBCodedOutputStream* output =
+ [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+
+ int32_t tag = GPBWireFormatMakeTag(TestAllTypes_FieldNumber_DefaultString,
+ GPBWireFormatLengthDelimited);
+ [output writeRawVarint32:tag];
+ [output writeRawVarint32:5];
+ // Create an invalid utf-8 byte array.
+ uint8_t bytes[5] = {0xc2, 0xf2};
+ [output writeRawData:[NSData dataWithBytes:bytes length:sizeof(bytes)]];
+ [output flush];
+
+ NSData* data =
+ [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+ GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
+ TestAllTypes* message =
+ [TestAllTypes parseFromCodedInputStream:input extensionRegistry:nil];
+ // Make sure we can read string properties twice without crashing.
+ XCTAssertEqual([message.defaultString length], (NSUInteger)0);
+ XCTAssertEqualObjects(@"", message.defaultString);
+}
+
+@end
diff --git a/objectivec/Tests/GPBCodedOuputStreamTests.m b/objectivec/Tests/GPBCodedOuputStreamTests.m
new file mode 100644
index 00000000..77d88033
--- /dev/null
+++ b/objectivec/Tests/GPBCodedOuputStreamTests.m
@@ -0,0 +1,321 @@
+// 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.
+
+#import "GPBTestUtilities.h"
+
+#import "GPBCodedOutputStream.h"
+#import "GPBCodedInputStream.h"
+#import "GPBUtilities_PackagePrivate.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+
+@interface CodedOutputStreamTests : GPBTestCase
+@end
+
+@implementation CodedOutputStreamTests
+
+- (NSData*)bytes_with_sentinel:(int32_t)unused, ... {
+ va_list list;
+ va_start(list, unused);
+
+ NSMutableData* values = [NSMutableData dataWithCapacity:0];
+ int32_t i;
+
+ while ((i = va_arg(list, int32_t)) != 256) {
+ NSAssert(i >= 0 && i < 256, @"");
+ uint8_t u = (uint8_t)i;
+ [values appendBytes:&u length:1];
+ }
+
+ va_end(list);
+
+ return values;
+}
+
+#define bytes(...) [self bytes_with_sentinel:0, __VA_ARGS__, 256]
+
+- (void)assertWriteLittleEndian32:(NSData*)data value:(int32_t)value {
+ NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+ GPBCodedOutputStream* output =
+ [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+ [output writeRawLittleEndian32:(int32_t)value];
+ [output flush];
+
+ NSData* actual =
+ [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+ XCTAssertEqualObjects(data, actual);
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+ rawOutput = [NSOutputStream outputStreamToMemory];
+ output = [GPBCodedOutputStream streamWithOutputStream:rawOutput
+ bufferSize:blockSize];
+ [output writeRawLittleEndian32:(int32_t)value];
+ [output flush];
+
+ actual = [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+ XCTAssertEqualObjects(data, actual);
+ }
+}
+
+- (void)assertWriteLittleEndian64:(NSData*)data value:(int64_t)value {
+ NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+ GPBCodedOutputStream* output =
+ [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+ [output writeRawLittleEndian64:value];
+ [output flush];
+
+ NSData* actual =
+ [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+ XCTAssertEqualObjects(data, actual);
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+ rawOutput = [NSOutputStream outputStreamToMemory];
+ output = [GPBCodedOutputStream streamWithOutputStream:rawOutput
+ bufferSize:blockSize];
+ [output writeRawLittleEndian64:value];
+ [output flush];
+
+ actual = [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+ XCTAssertEqualObjects(data, actual);
+ }
+}
+
+- (void)assertWriteVarint:(NSData*)data value:(int64_t)value {
+ // Only do 32-bit write if the value fits in 32 bits.
+ if (GPBLogicalRightShift64(value, 32) == 0) {
+ NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+ GPBCodedOutputStream* output =
+ [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+ [output writeRawVarint32:(int32_t)value];
+ [output flush];
+
+ NSData* actual =
+ [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+ XCTAssertEqualObjects(data, actual);
+
+ // Also try computing size.
+ XCTAssertEqual(GPBComputeRawVarint32Size((int32_t)value),
+ (size_t)data.length);
+ }
+
+ {
+ NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+ GPBCodedOutputStream* output =
+ [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+ [output writeRawVarint64:value];
+ [output flush];
+
+ NSData* actual =
+ [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+ XCTAssertEqualObjects(data, actual);
+
+ // Also try computing size.
+ XCTAssertEqual(GPBComputeRawVarint64Size(value), (size_t)data.length);
+ }
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+ // Only do 32-bit write if the value fits in 32 bits.
+ if (GPBLogicalRightShift64(value, 32) == 0) {
+ NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+ GPBCodedOutputStream* output =
+ [GPBCodedOutputStream streamWithOutputStream:rawOutput
+ bufferSize:blockSize];
+
+ [output writeRawVarint32:(int32_t)value];
+ [output flush];
+
+ NSData* actual =
+ [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+ XCTAssertEqualObjects(data, actual);
+ }
+
+ {
+ NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+ GPBCodedOutputStream* output =
+ [GPBCodedOutputStream streamWithOutputStream:rawOutput
+ bufferSize:blockSize];
+
+ [output writeRawVarint64:value];
+ [output flush];
+
+ NSData* actual =
+ [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+ XCTAssertEqualObjects(data, actual);
+ }
+ }
+}
+
+- (void)testWriteVarint1 {
+ [self assertWriteVarint:bytes(0x00) value:0];
+}
+
+- (void)testWriteVarint2 {
+ [self assertWriteVarint:bytes(0x01) value:1];
+}
+
+- (void)testWriteVarint3 {
+ [self assertWriteVarint:bytes(0x7f) value:127];
+}
+
+- (void)testWriteVarint4 {
+ // 14882
+ [self assertWriteVarint:bytes(0xa2, 0x74) value:(0x22 << 0) | (0x74 << 7)];
+}
+
+- (void)testWriteVarint5 {
+ // 2961488830
+ [self assertWriteVarint:bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b)
+ value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) |
+ (0x04 << 21) | (0x0bLL << 28)];
+}
+
+- (void)testWriteVarint6 {
+ // 64-bit
+ // 7256456126
+ [self assertWriteVarint:bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b)
+ value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) |
+ (0x04 << 21) | (0x1bLL << 28)];
+}
+
+- (void)testWriteVarint7 {
+ // 41256202580718336
+ [self assertWriteVarint:bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49)
+ value:(0x00 << 0) | (0x66 << 7) | (0x6b << 14) |
+ (0x1c << 21) | (0x43LL << 28) | (0x49LL << 35) |
+ (0x24LL << 42) | (0x49LL << 49)];
+}
+
+- (void)testWriteVarint8 {
+ // 11964378330978735131
+ [self assertWriteVarint:bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85,
+ 0xa6, 0x01)
+ value:(0x1b << 0) | (0x28 << 7) | (0x79 << 14) |
+ (0x42 << 21) | (0x3bLL << 28) | (0x56LL << 35) |
+ (0x00LL << 42) | (0x05LL << 49) | (0x26LL << 56) |
+ (0x01LL << 63)];
+}
+
+- (void)testWriteLittleEndian {
+ [self assertWriteLittleEndian32:bytes(0x78, 0x56, 0x34, 0x12)
+ value:0x12345678];
+ [self assertWriteLittleEndian32:bytes(0xf0, 0xde, 0xbc, 0x9a)
+ value:0x9abcdef0];
+
+ [self assertWriteLittleEndian64:bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56,
+ 0x34, 0x12)
+ value:0x123456789abcdef0LL];
+ [self assertWriteLittleEndian64:bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde,
+ 0xbc, 0x9a)
+ value:0x9abcdef012345678LL];
+}
+
+- (void)testEncodeZigZag {
+ XCTAssertEqual(0U, GPBEncodeZigZag32(0));
+ XCTAssertEqual(1U, GPBEncodeZigZag32(-1));
+ XCTAssertEqual(2U, GPBEncodeZigZag32(1));
+ XCTAssertEqual(3U, GPBEncodeZigZag32(-2));
+ XCTAssertEqual(0x7FFFFFFEU, GPBEncodeZigZag32(0x3FFFFFFF));
+ XCTAssertEqual(0x7FFFFFFFU, GPBEncodeZigZag32(0xC0000000));
+ XCTAssertEqual(0xFFFFFFFEU, GPBEncodeZigZag32(0x7FFFFFFF));
+ XCTAssertEqual(0xFFFFFFFFU, GPBEncodeZigZag32(0x80000000));
+
+ XCTAssertEqual(0ULL, GPBEncodeZigZag64(0));
+ XCTAssertEqual(1ULL, GPBEncodeZigZag64(-1));
+ XCTAssertEqual(2ULL, GPBEncodeZigZag64(1));
+ XCTAssertEqual(3ULL, GPBEncodeZigZag64(-2));
+ XCTAssertEqual(0x000000007FFFFFFEULL,
+ GPBEncodeZigZag64(0x000000003FFFFFFFLL));
+ XCTAssertEqual(0x000000007FFFFFFFULL,
+ GPBEncodeZigZag64(0xFFFFFFFFC0000000LL));
+ XCTAssertEqual(0x00000000FFFFFFFEULL,
+ GPBEncodeZigZag64(0x000000007FFFFFFFLL));
+ XCTAssertEqual(0x00000000FFFFFFFFULL,
+ GPBEncodeZigZag64(0xFFFFFFFF80000000LL));
+ XCTAssertEqual(0xFFFFFFFFFFFFFFFEULL,
+ GPBEncodeZigZag64(0x7FFFFFFFFFFFFFFFLL));
+ XCTAssertEqual(0xFFFFFFFFFFFFFFFFULL,
+ GPBEncodeZigZag64(0x8000000000000000LL));
+
+ // Some easier-to-verify round-trip tests. The inputs (other than 0, 1, -1)
+ // were chosen semi-randomly via keyboard bashing.
+ XCTAssertEqual(0U, GPBEncodeZigZag32(GPBDecodeZigZag32(0)));
+ XCTAssertEqual(1U, GPBEncodeZigZag32(GPBDecodeZigZag32(1)));
+ XCTAssertEqual(-1U, GPBEncodeZigZag32(GPBDecodeZigZag32(-1)));
+ XCTAssertEqual(14927U, GPBEncodeZigZag32(GPBDecodeZigZag32(14927)));
+ XCTAssertEqual(-3612U, GPBEncodeZigZag32(GPBDecodeZigZag32(-3612)));
+
+ XCTAssertEqual(0ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(0)));
+ XCTAssertEqual(1ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(1)));
+ XCTAssertEqual(-1ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(-1)));
+ XCTAssertEqual(14927ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(14927)));
+ XCTAssertEqual(-3612ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(-3612)));
+
+ XCTAssertEqual(856912304801416ULL,
+ GPBEncodeZigZag64(GPBDecodeZigZag64(856912304801416LL)));
+ XCTAssertEqual(-75123905439571256ULL,
+ GPBEncodeZigZag64(GPBDecodeZigZag64(-75123905439571256LL)));
+}
+
+- (void)testWriteWholeMessage {
+ // Not kGPBDefaultRepeatCount because we are comparing to a golden master file
+ // that was generated with 2.
+ TestAllTypes* message = [self allSetRepeatedCount:2];
+
+ NSData* rawBytes = message.data;
+ NSData* goldenData =
+ [self getDataFileNamed:@"golden_message" dataToWrite:rawBytes];
+ XCTAssertEqualObjects(rawBytes, goldenData);
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize < 256; blockSize *= 2) {
+ NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+ GPBCodedOutputStream* output =
+ [GPBCodedOutputStream streamWithOutputStream:rawOutput
+ bufferSize:blockSize];
+ [message writeToCodedOutputStream:output];
+ [output flush];
+
+ NSData* actual =
+ [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+ XCTAssertEqualObjects(rawBytes, actual);
+ }
+
+ // Not kGPBDefaultRepeatCount because we are comparing to a golden master file
+ // that was generated with 2.
+ TestAllExtensions* extensions = [self allExtensionsSetRepeatedCount:2];
+ rawBytes = extensions.data;
+ goldenData = [self getDataFileNamed:@"golden_packed_fields_message"
+ dataToWrite:rawBytes];
+ XCTAssertEqualObjects(rawBytes, goldenData);
+}
+
+@end
diff --git a/objectivec/Tests/GPBConcurrencyTests.m b/objectivec/Tests/GPBConcurrencyTests.m
new file mode 100644
index 00000000..3749fc34
--- /dev/null
+++ b/objectivec/Tests/GPBConcurrencyTests.m
@@ -0,0 +1,157 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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 "GPBTestUtilities.h"
+
+#import "google/protobuf/Unittest.pbobjc.h"
+
+static const int kNumThreads = 100;
+static const int kNumMessages = 100;
+
+@interface ConcurrencyTests : GPBTestCase
+@end
+
+@implementation ConcurrencyTests
+
+- (NSArray *)createThreadsWithSelector:(SEL)selector object:(id)object {
+ NSMutableArray *array = [NSMutableArray array];
+ for (NSUInteger i = 0; i < kNumThreads; i++) {
+ NSThread *thread =
+ [[NSThread alloc] initWithTarget:self selector:selector object:object];
+ [array addObject:thread];
+ [thread release];
+ }
+ return array;
+}
+
+- (NSArray *)createMessagesWithType:(Class)msgType {
+ NSMutableArray *array = [NSMutableArray array];
+ for (NSUInteger i = 0; i < kNumMessages; i++) {
+ [array addObject:[msgType message]];
+ }
+ return array;
+}
+
+- (void)startThreads:(NSArray *)threads {
+ for (NSThread *thread in threads) {
+ [thread start];
+ }
+}
+
+- (void)joinThreads:(NSArray *)threads {
+ for (NSThread *thread in threads) {
+ while (![thread isFinished])
+ ;
+ }
+}
+
+- (void)readForeignMessage:(NSArray *)messages {
+ for (NSUInteger i = 0; i < 10; i++) {
+ for (TestAllTypes *message in messages) {
+ XCTAssertEqual(message.optionalForeignMessage.c, 0);
+ }
+ }
+}
+
+- (void)testConcurrentReadOfUnsetMessageField {
+ NSArray *messages = [self createMessagesWithType:[TestAllTypes class]];
+ NSArray *threads =
+ [self createThreadsWithSelector:@selector(readForeignMessage:)
+ object:messages];
+ [self startThreads:threads];
+ [self joinThreads:threads];
+ for (TestAllTypes *message in messages) {
+ XCTAssertFalse(message.hasOptionalForeignMessage);
+ }
+}
+
+- (void)readRepeatedInt32:(NSArray *)messages {
+ for (int i = 0; i < 10; i++) {
+ for (TestAllTypes *message in messages) {
+ XCTAssertEqual([message.repeatedInt32Array count], (NSUInteger)0);
+ }
+ }
+}
+
+- (void)testConcurrentReadOfUnsetRepeatedIntField {
+ NSArray *messages = [self createMessagesWithType:[TestAllTypes class]];
+ NSArray *threads =
+ [self createThreadsWithSelector:@selector(readRepeatedInt32:)
+ object:messages];
+ [self startThreads:threads];
+ [self joinThreads:threads];
+ for (TestAllTypes *message in messages) {
+ XCTAssertEqual([message.repeatedInt32Array count], (NSUInteger)0);
+ }
+}
+
+- (void)readRepeatedString:(NSArray *)messages {
+ for (int i = 0; i < 10; i++) {
+ for (TestAllTypes *message in messages) {
+ XCTAssertEqual([message.repeatedStringArray count], (NSUInteger)0);
+ }
+ }
+}
+
+- (void)testConcurrentReadOfUnsetRepeatedStringField {
+ NSArray *messages = [self createMessagesWithType:[TestAllTypes class]];
+ NSArray *threads =
+ [self createThreadsWithSelector:@selector(readRepeatedString:)
+ object:messages];
+ [self startThreads:threads];
+ [self joinThreads:threads];
+ for (TestAllTypes *message in messages) {
+ XCTAssertEqual([message.repeatedStringArray count], (NSUInteger)0);
+ }
+}
+
+- (void)readOptionalForeignMessageExtension:(NSArray *)messages {
+ for (int i = 0; i < 10; i++) {
+ for (TestAllExtensions *message in messages) {
+ ForeignMessage *foreign =
+ [message getExtension:[UnittestRoot optionalForeignMessageExtension]];
+ XCTAssertEqual(foreign.c, 0);
+ }
+ }
+}
+
+- (void)testConcurrentReadOfUnsetExtensionField {
+ NSArray *messages = [self createMessagesWithType:[TestAllExtensions class]];
+ SEL sel = @selector(readOptionalForeignMessageExtension:);
+ NSArray *threads = [self createThreadsWithSelector:sel object:messages];
+ [self startThreads:threads];
+ [self joinThreads:threads];
+ GPBExtensionField *extension = [UnittestRoot optionalForeignMessageExtension];
+ for (TestAllExtensions *message in messages) {
+ XCTAssertFalse([message hasExtension:extension]);
+ }
+}
+
+@end
diff --git a/objectivec/Tests/GPBDescriptorTests.m b/objectivec/Tests/GPBDescriptorTests.m
new file mode 100644
index 00000000..ccdbb645
--- /dev/null
+++ b/objectivec/Tests/GPBDescriptorTests.m
@@ -0,0 +1,232 @@
+// 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.
+
+#import "GPBTestUtilities.h"
+
+#import <objc/runtime.h>
+
+#import "GPBDescriptor.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+
+@interface DescriptorTests : GPBTestCase
+@end
+
+@implementation DescriptorTests
+
+- (void)testFieldDescriptor {
+ GPBDescriptor *descriptor = [TestAllTypes descriptor];
+
+ // Nested Enum
+ GPBFieldDescriptor *fieldDescriptorWithName =
+ [descriptor fieldWithName:@"optionalNestedEnum"];
+ XCTAssertNotNil(fieldDescriptorWithName);
+ GPBFieldDescriptor *fieldDescriptorWithNumber =
+ [descriptor fieldWithNumber:21];
+ XCTAssertNotNil(fieldDescriptorWithNumber);
+ XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
+ XCTAssertNotNil(fieldDescriptorWithNumber.enumDescriptor);
+ XCTAssertEqualObjects(fieldDescriptorWithNumber.enumDescriptor.name,
+ @"TestAllTypes_NestedEnum");
+
+ // Foreign Enum
+ fieldDescriptorWithName = [descriptor fieldWithName:@"optionalForeignEnum"];
+ XCTAssertNotNil(fieldDescriptorWithName);
+ fieldDescriptorWithNumber = [descriptor fieldWithNumber:22];
+ XCTAssertNotNil(fieldDescriptorWithNumber);
+ XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
+ XCTAssertNotNil(fieldDescriptorWithNumber.enumDescriptor);
+ XCTAssertEqualObjects(fieldDescriptorWithNumber.enumDescriptor.name,
+ @"ForeignEnum");
+
+ // Import Enum
+ fieldDescriptorWithName = [descriptor fieldWithName:@"optionalImportEnum"];
+ XCTAssertNotNil(fieldDescriptorWithName);
+ fieldDescriptorWithNumber = [descriptor fieldWithNumber:23];
+ XCTAssertNotNil(fieldDescriptorWithNumber);
+ XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
+ XCTAssertNotNil(fieldDescriptorWithNumber.enumDescriptor);
+ XCTAssertEqualObjects(fieldDescriptorWithNumber.enumDescriptor.name,
+ @"ImportEnum");
+
+ // Nested Message
+ fieldDescriptorWithName = [descriptor fieldWithName:@"optionalNestedMessage"];
+ XCTAssertNotNil(fieldDescriptorWithName);
+ fieldDescriptorWithNumber = [descriptor fieldWithNumber:18];
+ XCTAssertNotNil(fieldDescriptorWithNumber);
+ XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
+ XCTAssertNil(fieldDescriptorWithNumber.enumDescriptor);
+
+ // Foreign Message
+ fieldDescriptorWithName =
+ [descriptor fieldWithName:@"optionalForeignMessage"];
+ XCTAssertNotNil(fieldDescriptorWithName);
+ fieldDescriptorWithNumber = [descriptor fieldWithNumber:19];
+ XCTAssertNotNil(fieldDescriptorWithNumber);
+ XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
+ XCTAssertNil(fieldDescriptorWithNumber.enumDescriptor);
+
+ // Import Message
+ fieldDescriptorWithName = [descriptor fieldWithName:@"optionalImportMessage"];
+ XCTAssertNotNil(fieldDescriptorWithName);
+ fieldDescriptorWithNumber = [descriptor fieldWithNumber:20];
+ XCTAssertNotNil(fieldDescriptorWithNumber);
+ XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
+ XCTAssertNil(fieldDescriptorWithNumber.enumDescriptor);
+}
+
+- (void)testEnumDescriptor {
+ GPBEnumDescriptor *descriptor = TestAllTypes_NestedEnum_EnumDescriptor();
+
+ NSString *enumName = [descriptor enumNameForValue:1];
+ XCTAssertNotNil(enumName);
+ int32_t value;
+ XCTAssertTrue(
+ [descriptor getValue:&value forEnumName:@"TestAllTypes_NestedEnum_Foo"]);
+ XCTAssertTrue(
+ [descriptor getValue:NULL forEnumName:@"TestAllTypes_NestedEnum_Foo"]);
+ XCTAssertEqual(value, TestAllTypes_NestedEnum_Foo);
+
+ enumName = [descriptor enumNameForValue:2];
+ XCTAssertNotNil(enumName);
+ XCTAssertTrue(
+ [descriptor getValue:&value forEnumName:@"TestAllTypes_NestedEnum_Bar"]);
+ XCTAssertEqual(value, TestAllTypes_NestedEnum_Bar);
+
+ enumName = [descriptor enumNameForValue:3];
+ XCTAssertNotNil(enumName);
+ XCTAssertTrue(
+ [descriptor getValue:&value forEnumName:@"TestAllTypes_NestedEnum_Baz"]);
+ XCTAssertEqual(value, TestAllTypes_NestedEnum_Baz);
+
+ // Bad values
+ enumName = [descriptor enumNameForValue:0];
+ XCTAssertNil(enumName);
+ XCTAssertFalse([descriptor getValue:&value forEnumName:@"Unknown"]);
+ XCTAssertFalse([descriptor getValue:NULL forEnumName:@"Unknown"]);
+ XCTAssertFalse([descriptor getValue:&value
+ forEnumName:@"TestAllTypes_NestedEnum_Unknown"]);
+ XCTAssertFalse([descriptor getValue:NULL
+ forEnumName:@"TestAllTypes_NestedEnum_Unknown"]);
+}
+
+- (void)testEnumValueValidator {
+ GPBDescriptor *descriptor = [TestAllTypes descriptor];
+ GPBFieldDescriptor *fieldDescriptor =
+ [descriptor fieldWithName:@"optionalNestedEnum"];
+
+ // Valid values
+ XCTAssertTrue([fieldDescriptor isValidEnumValue:1]);
+ XCTAssertTrue([fieldDescriptor isValidEnumValue:2]);
+ XCTAssertTrue([fieldDescriptor isValidEnumValue:3]);
+ XCTAssertTrue([fieldDescriptor isValidEnumValue:-1]);
+
+ // Invalid values
+ XCTAssertFalse([fieldDescriptor isValidEnumValue:4]);
+ XCTAssertFalse([fieldDescriptor isValidEnumValue:0]);
+ XCTAssertFalse([fieldDescriptor isValidEnumValue:-2]);
+}
+
+- (void)testEnumDescriptorLookup {
+ GPBDescriptor *descriptor = [TestAllTypes descriptor];
+ GPBEnumDescriptor *enumDescriptor =
+ [descriptor enumWithName:@"TestAllTypes_NestedEnum"];
+ XCTAssertNotNil(enumDescriptor);
+
+ // Descriptor cannot find foreign or imported enums.
+ enumDescriptor = [descriptor enumWithName:@"ForeignEnumEnum"];
+ XCTAssertNil(enumDescriptor);
+ enumDescriptor = [descriptor enumWithName:@"ImportEnumEnum"];
+ XCTAssertNil(enumDescriptor);
+}
+
+- (void)testOneofDescriptor {
+ GPBDescriptor *descriptor = [TestOneof2 descriptor];
+
+ // All fields should be listed.
+ XCTAssertEqual(descriptor.fields.count, 17U);
+
+ // There are two oneofs in there.
+ XCTAssertEqual(descriptor.oneofs.count, 2U);
+
+ GPBFieldDescriptor *fooStringField =
+ [descriptor fieldWithNumber:TestOneof2_FieldNumber_FooString];
+ XCTAssertNotNil(fooStringField);
+ GPBFieldDescriptor *barStringField =
+ [descriptor fieldWithNumber:TestOneof2_FieldNumber_BarString];
+ XCTAssertNotNil(barStringField);
+
+ // Check the oneofs to have what is expected.
+
+ GPBOneofDescriptor *oneofFoo = [descriptor oneofWithName:@"foo"];
+ XCTAssertNotNil(oneofFoo);
+ XCTAssertEqual(oneofFoo.fields.count, 9U);
+
+ // Pointer comparisons.
+ XCTAssertEqual([oneofFoo fieldWithNumber:TestOneof2_FieldNumber_FooString],
+ fooStringField);
+ XCTAssertEqual([oneofFoo fieldWithName:@"fooString"], fooStringField);
+
+ GPBOneofDescriptor *oneofBar = [descriptor oneofWithName:@"bar"];
+ XCTAssertNotNil(oneofBar);
+ XCTAssertEqual(oneofBar.fields.count, 6U);
+
+ // Pointer comparisons.
+ XCTAssertEqual([oneofBar fieldWithNumber:TestOneof2_FieldNumber_BarString],
+ barStringField);
+ XCTAssertEqual([oneofBar fieldWithName:@"barString"], barStringField);
+
+ // Unknown oneof not found.
+
+ XCTAssertNil([descriptor oneofWithName:@"mumble"]);
+ XCTAssertNil([descriptor oneofWithName:@"Foo"]);
+
+ // Unknown oneof item.
+
+ XCTAssertNil([oneofFoo fieldWithName:@"mumble"]);
+ XCTAssertNil([oneofFoo fieldWithNumber:666]);
+
+ // Field exists, but not in this oneof.
+
+ XCTAssertNil([oneofFoo fieldWithName:@"barString"]);
+ XCTAssertNil([oneofFoo fieldWithNumber:TestOneof2_FieldNumber_BarString]);
+ XCTAssertNil([oneofBar fieldWithName:@"fooString"]);
+ XCTAssertNil([oneofBar fieldWithNumber:TestOneof2_FieldNumber_FooString]);
+
+ // Check pointers back to the enclosing oneofs.
+ // (pointer comparisions)
+ XCTAssertEqual(fooStringField.containingOneof, oneofFoo);
+ XCTAssertEqual(barStringField.containingOneof, oneofBar);
+ GPBFieldDescriptor *bazString =
+ [descriptor fieldWithNumber:TestOneof2_FieldNumber_BazString];
+ XCTAssertNotNil(bazString);
+ XCTAssertNil(bazString.containingOneof);
+}
+
+@end
diff --git a/objectivec/Tests/GPBDictionaryTests+Bool.m b/objectivec/Tests/GPBDictionaryTests+Bool.m
new file mode 100644
index 00000000..bc4998be
--- /dev/null
+++ b/objectivec/Tests/GPBDictionaryTests+Bool.m
@@ -0,0 +1,2421 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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 "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+
+#ifndef GPBARRAYSIZE
+#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))))
+#endif // GPBARRAYSIZE
+
+// Pull in the macros (using an external file because expanding all tests
+// in a single file makes a file that is failing to work with within Xcode.
+//%PDDM-IMPORT-DEFINES GPBDictionaryTests.pddm
+
+//%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(UInt32, uint32_t, 100U, 101U)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> UInt32
+
+@interface GPBBoolUInt32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBBoolUInt32DictionaryTests
+
+- (void)testEmpty {
+ GPBBoolUInt32Dictionary *dict = [[GPBBoolUInt32Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, uint32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBBoolUInt32Dictionary *dict = [GPBBoolUInt32Dictionary dictionaryWithValue:100U forKey:YES];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, uint32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, YES);
+ XCTAssertEqual(aValue, 100U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const BOOL kKeys[] = { YES, NO };
+ const uint32_t kValues[] = { 100U, 101U };
+ GPBBoolUInt32Dictionary *dict =
+ [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ __block NSUInteger idx = 0;
+ BOOL *seenKeys = malloc(2 * sizeof(BOOL));
+ uint32_t *seenValues = malloc(2 * sizeof(uint32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, uint32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 2U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 2; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 2) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, uint32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 0) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const BOOL kKeys1[] = { YES, NO };
+ const BOOL kKeys2[] = { NO, YES };
+ const uint32_t kValues1[] = { 100U, 101U };
+ const uint32_t kValues2[] = { 101U, 100U };
+ const uint32_t kValues3[] = { 101U };
+ GPBBoolUInt32Dictionary *dict1 =
+ [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBBoolUInt32Dictionary *dict1prime =
+ [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBBoolUInt32Dictionary *dict2 =
+ [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBBoolUInt32Dictionary *dict3 =
+ [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBBoolUInt32Dictionary *dict4 =
+ [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 Fewer pairs; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const BOOL kKeys[] = { YES, NO };
+ const uint32_t kValues[] = { 100U, 101U };
+ GPBBoolUInt32Dictionary *dict =
+ [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolUInt32Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBBoolUInt32Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const BOOL kKeys[] = { YES, NO };
+ const uint32_t kValues[] = { 100U, 101U };
+ GPBBoolUInt32Dictionary *dict =
+ [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolUInt32Dictionary *dict2 =
+ [GPBBoolUInt32Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBBoolUInt32Dictionary *dict = [GPBBoolUInt32Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:100U forKey:YES];
+ XCTAssertEqual(dict.count, 1U);
+
+ const BOOL kKeys[] = { NO };
+ const uint32_t kValues[] = { 101U };
+ GPBBoolUInt32Dictionary *dict2 =
+ [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 101U);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const BOOL kKeys[] = { YES, NO};
+ const uint32_t kValues[] = { 100U, 101U };
+ GPBBoolUInt32Dictionary *dict =
+ [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const BOOL kKeys[] = { YES, NO };
+ const uint32_t kValues[] = { 100U, 101U };
+ GPBBoolUInt32Dictionary *dict =
+ [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ [dict setValue:101U forKey:YES];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ [dict setValue:100U forKey:NO];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 100U);
+
+ const BOOL kKeys2[] = { NO, YES };
+ const uint32_t kValues2[] = { 101U, 100U };
+ GPBBoolUInt32Dictionary *dict2 =
+ [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(Int32, int32_t, 200, 201)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Int32
+
+@interface GPBBoolInt32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBBoolInt32DictionaryTests
+
+- (void)testEmpty {
+ GPBBoolInt32Dictionary *dict = [[GPBBoolInt32Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBBoolInt32Dictionary *dict = [GPBBoolInt32Dictionary dictionaryWithValue:200 forKey:YES];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, YES);
+ XCTAssertEqual(aValue, 200);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const BOOL kKeys[] = { YES, NO };
+ const int32_t kValues[] = { 200, 201 };
+ GPBBoolInt32Dictionary *dict =
+ [[GPBBoolInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 201);
+
+ __block NSUInteger idx = 0;
+ BOOL *seenKeys = malloc(2 * sizeof(BOOL));
+ int32_t *seenValues = malloc(2 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 2U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 2; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 2) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 0) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const BOOL kKeys1[] = { YES, NO };
+ const BOOL kKeys2[] = { NO, YES };
+ const int32_t kValues1[] = { 200, 201 };
+ const int32_t kValues2[] = { 201, 200 };
+ const int32_t kValues3[] = { 201 };
+ GPBBoolInt32Dictionary *dict1 =
+ [[GPBBoolInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBBoolInt32Dictionary *dict1prime =
+ [[GPBBoolInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBBoolInt32Dictionary *dict2 =
+ [[GPBBoolInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBBoolInt32Dictionary *dict3 =
+ [[GPBBoolInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBBoolInt32Dictionary *dict4 =
+ [[GPBBoolInt32Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 Fewer pairs; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const BOOL kKeys[] = { YES, NO };
+ const int32_t kValues[] = { 200, 201 };
+ GPBBoolInt32Dictionary *dict =
+ [[GPBBoolInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolInt32Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBBoolInt32Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const BOOL kKeys[] = { YES, NO };
+ const int32_t kValues[] = { 200, 201 };
+ GPBBoolInt32Dictionary *dict =
+ [[GPBBoolInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolInt32Dictionary *dict2 =
+ [GPBBoolInt32Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBBoolInt32Dictionary *dict = [GPBBoolInt32Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:200 forKey:YES];
+ XCTAssertEqual(dict.count, 1U);
+
+ const BOOL kKeys[] = { NO };
+ const int32_t kValues[] = { 201 };
+ GPBBoolInt32Dictionary *dict2 =
+ [[GPBBoolInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 201);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const BOOL kKeys[] = { YES, NO};
+ const int32_t kValues[] = { 200, 201 };
+ GPBBoolInt32Dictionary *dict =
+ [[GPBBoolInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const BOOL kKeys[] = { YES, NO };
+ const int32_t kValues[] = { 200, 201 };
+ GPBBoolInt32Dictionary *dict =
+ [[GPBBoolInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 201);
+
+ [dict setValue:201 forKey:YES];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 201);
+
+ [dict setValue:200 forKey:NO];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 200);
+
+ const BOOL kKeys2[] = { NO, YES };
+ const int32_t kValues2[] = { 201, 200 };
+ GPBBoolInt32Dictionary *dict2 =
+ [[GPBBoolInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 201);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(UInt64, uint64_t, 300U, 301U)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> UInt64
+
+@interface GPBBoolUInt64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBBoolUInt64DictionaryTests
+
+- (void)testEmpty {
+ GPBBoolUInt64Dictionary *dict = [[GPBBoolUInt64Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, uint64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBBoolUInt64Dictionary *dict = [GPBBoolUInt64Dictionary dictionaryWithValue:300U forKey:YES];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, uint64_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, YES);
+ XCTAssertEqual(aValue, 300U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const BOOL kKeys[] = { YES, NO };
+ const uint64_t kValues[] = { 300U, 301U };
+ GPBBoolUInt64Dictionary *dict =
+ [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ __block NSUInteger idx = 0;
+ BOOL *seenKeys = malloc(2 * sizeof(BOOL));
+ uint64_t *seenValues = malloc(2 * sizeof(uint64_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, uint64_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 2U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 2; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 2) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, uint64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 0) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const BOOL kKeys1[] = { YES, NO };
+ const BOOL kKeys2[] = { NO, YES };
+ const uint64_t kValues1[] = { 300U, 301U };
+ const uint64_t kValues2[] = { 301U, 300U };
+ const uint64_t kValues3[] = { 301U };
+ GPBBoolUInt64Dictionary *dict1 =
+ [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBBoolUInt64Dictionary *dict1prime =
+ [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBBoolUInt64Dictionary *dict2 =
+ [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBBoolUInt64Dictionary *dict3 =
+ [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBBoolUInt64Dictionary *dict4 =
+ [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 Fewer pairs; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const BOOL kKeys[] = { YES, NO };
+ const uint64_t kValues[] = { 300U, 301U };
+ GPBBoolUInt64Dictionary *dict =
+ [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolUInt64Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBBoolUInt64Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const BOOL kKeys[] = { YES, NO };
+ const uint64_t kValues[] = { 300U, 301U };
+ GPBBoolUInt64Dictionary *dict =
+ [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolUInt64Dictionary *dict2 =
+ [GPBBoolUInt64Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBBoolUInt64Dictionary *dict = [GPBBoolUInt64Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:300U forKey:YES];
+ XCTAssertEqual(dict.count, 1U);
+
+ const BOOL kKeys[] = { NO };
+ const uint64_t kValues[] = { 301U };
+ GPBBoolUInt64Dictionary *dict2 =
+ [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 301U);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const BOOL kKeys[] = { YES, NO};
+ const uint64_t kValues[] = { 300U, 301U };
+ GPBBoolUInt64Dictionary *dict =
+ [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const BOOL kKeys[] = { YES, NO };
+ const uint64_t kValues[] = { 300U, 301U };
+ GPBBoolUInt64Dictionary *dict =
+ [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ [dict setValue:301U forKey:YES];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ [dict setValue:300U forKey:NO];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 300U);
+
+ const BOOL kKeys2[] = { NO, YES };
+ const uint64_t kValues2[] = { 301U, 300U };
+ GPBBoolUInt64Dictionary *dict2 =
+ [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(Int64, int64_t, 400, 401)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Int64
+
+@interface GPBBoolInt64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBBoolInt64DictionaryTests
+
+- (void)testEmpty {
+ GPBBoolInt64Dictionary *dict = [[GPBBoolInt64Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, int64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBBoolInt64Dictionary *dict = [GPBBoolInt64Dictionary dictionaryWithValue:400 forKey:YES];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, int64_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, YES);
+ XCTAssertEqual(aValue, 400);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const BOOL kKeys[] = { YES, NO };
+ const int64_t kValues[] = { 400, 401 };
+ GPBBoolInt64Dictionary *dict =
+ [[GPBBoolInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 401);
+
+ __block NSUInteger idx = 0;
+ BOOL *seenKeys = malloc(2 * sizeof(BOOL));
+ int64_t *seenValues = malloc(2 * sizeof(int64_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, int64_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 2U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 2; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 2) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, int64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 0) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const BOOL kKeys1[] = { YES, NO };
+ const BOOL kKeys2[] = { NO, YES };
+ const int64_t kValues1[] = { 400, 401 };
+ const int64_t kValues2[] = { 401, 400 };
+ const int64_t kValues3[] = { 401 };
+ GPBBoolInt64Dictionary *dict1 =
+ [[GPBBoolInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBBoolInt64Dictionary *dict1prime =
+ [[GPBBoolInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBBoolInt64Dictionary *dict2 =
+ [[GPBBoolInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBBoolInt64Dictionary *dict3 =
+ [[GPBBoolInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBBoolInt64Dictionary *dict4 =
+ [[GPBBoolInt64Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 Fewer pairs; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const BOOL kKeys[] = { YES, NO };
+ const int64_t kValues[] = { 400, 401 };
+ GPBBoolInt64Dictionary *dict =
+ [[GPBBoolInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolInt64Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBBoolInt64Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const BOOL kKeys[] = { YES, NO };
+ const int64_t kValues[] = { 400, 401 };
+ GPBBoolInt64Dictionary *dict =
+ [[GPBBoolInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolInt64Dictionary *dict2 =
+ [GPBBoolInt64Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBBoolInt64Dictionary *dict = [GPBBoolInt64Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:400 forKey:YES];
+ XCTAssertEqual(dict.count, 1U);
+
+ const BOOL kKeys[] = { NO };
+ const int64_t kValues[] = { 401 };
+ GPBBoolInt64Dictionary *dict2 =
+ [[GPBBoolInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 401);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const BOOL kKeys[] = { YES, NO};
+ const int64_t kValues[] = { 400, 401 };
+ GPBBoolInt64Dictionary *dict =
+ [[GPBBoolInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const BOOL kKeys[] = { YES, NO };
+ const int64_t kValues[] = { 400, 401 };
+ GPBBoolInt64Dictionary *dict =
+ [[GPBBoolInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 401);
+
+ [dict setValue:401 forKey:YES];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 401);
+
+ [dict setValue:400 forKey:NO];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 400);
+
+ const BOOL kKeys2[] = { NO, YES };
+ const int64_t kValues2[] = { 401, 400 };
+ GPBBoolInt64Dictionary *dict2 =
+ [[GPBBoolInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 401);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(Bool, BOOL, NO, YES)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Bool
+
+@interface GPBBoolBoolDictionaryTests : XCTestCase
+@end
+
+@implementation GPBBoolBoolDictionaryTests
+
+- (void)testEmpty {
+ GPBBoolBoolDictionary *dict = [[GPBBoolBoolDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, BOOL aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBBoolBoolDictionary *dict = [GPBBoolBoolDictionary dictionaryWithValue:NO forKey:YES];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, BOOL aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, YES);
+ XCTAssertEqual(aValue, NO);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const BOOL kKeys[] = { YES, NO };
+ const BOOL kValues[] = { NO, YES };
+ GPBBoolBoolDictionary *dict =
+ [[GPBBoolBoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, YES);
+
+ __block NSUInteger idx = 0;
+ BOOL *seenKeys = malloc(2 * sizeof(BOOL));
+ BOOL *seenValues = malloc(2 * sizeof(BOOL));
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, BOOL aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 2U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 2; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 2) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, BOOL aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 0) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const BOOL kKeys1[] = { YES, NO };
+ const BOOL kKeys2[] = { NO, YES };
+ const BOOL kValues1[] = { NO, YES };
+ const BOOL kValues2[] = { YES, NO };
+ const BOOL kValues3[] = { YES };
+ GPBBoolBoolDictionary *dict1 =
+ [[GPBBoolBoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBBoolBoolDictionary *dict1prime =
+ [[GPBBoolBoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBBoolBoolDictionary *dict2 =
+ [[GPBBoolBoolDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBBoolBoolDictionary *dict3 =
+ [[GPBBoolBoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBBoolBoolDictionary *dict4 =
+ [[GPBBoolBoolDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 Fewer pairs; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const BOOL kKeys[] = { YES, NO };
+ const BOOL kValues[] = { NO, YES };
+ GPBBoolBoolDictionary *dict =
+ [[GPBBoolBoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolBoolDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBBoolBoolDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const BOOL kKeys[] = { YES, NO };
+ const BOOL kValues[] = { NO, YES };
+ GPBBoolBoolDictionary *dict =
+ [[GPBBoolBoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolBoolDictionary *dict2 =
+ [GPBBoolBoolDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBBoolBoolDictionary *dict = [GPBBoolBoolDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:NO forKey:YES];
+ XCTAssertEqual(dict.count, 1U);
+
+ const BOOL kKeys[] = { NO };
+ const BOOL kValues[] = { YES };
+ GPBBoolBoolDictionary *dict2 =
+ [[GPBBoolBoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, YES);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const BOOL kKeys[] = { YES, NO};
+ const BOOL kValues[] = { NO, YES };
+ GPBBoolBoolDictionary *dict =
+ [[GPBBoolBoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const BOOL kKeys[] = { YES, NO };
+ const BOOL kValues[] = { NO, YES };
+ GPBBoolBoolDictionary *dict =
+ [[GPBBoolBoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, YES);
+
+ [dict setValue:YES forKey:YES];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, YES);
+
+ [dict setValue:NO forKey:NO];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, NO);
+
+ const BOOL kKeys2[] = { NO, YES };
+ const BOOL kValues2[] = { YES, NO };
+ GPBBoolBoolDictionary *dict2 =
+ [[GPBBoolBoolDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, YES);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(Float, float, 500.f, 501.f)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Float
+
+@interface GPBBoolFloatDictionaryTests : XCTestCase
+@end
+
+@implementation GPBBoolFloatDictionaryTests
+
+- (void)testEmpty {
+ GPBBoolFloatDictionary *dict = [[GPBBoolFloatDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, float aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBBoolFloatDictionary *dict = [GPBBoolFloatDictionary dictionaryWithValue:500.f forKey:YES];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ float value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, float aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, YES);
+ XCTAssertEqual(aValue, 500.f);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const BOOL kKeys[] = { YES, NO };
+ const float kValues[] = { 500.f, 501.f };
+ GPBBoolFloatDictionary *dict =
+ [[GPBBoolFloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ float value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ __block NSUInteger idx = 0;
+ BOOL *seenKeys = malloc(2 * sizeof(BOOL));
+ float *seenValues = malloc(2 * sizeof(float));
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, float aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 2U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 2; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 2) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, float aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 0) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const BOOL kKeys1[] = { YES, NO };
+ const BOOL kKeys2[] = { NO, YES };
+ const float kValues1[] = { 500.f, 501.f };
+ const float kValues2[] = { 501.f, 500.f };
+ const float kValues3[] = { 501.f };
+ GPBBoolFloatDictionary *dict1 =
+ [[GPBBoolFloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBBoolFloatDictionary *dict1prime =
+ [[GPBBoolFloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBBoolFloatDictionary *dict2 =
+ [[GPBBoolFloatDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBBoolFloatDictionary *dict3 =
+ [[GPBBoolFloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBBoolFloatDictionary *dict4 =
+ [[GPBBoolFloatDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 Fewer pairs; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const BOOL kKeys[] = { YES, NO };
+ const float kValues[] = { 500.f, 501.f };
+ GPBBoolFloatDictionary *dict =
+ [[GPBBoolFloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolFloatDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBBoolFloatDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const BOOL kKeys[] = { YES, NO };
+ const float kValues[] = { 500.f, 501.f };
+ GPBBoolFloatDictionary *dict =
+ [[GPBBoolFloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolFloatDictionary *dict2 =
+ [GPBBoolFloatDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBBoolFloatDictionary *dict = [GPBBoolFloatDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:500.f forKey:YES];
+ XCTAssertEqual(dict.count, 1U);
+
+ const BOOL kKeys[] = { NO };
+ const float kValues[] = { 501.f };
+ GPBBoolFloatDictionary *dict2 =
+ [[GPBBoolFloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+
+ float value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 501.f);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const BOOL kKeys[] = { YES, NO};
+ const float kValues[] = { 500.f, 501.f };
+ GPBBoolFloatDictionary *dict =
+ [[GPBBoolFloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ float value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const BOOL kKeys[] = { YES, NO };
+ const float kValues[] = { 500.f, 501.f };
+ GPBBoolFloatDictionary *dict =
+ [[GPBBoolFloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ float value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ [dict setValue:501.f forKey:YES];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ [dict setValue:500.f forKey:NO];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 500.f);
+
+ const BOOL kKeys2[] = { NO, YES };
+ const float kValues2[] = { 501.f, 500.f };
+ GPBBoolFloatDictionary *dict2 =
+ [[GPBBoolFloatDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(Double, double, 600., 601.)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Double
+
+@interface GPBBoolDoubleDictionaryTests : XCTestCase
+@end
+
+@implementation GPBBoolDoubleDictionaryTests
+
+- (void)testEmpty {
+ GPBBoolDoubleDictionary *dict = [[GPBBoolDoubleDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, double aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBBoolDoubleDictionary *dict = [GPBBoolDoubleDictionary dictionaryWithValue:600. forKey:YES];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ double value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, double aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, YES);
+ XCTAssertEqual(aValue, 600.);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const BOOL kKeys[] = { YES, NO };
+ const double kValues[] = { 600., 601. };
+ GPBBoolDoubleDictionary *dict =
+ [[GPBBoolDoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ double value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ __block NSUInteger idx = 0;
+ BOOL *seenKeys = malloc(2 * sizeof(BOOL));
+ double *seenValues = malloc(2 * sizeof(double));
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, double aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 2U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 2; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 2) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, double aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 0) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const BOOL kKeys1[] = { YES, NO };
+ const BOOL kKeys2[] = { NO, YES };
+ const double kValues1[] = { 600., 601. };
+ const double kValues2[] = { 601., 600. };
+ const double kValues3[] = { 601. };
+ GPBBoolDoubleDictionary *dict1 =
+ [[GPBBoolDoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBBoolDoubleDictionary *dict1prime =
+ [[GPBBoolDoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBBoolDoubleDictionary *dict2 =
+ [[GPBBoolDoubleDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBBoolDoubleDictionary *dict3 =
+ [[GPBBoolDoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBBoolDoubleDictionary *dict4 =
+ [[GPBBoolDoubleDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 Fewer pairs; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const BOOL kKeys[] = { YES, NO };
+ const double kValues[] = { 600., 601. };
+ GPBBoolDoubleDictionary *dict =
+ [[GPBBoolDoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolDoubleDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBBoolDoubleDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const BOOL kKeys[] = { YES, NO };
+ const double kValues[] = { 600., 601. };
+ GPBBoolDoubleDictionary *dict =
+ [[GPBBoolDoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolDoubleDictionary *dict2 =
+ [GPBBoolDoubleDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBBoolDoubleDictionary *dict = [GPBBoolDoubleDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:600. forKey:YES];
+ XCTAssertEqual(dict.count, 1U);
+
+ const BOOL kKeys[] = { NO };
+ const double kValues[] = { 601. };
+ GPBBoolDoubleDictionary *dict2 =
+ [[GPBBoolDoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+
+ double value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 601.);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const BOOL kKeys[] = { YES, NO};
+ const double kValues[] = { 600., 601. };
+ GPBBoolDoubleDictionary *dict =
+ [[GPBBoolDoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ double value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const BOOL kKeys[] = { YES, NO };
+ const double kValues[] = { 600., 601. };
+ GPBBoolDoubleDictionary *dict =
+ [[GPBBoolDoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ double value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ [dict setValue:601. forKey:YES];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ [dict setValue:600. forKey:NO];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 600.);
+
+ const BOOL kKeys2[] = { NO, YES };
+ const double kValues2[] = { 601., 600. };
+ GPBBoolDoubleDictionary *dict2 =
+ [[GPBBoolDoubleDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND TESTS_FOR_BOOL_KEY_OBJECT_VALUE(Object, id, @"abc", @"def")
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Object
+
+@interface GPBBoolObjectDictionaryTests : XCTestCase
+@end
+
+@implementation GPBBoolObjectDictionaryTests
+
+- (void)testEmpty {
+ GPBBoolObjectDictionary *dict = [[GPBBoolObjectDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertNil([dict valueForKey:YES]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, id aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBBoolObjectDictionary *dict = [GPBBoolObjectDictionary dictionaryWithValue:@"abc" forKey:YES];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertEqualObjects([dict valueForKey:YES], @"abc");
+ XCTAssertNil([dict valueForKey:NO]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, id aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, YES);
+ XCTAssertEqualObjects(aValue, @"abc");
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const BOOL kKeys[] = { YES, NO };
+ const id kValues[] = { @"abc", @"def" };
+ GPBBoolObjectDictionary *dict =
+ [[GPBBoolObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertEqualObjects([dict valueForKey:YES], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:NO], @"def");
+
+ __block NSUInteger idx = 0;
+ BOOL *seenKeys = malloc(2 * sizeof(BOOL));
+ id *seenValues = malloc(2 * sizeof(id));
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, id aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 2U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 2; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 2) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqualObjects(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, id aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 0) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const BOOL kKeys1[] = { YES, NO };
+ const BOOL kKeys2[] = { NO, YES };
+ const id kValues1[] = { @"abc", @"def" };
+ const id kValues2[] = { @"def", @"abc" };
+ const id kValues3[] = { @"def" };
+ GPBBoolObjectDictionary *dict1 =
+ [[GPBBoolObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBBoolObjectDictionary *dict1prime =
+ [[GPBBoolObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBBoolObjectDictionary *dict2 =
+ [[GPBBoolObjectDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBBoolObjectDictionary *dict3 =
+ [[GPBBoolObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBBoolObjectDictionary *dict4 =
+ [[GPBBoolObjectDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 Fewer pairs; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const BOOL kKeys[] = { YES, NO };
+ const id kValues[] = { @"abc", @"def" };
+ GPBBoolObjectDictionary *dict =
+ [[GPBBoolObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolObjectDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBBoolObjectDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const BOOL kKeys[] = { YES, NO };
+ const id kValues[] = { @"abc", @"def" };
+ GPBBoolObjectDictionary *dict =
+ [[GPBBoolObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolObjectDictionary *dict2 =
+ [GPBBoolObjectDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBBoolObjectDictionary *dict = [GPBBoolObjectDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:@"abc" forKey:YES];
+ XCTAssertEqual(dict.count, 1U);
+
+ const BOOL kKeys[] = { NO };
+ const id kValues[] = { @"def" };
+ GPBBoolObjectDictionary *dict2 =
+ [[GPBBoolObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+
+ XCTAssertEqualObjects([dict valueForKey:YES], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:NO], @"def");
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const BOOL kKeys[] = { YES, NO};
+ const id kValues[] = { @"abc", @"def" };
+ GPBBoolObjectDictionary *dict =
+ [[GPBBoolObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertEqualObjects([dict valueForKey:YES], @"abc");
+ XCTAssertNil([dict valueForKey:NO]);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertEqualObjects([dict valueForKey:YES], @"abc");
+ XCTAssertNil([dict valueForKey:NO]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertNil([dict valueForKey:YES]);
+ XCTAssertNil([dict valueForKey:NO]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const BOOL kKeys[] = { YES, NO };
+ const id kValues[] = { @"abc", @"def" };
+ GPBBoolObjectDictionary *dict =
+ [[GPBBoolObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertEqualObjects([dict valueForKey:YES], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:NO], @"def");
+
+ [dict setValue:@"def" forKey:YES];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertEqualObjects([dict valueForKey:YES], @"def");
+ XCTAssertEqualObjects([dict valueForKey:NO], @"def");
+
+ [dict setValue:@"abc" forKey:NO];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertEqualObjects([dict valueForKey:YES], @"def");
+ XCTAssertEqualObjects([dict valueForKey:NO], @"abc");
+
+ const BOOL kKeys2[] = { NO, YES };
+ const id kValues2[] = { @"def", @"abc" };
+ GPBBoolObjectDictionary *dict2 =
+ [[GPBBoolObjectDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertEqualObjects([dict valueForKey:YES], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:NO], @"def");
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND-END (8 expansions)
+
+
diff --git a/objectivec/Tests/GPBDictionaryTests+Int32.m b/objectivec/Tests/GPBDictionaryTests+Int32.m
new file mode 100644
index 00000000..5e25799c
--- /dev/null
+++ b/objectivec/Tests/GPBDictionaryTests+Int32.m
@@ -0,0 +1,3650 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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 "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+
+// Pull in the macros (using an external file because expanding all tests
+// in a single file makes a file that is failing to work with within Xcode.
+//%PDDM-IMPORT-DEFINES GPBDictionaryTests.pddm
+
+//%PDDM-EXPAND TEST_FOR_POD_KEY(Int32, int32_t, 11, 12, 13, 14)
+// This block of code is generated, do not edit it directly.
+
+#ifndef GPBARRAYSIZE
+#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))))
+#endif // GPBARRAYSIZE
+
+// To let the testing macros work, add some extra methods to simplify things.
+@interface GPBInt32EnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(int32_t)key;
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count;
+@end
+
+static BOOL TestingEnum_IsValidValue(int32_t value) {
+ switch (value) {
+ case 700:
+ case 701:
+ case 702:
+ case 703:
+ return YES;
+ default:
+ return NO;
+ }
+}
+
+@implementation GPBInt32EnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(int32_t)key {
+ // Cast is needed to compiler knows what class we are invoking initWithValues: on to get the
+ // type correct.
+ return [[(GPBInt32EnumDictionary*)[self alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count {
+ return [self initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:values
+ forKeys:keys
+ count:count];
+}
+@end
+
+
+#pragma mark - Int32 -> UInt32
+
+@interface GPBInt32UInt32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt32UInt32DictionaryTests
+
+- (void)testEmpty {
+ GPBInt32UInt32Dictionary *dict = [[GPBInt32UInt32Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, uint32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt32UInt32Dictionary *dict = [GPBInt32UInt32Dictionary dictionaryWithValue:100U forKey:11];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, uint32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 11);
+ XCTAssertEqual(aValue, 100U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int32_t kKeys[] = { 11, 12, 13 };
+ const uint32_t kValues[] = { 100U, 101U, 102U };
+ GPBInt32UInt32Dictionary *dict =
+ [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+ uint32_t *seenValues = malloc(3 * sizeof(uint32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, uint32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, uint32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int32_t kKeys1[] = { 11, 12, 13, 14 };
+ const int32_t kKeys2[] = { 12, 11, 14 };
+ const uint32_t kValues1[] = { 100U, 101U, 102U };
+ const uint32_t kValues2[] = { 100U, 103U, 102U };
+ const uint32_t kValues3[] = { 100U, 101U, 102U, 103U };
+ GPBInt32UInt32Dictionary *dict1 =
+ [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt32UInt32Dictionary *dict1prime =
+ [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt32UInt32Dictionary *dict2 =
+ [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt32UInt32Dictionary *dict3 =
+ [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt32UInt32Dictionary *dict4 =
+ [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBInt32UInt32Dictionary *dict =
+ [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32UInt32Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt32UInt32Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBInt32UInt32Dictionary *dict =
+ [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32UInt32Dictionary *dict2 =
+ [GPBInt32UInt32Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt32UInt32Dictionary *dict = [GPBInt32UInt32Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:100U forKey:11];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int32_t kKeys[] = { 12, 13, 14 };
+ const uint32_t kValues[] = { 101U, 102U, 103U };
+ GPBInt32UInt32Dictionary *dict2 =
+ [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 103U);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBInt32UInt32Dictionary *dict =
+ [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict removeValueForKey:14];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertFalse([dict valueForKey:13 value:NULL]);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBInt32UInt32Dictionary *dict =
+ [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict setValue:103U forKey:11];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict setValue:101U forKey:14];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ const int32_t kKeys2[] = { 12, 13 };
+ const uint32_t kValues2[] = { 102U, 100U };
+ GPBInt32UInt32Dictionary *dict2 =
+ [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int32 -> Int32
+
+@interface GPBInt32Int32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt32Int32DictionaryTests
+
+- (void)testEmpty {
+ GPBInt32Int32Dictionary *dict = [[GPBInt32Int32Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt32Int32Dictionary *dict = [GPBInt32Int32Dictionary dictionaryWithValue:200 forKey:11];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 11);
+ XCTAssertEqual(aValue, 200);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int32_t kKeys[] = { 11, 12, 13 };
+ const int32_t kValues[] = { 200, 201, 202 };
+ GPBInt32Int32Dictionary *dict =
+ [[GPBInt32Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int32_t kKeys1[] = { 11, 12, 13, 14 };
+ const int32_t kKeys2[] = { 12, 11, 14 };
+ const int32_t kValues1[] = { 200, 201, 202 };
+ const int32_t kValues2[] = { 200, 203, 202 };
+ const int32_t kValues3[] = { 200, 201, 202, 203 };
+ GPBInt32Int32Dictionary *dict1 =
+ [[GPBInt32Int32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt32Int32Dictionary *dict1prime =
+ [[GPBInt32Int32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt32Int32Dictionary *dict2 =
+ [[GPBInt32Int32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt32Int32Dictionary *dict3 =
+ [[GPBInt32Int32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt32Int32Dictionary *dict4 =
+ [[GPBInt32Int32Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBInt32Int32Dictionary *dict =
+ [[GPBInt32Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32Int32Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt32Int32Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBInt32Int32Dictionary *dict =
+ [[GPBInt32Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32Int32Dictionary *dict2 =
+ [GPBInt32Int32Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt32Int32Dictionary *dict = [GPBInt32Int32Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:200 forKey:11];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int32_t kKeys[] = { 12, 13, 14 };
+ const int32_t kValues[] = { 201, 202, 203 };
+ GPBInt32Int32Dictionary *dict2 =
+ [[GPBInt32Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 203);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBInt32Int32Dictionary *dict =
+ [[GPBInt32Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 203);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict removeValueForKey:14];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertFalse([dict valueForKey:13 value:NULL]);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBInt32Int32Dictionary *dict =
+ [[GPBInt32Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict setValue:203 forKey:11];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict setValue:201 forKey:14];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 201);
+
+ const int32_t kKeys2[] = { 12, 13 };
+ const int32_t kValues2[] = { 202, 200 };
+ GPBInt32Int32Dictionary *dict2 =
+ [[GPBInt32Int32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 201);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int32 -> UInt64
+
+@interface GPBInt32UInt64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt32UInt64DictionaryTests
+
+- (void)testEmpty {
+ GPBInt32UInt64Dictionary *dict = [[GPBInt32UInt64Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, uint64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt32UInt64Dictionary *dict = [GPBInt32UInt64Dictionary dictionaryWithValue:300U forKey:11];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, uint64_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 11);
+ XCTAssertEqual(aValue, 300U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int32_t kKeys[] = { 11, 12, 13 };
+ const uint64_t kValues[] = { 300U, 301U, 302U };
+ GPBInt32UInt64Dictionary *dict =
+ [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+ uint64_t *seenValues = malloc(3 * sizeof(uint64_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, uint64_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, uint64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int32_t kKeys1[] = { 11, 12, 13, 14 };
+ const int32_t kKeys2[] = { 12, 11, 14 };
+ const uint64_t kValues1[] = { 300U, 301U, 302U };
+ const uint64_t kValues2[] = { 300U, 303U, 302U };
+ const uint64_t kValues3[] = { 300U, 301U, 302U, 303U };
+ GPBInt32UInt64Dictionary *dict1 =
+ [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt32UInt64Dictionary *dict1prime =
+ [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt32UInt64Dictionary *dict2 =
+ [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt32UInt64Dictionary *dict3 =
+ [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt32UInt64Dictionary *dict4 =
+ [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBInt32UInt64Dictionary *dict =
+ [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32UInt64Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt32UInt64Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBInt32UInt64Dictionary *dict =
+ [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32UInt64Dictionary *dict2 =
+ [GPBInt32UInt64Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt32UInt64Dictionary *dict = [GPBInt32UInt64Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:300U forKey:11];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int32_t kKeys[] = { 12, 13, 14 };
+ const uint64_t kValues[] = { 301U, 302U, 303U };
+ GPBInt32UInt64Dictionary *dict2 =
+ [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 303U);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBInt32UInt64Dictionary *dict =
+ [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict removeValueForKey:14];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertFalse([dict valueForKey:13 value:NULL]);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBInt32UInt64Dictionary *dict =
+ [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict setValue:303U forKey:11];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict setValue:301U forKey:14];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ const int32_t kKeys2[] = { 12, 13 };
+ const uint64_t kValues2[] = { 302U, 300U };
+ GPBInt32UInt64Dictionary *dict2 =
+ [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int32 -> Int64
+
+@interface GPBInt32Int64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt32Int64DictionaryTests
+
+- (void)testEmpty {
+ GPBInt32Int64Dictionary *dict = [[GPBInt32Int64Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt32Int64Dictionary *dict = [GPBInt32Int64Dictionary dictionaryWithValue:400 forKey:11];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int64_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 11);
+ XCTAssertEqual(aValue, 400);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int32_t kKeys[] = { 11, 12, 13 };
+ const int64_t kValues[] = { 400, 401, 402 };
+ GPBInt32Int64Dictionary *dict =
+ [[GPBInt32Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+ int64_t *seenValues = malloc(3 * sizeof(int64_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int64_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int32_t kKeys1[] = { 11, 12, 13, 14 };
+ const int32_t kKeys2[] = { 12, 11, 14 };
+ const int64_t kValues1[] = { 400, 401, 402 };
+ const int64_t kValues2[] = { 400, 403, 402 };
+ const int64_t kValues3[] = { 400, 401, 402, 403 };
+ GPBInt32Int64Dictionary *dict1 =
+ [[GPBInt32Int64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt32Int64Dictionary *dict1prime =
+ [[GPBInt32Int64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt32Int64Dictionary *dict2 =
+ [[GPBInt32Int64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt32Int64Dictionary *dict3 =
+ [[GPBInt32Int64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt32Int64Dictionary *dict4 =
+ [[GPBInt32Int64Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBInt32Int64Dictionary *dict =
+ [[GPBInt32Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32Int64Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt32Int64Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBInt32Int64Dictionary *dict =
+ [[GPBInt32Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32Int64Dictionary *dict2 =
+ [GPBInt32Int64Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt32Int64Dictionary *dict = [GPBInt32Int64Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:400 forKey:11];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int32_t kKeys[] = { 12, 13, 14 };
+ const int64_t kValues[] = { 401, 402, 403 };
+ GPBInt32Int64Dictionary *dict2 =
+ [[GPBInt32Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 403);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBInt32Int64Dictionary *dict =
+ [[GPBInt32Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 403);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict removeValueForKey:14];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertFalse([dict valueForKey:13 value:NULL]);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBInt32Int64Dictionary *dict =
+ [[GPBInt32Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict setValue:403 forKey:11];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict setValue:401 forKey:14];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 401);
+
+ const int32_t kKeys2[] = { 12, 13 };
+ const int64_t kValues2[] = { 402, 400 };
+ GPBInt32Int64Dictionary *dict2 =
+ [[GPBInt32Int64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 401);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int32 -> Bool
+
+@interface GPBInt32BoolDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt32BoolDictionaryTests
+
+- (void)testEmpty {
+ GPBInt32BoolDictionary *dict = [[GPBInt32BoolDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, BOOL aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt32BoolDictionary *dict = [GPBInt32BoolDictionary dictionaryWithValue:YES forKey:11];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, BOOL aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 11);
+ XCTAssertEqual(aValue, YES);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int32_t kKeys[] = { 11, 12, 13 };
+ const BOOL kValues[] = { YES, YES, NO };
+ GPBInt32BoolDictionary *dict =
+ [[GPBInt32BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+ BOOL *seenValues = malloc(3 * sizeof(BOOL));
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, BOOL aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, BOOL aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int32_t kKeys1[] = { 11, 12, 13, 14 };
+ const int32_t kKeys2[] = { 12, 11, 14 };
+ const BOOL kValues1[] = { YES, YES, NO };
+ const BOOL kValues2[] = { YES, NO, NO };
+ const BOOL kValues3[] = { YES, YES, NO, NO };
+ GPBInt32BoolDictionary *dict1 =
+ [[GPBInt32BoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt32BoolDictionary *dict1prime =
+ [[GPBInt32BoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt32BoolDictionary *dict2 =
+ [[GPBInt32BoolDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt32BoolDictionary *dict3 =
+ [[GPBInt32BoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt32BoolDictionary *dict4 =
+ [[GPBInt32BoolDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBInt32BoolDictionary *dict =
+ [[GPBInt32BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32BoolDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt32BoolDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBInt32BoolDictionary *dict =
+ [[GPBInt32BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32BoolDictionary *dict2 =
+ [GPBInt32BoolDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt32BoolDictionary *dict = [GPBInt32BoolDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:YES forKey:11];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int32_t kKeys[] = { 12, 13, 14 };
+ const BOOL kValues[] = { YES, NO, NO };
+ GPBInt32BoolDictionary *dict2 =
+ [[GPBInt32BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, NO);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBInt32BoolDictionary *dict =
+ [[GPBInt32BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, NO);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict removeValueForKey:14];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertFalse([dict valueForKey:13 value:NULL]);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBInt32BoolDictionary *dict =
+ [[GPBInt32BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict setValue:NO forKey:11];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict setValue:YES forKey:14];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, YES);
+
+ const int32_t kKeys2[] = { 12, 13 };
+ const BOOL kValues2[] = { NO, YES };
+ GPBInt32BoolDictionary *dict2 =
+ [[GPBInt32BoolDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, YES);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int32 -> Float
+
+@interface GPBInt32FloatDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt32FloatDictionaryTests
+
+- (void)testEmpty {
+ GPBInt32FloatDictionary *dict = [[GPBInt32FloatDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, float aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt32FloatDictionary *dict = [GPBInt32FloatDictionary dictionaryWithValue:500.f forKey:11];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ float value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, float aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 11);
+ XCTAssertEqual(aValue, 500.f);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int32_t kKeys[] = { 11, 12, 13 };
+ const float kValues[] = { 500.f, 501.f, 502.f };
+ GPBInt32FloatDictionary *dict =
+ [[GPBInt32FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ float value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+ float *seenValues = malloc(3 * sizeof(float));
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, float aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, float aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int32_t kKeys1[] = { 11, 12, 13, 14 };
+ const int32_t kKeys2[] = { 12, 11, 14 };
+ const float kValues1[] = { 500.f, 501.f, 502.f };
+ const float kValues2[] = { 500.f, 503.f, 502.f };
+ const float kValues3[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBInt32FloatDictionary *dict1 =
+ [[GPBInt32FloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt32FloatDictionary *dict1prime =
+ [[GPBInt32FloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt32FloatDictionary *dict2 =
+ [[GPBInt32FloatDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt32FloatDictionary *dict3 =
+ [[GPBInt32FloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt32FloatDictionary *dict4 =
+ [[GPBInt32FloatDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBInt32FloatDictionary *dict =
+ [[GPBInt32FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32FloatDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt32FloatDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBInt32FloatDictionary *dict =
+ [[GPBInt32FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32FloatDictionary *dict2 =
+ [GPBInt32FloatDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt32FloatDictionary *dict = [GPBInt32FloatDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:500.f forKey:11];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int32_t kKeys[] = { 12, 13, 14 };
+ const float kValues[] = { 501.f, 502.f, 503.f };
+ GPBInt32FloatDictionary *dict2 =
+ [[GPBInt32FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ float value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 503.f);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBInt32FloatDictionary *dict =
+ [[GPBInt32FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ float value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict removeValueForKey:14];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertFalse([dict valueForKey:13 value:NULL]);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBInt32FloatDictionary *dict =
+ [[GPBInt32FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ float value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict setValue:503.f forKey:11];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict setValue:501.f forKey:14];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ const int32_t kKeys2[] = { 12, 13 };
+ const float kValues2[] = { 502.f, 500.f };
+ GPBInt32FloatDictionary *dict2 =
+ [[GPBInt32FloatDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int32 -> Double
+
+@interface GPBInt32DoubleDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt32DoubleDictionaryTests
+
+- (void)testEmpty {
+ GPBInt32DoubleDictionary *dict = [[GPBInt32DoubleDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, double aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt32DoubleDictionary *dict = [GPBInt32DoubleDictionary dictionaryWithValue:600. forKey:11];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ double value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, double aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 11);
+ XCTAssertEqual(aValue, 600.);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int32_t kKeys[] = { 11, 12, 13 };
+ const double kValues[] = { 600., 601., 602. };
+ GPBInt32DoubleDictionary *dict =
+ [[GPBInt32DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ double value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+ double *seenValues = malloc(3 * sizeof(double));
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, double aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, double aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int32_t kKeys1[] = { 11, 12, 13, 14 };
+ const int32_t kKeys2[] = { 12, 11, 14 };
+ const double kValues1[] = { 600., 601., 602. };
+ const double kValues2[] = { 600., 603., 602. };
+ const double kValues3[] = { 600., 601., 602., 603. };
+ GPBInt32DoubleDictionary *dict1 =
+ [[GPBInt32DoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt32DoubleDictionary *dict1prime =
+ [[GPBInt32DoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt32DoubleDictionary *dict2 =
+ [[GPBInt32DoubleDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt32DoubleDictionary *dict3 =
+ [[GPBInt32DoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt32DoubleDictionary *dict4 =
+ [[GPBInt32DoubleDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBInt32DoubleDictionary *dict =
+ [[GPBInt32DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32DoubleDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt32DoubleDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBInt32DoubleDictionary *dict =
+ [[GPBInt32DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32DoubleDictionary *dict2 =
+ [GPBInt32DoubleDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt32DoubleDictionary *dict = [GPBInt32DoubleDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:600. forKey:11];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int32_t kKeys[] = { 12, 13, 14 };
+ const double kValues[] = { 601., 602., 603. };
+ GPBInt32DoubleDictionary *dict2 =
+ [[GPBInt32DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ double value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 603.);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBInt32DoubleDictionary *dict =
+ [[GPBInt32DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ double value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict removeValueForKey:14];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertFalse([dict valueForKey:13 value:NULL]);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBInt32DoubleDictionary *dict =
+ [[GPBInt32DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ double value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict setValue:603. forKey:11];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict setValue:601. forKey:14];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ const int32_t kKeys2[] = { 12, 13 };
+ const double kValues2[] = { 602., 600. };
+ GPBInt32DoubleDictionary *dict2 =
+ [[GPBInt32DoubleDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int32 -> Enum
+
+@interface GPBInt32EnumDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt32EnumDictionaryTests
+
+- (void)testEmpty {
+ GPBInt32EnumDictionary *dict = [[GPBInt32EnumDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt32EnumDictionary *dict = [GPBInt32EnumDictionary dictionaryWithValue:700 forKey:11];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 11);
+ XCTAssertEqual(aValue, 700);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int32_t kKeys[] = { 11, 12, 13 };
+ const int32_t kValues[] = { 700, 701, 702 };
+ GPBInt32EnumDictionary *dict =
+ [[GPBInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int32_t kKeys1[] = { 11, 12, 13, 14 };
+ const int32_t kKeys2[] = { 12, 11, 14 };
+ const int32_t kValues1[] = { 700, 701, 702 };
+ const int32_t kValues2[] = { 700, 703, 702 };
+ const int32_t kValues3[] = { 700, 701, 702, 703 };
+ GPBInt32EnumDictionary *dict1 =
+ [[GPBInt32EnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt32EnumDictionary *dict1prime =
+ [[GPBInt32EnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt32EnumDictionary *dict2 =
+ [[GPBInt32EnumDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt32EnumDictionary *dict3 =
+ [[GPBInt32EnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt32EnumDictionary *dict4 =
+ [[GPBInt32EnumDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBInt32EnumDictionary *dict =
+ [[GPBInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32EnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt32EnumDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBInt32EnumDictionary *dict =
+ [[GPBInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32EnumDictionary *dict2 =
+ [GPBInt32EnumDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt32EnumDictionary *dict = [GPBInt32EnumDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:700 forKey:11];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int32_t kKeys[] = { 12, 13, 14 };
+ const int32_t kValues[] = { 701, 702, 703 };
+ GPBInt32EnumDictionary *dict2 =
+ [[GPBInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 703);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBInt32EnumDictionary *dict =
+ [[GPBInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 703);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict removeValueForKey:14];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertFalse([dict valueForKey:13 value:NULL]);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBInt32EnumDictionary *dict =
+ [[GPBInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict setValue:703 forKey:11];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict setValue:701 forKey:14];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 701);
+
+ const int32_t kKeys2[] = { 12, 13 };
+ const int32_t kValues2[] = { 702, 700 };
+ GPBInt32EnumDictionary *dict2 =
+ [[GPBInt32EnumDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 701);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int32 -> Enum (Unknown Enums)
+
+@interface GPBInt32EnumDictionaryUnknownEnumTests : XCTestCase
+@end
+
+@implementation GPBInt32EnumDictionaryUnknownEnumTests
+
+- (void)testRawBasics {
+ const int32_t kKeys[] = { 11, 12, 13 };
+ const int32_t kValues[] = { 700, 801, 702 };
+ GPBInt32EnumDictionary *dict =
+ [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue(dict.validationFunc == TestingEnum_IsValidValue); // Pointer comparison
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:11 rawValue:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:12 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:12 rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:13 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:13 rawValue:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:14 rawValue:NULL]);
+
+ __block NSUInteger idx = 0;
+ int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ if (i == 1) {
+ XCTAssertEqual(kGPBUnrecognizedEnumeratorValue, seenValues[j], @"i = %d, j = %d", i, j);
+ } else {
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ idx = 0;
+ [dict enumerateKeysAndRawValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndRawValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEqualityWithUnknowns {
+ const int32_t kKeys1[] = { 11, 12, 13, 14 };
+ const int32_t kKeys2[] = { 12, 11, 14 };
+ const int32_t kValues1[] = { 700, 801, 702 }; // Unknown
+ const int32_t kValues2[] = { 700, 803, 702 }; // Unknown
+ const int32_t kValues3[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBInt32EnumDictionary *dict1 =
+ [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt32EnumDictionary *dict1prime =
+ [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt32EnumDictionary *dict2 =
+ [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt32EnumDictionary *dict3 =
+ [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt32EnumDictionary *dict4 =
+ [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopyWithUnknowns {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknown
+ GPBInt32EnumDictionary *dict =
+ [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32EnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ XCTAssertEqualObjects(dict, dict2);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBInt32EnumDictionary *dict =
+ [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32EnumDictionary *dict2 =
+ [GPBInt32EnumDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ [dict release];
+}
+
+- (void)testUnknownAdds {
+ GPBInt32EnumDictionary *dict =
+ [GPBInt32EnumDictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertThrowsSpecificNamed([dict setValue:801 forKey:12], // Unknown
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(dict.count, 0U);
+ [dict setRawValue:801 forKey:12]; // Unknown
+ XCTAssertEqual(dict.count, 1U);
+
+ const int32_t kKeys[] = { 11, 13, 14 };
+ const int32_t kValues[] = { 700, 702, 803 }; // Unknown
+ GPBInt32EnumDictionary *dict2 =
+ [[GPBInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:12 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:12 rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:14 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:14 rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ [dict2 release];
+}
+
+- (void)testUnknownRemove {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBInt32EnumDictionary *dict =
+ [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:14 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:14 rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:14 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:14 rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict removeValueForKey:14];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertFalse([dict valueForKey:13 value:NULL]);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutationUnknowns {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBInt32EnumDictionary *dict =
+ [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:12 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:12 rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:14 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:14 rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ XCTAssertThrowsSpecificNamed([dict setValue:803 forKey:11], // Unknown
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:12 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:12 rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:14 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:14 rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict setRawValue:803 forKey:11]; // Unknown
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:11 rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:12 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:12 rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:14 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:14 rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict setRawValue:700 forKey:14];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:11 rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:12 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:12 rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 700);
+
+ const int32_t kKeys2[] = { 12, 13 };
+ const int32_t kValues2[] = { 702, 801 }; // Unknown
+ GPBInt32EnumDictionary *dict2 =
+ [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:11 rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:13 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:13 rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 700);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testCopyUnknowns {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int32_t kValues[] = { 700, 801, 702, 803 };
+ GPBInt32EnumDictionary *dict =
+ [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32EnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt32EnumDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int32 -> Object
+
+@interface GPBInt32ObjectDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt32ObjectDictionaryTests
+
+- (void)testEmpty {
+ GPBInt32ObjectDictionary *dict = [[GPBInt32ObjectDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertNil([dict valueForKey:11]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, id aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt32ObjectDictionary *dict = [GPBInt32ObjectDictionary dictionaryWithValue:@"abc" forKey:11];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertEqualObjects([dict valueForKey:11], @"abc");
+ XCTAssertNil([dict valueForKey:12]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, id aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 11);
+ XCTAssertEqualObjects(aValue, @"abc");
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int32_t kKeys[] = { 11, 12, 13 };
+ const id kValues[] = { @"abc", @"def", @"ghi" };
+ GPBInt32ObjectDictionary *dict =
+ [[GPBInt32ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertEqualObjects([dict valueForKey:11], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:12], @"def");
+ XCTAssertEqualObjects([dict valueForKey:13], @"ghi");
+ XCTAssertNil([dict valueForKey:14]);
+
+ __block NSUInteger idx = 0;
+ int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+ id *seenValues = malloc(3 * sizeof(id));
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, id aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqualObjects(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, id aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int32_t kKeys1[] = { 11, 12, 13, 14 };
+ const int32_t kKeys2[] = { 12, 11, 14 };
+ const id kValues1[] = { @"abc", @"def", @"ghi" };
+ const id kValues2[] = { @"abc", @"jkl", @"ghi" };
+ const id kValues3[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBInt32ObjectDictionary *dict1 =
+ [[GPBInt32ObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt32ObjectDictionary *dict1prime =
+ [[GPBInt32ObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt32ObjectDictionary *dict2 =
+ [[GPBInt32ObjectDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt32ObjectDictionary *dict3 =
+ [[GPBInt32ObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt32ObjectDictionary *dict4 =
+ [[GPBInt32ObjectDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBInt32ObjectDictionary *dict =
+ [[GPBInt32ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32ObjectDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt32ObjectDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBInt32ObjectDictionary *dict =
+ [[GPBInt32ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32ObjectDictionary *dict2 =
+ [GPBInt32ObjectDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt32ObjectDictionary *dict = [GPBInt32ObjectDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:@"abc" forKey:11];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int32_t kKeys[] = { 12, 13, 14 };
+ const id kValues[] = { @"def", @"ghi", @"jkl" };
+ GPBInt32ObjectDictionary *dict2 =
+ [[GPBInt32ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ XCTAssertEqualObjects([dict valueForKey:11], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:12], @"def");
+ XCTAssertEqualObjects([dict valueForKey:13], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:14], @"jkl");
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBInt32ObjectDictionary *dict =
+ [[GPBInt32ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertEqualObjects([dict valueForKey:11], @"abc");
+ XCTAssertNil([dict valueForKey:12]);
+ XCTAssertEqualObjects([dict valueForKey:13], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:14], @"jkl");
+
+ // Remove again does nothing.
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertEqualObjects([dict valueForKey:11], @"abc");
+ XCTAssertNil([dict valueForKey:12]);
+ XCTAssertEqualObjects([dict valueForKey:13], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:14], @"jkl");
+
+ [dict removeValueForKey:14];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertEqualObjects([dict valueForKey:11], @"abc");
+ XCTAssertNil([dict valueForKey:12]);
+ XCTAssertEqualObjects([dict valueForKey:13], @"ghi");
+ XCTAssertNil([dict valueForKey:14]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertNil([dict valueForKey:11]);
+ XCTAssertNil([dict valueForKey:12]);
+ XCTAssertNil([dict valueForKey:13]);
+ XCTAssertNil([dict valueForKey:14]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBInt32ObjectDictionary *dict =
+ [[GPBInt32ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:11], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:12], @"def");
+ XCTAssertEqualObjects([dict valueForKey:13], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:14], @"jkl");
+
+ [dict setValue:@"jkl" forKey:11];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:11], @"jkl");
+ XCTAssertEqualObjects([dict valueForKey:12], @"def");
+ XCTAssertEqualObjects([dict valueForKey:13], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:14], @"jkl");
+
+ [dict setValue:@"def" forKey:14];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:11], @"jkl");
+ XCTAssertEqualObjects([dict valueForKey:12], @"def");
+ XCTAssertEqualObjects([dict valueForKey:13], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:14], @"def");
+
+ const int32_t kKeys2[] = { 12, 13 };
+ const id kValues2[] = { @"ghi", @"abc" };
+ GPBInt32ObjectDictionary *dict2 =
+ [[GPBInt32ObjectDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:11], @"jkl");
+ XCTAssertEqualObjects([dict valueForKey:12], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:13], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:14], @"def");
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND-END TEST_FOR_POD_KEY(Int32, int32_t, 11, 12, 13, 14)
+
diff --git a/objectivec/Tests/GPBDictionaryTests+Int64.m b/objectivec/Tests/GPBDictionaryTests+Int64.m
new file mode 100644
index 00000000..6e794d38
--- /dev/null
+++ b/objectivec/Tests/GPBDictionaryTests+Int64.m
@@ -0,0 +1,3650 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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 "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+
+// Pull in the macros (using an external file because expanding all tests
+// in a single file makes a file that is failing to work with within Xcode.
+//%PDDM-IMPORT-DEFINES GPBDictionaryTests.pddm
+
+//%PDDM-EXPAND TEST_FOR_POD_KEY(Int64, int64_t, 21LL, 22LL, 23LL, 24LL)
+// This block of code is generated, do not edit it directly.
+
+#ifndef GPBARRAYSIZE
+#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))))
+#endif // GPBARRAYSIZE
+
+// To let the testing macros work, add some extra methods to simplify things.
+@interface GPBInt64EnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(int64_t)key;
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count;
+@end
+
+static BOOL TestingEnum_IsValidValue(int32_t value) {
+ switch (value) {
+ case 700:
+ case 701:
+ case 702:
+ case 703:
+ return YES;
+ default:
+ return NO;
+ }
+}
+
+@implementation GPBInt64EnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(int64_t)key {
+ // Cast is needed to compiler knows what class we are invoking initWithValues: on to get the
+ // type correct.
+ return [[(GPBInt64EnumDictionary*)[self alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count {
+ return [self initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:values
+ forKeys:keys
+ count:count];
+}
+@end
+
+
+#pragma mark - Int64 -> UInt32
+
+@interface GPBInt64UInt32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt64UInt32DictionaryTests
+
+- (void)testEmpty {
+ GPBInt64UInt32Dictionary *dict = [[GPBInt64UInt32Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, uint32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt64UInt32Dictionary *dict = [GPBInt64UInt32Dictionary dictionaryWithValue:100U forKey:21LL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, uint32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 21LL);
+ XCTAssertEqual(aValue, 100U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+ const uint32_t kValues[] = { 100U, 101U, 102U };
+ GPBInt64UInt32Dictionary *dict =
+ [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+ uint32_t *seenValues = malloc(3 * sizeof(uint32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, uint32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, uint32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+ const uint32_t kValues1[] = { 100U, 101U, 102U };
+ const uint32_t kValues2[] = { 100U, 103U, 102U };
+ const uint32_t kValues3[] = { 100U, 101U, 102U, 103U };
+ GPBInt64UInt32Dictionary *dict1 =
+ [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt64UInt32Dictionary *dict1prime =
+ [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt64UInt32Dictionary *dict2 =
+ [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt64UInt32Dictionary *dict3 =
+ [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt64UInt32Dictionary *dict4 =
+ [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBInt64UInt32Dictionary *dict =
+ [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64UInt32Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt64UInt32Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBInt64UInt32Dictionary *dict =
+ [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64UInt32Dictionary *dict2 =
+ [GPBInt64UInt32Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt64UInt32Dictionary *dict = [GPBInt64UInt32Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:100U forKey:21LL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int64_t kKeys[] = { 22LL, 23LL, 24LL };
+ const uint32_t kValues[] = { 101U, 102U, 103U };
+ GPBInt64UInt32Dictionary *dict2 =
+ [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 103U);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBInt64UInt32Dictionary *dict =
+ [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict removeValueForKey:24LL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:23LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBInt64UInt32Dictionary *dict =
+ [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict setValue:103U forKey:21LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict setValue:101U forKey:24LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ const int64_t kKeys2[] = { 22LL, 23LL };
+ const uint32_t kValues2[] = { 102U, 100U };
+ GPBInt64UInt32Dictionary *dict2 =
+ [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int64 -> Int32
+
+@interface GPBInt64Int32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt64Int32DictionaryTests
+
+- (void)testEmpty {
+ GPBInt64Int32Dictionary *dict = [[GPBInt64Int32Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt64Int32Dictionary *dict = [GPBInt64Int32Dictionary dictionaryWithValue:200 forKey:21LL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 21LL);
+ XCTAssertEqual(aValue, 200);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+ const int32_t kValues[] = { 200, 201, 202 };
+ GPBInt64Int32Dictionary *dict =
+ [[GPBInt64Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+ const int32_t kValues1[] = { 200, 201, 202 };
+ const int32_t kValues2[] = { 200, 203, 202 };
+ const int32_t kValues3[] = { 200, 201, 202, 203 };
+ GPBInt64Int32Dictionary *dict1 =
+ [[GPBInt64Int32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt64Int32Dictionary *dict1prime =
+ [[GPBInt64Int32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt64Int32Dictionary *dict2 =
+ [[GPBInt64Int32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt64Int32Dictionary *dict3 =
+ [[GPBInt64Int32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt64Int32Dictionary *dict4 =
+ [[GPBInt64Int32Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBInt64Int32Dictionary *dict =
+ [[GPBInt64Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64Int32Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt64Int32Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBInt64Int32Dictionary *dict =
+ [[GPBInt64Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64Int32Dictionary *dict2 =
+ [GPBInt64Int32Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt64Int32Dictionary *dict = [GPBInt64Int32Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:200 forKey:21LL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int64_t kKeys[] = { 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 201, 202, 203 };
+ GPBInt64Int32Dictionary *dict2 =
+ [[GPBInt64Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 203);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBInt64Int32Dictionary *dict =
+ [[GPBInt64Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 203);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict removeValueForKey:24LL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:23LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBInt64Int32Dictionary *dict =
+ [[GPBInt64Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict setValue:203 forKey:21LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict setValue:201 forKey:24LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 201);
+
+ const int64_t kKeys2[] = { 22LL, 23LL };
+ const int32_t kValues2[] = { 202, 200 };
+ GPBInt64Int32Dictionary *dict2 =
+ [[GPBInt64Int32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 201);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int64 -> UInt64
+
+@interface GPBInt64UInt64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt64UInt64DictionaryTests
+
+- (void)testEmpty {
+ GPBInt64UInt64Dictionary *dict = [[GPBInt64UInt64Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, uint64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt64UInt64Dictionary *dict = [GPBInt64UInt64Dictionary dictionaryWithValue:300U forKey:21LL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, uint64_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 21LL);
+ XCTAssertEqual(aValue, 300U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+ const uint64_t kValues[] = { 300U, 301U, 302U };
+ GPBInt64UInt64Dictionary *dict =
+ [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+ uint64_t *seenValues = malloc(3 * sizeof(uint64_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, uint64_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, uint64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+ const uint64_t kValues1[] = { 300U, 301U, 302U };
+ const uint64_t kValues2[] = { 300U, 303U, 302U };
+ const uint64_t kValues3[] = { 300U, 301U, 302U, 303U };
+ GPBInt64UInt64Dictionary *dict1 =
+ [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt64UInt64Dictionary *dict1prime =
+ [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt64UInt64Dictionary *dict2 =
+ [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt64UInt64Dictionary *dict3 =
+ [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt64UInt64Dictionary *dict4 =
+ [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBInt64UInt64Dictionary *dict =
+ [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64UInt64Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt64UInt64Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBInt64UInt64Dictionary *dict =
+ [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64UInt64Dictionary *dict2 =
+ [GPBInt64UInt64Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt64UInt64Dictionary *dict = [GPBInt64UInt64Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:300U forKey:21LL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int64_t kKeys[] = { 22LL, 23LL, 24LL };
+ const uint64_t kValues[] = { 301U, 302U, 303U };
+ GPBInt64UInt64Dictionary *dict2 =
+ [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 303U);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBInt64UInt64Dictionary *dict =
+ [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict removeValueForKey:24LL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:23LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBInt64UInt64Dictionary *dict =
+ [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict setValue:303U forKey:21LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict setValue:301U forKey:24LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ const int64_t kKeys2[] = { 22LL, 23LL };
+ const uint64_t kValues2[] = { 302U, 300U };
+ GPBInt64UInt64Dictionary *dict2 =
+ [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int64 -> Int64
+
+@interface GPBInt64Int64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt64Int64DictionaryTests
+
+- (void)testEmpty {
+ GPBInt64Int64Dictionary *dict = [[GPBInt64Int64Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt64Int64Dictionary *dict = [GPBInt64Int64Dictionary dictionaryWithValue:400 forKey:21LL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int64_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 21LL);
+ XCTAssertEqual(aValue, 400);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+ const int64_t kValues[] = { 400, 401, 402 };
+ GPBInt64Int64Dictionary *dict =
+ [[GPBInt64Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+ int64_t *seenValues = malloc(3 * sizeof(int64_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int64_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+ const int64_t kValues1[] = { 400, 401, 402 };
+ const int64_t kValues2[] = { 400, 403, 402 };
+ const int64_t kValues3[] = { 400, 401, 402, 403 };
+ GPBInt64Int64Dictionary *dict1 =
+ [[GPBInt64Int64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt64Int64Dictionary *dict1prime =
+ [[GPBInt64Int64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt64Int64Dictionary *dict2 =
+ [[GPBInt64Int64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt64Int64Dictionary *dict3 =
+ [[GPBInt64Int64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt64Int64Dictionary *dict4 =
+ [[GPBInt64Int64Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBInt64Int64Dictionary *dict =
+ [[GPBInt64Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64Int64Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt64Int64Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBInt64Int64Dictionary *dict =
+ [[GPBInt64Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64Int64Dictionary *dict2 =
+ [GPBInt64Int64Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt64Int64Dictionary *dict = [GPBInt64Int64Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:400 forKey:21LL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int64_t kKeys[] = { 22LL, 23LL, 24LL };
+ const int64_t kValues[] = { 401, 402, 403 };
+ GPBInt64Int64Dictionary *dict2 =
+ [[GPBInt64Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 403);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBInt64Int64Dictionary *dict =
+ [[GPBInt64Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 403);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict removeValueForKey:24LL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:23LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBInt64Int64Dictionary *dict =
+ [[GPBInt64Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict setValue:403 forKey:21LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict setValue:401 forKey:24LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 401);
+
+ const int64_t kKeys2[] = { 22LL, 23LL };
+ const int64_t kValues2[] = { 402, 400 };
+ GPBInt64Int64Dictionary *dict2 =
+ [[GPBInt64Int64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 401);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int64 -> Bool
+
+@interface GPBInt64BoolDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt64BoolDictionaryTests
+
+- (void)testEmpty {
+ GPBInt64BoolDictionary *dict = [[GPBInt64BoolDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, BOOL aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt64BoolDictionary *dict = [GPBInt64BoolDictionary dictionaryWithValue:YES forKey:21LL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, BOOL aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 21LL);
+ XCTAssertEqual(aValue, YES);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+ const BOOL kValues[] = { YES, YES, NO };
+ GPBInt64BoolDictionary *dict =
+ [[GPBInt64BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+ BOOL *seenValues = malloc(3 * sizeof(BOOL));
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, BOOL aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, BOOL aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+ const BOOL kValues1[] = { YES, YES, NO };
+ const BOOL kValues2[] = { YES, NO, NO };
+ const BOOL kValues3[] = { YES, YES, NO, NO };
+ GPBInt64BoolDictionary *dict1 =
+ [[GPBInt64BoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt64BoolDictionary *dict1prime =
+ [[GPBInt64BoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt64BoolDictionary *dict2 =
+ [[GPBInt64BoolDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt64BoolDictionary *dict3 =
+ [[GPBInt64BoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt64BoolDictionary *dict4 =
+ [[GPBInt64BoolDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBInt64BoolDictionary *dict =
+ [[GPBInt64BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64BoolDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt64BoolDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBInt64BoolDictionary *dict =
+ [[GPBInt64BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64BoolDictionary *dict2 =
+ [GPBInt64BoolDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt64BoolDictionary *dict = [GPBInt64BoolDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:YES forKey:21LL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int64_t kKeys[] = { 22LL, 23LL, 24LL };
+ const BOOL kValues[] = { YES, NO, NO };
+ GPBInt64BoolDictionary *dict2 =
+ [[GPBInt64BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, NO);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBInt64BoolDictionary *dict =
+ [[GPBInt64BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, NO);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict removeValueForKey:24LL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:23LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBInt64BoolDictionary *dict =
+ [[GPBInt64BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict setValue:NO forKey:21LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict setValue:YES forKey:24LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, YES);
+
+ const int64_t kKeys2[] = { 22LL, 23LL };
+ const BOOL kValues2[] = { NO, YES };
+ GPBInt64BoolDictionary *dict2 =
+ [[GPBInt64BoolDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, YES);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int64 -> Float
+
+@interface GPBInt64FloatDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt64FloatDictionaryTests
+
+- (void)testEmpty {
+ GPBInt64FloatDictionary *dict = [[GPBInt64FloatDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, float aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt64FloatDictionary *dict = [GPBInt64FloatDictionary dictionaryWithValue:500.f forKey:21LL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ float value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, float aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 21LL);
+ XCTAssertEqual(aValue, 500.f);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+ const float kValues[] = { 500.f, 501.f, 502.f };
+ GPBInt64FloatDictionary *dict =
+ [[GPBInt64FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ float value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+ float *seenValues = malloc(3 * sizeof(float));
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, float aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, float aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+ const float kValues1[] = { 500.f, 501.f, 502.f };
+ const float kValues2[] = { 500.f, 503.f, 502.f };
+ const float kValues3[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBInt64FloatDictionary *dict1 =
+ [[GPBInt64FloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt64FloatDictionary *dict1prime =
+ [[GPBInt64FloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt64FloatDictionary *dict2 =
+ [[GPBInt64FloatDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt64FloatDictionary *dict3 =
+ [[GPBInt64FloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt64FloatDictionary *dict4 =
+ [[GPBInt64FloatDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBInt64FloatDictionary *dict =
+ [[GPBInt64FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64FloatDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt64FloatDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBInt64FloatDictionary *dict =
+ [[GPBInt64FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64FloatDictionary *dict2 =
+ [GPBInt64FloatDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt64FloatDictionary *dict = [GPBInt64FloatDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:500.f forKey:21LL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int64_t kKeys[] = { 22LL, 23LL, 24LL };
+ const float kValues[] = { 501.f, 502.f, 503.f };
+ GPBInt64FloatDictionary *dict2 =
+ [[GPBInt64FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ float value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 503.f);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBInt64FloatDictionary *dict =
+ [[GPBInt64FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ float value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict removeValueForKey:24LL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:23LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBInt64FloatDictionary *dict =
+ [[GPBInt64FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ float value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict setValue:503.f forKey:21LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict setValue:501.f forKey:24LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ const int64_t kKeys2[] = { 22LL, 23LL };
+ const float kValues2[] = { 502.f, 500.f };
+ GPBInt64FloatDictionary *dict2 =
+ [[GPBInt64FloatDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int64 -> Double
+
+@interface GPBInt64DoubleDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt64DoubleDictionaryTests
+
+- (void)testEmpty {
+ GPBInt64DoubleDictionary *dict = [[GPBInt64DoubleDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, double aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt64DoubleDictionary *dict = [GPBInt64DoubleDictionary dictionaryWithValue:600. forKey:21LL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ double value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, double aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 21LL);
+ XCTAssertEqual(aValue, 600.);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+ const double kValues[] = { 600., 601., 602. };
+ GPBInt64DoubleDictionary *dict =
+ [[GPBInt64DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ double value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+ double *seenValues = malloc(3 * sizeof(double));
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, double aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, double aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+ const double kValues1[] = { 600., 601., 602. };
+ const double kValues2[] = { 600., 603., 602. };
+ const double kValues3[] = { 600., 601., 602., 603. };
+ GPBInt64DoubleDictionary *dict1 =
+ [[GPBInt64DoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt64DoubleDictionary *dict1prime =
+ [[GPBInt64DoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt64DoubleDictionary *dict2 =
+ [[GPBInt64DoubleDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt64DoubleDictionary *dict3 =
+ [[GPBInt64DoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt64DoubleDictionary *dict4 =
+ [[GPBInt64DoubleDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBInt64DoubleDictionary *dict =
+ [[GPBInt64DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64DoubleDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt64DoubleDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBInt64DoubleDictionary *dict =
+ [[GPBInt64DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64DoubleDictionary *dict2 =
+ [GPBInt64DoubleDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt64DoubleDictionary *dict = [GPBInt64DoubleDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:600. forKey:21LL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int64_t kKeys[] = { 22LL, 23LL, 24LL };
+ const double kValues[] = { 601., 602., 603. };
+ GPBInt64DoubleDictionary *dict2 =
+ [[GPBInt64DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ double value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 603.);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBInt64DoubleDictionary *dict =
+ [[GPBInt64DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ double value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict removeValueForKey:24LL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:23LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBInt64DoubleDictionary *dict =
+ [[GPBInt64DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ double value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict setValue:603. forKey:21LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict setValue:601. forKey:24LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ const int64_t kKeys2[] = { 22LL, 23LL };
+ const double kValues2[] = { 602., 600. };
+ GPBInt64DoubleDictionary *dict2 =
+ [[GPBInt64DoubleDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int64 -> Enum
+
+@interface GPBInt64EnumDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt64EnumDictionaryTests
+
+- (void)testEmpty {
+ GPBInt64EnumDictionary *dict = [[GPBInt64EnumDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt64EnumDictionary *dict = [GPBInt64EnumDictionary dictionaryWithValue:700 forKey:21LL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 21LL);
+ XCTAssertEqual(aValue, 700);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+ const int32_t kValues[] = { 700, 701, 702 };
+ GPBInt64EnumDictionary *dict =
+ [[GPBInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+ const int32_t kValues1[] = { 700, 701, 702 };
+ const int32_t kValues2[] = { 700, 703, 702 };
+ const int32_t kValues3[] = { 700, 701, 702, 703 };
+ GPBInt64EnumDictionary *dict1 =
+ [[GPBInt64EnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt64EnumDictionary *dict1prime =
+ [[GPBInt64EnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt64EnumDictionary *dict2 =
+ [[GPBInt64EnumDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt64EnumDictionary *dict3 =
+ [[GPBInt64EnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt64EnumDictionary *dict4 =
+ [[GPBInt64EnumDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBInt64EnumDictionary *dict =
+ [[GPBInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64EnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt64EnumDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBInt64EnumDictionary *dict =
+ [[GPBInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64EnumDictionary *dict2 =
+ [GPBInt64EnumDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt64EnumDictionary *dict = [GPBInt64EnumDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:700 forKey:21LL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int64_t kKeys[] = { 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 701, 702, 703 };
+ GPBInt64EnumDictionary *dict2 =
+ [[GPBInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 703);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBInt64EnumDictionary *dict =
+ [[GPBInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 703);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict removeValueForKey:24LL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:23LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBInt64EnumDictionary *dict =
+ [[GPBInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict setValue:703 forKey:21LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict setValue:701 forKey:24LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 701);
+
+ const int64_t kKeys2[] = { 22LL, 23LL };
+ const int32_t kValues2[] = { 702, 700 };
+ GPBInt64EnumDictionary *dict2 =
+ [[GPBInt64EnumDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 701);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int64 -> Enum (Unknown Enums)
+
+@interface GPBInt64EnumDictionaryUnknownEnumTests : XCTestCase
+@end
+
+@implementation GPBInt64EnumDictionaryUnknownEnumTests
+
+- (void)testRawBasics {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+ const int32_t kValues[] = { 700, 801, 702 };
+ GPBInt64EnumDictionary *dict =
+ [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue(dict.validationFunc == TestingEnum_IsValidValue); // Pointer comparison
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL rawValue:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:22LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:23LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL rawValue:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:24LL rawValue:NULL]);
+
+ __block NSUInteger idx = 0;
+ int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ if (i == 1) {
+ XCTAssertEqual(kGPBUnrecognizedEnumeratorValue, seenValues[j], @"i = %d, j = %d", i, j);
+ } else {
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ idx = 0;
+ [dict enumerateKeysAndRawValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndRawValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEqualityWithUnknowns {
+ const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+ const int32_t kValues1[] = { 700, 801, 702 }; // Unknown
+ const int32_t kValues2[] = { 700, 803, 702 }; // Unknown
+ const int32_t kValues3[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBInt64EnumDictionary *dict1 =
+ [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt64EnumDictionary *dict1prime =
+ [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt64EnumDictionary *dict2 =
+ [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt64EnumDictionary *dict3 =
+ [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt64EnumDictionary *dict4 =
+ [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopyWithUnknowns {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknown
+ GPBInt64EnumDictionary *dict =
+ [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64EnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ XCTAssertEqualObjects(dict, dict2);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBInt64EnumDictionary *dict =
+ [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64EnumDictionary *dict2 =
+ [GPBInt64EnumDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ [dict release];
+}
+
+- (void)testUnknownAdds {
+ GPBInt64EnumDictionary *dict =
+ [GPBInt64EnumDictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertThrowsSpecificNamed([dict setValue:801 forKey:22LL], // Unknown
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(dict.count, 0U);
+ [dict setRawValue:801 forKey:22LL]; // Unknown
+ XCTAssertEqual(dict.count, 1U);
+
+ const int64_t kKeys[] = { 21LL, 23LL, 24LL };
+ const int32_t kValues[] = { 700, 702, 803 }; // Unknown
+ GPBInt64EnumDictionary *dict2 =
+ [[GPBInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:22LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:24LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ [dict2 release];
+}
+
+- (void)testUnknownRemove {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBInt64EnumDictionary *dict =
+ [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:24LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:24LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict removeValueForKey:24LL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:23LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutationUnknowns {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBInt64EnumDictionary *dict =
+ [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:22LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:24LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ XCTAssertThrowsSpecificNamed([dict setValue:803 forKey:21LL], // Unknown
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:22LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:24LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict setRawValue:803 forKey:21LL]; // Unknown
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:22LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:24LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict setRawValue:700 forKey:24LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:22LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 700);
+
+ const int64_t kKeys2[] = { 22LL, 23LL };
+ const int32_t kValues2[] = { 702, 801 }; // Unknown
+ GPBInt64EnumDictionary *dict2 =
+ [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:23LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 700);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testCopyUnknowns {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 700, 801, 702, 803 };
+ GPBInt64EnumDictionary *dict =
+ [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64EnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt64EnumDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int64 -> Object
+
+@interface GPBInt64ObjectDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt64ObjectDictionaryTests
+
+- (void)testEmpty {
+ GPBInt64ObjectDictionary *dict = [[GPBInt64ObjectDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertNil([dict valueForKey:21LL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, id aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt64ObjectDictionary *dict = [GPBInt64ObjectDictionary dictionaryWithValue:@"abc" forKey:21LL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertEqualObjects([dict valueForKey:21LL], @"abc");
+ XCTAssertNil([dict valueForKey:22LL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, id aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 21LL);
+ XCTAssertEqualObjects(aValue, @"abc");
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+ const id kValues[] = { @"abc", @"def", @"ghi" };
+ GPBInt64ObjectDictionary *dict =
+ [[GPBInt64ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertEqualObjects([dict valueForKey:21LL], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:22LL], @"def");
+ XCTAssertEqualObjects([dict valueForKey:23LL], @"ghi");
+ XCTAssertNil([dict valueForKey:24LL]);
+
+ __block NSUInteger idx = 0;
+ int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+ id *seenValues = malloc(3 * sizeof(id));
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, id aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqualObjects(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, id aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+ const id kValues1[] = { @"abc", @"def", @"ghi" };
+ const id kValues2[] = { @"abc", @"jkl", @"ghi" };
+ const id kValues3[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBInt64ObjectDictionary *dict1 =
+ [[GPBInt64ObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt64ObjectDictionary *dict1prime =
+ [[GPBInt64ObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt64ObjectDictionary *dict2 =
+ [[GPBInt64ObjectDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt64ObjectDictionary *dict3 =
+ [[GPBInt64ObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt64ObjectDictionary *dict4 =
+ [[GPBInt64ObjectDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBInt64ObjectDictionary *dict =
+ [[GPBInt64ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64ObjectDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt64ObjectDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBInt64ObjectDictionary *dict =
+ [[GPBInt64ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64ObjectDictionary *dict2 =
+ [GPBInt64ObjectDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt64ObjectDictionary *dict = [GPBInt64ObjectDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:@"abc" forKey:21LL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int64_t kKeys[] = { 22LL, 23LL, 24LL };
+ const id kValues[] = { @"def", @"ghi", @"jkl" };
+ GPBInt64ObjectDictionary *dict2 =
+ [[GPBInt64ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ XCTAssertEqualObjects([dict valueForKey:21LL], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:22LL], @"def");
+ XCTAssertEqualObjects([dict valueForKey:23LL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:24LL], @"jkl");
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBInt64ObjectDictionary *dict =
+ [[GPBInt64ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertEqualObjects([dict valueForKey:21LL], @"abc");
+ XCTAssertNil([dict valueForKey:22LL]);
+ XCTAssertEqualObjects([dict valueForKey:23LL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:24LL], @"jkl");
+
+ // Remove again does nothing.
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertEqualObjects([dict valueForKey:21LL], @"abc");
+ XCTAssertNil([dict valueForKey:22LL]);
+ XCTAssertEqualObjects([dict valueForKey:23LL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:24LL], @"jkl");
+
+ [dict removeValueForKey:24LL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertEqualObjects([dict valueForKey:21LL], @"abc");
+ XCTAssertNil([dict valueForKey:22LL]);
+ XCTAssertEqualObjects([dict valueForKey:23LL], @"ghi");
+ XCTAssertNil([dict valueForKey:24LL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertNil([dict valueForKey:21LL]);
+ XCTAssertNil([dict valueForKey:22LL]);
+ XCTAssertNil([dict valueForKey:23LL]);
+ XCTAssertNil([dict valueForKey:24LL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBInt64ObjectDictionary *dict =
+ [[GPBInt64ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:21LL], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:22LL], @"def");
+ XCTAssertEqualObjects([dict valueForKey:23LL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:24LL], @"jkl");
+
+ [dict setValue:@"jkl" forKey:21LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:21LL], @"jkl");
+ XCTAssertEqualObjects([dict valueForKey:22LL], @"def");
+ XCTAssertEqualObjects([dict valueForKey:23LL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:24LL], @"jkl");
+
+ [dict setValue:@"def" forKey:24LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:21LL], @"jkl");
+ XCTAssertEqualObjects([dict valueForKey:22LL], @"def");
+ XCTAssertEqualObjects([dict valueForKey:23LL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:24LL], @"def");
+
+ const int64_t kKeys2[] = { 22LL, 23LL };
+ const id kValues2[] = { @"ghi", @"abc" };
+ GPBInt64ObjectDictionary *dict2 =
+ [[GPBInt64ObjectDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:21LL], @"jkl");
+ XCTAssertEqualObjects([dict valueForKey:22LL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:23LL], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:24LL], @"def");
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND-END TEST_FOR_POD_KEY(Int64, int64_t, 21LL, 22LL, 23LL, 24LL)
+
diff --git a/objectivec/Tests/GPBDictionaryTests+String.m b/objectivec/Tests/GPBDictionaryTests+String.m
new file mode 100644
index 00000000..95bf2d06
--- /dev/null
+++ b/objectivec/Tests/GPBDictionaryTests+String.m
@@ -0,0 +1,3362 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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 "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+
+// Pull in the macros (using an external file because expanding all tests
+// in a single file makes a file that is failing to work with within Xcode.
+//%PDDM-IMPORT-DEFINES GPBDictionaryTests.pddm
+
+//%PDDM-EXPAND TESTS_FOR_POD_VALUES(String, NSString, *, Objects, @"foo", @"bar", @"baz", @"mumble")
+// This block of code is generated, do not edit it directly.
+
+#ifndef GPBARRAYSIZE
+#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))))
+#endif // GPBARRAYSIZE
+
+// To let the testing macros work, add some extra methods to simplify things.
+@interface GPBStringEnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(NSString *)key;
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const NSString * [])keys
+ count:(NSUInteger)count;
+@end
+
+static BOOL TestingEnum_IsValidValue(int32_t value) {
+ switch (value) {
+ case 700:
+ case 701:
+ case 702:
+ case 703:
+ return YES;
+ default:
+ return NO;
+ }
+}
+
+@implementation GPBStringEnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(NSString *)key {
+ // Cast is needed to compiler knows what class we are invoking initWithValues: on to get the
+ // type correct.
+ return [[(GPBStringEnumDictionary*)[self alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const NSString * [])keys
+ count:(NSUInteger)count {
+ return [self initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:values
+ forKeys:keys
+ count:count];
+}
+@end
+
+
+#pragma mark - String -> UInt32
+
+@interface GPBStringUInt32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBStringUInt32DictionaryTests
+
+- (void)testEmpty {
+ GPBStringUInt32Dictionary *dict = [[GPBStringUInt32Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, uint32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBStringUInt32Dictionary *dict = [GPBStringUInt32Dictionary dictionaryWithValue:100U forKey:@"foo"];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, uint32_t aValue, BOOL *stop) {
+ XCTAssertEqualObjects(aKey, @"foo");
+ XCTAssertEqual(aValue, 100U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
+ const uint32_t kValues[] = { 100U, 101U, 102U };
+ GPBStringUInt32Dictionary *dict =
+ [[GPBStringUInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ __block NSUInteger idx = 0;
+ NSString **seenKeys = malloc(3 * sizeof(NSString*));
+ uint32_t *seenValues = malloc(3 * sizeof(uint32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, uint32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if ([kKeys[i] isEqual:seenKeys[j]]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, uint32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
+ const uint32_t kValues1[] = { 100U, 101U, 102U };
+ const uint32_t kValues2[] = { 100U, 103U, 102U };
+ const uint32_t kValues3[] = { 100U, 101U, 102U, 103U };
+ GPBStringUInt32Dictionary *dict1 =
+ [[GPBStringUInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBStringUInt32Dictionary *dict1prime =
+ [[GPBStringUInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBStringUInt32Dictionary *dict2 =
+ [[GPBStringUInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBStringUInt32Dictionary *dict3 =
+ [[GPBStringUInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBStringUInt32Dictionary *dict4 =
+ [[GPBStringUInt32Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBStringUInt32Dictionary *dict =
+ [[GPBStringUInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringUInt32Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBStringUInt32Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBStringUInt32Dictionary *dict =
+ [[GPBStringUInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringUInt32Dictionary *dict2 =
+ [GPBStringUInt32Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBStringUInt32Dictionary *dict = [GPBStringUInt32Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:100U forKey:@"foo"];
+ XCTAssertEqual(dict.count, 1U);
+
+ const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
+ const uint32_t kValues[] = { 101U, 102U, 103U };
+ GPBStringUInt32Dictionary *dict2 =
+ [[GPBStringUInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 103U);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBStringUInt32Dictionary *dict =
+ [[GPBStringUInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict removeValueForKey:@"mumble"];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBStringUInt32Dictionary *dict =
+ [[GPBStringUInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict setValue:103U forKey:@"foo"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict setValue:101U forKey:@"mumble"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ const NSString *kKeys2[] = { @"bar", @"baz" };
+ const uint32_t kValues2[] = { 102U, 100U };
+ GPBStringUInt32Dictionary *dict2 =
+ [[GPBStringUInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - String -> Int32
+
+@interface GPBStringInt32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBStringInt32DictionaryTests
+
+- (void)testEmpty {
+ GPBStringInt32Dictionary *dict = [[GPBStringInt32Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBStringInt32Dictionary *dict = [GPBStringInt32Dictionary dictionaryWithValue:200 forKey:@"foo"];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertEqualObjects(aKey, @"foo");
+ XCTAssertEqual(aValue, 200);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
+ const int32_t kValues[] = { 200, 201, 202 };
+ GPBStringInt32Dictionary *dict =
+ [[GPBStringInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ __block NSUInteger idx = 0;
+ NSString **seenKeys = malloc(3 * sizeof(NSString*));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if ([kKeys[i] isEqual:seenKeys[j]]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
+ const int32_t kValues1[] = { 200, 201, 202 };
+ const int32_t kValues2[] = { 200, 203, 202 };
+ const int32_t kValues3[] = { 200, 201, 202, 203 };
+ GPBStringInt32Dictionary *dict1 =
+ [[GPBStringInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBStringInt32Dictionary *dict1prime =
+ [[GPBStringInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBStringInt32Dictionary *dict2 =
+ [[GPBStringInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBStringInt32Dictionary *dict3 =
+ [[GPBStringInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBStringInt32Dictionary *dict4 =
+ [[GPBStringInt32Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBStringInt32Dictionary *dict =
+ [[GPBStringInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringInt32Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBStringInt32Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBStringInt32Dictionary *dict =
+ [[GPBStringInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringInt32Dictionary *dict2 =
+ [GPBStringInt32Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBStringInt32Dictionary *dict = [GPBStringInt32Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:200 forKey:@"foo"];
+ XCTAssertEqual(dict.count, 1U);
+
+ const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 201, 202, 203 };
+ GPBStringInt32Dictionary *dict2 =
+ [[GPBStringInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 203);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBStringInt32Dictionary *dict =
+ [[GPBStringInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 203);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict removeValueForKey:@"mumble"];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBStringInt32Dictionary *dict =
+ [[GPBStringInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict setValue:203 forKey:@"foo"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict setValue:201 forKey:@"mumble"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 201);
+
+ const NSString *kKeys2[] = { @"bar", @"baz" };
+ const int32_t kValues2[] = { 202, 200 };
+ GPBStringInt32Dictionary *dict2 =
+ [[GPBStringInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 201);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - String -> UInt64
+
+@interface GPBStringUInt64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBStringUInt64DictionaryTests
+
+- (void)testEmpty {
+ GPBStringUInt64Dictionary *dict = [[GPBStringUInt64Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, uint64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBStringUInt64Dictionary *dict = [GPBStringUInt64Dictionary dictionaryWithValue:300U forKey:@"foo"];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, uint64_t aValue, BOOL *stop) {
+ XCTAssertEqualObjects(aKey, @"foo");
+ XCTAssertEqual(aValue, 300U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
+ const uint64_t kValues[] = { 300U, 301U, 302U };
+ GPBStringUInt64Dictionary *dict =
+ [[GPBStringUInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ __block NSUInteger idx = 0;
+ NSString **seenKeys = malloc(3 * sizeof(NSString*));
+ uint64_t *seenValues = malloc(3 * sizeof(uint64_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, uint64_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if ([kKeys[i] isEqual:seenKeys[j]]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, uint64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
+ const uint64_t kValues1[] = { 300U, 301U, 302U };
+ const uint64_t kValues2[] = { 300U, 303U, 302U };
+ const uint64_t kValues3[] = { 300U, 301U, 302U, 303U };
+ GPBStringUInt64Dictionary *dict1 =
+ [[GPBStringUInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBStringUInt64Dictionary *dict1prime =
+ [[GPBStringUInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBStringUInt64Dictionary *dict2 =
+ [[GPBStringUInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBStringUInt64Dictionary *dict3 =
+ [[GPBStringUInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBStringUInt64Dictionary *dict4 =
+ [[GPBStringUInt64Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBStringUInt64Dictionary *dict =
+ [[GPBStringUInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringUInt64Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBStringUInt64Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBStringUInt64Dictionary *dict =
+ [[GPBStringUInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringUInt64Dictionary *dict2 =
+ [GPBStringUInt64Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBStringUInt64Dictionary *dict = [GPBStringUInt64Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:300U forKey:@"foo"];
+ XCTAssertEqual(dict.count, 1U);
+
+ const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
+ const uint64_t kValues[] = { 301U, 302U, 303U };
+ GPBStringUInt64Dictionary *dict2 =
+ [[GPBStringUInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 303U);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBStringUInt64Dictionary *dict =
+ [[GPBStringUInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict removeValueForKey:@"mumble"];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBStringUInt64Dictionary *dict =
+ [[GPBStringUInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict setValue:303U forKey:@"foo"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict setValue:301U forKey:@"mumble"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ const NSString *kKeys2[] = { @"bar", @"baz" };
+ const uint64_t kValues2[] = { 302U, 300U };
+ GPBStringUInt64Dictionary *dict2 =
+ [[GPBStringUInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - String -> Int64
+
+@interface GPBStringInt64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBStringInt64DictionaryTests
+
+- (void)testEmpty {
+ GPBStringInt64Dictionary *dict = [[GPBStringInt64Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBStringInt64Dictionary *dict = [GPBStringInt64Dictionary dictionaryWithValue:400 forKey:@"foo"];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int64_t aValue, BOOL *stop) {
+ XCTAssertEqualObjects(aKey, @"foo");
+ XCTAssertEqual(aValue, 400);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
+ const int64_t kValues[] = { 400, 401, 402 };
+ GPBStringInt64Dictionary *dict =
+ [[GPBStringInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ __block NSUInteger idx = 0;
+ NSString **seenKeys = malloc(3 * sizeof(NSString*));
+ int64_t *seenValues = malloc(3 * sizeof(int64_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int64_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if ([kKeys[i] isEqual:seenKeys[j]]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
+ const int64_t kValues1[] = { 400, 401, 402 };
+ const int64_t kValues2[] = { 400, 403, 402 };
+ const int64_t kValues3[] = { 400, 401, 402, 403 };
+ GPBStringInt64Dictionary *dict1 =
+ [[GPBStringInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBStringInt64Dictionary *dict1prime =
+ [[GPBStringInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBStringInt64Dictionary *dict2 =
+ [[GPBStringInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBStringInt64Dictionary *dict3 =
+ [[GPBStringInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBStringInt64Dictionary *dict4 =
+ [[GPBStringInt64Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBStringInt64Dictionary *dict =
+ [[GPBStringInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringInt64Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBStringInt64Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBStringInt64Dictionary *dict =
+ [[GPBStringInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringInt64Dictionary *dict2 =
+ [GPBStringInt64Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBStringInt64Dictionary *dict = [GPBStringInt64Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:400 forKey:@"foo"];
+ XCTAssertEqual(dict.count, 1U);
+
+ const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
+ const int64_t kValues[] = { 401, 402, 403 };
+ GPBStringInt64Dictionary *dict2 =
+ [[GPBStringInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 403);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBStringInt64Dictionary *dict =
+ [[GPBStringInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 403);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict removeValueForKey:@"mumble"];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBStringInt64Dictionary *dict =
+ [[GPBStringInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict setValue:403 forKey:@"foo"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict setValue:401 forKey:@"mumble"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 401);
+
+ const NSString *kKeys2[] = { @"bar", @"baz" };
+ const int64_t kValues2[] = { 402, 400 };
+ GPBStringInt64Dictionary *dict2 =
+ [[GPBStringInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 401);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - String -> Bool
+
+@interface GPBStringBoolDictionaryTests : XCTestCase
+@end
+
+@implementation GPBStringBoolDictionaryTests
+
+- (void)testEmpty {
+ GPBStringBoolDictionary *dict = [[GPBStringBoolDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, BOOL aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBStringBoolDictionary *dict = [GPBStringBoolDictionary dictionaryWithValue:YES forKey:@"foo"];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, BOOL aValue, BOOL *stop) {
+ XCTAssertEqualObjects(aKey, @"foo");
+ XCTAssertEqual(aValue, YES);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
+ const BOOL kValues[] = { YES, YES, NO };
+ GPBStringBoolDictionary *dict =
+ [[GPBStringBoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ __block NSUInteger idx = 0;
+ NSString **seenKeys = malloc(3 * sizeof(NSString*));
+ BOOL *seenValues = malloc(3 * sizeof(BOOL));
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, BOOL aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if ([kKeys[i] isEqual:seenKeys[j]]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, BOOL aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
+ const BOOL kValues1[] = { YES, YES, NO };
+ const BOOL kValues2[] = { YES, NO, NO };
+ const BOOL kValues3[] = { YES, YES, NO, NO };
+ GPBStringBoolDictionary *dict1 =
+ [[GPBStringBoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBStringBoolDictionary *dict1prime =
+ [[GPBStringBoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBStringBoolDictionary *dict2 =
+ [[GPBStringBoolDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBStringBoolDictionary *dict3 =
+ [[GPBStringBoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBStringBoolDictionary *dict4 =
+ [[GPBStringBoolDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBStringBoolDictionary *dict =
+ [[GPBStringBoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringBoolDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBStringBoolDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBStringBoolDictionary *dict =
+ [[GPBStringBoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringBoolDictionary *dict2 =
+ [GPBStringBoolDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBStringBoolDictionary *dict = [GPBStringBoolDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:YES forKey:@"foo"];
+ XCTAssertEqual(dict.count, 1U);
+
+ const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
+ const BOOL kValues[] = { YES, NO, NO };
+ GPBStringBoolDictionary *dict2 =
+ [[GPBStringBoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, NO);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBStringBoolDictionary *dict =
+ [[GPBStringBoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, NO);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict removeValueForKey:@"mumble"];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBStringBoolDictionary *dict =
+ [[GPBStringBoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict setValue:NO forKey:@"foo"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict setValue:YES forKey:@"mumble"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, YES);
+
+ const NSString *kKeys2[] = { @"bar", @"baz" };
+ const BOOL kValues2[] = { NO, YES };
+ GPBStringBoolDictionary *dict2 =
+ [[GPBStringBoolDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, YES);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - String -> Float
+
+@interface GPBStringFloatDictionaryTests : XCTestCase
+@end
+
+@implementation GPBStringFloatDictionaryTests
+
+- (void)testEmpty {
+ GPBStringFloatDictionary *dict = [[GPBStringFloatDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, float aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBStringFloatDictionary *dict = [GPBStringFloatDictionary dictionaryWithValue:500.f forKey:@"foo"];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ float value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, float aValue, BOOL *stop) {
+ XCTAssertEqualObjects(aKey, @"foo");
+ XCTAssertEqual(aValue, 500.f);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
+ const float kValues[] = { 500.f, 501.f, 502.f };
+ GPBStringFloatDictionary *dict =
+ [[GPBStringFloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ float value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ __block NSUInteger idx = 0;
+ NSString **seenKeys = malloc(3 * sizeof(NSString*));
+ float *seenValues = malloc(3 * sizeof(float));
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, float aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if ([kKeys[i] isEqual:seenKeys[j]]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, float aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
+ const float kValues1[] = { 500.f, 501.f, 502.f };
+ const float kValues2[] = { 500.f, 503.f, 502.f };
+ const float kValues3[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBStringFloatDictionary *dict1 =
+ [[GPBStringFloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBStringFloatDictionary *dict1prime =
+ [[GPBStringFloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBStringFloatDictionary *dict2 =
+ [[GPBStringFloatDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBStringFloatDictionary *dict3 =
+ [[GPBStringFloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBStringFloatDictionary *dict4 =
+ [[GPBStringFloatDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBStringFloatDictionary *dict =
+ [[GPBStringFloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringFloatDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBStringFloatDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBStringFloatDictionary *dict =
+ [[GPBStringFloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringFloatDictionary *dict2 =
+ [GPBStringFloatDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBStringFloatDictionary *dict = [GPBStringFloatDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:500.f forKey:@"foo"];
+ XCTAssertEqual(dict.count, 1U);
+
+ const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
+ const float kValues[] = { 501.f, 502.f, 503.f };
+ GPBStringFloatDictionary *dict2 =
+ [[GPBStringFloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ float value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 503.f);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBStringFloatDictionary *dict =
+ [[GPBStringFloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ float value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict removeValueForKey:@"mumble"];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBStringFloatDictionary *dict =
+ [[GPBStringFloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ float value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict setValue:503.f forKey:@"foo"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict setValue:501.f forKey:@"mumble"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ const NSString *kKeys2[] = { @"bar", @"baz" };
+ const float kValues2[] = { 502.f, 500.f };
+ GPBStringFloatDictionary *dict2 =
+ [[GPBStringFloatDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - String -> Double
+
+@interface GPBStringDoubleDictionaryTests : XCTestCase
+@end
+
+@implementation GPBStringDoubleDictionaryTests
+
+- (void)testEmpty {
+ GPBStringDoubleDictionary *dict = [[GPBStringDoubleDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, double aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBStringDoubleDictionary *dict = [GPBStringDoubleDictionary dictionaryWithValue:600. forKey:@"foo"];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ double value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, double aValue, BOOL *stop) {
+ XCTAssertEqualObjects(aKey, @"foo");
+ XCTAssertEqual(aValue, 600.);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
+ const double kValues[] = { 600., 601., 602. };
+ GPBStringDoubleDictionary *dict =
+ [[GPBStringDoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ double value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ __block NSUInteger idx = 0;
+ NSString **seenKeys = malloc(3 * sizeof(NSString*));
+ double *seenValues = malloc(3 * sizeof(double));
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, double aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if ([kKeys[i] isEqual:seenKeys[j]]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, double aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
+ const double kValues1[] = { 600., 601., 602. };
+ const double kValues2[] = { 600., 603., 602. };
+ const double kValues3[] = { 600., 601., 602., 603. };
+ GPBStringDoubleDictionary *dict1 =
+ [[GPBStringDoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBStringDoubleDictionary *dict1prime =
+ [[GPBStringDoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBStringDoubleDictionary *dict2 =
+ [[GPBStringDoubleDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBStringDoubleDictionary *dict3 =
+ [[GPBStringDoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBStringDoubleDictionary *dict4 =
+ [[GPBStringDoubleDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBStringDoubleDictionary *dict =
+ [[GPBStringDoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringDoubleDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBStringDoubleDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBStringDoubleDictionary *dict =
+ [[GPBStringDoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringDoubleDictionary *dict2 =
+ [GPBStringDoubleDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBStringDoubleDictionary *dict = [GPBStringDoubleDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:600. forKey:@"foo"];
+ XCTAssertEqual(dict.count, 1U);
+
+ const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
+ const double kValues[] = { 601., 602., 603. };
+ GPBStringDoubleDictionary *dict2 =
+ [[GPBStringDoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ double value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 603.);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBStringDoubleDictionary *dict =
+ [[GPBStringDoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ double value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict removeValueForKey:@"mumble"];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBStringDoubleDictionary *dict =
+ [[GPBStringDoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ double value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict setValue:603. forKey:@"foo"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict setValue:601. forKey:@"mumble"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ const NSString *kKeys2[] = { @"bar", @"baz" };
+ const double kValues2[] = { 602., 600. };
+ GPBStringDoubleDictionary *dict2 =
+ [[GPBStringDoubleDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - String -> Enum
+
+@interface GPBStringEnumDictionaryTests : XCTestCase
+@end
+
+@implementation GPBStringEnumDictionaryTests
+
+- (void)testEmpty {
+ GPBStringEnumDictionary *dict = [[GPBStringEnumDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBStringEnumDictionary *dict = [GPBStringEnumDictionary dictionaryWithValue:700 forKey:@"foo"];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertEqualObjects(aKey, @"foo");
+ XCTAssertEqual(aValue, 700);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
+ const int32_t kValues[] = { 700, 701, 702 };
+ GPBStringEnumDictionary *dict =
+ [[GPBStringEnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ __block NSUInteger idx = 0;
+ NSString **seenKeys = malloc(3 * sizeof(NSString*));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if ([kKeys[i] isEqual:seenKeys[j]]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
+ const int32_t kValues1[] = { 700, 701, 702 };
+ const int32_t kValues2[] = { 700, 703, 702 };
+ const int32_t kValues3[] = { 700, 701, 702, 703 };
+ GPBStringEnumDictionary *dict1 =
+ [[GPBStringEnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBStringEnumDictionary *dict1prime =
+ [[GPBStringEnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBStringEnumDictionary *dict2 =
+ [[GPBStringEnumDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBStringEnumDictionary *dict3 =
+ [[GPBStringEnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBStringEnumDictionary *dict4 =
+ [[GPBStringEnumDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBStringEnumDictionary *dict =
+ [[GPBStringEnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringEnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBStringEnumDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBStringEnumDictionary *dict =
+ [[GPBStringEnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringEnumDictionary *dict2 =
+ [GPBStringEnumDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBStringEnumDictionary *dict = [GPBStringEnumDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:700 forKey:@"foo"];
+ XCTAssertEqual(dict.count, 1U);
+
+ const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 701, 702, 703 };
+ GPBStringEnumDictionary *dict2 =
+ [[GPBStringEnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 703);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBStringEnumDictionary *dict =
+ [[GPBStringEnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 703);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict removeValueForKey:@"mumble"];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBStringEnumDictionary *dict =
+ [[GPBStringEnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict setValue:703 forKey:@"foo"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict setValue:701 forKey:@"mumble"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 701);
+
+ const NSString *kKeys2[] = { @"bar", @"baz" };
+ const int32_t kValues2[] = { 702, 700 };
+ GPBStringEnumDictionary *dict2 =
+ [[GPBStringEnumDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 701);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - String -> Enum (Unknown Enums)
+
+@interface GPBStringEnumDictionaryUnknownEnumTests : XCTestCase
+@end
+
+@implementation GPBStringEnumDictionaryUnknownEnumTests
+
+- (void)testRawBasics {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
+ const int32_t kValues[] = { 700, 801, 702 };
+ GPBStringEnumDictionary *dict =
+ [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue(dict.validationFunc == TestingEnum_IsValidValue); // Pointer comparison
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" rawValue:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:@"bar" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:@"baz" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" rawValue:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:@"mumble" rawValue:NULL]);
+
+ __block NSUInteger idx = 0;
+ NSString **seenKeys = malloc(3 * sizeof(NSString*));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if ([kKeys[i] isEqual:seenKeys[j]]) {
+ foundKey = YES;
+ if (i == 1) {
+ XCTAssertEqual(kGPBUnrecognizedEnumeratorValue, seenValues[j], @"i = %d, j = %d", i, j);
+ } else {
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ idx = 0;
+ [dict enumerateKeysAndRawValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if ([kKeys[i] isEqual:seenKeys[j]]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndRawValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEqualityWithUnknowns {
+ const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
+ const int32_t kValues1[] = { 700, 801, 702 }; // Unknown
+ const int32_t kValues2[] = { 700, 803, 702 }; // Unknown
+ const int32_t kValues3[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBStringEnumDictionary *dict1 =
+ [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBStringEnumDictionary *dict1prime =
+ [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBStringEnumDictionary *dict2 =
+ [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBStringEnumDictionary *dict3 =
+ [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBStringEnumDictionary *dict4 =
+ [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopyWithUnknowns {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknown
+ GPBStringEnumDictionary *dict =
+ [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringEnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ XCTAssertEqualObjects(dict, dict2);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBStringEnumDictionary *dict =
+ [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringEnumDictionary *dict2 =
+ [GPBStringEnumDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ [dict release];
+}
+
+- (void)testUnknownAdds {
+ GPBStringEnumDictionary *dict =
+ [GPBStringEnumDictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertThrowsSpecificNamed([dict setValue:801 forKey:@"bar"], // Unknown
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(dict.count, 0U);
+ [dict setRawValue:801 forKey:@"bar"]; // Unknown
+ XCTAssertEqual(dict.count, 1U);
+
+ const NSString *kKeys[] = { @"foo", @"baz", @"mumble" };
+ const int32_t kValues[] = { 700, 702, 803 }; // Unknown
+ GPBStringEnumDictionary *dict2 =
+ [[GPBStringEnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:@"bar" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:@"mumble" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ [dict2 release];
+}
+
+- (void)testUnknownRemove {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBStringEnumDictionary *dict =
+ [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"mumble" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"mumble" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict removeValueForKey:@"mumble"];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutationUnknowns {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBStringEnumDictionary *dict =
+ [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:@"bar" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"mumble" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ XCTAssertThrowsSpecificNamed([dict setValue:803 forKey:@"foo"], // Unknown
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:@"bar" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"mumble" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict setRawValue:803 forKey:@"foo"]; // Unknown
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:@"bar" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"mumble" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict setRawValue:700 forKey:@"mumble"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:@"bar" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 700);
+
+ const NSString *kKeys2[] = { @"bar", @"baz" };
+ const int32_t kValues2[] = { 702, 801 }; // Unknown
+ GPBStringEnumDictionary *dict2 =
+ [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"baz" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 700);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testCopyUnknowns {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 700, 801, 702, 803 };
+ GPBStringEnumDictionary *dict =
+ [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringEnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ XCTAssertTrue([dict2 isKindOfClass:[GPBStringEnumDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND-END TESTS_FOR_POD_VALUES(String, NSString, *, Objects, @"foo", @"bar", @"baz", @"mumble")
+
diff --git a/objectivec/Tests/GPBDictionaryTests+UInt32.m b/objectivec/Tests/GPBDictionaryTests+UInt32.m
new file mode 100644
index 00000000..a89ded3d
--- /dev/null
+++ b/objectivec/Tests/GPBDictionaryTests+UInt32.m
@@ -0,0 +1,3650 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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 "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+
+// Pull in the macros (using an external file because expanding all tests
+// in a single file makes a file that is failing to work with within Xcode.
+//%PDDM-IMPORT-DEFINES GPBDictionaryTests.pddm
+
+//%PDDM-EXPAND TEST_FOR_POD_KEY(UInt32, uint32_t, 1U, 2U, 3U, 4U)
+// This block of code is generated, do not edit it directly.
+
+#ifndef GPBARRAYSIZE
+#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))))
+#endif // GPBARRAYSIZE
+
+// To let the testing macros work, add some extra methods to simplify things.
+@interface GPBUInt32EnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(uint32_t)key;
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count;
+@end
+
+static BOOL TestingEnum_IsValidValue(int32_t value) {
+ switch (value) {
+ case 700:
+ case 701:
+ case 702:
+ case 703:
+ return YES;
+ default:
+ return NO;
+ }
+}
+
+@implementation GPBUInt32EnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(uint32_t)key {
+ // Cast is needed to compiler knows what class we are invoking initWithValues: on to get the
+ // type correct.
+ return [[(GPBUInt32EnumDictionary*)[self alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count {
+ return [self initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:values
+ forKeys:keys
+ count:count];
+}
+@end
+
+
+#pragma mark - UInt32 -> UInt32
+
+@interface GPBUInt32UInt32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt32UInt32DictionaryTests
+
+- (void)testEmpty {
+ GPBUInt32UInt32Dictionary *dict = [[GPBUInt32UInt32Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, uint32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt32UInt32Dictionary *dict = [GPBUInt32UInt32Dictionary dictionaryWithValue:100U forKey:1U];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, uint32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 1U);
+ XCTAssertEqual(aValue, 100U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint32_t kKeys[] = { 1U, 2U, 3U };
+ const uint32_t kValues[] = { 100U, 101U, 102U };
+ GPBUInt32UInt32Dictionary *dict =
+ [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+ uint32_t *seenValues = malloc(3 * sizeof(uint32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, uint32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, uint32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kKeys2[] = { 2U, 1U, 4U };
+ const uint32_t kValues1[] = { 100U, 101U, 102U };
+ const uint32_t kValues2[] = { 100U, 103U, 102U };
+ const uint32_t kValues3[] = { 100U, 101U, 102U, 103U };
+ GPBUInt32UInt32Dictionary *dict1 =
+ [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt32UInt32Dictionary *dict1prime =
+ [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt32UInt32Dictionary *dict2 =
+ [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt32UInt32Dictionary *dict3 =
+ [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt32UInt32Dictionary *dict4 =
+ [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBUInt32UInt32Dictionary *dict =
+ [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32UInt32Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32UInt32Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBUInt32UInt32Dictionary *dict =
+ [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32UInt32Dictionary *dict2 =
+ [GPBUInt32UInt32Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt32UInt32Dictionary *dict = [GPBUInt32UInt32Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:100U forKey:1U];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint32_t kKeys[] = { 2U, 3U, 4U };
+ const uint32_t kValues[] = { 101U, 102U, 103U };
+ GPBUInt32UInt32Dictionary *dict2 =
+ [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 103U);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBUInt32UInt32Dictionary *dict =
+ [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict removeValueForKey:4U];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertFalse([dict valueForKey:3U value:NULL]);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBUInt32UInt32Dictionary *dict =
+ [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict setValue:103U forKey:1U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict setValue:101U forKey:4U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ const uint32_t kKeys2[] = { 2U, 3U };
+ const uint32_t kValues2[] = { 102U, 100U };
+ GPBUInt32UInt32Dictionary *dict2 =
+ [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt32 -> Int32
+
+@interface GPBUInt32Int32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt32Int32DictionaryTests
+
+- (void)testEmpty {
+ GPBUInt32Int32Dictionary *dict = [[GPBUInt32Int32Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt32Int32Dictionary *dict = [GPBUInt32Int32Dictionary dictionaryWithValue:200 forKey:1U];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 1U);
+ XCTAssertEqual(aValue, 200);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint32_t kKeys[] = { 1U, 2U, 3U };
+ const int32_t kValues[] = { 200, 201, 202 };
+ GPBUInt32Int32Dictionary *dict =
+ [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kKeys2[] = { 2U, 1U, 4U };
+ const int32_t kValues1[] = { 200, 201, 202 };
+ const int32_t kValues2[] = { 200, 203, 202 };
+ const int32_t kValues3[] = { 200, 201, 202, 203 };
+ GPBUInt32Int32Dictionary *dict1 =
+ [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt32Int32Dictionary *dict1prime =
+ [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt32Int32Dictionary *dict2 =
+ [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt32Int32Dictionary *dict3 =
+ [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt32Int32Dictionary *dict4 =
+ [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBUInt32Int32Dictionary *dict =
+ [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32Int32Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32Int32Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBUInt32Int32Dictionary *dict =
+ [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32Int32Dictionary *dict2 =
+ [GPBUInt32Int32Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt32Int32Dictionary *dict = [GPBUInt32Int32Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:200 forKey:1U];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint32_t kKeys[] = { 2U, 3U, 4U };
+ const int32_t kValues[] = { 201, 202, 203 };
+ GPBUInt32Int32Dictionary *dict2 =
+ [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 203);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBUInt32Int32Dictionary *dict =
+ [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 203);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict removeValueForKey:4U];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertFalse([dict valueForKey:3U value:NULL]);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBUInt32Int32Dictionary *dict =
+ [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict setValue:203 forKey:1U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict setValue:201 forKey:4U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 201);
+
+ const uint32_t kKeys2[] = { 2U, 3U };
+ const int32_t kValues2[] = { 202, 200 };
+ GPBUInt32Int32Dictionary *dict2 =
+ [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 201);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt32 -> UInt64
+
+@interface GPBUInt32UInt64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt32UInt64DictionaryTests
+
+- (void)testEmpty {
+ GPBUInt32UInt64Dictionary *dict = [[GPBUInt32UInt64Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, uint64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt32UInt64Dictionary *dict = [GPBUInt32UInt64Dictionary dictionaryWithValue:300U forKey:1U];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, uint64_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 1U);
+ XCTAssertEqual(aValue, 300U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint32_t kKeys[] = { 1U, 2U, 3U };
+ const uint64_t kValues[] = { 300U, 301U, 302U };
+ GPBUInt32UInt64Dictionary *dict =
+ [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+ uint64_t *seenValues = malloc(3 * sizeof(uint64_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, uint64_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, uint64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kKeys2[] = { 2U, 1U, 4U };
+ const uint64_t kValues1[] = { 300U, 301U, 302U };
+ const uint64_t kValues2[] = { 300U, 303U, 302U };
+ const uint64_t kValues3[] = { 300U, 301U, 302U, 303U };
+ GPBUInt32UInt64Dictionary *dict1 =
+ [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt32UInt64Dictionary *dict1prime =
+ [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt32UInt64Dictionary *dict2 =
+ [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt32UInt64Dictionary *dict3 =
+ [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt32UInt64Dictionary *dict4 =
+ [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBUInt32UInt64Dictionary *dict =
+ [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32UInt64Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32UInt64Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBUInt32UInt64Dictionary *dict =
+ [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32UInt64Dictionary *dict2 =
+ [GPBUInt32UInt64Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt32UInt64Dictionary *dict = [GPBUInt32UInt64Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:300U forKey:1U];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint32_t kKeys[] = { 2U, 3U, 4U };
+ const uint64_t kValues[] = { 301U, 302U, 303U };
+ GPBUInt32UInt64Dictionary *dict2 =
+ [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 303U);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBUInt32UInt64Dictionary *dict =
+ [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict removeValueForKey:4U];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertFalse([dict valueForKey:3U value:NULL]);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBUInt32UInt64Dictionary *dict =
+ [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict setValue:303U forKey:1U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict setValue:301U forKey:4U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ const uint32_t kKeys2[] = { 2U, 3U };
+ const uint64_t kValues2[] = { 302U, 300U };
+ GPBUInt32UInt64Dictionary *dict2 =
+ [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt32 -> Int64
+
+@interface GPBUInt32Int64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt32Int64DictionaryTests
+
+- (void)testEmpty {
+ GPBUInt32Int64Dictionary *dict = [[GPBUInt32Int64Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt32Int64Dictionary *dict = [GPBUInt32Int64Dictionary dictionaryWithValue:400 forKey:1U];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int64_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 1U);
+ XCTAssertEqual(aValue, 400);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint32_t kKeys[] = { 1U, 2U, 3U };
+ const int64_t kValues[] = { 400, 401, 402 };
+ GPBUInt32Int64Dictionary *dict =
+ [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+ int64_t *seenValues = malloc(3 * sizeof(int64_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int64_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kKeys2[] = { 2U, 1U, 4U };
+ const int64_t kValues1[] = { 400, 401, 402 };
+ const int64_t kValues2[] = { 400, 403, 402 };
+ const int64_t kValues3[] = { 400, 401, 402, 403 };
+ GPBUInt32Int64Dictionary *dict1 =
+ [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt32Int64Dictionary *dict1prime =
+ [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt32Int64Dictionary *dict2 =
+ [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt32Int64Dictionary *dict3 =
+ [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt32Int64Dictionary *dict4 =
+ [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBUInt32Int64Dictionary *dict =
+ [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32Int64Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32Int64Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBUInt32Int64Dictionary *dict =
+ [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32Int64Dictionary *dict2 =
+ [GPBUInt32Int64Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt32Int64Dictionary *dict = [GPBUInt32Int64Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:400 forKey:1U];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint32_t kKeys[] = { 2U, 3U, 4U };
+ const int64_t kValues[] = { 401, 402, 403 };
+ GPBUInt32Int64Dictionary *dict2 =
+ [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 403);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBUInt32Int64Dictionary *dict =
+ [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 403);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict removeValueForKey:4U];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertFalse([dict valueForKey:3U value:NULL]);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBUInt32Int64Dictionary *dict =
+ [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict setValue:403 forKey:1U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict setValue:401 forKey:4U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 401);
+
+ const uint32_t kKeys2[] = { 2U, 3U };
+ const int64_t kValues2[] = { 402, 400 };
+ GPBUInt32Int64Dictionary *dict2 =
+ [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 401);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt32 -> Bool
+
+@interface GPBUInt32BoolDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt32BoolDictionaryTests
+
+- (void)testEmpty {
+ GPBUInt32BoolDictionary *dict = [[GPBUInt32BoolDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, BOOL aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt32BoolDictionary *dict = [GPBUInt32BoolDictionary dictionaryWithValue:YES forKey:1U];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, BOOL aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 1U);
+ XCTAssertEqual(aValue, YES);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint32_t kKeys[] = { 1U, 2U, 3U };
+ const BOOL kValues[] = { YES, YES, NO };
+ GPBUInt32BoolDictionary *dict =
+ [[GPBUInt32BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+ BOOL *seenValues = malloc(3 * sizeof(BOOL));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, BOOL aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, BOOL aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kKeys2[] = { 2U, 1U, 4U };
+ const BOOL kValues1[] = { YES, YES, NO };
+ const BOOL kValues2[] = { YES, NO, NO };
+ const BOOL kValues3[] = { YES, YES, NO, NO };
+ GPBUInt32BoolDictionary *dict1 =
+ [[GPBUInt32BoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt32BoolDictionary *dict1prime =
+ [[GPBUInt32BoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt32BoolDictionary *dict2 =
+ [[GPBUInt32BoolDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt32BoolDictionary *dict3 =
+ [[GPBUInt32BoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt32BoolDictionary *dict4 =
+ [[GPBUInt32BoolDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBUInt32BoolDictionary *dict =
+ [[GPBUInt32BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32BoolDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32BoolDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBUInt32BoolDictionary *dict =
+ [[GPBUInt32BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32BoolDictionary *dict2 =
+ [GPBUInt32BoolDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt32BoolDictionary *dict = [GPBUInt32BoolDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:YES forKey:1U];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint32_t kKeys[] = { 2U, 3U, 4U };
+ const BOOL kValues[] = { YES, NO, NO };
+ GPBUInt32BoolDictionary *dict2 =
+ [[GPBUInt32BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, NO);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBUInt32BoolDictionary *dict =
+ [[GPBUInt32BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, NO);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict removeValueForKey:4U];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertFalse([dict valueForKey:3U value:NULL]);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBUInt32BoolDictionary *dict =
+ [[GPBUInt32BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict setValue:NO forKey:1U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict setValue:YES forKey:4U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, YES);
+
+ const uint32_t kKeys2[] = { 2U, 3U };
+ const BOOL kValues2[] = { NO, YES };
+ GPBUInt32BoolDictionary *dict2 =
+ [[GPBUInt32BoolDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, YES);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt32 -> Float
+
+@interface GPBUInt32FloatDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt32FloatDictionaryTests
+
+- (void)testEmpty {
+ GPBUInt32FloatDictionary *dict = [[GPBUInt32FloatDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, float aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt32FloatDictionary *dict = [GPBUInt32FloatDictionary dictionaryWithValue:500.f forKey:1U];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ float value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, float aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 1U);
+ XCTAssertEqual(aValue, 500.f);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint32_t kKeys[] = { 1U, 2U, 3U };
+ const float kValues[] = { 500.f, 501.f, 502.f };
+ GPBUInt32FloatDictionary *dict =
+ [[GPBUInt32FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ float value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+ float *seenValues = malloc(3 * sizeof(float));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, float aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, float aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kKeys2[] = { 2U, 1U, 4U };
+ const float kValues1[] = { 500.f, 501.f, 502.f };
+ const float kValues2[] = { 500.f, 503.f, 502.f };
+ const float kValues3[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBUInt32FloatDictionary *dict1 =
+ [[GPBUInt32FloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt32FloatDictionary *dict1prime =
+ [[GPBUInt32FloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt32FloatDictionary *dict2 =
+ [[GPBUInt32FloatDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt32FloatDictionary *dict3 =
+ [[GPBUInt32FloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt32FloatDictionary *dict4 =
+ [[GPBUInt32FloatDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBUInt32FloatDictionary *dict =
+ [[GPBUInt32FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32FloatDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32FloatDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBUInt32FloatDictionary *dict =
+ [[GPBUInt32FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32FloatDictionary *dict2 =
+ [GPBUInt32FloatDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt32FloatDictionary *dict = [GPBUInt32FloatDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:500.f forKey:1U];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint32_t kKeys[] = { 2U, 3U, 4U };
+ const float kValues[] = { 501.f, 502.f, 503.f };
+ GPBUInt32FloatDictionary *dict2 =
+ [[GPBUInt32FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ float value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 503.f);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBUInt32FloatDictionary *dict =
+ [[GPBUInt32FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ float value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict removeValueForKey:4U];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertFalse([dict valueForKey:3U value:NULL]);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBUInt32FloatDictionary *dict =
+ [[GPBUInt32FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ float value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict setValue:503.f forKey:1U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict setValue:501.f forKey:4U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ const uint32_t kKeys2[] = { 2U, 3U };
+ const float kValues2[] = { 502.f, 500.f };
+ GPBUInt32FloatDictionary *dict2 =
+ [[GPBUInt32FloatDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt32 -> Double
+
+@interface GPBUInt32DoubleDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt32DoubleDictionaryTests
+
+- (void)testEmpty {
+ GPBUInt32DoubleDictionary *dict = [[GPBUInt32DoubleDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, double aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt32DoubleDictionary *dict = [GPBUInt32DoubleDictionary dictionaryWithValue:600. forKey:1U];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ double value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, double aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 1U);
+ XCTAssertEqual(aValue, 600.);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint32_t kKeys[] = { 1U, 2U, 3U };
+ const double kValues[] = { 600., 601., 602. };
+ GPBUInt32DoubleDictionary *dict =
+ [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ double value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+ double *seenValues = malloc(3 * sizeof(double));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, double aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, double aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kKeys2[] = { 2U, 1U, 4U };
+ const double kValues1[] = { 600., 601., 602. };
+ const double kValues2[] = { 600., 603., 602. };
+ const double kValues3[] = { 600., 601., 602., 603. };
+ GPBUInt32DoubleDictionary *dict1 =
+ [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt32DoubleDictionary *dict1prime =
+ [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt32DoubleDictionary *dict2 =
+ [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt32DoubleDictionary *dict3 =
+ [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt32DoubleDictionary *dict4 =
+ [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBUInt32DoubleDictionary *dict =
+ [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32DoubleDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32DoubleDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBUInt32DoubleDictionary *dict =
+ [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32DoubleDictionary *dict2 =
+ [GPBUInt32DoubleDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt32DoubleDictionary *dict = [GPBUInt32DoubleDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:600. forKey:1U];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint32_t kKeys[] = { 2U, 3U, 4U };
+ const double kValues[] = { 601., 602., 603. };
+ GPBUInt32DoubleDictionary *dict2 =
+ [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ double value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 603.);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBUInt32DoubleDictionary *dict =
+ [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ double value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict removeValueForKey:4U];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertFalse([dict valueForKey:3U value:NULL]);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBUInt32DoubleDictionary *dict =
+ [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ double value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict setValue:603. forKey:1U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict setValue:601. forKey:4U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ const uint32_t kKeys2[] = { 2U, 3U };
+ const double kValues2[] = { 602., 600. };
+ GPBUInt32DoubleDictionary *dict2 =
+ [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt32 -> Enum
+
+@interface GPBUInt32EnumDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt32EnumDictionaryTests
+
+- (void)testEmpty {
+ GPBUInt32EnumDictionary *dict = [[GPBUInt32EnumDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt32EnumDictionary *dict = [GPBUInt32EnumDictionary dictionaryWithValue:700 forKey:1U];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 1U);
+ XCTAssertEqual(aValue, 700);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint32_t kKeys[] = { 1U, 2U, 3U };
+ const int32_t kValues[] = { 700, 701, 702 };
+ GPBUInt32EnumDictionary *dict =
+ [[GPBUInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kKeys2[] = { 2U, 1U, 4U };
+ const int32_t kValues1[] = { 700, 701, 702 };
+ const int32_t kValues2[] = { 700, 703, 702 };
+ const int32_t kValues3[] = { 700, 701, 702, 703 };
+ GPBUInt32EnumDictionary *dict1 =
+ [[GPBUInt32EnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt32EnumDictionary *dict1prime =
+ [[GPBUInt32EnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt32EnumDictionary *dict2 =
+ [[GPBUInt32EnumDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt32EnumDictionary *dict3 =
+ [[GPBUInt32EnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt32EnumDictionary *dict4 =
+ [[GPBUInt32EnumDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBUInt32EnumDictionary *dict =
+ [[GPBUInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32EnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32EnumDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBUInt32EnumDictionary *dict =
+ [[GPBUInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32EnumDictionary *dict2 =
+ [GPBUInt32EnumDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt32EnumDictionary *dict = [GPBUInt32EnumDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:700 forKey:1U];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint32_t kKeys[] = { 2U, 3U, 4U };
+ const int32_t kValues[] = { 701, 702, 703 };
+ GPBUInt32EnumDictionary *dict2 =
+ [[GPBUInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 703);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBUInt32EnumDictionary *dict =
+ [[GPBUInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 703);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict removeValueForKey:4U];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertFalse([dict valueForKey:3U value:NULL]);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBUInt32EnumDictionary *dict =
+ [[GPBUInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict setValue:703 forKey:1U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict setValue:701 forKey:4U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 701);
+
+ const uint32_t kKeys2[] = { 2U, 3U };
+ const int32_t kValues2[] = { 702, 700 };
+ GPBUInt32EnumDictionary *dict2 =
+ [[GPBUInt32EnumDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 701);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt32 -> Enum (Unknown Enums)
+
+@interface GPBUInt32EnumDictionaryUnknownEnumTests : XCTestCase
+@end
+
+@implementation GPBUInt32EnumDictionaryUnknownEnumTests
+
+- (void)testRawBasics {
+ const uint32_t kKeys[] = { 1U, 2U, 3U };
+ const int32_t kValues[] = { 700, 801, 702 };
+ GPBUInt32EnumDictionary *dict =
+ [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue(dict.validationFunc == TestingEnum_IsValidValue); // Pointer comparison
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:1U rawValue:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:2U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:2U rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:3U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:3U rawValue:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:4U rawValue:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ if (i == 1) {
+ XCTAssertEqual(kGPBUnrecognizedEnumeratorValue, seenValues[j], @"i = %d, j = %d", i, j);
+ } else {
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ idx = 0;
+ [dict enumerateKeysAndRawValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndRawValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEqualityWithUnknowns {
+ const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kKeys2[] = { 2U, 1U, 4U };
+ const int32_t kValues1[] = { 700, 801, 702 }; // Unknown
+ const int32_t kValues2[] = { 700, 803, 702 }; // Unknown
+ const int32_t kValues3[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBUInt32EnumDictionary *dict1 =
+ [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt32EnumDictionary *dict1prime =
+ [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt32EnumDictionary *dict2 =
+ [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt32EnumDictionary *dict3 =
+ [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt32EnumDictionary *dict4 =
+ [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopyWithUnknowns {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknown
+ GPBUInt32EnumDictionary *dict =
+ [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32EnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ XCTAssertEqualObjects(dict, dict2);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBUInt32EnumDictionary *dict =
+ [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32EnumDictionary *dict2 =
+ [GPBUInt32EnumDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ [dict release];
+}
+
+- (void)testUnknownAdds {
+ GPBUInt32EnumDictionary *dict =
+ [GPBUInt32EnumDictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertThrowsSpecificNamed([dict setValue:801 forKey:2U], // Unknown
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(dict.count, 0U);
+ [dict setRawValue:801 forKey:2U]; // Unknown
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint32_t kKeys[] = { 1U, 3U, 4U };
+ const int32_t kValues[] = { 700, 702, 803 }; // Unknown
+ GPBUInt32EnumDictionary *dict2 =
+ [[GPBUInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:2U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:2U rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:4U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:4U rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ [dict2 release];
+}
+
+- (void)testUnknownRemove {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBUInt32EnumDictionary *dict =
+ [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:4U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:4U rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:4U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:4U rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict removeValueForKey:4U];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertFalse([dict valueForKey:3U value:NULL]);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutationUnknowns {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBUInt32EnumDictionary *dict =
+ [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:2U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:2U rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:4U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:4U rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ XCTAssertThrowsSpecificNamed([dict setValue:803 forKey:1U], // Unknown
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:2U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:2U rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:4U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:4U rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict setRawValue:803 forKey:1U]; // Unknown
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:1U rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:2U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:2U rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:4U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:4U rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict setRawValue:700 forKey:4U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:1U rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:2U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:2U rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 700);
+
+ const uint32_t kKeys2[] = { 2U, 3U };
+ const int32_t kValues2[] = { 702, 801 }; // Unknown
+ GPBUInt32EnumDictionary *dict2 =
+ [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:1U rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:3U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:3U rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 700);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testCopyUnknowns {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int32_t kValues[] = { 700, 801, 702, 803 };
+ GPBUInt32EnumDictionary *dict =
+ [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32EnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32EnumDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt32 -> Object
+
+@interface GPBUInt32ObjectDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt32ObjectDictionaryTests
+
+- (void)testEmpty {
+ GPBUInt32ObjectDictionary *dict = [[GPBUInt32ObjectDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertNil([dict valueForKey:1U]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, id aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt32ObjectDictionary *dict = [GPBUInt32ObjectDictionary dictionaryWithValue:@"abc" forKey:1U];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertEqualObjects([dict valueForKey:1U], @"abc");
+ XCTAssertNil([dict valueForKey:2U]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, id aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 1U);
+ XCTAssertEqualObjects(aValue, @"abc");
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint32_t kKeys[] = { 1U, 2U, 3U };
+ const id kValues[] = { @"abc", @"def", @"ghi" };
+ GPBUInt32ObjectDictionary *dict =
+ [[GPBUInt32ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertEqualObjects([dict valueForKey:1U], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:2U], @"def");
+ XCTAssertEqualObjects([dict valueForKey:3U], @"ghi");
+ XCTAssertNil([dict valueForKey:4U]);
+
+ __block NSUInteger idx = 0;
+ uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+ id *seenValues = malloc(3 * sizeof(id));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, id aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqualObjects(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, id aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kKeys2[] = { 2U, 1U, 4U };
+ const id kValues1[] = { @"abc", @"def", @"ghi" };
+ const id kValues2[] = { @"abc", @"jkl", @"ghi" };
+ const id kValues3[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBUInt32ObjectDictionary *dict1 =
+ [[GPBUInt32ObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt32ObjectDictionary *dict1prime =
+ [[GPBUInt32ObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt32ObjectDictionary *dict2 =
+ [[GPBUInt32ObjectDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt32ObjectDictionary *dict3 =
+ [[GPBUInt32ObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt32ObjectDictionary *dict4 =
+ [[GPBUInt32ObjectDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBUInt32ObjectDictionary *dict =
+ [[GPBUInt32ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32ObjectDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32ObjectDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBUInt32ObjectDictionary *dict =
+ [[GPBUInt32ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32ObjectDictionary *dict2 =
+ [GPBUInt32ObjectDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt32ObjectDictionary *dict = [GPBUInt32ObjectDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:@"abc" forKey:1U];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint32_t kKeys[] = { 2U, 3U, 4U };
+ const id kValues[] = { @"def", @"ghi", @"jkl" };
+ GPBUInt32ObjectDictionary *dict2 =
+ [[GPBUInt32ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ XCTAssertEqualObjects([dict valueForKey:1U], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:2U], @"def");
+ XCTAssertEqualObjects([dict valueForKey:3U], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:4U], @"jkl");
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBUInt32ObjectDictionary *dict =
+ [[GPBUInt32ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertEqualObjects([dict valueForKey:1U], @"abc");
+ XCTAssertNil([dict valueForKey:2U]);
+ XCTAssertEqualObjects([dict valueForKey:3U], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:4U], @"jkl");
+
+ // Remove again does nothing.
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertEqualObjects([dict valueForKey:1U], @"abc");
+ XCTAssertNil([dict valueForKey:2U]);
+ XCTAssertEqualObjects([dict valueForKey:3U], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:4U], @"jkl");
+
+ [dict removeValueForKey:4U];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertEqualObjects([dict valueForKey:1U], @"abc");
+ XCTAssertNil([dict valueForKey:2U]);
+ XCTAssertEqualObjects([dict valueForKey:3U], @"ghi");
+ XCTAssertNil([dict valueForKey:4U]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertNil([dict valueForKey:1U]);
+ XCTAssertNil([dict valueForKey:2U]);
+ XCTAssertNil([dict valueForKey:3U]);
+ XCTAssertNil([dict valueForKey:4U]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBUInt32ObjectDictionary *dict =
+ [[GPBUInt32ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:1U], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:2U], @"def");
+ XCTAssertEqualObjects([dict valueForKey:3U], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:4U], @"jkl");
+
+ [dict setValue:@"jkl" forKey:1U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:1U], @"jkl");
+ XCTAssertEqualObjects([dict valueForKey:2U], @"def");
+ XCTAssertEqualObjects([dict valueForKey:3U], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:4U], @"jkl");
+
+ [dict setValue:@"def" forKey:4U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:1U], @"jkl");
+ XCTAssertEqualObjects([dict valueForKey:2U], @"def");
+ XCTAssertEqualObjects([dict valueForKey:3U], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:4U], @"def");
+
+ const uint32_t kKeys2[] = { 2U, 3U };
+ const id kValues2[] = { @"ghi", @"abc" };
+ GPBUInt32ObjectDictionary *dict2 =
+ [[GPBUInt32ObjectDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:1U], @"jkl");
+ XCTAssertEqualObjects([dict valueForKey:2U], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:3U], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:4U], @"def");
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND-END TEST_FOR_POD_KEY(UInt32, uint32_t, 1U, 2U, 3U, 4U)
+
diff --git a/objectivec/Tests/GPBDictionaryTests+UInt64.m b/objectivec/Tests/GPBDictionaryTests+UInt64.m
new file mode 100644
index 00000000..355639c6
--- /dev/null
+++ b/objectivec/Tests/GPBDictionaryTests+UInt64.m
@@ -0,0 +1,3649 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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 "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+
+// Pull in the macros (using an external file because expanding all tests
+// in a single file makes a file that is failing to work with within Xcode.
+//%PDDM-IMPORT-DEFINES GPBDictionaryTests.pddm
+
+//%PDDM-EXPAND TEST_FOR_POD_KEY(UInt64, uint64_t, 31ULL, 32ULL, 33ULL, 34ULL)
+// This block of code is generated, do not edit it directly.
+
+#ifndef GPBARRAYSIZE
+#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))))
+#endif // GPBARRAYSIZE
+
+// To let the testing macros work, add some extra methods to simplify things.
+@interface GPBUInt64EnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(uint64_t)key;
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count;
+@end
+
+static BOOL TestingEnum_IsValidValue(int32_t value) {
+ switch (value) {
+ case 700:
+ case 701:
+ case 702:
+ case 703:
+ return YES;
+ default:
+ return NO;
+ }
+}
+
+@implementation GPBUInt64EnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(uint64_t)key {
+ // Cast is needed to compiler knows what class we are invoking initWithValues: on to get the
+ // type correct.
+ return [[(GPBUInt64EnumDictionary*)[self alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count {
+ return [self initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:values
+ forKeys:keys
+ count:count];
+}
+@end
+
+
+#pragma mark - UInt64 -> UInt32
+
+@interface GPBUInt64UInt32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt64UInt32DictionaryTests
+
+- (void)testEmpty {
+ GPBUInt64UInt32Dictionary *dict = [[GPBUInt64UInt32Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, uint32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt64UInt32Dictionary *dict = [GPBUInt64UInt32Dictionary dictionaryWithValue:100U forKey:31ULL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, uint32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 31ULL);
+ XCTAssertEqual(aValue, 100U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+ const uint32_t kValues[] = { 100U, 101U, 102U };
+ GPBUInt64UInt32Dictionary *dict =
+ [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+ uint32_t *seenValues = malloc(3 * sizeof(uint32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, uint32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, uint32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+ const uint32_t kValues1[] = { 100U, 101U, 102U };
+ const uint32_t kValues2[] = { 100U, 103U, 102U };
+ const uint32_t kValues3[] = { 100U, 101U, 102U, 103U };
+ GPBUInt64UInt32Dictionary *dict1 =
+ [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt64UInt32Dictionary *dict1prime =
+ [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt64UInt32Dictionary *dict2 =
+ [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt64UInt32Dictionary *dict3 =
+ [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt64UInt32Dictionary *dict4 =
+ [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBUInt64UInt32Dictionary *dict =
+ [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64UInt32Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64UInt32Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBUInt64UInt32Dictionary *dict =
+ [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64UInt32Dictionary *dict2 =
+ [GPBUInt64UInt32Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt64UInt32Dictionary *dict = [GPBUInt64UInt32Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:100U forKey:31ULL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
+ const uint32_t kValues[] = { 101U, 102U, 103U };
+ GPBUInt64UInt32Dictionary *dict2 =
+ [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 103U);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBUInt64UInt32Dictionary *dict =
+ [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict removeValueForKey:34ULL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:33ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBUInt64UInt32Dictionary *dict =
+ [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict setValue:103U forKey:31ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict setValue:101U forKey:34ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ const uint64_t kKeys2[] = { 32ULL, 33ULL };
+ const uint32_t kValues2[] = { 102U, 100U };
+ GPBUInt64UInt32Dictionary *dict2 =
+ [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt64 -> Int32
+
+@interface GPBUInt64Int32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt64Int32DictionaryTests
+
+- (void)testEmpty {
+ GPBUInt64Int32Dictionary *dict = [[GPBUInt64Int32Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt64Int32Dictionary *dict = [GPBUInt64Int32Dictionary dictionaryWithValue:200 forKey:31ULL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 31ULL);
+ XCTAssertEqual(aValue, 200);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+ const int32_t kValues[] = { 200, 201, 202 };
+ GPBUInt64Int32Dictionary *dict =
+ [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+ const int32_t kValues1[] = { 200, 201, 202 };
+ const int32_t kValues2[] = { 200, 203, 202 };
+ const int32_t kValues3[] = { 200, 201, 202, 203 };
+ GPBUInt64Int32Dictionary *dict1 =
+ [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt64Int32Dictionary *dict1prime =
+ [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt64Int32Dictionary *dict2 =
+ [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt64Int32Dictionary *dict3 =
+ [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt64Int32Dictionary *dict4 =
+ [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBUInt64Int32Dictionary *dict =
+ [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64Int32Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64Int32Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBUInt64Int32Dictionary *dict =
+ [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64Int32Dictionary *dict2 =
+ [GPBUInt64Int32Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt64Int32Dictionary *dict = [GPBUInt64Int32Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:200 forKey:31ULL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 201, 202, 203 };
+ GPBUInt64Int32Dictionary *dict2 =
+ [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 203);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBUInt64Int32Dictionary *dict =
+ [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 203);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict removeValueForKey:34ULL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:33ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBUInt64Int32Dictionary *dict =
+ [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict setValue:203 forKey:31ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict setValue:201 forKey:34ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 201);
+
+ const uint64_t kKeys2[] = { 32ULL, 33ULL };
+ const int32_t kValues2[] = { 202, 200 };
+ GPBUInt64Int32Dictionary *dict2 =
+ [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 201);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt64 -> UInt64
+
+@interface GPBUInt64UInt64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt64UInt64DictionaryTests
+
+- (void)testEmpty {
+ GPBUInt64UInt64Dictionary *dict = [[GPBUInt64UInt64Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, uint64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt64UInt64Dictionary *dict = [GPBUInt64UInt64Dictionary dictionaryWithValue:300U forKey:31ULL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, uint64_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 31ULL);
+ XCTAssertEqual(aValue, 300U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+ const uint64_t kValues[] = { 300U, 301U, 302U };
+ GPBUInt64UInt64Dictionary *dict =
+ [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+ uint64_t *seenValues = malloc(3 * sizeof(uint64_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, uint64_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, uint64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+ const uint64_t kValues1[] = { 300U, 301U, 302U };
+ const uint64_t kValues2[] = { 300U, 303U, 302U };
+ const uint64_t kValues3[] = { 300U, 301U, 302U, 303U };
+ GPBUInt64UInt64Dictionary *dict1 =
+ [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt64UInt64Dictionary *dict1prime =
+ [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt64UInt64Dictionary *dict2 =
+ [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt64UInt64Dictionary *dict3 =
+ [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt64UInt64Dictionary *dict4 =
+ [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBUInt64UInt64Dictionary *dict =
+ [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64UInt64Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64UInt64Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBUInt64UInt64Dictionary *dict =
+ [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64UInt64Dictionary *dict2 =
+ [GPBUInt64UInt64Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt64UInt64Dictionary *dict = [GPBUInt64UInt64Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:300U forKey:31ULL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
+ const uint64_t kValues[] = { 301U, 302U, 303U };
+ GPBUInt64UInt64Dictionary *dict2 =
+ [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 303U);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBUInt64UInt64Dictionary *dict =
+ [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict removeValueForKey:34ULL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:33ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBUInt64UInt64Dictionary *dict =
+ [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict setValue:303U forKey:31ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict setValue:301U forKey:34ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ const uint64_t kKeys2[] = { 32ULL, 33ULL };
+ const uint64_t kValues2[] = { 302U, 300U };
+ GPBUInt64UInt64Dictionary *dict2 =
+ [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt64 -> Int64
+
+@interface GPBUInt64Int64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt64Int64DictionaryTests
+
+- (void)testEmpty {
+ GPBUInt64Int64Dictionary *dict = [[GPBUInt64Int64Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt64Int64Dictionary *dict = [GPBUInt64Int64Dictionary dictionaryWithValue:400 forKey:31ULL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int64_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 31ULL);
+ XCTAssertEqual(aValue, 400);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+ const int64_t kValues[] = { 400, 401, 402 };
+ GPBUInt64Int64Dictionary *dict =
+ [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+ int64_t *seenValues = malloc(3 * sizeof(int64_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int64_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+ const int64_t kValues1[] = { 400, 401, 402 };
+ const int64_t kValues2[] = { 400, 403, 402 };
+ const int64_t kValues3[] = { 400, 401, 402, 403 };
+ GPBUInt64Int64Dictionary *dict1 =
+ [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt64Int64Dictionary *dict1prime =
+ [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt64Int64Dictionary *dict2 =
+ [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt64Int64Dictionary *dict3 =
+ [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt64Int64Dictionary *dict4 =
+ [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBUInt64Int64Dictionary *dict =
+ [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64Int64Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64Int64Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBUInt64Int64Dictionary *dict =
+ [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64Int64Dictionary *dict2 =
+ [GPBUInt64Int64Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt64Int64Dictionary *dict = [GPBUInt64Int64Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:400 forKey:31ULL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
+ const int64_t kValues[] = { 401, 402, 403 };
+ GPBUInt64Int64Dictionary *dict2 =
+ [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 403);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBUInt64Int64Dictionary *dict =
+ [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 403);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict removeValueForKey:34ULL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:33ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBUInt64Int64Dictionary *dict =
+ [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict setValue:403 forKey:31ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict setValue:401 forKey:34ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 401);
+
+ const uint64_t kKeys2[] = { 32ULL, 33ULL };
+ const int64_t kValues2[] = { 402, 400 };
+ GPBUInt64Int64Dictionary *dict2 =
+ [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 401);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt64 -> Bool
+
+@interface GPBUInt64BoolDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt64BoolDictionaryTests
+
+- (void)testEmpty {
+ GPBUInt64BoolDictionary *dict = [[GPBUInt64BoolDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, BOOL aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt64BoolDictionary *dict = [GPBUInt64BoolDictionary dictionaryWithValue:YES forKey:31ULL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, BOOL aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 31ULL);
+ XCTAssertEqual(aValue, YES);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+ const BOOL kValues[] = { YES, YES, NO };
+ GPBUInt64BoolDictionary *dict =
+ [[GPBUInt64BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+ BOOL *seenValues = malloc(3 * sizeof(BOOL));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, BOOL aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, BOOL aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+ const BOOL kValues1[] = { YES, YES, NO };
+ const BOOL kValues2[] = { YES, NO, NO };
+ const BOOL kValues3[] = { YES, YES, NO, NO };
+ GPBUInt64BoolDictionary *dict1 =
+ [[GPBUInt64BoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt64BoolDictionary *dict1prime =
+ [[GPBUInt64BoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt64BoolDictionary *dict2 =
+ [[GPBUInt64BoolDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt64BoolDictionary *dict3 =
+ [[GPBUInt64BoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt64BoolDictionary *dict4 =
+ [[GPBUInt64BoolDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBUInt64BoolDictionary *dict =
+ [[GPBUInt64BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64BoolDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64BoolDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBUInt64BoolDictionary *dict =
+ [[GPBUInt64BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64BoolDictionary *dict2 =
+ [GPBUInt64BoolDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt64BoolDictionary *dict = [GPBUInt64BoolDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:YES forKey:31ULL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
+ const BOOL kValues[] = { YES, NO, NO };
+ GPBUInt64BoolDictionary *dict2 =
+ [[GPBUInt64BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, NO);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBUInt64BoolDictionary *dict =
+ [[GPBUInt64BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, NO);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict removeValueForKey:34ULL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:33ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBUInt64BoolDictionary *dict =
+ [[GPBUInt64BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict setValue:NO forKey:31ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict setValue:YES forKey:34ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, YES);
+
+ const uint64_t kKeys2[] = { 32ULL, 33ULL };
+ const BOOL kValues2[] = { NO, YES };
+ GPBUInt64BoolDictionary *dict2 =
+ [[GPBUInt64BoolDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, YES);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt64 -> Float
+
+@interface GPBUInt64FloatDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt64FloatDictionaryTests
+
+- (void)testEmpty {
+ GPBUInt64FloatDictionary *dict = [[GPBUInt64FloatDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, float aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt64FloatDictionary *dict = [GPBUInt64FloatDictionary dictionaryWithValue:500.f forKey:31ULL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ float value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, float aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 31ULL);
+ XCTAssertEqual(aValue, 500.f);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+ const float kValues[] = { 500.f, 501.f, 502.f };
+ GPBUInt64FloatDictionary *dict =
+ [[GPBUInt64FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ float value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+ float *seenValues = malloc(3 * sizeof(float));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, float aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, float aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+ const float kValues1[] = { 500.f, 501.f, 502.f };
+ const float kValues2[] = { 500.f, 503.f, 502.f };
+ const float kValues3[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBUInt64FloatDictionary *dict1 =
+ [[GPBUInt64FloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt64FloatDictionary *dict1prime =
+ [[GPBUInt64FloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt64FloatDictionary *dict2 =
+ [[GPBUInt64FloatDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt64FloatDictionary *dict3 =
+ [[GPBUInt64FloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt64FloatDictionary *dict4 =
+ [[GPBUInt64FloatDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBUInt64FloatDictionary *dict =
+ [[GPBUInt64FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64FloatDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64FloatDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBUInt64FloatDictionary *dict =
+ [[GPBUInt64FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64FloatDictionary *dict2 =
+ [GPBUInt64FloatDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt64FloatDictionary *dict = [GPBUInt64FloatDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:500.f forKey:31ULL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
+ const float kValues[] = { 501.f, 502.f, 503.f };
+ GPBUInt64FloatDictionary *dict2 =
+ [[GPBUInt64FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ float value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 503.f);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBUInt64FloatDictionary *dict =
+ [[GPBUInt64FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ float value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict removeValueForKey:34ULL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:33ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBUInt64FloatDictionary *dict =
+ [[GPBUInt64FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ float value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict setValue:503.f forKey:31ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict setValue:501.f forKey:34ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ const uint64_t kKeys2[] = { 32ULL, 33ULL };
+ const float kValues2[] = { 502.f, 500.f };
+ GPBUInt64FloatDictionary *dict2 =
+ [[GPBUInt64FloatDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt64 -> Double
+
+@interface GPBUInt64DoubleDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt64DoubleDictionaryTests
+
+- (void)testEmpty {
+ GPBUInt64DoubleDictionary *dict = [[GPBUInt64DoubleDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, double aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt64DoubleDictionary *dict = [GPBUInt64DoubleDictionary dictionaryWithValue:600. forKey:31ULL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ double value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, double aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 31ULL);
+ XCTAssertEqual(aValue, 600.);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+ const double kValues[] = { 600., 601., 602. };
+ GPBUInt64DoubleDictionary *dict =
+ [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ double value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+ double *seenValues = malloc(3 * sizeof(double));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, double aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, double aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+ const double kValues1[] = { 600., 601., 602. };
+ const double kValues2[] = { 600., 603., 602. };
+ const double kValues3[] = { 600., 601., 602., 603. };
+ GPBUInt64DoubleDictionary *dict1 =
+ [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt64DoubleDictionary *dict1prime =
+ [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt64DoubleDictionary *dict2 =
+ [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt64DoubleDictionary *dict3 =
+ [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt64DoubleDictionary *dict4 =
+ [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBUInt64DoubleDictionary *dict =
+ [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64DoubleDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64DoubleDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBUInt64DoubleDictionary *dict =
+ [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64DoubleDictionary *dict2 =
+ [GPBUInt64DoubleDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt64DoubleDictionary *dict = [GPBUInt64DoubleDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:600. forKey:31ULL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
+ const double kValues[] = { 601., 602., 603. };
+ GPBUInt64DoubleDictionary *dict2 =
+ [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ double value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 603.);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBUInt64DoubleDictionary *dict =
+ [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ double value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict removeValueForKey:34ULL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:33ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBUInt64DoubleDictionary *dict =
+ [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ double value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict setValue:603. forKey:31ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict setValue:601. forKey:34ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ const uint64_t kKeys2[] = { 32ULL, 33ULL };
+ const double kValues2[] = { 602., 600. };
+ GPBUInt64DoubleDictionary *dict2 =
+ [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt64 -> Enum
+
+@interface GPBUInt64EnumDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt64EnumDictionaryTests
+
+- (void)testEmpty {
+ GPBUInt64EnumDictionary *dict = [[GPBUInt64EnumDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt64EnumDictionary *dict = [GPBUInt64EnumDictionary dictionaryWithValue:700 forKey:31ULL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 31ULL);
+ XCTAssertEqual(aValue, 700);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+ const int32_t kValues[] = { 700, 701, 702 };
+ GPBUInt64EnumDictionary *dict =
+ [[GPBUInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+ const int32_t kValues1[] = { 700, 701, 702 };
+ const int32_t kValues2[] = { 700, 703, 702 };
+ const int32_t kValues3[] = { 700, 701, 702, 703 };
+ GPBUInt64EnumDictionary *dict1 =
+ [[GPBUInt64EnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt64EnumDictionary *dict1prime =
+ [[GPBUInt64EnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt64EnumDictionary *dict2 =
+ [[GPBUInt64EnumDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt64EnumDictionary *dict3 =
+ [[GPBUInt64EnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt64EnumDictionary *dict4 =
+ [[GPBUInt64EnumDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBUInt64EnumDictionary *dict =
+ [[GPBUInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64EnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64EnumDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBUInt64EnumDictionary *dict =
+ [[GPBUInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64EnumDictionary *dict2 =
+ [GPBUInt64EnumDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt64EnumDictionary *dict = [GPBUInt64EnumDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:700 forKey:31ULL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 701, 702, 703 };
+ GPBUInt64EnumDictionary *dict2 =
+ [[GPBUInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 703);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBUInt64EnumDictionary *dict =
+ [[GPBUInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 703);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict removeValueForKey:34ULL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:33ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBUInt64EnumDictionary *dict =
+ [[GPBUInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict setValue:703 forKey:31ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict setValue:701 forKey:34ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 701);
+
+ const uint64_t kKeys2[] = { 32ULL, 33ULL };
+ const int32_t kValues2[] = { 702, 700 };
+ GPBUInt64EnumDictionary *dict2 =
+ [[GPBUInt64EnumDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 701);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt64 -> Enum (Unknown Enums)
+
+@interface GPBUInt64EnumDictionaryUnknownEnumTests : XCTestCase
+@end
+
+@implementation GPBUInt64EnumDictionaryUnknownEnumTests
+
+- (void)testRawBasics {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+ const int32_t kValues[] = { 700, 801, 702 };
+ GPBUInt64EnumDictionary *dict =
+ [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue(dict.validationFunc == TestingEnum_IsValidValue); // Pointer comparison
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL rawValue:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:32ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:33ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL rawValue:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:34ULL rawValue:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ if (i == 1) {
+ XCTAssertEqual(kGPBUnrecognizedEnumeratorValue, seenValues[j], @"i = %d, j = %d", i, j);
+ } else {
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ idx = 0;
+ [dict enumerateKeysAndRawValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndRawValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEqualityWithUnknowns {
+ const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+ const int32_t kValues1[] = { 700, 801, 702 }; // Unknown
+ const int32_t kValues2[] = { 700, 803, 702 }; // Unknown
+ const int32_t kValues3[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBUInt64EnumDictionary *dict1 =
+ [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt64EnumDictionary *dict1prime =
+ [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt64EnumDictionary *dict2 =
+ [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt64EnumDictionary *dict3 =
+ [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt64EnumDictionary *dict4 =
+ [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopyWithUnknowns {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknown
+ GPBUInt64EnumDictionary *dict =
+ [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64EnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ XCTAssertEqualObjects(dict, dict2);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBUInt64EnumDictionary *dict =
+ [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64EnumDictionary *dict2 =
+ [GPBUInt64EnumDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ [dict release];
+}
+
+- (void)testUnknownAdds {
+ GPBUInt64EnumDictionary *dict =
+ [GPBUInt64EnumDictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertThrowsSpecificNamed([dict setValue:801 forKey:32ULL], // Unknown
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(dict.count, 0U);
+ [dict setRawValue:801 forKey:32ULL]; // Unknown
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint64_t kKeys[] = { 31ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 700, 702, 803 }; // Unknown
+ GPBUInt64EnumDictionary *dict2 =
+ [[GPBUInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:32ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:34ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ [dict2 release];
+}
+
+- (void)testUnknownRemove {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBUInt64EnumDictionary *dict =
+ [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:34ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:34ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict removeValueForKey:34ULL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:33ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutationUnknowns {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBUInt64EnumDictionary *dict =
+ [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:32ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:34ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ XCTAssertThrowsSpecificNamed([dict setValue:803 forKey:31ULL], // Unknown
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:32ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:34ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict setRawValue:803 forKey:31ULL]; // Unknown
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:32ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:34ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict setRawValue:700 forKey:34ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:32ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 700);
+
+ const uint64_t kKeys2[] = { 32ULL, 33ULL };
+ const int32_t kValues2[] = { 702, 801 }; // Unknown
+ GPBUInt64EnumDictionary *dict2 =
+ [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:33ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 700);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testCopyUnknowns {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 700, 801, 702, 803 };
+ GPBUInt64EnumDictionary *dict =
+ [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64EnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64EnumDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt64 -> Object
+
+@interface GPBUInt64ObjectDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt64ObjectDictionaryTests
+
+- (void)testEmpty {
+ GPBUInt64ObjectDictionary *dict = [[GPBUInt64ObjectDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertNil([dict valueForKey:31ULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, id aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt64ObjectDictionary *dict = [GPBUInt64ObjectDictionary dictionaryWithValue:@"abc" forKey:31ULL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertEqualObjects([dict valueForKey:31ULL], @"abc");
+ XCTAssertNil([dict valueForKey:32ULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, id aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 31ULL);
+ XCTAssertEqualObjects(aValue, @"abc");
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+ const id kValues[] = { @"abc", @"def", @"ghi" };
+ GPBUInt64ObjectDictionary *dict =
+ [[GPBUInt64ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertEqualObjects([dict valueForKey:31ULL], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:32ULL], @"def");
+ XCTAssertEqualObjects([dict valueForKey:33ULL], @"ghi");
+ XCTAssertNil([dict valueForKey:34ULL]);
+
+ __block NSUInteger idx = 0;
+ uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+ id *seenValues = malloc(3 * sizeof(id));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, id aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqualObjects(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, id aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+ const id kValues1[] = { @"abc", @"def", @"ghi" };
+ const id kValues2[] = { @"abc", @"jkl", @"ghi" };
+ const id kValues3[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBUInt64ObjectDictionary *dict1 =
+ [[GPBUInt64ObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt64ObjectDictionary *dict1prime =
+ [[GPBUInt64ObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt64ObjectDictionary *dict2 =
+ [[GPBUInt64ObjectDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt64ObjectDictionary *dict3 =
+ [[GPBUInt64ObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt64ObjectDictionary *dict4 =
+ [[GPBUInt64ObjectDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBUInt64ObjectDictionary *dict =
+ [[GPBUInt64ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64ObjectDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64ObjectDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBUInt64ObjectDictionary *dict =
+ [[GPBUInt64ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64ObjectDictionary *dict2 =
+ [GPBUInt64ObjectDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt64ObjectDictionary *dict = [GPBUInt64ObjectDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:@"abc" forKey:31ULL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
+ const id kValues[] = { @"def", @"ghi", @"jkl" };
+ GPBUInt64ObjectDictionary *dict2 =
+ [[GPBUInt64ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ XCTAssertEqualObjects([dict valueForKey:31ULL], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:32ULL], @"def");
+ XCTAssertEqualObjects([dict valueForKey:33ULL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:34ULL], @"jkl");
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBUInt64ObjectDictionary *dict =
+ [[GPBUInt64ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertEqualObjects([dict valueForKey:31ULL], @"abc");
+ XCTAssertNil([dict valueForKey:32ULL]);
+ XCTAssertEqualObjects([dict valueForKey:33ULL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:34ULL], @"jkl");
+
+ // Remove again does nothing.
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertEqualObjects([dict valueForKey:31ULL], @"abc");
+ XCTAssertNil([dict valueForKey:32ULL]);
+ XCTAssertEqualObjects([dict valueForKey:33ULL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:34ULL], @"jkl");
+
+ [dict removeValueForKey:34ULL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertEqualObjects([dict valueForKey:31ULL], @"abc");
+ XCTAssertNil([dict valueForKey:32ULL]);
+ XCTAssertEqualObjects([dict valueForKey:33ULL], @"ghi");
+ XCTAssertNil([dict valueForKey:34ULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertNil([dict valueForKey:31ULL]);
+ XCTAssertNil([dict valueForKey:32ULL]);
+ XCTAssertNil([dict valueForKey:33ULL]);
+ XCTAssertNil([dict valueForKey:34ULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBUInt64ObjectDictionary *dict =
+ [[GPBUInt64ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:31ULL], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:32ULL], @"def");
+ XCTAssertEqualObjects([dict valueForKey:33ULL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:34ULL], @"jkl");
+
+ [dict setValue:@"jkl" forKey:31ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:31ULL], @"jkl");
+ XCTAssertEqualObjects([dict valueForKey:32ULL], @"def");
+ XCTAssertEqualObjects([dict valueForKey:33ULL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:34ULL], @"jkl");
+
+ [dict setValue:@"def" forKey:34ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:31ULL], @"jkl");
+ XCTAssertEqualObjects([dict valueForKey:32ULL], @"def");
+ XCTAssertEqualObjects([dict valueForKey:33ULL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:34ULL], @"def");
+
+ const uint64_t kKeys2[] = { 32ULL, 33ULL };
+ const id kValues2[] = { @"ghi", @"abc" };
+ GPBUInt64ObjectDictionary *dict2 =
+ [[GPBUInt64ObjectDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:31ULL], @"jkl");
+ XCTAssertEqualObjects([dict valueForKey:32ULL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:33ULL], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:34ULL], @"def");
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND-END TEST_FOR_POD_KEY(UInt64, uint64_t, 31ULL, 32ULL, 33ULL, 34ULL)
diff --git a/objectivec/Tests/GPBDictionaryTests.pddm b/objectivec/Tests/GPBDictionaryTests.pddm
new file mode 100644
index 00000000..39793e03
--- /dev/null
+++ b/objectivec/Tests/GPBDictionaryTests.pddm
@@ -0,0 +1,1044 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+
+//%PDDM-DEFINE TEST_FOR_POD_KEY(KEY_NAME, KEY_TYPE, KEY1, KEY2, KEY3, KEY4)
+//%TESTS_FOR_POD_VALUES(KEY_NAME, KEY_TYPE, , , KEY1, KEY2, KEY3, KEY4)
+//%TESTS_FOR_POD_KEY_OBJECT_VALUE(KEY_NAME, KEY_TYPE, KEY1, KEY2, KEY3, KEY4, Object, id, @"abc", @"def", @"ghi", @"jkl")
+
+//%PDDM-DEFINE TESTS_FOR_POD_VALUES(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4)
+//%TEST_HELPERS(KEY_NAME, KEY_TYPE, KisP)
+//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, UInt32, uint32_t, , 100U, 101U, 102U, 103U)
+//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Int32, int32_t, , 200, 201, 202, 203)
+//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, UInt64, uint64_t, , 300U, 301U, 302U, 303U)
+//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Int64, int64_t, , 400, 401, 402, 403)
+//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Bool, BOOL, , YES, YES, NO, NO)
+//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Float, float, , 500.f, 501.f, 502.f, 503.f)
+//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Double, double, , 600., 601., 602., 603.)
+//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Enum, int32_t, Raw, 700, 701, 702, 703)
+//%TESTS_FOR_ENUM_VALUE_RAW_ADDITIONS(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4)
+
+//%PDDM-DEFINE TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, VACCESSOR, VAL1, VAL2, VAL3, VAL4)
+//%TESTS_COMMON(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, , POD, VACCESSOR, VAL1, VAL2, VAL3, VAL4)
+
+//%PDDM-DEFINE TESTS_FOR_POD_KEY_OBJECT_VALUE(KEY_NAME, KEY_TYPE, KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, VAL1, VAL2, VAL3, VAL4)
+//%TESTS_COMMON(KEY_NAME, KEY_TYPE, , , KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, Objects, OBJECT, , VAL1, VAL2, VAL3, VAL4)
+
+//%PDDM-DEFINE TESTS_COMMON(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, VSUFFIX, VHELPER, VACCESSOR, VAL1, VAL2, VAL3, VAL4)
+//%#pragma mark - KEY_NAME -> VALUE_NAME
+//%
+//%@interface GPB##KEY_NAME##VALUE_NAME##DictionaryTests : XCTestCase
+//%@end
+//%
+//%@implementation GPB##KEY_NAME##VALUE_NAME##DictionaryTests
+//%
+//%- (void)testEmpty {
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
+//% XCTAssertNotNil(dict);
+//% XCTAssertEqual(dict.count, 0U);
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY1)
+//% [dict enumerateKeysAndValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
+//% #pragma unused(aKey, aValue, stop)
+//% XCTFail(@"Shouldn't get here!");
+//% }];
+//% [dict release];
+//%}
+//%
+//%- (void)testOne {
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithValue:VAL1 forKey:KEY1];
+//% XCTAssertNotNil(dict);
+//% XCTAssertEqual(dict.count, 1U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//% [dict enumerateKeysAndValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
+//% XCTAssertEqual##KSUFFIX(aKey, KEY1);
+//% XCTAssertEqual##VSUFFIX(aValue, VAL1);
+//% XCTAssertNotEqual(stop, NULL);
+//% }];
+//%}
+//%
+//%- (void)testBasics {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//% XCTAssertEqual(dict.count, 3U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY4)
+//%
+//% __block NSUInteger idx = 0;
+//% KEY_TYPE KisP##*seenKeys = malloc(3 * sizeof(KEY_TYPE##KisP));
+//% VALUE_TYPE *seenValues = malloc(3 * sizeof(VALUE_TYPE));
+//% [dict enumerateKeysAndValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
+//% XCTAssertLessThan(idx, 3U);
+//% seenKeys[idx] = aKey;
+//% seenValues[idx] = aValue;
+//% XCTAssertNotEqual(stop, NULL);
+//% ++idx;
+//% }];
+//% for (int i = 0; i < 3; ++i) {
+//% BOOL foundKey = NO;
+//% for (int j = 0; (j < 3) && !foundKey; ++j) {
+//% if (COMPARE_KEYS##KSUFFIX(kKeys[i], seenKeys[j])) {
+//% foundKey = YES;
+//% XCTAssertEqual##VSUFFIX(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+//% }
+//% }
+//% XCTAssertTrue(foundKey, @"i = %d", i);
+//% }
+//% free(seenKeys);
+//% free(seenValues);
+//%
+//% // Stopping the enumeration.
+//% idx = 0;
+//% [dict enumerateKeysAndValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
+//% #pragma unused(aKey, aValue)
+//% if (idx == 1) *stop = YES;
+//% XCTAssertNotEqual(idx, 2U);
+//% ++idx;
+//% }];
+//% [dict release];
+//%}
+//%
+//%- (void)testEquality {
+//% const KEY_TYPE KisP##kKeys1[] = { KEY1, KEY2, KEY3, KEY4 };
+//% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY1, KEY4 };
+//% const VALUE_TYPE kValues1[] = { VAL1, VAL2, VAL3 };
+//% const VALUE_TYPE kValues2[] = { VAL1, VAL4, VAL3 };
+//% const VALUE_TYPE kValues3[] = { VAL1, VAL2, VAL3, VAL4 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict1 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues1
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues1)];
+//% XCTAssertNotNil(dict1);
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict1prime =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues1
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues1)];
+//% XCTAssertNotNil(dict1prime);
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues2
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues2)];
+//% XCTAssertNotNil(dict2);
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict3 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues1
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys2
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues1)];
+//% XCTAssertNotNil(dict3);
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict4 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues3
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues3)];
+//% XCTAssertNotNil(dict4);
+//%
+//% // 1/1Prime should be different objects, but equal.
+//% XCTAssertNotEqual(dict1, dict1prime);
+//% XCTAssertEqualObjects(dict1, dict1prime);
+//% // Equal, so they must have same hash.
+//% XCTAssertEqual([dict1 hash], [dict1prime hash]);
+//%
+//% // 2 is save keys, different values; not equal.
+//% XCTAssertNotEqualObjects(dict1, dict2);
+//%
+//% // 3 is different keys, samae values; not equal.
+//% XCTAssertNotEqualObjects(dict1, dict3);
+//%
+//% // 4 extra pair; not equal
+//% XCTAssertNotEqualObjects(dict1, dict4);
+//%
+//% [dict1 release];
+//% [dict1prime release];
+//% [dict2 release];
+//% [dict3 release];
+//% [dict4 release];
+//%}
+//%
+//%- (void)testCopy {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//%
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 = [dict copy];
+//% XCTAssertNotNil(dict2);
+//%
+//% // Should be new object but equal.
+//% XCTAssertNotEqual(dict, dict2);
+//% XCTAssertEqualObjects(dict, dict2);
+//% XCTAssertTrue([dict2 isKindOfClass:[GPB##KEY_NAME##VALUE_NAME##Dictionary class]]);
+//%
+//% [dict2 release];
+//% [dict release];
+//%}
+//%
+//%- (void)testDictionaryFromDictionary {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//%
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//% [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithDictionary:dict];
+//% XCTAssertNotNil(dict2);
+//%
+//% // Should be new pointer, but equal objects.
+//% XCTAssertNotEqual(dict, dict2);
+//% XCTAssertEqualObjects(dict, dict2);
+//% [dict release];
+//%}
+//%
+//%- (void)testAdds {
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionary];
+//% XCTAssertNotNil(dict);
+//%
+//% XCTAssertEqual(dict.count, 0U);
+//% [dict setValue:VAL1 forKey:KEY1];
+//% XCTAssertEqual(dict.count, 1U);
+//%
+//% const KEY_TYPE KisP##kKeys[] = { KEY2, KEY3, KEY4 };
+//% const VALUE_TYPE kValues[] = { VAL2, VAL3, VAL4 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict2);
+//% [dict add##VACCESSOR##EntriesFromDictionary:dict2];
+//% XCTAssertEqual(dict.count, 4U);
+//%
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//% [dict2 release];
+//%}
+//%
+//%- (void)testRemove {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//% XCTAssertEqual(dict.count, 4U);
+//%
+//% [dict removeValueForKey:KEY2];
+//% XCTAssertEqual(dict.count, 3U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//%
+//% // Remove again does nothing.
+//% [dict removeValueForKey:KEY2];
+//% XCTAssertEqual(dict.count, 3U);
+//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//%
+//% [dict removeValueForKey:KEY4];
+//% XCTAssertEqual(dict.count, 2U);
+//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY4)
+//%
+//% [dict removeAll];
+//% XCTAssertEqual(dict.count, 0U);
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY3)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY4)
+//% [dict release];
+//%}
+//%
+//%- (void)testInplaceMutation {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//% XCTAssertEqual(dict.count, 4U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//%
+//% [dict setValue:VAL4 forKey:KEY1];
+//% XCTAssertEqual(dict.count, 4U);
+//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL4)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//%
+//% [dict setValue:VAL2 forKey:KEY4];
+//% XCTAssertEqual(dict.count, 4U);
+//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL4)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_VALUE##VHELPER(dict, value, KEY4, VAL2)
+//%
+//% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY3 };
+//% const VALUE_TYPE kValues2[] = { VAL3, VAL1 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues2
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys2
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues2)];
+//% XCTAssertNotNil(dict2);
+//% [dict add##VACCESSOR##EntriesFromDictionary:dict2];
+//% XCTAssertEqual(dict.count, 4U);
+//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL4)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL3)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL1)
+//%TEST_VALUE##VHELPER(dict, value, KEY4, VAL2)
+//%
+//% [dict2 release];
+//% [dict release];
+//%}
+//%
+//%@end
+//%
+
+//%PDDM-DEFINE TESTS_FOR_ENUM_VALUE_RAW_ADDITIONS(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4)
+//%TESTS_FOR_ENUM_VALUE_RAW_ADDITIONS2(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Enum, int32_t, , POD, 700, 801, 702, 803)
+//%PDDM-DEFINE TESTS_FOR_ENUM_VALUE_RAW_ADDITIONS2(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, VSUFFIX, VHELPER, VAL1, VAL2, VAL3, VAL4)
+//%#pragma mark - KEY_NAME -> VALUE_NAME (Unknown Enums)
+//%
+//%@interface GPB##KEY_NAME##VALUE_NAME##DictionaryUnknownEnumTests : XCTestCase
+//%@end
+//%
+//%@implementation GPB##KEY_NAME##VALUE_NAME##DictionaryUnknownEnumTests
+//%
+//%- (void)testRawBasics {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//% KEY_NAME$S VALUE_NAME$S rawValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//% XCTAssertEqual(dict.count, 3U);
+//% XCTAssertTrue(dict.validationFunc == TestingEnum_IsValidValue); // Pointer comparison
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_RAW_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, kGPBUnrecognizedEnumeratorValue)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%RAW_VALUE_NOT_FOUND##VHELPER(dict, KEY4)
+//%
+//% __block NSUInteger idx = 0;
+//% KEY_TYPE KisP##*seenKeys = malloc(3 * sizeof(KEY_TYPE##KisP));
+//% VALUE_TYPE *seenValues = malloc(3 * sizeof(VALUE_TYPE));
+//% [dict enumerateKeysAndValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
+//% XCTAssertLessThan(idx, 3U);
+//% seenKeys[idx] = aKey;
+//% seenValues[idx] = aValue;
+//% XCTAssertNotEqual(stop, NULL);
+//% ++idx;
+//% }];
+//% for (int i = 0; i < 3; ++i) {
+//% BOOL foundKey = NO;
+//% for (int j = 0; (j < 3) && !foundKey; ++j) {
+//% if (COMPARE_KEYS##KSUFFIX(kKeys[i], seenKeys[j])) {
+//% foundKey = YES;
+//% if (i == 1) {
+//% XCTAssertEqual##VSUFFIX(kGPBUnrecognizedEnumeratorValue, seenValues[j], @"i = %d, j = %d", i, j);
+//% } else {
+//% XCTAssertEqual##VSUFFIX(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+//% }
+//% }
+//% }
+//% XCTAssertTrue(foundKey, @"i = %d", i);
+//% }
+//% idx = 0;
+//% [dict enumerateKeysAndRawValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
+//% XCTAssertLessThan(idx, 3U);
+//% seenKeys[idx] = aKey;
+//% seenValues[idx] = aValue;
+//% XCTAssertNotEqual(stop, NULL);
+//% ++idx;
+//% }];
+//% for (int i = 0; i < 3; ++i) {
+//% BOOL foundKey = NO;
+//% for (int j = 0; (j < 3) && !foundKey; ++j) {
+//% if (COMPARE_KEYS##KSUFFIX(kKeys[i], seenKeys[j])) {
+//% foundKey = YES;
+//% XCTAssertEqual##VSUFFIX(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+//% }
+//% }
+//% XCTAssertTrue(foundKey, @"i = %d", i);
+//% }
+//% free(seenKeys);
+//% free(seenValues);
+//%
+//% // Stopping the enumeration.
+//% idx = 0;
+//% [dict enumerateKeysAndRawValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
+//% #pragma unused(aKey, aValue)
+//% if (idx == 1) *stop = YES;
+//% XCTAssertNotEqual(idx, 2U);
+//% ++idx;
+//% }];
+//% [dict release];
+//%}
+//%
+//%- (void)testEqualityWithUnknowns {
+//% const KEY_TYPE KisP##kKeys1[] = { KEY1, KEY2, KEY3, KEY4 };
+//% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY1, KEY4 };
+//% const VALUE_TYPE kValues1[] = { VAL1, VAL2, VAL3 }; // Unknown
+//% const VALUE_TYPE kValues2[] = { VAL1, VAL4, VAL3 }; // Unknown
+//% const VALUE_TYPE kValues3[] = { VAL1, VAL2, VAL3, VAL4 }; // Unknowns
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict1 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//% KEY_NAME$S VALUE_NAME$S rawValues:kValues1
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues1)];
+//% XCTAssertNotNil(dict1);
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict1prime =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//% KEY_NAME$S VALUE_NAME$S rawValues:kValues1
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues1)];
+//% XCTAssertNotNil(dict1prime);
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//% KEY_NAME$S VALUE_NAME$S rawValues:kValues2
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues2)];
+//% XCTAssertNotNil(dict2);
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict3 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//% KEY_NAME$S VALUE_NAME$S rawValues:kValues1
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys2
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues1)];
+//% XCTAssertNotNil(dict3);
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict4 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//% KEY_NAME$S VALUE_NAME$S rawValues:kValues3
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues3)];
+//% XCTAssertNotNil(dict4);
+//%
+//% // 1/1Prime should be different objects, but equal.
+//% XCTAssertNotEqual(dict1, dict1prime);
+//% XCTAssertEqualObjects(dict1, dict1prime);
+//% // Equal, so they must have same hash.
+//% XCTAssertEqual([dict1 hash], [dict1prime hash]);
+//%
+//% // 2 is save keys, different values; not equal.
+//% XCTAssertNotEqualObjects(dict1, dict2);
+//%
+//% // 3 is different keys, samae values; not equal.
+//% XCTAssertNotEqualObjects(dict1, dict3);
+//%
+//% // 4 extra pair; not equal
+//% XCTAssertNotEqualObjects(dict1, dict4);
+//%
+//% [dict1 release];
+//% [dict1prime release];
+//% [dict2 release];
+//% [dict3 release];
+//% [dict4 release];
+//%}
+//%
+//%- (void)testCopyWithUnknowns {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 }; // Unknown
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//% KEY_NAME$S VALUE_NAME$S rawValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//%
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 = [dict copy];
+//% XCTAssertNotNil(dict2);
+//%
+//% // Should be new pointer, but equal objects.
+//% XCTAssertNotEqual(dict, dict2);
+//% XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+//% XCTAssertEqualObjects(dict, dict2);
+//%
+//% [dict2 release];
+//% [dict release];
+//%}
+//%
+//%- (void)testDictionaryFromDictionary {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 }; // Unknowns
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//% KEY_NAME$S VALUE_NAME$S rawValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//%
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//% [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithDictionary:dict];
+//% XCTAssertNotNil(dict2);
+//%
+//% // Should be new pointer, but equal objects.
+//% XCTAssertNotEqual(dict, dict2);
+//% XCTAssertEqualObjects(dict, dict2);
+//% XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+//% [dict release];
+//%}
+//%
+//%- (void)testUnknownAdds {
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue];
+//% XCTAssertNotNil(dict);
+//%
+//% XCTAssertEqual(dict.count, 0U);
+//% XCTAssertThrowsSpecificNamed([dict setValue:VAL2 forKey:KEY2], // Unknown
+//% NSException, NSInvalidArgumentException);
+//% XCTAssertEqual(dict.count, 0U);
+//% [dict setRawValue:VAL2 forKey:KEY2]; // Unknown
+//% XCTAssertEqual(dict.count, 1U);
+//%
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY3, KEY4 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL3, VAL4 }; // Unknown
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict2);
+//% [dict addRawEntriesFromDictionary:dict2];
+//% XCTAssertEqual(dict.count, 4U);
+//%
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, kGPBUnrecognizedEnumeratorValue)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_VALUE##VHELPER(dict, value, KEY4, kGPBUnrecognizedEnumeratorValue)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//% [dict2 release];
+//%}
+//%
+//%- (void)testUnknownRemove {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 }; // Unknowns
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//% KEY_NAME$S VALUE_NAME$S rawValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//% XCTAssertEqual(dict.count, 4U);
+//%
+//% [dict removeValueForKey:KEY2];
+//% XCTAssertEqual(dict.count, 3U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//%
+//% // Remove again does nothing.
+//% [dict removeValueForKey:KEY2];
+//% XCTAssertEqual(dict.count, 3U);
+//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//%
+//% [dict removeValueForKey:KEY4];
+//% XCTAssertEqual(dict.count, 2U);
+//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY4)
+//%
+//% [dict removeAll];
+//% XCTAssertEqual(dict.count, 0U);
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY3)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY4)
+//% [dict release];
+//%}
+//%
+//%- (void)testInplaceMutationUnknowns {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 }; // Unknowns
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//% KEY_NAME$S VALUE_NAME$S rawValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//% XCTAssertEqual(dict.count, 4U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//%
+//% XCTAssertThrowsSpecificNamed([dict setValue:VAL4 forKey:KEY1], // Unknown
+//% NSException, NSInvalidArgumentException);
+//% XCTAssertEqual(dict.count, 4U);
+//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//%
+//% [dict setRawValue:VAL4 forKey:KEY1]; // Unknown
+//% XCTAssertEqual(dict.count, 4U);
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY1, VAL4)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//%
+//% [dict setRawValue:VAL1 forKey:KEY4];
+//% XCTAssertEqual(dict.count, 4U);
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY1, VAL4)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_VALUE##VHELPER(dict, value, KEY4, VAL1)
+//%
+//% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY3 };
+//% const VALUE_TYPE kValues2[] = { VAL3, VAL2 }; // Unknown
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//% KEY_NAME$S VALUE_NAME$S rawValues:kValues2
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys2
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues2)];
+//% XCTAssertNotNil(dict2);
+//% [dict addRawEntriesFromDictionary:dict2];
+//% XCTAssertEqual(dict.count, 4U);
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY1, VAL4)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL3)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY3, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY4, VAL1)
+//%
+//% [dict2 release];
+//% [dict release];
+//%}
+//%
+//%- (void)testCopyUnknowns {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//% KEY_NAME$S VALUE_NAME$S rawValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//%
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 = [dict copy];
+//% XCTAssertNotNil(dict2);
+//%
+//% // Should be new pointer, but equal objects.
+//% XCTAssertNotEqual(dict, dict2);
+//% XCTAssertEqualObjects(dict, dict2);
+//% XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+//% XCTAssertTrue([dict2 isKindOfClass:[GPB##KEY_NAME##VALUE_NAME##Dictionary class]]);
+//%
+//% [dict2 release];
+//% [dict release];
+//%}
+//%
+//%@end
+//%
+
+//
+// Helpers for PODs
+//
+
+//%PDDM-DEFINE DECLARE_VALUE_STORAGEPOD(VALUE_TYPE, NAME)
+//% VALUE_TYPE NAME;
+//%
+//%PDDM-DEFINE VALUE_NOT_FOUNDPOD(DICT, KEY)
+//% XCTAssertFalse([DICT valueForKey:KEY value:NULL]);
+//%PDDM-DEFINE TEST_VALUEPOD(DICT, STORAGE, KEY, VALUE)
+//% XCTAssertTrue([DICT valueForKey:KEY value:NULL]);
+//% XCTAssertTrue([DICT valueForKey:KEY value:&STORAGE]);
+//% XCTAssertEqual(STORAGE, VALUE);
+//%PDDM-DEFINE COMPARE_KEYS(KEY1, KEY2)
+//%KEY1 == KEY2
+//%PDDM-DEFINE RAW_VALUE_NOT_FOUNDPOD(DICT, KEY)
+//% XCTAssertFalse([DICT valueForKey:KEY rawValue:NULL]);
+//%PDDM-DEFINE TEST_RAW_VALUEPOD(DICT, STORAGE, KEY, VALUE)
+//% XCTAssertTrue([DICT valueForKey:KEY rawValue:NULL]);
+//% XCTAssertTrue([DICT valueForKey:KEY rawValue:&STORAGE]);
+//% XCTAssertEqual(STORAGE, VALUE);
+
+//
+// Helpers for Objects
+//
+
+//%PDDM-DEFINE DECLARE_VALUE_STORAGEOBJECT(VALUE_TYPE, NAME)
+// Empty
+//%PDDM-DEFINE VALUE_NOT_FOUNDOBJECT(DICT, KEY)
+//% XCTAssertNil([DICT valueForKey:KEY]);
+//%PDDM-DEFINE TEST_VALUEOBJECT(DICT, STORAGE, KEY, VALUE)
+//% XCTAssertEqualObjects([DICT valueForKey:KEY], VALUE);
+//%PDDM-DEFINE COMPARE_KEYSObjects(KEY1, KEY2)
+//%[KEY1 isEqual:KEY2]
+
+//
+// Helpers for tests.
+//
+
+//%PDDM-DEFINE TEST_HELPERS(KEY_NAME, KEY_TYPE, KisP)
+//%#ifndef GPBARRAYSIZE
+//%#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))))
+//%#endif // GPBARRAYSIZE
+//%
+//%// To let the testing macros work, add some extra methods to simplify things.
+//%@interface GPB##KEY_NAME##EnumDictionary (TestingTweak)
+//%+ (instancetype)dictionaryWithValue:(int32_t)value forKey:(KEY_TYPE##KisP$S##KisP)key;
+//%- (instancetype)initWithValues:(const int32_t [])values
+//% forKeys:(const KEY_TYPE##KisP$S##KisP [])keys
+//% count:(NSUInteger)count;
+//%@end
+//%
+//%static BOOL TestingEnum_IsValidValue(int32_t value) {
+//% switch (value) {
+//% case 700:
+//% case 701:
+//% case 702:
+//% case 703:
+//% return YES;
+//% default:
+//% return NO;
+//% }
+//%}
+//%
+//%@implementation GPB##KEY_NAME##EnumDictionary (TestingTweak)
+//%+ (instancetype)dictionaryWithValue:(int32_t)value forKey:(KEY_TYPE##KisP$S##KisP)key {
+//% // Cast is needed to compiler knows what class we are invoking initWithValues: on to get the
+//% // type correct.
+//% return [[(GPB##KEY_NAME##EnumDictionary*)[self alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//% KEY_NAME$S rawValues:&value
+//% KEY_NAME$S forKeys:&key
+//% KEY_NAME$S count:1] autorelease];
+//%}
+//%- (instancetype)initWithValues:(const int32_t [])values
+//% forKeys:(const KEY_TYPE##KisP$S##KisP [])keys
+//% count:(NSUInteger)count {
+//% return [self initWithValidationFunction:TestingEnum_IsValidValue
+//% rawValues:values
+//% forKeys:keys
+//% count:count];
+//%}
+//%@end
+//%
+//%
+
+
+//
+// BOOL test macros
+//
+//TODO(thomasvl): enum tests
+
+//%PDDM-DEFINE BOOL_TESTS_FOR_POD_VALUE(VALUE_NAME, VALUE_TYPE, VAL1, VAL2)
+//%BOOL_TESTS_COMMON(Bool, BOOL, , , YES, NO, VALUE_NAME, VALUE_TYPE, , POD, VAL1, VAL2)
+
+//%PDDM-DEFINE TESTS_FOR_BOOL_KEY_OBJECT_VALUE(VALUE_NAME, VALUE_TYPE, VAL1, VAL2)
+//%BOOL_TESTS_COMMON(Bool, BOOL, , , YES, NO, VALUE_NAME, VALUE_TYPE, Objects, OBJECT, VAL1, VAL2)
+
+//%PDDM-DEFINE BOOL_TESTS_COMMON(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, VALUE_NAME, VALUE_TYPE, VSUFFIX, VHELPER, VAL1, VAL2)
+//%#pragma mark - KEY_NAME -> VALUE_NAME
+//%
+//%@interface GPB##KEY_NAME##VALUE_NAME##DictionaryTests : XCTestCase
+//%@end
+//%
+//%@implementation GPB##KEY_NAME##VALUE_NAME##DictionaryTests
+//%
+//%- (void)testEmpty {
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
+//% XCTAssertNotNil(dict);
+//% XCTAssertEqual(dict.count, 0U);
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY1)
+//% [dict enumerateKeysAndValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
+//% #pragma unused(aKey, aValue, stop)
+//% XCTFail(@"Shouldn't get here!");
+//% }];
+//% [dict release];
+//%}
+//%
+//%- (void)testOne {
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithValue:VAL1 forKey:KEY1];
+//% XCTAssertNotNil(dict);
+//% XCTAssertEqual(dict.count, 1U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//% [dict enumerateKeysAndValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
+//% XCTAssertEqual##KSUFFIX(aKey, KEY1);
+//% XCTAssertEqual##VSUFFIX(aValue, VAL1);
+//% XCTAssertNotEqual(stop, NULL);
+//% }];
+//%}
+//%
+//%- (void)testBasics {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//% XCTAssertEqual(dict.count, 2U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%
+//% __block NSUInteger idx = 0;
+//% KEY_TYPE KisP##*seenKeys = malloc(2 * sizeof(KEY_TYPE##KisP));
+//% VALUE_TYPE *seenValues = malloc(2 * sizeof(VALUE_TYPE));
+//% [dict enumerateKeysAndValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
+//% XCTAssertLessThan(idx, 2U);
+//% seenKeys[idx] = aKey;
+//% seenValues[idx] = aValue;
+//% XCTAssertNotEqual(stop, NULL);
+//% ++idx;
+//% }];
+//% for (int i = 0; i < 2; ++i) {
+//% BOOL foundKey = NO;
+//% for (int j = 0; (j < 2) && !foundKey; ++j) {
+//% if (COMPARE_KEYS##KSUFFIX(kKeys[i], seenKeys[j])) {
+//% foundKey = YES;
+//% XCTAssertEqual##VSUFFIX(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+//% }
+//% }
+//% XCTAssertTrue(foundKey, @"i = %d", i);
+//% }
+//% free(seenKeys);
+//% free(seenValues);
+//%
+//% // Stopping the enumeration.
+//% idx = 0;
+//% [dict enumerateKeysAndValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
+//% #pragma unused(aKey, aValue)
+//% if (idx == 0) *stop = YES;
+//% XCTAssertNotEqual(idx, 2U);
+//% ++idx;
+//% }];
+//% [dict release];
+//%}
+//%
+//%- (void)testEquality {
+//% const KEY_TYPE KisP##kKeys1[] = { KEY1, KEY2 };
+//% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY1 };
+//% const VALUE_TYPE kValues1[] = { VAL1, VAL2 };
+//% const VALUE_TYPE kValues2[] = { VAL2, VAL1 };
+//% const VALUE_TYPE kValues3[] = { VAL2 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict1 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues1
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues1)];
+//% XCTAssertNotNil(dict1);
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict1prime =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues1
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues1)];
+//% XCTAssertNotNil(dict1prime);
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues2
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues2)];
+//% XCTAssertNotNil(dict2);
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict3 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues1
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys2
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues1)];
+//% XCTAssertNotNil(dict3);
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict4 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues3
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues3)];
+//% XCTAssertNotNil(dict4);
+//%
+//% // 1/1Prime should be different objects, but equal.
+//% XCTAssertNotEqual(dict1, dict1prime);
+//% XCTAssertEqualObjects(dict1, dict1prime);
+//% // Equal, so they must have same hash.
+//% XCTAssertEqual([dict1 hash], [dict1prime hash]);
+//%
+//% // 2 is save keys, different values; not equal.
+//% XCTAssertNotEqualObjects(dict1, dict2);
+//%
+//% // 3 is different keys, samae values; not equal.
+//% XCTAssertNotEqualObjects(dict1, dict3);
+//%
+//% // 4 Fewer pairs; not equal
+//% XCTAssertNotEqualObjects(dict1, dict4);
+//%
+//% [dict1 release];
+//% [dict1prime release];
+//% [dict2 release];
+//% [dict3 release];
+//% [dict4 release];
+//%}
+//%
+//%- (void)testCopy {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//%
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 = [dict copy];
+//% XCTAssertNotNil(dict2);
+//%
+//% // Should be new object but equal.
+//% XCTAssertNotEqual(dict, dict2);
+//% XCTAssertEqualObjects(dict, dict2);
+//% XCTAssertTrue([dict2 isKindOfClass:[GPB##KEY_NAME##VALUE_NAME##Dictionary class]]);
+//%
+//% [dict2 release];
+//% [dict release];
+//%}
+//%
+//%- (void)testDictionaryFromDictionary {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//%
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//% [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithDictionary:dict];
+//% XCTAssertNotNil(dict2);
+//%
+//% // Should be new pointer, but equal objects.
+//% XCTAssertNotEqual(dict, dict2);
+//% XCTAssertEqualObjects(dict, dict2);
+//% [dict release];
+//%}
+//%
+//%- (void)testAdds {
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionary];
+//% XCTAssertNotNil(dict);
+//%
+//% XCTAssertEqual(dict.count, 0U);
+//% [dict setValue:VAL1 forKey:KEY1];
+//% XCTAssertEqual(dict.count, 1U);
+//%
+//% const KEY_TYPE KisP##kKeys[] = { KEY2 };
+//% const VALUE_TYPE kValues[] = { VAL2 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict2);
+//% [dict addEntriesFromDictionary:dict2];
+//% XCTAssertEqual(dict.count, 2U);
+//%
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//% [dict2 release];
+//%}
+//%
+//%- (void)testRemove {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2};
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//% XCTAssertEqual(dict.count, 2U);
+//%
+//% [dict removeValueForKey:KEY2];
+//% XCTAssertEqual(dict.count, 1U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%
+//% // Remove again does nothing.
+//% [dict removeValueForKey:KEY2];
+//% XCTAssertEqual(dict.count, 1U);
+//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%
+//% [dict removeAll];
+//% XCTAssertEqual(dict.count, 0U);
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//% [dict release];
+//%}
+//%
+//%- (void)testInplaceMutation {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//% XCTAssertEqual(dict.count, 2U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%
+//% [dict setValue:VAL2 forKey:KEY1];
+//% XCTAssertEqual(dict.count, 2U);
+//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%
+//% [dict setValue:VAL1 forKey:KEY2];
+//% XCTAssertEqual(dict.count, 2U);
+//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL1)
+//%
+//% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY1 };
+//% const VALUE_TYPE kValues2[] = { VAL2, VAL1 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues2
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys2
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues2)];
+//% XCTAssertNotNil(dict2);
+//% [dict addEntriesFromDictionary:dict2];
+//% XCTAssertEqual(dict.count, 2U);
+//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%
+//% [dict2 release];
+//% [dict release];
+//%}
+//%
+//%@end
+//%
+
diff --git a/objectivec/Tests/GPBFilteredMessageTests.m b/objectivec/Tests/GPBFilteredMessageTests.m
new file mode 100644
index 00000000..b0588837
--- /dev/null
+++ b/objectivec/Tests/GPBFilteredMessageTests.m
@@ -0,0 +1,98 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2013 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.
+
+// Tests our filter system for ObjC.
+// The proto being filtered is unittest_filter.proto.
+// The filter file is Filter.txt.
+
+#import "GPBTestUtilities.h"
+
+#import "google/protobuf/UnittestFilter.pbobjc.h"
+
+// If we get an error about this already being defined, it is most likely
+// because of an error in protoc which is supposed to be filtering
+// the Remove message.
+enum { Other_FieldNumber_B = 0 };
+
+@interface FilteredMessageTests : GPBTestCase
+@end
+
+@implementation FilteredMessageTests
+
+- (void)testEnumFiltering {
+ // If compile fails here it is because protoc did not generate KeepEnum.
+ XCTAssertTrue(KeepEnum_IsValidValue(KeepEnum_KeepValue));
+ XCTAssertNotNil(KeepEnum_EnumDescriptor());
+
+ // If compile fails here it is because protoc did not generate
+ // KeepEnumInsideEnum and is probably due to nested enum handling being
+ // broken.
+ XCTAssertTrue(RemoveEnumMessage_KeepEnumInside_IsValidValue(
+ RemoveEnumMessage_KeepEnumInside_KeepValue));
+ XCTAssertNotNil(RemoveEnumMessage_KeepEnumInside_EnumDescriptor());
+}
+
+- (void)testMessageFiltering {
+ // Messages that should be generated.
+ XCTAssertNil([UnittestFilterRoot extensionRegistry]);
+ XCTAssertNotNil([[[Keep alloc] init] autorelease]);
+ XCTAssertNotNil([[[Other alloc] init] autorelease]);
+ XCTAssertNotNil([[[RemoveJustKidding alloc] init] autorelease]);
+ XCTAssertNotNil(
+ [[[RemoveEnumMessage_KeepNestedInside alloc] init] autorelease]);
+
+ // Messages that should not be generated
+ XCTAssertNil(NSClassFromString(@"Remove"));
+ XCTAssertNil(NSClassFromString(@"RemoveEnumMessage"));
+ XCTAssertNil(NSClassFromString(@"RemoveEnumMessage_RemoveNestedInside"));
+
+ // These should all fail compile if protoc is bad.
+ XCTAssertTrue([Other instancesRespondToSelector:@selector(hasA)]);
+ XCTAssertTrue([Other instancesRespondToSelector:@selector(setHasA:)]);
+ XCTAssertTrue([Other instancesRespondToSelector:@selector(a)]);
+ XCTAssertTrue([Other instancesRespondToSelector:@selector(setA:)]);
+
+ // These the compiler should not generate.
+ XCTAssertFalse(
+ [Other instancesRespondToSelector:NSSelectorFromString(@"hasB")]);
+ XCTAssertFalse(
+ [Other instancesRespondToSelector:NSSelectorFromString(@"setHasB:")]);
+ XCTAssertFalse([Other instancesRespondToSelector:NSSelectorFromString(@"b")]);
+ XCTAssertFalse(
+ [Other instancesRespondToSelector:NSSelectorFromString(@"setB:")]);
+
+ // This should fail if protoc filters it.
+ XCTAssertEqual(Other_FieldNumber_A, 1);
+
+ // Make sure the definition at the top of the file is providing the value.
+ XCTAssertEqual(Other_FieldNumber_B, 0);
+}
+
+@end
diff --git a/objectivec/Tests/GPBMessageTests+Merge.m b/objectivec/Tests/GPBMessageTests+Merge.m
new file mode 100644
index 00000000..599ad055
--- /dev/null
+++ b/objectivec/Tests/GPBMessageTests+Merge.m
@@ -0,0 +1,700 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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 "GPBTestUtilities.h"
+
+#import <objc/runtime.h>
+
+#import "GPBMessage.h"
+
+#import "google/protobuf/MapUnittest.pbobjc.h"
+#import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.h"
+#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+#import "google/protobuf/UnittestRuntimeProto3.pbobjc.h"
+
+@interface MessageMergeTests : GPBTestCase
+@end
+
+@implementation MessageMergeTests
+
+// TODO(thomasvl): Pull tests over from GPBMessageTests that are merge specific.
+
+- (void)testProto3MergingAndZeroValues {
+ // Proto2 covered in other tests.
+
+ Message3 *src = [[Message3 alloc] init];
+ Message3 *dst = [[Message3 alloc] init];
+ NSData *testData1 = [@"abc" dataUsingEncoding:NSUTF8StringEncoding];
+ NSData *testData2 = [@"def" dataUsingEncoding:NSUTF8StringEncoding];
+
+ dst.optionalInt32 = 1;
+ dst.optionalInt64 = 1;
+ dst.optionalUint32 = 1;
+ dst.optionalUint64 = 1;
+ dst.optionalSint32 = 1;
+ dst.optionalSint64 = 1;
+ dst.optionalFixed32 = 1;
+ dst.optionalFixed64 = 1;
+ dst.optionalSfixed32 = 1;
+ dst.optionalSfixed64 = 1;
+ dst.optionalFloat = 1.0f;
+ dst.optionalDouble = 1.0;
+ dst.optionalBool = YES;
+ dst.optionalString = @"bar";
+ dst.optionalBytes = testData1;
+ dst.optionalEnum = Message3_Enum_Bar;
+
+ // All zeros, nothing should overright.
+
+ src.optionalInt32 = 0;
+ src.optionalInt64 = 0;
+ src.optionalUint32 = 0;
+ src.optionalUint64 = 0;
+ src.optionalSint32 = 0;
+ src.optionalSint64 = 0;
+ src.optionalFixed32 = 0;
+ src.optionalFixed64 = 0;
+ src.optionalSfixed32 = 0;
+ src.optionalSfixed64 = 0;
+ src.optionalFloat = 0.0f;
+ src.optionalDouble = 0.0;
+ src.optionalBool = NO;
+ src.optionalString = @"";
+ src.optionalBytes = [NSData data];
+ src.optionalEnum = Message3_Enum_Foo; // first value
+
+ [dst mergeFrom:src];
+
+ XCTAssertEqual(dst.optionalInt32, 1);
+ XCTAssertEqual(dst.optionalInt64, 1);
+ XCTAssertEqual(dst.optionalUint32, 1U);
+ XCTAssertEqual(dst.optionalUint64, 1U);
+ XCTAssertEqual(dst.optionalSint32, 1);
+ XCTAssertEqual(dst.optionalSint64, 1);
+ XCTAssertEqual(dst.optionalFixed32, 1U);
+ XCTAssertEqual(dst.optionalFixed64, 1U);
+ XCTAssertEqual(dst.optionalSfixed32, 1);
+ XCTAssertEqual(dst.optionalSfixed64, 1);
+ XCTAssertEqual(dst.optionalFloat, 1.0f);
+ XCTAssertEqual(dst.optionalDouble, 1.0);
+ XCTAssertEqual(dst.optionalBool, YES);
+ XCTAssertEqualObjects(dst.optionalString, @"bar");
+ XCTAssertEqualObjects(dst.optionalBytes, testData1);
+ XCTAssertEqual(dst.optionalEnum, Message3_Enum_Bar);
+
+ // Half the values that will replace.
+
+ src.optionalInt32 = 0;
+ src.optionalInt64 = 2;
+ src.optionalUint32 = 0;
+ src.optionalUint64 = 2;
+ src.optionalSint32 = 0;
+ src.optionalSint64 = 2;
+ src.optionalFixed32 = 0;
+ src.optionalFixed64 = 2;
+ src.optionalSfixed32 = 0;
+ src.optionalSfixed64 = 2;
+ src.optionalFloat = 0.0f;
+ src.optionalDouble = 2.0;
+ src.optionalBool = YES; // No other value to use. :(
+ src.optionalString = @"baz";
+ src.optionalBytes = nil;
+ src.optionalEnum = Message3_Enum_Baz;
+
+ [dst mergeFrom:src];
+
+ XCTAssertEqual(dst.optionalInt32, 1);
+ XCTAssertEqual(dst.optionalInt64, 2);
+ XCTAssertEqual(dst.optionalUint32, 1U);
+ XCTAssertEqual(dst.optionalUint64, 2U);
+ XCTAssertEqual(dst.optionalSint32, 1);
+ XCTAssertEqual(dst.optionalSint64, 2);
+ XCTAssertEqual(dst.optionalFixed32, 1U);
+ XCTAssertEqual(dst.optionalFixed64, 2U);
+ XCTAssertEqual(dst.optionalSfixed32, 1);
+ XCTAssertEqual(dst.optionalSfixed64, 2);
+ XCTAssertEqual(dst.optionalFloat, 1.0f);
+ XCTAssertEqual(dst.optionalDouble, 2.0);
+ XCTAssertEqual(dst.optionalBool, YES);
+ XCTAssertEqualObjects(dst.optionalString, @"baz");
+ XCTAssertEqualObjects(dst.optionalBytes, testData1);
+ XCTAssertEqual(dst.optionalEnum, Message3_Enum_Baz);
+
+ // Other half the values that will replace.
+
+ src.optionalInt32 = 3;
+ src.optionalInt64 = 0;
+ src.optionalUint32 = 3;
+ src.optionalUint64 = 0;
+ src.optionalSint32 = 3;
+ src.optionalSint64 = 0;
+ src.optionalFixed32 = 3;
+ src.optionalFixed64 = 0;
+ src.optionalSfixed32 = 3;
+ src.optionalSfixed64 = 0;
+ src.optionalFloat = 3.0f;
+ src.optionalDouble = 0.0;
+ src.optionalBool = YES; // No other value to use. :(
+ src.optionalString = nil;
+ src.optionalBytes = testData2;
+ src.optionalEnum = Message3_Enum_Foo;
+
+ [dst mergeFrom:src];
+
+ XCTAssertEqual(dst.optionalInt32, 3);
+ XCTAssertEqual(dst.optionalInt64, 2);
+ XCTAssertEqual(dst.optionalUint32, 3U);
+ XCTAssertEqual(dst.optionalUint64, 2U);
+ XCTAssertEqual(dst.optionalSint32, 3);
+ XCTAssertEqual(dst.optionalSint64, 2);
+ XCTAssertEqual(dst.optionalFixed32, 3U);
+ XCTAssertEqual(dst.optionalFixed64, 2U);
+ XCTAssertEqual(dst.optionalSfixed32, 3);
+ XCTAssertEqual(dst.optionalSfixed64, 2);
+ XCTAssertEqual(dst.optionalFloat, 3.0f);
+ XCTAssertEqual(dst.optionalDouble, 2.0);
+ XCTAssertEqual(dst.optionalBool, YES);
+ XCTAssertEqualObjects(dst.optionalString, @"baz");
+ XCTAssertEqualObjects(dst.optionalBytes, testData2);
+ XCTAssertEqual(dst.optionalEnum, Message3_Enum_Baz);
+
+ [src release];
+ [dst release];
+}
+
+- (void)testProto3MergingEnums {
+ UnknownEnumsMyMessage *src = [UnknownEnumsMyMessage message];
+ UnknownEnumsMyMessage *dst = [UnknownEnumsMyMessage message];
+
+ // Known value.
+
+ src.e = UnknownEnumsMyEnum_Bar;
+ src.repeatedEArray =
+ [GPBEnumArray arrayWithValidationFunction:UnknownEnumsMyEnum_IsValidValue
+ rawValue:UnknownEnumsMyEnum_Bar];
+ src.repeatedPackedEArray =
+ [GPBEnumArray arrayWithValidationFunction:UnknownEnumsMyEnum_IsValidValue
+ rawValue:UnknownEnumsMyEnum_Bar];
+ src.oneofE1 = UnknownEnumsMyEnum_Bar;
+
+ [dst mergeFrom:src];
+
+ XCTAssertEqual(dst.e, UnknownEnumsMyEnum_Bar);
+ XCTAssertEqual(dst.repeatedEArray.count, 1U);
+ XCTAssertEqual([dst.repeatedEArray valueAtIndex:0], UnknownEnumsMyEnum_Bar);
+ XCTAssertEqual(dst.repeatedPackedEArray.count, 1U);
+ XCTAssertEqual([dst.repeatedPackedEArray valueAtIndex:0],
+ UnknownEnumsMyEnum_Bar);
+ XCTAssertEqual(dst.oneofE1, UnknownEnumsMyEnum_Bar);
+
+ // Unknown value.
+
+ const int32_t kUnknownValue = 666;
+
+ SetUnknownEnumsMyMessage_E_RawValue(src, kUnknownValue);
+ src.repeatedEArray =
+ [GPBEnumArray arrayWithValidationFunction:UnknownEnumsMyEnum_IsValidValue
+ rawValue:kUnknownValue];
+ src.repeatedPackedEArray =
+ [GPBEnumArray arrayWithValidationFunction:UnknownEnumsMyEnum_IsValidValue
+ rawValue:kUnknownValue];
+ SetUnknownEnumsMyMessage_OneofE1_RawValue(src, kUnknownValue);
+
+ [dst mergeFrom:src];
+
+ XCTAssertEqual(dst.e, UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual(UnknownEnumsMyMessage_E_RawValue(dst), kUnknownValue);
+ XCTAssertEqual(dst.repeatedEArray.count, 2U);
+ XCTAssertEqual([dst.repeatedEArray valueAtIndex:0], UnknownEnumsMyEnum_Bar);
+ XCTAssertEqual([dst.repeatedEArray valueAtIndex:1],
+ UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual([dst.repeatedEArray rawValueAtIndex:1], kUnknownValue);
+ XCTAssertEqual(dst.repeatedPackedEArray.count, 2U);
+ XCTAssertEqual([dst.repeatedPackedEArray valueAtIndex:0],
+ UnknownEnumsMyEnum_Bar);
+ XCTAssertEqual([dst.repeatedPackedEArray valueAtIndex:1],
+ UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual([dst.repeatedPackedEArray rawValueAtIndex:1], kUnknownValue);
+ XCTAssertEqual(dst.oneofE1,
+ UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual(UnknownEnumsMyMessage_OneofE1_RawValue(dst), kUnknownValue);
+}
+
+- (void)testProto2MergeOneof {
+ Message2 *src = [Message2 message];
+ Message2 *dst = [Message2 message];
+
+ //
+ // Make sure whatever is in dst gets cleared out be merging in something else.
+ //
+
+ dst.oneofEnum = Message2_Enum_Bar;
+
+//%PDDM-DEFINE MERGE2_TEST(SET_NAME, SET_VALUE, CLEARED_NAME, CLEARED_DEFAULT)
+//% src.oneof##SET_NAME = SET_VALUE;
+//% [dst mergeFrom:src];
+//% XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_Oneof##SET_NAME);
+//% XCTAssertEqual(dst.oneof##SET_NAME, SET_VALUE);
+//% XCTAssertEqual(dst.oneof##CLEARED_NAME, CLEARED_DEFAULT);
+//%
+//%PDDM-EXPAND MERGE2_TEST(Int32, 10, Enum, Message2_Enum_Baz)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofInt32 = 10;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofInt32);
+ XCTAssertEqual(dst.oneofInt32, 10);
+ XCTAssertEqual(dst.oneofEnum, Message2_Enum_Baz);
+
+//%PDDM-EXPAND MERGE2_TEST(Int64, 11, Int32, 100)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofInt64 = 11;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofInt64);
+ XCTAssertEqual(dst.oneofInt64, 11);
+ XCTAssertEqual(dst.oneofInt32, 100);
+
+//%PDDM-EXPAND MERGE2_TEST(Uint32, 12U, Int64, 101)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofUint32 = 12U;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofUint32);
+ XCTAssertEqual(dst.oneofUint32, 12U);
+ XCTAssertEqual(dst.oneofInt64, 101);
+
+//%PDDM-EXPAND MERGE2_TEST(Uint64, 13U, Uint32, 102U)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofUint64 = 13U;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofUint64);
+ XCTAssertEqual(dst.oneofUint64, 13U);
+ XCTAssertEqual(dst.oneofUint32, 102U);
+
+//%PDDM-EXPAND MERGE2_TEST(Sint32, 14, Uint64, 103U)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofSint32 = 14;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofSint32);
+ XCTAssertEqual(dst.oneofSint32, 14);
+ XCTAssertEqual(dst.oneofUint64, 103U);
+
+//%PDDM-EXPAND MERGE2_TEST(Sint64, 15, Sint32, 104)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofSint64 = 15;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofSint64);
+ XCTAssertEqual(dst.oneofSint64, 15);
+ XCTAssertEqual(dst.oneofSint32, 104);
+
+//%PDDM-EXPAND MERGE2_TEST(Fixed32, 16U, Sint64, 105)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofFixed32 = 16U;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofFixed32);
+ XCTAssertEqual(dst.oneofFixed32, 16U);
+ XCTAssertEqual(dst.oneofSint64, 105);
+
+//%PDDM-EXPAND MERGE2_TEST(Fixed64, 17U, Fixed32, 106U)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofFixed64 = 17U;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofFixed64);
+ XCTAssertEqual(dst.oneofFixed64, 17U);
+ XCTAssertEqual(dst.oneofFixed32, 106U);
+
+//%PDDM-EXPAND MERGE2_TEST(Sfixed32, 18, Fixed64, 107U)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofSfixed32 = 18;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofSfixed32);
+ XCTAssertEqual(dst.oneofSfixed32, 18);
+ XCTAssertEqual(dst.oneofFixed64, 107U);
+
+//%PDDM-EXPAND MERGE2_TEST(Sfixed64, 19, Sfixed32, 108)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofSfixed64 = 19;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofSfixed64);
+ XCTAssertEqual(dst.oneofSfixed64, 19);
+ XCTAssertEqual(dst.oneofSfixed32, 108);
+
+//%PDDM-EXPAND MERGE2_TEST(Float, 20.0f, Sfixed64, 109)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofFloat = 20.0f;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofFloat);
+ XCTAssertEqual(dst.oneofFloat, 20.0f);
+ XCTAssertEqual(dst.oneofSfixed64, 109);
+
+//%PDDM-EXPAND MERGE2_TEST(Double, 21.0, Float, 110.0f)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofDouble = 21.0;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofDouble);
+ XCTAssertEqual(dst.oneofDouble, 21.0);
+ XCTAssertEqual(dst.oneofFloat, 110.0f);
+
+//%PDDM-EXPAND MERGE2_TEST(Bool, NO, Double, 111.0)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofBool = NO;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofBool);
+ XCTAssertEqual(dst.oneofBool, NO);
+ XCTAssertEqual(dst.oneofDouble, 111.0);
+
+//%PDDM-EXPAND MERGE2_TEST(Enum, Message2_Enum_Bar, Bool, YES)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofEnum = Message2_Enum_Bar;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofEnum);
+ XCTAssertEqual(dst.oneofEnum, Message2_Enum_Bar);
+ XCTAssertEqual(dst.oneofBool, YES);
+
+//%PDDM-EXPAND-END (14 expansions)
+
+ NSString *oneofStringDefault = @"string";
+ NSData *oneofBytesDefault = [@"data" dataUsingEncoding:NSUTF8StringEncoding];
+
+ src.oneofString = @"foo";
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofString);
+ XCTAssertEqualObjects(dst.oneofString, @"foo");
+ XCTAssertEqual(dst.oneofEnum, Message2_Enum_Baz);
+
+ src.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofBytes);
+ XCTAssertEqualObjects(dst.oneofBytes,
+ [@"bar" dataUsingEncoding:NSUTF8StringEncoding]);
+ XCTAssertEqualObjects(dst.oneofString, oneofStringDefault);
+
+ Message2_OneofGroup *group = [Message2_OneofGroup message];
+ group.a = 666;
+ src.oneofGroup = group;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofGroup);
+ Message2_OneofGroup *mergedGroup = [[dst.oneofGroup retain] autorelease];
+ XCTAssertNotNil(mergedGroup);
+ XCTAssertNotEqual(mergedGroup, group); // Pointer comparision.
+ XCTAssertEqualObjects(mergedGroup, group);
+ XCTAssertEqualObjects(dst.oneofBytes, oneofBytesDefault);
+
+ Message2 *subMessage = [Message2 message];
+ subMessage.optionalInt32 = 777;
+ src.oneofMessage = subMessage;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofMessage);
+ Message2 *mergedSubMessage = [[dst.oneofMessage retain] autorelease];
+ XCTAssertNotNil(mergedSubMessage);
+ XCTAssertNotEqual(mergedSubMessage, subMessage); // Pointer comparision.
+ XCTAssertEqualObjects(mergedSubMessage, subMessage);
+ XCTAssertNotNil(dst.oneofGroup);
+ XCTAssertNotEqual(dst.oneofGroup, mergedGroup); // Pointer comparision.
+
+ // Back to something else ot make sure message clears out ok.
+
+ src.oneofInt32 = 10;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofInt32);
+ XCTAssertNotNil(dst.oneofMessage);
+ XCTAssertNotEqual(dst.oneofMessage,
+ mergedSubMessage); // Pointer comparision.
+
+ //
+ // Test merging in to message/group when they already had something.
+ //
+
+ src.oneofGroup = group;
+ mergedGroup = [Message2_OneofGroup message];
+ mergedGroup.b = 888;
+ dst.oneofGroup = mergedGroup;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofGroup);
+ // Shouldn't have been a new object.
+ XCTAssertEqual(dst.oneofGroup, mergedGroup); // Pointer comparision.
+ XCTAssertEqual(dst.oneofGroup.a, 666); // Pointer comparision.
+ XCTAssertEqual(dst.oneofGroup.b, 888); // Pointer comparision.
+
+ src.oneofMessage = subMessage;
+ mergedSubMessage = [Message2 message];
+ mergedSubMessage.optionalInt64 = 999;
+ dst.oneofMessage = mergedSubMessage;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofMessage);
+ // Shouldn't have been a new object.
+ XCTAssertEqual(dst.oneofMessage, mergedSubMessage); // Pointer comparision.
+ XCTAssertEqual(dst.oneofMessage.optionalInt32, 777); // Pointer comparision.
+ XCTAssertEqual(dst.oneofMessage.optionalInt64, 999); // Pointer comparision.
+}
+
+- (void)testProto3MergeOneof {
+ Message3 *src = [Message3 message];
+ Message3 *dst = [Message3 message];
+
+ //
+ // Make sure whatever is in dst gets cleared out be merging in something else.
+ //
+
+ dst.oneofEnum = Message3_Enum_Bar;
+
+//%PDDM-DEFINE MERGE3_TEST(SET_NAME, SET_VALUE, CLEARED_NAME, CLEARED_DEFAULT)
+//% src.oneof##SET_NAME = SET_VALUE;
+//% [dst mergeFrom:src];
+//% XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_Oneof##SET_NAME);
+//% XCTAssertEqual(dst.oneof##SET_NAME, SET_VALUE);
+//% XCTAssertEqual(dst.oneof##CLEARED_NAME, CLEARED_DEFAULT);
+//%
+//%PDDM-EXPAND MERGE3_TEST(Int32, 10, Enum, Message3_Enum_Foo)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofInt32 = 10;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofInt32);
+ XCTAssertEqual(dst.oneofInt32, 10);
+ XCTAssertEqual(dst.oneofEnum, Message3_Enum_Foo);
+
+//%PDDM-EXPAND MERGE3_TEST(Int64, 11, Int32, 0)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofInt64 = 11;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofInt64);
+ XCTAssertEqual(dst.oneofInt64, 11);
+ XCTAssertEqual(dst.oneofInt32, 0);
+
+//%PDDM-EXPAND MERGE3_TEST(Uint32, 12U, Int64, 0)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofUint32 = 12U;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofUint32);
+ XCTAssertEqual(dst.oneofUint32, 12U);
+ XCTAssertEqual(dst.oneofInt64, 0);
+
+//%PDDM-EXPAND MERGE3_TEST(Uint64, 13U, Uint32, 0U)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofUint64 = 13U;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofUint64);
+ XCTAssertEqual(dst.oneofUint64, 13U);
+ XCTAssertEqual(dst.oneofUint32, 0U);
+
+//%PDDM-EXPAND MERGE3_TEST(Sint32, 14, Uint64, 0U)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofSint32 = 14;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofSint32);
+ XCTAssertEqual(dst.oneofSint32, 14);
+ XCTAssertEqual(dst.oneofUint64, 0U);
+
+//%PDDM-EXPAND MERGE3_TEST(Sint64, 15, Sint32, 0)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofSint64 = 15;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofSint64);
+ XCTAssertEqual(dst.oneofSint64, 15);
+ XCTAssertEqual(dst.oneofSint32, 0);
+
+//%PDDM-EXPAND MERGE3_TEST(Fixed32, 16U, Sint64, 0)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofFixed32 = 16U;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofFixed32);
+ XCTAssertEqual(dst.oneofFixed32, 16U);
+ XCTAssertEqual(dst.oneofSint64, 0);
+
+//%PDDM-EXPAND MERGE3_TEST(Fixed64, 17U, Fixed32, 0U)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofFixed64 = 17U;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofFixed64);
+ XCTAssertEqual(dst.oneofFixed64, 17U);
+ XCTAssertEqual(dst.oneofFixed32, 0U);
+
+//%PDDM-EXPAND MERGE3_TEST(Sfixed32, 18, Fixed64, 0U)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofSfixed32 = 18;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofSfixed32);
+ XCTAssertEqual(dst.oneofSfixed32, 18);
+ XCTAssertEqual(dst.oneofFixed64, 0U);
+
+//%PDDM-EXPAND MERGE3_TEST(Sfixed64, 19, Sfixed32, 0)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofSfixed64 = 19;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofSfixed64);
+ XCTAssertEqual(dst.oneofSfixed64, 19);
+ XCTAssertEqual(dst.oneofSfixed32, 0);
+
+//%PDDM-EXPAND MERGE3_TEST(Float, 20.0f, Sfixed64, 0)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofFloat = 20.0f;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofFloat);
+ XCTAssertEqual(dst.oneofFloat, 20.0f);
+ XCTAssertEqual(dst.oneofSfixed64, 0);
+
+//%PDDM-EXPAND MERGE3_TEST(Double, 21.0, Float, 0.0f)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofDouble = 21.0;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofDouble);
+ XCTAssertEqual(dst.oneofDouble, 21.0);
+ XCTAssertEqual(dst.oneofFloat, 0.0f);
+
+//%PDDM-EXPAND MERGE3_TEST(Bool, YES, Double, 0.0)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofBool = YES;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofBool);
+ XCTAssertEqual(dst.oneofBool, YES);
+ XCTAssertEqual(dst.oneofDouble, 0.0);
+
+//%PDDM-EXPAND MERGE3_TEST(Enum, Message3_Enum_Bar, Bool, NO)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofEnum = Message3_Enum_Bar;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofEnum);
+ XCTAssertEqual(dst.oneofEnum, Message3_Enum_Bar);
+ XCTAssertEqual(dst.oneofBool, NO);
+
+//%PDDM-EXPAND-END (14 expansions)
+
+ NSString *oneofStringDefault = @"";
+ NSData *oneofBytesDefault = [NSData data];
+
+ src.oneofString = @"foo";
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofString);
+ XCTAssertEqualObjects(dst.oneofString, @"foo");
+ XCTAssertEqual(dst.oneofEnum, Message3_Enum_Foo);
+
+ src.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofBytes);
+ XCTAssertEqualObjects(dst.oneofBytes,
+ [@"bar" dataUsingEncoding:NSUTF8StringEncoding]);
+ XCTAssertEqualObjects(dst.oneofString, oneofStringDefault);
+
+
+ Message3 *subMessage = [Message3 message];
+ subMessage.optionalInt32 = 777;
+ src.oneofMessage = subMessage;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofMessage);
+ Message3 *mergedSubMessage = [[dst.oneofMessage retain] autorelease];
+ XCTAssertNotNil(mergedSubMessage);
+ XCTAssertNotEqual(mergedSubMessage, subMessage); // Pointer comparision.
+ XCTAssertEqualObjects(mergedSubMessage, subMessage);
+ XCTAssertEqualObjects(dst.oneofBytes, oneofBytesDefault);
+
+ // Back to something else ot make sure message clears out ok.
+
+ src.oneofInt32 = 10;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofInt32);
+ XCTAssertNotNil(dst.oneofMessage);
+ XCTAssertNotEqual(dst.oneofMessage,
+ mergedSubMessage); // Pointer comparision.
+
+ //
+ // Test merging in to message when they already had something.
+ //
+
+ src.oneofMessage = subMessage;
+ mergedSubMessage = [Message3 message];
+ mergedSubMessage.optionalInt64 = 999;
+ dst.oneofMessage = mergedSubMessage;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofMessage);
+ // Shouldn't have been a new object.
+ XCTAssertEqual(dst.oneofMessage, mergedSubMessage); // Pointer comparision.
+ XCTAssertEqual(dst.oneofMessage.optionalInt32, 777); // Pointer comparision.
+ XCTAssertEqual(dst.oneofMessage.optionalInt64, 999); // Pointer comparision.
+}
+
+#pragma mark - Subset from from map_tests.cc
+
+// TEST(GeneratedMapFieldTest, CopyFromMessageMap)
+- (void)testMap_CopyFromMessageMap {
+ TestMessageMap *msg1 = [[TestMessageMap alloc] init];
+ TestMessageMap *msg2 = [[TestMessageMap alloc] init];
+
+ TestAllTypes *subMsg = [TestAllTypes message];
+ subMsg.repeatedInt32Array = [GPBInt32Array arrayWithValue:100];
+ msg1.mapInt32Message = [GPBInt32ObjectDictionary dictionary];
+ [msg1.mapInt32Message setValue:subMsg forKey:0];
+ subMsg = nil;
+
+ subMsg = [TestAllTypes message];
+ subMsg.repeatedInt32Array = [GPBInt32Array arrayWithValue:101];
+ msg2.mapInt32Message = [GPBInt32ObjectDictionary dictionary];
+ [msg2.mapInt32Message setValue:subMsg forKey:0];
+ subMsg = nil;
+
+ [msg1 mergeFrom:msg2];
+
+ // Checks repeated field is overwritten.
+ XCTAssertEqual(msg1.mapInt32Message.count, 1U);
+ subMsg = [msg1.mapInt32Message valueForKey:0];
+ XCTAssertNotNil(subMsg);
+ XCTAssertEqual(subMsg.repeatedInt32Array.count, 1U);
+ XCTAssertEqual([subMsg.repeatedInt32Array valueAtIndex:0], 101);
+
+ [msg2 release];
+ [msg1 release];
+}
+
+@end
diff --git a/objectivec/Tests/GPBMessageTests+Runtime.m b/objectivec/Tests/GPBMessageTests+Runtime.m
new file mode 100644
index 00000000..6ad29ca5
--- /dev/null
+++ b/objectivec/Tests/GPBMessageTests+Runtime.m
@@ -0,0 +1,1978 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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 "GPBTestUtilities.h"
+
+#import <objc/runtime.h>
+
+#import "GPBMessage.h"
+
+#import "google/protobuf/MapUnittest.pbobjc.h"
+#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+#import "google/protobuf/UnittestRuntimeProto3.pbobjc.h"
+
+@interface MessageRuntimeTests : GPBTestCase
+@end
+
+@implementation MessageRuntimeTests
+
+// TODO(thomasvl): Pull tests over from GPBMessageTests that are runtime
+// specific.
+
+- (void)testProto2HasMethodSupport {
+ NSArray *names = @[
+ @"Int32",
+ @"Int64",
+ @"Uint32",
+ @"Uint64",
+ @"Sint32",
+ @"Sint64",
+ @"Fixed32",
+ @"Fixed64",
+ @"Sfixed32",
+ @"Sfixed64",
+ @"Float",
+ @"Double",
+ @"Bool",
+ @"String",
+ @"Bytes",
+ @"Group",
+ @"Message",
+ @"Enum",
+ ];
+
+ // Proto2 gets:
+ // - has* on all non repeated fields.
+ // - setHas* on all non repeated fields.
+
+ for (NSString *name in names) {
+ // build the selector, i.e. - hasOptionalInt32/setHasOptionalInt32:
+ SEL hasSel = NSSelectorFromString(
+ [NSString stringWithFormat:@"hasOptional%@", name]);
+ SEL setHasSel = NSSelectorFromString(
+ [NSString stringWithFormat:@"setHasOptional%@:", name]);
+ XCTAssertTrue([Message2 instancesRespondToSelector:hasSel], @"field: %@",
+ name);
+ XCTAssertTrue([Message2 instancesRespondToSelector:setHasSel], @"field: %@",
+ name);
+ }
+
+ // Repeated - no has/setHas
+
+ for (NSString *name in names) {
+ // build the selector, i.e. - hasRepeatedInt32/setHasRepeatedInt32:
+ SEL hasSel = NSSelectorFromString(
+ [NSString stringWithFormat:@"hasRepeated%@", name]);
+ SEL setHasSel = NSSelectorFromString(
+ [NSString stringWithFormat:@"setHasRepeated%@:", name]);
+ XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@",
+ name);
+ XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel],
+ @"field: %@", name);
+ }
+
+ // Oneofs - no has/setHas
+
+ for (NSString *name in names) {
+ // build the selector, i.e. - hasOneofInt32/setHasOneofInt32:
+ SEL hasSel =
+ NSSelectorFromString([NSString stringWithFormat:@"hasOneof%@", name]);
+ SEL setHasSel = NSSelectorFromString(
+ [NSString stringWithFormat:@"setHasOneof%@:", name]);
+ XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@",
+ name);
+ XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel],
+ @"field: %@", name);
+ }
+}
+
+- (void)testProto3HasMethodSupport {
+ NSArray *names = @[
+ @"Int32",
+ @"Int64",
+ @"Uint32",
+ @"Uint64",
+ @"Sint32",
+ @"Sint64",
+ @"Fixed32",
+ @"Fixed64",
+ @"Sfixed32",
+ @"Sfixed64",
+ @"Float",
+ @"Double",
+ @"Bool",
+ @"String",
+ @"Bytes",
+ @"Message",
+ @"Enum",
+ ];
+
+ // Proto3 gets:
+ // - has* on non repeated message fields.
+ // - setHas* on all non repeated message fields.
+
+ // Singlular
+
+ for (NSString *name in names) {
+ // build the selector, i.e. - hasOptionalInt32/setHasOptionalInt32:
+ SEL hasSel = NSSelectorFromString(
+ [NSString stringWithFormat:@"hasOptional%@", name]);
+ SEL setHasSel = NSSelectorFromString(
+ [NSString stringWithFormat:@"setHasOptional%@:", name]);
+ if ([name isEqual:@"Group"] || [name isEqual:@"Message"]) {
+ // Sub messages/groups are the exception.
+ XCTAssertTrue([Message3 instancesRespondToSelector:hasSel], @"field: %@",
+ name);
+ XCTAssertTrue([Message3 instancesRespondToSelector:setHasSel],
+ @"field: %@", name);
+ } else {
+ XCTAssertFalse([Message3 instancesRespondToSelector:hasSel], @"field: %@",
+ name);
+ XCTAssertFalse([Message3 instancesRespondToSelector:setHasSel],
+ @"field: %@", name);
+ }
+ }
+
+ // Repeated - no has/setHas
+
+ for (NSString *name in names) {
+ // build the selector, i.e. - hasRepeatedInt32/setHasRepeatedInt32:
+ SEL hasSel = NSSelectorFromString(
+ [NSString stringWithFormat:@"hasRepeated%@", name]);
+ SEL setHasSel = NSSelectorFromString(
+ [NSString stringWithFormat:@"setHasRepeated%@:", name]);
+ XCTAssertFalse([Message3 instancesRespondToSelector:hasSel], @"field: %@",
+ name);
+ XCTAssertFalse([Message3 instancesRespondToSelector:setHasSel],
+ @"field: %@", name);
+ }
+
+ // Oneofs - no has/setHas
+
+ for (NSString *name in names) {
+ // build the selector, i.e. - hasOneofInt32/setHasOneofInt32:
+ SEL hasSel =
+ NSSelectorFromString([NSString stringWithFormat:@"hasOneof%@", name]);
+ SEL setHasSel = NSSelectorFromString(
+ [NSString stringWithFormat:@"setHasOneof%@:", name]);
+ XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@",
+ name);
+ XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel],
+ @"field: %@", name);
+ }
+}
+
+- (void)testProto2SingleFieldHasBehavior {
+ //
+ // Setting to any value including the default value (0) should result has*
+ // being true.
+ //
+
+//%PDDM-DEFINE PROTO2_TEST_HAS_FIELD(FIELD, NON_ZERO_VALUE, ZERO_VALUE)
+//% { // optional##FIELD :: NON_ZERO_VALUE
+//% Message2 *msg = [[Message2 alloc] init];
+//% XCTAssertFalse(msg.hasOptional##FIELD);
+//% XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_Optional##FIELD));
+//% msg.optional##FIELD = NON_ZERO_VALUE;
+//% XCTAssertTrue(msg.hasOptional##FIELD);
+//% XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_Optional##FIELD));
+//% [msg release];
+//% }
+//% { // optional##FIELD :: ZERO_VALUE
+//% Message2 *msg = [[Message2 alloc] init];
+//% XCTAssertFalse(msg.hasOptional##FIELD);
+//% XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_Optional##FIELD));
+//% msg.optional##FIELD = ZERO_VALUE;
+//% XCTAssertTrue(msg.hasOptional##FIELD);
+//% XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_Optional##FIELD));
+//% [msg release];
+//% }
+//%
+//%PDDM-DEFINE PROTO2_TEST_HAS_FIELDS()
+//%PROTO2_TEST_HAS_FIELD(Int32, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Int64, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Uint32, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Uint64, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Sint32, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Sint64, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Fixed32, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Fixed64, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Sfixed32, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Sfixed64, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Float, 1.0f, 0.0f)
+//%PROTO2_TEST_HAS_FIELD(Double, 1.0, 0.0)
+//%PROTO2_TEST_HAS_FIELD(Bool, YES, NO)
+//%PROTO2_TEST_HAS_FIELD(String, @"foo", @"")
+//%PROTO2_TEST_HAS_FIELD(Bytes, [@"foo" dataUsingEncoding:NSUTF8StringEncoding], [NSData data])
+//% //
+//% // Test doesn't apply to optionalGroup/optionalMessage.
+//% //
+//%
+//%PROTO2_TEST_HAS_FIELD(Enum, Message2_Enum_Bar, Message2_Enum_Foo)
+//%PDDM-EXPAND PROTO2_TEST_HAS_FIELDS()
+// This block of code is generated, do not edit it directly.
+
+ { // optionalInt32 :: 1
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalInt32);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalInt32));
+ msg.optionalInt32 = 1;
+ XCTAssertTrue(msg.hasOptionalInt32);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalInt32));
+ [msg release];
+ }
+ { // optionalInt32 :: 0
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalInt32);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalInt32));
+ msg.optionalInt32 = 0;
+ XCTAssertTrue(msg.hasOptionalInt32);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalInt32));
+ [msg release];
+ }
+
+ { // optionalInt64 :: 1
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalInt64);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalInt64));
+ msg.optionalInt64 = 1;
+ XCTAssertTrue(msg.hasOptionalInt64);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalInt64));
+ [msg release];
+ }
+ { // optionalInt64 :: 0
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalInt64);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalInt64));
+ msg.optionalInt64 = 0;
+ XCTAssertTrue(msg.hasOptionalInt64);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalInt64));
+ [msg release];
+ }
+
+ { // optionalUint32 :: 1
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalUint32);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalUint32));
+ msg.optionalUint32 = 1;
+ XCTAssertTrue(msg.hasOptionalUint32);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalUint32));
+ [msg release];
+ }
+ { // optionalUint32 :: 0
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalUint32);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalUint32));
+ msg.optionalUint32 = 0;
+ XCTAssertTrue(msg.hasOptionalUint32);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalUint32));
+ [msg release];
+ }
+
+ { // optionalUint64 :: 1
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalUint64);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalUint64));
+ msg.optionalUint64 = 1;
+ XCTAssertTrue(msg.hasOptionalUint64);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalUint64));
+ [msg release];
+ }
+ { // optionalUint64 :: 0
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalUint64);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalUint64));
+ msg.optionalUint64 = 0;
+ XCTAssertTrue(msg.hasOptionalUint64);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalUint64));
+ [msg release];
+ }
+
+ { // optionalSint32 :: 1
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalSint32);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSint32));
+ msg.optionalSint32 = 1;
+ XCTAssertTrue(msg.hasOptionalSint32);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSint32));
+ [msg release];
+ }
+ { // optionalSint32 :: 0
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalSint32);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSint32));
+ msg.optionalSint32 = 0;
+ XCTAssertTrue(msg.hasOptionalSint32);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSint32));
+ [msg release];
+ }
+
+ { // optionalSint64 :: 1
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalSint64);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSint64));
+ msg.optionalSint64 = 1;
+ XCTAssertTrue(msg.hasOptionalSint64);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSint64));
+ [msg release];
+ }
+ { // optionalSint64 :: 0
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalSint64);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSint64));
+ msg.optionalSint64 = 0;
+ XCTAssertTrue(msg.hasOptionalSint64);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSint64));
+ [msg release];
+ }
+
+ { // optionalFixed32 :: 1
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalFixed32);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFixed32));
+ msg.optionalFixed32 = 1;
+ XCTAssertTrue(msg.hasOptionalFixed32);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFixed32));
+ [msg release];
+ }
+ { // optionalFixed32 :: 0
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalFixed32);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFixed32));
+ msg.optionalFixed32 = 0;
+ XCTAssertTrue(msg.hasOptionalFixed32);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFixed32));
+ [msg release];
+ }
+
+ { // optionalFixed64 :: 1
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalFixed64);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFixed64));
+ msg.optionalFixed64 = 1;
+ XCTAssertTrue(msg.hasOptionalFixed64);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFixed64));
+ [msg release];
+ }
+ { // optionalFixed64 :: 0
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalFixed64);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFixed64));
+ msg.optionalFixed64 = 0;
+ XCTAssertTrue(msg.hasOptionalFixed64);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFixed64));
+ [msg release];
+ }
+
+ { // optionalSfixed32 :: 1
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalSfixed32);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSfixed32));
+ msg.optionalSfixed32 = 1;
+ XCTAssertTrue(msg.hasOptionalSfixed32);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSfixed32));
+ [msg release];
+ }
+ { // optionalSfixed32 :: 0
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalSfixed32);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSfixed32));
+ msg.optionalSfixed32 = 0;
+ XCTAssertTrue(msg.hasOptionalSfixed32);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSfixed32));
+ [msg release];
+ }
+
+ { // optionalSfixed64 :: 1
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalSfixed64);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSfixed64));
+ msg.optionalSfixed64 = 1;
+ XCTAssertTrue(msg.hasOptionalSfixed64);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSfixed64));
+ [msg release];
+ }
+ { // optionalSfixed64 :: 0
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalSfixed64);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSfixed64));
+ msg.optionalSfixed64 = 0;
+ XCTAssertTrue(msg.hasOptionalSfixed64);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSfixed64));
+ [msg release];
+ }
+
+ { // optionalFloat :: 1.0f
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalFloat);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFloat));
+ msg.optionalFloat = 1.0f;
+ XCTAssertTrue(msg.hasOptionalFloat);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFloat));
+ [msg release];
+ }
+ { // optionalFloat :: 0.0f
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalFloat);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFloat));
+ msg.optionalFloat = 0.0f;
+ XCTAssertTrue(msg.hasOptionalFloat);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFloat));
+ [msg release];
+ }
+
+ { // optionalDouble :: 1.0
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalDouble);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalDouble));
+ msg.optionalDouble = 1.0;
+ XCTAssertTrue(msg.hasOptionalDouble);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalDouble));
+ [msg release];
+ }
+ { // optionalDouble :: 0.0
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalDouble);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalDouble));
+ msg.optionalDouble = 0.0;
+ XCTAssertTrue(msg.hasOptionalDouble);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalDouble));
+ [msg release];
+ }
+
+ { // optionalBool :: YES
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalBool);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalBool));
+ msg.optionalBool = YES;
+ XCTAssertTrue(msg.hasOptionalBool);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalBool));
+ [msg release];
+ }
+ { // optionalBool :: NO
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalBool);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalBool));
+ msg.optionalBool = NO;
+ XCTAssertTrue(msg.hasOptionalBool);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalBool));
+ [msg release];
+ }
+
+ { // optionalString :: @"foo"
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalString);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalString));
+ msg.optionalString = @"foo";
+ XCTAssertTrue(msg.hasOptionalString);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalString));
+ [msg release];
+ }
+ { // optionalString :: @""
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalString);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalString));
+ msg.optionalString = @"";
+ XCTAssertTrue(msg.hasOptionalString);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalString));
+ [msg release];
+ }
+
+ { // optionalBytes :: [@"foo" dataUsingEncoding:NSUTF8StringEncoding]
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalBytes);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalBytes));
+ msg.optionalBytes = [@"foo" dataUsingEncoding:NSUTF8StringEncoding];
+ XCTAssertTrue(msg.hasOptionalBytes);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalBytes));
+ [msg release];
+ }
+ { // optionalBytes :: [NSData data]
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalBytes);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalBytes));
+ msg.optionalBytes = [NSData data];
+ XCTAssertTrue(msg.hasOptionalBytes);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalBytes));
+ [msg release];
+ }
+
+ //
+ // Test doesn't apply to optionalGroup/optionalMessage.
+ //
+
+ { // optionalEnum :: Message2_Enum_Bar
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalEnum);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalEnum));
+ msg.optionalEnum = Message2_Enum_Bar;
+ XCTAssertTrue(msg.hasOptionalEnum);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalEnum));
+ [msg release];
+ }
+ { // optionalEnum :: Message2_Enum_Foo
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalEnum);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalEnum));
+ msg.optionalEnum = Message2_Enum_Foo;
+ XCTAssertTrue(msg.hasOptionalEnum);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalEnum));
+ [msg release];
+ }
+
+//%PDDM-EXPAND-END PROTO2_TEST_HAS_FIELDS()
+}
+
+- (void)testProto3SingleFieldHasBehavior {
+ //
+ // Setting to any value including the default value (0) should result has*
+ // being true.
+ //
+
+//%PDDM-DEFINE PROTO3_TEST_HAS_FIELD(FIELD, NON_ZERO_VALUE, ZERO_VALUE)
+//% { // optional##FIELD
+//% Message3 *msg = [[Message3 alloc] init];
+//% XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_Optional##FIELD));
+//% msg.optional##FIELD = NON_ZERO_VALUE;
+//% XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_Optional##FIELD));
+//% msg.optional##FIELD = ZERO_VALUE;
+//% XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_Optional##FIELD));
+//% [msg release];
+//% }
+//%
+//%PDDM-DEFINE PROTO3_TEST_HAS_FIELDS()
+//%PROTO3_TEST_HAS_FIELD(Int32, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Int64, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Uint32, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Uint64, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Sint32, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Sint64, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Fixed32, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Fixed64, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Sfixed32, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Sfixed64, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Float, 1.0f, 0.0f)
+//%PROTO3_TEST_HAS_FIELD(Double, 1.0, 0.0)
+//%PROTO3_TEST_HAS_FIELD(Bool, YES, NO)
+//%PROTO3_TEST_HAS_FIELD(String, @"foo", @"")
+//%PROTO3_TEST_HAS_FIELD(Bytes, [@"foo" dataUsingEncoding:NSUTF8StringEncoding], [NSData data])
+//% //
+//% // Test doesn't apply to optionalGroup/optionalMessage.
+//% //
+//%
+//%PROTO3_TEST_HAS_FIELD(Enum, Message3_Enum_Bar, Message3_Enum_Foo)
+//%PDDM-EXPAND PROTO3_TEST_HAS_FIELDS()
+// This block of code is generated, do not edit it directly.
+
+ { // optionalInt32
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalInt32));
+ msg.optionalInt32 = 1;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalInt32));
+ msg.optionalInt32 = 0;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalInt32));
+ [msg release];
+ }
+
+ { // optionalInt64
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalInt64));
+ msg.optionalInt64 = 1;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalInt64));
+ msg.optionalInt64 = 0;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalInt64));
+ [msg release];
+ }
+
+ { // optionalUint32
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalUint32));
+ msg.optionalUint32 = 1;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalUint32));
+ msg.optionalUint32 = 0;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalUint32));
+ [msg release];
+ }
+
+ { // optionalUint64
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalUint64));
+ msg.optionalUint64 = 1;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalUint64));
+ msg.optionalUint64 = 0;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalUint64));
+ [msg release];
+ }
+
+ { // optionalSint32
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSint32));
+ msg.optionalSint32 = 1;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSint32));
+ msg.optionalSint32 = 0;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSint32));
+ [msg release];
+ }
+
+ { // optionalSint64
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSint64));
+ msg.optionalSint64 = 1;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSint64));
+ msg.optionalSint64 = 0;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSint64));
+ [msg release];
+ }
+
+ { // optionalFixed32
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalFixed32));
+ msg.optionalFixed32 = 1;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalFixed32));
+ msg.optionalFixed32 = 0;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalFixed32));
+ [msg release];
+ }
+
+ { // optionalFixed64
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalFixed64));
+ msg.optionalFixed64 = 1;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalFixed64));
+ msg.optionalFixed64 = 0;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalFixed64));
+ [msg release];
+ }
+
+ { // optionalSfixed32
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSfixed32));
+ msg.optionalSfixed32 = 1;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSfixed32));
+ msg.optionalSfixed32 = 0;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSfixed32));
+ [msg release];
+ }
+
+ { // optionalSfixed64
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSfixed64));
+ msg.optionalSfixed64 = 1;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSfixed64));
+ msg.optionalSfixed64 = 0;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSfixed64));
+ [msg release];
+ }
+
+ { // optionalFloat
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalFloat));
+ msg.optionalFloat = 1.0f;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalFloat));
+ msg.optionalFloat = 0.0f;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalFloat));
+ [msg release];
+ }
+
+ { // optionalDouble
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalDouble));
+ msg.optionalDouble = 1.0;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalDouble));
+ msg.optionalDouble = 0.0;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalDouble));
+ [msg release];
+ }
+
+ { // optionalBool
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalBool));
+ msg.optionalBool = YES;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalBool));
+ msg.optionalBool = NO;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalBool));
+ [msg release];
+ }
+
+ { // optionalString
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalString));
+ msg.optionalString = @"foo";
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalString));
+ msg.optionalString = @"";
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalString));
+ [msg release];
+ }
+
+ { // optionalBytes
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalBytes));
+ msg.optionalBytes = [@"foo" dataUsingEncoding:NSUTF8StringEncoding];
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalBytes));
+ msg.optionalBytes = [NSData data];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalBytes));
+ [msg release];
+ }
+
+ //
+ // Test doesn't apply to optionalGroup/optionalMessage.
+ //
+
+ { // optionalEnum
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalEnum));
+ msg.optionalEnum = Message3_Enum_Bar;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalEnum));
+ msg.optionalEnum = Message3_Enum_Foo;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalEnum));
+ [msg release];
+ }
+
+//%PDDM-EXPAND-END PROTO3_TEST_HAS_FIELDS()
+}
+
+- (void)testAccessingProto2UnknownEnumValues {
+ Message2 *msg = [[Message2 alloc] init];
+
+ // Set it to something non zero, try and confirm it doesn't change.
+
+ msg.optionalEnum = Message2_Enum_Bar;
+ XCTAssertThrowsSpecificNamed(msg.optionalEnum = 666, NSException,
+ NSInvalidArgumentException);
+ XCTAssertEqual(msg.optionalEnum, Message2_Enum_Bar);
+
+ msg.oneofEnum = Message2_Enum_Bar;
+ XCTAssertThrowsSpecificNamed(msg.oneofEnum = 666, NSException,
+ NSInvalidArgumentException);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Bar);
+}
+
+- (void)testAccessingProto3UnknownEnumValues {
+ Message3 *msg = [[Message3 alloc] init];
+
+ // Set it to something non zero, try and confirm it doesn't change.
+
+ msg.optionalEnum = Message3_Enum_Bar;
+ XCTAssertThrowsSpecificNamed(msg.optionalEnum = 666, NSException,
+ NSInvalidArgumentException);
+ XCTAssertEqual(msg.optionalEnum, Message3_Enum_Bar);
+
+ msg.oneofEnum = Message3_Enum_Bar;
+ XCTAssertThrowsSpecificNamed(msg.oneofEnum = 666, NSException,
+ NSInvalidArgumentException);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Bar);
+
+ // Set via raw api to confirm it works.
+
+ SetMessage3_OptionalEnum_RawValue(msg, 666);
+ XCTAssertEqual(msg.optionalEnum,
+ Message3_Enum_GPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual(Message3_OptionalEnum_RawValue(msg), 666);
+
+ SetMessage3_OneofEnum_RawValue(msg, 666);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_GPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual(Message3_OneofEnum_RawValue(msg), 666);
+
+ [msg release];
+}
+
+- (void)testProto2OneofBasicBehaviors {
+ Message2 *msg = [[Message2 alloc] init];
+
+ NSString *oneofStringDefault = @"string";
+ NSData *oneofBytesDefault = [@"data" dataUsingEncoding:NSUTF8StringEncoding];
+
+ // Nothing set.
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_GPBUnsetOneOfCase);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+
+ // Set, check the case, check everyone has default but the one, confirm case
+ // didn't change.
+
+ msg.oneofInt32 = 1;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofInt32);
+ XCTAssertEqual(msg.oneofInt32, 1);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofInt32);
+
+ msg.oneofInt64 = 2;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofInt64);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 2);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofInt64);
+
+ msg.oneofUint32 = 3;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofUint32);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 3U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofUint32);
+
+ msg.oneofUint64 = 4;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofUint64);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 4U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofUint64);
+
+ msg.oneofSint32 = 5;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSint32);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 5);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSint32);
+
+ msg.oneofSint64 = 6;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSint64);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 6);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSint64);
+
+ msg.oneofFixed32 = 7;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFixed32);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 7U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFixed32);
+
+ msg.oneofFixed64 = 8;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFixed64);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 8U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFixed64);
+
+ msg.oneofSfixed32 = 9;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSfixed32);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 9);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSfixed32);
+
+ msg.oneofSfixed64 = 10;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSfixed64);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 10);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSfixed64);
+
+ msg.oneofFloat = 11.0f;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFloat);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 11.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFloat);
+
+ msg.oneofDouble = 12.0;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofDouble);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 12.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofDouble);
+
+ msg.oneofBool = NO;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofBool);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofBool);
+
+ msg.oneofString = @"foo";
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofString);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, @"foo");
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofString);
+
+ msg.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofBytes);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes,
+ [@"bar" dataUsingEncoding:NSUTF8StringEncoding]);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofBytes);
+
+ Message2_OneofGroup *group = [Message2_OneofGroup message];
+ msg.oneofGroup = group;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofGroup);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertEqual(msg.oneofGroup, group); // Pointer compare.
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofGroup);
+
+ Message2 *subMessage = [Message2 message];
+ msg.oneofMessage = subMessage;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofMessage);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotEqual(msg.oneofGroup, group); // Pointer compare.
+ XCTAssertEqual(msg.oneofMessage, subMessage); // Pointer compare.
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofMessage);
+
+ msg.oneofEnum = Message2_Enum_Bar;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofEnum);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotEqual(msg.oneofGroup, group); // Pointer compare.
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertNotEqual(msg.oneofMessage, subMessage); // Pointer compare.
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Bar);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofEnum);
+
+ // Test setting/calling clear clearing.
+
+ [msg release];
+ msg = [[Message2 alloc] init];
+
+ uint32_t values[] = {
+ Message2_O_OneOfCase_OneofInt32,
+ Message2_O_OneOfCase_OneofInt64,
+ Message2_O_OneOfCase_OneofUint32,
+ Message2_O_OneOfCase_OneofUint64,
+ Message2_O_OneOfCase_OneofSint32,
+ Message2_O_OneOfCase_OneofSint64,
+ Message2_O_OneOfCase_OneofFixed32,
+ Message2_O_OneOfCase_OneofFixed64,
+ Message2_O_OneOfCase_OneofSfixed32,
+ Message2_O_OneOfCase_OneofSfixed64,
+ Message2_O_OneOfCase_OneofFloat,
+ Message2_O_OneOfCase_OneofDouble,
+ Message2_O_OneOfCase_OneofBool,
+ Message2_O_OneOfCase_OneofString,
+ Message2_O_OneOfCase_OneofBytes,
+ Message2_O_OneOfCase_OneofGroup,
+ Message2_O_OneOfCase_OneofMessage,
+ Message2_O_OneOfCase_OneofEnum,
+ };
+
+ for (size_t i = 0; i < (sizeof(values) / sizeof((values[0]))); ++i) {
+ switch (values[i]) {
+ case Message2_O_OneOfCase_OneofInt32:
+ msg.oneofInt32 = 1;
+ break;
+ case Message2_O_OneOfCase_OneofInt64:
+ msg.oneofInt64 = 2;
+ break;
+ case Message2_O_OneOfCase_OneofUint32:
+ msg.oneofUint32 = 3;
+ break;
+ case Message2_O_OneOfCase_OneofUint64:
+ msg.oneofUint64 = 4;
+ break;
+ case Message2_O_OneOfCase_OneofSint32:
+ msg.oneofSint32 = 5;
+ break;
+ case Message2_O_OneOfCase_OneofSint64:
+ msg.oneofSint64 = 6;
+ break;
+ case Message2_O_OneOfCase_OneofFixed32:
+ msg.oneofFixed32 = 7;
+ break;
+ case Message2_O_OneOfCase_OneofFixed64:
+ msg.oneofFixed64 = 8;
+ break;
+ case Message2_O_OneOfCase_OneofSfixed32:
+ msg.oneofSfixed32 = 9;
+ break;
+ case Message2_O_OneOfCase_OneofSfixed64:
+ msg.oneofSfixed64 = 10;
+ break;
+ case Message2_O_OneOfCase_OneofFloat:
+ msg.oneofFloat = 11.0f;
+ break;
+ case Message2_O_OneOfCase_OneofDouble:
+ msg.oneofDouble = 12.0;
+ break;
+ case Message2_O_OneOfCase_OneofBool:
+ msg.oneofBool = YES;
+ break;
+ case Message2_O_OneOfCase_OneofString:
+ msg.oneofString = @"foo";
+ break;
+ case Message2_O_OneOfCase_OneofBytes:
+ msg.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
+ break;
+ case Message2_O_OneOfCase_OneofGroup:
+ msg.oneofGroup = group;
+ break;
+ case Message2_O_OneOfCase_OneofMessage:
+ msg.oneofMessage = subMessage;
+ break;
+ case Message2_O_OneOfCase_OneofEnum:
+ msg.oneofEnum = Message2_Enum_Bar;
+ break;
+ default:
+ XCTFail(@"shouldn't happen, loop: %zd", i);
+ break;
+ }
+
+ XCTAssertEqual(msg.oOneOfCase, values[i], "Loop: %zd", i);
+ // No need to check the value was set, the above tests did that.
+ Message2_ClearOOneOfCase(msg);
+ // Nothing in the case.
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_GPBUnsetOneOfCase,
+ "Loop: %zd", i);
+ // Confirm everything is back to defaults after a clear.
+ XCTAssertEqual(msg.oneofInt32, 100, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofInt64, 101, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofUint32, 102U, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofUint64, 103U, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofSint32, 104, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofSint64, 105, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofFixed32, 106U, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofFixed64, 107U, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofSfixed32, 108, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofSfixed64, 109, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofFloat, 110.0f, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofDouble, 111.0, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofBool, YES, "Loop: %zd", i);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault, "Loop: %zd", i);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault, "Loop: %zd", i);
+ XCTAssertNotNil(msg.oneofGroup, "Loop: %zd", i);
+ XCTAssertNotEqual(msg.oneofGroup, group, "Loop: %zd",
+ i); // Pointer compare.
+ XCTAssertNotNil(msg.oneofMessage, "Loop: %zd", i);
+ XCTAssertNotEqual(msg.oneofMessage, subMessage, "Loop: %zd",
+ i); // Pointer compare.
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz, "Loop: %zd", i);
+ }
+
+ [msg release];
+}
+
+- (void)testProto3OneofBasicBehaviors {
+ Message3 *msg = [[Message3 alloc] init];
+
+ NSString *oneofStringDefault = @"";
+ NSData *oneofBytesDefault = [NSData data];
+
+ // Nothing set.
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_GPBUnsetOneOfCase);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+
+ // Set, check the case, check everyone has default but the one, confirm case
+ // didn't change.
+
+ msg.oneofInt32 = 1;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofInt32);
+ XCTAssertEqual(msg.oneofInt32, 1);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofInt32);
+
+ msg.oneofInt64 = 2;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofInt64);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 2);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofInt64);
+
+ msg.oneofUint32 = 3;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofUint32);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 3U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofUint32);
+
+ msg.oneofUint64 = 4;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofUint64);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 4U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofUint64);
+
+ msg.oneofSint32 = 5;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSint32);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 5);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSint32);
+
+ msg.oneofSint64 = 6;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSint64);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 6);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSint64);
+
+ msg.oneofFixed32 = 7;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFixed32);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 7U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFixed32);
+
+ msg.oneofFixed64 = 8;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFixed64);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 8U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFixed64);
+
+ msg.oneofSfixed32 = 9;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSfixed32);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 9);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSfixed32);
+
+ msg.oneofSfixed64 = 10;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSfixed64);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 10);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSfixed64);
+
+ msg.oneofFloat = 11.0f;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFloat);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 11.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFloat);
+
+ msg.oneofDouble = 12.0;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofDouble);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 12.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofDouble);
+
+ msg.oneofBool = YES;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofBool);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofBool);
+
+ msg.oneofString = @"foo";
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofString);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, @"foo");
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofString);
+
+ msg.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofBytes);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes,
+ [@"bar" dataUsingEncoding:NSUTF8StringEncoding]);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofBytes);
+
+ Message3 *subMessage = [Message3 message];
+ msg.oneofMessage = subMessage;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofMessage);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertEqual(msg.oneofMessage, subMessage); // Pointer compare.
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofMessage);
+
+ msg.oneofEnum = Message3_Enum_Bar;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofEnum);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertNotEqual(msg.oneofMessage, subMessage); // Pointer compare.
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Bar);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofEnum);
+
+ // Test setting/calling clear clearing.
+
+ [msg release];
+ msg = [[Message3 alloc] init];
+
+ uint32_t values[] = {
+ Message3_O_OneOfCase_OneofInt32,
+ Message3_O_OneOfCase_OneofInt64,
+ Message3_O_OneOfCase_OneofUint32,
+ Message3_O_OneOfCase_OneofUint64,
+ Message3_O_OneOfCase_OneofSint32,
+ Message3_O_OneOfCase_OneofSint64,
+ Message3_O_OneOfCase_OneofFixed32,
+ Message3_O_OneOfCase_OneofFixed64,
+ Message3_O_OneOfCase_OneofSfixed32,
+ Message3_O_OneOfCase_OneofSfixed64,
+ Message3_O_OneOfCase_OneofFloat,
+ Message3_O_OneOfCase_OneofDouble,
+ Message3_O_OneOfCase_OneofBool,
+ Message3_O_OneOfCase_OneofString,
+ Message3_O_OneOfCase_OneofBytes,
+ Message3_O_OneOfCase_OneofMessage,
+ Message3_O_OneOfCase_OneofEnum,
+ };
+
+ for (size_t i = 0; i < (sizeof(values) / sizeof((values[0]))); ++i) {
+ switch (values[i]) {
+ case Message3_O_OneOfCase_OneofInt32:
+ msg.oneofInt32 = 1;
+ break;
+ case Message3_O_OneOfCase_OneofInt64:
+ msg.oneofInt64 = 2;
+ break;
+ case Message3_O_OneOfCase_OneofUint32:
+ msg.oneofUint32 = 3;
+ break;
+ case Message3_O_OneOfCase_OneofUint64:
+ msg.oneofUint64 = 4;
+ break;
+ case Message3_O_OneOfCase_OneofSint32:
+ msg.oneofSint32 = 5;
+ break;
+ case Message3_O_OneOfCase_OneofSint64:
+ msg.oneofSint64 = 6;
+ break;
+ case Message3_O_OneOfCase_OneofFixed32:
+ msg.oneofFixed32 = 7;
+ break;
+ case Message3_O_OneOfCase_OneofFixed64:
+ msg.oneofFixed64 = 8;
+ break;
+ case Message3_O_OneOfCase_OneofSfixed32:
+ msg.oneofSfixed32 = 9;
+ break;
+ case Message3_O_OneOfCase_OneofSfixed64:
+ msg.oneofSfixed64 = 10;
+ break;
+ case Message3_O_OneOfCase_OneofFloat:
+ msg.oneofFloat = 11.0f;
+ break;
+ case Message3_O_OneOfCase_OneofDouble:
+ msg.oneofDouble = 12.0;
+ break;
+ case Message3_O_OneOfCase_OneofBool:
+ msg.oneofBool = YES;
+ break;
+ case Message3_O_OneOfCase_OneofString:
+ msg.oneofString = @"foo";
+ break;
+ case Message3_O_OneOfCase_OneofBytes:
+ msg.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
+ break;
+ case Message3_O_OneOfCase_OneofMessage:
+ msg.oneofMessage = subMessage;
+ break;
+ case Message3_O_OneOfCase_OneofEnum:
+ msg.oneofEnum = Message3_Enum_Baz;
+ break;
+ default:
+ XCTFail(@"shouldn't happen, loop: %zd", i);
+ break;
+ }
+
+ XCTAssertEqual(msg.oOneOfCase, values[i], "Loop: %zd", i);
+ // No need to check the value was set, the above tests did that.
+ Message3_ClearOOneOfCase(msg);
+ // Nothing in the case.
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_GPBUnsetOneOfCase,
+ "Loop: %zd", i);
+ // Confirm everything is back to defaults after a clear.
+ XCTAssertEqual(msg.oneofInt32, 0, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofInt64, 0, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofUint32, 0U, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofUint64, 0U, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofSint32, 0, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofSint64, 0, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofFixed32, 0U, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofFixed64, 0U, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofSfixed32, 0, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofSfixed64, 0, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofFloat, 0.0f, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofDouble, 0.0, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofBool, NO, "Loop: %zd", i);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault, "Loop: %zd", i);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault, "Loop: %zd", i);
+ XCTAssertNotNil(msg.oneofMessage, "Loop: %zd", i);
+ XCTAssertNotEqual(msg.oneofMessage, subMessage, "Loop: %zd",
+ i); // Pointer compare.
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo, "Loop: %zd", i);
+ }
+
+ [msg release];
+}
+
+- (void)testCopyingMakesUniqueObjects {
+ const int repeatCount = 5;
+ TestAllTypes *msg1 = [TestAllTypes message];
+ [self setAllFields:msg1 repeatedCount:repeatCount];
+
+ TestAllTypes *msg2 = [[msg1 copy] autorelease];
+
+ XCTAssertNotEqual(msg1, msg2); // Ptr compare, new object.
+ XCTAssertEqualObjects(msg1, msg2); // Equal values.
+
+ // Pointer comparisions, different objects.
+
+ XCTAssertNotEqual(msg1.optionalGroup, msg2.optionalGroup);
+ XCTAssertNotEqual(msg1.optionalNestedMessage, msg2.optionalNestedMessage);
+ XCTAssertNotEqual(msg1.optionalForeignMessage, msg2.optionalForeignMessage);
+ XCTAssertNotEqual(msg1.optionalImportMessage, msg2.optionalImportMessage);
+
+ XCTAssertNotEqual(msg1.repeatedInt32Array, msg2.repeatedInt32Array);
+ XCTAssertNotEqual(msg1.repeatedInt64Array, msg2.repeatedInt64Array);
+ XCTAssertNotEqual(msg1.repeatedUint32Array, msg2.repeatedUint32Array);
+ XCTAssertNotEqual(msg1.repeatedUint64Array, msg2.repeatedUint64Array);
+ XCTAssertNotEqual(msg1.repeatedSint32Array, msg2.repeatedSint32Array);
+ XCTAssertNotEqual(msg1.repeatedSint64Array, msg2.repeatedSint64Array);
+ XCTAssertNotEqual(msg1.repeatedFixed32Array, msg2.repeatedFixed32Array);
+ XCTAssertNotEqual(msg1.repeatedFixed64Array, msg2.repeatedFixed64Array);
+ XCTAssertNotEqual(msg1.repeatedSfixed32Array, msg2.repeatedSfixed32Array);
+ XCTAssertNotEqual(msg1.repeatedSfixed64Array, msg2.repeatedSfixed64Array);
+ XCTAssertNotEqual(msg1.repeatedFloatArray, msg2.repeatedFloatArray);
+ XCTAssertNotEqual(msg1.repeatedDoubleArray, msg2.repeatedDoubleArray);
+ XCTAssertNotEqual(msg1.repeatedBoolArray, msg2.repeatedBoolArray);
+ XCTAssertNotEqual(msg1.repeatedStringArray, msg2.repeatedStringArray);
+ XCTAssertNotEqual(msg1.repeatedBytesArray, msg2.repeatedBytesArray);
+ XCTAssertNotEqual(msg1.repeatedGroupArray, msg2.repeatedGroupArray);
+ XCTAssertNotEqual(msg1.repeatedNestedMessageArray,
+ msg2.repeatedNestedMessageArray);
+ XCTAssertNotEqual(msg1.repeatedForeignMessageArray,
+ msg2.repeatedForeignMessageArray);
+ XCTAssertNotEqual(msg1.repeatedImportMessageArray,
+ msg2.repeatedImportMessageArray);
+ XCTAssertNotEqual(msg1.repeatedNestedEnumArray, msg2.repeatedNestedEnumArray);
+ XCTAssertNotEqual(msg1.repeatedForeignEnumArray,
+ msg2.repeatedForeignEnumArray);
+ XCTAssertNotEqual(msg1.repeatedImportEnumArray, msg2.repeatedImportEnumArray);
+ XCTAssertNotEqual(msg1.repeatedStringPieceArray,
+ msg2.repeatedStringPieceArray);
+ XCTAssertNotEqual(msg1.repeatedCordArray, msg2.repeatedCordArray);
+
+ for (int i = 0; i < repeatCount; i++) {
+ XCTAssertNotEqual(msg1.repeatedNestedMessageArray[i],
+ msg2.repeatedNestedMessageArray[i]);
+ XCTAssertNotEqual(msg1.repeatedForeignMessageArray[i],
+ msg2.repeatedForeignMessageArray[i]);
+ XCTAssertNotEqual(msg1.repeatedImportMessageArray[i],
+ msg2.repeatedImportMessageArray[i]);
+ }
+}
+
+- (void)testCopyingMapsMakesUniqueObjects {
+ TestMap *msg1 = [TestMap message];
+ [self setAllMapFields:msg1 numEntries:5];
+
+ TestMap *msg2 = [[msg1 copy] autorelease];
+
+ XCTAssertNotEqual(msg1, msg2); // Ptr compare, new object.
+ XCTAssertEqualObjects(msg1, msg2); // Equal values.
+
+ // Pointer comparisions, different objects.
+ XCTAssertNotEqual(msg1.mapInt32Int32, msg2.mapInt32Int32);
+ XCTAssertNotEqual(msg1.mapInt64Int64, msg2.mapInt64Int64);
+ XCTAssertNotEqual(msg1.mapUint32Uint32, msg2.mapUint32Uint32);
+ XCTAssertNotEqual(msg1.mapUint64Uint64, msg2.mapUint64Uint64);
+ XCTAssertNotEqual(msg1.mapSint32Sint32, msg2.mapSint32Sint32);
+ XCTAssertNotEqual(msg1.mapSint64Sint64, msg2.mapSint64Sint64);
+ XCTAssertNotEqual(msg1.mapFixed32Fixed32, msg2.mapFixed32Fixed32);
+ XCTAssertNotEqual(msg1.mapFixed64Fixed64, msg2.mapFixed64Fixed64);
+ XCTAssertNotEqual(msg1.mapSfixed32Sfixed32, msg2.mapSfixed32Sfixed32);
+ XCTAssertNotEqual(msg1.mapSfixed64Sfixed64, msg2.mapSfixed64Sfixed64);
+ XCTAssertNotEqual(msg1.mapInt32Float, msg2.mapInt32Float);
+ XCTAssertNotEqual(msg1.mapInt32Double, msg2.mapInt32Double);
+ XCTAssertNotEqual(msg1.mapBoolBool, msg2.mapBoolBool);
+ XCTAssertNotEqual(msg1.mapStringString, msg2.mapStringString);
+ XCTAssertNotEqual(msg1.mapInt32Bytes, msg2.mapInt32Bytes);
+ XCTAssertNotEqual(msg1.mapInt32Enum, msg2.mapInt32Enum);
+ XCTAssertNotEqual(msg1.mapInt32ForeignMessage, msg2.mapInt32ForeignMessage);
+
+ // Ensure the messages are unique per map.
+ [msg1.mapInt32ForeignMessage
+ enumerateKeysAndValuesUsingBlock:^(int32_t key, id value, BOOL *stop) {
+#pragma unused(stop)
+ ForeignMessage *subMsg2 = [msg2.mapInt32ForeignMessage valueForKey:key];
+ XCTAssertNotEqual(value, subMsg2); // Ptr compare, new object.
+ }];
+}
+
+#pragma mark - Subset from from map_tests.cc
+
+// TEST(GeneratedMapFieldTest, IsInitialized)
+- (void)testMap_IsInitialized {
+ TestRequiredMessageMap *msg = [[TestRequiredMessageMap alloc] init];
+
+ // Add an uninitialized message.
+ TestRequired *subMsg = [[TestRequired alloc] init];
+ msg.mapField = [GPBInt32ObjectDictionary dictionary];
+ [msg.mapField setValue:subMsg forKey:0];
+ XCTAssertFalse(msg.initialized);
+
+ // Initialize uninitialized message
+ subMsg.a = 0;
+ subMsg.b = 0;
+ subMsg.c = 0;
+ XCTAssertTrue(msg.initialized);
+
+ [subMsg release];
+ [msg release];
+}
+
+@end
diff --git a/objectivec/Tests/GPBMessageTests+Serialization.m b/objectivec/Tests/GPBMessageTests+Serialization.m
new file mode 100644
index 00000000..ddc2ae19
--- /dev/null
+++ b/objectivec/Tests/GPBMessageTests+Serialization.m
@@ -0,0 +1,838 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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 "GPBTestUtilities.h"
+
+#import <objc/runtime.h>
+
+#import "GPBMessage.h"
+
+#import "google/protobuf/MapProto2Unittest.pbobjc.h"
+#import "google/protobuf/MapUnittest.pbobjc.h"
+#import "google/protobuf/UnittestDropUnknownFields.pbobjc.h"
+#import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.h"
+#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+#import "google/protobuf/UnittestRuntimeProto3.pbobjc.h"
+
+#ifndef GPBARRAYSIZE
+#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))))
+#endif // GPBARRAYSIZE
+
+static NSData *DataFromCStr(const char *str) {
+ return [NSData dataWithBytes:str length:strlen(str)];
+}
+
+@interface MessageSerializationTests : GPBTestCase
+@end
+
+@implementation MessageSerializationTests
+
+// TODO(thomasvl): Pull tests over from GPBMessageTests that are serialization
+// specific.
+
+- (void)testProto3SerializationHandlingDefaults {
+ // Proto2 covered in other tests.
+
+ Message3 *msg = [[Message3 alloc] init];
+
+ // Add defaults, no output.
+
+ NSData *data = [msg data];
+ XCTAssertEqual([data length], 0U);
+
+ // All zeros, still nothing.
+
+ msg.optionalInt32 = 0;
+ msg.optionalInt64 = 0;
+ msg.optionalUint32 = 0;
+ msg.optionalUint64 = 0;
+ msg.optionalSint32 = 0;
+ msg.optionalSint64 = 0;
+ msg.optionalFixed32 = 0;
+ msg.optionalFixed64 = 0;
+ msg.optionalSfixed32 = 0;
+ msg.optionalSfixed64 = 0;
+ msg.optionalFloat = 0.0f;
+ msg.optionalDouble = 0.0;
+ msg.optionalBool = NO;
+ msg.optionalString = @"";
+ msg.optionalBytes = [NSData data];
+ msg.optionalEnum = Message3_Enum_Foo; // first value
+
+ data = [msg data];
+ XCTAssertEqual([data length], 0U);
+
+ // The two that also take nil as nothing.
+
+ msg.optionalString = nil;
+ msg.optionalBytes = nil;
+
+ data = [msg data];
+ XCTAssertEqual([data length], 0U);
+
+ // Set one field...
+
+ msg.optionalInt32 = 1;
+
+ data = [msg data];
+ const uint8_t expectedBytes[] = {0x08, 0x01};
+ NSData *expected = [NSData dataWithBytes:expectedBytes length:2];
+ XCTAssertEqualObjects(data, expected);
+
+ // Back to zero...
+
+ msg.optionalInt32 = 0;
+
+ data = [msg data];
+ XCTAssertEqual([data length], 0U);
+
+ [msg release];
+}
+
+- (void)testProto3DroppingUnknownFields {
+ DropUnknownsFooWithExtraFields *fooWithExtras =
+ [[DropUnknownsFooWithExtraFields alloc] init];
+
+ fooWithExtras.int32Value = 1;
+ fooWithExtras.enumValue = DropUnknownsFooWithExtraFields_NestedEnum_Baz;
+ fooWithExtras.extraInt32Value = 2;
+
+ DropUnknownsFoo *foo = [DropUnknownsFoo parseFromData:[fooWithExtras data]];
+
+ XCTAssertEqual(foo.int32Value, 1);
+ XCTAssertEqual(foo.enumValue, DropUnknownsFoo_NestedEnum_Baz);
+ // Nothing should end up in the unknowns.
+ XCTAssertEqual([foo.unknownFields countOfFields], 0U);
+
+ [fooWithExtras release];
+ fooWithExtras = [DropUnknownsFooWithExtraFields parseFromData:[foo data]];
+ XCTAssertEqual(fooWithExtras.int32Value, 1);
+ XCTAssertEqual(fooWithExtras.enumValue,
+ DropUnknownsFooWithExtraFields_NestedEnum_Baz);
+ // And the extra value is gone (back to the default).
+ XCTAssertEqual(fooWithExtras.extraInt32Value, 0);
+ XCTAssertEqual([foo.unknownFields countOfFields], 0U);
+}
+
+- (void)testProto2UnknownEnumToUnknownField {
+ Message3 *orig = [[Message3 alloc] init];
+
+ orig.optionalEnum = Message3_Enum_Extra3;
+ orig.repeatedEnumArray =
+ [GPBEnumArray arrayWithValidationFunction:Message3_Enum_IsValidValue
+ rawValue:Message3_Enum_Extra3];
+ orig.repeatedPackedEnumArray =
+ [GPBEnumArray arrayWithValidationFunction:Message3_Enum_IsValidValue
+ rawValue:Message3_Enum_Extra3];
+ orig.oneofEnum = Message3_Enum_Extra3;
+
+ Message2 *msg = [[Message2 alloc] initWithData:[orig data]];
+
+ // None of the fields should be set.
+
+ XCTAssertFalse(msg.hasOptionalEnum);
+ XCTAssertEqual(msg.repeatedEnumArray.count, 0U);
+ XCTAssertEqual(msg.repeatedPackedEnumArray.count, 0U);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_GPBUnsetOneOfCase);
+
+ // All the values should be in unknown fields.
+
+ GPBUnknownFieldSet *unknownFields = msg.unknownFields;
+
+ XCTAssertEqual([unknownFields countOfFields], 4U);
+ XCTAssertTrue([unknownFields hasField:Message2_FieldNumber_OptionalEnum]);
+ XCTAssertTrue(
+ [unknownFields hasField:Message2_FieldNumber_RepeatedEnumArray]);
+ XCTAssertTrue(
+ [unknownFields hasField:Message2_FieldNumber_RepeatedPackedEnumArray]);
+ XCTAssertTrue([unknownFields hasField:Message2_FieldNumber_OneofEnum]);
+
+ GPBField *field = [unknownFields getField:Message2_FieldNumber_OptionalEnum];
+ XCTAssertEqual(field.varintList.count, 1U);
+ XCTAssertEqual([field.varintList valueAtIndex:0],
+ (uint64_t)Message3_Enum_Extra3);
+
+ field = [unknownFields getField:Message2_FieldNumber_RepeatedEnumArray];
+ XCTAssertEqual(field.varintList.count, 1U);
+ XCTAssertEqual([field.varintList valueAtIndex:0],
+ (uint64_t)Message3_Enum_Extra3);
+
+ field = [unknownFields getField:Message2_FieldNumber_RepeatedPackedEnumArray];
+ XCTAssertEqual(field.varintList.count, 1U);
+ XCTAssertEqual([field.varintList valueAtIndex:0],
+ (uint64_t)Message3_Enum_Extra3);
+
+ field = [unknownFields getField:Message2_FieldNumber_OneofEnum];
+ XCTAssertEqual(field.varintList.count, 1U);
+ XCTAssertEqual([field.varintList valueAtIndex:0],
+ (uint64_t)Message3_Enum_Extra3);
+
+ [msg release];
+ [orig release];
+}
+
+- (void)testProto3UnknownEnumPreserving {
+ UnknownEnumsMyMessagePlusExtra *orig =
+ [UnknownEnumsMyMessagePlusExtra message];
+
+ orig.e = UnknownEnumsMyEnumPlusExtra_EExtra;
+ orig.repeatedEArray = [GPBEnumArray
+ arrayWithValidationFunction:UnknownEnumsMyEnumPlusExtra_IsValidValue
+ rawValue:UnknownEnumsMyEnumPlusExtra_EExtra];
+ orig.repeatedPackedEArray = [GPBEnumArray
+ arrayWithValidationFunction:UnknownEnumsMyEnumPlusExtra_IsValidValue
+ rawValue:UnknownEnumsMyEnumPlusExtra_EExtra];
+ orig.oneofE1 = UnknownEnumsMyEnumPlusExtra_EExtra;
+
+ // Everything should be there via raw values.
+
+ UnknownEnumsMyMessage *msg =
+ [UnknownEnumsMyMessage parseFromData:[orig data]];
+
+ XCTAssertEqual(msg.e, UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual(UnknownEnumsMyMessage_E_RawValue(msg),
+ UnknownEnumsMyEnumPlusExtra_EExtra);
+ XCTAssertEqual(msg.repeatedEArray.count, 1U);
+ XCTAssertEqual([msg.repeatedEArray valueAtIndex:0],
+ UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual([msg.repeatedEArray rawValueAtIndex:0],
+ (UnknownEnumsMyEnum)UnknownEnumsMyEnumPlusExtra_EExtra);
+ XCTAssertEqual(msg.repeatedPackedEArray.count, 1U);
+ XCTAssertEqual([msg.repeatedPackedEArray valueAtIndex:0],
+ UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual([msg.repeatedPackedEArray rawValueAtIndex:0],
+ (UnknownEnumsMyEnum)UnknownEnumsMyEnumPlusExtra_EExtra);
+ XCTAssertEqual(msg.oneofE1,
+ UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual(UnknownEnumsMyMessage_OneofE1_RawValue(msg),
+ UnknownEnumsMyEnumPlusExtra_EExtra);
+
+ // Everything should go out and come back.
+
+ orig = [UnknownEnumsMyMessagePlusExtra parseFromData:[msg data]];
+
+ XCTAssertEqual(orig.e, UnknownEnumsMyEnumPlusExtra_EExtra);
+ XCTAssertEqual(orig.repeatedEArray.count, 1U);
+ XCTAssertEqual([orig.repeatedEArray valueAtIndex:0],
+ UnknownEnumsMyEnumPlusExtra_EExtra);
+ XCTAssertEqual(orig.repeatedPackedEArray.count, 1U);
+ XCTAssertEqual([orig.repeatedPackedEArray valueAtIndex:0],
+ UnknownEnumsMyEnumPlusExtra_EExtra);
+ XCTAssertEqual(orig.oneofE1, UnknownEnumsMyEnumPlusExtra_EExtra);
+}
+
+//%PDDM-DEFINE TEST_ROUNDTRIP_ONEOF(MESSAGE, FIELD, VALUE)
+//%TEST_ROUNDTRIP_ONEOF_ADV(MESSAGE, FIELD, VALUE, )
+//%PDDM-DEFINE TEST_ROUNDTRIP_ONEOF_ADV(MESSAGE, FIELD, VALUE, EQ_SUFFIX)
+//% { // oneof##FIELD
+//% MESSAGE *orig = [[MESSAGE alloc] init];
+//% orig.oneof##FIELD = VALUE;
+//% XCTAssertEqual(orig.oOneOfCase, MESSAGE##_O_OneOfCase_Oneof##FIELD);
+//% MESSAGE *msg = [MESSAGE parseFromData:[orig data]];
+//% XCTAssertEqual(msg.oOneOfCase, MESSAGE##_O_OneOfCase_Oneof##FIELD);
+//% XCTAssertEqual##EQ_SUFFIX(msg.oneof##FIELD, VALUE);
+//% [orig release];
+//% }
+//%
+//%PDDM-DEFINE TEST_ROUNDTRIP_ONEOFS(SYNTAX, BOOL_NON_DEFAULT)
+//%- (void)testProto##SYNTAX##RoundTripOneof {
+//%
+//%GROUP_INIT##SYNTAX() Message##SYNTAX *subMessage = [[Message##SYNTAX alloc] init];
+//% XCTAssertNotNil(subMessage);
+//% subMessage.optionalInt32 = 666;
+//%
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Int32, 1)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Int64, 2)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Uint32, 3U)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Uint64, 4U)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Sint32, 5)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Sint64, 6)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Fixed32, 7U)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Fixed64, 8U)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Sfixed32, 9)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Sfixed64, 10)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Float, 11.0f)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Double, 12.0)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Bool, BOOL_NON_DEFAULT)
+//%TEST_ROUNDTRIP_ONEOF_ADV(Message##SYNTAX, String, @"foo", Objects)
+//%TEST_ROUNDTRIP_ONEOF_ADV(Message##SYNTAX, Bytes, [@"bar" dataUsingEncoding:NSUTF8StringEncoding], Objects)
+//%GROUP_TEST##SYNTAX()TEST_ROUNDTRIP_ONEOF_ADV(Message##SYNTAX, Message, subMessage, Objects)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Enum, Message2_Enum_Bar)
+//%GROUP_CLEANUP##SYNTAX() [subMessage release];
+//%}
+//%
+//%PDDM-DEFINE GROUP_INIT2()
+//% Message2_OneofGroup *group = [[Message2_OneofGroup alloc] init];
+//% XCTAssertNotNil(group);
+//% group.a = 777;
+//%
+//%PDDM-DEFINE GROUP_CLEANUP2()
+//% [group release];
+//%
+//%PDDM-DEFINE GROUP_TEST2()
+//%TEST_ROUNDTRIP_ONEOF_ADV(Message2, Group, group, Objects)
+//%
+//%PDDM-DEFINE GROUP_INIT3()
+// Empty
+//%PDDM-DEFINE GROUP_CLEANUP3()
+// Empty
+//%PDDM-DEFINE GROUP_TEST3()
+//% // Not "group" in proto3.
+//%
+//%
+//%PDDM-EXPAND TEST_ROUNDTRIP_ONEOFS(2, NO)
+// This block of code is generated, do not edit it directly.
+
+- (void)testProto2RoundTripOneof {
+
+ Message2_OneofGroup *group = [[Message2_OneofGroup alloc] init];
+ XCTAssertNotNil(group);
+ group.a = 777;
+ Message2 *subMessage = [[Message2 alloc] init];
+ XCTAssertNotNil(subMessage);
+ subMessage.optionalInt32 = 666;
+
+ { // oneofInt32
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofInt32 = 1;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofInt32);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofInt32);
+ XCTAssertEqual(msg.oneofInt32, 1);
+ [orig release];
+ }
+
+ { // oneofInt64
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofInt64 = 2;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofInt64);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofInt64);
+ XCTAssertEqual(msg.oneofInt64, 2);
+ [orig release];
+ }
+
+ { // oneofUint32
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofUint32 = 3U;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofUint32);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofUint32);
+ XCTAssertEqual(msg.oneofUint32, 3U);
+ [orig release];
+ }
+
+ { // oneofUint64
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofUint64 = 4U;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofUint64);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofUint64);
+ XCTAssertEqual(msg.oneofUint64, 4U);
+ [orig release];
+ }
+
+ { // oneofSint32
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofSint32 = 5;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofSint32);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSint32);
+ XCTAssertEqual(msg.oneofSint32, 5);
+ [orig release];
+ }
+
+ { // oneofSint64
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofSint64 = 6;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofSint64);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSint64);
+ XCTAssertEqual(msg.oneofSint64, 6);
+ [orig release];
+ }
+
+ { // oneofFixed32
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofFixed32 = 7U;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofFixed32);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFixed32);
+ XCTAssertEqual(msg.oneofFixed32, 7U);
+ [orig release];
+ }
+
+ { // oneofFixed64
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofFixed64 = 8U;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofFixed64);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFixed64);
+ XCTAssertEqual(msg.oneofFixed64, 8U);
+ [orig release];
+ }
+
+ { // oneofSfixed32
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofSfixed32 = 9;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofSfixed32);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSfixed32);
+ XCTAssertEqual(msg.oneofSfixed32, 9);
+ [orig release];
+ }
+
+ { // oneofSfixed64
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofSfixed64 = 10;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofSfixed64);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSfixed64);
+ XCTAssertEqual(msg.oneofSfixed64, 10);
+ [orig release];
+ }
+
+ { // oneofFloat
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofFloat = 11.0f;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofFloat);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFloat);
+ XCTAssertEqual(msg.oneofFloat, 11.0f);
+ [orig release];
+ }
+
+ { // oneofDouble
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofDouble = 12.0;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofDouble);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofDouble);
+ XCTAssertEqual(msg.oneofDouble, 12.0);
+ [orig release];
+ }
+
+ { // oneofBool
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofBool = NO;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofBool);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofBool);
+ XCTAssertEqual(msg.oneofBool, NO);
+ [orig release];
+ }
+
+ { // oneofString
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofString = @"foo";
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofString);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofString);
+ XCTAssertEqualObjects(msg.oneofString, @"foo");
+ [orig release];
+ }
+
+ { // oneofBytes
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofBytes);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofBytes);
+ XCTAssertEqualObjects(msg.oneofBytes, [@"bar" dataUsingEncoding:NSUTF8StringEncoding]);
+ [orig release];
+ }
+
+ { // oneofGroup
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofGroup = group;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofGroup);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofGroup);
+ XCTAssertEqualObjects(msg.oneofGroup, group);
+ [orig release];
+ }
+
+ { // oneofMessage
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofMessage = subMessage;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofMessage);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofMessage);
+ XCTAssertEqualObjects(msg.oneofMessage, subMessage);
+ [orig release];
+ }
+
+ { // oneofEnum
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofEnum = Message2_Enum_Bar;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofEnum);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofEnum);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Bar);
+ [orig release];
+ }
+
+ [group release];
+ [subMessage release];
+}
+
+//%PDDM-EXPAND TEST_ROUNDTRIP_ONEOFS(3, YES)
+// This block of code is generated, do not edit it directly.
+
+- (void)testProto3RoundTripOneof {
+
+ Message3 *subMessage = [[Message3 alloc] init];
+ XCTAssertNotNil(subMessage);
+ subMessage.optionalInt32 = 666;
+
+ { // oneofInt32
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofInt32 = 1;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofInt32);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofInt32);
+ XCTAssertEqual(msg.oneofInt32, 1);
+ [orig release];
+ }
+
+ { // oneofInt64
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofInt64 = 2;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofInt64);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofInt64);
+ XCTAssertEqual(msg.oneofInt64, 2);
+ [orig release];
+ }
+
+ { // oneofUint32
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofUint32 = 3U;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofUint32);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofUint32);
+ XCTAssertEqual(msg.oneofUint32, 3U);
+ [orig release];
+ }
+
+ { // oneofUint64
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofUint64 = 4U;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofUint64);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofUint64);
+ XCTAssertEqual(msg.oneofUint64, 4U);
+ [orig release];
+ }
+
+ { // oneofSint32
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofSint32 = 5;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofSint32);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSint32);
+ XCTAssertEqual(msg.oneofSint32, 5);
+ [orig release];
+ }
+
+ { // oneofSint64
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofSint64 = 6;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofSint64);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSint64);
+ XCTAssertEqual(msg.oneofSint64, 6);
+ [orig release];
+ }
+
+ { // oneofFixed32
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofFixed32 = 7U;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofFixed32);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFixed32);
+ XCTAssertEqual(msg.oneofFixed32, 7U);
+ [orig release];
+ }
+
+ { // oneofFixed64
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofFixed64 = 8U;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofFixed64);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFixed64);
+ XCTAssertEqual(msg.oneofFixed64, 8U);
+ [orig release];
+ }
+
+ { // oneofSfixed32
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofSfixed32 = 9;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofSfixed32);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSfixed32);
+ XCTAssertEqual(msg.oneofSfixed32, 9);
+ [orig release];
+ }
+
+ { // oneofSfixed64
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofSfixed64 = 10;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofSfixed64);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSfixed64);
+ XCTAssertEqual(msg.oneofSfixed64, 10);
+ [orig release];
+ }
+
+ { // oneofFloat
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofFloat = 11.0f;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofFloat);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFloat);
+ XCTAssertEqual(msg.oneofFloat, 11.0f);
+ [orig release];
+ }
+
+ { // oneofDouble
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofDouble = 12.0;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofDouble);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofDouble);
+ XCTAssertEqual(msg.oneofDouble, 12.0);
+ [orig release];
+ }
+
+ { // oneofBool
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofBool = YES;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofBool);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofBool);
+ XCTAssertEqual(msg.oneofBool, YES);
+ [orig release];
+ }
+
+ { // oneofString
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofString = @"foo";
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofString);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofString);
+ XCTAssertEqualObjects(msg.oneofString, @"foo");
+ [orig release];
+ }
+
+ { // oneofBytes
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofBytes);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofBytes);
+ XCTAssertEqualObjects(msg.oneofBytes, [@"bar" dataUsingEncoding:NSUTF8StringEncoding]);
+ [orig release];
+ }
+
+ // Not "group" in proto3.
+
+ { // oneofMessage
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofMessage = subMessage;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofMessage);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofMessage);
+ XCTAssertEqualObjects(msg.oneofMessage, subMessage);
+ [orig release];
+ }
+
+ { // oneofEnum
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofEnum = Message2_Enum_Bar;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofEnum);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofEnum);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Bar);
+ [orig release];
+ }
+
+ [subMessage release];
+}
+
+//%PDDM-EXPAND-END (2 expansions)
+
+#pragma mark - Subset from from map_tests.cc
+
+// TEST(GeneratedMapFieldTest, StandardWireFormat)
+- (void)testMap_StandardWireFormat {
+ NSData *data = DataFromCStr("\x0A\x04\x08\x01\x10\x01");
+
+ TestMap *msg = [[TestMap alloc] initWithData:data];
+ XCTAssertEqual(msg.mapInt32Int32.count, 1U);
+ int32_t val = 666;
+ XCTAssertTrue([msg.mapInt32Int32 valueForKey:1 value:&val]);
+ XCTAssertEqual(val, 1);
+
+ [msg release];
+}
+
+// TEST(GeneratedMapFieldTest, UnorderedWireFormat)
+- (void)testMap_UnorderedWireFormat {
+ // put value before key in wire format
+ NSData *data = DataFromCStr("\x0A\x04\x10\x01\x08\x02");
+
+ TestMap *msg = [[TestMap alloc] initWithData:data];
+ XCTAssertEqual(msg.mapInt32Int32.count, 1U);
+ int32_t val = 666;
+ XCTAssertTrue([msg.mapInt32Int32 valueForKey:2 value:&val]);
+ XCTAssertEqual(val, 1);
+
+ [msg release];
+}
+
+// TEST(GeneratedMapFieldTest, DuplicatedKeyWireFormat)
+- (void)testMap_DuplicatedKeyWireFormat {
+ // Two key fields in wire format
+ NSData *data = DataFromCStr("\x0A\x06\x08\x01\x08\x02\x10\x01");
+
+ TestMap *msg = [[TestMap alloc] initWithData:data];
+ XCTAssertEqual(msg.mapInt32Int32.count, 1U);
+ int32_t val = 666;
+ XCTAssertTrue([msg.mapInt32Int32 valueForKey:2 value:&val]);
+ XCTAssertEqual(val, 1);
+
+ [msg release];
+}
+
+// TEST(GeneratedMapFieldTest, DuplicatedValueWireFormat)
+- (void)testMap_DuplicatedValueWireFormat {
+ // Two value fields in wire format
+ NSData *data = DataFromCStr("\x0A\x06\x08\x01\x10\x01\x10\x02");
+
+ TestMap *msg = [[TestMap alloc] initWithData:data];
+ XCTAssertEqual(msg.mapInt32Int32.count, 1U);
+ int32_t val = 666;
+ XCTAssertTrue([msg.mapInt32Int32 valueForKey:1 value:&val]);
+ XCTAssertEqual(val, 2);
+
+ [msg release];
+}
+
+// TEST(GeneratedMapFieldTest, MissedKeyWireFormat)
+- (void)testMap_MissedKeyWireFormat {
+ // No key field in wire format
+ NSData *data = DataFromCStr("\x0A\x02\x10\x01");
+
+ TestMap *msg = [[TestMap alloc] initWithData:data];
+ XCTAssertEqual(msg.mapInt32Int32.count, 1U);
+ int32_t val = 666;
+ XCTAssertTrue([msg.mapInt32Int32 valueForKey:0 value:&val]);
+ XCTAssertEqual(val, 1);
+
+ [msg release];
+}
+
+// TEST(GeneratedMapFieldTest, MissedValueWireFormat)
+- (void)testMap_MissedValueWireFormat {
+ // No value field in wire format
+ NSData *data = DataFromCStr("\x0A\x02\x08\x01");
+
+ TestMap *msg = [[TestMap alloc] initWithData:data];
+ XCTAssertEqual(msg.mapInt32Int32.count, 1U);
+ int32_t val = 666;
+ XCTAssertTrue([msg.mapInt32Int32 valueForKey:1 value:&val]);
+ XCTAssertEqual(val, 0);
+
+ [msg release];
+}
+
+// TEST(GeneratedMapFieldTest, UnknownFieldWireFormat)
+- (void)testMap_UnknownFieldWireFormat {
+ // Unknown field in wire format
+ NSData *data = DataFromCStr("\x0A\x06\x08\x02\x10\x03\x18\x01");
+
+ TestMap *msg = [[TestMap alloc] initWithData:data];
+ XCTAssertEqual(msg.mapInt32Int32.count, 1U);
+ int32_t val = 666;
+ XCTAssertTrue([msg.mapInt32Int32 valueForKey:2 value:&val]);
+ XCTAssertEqual(val, 3);
+
+ [msg release];
+}
+
+// TEST(GeneratedMapFieldTest, CorruptedWireFormat)
+- (void)testMap_CorruptedWireFormat {
+ // corrupted data in wire format
+ NSData *data = DataFromCStr("\x0A\x06\x08\x02\x11\x03");
+
+ XCTAssertThrowsSpecificNamed([TestMap parseFromData:data], NSException,
+ NSParseErrorException);
+}
+
+// TEST(GeneratedMapFieldTest, Proto2UnknownEnum)
+- (void)testMap_Proto2UnknownEnum {
+ TestEnumMapPlusExtra *orig = [[TestEnumMapPlusExtra alloc] init];
+
+ orig.knownMapField = [GPBInt32EnumDictionary
+ dictionaryWithValidationFunction:Proto2MapEnumPlusExtra_IsValidValue];
+ orig.unknownMapField = [GPBInt32EnumDictionary
+ dictionaryWithValidationFunction:Proto2MapEnumPlusExtra_IsValidValue];
+ [orig.knownMapField setValue:Proto2MapEnumPlusExtra_EProto2MapEnumFoo
+ forKey:0];
+ [orig.unknownMapField setValue:Proto2MapEnumPlusExtra_EProto2MapEnumExtra
+ forKey:0];
+
+ TestEnumMap *msg1 = [TestEnumMap parseFromData:[orig data]];
+ XCTAssertEqual(msg1.knownMapField.count, 1U);
+ int32_t val = -1;
+ XCTAssertTrue([msg1.knownMapField valueForKey:0 value:&val]);
+ XCTAssertEqual(val, Proto2MapEnum_Proto2MapEnumFoo);
+ XCTAssertEqual(msg1.unknownFields.countOfFields, 1U);
+
+ TestEnumMapPlusExtra *msg2 = [TestEnumMapPlusExtra parseFromData:[msg1 data]];
+ val = -1;
+ XCTAssertEqual(msg2.knownMapField.count, 1U);
+ XCTAssertTrue([msg2.knownMapField valueForKey:0 value:&val]);
+ XCTAssertEqual(val, Proto2MapEnumPlusExtra_EProto2MapEnumFoo);
+ val = -1;
+ XCTAssertEqual(msg2.unknownMapField.count, 1U);
+ XCTAssertTrue([msg2.unknownMapField valueForKey:0 value:&val]);
+ XCTAssertEqual(val, Proto2MapEnumPlusExtra_EProto2MapEnumExtra);
+ XCTAssertEqual(msg2.unknownFields.countOfFields, 0U);
+
+ XCTAssertEqualObjects(orig, msg2);
+
+ [orig release];
+}
+
+#pragma mark -
+
+@end
diff --git a/objectivec/Tests/GPBMessageTests.m b/objectivec/Tests/GPBMessageTests.m
new file mode 100644
index 00000000..5ec67cd9
--- /dev/null
+++ b/objectivec/Tests/GPBMessageTests.m
@@ -0,0 +1,1728 @@
+// 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.
+
+#import "GPBTestUtilities.h"
+
+#import <objc/runtime.h>
+
+#import "GPBArray_PackagePrivate.h"
+#import "GPBDescriptor.h"
+#import "GPBField_PackagePrivate.h"
+#import "GPBMessage_PackagePrivate.h"
+#import "GPBUnknownFieldSet_PackagePrivate.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+#import "google/protobuf/UnittestObjc.pbobjc.h"
+#import "google/protobuf/UnittestNameMangling.pbobjc.h"
+
+@interface MessageTests : GPBTestCase
+@end
+
+@implementation MessageTests
+
+// TODO(thomasvl): this should get split into a few files of logic junks, it is
+// a jumble
+// of things at the moment (and the testutils have a bunch of the real
+// assertions).
+
+#ifdef DEBUG
+- (void)assertBlock:(void (^)())block
+ throwsWithMessageInUserInfo:(GPBMessage *)message {
+ @try {
+ block();
+ XCTAssertTrue(NO);
+ }
+ @catch (NSException *e) {
+ XCTAssertEqualObjects([e userInfo][GPBExceptionMessageKey], message);
+ }
+}
+#endif // DEBUG
+
+- (TestAllTypes *)mergeSource {
+ TestAllTypes *message = [TestAllTypes message];
+ [message setOptionalInt32:1];
+ [message setOptionalString:@"foo"];
+ [message setOptionalForeignMessage:[ForeignMessage message]];
+ message.repeatedStringArray = [NSMutableArray array];
+ [message.repeatedStringArray addObject:@"bar"];
+ return message;
+}
+
+- (TestAllTypes *)mergeDestination {
+ TestAllTypes *message = [TestAllTypes message];
+ [message setOptionalInt64:2];
+ [message setOptionalString:@"baz"];
+ ForeignMessage *foreignMessage = [ForeignMessage message];
+ [foreignMessage setC:3];
+ [message setOptionalForeignMessage:foreignMessage];
+ message.repeatedStringArray = [NSMutableArray array];
+ [message.repeatedStringArray addObject:@"qux"];
+ return message;
+}
+
+- (TestAllTypes *)mergeDestinationWithoutForeignMessageIvar {
+ TestAllTypes *message = [TestAllTypes message];
+ [message setOptionalInt64:2];
+ [message setOptionalString:@"baz"];
+ message.repeatedStringArray = [NSMutableArray array];
+ [message.repeatedStringArray addObject:@"qux"];
+ return message;
+}
+
+- (TestAllTypes *)mergeResult {
+ TestAllTypes *message = [TestAllTypes message];
+ [message setOptionalInt32:1];
+ [message setOptionalInt64:2];
+ [message setOptionalString:@"foo"];
+ ForeignMessage *foreignMessage = [ForeignMessage message];
+ [foreignMessage setC:3];
+ [message setOptionalForeignMessage:foreignMessage];
+ message.repeatedStringArray = [NSMutableArray array];
+ [message.repeatedStringArray addObject:@"qux"];
+ [message.repeatedStringArray addObject:@"bar"];
+ return message;
+}
+
+- (TestAllTypes *)mergeResultForDestinationWithoutForeignMessageIvar {
+ TestAllTypes *message = [TestAllTypes message];
+ [message setOptionalInt32:1];
+ [message setOptionalInt64:2];
+ [message setOptionalString:@"foo"];
+ ForeignMessage *foreignMessage = [ForeignMessage message];
+ [message setOptionalForeignMessage:foreignMessage];
+ message.repeatedStringArray = [NSMutableArray array];
+ [message.repeatedStringArray addObject:@"qux"];
+ [message.repeatedStringArray addObject:@"bar"];
+ return message;
+}
+
+- (TestAllExtensions *)mergeExtensionsDestination {
+ TestAllExtensions *message = [TestAllExtensions message];
+ [message setExtension:[UnittestRoot optionalInt32Extension] value:@5];
+ [message setExtension:[UnittestRoot optionalStringExtension] value:@"foo"];
+ ForeignMessage *foreignMessage = [ForeignMessage message];
+ foreignMessage.c = 4;
+ [message setExtension:[UnittestRoot optionalForeignMessageExtension]
+ value:foreignMessage];
+ TestAllTypes_NestedMessage *nestedMessage =
+ [TestAllTypes_NestedMessage message];
+ [message setExtension:[UnittestRoot optionalNestedMessageExtension]
+ value:nestedMessage];
+ return message;
+}
+
+- (TestAllExtensions *)mergeExtensionsSource {
+ TestAllExtensions *message = [TestAllExtensions message];
+ [message setExtension:[UnittestRoot optionalInt64Extension] value:@6];
+ [message setExtension:[UnittestRoot optionalStringExtension] value:@"bar"];
+ ForeignMessage *foreignMessage = [ForeignMessage message];
+ [message setExtension:[UnittestRoot optionalForeignMessageExtension]
+ value:foreignMessage];
+ TestAllTypes_NestedMessage *nestedMessage =
+ [TestAllTypes_NestedMessage message];
+ nestedMessage.bb = 7;
+ [message setExtension:[UnittestRoot optionalNestedMessageExtension]
+ value:nestedMessage];
+ return message;
+}
+
+- (TestAllExtensions *)mergeExtensionsResult {
+ TestAllExtensions *message = [TestAllExtensions message];
+ [message setExtension:[UnittestRoot optionalInt32Extension] value:@5];
+ [message setExtension:[UnittestRoot optionalInt64Extension] value:@6];
+ [message setExtension:[UnittestRoot optionalStringExtension] value:@"bar"];
+ ForeignMessage *foreignMessage = [ForeignMessage message];
+ foreignMessage.c = 4;
+ [message setExtension:[UnittestRoot optionalForeignMessageExtension]
+ value:foreignMessage];
+ TestAllTypes_NestedMessage *nestedMessage =
+ [TestAllTypes_NestedMessage message];
+ nestedMessage.bb = 7;
+ [message setExtension:[UnittestRoot optionalNestedMessageExtension]
+ value:nestedMessage];
+ return message;
+}
+
+- (void)testMergeFrom {
+ TestAllTypes *result = [[self.mergeDestination copy] autorelease];
+ [result mergeFrom:self.mergeSource];
+ NSData *resultData = [result data];
+ NSData *mergeResultData = [self.mergeResult data];
+ XCTAssertEqualObjects(resultData, mergeResultData);
+ XCTAssertEqualObjects(result, self.mergeResult);
+
+ // Test when destination does not have an Ivar (type is an object) but source
+ // has such Ivar.
+ // The result must has the Ivar which is same as the one in source.
+ result = [[self.mergeDestinationWithoutForeignMessageIvar copy] autorelease];
+ [result mergeFrom:self.mergeSource];
+ resultData = [result data];
+ mergeResultData =
+ [self.mergeResultForDestinationWithoutForeignMessageIvar data];
+ XCTAssertEqualObjects(resultData, mergeResultData);
+ XCTAssertEqualObjects(
+ result, self.mergeResultForDestinationWithoutForeignMessageIvar);
+
+ // Test when destination is empty.
+ // The result must is same as the source.
+ result = [TestAllTypes message];
+ [result mergeFrom:self.mergeSource];
+ resultData = [result data];
+ mergeResultData = [self.mergeSource data];
+ XCTAssertEqualObjects(resultData, mergeResultData);
+ XCTAssertEqualObjects(result, self.mergeSource);
+}
+
+- (void)testMergeFromWithExtensions {
+ TestAllExtensions *result = [self mergeExtensionsDestination];
+ [result mergeFrom:[self mergeExtensionsSource]];
+ NSData *resultData = [result data];
+ NSData *mergeResultData = [[self mergeExtensionsResult] data];
+ XCTAssertEqualObjects(resultData, mergeResultData);
+ XCTAssertEqualObjects(result, [self mergeExtensionsResult]);
+
+ // Test merging from data.
+ result = [self mergeExtensionsDestination];
+ [result mergeFromData:[[self mergeExtensionsSource] data]
+ extensionRegistry:[UnittestRoot extensionRegistry]];
+ resultData = [result data];
+ XCTAssertEqualObjects(resultData, mergeResultData);
+ XCTAssertEqualObjects(result, [self mergeExtensionsResult]);
+}
+
+- (void)testIsEquals {
+ TestAllTypes *result = [[self.mergeDestination copy] autorelease];
+ [result mergeFrom:self.mergeSource];
+ XCTAssertEqualObjects(result.data, self.mergeResult.data);
+ XCTAssertEqualObjects(result, self.mergeResult);
+ TestAllTypes *result2 = [[self.mergeDestination copy] autorelease];
+ XCTAssertNotEqualObjects(result2.data, self.mergeResult.data);
+ XCTAssertNotEqualObjects(result2, self.mergeResult);
+}
+
+// =================================================================
+// Required-field-related tests.
+
+- (TestRequired *)testRequiredInitialized {
+ TestRequired *message = [TestRequired message];
+ [message setA:1];
+ [message setB:2];
+ [message setC:3];
+ return message;
+}
+
+- (void)testRequired {
+ TestRequired *message = [TestRequired message];
+
+ XCTAssertFalse(message.initialized);
+ [message setA:1];
+ XCTAssertFalse(message.initialized);
+ [message setB:1];
+ XCTAssertFalse(message.initialized);
+ [message setC:1];
+ XCTAssertTrue(message.initialized);
+}
+
+- (void)testRequiredForeign {
+ TestRequiredForeign *message = [TestRequiredForeign message];
+
+ XCTAssertTrue(message.initialized);
+
+ [message setOptionalMessage:[TestRequired message]];
+ XCTAssertFalse(message.initialized);
+
+ [message setOptionalMessage:self.testRequiredInitialized];
+ XCTAssertTrue(message.initialized);
+
+ message.repeatedMessageArray = [NSMutableArray array];
+ [message.repeatedMessageArray addObject:[TestRequired message]];
+ XCTAssertFalse(message.initialized);
+
+ [message.repeatedMessageArray removeAllObjects];
+ [message.repeatedMessageArray addObject:self.testRequiredInitialized];
+ XCTAssertTrue(message.initialized);
+}
+
+- (void)testRequiredExtension {
+ TestAllExtensions *message = [TestAllExtensions message];
+
+ XCTAssertTrue(message.initialized);
+
+ [message setExtension:[TestRequired single] value:[TestRequired message]];
+ XCTAssertFalse(message.initialized);
+
+ [message setExtension:[TestRequired single]
+ value:self.testRequiredInitialized];
+ XCTAssertTrue(message.initialized);
+
+ [message addExtension:[TestRequired multi] value:[TestRequired message]];
+ XCTAssertFalse(message.initialized);
+
+ [message setExtension:[TestRequired multi]
+ index:0
+ value:self.testRequiredInitialized];
+ XCTAssertTrue(message.initialized);
+}
+
+#ifdef DEBUG
+- (void)testUninitializedException {
+ TestRequired *message = [TestRequired message];
+ [self assertBlock:^{
+ [message data];
+ } throwsWithMessageInUserInfo:message];
+}
+#endif // DEBUG
+
+- (void)testInitialized {
+ // We're mostly testing that no exception is thrown.
+ TestRequired *message = [TestRequired message];
+ XCTAssertFalse(message.initialized);
+}
+
+#ifdef DEBUG
+- (void)testNestedUninitializedException {
+ TestRequiredForeign *message = [TestRequiredForeign message];
+ [message setOptionalMessage:[TestRequired message]];
+ message.repeatedMessageArray = [NSMutableArray array];
+ [message.repeatedMessageArray addObject:[TestRequired message]];
+ [message.repeatedMessageArray addObject:[TestRequired message]];
+ [self assertBlock:^{
+ [message data];
+ } throwsWithMessageInUserInfo:message];
+}
+#endif // DEBUG
+
+- (void)testNestedInitialized {
+ // We're mostly testing that no exception is thrown.
+
+ TestRequiredForeign *message = [TestRequiredForeign message];
+ [message setOptionalMessage:[TestRequired message]];
+ message.repeatedMessageArray = [NSMutableArray array];
+ [message.repeatedMessageArray addObject:[TestRequired message]];
+ [message.repeatedMessageArray addObject:[TestRequired message]];
+
+ XCTAssertFalse(message.initialized);
+}
+
+#ifdef DEBUG
+- (void)testParseUninitialized {
+ [self assertBlock:^{
+ [TestRequired parseFromData:GPBEmptyNSData()];
+ } throwsWithMessageInUserInfo:[TestRequired message]];
+}
+#endif // DEBUG
+
+- (void)testCoding {
+ NSData *data =
+ [NSKeyedArchiver archivedDataWithRootObject:[self mergeResult]];
+ id unarchivedObject = [NSKeyedUnarchiver unarchiveObjectWithData:data];
+
+ XCTAssertEqualObjects(unarchivedObject, [self mergeResult]);
+
+ // Intentionally doing a pointer comparison.
+ XCTAssertNotEqual(unarchivedObject, [self mergeResult]);
+}
+
+- (void)testObjectReset {
+ // Tests a failure where clearing out defaults values caused an over release.
+ TestAllTypes *message = [TestAllTypes message];
+ message.hasOptionalNestedMessage = NO;
+ [message setOptionalNestedMessage:[TestAllTypes_NestedMessage message]];
+ message.hasOptionalNestedMessage = NO;
+ [message setOptionalNestedMessage:[TestAllTypes_NestedMessage message]];
+ [message setOptionalNestedMessage:nil];
+ message.hasOptionalNestedMessage = NO;
+}
+
+- (void)testSettingHasToYes {
+ TestAllTypes *message = [TestAllTypes message];
+ XCTAssertThrows([message setHasOptionalNestedMessage:YES]);
+}
+
+- (void)testRoot {
+ XCTAssertNotNil([UnittestRoot extensionRegistry]);
+}
+
+- (void)testGPBMessageSize {
+ // See the note in GPBMessage_PackagePrivate.h about why we want to keep the
+ // base instance size pointer size aligned.
+ size_t messageSize = class_getInstanceSize([GPBMessage class]);
+ XCTAssertEqual((messageSize % sizeof(void *)), (size_t)0,
+ @"Base size isn't pointer size aligned");
+
+ // Since we add storage ourselves (see +allocWithZone: in GPBMessage), confirm
+ // that the size of some generated classes is still the same as the base for
+ // that logic to work as desired.
+ size_t testMessageSize = class_getInstanceSize([TestAllTypes class]);
+ XCTAssertEqual(testMessageSize, messageSize);
+}
+
+- (void)testInit {
+ TestAllTypes *message = [TestAllTypes message];
+ [self assertClear:message];
+}
+
+- (void)testAccessors {
+ TestAllTypes *message = [TestAllTypes message];
+ [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount];
+ [self assertAllFieldsSet:message repeatedCount:kGPBDefaultRepeatCount];
+}
+
+- (void)testKVC_ValueForKey {
+ TestAllTypes *message = [TestAllTypes message];
+ [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount];
+ [self assertAllFieldsKVCMatch:message];
+}
+
+- (void)testKVC_SetValue_ForKey {
+ TestAllTypes *message = [TestAllTypes message];
+ [self setAllFieldsViaKVC:message repeatedCount:kGPBDefaultRepeatCount];
+ [self assertAllFieldsKVCMatch:message];
+ [self assertAllFieldsSet:message repeatedCount:kGPBDefaultRepeatCount];
+ [self assertAllFieldsKVCMatch:message];
+}
+
+- (void)testDescription {
+ // No real test, just exercise code
+ TestAllTypes *message = [TestAllTypes message];
+ [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount];
+
+ GPBUnknownFieldSet *unknownFields =
+ [[[GPBUnknownFieldSet alloc] init] autorelease];
+ GPBField *field = [[[GPBField alloc] initWithNumber:2] autorelease];
+ [field addVarint:2];
+ [unknownFields addField:field];
+ field = [[[GPBField alloc] initWithNumber:3] autorelease];
+ [field addVarint:4];
+ [unknownFields addField:field];
+
+ [message setUnknownFields:unknownFields];
+
+ NSString *description = [message description];
+ XCTAssertGreaterThan([description length], 0U);
+
+ GPBMessage *message2 = [TestAllExtensions message];
+ [message2 setExtension:[UnittestRoot optionalInt32Extension] value:@1];
+
+ [message2 addExtension:[UnittestRoot repeatedInt32Extension] value:@2];
+
+ description = [message2 description];
+ XCTAssertGreaterThan([description length], 0U);
+}
+
+- (void)testSetter {
+ // Test to make sure that if we set a value that has a default value
+ // with the default, that the has is set, and the value gets put into the
+ // message correctly.
+ TestAllTypes *message = [TestAllTypes message];
+ GPBDescriptor *descriptor = [[message class] descriptor];
+ XCTAssertNotNil(descriptor);
+ GPBFieldDescriptor *fieldDescriptor =
+ [descriptor fieldWithName:@"defaultInt32"];
+ XCTAssertNotNil(fieldDescriptor);
+ GPBValue defaultValue = [fieldDescriptor defaultValue];
+ [message setDefaultInt32:defaultValue.valueInt32];
+ XCTAssertTrue(message.hasDefaultInt32);
+ XCTAssertEqual(message.defaultInt32, defaultValue.valueInt32);
+
+ // Do the same thing with an object type.
+ message = [TestAllTypes message];
+ fieldDescriptor = [descriptor fieldWithName:@"defaultString"];
+ XCTAssertNotNil(fieldDescriptor);
+ defaultValue = [fieldDescriptor defaultValue];
+ [message setDefaultString:defaultValue.valueString];
+ XCTAssertTrue(message.hasDefaultString);
+ XCTAssertEqualObjects(message.defaultString, defaultValue.valueString);
+
+ // Test default string type.
+ message = [TestAllTypes message];
+ XCTAssertEqualObjects(message.defaultString, @"hello");
+ XCTAssertFalse(message.hasDefaultString);
+ fieldDescriptor = [descriptor fieldWithName:@"defaultString"];
+ XCTAssertNotNil(fieldDescriptor);
+ defaultValue = [fieldDescriptor defaultValue];
+ [message setDefaultString:defaultValue.valueString];
+ XCTAssertEqualObjects(message.defaultString, @"hello");
+ XCTAssertTrue(message.hasDefaultString);
+ [message setDefaultString:nil];
+ XCTAssertEqualObjects(message.defaultString, @"hello");
+ XCTAssertFalse(message.hasDefaultString);
+ message.hasDefaultString = NO;
+ XCTAssertFalse(message.hasDefaultString);
+ XCTAssertEqualObjects(message.defaultString, @"hello");
+
+ // Test default bytes type.
+ NSData *defaultBytes = [@"world" dataUsingEncoding:NSUTF8StringEncoding];
+ XCTAssertEqualObjects(message.defaultBytes, defaultBytes);
+ XCTAssertFalse(message.hasDefaultString);
+ fieldDescriptor = [descriptor fieldWithName:@"defaultBytes"];
+ XCTAssertNotNil(fieldDescriptor);
+ defaultValue = [fieldDescriptor defaultValue];
+ [message setDefaultBytes:defaultValue.valueData];
+ XCTAssertEqualObjects(message.defaultBytes, defaultBytes);
+ XCTAssertTrue(message.hasDefaultBytes);
+ [message setDefaultBytes:nil];
+ XCTAssertEqualObjects(message.defaultBytes, defaultBytes);
+ XCTAssertFalse(message.hasDefaultBytes);
+ message.hasDefaultBytes = NO;
+ XCTAssertFalse(message.hasDefaultBytes);
+ XCTAssertEqualObjects(message.defaultBytes, defaultBytes);
+
+ // Test optional string.
+ XCTAssertFalse(message.hasOptionalString);
+ XCTAssertEqualObjects(message.optionalString, @"");
+ XCTAssertFalse(message.hasOptionalString);
+ message.optionalString = nil;
+ XCTAssertFalse(message.hasOptionalString);
+ XCTAssertEqualObjects(message.optionalString, @"");
+ NSString *string = @"string";
+ message.optionalString = string;
+ XCTAssertEqualObjects(message.optionalString, string);
+ XCTAssertTrue(message.hasOptionalString);
+ message.optionalString = nil;
+ XCTAssertFalse(message.hasOptionalString);
+ XCTAssertEqualObjects(message.optionalString, @"");
+
+ // Test optional data.
+ XCTAssertFalse(message.hasOptionalBytes);
+ XCTAssertEqualObjects(message.optionalBytes, GPBEmptyNSData());
+ XCTAssertFalse(message.hasOptionalBytes);
+ message.optionalBytes = nil;
+ XCTAssertFalse(message.hasOptionalBytes);
+ XCTAssertEqualObjects(message.optionalBytes, GPBEmptyNSData());
+ NSData *data = [@"bytes" dataUsingEncoding:NSUTF8StringEncoding];
+ message.optionalBytes = data;
+ XCTAssertEqualObjects(message.optionalBytes, data);
+ XCTAssertTrue(message.hasOptionalBytes);
+ message.optionalBytes = nil;
+ XCTAssertFalse(message.hasOptionalBytes);
+ XCTAssertEqualObjects(message.optionalBytes, GPBEmptyNSData());
+
+ // Test lazy message setting
+ XCTAssertFalse(message.hasOptionalLazyMessage);
+ XCTAssertNotNil(message.optionalLazyMessage);
+ XCTAssertFalse(message.hasOptionalLazyMessage);
+ message.hasOptionalLazyMessage = NO;
+ XCTAssertFalse(message.hasOptionalLazyMessage);
+ XCTAssertNotNil(message.optionalLazyMessage);
+ XCTAssertFalse(message.hasOptionalLazyMessage);
+ message.optionalLazyMessage = nil;
+ XCTAssertFalse(message.hasOptionalLazyMessage);
+
+ // Test nested messages
+ XCTAssertFalse(message.hasOptionalLazyMessage);
+ message.optionalLazyMessage.bb = 1;
+ XCTAssertTrue(message.hasOptionalLazyMessage);
+ XCTAssertEqual(message.optionalLazyMessage.bb, 1);
+ XCTAssertNotNil(message.optionalLazyMessage);
+ message.optionalLazyMessage = nil;
+ XCTAssertFalse(message.hasOptionalLazyMessage);
+ XCTAssertEqual(message.optionalLazyMessage.bb, 0);
+ XCTAssertFalse(message.hasOptionalLazyMessage);
+ XCTAssertNotNil(message.optionalLazyMessage);
+
+ // -testDefaultSubMessages tests the "defaulting" handling of fields
+ // containing messages.
+}
+
+- (void)testRepeatedSetters {
+ TestAllTypes *message = [TestAllTypes message];
+ [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount];
+ [self modifyRepeatedFields:message];
+ [self assertRepeatedFieldsModified:message
+ repeatedCount:kGPBDefaultRepeatCount];
+}
+
+- (void)testClear {
+ TestAllTypes *message = [TestAllTypes message];
+ [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount];
+ [self clearAllFields:message];
+ [self assertClear:message];
+ TestAllTypes *message2 = [TestAllTypes message];
+ XCTAssertEqualObjects(message, message2);
+}
+
+- (void)testClearKVC {
+ TestAllTypes *message = [TestAllTypes message];
+ [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount];
+ [self clearAllFields:message];
+ [self assertClear:message];
+ [self assertClearKVC:message];
+}
+
+- (void)testClearExtension {
+ // clearExtension() is not actually used in TestUtil, so try it manually.
+ GPBMessage *message1 = [TestAllExtensions message];
+ [message1 setExtension:[UnittestRoot optionalInt32Extension] value:@1];
+
+ XCTAssertTrue([message1 hasExtension:[UnittestRoot optionalInt32Extension]]);
+ [message1 clearExtension:[UnittestRoot optionalInt32Extension]];
+ XCTAssertFalse([message1 hasExtension:[UnittestRoot optionalInt32Extension]]);
+
+ GPBMessage *message2 = [TestAllExtensions message];
+ [message2 addExtension:[UnittestRoot repeatedInt32Extension] value:@1];
+
+ XCTAssertEqual(
+ [[message2 getExtension:[UnittestRoot repeatedInt32Extension]] count],
+ (NSUInteger)1);
+ [message2 clearExtension:[UnittestRoot repeatedInt32Extension]];
+ XCTAssertEqual(
+ [[message2 getExtension:[UnittestRoot repeatedInt32Extension]] count],
+ (NSUInteger)0);
+
+ // Clearing an unset extension field shouldn't make the target message
+ // visible.
+ GPBMessage *message3 = [TestAllExtensions message];
+ GPBMessage *extension_msg =
+ [message3 getExtension:[UnittestObjcRoot recursiveExtension]];
+ XCTAssertFalse([message3 hasExtension:[UnittestObjcRoot recursiveExtension]]);
+ [extension_msg clearExtension:[UnittestRoot optionalInt32Extension]];
+ XCTAssertFalse([message3 hasExtension:[UnittestObjcRoot recursiveExtension]]);
+}
+
+- (void)testDefaultingSubMessages {
+ TestAllTypes *message = [TestAllTypes message];
+
+ // Initially they should all not have values.
+
+ XCTAssertFalse(message.hasOptionalGroup);
+ XCTAssertFalse(message.hasOptionalNestedMessage);
+ XCTAssertFalse(message.hasOptionalForeignMessage);
+ XCTAssertFalse(message.hasOptionalImportMessage);
+ XCTAssertFalse(message.hasOptionalPublicImportMessage);
+ XCTAssertFalse(message.hasOptionalLazyMessage);
+
+ // They should auto create something when fetched.
+
+ TestAllTypes_OptionalGroup *optionalGroup = [message.optionalGroup retain];
+ TestAllTypes_NestedMessage *optionalNestedMessage =
+ [message.optionalNestedMessage retain];
+ ForeignMessage *optionalForeignMessage =
+ [message.optionalForeignMessage retain];
+ ImportMessage *optionalImportMessage = [message.optionalImportMessage retain];
+ PublicImportMessage *optionalPublicImportMessage =
+ [message.optionalPublicImportMessage retain];
+ TestAllTypes_NestedMessage *optionalLazyMessage =
+ [message.optionalLazyMessage retain];
+
+ XCTAssertNotNil(optionalGroup);
+ XCTAssertNotNil(optionalNestedMessage);
+ XCTAssertNotNil(optionalForeignMessage);
+ XCTAssertNotNil(optionalImportMessage);
+ XCTAssertNotNil(optionalPublicImportMessage);
+ XCTAssertNotNil(optionalLazyMessage);
+
+ // Although they were created, they should not respond to hasValue until that
+ // submessage is mutated.
+
+ XCTAssertFalse(message.hasOptionalGroup);
+ XCTAssertFalse(message.hasOptionalNestedMessage);
+ XCTAssertFalse(message.hasOptionalForeignMessage);
+ XCTAssertFalse(message.hasOptionalImportMessage);
+ XCTAssertFalse(message.hasOptionalPublicImportMessage);
+ XCTAssertFalse(message.hasOptionalLazyMessage);
+
+ // And they set that value back in to the message since the value created was
+ // mutable (so a second fetch should give the same object).
+
+ XCTAssertEqual(message.optionalGroup, optionalGroup);
+ XCTAssertEqual(message.optionalNestedMessage, optionalNestedMessage);
+ XCTAssertEqual(message.optionalForeignMessage, optionalForeignMessage);
+ XCTAssertEqual(message.optionalImportMessage, optionalImportMessage);
+ XCTAssertEqual(message.optionalPublicImportMessage,
+ optionalPublicImportMessage);
+ XCTAssertEqual(message.optionalLazyMessage, optionalLazyMessage);
+
+ // And the default objects for a second message should be distinct (again,
+ // since they are mutable, each needs their own copy).
+
+ TestAllTypes *message2 = [TestAllTypes message];
+
+ // Intentionally doing a pointer comparison.
+ XCTAssertNotEqual(message2.optionalGroup, optionalGroup);
+ XCTAssertNotEqual(message2.optionalNestedMessage, optionalNestedMessage);
+ XCTAssertNotEqual(message2.optionalForeignMessage, optionalForeignMessage);
+ XCTAssertNotEqual(message2.optionalImportMessage, optionalImportMessage);
+ XCTAssertNotEqual(message2.optionalPublicImportMessage,
+ optionalPublicImportMessage);
+ XCTAssertNotEqual(message2.optionalLazyMessage, optionalLazyMessage);
+
+ // Setting the values to nil will clear the has flag, and on next access you
+ // get back new submessages.
+
+ message.optionalGroup = nil;
+ message.optionalNestedMessage = nil;
+ message.optionalForeignMessage = nil;
+ message.optionalImportMessage = nil;
+ message.optionalPublicImportMessage = nil;
+ message.optionalLazyMessage = nil;
+
+ XCTAssertFalse(message.hasOptionalGroup);
+ XCTAssertFalse(message.hasOptionalNestedMessage);
+ XCTAssertFalse(message.hasOptionalForeignMessage);
+ XCTAssertFalse(message.hasOptionalImportMessage);
+ XCTAssertFalse(message.hasOptionalPublicImportMessage);
+ XCTAssertFalse(message.hasOptionalLazyMessage);
+
+ // Intentionally doing a pointer comparison.
+ XCTAssertNotEqual(message.optionalGroup, optionalGroup);
+ XCTAssertNotEqual(message.optionalNestedMessage, optionalNestedMessage);
+ XCTAssertNotEqual(message.optionalForeignMessage, optionalForeignMessage);
+ XCTAssertNotEqual(message.optionalImportMessage, optionalImportMessage);
+ XCTAssertNotEqual(message.optionalPublicImportMessage,
+ optionalPublicImportMessage);
+ XCTAssertNotEqual(message.optionalLazyMessage, optionalLazyMessage);
+
+ [optionalGroup release];
+ [optionalNestedMessage release];
+ [optionalForeignMessage release];
+ [optionalImportMessage release];
+ [optionalPublicImportMessage release];
+ [optionalLazyMessage release];
+}
+
+- (void)testMultiplePointersToAutocreatedMessage {
+ // Multiple objects pointing to the same autocreated message.
+ TestAllTypes *message = [TestAllTypes message];
+ TestAllTypes *message2 = [TestAllTypes message];
+ message2.optionalGroup = message.optionalGroup;
+ XCTAssertTrue([message2 hasOptionalGroup]);
+ XCTAssertFalse([message hasOptionalGroup]);
+ message2.optionalGroup.a = 42;
+ XCTAssertTrue([message hasOptionalGroup]);
+ XCTAssertTrue([message2 hasOptionalGroup]);
+}
+
+- (void)testCopyWithAutocreatedMessage {
+ // Mutable copy should not copy autocreated messages.
+ TestAllTypes *message = [TestAllTypes message];
+ message.optionalGroup.a = 42;
+ XCTAssertNotNil(message.optionalNestedMessage);
+ TestAllTypes *message2 = [[message copy] autorelease];
+ XCTAssertTrue([message2 hasOptionalGroup]);
+ XCTAssertFalse([message2 hasOptionalNestedMessage]);
+
+ // Intentionally doing a pointer comparison.
+ XCTAssertNotEqual(message.optionalNestedMessage,
+ message2.optionalNestedMessage);
+}
+
+- (void)testClearAutocreatedSubmessage {
+ // Call clear on an intermediate submessage should cause it to get recreated
+ // on the next call.
+ TestRecursiveMessage *message = [TestRecursiveMessage message];
+ TestRecursiveMessage *message_inner = [message.a.a.a retain];
+ XCTAssertNotNil(message_inner);
+ XCTAssertTrue(GPBWasMessageAutocreatedBy(message_inner, message.a.a));
+ [message.a.a clear];
+ XCTAssertFalse(GPBWasMessageAutocreatedBy(message_inner, message.a.a));
+
+ // Intentionally doing a pointer comparison.
+ XCTAssertNotEqual(message.a.a.a, message_inner);
+ [message_inner release];
+}
+
+- (void)testRetainAutocreatedSubmessage {
+ // Should be able to retain autocreated submessage while the creator is
+ // dealloced.
+ TestAllTypes *message = [TestAllTypes message];
+
+ ForeignMessage *subMessage;
+ @autoreleasepool {
+ TestAllTypes *message2 = [TestAllTypes message];
+ subMessage = message2.optionalForeignMessage; // Autocreated
+ message.optionalForeignMessage = subMessage;
+ XCTAssertTrue(GPBWasMessageAutocreatedBy(message.optionalForeignMessage,
+ message2));
+ }
+
+ // Should be the same object, and should still be live.
+ XCTAssertEqual(message.optionalForeignMessage, subMessage);
+ XCTAssertNotNil([subMessage description]);
+}
+
+- (void)testSetNilAutocreatedSubmessage {
+ TestRecursiveMessage *message = [TestRecursiveMessage message];
+ TestRecursiveMessage *message_inner = [message.a.a retain];
+ XCTAssertFalse([message hasA]);
+ XCTAssertFalse([message.a hasA]);
+ message.a.a = nil;
+
+ // |message.a| has to be made visible, but |message.a.a| was set to nil so
+ // shouldn't be.
+ XCTAssertTrue([message hasA]);
+ XCTAssertFalse([message.a hasA]);
+
+ // Setting submessage to nil should cause it to lose its creator.
+ XCTAssertFalse(GPBWasMessageAutocreatedBy(message_inner, message.a));
+
+ // After setting to nil, getting it again should create a new autocreated
+ // message.
+ // Intentionally doing a pointer comparison.
+ XCTAssertNotEqual(message.a.a, message_inner);
+
+ [message_inner release];
+}
+
+- (void)testSetDoesntHaveAutocreatedSubmessage {
+ // Clearing submessage (set has == NO) should NOT cause it to lose its
+ // creator.
+ TestAllTypes *message = [TestAllTypes message];
+ TestAllTypes_NestedMessage *nestedMessage = message.optionalNestedMessage;
+ XCTAssertFalse([message hasOptionalNestedMessage]);
+ [message setHasOptionalNestedMessage:NO];
+ XCTAssertFalse([message hasOptionalNestedMessage]);
+ XCTAssertEqual(message.optionalNestedMessage, nestedMessage);
+}
+
+- (void)testSetAutocreatedMessageBecomesVisible {
+ // Setting a value should cause the submessage to appear to its creator.
+ // Test this several levels deep.
+ TestRecursiveMessage *message = [TestRecursiveMessage message];
+ message.a.a.a.a.i = 42;
+ XCTAssertTrue([message hasA]);
+ XCTAssertTrue([message.a hasA]);
+ XCTAssertTrue([message.a.a hasA]);
+ XCTAssertTrue([message.a.a.a hasA]);
+ XCTAssertFalse([message.a.a.a.a hasA]);
+ XCTAssertEqual(message.a.a.a.a.i, 42);
+}
+
+- (void)testClearUnsetFieldOfAutocreatedMessage {
+ // Clearing an unset field should not cause the submessage to appear to its
+ // creator.
+ TestRecursiveMessage *message = [TestRecursiveMessage message];
+ message.a.a.a.a.hasI = NO;
+ XCTAssertFalse([message hasA]);
+ XCTAssertFalse([message.a hasA]);
+ XCTAssertFalse([message.a.a hasA]);
+ XCTAssertFalse([message.a.a.a hasA]);
+}
+
+- (void)testAutocreatedSubmessageAssignSkip {
+ TestRecursiveMessage *message = [TestRecursiveMessage message];
+ TestRecursiveMessage *messageLevel1 = [message.a retain];
+ TestRecursiveMessage *messageLevel2 = [message.a.a retain];
+ TestRecursiveMessage *messageLevel3 = [message.a.a.a retain];
+ TestRecursiveMessage *messageLevel4 = [message.a.a.a.a retain];
+ XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel1, message));
+ XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel2, messageLevel1));
+ XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel3, messageLevel2));
+ XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel4, messageLevel3));
+
+ // Test skipping over an autocreated submessage and ensure it gets unset.
+ message.a = message.a.a;
+ XCTAssertEqual(message.a, messageLevel2);
+ XCTAssertTrue([message hasA]);
+ XCTAssertEqual(message.a.a, messageLevel3);
+ XCTAssertFalse([message.a hasA]);
+ XCTAssertEqual(message.a.a.a, messageLevel4);
+ XCTAssertFalse(GPBWasMessageAutocreatedBy(messageLevel1,
+ message)); // Because it was orphaned.
+ XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel2, messageLevel1));
+ XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel3, messageLevel2));
+
+ [messageLevel1 release];
+ [messageLevel2 release];
+ [messageLevel3 release];
+ [messageLevel4 release];
+}
+
+- (void)testAutocreatedSubmessageAssignLoop {
+ TestRecursiveMessage *message = [TestRecursiveMessage message];
+ TestRecursiveMessage *messageLevel1 = [message.a retain];
+ TestRecursiveMessage *messageLevel2 = [message.a.a retain];
+ TestRecursiveMessage *messageLevel3 = [message.a.a.a retain];
+ TestRecursiveMessage *messageLevel4 = [message.a.a.a.a retain];
+ XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel1, message));
+ XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel2, messageLevel1));
+ XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel3, messageLevel2));
+ XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel4, messageLevel3));
+
+ // Test a property with a loop. You'd never do this but at least ensure the
+ // autocreated submessages behave sanely.
+ message.a.a = message.a;
+ XCTAssertTrue([message hasA]);
+ XCTAssertEqual(message.a, messageLevel1);
+ XCTAssertTrue([message.a hasA]);
+ XCTAssertEqual(message.a.a, messageLevel1);
+ XCTAssertTrue([message.a.a hasA]);
+ XCTAssertEqual(message.a.a.a, messageLevel1);
+ XCTAssertFalse(GPBWasMessageAutocreatedBy(messageLevel1,
+ message)); // Because it was assigned.
+ XCTAssertFalse(GPBWasMessageAutocreatedBy(messageLevel2,
+ messageLevel1)); // Because it was orphaned.
+ XCTAssertFalse([messageLevel2 hasA]);
+
+ // Break the retain loop.
+ message.a.a = nil;
+ XCTAssertTrue([message hasA]);
+ XCTAssertFalse([message.a hasA]);
+
+ [messageLevel1 release];
+ [messageLevel2 release];
+ [messageLevel3 release];
+ [messageLevel4 release];
+}
+
+- (void)testSetAutocreatedSubmessage {
+ // Setting autocreated submessage to another value should cause the old one to
+ // lose its creator.
+ TestAllTypes *message = [TestAllTypes message];
+ TestAllTypes_NestedMessage *nestedMessage =
+ [message.optionalNestedMessage retain];
+
+ message.optionalNestedMessage = [TestAllTypes_NestedMessage message];
+ XCTAssertTrue([message hasOptionalNestedMessage]);
+ XCTAssertTrue(message.optionalNestedMessage != nestedMessage);
+ XCTAssertFalse(GPBWasMessageAutocreatedBy(nestedMessage, message));
+
+ [nestedMessage release];
+}
+
+- (void)testAutocreatedUnknownFields {
+ // Doing anything with (except reading) unknown fields should cause the
+ // submessage to become visible.
+ TestAllTypes *message = [TestAllTypes message];
+ XCTAssertNotNil(message.optionalNestedMessage);
+ XCTAssertFalse([message hasOptionalNestedMessage]);
+ XCTAssertNil(message.optionalNestedMessage.unknownFields);
+ XCTAssertFalse([message hasOptionalNestedMessage]);
+
+ GPBUnknownFieldSet *unknownFields =
+ [[[GPBUnknownFieldSet alloc] init] autorelease];
+ message.optionalNestedMessage.unknownFields = unknownFields;
+ XCTAssertTrue([message hasOptionalNestedMessage]);
+
+ message.optionalNestedMessage = nil;
+ XCTAssertFalse([message hasOptionalNestedMessage]);
+ [message.optionalNestedMessage setUnknownFields:unknownFields];
+ XCTAssertTrue([message hasOptionalNestedMessage]);
+}
+
+- (void)testSetAutocreatedSubmessageToSelf {
+ // Setting submessage to itself should cause it to become visible.
+ TestAllTypes *message = [TestAllTypes message];
+ XCTAssertNotNil(message.optionalNestedMessage);
+ XCTAssertFalse([message hasOptionalNestedMessage]);
+ message.optionalNestedMessage = message.optionalNestedMessage;
+ XCTAssertTrue([message hasOptionalNestedMessage]);
+}
+
+- (void)testAutocreatedSubmessageMemoryLeaks {
+ // Test for memory leaks with autocreated submessages.
+ TestRecursiveMessage *message;
+ TestRecursiveMessage *messageLevel1;
+ TestRecursiveMessage *messageLevel2;
+ TestRecursiveMessage *messageLevel3;
+ TestRecursiveMessage *messageLevel4;
+ @autoreleasepool {
+ message = [[TestRecursiveMessage alloc] init];
+ messageLevel1 = [message.a retain];
+ messageLevel2 = [message.a.a retain];
+ messageLevel3 = [message.a.a.a retain];
+ messageLevel4 = [message.a.a.a.a retain];
+ message.a.i = 1;
+ }
+
+ XCTAssertEqual(message.retainCount, (NSUInteger)1);
+ [message release];
+ XCTAssertEqual(messageLevel1.retainCount, (NSUInteger)1);
+ [messageLevel1 release];
+ XCTAssertEqual(messageLevel2.retainCount, (NSUInteger)1);
+ [messageLevel2 release];
+ XCTAssertEqual(messageLevel3.retainCount, (NSUInteger)1);
+ [messageLevel3 release];
+ XCTAssertEqual(messageLevel4.retainCount, (NSUInteger)1);
+ [messageLevel4 release];
+}
+
+- (void)testDefaultingArrays {
+ // Basic tests for default creation of arrays in a message.
+ TestRecursiveMessageWithRepeatedField *message =
+ [TestRecursiveMessageWithRepeatedField message];
+ TestRecursiveMessageWithRepeatedField *message2 =
+ [TestRecursiveMessageWithRepeatedField message];
+
+ // Simply accessing the array should not make any fields visible.
+ XCTAssertNotNil(message.a.a.iArray);
+ XCTAssertFalse([message hasA]);
+ XCTAssertFalse([message.a hasA]);
+ XCTAssertNotNil(message2.a.a.strArray);
+ XCTAssertFalse([message2 hasA]);
+ XCTAssertFalse([message2.a hasA]);
+
+ // But adding an element to the array should.
+ [message.a.a.iArray addValue:42];
+ XCTAssertTrue([message hasA]);
+ XCTAssertTrue([message.a hasA]);
+ XCTAssertEqual([message.a.a.iArray count], (NSUInteger)1);
+ [message2.a.a.strArray addObject:@"foo"];
+ XCTAssertTrue([message2 hasA]);
+ XCTAssertTrue([message2.a hasA]);
+ XCTAssertEqual([message2.a.a.strArray count], (NSUInteger)1);
+}
+
+- (void)testAutocreatedArrayShared {
+ // Multiple objects pointing to the same array.
+ TestRecursiveMessageWithRepeatedField *message1a =
+ [TestRecursiveMessageWithRepeatedField message];
+ TestRecursiveMessageWithRepeatedField *message1b =
+ [TestRecursiveMessageWithRepeatedField message];
+ message1a.a.iArray = message1b.a.iArray;
+ XCTAssertTrue([message1a hasA]);
+ XCTAssertFalse([message1b hasA]);
+ [message1a.a.iArray addValue:1];
+ XCTAssertTrue([message1a hasA]);
+ XCTAssertTrue([message1b hasA]);
+ XCTAssertEqual(message1a.a.iArray, message1b.a.iArray);
+
+ TestRecursiveMessageWithRepeatedField *message2a =
+ [TestRecursiveMessageWithRepeatedField message];
+ TestRecursiveMessageWithRepeatedField *message2b =
+ [TestRecursiveMessageWithRepeatedField message];
+ message2a.a.strArray = message2b.a.strArray;
+ XCTAssertTrue([message2a hasA]);
+ XCTAssertFalse([message2b hasA]);
+ [message2a.a.strArray addObject:@"bar"];
+ XCTAssertTrue([message2a hasA]);
+ XCTAssertTrue([message2b hasA]);
+ XCTAssertEqual(message2a.a.strArray, message2b.a.strArray);
+}
+
+- (void)testAutocreatedArrayCopy {
+ // Copy should not copy autocreated arrays.
+ TestAllTypes *message = [TestAllTypes message];
+ XCTAssertNotNil(message.repeatedStringArray);
+ XCTAssertNotNil(message.repeatedInt32Array);
+ TestAllTypes *message2 = [[message copy] autorelease];
+ // Pointer conparisions.
+ XCTAssertNotEqual(message.repeatedStringArray, message2.repeatedStringArray);
+ XCTAssertNotEqual(message.repeatedInt32Array, message2.repeatedInt32Array);
+
+ // Mutable copy should copy empty arrays that were explicitly set (end up
+ // with different objects that are equal).
+ TestAllTypes *message3 = [TestAllTypes message];
+ message3.repeatedInt32Array = [GPBInt32Array arrayWithValue:42];
+ message3.repeatedStringArray = [NSMutableArray arrayWithObject:@"wee"];
+ XCTAssertNotNil(message.repeatedInt32Array);
+ XCTAssertNotNil(message.repeatedStringArray);
+ TestAllTypes *message4 = [message3 copy];
+ XCTAssertNotEqual(message3.repeatedInt32Array, message4.repeatedInt32Array);
+ XCTAssertEqualObjects(message3.repeatedInt32Array,
+ message4.repeatedInt32Array);
+ XCTAssertNotEqual(message3.repeatedStringArray, message4.repeatedStringArray);
+ XCTAssertEqualObjects(message3.repeatedStringArray,
+ message4.repeatedStringArray);
+}
+
+- (void)testAutocreatedArrayRetain {
+ // Should be able to retain autocreated array while the creator is dealloced.
+ TestAllTypes *message = [TestAllTypes message];
+
+ @autoreleasepool {
+ TestAllTypes *message2 = [TestAllTypes message];
+ message.repeatedInt32Array = message2.repeatedInt32Array;
+ message.repeatedStringArray = message2.repeatedStringArray;
+ // Pointer conparision
+ XCTAssertEqual(message.repeatedInt32Array->_autocreator, message2);
+ XCTAssertTrue([message.repeatedStringArray
+ isKindOfClass:[GPBAutocreatedArray class]]);
+ XCTAssertEqual(
+ ((GPBAutocreatedArray *)message.repeatedStringArray)->_autocreator,
+ message2);
+ }
+
+ XCTAssertNil(message.repeatedInt32Array->_autocreator);
+ XCTAssertTrue(
+ [message.repeatedStringArray isKindOfClass:[GPBAutocreatedArray class]]);
+ XCTAssertNil(
+ ((GPBAutocreatedArray *)message.repeatedStringArray)->_autocreator);
+}
+
+- (void)testSetNilAutocreatedArray {
+ // Setting array to nil should cause it to lose its delegate.
+ TestAllTypes *message = [TestAllTypes message];
+ GPBInt32Array *repeatedInt32Array = [message.repeatedInt32Array retain];
+ GPBAutocreatedArray *repeatedStringArray =
+ (GPBAutocreatedArray *)[message.repeatedStringArray retain];
+ XCTAssertTrue([repeatedStringArray isKindOfClass:[GPBAutocreatedArray class]]);
+ XCTAssertEqual(repeatedInt32Array->_autocreator, message);
+ XCTAssertEqual(repeatedStringArray->_autocreator, message);
+ message.repeatedInt32Array = nil;
+ message.repeatedStringArray = nil;
+ XCTAssertNil(repeatedInt32Array->_autocreator);
+ XCTAssertNil(repeatedStringArray->_autocreator);
+ [repeatedInt32Array release];
+ [repeatedStringArray release];
+}
+
+- (void)testReplaceAutocreatedArray {
+ // Replacing array should orphan the old one and cause its creator to become
+ // visible.
+ {
+ TestRecursiveMessageWithRepeatedField *message =
+ [TestRecursiveMessageWithRepeatedField message];
+ XCTAssertNotNil(message.a);
+ XCTAssertNotNil(message.a.iArray);
+ XCTAssertFalse([message hasA]);
+ GPBInt32Array *iArray = [message.a.iArray retain];
+ XCTAssertEqual(iArray->_autocreator, message.a); // Pointer comparision
+ message.a.iArray = [GPBInt32Array arrayWithValue:1];
+ XCTAssertTrue([message hasA]);
+ XCTAssertNotEqual(message.a.iArray, iArray); // Pointer comparision
+ XCTAssertNil(iArray->_autocreator);
+ [iArray release];
+ }
+
+ {
+ TestRecursiveMessageWithRepeatedField *message =
+ [TestRecursiveMessageWithRepeatedField message];
+ XCTAssertNotNil(message.a);
+ XCTAssertNotNil(message.a.strArray);
+ XCTAssertFalse([message hasA]);
+ GPBAutocreatedArray *strArray =
+ (GPBAutocreatedArray *)[message.a.strArray retain];
+ XCTAssertTrue([strArray isKindOfClass:[GPBAutocreatedArray class]]);
+ XCTAssertEqual(strArray->_autocreator, message.a); // Pointer comparision
+ message.a.strArray = [NSMutableArray arrayWithObject:@"foo"];
+ XCTAssertTrue([message hasA]);
+ XCTAssertNotEqual(message.a.strArray, strArray); // Pointer comparision
+ XCTAssertNil(strArray->_autocreator);
+ [strArray release];
+ }
+}
+
+- (void)testSetAutocreatedArrayToSelf {
+ // Setting array to itself should cause it to become visible.
+ {
+ TestRecursiveMessageWithRepeatedField *message =
+ [TestRecursiveMessageWithRepeatedField message];
+ XCTAssertNotNil(message.a);
+ XCTAssertNotNil(message.a.iArray);
+ XCTAssertFalse([message hasA]);
+ message.a.iArray = message.a.iArray;
+ XCTAssertTrue([message hasA]);
+ XCTAssertNil(message.a.iArray->_autocreator);
+ }
+
+ {
+ TestRecursiveMessageWithRepeatedField *message =
+ [TestRecursiveMessageWithRepeatedField message];
+ XCTAssertNotNil(message.a);
+ XCTAssertNotNil(message.a.strArray);
+ XCTAssertFalse([message hasA]);
+ message.a.strArray = message.a.strArray;
+ XCTAssertTrue([message hasA]);
+ XCTAssertTrue([message.a.strArray isKindOfClass:[GPBAutocreatedArray class]]);
+ XCTAssertNil(((GPBAutocreatedArray *)message.a.strArray)->_autocreator);
+ }
+}
+
+- (void)testAutocreatedArrayRemoveAllValues {
+ // Calling removeAllValues on autocreated array should not cause it to be
+ // visible.
+ TestRecursiveMessageWithRepeatedField *message =
+ [TestRecursiveMessageWithRepeatedField message];
+ [message.a.iArray removeAll];
+ XCTAssertFalse([message hasA]);
+ [message.a.strArray removeAllObjects];
+ XCTAssertFalse([message hasA]);
+}
+
+- (void)testExtensionAccessors {
+ TestAllExtensions *message = [TestAllExtensions message];
+ [self setAllExtensions:message repeatedCount:kGPBDefaultRepeatCount];
+ [self assertAllExtensionsSet:message repeatedCount:kGPBDefaultRepeatCount];
+}
+
+- (void)testExtensionRepeatedSetters {
+ TestAllExtensions *message = [TestAllExtensions message];
+ [self setAllExtensions:message repeatedCount:kGPBDefaultRepeatCount];
+ [self modifyRepeatedExtensions:message];
+ [self assertRepeatedExtensionsModified:message
+ repeatedCount:kGPBDefaultRepeatCount];
+}
+
+- (void)testExtensionDefaults {
+ [self assertExtensionsClear:[TestAllExtensions message]];
+}
+
+- (void)testExtensionIsEquals {
+ TestAllExtensions *message = [TestAllExtensions message];
+ [self setAllExtensions:message repeatedCount:kGPBDefaultRepeatCount];
+ [self modifyRepeatedExtensions:message];
+ TestAllExtensions *message2 = [TestAllExtensions message];
+ [self setAllExtensions:message2 repeatedCount:kGPBDefaultRepeatCount];
+ XCTAssertFalse([message isEqual:message2]);
+ message2 = [TestAllExtensions message];
+ [self setAllExtensions:message2 repeatedCount:kGPBDefaultRepeatCount];
+ [self modifyRepeatedExtensions:message2];
+ XCTAssertEqualObjects(message, message2);
+}
+
+- (void)testExtensionsMergeFrom {
+ TestAllExtensions *message = [TestAllExtensions message];
+ [self setAllExtensions:message repeatedCount:kGPBDefaultRepeatCount];
+ [self modifyRepeatedExtensions:message];
+
+ message = [TestAllExtensions message];
+ [self setAllExtensions:message repeatedCount:kGPBDefaultRepeatCount];
+ TestAllExtensions *message2 = [TestAllExtensions message];
+ [self modifyRepeatedExtensions:message2];
+ [message2 mergeFrom:message];
+
+ XCTAssertEqualObjects(message, message2);
+}
+
+- (void)testDefaultingExtensionMessages {
+ TestAllExtensions *message = [TestAllExtensions message];
+
+ // Initially they should all not have values.
+
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]);
+ XCTAssertFalse(
+ [message hasExtension:[UnittestRoot optionalNestedMessageExtension]]);
+ XCTAssertFalse(
+ [message hasExtension:[UnittestRoot optionalForeignMessageExtension]]);
+ XCTAssertFalse(
+ [message hasExtension:[UnittestRoot optionalImportMessageExtension]]);
+ XCTAssertFalse([message
+ hasExtension:[UnittestRoot optionalPublicImportMessageExtension]]);
+ XCTAssertFalse(
+ [message hasExtension:[UnittestRoot optionalLazyMessageExtension]]);
+
+ // They should auto create something when fetched.
+
+ TestAllTypes_OptionalGroup *optionalGroup =
+ [message getExtension:[UnittestRoot optionalGroupExtension]];
+ TestAllTypes_NestedMessage *optionalNestedMessage =
+ [message getExtension:[UnittestRoot optionalNestedMessageExtension]];
+ ForeignMessage *optionalForeignMessage =
+ [message getExtension:[UnittestRoot optionalForeignMessageExtension]];
+ ImportMessage *optionalImportMessage =
+ [message getExtension:[UnittestRoot optionalImportMessageExtension]];
+ PublicImportMessage *optionalPublicImportMessage = [message
+ getExtension:[UnittestRoot optionalPublicImportMessageExtension]];
+ TestAllTypes_NestedMessage *optionalLazyMessage =
+ [message getExtension:[UnittestRoot optionalLazyMessageExtension]];
+
+ XCTAssertNotNil(optionalGroup);
+ XCTAssertNotNil(optionalNestedMessage);
+ XCTAssertNotNil(optionalForeignMessage);
+ XCTAssertNotNil(optionalImportMessage);
+ XCTAssertNotNil(optionalPublicImportMessage);
+ XCTAssertNotNil(optionalLazyMessage);
+
+ // Although it auto-created empty messages, it should not show that it has
+ // them.
+
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalNestedMessageExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalForeignMessageExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalImportMessageExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalPublicImportMessageExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalLazyMessageExtension]]);
+
+ // And they set that value back in to the message since the value created was
+ // mutable (so a second fetch should give the same object).
+
+ XCTAssertEqual([message getExtension:[UnittestRoot optionalGroupExtension]],
+ optionalGroup);
+ XCTAssertEqual(
+ [message getExtension:[UnittestRoot optionalNestedMessageExtension]],
+ optionalNestedMessage);
+ XCTAssertEqual(
+ [message getExtension:[UnittestRoot optionalForeignMessageExtension]],
+ optionalForeignMessage);
+ XCTAssertEqual(
+ [message getExtension:[UnittestRoot optionalImportMessageExtension]],
+ optionalImportMessage);
+ XCTAssertEqual(
+ [message getExtension:[UnittestRoot optionalPublicImportMessageExtension]],
+ optionalPublicImportMessage);
+ XCTAssertEqual(
+ [message getExtension:[UnittestRoot optionalLazyMessageExtension]],
+ optionalLazyMessage);
+
+ // And the default objects for a second message should be distinct (again,
+ // since they are mutable, each needs their own copy).
+
+ TestAllExtensions *message2 = [TestAllExtensions message];
+
+ // Intentionally doing a pointer comparison.
+ XCTAssertNotEqual(
+ [message2 getExtension:[UnittestRoot optionalGroupExtension]],
+ optionalGroup);
+ XCTAssertNotEqual(
+ [message2 getExtension:[UnittestRoot optionalNestedMessageExtension]],
+ optionalNestedMessage);
+ XCTAssertNotEqual(
+ [message2 getExtension:[UnittestRoot optionalForeignMessageExtension]],
+ optionalForeignMessage);
+ XCTAssertNotEqual(
+ [message2 getExtension:[UnittestRoot optionalImportMessageExtension]],
+ optionalImportMessage);
+ XCTAssertNotEqual(
+ [message2 getExtension:[UnittestRoot optionalPublicImportMessageExtension]],
+ optionalPublicImportMessage);
+ XCTAssertNotEqual(
+ [message2 getExtension:[UnittestRoot optionalLazyMessageExtension]],
+ optionalLazyMessage);
+
+ // Clear values, and on next access you get back new submessages.
+
+ [message setExtension:[UnittestRoot optionalGroupExtension] value:nil];
+ [message setExtension:[UnittestRoot optionalGroupExtension] value:nil];
+ [message setExtension:[UnittestRoot optionalNestedMessageExtension]
+ value:nil];
+ [message setExtension:[UnittestRoot optionalForeignMessageExtension]
+ value:nil];
+ [message setExtension:[UnittestRoot optionalImportMessageExtension]
+ value:nil];
+ [message setExtension:[UnittestRoot optionalPublicImportMessageExtension]
+ value:nil];
+ [message setExtension:[UnittestRoot optionalLazyMessageExtension] value:nil];
+
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]);
+ XCTAssertFalse(
+ [message hasExtension:[UnittestRoot optionalNestedMessageExtension]]);
+ XCTAssertFalse(
+ [message hasExtension:[UnittestRoot optionalForeignMessageExtension]]);
+ XCTAssertFalse(
+ [message hasExtension:[UnittestRoot optionalImportMessageExtension]]);
+ XCTAssertFalse([message
+ hasExtension:[UnittestRoot optionalPublicImportMessageExtension]]);
+ XCTAssertFalse(
+ [message hasExtension:[UnittestRoot optionalLazyMessageExtension]]);
+
+ XCTAssertEqual([message getExtension:[UnittestRoot optionalGroupExtension]],
+ optionalGroup);
+ XCTAssertEqual(
+ [message getExtension:[UnittestRoot optionalNestedMessageExtension]],
+ optionalNestedMessage);
+ XCTAssertEqual(
+ [message getExtension:[UnittestRoot optionalForeignMessageExtension]],
+ optionalForeignMessage);
+ XCTAssertEqual(
+ [message getExtension:[UnittestRoot optionalImportMessageExtension]],
+ optionalImportMessage);
+ XCTAssertEqual(
+ [message
+ getExtension:[UnittestRoot optionalPublicImportMessageExtension]],
+ optionalPublicImportMessage);
+ XCTAssertEqual(
+ [message getExtension:[UnittestRoot optionalLazyMessageExtension]],
+ optionalLazyMessage);
+}
+
+- (void)testMultiplePointersToAutocreatedExtension {
+ // 2 objects point to the same auto-created extension. One should "has" it.
+ // The other should not.
+ TestAllExtensions *message = [TestAllExtensions message];
+ TestAllExtensions *message2 = [TestAllExtensions message];
+ GPBExtensionField *extension = [UnittestRoot optionalGroupExtension];
+ [message setExtension:extension value:[message2 getExtension:extension]];
+ XCTAssertEqual([message getExtension:extension],
+ [message2 getExtension:extension]);
+ XCTAssertFalse([message2 hasExtension:extension]);
+ XCTAssertTrue([message hasExtension:extension]);
+
+ TestAllTypes_OptionalGroup *extensionValue =
+ [message2 getExtension:extension];
+ extensionValue.a = 1;
+ XCTAssertTrue([message2 hasExtension:extension]);
+ XCTAssertTrue([message hasExtension:extension]);
+}
+
+- (void)testCopyWithAutocreatedExtension {
+ // Mutable copy shouldn't copy autocreated extensions.
+ TestAllExtensions *message = [TestAllExtensions message];
+ GPBExtensionField *optionalGroupExtension =
+ [UnittestRoot optionalGroupExtension];
+ GPBExtensionField *optionalNestedMessageExtesion =
+ [UnittestRoot optionalNestedMessageExtension];
+ TestAllTypes_OptionalGroup *optionalGroup =
+ [message getExtension:optionalGroupExtension];
+ optionalGroup.a = 42;
+ XCTAssertNotNil(optionalGroup);
+ XCTAssertNotNil([message getExtension:optionalNestedMessageExtesion]);
+ XCTAssertTrue([message hasExtension:optionalGroupExtension]);
+ XCTAssertFalse([message hasExtension:optionalNestedMessageExtesion]);
+
+ TestAllExtensions *message2 = [[message copy] autorelease];
+
+ // message2 should end up with its own copy of the optional group.
+ XCTAssertTrue([message2 hasExtension:optionalGroupExtension]);
+ XCTAssertEqualObjects([message getExtension:optionalGroupExtension],
+ [message2 getExtension:optionalGroupExtension]);
+ // Intentionally doing a pointer comparison.
+ XCTAssertNotEqual([message getExtension:optionalGroupExtension],
+ [message2 getExtension:optionalGroupExtension]);
+
+ XCTAssertFalse([message2 hasExtension:optionalNestedMessageExtesion]);
+ // Intentionally doing a pointer comparison (auto creation should be
+ // different)
+ XCTAssertNotEqual([message getExtension:optionalNestedMessageExtesion],
+ [message2 getExtension:optionalNestedMessageExtesion]);
+}
+
+- (void)testClearMessageAutocreatedExtension {
+ // Call clear should cause it to recreate its autocreated extensions.
+ TestAllExtensions *message = [TestAllExtensions message];
+ GPBExtensionField *optionalGroupExtension =
+ [UnittestRoot optionalGroupExtension];
+ TestAllTypes_OptionalGroup *optionalGroup =
+ [[message getExtension:optionalGroupExtension] retain];
+ [message clear];
+ TestAllTypes_OptionalGroup *optionalGroupNew =
+ [message getExtension:optionalGroupExtension];
+
+ // Intentionally doing a pointer comparison.
+ XCTAssertNotEqual(optionalGroup, optionalGroupNew);
+ [optionalGroup release];
+}
+
+- (void)testRetainAutocreatedExtension {
+ // Should be able to retain autocreated extension while the creator is
+ // dealloced.
+ TestAllExtensions *message = [TestAllExtensions message];
+ GPBExtensionField *optionalGroupExtension =
+ [UnittestRoot optionalGroupExtension];
+
+ @autoreleasepool {
+ TestAllExtensions *message2 = [TestAllExtensions message];
+ [message setExtension:optionalGroupExtension
+ value:[message2 getExtension:optionalGroupExtension]];
+ XCTAssertTrue(GPBWasMessageAutocreatedBy(
+ [message getExtension:optionalGroupExtension], message2));
+ }
+
+ XCTAssertFalse(GPBWasMessageAutocreatedBy(
+ [message getExtension:optionalGroupExtension], message));
+}
+
+- (void)testClearAutocreatedExtension {
+ // Clearing autocreated extension should NOT cause it to lose its creator.
+ TestAllExtensions *message = [TestAllExtensions message];
+ GPBExtensionField *optionalGroupExtension =
+ [UnittestRoot optionalGroupExtension];
+ TestAllTypes_OptionalGroup *optionalGroup =
+ [[message getExtension:optionalGroupExtension] retain];
+ [message clearExtension:optionalGroupExtension];
+ TestAllTypes_OptionalGroup *optionalGroupNew =
+ [message getExtension:optionalGroupExtension];
+ XCTAssertEqual(optionalGroup, optionalGroupNew);
+ XCTAssertFalse([message hasExtension:optionalGroupExtension]);
+ [optionalGroup release];
+
+ // Clearing autocreated extension should not cause its creator to become
+ // visible
+ GPBExtensionField *recursiveExtension = [UnittestObjcRoot recursiveExtension];
+ TestAllExtensions *message_lvl2 = [message getExtension:recursiveExtension];
+ TestAllExtensions *message_lvl3 =
+ [message_lvl2 getExtension:recursiveExtension];
+ [message_lvl3 clearExtension:recursiveExtension];
+ XCTAssertFalse([message hasExtension:recursiveExtension]);
+}
+
+- (void)testSetAutocreatedExtensionBecomesVisible {
+ // Setting an extension should cause the extension to appear to its creator.
+ // Test this several levels deep.
+ TestAllExtensions *message = [TestAllExtensions message];
+ GPBExtensionField *recursiveExtension = [UnittestObjcRoot recursiveExtension];
+ TestAllExtensions *message_lvl2 = [message getExtension:recursiveExtension];
+ TestAllExtensions *message_lvl3 =
+ [message_lvl2 getExtension:recursiveExtension];
+ TestAllExtensions *message_lvl4 =
+ [message_lvl3 getExtension:recursiveExtension];
+ XCTAssertFalse([message hasExtension:recursiveExtension]);
+ XCTAssertFalse([message_lvl2 hasExtension:recursiveExtension]);
+ XCTAssertFalse([message_lvl3 hasExtension:recursiveExtension]);
+ XCTAssertFalse([message_lvl4 hasExtension:recursiveExtension]);
+ [message_lvl4 setExtension:[UnittestRoot optionalInt32Extension] value:@(1)];
+ XCTAssertTrue([message hasExtension:recursiveExtension]);
+ XCTAssertTrue([message_lvl2 hasExtension:recursiveExtension]);
+ XCTAssertTrue([message_lvl3 hasExtension:recursiveExtension]);
+ XCTAssertFalse([message_lvl4 hasExtension:recursiveExtension]);
+ XCTAssertFalse(GPBWasMessageAutocreatedBy(message_lvl4, message_lvl3));
+ XCTAssertFalse(GPBWasMessageAutocreatedBy(message_lvl3, message_lvl2));
+ XCTAssertFalse(GPBWasMessageAutocreatedBy(message_lvl2, message));
+}
+
+- (void)testSetAutocreatedExtensionToSelf {
+ // Setting extension to itself should cause it to become visible.
+ TestAllExtensions *message = [TestAllExtensions message];
+ GPBExtensionField *optionalGroupExtension =
+ [UnittestRoot optionalGroupExtension];
+ XCTAssertNotNil([message getExtension:optionalGroupExtension]);
+ XCTAssertFalse([message hasExtension:optionalGroupExtension]);
+ [message setExtension:optionalGroupExtension
+ value:[message getExtension:optionalGroupExtension]];
+ XCTAssertTrue([message hasExtension:optionalGroupExtension]);
+}
+
+- (void)testAutocreatedExtensionMemoryLeaks {
+ GPBExtensionField *recursiveExtension = [UnittestObjcRoot recursiveExtension];
+
+ // Test for memory leaks with autocreated extensions.
+ TestAllExtensions *message;
+ TestAllExtensions *message_lvl2;
+ TestAllExtensions *message_lvl3;
+ TestAllExtensions *message_lvl4;
+ @autoreleasepool {
+ message = [[TestAllExtensions alloc] init];
+ message_lvl2 = [[message getExtension:recursiveExtension] retain];
+ message_lvl3 = [[message_lvl2 getExtension:recursiveExtension] retain];
+ message_lvl4 = [[message_lvl3 getExtension:recursiveExtension] retain];
+ [message_lvl2 setExtension:[UnittestRoot optionalInt32Extension]
+ value:@(1)];
+ }
+
+ XCTAssertEqual(message.retainCount, (NSUInteger)1);
+ @autoreleasepool {
+ [message release];
+ }
+ XCTAssertEqual(message_lvl2.retainCount, (NSUInteger)1);
+ @autoreleasepool {
+ [message_lvl2 release];
+ }
+ XCTAssertEqual(message_lvl3.retainCount, (NSUInteger)1);
+ @autoreleasepool {
+ [message_lvl3 release];
+ }
+ XCTAssertEqual(message_lvl4.retainCount, (NSUInteger)1);
+ [message_lvl4 release];
+}
+
+- (void)testSetExtensionWithAutocreatedValue {
+ GPBExtensionField *recursiveExtension = [UnittestObjcRoot recursiveExtension];
+
+ TestAllExtensions *message;
+ @autoreleasepool {
+ message = [[TestAllExtensions alloc] init];
+ [message getExtension:recursiveExtension];
+ }
+
+ // This statements checks that the extension value isn't accidentally
+ // dealloced when removing it from the autocreated map.
+ [message setExtension:recursiveExtension
+ value:[message getExtension:recursiveExtension]];
+ XCTAssertTrue([message hasExtension:recursiveExtension]);
+ [message release];
+}
+
+- (void)testRecursion {
+ TestRecursiveMessage *message = [TestRecursiveMessage message];
+ XCTAssertNotNil(message.a);
+ XCTAssertNotNil(message.a.a);
+ XCTAssertEqual(message.a.a.i, 0);
+}
+
+- (void)testGenerateAndParseUnknownMessage {
+ GPBUnknownFieldSet *unknowns =
+ [[[GPBUnknownFieldSet alloc] init] autorelease];
+ [unknowns mergeVarintField:123 value:456];
+ GPBMessage *message = [GPBMessage message];
+ [message setUnknownFields:unknowns];
+ NSData *data = [message data];
+ GPBMessage *message2 = [GPBMessage parseFromData:data extensionRegistry:nil];
+ XCTAssertEqualObjects(message, message2);
+}
+
+- (void)testDelimitedWriteAndParseMultipleMessages {
+ GPBUnknownFieldSet *unknowns1 =
+ [[[GPBUnknownFieldSet alloc] init] autorelease];
+ [unknowns1 mergeVarintField:123 value:456];
+ GPBMessage *message1 = [GPBMessage message];
+ [message1 setUnknownFields:unknowns1];
+
+ GPBUnknownFieldSet *unknowns2 =
+ [[[GPBUnknownFieldSet alloc] init] autorelease];
+ [unknowns2 mergeVarintField:789 value:987];
+ [unknowns2 mergeVarintField:654 value:321];
+ GPBMessage *message2 = [GPBMessage message];
+ [message2 setUnknownFields:unknowns2];
+
+ NSMutableData *delimitedData = [NSMutableData data];
+ [delimitedData appendData:[message1 delimitedData]];
+ [delimitedData appendData:[message2 delimitedData]];
+ GPBCodedInputStream *input =
+ [GPBCodedInputStream streamWithData:delimitedData];
+ GPBMessage *message3 = [GPBMessage parseDelimitedFromCodedInputStream:input
+ extensionRegistry:nil];
+ GPBMessage *message4 = [GPBMessage parseDelimitedFromCodedInputStream:input
+ extensionRegistry:nil];
+ XCTAssertEqualObjects(message1, message3);
+ XCTAssertEqualObjects(message2, message4);
+}
+
+- (void)testDuplicateEnums {
+ XCTAssertEqual(TestEnumWithDupValue_Foo1, TestEnumWithDupValue_Foo2);
+}
+
+- (void)testWeirdDefaults {
+ ObjcWeirdDefaults *message = [ObjcWeirdDefaults message];
+ GPBDescriptor *descriptor = [[message class] descriptor];
+ GPBFieldDescriptor *fieldDesc = [descriptor fieldWithName:@"foo"];
+ XCTAssertNotNil(fieldDesc);
+ XCTAssertTrue(fieldDesc.hasDefaultValue);
+ XCTAssertFalse(message.hasFoo);
+ XCTAssertEqualObjects(message.foo, @"");
+
+ fieldDesc = [descriptor fieldWithName:@"bar"];
+ XCTAssertNotNil(fieldDesc);
+ XCTAssertTrue(fieldDesc.hasDefaultValue);
+ XCTAssertFalse(message.hasBar);
+ XCTAssertEqualObjects(message.bar, GPBEmptyNSData());
+}
+
+- (void)testEnumDescriptorFromExtensionDescriptor {
+ GPBExtensionField *extField = [UnittestRoot optionalForeignEnumExtension];
+ GPBExtensionDescriptor *extDescriptor = extField.descriptor;
+ XCTAssertEqual(extDescriptor.type, GPBTypeEnum);
+ GPBEnumDescriptor *enumDescriptor = extDescriptor.enumDescriptor;
+ GPBEnumDescriptor *expectedDescriptor = ForeignEnum_EnumDescriptor();
+ XCTAssertEqualObjects(enumDescriptor, expectedDescriptor);
+}
+
+- (void)testEnumNaming {
+ // objectivec_helpers.cc has some interesting cases to deal with in
+ // EnumValueName/EnumValueShortName. Confirm that things generated as
+ // expected.
+
+ // This block just has to compile to confirm we got the expected types/names.
+ // The *_IsValidValue() calls are just there to keep the projects warnings
+ // flags happy by providing use of the variables/values.
+
+ Foo aFoo = Foo_SerializedSize;
+ Foo_IsValidValue(aFoo);
+ aFoo = Foo_Size;
+ Foo_IsValidValue(aFoo);
+
+ Category_Enum aCat = Category_Enum_Red;
+ Category_Enum_IsValidValue(aCat);
+
+ Time aTime = Time_Base;
+ Time_IsValidValue(aTime);
+ aTime = Time_SomethingElse;
+ Time_IsValidValue(aTime);
+
+ // This block confirms the names in the decriptors is what we wanted.
+
+ GPBEnumDescriptor *descriptor;
+ NSString *valueName;
+
+ descriptor = Foo_EnumDescriptor();
+ XCTAssertNotNil(descriptor);
+ XCTAssertEqualObjects(@"Foo", descriptor.name);
+ valueName = [descriptor enumNameForValue:Foo_SerializedSize];
+ XCTAssertEqualObjects(@"Foo_SerializedSize", valueName);
+ valueName = [descriptor enumNameForValue:Foo_Size];
+ XCTAssertEqualObjects(@"Foo_Size", valueName);
+
+ descriptor = Category_Enum_EnumDescriptor();
+ XCTAssertNotNil(descriptor);
+ XCTAssertEqualObjects(@"Category_Enum", descriptor.name);
+ valueName = [descriptor enumNameForValue:Category_Enum_Red];
+ XCTAssertEqualObjects(@"Category_Enum_Red", valueName);
+
+ descriptor = Time_EnumDescriptor();
+ XCTAssertNotNil(descriptor);
+ XCTAssertEqualObjects(@"Time", descriptor.name);
+ valueName = [descriptor enumNameForValue:Time_Base];
+ XCTAssertEqualObjects(@"Time_Base", valueName);
+ valueName = [descriptor enumNameForValue:Time_SomethingElse];
+ XCTAssertEqualObjects(@"Time_SomethingElse", valueName);
+}
+
+- (void)testNegativeEnums {
+ EnumTestMsg *msg = [EnumTestMsg message];
+
+ // Defaults
+ XCTAssertEqual(msg.foo, EnumTestMsg_MyEnum_Zero);
+ XCTAssertEqual(msg.bar, EnumTestMsg_MyEnum_One);
+ XCTAssertEqual(msg.baz, EnumTestMsg_MyEnum_NegOne);
+ // Bounce to wire and back.
+ EnumTestMsg *msgPrime = [EnumTestMsg parseFromData:[msg data]];
+ XCTAssertEqualObjects(msgPrime, msg);
+ XCTAssertEqual(msgPrime.foo, EnumTestMsg_MyEnum_Zero);
+ XCTAssertEqual(msgPrime.bar, EnumTestMsg_MyEnum_One);
+ XCTAssertEqual(msgPrime.baz, EnumTestMsg_MyEnum_NegOne);
+
+ // Other values
+ msg.bar = EnumTestMsg_MyEnum_Two;
+ msg.baz = EnumTestMsg_MyEnum_NegTwo;
+ XCTAssertEqual(msg.bar, EnumTestMsg_MyEnum_Two);
+ XCTAssertEqual(msg.baz, EnumTestMsg_MyEnum_NegTwo);
+ // Bounce to wire and back.
+ msgPrime = [EnumTestMsg parseFromData:[msg data]];
+ XCTAssertEqualObjects(msgPrime, msg);
+ XCTAssertEqual(msgPrime.foo, EnumTestMsg_MyEnum_Zero);
+ XCTAssertEqual(msgPrime.bar, EnumTestMsg_MyEnum_Two);
+ XCTAssertEqual(msgPrime.baz, EnumTestMsg_MyEnum_NegTwo);
+
+ // Repeated field (shouldn't ever be an issue since developer has to use the
+ // right GPBArray methods themselves).
+ msg.mumbleArray = [GPBEnumArray
+ arrayWithValidationFunction:EnumTestMsg_MyEnum_IsValidValue];
+ [msg.mumbleArray addValue:EnumTestMsg_MyEnum_Zero];
+ [msg.mumbleArray addValue:EnumTestMsg_MyEnum_One];
+ [msg.mumbleArray addValue:EnumTestMsg_MyEnum_Two];
+ [msg.mumbleArray addValue:EnumTestMsg_MyEnum_NegOne];
+ [msg.mumbleArray addValue:EnumTestMsg_MyEnum_NegTwo];
+ XCTAssertEqual([msg.mumbleArray valueAtIndex:0], EnumTestMsg_MyEnum_Zero);
+ XCTAssertEqual([msg.mumbleArray valueAtIndex:1], EnumTestMsg_MyEnum_One);
+ XCTAssertEqual([msg.mumbleArray valueAtIndex:2], EnumTestMsg_MyEnum_Two);
+ XCTAssertEqual([msg.mumbleArray valueAtIndex:3], EnumTestMsg_MyEnum_NegOne);
+ XCTAssertEqual([msg.mumbleArray valueAtIndex:4], EnumTestMsg_MyEnum_NegTwo);
+ // Bounce to wire and back.
+ msgPrime = [EnumTestMsg parseFromData:[msg data]];
+ XCTAssertEqualObjects(msgPrime, msg);
+ XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:0],
+ EnumTestMsg_MyEnum_Zero);
+ XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:1], EnumTestMsg_MyEnum_One);
+ XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:2], EnumTestMsg_MyEnum_Two);
+ XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:3],
+ EnumTestMsg_MyEnum_NegOne);
+ XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:4],
+ EnumTestMsg_MyEnum_NegTwo);
+}
+
+- (void)testMutableNameManagling {
+ // These basically confirm that all the expected name mangling happened by not
+ // having compile errors.
+
+ // TODO(thomasvl): Write these, see unittest_name_mangling.proto.
+}
+
+@end
diff --git a/objectivec/Tests/GPBPerfTests.m b/objectivec/Tests/GPBPerfTests.m
new file mode 100644
index 00000000..d09021af
--- /dev/null
+++ b/objectivec/Tests/GPBPerfTests.m
@@ -0,0 +1,306 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2013 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 "GPBTestUtilities.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+#import "google/protobuf/UnittestObjc.pbobjc.h"
+
+//
+// This file really just uses the unittests framework as a testbed to
+// run some simple performance tests. The data can then be used to help
+// evaluate changes to the runtime.
+//
+
+static const uint32_t kRepeatedCount = 100;
+
+@interface PerfTests : GPBTestCase
+@end
+
+@implementation PerfTests
+
+- (void)setUp {
+ // A convenient place to put a break point if you want to connect instruments.
+ [super setUp];
+}
+
+- (void)testMessagePerformance {
+ [self measureBlock:^{
+ for (int i = 0; i < 200; ++i) {
+ TestAllTypes* message = [[TestAllTypes alloc] init];
+ [self setAllFields:message repeatedCount:kRepeatedCount];
+ NSData* rawBytes = [message data];
+ [message release];
+ message = [[TestAllTypes alloc] initWithData:rawBytes];
+ [message release];
+ }
+ }];
+}
+
+- (void)testExtensionsPerformance {
+ [self measureBlock:^{
+ for (int i = 0; i < 200; ++i) {
+ TestAllExtensions* message = [[TestAllExtensions alloc] init];
+ [self setAllExtensions:message repeatedCount:kRepeatedCount];
+ NSData* rawBytes = [message data];
+ [message release];
+ TestAllExtensions* message2 =
+ [[TestAllExtensions alloc] initWithData:rawBytes];
+ [message2 release];
+ }
+ }];
+}
+
+- (void)testPackedTypesPerformance {
+ [self measureBlock:^{
+ for (int i = 0; i < 1000; ++i) {
+ TestPackedTypes* message = [[TestPackedTypes alloc] init];
+ [self setPackedFields:message repeatedCount:kRepeatedCount];
+ NSData* rawBytes = [message data];
+ [message release];
+ message = [[TestPackedTypes alloc] initWithData:rawBytes];
+ [message release];
+ }
+ }];
+}
+
+- (void)testPackedExtensionsPerformance {
+ [self measureBlock:^{
+ for (int i = 0; i < 1000; ++i) {
+ TestPackedExtensions* message = [[TestPackedExtensions alloc] init];
+ [self setPackedExtensions:message repeatedCount:kRepeatedCount];
+ NSData* rawBytes = [message data];
+ [message release];
+ TestPackedExtensions* message2 =
+ [[TestPackedExtensions alloc] initWithData:rawBytes];
+ [message2 release];
+ }
+ }];
+}
+
+- (void)testHas {
+ TestAllTypes* message = [self allSetRepeatedCount:1];
+ [self measureBlock:^{
+ for (int i = 0; i < 10000; ++i) {
+ [message hasOptionalInt32];
+ message.hasOptionalInt32 = NO;
+ [message hasOptionalInt32];
+
+ [message hasOptionalInt64];
+ message.hasOptionalInt64 = NO;
+ [message hasOptionalInt64];
+
+ [message hasOptionalUint32];
+ message.hasOptionalUint32 = NO;
+ [message hasOptionalUint32];
+
+ [message hasOptionalUint64];
+ message.hasOptionalUint64 = NO;
+ [message hasOptionalUint64];
+
+ [message hasOptionalSint32];
+ message.hasOptionalSint32 = NO;
+ [message hasOptionalSint32];
+
+ [message hasOptionalSint64];
+ message.hasOptionalSint64 = NO;
+ [message hasOptionalSint64];
+
+ [message hasOptionalFixed32];
+ message.hasOptionalFixed32 = NO;
+ [message hasOptionalFixed32];
+
+ [message hasOptionalFixed64];
+ message.hasOptionalFixed64 = NO;
+ [message hasOptionalFixed64];
+
+ [message hasOptionalSfixed32];
+ message.hasOptionalSfixed32 = NO;
+ [message hasOptionalSfixed32];
+
+ [message hasOptionalSfixed64];
+ message.hasOptionalSfixed64 = NO;
+ [message hasOptionalSfixed64];
+
+ [message hasOptionalFloat];
+ message.hasOptionalFloat = NO;
+ [message hasOptionalFloat];
+
+ [message hasOptionalDouble];
+ message.hasOptionalDouble = NO;
+ [message hasOptionalDouble];
+
+ [message hasOptionalBool];
+ message.hasOptionalBool = NO;
+ [message hasOptionalBool];
+
+ [message hasOptionalString];
+ message.hasOptionalString = NO;
+ [message hasOptionalString];
+
+ [message hasOptionalBytes];
+ message.hasOptionalBytes = NO;
+ [message hasOptionalBytes];
+
+ [message hasOptionalGroup];
+ message.hasOptionalGroup = NO;
+ [message hasOptionalGroup];
+
+ [message hasOptionalNestedMessage];
+ message.hasOptionalNestedMessage = NO;
+ [message hasOptionalNestedMessage];
+
+ [message hasOptionalForeignMessage];
+ message.hasOptionalForeignMessage = NO;
+ [message hasOptionalForeignMessage];
+
+ [message hasOptionalImportMessage];
+ message.hasOptionalImportMessage = NO;
+ [message hasOptionalImportMessage];
+
+ [message.optionalGroup hasA];
+ message.optionalGroup.hasA = NO;
+ [message.optionalGroup hasA];
+
+ [message.optionalNestedMessage hasBb];
+ message.optionalNestedMessage.hasBb = NO;
+ [message.optionalNestedMessage hasBb];
+
+ [message.optionalForeignMessage hasC];
+ message.optionalForeignMessage.hasC = NO;
+ [message.optionalForeignMessage hasC];
+
+ [message.optionalImportMessage hasD];
+ message.optionalImportMessage.hasD = NO;
+ [message.optionalImportMessage hasD];
+
+ [message hasOptionalNestedEnum];
+ message.hasOptionalNestedEnum = NO;
+ [message hasOptionalNestedEnum];
+
+ [message hasOptionalForeignEnum];
+ message.hasOptionalForeignEnum = NO;
+ [message hasOptionalForeignEnum];
+
+ [message hasOptionalImportEnum];
+ message.hasOptionalImportEnum = NO;
+ [message hasOptionalImportEnum];
+
+ [message hasOptionalStringPiece];
+ message.hasOptionalStringPiece = NO;
+ [message hasOptionalStringPiece];
+
+ [message hasOptionalCord];
+ message.hasOptionalCord = NO;
+ [message hasOptionalCord];
+
+ [message hasDefaultInt32];
+ message.hasDefaultInt32 = NO;
+ [message hasDefaultInt32];
+
+ [message hasDefaultInt64];
+ message.hasDefaultInt64 = NO;
+ [message hasDefaultInt64];
+
+ [message hasDefaultUint32];
+ message.hasDefaultUint32 = NO;
+ [message hasDefaultUint32];
+
+ [message hasDefaultUint64];
+ message.hasDefaultUint64 = NO;
+ [message hasDefaultUint64];
+
+ [message hasDefaultSint32];
+ message.hasDefaultSint32 = NO;
+ [message hasDefaultSint32];
+
+ [message hasDefaultSint64];
+ message.hasDefaultSint64 = NO;
+ [message hasDefaultSint64];
+
+ [message hasDefaultFixed32];
+ message.hasDefaultFixed32 = NO;
+ [message hasDefaultFixed32];
+
+ [message hasDefaultFixed64];
+ message.hasDefaultFixed64 = NO;
+ [message hasDefaultFixed64];
+
+ [message hasDefaultSfixed32];
+ message.hasDefaultSfixed32 = NO;
+ [message hasDefaultSfixed32];
+
+ [message hasDefaultSfixed64];
+ message.hasDefaultSfixed64 = NO;
+ [message hasDefaultSfixed64];
+
+ [message hasDefaultFloat];
+ message.hasDefaultFloat = NO;
+ [message hasDefaultFloat];
+
+ [message hasDefaultDouble];
+ message.hasDefaultDouble = NO;
+ [message hasDefaultDouble];
+
+ [message hasDefaultBool];
+ message.hasDefaultBool = NO;
+ [message hasDefaultBool];
+
+ [message hasDefaultString];
+ message.hasDefaultString = NO;
+ [message hasDefaultString];
+
+ [message hasDefaultBytes];
+ message.hasDefaultBytes = NO;
+ [message hasDefaultBytes];
+
+ [message hasDefaultNestedEnum];
+ message.hasDefaultNestedEnum = NO;
+ [message hasDefaultNestedEnum];
+
+ [message hasDefaultForeignEnum];
+ message.hasDefaultForeignEnum = NO;
+ [message hasDefaultForeignEnum];
+
+ [message hasDefaultImportEnum];
+ message.hasDefaultImportEnum = NO;
+ [message hasDefaultImportEnum];
+
+ [message hasDefaultStringPiece];
+ message.hasDefaultStringPiece = NO;
+ [message hasDefaultStringPiece];
+
+ [message hasDefaultCord];
+ message.hasDefaultCord = NO;
+ [message hasDefaultCord];
+ }
+ }];
+}
+
+@end
diff --git a/objectivec/Tests/GPBStringTests.m b/objectivec/Tests/GPBStringTests.m
new file mode 100644
index 00000000..30f13775
--- /dev/null
+++ b/objectivec/Tests/GPBStringTests.m
@@ -0,0 +1,516 @@
+// 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.
+
+#import <XCTest/XCTest.h>
+
+#import "GPBCodedInputStream_PackagePrivate.h"
+
+#ifndef GPBARRAYSIZE
+#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))))
+#endif // GPBARRAYSIZE
+
+@interface TestClass : NSObject
+@property(nonatomic, retain) NSString *foo;
+@end
+
+@implementation TestClass
+@synthesize foo;
+@end
+
+@interface GPBStringTests : XCTestCase {
+ NSMutableArray *nsStrings_;
+ NSMutableArray *gpbStrings_;
+}
+
+@end
+
+@implementation GPBStringTests
+
+- (void)setUp {
+ [super setUp];
+ const char *strings[] = {
+ "ascii string",
+ "non-ascii string \xc3\xa9", // e with acute accent
+ "\xe2\x99\xa1", // White Heart
+ "mix \xe2\x99\xa4 string", // White Spade
+
+ // Decomposed forms from http://www.unicode.org/reports/tr15/
+ // 1.2 Singletons
+ "\xe2\x84\xa8 = A\xcc\x8a = \xc3\x85", "\xe2\x84\xa6 = \xce\xa9",
+
+ // 1.2 Canonical Composites
+ "A\xcc\x8a = \xc3\x85",
+ "o\xcc\x82 = \xc3\xb4",
+
+ // 1.2 Multiple Combining Marks
+ "s\xcc\xa3\xcc\x87 = \xe1\xb9\xa9",
+ "\xe1\xb8\x8b\xcc\xa3 = d\xcc\xa3\xcc\x87 = \xe1\xb8\x8d \xcc\x87",
+ "q\xcc\x87\xcc\xa3 = q\xcc\xa3\xcc\x87",
+
+ // BOM
+ "\xEF\xBB\xBF String with BOM",
+ "String with \xEF\xBB\xBF in middle",
+ "String with end bom \xEF\xBB\xBF",
+ "\xEF\xBB\xBF\xe2\x99\xa1", // BOM White Heart
+ "\xEF\xBB\xBF\xEF\xBB\xBF String with Two BOM",
+
+ // Supplementary Plane
+ "\xf0\x9d\x84\x9e", // MUSICAL SYMBOL G CLEF
+
+ // Tags
+ "\xf3\xa0\x80\x81", // Language Tag
+
+ // Variation Selectors
+ "\xf3\xa0\x84\x80", // VARIATION SELECTOR-17
+
+ // Specials
+ "\xef\xbb\xbf\xef\xbf\xbd\xef\xbf\xbf",
+
+ // Left To Right/Right To Left
+ // http://unicode.org/reports/tr9/
+
+ // Hello! <RTL marker>!Merhaba<LTR marker>
+ "Hello! \xE2\x80\x8F!\xd9\x85\xd8\xb1\xd8\xad\xd8\xa8\xd8\xa7\xE2\x80\x8E",
+
+ "\xE2\x80\x8E LTR At Start",
+ "LTR At End\xE2\x80\x8E",
+ "\xE2\x80\x8F RTL At Start",
+ "RTL At End\xE2\x80\x8F",
+ "\xE2\x80\x8E\xE2\x80\x8E Double LTR \xE2\x80\x8E\xE2\x80\x8E",
+ "\xE2\x80\x8F\xE2\x80\x8F Double RTL \xE2\x80\x8F\xE2\x80\x8F",
+ "\xE2\x80\x8F\xE2\x80\x8E LTR-RTL LTR-RTL \xE2\x80\x8E\xE2\x80\x8F",
+ };
+ size_t stringsSize = GPBARRAYSIZE(strings);
+ size_t numberUnicodeStrings = 17375;
+ nsStrings_ = [[NSMutableArray alloc]
+ initWithCapacity:stringsSize + numberUnicodeStrings];
+ gpbStrings_ = [[NSMutableArray alloc]
+ initWithCapacity:stringsSize + numberUnicodeStrings];
+ for (size_t i = 0; i < stringsSize; ++i) {
+ size_t length = strlen(strings[i]);
+ NSString *nsString = [[NSString alloc] initWithBytes:strings[i]
+ length:length
+ encoding:NSUTF8StringEncoding];
+ [nsStrings_ addObject:nsString];
+ [nsString release];
+ GPBString *gpbString = GPBCreateGPBStringWithUTF8(strings[i], length);
+ [gpbStrings_ addObject:gpbString];
+ [gpbString release];
+ }
+
+ // Generate all UTF8 characters in a variety of strings
+ // UTF8-1 - 1 Byte UTF 8 chars
+ int length = 0x7F + 1;
+ char *buffer = (char *)calloc(length, 1);
+ for (int i = 0; i < length; ++i) {
+ buffer[i] = (char)i;
+ }
+ NSString *nsString = [[NSString alloc] initWithBytes:buffer
+ length:length
+ encoding:NSUTF8StringEncoding];
+ [nsStrings_ addObject:nsString];
+ [nsString release];
+ GPBString *gpbString = GPBCreateGPBStringWithUTF8(buffer, length);
+ [gpbStrings_ addObject:gpbString];
+ [gpbString release];
+
+ // UTF8-2 - 2 Byte UTF 8 chars
+ int pointLength = 0xbf - 0x80 + 1;
+ length = pointLength * 2;
+ buffer = (char *)calloc(length, 1);
+ for (int i = 0xc2; i <= 0xdf; ++i) {
+ char *bufferPtr = buffer;
+ for (int j = 0x80; j <= 0xbf; ++j) {
+ (*bufferPtr++) = (char)i;
+ (*bufferPtr++) = (char)j;
+ }
+ nsString = [[NSString alloc] initWithBytes:buffer
+ length:length
+ encoding:NSUTF8StringEncoding];
+ [nsStrings_ addObject:nsString];
+ [nsString release];
+ gpbString = GPBCreateGPBStringWithUTF8(buffer, length);
+ [gpbStrings_ addObject:gpbString];
+ [gpbString release];
+ }
+ free(buffer);
+
+ // UTF8-3 - 3 Byte UTF 8 chars
+ length = pointLength * 3;
+ buffer = (char *)calloc(length, 1);
+ for (int i = 0xa0; i <= 0xbf; ++i) {
+ char *bufferPtr = buffer;
+ for (int j = 0x80; j <= 0xbf; ++j) {
+ (*bufferPtr++) = (char)0xE0;
+ (*bufferPtr++) = (char)i;
+ (*bufferPtr++) = (char)j;
+ }
+ nsString = [[NSString alloc] initWithBytes:buffer
+ length:length
+ encoding:NSUTF8StringEncoding];
+ [nsStrings_ addObject:nsString];
+ [nsString release];
+ gpbString = GPBCreateGPBStringWithUTF8(buffer, length);
+ [gpbStrings_ addObject:gpbString];
+ [gpbString release];
+ }
+ for (int i = 0xe1; i <= 0xec; ++i) {
+ for (int j = 0x80; j <= 0xbf; ++j) {
+ char *bufferPtr = buffer;
+ for (int k = 0x80; k <= 0xbf; ++k) {
+ (*bufferPtr++) = (char)i;
+ (*bufferPtr++) = (char)j;
+ (*bufferPtr++) = (char)k;
+ }
+ nsString = [[NSString alloc] initWithBytes:buffer
+ length:length
+ encoding:NSUTF8StringEncoding];
+ [nsStrings_ addObject:nsString];
+ [nsString release];
+ gpbString = GPBCreateGPBStringWithUTF8(buffer, length);
+ [gpbStrings_ addObject:gpbString];
+ [gpbString release];
+ }
+ }
+ for (int i = 0x80; i <= 0x9f; ++i) {
+ char *bufferPtr = buffer;
+ for (int j = 0x80; j <= 0xbf; ++j) {
+ (*bufferPtr++) = (char)0xED;
+ (*bufferPtr++) = (char)i;
+ (*bufferPtr++) = (char)j;
+ }
+ nsString = [[NSString alloc] initWithBytes:buffer
+ length:length
+ encoding:NSUTF8StringEncoding];
+ [nsStrings_ addObject:nsString];
+ [nsString release];
+ gpbString = GPBCreateGPBStringWithUTF8(buffer, length);
+ [gpbStrings_ addObject:gpbString];
+ [gpbString release];
+ }
+ for (int i = 0xee; i <= 0xef; ++i) {
+ for (int j = 0x80; j <= 0xbf; ++j) {
+ char *bufferPtr = buffer;
+ for (int k = 0x80; k <= 0xbf; ++k) {
+ (*bufferPtr++) = (char)i;
+ (*bufferPtr++) = (char)j;
+ (*bufferPtr++) = (char)k;
+ }
+ nsString = [[NSString alloc] initWithBytes:buffer
+ length:length
+ encoding:NSUTF8StringEncoding];
+ [nsStrings_ addObject:nsString];
+ [nsString release];
+ gpbString = GPBCreateGPBStringWithUTF8(buffer, length);
+ [gpbStrings_ addObject:gpbString];
+ [gpbString release];
+ }
+ }
+ free(buffer);
+
+ // UTF8-4 - 4 Byte UTF 8 chars
+ length = pointLength * 4;
+ buffer = (char *)calloc(length, 1);
+ for (int i = 0x90; i <= 0xbf; ++i) {
+ for (int j = 0x80; j <= 0xbf; ++j) {
+ char *bufferPtr = buffer;
+ for (int k = 0x80; k <= 0xbf; ++k) {
+ (*bufferPtr++) = (char)0xF0;
+ (*bufferPtr++) = (char)i;
+ (*bufferPtr++) = (char)j;
+ (*bufferPtr++) = (char)k;
+ }
+ nsString = [[NSString alloc] initWithBytes:buffer
+ length:length
+ encoding:NSUTF8StringEncoding];
+ [nsStrings_ addObject:nsString];
+ [nsString release];
+ gpbString = GPBCreateGPBStringWithUTF8(buffer, length);
+ [gpbStrings_ addObject:gpbString];
+ [gpbString release];
+ }
+ }
+ for (int i = 0xf1; i <= 0xf3; ++i) {
+ for (int j = 0x80; j <= 0xbf; ++j) {
+ for (int k = 0x80; k <= 0xbf; ++k) {
+ char *bufferPtr = buffer;
+ for (int m = 0x80; m <= 0xbf; ++m) {
+ (*bufferPtr++) = (char)i;
+ (*bufferPtr++) = (char)j;
+ (*bufferPtr++) = (char)k;
+ (*bufferPtr++) = (char)m;
+ }
+ nsString = [[NSString alloc] initWithBytes:buffer
+ length:length
+ encoding:NSUTF8StringEncoding];
+ [nsStrings_ addObject:nsString];
+ [nsString release];
+ gpbString = GPBCreateGPBStringWithUTF8(buffer, length);
+ [gpbStrings_ addObject:gpbString];
+ [gpbString release];
+ }
+ }
+ }
+ for (int i = 0x80; i <= 0x8f; ++i) {
+ for (int j = 0x80; j <= 0xbf; ++j) {
+ char *bufferPtr = buffer;
+ for (int k = 0x80; k <= 0xbf; ++k) {
+ (*bufferPtr++) = (char)0xF4;
+ (*bufferPtr++) = (char)i;
+ (*bufferPtr++) = (char)j;
+ (*bufferPtr++) = (char)k;
+ }
+ nsString = [[NSString alloc] initWithBytes:buffer
+ length:length
+ encoding:NSUTF8StringEncoding];
+ [nsStrings_ addObject:nsString];
+ [nsString release];
+ gpbString = GPBCreateGPBStringWithUTF8(buffer, length);
+ [gpbStrings_ addObject:gpbString];
+ [gpbString release];
+ }
+ }
+ free(buffer);
+}
+
+- (void)tearDown {
+ [nsStrings_ release];
+ [gpbStrings_ release];
+ [super tearDown];
+}
+
+- (void)testLength {
+ size_t i = 0;
+ for (NSString *nsString in nsStrings_) {
+ GPBString *gpbString = gpbStrings_[i];
+ XCTAssertEqual([nsString length], [gpbString length], @"%@ %@", nsString,
+ gpbString);
+ ++i;
+ }
+}
+
+- (void)testLengthOfBytesUsingEncoding {
+ NSStringEncoding encodings[] = {
+ NSUTF8StringEncoding,
+ NSASCIIStringEncoding,
+ NSISOLatin1StringEncoding,
+ NSMacOSRomanStringEncoding,
+ NSUTF16StringEncoding,
+ NSUTF32StringEncoding,
+ };
+
+ for (size_t j = 0; j < GPBARRAYSIZE(encodings); ++j) {
+ NSStringEncoding testEncoding = encodings[j];
+ size_t i = 0;
+ for (NSString *nsString in nsStrings_) {
+ GPBString *gpbString = gpbStrings_[i];
+ XCTAssertEqual([nsString lengthOfBytesUsingEncoding:testEncoding],
+ [gpbString lengthOfBytesUsingEncoding:testEncoding],
+ @"%@ %@", nsString, gpbString);
+ ++i;
+ }
+ }
+}
+
+- (void)testHash {
+ size_t i = 0;
+ for (NSString *nsString in nsStrings_) {
+ GPBString *gpbString = gpbStrings_[i];
+ XCTAssertEqual([nsString hash], [gpbString hash], @"%@ %@", nsString,
+ gpbString);
+ ++i;
+ }
+}
+
+- (void)testEquality {
+ size_t i = 0;
+ for (NSString *nsString in nsStrings_) {
+ GPBString *gpbString = gpbStrings_[i];
+ XCTAssertEqualObjects(nsString, gpbString);
+ ++i;
+ }
+}
+
+- (void)testCharacterAtIndex {
+ size_t i = 0;
+ for (NSString *nsString in nsStrings_) {
+ GPBString *gpbString = gpbStrings_[i];
+ NSUInteger length = [nsString length];
+ for (size_t j = 0; j < length; ++j) {
+ unichar nsChar = [nsString characterAtIndex:j];
+ unichar pbChar = [gpbString characterAtIndex:j];
+ XCTAssertEqual(nsChar, pbChar, @"%@ %@ %zu", nsString, gpbString, j);
+ }
+ ++i;
+ }
+}
+
+- (void)testCopy {
+ size_t i = 0;
+ for (NSString *nsString in nsStrings_) {
+ GPBString *gpbString = [[gpbStrings_[i] copy] autorelease];
+ XCTAssertEqualObjects(nsString, gpbString);
+ ++i;
+ }
+}
+
+- (void)testMutableCopy {
+ size_t i = 0;
+ for (NSString *nsString in nsStrings_) {
+ GPBString *gpbString = [[gpbStrings_[i] mutableCopy] autorelease];
+ XCTAssertEqualObjects(nsString, gpbString);
+ ++i;
+ }
+}
+
+- (void)testGetBytes {
+ // Do an attempt at a reasonably exhaustive test of get bytes.
+ // Get bytes with options other than 0 should always fall through to Apple
+ // code so we don't bother testing that path.
+ size_t i = 0;
+ char pbBuffer[256];
+ char nsBuffer[256];
+ int count = 0;
+ for (NSString *nsString in nsStrings_) {
+ GPBString *gpbString = gpbStrings_[i];
+ for (int j = 0; j < 100; ++j) {
+ // [NSString getBytes:maxLength:usedLength:encoding:options:range:remainingRange]
+ // does not return reliable results if the maxLength argument is 0,
+ // or range is 0,0.
+ // Radar 16385183
+ NSUInteger length = [nsString length];
+ NSUInteger maxBufferCount = (arc4random() % (length + 3)) + 1;
+ NSUInteger rangeStart = arc4random() % length;
+ NSUInteger rangeLength = arc4random() % (length - rangeStart);
+
+ NSRange range = NSMakeRange(rangeStart, rangeLength);
+
+ NSStringEncoding encodings[] = {
+ NSASCIIStringEncoding,
+ NSUTF8StringEncoding,
+ NSUTF16StringEncoding,
+ };
+
+ for (size_t k = 0; k < GPBARRAYSIZE(encodings); ++k) {
+ NSStringEncoding encoding = encodings[k];
+ NSUInteger pbUsedBufferCount = 0;
+ NSUInteger nsUsedBufferCount = 0;
+ NSRange pbLeftOver = NSMakeRange(0, 0);
+ NSRange nsLeftOver = NSMakeRange(0, 0);
+
+ BOOL pbGotBytes = [gpbString getBytes:pbBuffer
+ maxLength:maxBufferCount
+ usedLength:&pbUsedBufferCount
+ encoding:encoding
+ options:0
+ range:range
+ remainingRange:&pbLeftOver];
+ BOOL nsGotBytes = [nsString getBytes:nsBuffer
+ maxLength:maxBufferCount
+ usedLength:&nsUsedBufferCount
+ encoding:encoding
+ options:0
+ range:range
+ remainingRange:&nsLeftOver];
+ XCTAssertEqual(
+ (bool)pbGotBytes, (bool)nsGotBytes,
+ @"PB %d '%@' vs '%@' Encoding:%tu MaxLength: %tu Range: %@ "
+ @"Used: %tu, %tu LeftOver %@, %@)",
+ count, gpbString, nsString, encoding, maxBufferCount,
+ NSStringFromRange(range), pbUsedBufferCount, nsUsedBufferCount,
+ NSStringFromRange(pbLeftOver), NSStringFromRange(nsLeftOver));
+ XCTAssertEqual(
+ pbUsedBufferCount, nsUsedBufferCount,
+ @"PB %d '%@' vs '%@' Encoding:%tu MaxLength: %tu Range: %@ "
+ @"Used: %tu, %tu LeftOver %@, %@)",
+ count, gpbString, nsString, encoding, maxBufferCount,
+ NSStringFromRange(range), pbUsedBufferCount, nsUsedBufferCount,
+ NSStringFromRange(pbLeftOver), NSStringFromRange(nsLeftOver));
+ XCTAssertEqual(
+ pbLeftOver.location, nsLeftOver.location,
+ @"PB %d '%@' vs '%@' Encoding:%tu MaxLength: %tu Range: %@ "
+ @"Used: %tu, %tu LeftOver %@, %@)",
+ count, gpbString, nsString, encoding, maxBufferCount,
+ NSStringFromRange(range), pbUsedBufferCount, nsUsedBufferCount,
+ NSStringFromRange(pbLeftOver), NSStringFromRange(nsLeftOver));
+ XCTAssertEqual(
+ pbLeftOver.length, nsLeftOver.length,
+ @"PB %d '%@' vs '%@' Encoding:%tu MaxLength: %tu Range: %@ "
+ @"Used: %tu, %tu LeftOver %@, %@)",
+ count, gpbString, nsString, encoding, maxBufferCount,
+ NSStringFromRange(range), pbUsedBufferCount, nsUsedBufferCount,
+ NSStringFromRange(pbLeftOver), NSStringFromRange(nsLeftOver));
+ ++count;
+ }
+ }
+ ++i;
+ }
+}
+
+- (void)testLengthAndGetBytes {
+ // This test exists as an attempt to ferret out a bug.
+ // http://b/13516532
+ size_t i = 0;
+ char pbBuffer[256];
+ char nsBuffer[256];
+ for (NSString *nsString in nsStrings_) {
+ GPBString *gpbString = gpbStrings_[i++];
+ NSUInteger nsLength =
+ [nsString lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
+ NSUInteger pbLength =
+ [gpbString lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
+ XCTAssertEqual(nsLength, pbLength, @"%@ %@", nsString, gpbString);
+ NSUInteger pbUsedBufferCount = 0;
+ NSUInteger nsUsedBufferCount = 0;
+ NSRange pbLeftOver = NSMakeRange(0, 0);
+ NSRange nsLeftOver = NSMakeRange(0, 0);
+ NSRange range = NSMakeRange(0, [gpbString length]);
+ BOOL pbGotBytes = [gpbString getBytes:pbBuffer
+ maxLength:sizeof(pbBuffer)
+ usedLength:&pbUsedBufferCount
+ encoding:NSUTF8StringEncoding
+ options:0
+ range:range
+ remainingRange:&pbLeftOver];
+ BOOL nsGotBytes = [nsString getBytes:nsBuffer
+ maxLength:sizeof(nsBuffer)
+ usedLength:&nsUsedBufferCount
+ encoding:NSUTF8StringEncoding
+ options:0
+ range:range
+ remainingRange:&nsLeftOver];
+ XCTAssertTrue(pbGotBytes, @"%@", gpbString);
+ XCTAssertTrue(nsGotBytes, @"%@", nsString);
+ XCTAssertEqual(pbUsedBufferCount, pbLength, @"%@", gpbString);
+ XCTAssertEqual(nsUsedBufferCount, nsLength, @"%@", nsString);
+ }
+}
+
+@end
diff --git a/objectivec/Tests/GPBSwiftTests.swift b/objectivec/Tests/GPBSwiftTests.swift
new file mode 100644
index 00000000..e7b6f94c
--- /dev/null
+++ b/objectivec/Tests/GPBSwiftTests.swift
@@ -0,0 +1,405 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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
+import XCTest
+
+// Test some usage of the ObjC library from Swift.
+
+class GPBBridgeTests: XCTestCase {
+
+ func testProto2Basics() {
+ let msg = Message2()
+ let msg2 = Message2()
+ let msg3 = Message2_OptionalGroup()
+
+ msg.optionalInt32 = 100
+ msg.optionalString = "abc"
+ msg.optionalEnum = .Bar
+ msg2.optionalString = "other"
+ msg.optionalMessage = msg2
+ msg3.a = 200
+ msg.optionalGroup = msg3
+ msg.repeatedInt32Array.addValue(300)
+ msg.repeatedInt32Array.addValue(301)
+ msg.repeatedStringArray.addObject("mno")
+ msg.repeatedStringArray.addObject("pqr")
+ msg.repeatedEnumArray.addValue(Message2_Enum.Bar.rawValue)
+ msg.repeatedEnumArray.addValue(Message2_Enum.Baz.rawValue)
+
+ // Check has*.
+ XCTAssertTrue(msg.hasOptionalInt32)
+ XCTAssertTrue(msg.hasOptionalString)
+ XCTAssertTrue(msg.hasOptionalEnum)
+ XCTAssertTrue(msg2.hasOptionalString)
+ XCTAssertTrue(msg.hasOptionalMessage)
+ XCTAssertTrue(msg3.hasA)
+ XCTAssertTrue(msg.hasOptionalGroup)
+ XCTAssertFalse(msg.hasOptionalInt64)
+ XCTAssertFalse(msg.hasOptionalFloat)
+
+ // Check values.
+ XCTAssertEqual(msg.optionalInt32, Int32(100))
+ XCTAssertEqual(msg.optionalString, "abc")
+ XCTAssertEqual(msg2.optionalString, "other")
+ XCTAssertTrue(msg.optionalMessage === msg2)
+ XCTAssertEqual(msg.optionalEnum, Message2_Enum.Bar)
+ XCTAssertEqual(msg3.a, Int32(200))
+ XCTAssertTrue(msg.optionalGroup === msg3)
+ XCTAssertEqual(msg.repeatedInt32Array.count, UInt(2))
+ XCTAssertEqual(msg.repeatedInt32Array.valueAtIndex(0), Int32(300))
+ XCTAssertEqual(msg.repeatedInt32Array.valueAtIndex(1), Int32(301))
+ XCTAssertEqual(msg.repeatedStringArray.count, Int(2))
+ XCTAssertEqual(msg.repeatedStringArray.objectAtIndex(0) as! String, "mno")
+ XCTAssertEqual(msg.repeatedStringArray.objectAtIndex(1) as! String, "pqr")
+ XCTAssertEqual(msg.repeatedEnumArray.count, UInt(2))
+ XCTAssertEqual(msg.repeatedEnumArray.valueAtIndex(0), Message2_Enum.Bar.rawValue)
+ XCTAssertEqual(msg.repeatedEnumArray.valueAtIndex(1), Message2_Enum.Baz.rawValue)
+ XCTAssertEqual(msg.repeatedInt64Array.count, UInt(0))
+
+ // Clearing a string with nil.
+ msg2.optionalString = nil
+ XCTAssertFalse(msg2.hasOptionalString)
+ XCTAssertEqual(msg2.optionalString, "")
+
+ // Clearing a message with nil.
+ msg.optionalGroup = nil
+ XCTAssertFalse(msg.hasOptionalGroup)
+ XCTAssertTrue(msg.optionalGroup !== msg3) // New instance
+
+ // Clear.
+ msg.clear()
+ XCTAssertFalse(msg.hasOptionalInt32)
+ XCTAssertFalse(msg.hasOptionalString)
+ XCTAssertFalse(msg.hasOptionalEnum)
+ XCTAssertFalse(msg.hasOptionalMessage)
+ XCTAssertFalse(msg.hasOptionalInt64)
+ XCTAssertFalse(msg.hasOptionalFloat)
+ XCTAssertEqual(msg.optionalInt32, Int32(0))
+ XCTAssertEqual(msg.optionalString, "")
+ XCTAssertTrue(msg.optionalMessage !== msg2) // New instance
+ XCTAssertEqual(msg.optionalEnum, Message2_Enum.Foo) // Default
+ XCTAssertEqual(msg.repeatedInt32Array.count, UInt(0))
+ XCTAssertEqual(msg.repeatedStringArray.count, Int(0))
+ XCTAssertEqual(msg.repeatedEnumArray.count, UInt(0))
+ }
+
+ func testProto3Basics() {
+ let msg = Message3()
+ let msg2 = Message3()
+
+ msg.optionalInt32 = 100
+ msg.optionalString = "abc"
+ msg.optionalEnum = .Bar
+ msg2.optionalString = "other"
+ msg.optionalMessage = msg2
+ msg.repeatedInt32Array.addValue(300)
+ msg.repeatedInt32Array.addValue(301)
+ msg.repeatedStringArray.addObject("mno")
+ msg.repeatedStringArray.addObject("pqr")
+ // "proto3" syntax lets enum get unknown values.
+ msg.repeatedEnumArray.addValue(Message3_Enum.Bar.rawValue)
+ msg.repeatedEnumArray.addRawValue(666)
+ SetMessage3_OptionalEnum_RawValue(msg2, 666)
+
+ // Has only exists on for message fields.
+ XCTAssertTrue(msg.hasOptionalMessage)
+ XCTAssertFalse(msg2.hasOptionalMessage)
+
+ // Check values.
+ XCTAssertEqual(msg.optionalInt32, Int32(100))
+ XCTAssertEqual(msg.optionalString, "abc")
+ XCTAssertEqual(msg2.optionalString, "other")
+ XCTAssertTrue(msg.optionalMessage === msg2)
+ XCTAssertEqual(msg.optionalEnum, Message3_Enum.Bar)
+ XCTAssertEqual(msg.repeatedInt32Array.count, UInt(2))
+ XCTAssertEqual(msg.repeatedInt32Array.valueAtIndex(0), Int32(300))
+ XCTAssertEqual(msg.repeatedInt32Array.valueAtIndex(1), Int32(301))
+ XCTAssertEqual(msg.repeatedStringArray.count, Int(2))
+ XCTAssertEqual(msg.repeatedStringArray.objectAtIndex(0) as! String, "mno")
+ XCTAssertEqual(msg.repeatedStringArray.objectAtIndex(1) as! String, "pqr")
+ XCTAssertEqual(msg.repeatedInt64Array.count, UInt(0))
+ XCTAssertEqual(msg.repeatedEnumArray.count, UInt(2))
+ XCTAssertEqual(msg.repeatedEnumArray.valueAtIndex(0), Message3_Enum.Bar.rawValue)
+ XCTAssertEqual(msg.repeatedEnumArray.valueAtIndex(1), Message3_Enum.GPBUnrecognizedEnumeratorValue.rawValue)
+ XCTAssertEqual(msg.repeatedEnumArray.rawValueAtIndex(1), 666)
+ XCTAssertEqual(msg2.optionalEnum, Message3_Enum.GPBUnrecognizedEnumeratorValue)
+ XCTAssertEqual(Message3_OptionalEnum_RawValue(msg2), Int32(666))
+
+ // Clearing a string with nil.
+ msg2.optionalString = nil
+ XCTAssertEqual(msg2.optionalString, "")
+
+ // Clearing a message with nil.
+ msg.optionalMessage = nil
+ XCTAssertFalse(msg.hasOptionalMessage)
+ XCTAssertTrue(msg.optionalMessage !== msg2) // New instance
+
+ // Clear.
+ msg.clear()
+ XCTAssertFalse(msg.hasOptionalMessage)
+ XCTAssertEqual(msg.optionalInt32, Int32(0))
+ XCTAssertEqual(msg.optionalString, "")
+ XCTAssertTrue(msg.optionalMessage !== msg2) // New instance
+ XCTAssertEqual(msg.optionalEnum, Message3_Enum.Foo) // Default
+ XCTAssertEqual(msg.repeatedInt32Array.count, UInt(0))
+ XCTAssertEqual(msg.repeatedStringArray.count, Int(0))
+ XCTAssertEqual(msg.repeatedEnumArray.count, UInt(0))
+ msg2.clear()
+ XCTAssertEqual(msg2.optionalEnum, Message3_Enum.Foo) // Default
+ XCTAssertEqual(Message3_OptionalEnum_RawValue(msg2), Message3_Enum.Foo.rawValue)
+ }
+
+ func testAutoCreation() {
+ let msg = Message2()
+
+ XCTAssertFalse(msg.hasOptionalGroup)
+ XCTAssertFalse(msg.hasOptionalMessage)
+
+ // Access shouldn't result in has* but should return objects.
+ let msg2 = msg.optionalGroup
+ let msg3 = msg.optionalMessage.optionalMessage
+ let msg4 = msg.optionalMessage
+ XCTAssertNotNil(msg2)
+ XCTAssertNotNil(msg3)
+ XCTAssertFalse(msg.hasOptionalGroup)
+ XCTAssertFalse(msg.optionalMessage.hasOptionalMessage)
+ XCTAssertFalse(msg.hasOptionalMessage)
+
+ // Setting things should trigger has* getting set.
+ msg.optionalGroup.a = 10
+ msg.optionalMessage.optionalMessage.optionalInt32 = 100
+ XCTAssertTrue(msg.hasOptionalGroup)
+ XCTAssertTrue(msg.optionalMessage.hasOptionalMessage)
+ XCTAssertTrue(msg.hasOptionalMessage)
+
+ // And they should be the same pointer as before.
+ XCTAssertTrue(msg2 === msg.optionalGroup)
+ XCTAssertTrue(msg3 === msg.optionalMessage.optionalMessage)
+ XCTAssertTrue(msg4 === msg.optionalMessage)
+
+ // Clear gets us new objects next time around.
+ msg.clear()
+ XCTAssertFalse(msg.hasOptionalGroup)
+ XCTAssertFalse(msg.optionalMessage.hasOptionalMessage)
+ XCTAssertFalse(msg.hasOptionalMessage)
+ msg.optionalGroup.a = 20
+ msg.optionalMessage.optionalMessage.optionalInt32 = 200
+ XCTAssertTrue(msg.hasOptionalGroup)
+ XCTAssertTrue(msg.optionalMessage.hasOptionalMessage)
+ XCTAssertTrue(msg.hasOptionalMessage)
+ XCTAssertTrue(msg2 !== msg.optionalGroup)
+ XCTAssertTrue(msg3 !== msg.optionalMessage.optionalMessage)
+ XCTAssertTrue(msg4 !== msg.optionalMessage)
+
+ // Explicit set of a message, means autocreated object doesn't bind.
+ msg.clear()
+ let autoCreated = msg.optionalMessage
+ XCTAssertFalse(msg.hasOptionalMessage)
+ let msg5 = Message2()
+ msg5.optionalInt32 = 123
+ msg.optionalMessage = msg5
+ XCTAssertTrue(msg.hasOptionalMessage)
+ // Modifing the autocreated doesn't replaced the explicit set one.
+ autoCreated.optionalInt32 = 456
+ XCTAssertTrue(msg.hasOptionalMessage)
+ XCTAssertTrue(msg.optionalMessage === msg5)
+ XCTAssertEqual(msg.optionalMessage.optionalInt32, Int32(123))
+ }
+
+ func testProto2OneOfSupport() {
+ let msg = Message2()
+
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.GPBUnsetOneOfCase)
+ XCTAssertEqual(msg.oneofInt32, Int32(100)) // Default
+ XCTAssertEqual(msg.oneofFloat, Float(110.0)) // Default
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum.Baz) // Default
+ let autoCreated = msg.oneofMessage // Default create one.
+ XCTAssertNotNil(autoCreated)
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.GPBUnsetOneOfCase)
+
+ msg.oneofInt32 = 10
+ XCTAssertEqual(msg.oneofInt32, Int32(10))
+ XCTAssertEqual(msg.oneofFloat, Float(110.0)) // Default
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum.Baz) // Default
+ XCTAssertTrue(msg.oneofMessage === autoCreated) // Still the same
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.OneofInt32)
+
+ msg.oneofFloat = 20.0
+ XCTAssertEqual(msg.oneofInt32, Int32(100)) // Default
+ XCTAssertEqual(msg.oneofFloat, Float(20.0))
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum.Baz) // Default
+ XCTAssertTrue(msg.oneofMessage === autoCreated) // Still the same
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.OneofFloat)
+
+ msg.oneofEnum = .Bar
+ XCTAssertEqual(msg.oneofInt32, Int32(100)) // Default
+ XCTAssertEqual(msg.oneofFloat, Float(110.0)) // Default
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum.Bar)
+ XCTAssertTrue(msg.oneofMessage === autoCreated) // Still the same
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.OneofEnum)
+
+ // Sets via the autocreated instance.
+ msg.oneofMessage.optionalInt32 = 200
+ XCTAssertEqual(msg.oneofInt32, Int32(100)) // Default
+ XCTAssertEqual(msg.oneofFloat, Float(110.0)) // Default
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum.Baz) // Default
+ XCTAssertTrue(msg.oneofMessage === autoCreated) // Still the same
+ XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(200))
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.OneofMessage)
+
+ // Clear the oneof.
+ Message2_ClearOOneOfCase(msg)
+ XCTAssertEqual(msg.oneofInt32, Int32(100)) // Default
+ XCTAssertEqual(msg.oneofFloat, Float(110.0)) // Default
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum.Baz) // Default
+ let autoCreated2 = msg.oneofMessage // Default create one
+ XCTAssertNotNil(autoCreated2)
+ XCTAssertTrue(autoCreated2 !== autoCreated) // New instance
+ XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(0)) // Default
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.GPBUnsetOneOfCase)
+
+ msg.oneofInt32 = 10
+ XCTAssertEqual(msg.oneofInt32, Int32(10))
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.OneofInt32)
+
+ // Confirm Message.clear() handles the oneof correctly.
+ msg.clear()
+ XCTAssertEqual(msg.oneofInt32, Int32(100)) // Default
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.GPBUnsetOneOfCase)
+
+ // Sets via the autocreated instance.
+ msg.oneofMessage.optionalInt32 = 300
+ XCTAssertTrue(msg.oneofMessage !== autoCreated) // New instance
+ XCTAssertTrue(msg.oneofMessage !== autoCreated2) // New instance
+ XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(300))
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.OneofMessage)
+
+ // Set message to nil clears the oneof.
+ msg.oneofMessage = nil
+ XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(0)) // Default
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.GPBUnsetOneOfCase)
+}
+
+ func testProto3OneOfSupport() {
+ let msg = Message3()
+
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.GPBUnsetOneOfCase)
+ XCTAssertEqual(msg.oneofInt32, Int32(0)) // Default
+ XCTAssertEqual(msg.oneofFloat, Float(0.0)) // Default
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum.Foo) // Default
+ let autoCreated = msg.oneofMessage // Default create one.
+ XCTAssertNotNil(autoCreated)
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.GPBUnsetOneOfCase)
+
+ msg.oneofInt32 = 10
+ XCTAssertEqual(msg.oneofInt32, Int32(10))
+ XCTAssertEqual(msg.oneofFloat, Float(0.0)) // Default
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum.Foo) // Default
+ XCTAssertTrue(msg.oneofMessage === autoCreated) // Still the same
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.OneofInt32)
+
+ msg.oneofFloat = 20.0
+ XCTAssertEqual(msg.oneofInt32, Int32(0)) // Default
+ XCTAssertEqual(msg.oneofFloat, Float(20.0))
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum.Foo) // Default
+ XCTAssertTrue(msg.oneofMessage === autoCreated) // Still the same
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.OneofFloat)
+
+ msg.oneofEnum = .Bar
+ XCTAssertEqual(msg.oneofInt32, Int32(0)) // Default
+ XCTAssertEqual(msg.oneofFloat, Float(0.0)) // Default
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum.Bar)
+ XCTAssertTrue(msg.oneofMessage === autoCreated) // Still the same
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.OneofEnum)
+
+ // Sets via the autocreated instance.
+ msg.oneofMessage.optionalInt32 = 200
+ XCTAssertEqual(msg.oneofInt32, Int32(0)) // Default
+ XCTAssertEqual(msg.oneofFloat, Float(0.0)) // Default
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum.Foo) // Default
+ XCTAssertTrue(msg.oneofMessage === autoCreated) // Still the same
+ XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(200))
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.OneofMessage)
+
+ // Clear the oneof.
+ Message3_ClearOOneOfCase(msg)
+ XCTAssertEqual(msg.oneofInt32, Int32(0)) // Default
+ XCTAssertEqual(msg.oneofFloat, Float(0.0)) // Default
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum.Foo) // Default
+ let autoCreated2 = msg.oneofMessage // Default create one
+ XCTAssertNotNil(autoCreated2)
+ XCTAssertTrue(autoCreated2 !== autoCreated) // New instance
+ XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(0)) // Default
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.GPBUnsetOneOfCase)
+
+ msg.oneofInt32 = 10
+ XCTAssertEqual(msg.oneofInt32, Int32(10))
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.OneofInt32)
+
+ // Confirm Message.clear() handles the oneof correctly.
+ msg.clear()
+ XCTAssertEqual(msg.oneofInt32, Int32(0)) // Default
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.GPBUnsetOneOfCase)
+
+ // Sets via the autocreated instance.
+ msg.oneofMessage.optionalInt32 = 300
+ XCTAssertTrue(msg.oneofMessage !== autoCreated) // New instance
+ XCTAssertTrue(msg.oneofMessage !== autoCreated2) // New instance
+ XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(300))
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.OneofMessage)
+
+ // Set message to nil clears the oneof.
+ msg.oneofMessage = nil
+ XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(0)) // Default
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.GPBUnsetOneOfCase)
+ }
+
+ func testSerialization() {
+ let msg = Message2()
+
+ msg.optionalInt32 = 100
+ msg.optionalInt64 = 101
+ msg.optionalGroup.a = 102
+ msg.repeatedStringArray.addObject("abc")
+ msg.repeatedStringArray.addObject("def")
+
+ let data = msg.data()
+
+ let msg2 = Message2(data: data)
+ XCTAssertTrue(msg2 !== msg) // New instance
+ XCTAssertEqual(msg.optionalInt32, Int32(100))
+ XCTAssertEqual(msg.optionalInt64, Int64(101))
+ XCTAssertEqual(msg.optionalGroup.a, Int32(102))
+ XCTAssertEqual(msg.repeatedStringArray.count, Int(2))
+ XCTAssertEqual(msg2, msg)
+ }
+
+}
diff --git a/objectivec/Tests/GPBTestUtilities.h b/objectivec/Tests/GPBTestUtilities.h
new file mode 100644
index 00000000..37e30f96
--- /dev/null
+++ b/objectivec/Tests/GPBTestUtilities.h
@@ -0,0 +1,87 @@
+// 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.
+
+#import <XCTest/XCTest.h>
+
+@class TestAllExtensions;
+@class TestAllTypes;
+@class TestMap;
+@class TestPackedTypes;
+@class TestPackedExtensions;
+@class GPBExtensionRegistry;
+
+// The number of repetitions of any repeated objects inside of test messages.
+extern const uint32_t kGPBDefaultRepeatCount;
+
+@interface GPBTestCase : XCTestCase
+
+- (void)setAllFields:(TestAllTypes *)message repeatedCount:(uint32_t)count;
+- (void)clearAllFields:(TestAllTypes *)message;
+- (void)setAllExtensions:(TestAllExtensions *)message
+ repeatedCount:(uint32_t)count;
+- (void)setPackedFields:(TestPackedTypes *)message
+ repeatedCount:(uint32_t)count;
+- (void)setPackedExtensions:(TestPackedExtensions *)message
+ repeatedCount:(uint32_t)count;
+- (void)setAllMapFields:(TestMap *)message numEntries:(uint32_t)count;
+
+- (TestAllTypes *)allSetRepeatedCount:(uint32_t)count;
+- (TestAllExtensions *)allExtensionsSetRepeatedCount:(uint32_t)count;
+- (TestPackedTypes *)packedSetRepeatedCount:(uint32_t)count;
+- (TestPackedExtensions *)packedExtensionsSetRepeatedCount:(uint32_t)count;
+
+- (void)assertAllFieldsSet:(TestAllTypes *)message
+ repeatedCount:(uint32_t)count;
+- (void)assertAllExtensionsSet:(TestAllExtensions *)message
+ repeatedCount:(uint32_t)count;
+- (void)assertRepeatedFieldsModified:(TestAllTypes *)message
+ repeatedCount:(uint32_t)count;
+- (void)assertRepeatedExtensionsModified:(TestAllExtensions *)message
+ repeatedCount:(uint32_t)count;
+- (void)assertExtensionsClear:(TestAllExtensions *)message;
+- (void)assertClear:(TestAllTypes *)message;
+- (void)assertPackedFieldsSet:(TestPackedTypes *)message
+ repeatedCount:(uint32_t)count;
+- (void)assertPackedExtensionsSet:(TestPackedExtensions *)message
+ repeatedCount:(uint32_t)count;
+
+- (void)modifyRepeatedExtensions:(TestAllExtensions *)message;
+- (void)modifyRepeatedFields:(TestAllTypes *)message;
+
+- (GPBExtensionRegistry *)extensionRegistry;
+
+- (NSData *)getDataFileNamed:(NSString *)name dataToWrite:(NSData *)dataToWrite;
+
+- (void)assertAllFieldsKVCMatch:(TestAllTypes *)message;
+- (void)setAllFieldsViaKVC:(TestAllTypes *)message
+ repeatedCount:(uint32_t)count;
+- (void)assertClearKVC:(TestAllTypes *)message;
+
+@end
diff --git a/objectivec/Tests/GPBTestUtilities.m b/objectivec/Tests/GPBTestUtilities.m
new file mode 100644
index 00000000..d664a88a
--- /dev/null
+++ b/objectivec/Tests/GPBTestUtilities.m
@@ -0,0 +1,2350 @@
+// 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.
+
+#import "GPBTestUtilities.h"
+
+#import "google/protobuf/MapUnittest.pbobjc.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+
+const uint32_t kGPBDefaultRepeatCount = 2;
+
+// Small category to easily turn a CString into an NSData.
+@interface NSData (GPBTestCase)
++ (NSData *)gpbtu_dataWithCString:(char *)buffer;
++ (instancetype)gpbtu_dataWithEmbeddedNulls;
+@end
+
+@implementation NSData (GPBTestCase)
++ (NSData *)gpbtu_dataWithCString:(char *)buffer {
+ return [NSData dataWithBytes:buffer length:strlen(buffer)];
+}
+
++ (instancetype)gpbtu_dataWithUint32:(uint32_t)value {
+ return [[[self alloc] initWithUint32_gpbtu:value] autorelease];
+}
+
+- (instancetype)initWithUint32_gpbtu:(uint32_t)value {
+ value = CFSwapInt32HostToLittle(value);
+ return [self initWithBytes:&value length:sizeof(value)];
+}
+
++ (instancetype)gpbtu_dataWithEmbeddedNulls {
+ char bytes[6] = "\1\0\2\3\0\5";
+ return [self dataWithBytes:bytes length:sizeof(bytes)];
+}
+@end
+
+@implementation GPBTestCase
+
+// Return data for name. Optionally (based on #if setting) write out dataToWrite
+// to replace that data. Useful for setting golden masters.
+- (NSData *)getDataFileNamed:(NSString *)name
+ dataToWrite:(NSData *)dataToWrite {
+ NSBundle *bundle = [NSBundle bundleForClass:[self class]];
+ NSString *path = [bundle pathForResource:[name stringByDeletingPathExtension]
+ ofType:[name pathExtension]];
+ XCTAssertNotNil(path, @"Unable to find %@", name);
+ NSData *data = [NSData dataWithContentsOfFile:path];
+ XCTAssertNotNil(data, @"Unable to load from %@", path);
+#if 0
+ // Enable to write out golden master files.
+ if (!path) {
+ path = [[bundle resourcePath] stringByAppendingPathComponent:name];
+ }
+ NSError *error = nil;
+ BOOL wrote = [dataToWrite writeToFile:path options:NSDataWritingAtomic error:&error];
+ XCTAssertTrue(wrote, @"Unable to write %@ (%@)", path, error);
+ NSLog(@"Wrote data file to %@", path);
+#else
+ // Kill off the unused variable warning.
+ dataToWrite = dataToWrite;
+#endif
+ return data;
+}
+
+// -------------------------------------------------------------------
+
+- (void)modifyRepeatedExtensions:(TestAllExtensions *)message {
+ [message setExtension:[UnittestRoot repeatedInt32Extension]
+ index:1
+ value:@501];
+ [message setExtension:[UnittestRoot repeatedInt64Extension]
+ index:1
+ value:@502];
+ [message setExtension:[UnittestRoot repeatedUint32Extension]
+ index:1
+ value:@503];
+ [message setExtension:[UnittestRoot repeatedUint64Extension]
+ index:1
+ value:@504];
+ [message setExtension:[UnittestRoot repeatedSint32Extension]
+ index:1
+ value:@505];
+ [message setExtension:[UnittestRoot repeatedSint64Extension]
+ index:1
+ value:@506];
+ [message setExtension:[UnittestRoot repeatedFixed32Extension]
+ index:1
+ value:@507];
+ [message setExtension:[UnittestRoot repeatedFixed64Extension]
+ index:1
+ value:@508];
+ [message setExtension:[UnittestRoot repeatedSfixed32Extension]
+ index:1
+ value:@509];
+ [message setExtension:[UnittestRoot repeatedSfixed64Extension]
+ index:1
+ value:@510];
+ [message setExtension:[UnittestRoot repeatedFloatExtension]
+ index:1
+ value:@511.0f];
+ [message setExtension:[UnittestRoot repeatedDoubleExtension]
+ index:1
+ value:@512.0];
+ [message setExtension:[UnittestRoot repeatedBoolExtension]
+ index:1
+ value:@YES];
+ [message setExtension:[UnittestRoot repeatedStringExtension]
+ index:1
+ value:@"515"];
+ [message setExtension:[UnittestRoot repeatedBytesExtension]
+ index:1
+ value:[NSData gpbtu_dataWithUint32:516]];
+
+ RepeatedGroup_extension *repeatedGroup = [RepeatedGroup_extension message];
+ [repeatedGroup setA:517];
+ [message setExtension:[UnittestRoot repeatedGroupExtension]
+ index:1
+ value:repeatedGroup];
+ TestAllTypes_NestedMessage *nestedMessage =
+ [TestAllTypes_NestedMessage message];
+ [nestedMessage setBb:518];
+ [message setExtension:[UnittestRoot repeatedNestedMessageExtension]
+ index:1
+ value:nestedMessage];
+ ForeignMessage *foreignMessage = [ForeignMessage message];
+ [foreignMessage setC:519];
+ [message setExtension:[UnittestRoot repeatedForeignMessageExtension]
+ index:1
+ value:foreignMessage];
+ ImportMessage *importMessage = [ImportMessage message];
+ [importMessage setD:520];
+ [message setExtension:[UnittestRoot repeatedImportMessageExtension]
+ index:1
+ value:importMessage];
+
+ [message setExtension:[UnittestRoot repeatedNestedEnumExtension]
+ index:1
+ value:@(TestAllTypes_NestedEnum_Foo)];
+ [message setExtension:[UnittestRoot repeatedForeignEnumExtension]
+ index:1
+ value:@(ForeignEnum_ForeignFoo)];
+ [message setExtension:[UnittestRoot repeatedImportEnumExtension]
+ index:1
+ value:@(ImportEnum_ImportFoo)];
+
+ [message setExtension:[UnittestRoot repeatedStringPieceExtension]
+ index:1
+ value:@"524"];
+ [message setExtension:[UnittestRoot repeatedCordExtension]
+ index:1
+ value:@"525"];
+}
+
+- (void)assertAllExtensionsSet:(TestAllExtensions *)message
+ repeatedCount:(uint32_t)count {
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalInt32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalInt64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalUint32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalUint64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalSint32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalSint64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalFixed32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalFixed64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalSfixed32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalSfixed64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalFloatExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalDoubleExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalBoolExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalStringExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalBytesExtension]]);
+
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalGroupExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalNestedMessageExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalForeignMessageExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalImportMessageExtension]]);
+
+ XCTAssertTrue([[message getExtension:[UnittestRoot optionalGroupExtension]] hasA]);
+ XCTAssertTrue([[message getExtension:[UnittestRoot optionalNestedMessageExtension]] hasBb]);
+ XCTAssertTrue([[message getExtension:[UnittestRoot optionalForeignMessageExtension]] hasC]);
+ XCTAssertTrue([[message getExtension:[UnittestRoot optionalImportMessageExtension]] hasD]);
+
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalNestedEnumExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalForeignEnumExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalImportEnumExtension]]);
+
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalStringPieceExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalCordExtension]]);
+
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultInt32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultInt64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultUint32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultUint64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultSint32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultSint64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultFixed32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultFixed64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultSfixed32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultSfixed64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultFloatExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultDoubleExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultBoolExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultStringExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultBytesExtension]]);
+
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultNestedEnumExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultForeignEnumExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultImportEnumExtension]]);
+
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultStringPieceExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultCordExtension]]);
+
+ XCTAssertEqual(101, [[message getExtension:[UnittestRoot optionalInt32Extension]] intValue]);
+ XCTAssertEqual(102LL, [[message getExtension:[UnittestRoot optionalInt64Extension]] longLongValue]);
+ XCTAssertEqual(103U, [[message getExtension:[UnittestRoot optionalUint32Extension]] unsignedIntValue]);
+ XCTAssertEqual(104ULL, [[message getExtension:[UnittestRoot optionalUint64Extension]] unsignedLongLongValue]);
+ XCTAssertEqual(105, [[message getExtension:[UnittestRoot optionalSint32Extension]] intValue]);
+ XCTAssertEqual(106LL, [[message getExtension:[UnittestRoot optionalSint64Extension]] longLongValue]);
+ XCTAssertEqual(107U, [[message getExtension:[UnittestRoot optionalFixed32Extension]] unsignedIntValue]);
+ XCTAssertEqual(108ULL, [[message getExtension:[UnittestRoot optionalFixed64Extension]] unsignedLongLongValue]);
+ XCTAssertEqual(109, [[message getExtension:[UnittestRoot optionalSfixed32Extension]] intValue]);
+ XCTAssertEqual(110LL, [[message getExtension:[UnittestRoot optionalSfixed64Extension]] longLongValue]);
+ XCTAssertEqualWithAccuracy(111.0f, [[message getExtension:[UnittestRoot optionalFloatExtension]] floatValue], 0.01);
+ XCTAssertEqualWithAccuracy(112.0, [[message getExtension:[UnittestRoot optionalDoubleExtension]] doubleValue], 0.01);
+ XCTAssertTrue([[message getExtension:[UnittestRoot optionalBoolExtension]] boolValue]);
+ XCTAssertEqualObjects(@"115", [message getExtension:[UnittestRoot optionalStringExtension]]);
+ XCTAssertEqualObjects([NSData gpbtu_dataWithEmbeddedNulls], [message getExtension:[UnittestRoot optionalBytesExtension]]);
+
+ XCTAssertEqual(117, [(TestAllTypes_OptionalGroup*)[message getExtension:[UnittestRoot optionalGroupExtension]] a]);
+ XCTAssertEqual(118, [(TestAllTypes_NestedMessage*)[message getExtension:[UnittestRoot optionalNestedMessageExtension]] bb]);
+ XCTAssertEqual(119, [[message getExtension:[UnittestRoot optionalForeignMessageExtension]] c]);
+ XCTAssertEqual(120, [[message getExtension:[UnittestRoot optionalImportMessageExtension]] d]);
+
+ XCTAssertEqual(TestAllTypes_NestedEnum_Baz, [[message getExtension:[UnittestRoot optionalNestedEnumExtension]] intValue]);
+ XCTAssertEqual(ForeignEnum_ForeignBaz, [[message getExtension:[UnittestRoot optionalForeignEnumExtension]] intValue]);
+ XCTAssertEqual(ImportEnum_ImportBaz, [[message getExtension:[UnittestRoot optionalImportEnumExtension]] intValue]);
+
+ XCTAssertEqualObjects(@"124", [message getExtension:[UnittestRoot optionalStringPieceExtension]]);
+ XCTAssertEqualObjects(@"125", [message getExtension:[UnittestRoot optionalCordExtension]]);
+
+ // -----------------------------------------------------------------
+
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedInt32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedInt64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedUint32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedUint64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedSint32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedSint64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedFixed32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedFixed64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedSfixed32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedSfixed64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedFloatExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedDoubleExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedBoolExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedStringExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedBytesExtension]] count]);
+
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedGroupExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedNestedMessageExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedForeignMessageExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedImportMessageExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedNestedEnumExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedForeignEnumExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedImportEnumExtension]] count]);
+
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedStringPieceExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedCordExtension]] count]);
+
+ for (uint32_t i = 0; i < count; ++i) {
+ id extension = [message getExtension:[UnittestRoot repeatedInt32Extension]];
+ XCTAssertEqual((int)(201 + i * 100), [extension[i] intValue]);
+ extension = [message getExtension:[UnittestRoot repeatedInt64Extension]];
+ XCTAssertEqual(202 + i * 100, [extension[i] longLongValue]);
+ extension = [message getExtension:[UnittestRoot repeatedUint32Extension]];
+ XCTAssertEqual(203 + i * 100, [extension[i] unsignedIntValue]);
+ extension = [message getExtension:[UnittestRoot repeatedUint64Extension]];
+ XCTAssertEqual(204 + i * 100, [extension[i] unsignedLongLongValue]);
+ extension = [message getExtension:[UnittestRoot repeatedSint32Extension]];
+ XCTAssertEqual((int)(205 + i * 100), [extension[i] intValue]);
+ extension = [message getExtension:[UnittestRoot repeatedSint64Extension]];
+ XCTAssertEqual(206 + i * 100, [extension[i] longLongValue]);
+ extension = [message getExtension:[UnittestRoot repeatedFixed32Extension]];
+ XCTAssertEqual(207 + i * 100, [extension[i] unsignedIntValue]);
+ extension = [message getExtension:[UnittestRoot repeatedFixed64Extension]];
+ XCTAssertEqual(208 + i * 100, [extension[i] unsignedLongLongValue]);
+ extension = [message getExtension:[UnittestRoot repeatedSfixed32Extension]];
+ XCTAssertEqual((int)(209 + i * 100), [extension[i] intValue]);
+ extension = [message getExtension:[UnittestRoot repeatedSfixed64Extension]];
+ XCTAssertEqual(210 + i * 100, [extension[i] longLongValue]);
+ extension = [message getExtension:[UnittestRoot repeatedFloatExtension]];
+ XCTAssertEqualWithAccuracy(211 + i * 100, [extension[i] floatValue], 0.01);
+ extension = [message getExtension:[UnittestRoot repeatedDoubleExtension]];
+ XCTAssertEqualWithAccuracy(212 + i * 100, [extension[i] doubleValue], 0.01);
+ extension = [message getExtension:[UnittestRoot repeatedBoolExtension]];
+ XCTAssertEqual((i % 2) ? YES : NO, [extension[i] boolValue]);
+
+ NSString *string = [[NSString alloc] initWithFormat:@"%d", 215 + i * 100];
+ extension = [message getExtension:[UnittestRoot repeatedStringExtension]];
+ XCTAssertEqualObjects(string, extension[i]);
+ [string release];
+
+ NSData *data = [[NSData alloc] initWithUint32_gpbtu:216 + i * 100];
+ extension = [message getExtension:[UnittestRoot repeatedBytesExtension]];
+ XCTAssertEqualObjects(data, extension[i]);
+ [data release];
+
+ extension = [message getExtension:[UnittestRoot repeatedGroupExtension]];
+ XCTAssertEqual((int)(217 + i * 100), [(TestAllTypes_OptionalGroup*)extension[i] a]);
+ extension = [message getExtension:[UnittestRoot repeatedNestedMessageExtension]];
+ XCTAssertEqual((int)(218 + i * 100), [(TestAllTypes_NestedMessage*)extension[i] bb]);
+ extension = [message getExtension:[UnittestRoot repeatedForeignMessageExtension]];
+ XCTAssertEqual((int)(219 + i * 100), [extension[i] c]);
+ extension = [message getExtension:[UnittestRoot repeatedImportMessageExtension]];
+ XCTAssertEqual((int)(220 + i * 100), [extension[i] d]);
+
+ extension = [message getExtension:[UnittestRoot repeatedNestedEnumExtension]];
+ XCTAssertEqual((i % 2) ? TestAllTypes_NestedEnum_Bar : TestAllTypes_NestedEnum_Baz, [extension[i] intValue]);
+ extension = [message getExtension:[UnittestRoot repeatedForeignEnumExtension]];
+ XCTAssertEqual((i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz, [extension[i] intValue]);
+ extension = [message getExtension:[UnittestRoot repeatedImportEnumExtension]];
+ XCTAssertEqual((i % 2) ? ImportEnum_ImportBar : ImportEnum_ImportBaz, [extension[i] intValue]);
+
+ string = [[NSString alloc] initWithFormat:@"%d", 224 + i * 100];
+ extension = [message getExtension:[UnittestRoot repeatedStringPieceExtension]];
+ XCTAssertEqualObjects(string, extension[i]);
+ [string release];
+
+ string = [[NSString alloc] initWithFormat:@"%d", 225 + i * 100];
+ extension = [message getExtension:[UnittestRoot repeatedCordExtension]];
+ XCTAssertEqualObjects(string, extension[i]);
+ [string release];
+ }
+
+ // -----------------------------------------------------------------
+
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultInt32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultInt64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultUint32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultUint64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultSint32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultSint64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultFixed32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultFixed64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultSfixed32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultSfixed64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultFloatExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultDoubleExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultBoolExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultStringExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultBytesExtension]]);
+
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultNestedEnumExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultForeignEnumExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultImportEnumExtension]]);
+
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultStringPieceExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultCordExtension]]);
+
+ XCTAssertEqual(401, [[message getExtension:[UnittestRoot defaultInt32Extension]] intValue]);
+ XCTAssertEqual(402LL, [[message getExtension:[UnittestRoot defaultInt64Extension]] longLongValue]);
+ XCTAssertEqual(403U, [[message getExtension:[UnittestRoot defaultUint32Extension]] unsignedIntValue]);
+ XCTAssertEqual(404ULL, [[message getExtension:[UnittestRoot defaultUint64Extension]] unsignedLongLongValue]);
+ XCTAssertEqual(405, [[message getExtension:[UnittestRoot defaultSint32Extension]] intValue]);
+ XCTAssertEqual(406LL, [[message getExtension:[UnittestRoot defaultSint64Extension]] longLongValue]);
+ XCTAssertEqual(407U, [[message getExtension:[UnittestRoot defaultFixed32Extension]] unsignedIntValue]);
+ XCTAssertEqual(408ULL, [[message getExtension:[UnittestRoot defaultFixed64Extension]] unsignedLongLongValue]);
+ XCTAssertEqual(409, [[message getExtension:[UnittestRoot defaultSfixed32Extension]] intValue]);
+ XCTAssertEqual(410LL,[[message getExtension:[UnittestRoot defaultSfixed64Extension]] longLongValue]);
+ XCTAssertEqualWithAccuracy(411.0f, [[message getExtension:[UnittestRoot defaultFloatExtension]] floatValue], 0.01);
+ XCTAssertEqualWithAccuracy(412.0, [[message getExtension:[UnittestRoot defaultDoubleExtension]] doubleValue], 0.01);
+ XCTAssertFalse([[message getExtension:[UnittestRoot defaultBoolExtension]] boolValue]);
+ XCTAssertEqualObjects(@"415", [message getExtension:[UnittestRoot defaultStringExtension]]);
+ XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:416], [message getExtension:[UnittestRoot defaultBytesExtension]]);
+
+ XCTAssertEqual(TestAllTypes_NestedEnum_Foo, [[message getExtension:[UnittestRoot defaultNestedEnumExtension]] intValue]);
+ XCTAssertEqual(ForeignEnum_ForeignFoo, [[message getExtension:[UnittestRoot defaultForeignEnumExtension]] intValue]);
+ XCTAssertEqual(ImportEnum_ImportFoo, [[message getExtension:[UnittestRoot defaultImportEnumExtension]] intValue]);
+
+ XCTAssertEqualObjects(@"424", [message getExtension:[UnittestRoot defaultStringPieceExtension]]);
+ XCTAssertEqualObjects(@"425", [message getExtension:[UnittestRoot defaultCordExtension]]);
+}
+
+- (void)assertRepeatedExtensionsModified:(TestAllExtensions *)message
+ repeatedCount:(uint32_t)count {
+ // ModifyRepeatedFields only sets the second repeated element of each
+ // field. In addition to verifying this, we also verify that the first
+ // element and size were *not* modified.
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedInt32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedInt64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedUint32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedUint64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedSint32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedSint64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedFixed32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedFixed64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedSfixed32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedSfixed64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedFloatExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedDoubleExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedBoolExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedStringExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedBytesExtension]] count]);
+
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedGroupExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedNestedMessageExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedForeignMessageExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedImportMessageExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedNestedEnumExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedForeignEnumExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedImportEnumExtension]] count]);
+
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedStringPieceExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedCordExtension]] count]);
+
+ XCTAssertEqual(201,[[message getExtension:[UnittestRoot repeatedInt32Extension]][0] intValue]);
+ XCTAssertEqual(202LL, [[message getExtension:[UnittestRoot repeatedInt64Extension]][0] longLongValue]);
+ XCTAssertEqual(203U, [[message getExtension:[UnittestRoot repeatedUint32Extension]][0] unsignedIntValue]);
+ XCTAssertEqual(204ULL, [[message getExtension:[UnittestRoot repeatedUint64Extension]][0] unsignedLongLongValue]);
+ XCTAssertEqual(205, [[message getExtension:[UnittestRoot repeatedSint32Extension]][0] intValue]);
+ XCTAssertEqual(206LL, [[message getExtension:[UnittestRoot repeatedSint64Extension]][0] longLongValue]);
+ XCTAssertEqual(207U, [[message getExtension:[UnittestRoot repeatedFixed32Extension]][0] unsignedIntValue]);
+ XCTAssertEqual(208ULL, [[message getExtension:[UnittestRoot repeatedFixed64Extension]][0] unsignedLongLongValue]);
+ XCTAssertEqual(209, [[message getExtension:[UnittestRoot repeatedSfixed32Extension]][0] intValue]);
+ XCTAssertEqual(210LL, [[message getExtension:[UnittestRoot repeatedSfixed64Extension]][0] longLongValue]);
+ XCTAssertEqualWithAccuracy(211.0f, [[message getExtension:[UnittestRoot repeatedFloatExtension]][0] floatValue], 0.01);
+ XCTAssertEqualWithAccuracy(212.0, [[message getExtension:[UnittestRoot repeatedDoubleExtension]][0] doubleValue], 0.01);
+ XCTAssertFalse([[message getExtension:[UnittestRoot repeatedBoolExtension]][0] boolValue]);
+ XCTAssertEqualObjects(@"215", [message getExtension:[UnittestRoot repeatedStringExtension]][0]);
+ XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:216], [message getExtension:[UnittestRoot repeatedBytesExtension]][0]);
+
+ XCTAssertEqual(217, [(TestAllTypes_OptionalGroup*)[message getExtension:[UnittestRoot repeatedGroupExtension]][0] a]);
+ XCTAssertEqual(218, [(TestAllTypes_NestedMessage*)[message getExtension:[UnittestRoot repeatedNestedMessageExtension]][0] bb]);
+ XCTAssertEqual(219, [[message getExtension:[UnittestRoot repeatedForeignMessageExtension]][0] c]);
+ XCTAssertEqual(220, [[message getExtension:[UnittestRoot repeatedImportMessageExtension]][0] d]);
+
+ XCTAssertEqual(TestAllTypes_NestedEnum_Baz,
+ [[message getExtension:[UnittestRoot repeatedNestedEnumExtension]][0] intValue]);
+ XCTAssertEqual(ForeignEnum_ForeignBaz,
+ [[message getExtension:[UnittestRoot repeatedForeignEnumExtension]][0] intValue]);
+ XCTAssertEqual(ImportEnum_ImportBaz,
+ [[message getExtension:[UnittestRoot repeatedImportEnumExtension]][0] intValue]);
+
+ XCTAssertEqualObjects(@"224", [message getExtension:[UnittestRoot repeatedStringPieceExtension]][0]);
+ XCTAssertEqualObjects(@"225", [message getExtension:[UnittestRoot repeatedCordExtension]][0]);
+
+ // Actually verify the second (modified) elements now.
+ XCTAssertEqual(501, [[message getExtension:[UnittestRoot repeatedInt32Extension]][1] intValue]);
+ XCTAssertEqual(502LL, [[message getExtension:[UnittestRoot repeatedInt64Extension]][1] longLongValue]);
+ XCTAssertEqual(503U, [[message getExtension:[UnittestRoot repeatedUint32Extension]][1] unsignedIntValue]);
+ XCTAssertEqual(504ULL, [[message getExtension:[UnittestRoot repeatedUint64Extension]][1] unsignedLongLongValue]);
+ XCTAssertEqual(505, [[message getExtension:[UnittestRoot repeatedSint32Extension]][1] intValue]);
+ XCTAssertEqual(506LL, [[message getExtension:[UnittestRoot repeatedSint64Extension]][1] longLongValue]);
+ XCTAssertEqual(507U, [[message getExtension:[UnittestRoot repeatedFixed32Extension]][1] unsignedIntValue]);
+ XCTAssertEqual(508ULL, [[message getExtension:[UnittestRoot repeatedFixed64Extension]][1] unsignedLongLongValue]);
+ XCTAssertEqual(509, [[message getExtension:[UnittestRoot repeatedSfixed32Extension]][1] intValue]);
+ XCTAssertEqual(510LL, [[message getExtension:[UnittestRoot repeatedSfixed64Extension]][1] longLongValue]);
+ XCTAssertEqualWithAccuracy(511.0f, [[message getExtension:[UnittestRoot repeatedFloatExtension]][1] floatValue], 0.01);
+ XCTAssertEqualWithAccuracy(512.0, [[message getExtension:[UnittestRoot repeatedDoubleExtension]][1] doubleValue], 0.01);
+ XCTAssertTrue([[message getExtension:[UnittestRoot repeatedBoolExtension]][1] boolValue]);
+ XCTAssertEqualObjects(@"515", [message getExtension:[UnittestRoot repeatedStringExtension]][1]);
+ XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:516], [message getExtension:[UnittestRoot repeatedBytesExtension]][1]);
+
+ XCTAssertEqual(517, [(TestAllTypes_OptionalGroup*)[message getExtension:[UnittestRoot repeatedGroupExtension]][1] a]);
+ XCTAssertEqual(518, [(TestAllTypes_NestedMessage*)[message getExtension:[UnittestRoot repeatedNestedMessageExtension]][1] bb]);
+ XCTAssertEqual(519, [[message getExtension:[UnittestRoot repeatedForeignMessageExtension]][1] c]);
+ XCTAssertEqual(520, [[message getExtension:[UnittestRoot repeatedImportMessageExtension]][1] d]);
+
+ XCTAssertEqual(TestAllTypes_NestedEnum_Foo,
+ [[message getExtension:[UnittestRoot repeatedNestedEnumExtension]][1] intValue]);
+ XCTAssertEqual(ForeignEnum_ForeignFoo,
+ [[message getExtension:[UnittestRoot repeatedForeignEnumExtension]][1] intValue]);
+ XCTAssertEqual(ImportEnum_ImportFoo,
+ [[message getExtension:[UnittestRoot repeatedImportEnumExtension]][1] intValue]);
+
+ XCTAssertEqualObjects(@"524", [message getExtension:[UnittestRoot repeatedStringPieceExtension]][1]);
+ XCTAssertEqualObjects(@"525", [message getExtension:[UnittestRoot repeatedCordExtension]][1]);
+}
+
+// -------------------------------------------------------------------
+
+- (void)assertAllFieldsSet:(TestAllTypes *)message
+ repeatedCount:(uint32_t)count {
+ XCTAssertTrue(message.hasOptionalInt32);
+ XCTAssertTrue(message.hasOptionalInt64);
+ XCTAssertTrue(message.hasOptionalUint32);
+ XCTAssertTrue(message.hasOptionalUint64);
+ XCTAssertTrue(message.hasOptionalSint32);
+ XCTAssertTrue(message.hasOptionalSint64);
+ XCTAssertTrue(message.hasOptionalFixed32);
+ XCTAssertTrue(message.hasOptionalFixed64);
+ XCTAssertTrue(message.hasOptionalSfixed32);
+ XCTAssertTrue(message.hasOptionalSfixed64);
+ XCTAssertTrue(message.hasOptionalFloat);
+ XCTAssertTrue(message.hasOptionalDouble);
+ XCTAssertTrue(message.hasOptionalBool);
+ XCTAssertTrue(message.hasOptionalString);
+ XCTAssertTrue(message.hasOptionalBytes);
+
+ XCTAssertTrue(message.hasOptionalGroup);
+ XCTAssertTrue(message.hasOptionalNestedMessage);
+ XCTAssertTrue(message.hasOptionalForeignMessage);
+ XCTAssertTrue(message.hasOptionalImportMessage);
+
+ XCTAssertTrue(message.optionalGroup.hasA);
+ XCTAssertTrue(message.optionalNestedMessage.hasBb);
+ XCTAssertTrue(message.optionalForeignMessage.hasC);
+ XCTAssertTrue(message.optionalImportMessage.hasD);
+
+ XCTAssertTrue(message.hasOptionalNestedEnum);
+ XCTAssertTrue(message.hasOptionalForeignEnum);
+ XCTAssertTrue(message.hasOptionalImportEnum);
+
+ XCTAssertTrue(message.hasOptionalStringPiece);
+ XCTAssertTrue(message.hasOptionalCord);
+
+ XCTAssertEqual(101, message.optionalInt32);
+ XCTAssertEqual(102LL, message.optionalInt64);
+ XCTAssertEqual(103U, message.optionalUint32);
+ XCTAssertEqual(104ULL, message.optionalUint64);
+ XCTAssertEqual(105, message.optionalSint32);
+ XCTAssertEqual(106LL, message.optionalSint64);
+ XCTAssertEqual(107U, message.optionalFixed32);
+ XCTAssertEqual(108ULL, message.optionalFixed64);
+ XCTAssertEqual(109, message.optionalSfixed32);
+ XCTAssertEqual(110LL, message.optionalSfixed64);
+ XCTAssertEqualWithAccuracy(111.0f, message.optionalFloat, 0.1);
+ XCTAssertEqualWithAccuracy(112.0, message.optionalDouble, 0.1);
+ XCTAssertTrue(message.optionalBool);
+ XCTAssertEqualObjects(@"115", message.optionalString);
+ XCTAssertEqualObjects([NSData gpbtu_dataWithEmbeddedNulls],
+ message.optionalBytes);
+
+ XCTAssertEqual(117, message.optionalGroup.a);
+ XCTAssertEqual(118, message.optionalNestedMessage.bb);
+ XCTAssertEqual(119, message.optionalForeignMessage.c);
+ XCTAssertEqual(120, message.optionalImportMessage.d);
+
+ XCTAssertEqual(TestAllTypes_NestedEnum_Baz, message.optionalNestedEnum);
+ XCTAssertEqual(ForeignEnum_ForeignBaz, message.optionalForeignEnum);
+ XCTAssertEqual(ImportEnum_ImportBaz, message.optionalImportEnum);
+
+ XCTAssertEqualObjects(@"124", message.optionalStringPiece);
+ XCTAssertEqualObjects(@"125", message.optionalCord);
+
+ // -----------------------------------------------------------------
+
+ XCTAssertEqual(count, message.repeatedInt32Array.count);
+ XCTAssertEqual(count, message.repeatedInt64Array.count);
+ XCTAssertEqual(count, message.repeatedUint32Array.count);
+ XCTAssertEqual(count, message.repeatedUint64Array.count);
+ XCTAssertEqual(count, message.repeatedSint32Array.count);
+ XCTAssertEqual(count, message.repeatedSint64Array.count);
+ XCTAssertEqual(count, message.repeatedFixed32Array.count);
+ XCTAssertEqual(count, message.repeatedFixed64Array.count);
+ XCTAssertEqual(count, message.repeatedSfixed32Array.count);
+ XCTAssertEqual(count, message.repeatedSfixed64Array.count);
+ XCTAssertEqual(count, message.repeatedFloatArray.count);
+ XCTAssertEqual(count, message.repeatedDoubleArray.count);
+ XCTAssertEqual(count, message.repeatedBoolArray.count);
+ XCTAssertEqual(count, message.repeatedStringArray.count);
+ XCTAssertEqual(count, message.repeatedBytesArray.count);
+
+ XCTAssertEqual(count, message.repeatedGroupArray.count);
+ XCTAssertEqual(count, message.repeatedNestedMessageArray.count);
+ XCTAssertEqual(count, message.repeatedForeignMessageArray.count);
+ XCTAssertEqual(count, message.repeatedImportMessageArray.count);
+ XCTAssertEqual(count, message.repeatedNestedEnumArray.count);
+ XCTAssertEqual(count, message.repeatedForeignEnumArray.count);
+ XCTAssertEqual(count, message.repeatedImportEnumArray.count);
+
+ XCTAssertEqual(count, message.repeatedStringPieceArray.count);
+ XCTAssertEqual(count, message.repeatedCordArray.count);
+
+ for (uint32_t i = 0; i < count; ++i) {
+ XCTAssertEqual((int)(201 + i * 100),
+ [message.repeatedInt32Array valueAtIndex:i]);
+ XCTAssertEqual(202 + i * 100, [message.repeatedInt64Array valueAtIndex:i]);
+ XCTAssertEqual(203 + i * 100, [message.repeatedUint32Array valueAtIndex:i]);
+ XCTAssertEqual(204 + i * 100, [message.repeatedUint64Array valueAtIndex:i]);
+ XCTAssertEqual((int)(205 + i * 100),
+ [message.repeatedSint32Array valueAtIndex:i]);
+ XCTAssertEqual(206 + i * 100, [message.repeatedSint64Array valueAtIndex:i]);
+ XCTAssertEqual(207 + i * 100,
+ [message.repeatedFixed32Array valueAtIndex:i]);
+ XCTAssertEqual(208 + i * 100,
+ [message.repeatedFixed64Array valueAtIndex:i]);
+ XCTAssertEqual((int)(209 + i * 100),
+ [message.repeatedSfixed32Array valueAtIndex:i]);
+ XCTAssertEqual(210 + i * 100,
+ [message.repeatedSfixed64Array valueAtIndex:i]);
+ XCTAssertEqualWithAccuracy(
+ 211 + i * 100, [message.repeatedFloatArray valueAtIndex:i], 0.1);
+ XCTAssertEqualWithAccuracy(
+ 212 + i * 100, [message.repeatedDoubleArray valueAtIndex:i], 0.1);
+ XCTAssertEqual((i % 2) ? YES : NO,
+ [message.repeatedBoolArray valueAtIndex:i]);
+
+ NSString *string = [[NSString alloc] initWithFormat:@"%d", 215 + i * 100];
+ XCTAssertEqualObjects(string, message.repeatedStringArray[i]);
+ [string release];
+
+ NSData *data = [[NSData alloc] initWithUint32_gpbtu:216 + i * 100];
+ XCTAssertEqualObjects(data, message.repeatedBytesArray[i]);
+ [data release];
+
+ XCTAssertEqual((int)(217 + i * 100), ((TestAllTypes_RepeatedGroup*)message.repeatedGroupArray[i]).a);
+ XCTAssertEqual((int)(218 + i * 100), ((TestAllTypes_NestedMessage*)message.repeatedNestedMessageArray[i]).bb);
+ XCTAssertEqual((int)(219 + i * 100), ((ForeignMessage*)message.repeatedForeignMessageArray[i]).c);
+ XCTAssertEqual((int)(220 + i * 100), ((ImportMessage*)message.repeatedImportMessageArray[i]).d);
+
+ XCTAssertEqual((i % 2) ? TestAllTypes_NestedEnum_Bar : TestAllTypes_NestedEnum_Baz, [message.repeatedNestedEnumArray valueAtIndex:i]);
+ XCTAssertEqual((i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz, [message.repeatedForeignEnumArray valueAtIndex:i]);
+ XCTAssertEqual((i % 2) ? ImportEnum_ImportBar : ImportEnum_ImportBaz, [message.repeatedImportEnumArray valueAtIndex:i]);
+
+ string = [[NSString alloc] initWithFormat:@"%d", 224 + i * 100];
+ XCTAssertEqualObjects(string, message.repeatedStringPieceArray[i]);
+ [string release];
+
+ string = [[NSString alloc] initWithFormat:@"%d", 225 + i * 100];
+ XCTAssertEqualObjects(string, message.repeatedCordArray[i]);
+ [string release];
+ }
+
+ // -----------------------------------------------------------------
+
+ XCTAssertTrue(message.hasDefaultInt32);
+ XCTAssertTrue(message.hasDefaultInt64);
+ XCTAssertTrue(message.hasDefaultUint32);
+ XCTAssertTrue(message.hasDefaultUint64);
+ XCTAssertTrue(message.hasDefaultSint32);
+ XCTAssertTrue(message.hasDefaultSint64);
+ XCTAssertTrue(message.hasDefaultFixed32);
+ XCTAssertTrue(message.hasDefaultFixed64);
+ XCTAssertTrue(message.hasDefaultSfixed32);
+ XCTAssertTrue(message.hasDefaultSfixed64);
+ XCTAssertTrue(message.hasDefaultFloat);
+ XCTAssertTrue(message.hasDefaultDouble);
+ XCTAssertTrue(message.hasDefaultBool);
+ XCTAssertTrue(message.hasDefaultString);
+ XCTAssertTrue(message.hasDefaultBytes);
+
+ XCTAssertTrue(message.hasDefaultNestedEnum);
+ XCTAssertTrue(message.hasDefaultForeignEnum);
+ XCTAssertTrue(message.hasDefaultImportEnum);
+
+ XCTAssertTrue(message.hasDefaultStringPiece);
+ XCTAssertTrue(message.hasDefaultCord);
+
+ XCTAssertEqual(401, message.defaultInt32);
+ XCTAssertEqual(402LL, message.defaultInt64);
+ XCTAssertEqual(403U, message.defaultUint32);
+ XCTAssertEqual(404ULL, message.defaultUint64);
+ XCTAssertEqual(405, message.defaultSint32);
+ XCTAssertEqual(406LL, message.defaultSint64);
+ XCTAssertEqual(407U, message.defaultFixed32);
+ XCTAssertEqual(408ULL, message.defaultFixed64);
+ XCTAssertEqual(409, message.defaultSfixed32);
+ XCTAssertEqual(410LL, message.defaultSfixed64);
+ XCTAssertEqualWithAccuracy(411.0f, message.defaultFloat, 0.1);
+ XCTAssertEqualWithAccuracy(412.0, message.defaultDouble, 0.1);
+ XCTAssertFalse(message.defaultBool);
+ XCTAssertEqualObjects(@"415", message.defaultString);
+ XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:416],
+ message.defaultBytes);
+
+ XCTAssertEqual(TestAllTypes_NestedEnum_Foo, message.defaultNestedEnum);
+ XCTAssertEqual(ForeignEnum_ForeignFoo, message.defaultForeignEnum);
+ XCTAssertEqual(ImportEnum_ImportFoo, message.defaultImportEnum);
+
+ XCTAssertEqualObjects(@"424", message.defaultStringPiece);
+ XCTAssertEqualObjects(@"425", message.defaultCord);
+}
+
+- (void)setAllFields:(TestAllTypes *)message repeatedCount:(uint32_t)count {
+ [message setOptionalInt32:101];
+ [message setOptionalInt64:102];
+ [message setOptionalUint32:103];
+ [message setOptionalUint64:104];
+ [message setOptionalSint32:105];
+ [message setOptionalSint64:106];
+ [message setOptionalFixed32:107];
+ [message setOptionalFixed64:108];
+ [message setOptionalSfixed32:109];
+ [message setOptionalSfixed64:110];
+ [message setOptionalFloat:111];
+ [message setOptionalDouble:112];
+ [message setOptionalBool:YES];
+ [message setOptionalString:@"115"];
+ [message setOptionalBytes:[NSData gpbtu_dataWithEmbeddedNulls]];
+
+ TestAllTypes_OptionalGroup *allTypes = [TestAllTypes_OptionalGroup message];
+ [allTypes setA:117];
+ [message setOptionalGroup:allTypes];
+ TestAllTypes_NestedMessage *nestedMessage =
+ [TestAllTypes_NestedMessage message];
+ [nestedMessage setBb:118];
+ [message setOptionalNestedMessage:nestedMessage];
+ ForeignMessage *foreignMessage = [ForeignMessage message];
+ [foreignMessage setC:119];
+ [message setOptionalForeignMessage:foreignMessage];
+ ImportMessage *importMessage = [ImportMessage message];
+ [importMessage setD:120];
+ [message setOptionalImportMessage:importMessage];
+
+ [message setOptionalNestedEnum:TestAllTypes_NestedEnum_Baz];
+ [message setOptionalForeignEnum:ForeignEnum_ForeignBaz];
+ [message setOptionalImportEnum:ImportEnum_ImportBaz];
+
+ [message setOptionalStringPiece:@"124"];
+ [message setOptionalCord:@"125"];
+
+ // -----------------------------------------------------------------
+
+ for (uint32_t i = 0; i < count; i++) {
+ [message.repeatedInt32Array addValue:201 + i * 100];
+ [message.repeatedInt64Array addValue:202 + i * 100];
+ [message.repeatedUint32Array addValue:203 + i * 100];
+ [message.repeatedUint64Array addValue:204 + i * 100];
+ [message.repeatedSint32Array addValue:205 + i * 100];
+ [message.repeatedSint64Array addValue:206 + i * 100];
+ [message.repeatedFixed32Array addValue:207 + i * 100];
+ [message.repeatedFixed64Array addValue:208 + i * 100];
+ [message.repeatedSfixed32Array addValue:209 + i * 100];
+ [message.repeatedSfixed64Array addValue:210 + i * 100];
+ [message.repeatedFloatArray addValue:211 + i * 100];
+ [message.repeatedDoubleArray addValue:212 + i * 100];
+ [message.repeatedBoolArray addValue:(i % 2)];
+ NSString *string = [[NSString alloc] initWithFormat:@"%d", 215 + i * 100];
+ [message.repeatedStringArray addObject:string];
+ [string release];
+
+ NSData *data = [[NSData alloc] initWithUint32_gpbtu:216 + i * 100];
+ [message.repeatedBytesArray addObject:data];
+ [data release];
+
+ TestAllTypes_RepeatedGroup *testAll =
+ [[TestAllTypes_RepeatedGroup alloc] init];
+ [testAll setA:217 + i * 100];
+ [message.repeatedGroupArray addObject:testAll];
+ [testAll release];
+
+ nestedMessage = [[TestAllTypes_NestedMessage alloc] init];
+ [nestedMessage setBb:218 + i * 100];
+ [message.repeatedNestedMessageArray addObject:nestedMessage];
+ [nestedMessage release];
+
+ foreignMessage = [[ForeignMessage alloc] init];
+ [foreignMessage setC:219 + i * 100];
+ [message.repeatedForeignMessageArray addObject:foreignMessage];
+ [foreignMessage release];
+
+ importMessage = [[ImportMessage alloc] init];
+ [importMessage setD:220 + i * 100];
+ [message.repeatedImportMessageArray addObject:importMessage];
+ [importMessage release];
+
+ [message.repeatedNestedEnumArray addValue:(i % 2) ? TestAllTypes_NestedEnum_Bar : TestAllTypes_NestedEnum_Baz];
+
+ [message.repeatedForeignEnumArray addValue:(i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz];
+ [message.repeatedImportEnumArray addValue:(i % 2) ? ImportEnum_ImportBar : ImportEnum_ImportBaz];
+
+ string = [[NSString alloc] initWithFormat:@"%d", 224 + i * 100];
+ [message.repeatedStringPieceArray addObject:string];
+ [string release];
+
+ string = [[NSString alloc] initWithFormat:@"%d", 225 + i * 100];
+ [message.repeatedCordArray addObject:string];
+ [string release];
+ }
+ // -----------------------------------------------------------------
+
+ message.defaultInt32 = 401;
+ message.defaultInt64 = 402;
+ message.defaultUint32 = 403;
+ message.defaultUint64 = 404;
+ message.defaultSint32 = 405;
+ message.defaultSint64 = 406;
+ message.defaultFixed32 = 407;
+ message.defaultFixed64 = 408;
+ message.defaultSfixed32 = 409;
+ message.defaultSfixed64 = 410;
+ message.defaultFloat = 411;
+ message.defaultDouble = 412;
+ message.defaultBool = NO;
+ message.defaultString = @"415";
+ message.defaultBytes = [NSData gpbtu_dataWithUint32:416];
+
+ message.defaultNestedEnum = TestAllTypes_NestedEnum_Foo;
+ message.defaultForeignEnum = ForeignEnum_ForeignFoo;
+ message.defaultImportEnum = ImportEnum_ImportFoo;
+
+ message.defaultStringPiece = @"424";
+ message.defaultCord = @"425";
+}
+
+- (void)clearAllFields:(TestAllTypes *)message {
+ message.hasOptionalInt32 = NO;
+ message.hasOptionalInt64 = NO;
+ message.hasOptionalUint32 = NO;
+ message.hasOptionalUint64 = NO;
+ message.hasOptionalSint32 = NO;
+ message.hasOptionalSint64 = NO;
+ message.hasOptionalFixed32 = NO;
+ message.hasOptionalFixed64 = NO;
+ message.hasOptionalSfixed32 = NO;
+ message.hasOptionalSfixed64 = NO;
+ message.hasOptionalFloat = NO;
+ message.hasOptionalDouble = NO;
+ message.hasOptionalBool = NO;
+ message.hasOptionalString = NO;
+ message.hasOptionalBytes = NO;
+
+ message.hasOptionalGroup = NO;
+ message.hasOptionalNestedMessage = NO;
+ message.hasOptionalForeignMessage = NO;
+ message.hasOptionalImportMessage = NO;
+
+ message.hasOptionalNestedEnum = NO;
+ message.hasOptionalForeignEnum = NO;
+ message.hasOptionalImportEnum = NO;
+
+ message.hasOptionalStringPiece = NO;
+ message.hasOptionalCord = NO;
+
+ // -----------------------------------------------------------------
+
+ [message.repeatedInt32Array removeAll];
+ [message.repeatedInt64Array removeAll];
+ [message.repeatedUint32Array removeAll];
+ [message.repeatedUint64Array removeAll];
+ [message.repeatedSint32Array removeAll];
+ [message.repeatedSint64Array removeAll];
+ [message.repeatedFixed32Array removeAll];
+ [message.repeatedFixed64Array removeAll];
+ [message.repeatedSfixed32Array removeAll];
+ [message.repeatedSfixed64Array removeAll];
+ [message.repeatedFloatArray removeAll];
+ [message.repeatedDoubleArray removeAll];
+ [message.repeatedBoolArray removeAll];
+ [message.repeatedStringArray removeAllObjects];
+ [message.repeatedBytesArray removeAllObjects];
+
+ [message.repeatedGroupArray removeAllObjects];
+ [message.repeatedNestedMessageArray removeAllObjects];
+ [message.repeatedForeignMessageArray removeAllObjects];
+ [message.repeatedImportMessageArray removeAllObjects];
+
+ [message.repeatedNestedEnumArray removeAll];
+ [message.repeatedForeignEnumArray removeAll];
+ [message.repeatedImportEnumArray removeAll];
+
+ [message.repeatedStringPieceArray removeAllObjects];
+ [message.repeatedCordArray removeAllObjects];
+
+ // -----------------------------------------------------------------
+
+ message.hasDefaultInt32 = NO;
+ message.hasDefaultInt64 = NO;
+ message.hasDefaultUint32 = NO;
+ message.hasDefaultUint64 = NO;
+ message.hasDefaultSint32 = NO;
+ message.hasDefaultSint64 = NO;
+ message.hasDefaultFixed32 = NO;
+ message.hasDefaultFixed64 = NO;
+ message.hasDefaultSfixed32 = NO;
+ message.hasDefaultSfixed64 = NO;
+ message.hasDefaultFloat = NO;
+ message.hasDefaultDouble = NO;
+ message.hasDefaultBool = NO;
+ message.hasDefaultString = NO;
+ message.hasDefaultBytes = NO;
+
+ message.hasDefaultNestedEnum = NO;
+ message.hasDefaultForeignEnum = NO;
+ message.hasDefaultImportEnum = NO;
+
+ message.hasDefaultStringPiece = NO;
+ message.hasDefaultCord = NO;
+}
+
+- (void)setAllExtensions:(TestAllExtensions *)message
+ repeatedCount:(uint32_t)count {
+ [message setExtension:[UnittestRoot optionalInt32Extension] value:@101];
+ [message setExtension:[UnittestRoot optionalInt64Extension] value:@102L];
+ [message setExtension:[UnittestRoot optionalUint32Extension] value:@103];
+ [message setExtension:[UnittestRoot optionalUint64Extension] value:@104L];
+ [message setExtension:[UnittestRoot optionalSint32Extension] value:@105];
+ [message setExtension:[UnittestRoot optionalSint64Extension] value:@106L];
+ [message setExtension:[UnittestRoot optionalFixed32Extension] value:@107];
+ [message setExtension:[UnittestRoot optionalFixed64Extension] value:@108L];
+ [message setExtension:[UnittestRoot optionalSfixed32Extension] value:@109];
+ [message setExtension:[UnittestRoot optionalSfixed64Extension] value:@110L];
+ [message setExtension:[UnittestRoot optionalFloatExtension] value:@111.0f];
+ [message setExtension:[UnittestRoot optionalDoubleExtension] value:@112.0];
+ [message setExtension:[UnittestRoot optionalBoolExtension] value:@YES];
+ [message setExtension:[UnittestRoot optionalStringExtension] value:@"115"];
+ [message setExtension:[UnittestRoot optionalBytesExtension]
+ value:[NSData gpbtu_dataWithEmbeddedNulls]];
+
+ OptionalGroup_extension *optionalGroup = [OptionalGroup_extension message];
+ [optionalGroup setA:117];
+ [message setExtension:[UnittestRoot optionalGroupExtension]
+ value:optionalGroup];
+ TestAllTypes_NestedMessage *nestedMessage =
+ [TestAllTypes_NestedMessage message];
+ [nestedMessage setBb:118];
+ [message setExtension:[UnittestRoot optionalNestedMessageExtension]
+ value:nestedMessage];
+ ForeignMessage *foreignMessage = [ForeignMessage message];
+ [foreignMessage setC:119];
+ [message setExtension:[UnittestRoot optionalForeignMessageExtension]
+ value:foreignMessage];
+ ImportMessage *importMessage = [ImportMessage message];
+ [importMessage setD:120];
+ [message setExtension:[UnittestRoot optionalImportMessageExtension]
+ value:importMessage];
+
+ [message setExtension:[UnittestRoot optionalNestedEnumExtension]
+ value:@(TestAllTypes_NestedEnum_Baz)];
+ [message setExtension:[UnittestRoot optionalForeignEnumExtension]
+ value:@(ForeignEnum_ForeignBaz)];
+ [message setExtension:[UnittestRoot optionalImportEnumExtension]
+ value:@(ImportEnum_ImportBaz)];
+
+ [message setExtension:[UnittestRoot optionalStringPieceExtension]
+ value:@"124"];
+ [message setExtension:[UnittestRoot optionalCordExtension] value:@"125"];
+
+ for (uint32_t i = 0; i < count; ++i) {
+ [message addExtension:[UnittestRoot repeatedInt32Extension]
+ value:@(201 + i * 100)];
+ [message addExtension:[UnittestRoot repeatedInt64Extension]
+ value:@(202 + i * 100)];
+ [message addExtension:[UnittestRoot repeatedUint32Extension]
+ value:@(203 + i * 100)];
+ [message addExtension:[UnittestRoot repeatedUint64Extension]
+ value:@(204 + i * 100)];
+ [message addExtension:[UnittestRoot repeatedSint32Extension]
+ value:@(205 + i * 100)];
+ [message addExtension:[UnittestRoot repeatedSint64Extension]
+ value:@(206 + i * 100)];
+ [message addExtension:[UnittestRoot repeatedFixed32Extension]
+ value:@(207 + i * 100)];
+ [message addExtension:[UnittestRoot repeatedFixed64Extension]
+ value:@(208 + i * 100)];
+ [message addExtension:[UnittestRoot repeatedSfixed32Extension]
+ value:@(209 + i * 100)];
+ [message addExtension:[UnittestRoot repeatedSfixed64Extension]
+ value:@(210 + i * 100)];
+ [message addExtension:[UnittestRoot repeatedFloatExtension]
+ value:@(211 + i * 100)];
+ [message addExtension:[UnittestRoot repeatedDoubleExtension]
+ value:@(212 + i * 100)];
+ [message addExtension:[UnittestRoot repeatedBoolExtension]
+ value:@((i % 2) ? YES : NO)];
+ NSString *string = [[NSString alloc] initWithFormat:@"%d", 215 + i * 100];
+ [message addExtension:[UnittestRoot repeatedStringExtension] value:string];
+ [string release];
+ NSData *data = [[NSData alloc] initWithUint32_gpbtu:216 + i * 100];
+ [message addExtension:[UnittestRoot repeatedBytesExtension] value:data];
+ [data release];
+
+ RepeatedGroup_extension *repeatedGroup =
+ [[RepeatedGroup_extension alloc] init];
+ [repeatedGroup setA:217 + i * 100];
+ [message addExtension:[UnittestRoot repeatedGroupExtension]
+ value:repeatedGroup];
+ [repeatedGroup release];
+ nestedMessage = [[TestAllTypes_NestedMessage alloc] init];
+ [nestedMessage setBb:218 + i * 100];
+ [message addExtension:[UnittestRoot repeatedNestedMessageExtension]
+ value:nestedMessage];
+ [nestedMessage release];
+ foreignMessage = [[ForeignMessage alloc] init];
+ [foreignMessage setC:219 + i * 100];
+ [message addExtension:[UnittestRoot repeatedForeignMessageExtension]
+ value:foreignMessage];
+ [foreignMessage release];
+ importMessage = [[ImportMessage alloc] init];
+ [importMessage setD:220 + i * 100];
+ [message addExtension:[UnittestRoot repeatedImportMessageExtension]
+ value:importMessage];
+ [importMessage release];
+ [message addExtension:[UnittestRoot repeatedNestedEnumExtension]
+ value:@((i % 2) ? TestAllTypes_NestedEnum_Bar
+ : TestAllTypes_NestedEnum_Baz)];
+ [message addExtension:[UnittestRoot repeatedForeignEnumExtension]
+ value:@((i % 2) ? ForeignEnum_ForeignBar
+ : ForeignEnum_ForeignBaz)];
+ [message
+ addExtension:[UnittestRoot repeatedImportEnumExtension]
+ value:@((i % 2) ? ImportEnum_ImportBar : ImportEnum_ImportBaz)];
+
+ string = [[NSString alloc] initWithFormat:@"%d", 224 + i * 100];
+ [message addExtension:[UnittestRoot repeatedStringPieceExtension]
+ value:string];
+ [string release];
+
+ string = [[NSString alloc] initWithFormat:@"%d", 225 + i * 100];
+ [message addExtension:[UnittestRoot repeatedCordExtension] value:string];
+ [string release];
+ }
+
+ // -----------------------------------------------------------------
+
+ [message setExtension:[UnittestRoot defaultInt32Extension] value:@401];
+ [message setExtension:[UnittestRoot defaultInt64Extension] value:@402L];
+ [message setExtension:[UnittestRoot defaultUint32Extension] value:@403];
+ [message setExtension:[UnittestRoot defaultUint64Extension] value:@404L];
+ [message setExtension:[UnittestRoot defaultSint32Extension] value:@405];
+ [message setExtension:[UnittestRoot defaultSint64Extension] value:@406L];
+ [message setExtension:[UnittestRoot defaultFixed32Extension] value:@407];
+ [message setExtension:[UnittestRoot defaultFixed64Extension] value:@408L];
+ [message setExtension:[UnittestRoot defaultSfixed32Extension] value:@409];
+ [message setExtension:[UnittestRoot defaultSfixed64Extension] value:@410L];
+ [message setExtension:[UnittestRoot defaultFloatExtension] value:@411.0f];
+ [message setExtension:[UnittestRoot defaultDoubleExtension] value:@412.0];
+ [message setExtension:[UnittestRoot defaultBoolExtension] value:@NO];
+ [message setExtension:[UnittestRoot defaultStringExtension] value:@"415"];
+ [message setExtension:[UnittestRoot defaultBytesExtension]
+ value:[NSData gpbtu_dataWithUint32:416]];
+
+ [message setExtension:[UnittestRoot defaultNestedEnumExtension]
+ value:@(TestAllTypes_NestedEnum_Foo)];
+ [message setExtension:[UnittestRoot defaultForeignEnumExtension]
+ value:@(ForeignEnum_ForeignFoo)];
+ [message setExtension:[UnittestRoot defaultImportEnumExtension]
+ value:@(ImportEnum_ImportFoo)];
+
+ [message setExtension:[UnittestRoot defaultStringPieceExtension]
+ value:@"424"];
+ [message setExtension:[UnittestRoot defaultCordExtension] value:@"425"];
+}
+
+- (void)setAllMapFields:(TestMap *)message numEntries:(uint32_t)count {
+ message.mapInt32Int32 = [GPBInt32Int32Dictionary dictionary];
+ message.mapInt64Int64 = [GPBInt64Int64Dictionary dictionary];
+ message.mapUint32Uint32 = [GPBUInt32UInt32Dictionary dictionary];
+ message.mapUint64Uint64 = [GPBUInt64UInt64Dictionary dictionary];
+ message.mapSint32Sint32 = [GPBInt32Int32Dictionary dictionary];
+ message.mapSint64Sint64 = [GPBInt64Int64Dictionary dictionary];
+ message.mapFixed32Fixed32 = [GPBUInt32UInt32Dictionary dictionary];
+ message.mapFixed64Fixed64 = [GPBUInt64UInt64Dictionary dictionary];
+ message.mapSfixed32Sfixed32 = [GPBInt32Int32Dictionary dictionary];
+ message.mapSfixed64Sfixed64 = [GPBInt64Int64Dictionary dictionary];
+ message.mapInt32Float = [GPBInt32FloatDictionary dictionary];
+ message.mapInt32Double = [GPBInt32DoubleDictionary dictionary];
+ message.mapBoolBool = [GPBBoolBoolDictionary dictionary];
+ message.mapStringString = [NSMutableDictionary dictionary];
+ message.mapInt32Bytes = [GPBInt32ObjectDictionary dictionary];
+ message.mapInt32Enum = [GPBInt32EnumDictionary
+ dictionaryWithValidationFunction:MapEnum_IsValidValue];
+ message.mapInt32ForeignMessage = [GPBInt32ObjectDictionary dictionary];
+
+ for (uint32_t i = 0; i < count; i++) {
+ [message.mapInt32Int32 setValue:(i + 1) forKey:100 + i * 100];
+ [message.mapInt64Int64 setValue:(i + 1) forKey:101 + i * 100];
+ [message.mapUint32Uint32 setValue:(i + 1) forKey:102 + i * 100];
+ [message.mapUint64Uint64 setValue:(i + 1) forKey:103 + i * 100];
+ [message.mapSint32Sint32 setValue:(i + 1) forKey:104 + i * 100];
+ [message.mapSint64Sint64 setValue:(i + 1) forKey:105 + i * 100];
+ [message.mapFixed32Fixed32 setValue:(i + 1) forKey:106 + i * 100];
+ [message.mapFixed64Fixed64 setValue:(i + 1) forKey:107 + i * 100];
+ [message.mapSfixed32Sfixed32 setValue:(i + 1) forKey:108 + i * 100];
+ [message.mapSfixed64Sfixed64 setValue:(i + 1) forKey:109 + i * 100];
+ [message.mapInt32Float setValue:(i + 1) forKey:110 + i * 100];
+ [message.mapInt32Double setValue:(i + 1) forKey:111 + i * 100];
+ [message.mapBoolBool setValue:((i % 2) == 1) forKey:((i % 2) == 0)];
+
+ NSString *keyStr = [[NSString alloc] initWithFormat:@"%d", 112 + i * 100];
+ NSString *dataStr = [[NSString alloc] initWithFormat:@"%d", i + 1];
+ [message.mapStringString setObject:dataStr forKey:keyStr];
+ [keyStr release];
+ [dataStr release];
+
+ NSData *data = [[NSData alloc] initWithUint32_gpbtu:i + 1];
+ [message.mapInt32Bytes setValue:data forKey:113 + i * 100];
+ [data release];
+
+ [message.mapInt32Enum
+ setValue:(i % 2) ? MapEnum_MapEnumBar : MapEnum_MapEnumBaz
+ forKey:114 + i * 100];
+
+ ForeignMessage *subMsg = [[ForeignMessage alloc] init];
+ subMsg.c = i + 1;
+ [message.mapInt32ForeignMessage setValue:subMsg forKey:115 + i * 100];
+ [subMsg release];
+ }
+}
+
+- (GPBExtensionRegistry *)extensionRegistry {
+ return [UnittestRoot extensionRegistry];
+}
+
+- (TestAllTypes *)allSetRepeatedCount:(uint32_t)count {
+ TestAllTypes *message = [TestAllTypes message];
+ [self setAllFields:message repeatedCount:count];
+ return message;
+}
+
+- (TestAllExtensions *)allExtensionsSetRepeatedCount:(uint32_t)count {
+ TestAllExtensions *message = [TestAllExtensions message];
+ [self setAllExtensions:message repeatedCount:count];
+ return message;
+}
+
+- (TestPackedTypes *)packedSetRepeatedCount:(uint32_t)count {
+ TestPackedTypes *message = [TestPackedTypes message];
+ [self setPackedFields:message repeatedCount:count];
+ return message;
+}
+
+- (TestPackedExtensions *)packedExtensionsSetRepeatedCount:(uint32_t)count {
+ TestPackedExtensions *message = [TestPackedExtensions message];
+ [self setPackedExtensions:message repeatedCount:count];
+ return message;
+}
+
+// -------------------------------------------------------------------
+
+- (void)assertClear:(TestAllTypes *)message {
+ // hasBlah() should initially be NO for all optional fields.
+ XCTAssertFalse(message.hasOptionalInt32);
+ XCTAssertFalse(message.hasOptionalInt64);
+ XCTAssertFalse(message.hasOptionalUint32);
+ XCTAssertFalse(message.hasOptionalUint64);
+ XCTAssertFalse(message.hasOptionalSint32);
+ XCTAssertFalse(message.hasOptionalSint64);
+ XCTAssertFalse(message.hasOptionalFixed32);
+ XCTAssertFalse(message.hasOptionalFixed64);
+ XCTAssertFalse(message.hasOptionalSfixed32);
+ XCTAssertFalse(message.hasOptionalSfixed64);
+ XCTAssertFalse(message.hasOptionalFloat);
+ XCTAssertFalse(message.hasOptionalDouble);
+ XCTAssertFalse(message.hasOptionalBool);
+ XCTAssertFalse(message.hasOptionalString);
+ XCTAssertFalse(message.hasOptionalBytes);
+
+ XCTAssertFalse(message.hasOptionalGroup);
+ XCTAssertFalse(message.hasOptionalNestedMessage);
+ XCTAssertFalse(message.hasOptionalForeignMessage);
+ XCTAssertFalse(message.hasOptionalImportMessage);
+
+ XCTAssertFalse(message.hasOptionalNestedEnum);
+ XCTAssertFalse(message.hasOptionalForeignEnum);
+ XCTAssertFalse(message.hasOptionalImportEnum);
+
+ XCTAssertFalse(message.hasOptionalStringPiece);
+ XCTAssertFalse(message.hasOptionalCord);
+
+ // Optional fields without defaults are set to zero or something like it.
+ XCTAssertEqual(0, message.optionalInt32);
+ XCTAssertEqual(0LL, message.optionalInt64);
+ XCTAssertEqual(0U, message.optionalUint32);
+ XCTAssertEqual(0ULL, message.optionalUint64);
+ XCTAssertEqual(0, message.optionalSint32);
+ XCTAssertEqual(0LL, message.optionalSint64);
+ XCTAssertEqual(0U, message.optionalFixed32);
+ XCTAssertEqual(0ULL, message.optionalFixed64);
+ XCTAssertEqual(0, message.optionalSfixed32);
+ XCTAssertEqual(0LL, message.optionalSfixed64);
+ XCTAssertEqual(0.0f, message.optionalFloat);
+ XCTAssertEqual(0.0, message.optionalDouble);
+ XCTAssertFalse(message.optionalBool);
+ XCTAssertEqualObjects(message.optionalString, @"");
+ XCTAssertEqualObjects(message.optionalBytes, GPBEmptyNSData());
+
+ // Embedded messages should also be clear.
+ XCTAssertFalse(message.hasOptionalGroup);
+ XCTAssertFalse(message.hasOptionalNestedMessage);
+ XCTAssertFalse(message.hasOptionalForeignMessage);
+ XCTAssertFalse(message.hasOptionalImportMessage);
+
+ // Enums without defaults are set to the first value in the enum.
+ XCTAssertEqual(TestAllTypes_NestedEnum_Foo, message.optionalNestedEnum);
+ XCTAssertEqual(ForeignEnum_ForeignFoo, message.optionalForeignEnum);
+ XCTAssertEqual(ImportEnum_ImportFoo, message.optionalImportEnum);
+
+ XCTAssertEqualObjects(message.optionalStringPiece, @"");
+ XCTAssertEqualObjects(message.optionalCord, @"");
+
+ // Repeated fields are empty.
+ XCTAssertEqual(0U, message.repeatedInt32Array.count);
+ XCTAssertEqual(0U, message.repeatedInt64Array.count);
+ XCTAssertEqual(0U, message.repeatedUint32Array.count);
+ XCTAssertEqual(0U, message.repeatedUint64Array.count);
+ XCTAssertEqual(0U, message.repeatedSint32Array.count);
+ XCTAssertEqual(0U, message.repeatedSint64Array.count);
+ XCTAssertEqual(0U, message.repeatedFixed32Array.count);
+ XCTAssertEqual(0U, message.repeatedFixed64Array.count);
+ XCTAssertEqual(0U, message.repeatedSfixed32Array.count);
+ XCTAssertEqual(0U, message.repeatedSfixed64Array.count);
+ XCTAssertEqual(0U, message.repeatedFloatArray.count);
+ XCTAssertEqual(0U, message.repeatedDoubleArray.count);
+ XCTAssertEqual(0U, message.repeatedBoolArray.count);
+ XCTAssertEqual(0U, message.repeatedStringArray.count);
+ XCTAssertEqual(0U, message.repeatedBytesArray.count);
+
+ XCTAssertEqual(0U, message.repeatedGroupArray.count);
+ XCTAssertEqual(0U, message.repeatedNestedMessageArray.count);
+ XCTAssertEqual(0U, message.repeatedForeignMessageArray.count);
+ XCTAssertEqual(0U, message.repeatedImportMessageArray.count);
+ XCTAssertEqual(0U, message.repeatedNestedEnumArray.count);
+ XCTAssertEqual(0U, message.repeatedForeignEnumArray.count);
+ XCTAssertEqual(0U, message.repeatedImportEnumArray.count);
+
+ XCTAssertEqual(0U, message.repeatedStringPieceArray.count);
+ XCTAssertEqual(0U, message.repeatedCordArray.count);
+
+ // hasBlah() should also be NO for all default fields.
+ XCTAssertFalse(message.hasDefaultInt32);
+ XCTAssertFalse(message.hasDefaultInt64);
+ XCTAssertFalse(message.hasDefaultUint32);
+ XCTAssertFalse(message.hasDefaultUint64);
+ XCTAssertFalse(message.hasDefaultSint32);
+ XCTAssertFalse(message.hasDefaultSint64);
+ XCTAssertFalse(message.hasDefaultFixed32);
+ XCTAssertFalse(message.hasDefaultFixed64);
+ XCTAssertFalse(message.hasDefaultSfixed32);
+ XCTAssertFalse(message.hasDefaultSfixed64);
+ XCTAssertFalse(message.hasDefaultFloat);
+ XCTAssertFalse(message.hasDefaultDouble);
+ XCTAssertFalse(message.hasDefaultBool);
+ XCTAssertFalse(message.hasDefaultString);
+ XCTAssertFalse(message.hasDefaultBytes);
+
+ XCTAssertFalse(message.hasDefaultNestedEnum);
+ XCTAssertFalse(message.hasDefaultForeignEnum);
+ XCTAssertFalse(message.hasDefaultImportEnum);
+
+ XCTAssertFalse(message.hasDefaultStringPiece);
+ XCTAssertFalse(message.hasDefaultCord);
+
+ // Fields with defaults have their default values (duh).
+ XCTAssertEqual(41, message.defaultInt32);
+ XCTAssertEqual(42LL, message.defaultInt64);
+ XCTAssertEqual(43U, message.defaultUint32);
+ XCTAssertEqual(44ULL, message.defaultUint64);
+ XCTAssertEqual(-45, message.defaultSint32);
+ XCTAssertEqual(46LL, message.defaultSint64);
+ XCTAssertEqual(47U, message.defaultFixed32);
+ XCTAssertEqual(48ULL, message.defaultFixed64);
+ XCTAssertEqual(49, message.defaultSfixed32);
+ XCTAssertEqual(-50LL, message.defaultSfixed64);
+ XCTAssertEqualWithAccuracy(51.5f, message.defaultFloat, 0.1);
+ XCTAssertEqualWithAccuracy(52e3, message.defaultDouble, 0.1);
+ XCTAssertTrue(message.defaultBool);
+ XCTAssertEqualObjects(@"hello", message.defaultString);
+ XCTAssertEqualObjects([NSData gpbtu_dataWithCString:"world"],
+ message.defaultBytes);
+
+ XCTAssertEqual(TestAllTypes_NestedEnum_Bar, message.defaultNestedEnum);
+ XCTAssertEqual(ForeignEnum_ForeignBar, message.defaultForeignEnum);
+ XCTAssertEqual(ImportEnum_ImportBar, message.defaultImportEnum);
+
+ XCTAssertEqualObjects(@"abc", message.defaultStringPiece);
+ XCTAssertEqualObjects(@"123", message.defaultCord);
+}
+
+- (void)assertExtensionsClear:(TestAllExtensions *)message {
+ // hasBlah() should initially be NO for all optional fields.
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalInt32Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalInt64Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalUint32Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalUint64Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalSint32Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalSint64Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalFixed32Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalFixed64Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalSfixed32Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalSfixed64Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalFloatExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalDoubleExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalBoolExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalStringExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalBytesExtension]]);
+
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalNestedMessageExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalForeignMessageExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalImportMessageExtension]]);
+
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalNestedEnumExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalForeignEnumExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalImportEnumExtension]]);
+
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalStringPieceExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalCordExtension]]);
+
+ // Optional fields without defaults are set to zero or something like it.
+ XCTAssertEqual(0, [[message getExtension:[UnittestRoot optionalInt32Extension]] intValue]);
+ XCTAssertEqual(0LL,[[message getExtension:[UnittestRoot optionalInt64Extension]] longLongValue]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot optionalUint32Extension]] unsignedIntValue]);
+ XCTAssertEqual(0ULL, [[message getExtension:[UnittestRoot optionalUint64Extension]] unsignedLongLongValue]);
+ XCTAssertEqual(0, [[message getExtension:[UnittestRoot optionalSint32Extension]] intValue]);
+ XCTAssertEqual(0LL, [[message getExtension:[UnittestRoot optionalSint64Extension]] longLongValue]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot optionalFixed32Extension]] unsignedIntValue]);
+ XCTAssertEqual(0ULL, [[message getExtension:[UnittestRoot optionalFixed64Extension]] unsignedLongLongValue]);
+ XCTAssertEqual(0, [[message getExtension:[UnittestRoot optionalSfixed32Extension]] intValue]);
+ XCTAssertEqual(0LL, [[message getExtension:[UnittestRoot optionalSfixed64Extension]] longLongValue]);
+ XCTAssertEqualWithAccuracy(0.0f, [[message getExtension:[UnittestRoot optionalFloatExtension]] floatValue], 0.01);
+ XCTAssertEqualWithAccuracy(0.0, [[message getExtension:[UnittestRoot optionalDoubleExtension]] doubleValue], 0.01);
+ XCTAssertFalse([[message getExtension:[UnittestRoot optionalBoolExtension]] boolValue]);
+ XCTAssertEqualObjects(@"", [message getExtension:[UnittestRoot optionalStringExtension]]);
+ XCTAssertEqualObjects(GPBEmptyNSData(), [message getExtension:[UnittestRoot optionalBytesExtension]]);
+
+ // Embedded messages should also be clear.
+
+ XCTAssertFalse([[message getExtension:[UnittestRoot optionalGroupExtension]] hasA]);
+ XCTAssertFalse([[message getExtension:[UnittestRoot optionalNestedMessageExtension]] hasBb]);
+ XCTAssertFalse([[message getExtension:[UnittestRoot optionalForeignMessageExtension]] hasC]);
+ XCTAssertFalse([[message getExtension:[UnittestRoot optionalImportMessageExtension]] hasD]);
+
+ XCTAssertEqual(0, [(TestAllTypes_OptionalGroup*)[message getExtension:[UnittestRoot optionalGroupExtension]] a]);
+ XCTAssertEqual(0, [(TestAllTypes_NestedMessage*)[message getExtension:[UnittestRoot optionalNestedMessageExtension]] bb]);
+ XCTAssertEqual(0, [[message getExtension:[UnittestRoot optionalForeignMessageExtension]] c]);
+ XCTAssertEqual(0, [[message getExtension:[UnittestRoot optionalImportMessageExtension]] d]);
+
+ // Enums without defaults are set to the first value in the enum.
+ XCTAssertEqual(TestAllTypes_NestedEnum_Foo,
+ [[message getExtension:[UnittestRoot optionalNestedEnumExtension]] intValue]);
+ XCTAssertEqual(ForeignEnum_ForeignFoo,
+ [[message getExtension:[UnittestRoot optionalForeignEnumExtension]] intValue]);
+ XCTAssertEqual(ImportEnum_ImportFoo,
+ [[message getExtension:[UnittestRoot optionalImportEnumExtension]] intValue]);
+
+ XCTAssertEqualObjects(@"", [message getExtension:[UnittestRoot optionalStringPieceExtension]]);
+ XCTAssertEqualObjects(@"", [message getExtension:[UnittestRoot optionalCordExtension]]);
+
+ // Repeated fields are empty.
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedInt32Extension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedInt64Extension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedUint32Extension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedUint64Extension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedSint32Extension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedSint64Extension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedFixed32Extension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedFixed64Extension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedSfixed32Extension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedSfixed64Extension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedFloatExtension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedDoubleExtension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedBoolExtension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedStringExtension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedBytesExtension]] count]);
+
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedGroupExtension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedNestedMessageExtension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedForeignMessageExtension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedImportMessageExtension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedNestedEnumExtension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedForeignEnumExtension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedImportEnumExtension]] count]);
+
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedStringPieceExtension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedCordExtension]] count]);
+
+ // hasBlah() should also be NO for all default fields.
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultInt32Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultInt64Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultUint32Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultUint64Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultSint32Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultSint64Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultFixed32Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultFixed64Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultSfixed32Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultSfixed64Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultFloatExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultDoubleExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultBoolExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultStringExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultBytesExtension]]);
+
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultNestedEnumExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultForeignEnumExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultImportEnumExtension]]);
+
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultStringPieceExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultCordExtension]]);
+
+ // Fields with defaults have their default values (duh).
+ XCTAssertEqual( 41, [[message getExtension:[UnittestRoot defaultInt32Extension]] intValue]);
+ XCTAssertEqual( 42LL, [[message getExtension:[UnittestRoot defaultInt64Extension]] longLongValue]);
+ XCTAssertEqual( 43U, [[message getExtension:[UnittestRoot defaultUint32Extension]] unsignedIntValue]);
+ XCTAssertEqual( 44ULL, [[message getExtension:[UnittestRoot defaultUint64Extension]] unsignedLongLongValue]);
+ XCTAssertEqual(-45, [[message getExtension:[UnittestRoot defaultSint32Extension]] intValue]);
+ XCTAssertEqual( 46LL, [[message getExtension:[UnittestRoot defaultSint64Extension]] longLongValue]);
+ XCTAssertEqual( 47, [[message getExtension:[UnittestRoot defaultFixed32Extension]] intValue]);
+ XCTAssertEqual( 48ULL, [[message getExtension:[UnittestRoot defaultFixed64Extension]] unsignedLongLongValue]);
+ XCTAssertEqual( 49, [[message getExtension:[UnittestRoot defaultSfixed32Extension]] intValue]);
+ XCTAssertEqual(-50LL, [[message getExtension:[UnittestRoot defaultSfixed64Extension]] longLongValue]);
+ XCTAssertEqualWithAccuracy( 51.5f, [[message getExtension:[UnittestRoot defaultFloatExtension]] floatValue], 0.01);
+ XCTAssertEqualWithAccuracy( 52e3, [[message getExtension:[UnittestRoot defaultDoubleExtension]] doubleValue], 0.01);
+ XCTAssertTrue([[message getExtension:[UnittestRoot defaultBoolExtension]] boolValue]);
+ XCTAssertEqualObjects(@"hello", [message getExtension:[UnittestRoot defaultStringExtension]]);
+ XCTAssertEqualObjects([NSData gpbtu_dataWithCString:"world"], [message getExtension:[UnittestRoot defaultBytesExtension]]);
+
+ XCTAssertEqual(TestAllTypes_NestedEnum_Bar,
+ [[message getExtension:[UnittestRoot defaultNestedEnumExtension]] intValue]);
+ XCTAssertEqual(ForeignEnum_ForeignBar,
+ [[message getExtension:[UnittestRoot defaultForeignEnumExtension]] intValue]);
+ XCTAssertEqual(ImportEnum_ImportBar,
+ [[message getExtension:[UnittestRoot defaultImportEnumExtension]] intValue]);
+
+ XCTAssertEqualObjects(@"abc", [message getExtension:[UnittestRoot defaultStringPieceExtension]]);
+ XCTAssertEqualObjects(@"123", [message getExtension:[UnittestRoot defaultCordExtension]]);
+}
+
+- (void)modifyRepeatedFields:(TestAllTypes *)message {
+ [message.repeatedInt32Array replaceValueAtIndex:1 withValue:501];
+ [message.repeatedInt64Array replaceValueAtIndex:1 withValue:502];
+ [message.repeatedUint32Array replaceValueAtIndex:1 withValue:503];
+ [message.repeatedUint64Array replaceValueAtIndex:1 withValue:504];
+ [message.repeatedSint32Array replaceValueAtIndex:1 withValue:505];
+ [message.repeatedSint64Array replaceValueAtIndex:1 withValue:506];
+ [message.repeatedFixed32Array replaceValueAtIndex:1 withValue:507];
+ [message.repeatedFixed64Array replaceValueAtIndex:1 withValue:508];
+ [message.repeatedSfixed32Array replaceValueAtIndex:1 withValue:509];
+ [message.repeatedSfixed64Array replaceValueAtIndex:1 withValue:510];
+ [message.repeatedFloatArray replaceValueAtIndex:1 withValue:511];
+ [message.repeatedDoubleArray replaceValueAtIndex:1 withValue:512];
+ [message.repeatedBoolArray replaceValueAtIndex:1 withValue:YES];
+ [message.repeatedStringArray replaceObjectAtIndex:1 withObject:@"515"];
+
+ NSData *data = [[NSData alloc] initWithUint32_gpbtu:516];
+ [message.repeatedBytesArray replaceObjectAtIndex:1 withObject:data];
+ [data release];
+
+ TestAllTypes_RepeatedGroup *testAll =
+ [[TestAllTypes_RepeatedGroup alloc] init];
+ [testAll setA:517];
+ [message.repeatedGroupArray replaceObjectAtIndex:1 withObject:testAll];
+ [testAll release];
+
+ TestAllTypes_NestedMessage *nestedMessage =
+ [[TestAllTypes_NestedMessage alloc] init];
+ [nestedMessage setBb:518];
+ [message.repeatedNestedMessageArray replaceObjectAtIndex:1
+ withObject:nestedMessage];
+ [nestedMessage release];
+
+ ForeignMessage *foreignMessage = [[ForeignMessage alloc] init];
+ [foreignMessage setC:519];
+ [message.repeatedForeignMessageArray replaceObjectAtIndex:1
+ withObject:foreignMessage];
+ [foreignMessage release];
+
+ ImportMessage *importMessage = [[ImportMessage alloc] init];
+ [importMessage setD:520];
+ [message.repeatedImportMessageArray replaceObjectAtIndex:1
+ withObject:importMessage];
+ [importMessage release];
+
+ [message.repeatedNestedEnumArray replaceValueAtIndex:1 withValue:TestAllTypes_NestedEnum_Foo];
+ [message.repeatedForeignEnumArray replaceValueAtIndex:1 withValue:ForeignEnum_ForeignFoo];
+ [message.repeatedImportEnumArray replaceValueAtIndex:1 withValue:ImportEnum_ImportFoo];
+
+ [message.repeatedStringPieceArray replaceObjectAtIndex:1 withObject:@"524"];
+ [message.repeatedCordArray replaceObjectAtIndex:1 withObject:@"525"];
+}
+
+- (void)assertRepeatedFieldsModified:(TestAllTypes *)message
+ repeatedCount:(uint32_t)count {
+ // ModifyRepeatedFields only sets the second repeated element of each
+ // field. In addition to verifying this, we also verify that the first
+ // element and size were *not* modified.
+ XCTAssertEqual(count, message.repeatedInt32Array.count);
+ XCTAssertEqual(count, message.repeatedInt64Array.count);
+ XCTAssertEqual(count, message.repeatedUint32Array.count);
+ XCTAssertEqual(count, message.repeatedUint64Array.count);
+ XCTAssertEqual(count, message.repeatedSint32Array.count);
+ XCTAssertEqual(count, message.repeatedSint64Array.count);
+ XCTAssertEqual(count, message.repeatedFixed32Array.count);
+ XCTAssertEqual(count, message.repeatedFixed64Array.count);
+ XCTAssertEqual(count, message.repeatedSfixed32Array.count);
+ XCTAssertEqual(count, message.repeatedSfixed64Array.count);
+ XCTAssertEqual(count, message.repeatedFloatArray.count);
+ XCTAssertEqual(count, message.repeatedDoubleArray.count);
+ XCTAssertEqual(count, message.repeatedBoolArray.count);
+ XCTAssertEqual(count, message.repeatedStringArray.count);
+ XCTAssertEqual(count, message.repeatedBytesArray.count);
+
+ XCTAssertEqual(count, message.repeatedGroupArray.count);
+ XCTAssertEqual(count, message.repeatedNestedMessageArray.count);
+ XCTAssertEqual(count, message.repeatedForeignMessageArray.count);
+ XCTAssertEqual(count, message.repeatedImportMessageArray.count);
+ XCTAssertEqual(count, message.repeatedNestedEnumArray.count);
+ XCTAssertEqual(count, message.repeatedForeignEnumArray.count);
+ XCTAssertEqual(count, message.repeatedImportEnumArray.count);
+
+ XCTAssertEqual(count, message.repeatedStringPieceArray.count);
+ XCTAssertEqual(count, message.repeatedCordArray.count);
+
+ XCTAssertEqual(201, [message.repeatedInt32Array valueAtIndex:0]);
+ XCTAssertEqual(202LL, [message.repeatedInt64Array valueAtIndex:0]);
+ XCTAssertEqual(203U, [message.repeatedUint32Array valueAtIndex:0]);
+ XCTAssertEqual(204ULL, [message.repeatedUint64Array valueAtIndex:0]);
+ XCTAssertEqual(205, [message.repeatedSint32Array valueAtIndex:0]);
+ XCTAssertEqual(206LL, [message.repeatedSint64Array valueAtIndex:0]);
+ XCTAssertEqual(207U, [message.repeatedFixed32Array valueAtIndex:0]);
+ XCTAssertEqual(208ULL, [message.repeatedFixed64Array valueAtIndex:0]);
+ XCTAssertEqual(209, [message.repeatedSfixed32Array valueAtIndex:0]);
+ XCTAssertEqual(210LL, [message.repeatedSfixed64Array valueAtIndex:0]);
+ XCTAssertEqualWithAccuracy(211.0f, [message.repeatedFloatArray valueAtIndex:0], 0.01);
+ XCTAssertEqualWithAccuracy(212.0, [message.repeatedDoubleArray valueAtIndex:0], 0.01);
+ XCTAssertFalse([message.repeatedBoolArray valueAtIndex:0]);
+ XCTAssertEqualObjects(@"215", message.repeatedStringArray[0]);
+ XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:216],
+ message.repeatedBytesArray[0]);
+
+ XCTAssertEqual(217, ((TestAllTypes_RepeatedGroup*)message.repeatedGroupArray[0]).a);
+ XCTAssertEqual(218, ((TestAllTypes_NestedMessage*)message.repeatedNestedMessageArray[0]).bb);
+ XCTAssertEqual(219, ((ForeignMessage*)message.repeatedForeignMessageArray[0]).c);
+ XCTAssertEqual(220, ((ImportMessage*)message.repeatedImportMessageArray[0]).d);
+
+ XCTAssertEqual(TestAllTypes_NestedEnum_Baz, [message.repeatedNestedEnumArray valueAtIndex:0]);
+ XCTAssertEqual(ForeignEnum_ForeignBaz, [message.repeatedForeignEnumArray valueAtIndex:0]);
+ XCTAssertEqual(ImportEnum_ImportBaz, [message.repeatedImportEnumArray valueAtIndex:0]);
+
+ XCTAssertEqualObjects(@"224", message.repeatedStringPieceArray[0]);
+ XCTAssertEqualObjects(@"225", message.repeatedCordArray[0]);
+
+ // Actually verify the second (modified) elements now.
+ XCTAssertEqual(501, [message.repeatedInt32Array valueAtIndex:1]);
+ XCTAssertEqual(502LL, [message.repeatedInt64Array valueAtIndex:1]);
+ XCTAssertEqual(503U, [message.repeatedUint32Array valueAtIndex:1]);
+ XCTAssertEqual(504ULL, [message.repeatedUint64Array valueAtIndex:1]);
+ XCTAssertEqual(505, [message.repeatedSint32Array valueAtIndex:1]);
+ XCTAssertEqual(506LL, [message.repeatedSint64Array valueAtIndex:1]);
+ XCTAssertEqual(507U, [message.repeatedFixed32Array valueAtIndex:1]);
+ XCTAssertEqual(508ULL, [message.repeatedFixed64Array valueAtIndex:1]);
+ XCTAssertEqual(509, [message.repeatedSfixed32Array valueAtIndex:1]);
+ XCTAssertEqual(510LL, [message.repeatedSfixed64Array valueAtIndex:1]);
+ XCTAssertEqualWithAccuracy(511.0f, [message.repeatedFloatArray valueAtIndex:1], 0.01);
+ XCTAssertEqualWithAccuracy(512.0, [message.repeatedDoubleArray valueAtIndex:1], 0.01);
+ XCTAssertTrue([message.repeatedBoolArray valueAtIndex:1]);
+ XCTAssertEqualObjects(@"515", message.repeatedStringArray[1]);
+ XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:516],
+ message.repeatedBytesArray[1]);
+
+ XCTAssertEqual(517, ((TestAllTypes_RepeatedGroup*)message.repeatedGroupArray[1]).a);
+ XCTAssertEqual(518, ((TestAllTypes_NestedMessage*)message.repeatedNestedMessageArray[1]).bb);
+ XCTAssertEqual(519, ((ForeignMessage*)message.repeatedForeignMessageArray[1]).c);
+ XCTAssertEqual(520, ((ImportMessage*)message.repeatedImportMessageArray[1]).d);
+
+ XCTAssertEqual(TestAllTypes_NestedEnum_Foo, [message.repeatedNestedEnumArray valueAtIndex:1]);
+ XCTAssertEqual(ForeignEnum_ForeignFoo, [message.repeatedForeignEnumArray valueAtIndex:1]);
+ XCTAssertEqual(ImportEnum_ImportFoo, [message.repeatedImportEnumArray valueAtIndex:1]);
+
+ XCTAssertEqualObjects(@"524", message.repeatedStringPieceArray[1]);
+ XCTAssertEqualObjects(@"525", message.repeatedCordArray[1]);
+}
+
+- (void)setPackedFields:(TestPackedTypes *)message
+ repeatedCount:(uint32_t)count {
+ {
+ GPBInt32Array *scratch = [GPBInt32Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:601 + i * 100];
+ }
+ [message setPackedInt32Array:scratch];
+ }
+ {
+ GPBInt64Array *scratch = [GPBInt64Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:602 + i * 100];
+ }
+ [message setPackedInt64Array:scratch];
+ }
+ {
+ GPBUInt32Array *scratch = [GPBUInt32Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:603 + i * 100];
+ }
+ [message setPackedUint32Array:scratch];
+ }
+ {
+ GPBUInt64Array *scratch = [GPBUInt64Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:604 + i * 100];
+ }
+ [message setPackedUint64Array:scratch];
+ }
+ {
+ GPBInt32Array *scratch = [GPBInt32Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:605 + i * 100];
+ }
+ [message setPackedSint32Array:scratch];
+ }
+ {
+ GPBInt64Array *scratch = [GPBInt64Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:606 + i * 100];
+ }
+ [message setPackedSint64Array:scratch];
+ }
+ {
+ GPBUInt32Array *scratch = [GPBUInt32Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:607 + i * 100];
+ }
+ [message setPackedFixed32Array:scratch];
+ }
+ {
+ GPBUInt64Array *scratch = [GPBUInt64Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:608 + i * 100];
+ }
+ [message setPackedFixed64Array:scratch];
+ }
+ {
+ GPBInt32Array *scratch = [GPBInt32Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:609 + i * 100];
+ }
+ [message setPackedSfixed32Array:scratch];
+ }
+ {
+ GPBInt64Array *scratch = [GPBInt64Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:610 + i * 100];
+ }
+ [message setPackedSfixed64Array:scratch];
+ }
+ {
+ GPBFloatArray *scratch = [GPBFloatArray array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:611 + i * 100];
+ }
+ [message setPackedFloatArray:scratch];
+ }
+ {
+ GPBDoubleArray *scratch = [GPBDoubleArray array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:612 + i * 100];
+ }
+ [message setPackedDoubleArray:scratch];
+ }
+ {
+ GPBBoolArray *scratch = [GPBBoolArray array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:(i % 2) ? YES : NO];
+ }
+ [message setPackedBoolArray:scratch];
+ }
+ {
+ GPBEnumArray *scratch =
+ [GPBEnumArray arrayWithValidationFunction:ForeignEnum_IsValidValue];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch
+ addValue:(i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz];
+ }
+ [message setPackedEnumArray:scratch];
+ }
+}
+
+- (void)assertPackedFieldsSet:(TestPackedTypes *)message
+ repeatedCount:(uint32_t)count {
+ XCTAssertEqual(count, message.packedInt32Array.count);
+ XCTAssertEqual(count, message.packedInt64Array.count);
+ XCTAssertEqual(count, message.packedUint32Array.count);
+ XCTAssertEqual(count, message.packedUint64Array.count);
+ XCTAssertEqual(count, message.packedSint32Array.count);
+ XCTAssertEqual(count, message.packedSint64Array.count);
+ XCTAssertEqual(count, message.packedFixed32Array.count);
+ XCTAssertEqual(count, message.packedFixed64Array.count);
+ XCTAssertEqual(count, message.packedSfixed32Array.count);
+ XCTAssertEqual(count, message.packedSfixed64Array.count);
+ XCTAssertEqual(count, message.packedFloatArray.count);
+ XCTAssertEqual(count, message.packedDoubleArray.count);
+ XCTAssertEqual(count, message.packedBoolArray.count);
+ XCTAssertEqual(count, message.packedEnumArray.count);
+ for (uint32_t i = 0; i < count; ++i) {
+ XCTAssertEqual((int)(601 + i * 100),
+ [message.packedInt32Array valueAtIndex:i]);
+ XCTAssertEqual(602 + i * 100, [message.packedInt64Array valueAtIndex:i]);
+ XCTAssertEqual(603 + i * 100, [message.packedUint32Array valueAtIndex:i]);
+ XCTAssertEqual(604 + i * 100, [message.packedUint64Array valueAtIndex:i]);
+ XCTAssertEqual((int)(605 + i * 100),
+ [message.packedSint32Array valueAtIndex:i]);
+ XCTAssertEqual(606 + i * 100, [message.packedSint64Array valueAtIndex:i]);
+ XCTAssertEqual(607 + i * 100, [message.packedFixed32Array valueAtIndex:i]);
+ XCTAssertEqual(608 + i * 100, [message.packedFixed64Array valueAtIndex:i]);
+ XCTAssertEqual((int)(609 + i * 100),
+ [message.packedSfixed32Array valueAtIndex:i]);
+ XCTAssertEqual(610 + i * 100, [message.packedSfixed64Array valueAtIndex:i]);
+ XCTAssertEqualWithAccuracy(611 + i * 100,
+ [message.packedFloatArray valueAtIndex:i], 0.01);
+ XCTAssertEqualWithAccuracy(
+ 612 + i * 100, [message.packedDoubleArray valueAtIndex:i], 0.01);
+ XCTAssertEqual((i % 2) ? YES : NO,
+ [message.packedBoolArray valueAtIndex:i]);
+ XCTAssertEqual((i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz,
+ [message.packedEnumArray valueAtIndex:i]);
+ }
+}
+
+- (void)setPackedExtensions:(TestPackedExtensions *)message
+ repeatedCount:(uint32_t)count {
+ for (uint32_t i = 0; i < count; i++) {
+ [message addExtension:[UnittestRoot packedInt32Extension]
+ value:@(601 + i * 100)];
+ [message addExtension:[UnittestRoot packedInt64Extension]
+ value:@(602 + i * 100)];
+ [message addExtension:[UnittestRoot packedUint32Extension]
+ value:@(603 + i * 100)];
+ [message addExtension:[UnittestRoot packedUint64Extension]
+ value:@(604 + i * 100)];
+ [message addExtension:[UnittestRoot packedSint32Extension]
+ value:@(605 + i * 100)];
+ [message addExtension:[UnittestRoot packedSint64Extension]
+ value:@(606 + i * 100)];
+ [message addExtension:[UnittestRoot packedFixed32Extension]
+ value:@(607 + i * 100)];
+ [message addExtension:[UnittestRoot packedFixed64Extension]
+ value:@(608 + i * 100)];
+ [message addExtension:[UnittestRoot packedSfixed32Extension]
+ value:@(609 + i * 100)];
+ [message addExtension:[UnittestRoot packedSfixed64Extension]
+ value:@(610 + i * 100)];
+ [message addExtension:[UnittestRoot packedFloatExtension]
+ value:@(611 + i * 100)];
+ [message addExtension:[UnittestRoot packedDoubleExtension]
+ value:@(612 + i * 100)];
+ [message addExtension:[UnittestRoot packedBoolExtension]
+ value:@((i % 2) ? YES : NO)];
+ [message addExtension:[UnittestRoot packedEnumExtension]
+ value:@((i % 2) ? ForeignEnum_ForeignBar
+ : ForeignEnum_ForeignBaz)];
+ }
+}
+
+- (void)assertPackedExtensionsSet:(TestPackedExtensions *)message
+ repeatedCount:(uint32_t)count{
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedInt32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedInt64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedUint32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedUint64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedSint32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedSint64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedFixed32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedFixed64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedSfixed32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedSfixed64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedFloatExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedDoubleExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedBoolExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedEnumExtension]] count]);
+
+ for (uint32_t i = 0; i < count; ++i) {
+ id extension = [message getExtension:[UnittestRoot packedInt32Extension]];
+ XCTAssertEqual((int)(601 + i * 100), [extension[i] intValue]);
+ extension = [message getExtension:[UnittestRoot packedInt64Extension]];
+ XCTAssertEqual(602 + i * 100, [extension[i] longLongValue]);
+ extension = [message getExtension:[UnittestRoot packedUint32Extension]];
+ XCTAssertEqual(603 + i * 100, [extension[i] unsignedIntValue]);
+ extension = [message getExtension:[UnittestRoot packedUint64Extension]];
+ XCTAssertEqual(604 + i * 100, [extension[i] unsignedLongLongValue]);
+ extension = [message getExtension:[UnittestRoot packedSint32Extension]];
+ XCTAssertEqual((int)(605 + i * 100), [extension[i] intValue]);
+ extension = [message getExtension:[UnittestRoot packedSint64Extension]];
+ XCTAssertEqual(606 + i * 100, [extension[i] longLongValue]);
+ extension = [message getExtension:[UnittestRoot packedFixed32Extension]];
+ XCTAssertEqual(607 + i * 100, [extension[i] unsignedIntValue]);
+ extension = [message getExtension:[UnittestRoot packedFixed64Extension]];
+ XCTAssertEqual(608 + i * 100, [extension[i] unsignedLongLongValue]);
+ extension = [message getExtension:[UnittestRoot packedSfixed32Extension]];
+ XCTAssertEqual((int)(609 + i * 100), [extension[i] intValue]);
+ extension = [message getExtension:[UnittestRoot packedSfixed64Extension]];
+ XCTAssertEqual(610 + i * 100, [extension[i] longLongValue]);
+ extension = [message getExtension:[UnittestRoot packedFloatExtension]];
+ XCTAssertEqualWithAccuracy(611 + i * 100, [extension[i] floatValue], 0.01);
+ extension = [message getExtension:[UnittestRoot packedDoubleExtension]];
+ XCTAssertEqualWithAccuracy(612 + i * 100, [extension[i] doubleValue], 0.01);
+ extension = [message getExtension:[UnittestRoot packedBoolExtension]];
+ XCTAssertEqual((i % 2) ? YES : NO, [extension[i] boolValue]);
+ extension = [message getExtension:[UnittestRoot packedEnumExtension]];
+ XCTAssertEqual((i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz,
+ [extension[i] intValue]);
+ }
+}
+
+- (void)assertAllFieldsKVCMatch:(TestAllTypes *)message {
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalInt32"], @YES);
+ XCTAssertEqualObjects(@(message.optionalInt32), [message valueForKey:@"optionalInt32"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalInt64"], @YES);
+ XCTAssertEqualObjects(@(message.optionalInt64), [message valueForKey:@"optionalInt64"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalUint32"], @YES);
+ XCTAssertEqualObjects(@(message.optionalUint32), [message valueForKey:@"optionalUint32"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalUint64"], @YES);
+ XCTAssertEqualObjects(@(message.optionalUint64), [message valueForKey:@"optionalUint64"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalSint32"], @YES);
+ XCTAssertEqualObjects(@(message.optionalSint32), [message valueForKey:@"optionalSint32"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalSint64"], @YES);
+ XCTAssertEqualObjects(@(message.optionalSint64), [message valueForKey:@"optionalSint64"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalFixed32"], @YES);
+ XCTAssertEqualObjects(@(message.optionalFixed32), [message valueForKey:@"optionalFixed32"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalFixed64"], @YES);
+ XCTAssertEqualObjects(@(message.optionalFixed64), [message valueForKey:@"optionalFixed64"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalSfixed32"], @YES);
+ XCTAssertEqualObjects(@(message.optionalSfixed32), [message valueForKey:@"optionalSfixed32"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalSfixed64"], @YES);
+ XCTAssertEqualObjects(@(message.optionalSfixed64), [message valueForKey:@"optionalSfixed64"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalFloat"], @YES);
+ XCTAssertEqualObjects(@(message.optionalFloat), [message valueForKey:@"optionalFloat"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalDouble"], @YES);
+ XCTAssertEqualObjects(@(message.optionalDouble), [message valueForKey:@"optionalDouble"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalBool"], @YES);
+ XCTAssertEqualObjects(@(message.optionalBool), [message valueForKey:@"optionalBool"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalString"], @YES);
+ XCTAssertEqualObjects(message.optionalString, [message valueForKey:@"optionalString"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalBytes"], @YES);
+ XCTAssertEqualObjects(message.optionalBytes, [message valueForKey:@"optionalBytes"]);
+
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalGroup"], @YES);
+ XCTAssertNotNil(message.optionalGroup);
+ XCTAssertEqualObjects([message valueForKeyPath:@"optionalGroup.hasA"], @YES);
+ XCTAssertEqualObjects(@(message.optionalGroup.a), [message valueForKeyPath:@"optionalGroup.a"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalNestedMessage"], @YES);
+ XCTAssertNotNil(message.optionalNestedMessage);
+ XCTAssertEqualObjects([message valueForKeyPath:@"optionalNestedMessage.hasBb"], @YES);
+ XCTAssertEqualObjects(@(message.optionalNestedMessage.bb), [message valueForKeyPath:@"optionalNestedMessage.bb"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalForeignMessage"], @YES);
+ XCTAssertNotNil(message.optionalForeignMessage);
+ XCTAssertEqualObjects([message valueForKeyPath:@"optionalForeignMessage.hasC"], @YES);
+ XCTAssertEqualObjects(@(message.optionalForeignMessage.c), [message valueForKeyPath:@"optionalForeignMessage.c"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalImportMessage"], @YES);
+ XCTAssertNotNil(message.optionalForeignMessage);
+ XCTAssertEqualObjects([message valueForKeyPath:@"optionalImportMessage.hasD"], @YES);
+ XCTAssertEqualObjects(@(message.optionalImportMessage.d), [message valueForKeyPath:@"optionalImportMessage.d"]);
+
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalNestedEnum"], @YES);
+ XCTAssertEqualObjects(@(message.optionalNestedEnum), [message valueForKey:@"optionalNestedEnum"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalForeignEnum"], @YES);
+ XCTAssertEqualObjects(@(message.optionalForeignEnum), [message valueForKey:@"optionalForeignEnum"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalImportEnum"], @YES);
+ XCTAssertEqualObjects(@(message.optionalImportEnum), [message valueForKey:@"optionalImportEnum"]);
+
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalStringPiece"], @YES);
+ XCTAssertEqualObjects(message.optionalStringPiece, [message valueForKey:@"optionalStringPiece"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalCord"], @YES);
+ XCTAssertEqualObjects(message.optionalCord, [message valueForKey:@"optionalCord"]);
+
+ // -----------------------------------------------------------------
+
+ // GPBArray interface for repeated
+
+ XCTAssertEqualObjects(message.repeatedInt32Array, [message valueForKey:@"repeatedInt32Array"]);
+ XCTAssertEqualObjects(message.repeatedInt64Array, [message valueForKey:@"repeatedInt64Array"]);
+ XCTAssertEqualObjects(message.repeatedUint32Array, [message valueForKey:@"repeatedUint32Array"]);
+ XCTAssertEqualObjects(message.repeatedUint64Array, [message valueForKey:@"repeatedUint64Array"]);
+ XCTAssertEqualObjects(message.repeatedSint32Array, [message valueForKey:@"repeatedSint32Array"]);
+ XCTAssertEqualObjects(message.repeatedSint64Array, [message valueForKey:@"repeatedSint64Array"]);
+ XCTAssertEqualObjects(message.repeatedFixed32Array, [message valueForKey:@"repeatedFixed32Array"]);
+ XCTAssertEqualObjects(message.repeatedFixed64Array, [message valueForKey:@"repeatedFixed64Array"]);
+ XCTAssertEqualObjects(message.repeatedSfixed32Array, [message valueForKey:@"repeatedSfixed32Array"]);
+ XCTAssertEqualObjects(message.repeatedSfixed64Array, [message valueForKey:@"repeatedSfixed64Array"]);
+ XCTAssertEqualObjects(message.repeatedFloatArray, [message valueForKey:@"repeatedFloatArray"]);
+ XCTAssertEqualObjects(message.repeatedDoubleArray, [message valueForKey:@"repeatedDoubleArray"]);
+ XCTAssertEqualObjects(message.repeatedBoolArray, [message valueForKey:@"repeatedBoolArray"]);
+ XCTAssertEqualObjects(message.repeatedStringArray, [message valueForKey:@"repeatedStringArray"]);
+ XCTAssertEqualObjects(message.repeatedBytesArray, [message valueForKey:@"repeatedBytesArray"]);
+
+ XCTAssertEqualObjects(message.repeatedGroupArray, [message valueForKey:@"repeatedGroupArray"]);
+ XCTAssertEqualObjects(message.repeatedNestedMessageArray, [message valueForKey:@"repeatedNestedMessageArray"]);
+ XCTAssertEqualObjects(message.repeatedForeignMessageArray, [message valueForKey:@"repeatedForeignMessageArray"]);
+ XCTAssertEqualObjects(message.repeatedImportMessageArray, [message valueForKey:@"repeatedImportMessageArray"]);
+
+ XCTAssertEqualObjects(message.repeatedNestedEnumArray, [message valueForKey:@"repeatedNestedEnumArray"]);
+ XCTAssertEqualObjects(message.repeatedForeignEnumArray, [message valueForKey:@"repeatedForeignEnumArray"]);
+ XCTAssertEqualObjects(message.repeatedImportEnumArray, [message valueForKey:@"repeatedImportEnumArray"]);
+
+ XCTAssertEqualObjects(message.repeatedStringPieceArray, [message valueForKey:@"repeatedStringPieceArray"]);
+ XCTAssertEqualObjects(message.repeatedCordArray, [message valueForKey:@"repeatedCordArray"]);
+
+ // -----------------------------------------------------------------
+
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultInt32"], @YES);
+ XCTAssertEqualObjects(@(message.defaultInt32), [message valueForKey:@"defaultInt32"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultInt64"], @YES);
+ XCTAssertEqualObjects(@(message.defaultInt64), [message valueForKey:@"defaultInt64"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultUint32"], @YES);
+ XCTAssertEqualObjects(@(message.defaultUint32), [message valueForKey:@"defaultUint32"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultUint64"], @YES);
+ XCTAssertEqualObjects(@(message.defaultUint64), [message valueForKey:@"defaultUint64"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultSint32"], @YES);
+ XCTAssertEqualObjects(@(message.defaultSint32), [message valueForKey:@"defaultSint32"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultSint64"], @YES);
+ XCTAssertEqualObjects(@(message.defaultSint64), [message valueForKey:@"defaultSint64"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultFixed32"], @YES);
+ XCTAssertEqualObjects(@(message.defaultFixed32), [message valueForKey:@"defaultFixed32"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultFixed64"], @YES);
+ XCTAssertEqualObjects(@(message.defaultFixed64), [message valueForKey:@"defaultFixed64"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultSfixed32"], @YES);
+ XCTAssertEqualObjects(@(message.defaultSfixed32), [message valueForKey:@"defaultSfixed32"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultSfixed64"], @YES);
+ XCTAssertEqualObjects(@(message.defaultSfixed64), [message valueForKey:@"defaultSfixed64"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultFloat"], @YES);
+ XCTAssertEqualObjects(@(message.defaultFloat), [message valueForKey:@"defaultFloat"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultDouble"], @YES);
+ XCTAssertEqualObjects(@(message.defaultDouble), [message valueForKey:@"defaultDouble"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultBool"], @YES);
+ XCTAssertEqualObjects(@(message.defaultBool), [message valueForKey:@"defaultBool"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultString"], @YES);
+ XCTAssertEqualObjects(message.defaultString, [message valueForKey:@"defaultString"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultBytes"], @YES);
+ XCTAssertEqualObjects(message.defaultBytes, [message valueForKey:@"defaultBytes"]);
+
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultNestedEnum"], @YES);
+ XCTAssertEqualObjects(@(message.defaultNestedEnum), [message valueForKey:@"defaultNestedEnum"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultForeignEnum"], @YES);
+ XCTAssertEqualObjects(@(message.defaultForeignEnum), [message valueForKey:@"defaultForeignEnum"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultImportEnum"], @YES);
+ XCTAssertEqualObjects(@(message.defaultImportEnum), [message valueForKey:@"defaultImportEnum"]);
+
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultStringPiece"], @YES);
+ XCTAssertEqualObjects(message.defaultStringPiece, [message valueForKey:@"defaultStringPiece"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultCord"], @YES);
+ XCTAssertEqualObjects(message.defaultCord, [message valueForKey:@"defaultCord"]);
+}
+
+- (void)setAllFieldsViaKVC:(TestAllTypes *)message
+ repeatedCount:(uint32_t)count {
+ [message setValue:@101 forKey:@"optionalInt32"];
+ [message setValue:@102 forKey:@"optionalInt64"];
+ [message setValue:@103 forKey:@"optionalUint32"];
+ [message setValue:@104 forKey:@"optionalUint64"];
+ [message setValue:@105 forKey:@"optionalSint32"];
+ [message setValue:@106 forKey:@"optionalSint64"];
+ [message setValue:@107 forKey:@"optionalFixed32"];
+ [message setValue:@108 forKey:@"optionalFixed64"];
+ [message setValue:@109 forKey:@"optionalSfixed32"];
+ [message setValue:@110 forKey:@"optionalSfixed64"];
+ [message setValue:@111 forKey:@"optionalFloat"];
+ [message setValue:@112 forKey:@"optionalDouble"];
+ [message setValue:@YES forKey:@"optionalBool"];
+ [message setValue:@"115" forKey:@"optionalString"];
+ [message setValue:[NSData gpbtu_dataWithEmbeddedNulls]
+ forKey:@"optionalBytes"];
+
+ TestAllTypes_OptionalGroup *allTypes = [TestAllTypes_OptionalGroup message];
+ [allTypes setValue:@117 forKey:@"a"];
+ [message setValue:allTypes forKey:@"optionalGroup"];
+ TestAllTypes_NestedMessage *nestedMessage =
+ [TestAllTypes_NestedMessage message];
+ [nestedMessage setValue:@118 forKey:@"bb"];
+ [message setValue:nestedMessage forKey:@"optionalNestedMessage"];
+ ForeignMessage *foreignMessage = [ForeignMessage message];
+ [foreignMessage setValue:@119 forKey:@"c"];
+ [message setValue:foreignMessage forKey:@"optionalForeignMessage"];
+ ImportMessage *importMessage = [ImportMessage message];
+ [importMessage setValue:@120 forKey:@"d"];
+ [message setValue:importMessage forKey:@"optionalImportMessage"];
+
+ [message setValue:@(TestAllTypes_NestedEnum_Baz)
+ forKey:@"optionalNestedEnum"];
+ [message setValue:@(ForeignEnum_ForeignBaz) forKey:@"optionalForeignEnum"];
+ [message setValue:@(ImportEnum_ImportBaz) forKey:@"optionalImportEnum"];
+
+ [message setValue:@"124" forKey:@"optionalStringPiece"];
+ [message setValue:@"125" forKey:@"optionalCord"];
+
+ // -----------------------------------------------------------------
+
+ {
+ GPBInt32Array *scratch = [GPBInt32Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:201 + i * 100];
+ }
+ [message setValue:scratch forKey:@"repeatedInt32Array"];
+ }
+ {
+ GPBInt64Array *scratch = [GPBInt64Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:202 + i * 100];
+ }
+ [message setValue:scratch forKey:@"repeatedInt64Array"];
+ }
+ {
+ GPBUInt32Array *scratch = [GPBUInt32Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:203 + i * 100];
+ }
+ [message setValue:scratch forKey:@"repeatedUint32Array"];
+ }
+ {
+ GPBUInt64Array *scratch = [GPBUInt64Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:204 + i * 100];
+ }
+ [message setValue:scratch forKey:@"repeatedUint64Array"];
+ }
+ {
+ GPBInt32Array *scratch = [GPBInt32Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:205 + i * 100];
+ }
+ [message setValue:scratch forKey:@"repeatedSint32Array"];
+ }
+ {
+ GPBInt64Array *scratch = [GPBInt64Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:206 + i * 100];
+ }
+ [message setValue:scratch forKey:@"repeatedSint64Array"];
+ }
+ {
+ GPBUInt32Array *scratch = [GPBUInt32Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:207 + i * 100];
+ }
+ [message setValue:scratch forKey:@"repeatedFixed32Array"];
+ }
+ {
+ GPBUInt64Array *scratch = [GPBUInt64Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:208 + i * 100];
+ }
+ [message setValue:scratch forKey:@"repeatedFixed64Array"];
+ }
+ {
+ GPBInt32Array *scratch = [GPBInt32Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:209 + i * 100];
+ }
+ [message setValue:scratch forKey:@"repeatedSfixed32Array"];
+ }
+ {
+ GPBInt64Array *scratch = [GPBInt64Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:210 + i * 100];
+ }
+ [message setValue:scratch forKey:@"repeatedSfixed64Array"];
+ }
+ {
+ GPBFloatArray *scratch = [GPBFloatArray array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:211 + i * 100];
+ }
+ [message setValue:scratch forKey:@"repeatedFloatArray"];
+ }
+ {
+ GPBDoubleArray *scratch = [GPBDoubleArray array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:212 + i * 100];
+ }
+ [message setValue:scratch forKey:@"repeatedDoubleArray"];
+ }
+ {
+ GPBBoolArray *scratch = [GPBBoolArray array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:(i % 2) ? YES : NO];
+ }
+ [message setValue:scratch forKey:@"repeatedBoolArray"];
+ }
+
+ NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:count];
+ for (uint32_t i = 0; i < count; ++i) {
+ NSString *string = [[NSString alloc] initWithFormat:@"%d", 215 + i * 100];
+ [array addObject:string];
+ [string release];
+ }
+ [message setValue:array forKey:@"repeatedStringArray"];
+ [array release];
+
+ array = [[NSMutableArray alloc] initWithCapacity:count];
+ for (uint32_t i = 0; i < count; ++i) {
+ NSData *data = [[NSData alloc] initWithUint32_gpbtu:216 + i * 100];
+ [array addObject:data];
+ [data release];
+ }
+ [message setValue:array forKey:@"repeatedBytesArray"];
+ [array release];
+
+ array = [[NSMutableArray alloc] initWithCapacity:count];
+ for (uint32_t i = 0; i < count; ++i) {
+ TestAllTypes_RepeatedGroup *testAll =
+ [[TestAllTypes_RepeatedGroup alloc] init];
+ [testAll setA:217 + i * 100];
+ [array addObject:testAll];
+ [testAll release];
+ }
+ [message setValue:array forKey:@"repeatedGroupArray"];
+ [array release];
+
+ array = [[NSMutableArray alloc] initWithCapacity:count];
+ for (uint32_t i = 0; i < count; ++i) {
+ nestedMessage = [[TestAllTypes_NestedMessage alloc] init];
+ [nestedMessage setBb:218 + i * 100];
+ [array addObject:nestedMessage];
+ [nestedMessage release];
+ }
+ [message setValue:array forKey:@"repeatedNestedMessageArray"];
+ [array release];
+
+ array = [[NSMutableArray alloc] initWithCapacity:count];
+ for (uint32_t i = 0; i < count; ++i) {
+ foreignMessage = [[ForeignMessage alloc] init];
+ [foreignMessage setC:219 + i * 100];
+ [array addObject:foreignMessage];
+ [foreignMessage release];
+ }
+ [message setValue:array forKey:@"repeatedForeignMessageArray"];
+ [array release];
+
+ array = [[NSMutableArray alloc] initWithCapacity:count];
+ for (uint32_t i = 0; i < count; ++i) {
+ importMessage = [[ImportMessage alloc] init];
+ [importMessage setD:220 + i * 100];
+ [array addObject:importMessage];
+ [importMessage release];
+ }
+ [message setValue:array forKey:@"repeatedImportMessageArray"];
+ [array release];
+
+ {
+ GPBEnumArray *scratch = [GPBEnumArray
+ arrayWithValidationFunction:TestAllTypes_NestedEnum_IsValidValue];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:(i % 2) ? TestAllTypes_NestedEnum_Bar
+ : TestAllTypes_NestedEnum_Baz];
+ }
+ [message setValue:scratch forKey:@"repeatedNestedEnumArray"];
+ }
+ {
+ GPBEnumArray *scratch =
+ [GPBEnumArray arrayWithValidationFunction:ForeignEnum_IsValidValue];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch
+ addValue:(i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz];
+ }
+ [message setValue:scratch forKey:@"repeatedForeignEnumArray"];
+ }
+ {
+ GPBEnumArray *scratch =
+ [GPBEnumArray arrayWithValidationFunction:ImportEnum_IsValidValue];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:(i % 2) ? ImportEnum_ImportBar : ImportEnum_ImportBaz];
+ }
+ [message setValue:scratch forKey:@"repeatedImportEnumArray"];
+ }
+
+ array = [[NSMutableArray alloc] initWithCapacity:count];
+ for (uint32_t i = 0; i < count; ++i) {
+ NSString *string = [[NSString alloc] initWithFormat:@"%d", 224 + i * 100];
+ [array addObject:string];
+ [string release];
+ }
+ [message setValue:array forKey:@"repeatedStringPieceArray"];
+ [array release];
+
+ array = [[NSMutableArray alloc] initWithCapacity:count];
+ for (uint32_t i = 0; i < count; ++i) {
+ NSString *string = [[NSString alloc] initWithFormat:@"%d", 225 + i * 100];
+ [array addObject:string];
+ [string release];
+ }
+ [message setValue:array forKey:@"repeatedCordArray"];
+ [array release];
+
+ // -----------------------------------------------------------------
+
+ [message setValue:@401 forKey:@"defaultInt32"];
+ [message setValue:@402 forKey:@"defaultInt64"];
+ [message setValue:@403 forKey:@"defaultUint32"];
+ [message setValue:@404 forKey:@"defaultUint64"];
+ [message setValue:@405 forKey:@"defaultSint32"];
+ [message setValue:@406 forKey:@"defaultSint64"];
+ [message setValue:@407 forKey:@"defaultFixed32"];
+ [message setValue:@408 forKey:@"defaultFixed64"];
+ [message setValue:@409 forKey:@"defaultSfixed32"];
+ [message setValue:@410 forKey:@"defaultSfixed64"];
+ [message setValue:@411 forKey:@"defaultFloat"];
+ [message setValue:@412 forKey:@"defaultDouble"];
+ [message setValue:@NO forKey:@"defaultBool"];
+ [message setValue:@"415" forKey:@"defaultString"];
+ [message setValue:[NSData gpbtu_dataWithUint32:416] forKey:@"defaultBytes"];
+
+ [message setValue:@(TestAllTypes_NestedEnum_Foo) forKey:@"defaultNestedEnum"];
+ [message setValue:@(ForeignEnum_ForeignFoo) forKey:@"defaultForeignEnum"];
+ [message setValue:@(ImportEnum_ImportFoo) forKey:@"defaultImportEnum"];
+
+ [message setValue:@"424" forKey:@"defaultStringPiece"];
+ [message setValue:@"425" forKey:@"defaultCord"];
+}
+
+- (void)assertClearKVC:(TestAllTypes *)message {
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalInt32"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalInt64"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalUint32"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalUint64"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalSint32"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalSint64"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalFixed32"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalFixed64"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalSfixed32"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalSfixed64"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalFloat"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalDouble"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalBool"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalString"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalBytes"], @NO);
+
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalGroup"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalNestedMessage"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalForeignMessage"],
+ @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalImportMessage"], @NO);
+
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalNestedEnum"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalForeignEnum"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalImportEnum"], @NO);
+
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalStringPiece"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalCord"], @NO);
+
+ // Optional fields without defaults are set to zero or something like it.
+ XCTAssertEqualObjects([message valueForKey:@"optionalInt32"], @0);
+ XCTAssertEqualObjects([message valueForKey:@"optionalInt64"], @0);
+ XCTAssertEqualObjects([message valueForKey:@"optionalUint32"], @0);
+ XCTAssertEqualObjects([message valueForKey:@"optionalUint64"], @0);
+ XCTAssertEqualObjects([message valueForKey:@"optionalSint32"], @0);
+ XCTAssertEqualObjects([message valueForKey:@"optionalSint64"], @0);
+ XCTAssertEqualObjects([message valueForKey:@"optionalFixed32"], @0);
+ XCTAssertEqualObjects([message valueForKey:@"optionalFixed64"], @0);
+ XCTAssertEqualObjects([message valueForKey:@"optionalSfixed32"], @0);
+ XCTAssertEqualObjects([message valueForKey:@"optionalSfixed64"], @0);
+ XCTAssertEqualObjects([message valueForKey:@"optionalFloat"], @0);
+ XCTAssertEqualObjects([message valueForKey:@"optionalDouble"], @0);
+ XCTAssertEqualObjects([message valueForKey:@"optionalBool"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"optionalString"], @"");
+ XCTAssertEqualObjects([message valueForKey:@"optionalBytes"],
+ GPBEmptyNSData());
+
+ // Embedded messages should also be exist, but be clear.
+ XCTAssertNotNil([message valueForKeyPath:@"optionalGroup"]);
+ XCTAssertNotNil([message valueForKeyPath:@"optionalNestedMessage"]);
+ XCTAssertNotNil([message valueForKeyPath:@"optionalForeignMessage"]);
+ XCTAssertNotNil([message valueForKeyPath:@"optionalImportMessage"]);
+ XCTAssertEqualObjects([message valueForKeyPath:@"optionalGroup.hasA"], @NO);
+ XCTAssertEqualObjects(
+ [message valueForKeyPath:@"optionalNestedMessage.hasBb"], @NO);
+ XCTAssertEqualObjects(
+ [message valueForKeyPath:@"optionalForeignMessage.hasC"], @NO);
+ XCTAssertEqualObjects([message valueForKeyPath:@"optionalImportMessage.hasD"],
+ @NO);
+
+ XCTAssertEqualObjects([message valueForKeyPath:@"optionalGroup.a"], @0);
+ XCTAssertEqualObjects([message valueForKeyPath:@"optionalNestedMessage.bb"],
+ @0);
+ XCTAssertEqualObjects([message valueForKeyPath:@"optionalForeignMessage.c"],
+ @0);
+ XCTAssertEqualObjects([message valueForKeyPath:@"optionalImportMessage.d"],
+ @0);
+
+ // Enums without defaults are set to the first value in the enum.
+ XCTAssertEqualObjects([message valueForKey:@"optionalNestedEnum"],
+ @(TestAllTypes_NestedEnum_Foo));
+ XCTAssertEqualObjects([message valueForKey:@"optionalForeignEnum"],
+ @(ForeignEnum_ForeignFoo));
+ XCTAssertEqualObjects([message valueForKey:@"optionalImportEnum"],
+ @(ImportEnum_ImportFoo));
+
+ XCTAssertEqualObjects([message valueForKey:@"optionalStringPiece"], @"");
+ XCTAssertEqualObjects([message valueForKey:@"optionalCord"], @"");
+
+ // NSArray interface for repeated doesn't have has*, nil means no value.
+
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultInt32"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultInt64"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultUint32"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultUint64"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultSint32"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultSint64"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultFixed32"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultFixed64"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultSfixed32"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultSfixed64"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultFloat"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultDouble"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultBool"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultString"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultBytes"], @NO);
+
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultNestedEnum"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultForeignEnum"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultImportEnum"], @NO);
+
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultStringPiece"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultCord"], @NO);
+
+ // Fields with defaults have their default values (duh).
+ XCTAssertEqualObjects([message valueForKey:@"defaultInt32"], @41);
+ XCTAssertEqualObjects([message valueForKey:@"defaultInt64"], @42);
+ XCTAssertEqualObjects([message valueForKey:@"defaultUint32"], @43);
+ XCTAssertEqualObjects([message valueForKey:@"defaultUint64"], @44);
+ XCTAssertEqualObjects([message valueForKey:@"defaultSint32"], @-45);
+ XCTAssertEqualObjects([message valueForKey:@"defaultSint64"], @46);
+ XCTAssertEqualObjects([message valueForKey:@"defaultFixed32"], @47);
+ XCTAssertEqualObjects([message valueForKey:@"defaultFixed64"], @48);
+ XCTAssertEqualObjects([message valueForKey:@"defaultSfixed32"], @49);
+ XCTAssertEqualObjects([message valueForKey:@"defaultSfixed64"], @-50);
+ XCTAssertEqualObjects([message valueForKey:@"defaultFloat"], @51.5);
+ XCTAssertEqualObjects([message valueForKey:@"defaultDouble"], @52e3);
+ XCTAssertEqualObjects([message valueForKey:@"defaultBool"], @YES);
+ XCTAssertEqualObjects([message valueForKey:@"defaultString"], @"hello");
+ XCTAssertEqualObjects([message valueForKey:@"defaultBytes"],
+ [NSData gpbtu_dataWithCString:"world"]);
+
+ XCTAssertEqualObjects([message valueForKey:@"defaultNestedEnum"],
+ @(TestAllTypes_NestedEnum_Bar));
+ XCTAssertEqualObjects([message valueForKey:@"defaultForeignEnum"],
+ @(ForeignEnum_ForeignBar));
+ XCTAssertEqualObjects([message valueForKey:@"defaultImportEnum"],
+ @(ImportEnum_ImportBar));
+
+ XCTAssertEqualObjects([message valueForKey:@"defaultStringPiece"], @"abc");
+ XCTAssertEqualObjects([message valueForKey:@"defaultCord"], @"123");
+}
+
+@end
diff --git a/objectivec/Tests/GPBUnittestProtos.m b/objectivec/Tests/GPBUnittestProtos.m
new file mode 100644
index 00000000..2c271bf7
--- /dev/null
+++ b/objectivec/Tests/GPBUnittestProtos.m
@@ -0,0 +1,56 @@
+// 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.
+
+// Collects all the compiled protos into one file and compiles them to make sure
+// the compiler is generating valid code.
+
+#import "google/protobuf/MapProto2Unittest.pbobjc.m"
+#import "google/protobuf/MapUnittest.pbobjc.m"
+#import "google/protobuf/Unittest.pbobjc.m"
+#import "google/protobuf/UnittestCustomOptions.pbobjc.m"
+#import "google/protobuf/UnittestCycle.pbobjc.m"
+#import "google/protobuf/UnittestDropUnknownFields.pbobjc.m"
+#import "google/protobuf/UnittestEmbedOptimizeFor.pbobjc.m"
+#import "google/protobuf/UnittestEmpty.pbobjc.m"
+#import "google/protobuf/UnittestEnormousDescriptor.pbobjc.m"
+#import "google/protobuf/UnittestFilter.pbobjc.m"
+#import "google/protobuf/UnittestImport.pbobjc.m"
+#import "google/protobuf/UnittestImportLite.pbobjc.m"
+#import "google/protobuf/UnittestImportPublic.pbobjc.m"
+#import "google/protobuf/UnittestImportPublicLite.pbobjc.m"
+#import "google/protobuf/UnittestLite.pbobjc.m"
+#import "google/protobuf/UnittestMset.pbobjc.m"
+#import "google/protobuf/UnittestNameMangling.pbobjc.m"
+#import "google/protobuf/UnittestNoGenericServices.pbobjc.m"
+#import "google/protobuf/UnittestObjc.pbobjc.m"
+#import "google/protobuf/UnittestOptimizeFor.pbobjc.m"
+#import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.m"
+#import "google/protobuf/UnittestRuntimeProto2.pbobjc.m"
+#import "google/protobuf/UnittestRuntimeProto3.pbobjc.m"
diff --git a/objectivec/Tests/GPBUnknownFieldSetTest.m b/objectivec/Tests/GPBUnknownFieldSetTest.m
new file mode 100644
index 00000000..80186088
--- /dev/null
+++ b/objectivec/Tests/GPBUnknownFieldSetTest.m
@@ -0,0 +1,255 @@
+// 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.
+
+#import "GPBTestUtilities.h"
+
+#import "GPBField_PackagePrivate.h"
+#import "GPBUnknownFieldSet_PackagePrivate.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+
+@interface GPBUnknownFieldSet (GPBUnknownFieldSetTest)
+- (void)getTags:(int32_t*)tags;
+@end
+
+@interface UnknownFieldSetTest : GPBTestCase {
+ @private
+ TestAllTypes* allFields_;
+ NSData* allFieldsData_;
+
+ // An empty message that has been parsed from allFieldsData. So, it has
+ // unknown fields of every type.
+ TestEmptyMessage* emptyMessage_;
+ GPBUnknownFieldSet* unknownFields_;
+}
+
+@end
+
+@implementation UnknownFieldSetTest
+
+- (void)setUp {
+ allFields_ = [self allSetRepeatedCount:kGPBDefaultRepeatCount];
+ allFieldsData_ = [allFields_ data];
+ emptyMessage_ = [TestEmptyMessage parseFromData:allFieldsData_];
+ unknownFields_ = emptyMessage_.unknownFields;
+}
+
+- (GPBField*)getField:(int32_t)number {
+ return [unknownFields_ getField:number];
+}
+
+// Constructs a protocol buffer which contains fields with all the same
+// numbers as allFieldsData except that each field is some other wire
+// type.
+- (NSData*)getBizarroData {
+ GPBUnknownFieldSet* bizarroFields =
+ [[[GPBUnknownFieldSet alloc] init] autorelease];
+ NSUInteger count = [unknownFields_ countOfFields];
+ int32_t tags[count];
+ [unknownFields_ getTags:tags];
+ for (NSUInteger i = 0; i < count; ++i) {
+ int32_t tag = tags[i];
+ GPBField* field = [unknownFields_ getField:tag];
+ if (field.varintList.count == 0) {
+ // Original field is not a varint, so use a varint.
+ GPBField* varintField =
+ [[[GPBField alloc] initWithNumber:tag] autorelease];
+ [varintField addVarint:1];
+ [bizarroFields addField:varintField];
+ } else {
+ // Original field *is* a varint, so use something else.
+ GPBField* fixed32Field =
+ [[[GPBField alloc] initWithNumber:tag] autorelease];
+ [fixed32Field addFixed32:1];
+ [bizarroFields addField:fixed32Field];
+ }
+ }
+
+ return [bizarroFields data];
+}
+
+- (void)testSerialize {
+ // Check that serializing the UnknownFieldSet produces the original data
+ // again.
+ NSData* data = [emptyMessage_ data];
+ XCTAssertEqualObjects(allFieldsData_, data);
+}
+
+- (void)testCopyFrom {
+ TestEmptyMessage* message = [TestEmptyMessage message];
+ [message mergeFrom:emptyMessage_];
+
+ XCTAssertEqualObjects(emptyMessage_.data, message.data);
+}
+
+- (void)testMergeFrom {
+ GPBUnknownFieldSet* set1 = [[[GPBUnknownFieldSet alloc] init] autorelease];
+ GPBField* field = [[[GPBField alloc] initWithNumber:2] autorelease];
+ [field addVarint:2];
+ [set1 addField:field];
+ field = [[[GPBField alloc] initWithNumber:3] autorelease];
+ [field addVarint:4];
+ [set1 addField:field];
+
+ GPBUnknownFieldSet* set2 = [[[GPBUnknownFieldSet alloc] init] autorelease];
+ field = [[[GPBField alloc] initWithNumber:1] autorelease];
+ [field addVarint:1];
+ [set2 addField:field];
+ field = [[[GPBField alloc] initWithNumber:3] autorelease];
+ [field addVarint:3];
+ [set2 addField:field];
+
+ GPBUnknownFieldSet* set3 = [[[GPBUnknownFieldSet alloc] init] autorelease];
+ field = [[[GPBField alloc] initWithNumber:1] autorelease];
+ [field addVarint:1];
+ [set3 addField:field];
+ field = [[[GPBField alloc] initWithNumber:3] autorelease];
+ [field addVarint:4];
+ [set3 addField:field];
+
+ GPBUnknownFieldSet* set4 = [[[GPBUnknownFieldSet alloc] init] autorelease];
+ field = [[[GPBField alloc] initWithNumber:2] autorelease];
+ [field addVarint:2];
+ [set4 addField:field];
+ field = [[[GPBField alloc] initWithNumber:3] autorelease];
+ [field addVarint:3];
+ [set4 addField:field];
+
+ TestEmptyMessage* source1 = [TestEmptyMessage message];
+ [source1 setUnknownFields:set1];
+ TestEmptyMessage* source2 = [TestEmptyMessage message];
+ [source2 setUnknownFields:set2];
+ TestEmptyMessage* source3 = [TestEmptyMessage message];
+ [source3 setUnknownFields:set3];
+ TestEmptyMessage* source4 = [TestEmptyMessage message];
+ [source4 setUnknownFields:set4];
+
+ TestEmptyMessage* destination1 = [TestEmptyMessage message];
+ [destination1 mergeFrom:source1];
+ [destination1 mergeFrom:source2];
+
+ TestEmptyMessage* destination2 = [TestEmptyMessage message];
+ [destination2 mergeFrom:source3];
+ [destination2 mergeFrom:source4];
+
+ XCTAssertEqualObjects(destination1.data, destination2.data);
+}
+
+- (void)testClearMessage {
+ TestEmptyMessage* message = [TestEmptyMessage message];
+ [message mergeFrom:emptyMessage_];
+ [message clear];
+ XCTAssertEqual(message.serializedSize, (size_t)0);
+}
+
+- (void)testParseKnownAndUnknown {
+ // Test mixing known and unknown fields when parsing.
+ GPBUnknownFieldSet* fields = [[unknownFields_ copy] autorelease];
+ GPBField* field = [[[GPBField alloc] initWithNumber:123456] autorelease];
+ [field addVarint:654321];
+ [fields addField:field];
+
+ NSData* data = fields.data;
+ TestAllTypes* destination = [TestAllTypes parseFromData:data];
+
+ [self assertAllFieldsSet:destination repeatedCount:kGPBDefaultRepeatCount];
+ XCTAssertEqual(destination.unknownFields.countOfFields, (NSUInteger)1);
+
+ GPBField* field2 = [destination.unknownFields getField:123456];
+ XCTAssertEqual(field2.varintList.count, (NSUInteger)1);
+ XCTAssertEqual(654321ULL, [field2.varintList valueAtIndex:0]);
+}
+
+- (void)testWrongTypeTreatedAsUnknown {
+ // Test that fields of the wrong wire type are treated like unknown fields
+ // when parsing.
+
+ NSData* bizarroData = [self getBizarroData];
+ TestAllTypes* allTypesMessage = [TestAllTypes parseFromData:bizarroData];
+ TestEmptyMessage* emptyMessage = [TestEmptyMessage parseFromData:bizarroData];
+
+ // All fields should have been interpreted as unknown, so the debug strings
+ // should be the same.
+ XCTAssertEqualObjects(emptyMessage.data, allTypesMessage.data);
+}
+
+- (void)testUnknownExtensions {
+ // Make sure fields are properly parsed to the UnknownFieldSet even when
+ // they are declared as extension numbers.
+
+ TestEmptyMessageWithExtensions* message =
+ [TestEmptyMessageWithExtensions parseFromData:allFieldsData_];
+
+ XCTAssertEqual(unknownFields_.countOfFields,
+ message.unknownFields.countOfFields);
+ XCTAssertEqualObjects(allFieldsData_, message.data);
+}
+
+- (void)testWrongExtensionTypeTreatedAsUnknown {
+ // Test that fields of the wrong wire type are treated like unknown fields
+ // when parsing extensions.
+
+ NSData* bizarroData = [self getBizarroData];
+ TestAllExtensions* allExtensionsMessage =
+ [TestAllExtensions parseFromData:bizarroData];
+ TestEmptyMessage* emptyMessage = [TestEmptyMessage parseFromData:bizarroData];
+
+ // All fields should have been interpreted as unknown, so the debug strings
+ // should be the same.
+ XCTAssertEqualObjects(emptyMessage.data, allExtensionsMessage.data);
+}
+
+- (void)testLargeVarint {
+ GPBUnknownFieldSet* fields = [[unknownFields_ copy] autorelease];
+ GPBField* field = [[[GPBField alloc] initWithNumber:1] autorelease];
+ [field addVarint:0x7FFFFFFFFFFFFFFFL];
+ [fields addField:field];
+
+ NSData* data = [fields data];
+
+ GPBUnknownFieldSet* parsed = [[[GPBUnknownFieldSet alloc] init] autorelease];
+ [parsed mergeFromData:data];
+ GPBField* field2 = [parsed getField:1];
+ XCTAssertEqual(field2.varintList.count, (NSUInteger)1);
+ XCTAssertEqual(0x7FFFFFFFFFFFFFFFULL, [field2.varintList valueAtIndex:0]);
+}
+
+- (void)testMergingFields {
+ GPBField* field1 = [[[GPBField alloc] initWithNumber:1] autorelease];
+ [field1 addVarint:1];
+ [field1 addFixed32:2];
+ [field1 addFixed64:3];
+ [field1 addLengthDelimited:[NSData dataWithBytes:"hello" length:5]];
+ [field1 addGroup:[[unknownFields_ copy] autorelease]];
+ GPBField* field2 = [[[GPBField alloc] initWithNumber:2] autorelease];
+ [field2 mergeFromField:field1];
+ XCTAssertEqualObjects(field1, field2);
+}
+
+@end
diff --git a/objectivec/Tests/GPBUtilitiesTests.m b/objectivec/Tests/GPBUtilitiesTests.m
new file mode 100644
index 00000000..02de0197
--- /dev/null
+++ b/objectivec/Tests/GPBUtilitiesTests.m
@@ -0,0 +1,363 @@
+// 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.
+
+#import <XCTest/XCTest.h>
+
+#import "GPBUtilities_PackagePrivate.h"
+
+#import <objc/runtime.h>
+
+#import "GPBTestUtilities.h"
+
+#import "GPBDescriptor.h"
+#import "GPBDescriptor_PackagePrivate.h"
+#import "GPBMessage.h"
+
+#import "google/protobuf/MapUnittest.pbobjc.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+#import "google/protobuf/UnittestObjc.pbobjc.h"
+
+@interface UtilitiesTests : GPBTestCase
+@end
+
+// Support code for testing
+typedef struct {
+ uint32_t _has_storage_[1];
+ BOOL aBool;
+ int32_t aInt32;
+ uint32_t aUInt32;
+ int64_t aInt64;
+ uint64_t aUInt64;
+ float aFloat;
+ double aDouble;
+ id aObject;
+ BOOL _hasTest;
+ BOOL stopper;
+ BOOL shouldNotBeCounted;
+ GPBInt32Array *anArray;
+} ApplyFunctionsTest_Storage;
+
+@interface ApplyFunctionsTest : GPBMessage
+@property(nonatomic, readwrite) BOOL aBool;
+@property(nonatomic, readwrite) int32_t aInt32;
+@property(nonatomic, readwrite) uint32_t aUInt32;
+@property(nonatomic, readwrite) int64_t aInt64;
+@property(nonatomic, readwrite) uint64_t aUInt64;
+@property(nonatomic, readwrite) float aFloat;
+@property(nonatomic, readwrite) double aDouble;
+@property(nonatomic, readwrite, retain) id aObject;
+@property(nonatomic, readwrite) BOOL _hasTest;
+@property(nonatomic, readwrite) BOOL stopper;
+@property(nonatomic, readwrite) BOOL shouldNotBeCounted;
+@property(nonatomic, readwrite, retain) GPBInt32Array *anArray;
+@end
+
+@implementation ApplyFunctionsTest
+
+@dynamic aBool, aInt32, aUInt32, aInt64, aUInt64, aFloat, aDouble, aObject;
+@dynamic _hasTest, stopper, shouldNotBeCounted, anArray;
+
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+#define FIELD_ENTRY(NAME, INDEX) \
+ { \
+ .name = "a" #NAME, .hasIndex = INDEX, .type = GPBType##NAME, \
+ .offset = offsetof(ApplyFunctionsTest_Storage, a##NAME), \
+ }
+ FIELD_ENTRY(Bool, 1),
+ FIELD_ENTRY(Int32, 2),
+ FIELD_ENTRY(UInt32, 3),
+ FIELD_ENTRY(Int64, 4),
+ FIELD_ENTRY(UInt64, 5),
+ FIELD_ENTRY(Float, 6),
+ FIELD_ENTRY(Double, 7),
+#undef FIELD_ENTRY
+ {
+ .name = "aObject",
+ .type = GPBTypeString,
+ .hasIndex = 8,
+ .offset = offsetof(ApplyFunctionsTest_Storage, aObject),
+ },
+ {
+ .name = "stopper",
+ .type = GPBTypeBool,
+ .hasIndex = 9,
+ .offset = offsetof(ApplyFunctionsTest_Storage, stopper),
+ },
+ {
+ .name = "shouldNotBeCounted",
+ .type = GPBTypeBool,
+ .hasIndex = 10,
+ .offset = offsetof(ApplyFunctionsTest_Storage, shouldNotBeCounted),
+ },
+ {
+ .name = "anArray",
+ .type = GPBTypeInt32,
+ .hasIndex = 11,
+ .flags = GPBFieldRepeated,
+ .offset = offsetof(ApplyFunctionsTest_Storage, anArray),
+ },
+ };
+ descriptor = [GPBDescriptor
+ allocDescriptorForClass:[self class]
+ rootClass:Nil
+ file:nil
+ fields:fields
+ fieldCount:sizeof(fields) /
+ sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:NULL
+ enumCount:0
+ ranges:NULL
+ rangeCount:0
+ storageSize:sizeof(ApplyFunctionsTest_Storage)
+ wireFormat:NO];
+ }
+ return descriptor;
+}
+
+@end
+
+typedef struct {
+ int calledBool;
+ int calledInt32;
+ int calledUInt32;
+ int calledInt64;
+ int calledUInt64;
+ int calledFloat;
+ int calledDouble;
+ int calledObject;
+ int hitCount;
+} TestApplyFunctionsContext;
+
+// Really, who needs templates?
+// Macro for testing apply functions. Declares a variety of different functions
+// base on |NAME|.
+#define TEST_APPLY_FUNCTIONS_FUNC(NAME) \
+ static BOOL TestApplyFunction##NAME(GPBFieldDescriptor *field, \
+ void *voidContext) { \
+ TestApplyFunctionsContext *context = voidContext; \
+ if (field->getSel_ == sel_getUid("stopper")) return NO; \
+ context->called##NAME += 1; \
+ context->hitCount += 1; \
+ return YES; \
+ }
+
+TEST_APPLY_FUNCTIONS_FUNC(Bool)
+TEST_APPLY_FUNCTIONS_FUNC(Int32)
+TEST_APPLY_FUNCTIONS_FUNC(UInt32)
+TEST_APPLY_FUNCTIONS_FUNC(Int64)
+TEST_APPLY_FUNCTIONS_FUNC(UInt64)
+TEST_APPLY_FUNCTIONS_FUNC(Float)
+TEST_APPLY_FUNCTIONS_FUNC(Double)
+TEST_APPLY_FUNCTIONS_FUNC(Object)
+
+@implementation UtilitiesTests
+
+- (void)testRightShiftFunctions {
+ XCTAssertEqual((1UL << 31) >> 31, 1UL);
+ XCTAssertEqual((1 << 31) >> 31, -1);
+ XCTAssertEqual((1ULL << 63) >> 63, 1ULL);
+ XCTAssertEqual((1LL << 63) >> 63, -1LL);
+
+ XCTAssertEqual(GPBLogicalRightShift32((1 << 31), 31), 1);
+ XCTAssertEqual(GPBLogicalRightShift64((1LL << 63), 63), 1LL);
+}
+
+- (void)testMutability {
+ ApplyFunctionsTest *foo_message = [ApplyFunctionsTest message];
+ XCTAssertEqual(0, [foo_message aInt32]);
+ [foo_message setAInt32:100];
+ XCTAssertEqual(100, [foo_message aInt32]);
+}
+
+- (void)testSerializedSize {
+ ApplyFunctionsTest *foo_message = [ApplyFunctionsTest message];
+ [foo_message setAInt32:100];
+ size_t size1 = [foo_message serializedSize];
+ [foo_message setAInt64:100];
+ size_t size2 = [foo_message serializedSize];
+
+ // Intentionally doing a pointer comparison.
+ XCTAssertNotEqual(size1, size2);
+}
+
+- (void)testCopying {
+ ApplyFunctionsTest *foo_message = [ApplyFunctionsTest message];
+ [foo_message setAInt32:100];
+ [foo_message setAObject:@"Happy"];
+ ApplyFunctionsTest *foo = [[foo_message copy] autorelease];
+ XCTAssertNotEqual(foo, foo_message); // Pointer comparision
+ XCTAssertEqualObjects(foo, foo_message);
+}
+
+- (void)testApplyFunctions {
+ // Covers ApplyFunctionsToProtoVariables and
+ // ApplyFunctionsBasedOnEncodingType.
+ // This test depends on the layout of the ivars to be in the order
+ // declared in the interface. If this is not true, it will fail and will
+ // need to be rewritten to accomodate.
+ TestApplyFunctionsContext context;
+ memset(&context, 0, sizeof(context));
+ GPBApplyFunctions foo = GPBAPPLY_FUNCTIONS_INIT(TestApplyFunction);
+ ApplyFunctionsTest *msg = [ApplyFunctionsTest message];
+ GPBApplyFunctionsToMessageFields(&foo, msg, &context);
+
+ // Only eight vars should be set.
+ // "stopper" should cause the loop to quit so it and shouldNotBeCounted should
+ // not be counted.
+ // "_hasTest" should be skipped over.
+ // Each of the vars should only be set once.
+ XCTAssertEqual(context.hitCount, 8);
+ XCTAssertEqual(context.calledBool, 1);
+ XCTAssertEqual(context.calledInt32, 1);
+ XCTAssertEqual(context.calledUInt32, 1);
+ XCTAssertEqual(context.calledInt64, 1);
+ XCTAssertEqual(context.calledUInt64, 1);
+ XCTAssertEqual(context.calledFloat, 1);
+ XCTAssertEqual(context.calledDouble, 1);
+ XCTAssertEqual(context.calledObject, 1);
+}
+
+- (void)testGPBDecodeTextFormatName {
+ uint8_t decodeData[] = {
+ 0x6,
+ // An inlined string (first to make sure the leading null is handled
+ // correctly, and with a key of zero to check that).
+ 0x0, 0x0, 'z', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 'J', 0x0,
+ // All as is (00 op)
+ 0x1, 0x0A, 0x0,
+ // Underscore, upper + 9 (10 op)
+ 0x3, 0xCA, 0x0,
+ // Upper + 3 (10 op), underscore, upper + 5 (10 op)
+ 0x2, 0x44, 0xC6, 0x0,
+ // All Upper for 4 (11 op), underscore, underscore, upper + 5 (10 op),
+ // underscore, lower + 0 (01 op)
+ 0x4, 0x64, 0x80, 0xC5, 0xA1, 0x0,
+ // 2 byte key: as is + 3 (00 op), underscore, lower + 4 (01 op),
+ // underscore, lower + 3 (01 op), underscore, lower + 1 (01 op),
+ // underscore, lower + 30 (01 op), as is + 30 (00 op), as is + 13 (00 op),
+ // underscore, as is + 3 (00 op)
+ 0xE8, 0x07, 0x04, 0xA5, 0xA4, 0xA2, 0xBF, 0x1F, 0x0E, 0x84, 0x0,
+ };
+ NSString *inputStr = @"abcdefghIJ";
+
+ // Empty inputs
+
+ XCTAssertNil(GPBDecodeTextFormatName(nil, 1, NULL));
+ XCTAssertNil(GPBDecodeTextFormatName(decodeData, 1, NULL));
+ XCTAssertNil(GPBDecodeTextFormatName(nil, 1, inputStr));
+
+ // Keys not found.
+
+ XCTAssertNil(GPBDecodeTextFormatName(decodeData, 5, inputStr));
+ XCTAssertNil(GPBDecodeTextFormatName(decodeData, -1, inputStr));
+
+ // Some name decodes.
+
+ XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 1, inputStr), @"abcdefghIJ");
+ XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 2, inputStr), @"Abcd_EfghIJ");
+ XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 3, inputStr), @"_AbcdefghIJ");
+ XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 4, inputStr), @"ABCD__EfghI_j");
+
+ // An inlined string (and key of zero).
+ XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 0, inputStr), @"zbcdefghIJ");
+
+ // Long name so multiple decode ops are needed.
+ inputStr = @"longFieldNameIsLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1000";
+ XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 1000, inputStr),
+ @"long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000");
+}
+
+- (void)testTextFormat {
+ TestAllTypes *message = [TestAllTypes message];
+
+ // Not kGPBDefaultRepeatCount because we are comparing to golden master file
+ // which was generated with 2.
+ [self setAllFields:message repeatedCount:2];
+
+ NSString *result = GPBTextFormatForMessage(message, nil);
+
+ NSString *fileName = @"text_format_unittest_data.txt";
+ NSData *resultData = [result dataUsingEncoding:NSUTF8StringEncoding];
+ NSData *expectedData =
+ [self getDataFileNamed:fileName dataToWrite:resultData];
+ NSString *expected = [[NSString alloc] initWithData:expectedData
+ encoding:NSUTF8StringEncoding];
+ XCTAssertEqualObjects(expected, result);
+ [expected release];
+}
+
+- (void)testTextFormatExtra {
+ // -testTextFormat uses all protos with fields that don't require special
+ // handing for figuring out the names. The ObjC proto has a bunch of oddball
+ // field and enum names that require the decode info to get right, so this
+ // confirms they generated and decoded correctly.
+
+ self_Class *message = [self_Class message];
+ message.cmd = YES;
+ message.isProxy_p = YES;
+ message.subEnum = self_autorelease_RetainCount;
+ message.new_p.copy_p = @"foo";
+
+ NSString *expected = @"_cmd: true\n"
+ @"isProxy: true\n"
+ @"SubEnum: retainCount\n"
+ @"New {\n"
+ @" copy: \"foo\"\n"
+ @"}\n";
+ NSString *result = GPBTextFormatForMessage(message, nil);
+ XCTAssertEqualObjects(expected, result);
+}
+
+- (void)testTextFormatMaps {
+ TestMap *message = [TestMap message];
+
+ // Map iteration order doesn't have to be stable, so use only one entry.
+ [self setAllMapFields:message numEntries:1];
+
+ NSString *result = GPBTextFormatForMessage(message, nil);
+
+ NSString *fileName = @"text_format_map_unittest_data.txt";
+ NSData *resultData = [result dataUsingEncoding:NSUTF8StringEncoding];
+ NSData *expectedData =
+ [self getDataFileNamed:fileName dataToWrite:resultData];
+ NSString *expected = [[NSString alloc] initWithData:expectedData
+ encoding:NSUTF8StringEncoding];
+ XCTAssertEqualObjects(expected, result);
+ [expected release];
+}
+
+// TODO(thomasvl): add test with extensions once those format with correct names.
+
+@end
diff --git a/objectivec/Tests/GPBWellKnownTypesTest.m b/objectivec/Tests/GPBWellKnownTypesTest.m
new file mode 100644
index 00000000..78f4e637
--- /dev/null
+++ b/objectivec/Tests/GPBWellKnownTypesTest.m
@@ -0,0 +1,102 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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 "GPBWellKnownTypes.h"
+
+#import <XCTest/XCTest.h>
+
+// A basically random interval into the future for testing with.
+static const NSTimeInterval kFutureOffsetInterval = 15000;
+
+// Nanosecond time accuracy
+static const NSTimeInterval kTimeAccuracy = 1e-9;
+
+@interface WellKnownTypesTest : XCTestCase
+@end
+
+@implementation WellKnownTypesTest
+
+- (void)testTimeStamp {
+ // Test Creation.
+ NSDate *date = [NSDate date];
+ GPBTimestamp *timeStamp = [[GPBTimestamp alloc] initWithDate:date];
+ NSDate *timeStampDate = timeStamp.date;
+
+ // Comparing timeIntervals instead of directly comparing dates because date
+ // equality requires the time intervals to be exactly the same, and the
+ // timeintervals go through a bit of floating point error as they are
+ // converted back and forth from the internal representation.
+ XCTAssertEqualWithAccuracy(date.timeIntervalSince1970,
+ timeStampDate.timeIntervalSince1970,
+ kTimeAccuracy);
+
+ NSTimeInterval time = [date timeIntervalSince1970];
+ GPBTimestamp *timeStamp2 =
+ [[GPBTimestamp alloc] initWithTimeIntervalSince1970:time];
+ NSTimeInterval durationTime = timeStamp2.timeIntervalSince1970;
+ XCTAssertEqualWithAccuracy(time, durationTime, kTimeAccuracy);
+ [timeStamp release];
+
+ // Test Mutation.
+ date = [NSDate dateWithTimeIntervalSinceNow:kFutureOffsetInterval];
+ timeStamp2.date = date;
+ timeStampDate = timeStamp2.date;
+ XCTAssertEqualWithAccuracy(date.timeIntervalSince1970,
+ timeStampDate.timeIntervalSince1970,
+ kTimeAccuracy);
+
+ time = date.timeIntervalSince1970;
+ timeStamp2.timeIntervalSince1970 = time;
+ durationTime = timeStamp2.timeIntervalSince1970;
+ XCTAssertEqualWithAccuracy(time, durationTime, kTimeAccuracy);
+ [timeStamp2 release];
+}
+
+- (void)testDuration {
+ // Test Creation.
+ NSTimeInterval time = [[NSDate date] timeIntervalSince1970];
+ GPBDuration *duration =
+ [[GPBDuration alloc] initWithTimeIntervalSince1970:time];
+ NSTimeInterval durationTime = duration.timeIntervalSince1970;
+ XCTAssertEqualWithAccuracy(time, durationTime, kTimeAccuracy);
+ [duration release];
+
+ // Test Mutation.
+ GPBDuration *duration2 =
+ [[GPBDuration alloc] initWithTimeIntervalSince1970:time];
+ NSDate *date = [NSDate dateWithTimeIntervalSinceNow:kFutureOffsetInterval];
+ time = date.timeIntervalSince1970;
+ duration2.timeIntervalSince1970 = time;
+ durationTime = duration2.timeIntervalSince1970;
+ XCTAssertEqualWithAccuracy(time, durationTime, kTimeAccuracy);
+ [duration2 release];
+}
+
+@end
diff --git a/objectivec/Tests/GPBWireFormatTests.m b/objectivec/Tests/GPBWireFormatTests.m
new file mode 100644
index 00000000..1344af08
--- /dev/null
+++ b/objectivec/Tests/GPBWireFormatTests.m
@@ -0,0 +1,246 @@
+// 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.
+
+#import "GPBTestUtilities.h"
+
+#import "GPBCodedInputStream.h"
+#import "GPBMessage_PackagePrivate.h"
+#import "GPBField_PackagePrivate.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+#import "google/protobuf/UnittestMset.pbobjc.h"
+
+@interface WireFormatTests : GPBTestCase
+@end
+
+@implementation WireFormatTests
+
+- (void)testSerialization {
+ TestAllTypes* message = [self allSetRepeatedCount:kGPBDefaultRepeatCount];
+
+ NSData* rawBytes = message.data;
+ XCTAssertEqual(message.serializedSize, (size_t)rawBytes.length);
+
+ TestAllTypes* message2 = [TestAllTypes parseFromData:rawBytes];
+
+ [self assertAllFieldsSet:message2 repeatedCount:kGPBDefaultRepeatCount];
+}
+
+- (void)testSerializationPacked {
+ TestPackedTypes* message =
+ [self packedSetRepeatedCount:kGPBDefaultRepeatCount];
+
+ NSData* rawBytes = message.data;
+ XCTAssertEqual(message.serializedSize, (size_t)rawBytes.length);
+
+ TestPackedTypes* message2 = [TestPackedTypes parseFromData:rawBytes];
+
+ [self assertPackedFieldsSet:message2 repeatedCount:kGPBDefaultRepeatCount];
+}
+
+- (void)testSerializeExtensions {
+ // TestAllTypes and TestAllExtensions should have compatible wire formats,
+ // so if we serealize a TestAllExtensions then parse it as TestAllTypes
+ // it should work.
+
+ TestAllExtensions* message =
+ [self allExtensionsSetRepeatedCount:kGPBDefaultRepeatCount];
+ NSData* rawBytes = message.data;
+ XCTAssertEqual(message.serializedSize, (size_t)rawBytes.length);
+
+ TestAllTypes* message2 = [TestAllTypes parseFromData:rawBytes];
+
+ [self assertAllFieldsSet:message2 repeatedCount:kGPBDefaultRepeatCount];
+}
+
+- (void)testSerializePackedExtensions {
+ // TestPackedTypes and TestPackedExtensions should have compatible wire
+ // formats; check that they serialize to the same string.
+ TestPackedExtensions* message =
+ [self packedExtensionsSetRepeatedCount:kGPBDefaultRepeatCount];
+ NSData* rawBytes = message.data;
+
+ TestPackedTypes* message2 =
+ [self packedSetRepeatedCount:kGPBDefaultRepeatCount];
+ NSData* rawBytes2 = message2.data;
+
+ XCTAssertEqualObjects(rawBytes, rawBytes2);
+}
+
+- (void)testParseExtensions {
+ // TestAllTypes and TestAllExtensions should have compatible wire formats,
+ // so if we serialize a TestAllTypes then parse it as TestAllExtensions
+ // it should work.
+
+ TestAllTypes* message = [self allSetRepeatedCount:kGPBDefaultRepeatCount];
+ NSData* rawBytes = message.data;
+
+ GPBExtensionRegistry* registry = [self extensionRegistry];
+
+ TestAllExtensions* message2 =
+ [TestAllExtensions parseFromData:rawBytes extensionRegistry:registry];
+
+ [self assertAllExtensionsSet:message2 repeatedCount:kGPBDefaultRepeatCount];
+}
+
+
+- (void) testExtensionsSerializedSize {
+ size_t allSet = [self allSetRepeatedCount:kGPBDefaultRepeatCount].serializedSize;
+ size_t extensionSet = [self allExtensionsSetRepeatedCount:kGPBDefaultRepeatCount].serializedSize;
+ XCTAssertEqual(allSet, extensionSet);
+}
+
+- (void)testParsePackedExtensions {
+ // Ensure that packed extensions can be properly parsed.
+ TestPackedExtensions* message =
+ [self packedExtensionsSetRepeatedCount:kGPBDefaultRepeatCount];
+ NSData* rawBytes = message.data;
+
+ GPBExtensionRegistry* registry = [self extensionRegistry];
+
+ TestPackedExtensions* message2 =
+ [TestPackedExtensions parseFromData:rawBytes extensionRegistry:registry];
+
+ [self assertPackedExtensionsSet:message2
+ repeatedCount:kGPBDefaultRepeatCount];
+}
+
+const int kUnknownTypeId = 1550055;
+
+- (void)testSerializeMessageSet {
+ // Set up a TestMessageSet with two known messages and an unknown one.
+ TestMessageSet* message_set = [TestMessageSet message];
+ [[message_set getExtension:[TestMessageSetExtension1 messageSetExtension]]
+ setI:123];
+ [[message_set getExtension:[TestMessageSetExtension2 messageSetExtension]]
+ setStr:@"foo"];
+ GPBField* unknownField =
+ [[[GPBField alloc] initWithNumber:kUnknownTypeId] autorelease];
+ [unknownField addLengthDelimited:[NSData dataWithBytes:"bar" length:3]];
+ GPBUnknownFieldSet* unknownFieldSet =
+ [[[GPBUnknownFieldSet alloc] init] autorelease];
+ [unknownFieldSet addField:unknownField];
+ [message_set setUnknownFields:unknownFieldSet];
+
+ NSData* data = [message_set data];
+
+ // Parse back using RawMessageSet and check the contents.
+ RawMessageSet* raw = [RawMessageSet parseFromData:data];
+
+ XCTAssertEqual([raw.unknownFields countOfFields], (NSUInteger)0);
+
+ XCTAssertEqual(raw.itemArray.count, (NSUInteger)3);
+ XCTAssertEqual([raw.itemArray[0] typeId],
+ [TestMessageSetExtension1 messageSetExtension].fieldNumber);
+ XCTAssertEqual([raw.itemArray[1] typeId],
+ [TestMessageSetExtension2 messageSetExtension].fieldNumber);
+ XCTAssertEqual([raw.itemArray[2] typeId], kUnknownTypeId);
+
+ TestMessageSetExtension1* message1 =
+ [TestMessageSetExtension1 parseFromData:[raw.itemArray[0] message]];
+ XCTAssertEqual(message1.i, 123);
+
+ TestMessageSetExtension2* message2 =
+ [TestMessageSetExtension2 parseFromData:[raw.itemArray[1] message]];
+ XCTAssertEqualObjects(message2.str, @"foo");
+
+ XCTAssertEqualObjects([raw.itemArray[2] message],
+ [NSData dataWithBytes:"bar" length:3]);
+}
+
+- (void)testParseMessageSet {
+ // Set up a RawMessageSet with two known messages and an unknown one.
+ RawMessageSet* raw = [RawMessageSet message];
+
+ {
+ RawMessageSet_Item* item = [RawMessageSet_Item message];
+ item.typeId = [TestMessageSetExtension1 messageSetExtension].fieldNumber;
+ TestMessageSetExtension1* message = [TestMessageSetExtension1 message];
+ message.i = 123;
+ item.message = [message data];
+ raw.itemArray = [NSMutableArray array];
+ [raw.itemArray addObject:item];
+ }
+
+ {
+ RawMessageSet_Item* item = [RawMessageSet_Item message];
+ item.typeId = [TestMessageSetExtension2 messageSetExtension].fieldNumber;
+ TestMessageSetExtension2* message = [TestMessageSetExtension2 message];
+ message.str = @"foo";
+ item.message = [message data];
+ [raw.itemArray addObject:item];
+ }
+
+ {
+ RawMessageSet_Item* item = [RawMessageSet_Item message];
+ item.typeId = kUnknownTypeId;
+ item.message = [NSData dataWithBytes:"bar" length:3];
+ [raw.itemArray addObject:item];
+ }
+
+ NSData* data = [raw data];
+
+ // Parse as a TestMessageSet and check the contents.
+ TestMessageSet* messageSet =
+ [TestMessageSet parseFromData:data
+ extensionRegistry:[UnittestMsetRoot extensionRegistry]];
+
+ XCTAssertEqual(
+ [[messageSet
+ getExtension:[TestMessageSetExtension1 messageSetExtension]] i],
+ 123);
+ XCTAssertEqualObjects(
+ [[messageSet
+ getExtension:[TestMessageSetExtension2 messageSetExtension]] str],
+ @"foo");
+
+ XCTAssertEqual([messageSet.unknownFields countOfFields], (NSUInteger)1);
+ GPBField* unknownField = [messageSet.unknownFields getField:kUnknownTypeId];
+ XCTAssertNotNil(unknownField);
+ XCTAssertEqual(unknownField.lengthDelimitedList.count, (NSUInteger)1);
+ XCTAssertEqualObjects(unknownField.lengthDelimitedList[0],
+ [NSData dataWithBytes:"bar" length:3]);
+}
+
+- (void)assertFieldsInOrder:(NSData*)data {
+ GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
+ int32_t previousTag = 0;
+
+ while (YES) {
+ int32_t tag = [input readTag];
+ if (tag == 0) {
+ break;
+ }
+
+ XCTAssertGreaterThan(tag, previousTag);
+ [input skipField:tag];
+ }
+}
+
+@end
diff --git a/objectivec/Tests/UnitTests-Bridging-Header.h b/objectivec/Tests/UnitTests-Bridging-Header.h
new file mode 100644
index 00000000..46292fce
--- /dev/null
+++ b/objectivec/Tests/UnitTests-Bridging-Header.h
@@ -0,0 +1,6 @@
+//
+// Use this file to import your target's public headers that you would like to expose to Swift.
+//
+
+#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+#import "google/protobuf/UnittestRuntimeProto3.pbobjc.h"
diff --git a/objectivec/Tests/UnitTests-Info.plist b/objectivec/Tests/UnitTests-Info.plist
new file mode 100644
index 00000000..65013556
--- /dev/null
+++ b/objectivec/Tests/UnitTests-Info.plist
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.yourcompany.${PRODUCT_NAME:identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>BNDL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+</dict>
+</plist>
diff --git a/objectivec/Tests/golden_message b/objectivec/Tests/golden_message
new file mode 100644
index 00000000..7bceab41
--- /dev/null
+++ b/objectivec/Tests/golden_message
Binary files differ
diff --git a/objectivec/Tests/golden_packed_fields_message b/objectivec/Tests/golden_packed_fields_message
new file mode 100644
index 00000000..7bceab41
--- /dev/null
+++ b/objectivec/Tests/golden_packed_fields_message
Binary files differ
diff --git a/objectivec/Tests/iOSTestHarness/AppDelegate.m b/objectivec/Tests/iOSTestHarness/AppDelegate.m
new file mode 100644
index 00000000..8c4a586b
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/AppDelegate.m
@@ -0,0 +1,35 @@
+#import <UIKit/UIKit.h>
+
+@interface AppDelegate : UIResponder <UIApplicationDelegate>
+@property (strong, nonatomic) UIWindow *window;
+@end
+
+@implementation AppDelegate
+
+@synthesize window;
+
+- (BOOL)application:(UIApplication *)application
+ didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ #pragma unused (application, launchOptions)
+
+ self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
+ self.window.backgroundColor = [UIColor whiteColor];
+ [self.window makeKeyAndVisible];
+ self.window.rootViewController = [[UIViewController alloc] init];
+
+ UILabel *label =
+ [[UILabel alloc] initWithFrame:CGRectMake(0, 200, CGRectGetWidth(self.window.frame), 40)];
+ label.text = @"Protocol Buffer Test Harness";
+ label.textAlignment = NSTextAlignmentCenter;
+ [self.window addSubview:label];
+
+ return YES;
+}
+
+@end
+
+int main(int argc, char * argv[]) {
+ @autoreleasepool {
+ return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+ }
+}
diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/Contents.json b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 00000000..ecd3584e
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,116 @@
+{
+ "images" : [
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "3x"
+ },
+ {
+ "size" : "57x57",
+ "idiom" : "iphone",
+ "filename" : "iPhone6.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "57x57",
+ "idiom" : "iphone",
+ "filename" : "iPhone6@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "60x60",
+ "idiom" : "iphone",
+ "filename" : "iPhone7@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "60x60",
+ "idiom" : "iphone",
+ "filename" : "iPhone7@3x.png",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "50x50",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "50x50",
+ "scale" : "2x"
+ },
+ {
+ "size" : "72x72",
+ "idiom" : "ipad",
+ "filename" : "iPad6.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "72x72",
+ "idiom" : "ipad",
+ "filename" : "iPad6@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "76x76",
+ "idiom" : "ipad",
+ "filename" : "iPad7.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "76x76",
+ "idiom" : "ipad",
+ "filename" : "iPad7@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "car",
+ "size" : "120x120",
+ "scale" : "1x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6.png
new file mode 100644
index 00000000..43da2ee4
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6.png
Binary files differ
diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6@2x.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6@2x.png
new file mode 100644
index 00000000..2ec93704
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6@2x.png
Binary files differ
diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7.png
new file mode 100644
index 00000000..aec8bc1b
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7.png
Binary files differ
diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7@2x.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7@2x.png
new file mode 100644
index 00000000..e39cc3e7
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7@2x.png
Binary files differ
diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6.png
new file mode 100644
index 00000000..5572d79f
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6.png
Binary files differ
diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6@2x.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6@2x.png
new file mode 100644
index 00000000..2424997f
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6@2x.png
Binary files differ
diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7@2x.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7@2x.png
new file mode 100644
index 00000000..10bfc3cf
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7@2x.png
Binary files differ
diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7@3x.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7@3x.png
new file mode 100644
index 00000000..8d16f14d
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7@3x.png
Binary files differ
diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/LaunchImage.launchimage/Contents.json b/objectivec/Tests/iOSTestHarness/Images.xcassets/LaunchImage.launchimage/Contents.json
new file mode 100644
index 00000000..5a296668
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/Images.xcassets/LaunchImage.launchimage/Contents.json
@@ -0,0 +1,49 @@
+{
+ "images" : [
+ {
+ "orientation" : "portrait",
+ "idiom" : "ipad",
+ "minimum-system-version" : "7.0",
+ "extent" : "full-screen",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "landscape",
+ "idiom" : "ipad",
+ "minimum-system-version" : "7.0",
+ "extent" : "full-screen",
+ "scale" : "1x"
+ },
+ {
+ "orientation" : "landscape",
+ "idiom" : "ipad",
+ "minimum-system-version" : "7.0",
+ "extent" : "full-screen",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "iphone",
+ "minimum-system-version" : "7.0",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "iphone",
+ "minimum-system-version" : "7.0",
+ "subtype" : "retina4",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "ipad",
+ "minimum-system-version" : "7.0",
+ "extent" : "full-screen",
+ "scale" : "1x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/objectivec/Tests/iOSTestHarness/Info.plist b/objectivec/Tests/iOSTestHarness/Info.plist
new file mode 100644
index 00000000..31ab1578
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/Info.plist
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleDisplayName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.google.${PRODUCT_NAME:rfc1034identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+ <key>UILaunchStoryboardName</key>
+ <string>LaunchScreen</string>
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+ <key>UISupportedInterfaceOrientations~ipad</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ <string>UIInterfaceOrientationPortraitUpsideDown</string>
+ </array>
+</dict>
+</plist>
diff --git a/objectivec/Tests/iOSTestHarness/LaunchScreen.xib b/objectivec/Tests/iOSTestHarness/LaunchScreen.xib
new file mode 100644
index 00000000..22204bfe
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/LaunchScreen.xib
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6254" systemVersion="13F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
+ <dependencies>
+ <deployment identifier="iOS"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/>
+ <capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
+ </dependencies>
+ <objects>
+ <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+ <view contentMode="scaleToFill" id="iN0-l3-epB">
+ <rect key="frame" x="0.0" y="0.0" width="630" height="503"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Protocol Buffer Test Harness" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
+ <rect key="frame" x="20" y="147" width="591" height="43"/>
+ <fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
+ <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ </subviews>
+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
+ <constraints>
+ <constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="Kid-kn-2rF"/>
+ <constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
+ <constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
+ </constraints>
+ <nil key="simulatedStatusBarMetrics"/>
+ <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+ <point key="canvasLocation" x="479" y="456.5"/>
+ </view>
+ </objects>
+</document>
diff --git a/objectivec/Tests/iOSTestHarness/en.lproj/InfoPlist.strings b/objectivec/Tests/iOSTestHarness/en.lproj/InfoPlist.strings
new file mode 100644
index 00000000..477b28ff
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/en.lproj/InfoPlist.strings
@@ -0,0 +1,2 @@
+/* Localized versions of Info.plist keys */
+
diff --git a/objectivec/Tests/text_format_map_unittest_data.txt b/objectivec/Tests/text_format_map_unittest_data.txt
new file mode 100644
index 00000000..ad1195e2
--- /dev/null
+++ b/objectivec/Tests/text_format_map_unittest_data.txt
@@ -0,0 +1,70 @@
+map_int32_int32 {
+ key: 100
+ value: 1
+}
+map_int64_int64 {
+ key: 101
+ value: 1
+}
+map_uint32_uint32 {
+ key: 102
+ value: 1
+}
+map_uint64_uint64 {
+ key: 103
+ value: 1
+}
+map_sint32_sint32 {
+ key: 104
+ value: 1
+}
+map_sint64_sint64 {
+ key: 105
+ value: 1
+}
+map_fixed32_fixed32 {
+ key: 106
+ value: 1
+}
+map_fixed64_fixed64 {
+ key: 107
+ value: 1
+}
+map_sfixed32_sfixed32 {
+ key: 108
+ value: 1
+}
+map_sfixed64_sfixed64 {
+ key: 109
+ value: 1
+}
+map_int32_float {
+ key: 110
+ value: 1
+}
+map_int32_double {
+ key: 111
+ value: 1
+}
+map_bool_bool {
+ key: true
+ value: false
+}
+map_string_string {
+ key: "112"
+ value: "1"
+}
+map_int32_bytes {
+ key: 113
+ value: "\001\000\000\000"
+}
+map_int32_enum {
+ key: 114
+ value: MAP_ENUM_BAZ
+}
+map_int32_foreign_message {
+ key: 115
+ value {
+ c: 1
+ }
+}
diff --git a/objectivec/Tests/text_format_unittest_data.txt b/objectivec/Tests/text_format_unittest_data.txt
new file mode 100644
index 00000000..d10f1000
--- /dev/null
+++ b/objectivec/Tests/text_format_unittest_data.txt
@@ -0,0 +1,116 @@
+optional_int32: 101
+optional_int64: 102
+optional_uint32: 103
+optional_uint64: 104
+optional_sint32: 105
+optional_sint64: 106
+optional_fixed32: 107
+optional_fixed64: 108
+optional_sfixed32: 109
+optional_sfixed64: 110
+optional_float: 111
+optional_double: 112
+optional_bool: true
+optional_string: "115"
+optional_bytes: "\001\000\002\003\000\005"
+OptionalGroup {
+ a: 117
+}
+optional_nested_message {
+ bb: 118
+}
+optional_foreign_message {
+ c: 119
+}
+optional_import_message {
+ d: 120
+}
+optional_nested_enum: BAZ
+optional_foreign_enum: FOREIGN_BAZ
+optional_import_enum: IMPORT_BAZ
+optional_string_piece: "124"
+optional_cord: "125"
+repeated_int32: 201
+repeated_int32: 301
+repeated_int64: 202
+repeated_int64: 302
+repeated_uint32: 203
+repeated_uint32: 303
+repeated_uint64: 204
+repeated_uint64: 304
+repeated_sint32: 205
+repeated_sint32: 305
+repeated_sint64: 206
+repeated_sint64: 306
+repeated_fixed32: 207
+repeated_fixed32: 307
+repeated_fixed64: 208
+repeated_fixed64: 308
+repeated_sfixed32: 209
+repeated_sfixed32: 309
+repeated_sfixed64: 210
+repeated_sfixed64: 310
+repeated_float: 211
+repeated_float: 311
+repeated_double: 212
+repeated_double: 312
+repeated_bool: false
+repeated_bool: true
+repeated_string: "215"
+repeated_string: "315"
+repeated_bytes: "\330\000\000\000"
+repeated_bytes: "<\001\000\000"
+RepeatedGroup {
+ a: 217
+}
+RepeatedGroup {
+ a: 317
+}
+repeated_nested_message {
+ bb: 218
+}
+repeated_nested_message {
+ bb: 318
+}
+repeated_foreign_message {
+ c: 219
+}
+repeated_foreign_message {
+ c: 319
+}
+repeated_import_message {
+ d: 220
+}
+repeated_import_message {
+ d: 320
+}
+repeated_nested_enum: BAZ
+repeated_nested_enum: BAR
+repeated_foreign_enum: FOREIGN_BAZ
+repeated_foreign_enum: FOREIGN_BAR
+repeated_import_enum: IMPORT_BAZ
+repeated_import_enum: IMPORT_BAR
+repeated_string_piece: "224"
+repeated_string_piece: "324"
+repeated_cord: "225"
+repeated_cord: "325"
+default_int32: 401
+default_int64: 402
+default_uint32: 403
+default_uint64: 404
+default_sint32: 405
+default_sint64: 406
+default_fixed32: 407
+default_fixed64: 408
+default_sfixed32: 409
+default_sfixed64: 410
+default_float: 411
+default_double: 412
+default_bool: false
+default_string: "415"
+default_bytes: "\240\001\000\000"
+default_nested_enum: FOO
+default_foreign_enum: FOREIGN_FOO
+default_import_enum: IMPORT_FOO
+default_string_piece: "424"
+default_cord: "425"
diff --git a/objectivec/Tests/unittest_cycle.proto b/objectivec/Tests/unittest_cycle.proto
new file mode 100644
index 00000000..5f6f56a1
--- /dev/null
+++ b/objectivec/Tests/unittest_cycle.proto
@@ -0,0 +1,58 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// 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.
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+// Cycles in the Message graph can cause problems for the mutable classes
+// since the properties on the mutable class change types. This file just
+// needs to generate source, and that source must compile, to ensure the
+// generated source works for this sort of case.
+
+// You can't make a object graph that spans files, so this can only be done
+// within a single proto file.
+
+message CycleFoo {
+ optional CycleFoo a_foo = 1;
+ optional CycleBar a_bar = 2;
+ optional CycleBaz a_baz = 3;
+}
+
+message CycleBar {
+ optional CycleBar a_bar = 1;
+ optional CycleBaz a_baz = 2;
+ optional CycleFoo a_foo = 3;
+}
+
+message CycleBaz {
+ optional CycleBaz a_baz = 1;
+ optional CycleFoo a_foo = 2;
+ optional CycleBar a_bar = 3;
+}
diff --git a/objectivec/Tests/unittest_filter.proto b/objectivec/Tests/unittest_filter.proto
new file mode 100644
index 00000000..1398dfc8
--- /dev/null
+++ b/objectivec/Tests/unittest_filter.proto
@@ -0,0 +1,71 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2013 Google Inc. All rights reserved.
+//
+// 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.
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+
+message Keep {
+}
+
+message Remove {
+}
+
+message RemoveJustKidding {
+}
+
+message Other {
+ optional Keep a = 1;
+ optional Remove b = 2;
+}
+
+enum RemoveEnum {
+ RemoveValue = 1;
+}
+
+enum KeepEnum {
+ KeepValue = 1;
+}
+
+message RemoveEnumMessage {
+ enum KeepEnumInside {
+ KeepValue = 1;
+ }
+
+ enum RemoveEnumInside {
+ RemoveValue = 1;
+ }
+
+ message KeepNestedInside {
+ }
+
+ message RemoveNestedInside {
+ }
+}
diff --git a/objectivec/Tests/unittest_name_mangling.proto b/objectivec/Tests/unittest_name_mangling.proto
new file mode 100644
index 00000000..aadad6d6
--- /dev/null
+++ b/objectivec/Tests/unittest_name_mangling.proto
@@ -0,0 +1,37 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// 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.
+
+syntax = "proto2";
+
+option objc_class_prefix = "ABC";
+
+package protobuf_unittest;
+
+// TODO(thomasvl): Add tests for the special cases in name mangling.
+
diff --git a/objectivec/Tests/unittest_objc.proto b/objectivec/Tests/unittest_objc.proto
new file mode 100644
index 00000000..d288a30d
--- /dev/null
+++ b/objectivec/Tests/unittest_objc.proto
@@ -0,0 +1,389 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2011 Google Inc. All rights reserved.
+//
+// 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.
+
+syntax = "proto2";
+
+import "google/protobuf/unittest.proto";
+
+package protobuf_unittest;
+
+// Using the messages in unittest.proto, setup for recursive cases for testing
+// extensions at various depths.
+extend TestAllExtensions {
+ optional TestAllExtensions recursive_extension = 86;
+}
+
+// Recursive message to for testing autocreators at different depths.
+message TestRecursiveMessageWithRepeatedField {
+ optional TestRecursiveMessageWithRepeatedField a = 1;
+ repeated int32 i = 2;
+ repeated string str = 3;
+}
+
+// Recursive message and extension to for testing autocreators at different
+// depths.
+message TestRecursiveExtension {
+ optional TestRecursiveExtension recursive_sub_message = 1;
+ repeated int32 repeated_value = 2;
+ extensions 1000 to max;
+}
+
+extend TestRecursiveExtension {
+ optional TestRecursiveExtension recursive_message_extension = 1000;
+}
+
+message self {
+ message super {
+ optional int32 description = 1;
+ }
+
+ enum autorelease {
+ retain = 1;
+ release = 2;
+ retainCount = 3;
+ }
+
+ // Singular
+ optional bool id = 1;
+ optional bool _cmd = 2;
+ optional bool in = 3;
+ optional bool out = 4;
+ optional bool inout = 5;
+ optional bool bycopy = 6;
+ optional bool byref = 7;
+ optional bool oneway = 8;
+ optional bool dealloc = 9;
+ optional bool zone = 10;
+ optional bool isProxy = 11;
+ optional bool copy = 12;
+ optional bool readonly = 13;
+ optional bool default = 14;
+ optional bool assign = 15;
+ optional bool getter = 16;
+ optional bool setter = 17;
+ optional bool weak = 18;
+ optional bool public = 19;
+ optional bool case = 20;
+
+ optional autorelease SubEnum = 25;
+
+ optional group New = 50 {
+ optional string copy = 51;
+ }
+ optional group MutableCopy = 60 {
+ optional int32 extensionRegistry = 61;
+ }
+
+ extensions 90 to 94;
+
+}
+
+enum retain {
+ count = 4;
+ initialized = 5;
+ serializedSize = 6;
+}
+
+// EnumValueShortName: The short names shouldn't get suffixes/prefixes.
+enum Foo {
+ SERIALIZED_SIZE = 1;
+ SIZE = 2;
+ OTHER = 3;
+}
+
+// EnumValueShortName: The enum name gets a prefix.
+enum Category {
+ 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;
+}
+
+extend self {
+ repeated int32 debugDescription = 90 [packed = true];
+ repeated int64 finalize = 91 [packed = true];
+ repeated uint32 hash = 92 [packed = true];
+ repeated uint64 classForCoder = 93 [packed = true];
+ repeated sint32 byref = 94 [packed = true];
+}
+
+// Test handing of fields that start with init* since Xcode 5's ARC support
+// doesn't like messages that look like initializers but aren't.
+message ObjCInitFoo {
+ optional string init_val = 11;
+ optional int32 init_size = 12;
+ optional self init_self = 13;
+
+ repeated string init_vals = 21;
+ repeated int32 init_sizes = 22;
+ repeated self init_selfs = 23;
+}
+
+// Test handling of fields that start with retained names.
+message ObjCRetainedFoo {
+ optional string new_val_lower_complex = 11;
+ optional string new_Val_upper_complex = 12;
+ optional string newvalue_lower_no_underscore_complex = 13;
+ optional string newValue_upper_no_underscore_complex = 14;
+
+ optional int32 new_val_lower_primitive = 15;
+ optional int32 new_Val_upper_primitive = 16;
+ optional int32 newvalue_lower_no_underscore_primitive = 17;
+ optional int32 newValue_upper_no_underscore_primitive = 18;
+
+ optional self new_val_lower_message = 19;
+ optional self new_Val_upper_message = 20;
+ optional self newvalue_lower_no_underscore_message = 21;
+ optional self newValue_upper_no_underscore_message = 22;
+
+ optional Foo new_val_lower_enum = 23;
+ optional Foo new_Val_upper_enum = 24;
+ optional Foo newvalue_lower_no_underscore_enum = 25;
+ optional Foo newValue_upper_no_underscore_enum = 26;
+
+ repeated string new_val_lower_complex_repeated = 111;
+ repeated string new_Val_upper_complex_repeated = 112;
+ repeated string newvalue_lower_no_underscore_complex_repeated = 113;
+ repeated string newValue_upper_no_underscore_complex_repeated = 114;
+
+ repeated int32 new_val_lower_primitive_repeated = 115;
+ repeated int32 new_Val_upper_primitive_repeated = 116;
+ repeated int32 newvalue_lower_no_underscore_primitive_repeated = 117;
+ repeated int32 newValue_upper_no_underscore_primitive_repeated = 118;
+
+ repeated self new_val_lower_message_repeated = 119;
+ repeated self new_Val_upper_message_repeated = 120;
+ repeated self newvalue_lower_no_underscore_message_repeated = 121;
+ repeated self newValue_upper_no_underscore_message_repeated = 122;
+
+ repeated Foo new_val_lower_enum_repeated = 123;
+ repeated Foo new_Val_upper_enum_repeated = 124;
+ repeated Foo newvalue_lower_no_underscore_enum_repeated = 125;
+ repeated Foo newValue_upper_no_underscore_enum_repeated = 126;
+
+ optional string alloc_val_lower_complex = 211;
+ optional string alloc_Val_upper_complex = 212;
+ optional string allocvalue_lower_no_underscore_complex = 213;
+ optional string allocValue_upper_no_underscore_complex = 214;
+
+ optional int32 alloc_val_lower_primitive = 215;
+ optional int32 alloc_Val_upper_primitive = 216;
+ optional int32 allocvalue_lower_no_underscore_primitive = 217;
+ optional int32 allocValue_upper_no_underscore_primitive = 218;
+
+ optional self alloc_val_lower_message = 219;
+ optional self alloc_Val_upper_message = 220;
+ optional self allocvalue_lower_no_underscore_message = 221;
+ optional self allocValue_upper_no_underscore_message = 222;
+
+ optional Foo alloc_val_lower_enum = 223;
+ optional Foo alloc_Val_upper_enum = 224;
+ optional Foo allocvalue_lower_no_underscore_enum = 225;
+ optional Foo allocValue_upper_no_underscore_enum = 226;
+
+ repeated string alloc_val_lower_complex_repeated = 311;
+ repeated string alloc_Val_upper_complex_repeated = 312;
+ repeated string allocvalue_lower_no_underscore_complex_repeated = 313;
+ repeated string allocValue_upper_no_underscore_complex_repeated = 314;
+
+ repeated int32 alloc_val_lower_primitive_repeated = 315;
+ repeated int32 alloc_Val_upper_primitive_repeated = 316;
+ repeated int32 allocvalue_lower_no_underscore_primitive_repeated = 317;
+ repeated int32 allocValue_upper_no_underscore_primitive_repeated = 318;
+
+ repeated self alloc_val_lower_message_repeated = 319;
+ repeated self alloc_Val_upper_message_repeated = 320;
+ repeated self allocvalue_lower_no_underscore_message_repeated = 321;
+ repeated self allocValue_upper_no_underscore_message_repeated = 322;
+
+ repeated Foo alloc_val_lower_enum_repeated = 323;
+ repeated Foo alloc_Val_upper_enum_repeated = 324;
+ repeated Foo allocvalue_lower_no_underscore_enum_repeated = 325;
+ repeated Foo allocValue_upper_no_underscore_enum_repeated = 326;
+
+ optional string copy_val_lower_complex = 411;
+ optional string copy_Val_upper_complex = 412;
+ optional string copyvalue_lower_no_underscore_complex = 413;
+ optional string copyValue_upper_no_underscore_complex = 414;
+
+ optional int32 copy_val_lower_primitive = 415;
+ optional int32 copy_Val_upper_primitive = 416;
+ optional int32 copyvalue_lower_no_underscore_primitive = 417;
+ optional int32 copyValue_upper_no_underscore_primitive = 418;
+
+ optional self copy_val_lower_message = 419;
+ optional self copy_Val_upper_message = 420;
+ optional self copyvalue_lower_no_underscore_message = 421;
+ optional self copyValue_upper_no_underscore_message = 422;
+
+ optional Foo copy_val_lower_enum = 423;
+ optional Foo copy_Val_upper_enum = 424;
+ optional Foo copyvalue_lower_no_underscore_enum = 425;
+ optional Foo copyValue_upper_no_underscore_enum = 426;
+
+ repeated string copy_val_lower_complex_repeated = 511;
+ repeated string copy_Val_upper_complex_repeated = 512;
+ repeated string copyvalue_lower_no_underscore_complex_repeated = 513;
+ repeated string copyValue_upper_no_underscore_complex_repeated = 514;
+
+ repeated int32 copy_val_lower_primitive_repeated = 515;
+ repeated int32 copy_Val_upper_primitive_repeated = 516;
+ repeated int32 copyvalue_lower_no_underscore_primitive_repeated = 517;
+ repeated int32 copyValue_upper_no_underscore_primitive_repeated = 518;
+
+ repeated self copy_val_lower_message_repeated = 519;
+ repeated self copy_Val_upper_message_repeated = 520;
+ repeated self copyvalue_lower_no_underscore_message_repeated = 521;
+ repeated self copyValue_upper_no_underscore_message_repeated = 522;
+
+ repeated Foo copy_val_lower_enum_repeated = 523;
+ repeated Foo copy_Val_upper_enum_repeated = 524;
+ repeated Foo copyvalue_lower_no_underscore_enum_repeated = 525;
+ repeated Foo copyValue_upper_no_underscore_enum_repeated = 526;
+
+ optional string mutableCopy_val_lower_complex = 611;
+ optional string mutableCopy_Val_upper_complex = 612;
+ optional string mutableCopyvalue_lower_no_underscore_complex = 613;
+ optional string mutableCopyValue_upper_no_underscore_complex = 614;
+
+ optional int32 mutableCopy_val_lower_primitive = 615;
+ optional int32 mutableCopy_Val_upper_primitive = 616;
+ optional int32 mutableCopyvalue_lower_no_underscore_primitive = 617;
+ optional int32 mutableCopyValue_upper_no_underscore_primitive = 618;
+
+ optional self mutableCopy_val_lower_message = 619;
+ optional self mutableCopy_Val_upper_message = 620;
+ optional self mutableCopyvalue_lower_no_underscore_message = 621;
+ optional self mutableCopyValue_upper_no_underscore_message = 622;
+
+ optional Foo mutableCopy_val_lower_enum = 623;
+ optional Foo mutableCopy_Val_upper_enum = 624;
+ optional Foo mutableCopyvalue_lower_no_underscore_enum = 625;
+ optional Foo mutableCopyValue_upper_no_underscore_enum = 626;
+
+ repeated string mutableCopy_val_lower_complex_repeated = 711;
+ repeated string mutableCopy_Val_upper_complex_repeated = 712;
+ repeated string mutableCopyvalue_lower_no_underscore_complex_repeated = 713;
+ repeated string mutableCopyValue_upper_no_underscore_complex_repeated = 714;
+
+ repeated int32 mutableCopy_val_lower_primitive_repeated = 715;
+ repeated int32 mutableCopy_Val_upper_primitive_repeated = 716;
+ repeated int32 mutableCopyvalue_lower_no_underscore_primitive_repeated = 717;
+ repeated int32 mutableCopyValue_upper_no_underscore_primitive_repeated = 718;
+
+ repeated self mutableCopy_val_lower_message_repeated = 719;
+ repeated self mutableCopy_Val_upper_message_repeated = 720;
+ repeated self mutableCopyvalue_lower_no_underscore_message_repeated = 721;
+ repeated self mutableCopyValue_upper_no_underscore_message_repeated = 722;
+
+ repeated Foo mutableCopy_val_lower_enum_repeated = 723;
+ repeated Foo mutableCopy_Val_upper_enum_repeated = 724;
+ repeated Foo mutableCopyvalue_lower_no_underscore_enum_repeated = 725;
+ repeated Foo mutableCopyValue_upper_no_underscore_enum_repeated = 726;
+}
+
+// Test handling of fields that are the retained names.
+message ObjCRetainedComplex {
+ optional string new = 1;
+ optional string alloc = 2;
+ optional string copy = 3;
+ optional string mutableCopy = 4;
+}
+
+message ObjCRetainedComplexRepeated {
+ repeated string new = 1;
+ repeated string alloc = 2;
+ repeated string copy = 3;
+ repeated string mutableCopy = 4;
+}
+
+message ObjCRetainedPrimitive {
+ optional int32 new = 1;
+ optional int32 alloc = 2;
+ optional int32 copy = 3;
+ optional int32 mutableCopy = 4;
+}
+
+message ObjCRetainedPrimitiveRepeated {
+ repeated int32 new = 1;
+ repeated int32 alloc = 2;
+ repeated int32 copy = 3;
+ repeated int32 mutableCopy = 4;
+}
+
+message ObjCRetainedMessage {
+ optional self new = 1;
+ optional self alloc = 2;
+ optional self copy = 3;
+ optional self mutableCopy = 4;
+}
+
+message ObjCRetainedMessageRepeated {
+ repeated self new = 1;
+ repeated self alloc = 2;
+ repeated self copy = 3;
+ repeated self mutableCopy = 4;
+}
+
+// Test Handling some MacTypes
+message Point {
+ message Rect {
+ optional int32 TimeValue = 1;
+ }
+}
+
+// Test some weird defaults that we see in protos.
+message ObjcWeirdDefaults {
+ // Set default values that match the protocol buffer defined defaults to
+ // confirm hasDefault and the default values are set correctly.
+ optional string foo = 1 [default = ""];
+ optional bytes bar = 2 [default = ""];
+}
+
+// Used to confirm negative enum values work as expected.
+message EnumTestMsg {
+ enum MyEnum {
+ ZERO = 0;
+ ONE = 1;
+ TWO = 2;
+ NEG_ONE = -1;
+ NEG_TWO = -2;
+ }
+ optional MyEnum foo = 1;
+ optional MyEnum bar = 2 [default = ONE];
+ optional MyEnum baz = 3 [default = NEG_ONE];
+
+ repeated MyEnum mumble = 4;
+}
diff --git a/objectivec/Tests/unittest_runtime_proto2.proto b/objectivec/Tests/unittest_runtime_proto2.proto
new file mode 100644
index 00000000..f9fd3c35
--- /dev/null
+++ b/objectivec/Tests/unittest_runtime_proto2.proto
@@ -0,0 +1,108 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// 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.
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+message Message2 {
+ enum Enum {
+ FOO = 0;
+ BAR = 1;
+ BAZ = 2;
+ EXTRA_2 = 20;
+ }
+
+ optional int32 optional_int32 = 1;
+ optional int64 optional_int64 = 2;
+ optional uint32 optional_uint32 = 3;
+ optional uint64 optional_uint64 = 4;
+ optional sint32 optional_sint32 = 5;
+ optional sint64 optional_sint64 = 6;
+ optional fixed32 optional_fixed32 = 7;
+ optional fixed64 optional_fixed64 = 8;
+ optional sfixed32 optional_sfixed32 = 9;
+ optional sfixed64 optional_sfixed64 = 10;
+ optional float optional_float = 11;
+ optional double optional_double = 12;
+ optional bool optional_bool = 13;
+ optional string optional_string = 14;
+ optional bytes optional_bytes = 15;
+ optional group OptionalGroup = 16 {
+ optional int32 a = 17;
+ }
+ optional Message2 optional_message = 18;
+ optional Enum optional_enum = 19;
+
+ repeated int32 repeated_int32 = 31;
+ repeated int64 repeated_int64 = 32;
+ repeated uint32 repeated_uint32 = 33;
+ repeated uint64 repeated_uint64 = 34;
+ repeated sint32 repeated_sint32 = 35;
+ repeated sint64 repeated_sint64 = 36;
+ repeated fixed32 repeated_fixed32 = 37;
+ repeated fixed64 repeated_fixed64 = 38;
+ repeated sfixed32 repeated_sfixed32 = 39;
+ repeated sfixed64 repeated_sfixed64 = 40;
+ repeated float repeated_float = 41;
+ repeated double repeated_double = 42;
+ repeated bool repeated_bool = 43;
+ repeated string repeated_string = 44;
+ repeated bytes repeated_bytes = 45;
+ repeated group RepeatedGroup = 46 {
+ optional int32 a = 47;
+ }
+ repeated Message2 repeated_message = 48;
+ repeated Enum repeated_enum = 49;
+ repeated Enum repeated_packed_enum = 50 [packed=true];
+
+ oneof o {
+ int32 oneof_int32 = 51 [default = 100];
+ int64 oneof_int64 = 52 [default = 101];
+ uint32 oneof_uint32 = 53 [default = 102];
+ uint64 oneof_uint64 = 54 [default = 103];
+ sint32 oneof_sint32 = 55 [default = 104];
+ sint64 oneof_sint64 = 56 [default = 105];
+ fixed32 oneof_fixed32 = 57 [default = 106];
+ fixed64 oneof_fixed64 = 58 [default = 107];
+ sfixed32 oneof_sfixed32 = 59 [default = 108];
+ sfixed64 oneof_sfixed64 = 60 [default = 109];
+ float oneof_float = 61 [default = 110];
+ double oneof_double = 62 [default = 111];
+ bool oneof_bool = 63 [default = true];
+ string oneof_string = 64 [default = "string"];
+ bytes oneof_bytes = 65 [default = "data"];
+ group OneofGroup = 66 {
+ optional int32 a = 67;
+ optional int32 b = 167;
+ }
+ Message2 oneof_message = 68;
+ Enum oneof_enum = 69 [default = BAZ];
+ }
+}
diff --git a/objectivec/Tests/unittest_runtime_proto3.proto b/objectivec/Tests/unittest_runtime_proto3.proto
new file mode 100644
index 00000000..b6a2f4dc
--- /dev/null
+++ b/objectivec/Tests/unittest_runtime_proto3.proto
@@ -0,0 +1,101 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// 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.
+
+syntax = "proto3";
+
+package protobuf_unittest;
+
+message Message3 {
+ enum Enum {
+ FOO = 0;
+ BAR = 1;
+ BAZ = 2;
+ EXTRA_3 = 30;
+ }
+
+ int32 optional_int32 = 1;
+ int64 optional_int64 = 2;
+ uint32 optional_uint32 = 3;
+ uint64 optional_uint64 = 4;
+ sint32 optional_sint32 = 5;
+ sint64 optional_sint64 = 6;
+ fixed32 optional_fixed32 = 7;
+ fixed64 optional_fixed64 = 8;
+ sfixed32 optional_sfixed32 = 9;
+ sfixed64 optional_sfixed64 = 10;
+ float optional_float = 11;
+ double optional_double = 12;
+ bool optional_bool = 13;
+ string optional_string = 14;
+ bytes optional_bytes = 15;
+ // No 'group' in proto3.
+ Message3 optional_message = 18;
+ Enum optional_enum = 19;
+
+ repeated int32 repeated_int32 = 31;
+ repeated int64 repeated_int64 = 32;
+ repeated uint32 repeated_uint32 = 33;
+ repeated uint64 repeated_uint64 = 34;
+ repeated sint32 repeated_sint32 = 35;
+ repeated sint64 repeated_sint64 = 36;
+ repeated fixed32 repeated_fixed32 = 37;
+ repeated fixed64 repeated_fixed64 = 38;
+ repeated sfixed32 repeated_sfixed32 = 39;
+ repeated sfixed64 repeated_sfixed64 = 40;
+ repeated float repeated_float = 41;
+ repeated double repeated_double = 42;
+ repeated bool repeated_bool = 43;
+ repeated string repeated_string = 44;
+ repeated bytes repeated_bytes = 45;
+ // No 'group' in proto3.
+ repeated Message3 repeated_message = 48;
+ repeated Enum repeated_enum = 49;
+ repeated Enum repeated_packed_enum = 50 [packed=true];
+
+ oneof o {
+ int32 oneof_int32 = 51;
+ int64 oneof_int64 = 52;
+ uint32 oneof_uint32 = 53;
+ uint64 oneof_uint64 = 54;
+ sint32 oneof_sint32 = 55;
+ sint64 oneof_sint64 = 56;
+ fixed32 oneof_fixed32 = 57;
+ fixed64 oneof_fixed64 = 58;
+ sfixed32 oneof_sfixed32 = 59;
+ sfixed64 oneof_sfixed64 = 60;
+ float oneof_float = 61;
+ double oneof_double = 62;
+ bool oneof_bool = 63;
+ string oneof_string = 64;
+ bytes oneof_bytes = 65;
+ // No 'group' in proto3.
+ Message3 oneof_message = 68;
+ Enum oneof_enum = 69;
+ }
+}