blob: ada93c643fa6598ebe4ae67ca7f87a85d5bed3a4 [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)
33//%TESTS_FOR_POD_KEY_OBJECT_VALUE(KEY_NAME, KEY_TYPE, KEY1, KEY2, KEY3, KEY4, Object, id, @"abc", @"def", @"ghi", @"jkl")
34
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
53//%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)
54//%#pragma mark - KEY_NAME -> VALUE_NAME
55//%
56//%@interface GPB##KEY_NAME##VALUE_NAME##DictionaryTests : XCTestCase
57//%@end
58//%
59//%@implementation GPB##KEY_NAME##VALUE_NAME##DictionaryTests
60//%
61//%- (void)testEmpty {
62//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
63//% XCTAssertNotNil(dict);
64//% XCTAssertEqual(dict.count, 0U);
65//%VALUE_NOT_FOUND##VHELPER(dict, KEY1)
66//% [dict enumerateKeysAnd##VNAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u, BOOL *stop) {
67//% #pragma unused(aKey, a##VNAME$u, stop)
68//% XCTFail(@"Shouldn't get here!");
69//% }];
70//% [dict release];
71//%}
72//%
73//%- (void)testOne {
74//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWith##VNAME$u##:VAL1 forKey:KEY1];
75//% XCTAssertNotNil(dict);
76//% XCTAssertEqual(dict.count, 1U);
77//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
78//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
79//% [dict enumerateKeysAnd##VNAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u, BOOL *stop) {
80//% XCTAssertEqual##KSUFFIX(aKey, KEY1);
81//% XCTAssertEqual##VSUFFIX(a##VNAME$u, VAL1);
82//% XCTAssertNotEqual(stop, NULL);
83//% }];
84//%}
85//%
86//%- (void)testBasics {
87//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3 };
88//% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3 };
89//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
90//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
91//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## forKeys:kKeys
92//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
93//% XCTAssertNotNil(dict);
94//% XCTAssertEqual(dict.count, 3U);
95//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
96//%TEST_VALUE##VHELPER(dict, VNAME, KEY2, VAL2)
97//%TEST_VALUE##VHELPER(dict, VNAME, KEY3, VAL3)
98//%VALUE_NOT_FOUND##VHELPER(dict, KEY4)
99//%
100//% __block NSUInteger idx = 0;
101//% KEY_TYPE KisP##*seenKeys = malloc(3 * sizeof(KEY_TYPE##KisP));
102//% VALUE_TYPE *seen##VNAME$u##s = malloc(3 * sizeof(VALUE_TYPE));
103//% [dict enumerateKeysAnd##VNAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u, BOOL *stop) {
104//% XCTAssertLessThan(idx, 3U);
105//% seenKeys[idx] = aKey;
106//% seen##VNAME$u##s[idx] = a##VNAME$u##;
107//% XCTAssertNotEqual(stop, NULL);
108//% ++idx;
109//% }];
110//% for (int i = 0; i < 3; ++i) {
111//% BOOL foundKey = NO;
112//% for (int j = 0; (j < 3) && !foundKey; ++j) {
113//% if (COMPARE_KEYS##KSUFFIX(kKeys[i], seenKeys[j])) {
114//% foundKey = YES;
115//% XCTAssertEqual##VSUFFIX(k##VNAME$u##s[i], seen##VNAME$u##s[j], @"i = %d, j = %d", i, j);
116//% }
117//% }
118//% XCTAssertTrue(foundKey, @"i = %d", i);
119//% }
120//% free(seenKeys);
121//% free(seen##VNAME$u##s);
122//%
123//% // Stopping the enumeration.
124//% idx = 0;
125//% [dict enumerateKeysAnd##VNAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u, BOOL *stop) {
126//% #pragma unused(aKey, a##VNAME$u)
127//% if (idx == 1) *stop = YES;
128//% XCTAssertNotEqual(idx, 2U);
129//% ++idx;
130//% }];
131//% [dict release];
132//%}
133//%
134//%- (void)testEquality {
135//% const KEY_TYPE KisP##kKeys1[] = { KEY1, KEY2, KEY3, KEY4 };
136//% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY1, KEY4 };
137//% const VALUE_TYPE k##VNAME$u##s1[] = { VAL1, VAL2, VAL3 };
138//% const VALUE_TYPE k##VNAME$u##s2[] = { VAL1, VAL4, VAL3 };
139//% const VALUE_TYPE k##VNAME$u##s3[] = { VAL1, VAL2, VAL3, VAL4 };
140//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict1 =
141//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s1
142//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## forKeys:kKeys1
143//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## count:GPBARRAYSIZE(k##VNAME$u##s1)];
144//% XCTAssertNotNil(dict1);
145//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict1prime =
146//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s1
147//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## forKeys:kKeys1
148//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## count:GPBARRAYSIZE(k##VNAME$u##s1)];
149//% XCTAssertNotNil(dict1prime);
150//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
151//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s2
152//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## forKeys:kKeys1
153//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## count:GPBARRAYSIZE(k##VNAME$u##s2)];
154//% XCTAssertNotNil(dict2);
155//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict3 =
156//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s1
157//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## forKeys:kKeys2
158//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## count:GPBARRAYSIZE(k##VNAME$u##s1)];
159//% XCTAssertNotNil(dict3);
160//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict4 =
161//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s3
162//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## forKeys:kKeys1
163//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## count:GPBARRAYSIZE(k##VNAME$u##s3)];
164//% XCTAssertNotNil(dict4);
165//%
166//% // 1/1Prime should be different objects, but equal.
167//% XCTAssertNotEqual(dict1, dict1prime);
168//% XCTAssertEqualObjects(dict1, dict1prime);
169//% // Equal, so they must have same hash.
170//% XCTAssertEqual([dict1 hash], [dict1prime hash]);
171//%
172//% // 2 is same keys, different ##VNAME##s; not equal.
173//% XCTAssertNotEqualObjects(dict1, dict2);
174//%
175//% // 3 is different keys, same ##VNAME##s; not equal.
176//% XCTAssertNotEqualObjects(dict1, dict3);
177//%
178//% // 4 extra pair; not equal
179//% XCTAssertNotEqualObjects(dict1, dict4);
180//%
181//% [dict1 release];
182//% [dict1prime release];
183//% [dict2 release];
184//% [dict3 release];
185//% [dict4 release];
186//%}
187//%
188//%- (void)testCopy {
189//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
190//% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
191//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
192//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
193//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## forKeys:kKeys
194//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
195//% XCTAssertNotNil(dict);
196//%
197//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 = [dict copy];
198//% XCTAssertNotNil(dict2);
199//%
200//% // Should be new object but equal.
201//% XCTAssertNotEqual(dict, dict2);
202//% XCTAssertEqualObjects(dict, dict2);
203//% XCTAssertTrue([dict2 isKindOfClass:[GPB##KEY_NAME##VALUE_NAME##Dictionary class]]);
204//%
205//% [dict2 release];
206//% [dict release];
207//%}
208//%
209//%- (void)testDictionaryFromDictionary {
210//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
211//% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
212//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
213//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
214//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## forKeys:kKeys
215//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
216//% XCTAssertNotNil(dict);
217//%
218//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
219//% [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithDictionary:dict];
220//% XCTAssertNotNil(dict2);
221//%
222//% // Should be new pointer, but equal objects.
223//% XCTAssertNotEqual(dict, dict2);
224//% XCTAssertEqualObjects(dict, dict2);
225//% [dict release];
226//%}
227//%
228//%- (void)testAdds {
229//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionary];
230//% XCTAssertNotNil(dict);
231//%
232//% XCTAssertEqual(dict.count, 0U);
233//% [dict set##VNAME$u##:VAL1 forKey:KEY1];
234//% XCTAssertEqual(dict.count, 1U);
235//%
236//% const KEY_TYPE KisP##kKeys[] = { KEY2, KEY3, KEY4 };
237//% const VALUE_TYPE k##VNAME$u##s[] = { VAL2, VAL3, VAL4 };
238//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
239//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
240//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## forKeys:kKeys
241//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
242//% XCTAssertNotNil(dict2);
243//% [dict add##VACCESSOR##EntriesFromDictionary:dict2];
244//% XCTAssertEqual(dict.count, 4U);
245//%
246//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
247//%TEST_VALUE##VHELPER(dict, VNAME, KEY2, VAL2)
248//%TEST_VALUE##VHELPER(dict, VNAME, KEY3, VAL3)
249//%TEST_VALUE##VHELPER(dict, VNAME, KEY4, VAL4)
250//% [dict2 release];
251//%}
252//%
253//%- (void)testRemove {
254//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
255//% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
256//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
257//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
258//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## forKeys:kKeys
259//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
260//% XCTAssertNotNil(dict);
261//% XCTAssertEqual(dict.count, 4U);
262//%
263//% [dict remove##VNAME$u##ForKey:KEY2];
264//% XCTAssertEqual(dict.count, 3U);
265//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
266//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
267//%TEST_VALUE##VHELPER(dict, VNAME, KEY3, VAL3)
268//%TEST_VALUE##VHELPER(dict, VNAME, KEY4, VAL4)
269//%
270//% // Remove again does nothing.
271//% [dict remove##VNAME$u##ForKey:KEY2];
272//% XCTAssertEqual(dict.count, 3U);
273//%TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
274//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
275//%TEST_VALUE##VHELPER(dict, VNAME, KEY3, VAL3)
276//%TEST_VALUE##VHELPER(dict, VNAME, KEY4, VAL4)
277//%
278//% [dict remove##VNAME$u##ForKey:KEY4];
279//% XCTAssertEqual(dict.count, 2U);
280//%TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
281//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
282//%TEST_VALUE##VHELPER(dict, VNAME, KEY3, VAL3)
283//%VALUE_NOT_FOUND##VHELPER(dict, KEY4)
284//%
285//% [dict removeAll];
286//% XCTAssertEqual(dict.count, 0U);
287//%VALUE_NOT_FOUND##VHELPER(dict, KEY1)
288//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
289//%VALUE_NOT_FOUND##VHELPER(dict, KEY3)
290//%VALUE_NOT_FOUND##VHELPER(dict, KEY4)
291//% [dict release];
292//%}
293//%
294//%- (void)testInplaceMutation {
295//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
296//% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
297//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
298//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
299//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## forKeys:kKeys
300//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
301//% XCTAssertNotNil(dict);
302//% XCTAssertEqual(dict.count, 4U);
303//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
304//%TEST_VALUE##VHELPER(dict, VNAME, KEY2, VAL2)
305//%TEST_VALUE##VHELPER(dict, VNAME, KEY3, VAL3)
306//%TEST_VALUE##VHELPER(dict, VNAME, KEY4, VAL4)
307//%
308//% [dict set##VNAME$u##:VAL4 forKey:KEY1];
309//% XCTAssertEqual(dict.count, 4U);
310//%TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL4)
311//%TEST_VALUE##VHELPER(dict, VNAME, KEY2, VAL2)
312//%TEST_VALUE##VHELPER(dict, VNAME, KEY3, VAL3)
313//%TEST_VALUE##VHELPER(dict, VNAME, KEY4, VAL4)
314//%
315//% [dict set##VNAME$u##:VAL2 forKey:KEY4];
316//% XCTAssertEqual(dict.count, 4U);
317//%TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL4)
318//%TEST_VALUE##VHELPER(dict, VNAME, KEY2, VAL2)
319//%TEST_VALUE##VHELPER(dict, VNAME, KEY3, VAL3)
320//%TEST_VALUE##VHELPER(dict, VNAME, KEY4, VAL2)
321//%
322//% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY3 };
323//% const VALUE_TYPE k##VNAME$u##s2[] = { VAL3, VAL1 };
324//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
325//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s2
326//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## forKeys:kKeys2
327//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## count:GPBARRAYSIZE(k##VNAME$u##s2)];
328//% XCTAssertNotNil(dict2);
329//% [dict add##VACCESSOR##EntriesFromDictionary:dict2];
330//% XCTAssertEqual(dict.count, 4U);
331//%TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL4)
332//%TEST_VALUE##VHELPER(dict, VNAME, KEY2, VAL3)
333//%TEST_VALUE##VHELPER(dict, VNAME, KEY3, VAL1)
334//%TEST_VALUE##VHELPER(dict, VNAME, KEY4, VAL2)
335//%
336//% [dict2 release];
337//% [dict release];
338//%}
339//%
340//%@end
341//%
342
343//%PDDM-DEFINE TESTS_FOR_ENUM_VALUE_RAW_ADDITIONS(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4)
344//%TESTS_FOR_ENUM_VALUE_RAW_ADDITIONS2(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Enum, int32_t, , POD, 700, 801, 702, 803)
345//%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)
346//%#pragma mark - KEY_NAME -> VALUE_NAME (Unknown Enums)
347//%
348//%@interface GPB##KEY_NAME##VALUE_NAME##DictionaryUnknownEnumTests : XCTestCase
349//%@end
350//%
351//%@implementation GPB##KEY_NAME##VALUE_NAME##DictionaryUnknownEnumTests
352//%
353//%- (void)testRawBasics {
354//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3 };
355//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3 };
356//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
357//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
358//% KEY_NAME$S VALUE_NAME$S rawValues:kValues
359//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
360//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
361//% XCTAssertNotNil(dict);
362//% XCTAssertEqual(dict.count, 3U);
363//% XCTAssertTrue(dict.validationFunc == TestingEnum_IsValidValue); // Pointer comparison
364//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_RAW_VALUE##VHELPER(dict, value, KEY1, VAL1)
365//%TEST_VALUE##VHELPER(dict, value, KEY2, kGPBUnrecognizedEnumeratorValue)
366//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
367//%TEST_RAW_VALUE##VHELPER(dict, value, KEY3, VAL3)
368//%RAW_VALUE_NOT_FOUND##VHELPER(dict, KEY4)
369//%
370//% __block NSUInteger idx = 0;
371//% KEY_TYPE KisP##*seenKeys = malloc(3 * sizeof(KEY_TYPE##KisP));
372//% VALUE_TYPE *seenValues = malloc(3 * sizeof(VALUE_TYPE));
373//% [dict enumerateKeysAndValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
374//% XCTAssertLessThan(idx, 3U);
375//% seenKeys[idx] = aKey;
376//% seenValues[idx] = aValue;
377//% XCTAssertNotEqual(stop, NULL);
378//% ++idx;
379//% }];
380//% for (int i = 0; i < 3; ++i) {
381//% BOOL foundKey = NO;
382//% for (int j = 0; (j < 3) && !foundKey; ++j) {
383//% if (COMPARE_KEYS##KSUFFIX(kKeys[i], seenKeys[j])) {
384//% foundKey = YES;
385//% if (i == 1) {
386//% XCTAssertEqual##VSUFFIX(kGPBUnrecognizedEnumeratorValue, seenValues[j], @"i = %d, j = %d", i, j);
387//% } else {
388//% XCTAssertEqual##VSUFFIX(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
389//% }
390//% }
391//% }
392//% XCTAssertTrue(foundKey, @"i = %d", i);
393//% }
394//% idx = 0;
395//% [dict enumerateKeysAndRawValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
396//% XCTAssertLessThan(idx, 3U);
397//% seenKeys[idx] = aKey;
398//% seenValues[idx] = aValue;
399//% XCTAssertNotEqual(stop, NULL);
400//% ++idx;
401//% }];
402//% for (int i = 0; i < 3; ++i) {
403//% BOOL foundKey = NO;
404//% for (int j = 0; (j < 3) && !foundKey; ++j) {
405//% if (COMPARE_KEYS##KSUFFIX(kKeys[i], seenKeys[j])) {
406//% foundKey = YES;
407//% XCTAssertEqual##VSUFFIX(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
408//% }
409//% }
410//% XCTAssertTrue(foundKey, @"i = %d", i);
411//% }
412//% free(seenKeys);
413//% free(seenValues);
414//%
415//% // Stopping the enumeration.
416//% idx = 0;
417//% [dict enumerateKeysAndRawValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
418//% #pragma unused(aKey, aValue)
419//% if (idx == 1) *stop = YES;
420//% XCTAssertNotEqual(idx, 2U);
421//% ++idx;
422//% }];
423//% [dict release];
424//%}
425//%
426//%- (void)testEqualityWithUnknowns {
427//% const KEY_TYPE KisP##kKeys1[] = { KEY1, KEY2, KEY3, KEY4 };
428//% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY1, KEY4 };
429//% const VALUE_TYPE kValues1[] = { VAL1, VAL2, VAL3 }; // Unknown
430//% const VALUE_TYPE kValues2[] = { VAL1, VAL4, VAL3 }; // Unknown
431//% const VALUE_TYPE kValues3[] = { VAL1, VAL2, VAL3, VAL4 }; // Unknowns
432//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict1 =
433//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
434//% KEY_NAME$S VALUE_NAME$S rawValues:kValues1
435//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
436//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues1)];
437//% XCTAssertNotNil(dict1);
438//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict1prime =
439//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
440//% KEY_NAME$S VALUE_NAME$S rawValues:kValues1
441//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
442//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues1)];
443//% XCTAssertNotNil(dict1prime);
444//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
445//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
446//% KEY_NAME$S VALUE_NAME$S rawValues:kValues2
447//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
448//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues2)];
449//% XCTAssertNotNil(dict2);
450//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict3 =
451//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
452//% KEY_NAME$S VALUE_NAME$S rawValues:kValues1
453//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys2
454//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues1)];
455//% XCTAssertNotNil(dict3);
456//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict4 =
457//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
458//% KEY_NAME$S VALUE_NAME$S rawValues:kValues3
459//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
460//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues3)];
461//% XCTAssertNotNil(dict4);
462//%
463//% // 1/1Prime should be different objects, but equal.
464//% XCTAssertNotEqual(dict1, dict1prime);
465//% XCTAssertEqualObjects(dict1, dict1prime);
466//% // Equal, so they must have same hash.
467//% XCTAssertEqual([dict1 hash], [dict1prime hash]);
468//%
469//% // 2 is same keys, different values; not equal.
470//% XCTAssertNotEqualObjects(dict1, dict2);
471//%
472//% // 3 is different keys, same values; not equal.
473//% XCTAssertNotEqualObjects(dict1, dict3);
474//%
475//% // 4 extra pair; not equal
476//% XCTAssertNotEqualObjects(dict1, dict4);
477//%
478//% [dict1 release];
479//% [dict1prime release];
480//% [dict2 release];
481//% [dict3 release];
482//% [dict4 release];
483//%}
484//%
485//%- (void)testCopyWithUnknowns {
486//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
487//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 }; // Unknown
488//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
489//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
490//% KEY_NAME$S VALUE_NAME$S rawValues:kValues
491//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
492//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
493//% XCTAssertNotNil(dict);
494//%
495//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 = [dict copy];
496//% XCTAssertNotNil(dict2);
497//%
498//% // Should be new pointer, but equal objects.
499//% XCTAssertNotEqual(dict, dict2);
500//% XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
501//% XCTAssertEqualObjects(dict, dict2);
502//%
503//% [dict2 release];
504//% [dict release];
505//%}
506//%
507//%- (void)testDictionaryFromDictionary {
508//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
509//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 }; // Unknowns
510//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
511//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
512//% KEY_NAME$S VALUE_NAME$S rawValues:kValues
513//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
514//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
515//% XCTAssertNotNil(dict);
516//%
517//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
518//% [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithDictionary:dict];
519//% XCTAssertNotNil(dict2);
520//%
521//% // Should be new pointer, but equal objects.
522//% XCTAssertNotEqual(dict, dict2);
523//% XCTAssertEqualObjects(dict, dict2);
524//% XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
525//% [dict release];
526//%}
527//%
528//%- (void)testUnknownAdds {
529//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
530//% [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue];
531//% XCTAssertNotNil(dict);
532//%
533//% XCTAssertEqual(dict.count, 0U);
534//% XCTAssertThrowsSpecificNamed([dict setValue:VAL2 forKey:KEY2], // Unknown
535//% NSException, NSInvalidArgumentException);
536//% XCTAssertEqual(dict.count, 0U);
537//% [dict setRawValue:VAL2 forKey:KEY2]; // Unknown
538//% XCTAssertEqual(dict.count, 1U);
539//%
540//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY3, KEY4 };
541//% const VALUE_TYPE kValues[] = { VAL1, VAL3, VAL4 }; // Unknown
542//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
543//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
544//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
545//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
546//% XCTAssertNotNil(dict2);
547//% [dict addRawEntriesFromDictionary:dict2];
548//% XCTAssertEqual(dict.count, 4U);
549//%
550//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
551//%TEST_VALUE##VHELPER(dict, value, KEY2, kGPBUnrecognizedEnumeratorValue)
552//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
553//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
554//%TEST_VALUE##VHELPER(dict, value, KEY4, kGPBUnrecognizedEnumeratorValue)
555//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
556//% [dict2 release];
557//%}
558//%
559//%- (void)testUnknownRemove {
560//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
561//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 }; // Unknowns
562//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
563//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
564//% KEY_NAME$S VALUE_NAME$S rawValues:kValues
565//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
566//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
567//% XCTAssertNotNil(dict);
568//% XCTAssertEqual(dict.count, 4U);
569//%
570//% [dict removeValueForKey:KEY2];
571//% XCTAssertEqual(dict.count, 3U);
572//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
573//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
574//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
575//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
576//%
577//% // Remove again does nothing.
578//% [dict removeValueForKey:KEY2];
579//% XCTAssertEqual(dict.count, 3U);
580//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
581//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
582//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
583//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
584//%
585//% [dict removeValueForKey:KEY4];
586//% XCTAssertEqual(dict.count, 2U);
587//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
588//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
589//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
590//%VALUE_NOT_FOUND##VHELPER(dict, KEY4)
591//%
592//% [dict removeAll];
593//% XCTAssertEqual(dict.count, 0U);
594//%VALUE_NOT_FOUND##VHELPER(dict, KEY1)
595//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
596//%VALUE_NOT_FOUND##VHELPER(dict, KEY3)
597//%VALUE_NOT_FOUND##VHELPER(dict, KEY4)
598//% [dict release];
599//%}
600//%
601//%- (void)testInplaceMutationUnknowns {
602//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
603//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 }; // Unknowns
604//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
605//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
606//% KEY_NAME$S VALUE_NAME$S rawValues:kValues
607//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
608//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
609//% XCTAssertNotNil(dict);
610//% XCTAssertEqual(dict.count, 4U);
611//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
612//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
613//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
614//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
615//%
616//% XCTAssertThrowsSpecificNamed([dict setValue:VAL4 forKey:KEY1], // Unknown
617//% NSException, NSInvalidArgumentException);
618//% XCTAssertEqual(dict.count, 4U);
619//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
620//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
621//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
622//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
623//%
624//% [dict setRawValue:VAL4 forKey:KEY1]; // Unknown
625//% XCTAssertEqual(dict.count, 4U);
626//%TEST_RAW_VALUE##VHELPER(dict, value, KEY1, VAL4)
627//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
628//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
629//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
630//%
631//% [dict setRawValue:VAL1 forKey:KEY4];
632//% XCTAssertEqual(dict.count, 4U);
633//%TEST_RAW_VALUE##VHELPER(dict, value, KEY1, VAL4)
634//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
635//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
636//%TEST_VALUE##VHELPER(dict, value, KEY4, VAL1)
637//%
638//% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY3 };
639//% const VALUE_TYPE kValues2[] = { VAL3, VAL2 }; // Unknown
640//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
641//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
642//% KEY_NAME$S VALUE_NAME$S rawValues:kValues2
643//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys2
644//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues2)];
645//% XCTAssertNotNil(dict2);
646//% [dict addRawEntriesFromDictionary:dict2];
647//% XCTAssertEqual(dict.count, 4U);
648//%TEST_RAW_VALUE##VHELPER(dict, value, KEY1, VAL4)
649//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL3)
650//%TEST_RAW_VALUE##VHELPER(dict, value, KEY3, VAL2)
651//%TEST_VALUE##VHELPER(dict, value, KEY4, VAL1)
652//%
653//% [dict2 release];
654//% [dict release];
655//%}
656//%
657//%- (void)testCopyUnknowns {
658//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
659//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
660//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
661//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
662//% KEY_NAME$S VALUE_NAME$S rawValues:kValues
663//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
664//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
665//% XCTAssertNotNil(dict);
666//%
667//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 = [dict copy];
668//% XCTAssertNotNil(dict2);
669//%
670//% // Should be new pointer, but equal objects.
671//% XCTAssertNotEqual(dict, dict2);
672//% XCTAssertEqualObjects(dict, dict2);
673//% XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
674//% XCTAssertTrue([dict2 isKindOfClass:[GPB##KEY_NAME##VALUE_NAME##Dictionary class]]);
675//%
676//% [dict2 release];
677//% [dict release];
678//%}
679//%
680//%@end
681//%
682
683//
684// Helpers for PODs
685//
686
687//%PDDM-DEFINE DECLARE_VALUE_STORAGEPOD(VALUE_TYPE, NAME)
688//% VALUE_TYPE NAME;
689//%
690//%PDDM-DEFINE VALUE_NOT_FOUNDPOD(DICT, KEY)
691//% XCTAssertFalse([DICT valueForKey:KEY value:NULL]);
692//%PDDM-DEFINE TEST_VALUEPOD(DICT, STORAGE, KEY, VALUE)
693//% XCTAssertTrue([DICT valueForKey:KEY value:NULL]);
694//% XCTAssertTrue([DICT valueForKey:KEY value:&STORAGE]);
695//% XCTAssertEqual(STORAGE, VALUE);
696//%PDDM-DEFINE COMPARE_KEYS(KEY1, KEY2)
697//%KEY1 == KEY2
698//%PDDM-DEFINE RAW_VALUE_NOT_FOUNDPOD(DICT, KEY)
699//% XCTAssertFalse([DICT valueForKey:KEY rawValue:NULL]);
700//%PDDM-DEFINE TEST_RAW_VALUEPOD(DICT, STORAGE, KEY, VALUE)
701//% XCTAssertTrue([DICT valueForKey:KEY rawValue:NULL]);
702//% XCTAssertTrue([DICT valueForKey:KEY rawValue:&STORAGE]);
703//% XCTAssertEqual(STORAGE, VALUE);
704
705//
706// Helpers for Objects
707//
708
709//%PDDM-DEFINE DECLARE_VALUE_STORAGEOBJECT(VALUE_TYPE, NAME)
710// Empty
711//%PDDM-DEFINE VALUE_NOT_FOUNDOBJECT(DICT, KEY)
712//% XCTAssertNil([DICT objectForKey:KEY]);
713//%PDDM-DEFINE TEST_VALUEOBJECT(DICT, STORAGE, KEY, VALUE)
714//% XCTAssertEqualObjects([DICT objectForKey:KEY], VALUE);
715//%PDDM-DEFINE COMPARE_KEYSObjects(KEY1, KEY2)
716//%[KEY1 isEqual:KEY2]
717
718//
719// Helpers for tests.
720//
721
722//%PDDM-DEFINE TEST_HELPERS(KEY_NAME, KEY_TYPE, KisP)
723//%// To let the testing macros work, add some extra methods to simplify things.
724//%@interface GPB##KEY_NAME##EnumDictionary (TestingTweak)
725//%+ (instancetype)dictionaryWithValue:(int32_t)value forKey:(KEY_TYPE##KisP$S##KisP)key;
726//%- (instancetype)initWithValues:(const int32_t [])values
727//% forKeys:(const KEY_TYPE##KisP$S##KisP [])keys
728//% count:(NSUInteger)count;
729//%@end
730//%
731//%static BOOL TestingEnum_IsValidValue(int32_t value) {
732//% switch (value) {
733//% case 700:
734//% case 701:
735//% case 702:
736//% case 703:
737//% return YES;
738//% default:
739//% return NO;
740//% }
741//%}
742//%
743//%@implementation GPB##KEY_NAME##EnumDictionary (TestingTweak)
744//%+ (instancetype)dictionaryWithValue:(int32_t)value forKey:(KEY_TYPE##KisP$S##KisP)key {
745//% // Cast is needed to compiler knows what class we are invoking initWithValues: on to get the
746//% // type correct.
747//% return [[(GPB##KEY_NAME##EnumDictionary*)[self alloc] initWithValidationFunction:TestingEnum_IsValidValue
748//% KEY_NAME$S rawValues:&value
749//% KEY_NAME$S forKeys:&key
750//% KEY_NAME$S count:1] autorelease];
751//%}
752//%- (instancetype)initWithValues:(const int32_t [])values
753//% forKeys:(const KEY_TYPE##KisP$S##KisP [])keys
754//% count:(NSUInteger)count {
755//% return [self initWithValidationFunction:TestingEnum_IsValidValue
756//% rawValues:values
757//% forKeys:keys
758//% count:count];
759//%}
760//%@end
761//%
762//%
763
764
765//
766// BOOL test macros
767//
768//TODO(thomasvl): enum tests
769
770//%PDDM-DEFINE BOOL_TESTS_FOR_POD_VALUE(VALUE_NAME, VALUE_TYPE, VAL1, VAL2)
771//%BOOL_TESTS_COMMON(Bool, BOOL, , , YES, NO, VALUE_NAME, VALUE_TYPE, , value, POD, VAL1, VAL2)
772
773//%PDDM-DEFINE TESTS_FOR_BOOL_KEY_OBJECT_VALUE(VALUE_NAME, VALUE_TYPE, VAL1, VAL2)
774//%BOOL_TESTS_COMMON(Bool, BOOL, , , YES, NO, VALUE_NAME, VALUE_TYPE, Objects, object, OBJECT, VAL1, VAL2)
775
776//%PDDM-DEFINE BOOL_TESTS_COMMON(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, VALUE_NAME, VALUE_TYPE, VSUFFIX, VNAME, VHELPER, VAL1, VAL2)
777//%#pragma mark - KEY_NAME -> VALUE_NAME
778//%
779//%@interface GPB##KEY_NAME##VALUE_NAME##DictionaryTests : XCTestCase
780//%@end
781//%
782//%@implementation GPB##KEY_NAME##VALUE_NAME##DictionaryTests
783//%
784//%- (void)testEmpty {
785//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
786//% XCTAssertNotNil(dict);
787//% XCTAssertEqual(dict.count, 0U);
788//%VALUE_NOT_FOUND##VHELPER(dict, KEY1)
789//% [dict enumerateKeysAnd##VNAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u##, BOOL *stop) {
790//% #pragma unused(aKey, a##VNAME$u##, stop)
791//% XCTFail(@"Shouldn't get here!");
792//% }];
793//% [dict release];
794//%}
795//%
796//%- (void)testOne {
797//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWith##VNAME$u##:VAL1 forKey:KEY1];
798//% XCTAssertNotNil(dict);
799//% XCTAssertEqual(dict.count, 1U);
800//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
801//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
802//% [dict enumerateKeysAnd##VNAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u, BOOL *stop) {
803//% XCTAssertEqual##KSUFFIX(aKey, KEY1);
804//% XCTAssertEqual##VSUFFIX(a##VNAME$u, VAL1);
805//% XCTAssertNotEqual(stop, NULL);
806//% }];
807//%}
808//%
809//%- (void)testBasics {
810//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
811//% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
812//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
813//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
814//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## forKeys:kKeys
815//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
816//% XCTAssertNotNil(dict);
817//% XCTAssertEqual(dict.count, 2U);
818//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
819//%TEST_VALUE##VHELPER(dict, VNAME, KEY2, VAL2)
820//%
821//% __block NSUInteger idx = 0;
822//% KEY_TYPE KisP##*seenKeys = malloc(2 * sizeof(KEY_TYPE##KisP));
823//% VALUE_TYPE *seen##VNAME$u##s = malloc(2 * sizeof(VALUE_TYPE));
824//% [dict enumerateKeysAnd##VNAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u##, BOOL *stop) {
825//% XCTAssertLessThan(idx, 2U);
826//% seenKeys[idx] = aKey;
827//% seen##VNAME$u##s[idx] = a##VNAME$u;
828//% XCTAssertNotEqual(stop, NULL);
829//% ++idx;
830//% }];
831//% for (int i = 0; i < 2; ++i) {
832//% BOOL foundKey = NO;
833//% for (int j = 0; (j < 2) && !foundKey; ++j) {
834//% if (COMPARE_KEYS##KSUFFIX(kKeys[i], seenKeys[j])) {
835//% foundKey = YES;
836//% XCTAssertEqual##VSUFFIX(k##VNAME$u##s[i], seen##VNAME$u##s[j], @"i = %d, j = %d", i, j);
837//% }
838//% }
839//% XCTAssertTrue(foundKey, @"i = %d", i);
840//% }
841//% free(seenKeys);
842//% free(seen##VNAME$u##s);
843//%
844//% // Stopping the enumeration.
845//% idx = 0;
846//% [dict enumerateKeysAnd##VNAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u##, BOOL *stop) {
847//% #pragma unused(aKey, a##VNAME$u)
848//% if (idx == 0) *stop = YES;
849//% XCTAssertNotEqual(idx, 2U);
850//% ++idx;
851//% }];
852//% [dict release];
853//%}
854//%
855//%- (void)testEquality {
856//% const KEY_TYPE KisP##kKeys1[] = { KEY1, KEY2 };
857//% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY1 };
858//% const VALUE_TYPE k##VNAME$u##s1[] = { VAL1, VAL2 };
859//% const VALUE_TYPE k##VNAME$u##s2[] = { VAL2, VAL1 };
860//% const VALUE_TYPE k##VNAME$u##s3[] = { VAL2 };
861//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict1 =
862//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s1
863//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## forKeys:kKeys1
864//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## count:GPBARRAYSIZE(k##VNAME$u##s1)];
865//% XCTAssertNotNil(dict1);
866//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict1prime =
867//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s1
868//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## forKeys:kKeys1
869//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## count:GPBARRAYSIZE(k##VNAME$u##s1)];
870//% XCTAssertNotNil(dict1prime);
871//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
872//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s2
873//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## forKeys:kKeys1
874//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## count:GPBARRAYSIZE(k##VNAME$u##s2)];
875//% XCTAssertNotNil(dict2);
876//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict3 =
877//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s1
878//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## forKeys:kKeys2
879//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## count:GPBARRAYSIZE(k##VNAME$u##s1)];
880//% XCTAssertNotNil(dict3);
881//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict4 =
882//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s3
883//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## forKeys:kKeys1
884//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## count:GPBARRAYSIZE(k##VNAME$u##s3)];
885//% XCTAssertNotNil(dict4);
886//%
887//% // 1/1Prime should be different objects, but equal.
888//% XCTAssertNotEqual(dict1, dict1prime);
889//% XCTAssertEqualObjects(dict1, dict1prime);
890//% // Equal, so they must have same hash.
891//% XCTAssertEqual([dict1 hash], [dict1prime hash]);
892//%
893//% // 2 is same keys, different ##VNAME##s; not equal.
894//% XCTAssertNotEqualObjects(dict1, dict2);
895//%
896//% // 3 is different keys, same ##VNAME##s; not equal.
897//% XCTAssertNotEqualObjects(dict1, dict3);
898//%
899//% // 4 Fewer pairs; not equal
900//% XCTAssertNotEqualObjects(dict1, dict4);
901//%
902//% [dict1 release];
903//% [dict1prime release];
904//% [dict2 release];
905//% [dict3 release];
906//% [dict4 release];
907//%}
908//%
909//%- (void)testCopy {
910//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
911//% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
912//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
913//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
914//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## forKeys:kKeys
915//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
916//% XCTAssertNotNil(dict);
917//%
918//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 = [dict copy];
919//% XCTAssertNotNil(dict2);
920//%
921//% // Should be new object but equal.
922//% XCTAssertNotEqual(dict, dict2);
923//% XCTAssertEqualObjects(dict, dict2);
924//% XCTAssertTrue([dict2 isKindOfClass:[GPB##KEY_NAME##VALUE_NAME##Dictionary class]]);
925//%
926//% [dict2 release];
927//% [dict release];
928//%}
929//%
930//%- (void)testDictionaryFromDictionary {
931//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
932//% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
933//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
934//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
935//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## forKeys:kKeys
936//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
937//% XCTAssertNotNil(dict);
938//%
939//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
940//% [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithDictionary:dict];
941//% XCTAssertNotNil(dict2);
942//%
943//% // Should be new pointer, but equal objects.
944//% XCTAssertNotEqual(dict, dict2);
945//% XCTAssertEqualObjects(dict, dict2);
946//% [dict release];
947//%}
948//%
949//%- (void)testAdds {
950//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionary];
951//% XCTAssertNotNil(dict);
952//%
953//% XCTAssertEqual(dict.count, 0U);
954//% [dict set##VNAME$u:VAL1 forKey:KEY1];
955//% XCTAssertEqual(dict.count, 1U);
956//%
957//% const KEY_TYPE KisP##kKeys[] = { KEY2 };
958//% const VALUE_TYPE k##VNAME$u##s[] = { VAL2 };
959//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
960//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
961//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## forKeys:kKeys
962//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
963//% XCTAssertNotNil(dict2);
964//% [dict addEntriesFromDictionary:dict2];
965//% XCTAssertEqual(dict.count, 2U);
966//%
967//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
968//%TEST_VALUE##VHELPER(dict, VNAME, KEY2, VAL2)
969//% [dict2 release];
970//%}
971//%
972//%- (void)testRemove {
973//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2};
974//% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
975//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
976//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
977//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## forKeys:kKeys
978//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
979//% XCTAssertNotNil(dict);
980//% XCTAssertEqual(dict.count, 2U);
981//%
982//% [dict remove##VNAME$u##ForKey:KEY2];
983//% XCTAssertEqual(dict.count, 1U);
984//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
985//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
986//%
987//% // Remove again does nothing.
988//% [dict remove##VNAME$u##ForKey:KEY2];
989//% XCTAssertEqual(dict.count, 1U);
990//%TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
991//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
992//%
993//% [dict removeAll];
994//% XCTAssertEqual(dict.count, 0U);
995//%VALUE_NOT_FOUND##VHELPER(dict, KEY1)
996//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
997//% [dict release];
998//%}
999//%
1000//%- (void)testInplaceMutation {
1001//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
1002//% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
1003//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
1004//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
1005//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## forKeys:kKeys
1006//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
1007//% XCTAssertNotNil(dict);
1008//% XCTAssertEqual(dict.count, 2U);
1009//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
1010//%TEST_VALUE##VHELPER(dict, VNAME, KEY2, VAL2)
1011//%
1012//% [dict set##VNAME$u##:VAL2 forKey:KEY1];
1013//% XCTAssertEqual(dict.count, 2U);
1014//%TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL2)
1015//%TEST_VALUE##VHELPER(dict, VNAME, KEY2, VAL2)
1016//%
1017//% [dict set##VNAME$u##:VAL1 forKey:KEY2];
1018//% XCTAssertEqual(dict.count, 2U);
1019//%TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL2)
1020//%TEST_VALUE##VHELPER(dict, VNAME, KEY2, VAL1)
1021//%
1022//% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY1 };
1023//% const VALUE_TYPE k##VNAME$u##s2[] = { VAL2, VAL1 };
1024//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
1025//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s2
1026//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## forKeys:kKeys2
1027//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## count:GPBARRAYSIZE(k##VNAME$u##s2)];
1028//% XCTAssertNotNil(dict2);
1029//% [dict addEntriesFromDictionary:dict2];
1030//% XCTAssertEqual(dict.count, 2U);
1031//%TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
1032//%TEST_VALUE##VHELPER(dict, VNAME, KEY2, VAL2)
1033//%
1034//% [dict2 release];
1035//% [dict release];
1036//%}
1037//%
1038//%@end
1039//%
1040