GPBDictionaryTests+UInt32.m 133 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
// Protocol Buffers - Google's data interchange format
// Copyright 2015 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#import <Foundation/Foundation.h>
#import <XCTest/XCTest.h>

#import "GPBDictionary.h"

36
#import "GPBTestUtilities.h"
37 38 39 40 41 42 43 44 45 46 47
#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"

// Pull in the macros (using an external file because expanding all tests
// in a single file makes a file that is failing to work with within Xcode.
//%PDDM-IMPORT-DEFINES GPBDictionaryTests.pddm

//%PDDM-EXPAND TEST_FOR_POD_KEY(UInt32, uint32_t, 1U, 2U, 3U, 4U)
// This block of code is generated, do not edit it directly.

// To let the testing macros work, add some extra methods to simplify things.
@interface GPBUInt32EnumDictionary (TestingTweak)
48 49 50 51
+ (instancetype)dictionaryWithEnum:(int32_t)value forKey:(uint32_t)key;
- (instancetype)initWithEnums:(const int32_t [])values
                      forKeys:(const uint32_t [])keys
                        count:(NSUInteger)count;
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
@end

static BOOL TestingEnum_IsValidValue(int32_t value) {
  switch (value) {
    case 700:
    case 701:
    case 702:
    case 703:
      return YES;
    default:
      return NO;
  }
}

@implementation GPBUInt32EnumDictionary (TestingTweak)
67
+ (instancetype)dictionaryWithEnum:(int32_t)value forKey:(uint32_t)key {
68 69 70 71 72 73 74
  // Cast is needed to compiler knows what class we are invoking initWithValues: on to get the
  // type correct.
  return [[(GPBUInt32EnumDictionary*)[self alloc] initWithValidationFunction:TestingEnum_IsValidValue
                                                                   rawValues:&value
                                                                     forKeys:&key
                                                                       count:1] autorelease];
}
75 76 77
- (instancetype)initWithEnums:(const int32_t [])values
                      forKeys:(const uint32_t [])keys
                        count:(NSUInteger)count {
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
  return [self initWithValidationFunction:TestingEnum_IsValidValue
                                rawValues:values
                                  forKeys:keys
                                    count:count];
}
@end


#pragma mark - UInt32 -> UInt32

@interface GPBUInt32UInt32DictionaryTests : XCTestCase
@end

@implementation GPBUInt32UInt32DictionaryTests

- (void)testEmpty {
  GPBUInt32UInt32Dictionary *dict = [[GPBUInt32UInt32Dictionary alloc] init];
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 0U);
97 98
  XCTAssertFalse([dict getUInt32:NULL forKey:1U]);
  [dict enumerateKeysAndUInt32sUsingBlock:^(uint32_t aKey, uint32_t aValue, BOOL *stop) {
99 100 101 102 103 104 105
    #pragma unused(aKey, aValue, stop)
    XCTFail(@"Shouldn't get here!");
  }];
  [dict release];
}

- (void)testOne {
106
  GPBUInt32UInt32Dictionary *dict = [GPBUInt32UInt32Dictionary dictionaryWithUInt32:100U forKey:1U];
107 108 109
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 1U);
  uint32_t value;
110 111
  XCTAssertTrue([dict getUInt32:NULL forKey:1U]);
  XCTAssertTrue([dict getUInt32:&value forKey:1U]);
112
  XCTAssertEqual(value, 100U);
113 114
  XCTAssertFalse([dict getUInt32:NULL forKey:2U]);
  [dict enumerateKeysAndUInt32sUsingBlock:^(uint32_t aKey, uint32_t aValue, BOOL *stop) {
115 116 117 118 119 120 121 122 123 124
    XCTAssertEqual(aKey, 1U);
    XCTAssertEqual(aValue, 100U);
    XCTAssertNotEqual(stop, NULL);
  }];
}

- (void)testBasics {
  const uint32_t kKeys[] = { 1U, 2U, 3U };
  const uint32_t kValues[] = { 100U, 101U, 102U };
  GPBUInt32UInt32Dictionary *dict =
125 126 127
      [[GPBUInt32UInt32Dictionary alloc] initWithUInt32s:kValues
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kValues)];
128 129 130
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 3U);
  uint32_t value;
131 132
  XCTAssertTrue([dict getUInt32:NULL forKey:1U]);
  XCTAssertTrue([dict getUInt32:&value forKey:1U]);
133
  XCTAssertEqual(value, 100U);
134 135
  XCTAssertTrue([dict getUInt32:NULL forKey:2U]);
  XCTAssertTrue([dict getUInt32:&value forKey:2U]);
136
  XCTAssertEqual(value, 101U);
137 138
  XCTAssertTrue([dict getUInt32:NULL forKey:3U]);
  XCTAssertTrue([dict getUInt32:&value forKey:3U]);
139
  XCTAssertEqual(value, 102U);
140
  XCTAssertFalse([dict getUInt32:NULL forKey:4U]);
141 142 143 144

  __block NSUInteger idx = 0;
  uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
  uint32_t *seenValues = malloc(3 * sizeof(uint32_t));
145
  [dict enumerateKeysAndUInt32sUsingBlock:^(uint32_t aKey, uint32_t aValue, BOOL *stop) {
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
    XCTAssertLessThan(idx, 3U);
    seenKeys[idx] = aKey;
    seenValues[idx] = aValue;
    XCTAssertNotEqual(stop, NULL);
    ++idx;
  }];
  for (int i = 0; i < 3; ++i) {
    BOOL foundKey = NO;
    for (int j = 0; (j < 3) && !foundKey; ++j) {
      if (kKeys[i] == seenKeys[j]) {
        foundKey = YES;
        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
      }
    }
    XCTAssertTrue(foundKey, @"i = %d", i);
  }
  free(seenKeys);
  free(seenValues);

  // Stopping the enumeration.
  idx = 0;
167
  [dict enumerateKeysAndUInt32sUsingBlock:^(uint32_t aKey, uint32_t aValue, BOOL *stop) {
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
    #pragma unused(aKey, aValue)
    if (idx == 1) *stop = YES;
    XCTAssertNotEqual(idx, 2U);
    ++idx;
  }];
  [dict release];
}

- (void)testEquality {
  const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
  const uint32_t kKeys2[] = { 2U, 1U, 4U };
  const uint32_t kValues1[] = { 100U, 101U, 102U };
  const uint32_t kValues2[] = { 100U, 103U, 102U };
  const uint32_t kValues3[] = { 100U, 101U, 102U, 103U };
  GPBUInt32UInt32Dictionary *dict1 =
183 184 185
      [[GPBUInt32UInt32Dictionary alloc] initWithUInt32s:kValues1
                                                 forKeys:kKeys1
                                                   count:GPBARRAYSIZE(kValues1)];
186 187
  XCTAssertNotNil(dict1);
  GPBUInt32UInt32Dictionary *dict1prime =
188 189 190
      [[GPBUInt32UInt32Dictionary alloc] initWithUInt32s:kValues1
                                                 forKeys:kKeys1
                                                   count:GPBARRAYSIZE(kValues1)];
191 192
  XCTAssertNotNil(dict1prime);
  GPBUInt32UInt32Dictionary *dict2 =
193 194 195
      [[GPBUInt32UInt32Dictionary alloc] initWithUInt32s:kValues2
                                                 forKeys:kKeys1
                                                   count:GPBARRAYSIZE(kValues2)];
196 197
  XCTAssertNotNil(dict2);
  GPBUInt32UInt32Dictionary *dict3 =
198 199 200
      [[GPBUInt32UInt32Dictionary alloc] initWithUInt32s:kValues1
                                                 forKeys:kKeys2
                                                   count:GPBARRAYSIZE(kValues1)];
201 202
  XCTAssertNotNil(dict3);
  GPBUInt32UInt32Dictionary *dict4 =
203 204 205
      [[GPBUInt32UInt32Dictionary alloc] initWithUInt32s:kValues3
                                                 forKeys:kKeys1
                                                   count:GPBARRAYSIZE(kValues3)];
206 207 208 209 210 211 212 213
  XCTAssertNotNil(dict4);

  // 1/1Prime should be different objects, but equal.
  XCTAssertNotEqual(dict1, dict1prime);
  XCTAssertEqualObjects(dict1, dict1prime);
  // Equal, so they must have same hash.
  XCTAssertEqual([dict1 hash], [dict1prime hash]);

214
  // 2 is same keys, different values; not equal.
215 216
  XCTAssertNotEqualObjects(dict1, dict2);

217
  // 3 is different keys, same values; not equal.
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
  XCTAssertNotEqualObjects(dict1, dict3);

  // 4 extra pair; not equal
  XCTAssertNotEqualObjects(dict1, dict4);

  [dict1 release];
  [dict1prime release];
  [dict2 release];
  [dict3 release];
  [dict4 release];
}

- (void)testCopy {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
  GPBUInt32UInt32Dictionary *dict =
234 235 236
      [[GPBUInt32UInt32Dictionary alloc] initWithUInt32s:kValues
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kValues)];
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
  XCTAssertNotNil(dict);

  GPBUInt32UInt32Dictionary *dict2 = [dict copy];
  XCTAssertNotNil(dict2);

  // Should be new object but equal.
  XCTAssertNotEqual(dict, dict2);
  XCTAssertEqualObjects(dict, dict2);
  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32UInt32Dictionary class]]);

  [dict2 release];
  [dict release];
}

- (void)testDictionaryFromDictionary {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
  GPBUInt32UInt32Dictionary *dict =
255 256 257
      [[GPBUInt32UInt32Dictionary alloc] initWithUInt32s:kValues
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kValues)];
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
  XCTAssertNotNil(dict);

  GPBUInt32UInt32Dictionary *dict2 =
      [GPBUInt32UInt32Dictionary dictionaryWithDictionary:dict];
  XCTAssertNotNil(dict2);

  // Should be new pointer, but equal objects.
  XCTAssertNotEqual(dict, dict2);
  XCTAssertEqualObjects(dict, dict2);
  [dict release];
}

- (void)testAdds {
  GPBUInt32UInt32Dictionary *dict = [GPBUInt32UInt32Dictionary dictionary];
  XCTAssertNotNil(dict);

  XCTAssertEqual(dict.count, 0U);
275
  [dict setUInt32:100U forKey:1U];
276 277 278 279 280
  XCTAssertEqual(dict.count, 1U);

  const uint32_t kKeys[] = { 2U, 3U, 4U };
  const uint32_t kValues[] = { 101U, 102U, 103U };
  GPBUInt32UInt32Dictionary *dict2 =
281 282 283
      [[GPBUInt32UInt32Dictionary alloc] initWithUInt32s:kValues
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kValues)];
284 285 286 287 288
  XCTAssertNotNil(dict2);
  [dict addEntriesFromDictionary:dict2];
  XCTAssertEqual(dict.count, 4U);

  uint32_t value;
289 290
  XCTAssertTrue([dict getUInt32:NULL forKey:1U]);
  XCTAssertTrue([dict getUInt32:&value forKey:1U]);
291
  XCTAssertEqual(value, 100U);
292 293
  XCTAssertTrue([dict getUInt32:NULL forKey:2U]);
  XCTAssertTrue([dict getUInt32:&value forKey:2U]);
294
  XCTAssertEqual(value, 101U);
295 296
  XCTAssertTrue([dict getUInt32:NULL forKey:3U]);
  XCTAssertTrue([dict getUInt32:&value forKey:3U]);
297
  XCTAssertEqual(value, 102U);
298 299
  XCTAssertTrue([dict getUInt32:NULL forKey:4U]);
  XCTAssertTrue([dict getUInt32:&value forKey:4U]);
300 301 302 303 304 305 306 307
  XCTAssertEqual(value, 103U);
  [dict2 release];
}

- (void)testRemove {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
  GPBUInt32UInt32Dictionary *dict =
308 309 310
      [[GPBUInt32UInt32Dictionary alloc] initWithUInt32s:kValues
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kValues)];
311 312 313
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 4U);

314
  [dict removeUInt32ForKey:2U];
315 316
  XCTAssertEqual(dict.count, 3U);
  uint32_t value;
317 318
  XCTAssertTrue([dict getUInt32:NULL forKey:1U]);
  XCTAssertTrue([dict getUInt32:&value forKey:1U]);
319
  XCTAssertEqual(value, 100U);
320 321 322
  XCTAssertFalse([dict getUInt32:NULL forKey:2U]);
  XCTAssertTrue([dict getUInt32:NULL forKey:3U]);
  XCTAssertTrue([dict getUInt32:&value forKey:3U]);
323
  XCTAssertEqual(value, 102U);
324 325
  XCTAssertTrue([dict getUInt32:NULL forKey:4U]);
  XCTAssertTrue([dict getUInt32:&value forKey:4U]);
326 327 328
  XCTAssertEqual(value, 103U);

  // Remove again does nothing.
329
  [dict removeUInt32ForKey:2U];
330
  XCTAssertEqual(dict.count, 3U);
331 332
  XCTAssertTrue([dict getUInt32:NULL forKey:1U]);
  XCTAssertTrue([dict getUInt32:&value forKey:1U]);
333
  XCTAssertEqual(value, 100U);
334 335 336
  XCTAssertFalse([dict getUInt32:NULL forKey:2U]);
  XCTAssertTrue([dict getUInt32:NULL forKey:3U]);
  XCTAssertTrue([dict getUInt32:&value forKey:3U]);
337
  XCTAssertEqual(value, 102U);
338 339
  XCTAssertTrue([dict getUInt32:NULL forKey:4U]);
  XCTAssertTrue([dict getUInt32:&value forKey:4U]);
340 341
  XCTAssertEqual(value, 103U);

342
  [dict removeUInt32ForKey:4U];
343
  XCTAssertEqual(dict.count, 2U);
344 345
  XCTAssertTrue([dict getUInt32:NULL forKey:1U]);
  XCTAssertTrue([dict getUInt32:&value forKey:1U]);
346
  XCTAssertEqual(value, 100U);
347 348 349
  XCTAssertFalse([dict getUInt32:NULL forKey:2U]);
  XCTAssertTrue([dict getUInt32:NULL forKey:3U]);
  XCTAssertTrue([dict getUInt32:&value forKey:3U]);
350
  XCTAssertEqual(value, 102U);
351
  XCTAssertFalse([dict getUInt32:NULL forKey:4U]);
352 353 354

  [dict removeAll];
  XCTAssertEqual(dict.count, 0U);
355 356 357 358
  XCTAssertFalse([dict getUInt32:NULL forKey:1U]);
  XCTAssertFalse([dict getUInt32:NULL forKey:2U]);
  XCTAssertFalse([dict getUInt32:NULL forKey:3U]);
  XCTAssertFalse([dict getUInt32:NULL forKey:4U]);
359 360 361 362 363 364 365
  [dict release];
}

- (void)testInplaceMutation {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
  GPBUInt32UInt32Dictionary *dict =
366 367 368
      [[GPBUInt32UInt32Dictionary alloc] initWithUInt32s:kValues
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kValues)];
369 370 371
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 4U);
  uint32_t value;
372 373
  XCTAssertTrue([dict getUInt32:NULL forKey:1U]);
  XCTAssertTrue([dict getUInt32:&value forKey:1U]);
374
  XCTAssertEqual(value, 100U);
375 376
  XCTAssertTrue([dict getUInt32:NULL forKey:2U]);
  XCTAssertTrue([dict getUInt32:&value forKey:2U]);
377
  XCTAssertEqual(value, 101U);
378 379
  XCTAssertTrue([dict getUInt32:NULL forKey:3U]);
  XCTAssertTrue([dict getUInt32:&value forKey:3U]);
380
  XCTAssertEqual(value, 102U);
381 382
  XCTAssertTrue([dict getUInt32:NULL forKey:4U]);
  XCTAssertTrue([dict getUInt32:&value forKey:4U]);
383 384
  XCTAssertEqual(value, 103U);

385
  [dict setUInt32:103U forKey:1U];
386
  XCTAssertEqual(dict.count, 4U);
387 388
  XCTAssertTrue([dict getUInt32:NULL forKey:1U]);
  XCTAssertTrue([dict getUInt32:&value forKey:1U]);
389
  XCTAssertEqual(value, 103U);
390 391
  XCTAssertTrue([dict getUInt32:NULL forKey:2U]);
  XCTAssertTrue([dict getUInt32:&value forKey:2U]);
392
  XCTAssertEqual(value, 101U);
393 394
  XCTAssertTrue([dict getUInt32:NULL forKey:3U]);
  XCTAssertTrue([dict getUInt32:&value forKey:3U]);
395
  XCTAssertEqual(value, 102U);
396 397
  XCTAssertTrue([dict getUInt32:NULL forKey:4U]);
  XCTAssertTrue([dict getUInt32:&value forKey:4U]);
398 399
  XCTAssertEqual(value, 103U);

400
  [dict setUInt32:101U forKey:4U];
401
  XCTAssertEqual(dict.count, 4U);
402 403
  XCTAssertTrue([dict getUInt32:NULL forKey:1U]);
  XCTAssertTrue([dict getUInt32:&value forKey:1U]);
404
  XCTAssertEqual(value, 103U);
405 406
  XCTAssertTrue([dict getUInt32:NULL forKey:2U]);
  XCTAssertTrue([dict getUInt32:&value forKey:2U]);
407
  XCTAssertEqual(value, 101U);
408 409
  XCTAssertTrue([dict getUInt32:NULL forKey:3U]);
  XCTAssertTrue([dict getUInt32:&value forKey:3U]);
410
  XCTAssertEqual(value, 102U);
411 412
  XCTAssertTrue([dict getUInt32:NULL forKey:4U]);
  XCTAssertTrue([dict getUInt32:&value forKey:4U]);
413 414 415 416 417
  XCTAssertEqual(value, 101U);

  const uint32_t kKeys2[] = { 2U, 3U };
  const uint32_t kValues2[] = { 102U, 100U };
  GPBUInt32UInt32Dictionary *dict2 =
418 419 420
      [[GPBUInt32UInt32Dictionary alloc] initWithUInt32s:kValues2
                                                 forKeys:kKeys2
                                                   count:GPBARRAYSIZE(kValues2)];
421 422 423
  XCTAssertNotNil(dict2);
  [dict addEntriesFromDictionary:dict2];
  XCTAssertEqual(dict.count, 4U);
424 425
  XCTAssertTrue([dict getUInt32:NULL forKey:1U]);
  XCTAssertTrue([dict getUInt32:&value forKey:1U]);
426
  XCTAssertEqual(value, 103U);
427 428
  XCTAssertTrue([dict getUInt32:NULL forKey:2U]);
  XCTAssertTrue([dict getUInt32:&value forKey:2U]);
429
  XCTAssertEqual(value, 102U);
430 431
  XCTAssertTrue([dict getUInt32:NULL forKey:3U]);
  XCTAssertTrue([dict getUInt32:&value forKey:3U]);
432
  XCTAssertEqual(value, 100U);
433 434
  XCTAssertTrue([dict getUInt32:NULL forKey:4U]);
  XCTAssertTrue([dict getUInt32:&value forKey:4U]);
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453
  XCTAssertEqual(value, 101U);

  [dict2 release];
  [dict release];
}

@end

#pragma mark - UInt32 -> Int32

@interface GPBUInt32Int32DictionaryTests : XCTestCase
@end

@implementation GPBUInt32Int32DictionaryTests

- (void)testEmpty {
  GPBUInt32Int32Dictionary *dict = [[GPBUInt32Int32Dictionary alloc] init];
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 0U);
454 455
  XCTAssertFalse([dict getInt32:NULL forKey:1U]);
  [dict enumerateKeysAndInt32sUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
456 457 458 459 460 461 462
    #pragma unused(aKey, aValue, stop)
    XCTFail(@"Shouldn't get here!");
  }];
  [dict release];
}

- (void)testOne {
463
  GPBUInt32Int32Dictionary *dict = [GPBUInt32Int32Dictionary dictionaryWithInt32:200 forKey:1U];
464 465 466
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 1U);
  int32_t value;
467 468
  XCTAssertTrue([dict getInt32:NULL forKey:1U]);
  XCTAssertTrue([dict getInt32:&value forKey:1U]);
469
  XCTAssertEqual(value, 200);
470 471
  XCTAssertFalse([dict getInt32:NULL forKey:2U]);
  [dict enumerateKeysAndInt32sUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
472 473 474 475 476 477 478 479 480 481
    XCTAssertEqual(aKey, 1U);
    XCTAssertEqual(aValue, 200);
    XCTAssertNotEqual(stop, NULL);
  }];
}

- (void)testBasics {
  const uint32_t kKeys[] = { 1U, 2U, 3U };
  const int32_t kValues[] = { 200, 201, 202 };
  GPBUInt32Int32Dictionary *dict =
482
      [[GPBUInt32Int32Dictionary alloc] initWithInt32s:kValues
483 484 485 486 487
                                               forKeys:kKeys
                                                 count:GPBARRAYSIZE(kValues)];
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 3U);
  int32_t value;
488 489
  XCTAssertTrue([dict getInt32:NULL forKey:1U]);
  XCTAssertTrue([dict getInt32:&value forKey:1U]);
490
  XCTAssertEqual(value, 200);
491 492
  XCTAssertTrue([dict getInt32:NULL forKey:2U]);
  XCTAssertTrue([dict getInt32:&value forKey:2U]);
493
  XCTAssertEqual(value, 201);
494 495
  XCTAssertTrue([dict getInt32:NULL forKey:3U]);
  XCTAssertTrue([dict getInt32:&value forKey:3U]);
496
  XCTAssertEqual(value, 202);
497
  XCTAssertFalse([dict getInt32:NULL forKey:4U]);
