diff options
Diffstat (limited to 'objectivec/Tests/GPBDictionaryTests.pddm')
-rw-r--r-- | objectivec/Tests/GPBDictionaryTests.pddm | 1044 |
1 files changed, 1044 insertions, 0 deletions
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 +//% + |