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