498 499 500 501

  __block NSUInteger idx = 0;
  uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
  int32_t *seenValues = malloc(3 * sizeof(int32_t));
502
  [dict enumerateKeysAndInt32sUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523
    XCTAssertLessThan(idx, 3U);
    seenKeys[idx] = aKey;
    seenValues[idx] = aValue;
    XCTAssertNotEqual(stop, NULL);
    ++idx;
  }];
  for (int i = 0; i < 3; ++i) {
    BOOL foundKey = NO;
    for (int j = 0; (j < 3) && !foundKey; ++j) {
      if (kKeys[i] == seenKeys[j]) {
        foundKey = YES;
        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
      }
    }
    XCTAssertTrue(foundKey, @"i = %d", i);
  }
  free(seenKeys);
  free(seenValues);

  // Stopping the enumeration.
  idx = 0;
524
  [dict enumerateKeysAndInt32sUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
525 526 527 528 529 530 531 532 533 534 535 536 537 538 539
    #pragma unused(aKey, aValue)
    if (idx == 1) *stop = YES;
    XCTAssertNotEqual(idx, 2U);
    ++idx;
  }];
  [dict release];
}

- (void)testEquality {
  const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
  const uint32_t kKeys2[] = { 2U, 1U, 4U };
  const int32_t kValues1[] = { 200, 201, 202 };
  const int32_t kValues2[] = { 200, 203, 202 };
  const int32_t kValues3[] = { 200, 201, 202, 203 };
  GPBUInt32Int32Dictionary *dict1 =
540
      [[GPBUInt32Int32Dictionary alloc] initWithInt32s:kValues1
541 542 543 544
                                               forKeys:kKeys1
                                                 count:GPBARRAYSIZE(kValues1)];
  XCTAssertNotNil(dict1);
  GPBUInt32Int32Dictionary *dict1prime =
545
      [[GPBUInt32Int32Dictionary alloc] initWithInt32s:kValues1
546 547 548 549
                                               forKeys:kKeys1
                                                 count:GPBARRAYSIZE(kValues1)];
  XCTAssertNotNil(dict1prime);
  GPBUInt32Int32Dictionary *dict2 =
550
      [[GPBUInt32Int32Dictionary alloc] initWithInt32s:kValues2
551 552 553 554
                                               forKeys:kKeys1
                                                 count:GPBARRAYSIZE(kValues2)];
  XCTAssertNotNil(dict2);
  GPBUInt32Int32Dictionary *dict3 =
555
      [[GPBUInt32Int32Dictionary alloc] initWithInt32s:kValues1
556 557 558 559
                                               forKeys:kKeys2
                                                 count:GPBARRAYSIZE(kValues1)];
  XCTAssertNotNil(dict3);
  GPBUInt32Int32Dictionary *dict4 =
560
      [[GPBUInt32Int32Dictionary alloc] initWithInt32s:kValues3
561 562 563 564 565 566 567 568 569 570
                                               forKeys:kKeys1
                                                 count:GPBARRAYSIZE(kValues3)];
  XCTAssertNotNil(dict4);

  // 1/1Prime should be different objects, but equal.
  XCTAssertNotEqual(dict1, dict1prime);
  XCTAssertEqualObjects(dict1, dict1prime);
  // Equal, so they must have same hash.
  XCTAssertEqual([dict1 hash], [dict1prime hash]);

571
  // 2 is same keys, different values; not equal.
572 573
  XCTAssertNotEqualObjects(dict1, dict2);

574
  // 3 is different keys, same values; not equal.
575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590
  XCTAssertNotEqualObjects(dict1, dict3);

  // 4 extra pair; not equal
  XCTAssertNotEqualObjects(dict1, dict4);

  [dict1 release];
  [dict1prime release];
  [dict2 release];
  [dict3 release];
  [dict4 release];
}

- (void)testCopy {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const int32_t kValues[] = { 200, 201, 202, 203 };
  GPBUInt32Int32Dictionary *dict =
591
      [[GPBUInt32Int32Dictionary alloc] initWithInt32s:kValues
592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611
                                               forKeys:kKeys
                                                 count:GPBARRAYSIZE(kValues)];
  XCTAssertNotNil(dict);

  GPBUInt32Int32Dictionary *dict2 = [dict copy];
  XCTAssertNotNil(dict2);

  // Should be new object but equal.
  XCTAssertNotEqual(dict, dict2);
  XCTAssertEqualObjects(dict, dict2);
  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32Int32Dictionary class]]);

  [dict2 release];
  [dict release];
}

- (void)testDictionaryFromDictionary {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const int32_t kValues[] = { 200, 201, 202, 203 };
  GPBUInt32Int32Dictionary *dict =
612
      [[GPBUInt32Int32Dictionary alloc] initWithInt32s:kValues
613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631
                                               forKeys:kKeys
                                                 count:GPBARRAYSIZE(kValues)];
  XCTAssertNotNil(dict);

  GPBUInt32Int32Dictionary *dict2 =
      [GPBUInt32Int32Dictionary dictionaryWithDictionary:dict];
  XCTAssertNotNil(dict2);

  // Should be new pointer, but equal objects.
  XCTAssertNotEqual(dict, dict2);
  XCTAssertEqualObjects(dict, dict2);
  [dict release];
}

- (void)testAdds {
  GPBUInt32Int32Dictionary *dict = [GPBUInt32Int32Dictionary dictionary];
  XCTAssertNotNil(dict);

  XCTAssertEqual(dict.count, 0U);
632
  [dict setInt32:200 forKey:1U];
633 634 635 636 637
  XCTAssertEqual(dict.count, 1U);

  const uint32_t kKeys[] = { 2U, 3U, 4U };
  const int32_t kValues[] = { 201, 202, 203 };
  GPBUInt32Int32Dictionary *dict2 =
638
      [[GPBUInt32Int32Dictionary alloc] initWithInt32s:kValues
639 640 641 642 643 644 645
                                               forKeys:kKeys
                                                 count:GPBARRAYSIZE(kValues)];
  XCTAssertNotNil(dict2);
  [dict addEntriesFromDictionary:dict2];
  XCTAssertEqual(dict.count, 4U);

  int32_t value;
646 647
  XCTAssertTrue([dict getInt32:NULL forKey:1U]);
  XCTAssertTrue([dict getInt32:&value forKey:1U]);
648
  XCTAssertEqual(value, 200);
649 650
  XCTAssertTrue([dict getInt32:NULL forKey:2U]);
  XCTAssertTrue([dict getInt32:&value forKey:2U]);
651
  XCTAssertEqual(value, 201);
652 653
  XCTAssertTrue([dict getInt32:NULL forKey:3U]);
  XCTAssertTrue([dict getInt32:&value forKey:3U]);
654
  XCTAssertEqual(value, 202);
655 656
  XCTAssertTrue([dict getInt32:NULL forKey:4U]);
  XCTAssertTrue([dict getInt32:&value forKey:4U]);
657 658 659 660 661 662 663 664
  XCTAssertEqual(value, 203);
  [dict2 release];
}

- (void)testRemove {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const int32_t kValues[] = { 200, 201, 202, 203 };
  GPBUInt32Int32Dictionary *dict =
665 666 667
      [[GPBUInt32Int32Dictionary alloc] initWithInt32s:kValues
                                               forKeys:kKeys
                                                 count:GPBARRAYSIZE(kValues)];
668 669 670
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 4U);

671
  [dict removeInt32ForKey:2U];
672 673
  XCTAssertEqual(dict.count, 3U);
  int32_t value;
674 675
  XCTAssertTrue([dict getInt32:NULL forKey:1U]);
  XCTAssertTrue([dict getInt32:&value forKey:1U]);
676
  XCTAssertEqual(value, 200);
677 678 679
  XCTAssertFalse([dict getInt32:NULL forKey:2U]);
  XCTAssertTrue([dict getInt32:NULL forKey:3U]);
  XCTAssertTrue([dict getInt32:&value forKey:3U]);
680
  XCTAssertEqual(value, 202);
681 682
  XCTAssertTrue([dict getInt32:NULL forKey:4U]);
  XCTAssertTrue([dict getInt32:&value forKey:4U]);
683 684 685
  XCTAssertEqual(value, 203);

  // Remove again does nothing.
686
  [dict removeInt32ForKey:2U];
687
  XCTAssertEqual(dict.count, 3U);
688 689
  XCTAssertTrue([dict getInt32:NULL forKey:1U]);
  XCTAssertTrue([dict getInt32:&value forKey:1U]);
690
  XCTAssertEqual(value, 200);
691 692 693
  XCTAssertFalse([dict getInt32:NULL forKey:2U]);
  XCTAssertTrue([dict getInt32:NULL forKey:3U]);
  XCTAssertTrue([dict getInt32:&value forKey:3U]);
694
  XCTAssertEqual(value, 202);
695 696
  XCTAssertTrue([dict getInt32:NULL forKey:4U]);
  XCTAssertTrue([dict getInt32:&value forKey:4U]);
697 698
  XCTAssertEqual(value, 203);

699
  [dict removeInt32ForKey:4U];
700
  XCTAssertEqual(dict.count, 2U);
701 702
  XCTAssertTrue([dict getInt32:NULL forKey:1U]);
  XCTAssertTrue([dict getInt32:&value forKey:1U]);
703
  XCTAssertEqual(value, 200);
704 705 706
  XCTAssertFalse([dict getInt32:NULL forKey:2U]);
  XCTAssertTrue([dict getInt32:NULL forKey:3U]);
  XCTAssertTrue([dict getInt32:&value forKey:3U]);
707
  XCTAssertEqual(value, 202);
708
  XCTAssertFalse([dict getInt32:NULL forKey:4U]);
709 710 711

  [dict removeAll];
  XCTAssertEqual(dict.count, 0U);
712 713 714 715
  XCTAssertFalse([dict getInt32:NULL forKey:1U]);
  XCTAssertFalse([dict getInt32:NULL forKey:2U]);
  XCTAssertFalse([dict getInt32:NULL forKey:3U]);
  XCTAssertFalse([dict getInt32:NULL forKey:4U]);
716 717 718 719 720 721 722
  [dict release];
}

- (void)testInplaceMutation {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const int32_t kValues[] = { 200, 201, 202, 203 };
  GPBUInt32Int32Dictionary *dict =
723 724 725
      [[GPBUInt32Int32Dictionary alloc] initWithInt32s:kValues
                                               forKeys:kKeys
                                                 count:GPBARRAYSIZE(kValues)];
726 727 728
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 4U);
  int32_t value;
729 730
  XCTAssertTrue([dict getInt32:NULL forKey:1U]);
  XCTAssertTrue([dict getInt32:&value forKey:1U]);
731
  XCTAssertEqual(value, 200);
732 733
  XCTAssertTrue([dict getInt32:NULL forKey:2U]);
  XCTAssertTrue([dict getInt32:&value forKey:2U]);
734
  XCTAssertEqual(value, 201);
735 736
  XCTAssertTrue([dict getInt32:NULL forKey:3U]);
  XCTAssertTrue([dict getInt32:&value forKey:3U]);
737
  XCTAssertEqual(value, 202);
738 739
  XCTAssertTrue([dict getInt32:NULL forKey:4U]);
  XCTAssertTrue([dict getInt32:&value forKey:4U]);
740 741
  XCTAssertEqual(value, 203);

742
  [dict setInt32:203 forKey:1U];
743
  XCTAssertEqual(dict.count, 4U);
744 745
  XCTAssertTrue([dict getInt32:NULL forKey:1U]);
  XCTAssertTrue([dict getInt32:&value forKey:1U]);
746
  XCTAssertEqual(value, 203);
747 748
  XCTAssertTrue([dict getInt32:NULL forKey:2U]);
  XCTAssertTrue([dict getInt32:&value forKey:2U]);
749
  XCTAssertEqual(value, 201);
750 751
  XCTAssertTrue([dict getInt32:NULL forKey:3U]);
  XCTAssertTrue([dict getInt32:&value forKey:3U]);
752
  XCTAssertEqual(value, 202);
753 754
  XCTAssertTrue([dict getInt32:NULL forKey:4U]);
  XCTAssertTrue([dict getInt32:&value forKey:4U]);
755 756
  XCTAssertEqual(value, 203);

757
  [dict setInt32:201 forKey:4U];
758
  XCTAssertEqual(dict.count, 4U);
759 760
  XCTAssertTrue([dict getInt32:NULL forKey:1U]);
  XCTAssertTrue([dict getInt32:&value forKey:1U]);
761
  XCTAssertEqual(value, 203);
762 763
  XCTAssertTrue([dict getInt32:NULL forKey:2U]);
  XCTAssertTrue([dict getInt32:&value forKey:2U]);
764
  XCTAssertEqual(value, 201);
765 766
  XCTAssertTrue([dict getInt32:NULL forKey:3U]);
  XCTAssertTrue([dict getInt32:&value forKey:3U]);
767
  XCTAssertEqual(value, 202);
768 769
  XCTAssertTrue([dict getInt32:NULL forKey:4U]);
  XCTAssertTrue([dict getInt32:&value forKey:4U]);
770 771 772 773 774
  XCTAssertEqual(value, 201);

  const uint32_t kKeys2[] = { 2U, 3U };
  const int32_t kValues2[] = { 202, 200 };
  GPBUInt32Int32Dictionary *dict2 =
775
      [[GPBUInt32Int32Dictionary alloc] initWithInt32s:kValues2
776 777 778 779 780
                                               forKeys:kKeys2
                                                 count:GPBARRAYSIZE(kValues2)];
  XCTAssertNotNil(dict2);
  [dict addEntriesFromDictionary:dict2];
  XCTAssertEqual(dict.count, 4U);
781 782
  XCTAssertTrue([dict getInt32:NULL forKey:1U]);
  XCTAssertTrue([dict getInt32:&value forKey:1U]);
783
  XCTAssertEqual(value, 203);
784 785
  XCTAssertTrue([dict getInt32:NULL forKey:2U]);
  XCTAssertTrue([dict getInt32:&value forKey:2U]);
786
  XCTAssertEqual(value, 202);
787 788
  XCTAssertTrue([dict getInt32:NULL forKey:3U]);
  XCTAssertTrue([dict getInt32:&value forKey:3U]);
789
  XCTAssertEqual(value, 200);
790 791
  XCTAssertTrue([dict getInt32:NULL forKey:4U]);
  XCTAssertTrue([dict getInt32:&value forKey:4U]);
792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810
  XCTAssertEqual(value, 201);

  [dict2 release];
  [dict release];
}

@end

#pragma mark - UInt32 -> UInt64

@interface GPBUInt32UInt64DictionaryTests : XCTestCase
@end

@implementation GPBUInt32UInt64DictionaryTests

- (void)testEmpty {
  GPBUInt32UInt64Dictionary *dict = [[GPBUInt32UInt64Dictionary alloc] init];
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 0U);
811 812
  XCTAssertFalse([dict getUInt64:NULL forKey:1U]);
  [dict enumerateKeysAndUInt64sUsingBlock:^(uint32_t aKey, uint64_t aValue, BOOL *stop) {
813 814 815 816 817 818 819
    #pragma unused(aKey, aValue, stop)
    XCTFail(@"Shouldn't get here!");
  }];
  [dict release];
}

- (void)testOne {
820
  GPBUInt32UInt64Dictionary *dict = [GPBUInt32UInt64Dictionary dictionaryWithUInt64:300U forKey:1U];
821 822 823
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 1U);
  uint64_t value;
824 825
  XCTAssertTrue([dict getUInt64:NULL forKey:1U]);
  XCTAssertTrue([dict getUInt64:&value forKey:1U]);
826
  XCTAssertEqual(value, 300U);
827 828
  XCTAssertFalse([dict getUInt64:NULL forKey:2U]);
  [dict enumerateKeysAndUInt64sUsingBlock:^(uint32_t aKey, uint64_t aValue, BOOL *stop) {
829 830 831 832 833 834 835 836 837 838
    XCTAssertEqual(aKey, 1U);
    XCTAssertEqual(aValue, 300U);
    XCTAssertNotEqual(stop, NULL);
  }];
}

- (void)testBasics {
  const uint32_t kKeys[] = { 1U, 2U, 3U };
  const uint64_t kValues[] = { 300U, 301U, 302U };
  GPBUInt32UInt64Dictionary *dict =
839 840 841
      [[GPBUInt32UInt64Dictionary alloc] initWithUInt64s:kValues
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kValues)];
842 843 844
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 3U);
  uint64_t value;
845 846
  XCTAssertTrue([dict getUInt64:NULL forKey:1U]);
  XCTAssertTrue([dict getUInt64:&value forKey:1U]);
847
  XCTAssertEqual(value, 300U);
848 849
  XCTAssertTrue([dict getUInt64:NULL forKey:2U]);
  XCTAssertTrue([dict getUInt64:&value forKey:2U]);
850
  XCTAssertEqual(value, 301U);
851 852
  XCTAssertTrue([dict getUInt64:NULL forKey:3U]);
  XCTAssertTrue([dict getUInt64:&value forKey:3U]);
853
  XCTAssertEqual(value, 302U);
854
  XCTAssertFalse([dict getUInt64:NULL forKey:4U]);
855 856 857 858

  __block NSUInteger idx = 0;
  uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
  uint64_t *seenValues = malloc(3 * sizeof(uint64_t));
859
  [dict enumerateKeysAndUInt64sUsingBlock:^(uint32_t aKey, uint64_t aValue, BOOL *stop) {
860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880
    XCTAssertLessThan(idx, 3U);
    seenKeys[idx] = aKey;
    seenValues[idx] = aValue;
    XCTAssertNotEqual(stop, NULL);
    ++idx;
  }];
  for (int i = 0; i < 3; ++i) {
    BOOL foundKey = NO;
    for (int j = 0; (j < 3) && !foundKey; ++j) {
      if (kKeys[i] == seenKeys[j]) {
        foundKey = YES;
        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
      }
    }
    XCTAssertTrue(foundKey, @"i = %d", i);
  }
  free(seenKeys);
  free(seenValues);

  // Stopping the enumeration.
  idx = 0;
881
  [dict enumerateKeysAndUInt64sUsingBlock:^(uint32_t aKey, uint64_t aValue, BOOL *stop) {
882 883 884 885 886 887 888 889 890 891 892 893 894 895 896
    #pragma unused(aKey, aValue)
    if (idx == 1) *stop = YES;
    XCTAssertNotEqual(idx, 2U);
    ++idx;
  }];
  [dict release];
}

- (void)testEquality {
  const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
  const uint32_t kKeys2[] = { 2U, 1U, 4U };
  const uint64_t kValues1[] = { 300U, 301U, 302U };
  const uint64_t kValues2[] = { 300U, 303U, 302U };
  const uint64_t kValues3[] = { 300U, 301U, 302U, 303U };
  GPBUInt32UInt64Dictionary *dict1 =
897 898 899
      [[GPBUInt32UInt64Dictionary alloc] initWithUInt64s:kValues1
                                                 forKeys:kKeys1
                                                   count:GPBARRAYSIZE(kValues1)];
900 901
  XCTAssertNotNil(dict1);
  GPBUInt32UInt64Dictionary *dict1prime =
902 903 904
      [[GPBUInt32UInt64Dictionary alloc] initWithUInt64s:kValues1
                                                 forKeys:kKeys1
                                                   count:GPBARRAYSIZE(kValues1)];
905 906
  XCTAssertNotNil(dict1prime);
  GPBUInt32UInt64Dictionary *dict2 =
907 908 909
      [[GPBUInt32UInt64Dictionary alloc] initWithUInt64s:kValues2
                                                 forKeys:kKeys1
                                                   count:GPBARRAYSIZE(kValues2)];
910 911
  XCTAssertNotNil(dict2);
  GPBUInt32UInt64Dictionary *dict3 =
912 913 914
      [[GPBUInt32UInt64Dictionary alloc] initWithUInt64s:kValues1
                                                 forKeys:kKeys2
                                                   count:GPBARRAYSIZE(kValues1)];
915 916
  XCTAssertNotNil(dict3);
  GPBUInt32UInt64Dictionary *dict4 =
917 918 919
      [[GPBUInt32UInt64Dictionary alloc] initWithUInt64s:kValues3
                                                 forKeys:kKeys1
                                                   count:GPBARRAYSIZE(kValues3)];
920 921 922 923 924 925 926 927
  XCTAssertNotNil(dict4);

  // 1/1Prime should be different objects, but equal.
  XCTAssertNotEqual(dict1, dict1prime);
  XCTAssertEqualObjects(dict1, dict1prime);
  // Equal, so they must have same hash.
  XCTAssertEqual([dict1 hash], [dict1prime hash]);

928
  // 2 is same keys, different values; not equal.
929 930
  XCTAssertNotEqualObjects(dict1, dict2);

931
  // 3 is different keys, same values; not equal.
932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947
  XCTAssertNotEqualObjects(dict1, dict3);

  // 4 extra pair; not equal
  XCTAssertNotEqualObjects(dict1, dict4);

  [dict1 release];
  [dict1prime release];
  [dict2 release];
  [dict3 release];
  [dict4 release];
}

- (void)testCopy {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
  GPBUInt32UInt64Dictionary *dict =
948 949 950
      [[GPBUInt32UInt64Dictionary alloc] initWithUInt64s:kValues
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kValues)];
951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968
  XCTAssertNotNil(dict);

  GPBUInt32UInt64Dictionary *dict2 = [dict copy];
  XCTAssertNotNil(dict2);

  // Should be new object but equal.
  XCTAssertNotEqual(dict, dict2);
  XCTAssertEqualObjects(dict, dict2);
  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32UInt64Dictionary class]]);

  [dict2 release];
  [dict release];
}

