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 | |
222 - (void)testWriteVarint1 { | 196 - (void)testWriteVarint1 { |
223 [self assertWriteVarint:bytes(0x00) value:0]; | 197 [self assertWriteVarint:bytes(0x00) value:0]; |
224 } | 198 } |
225 | 199 |
226 - (void)testWriteVarint2 { | 200 - (void)testWriteVarint2 { |
227 [self assertWriteVarint:bytes(0x01) value:1]; | 201 [self assertWriteVarint:bytes(0x01) value:1]; |
228 } | 202 } |
229 | 203 |
230 - (void)testWriteVarint3 { | 204 - (void)testWriteVarint3 { |
231 [self assertWriteVarint:bytes(0x7f) value:127]; | 205 [self assertWriteVarint:bytes(0x7f) value:127]; |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
356 | 330 |
357 // Not kGPBDefaultRepeatCount because we are comparing to a golden master file | 331 // Not kGPBDefaultRepeatCount because we are comparing to a golden master file |
358 // that was generated with 2. | 332 // that was generated with 2. |
359 TestAllExtensions* extensions = [self allExtensionsSetRepeatedCount:2]; | 333 TestAllExtensions* extensions = [self allExtensionsSetRepeatedCount:2]; |
360 rawBytes = extensions.data; | 334 rawBytes = extensions.data; |
361 goldenData = [self getDataFileNamed:@"golden_packed_fields_message" | 335 goldenData = [self getDataFileNamed:@"golden_packed_fields_message" |
362 dataToWrite:rawBytes]; | 336 dataToWrite:rawBytes]; |
363 XCTAssertEqualObjects(rawBytes, goldenData); | 337 XCTAssertEqualObjects(rawBytes, goldenData); |
364 } | 338 } |
365 | 339 |
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 | |
426 @end | 340 @end |
OLD | NEW |