1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2015 Google Inc. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
8 //%PDDM-DEFINE TEST_FOR_POD_KEY(KEY_NAME, KEY_TYPE, KEY1, KEY2, KEY3, KEY4)
9 //%TESTS_FOR_POD_VALUES(KEY_NAME, KEY_TYPE, , , KEY1, KEY2, KEY3, KEY4)
10 //%TESTS_FOR_POD_KEY_OBJECT_VALUE(KEY_NAME, KEY_TYPE, KEY1, KEY2, KEY3, KEY4, Object, NSString*, @"abc", @"def", @"ghi", @"jkl")
12 //%PDDM-DEFINE TESTS_FOR_POD_VALUES(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4)
13 //%TEST_HELPERS(KEY_NAME, KEY_TYPE, KisP)
14 //%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, UInt32, uint32_t, , 100U, 101U, 102U, 103U)
15 //%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Int32, int32_t, , 200, 201, 202, 203)
16 //%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, UInt64, uint64_t, , 300U, 301U, 302U, 303U)
17 //%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Int64, int64_t, , 400, 401, 402, 403)
18 //%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Bool, BOOL, , YES, YES, NO, NO)
19 //%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Float, float, , 500.f, 501.f, 502.f, 503.f)
20 //%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Double, double, , 600., 601., 602., 603.)
21 //%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Enum, int32_t, Raw, 700, 701, 702, 703)
22 //%TESTS_FOR_ENUM_VALUE_RAW_ADDITIONS(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4)
24 //%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)
25 //%TESTS_COMMON(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, , value, POD, VACCESSOR, VAL1, VAL2, VAL3, VAL4)
27 //%PDDM-DEFINE TESTS_FOR_POD_KEY_OBJECT_VALUE(KEY_NAME, KEY_TYPE, KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, VAL1, VAL2, VAL3, VAL4)
28 //%TESTS_COMMON(KEY_NAME, KEY_TYPE, , , KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, Objects, object, OBJECT, , VAL1, VAL2, VAL3, VAL4)
30 //%PDDM-DEFINE DICTIONARY_CLASS_DECLPOD(KEY_NAME, VALUE_NAME, VALUE_TYPE)
31 //%GPB##KEY_NAME##VALUE_NAME##Dictionary
32 //%PDDM-DEFINE DICTIONARY_CLASS_DECLEnum(KEY_NAME, VALUE_NAME, VALUE_TYPE)
33 //%GPB##KEY_NAME##VALUE_NAME##Dictionary
34 //%PDDM-DEFINE DICTIONARY_CLASS_DECLOBJECT(KEY_NAME, VALUE_NAME, VALUE_TYPE)
35 //%GPB##KEY_NAME##VALUE_NAME##Dictionary<VALUE_TYPE>
37 //%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)
38 //%#pragma mark - KEY_NAME -> VALUE_NAME
40 //%@interface GPB##KEY_NAME##VALUE_NAME##DictionaryTests : XCTestCase
43 //%@implementation GPB##KEY_NAME##VALUE_NAME##DictionaryTests
45 //%- (void)testEmpty {
46 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
47 //% XCTAssertNotNil(dict);
48 //% XCTAssertEqual(dict.count, 0U);
49 //%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY1)
50 //% [dict enumerateKeysAnd##VALUE_NAME$u##sUsingBlock:^(__unused KEY_TYPE KisP##aKey, __unused VALUE_TYPE a##VNAME$u, __unused BOOL *stop) {
51 //% XCTFail(@"Shouldn't get here!");
57 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
58 //% [dict set##VALUE_NAME$u##:VAL1 forKey:KEY1];
59 //% XCTAssertNotNil(dict);
60 //% XCTAssertEqual(dict.count, 1U);
61 //%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
62 //%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
63 //% [dict enumerateKeysAnd##VALUE_NAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u, BOOL *stop) {
64 //% XCTAssertEqual##KSUFFIX(aKey, KEY1);
65 //% XCTAssertEqual##VSUFFIX(a##VNAME$u, VAL1);
66 //% XCTAssertNotEqual(stop, NULL);
71 //%- (void)testBasics {
72 //% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3 };
73 //% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3 };
74 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
75 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME$u##s:k##VNAME$u##s
76 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
77 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
78 //% XCTAssertNotNil(dict);
79 //% XCTAssertEqual(dict.count, 3U);
80 //%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
81 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
82 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL3)
83 //%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY4)
85 //% __block NSUInteger idx = 0;
86 //% KEY_TYPE KisP##*seenKeys = malloc(3 * sizeof(KEY_TYPE##KisP));
87 //% VALUE_TYPE *seen##VNAME$u##s = malloc(3 * sizeof(VALUE_TYPE));
88 //% [dict enumerateKeysAnd##VALUE_NAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u, BOOL *stop) {
89 //% XCTAssertLessThan(idx, 3U);
90 //% seenKeys[idx] = aKey;
91 //% seen##VNAME$u##s[idx] = a##VNAME$u##;
92 //% XCTAssertNotEqual(stop, NULL);
95 //% for (int i = 0; i < 3; ++i) {
96 //% BOOL foundKey = NO;
97 //% for (int j = 0; (j < 3) && !foundKey; ++j) {
98 //% if (COMPARE_KEYS##KSUFFIX(kKeys[i], seenKeys[j])) {
100 //% XCTAssertEqual##VSUFFIX(k##VNAME$u##s[i], seen##VNAME$u##s[j], @"i = %d, j = %d", i, j);
103 //% XCTAssertTrue(foundKey, @"i = %d", i);
106 //% free(seen##VNAME$u##s);
108 //% // Stopping the enumeration.
110 //% [dict enumerateKeysAnd##VALUE_NAME$u##sUsingBlock:^(__unused KEY_TYPE KisP##aKey, __unused VALUE_TYPE a##VNAME$u, BOOL *stop) {
111 //% if (idx == 1) *stop = YES;
112 //% XCTAssertNotEqual(idx, 2U);
118 //%- (void)testEquality {
119 //% const KEY_TYPE KisP##kKeys1[] = { KEY1, KEY2, KEY3, KEY4 };
120 //% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY1, KEY4 };
121 //% const VALUE_TYPE k##VNAME$u##s1[] = { VAL1, VAL2, VAL3 };
122 //% const VALUE_TYPE k##VNAME$u##s2[] = { VAL1, VAL4, VAL3 };
123 //% const VALUE_TYPE k##VNAME$u##s3[] = { VAL1, VAL2, VAL3, VAL4 };
124 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1 =
125 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s1
126 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys1
127 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s1)];
128 //% XCTAssertNotNil(dict1);
129 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1prime =
130 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s1
131 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys1
132 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s1)];
133 //% XCTAssertNotNil(dict1prime);
134 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
135 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s2
136 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys1
137 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s2)];
138 //% XCTAssertNotNil(dict2);
139 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict3 =
140 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s1
141 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys2
142 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s1)];
143 //% XCTAssertNotNil(dict3);
144 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict4 =
145 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s3
146 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys1
147 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s3)];
148 //% XCTAssertNotNil(dict4);
150 //% // 1/1Prime should be different objects, but equal.
151 //% XCTAssertNotEqual(dict1, dict1prime);
152 //% XCTAssertEqualObjects(dict1, dict1prime);
153 //% // Equal, so they must have same hash.
154 //% XCTAssertEqual([dict1 hash], [dict1prime hash]);
156 //% // 2 is same keys, different ##VNAME##s; not equal.
157 //% XCTAssertNotEqualObjects(dict1, dict2);
159 //% // 3 is different keys, same ##VNAME##s; not equal.
160 //% XCTAssertNotEqualObjects(dict1, dict3);
162 //% // 4 extra pair; not equal
163 //% XCTAssertNotEqualObjects(dict1, dict4);
166 //% [dict1prime release];
172 //%- (void)testCopy {
173 //% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
174 //% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
175 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
176 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
177 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
178 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
179 //% XCTAssertNotNil(dict);
181 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 = [dict copy];
182 //% XCTAssertNotNil(dict2);
184 //% // Should be new object but equal.
185 //% XCTAssertNotEqual(dict, dict2);
186 //% XCTAssertEqualObjects(dict, dict2);
187 //% XCTAssertTrue([dict2 isKindOfClass:[GPB##KEY_NAME##VALUE_NAME##Dictionary class]]);
193 //%- (void)testDictionaryFromDictionary {
194 //% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
195 //% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
196 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
197 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
198 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
199 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
200 //% XCTAssertNotNil(dict);
202 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
203 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithDictionary:dict];
204 //% XCTAssertNotNil(dict2);
206 //% // Should be new pointer, but equal objects.
207 //% XCTAssertNotEqual(dict, dict2);
208 //% XCTAssertEqualObjects(dict, dict2);
213 //%- (void)testAdds {
214 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
215 //% XCTAssertNotNil(dict);
217 //% XCTAssertEqual(dict.count, 0U);
218 //% [dict set##VALUE_NAME##:VAL1 forKey:KEY1];
219 //% XCTAssertEqual(dict.count, 1U);
221 //% const KEY_TYPE KisP##kKeys[] = { KEY2, KEY3, KEY4 };
222 //% const VALUE_TYPE k##VNAME$u##s[] = { VAL2, VAL3, VAL4 };
223 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
224 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
225 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
226 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
227 //% XCTAssertNotNil(dict2);
228 //% [dict add##VACCESSOR##EntriesFromDictionary:dict2];
229 //% XCTAssertEqual(dict.count, 4U);
231 //%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
232 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
233 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL3)
234 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY4, VAL4)
239 //%- (void)testRemove {
240 //% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
241 //% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
242 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
243 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
244 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
245 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
246 //% XCTAssertNotNil(dict);
247 //% XCTAssertEqual(dict.count, 4U);
249 //% [dict remove##VALUE_NAME##ForKey:KEY2];
250 //% XCTAssertEqual(dict.count, 3U);
251 //%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
252 //%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
253 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL3)
254 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY4, VAL4)
256 //% // Remove again does nothing.
257 //% [dict remove##VALUE_NAME##ForKey:KEY2];
258 //% XCTAssertEqual(dict.count, 3U);
259 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
260 //%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
261 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL3)
262 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY4, VAL4)
264 //% [dict remove##VALUE_NAME##ForKey:KEY4];
265 //% XCTAssertEqual(dict.count, 2U);
266 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
267 //%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
268 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL3)
269 //%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY4)
271 //% [dict removeAll];
272 //% XCTAssertEqual(dict.count, 0U);
273 //%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY1)
274 //%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
275 //%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY3)
276 //%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY4)
280 //%- (void)testInplaceMutation {
281 //% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
282 //% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
283 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
284 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
285 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
286 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
287 //% XCTAssertNotNil(dict);
288 //% XCTAssertEqual(dict.count, 4U);
289 //%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
290 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
291 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL3)
292 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY4, VAL4)
294 //% [dict set##VALUE_NAME##:VAL4 forKey:KEY1];
295 //% XCTAssertEqual(dict.count, 4U);
296 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL4)
297 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
298 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL3)
299 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY4, VAL4)
301 //% [dict set##VALUE_NAME##:VAL2 forKey:KEY4];
302 //% XCTAssertEqual(dict.count, 4U);
303 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL4)
304 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
305 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL3)
306 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY4, VAL2)
308 //% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY3 };
309 //% const VALUE_TYPE k##VNAME$u##s2[] = { VAL3, VAL1 };
310 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
311 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s2
312 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys2
313 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s2)];
314 //% XCTAssertNotNil(dict2);
315 //% [dict add##VACCESSOR##EntriesFromDictionary:dict2];
316 //% XCTAssertEqual(dict.count, 4U);
317 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL4)
318 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL3)
319 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL1)
320 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY4, VAL2)
329 //%PDDM-DEFINE TESTS_FOR_ENUM_VALUE_RAW_ADDITIONS(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4)
330 //%TESTS_FOR_ENUM_VALUE_RAW_ADDITIONS2(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Enum, int32_t, , POD, 700, 801, 702, 803)
331 //%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)
332 //%#pragma mark - KEY_NAME -> VALUE_NAME (Unknown Enums)
334 //%@interface GPB##KEY_NAME##VALUE_NAME##DictionaryUnknownEnumTests : XCTestCase
337 //%@implementation GPB##KEY_NAME##VALUE_NAME##DictionaryUnknownEnumTests
339 //%- (void)testRawBasics {
340 //% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3 };
341 //% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3 };
342 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
343 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
344 //% KEY_NAME$S VALUE_NAME$S rawValues:kValues
345 //% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
346 //% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
347 //% XCTAssertNotNil(dict);
348 //% XCTAssertEqual(dict.count, 3U);
349 //% XCTAssertTrue(dict.validationFunc == TestingEnum_IsValidValue); // Pointer comparison
350 //%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_RAW_VALUE##VHELPER(dict, value, KEY1, VAL1)
351 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY2, kGPBUnrecognizedEnumeratorValue)
352 //%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
353 //%TEST_RAW_VALUE##VHELPER(dict, value, KEY3, VAL3)
354 //%RAW_VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY4)
356 //% __block NSUInteger idx = 0;
357 //% KEY_TYPE KisP##*seenKeys = malloc(3 * sizeof(KEY_TYPE##KisP));
358 //% VALUE_TYPE *seenValues = malloc(3 * sizeof(VALUE_TYPE));
359 //% [dict enumerateKeysAndEnumsUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
360 //% XCTAssertLessThan(idx, 3U);
361 //% seenKeys[idx] = aKey;
362 //% seenValues[idx] = aValue;
363 //% XCTAssertNotEqual(stop, NULL);
366 //% for (int i = 0; i < 3; ++i) {
367 //% BOOL foundKey = NO;
368 //% for (int j = 0; (j < 3) && !foundKey; ++j) {
369 //% if (COMPARE_KEYS##KSUFFIX(kKeys[i], seenKeys[j])) {
372 //% XCTAssertEqual##VSUFFIX(kGPBUnrecognizedEnumeratorValue, seenValues[j], @"i = %d, j = %d", i, j);
374 //% XCTAssertEqual##VSUFFIX(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
378 //% XCTAssertTrue(foundKey, @"i = %d", i);
381 //% [dict enumerateKeysAndRawValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
382 //% XCTAssertLessThan(idx, 3U);
383 //% seenKeys[idx] = aKey;
384 //% seenValues[idx] = aValue;
385 //% XCTAssertNotEqual(stop, NULL);
388 //% for (int i = 0; i < 3; ++i) {
389 //% BOOL foundKey = NO;
390 //% for (int j = 0; (j < 3) && !foundKey; ++j) {
391 //% if (COMPARE_KEYS##KSUFFIX(kKeys[i], seenKeys[j])) {
393 //% XCTAssertEqual##VSUFFIX(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
396 //% XCTAssertTrue(foundKey, @"i = %d", i);
399 //% free(seenValues);
401 //% // Stopping the enumeration.
403 //% [dict enumerateKeysAndRawValuesUsingBlock:^(__unused KEY_TYPE KisP##aKey, __unused VALUE_TYPE aValue, BOOL *stop) {
404 //% if (idx == 1) *stop = YES;
405 //% XCTAssertNotEqual(idx, 2U);
411 //%- (void)testEqualityWithUnknowns {
412 //% const KEY_TYPE KisP##kKeys1[] = { KEY1, KEY2, KEY3, KEY4 };
413 //% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY1, KEY4 };
414 //% const VALUE_TYPE kValues1[] = { VAL1, VAL2, VAL3 }; // Unknown
415 //% const VALUE_TYPE kValues2[] = { VAL1, VAL4, VAL3 }; // Unknown
416 //% const VALUE_TYPE kValues3[] = { VAL1, VAL2, VAL3, VAL4 }; // Unknowns
417 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1 =
418 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
419 //% KEY_NAME$S VALUE_NAME$S rawValues:kValues1
420 //% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
421 //% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues1)];
422 //% XCTAssertNotNil(dict1);
423 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1prime =
424 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
425 //% KEY_NAME$S VALUE_NAME$S rawValues:kValues1
426 //% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
427 //% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues1)];
428 //% XCTAssertNotNil(dict1prime);
429 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
430 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
431 //% KEY_NAME$S VALUE_NAME$S rawValues:kValues2
432 //% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
433 //% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues2)];
434 //% XCTAssertNotNil(dict2);
435 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict3 =
436 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
437 //% KEY_NAME$S VALUE_NAME$S rawValues:kValues1
438 //% KEY_NAME$S VALUE_NAME$S forKeys:kKeys2
439 //% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues1)];
440 //% XCTAssertNotNil(dict3);
441 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict4 =
442 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
443 //% KEY_NAME$S VALUE_NAME$S rawValues:kValues3
444 //% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
445 //% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues3)];
446 //% XCTAssertNotNil(dict4);
448 //% // 1/1Prime should be different objects, but equal.
449 //% XCTAssertNotEqual(dict1, dict1prime);
450 //% XCTAssertEqualObjects(dict1, dict1prime);
451 //% // Equal, so they must have same hash.
452 //% XCTAssertEqual([dict1 hash], [dict1prime hash]);
454 //% // 2 is same keys, different values; not equal.
455 //% XCTAssertNotEqualObjects(dict1, dict2);
457 //% // 3 is different keys, same values; not equal.
458 //% XCTAssertNotEqualObjects(dict1, dict3);
460 //% // 4 extra pair; not equal
461 //% XCTAssertNotEqualObjects(dict1, dict4);
464 //% [dict1prime release];
470 //%- (void)testCopyWithUnknowns {
471 //% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
472 //% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 }; // Unknown
473 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
474 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
475 //% KEY_NAME$S VALUE_NAME$S rawValues:kValues
476 //% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
477 //% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
478 //% XCTAssertNotNil(dict);
480 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 = [dict copy];
481 //% XCTAssertNotNil(dict2);
483 //% // Should be new pointer, but equal objects.
484 //% XCTAssertNotEqual(dict, dict2);
485 //% XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
486 //% XCTAssertEqualObjects(dict, dict2);
492 //%- (void)testDictionaryFromDictionary {
493 //% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
494 //% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 }; // Unknowns
495 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
496 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
497 //% KEY_NAME$S VALUE_NAME$S rawValues:kValues
498 //% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
499 //% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
500 //% XCTAssertNotNil(dict);
502 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
503 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithDictionary:dict];
504 //% XCTAssertNotNil(dict2);
506 //% // Should be new pointer, but equal objects.
507 //% XCTAssertNotEqual(dict, dict2);
508 //% XCTAssertEqualObjects(dict, dict2);
509 //% XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
514 //%- (void)testUnknownAdds {
515 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
516 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue];
517 //% XCTAssertNotNil(dict);
519 //% XCTAssertEqual(dict.count, 0U);
520 //% XCTAssertThrowsSpecificNamed([dict setEnum:VAL2 forKey:KEY2], // Unknown
521 //% NSException, NSInvalidArgumentException);
522 //% XCTAssertEqual(dict.count, 0U);
523 //% [dict setRawValue:VAL2 forKey:KEY2]; // Unknown
524 //% XCTAssertEqual(dict.count, 1U);
526 //% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY3, KEY4 };
527 //% const VALUE_TYPE kValues[] = { VAL1, VAL3, VAL4 }; // Unknown
528 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
529 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithEnums:kValues
530 //% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
531 //% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
532 //% XCTAssertNotNil(dict2);
533 //% [dict addRawEntriesFromDictionary:dict2];
534 //% XCTAssertEqual(dict.count, 4U);
536 //%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY1, VAL1)
537 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY2, kGPBUnrecognizedEnumeratorValue)
538 //%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
539 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY3, VAL3)
540 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY4, kGPBUnrecognizedEnumeratorValue)
541 //%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
546 //%- (void)testUnknownRemove {
547 //% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
548 //% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 }; // Unknowns
549 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
550 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
551 //% KEY_NAME$S VALUE_NAME$S rawValues:kValues
552 //% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
553 //% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
554 //% XCTAssertNotNil(dict);
555 //% XCTAssertEqual(dict.count, 4U);
557 //% [dict removeEnumForKey:KEY2];
558 //% XCTAssertEqual(dict.count, 3U);
559 //%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY1, VAL1)
560 //%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
561 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY3, VAL3)
562 //%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
564 //% // Remove again does nothing.
565 //% [dict removeEnumForKey:KEY2];
566 //% XCTAssertEqual(dict.count, 3U);
567 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY1, VAL1)
568 //%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
569 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY3, VAL3)
570 //%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
572 //% [dict removeEnumForKey:KEY4];
573 //% XCTAssertEqual(dict.count, 2U);
574 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY1, VAL1)
575 //%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
576 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY3, VAL3)
577 //%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY4)
579 //% [dict removeAll];
580 //% XCTAssertEqual(dict.count, 0U);
581 //%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY1)
582 //%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
583 //%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY3)
584 //%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY4)
588 //%- (void)testInplaceMutationUnknowns {
589 //% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
590 //% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 }; // Unknowns
591 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
592 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
593 //% KEY_NAME$S VALUE_NAME$S rawValues:kValues
594 //% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
595 //% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
596 //% XCTAssertNotNil(dict);
597 //% XCTAssertEqual(dict.count, 4U);
598 //%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY1, VAL1)
599 //%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
600 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY3, VAL3)
601 //%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
603 //% XCTAssertThrowsSpecificNamed([dict setEnum:VAL4 forKey:KEY1], // Unknown
604 //% NSException, NSInvalidArgumentException);
605 //% XCTAssertEqual(dict.count, 4U);
606 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY1, VAL1)
607 //%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
608 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY3, VAL3)
609 //%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
611 //% [dict setRawValue:VAL4 forKey:KEY1]; // Unknown
612 //% XCTAssertEqual(dict.count, 4U);
613 //%TEST_RAW_VALUE##VHELPER(dict, value, KEY1, VAL4)
614 //%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
615 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY3, VAL3)
616 //%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
618 //% [dict setRawValue:VAL1 forKey:KEY4];
619 //% XCTAssertEqual(dict.count, 4U);
620 //%TEST_RAW_VALUE##VHELPER(dict, value, KEY1, VAL4)
621 //%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
622 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY3, VAL3)
623 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY4, VAL1)
625 //% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY3 };
626 //% const VALUE_TYPE kValues2[] = { VAL3, VAL2 }; // Unknown
627 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
628 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
629 //% KEY_NAME$S VALUE_NAME$S rawValues:kValues2
630 //% KEY_NAME$S VALUE_NAME$S forKeys:kKeys2
631 //% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues2)];
632 //% XCTAssertNotNil(dict2);
633 //% [dict addRawEntriesFromDictionary:dict2];
634 //% XCTAssertEqual(dict.count, 4U);
635 //%TEST_RAW_VALUE##VHELPER(dict, value, KEY1, VAL4)
636 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY2, VAL3)
637 //%TEST_RAW_VALUE##VHELPER(dict, value, KEY3, VAL2)
638 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY4, VAL1)
644 //%- (void)testCopyUnknowns {
645 //% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
646 //% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
647 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
648 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
649 //% KEY_NAME$S VALUE_NAME$S rawValues:kValues
650 //% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
651 //% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
652 //% XCTAssertNotNil(dict);
654 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 = [dict copy];
655 //% XCTAssertNotNil(dict2);
657 //% // Should be new pointer, but equal objects.
658 //% XCTAssertNotEqual(dict, dict2);
659 //% XCTAssertEqualObjects(dict, dict2);
660 //% XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
661 //% XCTAssertTrue([dict2 isKindOfClass:[GPB##KEY_NAME##VALUE_NAME##Dictionary class]]);
674 //%PDDM-DEFINE DECLARE_VALUE_STORAGEPOD(VALUE_TYPE, NAME)
677 //%PDDM-DEFINE VALUE_NOT_FOUNDPOD(VALUE_NAME, DICT, KEY)
678 //% XCTAssertFalse([DICT get##VALUE_NAME##:NULL forKey:KEY]);
679 //%PDDM-DEFINE TEST_VALUEPOD(VALUE_NAME, DICT, STORAGE, KEY, VALUE)
680 //% XCTAssertTrue([DICT get##VALUE_NAME##:NULL forKey:KEY]);
681 //% XCTAssertTrue([DICT get##VALUE_NAME##:&STORAGE forKey:KEY]);
682 //% XCTAssertEqual(STORAGE, VALUE);
683 //%PDDM-DEFINE COMPARE_KEYS(KEY1, KEY2)
685 //%PDDM-DEFINE RAW_VALUE_NOT_FOUNDPOD(VALUE_NAME, DICT, KEY)
686 //% XCTAssertFalse([DICT getRawValue:NULL forKey:KEY]);
687 //%PDDM-DEFINE TEST_RAW_VALUEPOD(DICT, STORAGE, KEY, VALUE)
688 //% XCTAssertTrue([DICT getRawValue:NULL forKey:KEY]);
689 //% XCTAssertTrue([DICT getRawValue:&STORAGE forKey:KEY]);
690 //% XCTAssertEqual(STORAGE, VALUE);
693 // Helpers for Objects
696 //%PDDM-DEFINE DECLARE_VALUE_STORAGEOBJECT(VALUE_TYPE, NAME)
698 //%PDDM-DEFINE VALUE_NOT_FOUNDOBJECT(VALUE_NAME, DICT, KEY)
699 //% XCTAssertNil([DICT objectForKey:KEY]);
700 //%PDDM-DEFINE TEST_VALUEOBJECT(VALUE_NAME, DICT, STORAGE, KEY, VALUE)
701 //% XCTAssertEqualObjects([DICT objectForKey:KEY], VALUE);
702 //%PDDM-DEFINE COMPARE_KEYSObjects(KEY1, KEY2)
703 //%[KEY1 isEqual:KEY2]
706 // Helpers for tests.
709 //%PDDM-DEFINE TEST_HELPERS(KEY_NAME, KEY_TYPE, KisP)
710 //%// To let the testing macros work, add some extra methods to simplify things.
711 //%@interface GPB##KEY_NAME##EnumDictionary (TestingTweak)
712 //%- (instancetype)initWithEnums:(const int32_t [])values
713 //% forKeys:(const KEY_TYPE##KisP$S##KisP [])keys
714 //% count:(NSUInteger)count;
717 //%static BOOL TestingEnum_IsValidValue(int32_t value) {
729 //%@implementation GPB##KEY_NAME##EnumDictionary (TestingTweak)
730 //%- (instancetype)initWithEnums:(const int32_t [])values
731 //% forKeys:(const KEY_TYPE##KisP$S##KisP [])keys
732 //% count:(NSUInteger)count {
733 //% return [self initWithValidationFunction:TestingEnum_IsValidValue
748 //%PDDM-DEFINE BOOL_TESTS_FOR_POD_VALUE(VALUE_NAME, VALUE_TYPE, VAL1, VAL2)
749 //%BOOL_TESTS_COMMON(Bool, BOOL, , , YES, NO, VALUE_NAME, VALUE_TYPE, , value, POD, VAL1, VAL2)
751 //%PDDM-DEFINE TESTS_FOR_BOOL_KEY_OBJECT_VALUE(VALUE_NAME, VALUE_TYPE, VAL1, VAL2)
752 //%BOOL_TESTS_COMMON(Bool, BOOL, , , YES, NO, VALUE_NAME, VALUE_TYPE, Objects, object, OBJECT, VAL1, VAL2)
754 //%PDDM-DEFINE BOOL_TESTS_COMMON(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, VALUE_NAME, VALUE_TYPE, VSUFFIX, VNAME, VHELPER, VAL1, VAL2)
755 //%#pragma mark - KEY_NAME -> VALUE_NAME
757 //%@interface GPB##KEY_NAME##VALUE_NAME##DictionaryTests : XCTestCase
760 //%@implementation GPB##KEY_NAME##VALUE_NAME##DictionaryTests
762 //%- (void)testEmpty {
763 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
764 //% XCTAssertNotNil(dict);
765 //% XCTAssertEqual(dict.count, 0U);
766 //%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY1)
767 //% [dict enumerateKeysAnd##VALUE_NAME##sUsingBlock:^(__unused KEY_TYPE KisP##aKey, __unused VALUE_TYPE a##VNAME$u##, __unused BOOL *stop) {
768 //% XCTFail(@"Shouldn't get here!");
774 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
775 //% [dict set##VALUE_NAME$u##:VAL1 forKey:KEY1];
776 //% XCTAssertNotNil(dict);
777 //% XCTAssertEqual(dict.count, 1U);
778 //%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
779 //%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
780 //% [dict enumerateKeysAnd##VALUE_NAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u, BOOL *stop) {
781 //% XCTAssertEqual##KSUFFIX(aKey, KEY1);
782 //% XCTAssertEqual##VSUFFIX(a##VNAME$u, VAL1);
783 //% XCTAssertNotEqual(stop, NULL);
788 //%- (void)testBasics {
789 //% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
790 //% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
791 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
792 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
793 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
794 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
795 //% XCTAssertNotNil(dict);
796 //% XCTAssertEqual(dict.count, 2U);
797 //%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
798 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
800 //% __block NSUInteger idx = 0;
801 //% KEY_TYPE KisP##*seenKeys = malloc(2 * sizeof(KEY_TYPE##KisP));
802 //% VALUE_TYPE *seen##VNAME$u##s = malloc(2 * sizeof(VALUE_TYPE));
803 //% [dict enumerateKeysAnd##VALUE_NAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u##, BOOL *stop) {
804 //% XCTAssertLessThan(idx, 2U);
805 //% seenKeys[idx] = aKey;
806 //% seen##VNAME$u##s[idx] = a##VNAME$u;
807 //% XCTAssertNotEqual(stop, NULL);
810 //% for (int i = 0; i < 2; ++i) {
811 //% BOOL foundKey = NO;
812 //% for (int j = 0; (j < 2) && !foundKey; ++j) {
813 //% if (COMPARE_KEYS##KSUFFIX(kKeys[i], seenKeys[j])) {
815 //% XCTAssertEqual##VSUFFIX(k##VNAME$u##s[i], seen##VNAME$u##s[j], @"i = %d, j = %d", i, j);
818 //% XCTAssertTrue(foundKey, @"i = %d", i);
821 //% free(seen##VNAME$u##s);
823 //% // Stopping the enumeration.
825 //% [dict enumerateKeysAnd##VALUE_NAME$u##sUsingBlock:^(__unused KEY_TYPE KisP##aKey, __unused VALUE_TYPE a##VNAME$u##, BOOL *stop) {
826 //% if (idx == 0) *stop = YES;
827 //% XCTAssertNotEqual(idx, 2U);
833 //%- (void)testEquality {
834 //% const KEY_TYPE KisP##kKeys1[] = { KEY1, KEY2 };
835 //% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY1 };
836 //% const VALUE_TYPE k##VNAME$u##s1[] = { VAL1, VAL2 };
837 //% const VALUE_TYPE k##VNAME$u##s2[] = { VAL2, VAL1 };
838 //% const VALUE_TYPE k##VNAME$u##s3[] = { VAL2 };
839 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1 =
840 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s1
841 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys1
842 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s1)];
843 //% XCTAssertNotNil(dict1);
844 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1prime =
845 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s1
846 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys1
847 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s1)];
848 //% XCTAssertNotNil(dict1prime);
849 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
850 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s2
851 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys1
852 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s2)];
853 //% XCTAssertNotNil(dict2);
854 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict3 =
855 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s1
856 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys2
857 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s1)];
858 //% XCTAssertNotNil(dict3);
859 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict4 =
860 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s3
861 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys1
862 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s3)];
863 //% XCTAssertNotNil(dict4);
865 //% // 1/1Prime should be different objects, but equal.
866 //% XCTAssertNotEqual(dict1, dict1prime);
867 //% XCTAssertEqualObjects(dict1, dict1prime);
868 //% // Equal, so they must have same hash.
869 //% XCTAssertEqual([dict1 hash], [dict1prime hash]);
871 //% // 2 is same keys, different ##VNAME##s; not equal.
872 //% XCTAssertNotEqualObjects(dict1, dict2);
874 //% // 3 is different keys, same ##VNAME##s; not equal.
875 //% XCTAssertNotEqualObjects(dict1, dict3);
877 //% // 4 Fewer pairs; not equal
878 //% XCTAssertNotEqualObjects(dict1, dict4);
881 //% [dict1prime release];
887 //%- (void)testCopy {
888 //% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
889 //% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
890 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
891 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
892 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
893 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
894 //% XCTAssertNotNil(dict);
896 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 = [dict copy];
897 //% XCTAssertNotNil(dict2);
899 //% // Should be new object but equal.
900 //% XCTAssertNotEqual(dict, dict2);
901 //% XCTAssertEqualObjects(dict, dict2);
902 //% XCTAssertTrue([dict2 isKindOfClass:[GPB##KEY_NAME##VALUE_NAME##Dictionary class]]);
908 //%- (void)testDictionaryFromDictionary {
909 //% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
910 //% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
911 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
912 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
913 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
914 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
915 //% XCTAssertNotNil(dict);
917 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
918 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithDictionary:dict];
919 //% XCTAssertNotNil(dict2);
921 //% // Should be new pointer, but equal objects.
922 //% XCTAssertNotEqual(dict, dict2);
923 //% XCTAssertEqualObjects(dict, dict2);
928 //%- (void)testAdds {
929 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
930 //% XCTAssertNotNil(dict);
932 //% XCTAssertEqual(dict.count, 0U);
933 //% [dict set##VALUE_NAME:VAL1 forKey:KEY1];
934 //% XCTAssertEqual(dict.count, 1U);
936 //% const KEY_TYPE KisP##kKeys[] = { KEY2 };
937 //% const VALUE_TYPE k##VNAME$u##s[] = { VAL2 };
938 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
939 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
940 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
941 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
942 //% XCTAssertNotNil(dict2);
943 //% [dict addEntriesFromDictionary:dict2];
944 //% XCTAssertEqual(dict.count, 2U);
946 //%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
947 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
952 //%- (void)testRemove {
953 //% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2};
954 //% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
955 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
956 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s
957 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys
958 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s)];
959 //% XCTAssertNotNil(dict);
960 //% XCTAssertEqual(dict.count, 2U);
962 //% [dict remove##VALUE_NAME##ForKey:KEY2];
963 //% XCTAssertEqual(dict.count, 1U);
964 //%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
965 //%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
967 //% // Remove again does nothing.
968 //% [dict remove##VALUE_NAME##ForKey:KEY2];
969 //% XCTAssertEqual(dict.count, 1U);
970 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
971 //%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
973 //% [dict removeAll];
974 //% XCTAssertEqual(dict.count, 0U);
975 //%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY1)
976 //%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY2)
980 //%- (void)testInplaceMutation {
981 //% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
982 //% const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
983 //% 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)];
987 //% XCTAssertNotNil(dict);
988 //% XCTAssertEqual(dict.count, 2U);
989 //%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
990 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
992 //% [dict set##VALUE_NAME##:VAL2 forKey:KEY1];
993 //% XCTAssertEqual(dict.count, 2U);
994 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL2)
995 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
997 //% [dict set##VALUE_NAME##:VAL1 forKey:KEY2];
998 //% XCTAssertEqual(dict.count, 2U);
999 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL2)
1000 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL1)
1002 //% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY1 };
1003 //% const VALUE_TYPE k##VNAME$u##s2[] = { VAL2, VAL1 };
1004 //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
1005 //% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VALUE_NAME##s:k##VNAME$u##s2
1006 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## forKeys:kKeys2
1007 //% KEY_NAME$S VALUE_NAME$S ##VALUE_NAME$S## count:GPBARRAYSIZE(k##VNAME$u##s2)];
1008 //% XCTAssertNotNil(dict2);
1009 //% [dict addEntriesFromDictionary:dict2];
1010 //% XCTAssertEqual(dict.count, 2U);
1011 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1)
1012 //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2)
1014 //% [dict2 release];