- (void)testDictionaryFromDictionary {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
  GPBUInt32UInt64Dictionary *dict =
969 970 971
      [[GPBUInt32UInt64Dictionary alloc] initWithUInt64s:kValues
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kValues)];
972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988
  XCTAssertNotNil(dict);

  GPBUInt32UInt64Dictionary *dict2 =
      [GPBUInt32UInt64Dictionary dictionaryWithDictionary:dict];
  XCTAssertNotNil(dict2);

  // Should be new pointer, but equal objects.
  XCTAssertNotEqual(dict, dict2);
  XCTAssertEqualObjects(dict, dict2);
  [dict release];
}

- (void)testAdds {
  GPBUInt32UInt64Dictionary *dict = [GPBUInt32UInt64Dictionary dictionary];
  XCTAssertNotNil(dict);

  XCTAssertEqual(dict.count, 0U);
989
  [dict setUInt64:300U forKey:1U];
990 991 992 993 994
  XCTAssertEqual(dict.count, 1U);

  const uint32_t kKeys[] = { 2U, 3U, 4U };
  const uint64_t kValues[] = { 301U, 302U, 303U };
  GPBUInt32UInt64Dictionary *dict2 =
995 996 997
      [[GPBUInt32UInt64Dictionary alloc] initWithUInt64s:kValues
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kValues)];
998 999 1000 1001 1002
  XCTAssertNotNil(dict2);
  [dict addEntriesFromDictionary:dict2];
  XCTAssertEqual(dict.count, 4U);

  uint64_t value;
1003 1004
  XCTAssertTrue([dict getUInt64:NULL forKey:1U]);
  XCTAssertTrue([dict getUInt64:&value forKey:1U]);
1005
  XCTAssertEqual(value, 300U);
1006 1007
  XCTAssertTrue([dict getUInt64:NULL forKey:2U]);
  XCTAssertTrue([dict getUInt64:&value forKey:2U]);
1008
  XCTAssertEqual(value, 301U);
1009 1010
  XCTAssertTrue([dict getUInt64:NULL forKey:3U]);
  XCTAssertTrue([dict getUInt64:&value forKey:3U]);
1011
  XCTAssertEqual(value, 302U);
1012 1013
  XCTAssertTrue([dict getUInt64:NULL forKey:4U]);
  XCTAssertTrue([dict getUInt64:&value forKey:4U]);
1014 1015 1016 1017 1018 1019 1020 1021
  XCTAssertEqual(value, 303U);
  [dict2 release];
}

- (void)testRemove {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
  GPBUInt32UInt64Dictionary *dict =
1022 1023 1024
      [[GPBUInt32UInt64Dictionary alloc] initWithUInt64s:kValues
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kValues)];
1025 1026 1027
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 4U);

1028
  [dict removeUInt64ForKey:2U];
1029 1030
  XCTAssertEqual(dict.count, 3U);
  uint64_t value;
1031 1032
  XCTAssertTrue([dict getUInt64:NULL forKey:1U]);
  XCTAssertTrue([dict getUInt64:&value forKey:1U]);
1033
  XCTAssertEqual(value, 300U);
1034 1035 1036
  XCTAssertFalse([dict getUInt64:NULL forKey:2U]);
  XCTAssertTrue([dict getUInt64:NULL forKey:3U]);
  XCTAssertTrue([dict getUInt64:&value forKey:3U]);
1037
  XCTAssertEqual(value, 302U);
1038 1039
  XCTAssertTrue([dict getUInt64:NULL forKey:4U]);
  XCTAssertTrue([dict getUInt64:&value forKey:4U]);
1040 1041 1042
  XCTAssertEqual(value, 303U);

  // Remove again does nothing.
1043
  [dict removeUInt64ForKey:2U];
1044
  XCTAssertEqual(dict.count, 3U);
1045 1046
  XCTAssertTrue([dict getUInt64:NULL forKey:1U]);
  XCTAssertTrue([dict getUInt64:&value forKey:1U]);
1047
  XCTAssertEqual(value, 300U);
1048 1049 1050
  XCTAssertFalse([dict getUInt64:NULL forKey:2U]);
  XCTAssertTrue([dict getUInt64:NULL forKey:3U]);
  XCTAssertTrue([dict getUInt64:&value forKey:3U]);
1051
  XCTAssertEqual(value, 302U);
1052 1053
  XCTAssertTrue([dict getUInt64:NULL forKey:4U]);
  XCTAssertTrue([dict getUInt64:&value forKey:4U]);
1054 1055
  XCTAssertEqual(value, 303U);

1056
  [dict removeUInt64ForKey:4U];
1057
  XCTAssertEqual(dict.count, 2U);
1058 1059
  XCTAssertTrue([dict getUInt64:NULL forKey:1U]);
  XCTAssertTrue([dict getUInt64:&value forKey:1U]);
1060
  XCTAssertEqual(value, 300U);
1061 1062 1063
  XCTAssertFalse([dict getUInt64:NULL forKey:2U]);
  XCTAssertTrue([dict getUInt64:NULL forKey:3U]);
  XCTAssertTrue([dict getUInt64:&value forKey:3U]);
1064
  XCTAssertEqual(value, 302U);
1065
  XCTAssertFalse([dict getUInt64:NULL forKey:4U]);
1066 1067 1068

  [dict removeAll];
  XCTAssertEqual(dict.count, 0U);
1069 1070 1071 1072
  XCTAssertFalse([dict getUInt64:NULL forKey:1U]);
  XCTAssertFalse([dict getUInt64:NULL forKey:2U]);
  XCTAssertFalse([dict getUInt64:NULL forKey:3U]);
  XCTAssertFalse([dict getUInt64:NULL forKey:4U]);
1073 1074 1075 1076 1077 1078 1079
  [dict release];
}

- (void)testInplaceMutation {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
  GPBUInt32UInt64Dictionary *dict =
1080 1081 1082
      [[GPBUInt32UInt64Dictionary alloc] initWithUInt64s:kValues
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kValues)];
1083 1084 1085
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 4U);
  uint64_t value;
1086 1087
  XCTAssertTrue([dict getUInt64:NULL forKey:1U]);
  XCTAssertTrue([dict getUInt64:&value forKey:1U]);
1088
  XCTAssertEqual(value, 300U);
1089 1090
  XCTAssertTrue([dict getUInt64:NULL forKey:2U]);
  XCTAssertTrue([dict getUInt64:&value forKey:2U]);
1091
  XCTAssertEqual(value, 301U);
1092 1093
  XCTAssertTrue([dict getUInt64:NULL forKey:3U]);
  XCTAssertTrue([dict getUInt64:&value forKey:3U]);
1094
  XCTAssertEqual(value, 302U);
1095 1096
  XCTAssertTrue([dict getUInt64:NULL forKey:4U]);
  XCTAssertTrue([dict getUInt64:&value forKey:4U]);
1097 1098
  XCTAssertEqual(value, 303U);

1099
  [dict setUInt64:303U forKey:1U];
1100
  XCTAssertEqual(dict.count, 4U);
1101 1102
  XCTAssertTrue([dict getUInt64:NULL forKey:1U]);
  XCTAssertTrue([dict getUInt64:&value forKey:1U]);
1103
  XCTAssertEqual(value, 303U);
1104 1105
  XCTAssertTrue([dict getUInt64:NULL forKey:2U]);
  XCTAssertTrue([dict getUInt64:&value forKey:2U]);
1106
  XCTAssertEqual(value, 301U);
1107 1108
  XCTAssertTrue([dict getUInt64:NULL forKey:3U]);
  XCTAssertTrue([dict getUInt64:&value forKey:3U]);
1109
  XCTAssertEqual(value, 302U);
1110 1111
  XCTAssertTrue([dict getUInt64:NULL forKey:4U]);
  XCTAssertTrue([dict getUInt64:&value forKey:4U]);
1112 1113
  XCTAssertEqual(value, 303U);

1114
  [dict setUInt64:301U forKey:4U];
1115
  XCTAssertEqual(dict.count, 4U);
1116 1117
  XCTAssertTrue([dict getUInt64:NULL forKey:1U]);
  XCTAssertTrue([dict getUInt64:&value forKey:1U]);
1118
  XCTAssertEqual(value, 303U);
1119 1120
  XCTAssertTrue([dict getUInt64:NULL forKey:2U]);
  XCTAssertTrue([dict getUInt64:&value forKey:2U]);
1121
  XCTAssertEqual(value, 301U);
1122 1123
  XCTAssertTrue([dict getUInt64:NULL forKey:3U]);
  XCTAssertTrue([dict getUInt64:&value forKey:3U]);
1124
  XCTAssertEqual(value, 302U);
1125 1126
  XCTAssertTrue([dict getUInt64:NULL forKey:4U]);
  XCTAssertTrue([dict getUInt64:&value forKey:4U]);
1127 1128 1129 1130 1131
  XCTAssertEqual(value, 301U);

  const uint32_t kKeys2[] = { 2U, 3U };
  const uint64_t kValues2[] = { 302U, 300U };
  GPBUInt32UInt64Dictionary *dict2 =
1132 1133 1134
      [[GPBUInt32UInt64Dictionary alloc] initWithUInt64s:kValues2
                                                 forKeys:kKeys2
                                                   count:GPBARRAYSIZE(kValues2)];
1135 1136 1137
  XCTAssertNotNil(dict2);
  [dict addEntriesFromDictionary:dict2];
  XCTAssertEqual(dict.count, 4U);
1138 1139
  XCTAssertTrue([dict getUInt64:NULL forKey:1U]);
  XCTAssertTrue([dict getUInt64:&value forKey:1U]);
1140
  XCTAssertEqual(value, 303U);
1141 1142
  XCTAssertTrue([dict getUInt64:NULL forKey:2U]);
  XCTAssertTrue([dict getUInt64:&value forKey:2U]);
1143
  XCTAssertEqual(value, 302U);
1144 1145
  XCTAssertTrue([dict getUInt64:NULL forKey:3U]);
  XCTAssertTrue([dict getUInt64:&value forKey:3U]);
1146
  XCTAssertEqual(value, 300U);
1147 1148
  XCTAssertTrue([dict getUInt64:NULL forKey:4U]);
  XCTAssertTrue([dict getUInt64:&value forKey:4U]);
1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167
  XCTAssertEqual(value, 301U);

  [dict2 release];
  [dict release];
}

@end

#pragma mark - UInt32 -> Int64

@interface GPBUInt32Int64DictionaryTests : XCTestCase
@end

@implementation GPBUInt32Int64DictionaryTests

- (void)testEmpty {
  GPBUInt32Int64Dictionary *dict = [[GPBUInt32Int64Dictionary alloc] init];
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 0U);
1168 1169
  XCTAssertFalse([dict getInt64:NULL forKey:1U]);
  [dict enumerateKeysAndInt64sUsingBlock:^(uint32_t aKey, int64_t aValue, BOOL *stop) {
1170 1171 1172 1173 1174 1175 1176
    #pragma unused(aKey, aValue, stop)
    XCTFail(@"Shouldn't get here!");
  }];
  [dict release];
}

- (void)testOne {
1177
  GPBUInt32Int64Dictionary *dict = [GPBUInt32Int64Dictionary dictionaryWithInt64:400 forKey:1U];
1178 1179 1180
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 1U);
  int64_t value;
1181 1182
  XCTAssertTrue([dict getInt64:NULL forKey:1U]);
  XCTAssertTrue([dict getInt64:&value forKey:1U]);
1183
  XCTAssertEqual(value, 400);
1184 1185
  XCTAssertFalse([dict getInt64:NULL forKey:2U]);
  [dict enumerateKeysAndInt64sUsingBlock:^(uint32_t aKey, int64_t aValue, BOOL *stop) {
1186 1187 1188 1189 1190 1191 1192 1193 1194 1195
    XCTAssertEqual(aKey, 1U);
    XCTAssertEqual(aValue, 400);
    XCTAssertNotEqual(stop, NULL);
  }];
}

- (void)testBasics {
  const uint32_t kKeys[] = { 1U, 2U, 3U };
  const int64_t kValues[] = { 400, 401, 402 };
  GPBUInt32Int64Dictionary *dict =
1196
      [[GPBUInt32Int64Dictionary alloc] initWithInt64s:kValues
1197 1198 1199 1200 1201
                                               forKeys:kKeys
                                                 count:GPBARRAYSIZE(kValues)];
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 3U);
  int64_t value;
1202 1203
  XCTAssertTrue([dict getInt64:NULL forKey:1U]);
  XCTAssertTrue([dict getInt64:&value forKey:1U]);
1204
  XCTAssertEqual(value, 400);
1205 1206
  XCTAssertTrue([dict getInt64:NULL forKey:2U]);
  XCTAssertTrue([dict getInt64:&value forKey:2U]);
1207
  XCTAssertEqual(value, 401);
1208 1209
  XCTAssertTrue([dict getInt64:NULL forKey:3U]);
  XCTAssertTrue([dict getInt64:&value forKey:3U]);
1210
  XCTAssertEqual(value, 402);
1211
  XCTAssertFalse([dict getInt64:NULL forKey:4U]);
1212 1213 1214 1215

  __block NSUInteger idx = 0;
  uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
  int64_t *seenValues = malloc(3 * sizeof(int64_t));
1216
  [dict enumerateKeysAndInt64sUsingBlock:^(uint32_t aKey, int64_t aValue, BOOL *stop) {
1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237
    XCTAssertLessThan(idx, 3U);
    seenKeys[idx] = aKey;
    seenValues[idx] = aValue;
    XCTAssertNotEqual(stop, NULL);
    ++idx;
  }];
  for (int i = 0; i < 3; ++i) {
    BOOL foundKey = NO;
    for (int j = 0; (j < 3) && !foundKey; ++j) {
      if (kKeys[i] == seenKeys[j]) {
        foundKey = YES;
        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
      }
    }
    XCTAssertTrue(foundKey, @"i = %d", i);
  }
  free(seenKeys);
  free(seenValues);

  // Stopping the enumeration.
  idx = 0;
1238
  [dict enumerateKeysAndInt64sUsingBlock:^(uint32_t aKey, int64_t aValue, BOOL *stop) {
1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253
    #pragma unused(aKey, aValue)
    if (idx == 1) *stop = YES;
    XCTAssertNotEqual(idx, 2U);
    ++idx;
  }];
  [dict release];
}

- (void)testEquality {
  const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
  const uint32_t kKeys2[] = { 2U, 1U, 4U };
  const int64_t kValues1[] = { 400, 401, 402 };
  const int64_t kValues2[] = { 400, 403, 402 };
  const int64_t kValues3[] = { 400, 401, 402, 403 };
  GPBUInt32Int64Dictionary *dict1 =
1254
      [[GPBUInt32Int64Dictionary alloc] initWithInt64s:kValues1
1255 1256 1257 1258
                                               forKeys:kKeys1
                                                 count:GPBARRAYSIZE(kValues1)];
  XCTAssertNotNil(dict1);
  GPBUInt32Int64Dictionary *dict1prime =
1259
      [[GPBUInt32Int64Dictionary alloc] initWithInt64s:kValues1
1260 1261 1262 1263
                                               forKeys:kKeys1
                                                 count:GPBARRAYSIZE(kValues1)];
  XCTAssertNotNil(dict1prime);
  GPBUInt32Int64Dictionary *dict2 =
1264
      [[GPBUInt32Int64Dictionary alloc] initWithInt64s:kValues2
1265 1266 1267 1268
                                               forKeys:kKeys1
                                                 count:GPBARRAYSIZE(kValues2)];
  XCTAssertNotNil(dict2);
  GPBUInt32Int64Dictionary *dict3 =
1269
      [[GPBUInt32Int64Dictionary alloc] initWithInt64s:kValues1
1270 1271 1272 1273
                                               forKeys:kKeys2
                                                 count:GPBARRAYSIZE(kValues1)];
  XCTAssertNotNil(dict3);
  GPBUInt32Int64Dictionary *dict4 =
1274
      [[GPBUInt32Int64Dictionary alloc] initWithInt64s:kValues3
1275 1276 1277 1278 1279 1280 1281 1282 1283 1284
                                               forKeys:kKeys1
                                                 count:GPBARRAYSIZE(kValues3)];
  XCTAssertNotNil(dict4);

  // 1/1Prime should be different objects, but equal.
  XCTAssertNotEqual(dict1, dict1prime);
  XCTAssertEqualObjects(dict1, dict1prime);
  // Equal, so they must have same hash.
  XCTAssertEqual([dict1 hash], [dict1prime hash]);

1285
  // 2 is same keys, different values; not equal.
1286 1287
  XCTAssertNotEqualObjects(dict1, dict2);

1288
  // 3 is different keys, same values; not equal.
1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304
  XCTAssertNotEqualObjects(dict1, dict3);

  // 4 extra pair; not equal
  XCTAssertNotEqualObjects(dict1, dict4);

  [dict1 release];
  [dict1prime release];
  [dict2 release];
  [dict3 release];
  [dict4 release];
}

- (void)testCopy {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const int64_t kValues[] = { 400, 401, 402, 403 };
  GPBUInt32Int64Dictionary *dict =
1305
      [[GPBUInt32Int64Dictionary alloc] initWithInt64s:kValues
1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325
                                               forKeys:kKeys
                                                 count:GPBARRAYSIZE(kValues)];
  XCTAssertNotNil(dict);

  GPBUInt32Int64Dictionary *dict2 = [dict copy];
  XCTAssertNotNil(dict2);

  // Should be new object but equal.
  XCTAssertNotEqual(dict, dict2);
  XCTAssertEqualObjects(dict, dict2);
  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32Int64Dictionary class]]);

  [dict2 release];
  [dict release];
}

- (void)testDictionaryFromDictionary {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const int64_t kValues[] = { 400, 401, 402, 403 };
  GPBUInt32Int64Dictionary *dict =
1326
      [[GPBUInt32Int64Dictionary alloc] initWithInt64s:kValues
1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345
                                               forKeys:kKeys
                                                 count:GPBARRAYSIZE(kValues)];
  XCTAssertNotNil(dict);

  GPBUInt32Int64Dictionary *dict2 =
      [GPBUInt32Int64Dictionary dictionaryWithDictionary:dict];
  XCTAssertNotNil(dict2);

  // Should be new pointer, but equal objects.
  XCTAssertNotEqual(dict, dict2);
  XCTAssertEqualObjects(dict, dict2);
  [dict release];
}

- (void)testAdds {
  GPBUInt32Int64Dictionary *dict = [GPBUInt32Int64Dictionary dictionary];
  XCTAssertNotNil(dict);

  XCTAssertEqual(dict.count, 0U);
1346
  [dict setInt64:400 forKey:1U];
1347 1348 1349 1350 1351
  XCTAssertEqual(dict.count, 1U);

  const uint32_t kKeys[] = { 2U, 3U, 4U };
  const int64_t kValues[] = { 401, 402, 403 };
  GPBUInt32Int64Dictionary *dict2 =
1352
      [[GPBUInt32Int64Dictionary alloc] initWithInt64s:kValues
1353 1354 1355 1356 1357 1358 1359
                                               forKeys:kKeys
                                                 count:GPBARRAYSIZE(kValues)];
  XCTAssertNotNil(dict2);
  [dict addEntriesFromDictionary:dict2];
  XCTAssertEqual(dict.count, 4U);

  int64_t value;
1360 1361
  XCTAssertTrue([dict getInt64:NULL forKey:1U]);
  XCTAssertTrue([dict getInt64:&value forKey:1U]);
1362
  XCTAssertEqual(value, 400);
1363 1364
  XCTAssertTrue([dict getInt64:NULL forKey:2U]);
  XCTAssertTrue([dict getInt64:&value forKey:2U]);
1365
  XCTAssertEqual(value, 401);
1366 1367
  XCTAssertTrue([dict getInt64:NULL forKey:3U]);
  XCTAssertTrue([dict getInt64:&value forKey:3U]);
1368
  XCTAssertEqual(value, 402);
1369 1370
  XCTAssertTrue([dict getInt64:NULL forKey:4U]);
  XCTAssertTrue([dict getInt64:&value forKey:4U]);
1371 1372 1373 1374 1375 1376 1377 1378
  XCTAssertEqual(value, 403);
  [dict2 release];
}

- (void)testRemove {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const int64_t kValues[] = { 400, 401, 402, 403 };
  GPBUInt32Int64Dictionary *dict =
1379 1380 1381
      [[GPBUInt32Int64Dictionary alloc] initWithInt64s:kValues
                                               forKeys:kKeys
                                                 count:GPBARRAYSIZE(kValues)];
1382 1383 1384
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 4U);

1385
  [dict removeInt64ForKey:2U];
1386 1387
  XCTAssertEqual(dict.count, 3U);
  int64_t value;
1388 1389
  XCTAssertTrue([dict getInt64:NULL forKey:1U]);
  XCTAssertTrue([dict getInt64:&value forKey:1U]);
1390
  XCTAssertEqual(value, 400);
1391 1392 1393
  XCTAssertFalse([dict getInt64:NULL forKey:2U]);
  XCTAssertTrue([dict getInt64:NULL forKey:3U]);
  XCTAssertTrue([dict getInt64:&value forKey:3U]);
1394
  XCTAssertEqual(value, 402);
1395 1396
  XCTAssertTrue([dict getInt64:NULL forKey:4U]);
  XCTAssertTrue([dict getInt64:&value forKey:4U]);
1397 1398 1399
  XCTAssertEqual(value, 403);

  // Remove again does nothing.
1400
  [dict removeInt64ForKey:2U];
1401
  XCTAssertEqual(dict.count, 3U);
1402 1403
  XCTAssertTrue([dict getInt64:NULL forKey:1U]);
  XCTAssertTrue([dict getInt64:&value forKey:1U]);
