OLD | NEW |
1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
4 // | 4 // |
5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
7 // met: | 7 // met: |
8 // | 8 // |
9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 [output writeRawVarint64:value]; | 186 [output writeRawVarint64:value]; |
187 [output flush]; | 187 [output flush]; |
188 | 188 |
189 NSData* actual = | 189 NSData* actual = |
190 [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey]; | 190 [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey]; |
191 XCTAssertEqualObjects(data, actual); | 191 XCTAssertEqualObjects(data, actual); |
192 } | 192 } |
193 } | 193 } |
194 } | 194 } |
195 | 195 |
| 196 - (void)assertWriteStringNoTag:(NSData*)data |
| 197 value:(NSString *)value |
| 198 context:(NSString *)contextMessage { |
| 199 NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory]; |
| 200 GPBCodedOutputStream* output = |
| 201 [GPBCodedOutputStream streamWithOutputStream:rawOutput]; |
| 202 [output writeStringNoTag:value]; |
| 203 [output flush]; |
| 204 |
| 205 NSData* actual = |
| 206 [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey]; |
| 207 XCTAssertEqualObjects(data, actual, @"%@", contextMessage); |
| 208 |
| 209 // Try different block sizes. |
| 210 for (int blockSize = 1; blockSize <= 16; blockSize *= 2) { |
| 211 rawOutput = [NSOutputStream outputStreamToMemory]; |
| 212 output = [GPBCodedOutputStream streamWithOutputStream:rawOutput |
| 213 bufferSize:blockSize]; |
| 214 [output writeStringNoTag:value]; |
| 215 [output flush]; |
| 216 |
| 217 actual = [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey]; |
| 218 XCTAssertEqualObjects(data, actual, @"%@", contextMessage); |
| 219 } |
| 220 } |
| 221 |
196 - (void)testWriteVarint1 { | 222 - (void)testWriteVarint1 { |
197 [self assertWriteVarint:bytes(0x00) value:0]; | 223 [self assertWriteVarint:bytes(0x00) value:0]; |
198 } | 224 } |
199 | 225 |
200 - (void)testWriteVarint2 { | 226 - (void)testWriteVarint2 { |
201 [self assertWriteVarint:bytes(0x01) value:1]; | 227 [self assertWriteVarint:bytes(0x01) value:1]; |
202 } | 228 } |
203 | 229 |
204 - (void)testWriteVarint3 { | 230 - (void)testWriteVarint3 { |
205 [self assertWriteVarint:bytes(0x7f) value:127]; | 231 [self assertWriteVarint:bytes(0x7f) value:127]; |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
330 | 356 |
331 // Not kGPBDefaultRepeatCount because we are comparing to a golden master file | 357 // Not kGPBDefaultRepeatCount because we are comparing to a golden master file |
332 // that was generated with 2. | 358 // that was generated with 2. |
333 TestAllExtensions* extensions = [self allExtensionsSetRepeatedCount:2]; | 359 TestAllExtensions* extensions = [self allExtensionsSetRepeatedCount:2]; |
334 rawBytes = extensions.data; | 360 rawBytes = extensions.data; |
335 goldenData = [self getDataFileNamed:@"golden_packed_fields_message" | 361 goldenData = [self getDataFileNamed:@"golden_packed_fields_message" |
336 dataToWrite:rawBytes]; | 362 dataToWrite:rawBytes]; |
337 XCTAssertEqualObjects(rawBytes, goldenData); | 363 XCTAssertEqualObjects(rawBytes, goldenData); |
338 } | 364 } |
339 | 365 |
| 366 - (void)testCFStringGetCStringPtrAndStringsWithNullChars { |
| 367 // This test exists to verify that CFStrings with embedded NULLs still expose |
| 368 // their raw buffer if they are backed by UTF8 storage. If this fails, the |
| 369 // quick/direct access paths in GPBCodedOutputStream that depend on |
| 370 // CFStringGetCStringPtr need to be re-evalutated (maybe just removed). |
| 371 // And yes, we do get NULLs in strings from some servers. |
| 372 |
| 373 char zeroTest[] = "\0Test\0String"; |
| 374 // Note: there is a \0 at the end of this since it is a c-string. |
| 375 NSString *asNSString = [[NSString alloc] initWithBytes:zeroTest |
| 376 length:sizeof(zeroTest) |
| 377 encoding:NSUTF8StringEncoding]; |
| 378 const char *cString = |
| 379 CFStringGetCStringPtr((CFStringRef)asNSString, kCFStringEncodingUTF8); |
| 380 XCTAssertTrue(cString != NULL); |
| 381 // Again, if the above assert fails, then it means NSString no longer exposes |
| 382 // the raw utf8 storage of a string created from utf8 input, so the code using |
| 383 // CFStringGetCStringPtr in GPBCodedOutputStream will still work (it will take |
| 384 // a different code path); but the optimizations for when |
| 385 // CFStringGetCStringPtr does work could possibly go away. |
| 386 |
| 387 XCTAssertEqual(sizeof(zeroTest), |
| 388 [asNSString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]); |
| 389 XCTAssertTrue(0 == memcmp(cString, zeroTest, sizeof(zeroTest))); |
| 390 [asNSString release]; |
| 391 } |
| 392 |
| 393 - (void)testWriteStringsWithZeroChar { |
| 394 // Unicode allows `\0` as a character, and NSString is a class cluster, so |
| 395 // there are a few different classes that could end up beind a given string. |
| 396 // Historically, we've seen differences based on constant strings in code and |
| 397 // strings built via the NSString apis. So this round trips them to ensure |
| 398 // they are acting as expected. |
| 399 |
| 400 NSArray<NSString *> *strs = @[ |
| 401 @"\0at start", |
| 402 @"in\0middle", |
| 403 @"at end\0", |
| 404 ]; |
| 405 int i = 0; |
| 406 for (NSString *str in strs) { |
| 407 NSData *asUTF8 = [str dataUsingEncoding:NSUTF8StringEncoding]; |
| 408 NSMutableData *expected = [NSMutableData data]; |
| 409 uint8_t lengthByte = (uint8_t)asUTF8.length; |
| 410 [expected appendBytes:&lengthByte length:1]; |
| 411 [expected appendData:asUTF8]; |
| 412 |
| 413 NSString *context = [NSString stringWithFormat:@"Loop %d - Literal", i]; |
| 414 [self assertWriteStringNoTag:expected value:str context:context]; |
| 415 |
| 416 // Force a new string to be built which gets a different class from the |
| 417 // NSString class cluster than the literal did. |
| 418 NSString *str2 = [NSString stringWithFormat:@"%@", str]; |
| 419 context = [NSString stringWithFormat:@"Loop %d - Built", i]; |
| 420 [self assertWriteStringNoTag:expected value:str2 context:context]; |
| 421 |
| 422 ++i; |
| 423 } |
| 424 } |
| 425 |
340 @end | 426 @end |
OLD | NEW |