• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Protocol Buffers - Google's data interchange format
2// Copyright 2015 Google Inc.  All rights reserved.
3//
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
7
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")
11
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)
23
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)
26
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)
29
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>
36
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
39//%
40//%@interface GPB##KEY_NAME##VALUE_NAME##DictionaryTests : XCTestCase
41//%@end
42//%
43//%@implementation GPB##KEY_NAME##VALUE_NAME##DictionaryTests
44//%
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!");
52//%  }];
53//%  [dict release];
54//%}
55//%
56//%- (void)testOne {
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);
67//%  }];
68//%  [dict release];
69//%}
70//%
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)
84//%
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);
93//%    ++idx;
94//%  }];
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])) {
99//%        foundKey = YES;
100//%        XCTAssertEqual##VSUFFIX(k##VNAME$u##s[i], seen##VNAME$u##s[j], @"i = %d, j = %d", i, j);
101//%      }
102//%    }
103//%    XCTAssertTrue(foundKey, @"i = %d", i);
104//%  }
105//%  free(seenKeys);
106//%  free(seen##VNAME$u##s);
107//%
108//%  // Stopping the enumeration.
109//%  idx = 0;
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);
113//%    ++idx;
114//%  }];
115//%  [dict release];
116//%}
117//%
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);
149//%
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]);
155//%
156//%  // 2 is same keys, different ##VNAME##s; not equal.
157//%  XCTAssertNotEqualObjects(dict1, dict2);
158//%
159//%  // 3 is different keys, same ##VNAME##s; not equal.
160//%  XCTAssertNotEqualObjects(dict1, dict3);
161//%
162//%  // 4 extra pair; not equal
163//%  XCTAssertNotEqualObjects(dict1, dict4);
164//%
165//%  [dict1 release];
166//%  [dict1prime release];
167//%  [dict2 release];
168//%  [dict3 release];
169//%  [dict4 release];
170//%}
171//%
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);
180//%
181//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 = [dict copy];
182//%  XCTAssertNotNil(dict2);
183//%
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]]);
188//%
189//%  [dict2 release];
190//%  [dict release];
191//%}
192//%
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);
201//%
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);
205//%
206//%  // Should be new pointer, but equal objects.
207//%  XCTAssertNotEqual(dict, dict2);
208//%  XCTAssertEqualObjects(dict, dict2);
209//%  [dict2 release];
210//%  [dict release];
211//%}
212//%
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);
216//%
217//%  XCTAssertEqual(dict.count, 0U);
218//%  [dict set##VALUE_NAME##:VAL1 forKey:KEY1];
219//%  XCTAssertEqual(dict.count, 1U);
220//%
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);
230//%
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)
235//%  [dict2 release];
236//%  [dict release];
237//%}
238//%
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);
248//%
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)
255//%
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)
263//%
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)
270//%
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)
277//%  [dict release];
278//%}
279//%
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)
293//%
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)
300//%
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)
307//%
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)
321//%
322//%  [dict2 release];
323//%  [dict release];
324//%}
325//%
326//%@end
327//%
328
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)
333//%
334//%@interface GPB##KEY_NAME##VALUE_NAME##DictionaryUnknownEnumTests : XCTestCase
335//%@end
336//%
337//%@implementation GPB##KEY_NAME##VALUE_NAME##DictionaryUnknownEnumTests
338//%
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)
355//%
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);
364//%    ++idx;
365//%  }];
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])) {
370//%        foundKey = YES;
371//%        if (i == 1) {
372//%          XCTAssertEqual##VSUFFIX(kGPBUnrecognizedEnumeratorValue, seenValues[j], @"i = %d, j = %d", i, j);
373//%        } else {
374//%          XCTAssertEqual##VSUFFIX(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
375//%        }
376//%      }
377//%    }
378//%    XCTAssertTrue(foundKey, @"i = %d", i);
379//%  }
380//%  idx = 0;
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);
386//%    ++idx;
387//%  }];
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])) {
392//%        foundKey = YES;
393//%        XCTAssertEqual##VSUFFIX(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
394//%      }
395//%    }
396//%    XCTAssertTrue(foundKey, @"i = %d", i);
397//%  }
398//%  free(seenKeys);
399//%  free(seenValues);
400//%
401//%  // Stopping the enumeration.
402//%  idx = 0;
403//%  [dict enumerateKeysAndRawValuesUsingBlock:^(__unused KEY_TYPE KisP##aKey, __unused VALUE_TYPE aValue, BOOL *stop) {
404//%    if (idx == 1) *stop = YES;
405//%    XCTAssertNotEqual(idx, 2U);
406//%    ++idx;
407//%  }];
408//%  [dict release];
409//%}
410//%
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);
447//%
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]);
453//%
454//%  // 2 is same keys, different values; not equal.
455//%  XCTAssertNotEqualObjects(dict1, dict2);
456//%
457//%  // 3 is different keys, same values; not equal.
458//%  XCTAssertNotEqualObjects(dict1, dict3);
459//%
460//%  // 4 extra pair; not equal
461//%  XCTAssertNotEqualObjects(dict1, dict4);
462//%
463//%  [dict1 release];
464//%  [dict1prime release];
465//%  [dict2 release];
466//%  [dict3 release];
467//%  [dict4 release];
468//%}
469//%
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);
479//%
480//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 = [dict copy];
481//%  XCTAssertNotNil(dict2);
482//%
483//%  // Should be new pointer, but equal objects.
484//%  XCTAssertNotEqual(dict, dict2);
485//%  XCTAssertEqual(dict.validationFunc, dict2.validationFunc);  // Pointer comparison
486//%  XCTAssertEqualObjects(dict, dict2);
487//%
488//%  [dict2 release];
489//%  [dict release];
490//%}
491//%
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);
501//%
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);
505//%
506//%  // Should be new pointer, but equal objects.
507//%  XCTAssertNotEqual(dict, dict2);
508//%  XCTAssertEqualObjects(dict, dict2);
509//%  XCTAssertEqual(dict.validationFunc, dict2.validationFunc);  // Pointer comparison
510//%  [dict2 release];
511//%  [dict release];
512//%}
513//%
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);
518//%
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);
525//%
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);
535//%
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)
542//%  [dict2 release];
543//%  [dict release];
544//%}
545//%
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);
556//%
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)
563//%
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)
571//%
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)
578//%
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)
585//%  [dict release];
586//%}
587//%
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)
602//%
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)
610//%
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)
617//%
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)
624//%
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)
639//%
640//%  [dict2 release];
641//%  [dict release];
642//%}
643//%
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);
653//%
654//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 = [dict copy];
655//%  XCTAssertNotNil(dict2);
656//%
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]]);
662//%
663//%  [dict2 release];
664//%  [dict release];
665//%}
666//%
667//%@end
668//%
669
670//
671// Helpers for PODs
672//
673
674//%PDDM-DEFINE DECLARE_VALUE_STORAGEPOD(VALUE_TYPE, NAME)
675//%  VALUE_TYPE NAME;
676//%
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)
684//%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);
691
692//
693// Helpers for Objects
694//
695
696//%PDDM-DEFINE DECLARE_VALUE_STORAGEOBJECT(VALUE_TYPE, NAME)
697// Empty
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]
704
705//
706// Helpers for tests.
707//
708
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;
715//%@end
716//%
717//%static BOOL TestingEnum_IsValidValue(int32_t value) {
718//%  switch (value) {
719//%    case 700:
720//%    case 701:
721//%    case 702:
722//%    case 703:
723//%      return YES;
724//%    default:
725//%      return NO;
726//%  }
727//%}
728//%
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
734//%                                rawValues:values
735//%                                  forKeys:keys
736//%                                    count:count];
737//%}
738//%@end
739//%
740//%
741
742
743//
744// BOOL test macros
745//
746//TODO: enum tests
747
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)
750
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)
753
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
756//%
757//%@interface GPB##KEY_NAME##VALUE_NAME##DictionaryTests : XCTestCase
758//%@end
759//%
760//%@implementation GPB##KEY_NAME##VALUE_NAME##DictionaryTests
761//%
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!");
769//%  }];
770//%  [dict release];
771//%}
772//%
773//%- (void)testOne {
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);
784//%  }];
785//%  [dict release];
786//%}
787//%
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)
799//%
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);
808//%    ++idx;
809//%  }];
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])) {
814//%        foundKey = YES;
815//%        XCTAssertEqual##VSUFFIX(k##VNAME$u##s[i], seen##VNAME$u##s[j], @"i = %d, j = %d", i, j);
816//%      }
817//%    }
818//%    XCTAssertTrue(foundKey, @"i = %d", i);
819//%  }
820//%  free(seenKeys);
821//%  free(seen##VNAME$u##s);
822//%
823//%  // Stopping the enumeration.
824//%  idx = 0;
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);
828//%    ++idx;
829//%  }];
830//%  [dict release];
831//%}
832//%
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);
864//%
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]);
870//%
871//%  // 2 is same keys, different ##VNAME##s; not equal.
872//%  XCTAssertNotEqualObjects(dict1, dict2);
873//%
874//%  // 3 is different keys, same ##VNAME##s; not equal.
875//%  XCTAssertNotEqualObjects(dict1, dict3);
876//%
877//%  // 4 Fewer pairs; not equal
878//%  XCTAssertNotEqualObjects(dict1, dict4);
879//%
880//%  [dict1 release];
881//%  [dict1prime release];
882//%  [dict2 release];
883//%  [dict3 release];
884//%  [dict4 release];
885//%}
886//%
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);
895//%
896//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 = [dict copy];
897//%  XCTAssertNotNil(dict2);
898//%
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]]);
903//%
904//%  [dict2 release];
905//%  [dict release];
906//%}
907//%
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);
916//%
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);
920//%
921//%  // Should be new pointer, but equal objects.
922//%  XCTAssertNotEqual(dict, dict2);
923//%  XCTAssertEqualObjects(dict, dict2);
924//%  [dict2 release];
925//%  [dict release];
926//%}
927//%
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);
931//%
932//%  XCTAssertEqual(dict.count, 0U);
933//%  [dict set##VALUE_NAME:VAL1 forKey:KEY1];
934//%  XCTAssertEqual(dict.count, 1U);
935//%
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);
945//%
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)
948//%  [dict2 release];
949//%  [dict release];
950//%}
951//%
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);
961//%
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)
966//%
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)
972//%
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)
977//%  [dict release];
978//%}
979//%
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)
991//%
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)
996//%
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)
1001//%
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)
1013//%
1014//%  [dict2 release];
1015//%  [dict release];
1016//%}
1017//%
1018//%@end
1019//%
1020
1021