1404
  XCTAssertEqual(value, 400);
1405 1406 1407
  XCTAssertFalse([dict getInt64:NULL forKey:2U]);
  XCTAssertTrue([dict getInt64:NULL forKey:3U]);
  XCTAssertTrue([dict getInt64:&value forKey:3U]);
1408
  XCTAssertEqual(value, 402);
1409 1410
  XCTAssertTrue([dict getInt64:NULL forKey:4U]);
  XCTAssertTrue([dict getInt64:&value forKey:4U]);
1411 1412
  XCTAssertEqual(value, 403);

1413
  [dict removeInt64ForKey:4U];
1414
  XCTAssertEqual(dict.count, 2U);
1415 1416
  XCTAssertTrue([dict getInt64:NULL forKey:1U]);
  XCTAssertTrue([dict getInt64:&value forKey:1U]);
1417
  XCTAssertEqual(value, 400);
1418 1419 1420
  XCTAssertFalse([dict getInt64:NULL forKey:2U]);
  XCTAssertTrue([dict getInt64:NULL forKey:3U]);
  XCTAssertTrue([dict getInt64:&value forKey:3U]);
1421
  XCTAssertEqual(value, 402);
1422
  XCTAssertFalse([dict getInt64:NULL forKey:4U]);
1423 1424 1425

  [dict removeAll];
  XCTAssertEqual(dict.count, 0U);
1426 1427 1428 1429
  XCTAssertFalse([dict getInt64:NULL forKey:1U]);
  XCTAssertFalse([dict getInt64:NULL forKey:2U]);
  XCTAssertFalse([dict getInt64:NULL forKey:3U]);
  XCTAssertFalse([dict getInt64:NULL forKey:4U]);
1430 1431 1432 1433 1434 1435 1436
  [dict release];
}

- (void)testInplaceMutation {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const int64_t kValues[] = { 400, 401, 402, 403 };
  GPBUInt32Int64Dictionary *dict =
1437 1438 1439
      [[GPBUInt32Int64Dictionary alloc] initWithInt64s:kValues
                                               forKeys:kKeys
                                                 count:GPBARRAYSIZE(kValues)];
1440 1441 1442
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 4U);
  int64_t value;
1443 1444
  XCTAssertTrue([dict getInt64:NULL forKey:1U]);
  XCTAssertTrue([dict getInt64:&value forKey:1U]);
1445
  XCTAssertEqual(value, 400);
1446 1447
  XCTAssertTrue([dict getInt64:NULL forKey:2U]);
  XCTAssertTrue([dict getInt64:&value forKey:2U]);
1448
  XCTAssertEqual(value, 401);
1449 1450
  XCTAssertTrue([dict getInt64:NULL forKey:3U]);
  XCTAssertTrue([dict getInt64:&value forKey:3U]);
1451
  XCTAssertEqual(value, 402);
1452 1453
  XCTAssertTrue([dict getInt64:NULL forKey:4U]);
  XCTAssertTrue([dict getInt64:&value forKey:4U]);
1454 1455
  XCTAssertEqual(value, 403);

1456
  [dict setInt64:403 forKey:1U];
1457
  XCTAssertEqual(dict.count, 4U);
1458 1459
  XCTAssertTrue([dict getInt64:NULL forKey:1U]);
  XCTAssertTrue([dict getInt64:&value forKey:1U]);
1460
  XCTAssertEqual(value, 403);
1461 1462
  XCTAssertTrue([dict getInt64:NULL forKey:2U]);
  XCTAssertTrue([dict getInt64:&value forKey:2U]);
1463
  XCTAssertEqual(value, 401);
1464 1465
  XCTAssertTrue([dict getInt64:NULL forKey:3U]);
  XCTAssertTrue([dict getInt64:&value forKey:3U]);
1466
  XCTAssertEqual(value, 402);
1467 1468
  XCTAssertTrue([dict getInt64:NULL forKey:4U]);
  XCTAssertTrue([dict getInt64:&value forKey:4U]);
1469 1470
  XCTAssertEqual(value, 403);

1471
  [dict setInt64:401 forKey:4U];
1472
  XCTAssertEqual(dict.count, 4U);
1473 1474
  XCTAssertTrue([dict getInt64:NULL forKey:1U]);
  XCTAssertTrue([dict getInt64:&value forKey:1U]);
1475
  XCTAssertEqual(value, 403);
1476 1477
  XCTAssertTrue([dict getInt64:NULL forKey:2U]);
  XCTAssertTrue([dict getInt64:&value forKey:2U]);
1478
  XCTAssertEqual(value, 401);
1479 1480
  XCTAssertTrue([dict getInt64:NULL forKey:3U]);
  XCTAssertTrue([dict getInt64:&value forKey:3U]);
1481
  XCTAssertEqual(value, 402);
1482 1483
  XCTAssertTrue([dict getInt64:NULL forKey:4U]);
  XCTAssertTrue([dict getInt64:&value forKey:4U]);
1484 1485 1486 1487 1488
  XCTAssertEqual(value, 401);

  const uint32_t kKeys2[] = { 2U, 3U };
  const int64_t kValues2[] = { 402, 400 };
  GPBUInt32Int64Dictionary *dict2 =
1489
      [[GPBUInt32Int64Dictionary alloc] initWithInt64s:kValues2
1490 1491 1492 1493 1494
                                               forKeys:kKeys2
                                                 count:GPBARRAYSIZE(kValues2)];
  XCTAssertNotNil(dict2);
  [dict addEntriesFromDictionary:dict2];
  XCTAssertEqual(dict.count, 4U);
1495 1496
  XCTAssertTrue([dict getInt64:NULL forKey:1U]);
  XCTAssertTrue([dict getInt64:&value forKey:1U]);
1497
  XCTAssertEqual(value, 403);
1498 1499
  XCTAssertTrue([dict getInt64:NULL forKey:2U]);
  XCTAssertTrue([dict getInt64:&value forKey:2U]);
1500
  XCTAssertEqual(value, 402);
1501 1502
  XCTAssertTrue([dict getInt64:NULL forKey:3U]);
  XCTAssertTrue([dict getInt64:&value forKey:3U]);
1503
  XCTAssertEqual(value, 400);
1504 1505
  XCTAssertTrue([dict getInt64:NULL forKey:4U]);
  XCTAssertTrue([dict getInt64:&value forKey:4U]);
1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524
  XCTAssertEqual(value, 401);

  [dict2 release];
  [dict release];
}

@end

#pragma mark - UInt32 -> Bool

@interface GPBUInt32BoolDictionaryTests : XCTestCase
@end

@implementation GPBUInt32BoolDictionaryTests

- (void)testEmpty {
  GPBUInt32BoolDictionary *dict = [[GPBUInt32BoolDictionary alloc] init];
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 0U);
1525 1526
  XCTAssertFalse([dict getBool:NULL forKey:1U]);
  [dict enumerateKeysAndBoolsUsingBlock:^(uint32_t aKey, BOOL aValue, BOOL *stop) {
1527 1528 1529 1530 1531 1532 1533
    #pragma unused(aKey, aValue, stop)
    XCTFail(@"Shouldn't get here!");
  }];
  [dict release];
}

- (void)testOne {
1534
  GPBUInt32BoolDictionary *dict = [GPBUInt32BoolDictionary dictionaryWithBool:YES forKey:1U];
1535 1536 1537
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 1U);
  BOOL value;
1538 1539
  XCTAssertTrue([dict getBool:NULL forKey:1U]);
  XCTAssertTrue([dict getBool:&value forKey:1U]);
1540
  XCTAssertEqual(value, YES);
1541 1542
  XCTAssertFalse([dict getBool:NULL forKey:2U]);
  [dict enumerateKeysAndBoolsUsingBlock:^(uint32_t aKey, BOOL aValue, BOOL *stop) {
1543 1544 1545 1546 1547 1548 1549 1550 1551 1552
    XCTAssertEqual(aKey, 1U);
    XCTAssertEqual(aValue, YES);
    XCTAssertNotEqual(stop, NULL);
  }];
}

- (void)testBasics {
  const uint32_t kKeys[] = { 1U, 2U, 3U };
  const BOOL kValues[] = { YES, YES, NO };
  GPBUInt32BoolDictionary *dict =
1553 1554 1555
      [[GPBUInt32BoolDictionary alloc] initWithBools:kValues
                                             forKeys:kKeys
                                               count:GPBARRAYSIZE(kValues)];
1556 1557 1558
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 3U);
  BOOL value;
1559 1560
  XCTAssertTrue([dict getBool:NULL forKey:1U]);
  XCTAssertTrue([dict getBool:&value forKey:1U]);
1561
  XCTAssertEqual(value, YES);
1562 1563
  XCTAssertTrue([dict getBool:NULL forKey:2U]);
  XCTAssertTrue([dict getBool:&value forKey:2U]);
1564
  XCTAssertEqual(value, YES);
1565 1566
  XCTAssertTrue([dict getBool:NULL forKey:3U]);
  XCTAssertTrue([dict getBool:&value forKey:3U]);
1567
  XCTAssertEqual(value, NO);
1568
  XCTAssertFalse([dict getBool:NULL forKey:4U]);
1569 1570 1571 1572

  __block NSUInteger idx = 0;
  uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
  BOOL *seenValues = malloc(3 * sizeof(BOOL));
1573
  [dict enumerateKeysAndBoolsUsingBlock:^(uint32_t aKey, BOOL aValue, BOOL *stop) {
1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594
    XCTAssertLessThan(idx, 3U);
    seenKeys[idx] = aKey;
    seenValues[idx] = aValue;
    XCTAssertNotEqual(stop, NULL);
    ++idx;
  }];
  for (int i = 0; i < 3; ++i) {
    BOOL foundKey = NO;
    for (int j = 0; (j < 3) && !foundKey; ++j) {
      if (kKeys[i] == seenKeys[j]) {
        foundKey = YES;
        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
      }
    }
    XCTAssertTrue(foundKey, @"i = %d", i);
  }
  free(seenKeys);
  free(seenValues);

  // Stopping the enumeration.
  idx = 0;
1595
  [dict enumerateKeysAndBoolsUsingBlock:^(uint32_t aKey, BOOL aValue, BOOL *stop) {
1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610
    #pragma unused(aKey, aValue)
    if (idx == 1) *stop = YES;
    XCTAssertNotEqual(idx, 2U);
    ++idx;
  }];
  [dict release];
}

- (void)testEquality {
  const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
  const uint32_t kKeys2[] = { 2U, 1U, 4U };
  const BOOL kValues1[] = { YES, YES, NO };
  const BOOL kValues2[] = { YES, NO, NO };
  const BOOL kValues3[] = { YES, YES, NO, NO };
  GPBUInt32BoolDictionary *dict1 =
1611 1612 1613
      [[GPBUInt32BoolDictionary alloc] initWithBools:kValues1
                                             forKeys:kKeys1
                                               count:GPBARRAYSIZE(kValues1)];
1614 1615
  XCTAssertNotNil(dict1);
  GPBUInt32BoolDictionary *dict1prime =
1616 1617 1618
      [[GPBUInt32BoolDictionary alloc] initWithBools:kValues1
                                             forKeys:kKeys1
                                               count:GPBARRAYSIZE(kValues1)];
1619 1620
  XCTAssertNotNil(dict1prime);
  GPBUInt32BoolDictionary *dict2 =
1621 1622 1623
      [[GPBUInt32BoolDictionary alloc] initWithBools:kValues2
                                             forKeys:kKeys1
                                               count:GPBARRAYSIZE(kValues2)];
1624 1625
  XCTAssertNotNil(dict2);
  GPBUInt32BoolDictionary *dict3 =
1626 1627 1628
      [[GPBUInt32BoolDictionary alloc] initWithBools:kValues1
                                             forKeys:kKeys2
                                               count:GPBARRAYSIZE(kValues1)];
1629 1630
  XCTAssertNotNil(dict3);
  GPBUInt32BoolDictionary *dict4 =
1631 1632 1633
      [[GPBUInt32BoolDictionary alloc] initWithBools:kValues3
                                             forKeys:kKeys1
                                               count:GPBARRAYSIZE(kValues3)];
1634 1635 1636 1637 1638 1639 1640 1641
  XCTAssertNotNil(dict4);

  // 1/1Prime should be different objects, but equal.
  XCTAssertNotEqual(dict1, dict1prime);
  XCTAssertEqualObjects(dict1, dict1prime);
  // Equal, so they must have same hash.
  XCTAssertEqual([dict1 hash], [dict1prime hash]);

1642
  // 2 is same keys, different values; not equal.
1643 1644
  XCTAssertNotEqualObjects(dict1, dict2);

1645
  // 3 is different keys, same values; not equal.
1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661
  XCTAssertNotEqualObjects(dict1, dict3);

  // 4 extra pair; not equal
  XCTAssertNotEqualObjects(dict1, dict4);

  [dict1 release];
  [dict1prime release];
  [dict2 release];
  [dict3 release];
  [dict4 release];
}

- (void)testCopy {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const BOOL kValues[] = { YES, YES, NO, NO };
  GPBUInt32BoolDictionary *dict =
1662 1663 1664
      [[GPBUInt32BoolDictionary alloc] initWithBools:kValues
                                             forKeys:kKeys
                                               count:GPBARRAYSIZE(kValues)];
1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682
  XCTAssertNotNil(dict);

  GPBUInt32BoolDictionary *dict2 = [dict copy];
  XCTAssertNotNil(dict2);

  // Should be new object but equal.
  XCTAssertNotEqual(dict, dict2);
  XCTAssertEqualObjects(dict, dict2);
  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32BoolDictionary class]]);

  [dict2 release];
  [dict release];
}

- (void)testDictionaryFromDictionary {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const BOOL kValues[] = { YES, YES, NO, NO };
  GPBUInt32BoolDictionary *dict =
1683 1684 1685
      [[GPBUInt32BoolDictionary alloc] initWithBools:kValues
                                             forKeys:kKeys
                                               count:GPBARRAYSIZE(kValues)];
1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702
  XCTAssertNotNil(dict);

  GPBUInt32BoolDictionary *dict2 =
      [GPBUInt32BoolDictionary dictionaryWithDictionary:dict];
  XCTAssertNotNil(dict2);

  // Should be new pointer, but equal objects.
  XCTAssertNotEqual(dict, dict2);
  XCTAssertEqualObjects(dict, dict2);
  [dict release];
}

- (void)testAdds {
  GPBUInt32BoolDictionary *dict = [GPBUInt32BoolDictionary dictionary];
  XCTAssertNotNil(dict);

  XCTAssertEqual(dict.count, 0U);
1703
  [dict setBool:YES forKey:1U];
1704 1705 1706 1707 1708
  XCTAssertEqual(dict.count, 1U);

  const uint32_t kKeys[] = { 2U, 3U, 4U };
  const BOOL kValues[] = { YES, NO, NO };
  GPBUInt32BoolDictionary *dict2 =
1709 1710 1711
      [[GPBUInt32BoolDictionary alloc] initWithBools:kValues
                                             forKeys:kKeys
                                               count:GPBARRAYSIZE(kValues)];
1712 1713 1714 1715 1716
  XCTAssertNotNil(dict2);
  [dict addEntriesFromDictionary:dict2];
  XCTAssertEqual(dict.count, 4U);

  BOOL value;
1717 1718
  XCTAssertTrue([dict getBool:NULL forKey:1U]);
  XCTAssertTrue([dict getBool:&value forKey:1U]);
1719
  XCTAssertEqual(value, YES);
1720 1721
  XCTAssertTrue([dict getBool:NULL forKey:2U]);
  XCTAssertTrue([dict getBool:&value forKey:2U]);
1722
  XCTAssertEqual(value, YES);
1723 1724
  XCTAssertTrue([dict getBool:NULL forKey:3U]);
  XCTAssertTrue([dict getBool:&value forKey:3U]);
1725
  XCTAssertEqual(value, NO);
1726 1727
  XCTAssertTrue([dict getBool:NULL forKey:4U]);
  XCTAssertTrue([dict getBool:&value forKey:4U]);
1728 1729 1730 1731 1732 1733 1734 1735
  XCTAssertEqual(value, NO);
  [dict2 release];
}

- (void)testRemove {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const BOOL kValues[] = { YES, YES, NO, NO };
  GPBUInt32BoolDictionary *dict =
1736 1737 1738
      [[GPBUInt32BoolDictionary alloc] initWithBools:kValues
                                             forKeys:kKeys
                                               count:GPBARRAYSIZE(kValues)];
1739 1740 1741
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 4U);

1742
  [dict removeBoolForKey:2U];
1743 1744
  XCTAssertEqual(dict.count, 3U);
  BOOL value;
1745 1746
  XCTAssertTrue([dict getBool:NULL forKey:1U]);
  XCTAssertTrue([dict getBool:&value forKey:1U]);
1747
  XCTAssertEqual(value, YES);
1748 1749 1750
  XCTAssertFalse([dict getBool:NULL forKey:2U]);
  XCTAssertTrue([dict getBool:NULL forKey:3U]);
  XCTAssertTrue([dict getBool:&value forKey:3U]);
1751
  XCTAssertEqual(value, NO);
1752 1753
  XCTAssertTrue([dict getBool:NULL forKey:4U]);
  XCTAssertTrue([dict getBool:&value forKey:4U]);
1754 1755 1756
  XCTAssertEqual(value, NO);

  // Remove again does nothing.
1757
  [dict removeBoolForKey:2U];
1758
  XCTAssertEqual(dict.count, 3U);
1759 1760
  XCTAssertTrue([dict getBool:NULL forKey:1U]);
  XCTAssertTrue([dict getBool:&value forKey:1U]);
1761
  XCTAssertEqual(value, YES);
1762 1763 1764
  XCTAssertFalse([dict getBool:NULL forKey:2U]);
  XCTAssertTrue([dict getBool:NULL forKey:3U]);
  XCTAssertTrue([dict getBool:&value forKey:3U]);
1765
  XCTAssertEqual(value, NO);
1766 1767
  XCTAssertTrue([dict getBool:NULL forKey:4U]);
  XCTAssertTrue([dict getBool:&value forKey:4U]);
1768 1769
  XCTAssertEqual(value, NO);

1770
  [dict removeBoolForKey:4U];
1771
  XCTAssertEqual(dict.count, 2U);
1772 1773
  XCTAssertTrue([dict getBool:NULL forKey:1U]);
  XCTAssertTrue([dict getBool:&value forKey:1U]);
1774
  XCTAssertEqual(value, YES);
1775 1776 1777
  XCTAssertFalse([dict getBool:NULL forKey:2U]);
  XCTAssertTrue([dict getBool:NULL forKey:3U]);
  XCTAssertTrue([dict getBool:&value forKey:3U]);
1778
  XCTAssertEqual(value, NO);
1779
  XCTAssertFalse([dict getBool:NULL forKey:4U]);
1780 1781 1782

  [dict removeAll];
  XCTAssertEqual(dict.count, 0U);
1783 1784 1785 1786
  XCTAssertFalse([dict getBool:NULL forKey:1U]);
  XCTAssertFalse([dict getBool:NULL forKey:2U]);
  XCTAssertFalse([dict getBool:NULL forKey:3U]);
  XCTAssertFalse([dict getBool:NULL forKey:4U]);
1787 1788 1789 1790 1791 1792 1793
  [dict release];
}

- (void)testInplaceMutation {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const BOOL kValues[] = { YES, YES, NO, NO };
  GPBUInt32BoolDictionary *dict =
1794 1795 1796
      [[GPBUInt32BoolDictionary alloc] initWithBools:kValues
                                             forKeys:kKeys
                                               count:GPBARRAYSIZE(kValues)];
1797 1798 1799
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 4U);
  BOOL value;
1800 1801
  XCTAssertTrue([dict getBool:NULL forKey:1U]);
  XCTAssertTrue([dict getBool:&value forKey:1U]);
1802
  XCTAssertEqual(value, YES);
1803 1804
  XCTAssertTrue([dict getBool:NULL forKey:2U]);
  XCTAssertTrue([dict getBool:&value forKey:2U]);
1805
  XCTAssertEqual(value, YES);
1806 1807
  XCTAssertTrue([dict getBool:NULL forKey:3U]);
  XCTAssertTrue([dict getBool:&value forKey:3U]);
1808
  XCTAssertEqual(value, NO);
1809 1810
  XCTAssertTrue([dict getBool:NULL forKey:4U]);
  XCTAssertTrue([dict getBool:&value forKey:4U]);
1811 1812
  XCTAssertEqual(value, NO);

1813
  [dict setBool:NO forKey:1U];
1814
  XCTAssertEqual(dict.count, 4U);
1815 1816
  XCTAssertTrue([dict getBool:NULL forKey:1U]);
  XCTAssertTrue([dict getBool:&value forKey:1U]);
1817
  XCTAssertEqual(value, NO);
1818 1819
  XCTAssertTrue([dict getBool:NULL forKey:2U]);
  XCTAssertTrue([dict getBool:&value forKey:2U]);
1820
  XCTAssertEqual(value, YES);
1821 1822
  XCTAssertTrue([dict getBool:NULL forKey:3U]);
  XCTAssertTrue([dict getBool:&value forKey:3U]);
1823
  XCTAssertEqual(value, NO);
1824 1825
  XCTAssertTrue([dict getBool:NULL forKey:4U]);
  XCTAssertTrue([dict getBool:&value forKey:4U]);
1826 1827
  XCTAssertEqual(value, NO);

1828
  [dict setBool:YES forKey:4U];
1829
  XCTAssertEqual(dict.count, 4U);
