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