a230b5d209
Note: Breaking API change on the Dictionary classes. The numeric value classes were using "Value" in the naming, but this silently collided with the KVC category on NSObject; meaning KVC code could break up a keypath and call these selectors with the wrong types leading to crashes (even though the code all would compile cleanly). - Rename the methods to use the "type" instead of literal "Value". - Update all the impls and tests. - Enable the warning that will catch issues like this in the future. Fixes https://github.com/google/protobuf/issues/1616
1048 lines
50 KiB
Plaintext
1048 lines
50 KiB
Plaintext
// 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, NSString*, @"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, , value, 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, OBJECT, , VAL1, VAL2, VAL3, VAL4)
|
|
|
|
//%PDDM-DEFINE DICTIONARY_CLASS_DECLPOD(KEY_NAME, VALUE_NAME, VALUE_TYPE)
|
|
//%GPB##KEY_NAME##VALUE_NAME##Dictionary
|
|
//%PDDM-DEFINE DICTIONARY_CLASS_DECLEnum(KEY_NAME, VALUE_NAME, VALUE_TYPE)
|
|
//%GPB##KEY_NAME##VALUE_NAME##Dictionary
|
|
//%PDDM-DEFINE DICTIONARY_CLASS_DECLOBJECT(KEY_NAME, VALUE_NAME, VALUE_TYPE)
|
|
//%GPB##KEY_NAME##VALUE_NAME##Dictionary<VALUE_TYPE>
|
|
|
|
//%PDDM-DEFINE TESTS_COMMON(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, VSUFFIX, VNAME, 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 {
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
|
|
//% XCTAssertNotNil(dict);
|
|
//% XCTAssertEqual(dict.count, 0U);
|
|
//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY1)
|
|
//% [dict enumerateKeysAnd##VALUE_NAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u, BOOL *stop) {
|
|
//% #pragma unused(aKey, a##VNAME$u, stop)
|
|
//% XCTFail(@"Shouldn't get here!");
|
|
//% }];
|
|
//% [dict release];
|
|
//%}
|
|
//%
|
|
//%- (void)testOne {
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWith##VALUE_NAME$u##:VAL1 forKey:KEY1];
|
|
//% XCTAssertNotNil(dict);
|
|
//% XCTAssertEqual(dict.count, 1U);
|
|
//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
|
|
//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
|
|
//% [dict enumerateKeysAnd##VALUE_NAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u, BOOL *stop) {
|
|
//% XCTAssertEqual##KSUFFIX(aKey, KEY1);
|
|
//% XCTAssertEqual##VSUFFIX(a##VNAME$u, VAL1);
|
|
//% XCTAssertNotEqual(stop, NULL);
|
|
//% }];
|
|
//%}
|
|
//%
|
|
//%- (void)testBasics {
|
|
//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3 };
|
|
//% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3 };
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
|
|
//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME$u##s:k##VNAME$u##s
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
|
|
//% XCTAssertNotNil(dict);
|
|
//% XCTAssertEqual(dict.count, 3U);
|
|
//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL3)
|
|
//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY4)
|
|
//%
|
|
//% __block NSUInteger idx = 0;
|
|
//% KEY_TYPE KisP##*seenKeys = malloc(3 * sizeof(KEY_TYPE##KisP));
|
|
//% VALUE_TYPE *seen##VNAME$u##s = malloc(3 * sizeof(VALUE_TYPE));
|
|
//% [dict enumerateKeysAnd##VALUE_NAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u, BOOL *stop) {
|
|
//% XCTAssertLessThan(idx, 3U);
|
|
//% seenKeys[idx] = aKey;
|
|
//% seen##VNAME$u##s[idx] = a##VNAME$u##;
|
|
//% 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(k##VNAME$u##s[i], seen##VNAME$u##s[j], @"i = %d, j = %d", i, j);
|
|
//% }
|
|
//% }
|
|
//% XCTAssertTrue(foundKey, @"i = %d", i);
|
|
//% }
|
|
//% free(seenKeys);
|
|
//% free(seen##VNAME$u##s);
|
|
//%
|
|
//% // Stopping the enumeration.
|
|
//% idx = 0;
|
|
//% [dict enumerateKeysAnd##VALUE_NAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u, BOOL *stop) {
|
|
//% #pragma unused(aKey, a##VNAME$u)
|
|
//% 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 k##VNAME$u##s1[] = { VAL1, VAL2, VAL3 };
|
|
//% const VALUE_TYPE k##VNAME$u##s2[] = { VAL1, VAL4, VAL3 };
|
|
//% const VALUE_TYPE k##VNAME$u##s3[] = { VAL1, VAL2, VAL3, VAL4 };
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1 =
|
|
//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s1
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys1
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s1)];
|
|
//% XCTAssertNotNil(dict1);
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1prime =
|
|
//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s1
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys1
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s1)];
|
|
//% XCTAssertNotNil(dict1prime);
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
|
|
//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s2
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys1
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s2)];
|
|
//% XCTAssertNotNil(dict2);
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict3 =
|
|
//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s1
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys2
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s1)];
|
|
//% XCTAssertNotNil(dict3);
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict4 =
|
|
//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s3
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys1
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s3)];
|
|
//% 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 same keys, different ##VNAME##s; not equal.
|
|
//% XCTAssertNotEqualObjects(dict1, dict2);
|
|
//%
|
|
//% // 3 is different keys, same ##VNAME##s; 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 k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
|
|
//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
|
|
//% XCTAssertNotNil(dict);
|
|
//%
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *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 k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
|
|
//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
|
|
//% XCTAssertNotNil(dict);
|
|
//%
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *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 {
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionary];
|
|
//% XCTAssertNotNil(dict);
|
|
//%
|
|
//% XCTAssertEqual(dict.count, 0U);
|
|
//% [dict set##VALUE_NAME##:VAL1 forKey:KEY1];
|
|
//% XCTAssertEqual(dict.count, 1U);
|
|
//%
|
|
//% const KEY_TYPE KisP##kKeys[] = { KEY2, KEY3, KEY4 };
|
|
//% const VALUE_TYPE k##VNAME$u##s[] = { VAL2, VAL3, VAL4 };
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
|
|
//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
|
|
//% XCTAssertNotNil(dict2);
|
|
//% [dict add##VACCESSOR##EntriesFromDictionary:dict2];
|
|
//% XCTAssertEqual(dict.count, 4U);
|
|
//%
|
|
//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL3)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY4, VAL4)
|
|
//% [dict2 release];
|
|
//%}
|
|
//%
|
|
//%- (void)testRemove {
|
|
//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
|
|
//% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
|
|
//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
|
|
//% XCTAssertNotNil(dict);
|
|
//% XCTAssertEqual(dict.count, 4U);
|
|
//%
|
|
//% [dict remove##VALUE_NAME##ForKey:KEY2];
|
|
//% XCTAssertEqual(dict.count, 3U);
|
|
//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
|
|
//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL3)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY4, VAL4)
|
|
//%
|
|
//% // Remove again does nothing.
|
|
//% [dict remove##VALUE_NAME##ForKey:KEY2];
|
|
//% XCTAssertEqual(dict.count, 3U);
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
|
|
//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL3)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY4, VAL4)
|
|
//%
|
|
//% [dict remove##VALUE_NAME##ForKey:KEY4];
|
|
//% XCTAssertEqual(dict.count, 2U);
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
|
|
//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL3)
|
|
//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY4)
|
|
//%
|
|
//% [dict removeAll];
|
|
//% XCTAssertEqual(dict.count, 0U);
|
|
//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY1)
|
|
//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
|
|
//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY3)
|
|
//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY4)
|
|
//% [dict release];
|
|
//%}
|
|
//%
|
|
//%- (void)testInplaceMutation {
|
|
//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
|
|
//% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
|
|
//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
|
|
//% XCTAssertNotNil(dict);
|
|
//% XCTAssertEqual(dict.count, 4U);
|
|
//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL3)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY4, VAL4)
|
|
//%
|
|
//% [dict set##VALUE_NAME##:VAL4 forKey:KEY1];
|
|
//% XCTAssertEqual(dict.count, 4U);
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL4)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL3)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY4, VAL4)
|
|
//%
|
|
//% [dict set##VALUE_NAME##:VAL2 forKey:KEY4];
|
|
//% XCTAssertEqual(dict.count, 4U);
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL4)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL3)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY4, VAL2)
|
|
//%
|
|
//% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY3 };
|
|
//% const VALUE_TYPE k##VNAME$u##s2[] = { VAL3, VAL1 };
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
|
|
//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s2
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys2
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s2)];
|
|
//% XCTAssertNotNil(dict2);
|
|
//% [dict add##VACCESSOR##EntriesFromDictionary:dict2];
|
|
//% XCTAssertEqual(dict.count, 4U);
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL4)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL3)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL1)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, 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 };
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *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(VALUE_NAME, 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(VALUE_NAME, 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 enumerateKeysAndEnumsUsingBlock:^(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
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *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);
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *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);
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *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);
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *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);
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *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 same keys, different values; not equal.
|
|
//% XCTAssertNotEqualObjects(dict1, dict2);
|
|
//%
|
|
//% // 3 is different keys, same 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
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *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);
|
|
//%
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *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
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *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);
|
|
//%
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *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 {
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
|
|
//% [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue];
|
|
//% XCTAssertNotNil(dict);
|
|
//%
|
|
//% XCTAssertEqual(dict.count, 0U);
|
|
//% XCTAssertThrowsSpecificNamed([dict setEnum: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
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
|
|
//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithEnums: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(VALUE_NAME, dict, value, KEY1, VAL1)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY2, kGPBUnrecognizedEnumeratorValue)
|
|
//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY3, VAL3)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, 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
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *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 removeEnumForKey:KEY2];
|
|
//% XCTAssertEqual(dict.count, 3U);
|
|
//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY1, VAL1)
|
|
//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY3, VAL3)
|
|
//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
|
|
//%
|
|
//% // Remove again does nothing.
|
|
//% [dict removeEnumForKey:KEY2];
|
|
//% XCTAssertEqual(dict.count, 3U);
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY1, VAL1)
|
|
//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY3, VAL3)
|
|
//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
|
|
//%
|
|
//% [dict removeEnumForKey:KEY4];
|
|
//% XCTAssertEqual(dict.count, 2U);
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY1, VAL1)
|
|
//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY3, VAL3)
|
|
//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY4)
|
|
//%
|
|
//% [dict removeAll];
|
|
//% XCTAssertEqual(dict.count, 0U);
|
|
//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY1)
|
|
//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
|
|
//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY3)
|
|
//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY4)
|
|
//% [dict release];
|
|
//%}
|
|
//%
|
|
//%- (void)testInplaceMutationUnknowns {
|
|
//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
|
|
//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 }; // Unknowns
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *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(VALUE_NAME, dict, value, KEY1, VAL1)
|
|
//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY3, VAL3)
|
|
//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
|
|
//%
|
|
//% XCTAssertThrowsSpecificNamed([dict setEnum:VAL4 forKey:KEY1], // Unknown
|
|
//% NSException, NSInvalidArgumentException);
|
|
//% XCTAssertEqual(dict.count, 4U);
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY1, VAL1)
|
|
//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, 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(VALUE_NAME, 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(VALUE_NAME, dict, value, KEY3, VAL3)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY4, VAL1)
|
|
//%
|
|
//% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY3 };
|
|
//% const VALUE_TYPE kValues2[] = { VAL3, VAL2 }; // Unknown
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *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(VALUE_NAME, dict, value, KEY2, VAL3)
|
|
//%TEST_RAW_VALUE##VHELPER(dict, value, KEY3, VAL2)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, 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 };
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *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);
|
|
//%
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *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(VALUE_NAME, DICT, KEY)
|
|
//% XCTAssertFalse([DICT get##VALUE_NAME##:NULL forKey:KEY]);
|
|
//%PDDM-DEFINE TEST_VALUEPOD(VALUE_NAME, DICT, STORAGE, KEY, VALUE)
|
|
//% XCTAssertTrue([DICT get##VALUE_NAME##:NULL forKey:KEY]);
|
|
//% XCTAssertTrue([DICT get##VALUE_NAME##:&STORAGE forKey:KEY]);
|
|
//% XCTAssertEqual(STORAGE, VALUE);
|
|
//%PDDM-DEFINE COMPARE_KEYS(KEY1, KEY2)
|
|
//%KEY1 == KEY2
|
|
//%PDDM-DEFINE RAW_VALUE_NOT_FOUNDPOD(VALUE_NAME, DICT, KEY)
|
|
//% XCTAssertFalse([DICT getRawValue:NULL forKey:KEY]);
|
|
//%PDDM-DEFINE TEST_RAW_VALUEPOD(DICT, STORAGE, KEY, VALUE)
|
|
//% XCTAssertTrue([DICT getRawValue:NULL forKey:KEY]);
|
|
//% XCTAssertTrue([DICT getRawValue:&STORAGE forKey:KEY]);
|
|
//% XCTAssertEqual(STORAGE, VALUE);
|
|
|
|
//
|
|
// Helpers for Objects
|
|
//
|
|
|
|
//%PDDM-DEFINE DECLARE_VALUE_STORAGEOBJECT(VALUE_TYPE, NAME)
|
|
// Empty
|
|
//%PDDM-DEFINE VALUE_NOT_FOUNDOBJECT(VALUE_NAME, DICT, KEY)
|
|
//% XCTAssertNil([DICT objectForKey:KEY]);
|
|
//%PDDM-DEFINE TEST_VALUEOBJECT(VALUE_NAME, DICT, STORAGE, KEY, VALUE)
|
|
//% XCTAssertEqualObjects([DICT objectForKey:KEY], VALUE);
|
|
//%PDDM-DEFINE COMPARE_KEYSObjects(KEY1, KEY2)
|
|
//%[KEY1 isEqual:KEY2]
|
|
|
|
//
|
|
// Helpers for tests.
|
|
//
|
|
|
|
//%PDDM-DEFINE TEST_HELPERS(KEY_NAME, KEY_TYPE, KisP)
|
|
//%// To let the testing macros work, add some extra methods to simplify things.
|
|
//%@interface GPB##KEY_NAME##EnumDictionary (TestingTweak)
|
|
//%+ (instancetype)dictionaryWithEnum:(int32_t)value forKey:(KEY_TYPE##KisP$S##KisP)key;
|
|
//%- (instancetype)initWithEnums:(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)dictionaryWithEnum:(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)initWithEnums:(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, , value, 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, OBJECT, VAL1, VAL2)
|
|
|
|
//%PDDM-DEFINE BOOL_TESTS_COMMON(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, VALUE_NAME, VALUE_TYPE, VSUFFIX, VNAME, 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 {
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
|
|
//% XCTAssertNotNil(dict);
|
|
//% XCTAssertEqual(dict.count, 0U);
|
|
//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY1)
|
|
//% [dict enumerateKeysAnd##VALUE_NAME##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u##, BOOL *stop) {
|
|
//% #pragma unused(aKey, a##VNAME$u##, stop)
|
|
//% XCTFail(@"Shouldn't get here!");
|
|
//% }];
|
|
//% [dict release];
|
|
//%}
|
|
//%
|
|
//%- (void)testOne {
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWith##VALUE_NAME$u##:VAL1 forKey:KEY1];
|
|
//% XCTAssertNotNil(dict);
|
|
//% XCTAssertEqual(dict.count, 1U);
|
|
//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
|
|
//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
|
|
//% [dict enumerateKeysAnd##VALUE_NAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u, BOOL *stop) {
|
|
//% XCTAssertEqual##KSUFFIX(aKey, KEY1);
|
|
//% XCTAssertEqual##VSUFFIX(a##VNAME$u, VAL1);
|
|
//% XCTAssertNotEqual(stop, NULL);
|
|
//% }];
|
|
//%}
|
|
//%
|
|
//%- (void)testBasics {
|
|
//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
|
|
//% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
|
|
//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
|
|
//% XCTAssertNotNil(dict);
|
|
//% XCTAssertEqual(dict.count, 2U);
|
|
//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
|
|
//%
|
|
//% __block NSUInteger idx = 0;
|
|
//% KEY_TYPE KisP##*seenKeys = malloc(2 * sizeof(KEY_TYPE##KisP));
|
|
//% VALUE_TYPE *seen##VNAME$u##s = malloc(2 * sizeof(VALUE_TYPE));
|
|
//% [dict enumerateKeysAnd##VALUE_NAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u##, BOOL *stop) {
|
|
//% XCTAssertLessThan(idx, 2U);
|
|
//% seenKeys[idx] = aKey;
|
|
//% seen##VNAME$u##s[idx] = a##VNAME$u;
|
|
//% 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(k##VNAME$u##s[i], seen##VNAME$u##s[j], @"i = %d, j = %d", i, j);
|
|
//% }
|
|
//% }
|
|
//% XCTAssertTrue(foundKey, @"i = %d", i);
|
|
//% }
|
|
//% free(seenKeys);
|
|
//% free(seen##VNAME$u##s);
|
|
//%
|
|
//% // Stopping the enumeration.
|
|
//% idx = 0;
|
|
//% [dict enumerateKeysAnd##VALUE_NAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u##, BOOL *stop) {
|
|
//% #pragma unused(aKey, a##VNAME$u)
|
|
//% 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 k##VNAME$u##s1[] = { VAL1, VAL2 };
|
|
//% const VALUE_TYPE k##VNAME$u##s2[] = { VAL2, VAL1 };
|
|
//% const VALUE_TYPE k##VNAME$u##s3[] = { VAL2 };
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1 =
|
|
//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s1
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys1
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s1)];
|
|
//% XCTAssertNotNil(dict1);
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1prime =
|
|
//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s1
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys1
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s1)];
|
|
//% XCTAssertNotNil(dict1prime);
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
|
|
//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s2
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys1
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s2)];
|
|
//% XCTAssertNotNil(dict2);
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict3 =
|
|
//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s1
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys2
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s1)];
|
|
//% XCTAssertNotNil(dict3);
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict4 =
|
|
//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s3
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys1
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s3)];
|
|
//% 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 same keys, different ##VNAME##s; not equal.
|
|
//% XCTAssertNotEqualObjects(dict1, dict2);
|
|
//%
|
|
//% // 3 is different keys, same ##VNAME##s; 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 k##VNAME$u##s[] = { VAL1, VAL2 };
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
|
|
//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
|
|
//% XCTAssertNotNil(dict);
|
|
//%
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *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 k##VNAME$u##s[] = { VAL1, VAL2 };
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
|
|
//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
|
|
//% XCTAssertNotNil(dict);
|
|
//%
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *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 {
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionary];
|
|
//% XCTAssertNotNil(dict);
|
|
//%
|
|
//% XCTAssertEqual(dict.count, 0U);
|
|
//% [dict set##VALUE_NAME:VAL1 forKey:KEY1];
|
|
//% XCTAssertEqual(dict.count, 1U);
|
|
//%
|
|
//% const KEY_TYPE KisP##kKeys[] = { KEY2 };
|
|
//% const VALUE_TYPE k##VNAME$u##s[] = { VAL2 };
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
|
|
//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
|
|
//% XCTAssertNotNil(dict2);
|
|
//% [dict addEntriesFromDictionary:dict2];
|
|
//% XCTAssertEqual(dict.count, 2U);
|
|
//%
|
|
//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
|
|
//% [dict2 release];
|
|
//%}
|
|
//%
|
|
//%- (void)testRemove {
|
|
//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2};
|
|
//% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
|
|
//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
|
|
//% XCTAssertNotNil(dict);
|
|
//% XCTAssertEqual(dict.count, 2U);
|
|
//%
|
|
//% [dict remove##VALUE_NAME##ForKey:KEY2];
|
|
//% XCTAssertEqual(dict.count, 1U);
|
|
//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
|
|
//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
|
|
//%
|
|
//% // Remove again does nothing.
|
|
//% [dict remove##VALUE_NAME##ForKey:KEY2];
|
|
//% XCTAssertEqual(dict.count, 1U);
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
|
|
//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
|
|
//%
|
|
//% [dict removeAll];
|
|
//% XCTAssertEqual(dict.count, 0U);
|
|
//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY1)
|
|
//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
|
|
//% [dict release];
|
|
//%}
|
|
//%
|
|
//%- (void)testInplaceMutation {
|
|
//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
|
|
//% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
|
|
//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
|
|
//% XCTAssertNotNil(dict);
|
|
//% XCTAssertEqual(dict.count, 2U);
|
|
//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
|
|
//%
|
|
//% [dict set##VALUE_NAME##:VAL2 forKey:KEY1];
|
|
//% XCTAssertEqual(dict.count, 2U);
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL2)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
|
|
//%
|
|
//% [dict set##VALUE_NAME##:VAL1 forKey:KEY2];
|
|
//% XCTAssertEqual(dict.count, 2U);
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL2)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL1)
|
|
//%
|
|
//% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY1 };
|
|
//% const VALUE_TYPE k##VNAME$u##s2[] = { VAL2, VAL1 };
|
|
//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
|
|
//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s2
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys2
|
|
//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s2)];
|
|
//% XCTAssertNotNil(dict2);
|
|
//% [dict addEntriesFromDictionary:dict2];
|
|
//% XCTAssertEqual(dict.count, 2U);
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
|
|
//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
|
|
//%
|
|
//% [dict2 release];
|
|
//% [dict release];
|
|
//%}
|
|
//%
|
|
//%@end
|
|
//%
|
|
|