1830 1831
  XCTAssertTrue([dict getBool:NULL forKey:1U]);
  XCTAssertTrue([dict getBool:&value forKey:1U]);
1832
  XCTAssertEqual(value, NO);
1833 1834
  XCTAssertTrue([dict getBool:NULL forKey:2U]);
  XCTAssertTrue([dict getBool:&value forKey:2U]);
1835
  XCTAssertEqual(value, YES);
1836 1837
  XCTAssertTrue([dict getBool:NULL forKey:3U]);
  XCTAssertTrue([dict getBool:&value forKey:3U]);
1838
  XCTAssertEqual(value, NO);
1839 1840
  XCTAssertTrue([dict getBool:NULL forKey:4U]);
  XCTAssertTrue([dict getBool:&value forKey:4U]);
1841 1842 1843 1844 1845
  XCTAssertEqual(value, YES);

  const uint32_t kKeys2[] = { 2U, 3U };
  const BOOL kValues2[] = { NO, YES };
  GPBUInt32BoolDictionary *dict2 =
1846 1847 1848
      [[GPBUInt32BoolDictionary alloc] initWithBools:kValues2
                                             forKeys:kKeys2
                                               count:GPBARRAYSIZE(kValues2)];
1849 1850 1851
  XCTAssertNotNil(dict2);
  [dict addEntriesFromDictionary:dict2];
  XCTAssertEqual(dict.count, 4U);
1852 1853
  XCTAssertTrue([dict getBool:NULL forKey:1U]);
  XCTAssertTrue([dict getBool:&value forKey:1U]);
1854
  XCTAssertEqual(value, NO);
1855 1856
  XCTAssertTrue([dict getBool:NULL forKey:2U]);
  XCTAssertTrue([dict getBool:&value forKey:2U]);
1857
  XCTAssertEqual(value, NO);
1858 1859
  XCTAssertTrue([dict getBool:NULL forKey:3U]);
  XCTAssertTrue([dict getBool:&value forKey:3U]);
1860
  XCTAssertEqual(value, YES);
1861 1862
  XCTAssertTrue([dict getBool:NULL forKey:4U]);
  XCTAssertTrue([dict getBool:&value forKey:4U]);
1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881
  XCTAssertEqual(value, YES);

  [dict2 release];
  [dict release];
}

@end

#pragma mark - UInt32 -> Float

@interface GPBUInt32FloatDictionaryTests : XCTestCase
@end

@implementation GPBUInt32FloatDictionaryTests

- (void)testEmpty {
  GPBUInt32FloatDictionary *dict = [[GPBUInt32FloatDictionary alloc] init];
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 0U);
1882 1883
  XCTAssertFalse([dict getFloat:NULL forKey:1U]);
  [dict enumerateKeysAndFloatsUsingBlock:^(uint32_t aKey, float aValue, BOOL *stop) {
1884 1885 1886 1887 1888 1889 1890
    #pragma unused(aKey, aValue, stop)
    XCTFail(@"Shouldn't get here!");
  }];
  [dict release];
}

- (void)testOne {
1891
  GPBUInt32FloatDictionary *dict = [GPBUInt32FloatDictionary dictionaryWithFloat:500.f forKey:1U];
1892 1893 1894
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 1U);
  float value;
1895 1896
  XCTAssertTrue([dict getFloat:NULL forKey:1U]);
  XCTAssertTrue([dict getFloat:&value forKey:1U]);
1897
  XCTAssertEqual(value, 500.f);
1898 1899
  XCTAssertFalse([dict getFloat:NULL forKey:2U]);
  [dict enumerateKeysAndFloatsUsingBlock:^(uint32_t aKey, float aValue, BOOL *stop) {
1900 1901 1902 1903 1904 1905 1906 1907 1908 1909
    XCTAssertEqual(aKey, 1U);
    XCTAssertEqual(aValue, 500.f);
    XCTAssertNotEqual(stop, NULL);
  }];
}

- (void)testBasics {
  const uint32_t kKeys[] = { 1U, 2U, 3U };
  const float kValues[] = { 500.f, 501.f, 502.f };
  GPBUInt32FloatDictionary *dict =
1910
      [[GPBUInt32FloatDictionary alloc] initWithFloats:kValues
1911 1912 1913 1914 1915
                                               forKeys:kKeys
                                                 count:GPBARRAYSIZE(kValues)];
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 3U);
  float value;
1916 1917
  XCTAssertTrue([dict getFloat:NULL forKey:1U]);
  XCTAssertTrue([dict getFloat:&value forKey:1U]);
1918
  XCTAssertEqual(value, 500.f);
1919 1920
  XCTAssertTrue([dict getFloat:NULL forKey:2U]);
  XCTAssertTrue([dict getFloat:&value forKey:2U]);
1921
  XCTAssertEqual(value, 501.f);
1922 1923
  XCTAssertTrue([dict getFloat:NULL forKey:3U]);
  XCTAssertTrue([dict getFloat:&value forKey:3U]);
1924
  XCTAssertEqual(value, 502.f);
1925
  XCTAssertFalse([dict getFloat:NULL forKey:4U]);
1926 1927 1928 1929

  __block NSUInteger idx = 0;
  uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
  float *seenValues = malloc(3 * sizeof(float));
1930
  [dict enumerateKeysAndFloatsUsingBlock:^(uint32_t aKey, float aValue, BOOL *stop) {
1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951
    XCTAssertLessThan(idx, 3U);
    seenKeys[idx] = aKey;
    seenValues[idx] = aValue;
    XCTAssertNotEqual(stop, NULL);
    ++idx;
  }];
  for (int i = 0; i < 3; ++i) {
    BOOL foundKey = NO;
    for (int j = 0; (j < 3) && !foundKey; ++j) {
      if (kKeys[i] == seenKeys[j]) {
        foundKey = YES;
        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
      }
    }
    XCTAssertTrue(foundKey, @"i = %d", i);
  }
  free(seenKeys);
  free(seenValues);

  // Stopping the enumeration.
  idx = 0;
1952
  [dict enumerateKeysAndFloatsUsingBlock:^(uint32_t aKey, float aValue, BOOL *stop) {
1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967
    #pragma unused(aKey, aValue)
    if (idx == 1) *stop = YES;
    XCTAssertNotEqual(idx, 2U);
    ++idx;
  }];
  [dict release];
}

- (void)testEquality {
  const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
  const uint32_t kKeys2[] = { 2U, 1U, 4U };
  const float kValues1[] = { 500.f, 501.f, 502.f };
  const float kValues2[] = { 500.f, 503.f, 502.f };
  const float kValues3[] = { 500.f, 501.f, 502.f, 503.f };
  GPBUInt32FloatDictionary *dict1 =
1968
      [[GPBUInt32FloatDictionary alloc] initWithFloats:kValues1
1969 1970 1971 1972
                                               forKeys:kKeys1
                                                 count:GPBARRAYSIZE(kValues1)];
  XCTAssertNotNil(dict1);
  GPBUInt32FloatDictionary *dict1prime =
1973
      [[GPBUInt32FloatDictionary alloc] initWithFloats:kValues1
1974 1975 1976 1977
                                               forKeys:kKeys1
                                                 count:GPBARRAYSIZE(kValues1)];
  XCTAssertNotNil(dict1prime);
  GPBUInt32FloatDictionary *dict2 =
1978
      [[GPBUInt32FloatDictionary alloc] initWithFloats:kValues2
1979 1980 1981 1982
                                               forKeys:kKeys1
                                                 count:GPBARRAYSIZE(kValues2)];
  XCTAssertNotNil(dict2);
  GPBUInt32FloatDictionary *dict3 =
1983
      [[GPBUInt32FloatDictionary alloc] initWithFloats:kValues1
1984 1985 1986 1987
                                               forKeys:kKeys2
                                                 count:GPBARRAYSIZE(kValues1)];
  XCTAssertNotNil(dict3);
  GPBUInt32FloatDictionary *dict4 =
1988
      [[GPBUInt32FloatDictionary alloc] initWithFloats:kValues3
1989 1990 1991 1992 1993 1994 1995 1996 1997 1998
                                               forKeys:kKeys1
                                                 count:GPBARRAYSIZE(kValues3)];
  XCTAssertNotNil(dict4);

  // 1/1Prime should be different objects, but equal.
  XCTAssertNotEqual(dict1, dict1prime);
  XCTAssertEqualObjects(dict1, dict1prime);
  // Equal, so they must have same hash.
  XCTAssertEqual([dict1 hash], [dict1prime hash]);

1999
  // 2 is same keys, different values; not equal.
2000 2001
  XCTAssertNotEqualObjects(dict1, dict2);

2002
  // 3 is different keys, same values; not equal.
2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018
  XCTAssertNotEqualObjects(dict1, dict3);

  // 4 extra pair; not equal
  XCTAssertNotEqualObjects(dict1, dict4);

  [dict1 release];
  [dict1prime release];
  [dict2 release];
  [dict3 release];
  [dict4 release];
}

- (void)testCopy {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
  GPBUInt32FloatDictionary *dict =
2019
      [[GPBUInt32FloatDictionary alloc] initWithFloats:kValues
2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039
                                               forKeys:kKeys
                                                 count:GPBARRAYSIZE(kValues)];
  XCTAssertNotNil(dict);

  GPBUInt32FloatDictionary *dict2 = [dict copy];
  XCTAssertNotNil(dict2);

  // Should be new object but equal.
  XCTAssertNotEqual(dict, dict2);
  XCTAssertEqualObjects(dict, dict2);
  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32FloatDictionary class]]);

  [dict2 release];
  [dict release];
}

- (void)testDictionaryFromDictionary {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
  GPBUInt32FloatDictionary *dict =
2040
      [[GPBUInt32FloatDictionary alloc] initWithFloats:kValues
2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059
                                               forKeys:kKeys
                                                 count:GPBARRAYSIZE(kValues)];
  XCTAssertNotNil(dict);

  GPBUInt32FloatDictionary *dict2 =
      [GPBUInt32FloatDictionary dictionaryWithDictionary:dict];
  XCTAssertNotNil(dict2);

  // Should be new pointer, but equal objects.
  XCTAssertNotEqual(dict, dict2);
  XCTAssertEqualObjects(dict, dict2);
  [dict release];
}

- (void)testAdds {
  GPBUInt32FloatDictionary *dict = [GPBUInt32FloatDictionary dictionary];
  XCTAssertNotNil(dict);

  XCTAssertEqual(dict.count, 0U);
2060
  [dict setFloat:500.f forKey:1U];
2061 2062 2063 2064 2065
  XCTAssertEqual(dict.count, 1U);

  const uint32_t kKeys[] = { 2U, 3U, 4U };
  const float kValues[] = { 501.f, 502.f, 503.f };
  GPBUInt32FloatDictionary *dict2 =
2066
      [[GPBUInt32FloatDictionary alloc] initWithFloats:kValues
2067 2068 2069 2070 2071 2072 2073
                                               forKeys:kKeys
                                                 count:GPBARRAYSIZE(kValues)];
  XCTAssertNotNil(dict2);
  [dict addEntriesFromDictionary:dict2];
  XCTAssertEqual(dict.count, 4U);

  float value;
2074 2075
  XCTAssertTrue([dict getFloat:NULL forKey:1U]);
  XCTAssertTrue([dict getFloat:&value forKey:1U]);
2076
  XCTAssertEqual(value, 500.f);
2077 2078
  XCTAssertTrue([dict getFloat:NULL forKey:2U]);
  XCTAssertTrue([dict getFloat:&value forKey:2U]);
2079
  XCTAssertEqual(value, 501.f);
2080 2081
  XCTAssertTrue([dict getFloat:NULL forKey:3U]);
  XCTAssertTrue([dict getFloat:&value forKey:3U]);
2082
  XCTAssertEqual(value, 502.f);
2083 2084
  XCTAssertTrue([dict getFloat:NULL forKey:4U]);
  XCTAssertTrue([dict getFloat:&value forKey:4U]);
2085 2086 2087 2088 2089 2090 2091 2092
  XCTAssertEqual(value, 503.f);
  [dict2 release];
}

- (void)testRemove {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
  GPBUInt32FloatDictionary *dict =
2093 2094 2095
      [[GPBUInt32FloatDictionary alloc] initWithFloats:kValues
                                               forKeys:kKeys
                                                 count:GPBARRAYSIZE(kValues)];
2096 2097 2098
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 4U);

2099
  [dict removeFloatForKey:2U];
2100 2101
  XCTAssertEqual(dict.count, 3U);
  float value;
2102 2103
  XCTAssertTrue([dict getFloat:NULL forKey:1U]);
  XCTAssertTrue([dict getFloat:&value forKey:1U]);
2104
  XCTAssertEqual(value, 500.f);
2105 2106 2107
  XCTAssertFalse([dict getFloat:NULL forKey:2U]);
  XCTAssertTrue([dict getFloat:NULL forKey:3U]);
  XCTAssertTrue([dict getFloat:&value forKey:3U]);
2108
  XCTAssertEqual(value, 502.f);
2109 2110
  XCTAssertTrue([dict getFloat:NULL forKey:4U]);
  XCTAssertTrue([dict getFloat:&value forKey:4U]);
2111 2112 2113
  XCTAssertEqual(value, 503.f);

  // Remove again does nothing.
2114
  [dict removeFloatForKey:2U];
2115
  XCTAssertEqual(dict.count, 3U);
2116 2117
  XCTAssertTrue([dict getFloat:NULL forKey:1U]);
  XCTAssertTrue([dict getFloat:&value forKey:1U]);
2118
  XCTAssertEqual(value, 500.f);
2119 2120 2121
  XCTAssertFalse([dict getFloat:NULL forKey:2U]);
  XCTAssertTrue([dict getFloat:NULL forKey:3U]);
  XCTAssertTrue([dict getFloat:&value forKey:3U]);
2122
  XCTAssertEqual(value, 502.f);
2123 2124
  XCTAssertTrue([dict getFloat:NULL forKey:4U]);
  XCTAssertTrue([dict getFloat:&value forKey:4U]);
2125 2126
  XCTAssertEqual(value, 503.f);

2127
  [dict removeFloatForKey:4U];
2128
  XCTAssertEqual(dict.count, 2U);
2129 2130
  XCTAssertTrue([dict getFloat:NULL forKey:1U]);
  XCTAssertTrue([dict getFloat:&value forKey:1U]);
2131
  XCTAssertEqual(value, 500.f);
2132 2133 2134
  XCTAssertFalse([dict getFloat:NULL forKey:2U]);
  XCTAssertTrue([dict getFloat:NULL forKey:3U]);
  XCTAssertTrue([dict getFloat:&value forKey:3U]);
2135
  XCTAssertEqual(value, 502.f);
2136
  XCTAssertFalse([dict getFloat:NULL forKey:4U]);
2137 2138 2139

  [dict removeAll];
  XCTAssertEqual(dict.count, 0U);
2140 2141 2142 2143
  XCTAssertFalse([dict getFloat:NULL forKey:1U]);
  XCTAssertFalse([dict getFloat:NULL forKey:2U]);
  XCTAssertFalse([dict getFloat:NULL forKey:3U]);
  XCTAssertFalse([dict getFloat:NULL forKey:4U]);
2144 2145 2146 2147 2148 2149 2150
  [dict release];
}

- (void)testInplaceMutation {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
  GPBUInt32FloatDictionary *dict =
2151 2152 2153
      [[GPBUInt32FloatDictionary alloc] initWithFloats:kValues
                                               forKeys:kKeys
                                                 count:GPBARRAYSIZE(kValues)];
2154 2155 2156
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 4U);
  float value;
2157 2158
  XCTAssertTrue([dict getFloat:NULL forKey:1U]);
  XCTAssertTrue([dict getFloat:&value forKey:1U]);
2159
  XCTAssertEqual(value, 500.f);
2160 2161
  XCTAssertTrue([dict getFloat:NULL forKey:2U]);
  XCTAssertTrue([dict getFloat:&value forKey:2U]);
2162
  XCTAssertEqual(value, 501.f);
2163 2164
  XCTAssertTrue([dict getFloat:NULL forKey:3U]);
  XCTAssertTrue([dict getFloat:&value forKey:3U]);
2165
  XCTAssertEqual(value, 502.f);
2166 2167
  XCTAssertTrue([dict getFloat:NULL forKey:4U]);
  XCTAssertTrue([dict getFloat:&value forKey:4U]);
2168 2169
  XCTAssertEqual(value, 503.f);

2170
  [dict setFloat:503.f forKey:1U];
2171
  XCTAssertEqual(dict.count, 4U);
2172 2173
  XCTAssertTrue([dict getFloat:NULL forKey:1U]);
  XCTAssertTrue([dict getFloat:&value forKey:1U]);
2174
  XCTAssertEqual(value, 503.f);
2175 2176
  XCTAssertTrue([dict getFloat:NULL forKey:2U]);
  XCTAssertTrue([dict getFloat:&value forKey:2U]);
2177
  XCTAssertEqual(value, 501.f);
2178 2179
  XCTAssertTrue([dict getFloat:NULL forKey:3U]);
  XCTAssertTrue([dict getFloat:&value forKey:3U]);
2180
  XCTAssertEqual(value, 502.f);
2181 2182
  XCTAssertTrue([dict getFloat:NULL forKey:4U]);
  XCTAssertTrue([dict getFloat:&value forKey:4U]);
2183 2184
  XCTAssertEqual(value, 503.f);

2185
  [dict setFloat:501.f forKey:4U];
2186
  XCTAssertEqual(dict.count, 4U);
2187 2188
  XCTAssertTrue([dict getFloat:NULL forKey:1U]);
  XCTAssertTrue([dict getFloat:&value forKey:1U]);
2189
  XCTAssertEqual(value, 503.f);
2190 2191
  XCTAssertTrue([dict getFloat:NULL forKey:2U]);
  XCTAssertTrue([dict getFloat:&value forKey:2U]);
2192
  XCTAssertEqual(value, 501.f);
2193 2194
  XCTAssertTrue([dict getFloat:NULL forKey:3U]);
  XCTAssertTrue([dict getFloat:&value forKey:3U]);
2195
  XCTAssertEqual(value, 502.f);
2196 2197
  XCTAssertTrue([dict getFloat:NULL forKey:4U]);
  XCTAssertTrue([dict getFloat:&value forKey:4U]);
2198 2199 2200 2201 2202
  XCTAssertEqual(value, 501.f);

  const uint32_t kKeys2[] = { 2U, 3U };
  const float kValues2[] = { 502.f, 500.f };
  GPBUInt32FloatDictionary *dict2 =
2203
      [[GPBUInt32FloatDictionary alloc] initWithFloats:kValues2
2204 2205 2206 2207 2208
                                               forKeys:kKeys2
                                                 count:GPBARRAYSIZE(kValues2)];
  XCTAssertNotNil(dict2);
  [dict addEntriesFromDictionary:dict2];
  XCTAssertEqual(dict.count, 4U);
2209 2210
  XCTAssertTrue([dict getFloat:NULL forKey:1U]);
  XCTAssertTrue([dict getFloat:&value forKey:1U]);
2211
  XCTAssertEqual(value, 503.f);
2212 2213
  XCTAssertTrue([dict getFloat:NULL forKey:2U]);
  XCTAssertTrue([dict getFloat:&value forKey:2U]);
2214
  XCTAssertEqual(value, 502.f);
2215 2216
  XCTAssertTrue([dict getFloat:NULL forKey:3U]);
  XCTAssertTrue([dict getFloat:&value forKey:3U]);
2217
  XCTAssertEqual(value, 500.f);
2218 2219
  XCTAssertTrue([dict getFloat:NULL forKey:4U]);
  XCTAssertTrue([dict getFloat:&value forKey:4U]);
2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238
  XCTAssertEqual(value, 501.f);

  [dict2 release];
  [dict release];
}

@end

#pragma mark - UInt32 -> Double

@interface GPBUInt32DoubleDictionaryTests : XCTestCase
@end

@implementation GPBUInt32DoubleDictionaryTests

- (void)testEmpty {
  GPBUInt32DoubleDictionary *dict = [[GPBUInt32DoubleDictionary alloc] init];
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 0U);
2239 2240
  XCTAssertFalse([dict getDouble:NULL forKey:1U]);
  [dict enumerateKeysAndDoublesUsingBlock:^(uint32_t aKey, double aValue, BOOL *stop) {
2241 2242 2243 2244 2245 2246 2247
    #pragma unused(aKey, aValue, stop)
    XCTFail(@"Shouldn't get here!");
  }];
  [dict release];
}

- (void)testOne {
2248
  GPBUInt32DoubleDictionary *dict = [GPBUInt32DoubleDictionary dictionaryWithDouble:600. forKey:1U];
2249 2250 2251
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 1U);
  double value;
2252 2253
  XCTAssertTrue([dict getDouble:NULL forKey:1U]);
  XCTAssertTrue([dict getDouble:&value forKey:1U]);
2254
  XCTAssertEqual(value, 600.);
2255 2256
  XCTAssertFalse([dict getDouble:NULL forKey:2U]);
  [dict enumerateKeysAndDoublesUsingBlock:^(uint32_t aKey, double aValue, BOOL *stop) {
2257 2258 2259 2260 2261 2262 2263 2264 2265 2266
    XCTAssertEqual(aKey, 1U);
    XCTAssertEqual(aValue, 600.);
    XCTAssertNotEqual(stop, NULL);
  }];
}

- (void)testBasics {
  const uint32_t kKeys[] = { 1U, 2U, 3U };
  const double kValues[] = { 600., 601., 602. };
  GPBUInt32DoubleDictionary *dict =
2267 2268 2269
      [[GPBUInt32DoubleDictionary alloc] initWithDoubles:kValues
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kValues)];
2270 2271 2272
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 3U);
  double value;
