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