• 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#import <Foundation/Foundation.h>
32#import <XCTest/XCTest.h>
33
34#import "GPBDictionary.h"
35
36#import "GPBTestUtilities.h"
37#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
38
39// Pull in the macros (using an external file because expanding all tests
40// in a single file makes a file that is failing to work with within Xcode.
41//%PDDM-IMPORT-DEFINES GPBDictionaryTests.pddm
42
43//%PDDM-EXPAND TESTS_FOR_POD_VALUES(String, NSString, *, Objects, @"foo", @"bar", @"baz", @"mumble")
44// This block of code is generated, do not edit it directly.
45// clang-format off
46
47// To let the testing macros work, add some extra methods to simplify things.
48@interface GPBStringEnumDictionary (TestingTweak)
49- (instancetype)initWithEnums:(const int32_t [])values
50                      forKeys:(const NSString * [])keys
51                        count:(NSUInteger)count;
52@end
53
54static BOOL TestingEnum_IsValidValue(int32_t value) {
55  switch (value) {
56    case 700:
57    case 701:
58    case 702:
59    case 703:
60      return YES;
61    default:
62      return NO;
63  }
64}
65
66@implementation GPBStringEnumDictionary (TestingTweak)
67- (instancetype)initWithEnums:(const int32_t [])values
68                      forKeys:(const NSString * [])keys
69                        count:(NSUInteger)count {
70  return [self initWithValidationFunction:TestingEnum_IsValidValue
71                                rawValues:values
72                                  forKeys:keys
73                                    count:count];
74}
75@end
76
77
78#pragma mark - String -> UInt32
79
80@interface GPBStringUInt32DictionaryTests : XCTestCase
81@end
82
83@implementation GPBStringUInt32DictionaryTests
84
85- (void)testEmpty {
86  GPBStringUInt32Dictionary *dict = [[GPBStringUInt32Dictionary alloc] init];
87  XCTAssertNotNil(dict);
88  XCTAssertEqual(dict.count, 0U);
89  XCTAssertFalse([dict getUInt32:NULL forKey:@"foo"]);
90  [dict enumerateKeysAndUInt32sUsingBlock:^(NSString *aKey, uint32_t aValue, BOOL *stop) {
91    #pragma unused(aKey, aValue, stop)
92    XCTFail(@"Shouldn't get here!");
93  }];
94  [dict release];
95}
96
97- (void)testOne {
98  GPBStringUInt32Dictionary *dict = [[GPBStringUInt32Dictionary alloc] init];
99  [dict setUInt32:100U forKey:@"foo"];
100  XCTAssertNotNil(dict);
101  XCTAssertEqual(dict.count, 1U);
102  uint32_t value;
103  XCTAssertTrue([dict getUInt32:NULL forKey:@"foo"]);
104  XCTAssertTrue([dict getUInt32:&value forKey:@"foo"]);
105  XCTAssertEqual(value, 100U);
106  XCTAssertFalse([dict getUInt32:NULL forKey:@"bar"]);
107  [dict enumerateKeysAndUInt32sUsingBlock:^(NSString *aKey, uint32_t aValue, BOOL *stop) {
108    XCTAssertEqualObjects(aKey, @"foo");
109    XCTAssertEqual(aValue, 100U);
110    XCTAssertNotEqual(stop, NULL);
111  }];
112  [dict release];
113}
114
115- (void)testBasics {
116  const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
117  const uint32_t kValues[] = { 100U, 101U, 102U };
118  GPBStringUInt32Dictionary *dict =
119      [[GPBStringUInt32Dictionary alloc] initWithUInt32s:kValues
120                                                 forKeys:kKeys
121                                                   count:GPBARRAYSIZE(kValues)];
122  XCTAssertNotNil(dict);
123  XCTAssertEqual(dict.count, 3U);
124  uint32_t value;
125  XCTAssertTrue([dict getUInt32:NULL forKey:@"foo"]);
126  XCTAssertTrue([dict getUInt32:&value forKey:@"foo"]);
127  XCTAssertEqual(value, 100U);
128  XCTAssertTrue([dict getUInt32:NULL forKey:@"bar"]);
129  XCTAssertTrue([dict getUInt32:&value forKey:@"bar"]);
130  XCTAssertEqual(value, 101U);
131  XCTAssertTrue([dict getUInt32:NULL forKey:@"baz"]);
132  XCTAssertTrue([dict getUInt32:&value forKey:@"baz"]);
133  XCTAssertEqual(value, 102U);
134  XCTAssertFalse([dict getUInt32:NULL forKey:@"mumble"]);
135
136  __block NSUInteger idx = 0;
137  NSString **seenKeys = malloc(3 * sizeof(NSString*));
138  uint32_t *seenValues = malloc(3 * sizeof(uint32_t));
139  [dict enumerateKeysAndUInt32sUsingBlock:^(NSString *aKey, uint32_t aValue, BOOL *stop) {
140    XCTAssertLessThan(idx, 3U);
141    seenKeys[idx] = aKey;
142    seenValues[idx] = aValue;
143    XCTAssertNotEqual(stop, NULL);
144    ++idx;
145  }];
146  for (int i = 0; i < 3; ++i) {
147    BOOL foundKey = NO;
148    for (int j = 0; (j < 3) && !foundKey; ++j) {
149      if ([kKeys[i] isEqual:seenKeys[j]]) {
150        foundKey = YES;
151        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
152      }
153    }
154    XCTAssertTrue(foundKey, @"i = %d", i);
155  }
156  free(seenKeys);
157  free(seenValues);
158
159  // Stopping the enumeration.
160  idx = 0;
161  [dict enumerateKeysAndUInt32sUsingBlock:^(NSString *aKey, uint32_t aValue, BOOL *stop) {
162    #pragma unused(aKey, aValue)
163    if (idx == 1) *stop = YES;
164    XCTAssertNotEqual(idx, 2U);
165    ++idx;
166  }];
167  [dict release];
168}
169
170- (void)testEquality {
171  const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
172  const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
173  const uint32_t kValues1[] = { 100U, 101U, 102U };
174  const uint32_t kValues2[] = { 100U, 103U, 102U };
175  const uint32_t kValues3[] = { 100U, 101U, 102U, 103U };
176  GPBStringUInt32Dictionary *dict1 =
177      [[GPBStringUInt32Dictionary alloc] initWithUInt32s:kValues1
178                                                 forKeys:kKeys1
179                                                   count:GPBARRAYSIZE(kValues1)];
180  XCTAssertNotNil(dict1);
181  GPBStringUInt32Dictionary *dict1prime =
182      [[GPBStringUInt32Dictionary alloc] initWithUInt32s:kValues1
183                                                 forKeys:kKeys1
184                                                   count:GPBARRAYSIZE(kValues1)];
185  XCTAssertNotNil(dict1prime);
186  GPBStringUInt32Dictionary *dict2 =
187      [[GPBStringUInt32Dictionary alloc] initWithUInt32s:kValues2
188                                                 forKeys:kKeys1
189                                                   count:GPBARRAYSIZE(kValues2)];
190  XCTAssertNotNil(dict2);
191  GPBStringUInt32Dictionary *dict3 =
192      [[GPBStringUInt32Dictionary alloc] initWithUInt32s:kValues1
193                                                 forKeys:kKeys2
194                                                   count:GPBARRAYSIZE(kValues1)];
195  XCTAssertNotNil(dict3);
196  GPBStringUInt32Dictionary *dict4 =
197      [[GPBStringUInt32Dictionary alloc] initWithUInt32s:kValues3
198                                                 forKeys:kKeys1
199                                                   count:GPBARRAYSIZE(kValues3)];
200  XCTAssertNotNil(dict4);
201
202  // 1/1Prime should be different objects, but equal.
203  XCTAssertNotEqual(dict1, dict1prime);
204  XCTAssertEqualObjects(dict1, dict1prime);
205  // Equal, so they must have same hash.
206  XCTAssertEqual([dict1 hash], [dict1prime hash]);
207
208  // 2 is same keys, different values; not equal.
209  XCTAssertNotEqualObjects(dict1, dict2);
210
211  // 3 is different keys, same values; not equal.
212  XCTAssertNotEqualObjects(dict1, dict3);
213
214  // 4 extra pair; not equal
215  XCTAssertNotEqualObjects(dict1, dict4);
216
217  [dict1 release];
218  [dict1prime release];
219  [dict2 release];
220  [dict3 release];
221  [dict4 release];
222}
223
224- (void)testCopy {
225  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
226  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
227  GPBStringUInt32Dictionary *dict =
228      [[GPBStringUInt32Dictionary alloc] initWithUInt32s:kValues
229                                                 forKeys:kKeys
230                                                   count:GPBARRAYSIZE(kValues)];
231  XCTAssertNotNil(dict);
232
233  GPBStringUInt32Dictionary *dict2 = [dict copy];
234  XCTAssertNotNil(dict2);
235
236  // Should be new object but equal.
237  XCTAssertNotEqual(dict, dict2);
238  XCTAssertEqualObjects(dict, dict2);
239  XCTAssertTrue([dict2 isKindOfClass:[GPBStringUInt32Dictionary class]]);
240
241  [dict2 release];
242  [dict release];
243}
244
245- (void)testDictionaryFromDictionary {
246  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
247  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
248  GPBStringUInt32Dictionary *dict =
249      [[GPBStringUInt32Dictionary alloc] initWithUInt32s:kValues
250                                                 forKeys:kKeys
251                                                   count:GPBARRAYSIZE(kValues)];
252  XCTAssertNotNil(dict);
253
254  GPBStringUInt32Dictionary *dict2 =
255      [[GPBStringUInt32Dictionary alloc] initWithDictionary:dict];
256  XCTAssertNotNil(dict2);
257
258  // Should be new pointer, but equal objects.
259  XCTAssertNotEqual(dict, dict2);
260  XCTAssertEqualObjects(dict, dict2);
261  [dict2 release];
262  [dict release];
263}
264
265- (void)testAdds {
266  GPBStringUInt32Dictionary *dict = [[GPBStringUInt32Dictionary alloc] init];
267  XCTAssertNotNil(dict);
268
269  XCTAssertEqual(dict.count, 0U);
270  [dict setUInt32:100U forKey:@"foo"];
271  XCTAssertEqual(dict.count, 1U);
272
273  const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
274  const uint32_t kValues[] = { 101U, 102U, 103U };
275  GPBStringUInt32Dictionary *dict2 =
276      [[GPBStringUInt32Dictionary alloc] initWithUInt32s:kValues
277                                                 forKeys:kKeys
278                                                   count:GPBARRAYSIZE(kValues)];
279  XCTAssertNotNil(dict2);
280  [dict addEntriesFromDictionary:dict2];
281  XCTAssertEqual(dict.count, 4U);
282
283  uint32_t value;
284  XCTAssertTrue([dict getUInt32:NULL forKey:@"foo"]);
285  XCTAssertTrue([dict getUInt32:&value forKey:@"foo"]);
286  XCTAssertEqual(value, 100U);
287  XCTAssertTrue([dict getUInt32:NULL forKey:@"bar"]);
288  XCTAssertTrue([dict getUInt32:&value forKey:@"bar"]);
289  XCTAssertEqual(value, 101U);
290  XCTAssertTrue([dict getUInt32:NULL forKey:@"baz"]);
291  XCTAssertTrue([dict getUInt32:&value forKey:@"baz"]);
292  XCTAssertEqual(value, 102U);
293  XCTAssertTrue([dict getUInt32:NULL forKey:@"mumble"]);
294  XCTAssertTrue([dict getUInt32:&value forKey:@"mumble"]);
295  XCTAssertEqual(value, 103U);
296  [dict2 release];
297  [dict release];
298}
299
300- (void)testRemove {
301  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
302  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
303  GPBStringUInt32Dictionary *dict =
304      [[GPBStringUInt32Dictionary alloc] initWithUInt32s:kValues
305                                                 forKeys:kKeys
306                                                   count:GPBARRAYSIZE(kValues)];
307  XCTAssertNotNil(dict);
308  XCTAssertEqual(dict.count, 4U);
309
310  [dict removeUInt32ForKey:@"bar"];
311  XCTAssertEqual(dict.count, 3U);
312  uint32_t value;
313  XCTAssertTrue([dict getUInt32:NULL forKey:@"foo"]);
314  XCTAssertTrue([dict getUInt32:&value forKey:@"foo"]);
315  XCTAssertEqual(value, 100U);
316  XCTAssertFalse([dict getUInt32:NULL forKey:@"bar"]);
317  XCTAssertTrue([dict getUInt32:NULL forKey:@"baz"]);
318  XCTAssertTrue([dict getUInt32:&value forKey:@"baz"]);
319  XCTAssertEqual(value, 102U);
320  XCTAssertTrue([dict getUInt32:NULL forKey:@"mumble"]);
321  XCTAssertTrue([dict getUInt32:&value forKey:@"mumble"]);
322  XCTAssertEqual(value, 103U);
323
324  // Remove again does nothing.
325  [dict removeUInt32ForKey:@"bar"];
326  XCTAssertEqual(dict.count, 3U);
327  XCTAssertTrue([dict getUInt32:NULL forKey:@"foo"]);
328  XCTAssertTrue([dict getUInt32:&value forKey:@"foo"]);
329  XCTAssertEqual(value, 100U);
330  XCTAssertFalse([dict getUInt32:NULL forKey:@"bar"]);
331  XCTAssertTrue([dict getUInt32:NULL forKey:@"baz"]);
332  XCTAssertTrue([dict getUInt32:&value forKey:@"baz"]);
333  XCTAssertEqual(value, 102U);
334  XCTAssertTrue([dict getUInt32:NULL forKey:@"mumble"]);
335  XCTAssertTrue([dict getUInt32:&value forKey:@"mumble"]);
336  XCTAssertEqual(value, 103U);
337
338  [dict removeUInt32ForKey:@"mumble"];
339  XCTAssertEqual(dict.count, 2U);
340  XCTAssertTrue([dict getUInt32:NULL forKey:@"foo"]);
341  XCTAssertTrue([dict getUInt32:&value forKey:@"foo"]);
342  XCTAssertEqual(value, 100U);
343  XCTAssertFalse([dict getUInt32:NULL forKey:@"bar"]);
344  XCTAssertTrue([dict getUInt32:NULL forKey:@"baz"]);
345  XCTAssertTrue([dict getUInt32:&value forKey:@"baz"]);
346  XCTAssertEqual(value, 102U);
347  XCTAssertFalse([dict getUInt32:NULL forKey:@"mumble"]);
348
349  [dict removeAll];
350  XCTAssertEqual(dict.count, 0U);
351  XCTAssertFalse([dict getUInt32:NULL forKey:@"foo"]);
352  XCTAssertFalse([dict getUInt32:NULL forKey:@"bar"]);
353  XCTAssertFalse([dict getUInt32:NULL forKey:@"baz"]);
354  XCTAssertFalse([dict getUInt32:NULL forKey:@"mumble"]);
355  [dict release];
356}
357
358- (void)testInplaceMutation {
359  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
360  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
361  GPBStringUInt32Dictionary *dict =
362      [[GPBStringUInt32Dictionary alloc] initWithUInt32s:kValues
363                                                 forKeys:kKeys
364                                                   count:GPBARRAYSIZE(kValues)];
365  XCTAssertNotNil(dict);
366  XCTAssertEqual(dict.count, 4U);
367  uint32_t value;
368  XCTAssertTrue([dict getUInt32:NULL forKey:@"foo"]);
369  XCTAssertTrue([dict getUInt32:&value forKey:@"foo"]);
370  XCTAssertEqual(value, 100U);
371  XCTAssertTrue([dict getUInt32:NULL forKey:@"bar"]);
372  XCTAssertTrue([dict getUInt32:&value forKey:@"bar"]);
373  XCTAssertEqual(value, 101U);
374  XCTAssertTrue([dict getUInt32:NULL forKey:@"baz"]);
375  XCTAssertTrue([dict getUInt32:&value forKey:@"baz"]);
376  XCTAssertEqual(value, 102U);
377  XCTAssertTrue([dict getUInt32:NULL forKey:@"mumble"]);
378  XCTAssertTrue([dict getUInt32:&value forKey:@"mumble"]);
379  XCTAssertEqual(value, 103U);
380
381  [dict setUInt32:103U forKey:@"foo"];
382  XCTAssertEqual(dict.count, 4U);
383  XCTAssertTrue([dict getUInt32:NULL forKey:@"foo"]);
384  XCTAssertTrue([dict getUInt32:&value forKey:@"foo"]);
385  XCTAssertEqual(value, 103U);
386  XCTAssertTrue([dict getUInt32:NULL forKey:@"bar"]);
387  XCTAssertTrue([dict getUInt32:&value forKey:@"bar"]);
388  XCTAssertEqual(value, 101U);
389  XCTAssertTrue([dict getUInt32:NULL forKey:@"baz"]);
390  XCTAssertTrue([dict getUInt32:&value forKey:@"baz"]);
391  XCTAssertEqual(value, 102U);
392  XCTAssertTrue([dict getUInt32:NULL forKey:@"mumble"]);
393  XCTAssertTrue([dict getUInt32:&value forKey:@"mumble"]);
394  XCTAssertEqual(value, 103U);
395
396  [dict setUInt32:101U forKey:@"mumble"];
397  XCTAssertEqual(dict.count, 4U);
398  XCTAssertTrue([dict getUInt32:NULL forKey:@"foo"]);
399  XCTAssertTrue([dict getUInt32:&value forKey:@"foo"]);
400  XCTAssertEqual(value, 103U);
401  XCTAssertTrue([dict getUInt32:NULL forKey:@"bar"]);
402  XCTAssertTrue([dict getUInt32:&value forKey:@"bar"]);
403  XCTAssertEqual(value, 101U);
404  XCTAssertTrue([dict getUInt32:NULL forKey:@"baz"]);
405  XCTAssertTrue([dict getUInt32:&value forKey:@"baz"]);
406  XCTAssertEqual(value, 102U);
407  XCTAssertTrue([dict getUInt32:NULL forKey:@"mumble"]);
408  XCTAssertTrue([dict getUInt32:&value forKey:@"mumble"]);
409  XCTAssertEqual(value, 101U);
410
411  const NSString *kKeys2[] = { @"bar", @"baz" };
412  const uint32_t kValues2[] = { 102U, 100U };
413  GPBStringUInt32Dictionary *dict2 =
414      [[GPBStringUInt32Dictionary alloc] initWithUInt32s:kValues2
415                                                 forKeys:kKeys2
416                                                   count:GPBARRAYSIZE(kValues2)];
417  XCTAssertNotNil(dict2);
418  [dict addEntriesFromDictionary:dict2];
419  XCTAssertEqual(dict.count, 4U);
420  XCTAssertTrue([dict getUInt32:NULL forKey:@"foo"]);
421  XCTAssertTrue([dict getUInt32:&value forKey:@"foo"]);
422  XCTAssertEqual(value, 103U);
423  XCTAssertTrue([dict getUInt32:NULL forKey:@"bar"]);
424  XCTAssertTrue([dict getUInt32:&value forKey:@"bar"]);
425  XCTAssertEqual(value, 102U);
426  XCTAssertTrue([dict getUInt32:NULL forKey:@"baz"]);
427  XCTAssertTrue([dict getUInt32:&value forKey:@"baz"]);
428  XCTAssertEqual(value, 100U);
429  XCTAssertTrue([dict getUInt32:NULL forKey:@"mumble"]);
430  XCTAssertTrue([dict getUInt32:&value forKey:@"mumble"]);
431  XCTAssertEqual(value, 101U);
432
433  [dict2 release];
434  [dict release];
435}
436
437@end
438
439#pragma mark - String -> Int32
440
441@interface GPBStringInt32DictionaryTests : XCTestCase
442@end
443
444@implementation GPBStringInt32DictionaryTests
445
446- (void)testEmpty {
447  GPBStringInt32Dictionary *dict = [[GPBStringInt32Dictionary alloc] init];
448  XCTAssertNotNil(dict);
449  XCTAssertEqual(dict.count, 0U);
450  XCTAssertFalse([dict getInt32:NULL forKey:@"foo"]);
451  [dict enumerateKeysAndInt32sUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
452    #pragma unused(aKey, aValue, stop)
453    XCTFail(@"Shouldn't get here!");
454  }];
455  [dict release];
456}
457
458- (void)testOne {
459  GPBStringInt32Dictionary *dict = [[GPBStringInt32Dictionary alloc] init];
460  [dict setInt32:200 forKey:@"foo"];
461  XCTAssertNotNil(dict);
462  XCTAssertEqual(dict.count, 1U);
463  int32_t value;
464  XCTAssertTrue([dict getInt32:NULL forKey:@"foo"]);
465  XCTAssertTrue([dict getInt32:&value forKey:@"foo"]);
466  XCTAssertEqual(value, 200);
467  XCTAssertFalse([dict getInt32:NULL forKey:@"bar"]);
468  [dict enumerateKeysAndInt32sUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
469    XCTAssertEqualObjects(aKey, @"foo");
470    XCTAssertEqual(aValue, 200);
471    XCTAssertNotEqual(stop, NULL);
472  }];
473  [dict release];
474}
475
476- (void)testBasics {
477  const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
478  const int32_t kValues[] = { 200, 201, 202 };
479  GPBStringInt32Dictionary *dict =
480      [[GPBStringInt32Dictionary alloc] initWithInt32s:kValues
481                                               forKeys:kKeys
482                                                 count:GPBARRAYSIZE(kValues)];
483  XCTAssertNotNil(dict);
484  XCTAssertEqual(dict.count, 3U);
485  int32_t value;
486  XCTAssertTrue([dict getInt32:NULL forKey:@"foo"]);
487  XCTAssertTrue([dict getInt32:&value forKey:@"foo"]);
488  XCTAssertEqual(value, 200);
489  XCTAssertTrue([dict getInt32:NULL forKey:@"bar"]);
490  XCTAssertTrue([dict getInt32:&value forKey:@"bar"]);
491  XCTAssertEqual(value, 201);
492  XCTAssertTrue([dict getInt32:NULL forKey:@"baz"]);
493  XCTAssertTrue([dict getInt32:&value forKey:@"baz"]);
494  XCTAssertEqual(value, 202);
495  XCTAssertFalse([dict getInt32:NULL forKey:@"mumble"]);
496
497  __block NSUInteger idx = 0;
498  NSString **seenKeys = malloc(3 * sizeof(NSString*));
499  int32_t *seenValues = malloc(3 * sizeof(int32_t));
500  [dict enumerateKeysAndInt32sUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
501    XCTAssertLessThan(idx, 3U);
502    seenKeys[idx] = aKey;
503    seenValues[idx] = aValue;
504    XCTAssertNotEqual(stop, NULL);
505    ++idx;
506  }];
507  for (int i = 0; i < 3; ++i) {
508    BOOL foundKey = NO;
509    for (int j = 0; (j < 3) && !foundKey; ++j) {
510      if ([kKeys[i] isEqual:seenKeys[j]]) {
511        foundKey = YES;
512        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
513      }
514    }
515    XCTAssertTrue(foundKey, @"i = %d", i);
516  }
517  free(seenKeys);
518  free(seenValues);
519
520  // Stopping the enumeration.
521  idx = 0;
522  [dict enumerateKeysAndInt32sUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
523    #pragma unused(aKey, aValue)
524    if (idx == 1) *stop = YES;
525    XCTAssertNotEqual(idx, 2U);
526    ++idx;
527  }];
528  [dict release];
529}
530
531- (void)testEquality {
532  const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
533  const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
534  const int32_t kValues1[] = { 200, 201, 202 };
535  const int32_t kValues2[] = { 200, 203, 202 };
536  const int32_t kValues3[] = { 200, 201, 202, 203 };
537  GPBStringInt32Dictionary *dict1 =
538      [[GPBStringInt32Dictionary alloc] initWithInt32s:kValues1
539                                               forKeys:kKeys1
540                                                 count:GPBARRAYSIZE(kValues1)];
541  XCTAssertNotNil(dict1);
542  GPBStringInt32Dictionary *dict1prime =
543      [[GPBStringInt32Dictionary alloc] initWithInt32s:kValues1
544                                               forKeys:kKeys1
545                                                 count:GPBARRAYSIZE(kValues1)];
546  XCTAssertNotNil(dict1prime);
547  GPBStringInt32Dictionary *dict2 =
548      [[GPBStringInt32Dictionary alloc] initWithInt32s:kValues2
549                                               forKeys:kKeys1
550                                                 count:GPBARRAYSIZE(kValues2)];
551  XCTAssertNotNil(dict2);
552  GPBStringInt32Dictionary *dict3 =
553      [[GPBStringInt32Dictionary alloc] initWithInt32s:kValues1
554                                               forKeys:kKeys2
555                                                 count:GPBARRAYSIZE(kValues1)];
556  XCTAssertNotNil(dict3);
557  GPBStringInt32Dictionary *dict4 =
558      [[GPBStringInt32Dictionary alloc] initWithInt32s:kValues3
559                                               forKeys:kKeys1
560                                                 count:GPBARRAYSIZE(kValues3)];
561  XCTAssertNotNil(dict4);
562
563  // 1/1Prime should be different objects, but equal.
564  XCTAssertNotEqual(dict1, dict1prime);
565  XCTAssertEqualObjects(dict1, dict1prime);
566  // Equal, so they must have same hash.
567  XCTAssertEqual([dict1 hash], [dict1prime hash]);
568
569  // 2 is same keys, different values; not equal.
570  XCTAssertNotEqualObjects(dict1, dict2);
571
572  // 3 is different keys, same values; not equal.
573  XCTAssertNotEqualObjects(dict1, dict3);
574
575  // 4 extra pair; not equal
576  XCTAssertNotEqualObjects(dict1, dict4);
577
578  [dict1 release];
579  [dict1prime release];
580  [dict2 release];
581  [dict3 release];
582  [dict4 release];
583}
584
585- (void)testCopy {
586  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
587  const int32_t kValues[] = { 200, 201, 202, 203 };
588  GPBStringInt32Dictionary *dict =
589      [[GPBStringInt32Dictionary alloc] initWithInt32s:kValues
590                                               forKeys:kKeys
591                                                 count:GPBARRAYSIZE(kValues)];
592  XCTAssertNotNil(dict);
593
594  GPBStringInt32Dictionary *dict2 = [dict copy];
595  XCTAssertNotNil(dict2);
596
597  // Should be new object but equal.
598  XCTAssertNotEqual(dict, dict2);
599  XCTAssertEqualObjects(dict, dict2);
600  XCTAssertTrue([dict2 isKindOfClass:[GPBStringInt32Dictionary class]]);
601
602  [dict2 release];
603  [dict release];
604}
605
606- (void)testDictionaryFromDictionary {
607  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
608  const int32_t kValues[] = { 200, 201, 202, 203 };
609  GPBStringInt32Dictionary *dict =
610      [[GPBStringInt32Dictionary alloc] initWithInt32s:kValues
611                                               forKeys:kKeys
612                                                 count:GPBARRAYSIZE(kValues)];
613  XCTAssertNotNil(dict);
614
615  GPBStringInt32Dictionary *dict2 =
616      [[GPBStringInt32Dictionary alloc] initWithDictionary:dict];
617  XCTAssertNotNil(dict2);
618
619  // Should be new pointer, but equal objects.
620  XCTAssertNotEqual(dict, dict2);
621  XCTAssertEqualObjects(dict, dict2);
622  [dict2 release];
623  [dict release];
624}
625
626- (void)testAdds {
627  GPBStringInt32Dictionary *dict = [[GPBStringInt32Dictionary alloc] init];
628  XCTAssertNotNil(dict);
629
630  XCTAssertEqual(dict.count, 0U);
631  [dict setInt32:200 forKey:@"foo"];
632  XCTAssertEqual(dict.count, 1U);
633
634  const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
635  const int32_t kValues[] = { 201, 202, 203 };
636  GPBStringInt32Dictionary *dict2 =
637      [[GPBStringInt32Dictionary alloc] initWithInt32s:kValues
638                                               forKeys:kKeys
639                                                 count:GPBARRAYSIZE(kValues)];
640  XCTAssertNotNil(dict2);
641  [dict addEntriesFromDictionary:dict2];
642  XCTAssertEqual(dict.count, 4U);
643
644  int32_t value;
645  XCTAssertTrue([dict getInt32:NULL forKey:@"foo"]);
646  XCTAssertTrue([dict getInt32:&value forKey:@"foo"]);
647  XCTAssertEqual(value, 200);
648  XCTAssertTrue([dict getInt32:NULL forKey:@"bar"]);
649  XCTAssertTrue([dict getInt32:&value forKey:@"bar"]);
650  XCTAssertEqual(value, 201);
651  XCTAssertTrue([dict getInt32:NULL forKey:@"baz"]);
652  XCTAssertTrue([dict getInt32:&value forKey:@"baz"]);
653  XCTAssertEqual(value, 202);
654  XCTAssertTrue([dict getInt32:NULL forKey:@"mumble"]);
655  XCTAssertTrue([dict getInt32:&value forKey:@"mumble"]);
656  XCTAssertEqual(value, 203);
657  [dict2 release];
658  [dict release];
659}
660
661- (void)testRemove {
662  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
663  const int32_t kValues[] = { 200, 201, 202, 203 };
664  GPBStringInt32Dictionary *dict =
665      [[GPBStringInt32Dictionary alloc] initWithInt32s:kValues
666                                               forKeys:kKeys
667                                                 count:GPBARRAYSIZE(kValues)];
668  XCTAssertNotNil(dict);
669  XCTAssertEqual(dict.count, 4U);
670
671  [dict removeInt32ForKey:@"bar"];
672  XCTAssertEqual(dict.count, 3U);
673  int32_t value;
674  XCTAssertTrue([dict getInt32:NULL forKey:@"foo"]);
675  XCTAssertTrue([dict getInt32:&value forKey:@"foo"]);
676  XCTAssertEqual(value, 200);
677  XCTAssertFalse([dict getInt32:NULL forKey:@"bar"]);
678  XCTAssertTrue([dict getInt32:NULL forKey:@"baz"]);
679  XCTAssertTrue([dict getInt32:&value forKey:@"baz"]);
680  XCTAssertEqual(value, 202);
681  XCTAssertTrue([dict getInt32:NULL forKey:@"mumble"]);
682  XCTAssertTrue([dict getInt32:&value forKey:@"mumble"]);
683  XCTAssertEqual(value, 203);
684
685  // Remove again does nothing.
686  [dict removeInt32ForKey:@"bar"];
687  XCTAssertEqual(dict.count, 3U);
688  XCTAssertTrue([dict getInt32:NULL forKey:@"foo"]);
689  XCTAssertTrue([dict getInt32:&value forKey:@"foo"]);
690  XCTAssertEqual(value, 200);
691  XCTAssertFalse([dict getInt32:NULL forKey:@"bar"]);
692  XCTAssertTrue([dict getInt32:NULL forKey:@"baz"]);
693  XCTAssertTrue([dict getInt32:&value forKey:@"baz"]);
694  XCTAssertEqual(value, 202);
695  XCTAssertTrue([dict getInt32:NULL forKey:@"mumble"]);
696  XCTAssertTrue([dict getInt32:&value forKey:@"mumble"]);
697  XCTAssertEqual(value, 203);
698
699  [dict removeInt32ForKey:@"mumble"];
700  XCTAssertEqual(dict.count, 2U);
701  XCTAssertTrue([dict getInt32:NULL forKey:@"foo"]);
702  XCTAssertTrue([dict getInt32:&value forKey:@"foo"]);
703  XCTAssertEqual(value, 200);
704  XCTAssertFalse([dict getInt32:NULL forKey:@"bar"]);
705  XCTAssertTrue([dict getInt32:NULL forKey:@"baz"]);
706  XCTAssertTrue([dict getInt32:&value forKey:@"baz"]);
707  XCTAssertEqual(value, 202);
708  XCTAssertFalse([dict getInt32:NULL forKey:@"mumble"]);
709
710  [dict removeAll];
711  XCTAssertEqual(dict.count, 0U);
712  XCTAssertFalse([dict getInt32:NULL forKey:@"foo"]);
713  XCTAssertFalse([dict getInt32:NULL forKey:@"bar"]);
714  XCTAssertFalse([dict getInt32:NULL forKey:@"baz"]);
715  XCTAssertFalse([dict getInt32:NULL forKey:@"mumble"]);
716  [dict release];
717}
718
719- (void)testInplaceMutation {
720  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
721  const int32_t kValues[] = { 200, 201, 202, 203 };
722  GPBStringInt32Dictionary *dict =
723      [[GPBStringInt32Dictionary alloc] initWithInt32s:kValues
724                                               forKeys:kKeys
725                                                 count:GPBARRAYSIZE(kValues)];
726  XCTAssertNotNil(dict);
727  XCTAssertEqual(dict.count, 4U);
728  int32_t value;
729  XCTAssertTrue([dict getInt32:NULL forKey:@"foo"]);
730  XCTAssertTrue([dict getInt32:&value forKey:@"foo"]);
731  XCTAssertEqual(value, 200);
732  XCTAssertTrue([dict getInt32:NULL forKey:@"bar"]);
733  XCTAssertTrue([dict getInt32:&value forKey:@"bar"]);
734  XCTAssertEqual(value, 201);
735  XCTAssertTrue([dict getInt32:NULL forKey:@"baz"]);
736  XCTAssertTrue([dict getInt32:&value forKey:@"baz"]);
737  XCTAssertEqual(value, 202);
738  XCTAssertTrue([dict getInt32:NULL forKey:@"mumble"]);
739  XCTAssertTrue([dict getInt32:&value forKey:@"mumble"]);
740  XCTAssertEqual(value, 203);
741
742  [dict setInt32:203 forKey:@"foo"];
743  XCTAssertEqual(dict.count, 4U);
744  XCTAssertTrue([dict getInt32:NULL forKey:@"foo"]);
745  XCTAssertTrue([dict getInt32:&value forKey:@"foo"]);
746  XCTAssertEqual(value, 203);
747  XCTAssertTrue([dict getInt32:NULL forKey:@"bar"]);
748  XCTAssertTrue([dict getInt32:&value forKey:@"bar"]);
749  XCTAssertEqual(value, 201);
750  XCTAssertTrue([dict getInt32:NULL forKey:@"baz"]);
751  XCTAssertTrue([dict getInt32:&value forKey:@"baz"]);
752  XCTAssertEqual(value, 202);
753  XCTAssertTrue([dict getInt32:NULL forKey:@"mumble"]);
754  XCTAssertTrue([dict getInt32:&value forKey:@"mumble"]);
755  XCTAssertEqual(value, 203);
756
757  [dict setInt32:201 forKey:@"mumble"];
758  XCTAssertEqual(dict.count, 4U);
759  XCTAssertTrue([dict getInt32:NULL forKey:@"foo"]);
760  XCTAssertTrue([dict getInt32:&value forKey:@"foo"]);
761  XCTAssertEqual(value, 203);
762  XCTAssertTrue([dict getInt32:NULL forKey:@"bar"]);
763  XCTAssertTrue([dict getInt32:&value forKey:@"bar"]);
764  XCTAssertEqual(value, 201);
765  XCTAssertTrue([dict getInt32:NULL forKey:@"baz"]);
766  XCTAssertTrue([dict getInt32:&value forKey:@"baz"]);
767  XCTAssertEqual(value, 202);
768  XCTAssertTrue([dict getInt32:NULL forKey:@"mumble"]);
769  XCTAssertTrue([dict getInt32:&value forKey:@"mumble"]);
770  XCTAssertEqual(value, 201);
771
772  const NSString *kKeys2[] = { @"bar", @"baz" };
773  const int32_t kValues2[] = { 202, 200 };
774  GPBStringInt32Dictionary *dict2 =
775      [[GPBStringInt32Dictionary alloc] initWithInt32s:kValues2
776                                               forKeys:kKeys2
777                                                 count:GPBARRAYSIZE(kValues2)];
778  XCTAssertNotNil(dict2);
779  [dict addEntriesFromDictionary:dict2];
780  XCTAssertEqual(dict.count, 4U);
781  XCTAssertTrue([dict getInt32:NULL forKey:@"foo"]);
782  XCTAssertTrue([dict getInt32:&value forKey:@"foo"]);
783  XCTAssertEqual(value, 203);
784  XCTAssertTrue([dict getInt32:NULL forKey:@"bar"]);
785  XCTAssertTrue([dict getInt32:&value forKey:@"bar"]);
786  XCTAssertEqual(value, 202);
787  XCTAssertTrue([dict getInt32:NULL forKey:@"baz"]);
788  XCTAssertTrue([dict getInt32:&value forKey:@"baz"]);
789  XCTAssertEqual(value, 200);
790  XCTAssertTrue([dict getInt32:NULL forKey:@"mumble"]);
791  XCTAssertTrue([dict getInt32:&value forKey:@"mumble"]);
792  XCTAssertEqual(value, 201);
793
794  [dict2 release];
795  [dict release];
796}
797
798@end
799
800#pragma mark - String -> UInt64
801
802@interface GPBStringUInt64DictionaryTests : XCTestCase
803@end
804
805@implementation GPBStringUInt64DictionaryTests
806
807- (void)testEmpty {
808  GPBStringUInt64Dictionary *dict = [[GPBStringUInt64Dictionary alloc] init];
809  XCTAssertNotNil(dict);
810  XCTAssertEqual(dict.count, 0U);
811  XCTAssertFalse([dict getUInt64:NULL forKey:@"foo"]);
812  [dict enumerateKeysAndUInt64sUsingBlock:^(NSString *aKey, uint64_t aValue, BOOL *stop) {
813    #pragma unused(aKey, aValue, stop)
814    XCTFail(@"Shouldn't get here!");
815  }];
816  [dict release];
817}
818
819- (void)testOne {
820  GPBStringUInt64Dictionary *dict = [[GPBStringUInt64Dictionary alloc] init];
821  [dict setUInt64:300U forKey:@"foo"];
822  XCTAssertNotNil(dict);
823  XCTAssertEqual(dict.count, 1U);
824  uint64_t value;
825  XCTAssertTrue([dict getUInt64:NULL forKey:@"foo"]);
826  XCTAssertTrue([dict getUInt64:&value forKey:@"foo"]);
827  XCTAssertEqual(value, 300U);
828  XCTAssertFalse([dict getUInt64:NULL forKey:@"bar"]);
829  [dict enumerateKeysAndUInt64sUsingBlock:^(NSString *aKey, uint64_t aValue, BOOL *stop) {
830    XCTAssertEqualObjects(aKey, @"foo");
831    XCTAssertEqual(aValue, 300U);
832    XCTAssertNotEqual(stop, NULL);
833  }];
834  [dict release];
835}
836
837- (void)testBasics {
838  const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
839  const uint64_t kValues[] = { 300U, 301U, 302U };
840  GPBStringUInt64Dictionary *dict =
841      [[GPBStringUInt64Dictionary alloc] initWithUInt64s:kValues
842                                                 forKeys:kKeys
843                                                   count:GPBARRAYSIZE(kValues)];
844  XCTAssertNotNil(dict);
845  XCTAssertEqual(dict.count, 3U);
846  uint64_t value;
847  XCTAssertTrue([dict getUInt64:NULL forKey:@"foo"]);
848  XCTAssertTrue([dict getUInt64:&value forKey:@"foo"]);
849  XCTAssertEqual(value, 300U);
850  XCTAssertTrue([dict getUInt64:NULL forKey:@"bar"]);
851  XCTAssertTrue([dict getUInt64:&value forKey:@"bar"]);
852  XCTAssertEqual(value, 301U);
853  XCTAssertTrue([dict getUInt64:NULL forKey:@"baz"]);
854  XCTAssertTrue([dict getUInt64:&value forKey:@"baz"]);
855  XCTAssertEqual(value, 302U);
856  XCTAssertFalse([dict getUInt64:NULL forKey:@"mumble"]);
857
858  __block NSUInteger idx = 0;
859  NSString **seenKeys = malloc(3 * sizeof(NSString*));
860  uint64_t *seenValues = malloc(3 * sizeof(uint64_t));
861  [dict enumerateKeysAndUInt64sUsingBlock:^(NSString *aKey, uint64_t aValue, BOOL *stop) {
862    XCTAssertLessThan(idx, 3U);
863    seenKeys[idx] = aKey;
864    seenValues[idx] = aValue;
865    XCTAssertNotEqual(stop, NULL);
866    ++idx;
867  }];
868  for (int i = 0; i < 3; ++i) {
869    BOOL foundKey = NO;
870    for (int j = 0; (j < 3) && !foundKey; ++j) {
871      if ([kKeys[i] isEqual:seenKeys[j]]) {
872        foundKey = YES;
873        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
874      }
875    }
876    XCTAssertTrue(foundKey, @"i = %d", i);
877  }
878  free(seenKeys);
879  free(seenValues);
880
881  // Stopping the enumeration.
882  idx = 0;
883  [dict enumerateKeysAndUInt64sUsingBlock:^(NSString *aKey, uint64_t aValue, BOOL *stop) {
884    #pragma unused(aKey, aValue)
885    if (idx == 1) *stop = YES;
886    XCTAssertNotEqual(idx, 2U);
887    ++idx;
888  }];
889  [dict release];
890}
891
892- (void)testEquality {
893  const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
894  const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
895  const uint64_t kValues1[] = { 300U, 301U, 302U };
896  const uint64_t kValues2[] = { 300U, 303U, 302U };
897  const uint64_t kValues3[] = { 300U, 301U, 302U, 303U };
898  GPBStringUInt64Dictionary *dict1 =
899      [[GPBStringUInt64Dictionary alloc] initWithUInt64s:kValues1
900                                                 forKeys:kKeys1
901                                                   count:GPBARRAYSIZE(kValues1)];
902  XCTAssertNotNil(dict1);
903  GPBStringUInt64Dictionary *dict1prime =
904      [[GPBStringUInt64Dictionary alloc] initWithUInt64s:kValues1
905                                                 forKeys:kKeys1
906                                                   count:GPBARRAYSIZE(kValues1)];
907  XCTAssertNotNil(dict1prime);
908  GPBStringUInt64Dictionary *dict2 =
909      [[GPBStringUInt64Dictionary alloc] initWithUInt64s:kValues2
910                                                 forKeys:kKeys1
911                                                   count:GPBARRAYSIZE(kValues2)];
912  XCTAssertNotNil(dict2);
913  GPBStringUInt64Dictionary *dict3 =
914      [[GPBStringUInt64Dictionary alloc] initWithUInt64s:kValues1
915                                                 forKeys:kKeys2
916                                                   count:GPBARRAYSIZE(kValues1)];
917  XCTAssertNotNil(dict3);
918  GPBStringUInt64Dictionary *dict4 =
919      [[GPBStringUInt64Dictionary alloc] initWithUInt64s:kValues3
920                                                 forKeys:kKeys1
921                                                   count:GPBARRAYSIZE(kValues3)];
922  XCTAssertNotNil(dict4);
923
924  // 1/1Prime should be different objects, but equal.
925  XCTAssertNotEqual(dict1, dict1prime);
926  XCTAssertEqualObjects(dict1, dict1prime);
927  // Equal, so they must have same hash.
928  XCTAssertEqual([dict1 hash], [dict1prime hash]);
929
930  // 2 is same keys, different values; not equal.
931  XCTAssertNotEqualObjects(dict1, dict2);
932
933  // 3 is different keys, same values; not equal.
934  XCTAssertNotEqualObjects(dict1, dict3);
935
936  // 4 extra pair; not equal
937  XCTAssertNotEqualObjects(dict1, dict4);
938
939  [dict1 release];
940  [dict1prime release];
941  [dict2 release];
942  [dict3 release];
943  [dict4 release];
944}
945
946- (void)testCopy {
947  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
948  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
949  GPBStringUInt64Dictionary *dict =
950      [[GPBStringUInt64Dictionary alloc] initWithUInt64s:kValues
951                                                 forKeys:kKeys
952                                                   count:GPBARRAYSIZE(kValues)];
953  XCTAssertNotNil(dict);
954
955  GPBStringUInt64Dictionary *dict2 = [dict copy];
956  XCTAssertNotNil(dict2);
957
958  // Should be new object but equal.
959  XCTAssertNotEqual(dict, dict2);
960  XCTAssertEqualObjects(dict, dict2);
961  XCTAssertTrue([dict2 isKindOfClass:[GPBStringUInt64Dictionary class]]);
962
963  [dict2 release];
964  [dict release];
965}
966
967- (void)testDictionaryFromDictionary {
968  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
969  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
970  GPBStringUInt64Dictionary *dict =
971      [[GPBStringUInt64Dictionary alloc] initWithUInt64s:kValues
972                                                 forKeys:kKeys
973                                                   count:GPBARRAYSIZE(kValues)];
974  XCTAssertNotNil(dict);
975
976  GPBStringUInt64Dictionary *dict2 =
977      [[GPBStringUInt64Dictionary alloc] initWithDictionary:dict];
978  XCTAssertNotNil(dict2);
979
980  // Should be new pointer, but equal objects.
981  XCTAssertNotEqual(dict, dict2);
982  XCTAssertEqualObjects(dict, dict2);
983  [dict2 release];
984  [dict release];
985}
986
987- (void)testAdds {
988  GPBStringUInt64Dictionary *dict = [[GPBStringUInt64Dictionary alloc] init];
989  XCTAssertNotNil(dict);
990
991  XCTAssertEqual(dict.count, 0U);
992  [dict setUInt64:300U forKey:@"foo"];
993  XCTAssertEqual(dict.count, 1U);
994
995  const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
996  const uint64_t kValues[] = { 301U, 302U, 303U };
997  GPBStringUInt64Dictionary *dict2 =
998      [[GPBStringUInt64Dictionary alloc] initWithUInt64s:kValues
999                                                 forKeys:kKeys
1000                                                   count:GPBARRAYSIZE(kValues)];
1001  XCTAssertNotNil(dict2);
1002  [dict addEntriesFromDictionary:dict2];
1003  XCTAssertEqual(dict.count, 4U);
1004
1005  uint64_t value;
1006  XCTAssertTrue([dict getUInt64:NULL forKey:@"foo"]);
1007  XCTAssertTrue([dict getUInt64:&value forKey:@"foo"]);
1008  XCTAssertEqual(value, 300U);
1009  XCTAssertTrue([dict getUInt64:NULL forKey:@"bar"]);
1010  XCTAssertTrue([dict getUInt64:&value forKey:@"bar"]);
1011  XCTAssertEqual(value, 301U);
1012  XCTAssertTrue([dict getUInt64:NULL forKey:@"baz"]);
1013  XCTAssertTrue([dict getUInt64:&value forKey:@"baz"]);
1014  XCTAssertEqual(value, 302U);
1015  XCTAssertTrue([dict getUInt64:NULL forKey:@"mumble"]);
1016  XCTAssertTrue([dict getUInt64:&value forKey:@"mumble"]);
1017  XCTAssertEqual(value, 303U);
1018  [dict2 release];
1019  [dict release];
1020}
1021
1022- (void)testRemove {
1023  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
1024  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
1025  GPBStringUInt64Dictionary *dict =
1026      [[GPBStringUInt64Dictionary alloc] initWithUInt64s:kValues
1027                                                 forKeys:kKeys
1028                                                   count:GPBARRAYSIZE(kValues)];
1029  XCTAssertNotNil(dict);
1030  XCTAssertEqual(dict.count, 4U);
1031
1032  [dict removeUInt64ForKey:@"bar"];
1033  XCTAssertEqual(dict.count, 3U);
1034  uint64_t value;
1035  XCTAssertTrue([dict getUInt64:NULL forKey:@"foo"]);
1036  XCTAssertTrue([dict getUInt64:&value forKey:@"foo"]);
1037  XCTAssertEqual(value, 300U);
1038  XCTAssertFalse([dict getUInt64:NULL forKey:@"bar"]);
1039  XCTAssertTrue([dict getUInt64:NULL forKey:@"baz"]);
1040  XCTAssertTrue([dict getUInt64:&value forKey:@"baz"]);
1041  XCTAssertEqual(value, 302U);
1042  XCTAssertTrue([dict getUInt64:NULL forKey:@"mumble"]);
1043  XCTAssertTrue([dict getUInt64:&value forKey:@"mumble"]);
1044  XCTAssertEqual(value, 303U);
1045
1046  // Remove again does nothing.
1047  [dict removeUInt64ForKey:@"bar"];
1048  XCTAssertEqual(dict.count, 3U);
1049  XCTAssertTrue([dict getUInt64:NULL forKey:@"foo"]);
1050  XCTAssertTrue([dict getUInt64:&value forKey:@"foo"]);
1051  XCTAssertEqual(value, 300U);
1052  XCTAssertFalse([dict getUInt64:NULL forKey:@"bar"]);
1053  XCTAssertTrue([dict getUInt64:NULL forKey:@"baz"]);
1054  XCTAssertTrue([dict getUInt64:&value forKey:@"baz"]);
1055  XCTAssertEqual(value, 302U);
1056  XCTAssertTrue([dict getUInt64:NULL forKey:@"mumble"]);
1057  XCTAssertTrue([dict getUInt64:&value forKey:@"mumble"]);
1058  XCTAssertEqual(value, 303U);
1059
1060  [dict removeUInt64ForKey:@"mumble"];
1061  XCTAssertEqual(dict.count, 2U);
1062  XCTAssertTrue([dict getUInt64:NULL forKey:@"foo"]);
1063  XCTAssertTrue([dict getUInt64:&value forKey:@"foo"]);
1064  XCTAssertEqual(value, 300U);
1065  XCTAssertFalse([dict getUInt64:NULL forKey:@"bar"]);
1066  XCTAssertTrue([dict getUInt64:NULL forKey:@"baz"]);
1067  XCTAssertTrue([dict getUInt64:&value forKey:@"baz"]);
1068  XCTAssertEqual(value, 302U);
1069  XCTAssertFalse([dict getUInt64:NULL forKey:@"mumble"]);
1070
1071  [dict removeAll];
1072  XCTAssertEqual(dict.count, 0U);
1073  XCTAssertFalse([dict getUInt64:NULL forKey:@"foo"]);
1074  XCTAssertFalse([dict getUInt64:NULL forKey:@"bar"]);
1075  XCTAssertFalse([dict getUInt64:NULL forKey:@"baz"]);
1076  XCTAssertFalse([dict getUInt64:NULL forKey:@"mumble"]);
1077  [dict release];
1078}
1079
1080- (void)testInplaceMutation {
1081  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
1082  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
1083  GPBStringUInt64Dictionary *dict =
1084      [[GPBStringUInt64Dictionary alloc] initWithUInt64s:kValues
1085                                                 forKeys:kKeys
1086                                                   count:GPBARRAYSIZE(kValues)];
1087  XCTAssertNotNil(dict);
1088  XCTAssertEqual(dict.count, 4U);
1089  uint64_t value;
1090  XCTAssertTrue([dict getUInt64:NULL forKey:@"foo"]);
1091  XCTAssertTrue([dict getUInt64:&value forKey:@"foo"]);
1092  XCTAssertEqual(value, 300U);
1093  XCTAssertTrue([dict getUInt64:NULL forKey:@"bar"]);
1094  XCTAssertTrue([dict getUInt64:&value forKey:@"bar"]);
1095  XCTAssertEqual(value, 301U);
1096  XCTAssertTrue([dict getUInt64:NULL forKey:@"baz"]);
1097  XCTAssertTrue([dict getUInt64:&value forKey:@"baz"]);
1098  XCTAssertEqual(value, 302U);
1099  XCTAssertTrue([dict getUInt64:NULL forKey:@"mumble"]);
1100  XCTAssertTrue([dict getUInt64:&value forKey:@"mumble"]);
1101  XCTAssertEqual(value, 303U);
1102
1103  [dict setUInt64:303U forKey:@"foo"];
1104  XCTAssertEqual(dict.count, 4U);
1105  XCTAssertTrue([dict getUInt64:NULL forKey:@"foo"]);
1106  XCTAssertTrue([dict getUInt64:&value forKey:@"foo"]);
1107  XCTAssertEqual(value, 303U);
1108  XCTAssertTrue([dict getUInt64:NULL forKey:@"bar"]);
1109  XCTAssertTrue([dict getUInt64:&value forKey:@"bar"]);
1110  XCTAssertEqual(value, 301U);
1111  XCTAssertTrue([dict getUInt64:NULL forKey:@"baz"]);
1112  XCTAssertTrue([dict getUInt64:&value forKey:@"baz"]);
1113  XCTAssertEqual(value, 302U);
1114  XCTAssertTrue([dict getUInt64:NULL forKey:@"mumble"]);
1115  XCTAssertTrue([dict getUInt64:&value forKey:@"mumble"]);
1116  XCTAssertEqual(value, 303U);
1117
1118  [dict setUInt64:301U forKey:@"mumble"];
1119  XCTAssertEqual(dict.count, 4U);
1120  XCTAssertTrue([dict getUInt64:NULL forKey:@"foo"]);
1121  XCTAssertTrue([dict getUInt64:&value forKey:@"foo"]);
1122  XCTAssertEqual(value, 303U);
1123  XCTAssertTrue([dict getUInt64:NULL forKey:@"bar"]);
1124  XCTAssertTrue([dict getUInt64:&value forKey:@"bar"]);
1125  XCTAssertEqual(value, 301U);
1126  XCTAssertTrue([dict getUInt64:NULL forKey:@"baz"]);
1127  XCTAssertTrue([dict getUInt64:&value forKey:@"baz"]);
1128  XCTAssertEqual(value, 302U);
1129  XCTAssertTrue([dict getUInt64:NULL forKey:@"mumble"]);
1130  XCTAssertTrue([dict getUInt64:&value forKey:@"mumble"]);
1131  XCTAssertEqual(value, 301U);
1132
1133  const NSString *kKeys2[] = { @"bar", @"baz" };
1134  const uint64_t kValues2[] = { 302U, 300U };
1135  GPBStringUInt64Dictionary *dict2 =
1136      [[GPBStringUInt64Dictionary alloc] initWithUInt64s:kValues2
1137                                                 forKeys:kKeys2
1138                                                   count:GPBARRAYSIZE(kValues2)];
1139  XCTAssertNotNil(dict2);
1140  [dict addEntriesFromDictionary:dict2];
1141  XCTAssertEqual(dict.count, 4U);
1142  XCTAssertTrue([dict getUInt64:NULL forKey:@"foo"]);
1143  XCTAssertTrue([dict getUInt64:&value forKey:@"foo"]);
1144  XCTAssertEqual(value, 303U);
1145  XCTAssertTrue([dict getUInt64:NULL forKey:@"bar"]);
1146  XCTAssertTrue([dict getUInt64:&value forKey:@"bar"]);
1147  XCTAssertEqual(value, 302U);
1148  XCTAssertTrue([dict getUInt64:NULL forKey:@"baz"]);
1149  XCTAssertTrue([dict getUInt64:&value forKey:@"baz"]);
1150  XCTAssertEqual(value, 300U);
1151  XCTAssertTrue([dict getUInt64:NULL forKey:@"mumble"]);
1152  XCTAssertTrue([dict getUInt64:&value forKey:@"mumble"]);
1153  XCTAssertEqual(value, 301U);
1154
1155  [dict2 release];
1156  [dict release];
1157}
1158
1159@end
1160
1161#pragma mark - String -> Int64
1162
1163@interface GPBStringInt64DictionaryTests : XCTestCase
1164@end
1165
1166@implementation GPBStringInt64DictionaryTests
1167
1168- (void)testEmpty {
1169  GPBStringInt64Dictionary *dict = [[GPBStringInt64Dictionary alloc] init];
1170  XCTAssertNotNil(dict);
1171  XCTAssertEqual(dict.count, 0U);
1172  XCTAssertFalse([dict getInt64:NULL forKey:@"foo"]);
1173  [dict enumerateKeysAndInt64sUsingBlock:^(NSString *aKey, int64_t aValue, BOOL *stop) {
1174    #pragma unused(aKey, aValue, stop)
1175    XCTFail(@"Shouldn't get here!");
1176  }];
1177  [dict release];
1178}
1179
1180- (void)testOne {
1181  GPBStringInt64Dictionary *dict = [[GPBStringInt64Dictionary alloc] init];
1182  [dict setInt64:400 forKey:@"foo"];
1183  XCTAssertNotNil(dict);
1184  XCTAssertEqual(dict.count, 1U);
1185  int64_t value;
1186  XCTAssertTrue([dict getInt64:NULL forKey:@"foo"]);
1187  XCTAssertTrue([dict getInt64:&value forKey:@"foo"]);
1188  XCTAssertEqual(value, 400);
1189  XCTAssertFalse([dict getInt64:NULL forKey:@"bar"]);
1190  [dict enumerateKeysAndInt64sUsingBlock:^(NSString *aKey, int64_t aValue, BOOL *stop) {
1191    XCTAssertEqualObjects(aKey, @"foo");
1192    XCTAssertEqual(aValue, 400);
1193    XCTAssertNotEqual(stop, NULL);
1194  }];
1195  [dict release];
1196}
1197
1198- (void)testBasics {
1199  const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
1200  const int64_t kValues[] = { 400, 401, 402 };
1201  GPBStringInt64Dictionary *dict =
1202      [[GPBStringInt64Dictionary alloc] initWithInt64s:kValues
1203                                               forKeys:kKeys
1204                                                 count:GPBARRAYSIZE(kValues)];
1205  XCTAssertNotNil(dict);
1206  XCTAssertEqual(dict.count, 3U);
1207  int64_t value;
1208  XCTAssertTrue([dict getInt64:NULL forKey:@"foo"]);
1209  XCTAssertTrue([dict getInt64:&value forKey:@"foo"]);
1210  XCTAssertEqual(value, 400);
1211  XCTAssertTrue([dict getInt64:NULL forKey:@"bar"]);
1212  XCTAssertTrue([dict getInt64:&value forKey:@"bar"]);
1213  XCTAssertEqual(value, 401);
1214  XCTAssertTrue([dict getInt64:NULL forKey:@"baz"]);
1215  XCTAssertTrue([dict getInt64:&value forKey:@"baz"]);
1216  XCTAssertEqual(value, 402);
1217  XCTAssertFalse([dict getInt64:NULL forKey:@"mumble"]);
1218
1219  __block NSUInteger idx = 0;
1220  NSString **seenKeys = malloc(3 * sizeof(NSString*));
1221  int64_t *seenValues = malloc(3 * sizeof(int64_t));
1222  [dict enumerateKeysAndInt64sUsingBlock:^(NSString *aKey, int64_t aValue, BOOL *stop) {
1223    XCTAssertLessThan(idx, 3U);
1224    seenKeys[idx] = aKey;
1225    seenValues[idx] = aValue;
1226    XCTAssertNotEqual(stop, NULL);
1227    ++idx;
1228  }];
1229  for (int i = 0; i < 3; ++i) {
1230    BOOL foundKey = NO;
1231    for (int j = 0; (j < 3) && !foundKey; ++j) {
1232      if ([kKeys[i] isEqual:seenKeys[j]]) {
1233        foundKey = YES;
1234        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
1235      }
1236    }
1237    XCTAssertTrue(foundKey, @"i = %d", i);
1238  }
1239  free(seenKeys);
1240  free(seenValues);
1241
1242  // Stopping the enumeration.
1243  idx = 0;
1244  [dict enumerateKeysAndInt64sUsingBlock:^(NSString *aKey, int64_t aValue, BOOL *stop) {
1245    #pragma unused(aKey, aValue)
1246    if (idx == 1) *stop = YES;
1247    XCTAssertNotEqual(idx, 2U);
1248    ++idx;
1249  }];
1250  [dict release];
1251}
1252
1253- (void)testEquality {
1254  const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
1255  const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
1256  const int64_t kValues1[] = { 400, 401, 402 };
1257  const int64_t kValues2[] = { 400, 403, 402 };
1258  const int64_t kValues3[] = { 400, 401, 402, 403 };
1259  GPBStringInt64Dictionary *dict1 =
1260      [[GPBStringInt64Dictionary alloc] initWithInt64s:kValues1
1261                                               forKeys:kKeys1
1262                                                 count:GPBARRAYSIZE(kValues1)];
1263  XCTAssertNotNil(dict1);
1264  GPBStringInt64Dictionary *dict1prime =
1265      [[GPBStringInt64Dictionary alloc] initWithInt64s:kValues1
1266                                               forKeys:kKeys1
1267                                                 count:GPBARRAYSIZE(kValues1)];
1268  XCTAssertNotNil(dict1prime);
1269  GPBStringInt64Dictionary *dict2 =
1270      [[GPBStringInt64Dictionary alloc] initWithInt64s:kValues2
1271                                               forKeys:kKeys1
1272                                                 count:GPBARRAYSIZE(kValues2)];
1273  XCTAssertNotNil(dict2);
1274  GPBStringInt64Dictionary *dict3 =
1275      [[GPBStringInt64Dictionary alloc] initWithInt64s:kValues1
1276                                               forKeys:kKeys2
1277                                                 count:GPBARRAYSIZE(kValues1)];
1278  XCTAssertNotNil(dict3);
1279  GPBStringInt64Dictionary *dict4 =
1280      [[GPBStringInt64Dictionary alloc] initWithInt64s:kValues3
1281                                               forKeys:kKeys1
1282                                                 count:GPBARRAYSIZE(kValues3)];
1283  XCTAssertNotNil(dict4);
1284
1285  // 1/1Prime should be different objects, but equal.
1286  XCTAssertNotEqual(dict1, dict1prime);
1287  XCTAssertEqualObjects(dict1, dict1prime);
1288  // Equal, so they must have same hash.
1289  XCTAssertEqual([dict1 hash], [dict1prime hash]);
1290
1291  // 2 is same keys, different values; not equal.
1292  XCTAssertNotEqualObjects(dict1, dict2);
1293
1294  // 3 is different keys, same values; not equal.
1295  XCTAssertNotEqualObjects(dict1, dict3);
1296
1297  // 4 extra pair; not equal
1298  XCTAssertNotEqualObjects(dict1, dict4);
1299
1300  [dict1 release];
1301  [dict1prime release];
1302  [dict2 release];
1303  [dict3 release];
1304  [dict4 release];
1305}
1306
1307- (void)testCopy {
1308  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
1309  const int64_t kValues[] = { 400, 401, 402, 403 };
1310  GPBStringInt64Dictionary *dict =
1311      [[GPBStringInt64Dictionary alloc] initWithInt64s:kValues
1312                                               forKeys:kKeys
1313                                                 count:GPBARRAYSIZE(kValues)];
1314  XCTAssertNotNil(dict);
1315
1316  GPBStringInt64Dictionary *dict2 = [dict copy];
1317  XCTAssertNotNil(dict2);
1318
1319  // Should be new object but equal.
1320  XCTAssertNotEqual(dict, dict2);
1321  XCTAssertEqualObjects(dict, dict2);
1322  XCTAssertTrue([dict2 isKindOfClass:[GPBStringInt64Dictionary class]]);
1323
1324  [dict2 release];
1325  [dict release];
1326}
1327
1328- (void)testDictionaryFromDictionary {
1329  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
1330  const int64_t kValues[] = { 400, 401, 402, 403 };
1331  GPBStringInt64Dictionary *dict =
1332      [[GPBStringInt64Dictionary alloc] initWithInt64s:kValues
1333                                               forKeys:kKeys
1334                                                 count:GPBARRAYSIZE(kValues)];
1335  XCTAssertNotNil(dict);
1336
1337  GPBStringInt64Dictionary *dict2 =
1338      [[GPBStringInt64Dictionary alloc] initWithDictionary:dict];
1339  XCTAssertNotNil(dict2);
1340
1341  // Should be new pointer, but equal objects.
1342  XCTAssertNotEqual(dict, dict2);
1343  XCTAssertEqualObjects(dict, dict2);
1344  [dict2 release];
1345  [dict release];
1346}
1347
1348- (void)testAdds {
1349  GPBStringInt64Dictionary *dict = [[GPBStringInt64Dictionary alloc] init];
1350  XCTAssertNotNil(dict);
1351
1352  XCTAssertEqual(dict.count, 0U);
1353  [dict setInt64:400 forKey:@"foo"];
1354  XCTAssertEqual(dict.count, 1U);
1355
1356  const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
1357  const int64_t kValues[] = { 401, 402, 403 };
1358  GPBStringInt64Dictionary *dict2 =
1359      [[GPBStringInt64Dictionary alloc] initWithInt64s:kValues
1360                                               forKeys:kKeys
1361                                                 count:GPBARRAYSIZE(kValues)];
1362  XCTAssertNotNil(dict2);
1363  [dict addEntriesFromDictionary:dict2];
1364  XCTAssertEqual(dict.count, 4U);
1365
1366  int64_t value;
1367  XCTAssertTrue([dict getInt64:NULL forKey:@"foo"]);
1368  XCTAssertTrue([dict getInt64:&value forKey:@"foo"]);
1369  XCTAssertEqual(value, 400);
1370  XCTAssertTrue([dict getInt64:NULL forKey:@"bar"]);
1371  XCTAssertTrue([dict getInt64:&value forKey:@"bar"]);
1372  XCTAssertEqual(value, 401);
1373  XCTAssertTrue([dict getInt64:NULL forKey:@"baz"]);
1374  XCTAssertTrue([dict getInt64:&value forKey:@"baz"]);
1375  XCTAssertEqual(value, 402);
1376  XCTAssertTrue([dict getInt64:NULL forKey:@"mumble"]);
1377  XCTAssertTrue([dict getInt64:&value forKey:@"mumble"]);
1378  XCTAssertEqual(value, 403);
1379  [dict2 release];
1380  [dict release];
1381}
1382
1383- (void)testRemove {
1384  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
1385  const int64_t kValues[] = { 400, 401, 402, 403 };
1386  GPBStringInt64Dictionary *dict =
1387      [[GPBStringInt64Dictionary alloc] initWithInt64s:kValues
1388                                               forKeys:kKeys
1389                                                 count:GPBARRAYSIZE(kValues)];
1390  XCTAssertNotNil(dict);
1391  XCTAssertEqual(dict.count, 4U);
1392
1393  [dict removeInt64ForKey:@"bar"];
1394  XCTAssertEqual(dict.count, 3U);
1395  int64_t value;
1396  XCTAssertTrue([dict getInt64:NULL forKey:@"foo"]);
1397  XCTAssertTrue([dict getInt64:&value forKey:@"foo"]);
1398  XCTAssertEqual(value, 400);
1399  XCTAssertFalse([dict getInt64:NULL forKey:@"bar"]);
1400  XCTAssertTrue([dict getInt64:NULL forKey:@"baz"]);
1401  XCTAssertTrue([dict getInt64:&value forKey:@"baz"]);
1402  XCTAssertEqual(value, 402);
1403  XCTAssertTrue([dict getInt64:NULL forKey:@"mumble"]);
1404  XCTAssertTrue([dict getInt64:&value forKey:@"mumble"]);
1405  XCTAssertEqual(value, 403);
1406
1407  // Remove again does nothing.
1408  [dict removeInt64ForKey:@"bar"];
1409  XCTAssertEqual(dict.count, 3U);
1410  XCTAssertTrue([dict getInt64:NULL forKey:@"foo"]);
1411  XCTAssertTrue([dict getInt64:&value forKey:@"foo"]);
1412  XCTAssertEqual(value, 400);
1413  XCTAssertFalse([dict getInt64:NULL forKey:@"bar"]);
1414  XCTAssertTrue([dict getInt64:NULL forKey:@"baz"]);
1415  XCTAssertTrue([dict getInt64:&value forKey:@"baz"]);
1416  XCTAssertEqual(value, 402);
1417  XCTAssertTrue([dict getInt64:NULL forKey:@"mumble"]);
1418  XCTAssertTrue([dict getInt64:&value forKey:@"mumble"]);
1419  XCTAssertEqual(value, 403);
1420
1421  [dict removeInt64ForKey:@"mumble"];
1422  XCTAssertEqual(dict.count, 2U);
1423  XCTAssertTrue([dict getInt64:NULL forKey:@"foo"]);
1424  XCTAssertTrue([dict getInt64:&value forKey:@"foo"]);
1425  XCTAssertEqual(value, 400);
1426  XCTAssertFalse([dict getInt64:NULL forKey:@"bar"]);
1427  XCTAssertTrue([dict getInt64:NULL forKey:@"baz"]);
1428  XCTAssertTrue([dict getInt64:&value forKey:@"baz"]);
1429  XCTAssertEqual(value, 402);
1430  XCTAssertFalse([dict getInt64:NULL forKey:@"mumble"]);
1431
1432  [dict removeAll];
1433  XCTAssertEqual(dict.count, 0U);
1434  XCTAssertFalse([dict getInt64:NULL forKey:@"foo"]);
1435  XCTAssertFalse([dict getInt64:NULL forKey:@"bar"]);
1436  XCTAssertFalse([dict getInt64:NULL forKey:@"baz"]);
1437  XCTAssertFalse([dict getInt64:NULL forKey:@"mumble"]);
1438  [dict release];
1439}
1440
1441- (void)testInplaceMutation {
1442  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
1443  const int64_t kValues[] = { 400, 401, 402, 403 };
1444  GPBStringInt64Dictionary *dict =
1445      [[GPBStringInt64Dictionary alloc] initWithInt64s:kValues
1446                                               forKeys:kKeys
1447                                                 count:GPBARRAYSIZE(kValues)];
1448  XCTAssertNotNil(dict);
1449  XCTAssertEqual(dict.count, 4U);
1450  int64_t value;
1451  XCTAssertTrue([dict getInt64:NULL forKey:@"foo"]);
1452  XCTAssertTrue([dict getInt64:&value forKey:@"foo"]);
1453  XCTAssertEqual(value, 400);
1454  XCTAssertTrue([dict getInt64:NULL forKey:@"bar"]);
1455  XCTAssertTrue([dict getInt64:&value forKey:@"bar"]);
1456  XCTAssertEqual(value, 401);
1457  XCTAssertTrue([dict getInt64:NULL forKey:@"baz"]);
1458  XCTAssertTrue([dict getInt64:&value forKey:@"baz"]);
1459  XCTAssertEqual(value, 402);
1460  XCTAssertTrue([dict getInt64:NULL forKey:@"mumble"]);
1461  XCTAssertTrue([dict getInt64:&value forKey:@"mumble"]);
1462  XCTAssertEqual(value, 403);
1463
1464  [dict setInt64:403 forKey:@"foo"];
1465  XCTAssertEqual(dict.count, 4U);
1466  XCTAssertTrue([dict getInt64:NULL forKey:@"foo"]);
1467  XCTAssertTrue([dict getInt64:&value forKey:@"foo"]);
1468  XCTAssertEqual(value, 403);
1469  XCTAssertTrue([dict getInt64:NULL forKey:@"bar"]);
1470  XCTAssertTrue([dict getInt64:&value forKey:@"bar"]);
1471  XCTAssertEqual(value, 401);
1472  XCTAssertTrue([dict getInt64:NULL forKey:@"baz"]);
1473  XCTAssertTrue([dict getInt64:&value forKey:@"baz"]);
1474  XCTAssertEqual(value, 402);
1475  XCTAssertTrue([dict getInt64:NULL forKey:@"mumble"]);
1476  XCTAssertTrue([dict getInt64:&value forKey:@"mumble"]);
1477  XCTAssertEqual(value, 403);
1478
1479  [dict setInt64:401 forKey:@"mumble"];
1480  XCTAssertEqual(dict.count, 4U);
1481  XCTAssertTrue([dict getInt64:NULL forKey:@"foo"]);
1482  XCTAssertTrue([dict getInt64:&value forKey:@"foo"]);
1483  XCTAssertEqual(value, 403);
1484  XCTAssertTrue([dict getInt64:NULL forKey:@"bar"]);
1485  XCTAssertTrue([dict getInt64:&value forKey:@"bar"]);
1486  XCTAssertEqual(value, 401);
1487  XCTAssertTrue([dict getInt64:NULL forKey:@"baz"]);
1488  XCTAssertTrue([dict getInt64:&value forKey:@"baz"]);
1489  XCTAssertEqual(value, 402);
1490  XCTAssertTrue([dict getInt64:NULL forKey:@"mumble"]);
1491  XCTAssertTrue([dict getInt64:&value forKey:@"mumble"]);
1492  XCTAssertEqual(value, 401);
1493
1494  const NSString *kKeys2[] = { @"bar", @"baz" };
1495  const int64_t kValues2[] = { 402, 400 };
1496  GPBStringInt64Dictionary *dict2 =
1497      [[GPBStringInt64Dictionary alloc] initWithInt64s:kValues2
1498                                               forKeys:kKeys2
1499                                                 count:GPBARRAYSIZE(kValues2)];
1500  XCTAssertNotNil(dict2);
1501  [dict addEntriesFromDictionary:dict2];
1502  XCTAssertEqual(dict.count, 4U);
1503  XCTAssertTrue([dict getInt64:NULL forKey:@"foo"]);
1504  XCTAssertTrue([dict getInt64:&value forKey:@"foo"]);
1505  XCTAssertEqual(value, 403);
1506  XCTAssertTrue([dict getInt64:NULL forKey:@"bar"]);
1507  XCTAssertTrue([dict getInt64:&value forKey:@"bar"]);
1508  XCTAssertEqual(value, 402);
1509  XCTAssertTrue([dict getInt64:NULL forKey:@"baz"]);
1510  XCTAssertTrue([dict getInt64:&value forKey:@"baz"]);
1511  XCTAssertEqual(value, 400);
1512  XCTAssertTrue([dict getInt64:NULL forKey:@"mumble"]);
1513  XCTAssertTrue([dict getInt64:&value forKey:@"mumble"]);
1514  XCTAssertEqual(value, 401);
1515
1516  [dict2 release];
1517  [dict release];
1518}
1519
1520@end
1521
1522#pragma mark - String -> Bool
1523
1524@interface GPBStringBoolDictionaryTests : XCTestCase
1525@end
1526
1527@implementation GPBStringBoolDictionaryTests
1528
1529- (void)testEmpty {
1530  GPBStringBoolDictionary *dict = [[GPBStringBoolDictionary alloc] init];
1531  XCTAssertNotNil(dict);
1532  XCTAssertEqual(dict.count, 0U);
1533  XCTAssertFalse([dict getBool:NULL forKey:@"foo"]);
1534  [dict enumerateKeysAndBoolsUsingBlock:^(NSString *aKey, BOOL aValue, BOOL *stop) {
1535    #pragma unused(aKey, aValue, stop)
1536    XCTFail(@"Shouldn't get here!");
1537  }];
1538  [dict release];
1539}
1540
1541- (void)testOne {
1542  GPBStringBoolDictionary *dict = [[GPBStringBoolDictionary alloc] init];
1543  [dict setBool:YES forKey:@"foo"];
1544  XCTAssertNotNil(dict);
1545  XCTAssertEqual(dict.count, 1U);
1546  BOOL value;
1547  XCTAssertTrue([dict getBool:NULL forKey:@"foo"]);
1548  XCTAssertTrue([dict getBool:&value forKey:@"foo"]);
1549  XCTAssertEqual(value, YES);
1550  XCTAssertFalse([dict getBool:NULL forKey:@"bar"]);
1551  [dict enumerateKeysAndBoolsUsingBlock:^(NSString *aKey, BOOL aValue, BOOL *stop) {
1552    XCTAssertEqualObjects(aKey, @"foo");
1553    XCTAssertEqual(aValue, YES);
1554    XCTAssertNotEqual(stop, NULL);
1555  }];
1556  [dict release];
1557}
1558
1559- (void)testBasics {
1560  const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
1561  const BOOL kValues[] = { YES, YES, NO };
1562  GPBStringBoolDictionary *dict =
1563      [[GPBStringBoolDictionary alloc] initWithBools:kValues
1564                                             forKeys:kKeys
1565                                               count:GPBARRAYSIZE(kValues)];
1566  XCTAssertNotNil(dict);
1567  XCTAssertEqual(dict.count, 3U);
1568  BOOL value;
1569  XCTAssertTrue([dict getBool:NULL forKey:@"foo"]);
1570  XCTAssertTrue([dict getBool:&value forKey:@"foo"]);
1571  XCTAssertEqual(value, YES);
1572  XCTAssertTrue([dict getBool:NULL forKey:@"bar"]);
1573  XCTAssertTrue([dict getBool:&value forKey:@"bar"]);
1574  XCTAssertEqual(value, YES);
1575  XCTAssertTrue([dict getBool:NULL forKey:@"baz"]);
1576  XCTAssertTrue([dict getBool:&value forKey:@"baz"]);
1577  XCTAssertEqual(value, NO);
1578  XCTAssertFalse([dict getBool:NULL forKey:@"mumble"]);
1579
1580  __block NSUInteger idx = 0;
1581  NSString **seenKeys = malloc(3 * sizeof(NSString*));
1582  BOOL *seenValues = malloc(3 * sizeof(BOOL));
1583  [dict enumerateKeysAndBoolsUsingBlock:^(NSString *aKey, BOOL aValue, BOOL *stop) {
1584    XCTAssertLessThan(idx, 3U);
1585    seenKeys[idx] = aKey;
1586    seenValues[idx] = aValue;
1587    XCTAssertNotEqual(stop, NULL);
1588    ++idx;
1589  }];
1590  for (int i = 0; i < 3; ++i) {
1591    BOOL foundKey = NO;
1592    for (int j = 0; (j < 3) && !foundKey; ++j) {
1593      if ([kKeys[i] isEqual:seenKeys[j]]) {
1594        foundKey = YES;
1595        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
1596      }
1597    }
1598    XCTAssertTrue(foundKey, @"i = %d", i);
1599  }
1600  free(seenKeys);
1601  free(seenValues);
1602
1603  // Stopping the enumeration.
1604  idx = 0;
1605  [dict enumerateKeysAndBoolsUsingBlock:^(NSString *aKey, BOOL aValue, BOOL *stop) {
1606    #pragma unused(aKey, aValue)
1607    if (idx == 1) *stop = YES;
1608    XCTAssertNotEqual(idx, 2U);
1609    ++idx;
1610  }];
1611  [dict release];
1612}
1613
1614- (void)testEquality {
1615  const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
1616  const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
1617  const BOOL kValues1[] = { YES, YES, NO };
1618  const BOOL kValues2[] = { YES, NO, NO };
1619  const BOOL kValues3[] = { YES, YES, NO, NO };
1620  GPBStringBoolDictionary *dict1 =
1621      [[GPBStringBoolDictionary alloc] initWithBools:kValues1
1622                                             forKeys:kKeys1
1623                                               count:GPBARRAYSIZE(kValues1)];
1624  XCTAssertNotNil(dict1);
1625  GPBStringBoolDictionary *dict1prime =
1626      [[GPBStringBoolDictionary alloc] initWithBools:kValues1
1627                                             forKeys:kKeys1
1628                                               count:GPBARRAYSIZE(kValues1)];
1629  XCTAssertNotNil(dict1prime);
1630  GPBStringBoolDictionary *dict2 =
1631      [[GPBStringBoolDictionary alloc] initWithBools:kValues2
1632                                             forKeys:kKeys1
1633                                               count:GPBARRAYSIZE(kValues2)];
1634  XCTAssertNotNil(dict2);
1635  GPBStringBoolDictionary *dict3 =
1636      [[GPBStringBoolDictionary alloc] initWithBools:kValues1
1637                                             forKeys:kKeys2
1638                                               count:GPBARRAYSIZE(kValues1)];
1639  XCTAssertNotNil(dict3);
1640  GPBStringBoolDictionary *dict4 =
1641      [[GPBStringBoolDictionary alloc] initWithBools:kValues3
1642                                             forKeys:kKeys1
1643                                               count:GPBARRAYSIZE(kValues3)];
1644  XCTAssertNotNil(dict4);
1645
1646  // 1/1Prime should be different objects, but equal.
1647  XCTAssertNotEqual(dict1, dict1prime);
1648  XCTAssertEqualObjects(dict1, dict1prime);
1649  // Equal, so they must have same hash.
1650  XCTAssertEqual([dict1 hash], [dict1prime hash]);
1651
1652  // 2 is same keys, different values; not equal.
1653  XCTAssertNotEqualObjects(dict1, dict2);
1654
1655  // 3 is different keys, same values; not equal.
1656  XCTAssertNotEqualObjects(dict1, dict3);
1657
1658  // 4 extra pair; not equal
1659  XCTAssertNotEqualObjects(dict1, dict4);
1660
1661  [dict1 release];
1662  [dict1prime release];
1663  [dict2 release];
1664  [dict3 release];
1665  [dict4 release];
1666}
1667
1668- (void)testCopy {
1669  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
1670  const BOOL kValues[] = { YES, YES, NO, NO };
1671  GPBStringBoolDictionary *dict =
1672      [[GPBStringBoolDictionary alloc] initWithBools:kValues
1673                                             forKeys:kKeys
1674                                               count:GPBARRAYSIZE(kValues)];
1675  XCTAssertNotNil(dict);
1676
1677  GPBStringBoolDictionary *dict2 = [dict copy];
1678  XCTAssertNotNil(dict2);
1679
1680  // Should be new object but equal.
1681  XCTAssertNotEqual(dict, dict2);
1682  XCTAssertEqualObjects(dict, dict2);
1683  XCTAssertTrue([dict2 isKindOfClass:[GPBStringBoolDictionary class]]);
1684
1685  [dict2 release];
1686  [dict release];
1687}
1688
1689- (void)testDictionaryFromDictionary {
1690  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
1691  const BOOL kValues[] = { YES, YES, NO, NO };
1692  GPBStringBoolDictionary *dict =
1693      [[GPBStringBoolDictionary alloc] initWithBools:kValues
1694                                             forKeys:kKeys
1695                                               count:GPBARRAYSIZE(kValues)];
1696  XCTAssertNotNil(dict);
1697
1698  GPBStringBoolDictionary *dict2 =
1699      [[GPBStringBoolDictionary alloc] initWithDictionary:dict];
1700  XCTAssertNotNil(dict2);
1701
1702  // Should be new pointer, but equal objects.
1703  XCTAssertNotEqual(dict, dict2);
1704  XCTAssertEqualObjects(dict, dict2);
1705  [dict2 release];
1706  [dict release];
1707}
1708
1709- (void)testAdds {
1710  GPBStringBoolDictionary *dict = [[GPBStringBoolDictionary alloc] init];
1711  XCTAssertNotNil(dict);
1712
1713  XCTAssertEqual(dict.count, 0U);
1714  [dict setBool:YES forKey:@"foo"];
1715  XCTAssertEqual(dict.count, 1U);
1716
1717  const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
1718  const BOOL kValues[] = { YES, NO, NO };
1719  GPBStringBoolDictionary *dict2 =
1720      [[GPBStringBoolDictionary alloc] initWithBools:kValues
1721                                             forKeys:kKeys
1722                                               count:GPBARRAYSIZE(kValues)];
1723  XCTAssertNotNil(dict2);
1724  [dict addEntriesFromDictionary:dict2];
1725  XCTAssertEqual(dict.count, 4U);
1726
1727  BOOL value;
1728  XCTAssertTrue([dict getBool:NULL forKey:@"foo"]);
1729  XCTAssertTrue([dict getBool:&value forKey:@"foo"]);
1730  XCTAssertEqual(value, YES);
1731  XCTAssertTrue([dict getBool:NULL forKey:@"bar"]);
1732  XCTAssertTrue([dict getBool:&value forKey:@"bar"]);
1733  XCTAssertEqual(value, YES);
1734  XCTAssertTrue([dict getBool:NULL forKey:@"baz"]);
1735  XCTAssertTrue([dict getBool:&value forKey:@"baz"]);
1736  XCTAssertEqual(value, NO);
1737  XCTAssertTrue([dict getBool:NULL forKey:@"mumble"]);
1738  XCTAssertTrue([dict getBool:&value forKey:@"mumble"]);
1739  XCTAssertEqual(value, NO);
1740  [dict2 release];
1741  [dict release];
1742}
1743
1744- (void)testRemove {
1745  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
1746  const BOOL kValues[] = { YES, YES, NO, NO };
1747  GPBStringBoolDictionary *dict =
1748      [[GPBStringBoolDictionary alloc] initWithBools:kValues
1749                                             forKeys:kKeys
1750                                               count:GPBARRAYSIZE(kValues)];
1751  XCTAssertNotNil(dict);
1752  XCTAssertEqual(dict.count, 4U);
1753
1754  [dict removeBoolForKey:@"bar"];
1755  XCTAssertEqual(dict.count, 3U);
1756  BOOL value;
1757  XCTAssertTrue([dict getBool:NULL forKey:@"foo"]);
1758  XCTAssertTrue([dict getBool:&value forKey:@"foo"]);
1759  XCTAssertEqual(value, YES);
1760  XCTAssertFalse([dict getBool:NULL forKey:@"bar"]);
1761  XCTAssertTrue([dict getBool:NULL forKey:@"baz"]);
1762  XCTAssertTrue([dict getBool:&value forKey:@"baz"]);
1763  XCTAssertEqual(value, NO);
1764  XCTAssertTrue([dict getBool:NULL forKey:@"mumble"]);
1765  XCTAssertTrue([dict getBool:&value forKey:@"mumble"]);
1766  XCTAssertEqual(value, NO);
1767
1768  // Remove again does nothing.
1769  [dict removeBoolForKey:@"bar"];
1770  XCTAssertEqual(dict.count, 3U);
1771  XCTAssertTrue([dict getBool:NULL forKey:@"foo"]);
1772  XCTAssertTrue([dict getBool:&value forKey:@"foo"]);
1773  XCTAssertEqual(value, YES);
1774  XCTAssertFalse([dict getBool:NULL forKey:@"bar"]);
1775  XCTAssertTrue([dict getBool:NULL forKey:@"baz"]);
1776  XCTAssertTrue([dict getBool:&value forKey:@"baz"]);
1777  XCTAssertEqual(value, NO);
1778  XCTAssertTrue([dict getBool:NULL forKey:@"mumble"]);
1779  XCTAssertTrue([dict getBool:&value forKey:@"mumble"]);
1780  XCTAssertEqual(value, NO);
1781
1782  [dict removeBoolForKey:@"mumble"];
1783  XCTAssertEqual(dict.count, 2U);
1784  XCTAssertTrue([dict getBool:NULL forKey:@"foo"]);
1785  XCTAssertTrue([dict getBool:&value forKey:@"foo"]);
1786  XCTAssertEqual(value, YES);
1787  XCTAssertFalse([dict getBool:NULL forKey:@"bar"]);
1788  XCTAssertTrue([dict getBool:NULL forKey:@"baz"]);
1789  XCTAssertTrue([dict getBool:&value forKey:@"baz"]);
1790  XCTAssertEqual(value, NO);
1791  XCTAssertFalse([dict getBool:NULL forKey:@"mumble"]);
1792
1793  [dict removeAll];
1794  XCTAssertEqual(dict.count, 0U);
1795  XCTAssertFalse([dict getBool:NULL forKey:@"foo"]);
1796  XCTAssertFalse([dict getBool:NULL forKey:@"bar"]);
1797  XCTAssertFalse([dict getBool:NULL forKey:@"baz"]);
1798  XCTAssertFalse([dict getBool:NULL forKey:@"mumble"]);
1799  [dict release];
1800}
1801
1802- (void)testInplaceMutation {
1803  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
1804  const BOOL kValues[] = { YES, YES, NO, NO };
1805  GPBStringBoolDictionary *dict =
1806      [[GPBStringBoolDictionary alloc] initWithBools:kValues
1807                                             forKeys:kKeys
1808                                               count:GPBARRAYSIZE(kValues)];
1809  XCTAssertNotNil(dict);
1810  XCTAssertEqual(dict.count, 4U);
1811  BOOL value;
1812  XCTAssertTrue([dict getBool:NULL forKey:@"foo"]);
1813  XCTAssertTrue([dict getBool:&value forKey:@"foo"]);
1814  XCTAssertEqual(value, YES);
1815  XCTAssertTrue([dict getBool:NULL forKey:@"bar"]);
1816  XCTAssertTrue([dict getBool:&value forKey:@"bar"]);
1817  XCTAssertEqual(value, YES);
1818  XCTAssertTrue([dict getBool:NULL forKey:@"baz"]);
1819  XCTAssertTrue([dict getBool:&value forKey:@"baz"]);
1820  XCTAssertEqual(value, NO);
1821  XCTAssertTrue([dict getBool:NULL forKey:@"mumble"]);
1822  XCTAssertTrue([dict getBool:&value forKey:@"mumble"]);
1823  XCTAssertEqual(value, NO);
1824
1825  [dict setBool:NO forKey:@"foo"];
1826  XCTAssertEqual(dict.count, 4U);
1827  XCTAssertTrue([dict getBool:NULL forKey:@"foo"]);
1828  XCTAssertTrue([dict getBool:&value forKey:@"foo"]);
1829  XCTAssertEqual(value, NO);
1830  XCTAssertTrue([dict getBool:NULL forKey:@"bar"]);
1831  XCTAssertTrue([dict getBool:&value forKey:@"bar"]);
1832  XCTAssertEqual(value, YES);
1833  XCTAssertTrue([dict getBool:NULL forKey:@"baz"]);
1834  XCTAssertTrue([dict getBool:&value forKey:@"baz"]);
1835  XCTAssertEqual(value, NO);
1836  XCTAssertTrue([dict getBool:NULL forKey:@"mumble"]);
1837  XCTAssertTrue([dict getBool:&value forKey:@"mumble"]);
1838  XCTAssertEqual(value, NO);
1839
1840  [dict setBool:YES forKey:@"mumble"];
1841  XCTAssertEqual(dict.count, 4U);
1842  XCTAssertTrue([dict getBool:NULL forKey:@"foo"]);
1843  XCTAssertTrue([dict getBool:&value forKey:@"foo"]);
1844  XCTAssertEqual(value, NO);
1845  XCTAssertTrue([dict getBool:NULL forKey:@"bar"]);
1846  XCTAssertTrue([dict getBool:&value forKey:@"bar"]);
1847  XCTAssertEqual(value, YES);
1848  XCTAssertTrue([dict getBool:NULL forKey:@"baz"]);
1849  XCTAssertTrue([dict getBool:&value forKey:@"baz"]);
1850  XCTAssertEqual(value, NO);
1851  XCTAssertTrue([dict getBool:NULL forKey:@"mumble"]);
1852  XCTAssertTrue([dict getBool:&value forKey:@"mumble"]);
1853  XCTAssertEqual(value, YES);
1854
1855  const NSString *kKeys2[] = { @"bar", @"baz" };
1856  const BOOL kValues2[] = { NO, YES };
1857  GPBStringBoolDictionary *dict2 =
1858      [[GPBStringBoolDictionary alloc] initWithBools:kValues2
1859                                             forKeys:kKeys2
1860                                               count:GPBARRAYSIZE(kValues2)];
1861  XCTAssertNotNil(dict2);
1862  [dict addEntriesFromDictionary:dict2];
1863  XCTAssertEqual(dict.count, 4U);
1864  XCTAssertTrue([dict getBool:NULL forKey:@"foo"]);
1865  XCTAssertTrue([dict getBool:&value forKey:@"foo"]);
1866  XCTAssertEqual(value, NO);
1867  XCTAssertTrue([dict getBool:NULL forKey:@"bar"]);
1868  XCTAssertTrue([dict getBool:&value forKey:@"bar"]);
1869  XCTAssertEqual(value, NO);
1870  XCTAssertTrue([dict getBool:NULL forKey:@"baz"]);
1871  XCTAssertTrue([dict getBool:&value forKey:@"baz"]);
1872  XCTAssertEqual(value, YES);
1873  XCTAssertTrue([dict getBool:NULL forKey:@"mumble"]);
1874  XCTAssertTrue([dict getBool:&value forKey:@"mumble"]);
1875  XCTAssertEqual(value, YES);
1876
1877  [dict2 release];
1878  [dict release];
1879}
1880
1881@end
1882
1883#pragma mark - String -> Float
1884
1885@interface GPBStringFloatDictionaryTests : XCTestCase
1886@end
1887
1888@implementation GPBStringFloatDictionaryTests
1889
1890- (void)testEmpty {
1891  GPBStringFloatDictionary *dict = [[GPBStringFloatDictionary alloc] init];
1892  XCTAssertNotNil(dict);
1893  XCTAssertEqual(dict.count, 0U);
1894  XCTAssertFalse([dict getFloat:NULL forKey:@"foo"]);
1895  [dict enumerateKeysAndFloatsUsingBlock:^(NSString *aKey, float aValue, BOOL *stop) {
1896    #pragma unused(aKey, aValue, stop)
1897    XCTFail(@"Shouldn't get here!");
1898  }];
1899  [dict release];
1900}
1901
1902- (void)testOne {
1903  GPBStringFloatDictionary *dict = [[GPBStringFloatDictionary alloc] init];
1904  [dict setFloat:500.f forKey:@"foo"];
1905  XCTAssertNotNil(dict);
1906  XCTAssertEqual(dict.count, 1U);
1907  float value;
1908  XCTAssertTrue([dict getFloat:NULL forKey:@"foo"]);
1909  XCTAssertTrue([dict getFloat:&value forKey:@"foo"]);
1910  XCTAssertEqual(value, 500.f);
1911  XCTAssertFalse([dict getFloat:NULL forKey:@"bar"]);
1912  [dict enumerateKeysAndFloatsUsingBlock:^(NSString *aKey, float aValue, BOOL *stop) {
1913    XCTAssertEqualObjects(aKey, @"foo");
1914    XCTAssertEqual(aValue, 500.f);
1915    XCTAssertNotEqual(stop, NULL);
1916  }];
1917  [dict release];
1918}
1919
1920- (void)testBasics {
1921  const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
1922  const float kValues[] = { 500.f, 501.f, 502.f };
1923  GPBStringFloatDictionary *dict =
1924      [[GPBStringFloatDictionary alloc] initWithFloats:kValues
1925                                               forKeys:kKeys
1926                                                 count:GPBARRAYSIZE(kValues)];
1927  XCTAssertNotNil(dict);
1928  XCTAssertEqual(dict.count, 3U);
1929  float value;
1930  XCTAssertTrue([dict getFloat:NULL forKey:@"foo"]);
1931  XCTAssertTrue([dict getFloat:&value forKey:@"foo"]);
1932  XCTAssertEqual(value, 500.f);
1933  XCTAssertTrue([dict getFloat:NULL forKey:@"bar"]);
1934  XCTAssertTrue([dict getFloat:&value forKey:@"bar"]);
1935  XCTAssertEqual(value, 501.f);
1936  XCTAssertTrue([dict getFloat:NULL forKey:@"baz"]);
1937  XCTAssertTrue([dict getFloat:&value forKey:@"baz"]);
1938  XCTAssertEqual(value, 502.f);
1939  XCTAssertFalse([dict getFloat:NULL forKey:@"mumble"]);
1940
1941  __block NSUInteger idx = 0;
1942  NSString **seenKeys = malloc(3 * sizeof(NSString*));
1943  float *seenValues = malloc(3 * sizeof(float));
1944  [dict enumerateKeysAndFloatsUsingBlock:^(NSString *aKey, float aValue, BOOL *stop) {
1945    XCTAssertLessThan(idx, 3U);
1946    seenKeys[idx] = aKey;
1947    seenValues[idx] = aValue;
1948    XCTAssertNotEqual(stop, NULL);
1949    ++idx;
1950  }];
1951  for (int i = 0; i < 3; ++i) {
1952    BOOL foundKey = NO;
1953    for (int j = 0; (j < 3) && !foundKey; ++j) {
1954      if ([kKeys[i] isEqual:seenKeys[j]]) {
1955        foundKey = YES;
1956        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
1957      }
1958    }
1959    XCTAssertTrue(foundKey, @"i = %d", i);
1960  }
1961  free(seenKeys);
1962  free(seenValues);
1963
1964  // Stopping the enumeration.
1965  idx = 0;
1966  [dict enumerateKeysAndFloatsUsingBlock:^(NSString *aKey, float aValue, BOOL *stop) {
1967    #pragma unused(aKey, aValue)
1968    if (idx == 1) *stop = YES;
1969    XCTAssertNotEqual(idx, 2U);
1970    ++idx;
1971  }];
1972  [dict release];
1973}
1974
1975- (void)testEquality {
1976  const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
1977  const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
1978  const float kValues1[] = { 500.f, 501.f, 502.f };
1979  const float kValues2[] = { 500.f, 503.f, 502.f };
1980  const float kValues3[] = { 500.f, 501.f, 502.f, 503.f };
1981  GPBStringFloatDictionary *dict1 =
1982      [[GPBStringFloatDictionary alloc] initWithFloats:kValues1
1983                                               forKeys:kKeys1
1984                                                 count:GPBARRAYSIZE(kValues1)];
1985  XCTAssertNotNil(dict1);
1986  GPBStringFloatDictionary *dict1prime =
1987      [[GPBStringFloatDictionary alloc] initWithFloats:kValues1
1988                                               forKeys:kKeys1
1989                                                 count:GPBARRAYSIZE(kValues1)];
1990  XCTAssertNotNil(dict1prime);
1991  GPBStringFloatDictionary *dict2 =
1992      [[GPBStringFloatDictionary alloc] initWithFloats:kValues2
1993                                               forKeys:kKeys1
1994                                                 count:GPBARRAYSIZE(kValues2)];
1995  XCTAssertNotNil(dict2);
1996  GPBStringFloatDictionary *dict3 =
1997      [[GPBStringFloatDictionary alloc] initWithFloats:kValues1
1998                                               forKeys:kKeys2
1999                                                 count:GPBARRAYSIZE(kValues1)];
2000  XCTAssertNotNil(dict3);
2001  GPBStringFloatDictionary *dict4 =
2002      [[GPBStringFloatDictionary alloc] initWithFloats:kValues3
2003                                               forKeys:kKeys1
2004                                                 count:GPBARRAYSIZE(kValues3)];
2005  XCTAssertNotNil(dict4);
2006
2007  // 1/1Prime should be different objects, but equal.
2008  XCTAssertNotEqual(dict1, dict1prime);
2009  XCTAssertEqualObjects(dict1, dict1prime);
2010  // Equal, so they must have same hash.
2011  XCTAssertEqual([dict1 hash], [dict1prime hash]);
2012
2013  // 2 is same keys, different values; not equal.
2014  XCTAssertNotEqualObjects(dict1, dict2);
2015
2016  // 3 is different keys, same values; not equal.
2017  XCTAssertNotEqualObjects(dict1, dict3);
2018
2019  // 4 extra pair; not equal
2020  XCTAssertNotEqualObjects(dict1, dict4);
2021
2022  [dict1 release];
2023  [dict1prime release];
2024  [dict2 release];
2025  [dict3 release];
2026  [dict4 release];
2027}
2028
2029- (void)testCopy {
2030  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
2031  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
2032  GPBStringFloatDictionary *dict =
2033      [[GPBStringFloatDictionary alloc] initWithFloats:kValues
2034                                               forKeys:kKeys
2035                                                 count:GPBARRAYSIZE(kValues)];
2036  XCTAssertNotNil(dict);
2037
2038  GPBStringFloatDictionary *dict2 = [dict copy];
2039  XCTAssertNotNil(dict2);
2040
2041  // Should be new object but equal.
2042  XCTAssertNotEqual(dict, dict2);
2043  XCTAssertEqualObjects(dict, dict2);
2044  XCTAssertTrue([dict2 isKindOfClass:[GPBStringFloatDictionary class]]);
2045
2046  [dict2 release];
2047  [dict release];
2048}
2049
2050- (void)testDictionaryFromDictionary {
2051  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
2052  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
2053  GPBStringFloatDictionary *dict =
2054      [[GPBStringFloatDictionary alloc] initWithFloats:kValues
2055                                               forKeys:kKeys
2056                                                 count:GPBARRAYSIZE(kValues)];
2057  XCTAssertNotNil(dict);
2058
2059  GPBStringFloatDictionary *dict2 =
2060      [[GPBStringFloatDictionary alloc] initWithDictionary:dict];
2061  XCTAssertNotNil(dict2);
2062
2063  // Should be new pointer, but equal objects.
2064  XCTAssertNotEqual(dict, dict2);
2065  XCTAssertEqualObjects(dict, dict2);
2066  [dict2 release];
2067  [dict release];
2068}
2069
2070- (void)testAdds {
2071  GPBStringFloatDictionary *dict = [[GPBStringFloatDictionary alloc] init];
2072  XCTAssertNotNil(dict);
2073
2074  XCTAssertEqual(dict.count, 0U);
2075  [dict setFloat:500.f forKey:@"foo"];
2076  XCTAssertEqual(dict.count, 1U);
2077
2078  const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
2079  const float kValues[] = { 501.f, 502.f, 503.f };
2080  GPBStringFloatDictionary *dict2 =
2081      [[GPBStringFloatDictionary alloc] initWithFloats:kValues
2082                                               forKeys:kKeys
2083                                                 count:GPBARRAYSIZE(kValues)];
2084  XCTAssertNotNil(dict2);
2085  [dict addEntriesFromDictionary:dict2];
2086  XCTAssertEqual(dict.count, 4U);
2087
2088  float value;
2089  XCTAssertTrue([dict getFloat:NULL forKey:@"foo"]);
2090  XCTAssertTrue([dict getFloat:&value forKey:@"foo"]);
2091  XCTAssertEqual(value, 500.f);
2092  XCTAssertTrue([dict getFloat:NULL forKey:@"bar"]);
2093  XCTAssertTrue([dict getFloat:&value forKey:@"bar"]);
2094  XCTAssertEqual(value, 501.f);
2095  XCTAssertTrue([dict getFloat:NULL forKey:@"baz"]);
2096  XCTAssertTrue([dict getFloat:&value forKey:@"baz"]);
2097  XCTAssertEqual(value, 502.f);
2098  XCTAssertTrue([dict getFloat:NULL forKey:@"mumble"]);
2099  XCTAssertTrue([dict getFloat:&value forKey:@"mumble"]);
2100  XCTAssertEqual(value, 503.f);
2101  [dict2 release];
2102  [dict release];
2103}
2104
2105- (void)testRemove {
2106  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
2107  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
2108  GPBStringFloatDictionary *dict =
2109      [[GPBStringFloatDictionary alloc] initWithFloats:kValues
2110                                               forKeys:kKeys
2111                                                 count:GPBARRAYSIZE(kValues)];
2112  XCTAssertNotNil(dict);
2113  XCTAssertEqual(dict.count, 4U);
2114
2115  [dict removeFloatForKey:@"bar"];
2116  XCTAssertEqual(dict.count, 3U);
2117  float value;
2118  XCTAssertTrue([dict getFloat:NULL forKey:@"foo"]);
2119  XCTAssertTrue([dict getFloat:&value forKey:@"foo"]);
2120  XCTAssertEqual(value, 500.f);
2121  XCTAssertFalse([dict getFloat:NULL forKey:@"bar"]);
2122  XCTAssertTrue([dict getFloat:NULL forKey:@"baz"]);
2123  XCTAssertTrue([dict getFloat:&value forKey:@"baz"]);
2124  XCTAssertEqual(value, 502.f);
2125  XCTAssertTrue([dict getFloat:NULL forKey:@"mumble"]);
2126  XCTAssertTrue([dict getFloat:&value forKey:@"mumble"]);
2127  XCTAssertEqual(value, 503.f);
2128
2129  // Remove again does nothing.
2130  [dict removeFloatForKey:@"bar"];
2131  XCTAssertEqual(dict.count, 3U);
2132  XCTAssertTrue([dict getFloat:NULL forKey:@"foo"]);
2133  XCTAssertTrue([dict getFloat:&value forKey:@"foo"]);
2134  XCTAssertEqual(value, 500.f);
2135  XCTAssertFalse([dict getFloat:NULL forKey:@"bar"]);
2136  XCTAssertTrue([dict getFloat:NULL forKey:@"baz"]);
2137  XCTAssertTrue([dict getFloat:&value forKey:@"baz"]);
2138  XCTAssertEqual(value, 502.f);
2139  XCTAssertTrue([dict getFloat:NULL forKey:@"mumble"]);
2140  XCTAssertTrue([dict getFloat:&value forKey:@"mumble"]);
2141  XCTAssertEqual(value, 503.f);
2142
2143  [dict removeFloatForKey:@"mumble"];
2144  XCTAssertEqual(dict.count, 2U);
2145  XCTAssertTrue([dict getFloat:NULL forKey:@"foo"]);
2146  XCTAssertTrue([dict getFloat:&value forKey:@"foo"]);
2147  XCTAssertEqual(value, 500.f);
2148  XCTAssertFalse([dict getFloat:NULL forKey:@"bar"]);
2149  XCTAssertTrue([dict getFloat:NULL forKey:@"baz"]);
2150  XCTAssertTrue([dict getFloat:&value forKey:@"baz"]);
2151  XCTAssertEqual(value, 502.f);
2152  XCTAssertFalse([dict getFloat:NULL forKey:@"mumble"]);
2153
2154  [dict removeAll];
2155  XCTAssertEqual(dict.count, 0U);
2156  XCTAssertFalse([dict getFloat:NULL forKey:@"foo"]);
2157  XCTAssertFalse([dict getFloat:NULL forKey:@"bar"]);
2158  XCTAssertFalse([dict getFloat:NULL forKey:@"baz"]);
2159  XCTAssertFalse([dict getFloat:NULL forKey:@"mumble"]);
2160  [dict release];
2161}
2162
2163- (void)testInplaceMutation {
2164  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
2165  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
2166  GPBStringFloatDictionary *dict =
2167      [[GPBStringFloatDictionary alloc] initWithFloats:kValues
2168                                               forKeys:kKeys
2169                                                 count:GPBARRAYSIZE(kValues)];
2170  XCTAssertNotNil(dict);
2171  XCTAssertEqual(dict.count, 4U);
2172  float value;
2173  XCTAssertTrue([dict getFloat:NULL forKey:@"foo"]);
2174  XCTAssertTrue([dict getFloat:&value forKey:@"foo"]);
2175  XCTAssertEqual(value, 500.f);
2176  XCTAssertTrue([dict getFloat:NULL forKey:@"bar"]);
2177  XCTAssertTrue([dict getFloat:&value forKey:@"bar"]);
2178  XCTAssertEqual(value, 501.f);
2179  XCTAssertTrue([dict getFloat:NULL forKey:@"baz"]);
2180  XCTAssertTrue([dict getFloat:&value forKey:@"baz"]);
2181  XCTAssertEqual(value, 502.f);
2182  XCTAssertTrue([dict getFloat:NULL forKey:@"mumble"]);
2183  XCTAssertTrue([dict getFloat:&value forKey:@"mumble"]);
2184  XCTAssertEqual(value, 503.f);
2185
2186  [dict setFloat:503.f forKey:@"foo"];
2187  XCTAssertEqual(dict.count, 4U);
2188  XCTAssertTrue([dict getFloat:NULL forKey:@"foo"]);
2189  XCTAssertTrue([dict getFloat:&value forKey:@"foo"]);
2190  XCTAssertEqual(value, 503.f);
2191  XCTAssertTrue([dict getFloat:NULL forKey:@"bar"]);
2192  XCTAssertTrue([dict getFloat:&value forKey:@"bar"]);
2193  XCTAssertEqual(value, 501.f);
2194  XCTAssertTrue([dict getFloat:NULL forKey:@"baz"]);
2195  XCTAssertTrue([dict getFloat:&value forKey:@"baz"]);
2196  XCTAssertEqual(value, 502.f);
2197  XCTAssertTrue([dict getFloat:NULL forKey:@"mumble"]);
2198  XCTAssertTrue([dict getFloat:&value forKey:@"mumble"]);
2199  XCTAssertEqual(value, 503.f);
2200
2201  [dict setFloat:501.f forKey:@"mumble"];
2202  XCTAssertEqual(dict.count, 4U);
2203  XCTAssertTrue([dict getFloat:NULL forKey:@"foo"]);
2204  XCTAssertTrue([dict getFloat:&value forKey:@"foo"]);
2205  XCTAssertEqual(value, 503.f);
2206  XCTAssertTrue([dict getFloat:NULL forKey:@"bar"]);
2207  XCTAssertTrue([dict getFloat:&value forKey:@"bar"]);
2208  XCTAssertEqual(value, 501.f);
2209  XCTAssertTrue([dict getFloat:NULL forKey:@"baz"]);
2210  XCTAssertTrue([dict getFloat:&value forKey:@"baz"]);
2211  XCTAssertEqual(value, 502.f);
2212  XCTAssertTrue([dict getFloat:NULL forKey:@"mumble"]);
2213  XCTAssertTrue([dict getFloat:&value forKey:@"mumble"]);
2214  XCTAssertEqual(value, 501.f);
2215
2216  const NSString *kKeys2[] = { @"bar", @"baz" };
2217  const float kValues2[] = { 502.f, 500.f };
2218  GPBStringFloatDictionary *dict2 =
2219      [[GPBStringFloatDictionary alloc] initWithFloats:kValues2
2220                                               forKeys:kKeys2
2221                                                 count:GPBARRAYSIZE(kValues2)];
2222  XCTAssertNotNil(dict2);
2223  [dict addEntriesFromDictionary:dict2];
2224  XCTAssertEqual(dict.count, 4U);
2225  XCTAssertTrue([dict getFloat:NULL forKey:@"foo"]);
2226  XCTAssertTrue([dict getFloat:&value forKey:@"foo"]);
2227  XCTAssertEqual(value, 503.f);
2228  XCTAssertTrue([dict getFloat:NULL forKey:@"bar"]);
2229  XCTAssertTrue([dict getFloat:&value forKey:@"bar"]);
2230  XCTAssertEqual(value, 502.f);
2231  XCTAssertTrue([dict getFloat:NULL forKey:@"baz"]);
2232  XCTAssertTrue([dict getFloat:&value forKey:@"baz"]);
2233  XCTAssertEqual(value, 500.f);
2234  XCTAssertTrue([dict getFloat:NULL forKey:@"mumble"]);
2235  XCTAssertTrue([dict getFloat:&value forKey:@"mumble"]);
2236  XCTAssertEqual(value, 501.f);
2237
2238  [dict2 release];
2239  [dict release];
2240}
2241
2242@end
2243
2244#pragma mark - String -> Double
2245
2246@interface GPBStringDoubleDictionaryTests : XCTestCase
2247@end
2248
2249@implementation GPBStringDoubleDictionaryTests
2250
2251- (void)testEmpty {
2252  GPBStringDoubleDictionary *dict = [[GPBStringDoubleDictionary alloc] init];
2253  XCTAssertNotNil(dict);
2254  XCTAssertEqual(dict.count, 0U);
2255  XCTAssertFalse([dict getDouble:NULL forKey:@"foo"]);
2256  [dict enumerateKeysAndDoublesUsingBlock:^(NSString *aKey, double aValue, BOOL *stop) {
2257    #pragma unused(aKey, aValue, stop)
2258    XCTFail(@"Shouldn't get here!");
2259  }];
2260  [dict release];
2261}
2262
2263- (void)testOne {
2264  GPBStringDoubleDictionary *dict = [[GPBStringDoubleDictionary alloc] init];
2265  [dict setDouble:600. forKey:@"foo"];
2266  XCTAssertNotNil(dict);
2267  XCTAssertEqual(dict.count, 1U);
2268  double value;
2269  XCTAssertTrue([dict getDouble:NULL forKey:@"foo"]);
2270  XCTAssertTrue([dict getDouble:&value forKey:@"foo"]);
2271  XCTAssertEqual(value, 600.);
2272  XCTAssertFalse([dict getDouble:NULL forKey:@"bar"]);
2273  [dict enumerateKeysAndDoublesUsingBlock:^(NSString *aKey, double aValue, BOOL *stop) {
2274    XCTAssertEqualObjects(aKey, @"foo");
2275    XCTAssertEqual(aValue, 600.);
2276    XCTAssertNotEqual(stop, NULL);
2277  }];
2278  [dict release];
2279}
2280
2281- (void)testBasics {
2282  const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
2283  const double kValues[] = { 600., 601., 602. };
2284  GPBStringDoubleDictionary *dict =
2285      [[GPBStringDoubleDictionary alloc] initWithDoubles:kValues
2286                                                 forKeys:kKeys
2287                                                   count:GPBARRAYSIZE(kValues)];
2288  XCTAssertNotNil(dict);
2289  XCTAssertEqual(dict.count, 3U);
2290  double value;
2291  XCTAssertTrue([dict getDouble:NULL forKey:@"foo"]);
2292  XCTAssertTrue([dict getDouble:&value forKey:@"foo"]);
2293  XCTAssertEqual(value, 600.);
2294  XCTAssertTrue([dict getDouble:NULL forKey:@"bar"]);
2295  XCTAssertTrue([dict getDouble:&value forKey:@"bar"]);
2296  XCTAssertEqual(value, 601.);
2297  XCTAssertTrue([dict getDouble:NULL forKey:@"baz"]);
2298  XCTAssertTrue([dict getDouble:&value forKey:@"baz"]);
2299  XCTAssertEqual(value, 602.);
2300  XCTAssertFalse([dict getDouble:NULL forKey:@"mumble"]);
2301
2302  __block NSUInteger idx = 0;
2303  NSString **seenKeys = malloc(3 * sizeof(NSString*));
2304  double *seenValues = malloc(3 * sizeof(double));
2305  [dict enumerateKeysAndDoublesUsingBlock:^(NSString *aKey, double aValue, BOOL *stop) {
2306    XCTAssertLessThan(idx, 3U);
2307    seenKeys[idx] = aKey;
2308    seenValues[idx] = aValue;
2309    XCTAssertNotEqual(stop, NULL);
2310    ++idx;
2311  }];
2312  for (int i = 0; i < 3; ++i) {
2313    BOOL foundKey = NO;
2314    for (int j = 0; (j < 3) && !foundKey; ++j) {
2315      if ([kKeys[i] isEqual:seenKeys[j]]) {
2316        foundKey = YES;
2317        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
2318      }
2319    }
2320    XCTAssertTrue(foundKey, @"i = %d", i);
2321  }
2322  free(seenKeys);
2323  free(seenValues);
2324
2325  // Stopping the enumeration.
2326  idx = 0;
2327  [dict enumerateKeysAndDoublesUsingBlock:^(NSString *aKey, double aValue, BOOL *stop) {
2328    #pragma unused(aKey, aValue)
2329    if (idx == 1) *stop = YES;
2330    XCTAssertNotEqual(idx, 2U);
2331    ++idx;
2332  }];
2333  [dict release];
2334}
2335
2336- (void)testEquality {
2337  const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
2338  const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
2339  const double kValues1[] = { 600., 601., 602. };
2340  const double kValues2[] = { 600., 603., 602. };
2341  const double kValues3[] = { 600., 601., 602., 603. };
2342  GPBStringDoubleDictionary *dict1 =
2343      [[GPBStringDoubleDictionary alloc] initWithDoubles:kValues1
2344                                                 forKeys:kKeys1
2345                                                   count:GPBARRAYSIZE(kValues1)];
2346  XCTAssertNotNil(dict1);
2347  GPBStringDoubleDictionary *dict1prime =
2348      [[GPBStringDoubleDictionary alloc] initWithDoubles:kValues1
2349                                                 forKeys:kKeys1
2350                                                   count:GPBARRAYSIZE(kValues1)];
2351  XCTAssertNotNil(dict1prime);
2352  GPBStringDoubleDictionary *dict2 =
2353      [[GPBStringDoubleDictionary alloc] initWithDoubles:kValues2
2354                                                 forKeys:kKeys1
2355                                                   count:GPBARRAYSIZE(kValues2)];
2356  XCTAssertNotNil(dict2);
2357  GPBStringDoubleDictionary *dict3 =
2358      [[GPBStringDoubleDictionary alloc] initWithDoubles:kValues1
2359                                                 forKeys:kKeys2
2360                                                   count:GPBARRAYSIZE(kValues1)];
2361  XCTAssertNotNil(dict3);
2362  GPBStringDoubleDictionary *dict4 =
2363      [[GPBStringDoubleDictionary alloc] initWithDoubles:kValues3
2364                                                 forKeys:kKeys1
2365                                                   count:GPBARRAYSIZE(kValues3)];
2366  XCTAssertNotNil(dict4);
2367
2368  // 1/1Prime should be different objects, but equal.
2369  XCTAssertNotEqual(dict1, dict1prime);
2370  XCTAssertEqualObjects(dict1, dict1prime);
2371  // Equal, so they must have same hash.
2372  XCTAssertEqual([dict1 hash], [dict1prime hash]);
2373
2374  // 2 is same keys, different values; not equal.
2375  XCTAssertNotEqualObjects(dict1, dict2);
2376
2377  // 3 is different keys, same values; not equal.
2378  XCTAssertNotEqualObjects(dict1, dict3);
2379
2380  // 4 extra pair; not equal
2381  XCTAssertNotEqualObjects(dict1, dict4);
2382
2383  [dict1 release];
2384  [dict1prime release];
2385  [dict2 release];
2386  [dict3 release];
2387  [dict4 release];
2388}
2389
2390- (void)testCopy {
2391  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
2392  const double kValues[] = { 600., 601., 602., 603. };
2393  GPBStringDoubleDictionary *dict =
2394      [[GPBStringDoubleDictionary alloc] initWithDoubles:kValues
2395                                                 forKeys:kKeys
2396                                                   count:GPBARRAYSIZE(kValues)];
2397  XCTAssertNotNil(dict);
2398
2399  GPBStringDoubleDictionary *dict2 = [dict copy];
2400  XCTAssertNotNil(dict2);
2401
2402  // Should be new object but equal.
2403  XCTAssertNotEqual(dict, dict2);
2404  XCTAssertEqualObjects(dict, dict2);
2405  XCTAssertTrue([dict2 isKindOfClass:[GPBStringDoubleDictionary class]]);
2406
2407  [dict2 release];
2408  [dict release];
2409}
2410
2411- (void)testDictionaryFromDictionary {
2412  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
2413  const double kValues[] = { 600., 601., 602., 603. };
2414  GPBStringDoubleDictionary *dict =
2415      [[GPBStringDoubleDictionary alloc] initWithDoubles:kValues
2416                                                 forKeys:kKeys
2417                                                   count:GPBARRAYSIZE(kValues)];
2418  XCTAssertNotNil(dict);
2419
2420  GPBStringDoubleDictionary *dict2 =
2421      [[GPBStringDoubleDictionary alloc] initWithDictionary:dict];
2422  XCTAssertNotNil(dict2);
2423
2424  // Should be new pointer, but equal objects.
2425  XCTAssertNotEqual(dict, dict2);
2426  XCTAssertEqualObjects(dict, dict2);
2427  [dict2 release];
2428  [dict release];
2429}
2430
2431- (void)testAdds {
2432  GPBStringDoubleDictionary *dict = [[GPBStringDoubleDictionary alloc] init];
2433  XCTAssertNotNil(dict);
2434
2435  XCTAssertEqual(dict.count, 0U);
2436  [dict setDouble:600. forKey:@"foo"];
2437  XCTAssertEqual(dict.count, 1U);
2438
2439  const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
2440  const double kValues[] = { 601., 602., 603. };
2441  GPBStringDoubleDictionary *dict2 =
2442      [[GPBStringDoubleDictionary alloc] initWithDoubles:kValues
2443                                                 forKeys:kKeys
2444                                                   count:GPBARRAYSIZE(kValues)];
2445  XCTAssertNotNil(dict2);
2446  [dict addEntriesFromDictionary:dict2];
2447  XCTAssertEqual(dict.count, 4U);
2448
2449  double value;
2450  XCTAssertTrue([dict getDouble:NULL forKey:@"foo"]);
2451  XCTAssertTrue([dict getDouble:&value forKey:@"foo"]);
2452  XCTAssertEqual(value, 600.);
2453  XCTAssertTrue([dict getDouble:NULL forKey:@"bar"]);
2454  XCTAssertTrue([dict getDouble:&value forKey:@"bar"]);
2455  XCTAssertEqual(value, 601.);
2456  XCTAssertTrue([dict getDouble:NULL forKey:@"baz"]);
2457  XCTAssertTrue([dict getDouble:&value forKey:@"baz"]);
2458  XCTAssertEqual(value, 602.);
2459  XCTAssertTrue([dict getDouble:NULL forKey:@"mumble"]);
2460  XCTAssertTrue([dict getDouble:&value forKey:@"mumble"]);
2461  XCTAssertEqual(value, 603.);
2462  [dict2 release];
2463  [dict release];
2464}
2465
2466- (void)testRemove {
2467  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
2468  const double kValues[] = { 600., 601., 602., 603. };
2469  GPBStringDoubleDictionary *dict =
2470      [[GPBStringDoubleDictionary alloc] initWithDoubles:kValues
2471                                                 forKeys:kKeys
2472                                                   count:GPBARRAYSIZE(kValues)];
2473  XCTAssertNotNil(dict);
2474  XCTAssertEqual(dict.count, 4U);
2475
2476  [dict removeDoubleForKey:@"bar"];
2477  XCTAssertEqual(dict.count, 3U);
2478  double value;
2479  XCTAssertTrue([dict getDouble:NULL forKey:@"foo"]);
2480  XCTAssertTrue([dict getDouble:&value forKey:@"foo"]);
2481  XCTAssertEqual(value, 600.);
2482  XCTAssertFalse([dict getDouble:NULL forKey:@"bar"]);
2483  XCTAssertTrue([dict getDouble:NULL forKey:@"baz"]);
2484  XCTAssertTrue([dict getDouble:&value forKey:@"baz"]);
2485  XCTAssertEqual(value, 602.);
2486  XCTAssertTrue([dict getDouble:NULL forKey:@"mumble"]);
2487  XCTAssertTrue([dict getDouble:&value forKey:@"mumble"]);
2488  XCTAssertEqual(value, 603.);
2489
2490  // Remove again does nothing.
2491  [dict removeDoubleForKey:@"bar"];
2492  XCTAssertEqual(dict.count, 3U);
2493  XCTAssertTrue([dict getDouble:NULL forKey:@"foo"]);
2494  XCTAssertTrue([dict getDouble:&value forKey:@"foo"]);
2495  XCTAssertEqual(value, 600.);
2496  XCTAssertFalse([dict getDouble:NULL forKey:@"bar"]);
2497  XCTAssertTrue([dict getDouble:NULL forKey:@"baz"]);
2498  XCTAssertTrue([dict getDouble:&value forKey:@"baz"]);
2499  XCTAssertEqual(value, 602.);
2500  XCTAssertTrue([dict getDouble:NULL forKey:@"mumble"]);
2501  XCTAssertTrue([dict getDouble:&value forKey:@"mumble"]);
2502  XCTAssertEqual(value, 603.);
2503
2504  [dict removeDoubleForKey:@"mumble"];
2505  XCTAssertEqual(dict.count, 2U);
2506  XCTAssertTrue([dict getDouble:NULL forKey:@"foo"]);
2507  XCTAssertTrue([dict getDouble:&value forKey:@"foo"]);
2508  XCTAssertEqual(value, 600.);
2509  XCTAssertFalse([dict getDouble:NULL forKey:@"bar"]);
2510  XCTAssertTrue([dict getDouble:NULL forKey:@"baz"]);
2511  XCTAssertTrue([dict getDouble:&value forKey:@"baz"]);
2512  XCTAssertEqual(value, 602.);
2513  XCTAssertFalse([dict getDouble:NULL forKey:@"mumble"]);
2514
2515  [dict removeAll];
2516  XCTAssertEqual(dict.count, 0U);
2517  XCTAssertFalse([dict getDouble:NULL forKey:@"foo"]);
2518  XCTAssertFalse([dict getDouble:NULL forKey:@"bar"]);
2519  XCTAssertFalse([dict getDouble:NULL forKey:@"baz"]);
2520  XCTAssertFalse([dict getDouble:NULL forKey:@"mumble"]);
2521  [dict release];
2522}
2523
2524- (void)testInplaceMutation {
2525  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
2526  const double kValues[] = { 600., 601., 602., 603. };
2527  GPBStringDoubleDictionary *dict =
2528      [[GPBStringDoubleDictionary alloc] initWithDoubles:kValues
2529                                                 forKeys:kKeys
2530                                                   count:GPBARRAYSIZE(kValues)];
2531  XCTAssertNotNil(dict);
2532  XCTAssertEqual(dict.count, 4U);
2533  double value;
2534  XCTAssertTrue([dict getDouble:NULL forKey:@"foo"]);
2535  XCTAssertTrue([dict getDouble:&value forKey:@"foo"]);
2536  XCTAssertEqual(value, 600.);
2537  XCTAssertTrue([dict getDouble:NULL forKey:@"bar"]);
2538  XCTAssertTrue([dict getDouble:&value forKey:@"bar"]);
2539  XCTAssertEqual(value, 601.);
2540  XCTAssertTrue([dict getDouble:NULL forKey:@"baz"]);
2541  XCTAssertTrue([dict getDouble:&value forKey:@"baz"]);
2542  XCTAssertEqual(value, 602.);
2543  XCTAssertTrue([dict getDouble:NULL forKey:@"mumble"]);
2544  XCTAssertTrue([dict getDouble:&value forKey:@"mumble"]);
2545  XCTAssertEqual(value, 603.);
2546
2547  [dict setDouble:603. forKey:@"foo"];
2548  XCTAssertEqual(dict.count, 4U);
2549  XCTAssertTrue([dict getDouble:NULL forKey:@"foo"]);
2550  XCTAssertTrue([dict getDouble:&value forKey:@"foo"]);
2551  XCTAssertEqual(value, 603.);
2552  XCTAssertTrue([dict getDouble:NULL forKey:@"bar"]);
2553  XCTAssertTrue([dict getDouble:&value forKey:@"bar"]);
2554  XCTAssertEqual(value, 601.);
2555  XCTAssertTrue([dict getDouble:NULL forKey:@"baz"]);
2556  XCTAssertTrue([dict getDouble:&value forKey:@"baz"]);
2557  XCTAssertEqual(value, 602.);
2558  XCTAssertTrue([dict getDouble:NULL forKey:@"mumble"]);
2559  XCTAssertTrue([dict getDouble:&value forKey:@"mumble"]);
2560  XCTAssertEqual(value, 603.);
2561
2562  [dict setDouble:601. forKey:@"mumble"];
2563  XCTAssertEqual(dict.count, 4U);
2564  XCTAssertTrue([dict getDouble:NULL forKey:@"foo"]);
2565  XCTAssertTrue([dict getDouble:&value forKey:@"foo"]);
2566  XCTAssertEqual(value, 603.);
2567  XCTAssertTrue([dict getDouble:NULL forKey:@"bar"]);
2568  XCTAssertTrue([dict getDouble:&value forKey:@"bar"]);
2569  XCTAssertEqual(value, 601.);
2570  XCTAssertTrue([dict getDouble:NULL forKey:@"baz"]);
2571  XCTAssertTrue([dict getDouble:&value forKey:@"baz"]);
2572  XCTAssertEqual(value, 602.);
2573  XCTAssertTrue([dict getDouble:NULL forKey:@"mumble"]);
2574  XCTAssertTrue([dict getDouble:&value forKey:@"mumble"]);
2575  XCTAssertEqual(value, 601.);
2576
2577  const NSString *kKeys2[] = { @"bar", @"baz" };
2578  const double kValues2[] = { 602., 600. };
2579  GPBStringDoubleDictionary *dict2 =
2580      [[GPBStringDoubleDictionary alloc] initWithDoubles:kValues2
2581                                                 forKeys:kKeys2
2582                                                   count:GPBARRAYSIZE(kValues2)];
2583  XCTAssertNotNil(dict2);
2584  [dict addEntriesFromDictionary:dict2];
2585  XCTAssertEqual(dict.count, 4U);
2586  XCTAssertTrue([dict getDouble:NULL forKey:@"foo"]);
2587  XCTAssertTrue([dict getDouble:&value forKey:@"foo"]);
2588  XCTAssertEqual(value, 603.);
2589  XCTAssertTrue([dict getDouble:NULL forKey:@"bar"]);
2590  XCTAssertTrue([dict getDouble:&value forKey:@"bar"]);
2591  XCTAssertEqual(value, 602.);
2592  XCTAssertTrue([dict getDouble:NULL forKey:@"baz"]);
2593  XCTAssertTrue([dict getDouble:&value forKey:@"baz"]);
2594  XCTAssertEqual(value, 600.);
2595  XCTAssertTrue([dict getDouble:NULL forKey:@"mumble"]);
2596  XCTAssertTrue([dict getDouble:&value forKey:@"mumble"]);
2597  XCTAssertEqual(value, 601.);
2598
2599  [dict2 release];
2600  [dict release];
2601}
2602
2603@end
2604
2605#pragma mark - String -> Enum
2606
2607@interface GPBStringEnumDictionaryTests : XCTestCase
2608@end
2609
2610@implementation GPBStringEnumDictionaryTests
2611
2612- (void)testEmpty {
2613  GPBStringEnumDictionary *dict = [[GPBStringEnumDictionary alloc] init];
2614  XCTAssertNotNil(dict);
2615  XCTAssertEqual(dict.count, 0U);
2616  XCTAssertFalse([dict getEnum:NULL forKey:@"foo"]);
2617  [dict enumerateKeysAndEnumsUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
2618    #pragma unused(aKey, aValue, stop)
2619    XCTFail(@"Shouldn't get here!");
2620  }];
2621  [dict release];
2622}
2623
2624- (void)testOne {
2625  GPBStringEnumDictionary *dict = [[GPBStringEnumDictionary alloc] init];
2626  [dict setEnum:700 forKey:@"foo"];
2627  XCTAssertNotNil(dict);
2628  XCTAssertEqual(dict.count, 1U);
2629  int32_t value;
2630  XCTAssertTrue([dict getEnum:NULL forKey:@"foo"]);
2631  XCTAssertTrue([dict getEnum:&value forKey:@"foo"]);
2632  XCTAssertEqual(value, 700);
2633  XCTAssertFalse([dict getEnum:NULL forKey:@"bar"]);
2634  [dict enumerateKeysAndEnumsUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
2635    XCTAssertEqualObjects(aKey, @"foo");
2636    XCTAssertEqual(aValue, 700);
2637    XCTAssertNotEqual(stop, NULL);
2638  }];
2639  [dict release];
2640}
2641
2642- (void)testBasics {
2643  const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
2644  const int32_t kValues[] = { 700, 701, 702 };
2645  GPBStringEnumDictionary *dict =
2646      [[GPBStringEnumDictionary alloc] initWithEnums:kValues
2647                                             forKeys:kKeys
2648                                               count:GPBARRAYSIZE(kValues)];
2649  XCTAssertNotNil(dict);
2650  XCTAssertEqual(dict.count, 3U);
2651  int32_t value;
2652  XCTAssertTrue([dict getEnum:NULL forKey:@"foo"]);
2653  XCTAssertTrue([dict getEnum:&value forKey:@"foo"]);
2654  XCTAssertEqual(value, 700);
2655  XCTAssertTrue([dict getEnum:NULL forKey:@"bar"]);
2656  XCTAssertTrue([dict getEnum:&value forKey:@"bar"]);
2657  XCTAssertEqual(value, 701);
2658  XCTAssertTrue([dict getEnum:NULL forKey:@"baz"]);
2659  XCTAssertTrue([dict getEnum:&value forKey:@"baz"]);
2660  XCTAssertEqual(value, 702);
2661  XCTAssertFalse([dict getEnum:NULL forKey:@"mumble"]);
2662
2663  __block NSUInteger idx = 0;
2664  NSString **seenKeys = malloc(3 * sizeof(NSString*));
2665  int32_t *seenValues = malloc(3 * sizeof(int32_t));
2666  [dict enumerateKeysAndEnumsUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
2667    XCTAssertLessThan(idx, 3U);
2668    seenKeys[idx] = aKey;
2669    seenValues[idx] = aValue;
2670    XCTAssertNotEqual(stop, NULL);
2671    ++idx;
2672  }];
2673  for (int i = 0; i < 3; ++i) {
2674    BOOL foundKey = NO;
2675    for (int j = 0; (j < 3) && !foundKey; ++j) {
2676      if ([kKeys[i] isEqual:seenKeys[j]]) {
2677        foundKey = YES;
2678        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
2679      }
2680    }
2681    XCTAssertTrue(foundKey, @"i = %d", i);
2682  }
2683  free(seenKeys);
2684  free(seenValues);
2685
2686  // Stopping the enumeration.
2687  idx = 0;
2688  [dict enumerateKeysAndEnumsUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
2689    #pragma unused(aKey, aValue)
2690    if (idx == 1) *stop = YES;
2691    XCTAssertNotEqual(idx, 2U);
2692    ++idx;
2693  }];
2694  [dict release];
2695}
2696
2697- (void)testEquality {
2698  const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
2699  const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
2700  const int32_t kValues1[] = { 700, 701, 702 };
2701  const int32_t kValues2[] = { 700, 703, 702 };
2702  const int32_t kValues3[] = { 700, 701, 702, 703 };
2703  GPBStringEnumDictionary *dict1 =
2704      [[GPBStringEnumDictionary alloc] initWithEnums:kValues1
2705                                             forKeys:kKeys1
2706                                               count:GPBARRAYSIZE(kValues1)];
2707  XCTAssertNotNil(dict1);
2708  GPBStringEnumDictionary *dict1prime =
2709      [[GPBStringEnumDictionary alloc] initWithEnums:kValues1
2710                                             forKeys:kKeys1
2711                                               count:GPBARRAYSIZE(kValues1)];
2712  XCTAssertNotNil(dict1prime);
2713  GPBStringEnumDictionary *dict2 =
2714      [[GPBStringEnumDictionary alloc] initWithEnums:kValues2
2715                                             forKeys:kKeys1
2716                                               count:GPBARRAYSIZE(kValues2)];
2717  XCTAssertNotNil(dict2);
2718  GPBStringEnumDictionary *dict3 =
2719      [[GPBStringEnumDictionary alloc] initWithEnums:kValues1
2720                                             forKeys:kKeys2
2721                                               count:GPBARRAYSIZE(kValues1)];
2722  XCTAssertNotNil(dict3);
2723  GPBStringEnumDictionary *dict4 =
2724      [[GPBStringEnumDictionary alloc] initWithEnums:kValues3
2725                                             forKeys:kKeys1
2726                                               count:GPBARRAYSIZE(kValues3)];
2727  XCTAssertNotNil(dict4);
2728
2729  // 1/1Prime should be different objects, but equal.
2730  XCTAssertNotEqual(dict1, dict1prime);
2731  XCTAssertEqualObjects(dict1, dict1prime);
2732  // Equal, so they must have same hash.
2733  XCTAssertEqual([dict1 hash], [dict1prime hash]);
2734
2735  // 2 is same keys, different values; not equal.
2736  XCTAssertNotEqualObjects(dict1, dict2);
2737
2738  // 3 is different keys, same values; not equal.
2739  XCTAssertNotEqualObjects(dict1, dict3);
2740
2741  // 4 extra pair; not equal
2742  XCTAssertNotEqualObjects(dict1, dict4);
2743
2744  [dict1 release];
2745  [dict1prime release];
2746  [dict2 release];
2747  [dict3 release];
2748  [dict4 release];
2749}
2750
2751- (void)testCopy {
2752  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
2753  const int32_t kValues[] = { 700, 701, 702, 703 };
2754  GPBStringEnumDictionary *dict =
2755      [[GPBStringEnumDictionary alloc] initWithEnums:kValues
2756                                             forKeys:kKeys
2757                                               count:GPBARRAYSIZE(kValues)];
2758  XCTAssertNotNil(dict);
2759
2760  GPBStringEnumDictionary *dict2 = [dict copy];
2761  XCTAssertNotNil(dict2);
2762
2763  // Should be new object but equal.
2764  XCTAssertNotEqual(dict, dict2);
2765  XCTAssertEqualObjects(dict, dict2);
2766  XCTAssertTrue([dict2 isKindOfClass:[GPBStringEnumDictionary class]]);
2767
2768  [dict2 release];
2769  [dict release];
2770}
2771
2772- (void)testDictionaryFromDictionary {
2773  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
2774  const int32_t kValues[] = { 700, 701, 702, 703 };
2775  GPBStringEnumDictionary *dict =
2776      [[GPBStringEnumDictionary alloc] initWithEnums:kValues
2777                                             forKeys:kKeys
2778                                               count:GPBARRAYSIZE(kValues)];
2779  XCTAssertNotNil(dict);
2780
2781  GPBStringEnumDictionary *dict2 =
2782      [[GPBStringEnumDictionary alloc] initWithDictionary:dict];
2783  XCTAssertNotNil(dict2);
2784
2785  // Should be new pointer, but equal objects.
2786  XCTAssertNotEqual(dict, dict2);
2787  XCTAssertEqualObjects(dict, dict2);
2788  [dict2 release];
2789  [dict release];
2790}
2791
2792- (void)testAdds {
2793  GPBStringEnumDictionary *dict = [[GPBStringEnumDictionary alloc] init];
2794  XCTAssertNotNil(dict);
2795
2796  XCTAssertEqual(dict.count, 0U);
2797  [dict setEnum:700 forKey:@"foo"];
2798  XCTAssertEqual(dict.count, 1U);
2799
2800  const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
2801  const int32_t kValues[] = { 701, 702, 703 };
2802  GPBStringEnumDictionary *dict2 =
2803      [[GPBStringEnumDictionary alloc] initWithEnums:kValues
2804                                             forKeys:kKeys
2805                                               count:GPBARRAYSIZE(kValues)];
2806  XCTAssertNotNil(dict2);
2807  [dict addRawEntriesFromDictionary:dict2];
2808  XCTAssertEqual(dict.count, 4U);
2809
2810  int32_t value;
2811  XCTAssertTrue([dict getEnum:NULL forKey:@"foo"]);
2812  XCTAssertTrue([dict getEnum:&value forKey:@"foo"]);
2813  XCTAssertEqual(value, 700);
2814  XCTAssertTrue([dict getEnum:NULL forKey:@"bar"]);
2815  XCTAssertTrue([dict getEnum:&value forKey:@"bar"]);
2816  XCTAssertEqual(value, 701);
2817  XCTAssertTrue([dict getEnum:NULL forKey:@"baz"]);
2818  XCTAssertTrue([dict getEnum:&value forKey:@"baz"]);
2819  XCTAssertEqual(value, 702);
2820  XCTAssertTrue([dict getEnum:NULL forKey:@"mumble"]);
2821  XCTAssertTrue([dict getEnum:&value forKey:@"mumble"]);
2822  XCTAssertEqual(value, 703);
2823  [dict2 release];
2824  [dict release];
2825}
2826
2827- (void)testRemove {
2828  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
2829  const int32_t kValues[] = { 700, 701, 702, 703 };
2830  GPBStringEnumDictionary *dict =
2831      [[GPBStringEnumDictionary alloc] initWithEnums:kValues
2832                                             forKeys:kKeys
2833                                               count:GPBARRAYSIZE(kValues)];
2834  XCTAssertNotNil(dict);
2835  XCTAssertEqual(dict.count, 4U);
2836
2837  [dict removeEnumForKey:@"bar"];
2838  XCTAssertEqual(dict.count, 3U);
2839  int32_t value;
2840  XCTAssertTrue([dict getEnum:NULL forKey:@"foo"]);
2841  XCTAssertTrue([dict getEnum:&value forKey:@"foo"]);
2842  XCTAssertEqual(value, 700);
2843  XCTAssertFalse([dict getEnum:NULL forKey:@"bar"]);
2844  XCTAssertTrue([dict getEnum:NULL forKey:@"baz"]);
2845  XCTAssertTrue([dict getEnum:&value forKey:@"baz"]);
2846  XCTAssertEqual(value, 702);
2847  XCTAssertTrue([dict getEnum:NULL forKey:@"mumble"]);
2848  XCTAssertTrue([dict getEnum:&value forKey:@"mumble"]);
2849  XCTAssertEqual(value, 703);
2850
2851  // Remove again does nothing.
2852  [dict removeEnumForKey:@"bar"];
2853  XCTAssertEqual(dict.count, 3U);
2854  XCTAssertTrue([dict getEnum:NULL forKey:@"foo"]);
2855  XCTAssertTrue([dict getEnum:&value forKey:@"foo"]);
2856  XCTAssertEqual(value, 700);
2857  XCTAssertFalse([dict getEnum:NULL forKey:@"bar"]);
2858  XCTAssertTrue([dict getEnum:NULL forKey:@"baz"]);
2859  XCTAssertTrue([dict getEnum:&value forKey:@"baz"]);
2860  XCTAssertEqual(value, 702);
2861  XCTAssertTrue([dict getEnum:NULL forKey:@"mumble"]);
2862  XCTAssertTrue([dict getEnum:&value forKey:@"mumble"]);
2863  XCTAssertEqual(value, 703);
2864
2865  [dict removeEnumForKey:@"mumble"];
2866  XCTAssertEqual(dict.count, 2U);
2867  XCTAssertTrue([dict getEnum:NULL forKey:@"foo"]);
2868  XCTAssertTrue([dict getEnum:&value forKey:@"foo"]);
2869  XCTAssertEqual(value, 700);
2870  XCTAssertFalse([dict getEnum:NULL forKey:@"bar"]);
2871  XCTAssertTrue([dict getEnum:NULL forKey:@"baz"]);
2872  XCTAssertTrue([dict getEnum:&value forKey:@"baz"]);
2873  XCTAssertEqual(value, 702);
2874  XCTAssertFalse([dict getEnum:NULL forKey:@"mumble"]);
2875
2876  [dict removeAll];
2877  XCTAssertEqual(dict.count, 0U);
2878  XCTAssertFalse([dict getEnum:NULL forKey:@"foo"]);
2879  XCTAssertFalse([dict getEnum:NULL forKey:@"bar"]);
2880  XCTAssertFalse([dict getEnum:NULL forKey:@"baz"]);
2881  XCTAssertFalse([dict getEnum:NULL forKey:@"mumble"]);
2882  [dict release];
2883}
2884
2885- (void)testInplaceMutation {
2886  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
2887  const int32_t kValues[] = { 700, 701, 702, 703 };
2888  GPBStringEnumDictionary *dict =
2889      [[GPBStringEnumDictionary alloc] initWithEnums:kValues
2890                                             forKeys:kKeys
2891                                               count:GPBARRAYSIZE(kValues)];
2892  XCTAssertNotNil(dict);
2893  XCTAssertEqual(dict.count, 4U);
2894  int32_t value;
2895  XCTAssertTrue([dict getEnum:NULL forKey:@"foo"]);
2896  XCTAssertTrue([dict getEnum:&value forKey:@"foo"]);
2897  XCTAssertEqual(value, 700);
2898  XCTAssertTrue([dict getEnum:NULL forKey:@"bar"]);
2899  XCTAssertTrue([dict getEnum:&value forKey:@"bar"]);
2900  XCTAssertEqual(value, 701);
2901  XCTAssertTrue([dict getEnum:NULL forKey:@"baz"]);
2902  XCTAssertTrue([dict getEnum:&value forKey:@"baz"]);
2903  XCTAssertEqual(value, 702);
2904  XCTAssertTrue([dict getEnum:NULL forKey:@"mumble"]);
2905  XCTAssertTrue([dict getEnum:&value forKey:@"mumble"]);
2906  XCTAssertEqual(value, 703);
2907
2908  [dict setEnum:703 forKey:@"foo"];
2909  XCTAssertEqual(dict.count, 4U);
2910  XCTAssertTrue([dict getEnum:NULL forKey:@"foo"]);
2911  XCTAssertTrue([dict getEnum:&value forKey:@"foo"]);
2912  XCTAssertEqual(value, 703);
2913  XCTAssertTrue([dict getEnum:NULL forKey:@"bar"]);
2914  XCTAssertTrue([dict getEnum:&value forKey:@"bar"]);
2915  XCTAssertEqual(value, 701);
2916  XCTAssertTrue([dict getEnum:NULL forKey:@"baz"]);
2917  XCTAssertTrue([dict getEnum:&value forKey:@"baz"]);
2918  XCTAssertEqual(value, 702);
2919  XCTAssertTrue([dict getEnum:NULL forKey:@"mumble"]);
2920  XCTAssertTrue([dict getEnum:&value forKey:@"mumble"]);
2921  XCTAssertEqual(value, 703);
2922
2923  [dict setEnum:701 forKey:@"mumble"];
2924  XCTAssertEqual(dict.count, 4U);
2925  XCTAssertTrue([dict getEnum:NULL forKey:@"foo"]);
2926  XCTAssertTrue([dict getEnum:&value forKey:@"foo"]);
2927  XCTAssertEqual(value, 703);
2928  XCTAssertTrue([dict getEnum:NULL forKey:@"bar"]);
2929  XCTAssertTrue([dict getEnum:&value forKey:@"bar"]);
2930  XCTAssertEqual(value, 701);
2931  XCTAssertTrue([dict getEnum:NULL forKey:@"baz"]);
2932  XCTAssertTrue([dict getEnum:&value forKey:@"baz"]);
2933  XCTAssertEqual(value, 702);
2934  XCTAssertTrue([dict getEnum:NULL forKey:@"mumble"]);
2935  XCTAssertTrue([dict getEnum:&value forKey:@"mumble"]);
2936  XCTAssertEqual(value, 701);
2937
2938  const NSString *kKeys2[] = { @"bar", @"baz" };
2939  const int32_t kValues2[] = { 702, 700 };
2940  GPBStringEnumDictionary *dict2 =
2941      [[GPBStringEnumDictionary alloc] initWithEnums:kValues2
2942                                             forKeys:kKeys2
2943                                               count:GPBARRAYSIZE(kValues2)];
2944  XCTAssertNotNil(dict2);
2945  [dict addRawEntriesFromDictionary:dict2];
2946  XCTAssertEqual(dict.count, 4U);
2947  XCTAssertTrue([dict getEnum:NULL forKey:@"foo"]);
2948  XCTAssertTrue([dict getEnum:&value forKey:@"foo"]);
2949  XCTAssertEqual(value, 703);
2950  XCTAssertTrue([dict getEnum:NULL forKey:@"bar"]);
2951  XCTAssertTrue([dict getEnum:&value forKey:@"bar"]);
2952  XCTAssertEqual(value, 702);
2953  XCTAssertTrue([dict getEnum:NULL forKey:@"baz"]);
2954  XCTAssertTrue([dict getEnum:&value forKey:@"baz"]);
2955  XCTAssertEqual(value, 700);
2956  XCTAssertTrue([dict getEnum:NULL forKey:@"mumble"]);
2957  XCTAssertTrue([dict getEnum:&value forKey:@"mumble"]);
2958  XCTAssertEqual(value, 701);
2959
2960  [dict2 release];
2961  [dict release];
2962}
2963
2964@end
2965
2966#pragma mark - String -> Enum (Unknown Enums)
2967
2968@interface GPBStringEnumDictionaryUnknownEnumTests : XCTestCase
2969@end
2970
2971@implementation GPBStringEnumDictionaryUnknownEnumTests
2972
2973- (void)testRawBasics {
2974  const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
2975  const int32_t kValues[] = { 700, 801, 702 };
2976  GPBStringEnumDictionary *dict =
2977      [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
2978                                                        rawValues:kValues
2979                                                          forKeys:kKeys
2980                                                            count:GPBARRAYSIZE(kValues)];
2981  XCTAssertNotNil(dict);
2982  XCTAssertEqual(dict.count, 3U);
2983  XCTAssertTrue(dict.validationFunc == TestingEnum_IsValidValue);  // Pointer comparison
2984  int32_t value;
2985  XCTAssertTrue([dict getRawValue:NULL forKey:@"foo"]);
2986  XCTAssertTrue([dict getRawValue:&value forKey:@"foo"]);
2987  XCTAssertEqual(value, 700);
2988  XCTAssertTrue([dict getEnum:NULL forKey:@"bar"]);
2989  XCTAssertTrue([dict getEnum:&value forKey:@"bar"]);
2990  XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
2991  XCTAssertTrue([dict getRawValue:NULL forKey:@"bar"]);
2992  XCTAssertTrue([dict getRawValue:&value forKey:@"bar"]);
2993  XCTAssertEqual(value, 801);
2994  XCTAssertTrue([dict getRawValue:NULL forKey:@"baz"]);
2995  XCTAssertTrue([dict getRawValue:&value forKey:@"baz"]);
2996  XCTAssertEqual(value, 702);
2997  XCTAssertFalse([dict getRawValue:NULL forKey:@"mumble"]);
2998
2999  __block NSUInteger idx = 0;
3000  NSString **seenKeys = malloc(3 * sizeof(NSString*));
3001  int32_t *seenValues = malloc(3 * sizeof(int32_t));
3002  [dict enumerateKeysAndEnumsUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
3003    XCTAssertLessThan(idx, 3U);
3004    seenKeys[idx] = aKey;
3005    seenValues[idx] = aValue;
3006    XCTAssertNotEqual(stop, NULL);
3007    ++idx;
3008  }];
3009  for (int i = 0; i < 3; ++i) {
3010    BOOL foundKey = NO;
3011    for (int j = 0; (j < 3) && !foundKey; ++j) {
3012      if ([kKeys[i] isEqual:seenKeys[j]]) {
3013        foundKey = YES;
3014        if (i == 1) {
3015          XCTAssertEqual(kGPBUnrecognizedEnumeratorValue, seenValues[j], @"i = %d, j = %d", i, j);
3016        } else {
3017          XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
3018        }
3019      }
3020    }
3021    XCTAssertTrue(foundKey, @"i = %d", i);
3022  }
3023  idx = 0;
3024  [dict enumerateKeysAndRawValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
3025    XCTAssertLessThan(idx, 3U);
3026    seenKeys[idx] = aKey;
3027    seenValues[idx] = aValue;
3028    XCTAssertNotEqual(stop, NULL);
3029    ++idx;
3030  }];
3031  for (int i = 0; i < 3; ++i) {
3032    BOOL foundKey = NO;
3033    for (int j = 0; (j < 3) && !foundKey; ++j) {
3034      if ([kKeys[i] isEqual:seenKeys[j]]) {
3035        foundKey = YES;
3036        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
3037      }
3038    }
3039    XCTAssertTrue(foundKey, @"i = %d", i);
3040  }
3041  free(seenKeys);
3042  free(seenValues);
3043
3044  // Stopping the enumeration.
3045  idx = 0;
3046  [dict enumerateKeysAndRawValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
3047    #pragma unused(aKey, aValue)
3048    if (idx == 1) *stop = YES;
3049    XCTAssertNotEqual(idx, 2U);
3050    ++idx;
3051  }];
3052  [dict release];
3053}
3054
3055- (void)testEqualityWithUnknowns {
3056  const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
3057  const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
3058  const int32_t kValues1[] = { 700, 801, 702 };  // Unknown
3059  const int32_t kValues2[] = { 700, 803, 702 };  // Unknown
3060  const int32_t kValues3[] = { 700, 801, 702, 803 };  // Unknowns
3061  GPBStringEnumDictionary *dict1 =
3062      [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
3063                                                        rawValues:kValues1
3064                                                          forKeys:kKeys1
3065                                                            count:GPBARRAYSIZE(kValues1)];
3066  XCTAssertNotNil(dict1);
3067  GPBStringEnumDictionary *dict1prime =
3068      [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
3069                                                        rawValues:kValues1
3070                                                          forKeys:kKeys1
3071                                                            count:GPBARRAYSIZE(kValues1)];
3072  XCTAssertNotNil(dict1prime);
3073  GPBStringEnumDictionary *dict2 =
3074      [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
3075                                                        rawValues:kValues2
3076                                                          forKeys:kKeys1
3077                                                            count:GPBARRAYSIZE(kValues2)];
3078  XCTAssertNotNil(dict2);
3079  GPBStringEnumDictionary *dict3 =
3080      [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
3081                                                        rawValues:kValues1
3082                                                          forKeys:kKeys2
3083                                                            count:GPBARRAYSIZE(kValues1)];
3084  XCTAssertNotNil(dict3);
3085  GPBStringEnumDictionary *dict4 =
3086      [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
3087                                                        rawValues:kValues3
3088                                                          forKeys:kKeys1
3089                                                            count:GPBARRAYSIZE(kValues3)];
3090  XCTAssertNotNil(dict4);
3091
3092  // 1/1Prime should be different objects, but equal.
3093  XCTAssertNotEqual(dict1, dict1prime);
3094  XCTAssertEqualObjects(dict1, dict1prime);
3095  // Equal, so they must have same hash.
3096  XCTAssertEqual([dict1 hash], [dict1prime hash]);
3097
3098  // 2 is same keys, different values; not equal.
3099  XCTAssertNotEqualObjects(dict1, dict2);
3100
3101  // 3 is different keys, same values; not equal.
3102  XCTAssertNotEqualObjects(dict1, dict3);
3103
3104  // 4 extra pair; not equal
3105  XCTAssertNotEqualObjects(dict1, dict4);
3106
3107  [dict1 release];
3108  [dict1prime release];
3109  [dict2 release];
3110  [dict3 release];
3111  [dict4 release];
3112}
3113
3114- (void)testCopyWithUnknowns {
3115  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
3116  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknown
3117  GPBStringEnumDictionary *dict =
3118      [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
3119                                                        rawValues:kValues
3120                                                          forKeys:kKeys
3121                                                            count:GPBARRAYSIZE(kValues)];
3122  XCTAssertNotNil(dict);
3123
3124  GPBStringEnumDictionary *dict2 = [dict copy];
3125  XCTAssertNotNil(dict2);
3126
3127  // Should be new pointer, but equal objects.
3128  XCTAssertNotEqual(dict, dict2);
3129  XCTAssertEqual(dict.validationFunc, dict2.validationFunc);  // Pointer comparison
3130  XCTAssertEqualObjects(dict, dict2);
3131
3132  [dict2 release];
3133  [dict release];
3134}
3135
3136- (void)testDictionaryFromDictionary {
3137  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
3138  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknowns
3139  GPBStringEnumDictionary *dict =
3140      [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
3141                                                        rawValues:kValues
3142                                                          forKeys:kKeys
3143                                                            count:GPBARRAYSIZE(kValues)];
3144  XCTAssertNotNil(dict);
3145
3146  GPBStringEnumDictionary *dict2 =
3147      [[GPBStringEnumDictionary alloc] initWithDictionary:dict];
3148  XCTAssertNotNil(dict2);
3149
3150  // Should be new pointer, but equal objects.
3151  XCTAssertNotEqual(dict, dict2);
3152  XCTAssertEqualObjects(dict, dict2);
3153  XCTAssertEqual(dict.validationFunc, dict2.validationFunc);  // Pointer comparison
3154  [dict2 release];
3155  [dict release];
3156}
3157
3158- (void)testUnknownAdds {
3159  GPBStringEnumDictionary *dict =
3160      [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue];
3161  XCTAssertNotNil(dict);
3162
3163  XCTAssertEqual(dict.count, 0U);
3164  XCTAssertThrowsSpecificNamed([dict setEnum:801 forKey:@"bar"],  // Unknown
3165                               NSException, NSInvalidArgumentException);
3166  XCTAssertEqual(dict.count, 0U);
3167  [dict setRawValue:801 forKey:@"bar"];  // Unknown
3168  XCTAssertEqual(dict.count, 1U);
3169
3170  const NSString *kKeys[] = { @"foo", @"baz", @"mumble" };
3171  const int32_t kValues[] = { 700, 702, 803 };  // Unknown
3172  GPBStringEnumDictionary *dict2 =
3173      [[GPBStringEnumDictionary alloc] initWithEnums:kValues
3174                                               forKeys:kKeys
3175                                                 count:GPBARRAYSIZE(kValues)];
3176  XCTAssertNotNil(dict2);
3177  [dict addRawEntriesFromDictionary:dict2];
3178  XCTAssertEqual(dict.count, 4U);
3179
3180  int32_t value;
3181  XCTAssertTrue([dict getEnum:NULL forKey:@"foo"]);
3182  XCTAssertTrue([dict getEnum:&value forKey:@"foo"]);
3183  XCTAssertEqual(value, 700);
3184  XCTAssertTrue([dict getEnum:NULL forKey:@"bar"]);
3185  XCTAssertTrue([dict getEnum:&value forKey:@"bar"]);
3186  XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
3187  XCTAssertTrue([dict getRawValue:NULL forKey:@"bar"]);
3188  XCTAssertTrue([dict getRawValue:&value forKey:@"bar"]);
3189  XCTAssertEqual(value, 801);
3190  XCTAssertTrue([dict getEnum:NULL forKey:@"baz"]);
3191  XCTAssertTrue([dict getEnum:&value forKey:@"baz"]);
3192  XCTAssertEqual(value, 702);
3193  XCTAssertTrue([dict getEnum:NULL forKey:@"mumble"]);
3194  XCTAssertTrue([dict getEnum:&value forKey:@"mumble"]);
3195  XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
3196  XCTAssertTrue([dict getRawValue:NULL forKey:@"mumble"]);
3197  XCTAssertTrue([dict getRawValue:&value forKey:@"mumble"]);
3198  XCTAssertEqual(value, 803);
3199  [dict2 release];
3200  [dict release];
3201}
3202
3203- (void)testUnknownRemove {
3204  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
3205  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknowns
3206  GPBStringEnumDictionary *dict =
3207      [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
3208                                                        rawValues:kValues
3209                                                          forKeys:kKeys
3210                                                            count:GPBARRAYSIZE(kValues)];
3211  XCTAssertNotNil(dict);
3212  XCTAssertEqual(dict.count, 4U);
3213
3214  [dict removeEnumForKey:@"bar"];
3215  XCTAssertEqual(dict.count, 3U);
3216  int32_t value;
3217  XCTAssertTrue([dict getEnum:NULL forKey:@"foo"]);
3218  XCTAssertTrue([dict getEnum:&value forKey:@"foo"]);
3219  XCTAssertEqual(value, 700);
3220  XCTAssertFalse([dict getEnum:NULL forKey:@"bar"]);
3221  XCTAssertTrue([dict getEnum:NULL forKey:@"baz"]);
3222  XCTAssertTrue([dict getEnum:&value forKey:@"baz"]);
3223  XCTAssertEqual(value, 702);
3224  XCTAssertTrue([dict getRawValue:NULL forKey:@"mumble"]);
3225  XCTAssertTrue([dict getRawValue:&value forKey:@"mumble"]);
3226  XCTAssertEqual(value, 803);
3227
3228  // Remove again does nothing.
3229  [dict removeEnumForKey:@"bar"];
3230  XCTAssertEqual(dict.count, 3U);
3231  XCTAssertTrue([dict getEnum:NULL forKey:@"foo"]);
3232  XCTAssertTrue([dict getEnum:&value forKey:@"foo"]);
3233  XCTAssertEqual(value, 700);
3234  XCTAssertFalse([dict getEnum:NULL forKey:@"bar"]);
3235  XCTAssertTrue([dict getEnum:NULL forKey:@"baz"]);
3236  XCTAssertTrue([dict getEnum:&value forKey:@"baz"]);
3237  XCTAssertEqual(value, 702);
3238  XCTAssertTrue([dict getRawValue:NULL forKey:@"mumble"]);
3239  XCTAssertTrue([dict getRawValue:&value forKey:@"mumble"]);
3240  XCTAssertEqual(value, 803);
3241
3242  [dict removeEnumForKey:@"mumble"];
3243  XCTAssertEqual(dict.count, 2U);
3244  XCTAssertTrue([dict getEnum:NULL forKey:@"foo"]);
3245  XCTAssertTrue([dict getEnum:&value forKey:@"foo"]);
3246  XCTAssertEqual(value, 700);
3247  XCTAssertFalse([dict getEnum:NULL forKey:@"bar"]);
3248  XCTAssertTrue([dict getEnum:NULL forKey:@"baz"]);
3249  XCTAssertTrue([dict getEnum:&value forKey:@"baz"]);
3250  XCTAssertEqual(value, 702);
3251  XCTAssertFalse([dict getEnum:NULL forKey:@"mumble"]);
3252
3253  [dict removeAll];
3254  XCTAssertEqual(dict.count, 0U);
3255  XCTAssertFalse([dict getEnum:NULL forKey:@"foo"]);
3256  XCTAssertFalse([dict getEnum:NULL forKey:@"bar"]);
3257  XCTAssertFalse([dict getEnum:NULL forKey:@"baz"]);
3258  XCTAssertFalse([dict getEnum:NULL forKey:@"mumble"]);
3259  [dict release];
3260}
3261
3262- (void)testInplaceMutationUnknowns {
3263  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
3264  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknowns
3265  GPBStringEnumDictionary *dict =
3266      [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
3267                                                        rawValues:kValues
3268                                                          forKeys:kKeys
3269                                                            count:GPBARRAYSIZE(kValues)];
3270  XCTAssertNotNil(dict);
3271  XCTAssertEqual(dict.count, 4U);
3272  int32_t value;
3273  XCTAssertTrue([dict getEnum:NULL forKey:@"foo"]);
3274  XCTAssertTrue([dict getEnum:&value forKey:@"foo"]);
3275  XCTAssertEqual(value, 700);
3276  XCTAssertTrue([dict getRawValue:NULL forKey:@"bar"]);
3277  XCTAssertTrue([dict getRawValue:&value forKey:@"bar"]);
3278  XCTAssertEqual(value, 801);
3279  XCTAssertTrue([dict getEnum:NULL forKey:@"baz"]);
3280  XCTAssertTrue([dict getEnum:&value forKey:@"baz"]);
3281  XCTAssertEqual(value, 702);
3282  XCTAssertTrue([dict getRawValue:NULL forKey:@"mumble"]);
3283  XCTAssertTrue([dict getRawValue:&value forKey:@"mumble"]);
3284  XCTAssertEqual(value, 803);
3285
3286  XCTAssertThrowsSpecificNamed([dict setEnum:803 forKey:@"foo"],  // Unknown
3287                               NSException, NSInvalidArgumentException);
3288  XCTAssertEqual(dict.count, 4U);
3289  XCTAssertTrue([dict getEnum:NULL forKey:@"foo"]);
3290  XCTAssertTrue([dict getEnum:&value forKey:@"foo"]);
3291  XCTAssertEqual(value, 700);
3292  XCTAssertTrue([dict getRawValue:NULL forKey:@"bar"]);
3293  XCTAssertTrue([dict getRawValue:&value forKey:@"bar"]);
3294  XCTAssertEqual(value, 801);
3295  XCTAssertTrue([dict getEnum:NULL forKey:@"baz"]);
3296  XCTAssertTrue([dict getEnum:&value forKey:@"baz"]);
3297  XCTAssertEqual(value, 702);
3298  XCTAssertTrue([dict getRawValue:NULL forKey:@"mumble"]);
3299  XCTAssertTrue([dict getRawValue:&value forKey:@"mumble"]);
3300  XCTAssertEqual(value, 803);
3301
3302  [dict setRawValue:803 forKey:@"foo"];  // Unknown
3303  XCTAssertEqual(dict.count, 4U);
3304  XCTAssertTrue([dict getRawValue:NULL forKey:@"foo"]);
3305  XCTAssertTrue([dict getRawValue:&value forKey:@"foo"]);
3306  XCTAssertEqual(value, 803);
3307  XCTAssertTrue([dict getRawValue:NULL forKey:@"bar"]);
3308  XCTAssertTrue([dict getRawValue:&value forKey:@"bar"]);
3309  XCTAssertEqual(value, 801);
3310  XCTAssertTrue([dict getEnum:NULL forKey:@"baz"]);
3311  XCTAssertTrue([dict getEnum:&value forKey:@"baz"]);
3312  XCTAssertEqual(value, 702);
3313  XCTAssertTrue([dict getRawValue:NULL forKey:@"mumble"]);
3314  XCTAssertTrue([dict getRawValue:&value forKey:@"mumble"]);
3315  XCTAssertEqual(value, 803);
3316
3317  [dict setRawValue:700 forKey:@"mumble"];
3318  XCTAssertEqual(dict.count, 4U);
3319  XCTAssertTrue([dict getRawValue:NULL forKey:@"foo"]);
3320  XCTAssertTrue([dict getRawValue:&value forKey:@"foo"]);
3321  XCTAssertEqual(value, 803);
3322  XCTAssertTrue([dict getRawValue:NULL forKey:@"bar"]);
3323  XCTAssertTrue([dict getRawValue:&value forKey:@"bar"]);
3324  XCTAssertEqual(value, 801);
3325  XCTAssertTrue([dict getEnum:NULL forKey:@"baz"]);
3326  XCTAssertTrue([dict getEnum:&value forKey:@"baz"]);
3327  XCTAssertEqual(value, 702);
3328  XCTAssertTrue([dict getEnum:NULL forKey:@"mumble"]);
3329  XCTAssertTrue([dict getEnum:&value forKey:@"mumble"]);
3330  XCTAssertEqual(value, 700);
3331
3332  const NSString *kKeys2[] = { @"bar", @"baz" };
3333  const int32_t kValues2[] = { 702, 801 };  // Unknown
3334  GPBStringEnumDictionary *dict2 =
3335      [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
3336                                                        rawValues:kValues2
3337                                                          forKeys:kKeys2
3338                                                            count:GPBARRAYSIZE(kValues2)];
3339  XCTAssertNotNil(dict2);
3340  [dict addRawEntriesFromDictionary:dict2];
3341  XCTAssertEqual(dict.count, 4U);
3342  XCTAssertTrue([dict getRawValue:NULL forKey:@"foo"]);
3343  XCTAssertTrue([dict getRawValue:&value forKey:@"foo"]);
3344  XCTAssertEqual(value, 803);
3345  XCTAssertTrue([dict getEnum:NULL forKey:@"bar"]);
3346  XCTAssertTrue([dict getEnum:&value forKey:@"bar"]);
3347  XCTAssertEqual(value, 702);
3348  XCTAssertTrue([dict getRawValue:NULL forKey:@"baz"]);
3349  XCTAssertTrue([dict getRawValue:&value forKey:@"baz"]);
3350  XCTAssertEqual(value, 801);
3351  XCTAssertTrue([dict getEnum:NULL forKey:@"mumble"]);
3352  XCTAssertTrue([dict getEnum:&value forKey:@"mumble"]);
3353  XCTAssertEqual(value, 700);
3354
3355  [dict2 release];
3356  [dict release];
3357}
3358
3359- (void)testCopyUnknowns {
3360  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
3361  const int32_t kValues[] = { 700, 801, 702, 803 };
3362  GPBStringEnumDictionary *dict =
3363      [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
3364                                                        rawValues:kValues
3365                                                          forKeys:kKeys
3366                                                            count:GPBARRAYSIZE(kValues)];
3367  XCTAssertNotNil(dict);
3368
3369  GPBStringEnumDictionary *dict2 = [dict copy];
3370  XCTAssertNotNil(dict2);
3371
3372  // Should be new pointer, but equal objects.
3373  XCTAssertNotEqual(dict, dict2);
3374  XCTAssertEqualObjects(dict, dict2);
3375  XCTAssertEqual(dict.validationFunc, dict2.validationFunc);  // Pointer comparison
3376  XCTAssertTrue([dict2 isKindOfClass:[GPBStringEnumDictionary class]]);
3377
3378  [dict2 release];
3379  [dict release];
3380}
3381
3382@end
3383
3384// clang-format on
3385//%PDDM-EXPAND-END TESTS_FOR_POD_VALUES(String, NSString, *, Objects, @"foo", @"bar", @"baz", @"mumble")
3386
3387