2273 2274
  XCTAssertTrue([dict getDouble:NULL forKey:1U]);
  XCTAssertTrue([dict getDouble:&value forKey:1U]);
2275
  XCTAssertEqual(value, 600.);
2276 2277
  XCTAssertTrue([dict getDouble:NULL forKey:2U]);
  XCTAssertTrue([dict getDouble:&value forKey:2U]);
2278
  XCTAssertEqual(value, 601.);
2279 2280
  XCTAssertTrue([dict getDouble:NULL forKey:3U]);
  XCTAssertTrue([dict getDouble:&value forKey:3U]);
2281
  XCTAssertEqual(value, 602.);
2282
  XCTAssertFalse([dict getDouble:NULL forKey:4U]);
2283 2284 2285 2286

  __block NSUInteger idx = 0;
  uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
  double *seenValues = malloc(3 * sizeof(double));
2287
  [dict enumerateKeysAndDoublesUsingBlock:^(uint32_t aKey, double aValue, BOOL *stop) {
2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308
    XCTAssertLessThan(idx, 3U);
    seenKeys[idx] = aKey;
    seenValues[idx] = aValue;
    XCTAssertNotEqual(stop, NULL);
    ++idx;
  }];
  for (int i = 0; i < 3; ++i) {
    BOOL foundKey = NO;
    for (int j = 0; (j < 3) && !foundKey; ++j) {
      if (kKeys[i] == seenKeys[j]) {
        foundKey = YES;
        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
      }
    }
    XCTAssertTrue(foundKey, @"i = %d", i);
  }
  free(seenKeys);
  free(seenValues);

  // Stopping the enumeration.
  idx = 0;
2309
  [dict enumerateKeysAndDoublesUsingBlock:^(uint32_t aKey, double aValue, BOOL *stop) {
2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324
    #pragma unused(aKey, aValue)
    if (idx == 1) *stop = YES;
    XCTAssertNotEqual(idx, 2U);
    ++idx;
  }];
  [dict release];
}

- (void)testEquality {
  const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
  const uint32_t kKeys2[] = { 2U, 1U, 4U };
  const double kValues1[] = { 600., 601., 602. };
  const double kValues2[] = { 600., 603., 602. };
  const double kValues3[] = { 600., 601., 602., 603. };
  GPBUInt32DoubleDictionary *dict1 =
2325 2326 2327
      [[GPBUInt32DoubleDictionary alloc] initWithDoubles:kValues1
                                                 forKeys:kKeys1
                                                   count:GPBARRAYSIZE(kValues1)];
2328 2329
  XCTAssertNotNil(dict1);
  GPBUInt32DoubleDictionary *dict1prime =
2330 2331 2332
      [[GPBUInt32DoubleDictionary alloc] initWithDoubles:kValues1
                                                 forKeys:kKeys1
                                                   count:GPBARRAYSIZE(kValues1)];
2333 2334
  XCTAssertNotNil(dict1prime);
  GPBUInt32DoubleDictionary *dict2 =
2335 2336 2337
      [[GPBUInt32DoubleDictionary alloc] initWithDoubles:kValues2
                                                 forKeys:kKeys1
                                                   count:GPBARRAYSIZE(kValues2)];
2338 2339
  XCTAssertNotNil(dict2);
  GPBUInt32DoubleDictionary *dict3 =
2340 2341 2342
      [[GPBUInt32DoubleDictionary alloc] initWithDoubles:kValues1
                                                 forKeys:kKeys2
                                                   count:GPBARRAYSIZE(kValues1)];
2343 2344
  XCTAssertNotNil(dict3);
  GPBUInt32DoubleDictionary *dict4 =
2345 2346 2347
      [[GPBUInt32DoubleDictionary alloc] initWithDoubles:kValues3
                                                 forKeys:kKeys1
                                                   count:GPBARRAYSIZE(kValues3)];
2348 2349 2350 2351 2352 2353 2354 2355
  XCTAssertNotNil(dict4);

  // 1/1Prime should be different objects, but equal.
  XCTAssertNotEqual(dict1, dict1prime);
  XCTAssertEqualObjects(dict1, dict1prime);
  // Equal, so they must have same hash.
  XCTAssertEqual([dict1 hash], [dict1prime hash]);

2356
  // 2 is same keys, different values; not equal.
2357 2358
  XCTAssertNotEqualObjects(dict1, dict2);

2359
  // 3 is different keys, same values; not equal.
2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375
  XCTAssertNotEqualObjects(dict1, dict3);

  // 4 extra pair; not equal
  XCTAssertNotEqualObjects(dict1, dict4);

  [dict1 release];
  [dict1prime release];
  [dict2 release];
  [dict3 release];
  [dict4 release];
}

- (void)testCopy {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const double kValues[] = { 600., 601., 602., 603. };
  GPBUInt32DoubleDictionary *dict =
2376 2377 2378
      [[GPBUInt32DoubleDictionary alloc] initWithDoubles:kValues
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kValues)];
2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396
  XCTAssertNotNil(dict);

  GPBUInt32DoubleDictionary *dict2 = [dict copy];
  XCTAssertNotNil(dict2);

  // Should be new object but equal.
  XCTAssertNotEqual(dict, dict2);
  XCTAssertEqualObjects(dict, dict2);
  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32DoubleDictionary class]]);

  [dict2 release];
  [dict release];
}

- (void)testDictionaryFromDictionary {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const double kValues[] = { 600., 601., 602., 603. };
  GPBUInt32DoubleDictionary *dict =
2397 2398 2399
      [[GPBUInt32DoubleDictionary alloc] initWithDoubles:kValues
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kValues)];
2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416
  XCTAssertNotNil(dict);

  GPBUInt32DoubleDictionary *dict2 =
      [GPBUInt32DoubleDictionary dictionaryWithDictionary:dict];
  XCTAssertNotNil(dict2);

  // Should be new pointer, but equal objects.
  XCTAssertNotEqual(dict, dict2);
  XCTAssertEqualObjects(dict, dict2);
  [dict release];
}

- (void)testAdds {
  GPBUInt32DoubleDictionary *dict = [GPBUInt32DoubleDictionary dictionary];
  XCTAssertNotNil(dict);

  XCTAssertEqual(dict.count, 0U);
2417
  [dict setDouble:600. forKey:1U];
2418 2419 2420 2421 2422
  XCTAssertEqual(dict.count, 1U);

  const uint32_t kKeys[] = { 2U, 3U, 4U };
  const double kValues[] = { 601., 602., 603. };
  GPBUInt32DoubleDictionary *dict2 =
2423 2424 2425
      [[GPBUInt32DoubleDictionary alloc] initWithDoubles:kValues
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kValues)];
2426 2427 2428 2429 2430
  XCTAssertNotNil(dict2);
  [dict addEntriesFromDictionary:dict2];
  XCTAssertEqual(dict.count, 4U);

  double value;
2431 2432
  XCTAssertTrue([dict getDouble:NULL forKey:1U]);
  XCTAssertTrue([dict getDouble:&value forKey:1U]);
2433
  XCTAssertEqual(value, 600.);
2434 2435
  XCTAssertTrue([dict getDouble:NULL forKey:2U]);
  XCTAssertTrue([dict getDouble:&value forKey:2U]);
2436
  XCTAssertEqual(value, 601.);
2437 2438
  XCTAssertTrue([dict getDouble:NULL forKey:3U]);
  XCTAssertTrue([dict getDouble:&value forKey:3U]);
2439
  XCTAssertEqual(value, 602.);
2440 2441
  XCTAssertTrue([dict getDouble:NULL forKey:4U]);
  XCTAssertTrue([dict getDouble:&value forKey:4U]);
2442 2443 2444 2445 2446 2447 2448 2449
  XCTAssertEqual(value, 603.);
  [dict2 release];
}

- (void)testRemove {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const double kValues[] = { 600., 601., 602., 603. };
  GPBUInt32DoubleDictionary *dict =
2450 2451 2452
      [[GPBUInt32DoubleDictionary alloc] initWithDoubles:kValues
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kValues)];
2453 2454 2455
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 4U);

2456
  [dict removeDoubleForKey:2U];
2457 2458
  XCTAssertEqual(dict.count, 3U);
  double value;
2459 2460
  XCTAssertTrue([dict getDouble:NULL forKey:1U]);
  XCTAssertTrue([dict getDouble:&value forKey:1U]);
2461
  XCTAssertEqual(value, 600.);
2462 2463 2464
  XCTAssertFalse([dict getDouble:NULL forKey:2U]);
  XCTAssertTrue([dict getDouble:NULL forKey:3U]);
  XCTAssertTrue([dict getDouble:&value forKey:3U]);
2465
  XCTAssertEqual(value, 602.);
2466 2467
  XCTAssertTrue([dict getDouble:NULL forKey:4U]);
  XCTAssertTrue([dict getDouble:&value forKey:4U]);
2468 2469 2470
  XCTAssertEqual(value, 603.);

  // Remove again does nothing.
2471
  [dict removeDoubleForKey:2U];
2472
  XCTAssertEqual(dict.count, 3U);
2473 2474
  XCTAssertTrue([dict getDouble:NULL forKey:1U]);
  XCTAssertTrue([dict getDouble:&value forKey:1U]);
2475
  XCTAssertEqual(value, 600.);
2476 2477 2478
  XCTAssertFalse([dict getDouble:NULL forKey:2U]);
  XCTAssertTrue([dict getDouble:NULL forKey:3U]);
  XCTAssertTrue([dict getDouble:&value forKey:3U]);
2479
  XCTAssertEqual(value, 602.);
2480 2481
  XCTAssertTrue([dict getDouble:NULL forKey:4U]);
  XCTAssertTrue([dict getDouble:&value forKey:4U]);
2482 2483
  XCTAssertEqual(value, 603.);

2484
  [dict removeDoubleForKey:4U];
2485
  XCTAssertEqual(dict.count, 2U);
2486 2487
  XCTAssertTrue([dict getDouble:NULL forKey:1U]);
  XCTAssertTrue([dict getDouble:&value forKey:1U]);
2488
  XCTAssertEqual(value, 600.);
2489 2490 2491
  XCTAssertFalse([dict getDouble:NULL forKey:2U]);
  XCTAssertTrue([dict getDouble:NULL forKey:3U]);
  XCTAssertTrue([dict getDouble:&value forKey:3U]);
2492
  XCTAssertEqual(value, 602.);
2493
  XCTAssertFalse([dict getDouble:NULL forKey:4U]);
2494 2495 2496

  [dict removeAll];
  XCTAssertEqual(dict.count, 0U);
2497 2498 2499 2500
  XCTAssertFalse([dict getDouble:NULL forKey:1U]);
  XCTAssertFalse([dict getDouble:NULL forKey:2U]);
  XCTAssertFalse([dict getDouble:NULL forKey:3U]);
  XCTAssertFalse([dict getDouble:NULL forKey:4U]);
2501 2502 2503 2504 2505 2506 2507
  [dict release];
}

- (void)testInplaceMutation {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const double kValues[] = { 600., 601., 602., 603. };
  GPBUInt32DoubleDictionary *dict =
2508 2509 2510
      [[GPBUInt32DoubleDictionary alloc] initWithDoubles:kValues
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kValues)];
2511 2512 2513
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 4U);
  double value;
2514 2515
  XCTAssertTrue([dict getDouble:NULL forKey:1U]);
  XCTAssertTrue([dict getDouble:&value forKey:1U]);
2516
  XCTAssertEqual(value, 600.);
2517 2518
  XCTAssertTrue([dict getDouble:NULL forKey:2U]);
  XCTAssertTrue([dict getDouble:&value forKey:2U]);
2519
  XCTAssertEqual(value, 601.);
2520 2521
  XCTAssertTrue([dict getDouble:NULL forKey:3U]);
  XCTAssertTrue([dict getDouble:&value forKey:3U]);
2522
  XCTAssertEqual(value, 602.);
2523 2524
  XCTAssertTrue([dict getDouble:NULL forKey:4U]);
  XCTAssertTrue([dict getDouble:&value forKey:4U]);
2525 2526
  XCTAssertEqual(value, 603.);

2527
  [dict setDouble:603. forKey:1U];
2528
  XCTAssertEqual(dict.count, 4U);
2529 2530
  XCTAssertTrue([dict getDouble:NULL forKey:1U]);
  XCTAssertTrue([dict getDouble:&value forKey:1U]);
2531
  XCTAssertEqual(value, 603.);
2532 2533
  XCTAssertTrue([dict getDouble:NULL forKey:2U]);
  XCTAssertTrue([dict getDouble:&value forKey:2U]);
2534
  XCTAssertEqual(value, 601.);
2535 2536
  XCTAssertTrue([dict getDouble:NULL forKey:3U]);
  XCTAssertTrue([dict getDouble:&value forKey:3U]);
2537
  XCTAssertEqual(value, 602.);
2538 2539
  XCTAssertTrue([dict getDouble:NULL forKey:4U]);
  XCTAssertTrue([dict getDouble:&value forKey:4U]);
2540 2541
  XCTAssertEqual(value, 603.);

2542
  [dict setDouble:601. forKey:4U];
2543
  XCTAssertEqual(dict.count, 4U);
2544 2545
  XCTAssertTrue([dict getDouble:NULL forKey:1U]);
  XCTAssertTrue([dict getDouble:&value forKey:1U]);
2546
  XCTAssertEqual(value, 603.);
2547 2548
  XCTAssertTrue([dict getDouble:NULL forKey:2U]);
  XCTAssertTrue([dict getDouble:&value forKey:2U]);
2549
  XCTAssertEqual(value, 601.);
2550 2551
  XCTAssertTrue([dict getDouble:NULL forKey:3U]);
  XCTAssertTrue([dict getDouble:&value forKey:3U]);
2552
  XCTAssertEqual(value, 602.);
2553 2554
  XCTAssertTrue([dict getDouble:NULL forKey:4U]);
  XCTAssertTrue([dict getDouble:&value forKey:4U]);
2555 2556 2557 2558 2559
  XCTAssertEqual(value, 601.);

  const uint32_t kKeys2[] = { 2U, 3U };
  const double kValues2[] = { 602., 600. };
  GPBUInt32DoubleDictionary *dict2 =
2560 2561 2562
      [[GPBUInt32DoubleDictionary alloc] initWithDoubles:kValues2
                                                 forKeys:kKeys2
                                                   count:GPBARRAYSIZE(kValues2)];
2563 2564 2565
  XCTAssertNotNil(dict2);
  [dict addEntriesFromDictionary:dict2];
  XCTAssertEqual(dict.count, 4U);
2566 2567
  XCTAssertTrue([dict getDouble:NULL forKey:1U]);
  XCTAssertTrue([dict getDouble:&value forKey:1U]);
2568
  XCTAssertEqual(value, 603.);
2569 2570
  XCTAssertTrue([dict getDouble:NULL forKey:2U]);
  XCTAssertTrue([dict getDouble:&value forKey:2U]);
2571
  XCTAssertEqual(value, 602.);
2572 2573
  XCTAssertTrue([dict getDouble:NULL forKey:3U]);
  XCTAssertTrue([dict getDouble:&value forKey:3U]);
2574
  XCTAssertEqual(value, 600.);
2575 2576
  XCTAssertTrue([dict getDouble:NULL forKey:4U]);
  XCTAssertTrue([dict getDouble:&value forKey:4U]);
2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595
  XCTAssertEqual(value, 601.);

  [dict2 release];
  [dict release];
}

@end

#pragma mark - UInt32 -> Enum

@interface GPBUInt32EnumDictionaryTests : XCTestCase
@end

@implementation GPBUInt32EnumDictionaryTests

- (void)testEmpty {
  GPBUInt32EnumDictionary *dict = [[GPBUInt32EnumDictionary alloc] init];
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 0U);
2596 2597
  XCTAssertFalse([dict getEnum:NULL forKey:1U]);
  [dict enumerateKeysAndEnumsUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
2598 2599 2600 2601 2602 2603 2604
    #pragma unused(aKey, aValue, stop)
    XCTFail(@"Shouldn't get here!");
  }];
  [dict release];
}

- (void)testOne {
2605
  GPBUInt32EnumDictionary *dict = [GPBUInt32EnumDictionary dictionaryWithEnum:700 forKey:1U];
2606 2607 2608
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 1U);
  int32_t value;
2609 2610
  XCTAssertTrue([dict getEnum:NULL forKey:1U]);
  XCTAssertTrue([dict getEnum:&value forKey:1U]);
2611
  XCTAssertEqual(value, 700);
2612 2613
  XCTAssertFalse([dict getEnum:NULL forKey:2U]);
  [dict enumerateKeysAndEnumsUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
2614 2615 2616 2617 2618 2619 2620 2621 2622 2623
    XCTAssertEqual(aKey, 1U);
    XCTAssertEqual(aValue, 700);
    XCTAssertNotEqual(stop, NULL);
  }];
}

- (void)testBasics {
  const uint32_t kKeys[] = { 1U, 2U, 3U };
  const int32_t kValues[] = { 700, 701, 702 };
  GPBUInt32EnumDictionary *dict =
2624 2625 2626
      [[GPBUInt32EnumDictionary alloc] initWithEnums:kValues
                                             forKeys:kKeys
                                               count:GPBARRAYSIZE(kValues)];
2627 2628 2629
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 3U);
  int32_t value;
2630 2631
  XCTAssertTrue([dict getEnum:NULL forKey:1U]);
  XCTAssertTrue([dict getEnum:&value forKey:1U]);
2632
  XCTAssertEqual(value, 700);
2633 2634
  XCTAssertTrue([dict getEnum:NULL forKey:2U]);
  XCTAssertTrue([dict getEnum:&value forKey:2U]);
2635
  XCTAssertEqual(value, 701);
2636 2637
  XCTAssertTrue([dict getEnum:NULL forKey:3U]);
  XCTAssertTrue([dict getEnum:&value forKey:3U]);
2638
  XCTAssertEqual(value, 702);
2639
  XCTAssertFalse([dict getEnum:NULL forKey:4U]);
2640 2641 2642 2643

  __block NSUInteger idx = 0;
  uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
  int32_t *seenValues = malloc(3 * sizeof(int32_t));
2644
  [dict enumerateKeysAndEnumsUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665
    XCTAssertLessThan(idx, 3U);
    seenKeys[idx] = aKey;
    seenValues[idx] = aValue;
    XCTAssertNotEqual(stop, NULL);
    ++idx;
  }];
  for (int i = 0; i < 3; ++i) {
    BOOL foundKey = NO;
    for (int j = 0; (j < 3) && !foundKey; ++j) {
      if (kKeys[i] == seenKeys[j]) {
        foundKey = YES;
        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
      }
    }
    XCTAssertTrue(foundKey, @"i = %d", i);
  }
  free(seenKeys);
  free(seenValues);

  // Stopping the enumeration.
  idx = 0;
2666
  [dict enumerateKeysAndEnumsUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681
    #pragma unused(aKey, aValue)
    if (idx == 1) *stop = YES;
    XCTAssertNotEqual(idx, 2U);
    ++idx;
  }];
  [dict release];
}

- (void)testEquality {
  const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
  const uint32_t kKeys2[] = { 2U, 1U, 4U };
  const int32_t kValues1[] = { 700, 701, 702 };
  const int32_t kValues2[] = { 700, 703, 702 };
  const int32_t kValues3[] = { 700, 701, 702, 703 };
  GPBUInt32EnumDictionary *dict1 =
2682 2683 2684
      [[GPBUInt32EnumDictionary alloc] initWithEnums:kValues1
                                             forKeys:kKeys1
                                               count:GPBARRAYSIZE(kValues1)];
2685 2686
  XCTAssertNotNil(dict1);
  GPBUInt32EnumDictionary *dict1prime =
2687 2688 2689
      [[GPBUInt32EnumDictionary alloc] initWithEnums:kValues1
                                             forKeys:kKeys1
                                               count:GPBARRAYSIZE(kValues1)];
2690 2691
  XCTAssertNotNil(dict1prime);
  GPBUInt32EnumDictionary *dict2 =
2692 2693 2694
      [[GPBUInt32EnumDictionary alloc] initWithEnums:kValues2
                                             forKeys:kKeys1
                                               count:GPBARRAYSIZE(kValues2)];
2695 2696
  XCTAssertNotNil(dict2);
  GPBUInt32EnumDictionary *dict3 =
2697 2698 2699
      [[GPBUInt32EnumDictionary alloc] initWithEnums:kValues1
                                             forKeys:kKeys2
                                               count:GPBARRAYSIZE(kValues1)];
2700 2701
  XCTAssertNotNil(dict3);
  GPBUInt32EnumDictionary *dict4 =
2702 2703 2704
      [[GPBUInt32EnumDictionary alloc] initWithEnums:kValues3
                                             forKeys:kKeys1
                                               count:GPBARRAYSIZE(kValues3)];
2705 2706 2707 2708 2709 2710 2711 2712
  XCTAssertNotNil(dict4);

  // 1/1Prime should be different objects, but equal.
  XCTAssertNotEqual(dict1, dict1prime);
  XCTAssertEqualObjects(dict1, dict1prime);
  // Equal, so they must have same hash.
  XCTAssertEqual([dict1 hash], [dict1prime hash]);

2713
  // 2 is same keys, different values; not equal.
2714 2715
  XCTAssertNotEqualObjects(dict1, dict2);

2716
  // 3 is different keys, same values; not equal.
2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732
  XCTAssertNotEqualObjects(dict1, dict3);

  // 4 extra pair; not equal
  XCTAssertNotEqualObjects(dict1, dict4);

  [dict1 release];
  [dict1prime release];
  [dict2 release];
  [dict3 release];
  [dict4 release];
}

