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