blob: 17f12c28f00318444fee16a6b30196d478a7aebf [file] [log] [blame]
Brian Silverman9c614bc2016-02-15 20:20:02 -05001// Protocol Buffers - Google's data interchange format
2// Copyright 2015 Google Inc. All rights reserved.
3// https://developers.google.com/protocol-buffers/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15// * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31//%PDDM-DEFINE TEST_FOR_POD_KEY(KEY_NAME, KEY_TYPE, KEY1, KEY2, KEY3, KEY4)
32//%TESTS_FOR_POD_VALUES(KEY_NAME, KEY_TYPE, , , KEY1, KEY2, KEY3, KEY4)
Austin Schuh40c16522018-10-28 20:27:54 -070033//%TESTS_FOR_POD_KEY_OBJECT_VALUE(KEY_NAME, KEY_TYPE, KEY1, KEY2, KEY3, KEY4, Object, NSString*, @"abc", @"def", @"ghi", @"jkl")
Brian Silverman9c614bc2016-02-15 20:20:02 -050034
35//%PDDM-DEFINE TESTS_FOR_POD_VALUES(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4)
36//%TEST_HELPERS(KEY_NAME, KEY_TYPE, KisP)
37//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, UInt32, uint32_t, , 100U, 101U, 102U, 103U)
38//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Int32, int32_t, , 200, 201, 202, 203)
39//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, UInt64, uint64_t, , 300U, 301U, 302U, 303U)
40//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Int64, int64_t, , 400, 401, 402, 403)
41//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Bool, BOOL, , YES, YES, NO, NO)
42//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Float, float, , 500.f, 501.f, 502.f, 503.f)
43//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Double, double, , 600., 601., 602., 603.)
44//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Enum, int32_t, Raw, 700, 701, 702, 703)
45//%TESTS_FOR_ENUM_VALUE_RAW_ADDITIONS(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4)
46
47//%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)
48//%TESTS_COMMON(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, , value, POD, VACCESSOR, VAL1, VAL2, VAL3, VAL4)
49
50//%PDDM-DEFINE TESTS_FOR_POD_KEY_OBJECT_VALUE(KEY_NAME, KEY_TYPE, KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, VAL1, VAL2, VAL3, VAL4)
51//%TESTS_COMMON(KEY_NAME, KEY_TYPE, , , KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, Objects, object, OBJECT, , VAL1, VAL2, VAL3, VAL4)
52
Austin Schuh40c16522018-10-28 20:27:54 -070053//%PDDM-DEFINE DICTIONARY_CLASS_DECLPOD(KEY_NAME, VALUE_NAME, VALUE_TYPE)
54//%GPB##KEY_NAME##VALUE_NAME##Dictionary
55//%PDDM-DEFINE DICTIONARY_CLASS_DECLEnum(KEY_NAME, VALUE_NAME, VALUE_TYPE)
56//%GPB##KEY_NAME##VALUE_NAME##Dictionary
57//%PDDM-DEFINE DICTIONARY_CLASS_DECLOBJECT(KEY_NAME, VALUE_NAME, VALUE_TYPE)
58//%GPB##KEY_NAME##VALUE_NAME##Dictionary<VALUE_TYPE>
59
Brian Silverman9c614bc2016-02-15 20:20:02 -050060//%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)
61//%#pragma mark - KEY_NAME -> VALUE_NAME
62//%
63//%@interface GPB##KEY_NAME##VALUE_NAME##DictionaryTests : XCTestCase
64//%@end
65//%
66//%@implementation GPB##KEY_NAME##VALUE_NAME##DictionaryTests
67//%
68//%- (void)testEmpty {
Austin Schuh40c16522018-10-28 20:27:54 -070069//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
Brian Silverman9c614bc2016-02-15 20:20:02 -050070//% XCTAssertNotNil(dict);
71//% XCTAssertEqual(dict.count, 0U);
Austin Schuh40c16522018-10-28 20:27:54 -070072//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY1)
73//% [dict enumerateKeysAnd##VALUE_NAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u, BOOL *stop) {
Brian Silverman9c614bc2016-02-15 20:20:02 -050074//% #pragma unused(aKey, a##VNAME$u, stop)
75//% XCTFail(@"Shouldn't get here!");
76//% }];
77//% [dict release];
78//%}
79//%
80//%- (void)testOne {
Austin Schuh40c16522018-10-28 20:27:54 -070081//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
82//% [dict set##VALUE_NAME$u##:VAL1 forKey:KEY1];
Brian Silverman9c614bc2016-02-15 20:20:02 -050083//% XCTAssertNotNil(dict);
84//% XCTAssertEqual(dict.count, 1U);
Austin Schuh40c16522018-10-28 20:27:54 -070085//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
86//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
87//% [dict enumerateKeysAnd##VALUE_NAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u, BOOL *stop) {
Brian Silverman9c614bc2016-02-15 20:20:02 -050088//% XCTAssertEqual##KSUFFIX(aKey, KEY1);
89//% XCTAssertEqual##VSUFFIX(a##VNAME$u, VAL1);
90//% XCTAssertNotEqual(stop, NULL);
91//% }];
Austin Schuh40c16522018-10-28 20:27:54 -070092//% [dict release];
Brian Silverman9c614bc2016-02-15 20:20:02 -050093//%}
94//%
95//%- (void)testBasics {
96//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3 };
97//% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3 };
Austin Schuh40c16522018-10-28 20:27:54 -070098//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
99//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME$u##s:k##VNAME$u##s
100//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
101//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500102//% XCTAssertNotNil(dict);
103//% XCTAssertEqual(dict.count, 3U);
Austin Schuh40c16522018-10-28 20:27:54 -0700104//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
105//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
106//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL3)
107//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY4)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500108//%
109//% __block NSUInteger idx = 0;
110//% KEY_TYPE KisP##*seenKeys = malloc(3 * sizeof(KEY_TYPE##KisP));
111//% VALUE_TYPE *seen##VNAME$u##s = malloc(3 * sizeof(VALUE_TYPE));
Austin Schuh40c16522018-10-28 20:27:54 -0700112//% [dict enumerateKeysAnd##VALUE_NAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u, BOOL *stop) {
Brian Silverman9c614bc2016-02-15 20:20:02 -0500113//% XCTAssertLessThan(idx, 3U);
114//% seenKeys[idx] = aKey;
115//% seen##VNAME$u##s[idx] = a##VNAME$u##;
116//% XCTAssertNotEqual(stop, NULL);
117//% ++idx;
118//% }];
119//% for (int i = 0; i < 3; ++i) {
120//% BOOL foundKey = NO;
121//% for (int j = 0; (j < 3) && !foundKey; ++j) {
122//% if (COMPARE_KEYS##KSUFFIX(kKeys[i], seenKeys[j])) {
123//% foundKey = YES;
124//% XCTAssertEqual##VSUFFIX(k##VNAME$u##s[i], seen##VNAME$u##s[j], @"i = %d, j = %d", i, j);
125//% }
126//% }
127//% XCTAssertTrue(foundKey, @"i = %d", i);
128//% }
129//% free(seenKeys);
130//% free(seen##VNAME$u##s);
131//%
132//% // Stopping the enumeration.
133//% idx = 0;
Austin Schuh40c16522018-10-28 20:27:54 -0700134//% [dict enumerateKeysAnd##VALUE_NAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u, BOOL *stop) {
Brian Silverman9c614bc2016-02-15 20:20:02 -0500135//% #pragma unused(aKey, a##VNAME$u)
136//% if (idx == 1) *stop = YES;
137//% XCTAssertNotEqual(idx, 2U);
138//% ++idx;
139//% }];
140//% [dict release];
141//%}
142//%
143//%- (void)testEquality {
144//% const KEY_TYPE KisP##kKeys1[] = { KEY1, KEY2, KEY3, KEY4 };
145//% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY1, KEY4 };
146//% const VALUE_TYPE k##VNAME$u##s1[] = { VAL1, VAL2, VAL3 };
147//% const VALUE_TYPE k##VNAME$u##s2[] = { VAL1, VAL4, VAL3 };
148//% const VALUE_TYPE k##VNAME$u##s3[] = { VAL1, VAL2, VAL3, VAL4 };
Austin Schuh40c16522018-10-28 20:27:54 -0700149//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1 =
150//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s1
151//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys1
152//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s1)];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500153//% XCTAssertNotNil(dict1);
Austin Schuh40c16522018-10-28 20:27:54 -0700154//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1prime =
155//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s1
156//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys1
157//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s1)];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500158//% XCTAssertNotNil(dict1prime);
Austin Schuh40c16522018-10-28 20:27:54 -0700159//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
160//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s2
161//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys1
162//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s2)];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500163//% XCTAssertNotNil(dict2);
Austin Schuh40c16522018-10-28 20:27:54 -0700164//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict3 =
165//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s1
166//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys2
167//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s1)];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500168//% XCTAssertNotNil(dict3);
Austin Schuh40c16522018-10-28 20:27:54 -0700169//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict4 =
170//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s3
171//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys1
172//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s3)];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500173//% XCTAssertNotNil(dict4);
174//%
175//% // 1/1Prime should be different objects, but equal.
176//% XCTAssertNotEqual(dict1, dict1prime);
177//% XCTAssertEqualObjects(dict1, dict1prime);
178//% // Equal, so they must have same hash.
179//% XCTAssertEqual([dict1 hash], [dict1prime hash]);
180//%
181//% // 2 is same keys, different ##VNAME##s; not equal.
182//% XCTAssertNotEqualObjects(dict1, dict2);
183//%
184//% // 3 is different keys, same ##VNAME##s; not equal.
185//% XCTAssertNotEqualObjects(dict1, dict3);
186//%
187//% // 4 extra pair; not equal
188//% XCTAssertNotEqualObjects(dict1, dict4);
189//%
190//% [dict1 release];
191//% [dict1prime release];
192//% [dict2 release];
193//% [dict3 release];
194//% [dict4 release];
195//%}
196//%
197//%- (void)testCopy {
198//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
199//% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
Austin Schuh40c16522018-10-28 20:27:54 -0700200//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
201//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
202//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
203//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500204//% XCTAssertNotNil(dict);
205//%
Austin Schuh40c16522018-10-28 20:27:54 -0700206//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 = [dict copy];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500207//% XCTAssertNotNil(dict2);
208//%
209//% // Should be new object but equal.
210//% XCTAssertNotEqual(dict, dict2);
211//% XCTAssertEqualObjects(dict, dict2);
212//% XCTAssertTrue([dict2 isKindOfClass:[GPB##KEY_NAME##VALUE_NAME##Dictionary class]]);
213//%
214//% [dict2 release];
215//% [dict release];
216//%}
217//%
218//%- (void)testDictionaryFromDictionary {
219//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
220//% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
Austin Schuh40c16522018-10-28 20:27:54 -0700221//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
222//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
223//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
224//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500225//% XCTAssertNotNil(dict);
226//%
Austin Schuh40c16522018-10-28 20:27:54 -0700227//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
228//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithDictionary:dict];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500229//% XCTAssertNotNil(dict2);
230//%
231//% // Should be new pointer, but equal objects.
232//% XCTAssertNotEqual(dict, dict2);
233//% XCTAssertEqualObjects(dict, dict2);
Austin Schuh40c16522018-10-28 20:27:54 -0700234//% [dict2 release];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500235//% [dict release];
236//%}
237//%
238//%- (void)testAdds {
Austin Schuh40c16522018-10-28 20:27:54 -0700239//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500240//% XCTAssertNotNil(dict);
241//%
242//% XCTAssertEqual(dict.count, 0U);
Austin Schuh40c16522018-10-28 20:27:54 -0700243//% [dict set##VALUE_NAME##:VAL1 forKey:KEY1];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500244//% XCTAssertEqual(dict.count, 1U);
245//%
246//% const KEY_TYPE KisP##kKeys[] = { KEY2, KEY3, KEY4 };
247//% const VALUE_TYPE k##VNAME$u##s[] = { VAL2, VAL3, VAL4 };
Austin Schuh40c16522018-10-28 20:27:54 -0700248//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
249//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
250//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
251//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500252//% XCTAssertNotNil(dict2);
253//% [dict add##VACCESSOR##EntriesFromDictionary:dict2];
254//% XCTAssertEqual(dict.count, 4U);
255//%
Austin Schuh40c16522018-10-28 20:27:54 -0700256//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
257//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
258//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL3)
259//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY4, VAL4)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500260//% [dict2 release];
Austin Schuh40c16522018-10-28 20:27:54 -0700261//% [dict release];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500262//%}
263//%
264//%- (void)testRemove {
265//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
266//% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
Austin Schuh40c16522018-10-28 20:27:54 -0700267//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
268//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
269//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
270//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500271//% XCTAssertNotNil(dict);
272//% XCTAssertEqual(dict.count, 4U);
273//%
Austin Schuh40c16522018-10-28 20:27:54 -0700274//% [dict remove##VALUE_NAME##ForKey:KEY2];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500275//% XCTAssertEqual(dict.count, 3U);
Austin Schuh40c16522018-10-28 20:27:54 -0700276//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
277//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
278//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL3)
279//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY4, VAL4)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500280//%
281//% // Remove again does nothing.
Austin Schuh40c16522018-10-28 20:27:54 -0700282//% [dict remove##VALUE_NAME##ForKey:KEY2];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500283//% XCTAssertEqual(dict.count, 3U);
Austin Schuh40c16522018-10-28 20:27:54 -0700284//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
285//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
286//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL3)
287//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY4, VAL4)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500288//%
Austin Schuh40c16522018-10-28 20:27:54 -0700289//% [dict remove##VALUE_NAME##ForKey:KEY4];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500290//% XCTAssertEqual(dict.count, 2U);
Austin Schuh40c16522018-10-28 20:27:54 -0700291//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
292//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
293//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL3)
294//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY4)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500295//%
296//% [dict removeAll];
297//% XCTAssertEqual(dict.count, 0U);
Austin Schuh40c16522018-10-28 20:27:54 -0700298//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY1)
299//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
300//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY3)
301//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY4)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500302//% [dict release];
303//%}
304//%
305//%- (void)testInplaceMutation {
306//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
307//% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
Austin Schuh40c16522018-10-28 20:27:54 -0700308//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
309//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
310//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
311//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500312//% XCTAssertNotNil(dict);
313//% XCTAssertEqual(dict.count, 4U);
Austin Schuh40c16522018-10-28 20:27:54 -0700314//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
315//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
316//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL3)
317//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY4, VAL4)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500318//%
Austin Schuh40c16522018-10-28 20:27:54 -0700319//% [dict set##VALUE_NAME##:VAL4 forKey:KEY1];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500320//% XCTAssertEqual(dict.count, 4U);
Austin Schuh40c16522018-10-28 20:27:54 -0700321//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL4)
322//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
323//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL3)
324//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY4, VAL4)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500325//%
Austin Schuh40c16522018-10-28 20:27:54 -0700326//% [dict set##VALUE_NAME##:VAL2 forKey:KEY4];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500327//% XCTAssertEqual(dict.count, 4U);
Austin Schuh40c16522018-10-28 20:27:54 -0700328//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL4)
329//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
330//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL3)
331//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY4, VAL2)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500332//%
333//% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY3 };
334//% const VALUE_TYPE k##VNAME$u##s2[] = { VAL3, VAL1 };
Austin Schuh40c16522018-10-28 20:27:54 -0700335//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
336//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s2
337//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys2
338//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s2)];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500339//% XCTAssertNotNil(dict2);
340//% [dict add##VACCESSOR##EntriesFromDictionary:dict2];
341//% XCTAssertEqual(dict.count, 4U);
Austin Schuh40c16522018-10-28 20:27:54 -0700342//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL4)
343//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL3)
344//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL1)
345//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY4, VAL2)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500346//%
347//% [dict2 release];
348//% [dict release];
349//%}
350//%
351//%@end
352//%
353
354//%PDDM-DEFINE TESTS_FOR_ENUM_VALUE_RAW_ADDITIONS(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4)
355//%TESTS_FOR_ENUM_VALUE_RAW_ADDITIONS2(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Enum, int32_t, , POD, 700, 801, 702, 803)
356//%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)
357//%#pragma mark - KEY_NAME -> VALUE_NAME (Unknown Enums)
358//%
359//%@interface GPB##KEY_NAME##VALUE_NAME##DictionaryUnknownEnumTests : XCTestCase
360//%@end
361//%
362//%@implementation GPB##KEY_NAME##VALUE_NAME##DictionaryUnknownEnumTests
363//%
364//%- (void)testRawBasics {
365//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3 };
366//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3 };
Austin Schuh40c16522018-10-28 20:27:54 -0700367//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
Brian Silverman9c614bc2016-02-15 20:20:02 -0500368//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
369//% KEY_NAME$S VALUE_NAME$S rawValues:kValues
370//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
371//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
372//% XCTAssertNotNil(dict);
373//% XCTAssertEqual(dict.count, 3U);
374//% XCTAssertTrue(dict.validationFunc == TestingEnum_IsValidValue); // Pointer comparison
375//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_RAW_VALUE##VHELPER(dict, value, KEY1, VAL1)
Austin Schuh40c16522018-10-28 20:27:54 -0700376//%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY2, kGPBUnrecognizedEnumeratorValue)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500377//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
378//%TEST_RAW_VALUE##VHELPER(dict, value, KEY3, VAL3)
Austin Schuh40c16522018-10-28 20:27:54 -0700379//%RAW_VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY4)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500380//%
381//% __block NSUInteger idx = 0;
382//% KEY_TYPE KisP##*seenKeys = malloc(3 * sizeof(KEY_TYPE##KisP));
383//% VALUE_TYPE *seenValues = malloc(3 * sizeof(VALUE_TYPE));
Austin Schuh40c16522018-10-28 20:27:54 -0700384//% [dict enumerateKeysAndEnumsUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
Brian Silverman9c614bc2016-02-15 20:20:02 -0500385//% XCTAssertLessThan(idx, 3U);
386//% seenKeys[idx] = aKey;
387//% seenValues[idx] = aValue;
388//% XCTAssertNotEqual(stop, NULL);
389//% ++idx;
390//% }];
391//% for (int i = 0; i < 3; ++i) {
392//% BOOL foundKey = NO;
393//% for (int j = 0; (j < 3) && !foundKey; ++j) {
394//% if (COMPARE_KEYS##KSUFFIX(kKeys[i], seenKeys[j])) {
395//% foundKey = YES;
396//% if (i == 1) {
397//% XCTAssertEqual##VSUFFIX(kGPBUnrecognizedEnumeratorValue, seenValues[j], @"i = %d, j = %d", i, j);
398//% } else {
399//% XCTAssertEqual##VSUFFIX(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
400//% }
401//% }
402//% }
403//% XCTAssertTrue(foundKey, @"i = %d", i);
404//% }
405//% idx = 0;
406//% [dict enumerateKeysAndRawValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
407//% XCTAssertLessThan(idx, 3U);
408//% seenKeys[idx] = aKey;
409//% seenValues[idx] = aValue;
410//% XCTAssertNotEqual(stop, NULL);
411//% ++idx;
412//% }];
413//% for (int i = 0; i < 3; ++i) {
414//% BOOL foundKey = NO;
415//% for (int j = 0; (j < 3) && !foundKey; ++j) {
416//% if (COMPARE_KEYS##KSUFFIX(kKeys[i], seenKeys[j])) {
417//% foundKey = YES;
418//% XCTAssertEqual##VSUFFIX(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
419//% }
420//% }
421//% XCTAssertTrue(foundKey, @"i = %d", i);
422//% }
423//% free(seenKeys);
424//% free(seenValues);
425//%
426//% // Stopping the enumeration.
427//% idx = 0;
428//% [dict enumerateKeysAndRawValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
429//% #pragma unused(aKey, aValue)
430//% if (idx == 1) *stop = YES;
431//% XCTAssertNotEqual(idx, 2U);
432//% ++idx;
433//% }];
434//% [dict release];
435//%}
436//%
437//%- (void)testEqualityWithUnknowns {
438//% const KEY_TYPE KisP##kKeys1[] = { KEY1, KEY2, KEY3, KEY4 };
439//% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY1, KEY4 };
440//% const VALUE_TYPE kValues1[] = { VAL1, VAL2, VAL3 }; // Unknown
441//% const VALUE_TYPE kValues2[] = { VAL1, VAL4, VAL3 }; // Unknown
442//% const VALUE_TYPE kValues3[] = { VAL1, VAL2, VAL3, VAL4 }; // Unknowns
Austin Schuh40c16522018-10-28 20:27:54 -0700443//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1 =
Brian Silverman9c614bc2016-02-15 20:20:02 -0500444//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
445//% KEY_NAME$S VALUE_NAME$S rawValues:kValues1
446//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
447//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues1)];
448//% XCTAssertNotNil(dict1);
Austin Schuh40c16522018-10-28 20:27:54 -0700449//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1prime =
Brian Silverman9c614bc2016-02-15 20:20:02 -0500450//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
451//% KEY_NAME$S VALUE_NAME$S rawValues:kValues1
452//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
453//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues1)];
454//% XCTAssertNotNil(dict1prime);
Austin Schuh40c16522018-10-28 20:27:54 -0700455//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
Brian Silverman9c614bc2016-02-15 20:20:02 -0500456//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
457//% KEY_NAME$S VALUE_NAME$S rawValues:kValues2
458//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
459//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues2)];
460//% XCTAssertNotNil(dict2);
Austin Schuh40c16522018-10-28 20:27:54 -0700461//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict3 =
Brian Silverman9c614bc2016-02-15 20:20:02 -0500462//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
463//% KEY_NAME$S VALUE_NAME$S rawValues:kValues1
464//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys2
465//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues1)];
466//% XCTAssertNotNil(dict3);
Austin Schuh40c16522018-10-28 20:27:54 -0700467//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict4 =
Brian Silverman9c614bc2016-02-15 20:20:02 -0500468//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
469//% KEY_NAME$S VALUE_NAME$S rawValues:kValues3
470//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
471//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues3)];
472//% XCTAssertNotNil(dict4);
473//%
474//% // 1/1Prime should be different objects, but equal.
475//% XCTAssertNotEqual(dict1, dict1prime);
476//% XCTAssertEqualObjects(dict1, dict1prime);
477//% // Equal, so they must have same hash.
478//% XCTAssertEqual([dict1 hash], [dict1prime hash]);
479//%
480//% // 2 is same keys, different values; not equal.
481//% XCTAssertNotEqualObjects(dict1, dict2);
482//%
483//% // 3 is different keys, same values; not equal.
484//% XCTAssertNotEqualObjects(dict1, dict3);
485//%
486//% // 4 extra pair; not equal
487//% XCTAssertNotEqualObjects(dict1, dict4);
488//%
489//% [dict1 release];
490//% [dict1prime release];
491//% [dict2 release];
492//% [dict3 release];
493//% [dict4 release];
494//%}
495//%
496//%- (void)testCopyWithUnknowns {
497//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
498//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 }; // Unknown
Austin Schuh40c16522018-10-28 20:27:54 -0700499//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
Brian Silverman9c614bc2016-02-15 20:20:02 -0500500//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
501//% KEY_NAME$S VALUE_NAME$S rawValues:kValues
502//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
503//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
504//% XCTAssertNotNil(dict);
505//%
Austin Schuh40c16522018-10-28 20:27:54 -0700506//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 = [dict copy];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500507//% XCTAssertNotNil(dict2);
508//%
509//% // Should be new pointer, but equal objects.
510//% XCTAssertNotEqual(dict, dict2);
511//% XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
512//% XCTAssertEqualObjects(dict, dict2);
513//%
514//% [dict2 release];
515//% [dict release];
516//%}
517//%
518//%- (void)testDictionaryFromDictionary {
519//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
520//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 }; // Unknowns
Austin Schuh40c16522018-10-28 20:27:54 -0700521//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
Brian Silverman9c614bc2016-02-15 20:20:02 -0500522//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
523//% KEY_NAME$S VALUE_NAME$S rawValues:kValues
524//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
525//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
526//% XCTAssertNotNil(dict);
527//%
Austin Schuh40c16522018-10-28 20:27:54 -0700528//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
529//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithDictionary:dict];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500530//% XCTAssertNotNil(dict2);
531//%
532//% // Should be new pointer, but equal objects.
533//% XCTAssertNotEqual(dict, dict2);
534//% XCTAssertEqualObjects(dict, dict2);
535//% XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
Austin Schuh40c16522018-10-28 20:27:54 -0700536//% [dict2 release];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500537//% [dict release];
538//%}
539//%
540//%- (void)testUnknownAdds {
Austin Schuh40c16522018-10-28 20:27:54 -0700541//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
542//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500543//% XCTAssertNotNil(dict);
544//%
545//% XCTAssertEqual(dict.count, 0U);
Austin Schuh40c16522018-10-28 20:27:54 -0700546//% XCTAssertThrowsSpecificNamed([dict setEnum:VAL2 forKey:KEY2], // Unknown
Brian Silverman9c614bc2016-02-15 20:20:02 -0500547//% NSException, NSInvalidArgumentException);
548//% XCTAssertEqual(dict.count, 0U);
549//% [dict setRawValue:VAL2 forKey:KEY2]; // Unknown
550//% XCTAssertEqual(dict.count, 1U);
551//%
552//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY3, KEY4 };
553//% const VALUE_TYPE kValues[] = { VAL1, VAL3, VAL4 }; // Unknown
Austin Schuh40c16522018-10-28 20:27:54 -0700554//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
555//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithEnums:kValues
556//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
557//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500558//% XCTAssertNotNil(dict2);
559//% [dict addRawEntriesFromDictionary:dict2];
560//% XCTAssertEqual(dict.count, 4U);
561//%
Austin Schuh40c16522018-10-28 20:27:54 -0700562//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY1, VAL1)
563//%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY2, kGPBUnrecognizedEnumeratorValue)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500564//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
Austin Schuh40c16522018-10-28 20:27:54 -0700565//%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY3, VAL3)
566//%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY4, kGPBUnrecognizedEnumeratorValue)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500567//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
568//% [dict2 release];
Austin Schuh40c16522018-10-28 20:27:54 -0700569//% [dict release];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500570//%}
571//%
572//%- (void)testUnknownRemove {
573//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
574//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 }; // Unknowns
Austin Schuh40c16522018-10-28 20:27:54 -0700575//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
Brian Silverman9c614bc2016-02-15 20:20:02 -0500576//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
577//% KEY_NAME$S VALUE_NAME$S rawValues:kValues
578//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
579//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
580//% XCTAssertNotNil(dict);
581//% XCTAssertEqual(dict.count, 4U);
582//%
Austin Schuh40c16522018-10-28 20:27:54 -0700583//% [dict removeEnumForKey:KEY2];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500584//% XCTAssertEqual(dict.count, 3U);
Austin Schuh40c16522018-10-28 20:27:54 -0700585//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY1, VAL1)
586//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
587//%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY3, VAL3)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500588//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
589//%
590//% // Remove again does nothing.
Austin Schuh40c16522018-10-28 20:27:54 -0700591//% [dict removeEnumForKey:KEY2];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500592//% XCTAssertEqual(dict.count, 3U);
Austin Schuh40c16522018-10-28 20:27:54 -0700593//%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY1, VAL1)
594//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
595//%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY3, VAL3)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500596//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
597//%
Austin Schuh40c16522018-10-28 20:27:54 -0700598//% [dict removeEnumForKey:KEY4];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500599//% XCTAssertEqual(dict.count, 2U);
Austin Schuh40c16522018-10-28 20:27:54 -0700600//%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY1, VAL1)
601//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
602//%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY3, VAL3)
603//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY4)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500604//%
605//% [dict removeAll];
606//% XCTAssertEqual(dict.count, 0U);
Austin Schuh40c16522018-10-28 20:27:54 -0700607//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY1)
608//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
609//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY3)
610//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY4)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500611//% [dict release];
612//%}
613//%
614//%- (void)testInplaceMutationUnknowns {
615//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
616//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 }; // Unknowns
Austin Schuh40c16522018-10-28 20:27:54 -0700617//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
Brian Silverman9c614bc2016-02-15 20:20:02 -0500618//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
619//% KEY_NAME$S VALUE_NAME$S rawValues:kValues
620//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
621//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
622//% XCTAssertNotNil(dict);
623//% XCTAssertEqual(dict.count, 4U);
Austin Schuh40c16522018-10-28 20:27:54 -0700624//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY1, VAL1)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500625//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
Austin Schuh40c16522018-10-28 20:27:54 -0700626//%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY3, VAL3)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500627//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
628//%
Austin Schuh40c16522018-10-28 20:27:54 -0700629//% XCTAssertThrowsSpecificNamed([dict setEnum:VAL4 forKey:KEY1], // Unknown
Brian Silverman9c614bc2016-02-15 20:20:02 -0500630//% NSException, NSInvalidArgumentException);
631//% XCTAssertEqual(dict.count, 4U);
Austin Schuh40c16522018-10-28 20:27:54 -0700632//%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY1, VAL1)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500633//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
Austin Schuh40c16522018-10-28 20:27:54 -0700634//%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY3, VAL3)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500635//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
636//%
637//% [dict setRawValue:VAL4 forKey:KEY1]; // Unknown
638//% XCTAssertEqual(dict.count, 4U);
639//%TEST_RAW_VALUE##VHELPER(dict, value, KEY1, VAL4)
640//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
Austin Schuh40c16522018-10-28 20:27:54 -0700641//%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY3, VAL3)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500642//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
643//%
644//% [dict setRawValue:VAL1 forKey:KEY4];
645//% XCTAssertEqual(dict.count, 4U);
646//%TEST_RAW_VALUE##VHELPER(dict, value, KEY1, VAL4)
647//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
Austin Schuh40c16522018-10-28 20:27:54 -0700648//%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY3, VAL3)
649//%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY4, VAL1)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500650//%
651//% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY3 };
652//% const VALUE_TYPE kValues2[] = { VAL3, VAL2 }; // Unknown
Austin Schuh40c16522018-10-28 20:27:54 -0700653//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
Brian Silverman9c614bc2016-02-15 20:20:02 -0500654//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
655//% KEY_NAME$S VALUE_NAME$S rawValues:kValues2
656//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys2
657//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues2)];
658//% XCTAssertNotNil(dict2);
659//% [dict addRawEntriesFromDictionary:dict2];
660//% XCTAssertEqual(dict.count, 4U);
661//%TEST_RAW_VALUE##VHELPER(dict, value, KEY1, VAL4)
Austin Schuh40c16522018-10-28 20:27:54 -0700662//%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY2, VAL3)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500663//%TEST_RAW_VALUE##VHELPER(dict, value, KEY3, VAL2)
Austin Schuh40c16522018-10-28 20:27:54 -0700664//%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY4, VAL1)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500665//%
666//% [dict2 release];
667//% [dict release];
668//%}
669//%
670//%- (void)testCopyUnknowns {
671//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
672//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
Austin Schuh40c16522018-10-28 20:27:54 -0700673//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
Brian Silverman9c614bc2016-02-15 20:20:02 -0500674//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
675//% KEY_NAME$S VALUE_NAME$S rawValues:kValues
676//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
677//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
678//% XCTAssertNotNil(dict);
679//%
Austin Schuh40c16522018-10-28 20:27:54 -0700680//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 = [dict copy];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500681//% XCTAssertNotNil(dict2);
682//%
683//% // Should be new pointer, but equal objects.
684//% XCTAssertNotEqual(dict, dict2);
685//% XCTAssertEqualObjects(dict, dict2);
686//% XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
687//% XCTAssertTrue([dict2 isKindOfClass:[GPB##KEY_NAME##VALUE_NAME##Dictionary class]]);
688//%
689//% [dict2 release];
690//% [dict release];
691//%}
692//%
693//%@end
694//%
695
696//
697// Helpers for PODs
698//
699
700//%PDDM-DEFINE DECLARE_VALUE_STORAGEPOD(VALUE_TYPE, NAME)
701//% VALUE_TYPE NAME;
702//%
Austin Schuh40c16522018-10-28 20:27:54 -0700703//%PDDM-DEFINE VALUE_NOT_FOUNDPOD(VALUE_NAME, DICT, KEY)
704//% XCTAssertFalse([DICT get##VALUE_NAME##:NULL forKey:KEY]);
705//%PDDM-DEFINE TEST_VALUEPOD(VALUE_NAME, DICT, STORAGE, KEY, VALUE)
706//% XCTAssertTrue([DICT get##VALUE_NAME##:NULL forKey:KEY]);
707//% XCTAssertTrue([DICT get##VALUE_NAME##:&STORAGE forKey:KEY]);
Brian Silverman9c614bc2016-02-15 20:20:02 -0500708//% XCTAssertEqual(STORAGE, VALUE);
709//%PDDM-DEFINE COMPARE_KEYS(KEY1, KEY2)
710//%KEY1 == KEY2
Austin Schuh40c16522018-10-28 20:27:54 -0700711//%PDDM-DEFINE RAW_VALUE_NOT_FOUNDPOD(VALUE_NAME, DICT, KEY)
712//% XCTAssertFalse([DICT getRawValue:NULL forKey:KEY]);
Brian Silverman9c614bc2016-02-15 20:20:02 -0500713//%PDDM-DEFINE TEST_RAW_VALUEPOD(DICT, STORAGE, KEY, VALUE)
Austin Schuh40c16522018-10-28 20:27:54 -0700714//% XCTAssertTrue([DICT getRawValue:NULL forKey:KEY]);
715//% XCTAssertTrue([DICT getRawValue:&STORAGE forKey:KEY]);
Brian Silverman9c614bc2016-02-15 20:20:02 -0500716//% XCTAssertEqual(STORAGE, VALUE);
717
718//
719// Helpers for Objects
720//
721
722//%PDDM-DEFINE DECLARE_VALUE_STORAGEOBJECT(VALUE_TYPE, NAME)
723// Empty
Austin Schuh40c16522018-10-28 20:27:54 -0700724//%PDDM-DEFINE VALUE_NOT_FOUNDOBJECT(VALUE_NAME, DICT, KEY)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500725//% XCTAssertNil([DICT objectForKey:KEY]);
Austin Schuh40c16522018-10-28 20:27:54 -0700726//%PDDM-DEFINE TEST_VALUEOBJECT(VALUE_NAME, DICT, STORAGE, KEY, VALUE)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500727//% XCTAssertEqualObjects([DICT objectForKey:KEY], VALUE);
728//%PDDM-DEFINE COMPARE_KEYSObjects(KEY1, KEY2)
729//%[KEY1 isEqual:KEY2]
730
731//
732// Helpers for tests.
733//
734
735//%PDDM-DEFINE TEST_HELPERS(KEY_NAME, KEY_TYPE, KisP)
736//%// To let the testing macros work, add some extra methods to simplify things.
737//%@interface GPB##KEY_NAME##EnumDictionary (TestingTweak)
Austin Schuh40c16522018-10-28 20:27:54 -0700738//%- (instancetype)initWithEnums:(const int32_t [])values
739//% forKeys:(const KEY_TYPE##KisP$S##KisP [])keys
740//% count:(NSUInteger)count;
Brian Silverman9c614bc2016-02-15 20:20:02 -0500741//%@end
742//%
743//%static BOOL TestingEnum_IsValidValue(int32_t value) {
744//% switch (value) {
745//% case 700:
746//% case 701:
747//% case 702:
748//% case 703:
749//% return YES;
750//% default:
751//% return NO;
752//% }
753//%}
754//%
755//%@implementation GPB##KEY_NAME##EnumDictionary (TestingTweak)
Austin Schuh40c16522018-10-28 20:27:54 -0700756//%- (instancetype)initWithEnums:(const int32_t [])values
757//% forKeys:(const KEY_TYPE##KisP$S##KisP [])keys
758//% count:(NSUInteger)count {
Brian Silverman9c614bc2016-02-15 20:20:02 -0500759//% return [self initWithValidationFunction:TestingEnum_IsValidValue
760//% rawValues:values
761//% forKeys:keys
762//% count:count];
763//%}
764//%@end
765//%
766//%
767
768
769//
770// BOOL test macros
771//
772//TODO(thomasvl): enum tests
773
774//%PDDM-DEFINE BOOL_TESTS_FOR_POD_VALUE(VALUE_NAME, VALUE_TYPE, VAL1, VAL2)
775//%BOOL_TESTS_COMMON(Bool, BOOL, , , YES, NO, VALUE_NAME, VALUE_TYPE, , value, POD, VAL1, VAL2)
776
777//%PDDM-DEFINE TESTS_FOR_BOOL_KEY_OBJECT_VALUE(VALUE_NAME, VALUE_TYPE, VAL1, VAL2)
778//%BOOL_TESTS_COMMON(Bool, BOOL, , , YES, NO, VALUE_NAME, VALUE_TYPE, Objects, object, OBJECT, VAL1, VAL2)
779
780//%PDDM-DEFINE BOOL_TESTS_COMMON(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, VALUE_NAME, VALUE_TYPE, VSUFFIX, VNAME, VHELPER, VAL1, VAL2)
781//%#pragma mark - KEY_NAME -> VALUE_NAME
782//%
783//%@interface GPB##KEY_NAME##VALUE_NAME##DictionaryTests : XCTestCase
784//%@end
785//%
786//%@implementation GPB##KEY_NAME##VALUE_NAME##DictionaryTests
787//%
788//%- (void)testEmpty {
Austin Schuh40c16522018-10-28 20:27:54 -0700789//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500790//% XCTAssertNotNil(dict);
791//% XCTAssertEqual(dict.count, 0U);
Austin Schuh40c16522018-10-28 20:27:54 -0700792//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY1)
793//% [dict enumerateKeysAnd##VALUE_NAME##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u##, BOOL *stop) {
Brian Silverman9c614bc2016-02-15 20:20:02 -0500794//% #pragma unused(aKey, a##VNAME$u##, stop)
795//% XCTFail(@"Shouldn't get here!");
796//% }];
797//% [dict release];
798//%}
799//%
800//%- (void)testOne {
Austin Schuh40c16522018-10-28 20:27:54 -0700801//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
802//% [dict set##VALUE_NAME$u##:VAL1 forKey:KEY1];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500803//% XCTAssertNotNil(dict);
804//% XCTAssertEqual(dict.count, 1U);
Austin Schuh40c16522018-10-28 20:27:54 -0700805//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
806//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
807//% [dict enumerateKeysAnd##VALUE_NAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u, BOOL *stop) {
Brian Silverman9c614bc2016-02-15 20:20:02 -0500808//% XCTAssertEqual##KSUFFIX(aKey, KEY1);
809//% XCTAssertEqual##VSUFFIX(a##VNAME$u, VAL1);
810//% XCTAssertNotEqual(stop, NULL);
811//% }];
Austin Schuh40c16522018-10-28 20:27:54 -0700812//% [dict release];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500813//%}
814//%
815//%- (void)testBasics {
816//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
817//% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
Austin Schuh40c16522018-10-28 20:27:54 -0700818//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
819//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
820//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
821//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500822//% XCTAssertNotNil(dict);
823//% XCTAssertEqual(dict.count, 2U);
Austin Schuh40c16522018-10-28 20:27:54 -0700824//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
825//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500826//%
827//% __block NSUInteger idx = 0;
828//% KEY_TYPE KisP##*seenKeys = malloc(2 * sizeof(KEY_TYPE##KisP));
829//% VALUE_TYPE *seen##VNAME$u##s = malloc(2 * sizeof(VALUE_TYPE));
Austin Schuh40c16522018-10-28 20:27:54 -0700830//% [dict enumerateKeysAnd##VALUE_NAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u##, BOOL *stop) {
Brian Silverman9c614bc2016-02-15 20:20:02 -0500831//% XCTAssertLessThan(idx, 2U);
832//% seenKeys[idx] = aKey;
833//% seen##VNAME$u##s[idx] = a##VNAME$u;
834//% XCTAssertNotEqual(stop, NULL);
835//% ++idx;
836//% }];
837//% for (int i = 0; i < 2; ++i) {
838//% BOOL foundKey = NO;
839//% for (int j = 0; (j < 2) && !foundKey; ++j) {
840//% if (COMPARE_KEYS##KSUFFIX(kKeys[i], seenKeys[j])) {
841//% foundKey = YES;
842//% XCTAssertEqual##VSUFFIX(k##VNAME$u##s[i], seen##VNAME$u##s[j], @"i = %d, j = %d", i, j);
843//% }
844//% }
845//% XCTAssertTrue(foundKey, @"i = %d", i);
846//% }
847//% free(seenKeys);
848//% free(seen##VNAME$u##s);
849//%
850//% // Stopping the enumeration.
851//% idx = 0;
Austin Schuh40c16522018-10-28 20:27:54 -0700852//% [dict enumerateKeysAnd##VALUE_NAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u##, BOOL *stop) {
Brian Silverman9c614bc2016-02-15 20:20:02 -0500853//% #pragma unused(aKey, a##VNAME$u)
854//% if (idx == 0) *stop = YES;
855//% XCTAssertNotEqual(idx, 2U);
856//% ++idx;
857//% }];
858//% [dict release];
859//%}
860//%
861//%- (void)testEquality {
862//% const KEY_TYPE KisP##kKeys1[] = { KEY1, KEY2 };
863//% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY1 };
864//% const VALUE_TYPE k##VNAME$u##s1[] = { VAL1, VAL2 };
865//% const VALUE_TYPE k##VNAME$u##s2[] = { VAL2, VAL1 };
866//% const VALUE_TYPE k##VNAME$u##s3[] = { VAL2 };
Austin Schuh40c16522018-10-28 20:27:54 -0700867//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1 =
868//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s1
869//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys1
870//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s1)];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500871//% XCTAssertNotNil(dict1);
Austin Schuh40c16522018-10-28 20:27:54 -0700872//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1prime =
873//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s1
874//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys1
875//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s1)];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500876//% XCTAssertNotNil(dict1prime);
Austin Schuh40c16522018-10-28 20:27:54 -0700877//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
878//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s2
879//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys1
880//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s2)];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500881//% XCTAssertNotNil(dict2);
Austin Schuh40c16522018-10-28 20:27:54 -0700882//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict3 =
883//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s1
884//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys2
885//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s1)];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500886//% XCTAssertNotNil(dict3);
Austin Schuh40c16522018-10-28 20:27:54 -0700887//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict4 =
888//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s3
889//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys1
890//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s3)];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500891//% XCTAssertNotNil(dict4);
892//%
893//% // 1/1Prime should be different objects, but equal.
894//% XCTAssertNotEqual(dict1, dict1prime);
895//% XCTAssertEqualObjects(dict1, dict1prime);
896//% // Equal, so they must have same hash.
897//% XCTAssertEqual([dict1 hash], [dict1prime hash]);
898//%
899//% // 2 is same keys, different ##VNAME##s; not equal.
900//% XCTAssertNotEqualObjects(dict1, dict2);
901//%
902//% // 3 is different keys, same ##VNAME##s; not equal.
903//% XCTAssertNotEqualObjects(dict1, dict3);
904//%
905//% // 4 Fewer pairs; not equal
906//% XCTAssertNotEqualObjects(dict1, dict4);
907//%
908//% [dict1 release];
909//% [dict1prime release];
910//% [dict2 release];
911//% [dict3 release];
912//% [dict4 release];
913//%}
914//%
915//%- (void)testCopy {
916//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
917//% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
Austin Schuh40c16522018-10-28 20:27:54 -0700918//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
919//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
920//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
921//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500922//% XCTAssertNotNil(dict);
923//%
Austin Schuh40c16522018-10-28 20:27:54 -0700924//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 = [dict copy];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500925//% XCTAssertNotNil(dict2);
926//%
927//% // Should be new object but equal.
928//% XCTAssertNotEqual(dict, dict2);
929//% XCTAssertEqualObjects(dict, dict2);
930//% XCTAssertTrue([dict2 isKindOfClass:[GPB##KEY_NAME##VALUE_NAME##Dictionary class]]);
931//%
932//% [dict2 release];
933//% [dict release];
934//%}
935//%
936//%- (void)testDictionaryFromDictionary {
937//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
938//% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
Austin Schuh40c16522018-10-28 20:27:54 -0700939//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
940//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
941//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
942//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500943//% XCTAssertNotNil(dict);
944//%
Austin Schuh40c16522018-10-28 20:27:54 -0700945//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
946//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithDictionary:dict];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500947//% XCTAssertNotNil(dict2);
948//%
949//% // Should be new pointer, but equal objects.
950//% XCTAssertNotEqual(dict, dict2);
951//% XCTAssertEqualObjects(dict, dict2);
Austin Schuh40c16522018-10-28 20:27:54 -0700952//% [dict2 release];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500953//% [dict release];
954//%}
955//%
956//%- (void)testAdds {
Austin Schuh40c16522018-10-28 20:27:54 -0700957//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500958//% XCTAssertNotNil(dict);
959//%
960//% XCTAssertEqual(dict.count, 0U);
Austin Schuh40c16522018-10-28 20:27:54 -0700961//% [dict set##VALUE_NAME:VAL1 forKey:KEY1];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500962//% XCTAssertEqual(dict.count, 1U);
963//%
964//% const KEY_TYPE KisP##kKeys[] = { KEY2 };
965//% const VALUE_TYPE k##VNAME$u##s[] = { VAL2 };
Austin Schuh40c16522018-10-28 20:27:54 -0700966//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
967//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
968//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
969//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500970//% XCTAssertNotNil(dict2);
971//% [dict addEntriesFromDictionary:dict2];
972//% XCTAssertEqual(dict.count, 2U);
973//%
Austin Schuh40c16522018-10-28 20:27:54 -0700974//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
975//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500976//% [dict2 release];
Austin Schuh40c16522018-10-28 20:27:54 -0700977//% [dict release];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500978//%}
979//%
980//%- (void)testRemove {
981//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2};
982//% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
Austin Schuh40c16522018-10-28 20:27:54 -0700983//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
984//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
985//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
986//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500987//% XCTAssertNotNil(dict);
988//% XCTAssertEqual(dict.count, 2U);
989//%
Austin Schuh40c16522018-10-28 20:27:54 -0700990//% [dict remove##VALUE_NAME##ForKey:KEY2];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500991//% XCTAssertEqual(dict.count, 1U);
Austin Schuh40c16522018-10-28 20:27:54 -0700992//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
993//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
Brian Silverman9c614bc2016-02-15 20:20:02 -0500994//%
995//% // Remove again does nothing.
Austin Schuh40c16522018-10-28 20:27:54 -0700996//% [dict remove##VALUE_NAME##ForKey:KEY2];
Brian Silverman9c614bc2016-02-15 20:20:02 -0500997//% XCTAssertEqual(dict.count, 1U);
Austin Schuh40c16522018-10-28 20:27:54 -0700998//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
999//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
Brian Silverman9c614bc2016-02-15 20:20:02 -05001000//%
1001//% [dict removeAll];
1002//% XCTAssertEqual(dict.count, 0U);
Austin Schuh40c16522018-10-28 20:27:54 -07001003//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY1)
1004//%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
Brian Silverman9c614bc2016-02-15 20:20:02 -05001005//% [dict release];
1006//%}
1007//%
1008//%- (void)testInplaceMutation {
1009//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
1010//% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
Austin Schuh40c16522018-10-28 20:27:54 -07001011//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
1012//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
1013//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
1014//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
Brian Silverman9c614bc2016-02-15 20:20:02 -05001015//% XCTAssertNotNil(dict);
1016//% XCTAssertEqual(dict.count, 2U);
Austin Schuh40c16522018-10-28 20:27:54 -07001017//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
1018//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
Brian Silverman9c614bc2016-02-15 20:20:02 -05001019//%
Austin Schuh40c16522018-10-28 20:27:54 -07001020//% [dict set##VALUE_NAME##:VAL2 forKey:KEY1];
Brian Silverman9c614bc2016-02-15 20:20:02 -05001021//% XCTAssertEqual(dict.count, 2U);
Austin Schuh40c16522018-10-28 20:27:54 -07001022//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL2)
1023//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
Brian Silverman9c614bc2016-02-15 20:20:02 -05001024//%
Austin Schuh40c16522018-10-28 20:27:54 -07001025//% [dict set##VALUE_NAME##:VAL1 forKey:KEY2];
Brian Silverman9c614bc2016-02-15 20:20:02 -05001026//% XCTAssertEqual(dict.count, 2U);
Austin Schuh40c16522018-10-28 20:27:54 -07001027//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL2)
1028//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL1)
Brian Silverman9c614bc2016-02-15 20:20:02 -05001029//%
1030//% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY1 };
1031//% const VALUE_TYPE k##VNAME$u##s2[] = { VAL2, VAL1 };
Austin Schuh40c16522018-10-28 20:27:54 -07001032//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
1033//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s2
1034//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys2
1035//% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s2)];
Brian Silverman9c614bc2016-02-15 20:20:02 -05001036//% XCTAssertNotNil(dict2);
1037//% [dict addEntriesFromDictionary:dict2];
1038//% XCTAssertEqual(dict.count, 2U);
Austin Schuh40c16522018-10-28 20:27:54 -07001039//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
1040//%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
Brian Silverman9c614bc2016-02-15 20:20:02 -05001041//%
1042//% [dict2 release];
1043//% [dict release];
1044//%}
1045//%
1046//%@end
1047//%
1048