- (void)testCopy {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const int32_t kValues[] = { 700, 701, 702, 703 };
  GPBUInt32EnumDictionary *dict =
2733 2734 2735
      [[GPBUInt32EnumDictionary alloc] initWithEnums:kValues
                                             forKeys:kKeys
                                               count:GPBARRAYSIZE(kValues)];
2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753
  XCTAssertNotNil(dict);

  GPBUInt32EnumDictionary *dict2 = [dict copy];
  XCTAssertNotNil(dict2);

  // Should be new object but equal.
  XCTAssertNotEqual(dict, dict2);
  XCTAssertEqualObjects(dict, dict2);
  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32EnumDictionary class]]);

  [dict2 release];
  [dict release];
}

- (void)testDictionaryFromDictionary {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const int32_t kValues[] = { 700, 701, 702, 703 };
  GPBUInt32EnumDictionary *dict =
2754 2755 2756
      [[GPBUInt32EnumDictionary alloc] initWithEnums:kValues
                                             forKeys:kKeys
                                               count:GPBARRAYSIZE(kValues)];
2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773
  XCTAssertNotNil(dict);

  GPBUInt32EnumDictionary *dict2 =
      [GPBUInt32EnumDictionary dictionaryWithDictionary:dict];
  XCTAssertNotNil(dict2);

  // Should be new pointer, but equal objects.
  XCTAssertNotEqual(dict, dict2);
  XCTAssertEqualObjects(dict, dict2);
  [dict release];
}

- (void)testAdds {
  GPBUInt32EnumDictionary *dict = [GPBUInt32EnumDictionary dictionary];
  XCTAssertNotNil(dict);

  XCTAssertEqual(dict.count, 0U);
2774
  [dict setEnum:700 forKey:1U];
2775 2776 2777 2778 2779
  XCTAssertEqual(dict.count, 1U);

  const uint32_t kKeys[] = { 2U, 3U, 4U };
  const int32_t kValues[] = { 701, 702, 703 };
  GPBUInt32EnumDictionary *dict2 =
2780 2781 2782
      [[GPBUInt32EnumDictionary alloc] initWithEnums:kValues
                                             forKeys:kKeys
                                               count:GPBARRAYSIZE(kValues)];
2783 2784 2785 2786 2787
  XCTAssertNotNil(dict2);
  [dict addRawEntriesFromDictionary:dict2];
  XCTAssertEqual(dict.count, 4U);

  int32_t value;
2788 2789
  XCTAssertTrue([dict getEnum:NULL forKey:1U]);
  XCTAssertTrue([dict getEnum:&value forKey:1U]);
2790
  XCTAssertEqual(value, 700);
2791 2792
  XCTAssertTrue([dict getEnum:NULL forKey:2U]);
  XCTAssertTrue([dict getEnum:&value forKey:2U]);
2793
  XCTAssertEqual(value, 701);
2794 2795
  XCTAssertTrue([dict getEnum:NULL forKey:3U]);
  XCTAssertTrue([dict getEnum:&value forKey:3U]);
2796
  XCTAssertEqual(value, 702);
2797 2798
  XCTAssertTrue([dict getEnum:NULL forKey:4U]);
  XCTAssertTrue([dict getEnum:&value forKey:4U]);
2799 2800 2801 2802 2803 2804 2805 2806
  XCTAssertEqual(value, 703);
  [dict2 release];
}

- (void)testRemove {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const int32_t kValues[] = { 700, 701, 702, 703 };
  GPBUInt32EnumDictionary *dict =
2807 2808 2809
      [[GPBUInt32EnumDictionary alloc] initWithEnums:kValues
                                             forKeys:kKeys
                                               count:GPBARRAYSIZE(kValues)];
2810 2811 2812
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 4U);

2813
  [dict removeEnumForKey:2U];
2814 2815
  XCTAssertEqual(dict.count, 3U);
  int32_t value;
2816 2817
  XCTAssertTrue([dict getEnum:NULL forKey:1U]);
  XCTAssertTrue([dict getEnum:&value forKey:1U]);
2818
  XCTAssertEqual(value, 700);
2819 2820 2821
  XCTAssertFalse([dict getEnum:NULL forKey:2U]);
  XCTAssertTrue([dict getEnum:NULL forKey:3U]);
  XCTAssertTrue([dict getEnum:&value forKey:3U]);
2822
  XCTAssertEqual(value, 702);
2823 2824
  XCTAssertTrue([dict getEnum:NULL forKey:4U]);
  XCTAssertTrue([dict getEnum:&value forKey:4U]);
2825 2826 2827
  XCTAssertEqual(value, 703);

  // Remove again does nothing.
2828
  [dict removeEnumForKey:2U];
2829
  XCTAssertEqual(dict.count, 3U);
2830 2831
  XCTAssertTrue([dict getEnum:NULL forKey:1U]);
  XCTAssertTrue([dict getEnum:&value forKey:1U]);
2832
  XCTAssertEqual(value, 700);
2833 2834 2835
  XCTAssertFalse([dict getEnum:NULL forKey:2U]);
  XCTAssertTrue([dict getEnum:NULL forKey:3U]);
  XCTAssertTrue([dict getEnum:&value forKey:3U]);
2836
  XCTAssertEqual(value, 702);
2837 2838
  XCTAssertTrue([dict getEnum:NULL forKey:4U]);
  XCTAssertTrue([dict getEnum:&value forKey:4U]);
2839 2840
  XCTAssertEqual(value, 703);

2841
  [dict removeEnumForKey:4U];
2842
  XCTAssertEqual(dict.count, 2U);
2843 2844
  XCTAssertTrue([dict getEnum:NULL forKey:1U]);
  XCTAssertTrue([dict getEnum:&value forKey:1U]);
2845
  XCTAssertEqual(value, 700);
2846 2847 2848
  XCTAssertFalse([dict getEnum:NULL forKey:2U]);
  XCTAssertTrue([dict getEnum:NULL forKey:3U]);
  XCTAssertTrue([dict getEnum:&value forKey:3U]);
2849
  XCTAssertEqual(value, 702);
2850
  XCTAssertFalse([dict getEnum:NULL forKey:4U]);
2851 2852 2853

  [dict removeAll];
  XCTAssertEqual(dict.count, 0U);
2854 2855 2856 2857
  XCTAssertFalse([dict getEnum:NULL forKey:1U]);
  XCTAssertFalse([dict getEnum:NULL forKey:2U]);
  XCTAssertFalse([dict getEnum:NULL forKey:3U]);
  XCTAssertFalse([dict getEnum:NULL forKey:4U]);
2858 2859 2860 2861 2862 2863 2864
  [dict release];
}

- (void)testInplaceMutation {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const int32_t kValues[] = { 700, 701, 702, 703 };
  GPBUInt32EnumDictionary *dict =
2865 2866 2867
      [[GPBUInt32EnumDictionary alloc] initWithEnums:kValues
                                             forKeys:kKeys
                                               count:GPBARRAYSIZE(kValues)];
2868 2869 2870
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 4U);
  int32_t value;
2871 2872
  XCTAssertTrue([dict getEnum:NULL forKey:1U]);
  XCTAssertTrue([dict getEnum:&value forKey:1U]);
2873
  XCTAssertEqual(value, 700);
2874 2875
  XCTAssertTrue([dict getEnum:NULL forKey:2U]);
  XCTAssertTrue([dict getEnum:&value forKey:2U]);
2876
  XCTAssertEqual(value, 701);
2877 2878
  XCTAssertTrue([dict getEnum:NULL forKey:3U]);
  XCTAssertTrue([dict getEnum:&value forKey:3U]);
2879
  XCTAssertEqual(value, 702);
2880 2881
  XCTAssertTrue([dict getEnum:NULL forKey:4U]);
  XCTAssertTrue([dict getEnum:&value forKey:4U]);
2882 2883
  XCTAssertEqual(value, 703);

2884
  [dict setEnum:703 forKey:1U];
2885
  XCTAssertEqual(dict.count, 4U);
2886 2887
  XCTAssertTrue([dict getEnum:NULL forKey:1U]);
  XCTAssertTrue([dict getEnum:&value forKey:1U]);
2888
  XCTAssertEqual(value, 703);
2889 2890
  XCTAssertTrue([dict getEnum:NULL forKey:2U]);
  XCTAssertTrue([dict getEnum:&value forKey:2U]);
2891
  XCTAssertEqual(value, 701);
2892 2893
  XCTAssertTrue([dict getEnum:NULL forKey:3U]);
  XCTAssertTrue([dict getEnum:&value forKey:3U]);
2894
  XCTAssertEqual(value, 702);
2895 2896
  XCTAssertTrue([dict getEnum:NULL forKey:4U]);
  XCTAssertTrue([dict getEnum:&value forKey:4U]);
2897 2898
  XCTAssertEqual(value, 703);

2899
  [dict setEnum:701 forKey:4U];
2900
  XCTAssertEqual(dict.count, 4U);
2901 2902
  XCTAssertTrue([dict getEnum:NULL forKey:1U]);
  XCTAssertTrue([dict getEnum:&value forKey:1U]);
2903
  XCTAssertEqual(value, 703);
2904 2905
  XCTAssertTrue([dict getEnum:NULL forKey:2U]);
  XCTAssertTrue([dict getEnum:&value forKey:2U]);
2906
  XCTAssertEqual(value, 701);
2907 2908
  XCTAssertTrue([dict getEnum:NULL forKey:3U]);
  XCTAssertTrue([dict getEnum:&value forKey:3U]);
2909
  XCTAssertEqual(value, 702);
2910 2911
  XCTAssertTrue([dict getEnum:NULL forKey:4U]);
  XCTAssertTrue([dict getEnum:&value forKey:4U]);
2912 2913 2914 2915 2916
  XCTAssertEqual(value, 701);

  const uint32_t kKeys2[] = { 2U, 3U };
  const int32_t kValues2[] = { 702, 700 };
  GPBUInt32EnumDictionary *dict2 =
2917 2918 2919
      [[GPBUInt32EnumDictionary alloc] initWithEnums:kValues2
                                             forKeys:kKeys2
                                               count:GPBARRAYSIZE(kValues2)];
2920 2921 2922
  XCTAssertNotNil(dict2);
  [dict addRawEntriesFromDictionary:dict2];
  XCTAssertEqual(dict.count, 4U);
2923 2924
  XCTAssertTrue([dict getEnum:NULL forKey:1U]);
  XCTAssertTrue([dict getEnum:&value forKey:1U]);
2925
  XCTAssertEqual(value, 703);
2926 2927
  XCTAssertTrue([dict getEnum:NULL forKey:2U]);
  XCTAssertTrue([dict getEnum:&value forKey:2U]);
2928
  XCTAssertEqual(value, 702);
2929 2930
  XCTAssertTrue([dict getEnum:NULL forKey:3U]);
  XCTAssertTrue([dict getEnum:&value forKey:3U]);
2931
  XCTAssertEqual(value, 700);
2932 2933
  XCTAssertTrue([dict getEnum:NULL forKey:4U]);
  XCTAssertTrue([dict getEnum:&value forKey:4U]);
2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960
  XCTAssertEqual(value, 701);

  [dict2 release];
  [dict release];
}

@end

#pragma mark - UInt32 -> Enum (Unknown Enums)

@interface GPBUInt32EnumDictionaryUnknownEnumTests : XCTestCase
@end

@implementation GPBUInt32EnumDictionaryUnknownEnumTests

- (void)testRawBasics {
  const uint32_t kKeys[] = { 1U, 2U, 3U };
  const int32_t kValues[] = { 700, 801, 702 };
  GPBUInt32EnumDictionary *dict =
      [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
                                                        rawValues:kValues
                                                          forKeys:kKeys
                                                            count:GPBARRAYSIZE(kValues)];
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 3U);
  XCTAssertTrue(dict.validationFunc == TestingEnum_IsValidValue);  // Pointer comparison
  int32_t value;
2961 2962
  XCTAssertTrue([dict getRawValue:NULL forKey:1U]);
  XCTAssertTrue([dict getRawValue:&value forKey:1U]);
2963
  XCTAssertEqual(value, 700);
2964 2965
  XCTAssertTrue([dict getEnum:NULL forKey:2U]);
  XCTAssertTrue([dict getEnum:&value forKey:2U]);
2966
  XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
2967 2968
  XCTAssertTrue([dict getRawValue:NULL forKey:2U]);
  XCTAssertTrue([dict getRawValue:&value forKey:2U]);
2969
  XCTAssertEqual(value, 801);
2970 2971
  XCTAssertTrue([dict getRawValue:NULL forKey:3U]);
  XCTAssertTrue([dict getRawValue:&value forKey:3U]);
2972
  XCTAssertEqual(value, 702);
2973
  XCTAssertFalse([dict getRawValue:NULL forKey:4U]);
2974 2975 2976 2977

  __block NSUInteger idx = 0;
  uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
  int32_t *seenValues = malloc(3 * sizeof(int32_t));
2978
  [dict enumerateKeysAndEnumsUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073
    XCTAssertLessThan(idx, 3U);
    seenKeys[idx] = aKey;
    seenValues[idx] = aValue;
    XCTAssertNotEqual(stop, NULL);
    ++idx;
  }];
  for (int i = 0; i < 3; ++i) {
    BOOL foundKey = NO;
    for (int j = 0; (j < 3) && !foundKey; ++j) {
      if (kKeys[i] == seenKeys[j]) {
        foundKey = YES;
        if (i == 1) {
          XCTAssertEqual(kGPBUnrecognizedEnumeratorValue, seenValues[j], @"i = %d, j = %d", i, j);
        } else {
          XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
        }
      }
    }
    XCTAssertTrue(foundKey, @"i = %d", i);
  }
  idx = 0;
  [dict enumerateKeysAndRawValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
    XCTAssertLessThan(idx, 3U);
    seenKeys[idx] = aKey;
    seenValues[idx] = aValue;
    XCTAssertNotEqual(stop, NULL);
    ++idx;
  }];
  for (int i = 0; i < 3; ++i) {
    BOOL foundKey = NO;
    for (int j = 0; (j < 3) && !foundKey; ++j) {
      if (kKeys[i] == seenKeys[j]) {
        foundKey = YES;
        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
      }
    }
    XCTAssertTrue(foundKey, @"i = %d", i);
  }
  free(seenKeys);
  free(seenValues);

  // Stopping the enumeration.
  idx = 0;
  [dict enumerateKeysAndRawValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
    #pragma unused(aKey, aValue)
    if (idx == 1) *stop = YES;
    XCTAssertNotEqual(idx, 2U);
    ++idx;
  }];
  [dict release];
}

- (void)testEqualityWithUnknowns {
  const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
  const uint32_t kKeys2[] = { 2U, 1U, 4U };
  const int32_t kValues1[] = { 700, 801, 702 };  // Unknown
  const int32_t kValues2[] = { 700, 803, 702 };  // Unknown
  const int32_t kValues3[] = { 700, 801, 702, 803 };  // Unknowns
  GPBUInt32EnumDictionary *dict1 =
      [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
                                                        rawValues:kValues1
                                                          forKeys:kKeys1
                                                            count:GPBARRAYSIZE(kValues1)];
  XCTAssertNotNil(dict1);
  GPBUInt32EnumDictionary *dict1prime =
      [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
                                                        rawValues:kValues1
                                                          forKeys:kKeys1
                                                            count:GPBARRAYSIZE(kValues1)];
  XCTAssertNotNil(dict1prime);
  GPBUInt32EnumDictionary *dict2 =
      [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
                                                        rawValues:kValues2
                                                          forKeys:kKeys1
                                                            count:GPBARRAYSIZE(kValues2)];
  XCTAssertNotNil(dict2);
  GPBUInt32EnumDictionary *dict3 =
      [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
                                                        rawValues:kValues1
                                                          forKeys:kKeys2
                                                            count:GPBARRAYSIZE(kValues1)];
  XCTAssertNotNil(dict3);
  GPBUInt32EnumDictionary *dict4 =
      [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
                                                        rawValues:kValues3
                                                          forKeys:kKeys1
                                                            count:GPBARRAYSIZE(kValues3)];
  XCTAssertNotNil(dict4);

  // 1/1Prime should be different objects, but equal.
  XCTAssertNotEqual(dict1, dict1prime);
  XCTAssertEqualObjects(dict1, dict1prime);
  // Equal, so they must have same hash.
  XCTAssertEqual([dict1 hash], [dict1prime hash]);

3074
  // 2 is same keys, different values; not equal.
3075 3076
  XCTAssertNotEqualObjects(dict1, dict2);

3077
  // 3 is different keys, same values; not equal.
3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138
  XCTAssertNotEqualObjects(dict1, dict3);

  // 4 extra pair; not equal
  XCTAssertNotEqualObjects(dict1, dict4);

  [dict1 release];
  [dict1prime release];
  [dict2 release];
  [dict3 release];
  [dict4 release];
}

- (void)testCopyWithUnknowns {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknown
  GPBUInt32EnumDictionary *dict =
      [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
                                                        rawValues:kValues
                                                          forKeys:kKeys
                                                            count:GPBARRAYSIZE(kValues)];
  XCTAssertNotNil(dict);

  GPBUInt32EnumDictionary *dict2 = [dict copy];
  XCTAssertNotNil(dict2);

  // Should be new pointer, but equal objects.
  XCTAssertNotEqual(dict, dict2);
  XCTAssertEqual(dict.validationFunc, dict2.validationFunc);  // Pointer comparison
  XCTAssertEqualObjects(dict, dict2);

  [dict2 release];
  [dict release];
}

- (void)testDictionaryFromDictionary {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknowns
  GPBUInt32EnumDictionary *dict =
      [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
                                                        rawValues:kValues
                                                          forKeys:kKeys
                                                            count:GPBARRAYSIZE(kValues)];
  XCTAssertNotNil(dict);

  GPBUInt32EnumDictionary *dict2 =
      [GPBUInt32EnumDictionary dictionaryWithDictionary:dict];
  XCTAssertNotNil(dict2);

  // Should be new pointer, but equal objects.
  XCTAssertNotEqual(dict, dict2);
  XCTAssertEqualObjects(dict, dict2);
  XCTAssertEqual(dict.validationFunc, dict2.validationFunc);  // Pointer comparison
  [dict release];
}

- (void)testUnknownAdds {
  GPBUInt32EnumDictionary *dict =
    [GPBUInt32EnumDictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue];
  XCTAssertNotNil(dict);

  XCTAssertEqual(dict.count, 0U);
3139
  XCTAssertThrowsSpecificNamed([dict setEnum:801 forKey:2U],  // Unknown
3140 3141 3142 3143 3144 3145 3146 3147
                               NSException, NSInvalidArgumentException);
  XCTAssertEqual(dict.count, 0U);
  [dict setRawValue:801 forKey:2U];  // Unknown
  XCTAssertEqual(dict.count, 1U);

  const uint32_t kKeys[] = { 1U, 3U, 4U };
  const int32_t kValues[] = { 700, 702, 803 };  // Unknown
  GPBUInt32EnumDictionary *dict2 =
3148 3149 3150
      [[GPBUInt32EnumDictionary alloc] initWithEnums:kValues
                                               forKeys:kKeys
                                                 count:GPBARRAYSIZE(kValues)];
3151 3152 3153 3154 3155
  XCTAssertNotNil(dict2);
  [dict addRawEntriesFromDictionary:dict2];
  XCTAssertEqual(dict.count, 4U);

  int32_t value;
3156 3157
  XCTAssertTrue([dict getEnum:NULL forKey:1U]);
  XCTAssertTrue([dict getEnum:&value forKey:1U]);
3158
  XCTAssertEqual(value, 700);
3159 3160
  XCTAssertTrue([dict getEnum:NULL forKey:2U]);
  XCTAssertTrue([dict getEnum:&value forKey:2U]);
3161
  XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
3162 3163
  XCTAssertTrue([dict getRawValue:NULL forKey:2U]);
  XCTAssertTrue([dict getRawValue:&value forKey:2U]);
3164
  XCTAssertEqual(value, 801);
3165 3166
  XCTAssertTrue([dict getEnum:NULL forKey:3U]);
  XCTAssertTrue([dict getEnum:&value forKey:3U]);
3167
  XCTAssertEqual(value, 702);
3168 3169
  XCTAssertTrue([dict getEnum:NULL forKey:4U]);
  XCTAssertTrue([dict getEnum:&value forKey:4U]);
3170
  XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
3171 3172
  XCTAssertTrue([dict getRawValue:NULL forKey:4U]);
  XCTAssertTrue([dict getRawValue:&value forKey:4U]);
3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187
  XCTAssertEqual(value, 803);
  [dict2 release];
}

- (void)testUnknownRemove {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknowns
  GPBUInt32EnumDictionary *dict =
      [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
                                                        rawValues:kValues
                                                          forKeys:kKeys
                                                            count:GPBARRAYSIZE(kValues)];
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 4U);

3188
  [dict removeEnumForKey:2U];
3189 3190
  XCTAssertEqual(dict.count, 3U);
  int32_t value;
3191 3192
  XCTAssertTrue([dict getEnum:NULL forKey:1U]);
  XCTAssertTrue([dict getEnum:&value forKey:1U]);
3193
  XCTAssertEqual(value, 700);
3194 3195 3196
  XCTAssertFalse([dict getEnum:NULL forKey:2U]);
  XCTAssertTrue([dict getEnum:NULL forKey:3U]);
  XCTAssertTrue([dict getEnum:&value forKey:3U]);
3197
  XCTAssertEqual(value, 702);
3198 3199
  XCTAssertTrue([dict getRawValue:NULL forKey:4U]);
  XCTAssertTrue([dict getRawValue:&value forKey:4U]);
3200 3201 3202
  XCTAssertEqual(value, 803);

  // Remove again does nothing.
3203
  [dict removeEnumForKey:2U];
3204
  XCTAssertEqual(dict.count, 3U);
3205 3206
  XCTAssertTrue([dict getEnum:NULL forKey:1U]);
  XCTAssertTrue([dict getEnum:&value forKey:1U]);
3207
  XCTAssertEqual(value, 700);
3208 3209 3210
  XCTAssertFalse([dict getEnum:NULL forKey:2U]);
  XCTAssertTrue([dict getEnum:NULL forKey:3U]);
  XCTAssertTrue([dict getEnum:&value forKey:3U]);
3211
  XCTAssertEqual(value, 702);
3212 3213
  XCTAssertTrue([dict getRawValue:NULL forKey:4U]);
  XCTAssertTrue([dict getRawValue:&value forKey:4U]);
3214 3215
  XCTAssertEqual(value, 803);

3216
  [dict removeEnumForKey:4U];
3217
  XCTAssertEqual(dict.count, 2U);
3218 3219
  XCTAssertTrue([dict getEnum:NULL forKey:1U]);
  XCTAssertTrue([dict getEnum:&value forKey:1U]);
3220
  XCTAssertEqual(value, 700);
3221 3222 3223
  XCTAssertFalse([dict getEnum:NULL forKey:2U]);
  XCTAssertTrue([dict getEnum:NULL forKey:3U]);
  XCTAssertTrue([dict getEnum:&value forKey:3U]);
3224
  XCTAssertEqual(value, 702);
3225
  XCTAssertFalse([dict getEnum:NULL forKey:4U]);
3226 3227 3228

  [dict removeAll];
  XCTAssertEqual(dict.count, 0U);
3229 3230 3231 3232
  XCTAssertFalse([dict getEnum:NULL forKey:1U]);
  XCTAssertFalse([dict getEnum:NULL forKey:2U]);
  XCTAssertFalse([dict getEnum:NULL forKey:3U]);
  XCTAssertFalse([dict getEnum:NULL forKey:4U]);
3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246
  [dict release];
}

- (void)testInplaceMutationUnknowns {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknowns
  GPBUInt32EnumDictionary *dict =
      [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
                                                        rawValues:kValues
                                                          forKeys:kKeys
                                                            count:GPBARRAYSIZE(kValues)];
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 4U);
  int32_t value;
3247 3248
  XCTAssertTrue([dict getEnum:NULL forKey:1U]);
  XCTAssertTrue([dict getEnum:&value forKey:1U]);
3249
  XCTAssertEqual(value, 700);
3250 3251
  XCTAssertTrue([dict getRawValue:NULL forKey:2U]);
  XCTAssertTrue([dict getRawValue:&value forKey:2U]);
3252
  XCTAssertEqual(value, 801);
3253 3254
  XCTAssertTrue([dict getEnum:NULL forKey:3U]);
  XCTAssertTrue([dict getEnum:&value forKey:3U]);
3255
  XCTAssertEqual(value, 702);
3256 3257
  XCTAssertTrue([dict getRawValue:NULL forKey:4U]);
  XCTAssertTrue([dict getRawValue:&value forKey:4U]);
3258 3259
  XCTAssertEqual(value, 803);

3260
  XCTAssertThrowsSpecificNamed([dict setEnum:803 forKey:1U],  // Unknown
3261 3262
                               NSException, NSInvalidArgumentException);
  XCTAssertEqual(dict.count, 4U);
3263 3264
  XCTAssertTrue([dict getEnum:NULL forKey:1U]);
  XCTAssertTrue([dict getEnum:&value forKey:1U]);
3265
  XCTAssertEqual(value, 700);
3266 3267
  XCTAssertTrue([dict getRawValue:NULL forKey:2U]);
  XCTAssertTrue([dict getRawValue:&value forKey:2U]);
3268
  XCTAssertEqual(value, 801);
3269 3270
  XCTAssertTrue([dict getEnum:NULL forKey:3U]);
  XCTAssertTrue([dict getEnum:&value forKey:3U]);
3271
  XCTAssertEqual(value, 702);
3272 3273
  XCTAssertTrue([dict getRawValue:NULL forKey:4U]);
  XCTAssertTrue([dict getRawValue:&value forKey:4U]);
3274 3275 3276 3277
  XCTAssertEqual(value, 803);

  [dict setRawValue:803 forKey:1U];  // Unknown
  XCTAssertEqual(dict.count, 4U);
3278 3279
  XCTAssertTrue([dict getRawValue:NULL forKey:1U]);
  XCTAssertTrue([dict getRawValue:&value forKey:1U]);
3280
  XCTAssertEqual(value, 803);
3281 3282
  XCTAssertTrue([dict getRawValue:NULL forKey:2U]);
  XCTAssertTrue([dict getRawValue:&value forKey:2U]);
3283
  XCTAssertEqual(value, 801);
3284 3285
  XCTAssertTrue([dict getEnum:NULL forKey:3U]);
  XCTAssertTrue([dict getEnum:&value forKey:3U]);
3286
  XCTAssertEqual(value, 702);
3287 3288
  XCTAssertTrue([dict getRawValue:NULL forKey:4U]);
  XCTAssertTrue([dict getRawValue:&value forKey:4U]);
3289 3290 3291 3292
  XCTAssertEqual(value, 803);

  [dict setRawValue:700 forKey:4U];
  XCTAssertEqual(dict.count, 4U);
3293 3294
  XCTAssertTrue([dict getRawValue:NULL forKey:1U]);
  XCTAssertTrue([dict getRawValue:&value forKey:1U]);
3295
  XCTAssertEqual(value, 803);
3296 3297
  XCTAssertTrue([dict getRawValue:NULL forKey:2U]);
  XCTAssertTrue([dict getRawValue:&value forKey:2U]);
3298
  XCTAssertEqual(value, 801);
3299 3300
  XCTAssertTrue([dict getEnum:NULL forKey:3U]);
  XCTAssertTrue([dict getEnum:&value forKey:3U]);
3301
  XCTAssertEqual(value, 702);
3302 3303
  XCTAssertTrue([dict getEnum:NULL forKey:4U]);
  XCTAssertTrue([dict getEnum:&value forKey:4U]);
3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315
  XCTAssertEqual(value, 700);

  const uint32_t kKeys2[] = { 2U, 3U };
  const int32_t kValues2[] = { 702, 801 };  // Unknown
  GPBUInt32EnumDictionary *dict2 =
      [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
                                                        rawValues:kValues2
                                                          forKeys:kKeys2
                                                            count:GPBARRAYSIZE(kValues2)];
  XCTAssertNotNil(dict2);
  [dict addRawEntriesFromDictionary:dict2];
  XCTAssertEqual(dict.count, 4U);
3316 3317
  XCTAssertTrue([dict getRawValue:NULL forKey:1U]);
  XCTAssertTrue([dict getRawValue:&value forKey:1U]);
3318
  XCTAssertEqual(value, 803);
3319 3320
  XCTAssertTrue([dict getEnum:NULL forKey:2U]);
  XCTAssertTrue([dict getEnum:&value forKey:2U]);
3321
  XCTAssertEqual(value, 702);
3322 3323
  XCTAssertTrue([dict getRawValue:NULL forKey:3U]);
  XCTAssertTrue([dict getRawValue:&value forKey:3U]);
3324
  XCTAssertEqual(value, 801);
3325 3326
  XCTAssertTrue([dict getEnum:NULL forKey:4U]);
  XCTAssertTrue([dict getEnum:&value forKey:4U]);
3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365
  XCTAssertEqual(value, 700);

  [dict2 release];
  [dict release];
}

- (void)testCopyUnknowns {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
  const int32_t kValues[] = { 700, 801, 702, 803 };
  GPBUInt32EnumDictionary *dict =
      [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
                                                        rawValues:kValues
                                                          forKeys:kKeys
                                                            count:GPBARRAYSIZE(kValues)];
  XCTAssertNotNil(dict);

  GPBUInt32EnumDictionary *dict2 = [dict copy];
  XCTAssertNotNil(dict2);

  // Should be new pointer, but equal objects.
  XCTAssertNotEqual(dict, dict2);
  XCTAssertEqualObjects(dict, dict2);
  XCTAssertEqual(dict.validationFunc, dict2.validationFunc);  // Pointer comparison
  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32EnumDictionary class]]);

  [dict2 release];
  [dict release];
}

@end

#pragma mark - UInt32 -> Object

@interface GPBUInt32ObjectDictionaryTests : XCTestCase
@end

@implementation GPBUInt32ObjectDictionaryTests

- (void)testEmpty {
3366
  GPBUInt32ObjectDictionary<NSString*> *dict = [[GPBUInt32ObjectDictionary alloc] init];
3367 3368
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 0U);
3369
  XCTAssertNil([dict objectForKey:1U]);
3370
  [dict enumerateKeysAndObjectsUsingBlock:^(uint32_t aKey, NSString* aObject, BOOL *stop) {
3371
    #pragma unused(aKey, aObject, stop)
3372 3373 3374 3375 3376 3377
    XCTFail(@"Shouldn't get here!");
  }];
  [dict release];
}

- (void)testOne {
3378
  GPBUInt32ObjectDictionary<NSString*> *dict = [GPBUInt32ObjectDictionary dictionaryWithObject:@"abc" forKey:1U];
3379 3380
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 1U);
3381 3382
  XCTAssertEqualObjects([dict objectForKey:1U], @"abc");
  XCTAssertNil([dict objectForKey:2U]);
3383
  [dict enumerateKeysAndObjectsUsingBlock:^(uint32_t aKey, NSString* aObject, BOOL *stop) {
3384
    XCTAssertEqual(aKey, 1U);
3385
    XCTAssertEqualObjects(aObject, @"abc");
3386 3387 3388 3389 3390 3391
    XCTAssertNotEqual(stop, NULL);
  }];
}

- (void)testBasics {
  const uint32_t kKeys[] = { 1U, 2U, 3U };
3392 3393
  const NSString* kObjects[] = { @"abc", @"def", @"ghi" };
  GPBUInt32ObjectDictionary<NSString*> *dict =
3394 3395 3396
      [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kObjects)];
3397 3398
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 3U);
3399 3400 3401 3402
  XCTAssertEqualObjects([dict objectForKey:1U], @"abc");
  XCTAssertEqualObjects([dict objectForKey:2U], @"def");
  XCTAssertEqualObjects([dict objectForKey:3U], @"ghi");
  XCTAssertNil([dict objectForKey:4U]);
3403 3404 3405

  __block NSUInteger idx = 0;
  uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
3406 3407
  NSString* *seenObjects = malloc(3 * sizeof(NSString*));
  [dict enumerateKeysAndObjectsUsingBlock:^(uint32_t aKey, NSString* aObject, BOOL *stop) {
3408 3409
    XCTAssertLessThan(idx, 3U);
    seenKeys[idx] = aKey;
3410
    seenObjects[idx] = aObject;
3411 3412 3413 3414 3415 3416 3417 3418
    XCTAssertNotEqual(stop, NULL);
    ++idx;
  }];
  for (int i = 0; i < 3; ++i) {
    BOOL foundKey = NO;
    for (int j = 0; (j < 3) && !foundKey; ++j) {
      if (kKeys[i] == seenKeys[j]) {
        foundKey = YES;
3419
        XCTAssertEqualObjects(kObjects[i], seenObjects[j], @"i = %d, j = %d", i, j);
3420 3421 3422 3423 3424
      }
    }
    XCTAssertTrue(foundKey, @"i = %d", i);
  }
  free(seenKeys);
3425
  free(seenObjects);
3426 3427 3428

  // Stopping the enumeration.
  idx = 0;
3429
  [dict enumerateKeysAndObjectsUsingBlock:^(uint32_t aKey, NSString* aObject, BOOL *stop) {
3430
    #pragma unused(aKey, aObject)
3431 3432 3433 3434 3435 3436 3437 3438 3439 3440
    if (idx == 1) *stop = YES;
    XCTAssertNotEqual(idx, 2U);
    ++idx;
  }];
  [dict release];
}

- (void)testEquality {
  const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
  const uint32_t kKeys2[] = { 2U, 1U, 4U };
3441 3442 3443 3444
  const NSString* kObjects1[] = { @"abc", @"def", @"ghi" };
  const NSString* kObjects2[] = { @"abc", @"jkl", @"ghi" };
  const NSString* kObjects3[] = { @"abc", @"def", @"ghi", @"jkl" };
  GPBUInt32ObjectDictionary<NSString*> *dict1 =
3445 3446 3447
      [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects1
                                                 forKeys:kKeys1
                                                   count:GPBARRAYSIZE(kObjects1)];
3448
  XCTAssertNotNil(dict1);
3449
  GPBUInt32ObjectDictionary<NSString*> *dict1prime =
3450 3451 3452
      [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects1
                                                 forKeys:kKeys1
                                                   count:GPBARRAYSIZE(kObjects1)];
3453
  XCTAssertNotNil(dict1prime);
3454
  GPBUInt32ObjectDictionary<NSString*> *dict2 =
3455 3456 3457
      [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects2
                                                 forKeys:kKeys1
                                                   count:GPBARRAYSIZE(kObjects2)];
3458
  XCTAssertNotNil(dict2);
3459
  GPBUInt32ObjectDictionary<NSString*> *dict3 =
3460 3461 3462
      [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects1
                                                 forKeys:kKeys2
                                                   count:GPBARRAYSIZE(kObjects1)];
3463
  XCTAssertNotNil(dict3);
3464
  GPBUInt32ObjectDictionary<NSString*> *dict4 =
3465 3466 3467
      [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects3
                                                 forKeys:kKeys1
                                                   count:GPBARRAYSIZE(kObjects3)];
3468 3469 3470 3471 3472 3473 3474 3475
  XCTAssertNotNil(dict4);

  // 1/1Prime should be different objects, but equal.
  XCTAssertNotEqual(dict1, dict1prime);
  XCTAssertEqualObjects(dict1, dict1prime);
  // Equal, so they must have same hash.
  XCTAssertEqual([dict1 hash], [dict1prime hash]);

3476
  // 2 is same keys, different objects; not equal.
3477 3478
  XCTAssertNotEqualObjects(dict1, dict2);

3479
  // 3 is different keys, same objects; not equal.
3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493
  XCTAssertNotEqualObjects(dict1, dict3);

  // 4 extra pair; not equal
  XCTAssertNotEqualObjects(dict1, dict4);

  [dict1 release];
  [dict1prime release];
  [dict2 release];
  [dict3 release];
  [dict4 release];
}

- (void)testCopy {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
3494 3495
  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
  GPBUInt32ObjectDictionary<NSString*> *dict =
3496 3497 3498
      [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kObjects)];
3499 3500
  XCTAssertNotNil(dict);

3501
  GPBUInt32ObjectDictionary<NSString*> *dict2 = [dict copy];
3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514
  XCTAssertNotNil(dict2);

  // Should be new object but equal.
  XCTAssertNotEqual(dict, dict2);
  XCTAssertEqualObjects(dict, dict2);
  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32ObjectDictionary class]]);

  [dict2 release];
  [dict release];
}

- (void)testDictionaryFromDictionary {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
3515 3516
  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
  GPBUInt32ObjectDictionary<NSString*> *dict =
3517 3518 3519
      [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kObjects)];
3520 3521
  XCTAssertNotNil(dict);

3522
  GPBUInt32ObjectDictionary<NSString*> *dict2 =
3523 3524 3525 3526 3527 3528 3529 3530 3531 3532
      [GPBUInt32ObjectDictionary dictionaryWithDictionary:dict];
  XCTAssertNotNil(dict2);

  // Should be new pointer, but equal objects.
  XCTAssertNotEqual(dict, dict2);
  XCTAssertEqualObjects(dict, dict2);
  [dict release];
}

- (void)testAdds {
3533
  GPBUInt32ObjectDictionary<NSString*> *dict = [GPBUInt32ObjectDictionary dictionary];
3534 3535 3536
  XCTAssertNotNil(dict);

  XCTAssertEqual(dict.count, 0U);
3537
  [dict setObject:@"abc" forKey:1U];
3538 3539 3540
  XCTAssertEqual(dict.count, 1U);

  const uint32_t kKeys[] = { 2U, 3U, 4U };
3541 3542
  const NSString* kObjects[] = { @"def", @"ghi", @"jkl" };
  GPBUInt32ObjectDictionary<NSString*> *dict2 =
3543 3544 3545
      [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kObjects)];
3546 3547 3548 3549
  XCTAssertNotNil(dict2);
  [dict addEntriesFromDictionary:dict2];
  XCTAssertEqual(dict.count, 4U);

3550 3551 3552 3553
  XCTAssertEqualObjects([dict objectForKey:1U], @"abc");
  XCTAssertEqualObjects([dict objectForKey:2U], @"def");
  XCTAssertEqualObjects([dict objectForKey:3U], @"ghi");
  XCTAssertEqualObjects([dict objectForKey:4U], @"jkl");
3554 3555 3556 3557 3558
  [dict2 release];
}

- (void)testRemove {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
3559 3560
  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
  GPBUInt32ObjectDictionary<NSString*> *dict =
3561
      [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects
3562 3563
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kObjects)];
3564 3565 3566
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 4U);

3567
  [dict removeObjectForKey:2U];
3568
  XCTAssertEqual(dict.count, 3U);
3569 3570 3571 3572
  XCTAssertEqualObjects([dict objectForKey:1U], @"abc");
  XCTAssertNil([dict objectForKey:2U]);
  XCTAssertEqualObjects([dict objectForKey:3U], @"ghi");
  XCTAssertEqualObjects([dict objectForKey:4U], @"jkl");
3573 3574

  // Remove again does nothing.
3575
  [dict removeObjectForKey:2U];
3576
  XCTAssertEqual(dict.count, 3U);
3577 3578 3579 3580
  XCTAssertEqualObjects([dict objectForKey:1U], @"abc");
  XCTAssertNil([dict objectForKey:2U]);
  XCTAssertEqualObjects([dict objectForKey:3U], @"ghi");
  XCTAssertEqualObjects([dict objectForKey:4U], @"jkl");
3581

3582
  [dict removeObjectForKey:4U];
3583
  XCTAssertEqual(dict.count, 2U);
3584 3585 3586 3587
  XCTAssertEqualObjects([dict objectForKey:1U], @"abc");
  XCTAssertNil([dict objectForKey:2U]);
  XCTAssertEqualObjects([dict objectForKey:3U], @"ghi");
  XCTAssertNil([dict objectForKey:4U]);
3588 3589 3590

  [dict removeAll];
  XCTAssertEqual(dict.count, 0U);
3591 3592 3593 3594
  XCTAssertNil([dict objectForKey:1U]);
  XCTAssertNil([dict objectForKey:2U]);
  XCTAssertNil([dict objectForKey:3U]);
  XCTAssertNil([dict objectForKey:4U]);
3595 3596 3597 3598 3599
  [dict release];
}

- (void)testInplaceMutation {
  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
3600 3601
  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
  GPBUInt32ObjectDictionary<NSString*> *dict =
3602
      [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects
3603 3604
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kObjects)];
3605 3606
  XCTAssertNotNil(dict);
  XCTAssertEqual(dict.count, 4U);
3607 3608 3609 3610
  XCTAssertEqualObjects([dict objectForKey:1U], @"abc");
  XCTAssertEqualObjects([dict objectForKey:2U], @"def");
  XCTAssertEqualObjects([dict objectForKey:3U], @"ghi");
  XCTAssertEqualObjects([dict objectForKey:4U], @"jkl");
3611

3612
  [dict setObject:@"jkl" forKey:1U];
3613
  XCTAssertEqual(dict.count, 4U);
3614 3615 3616 3617
  XCTAssertEqualObjects([dict objectForKey:1U], @"jkl");
  XCTAssertEqualObjects([dict objectForKey:2U], @"def");
  XCTAssertEqualObjects([dict objectForKey:3U], @"ghi");
  XCTAssertEqualObjects([dict objectForKey:4U], @"jkl");
3618

3619
  [dict setObject:@"def" forKey:4U];
3620
  XCTAssertEqual(dict.count, 4U);
3621 3622 3623 3624
  XCTAssertEqualObjects([dict objectForKey:1U], @"jkl");
  XCTAssertEqualObjects([dict objectForKey:2U], @"def");
  XCTAssertEqualObjects([dict objectForKey:3U], @"ghi");
  XCTAssertEqualObjects([dict objectForKey:4U], @"def");
3625 3626

  const uint32_t kKeys2[] = { 2U, 3U };
3627 3628
  const NSString* kObjects2[] = { @"ghi", @"abc" };
  GPBUInt32ObjectDictionary<NSString*> *dict2 =
3629 3630 3631
      [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects2
                                                 forKeys:kKeys2
                                                   count:GPBARRAYSIZE(kObjects2)];
3632 3633 3634
  XCTAssertNotNil(dict2);
  [dict addEntriesFromDictionary:dict2];
  XCTAssertEqual(dict.count, 4U);
3635 3636 3637 3638
  XCTAssertEqualObjects([dict objectForKey:1U], @"jkl");
  XCTAssertEqualObjects([dict objectForKey:2U], @"ghi");
  XCTAssertEqualObjects([dict objectForKey:3U], @"abc");
  XCTAssertEqualObjects([dict objectForKey:4U], @"def");
3639 3640 3641 3642 3643 3644 3645 3646 3647

  [dict2 release];
  [dict release];
}

@end

//%PDDM-EXPAND-END TEST_FOR_POD_KEY(UInt32, uint32_t, 1U, 2U, 3U, 4U)