| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513 | // Protocol Buffers - Google's data interchange format// Copyright 2008 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 <XCTest/XCTest.h>#import "GPBCodedInputStream_PackagePrivate.h"#import "GPBTestUtilities.h"@interface TestClass : NSObject@property(nonatomic, retain) NSString *foo;@end@implementation TestClass@synthesize foo;@end@interface GPBStringTests : XCTestCase {  NSMutableArray *nsStrings_;  NSMutableArray *gpbStrings_;}@end@implementation GPBStringTests- (void)setUp {  [super setUp];  const char *strings[] = {      "ascii string",      "non-ascii string \xc3\xa9",  // e with acute accent      "\xe2\x99\xa1",               // White Heart      "mix \xe2\x99\xa4 string",    // White Spade      // Decomposed forms from http://www.unicode.org/reports/tr15/      // 1.2 Singletons      "\xe2\x84\xa8 = A\xcc\x8a = \xc3\x85", "\xe2\x84\xa6 = \xce\xa9",      // 1.2 Canonical Composites      "A\xcc\x8a = \xc3\x85",      "o\xcc\x82 = \xc3\xb4",      // 1.2 Multiple Combining Marks      "s\xcc\xa3\xcc\x87 = \xe1\xb9\xa9",      "\xe1\xb8\x8b\xcc\xa3 = d\xcc\xa3\xcc\x87 = \xe1\xb8\x8d \xcc\x87",      "q\xcc\x87\xcc\xa3 = q\xcc\xa3\xcc\x87",      // BOM      "\xEF\xBB\xBF String with BOM",      "String with \xEF\xBB\xBF in middle",      "String with end bom \xEF\xBB\xBF",      "\xEF\xBB\xBF\xe2\x99\xa1",  // BOM White Heart      "\xEF\xBB\xBF\xEF\xBB\xBF String with Two BOM",      // Supplementary Plane      "\xf0\x9d\x84\x9e",  // MUSICAL SYMBOL G CLEF      // Tags      "\xf3\xa0\x80\x81",  // Language Tag      // Variation Selectors      "\xf3\xa0\x84\x80",  // VARIATION SELECTOR-17      // Specials      "\xef\xbb\xbf\xef\xbf\xbd\xef\xbf\xbf",      // Left To Right/Right To Left      // http://unicode.org/reports/tr9/      // Hello! <RTL marker>!Merhaba<LTR marker>      "Hello! \xE2\x80\x8F!\xd9\x85\xd8\xb1\xd8\xad\xd8\xa8\xd8\xa7\xE2\x80\x8E",      "\xE2\x80\x8E LTR At Start",      "LTR At End\xE2\x80\x8E",      "\xE2\x80\x8F RTL At Start",      "RTL At End\xE2\x80\x8F",      "\xE2\x80\x8E\xE2\x80\x8E Double LTR \xE2\x80\x8E\xE2\x80\x8E",      "\xE2\x80\x8F\xE2\x80\x8F Double RTL \xE2\x80\x8F\xE2\x80\x8F",      "\xE2\x80\x8F\xE2\x80\x8E LTR-RTL LTR-RTL \xE2\x80\x8E\xE2\x80\x8F",  };  size_t stringsSize = GPBARRAYSIZE(strings);  size_t numberUnicodeStrings = 17375;  nsStrings_ = [[NSMutableArray alloc]      initWithCapacity:stringsSize + numberUnicodeStrings];  gpbStrings_ = [[NSMutableArray alloc]      initWithCapacity:stringsSize + numberUnicodeStrings];  for (size_t i = 0; i < stringsSize; ++i) {    size_t length = strlen(strings[i]);    NSString *nsString = [[NSString alloc] initWithBytes:strings[i]                                                  length:length                                                encoding:NSUTF8StringEncoding];    [nsStrings_ addObject:nsString];    [nsString release];    GPBString *gpbString = GPBCreateGPBStringWithUTF8(strings[i], length);    [gpbStrings_ addObject:gpbString];    [gpbString release];  }  // Generate all UTF8 characters in a variety of strings  // UTF8-1 - 1 Byte UTF 8 chars  int length = 0x7F + 1;  char *buffer = (char *)calloc(length, 1);  for (int i = 0; i < length; ++i) {    buffer[i] = (char)i;  }  NSString *nsString = [[NSString alloc] initWithBytes:buffer                                                length:length                                              encoding:NSUTF8StringEncoding];  [nsStrings_ addObject:nsString];  [nsString release];  GPBString *gpbString = GPBCreateGPBStringWithUTF8(buffer, length);  [gpbStrings_ addObject:gpbString];  [gpbString release];  // UTF8-2 - 2 Byte UTF 8 chars  int pointLength = 0xbf - 0x80 + 1;  length = pointLength * 2;  buffer = (char *)calloc(length, 1);  for (int i = 0xc2; i <= 0xdf; ++i) {    char *bufferPtr = buffer;    for (int j = 0x80; j <= 0xbf; ++j) {      (*bufferPtr++) = (char)i;      (*bufferPtr++) = (char)j;    }    nsString = [[NSString alloc] initWithBytes:buffer                                        length:length                                      encoding:NSUTF8StringEncoding];    [nsStrings_ addObject:nsString];    [nsString release];    gpbString = GPBCreateGPBStringWithUTF8(buffer, length);    [gpbStrings_ addObject:gpbString];    [gpbString release];  }  free(buffer);  // UTF8-3 - 3 Byte UTF 8 chars  length = pointLength * 3;  buffer = (char *)calloc(length, 1);  for (int i = 0xa0; i <= 0xbf; ++i) {    char *bufferPtr = buffer;    for (int j = 0x80; j <= 0xbf; ++j) {      (*bufferPtr++) = (char)0xE0;      (*bufferPtr++) = (char)i;      (*bufferPtr++) = (char)j;    }    nsString = [[NSString alloc] initWithBytes:buffer                                        length:length                                      encoding:NSUTF8StringEncoding];    [nsStrings_ addObject:nsString];    [nsString release];    gpbString = GPBCreateGPBStringWithUTF8(buffer, length);    [gpbStrings_ addObject:gpbString];    [gpbString release];  }  for (int i = 0xe1; i <= 0xec; ++i) {    for (int j = 0x80; j <= 0xbf; ++j) {      char *bufferPtr = buffer;      for (int k = 0x80; k <= 0xbf; ++k) {        (*bufferPtr++) = (char)i;        (*bufferPtr++) = (char)j;        (*bufferPtr++) = (char)k;      }      nsString = [[NSString alloc] initWithBytes:buffer                                          length:length                                        encoding:NSUTF8StringEncoding];      [nsStrings_ addObject:nsString];      [nsString release];      gpbString = GPBCreateGPBStringWithUTF8(buffer, length);      [gpbStrings_ addObject:gpbString];      [gpbString release];    }  }  for (int i = 0x80; i <= 0x9f; ++i) {    char *bufferPtr = buffer;    for (int j = 0x80; j <= 0xbf; ++j) {      (*bufferPtr++) = (char)0xED;      (*bufferPtr++) = (char)i;      (*bufferPtr++) = (char)j;    }    nsString = [[NSString alloc] initWithBytes:buffer                                        length:length                                      encoding:NSUTF8StringEncoding];    [nsStrings_ addObject:nsString];    [nsString release];    gpbString = GPBCreateGPBStringWithUTF8(buffer, length);    [gpbStrings_ addObject:gpbString];    [gpbString release];  }  for (int i = 0xee; i <= 0xef; ++i) {    for (int j = 0x80; j <= 0xbf; ++j) {      char *bufferPtr = buffer;      for (int k = 0x80; k <= 0xbf; ++k) {        (*bufferPtr++) = (char)i;        (*bufferPtr++) = (char)j;        (*bufferPtr++) = (char)k;      }      nsString = [[NSString alloc] initWithBytes:buffer                                          length:length                                        encoding:NSUTF8StringEncoding];      [nsStrings_ addObject:nsString];      [nsString release];      gpbString = GPBCreateGPBStringWithUTF8(buffer, length);      [gpbStrings_ addObject:gpbString];      [gpbString release];    }  }  free(buffer);  // UTF8-4 - 4 Byte UTF 8 chars  length = pointLength * 4;  buffer = (char *)calloc(length, 1);  for (int i = 0x90; i <= 0xbf; ++i) {    for (int j = 0x80; j <= 0xbf; ++j) {      char *bufferPtr = buffer;      for (int k = 0x80; k <= 0xbf; ++k) {        (*bufferPtr++) = (char)0xF0;        (*bufferPtr++) = (char)i;        (*bufferPtr++) = (char)j;        (*bufferPtr++) = (char)k;      }      nsString = [[NSString alloc] initWithBytes:buffer                                          length:length                                        encoding:NSUTF8StringEncoding];      [nsStrings_ addObject:nsString];      [nsString release];      gpbString = GPBCreateGPBStringWithUTF8(buffer, length);      [gpbStrings_ addObject:gpbString];      [gpbString release];    }  }  for (int i = 0xf1; i <= 0xf3; ++i) {    for (int j = 0x80; j <= 0xbf; ++j) {      for (int k = 0x80; k <= 0xbf; ++k) {        char *bufferPtr = buffer;        for (int m = 0x80; m <= 0xbf; ++m) {          (*bufferPtr++) = (char)i;          (*bufferPtr++) = (char)j;          (*bufferPtr++) = (char)k;          (*bufferPtr++) = (char)m;        }        nsString = [[NSString alloc] initWithBytes:buffer                                            length:length                                          encoding:NSUTF8StringEncoding];        [nsStrings_ addObject:nsString];        [nsString release];        gpbString = GPBCreateGPBStringWithUTF8(buffer, length);        [gpbStrings_ addObject:gpbString];        [gpbString release];      }    }  }  for (int i = 0x80; i <= 0x8f; ++i) {    for (int j = 0x80; j <= 0xbf; ++j) {      char *bufferPtr = buffer;      for (int k = 0x80; k <= 0xbf; ++k) {        (*bufferPtr++) = (char)0xF4;        (*bufferPtr++) = (char)i;        (*bufferPtr++) = (char)j;        (*bufferPtr++) = (char)k;      }      nsString = [[NSString alloc] initWithBytes:buffer                                          length:length                                        encoding:NSUTF8StringEncoding];      [nsStrings_ addObject:nsString];      [nsString release];      gpbString = GPBCreateGPBStringWithUTF8(buffer, length);      [gpbStrings_ addObject:gpbString];      [gpbString release];    }  }  free(buffer);}- (void)tearDown {  [nsStrings_ release];  [gpbStrings_ release];  [super tearDown];}- (void)testLength {  size_t i = 0;  for (NSString *nsString in nsStrings_) {    GPBString *gpbString = gpbStrings_[i];    XCTAssertEqual([nsString length], [gpbString length], @"%@ %@", nsString,                   gpbString);    ++i;  }}- (void)testLengthOfBytesUsingEncoding {  NSStringEncoding encodings[] = {    NSUTF8StringEncoding,    NSASCIIStringEncoding,    NSISOLatin1StringEncoding,    NSMacOSRomanStringEncoding,    NSUTF16StringEncoding,    NSUTF32StringEncoding,  };  for (size_t j = 0; j < GPBARRAYSIZE(encodings); ++j) {    NSStringEncoding testEncoding = encodings[j];    size_t i = 0;    for (NSString *nsString in nsStrings_) {      GPBString *gpbString = gpbStrings_[i];      XCTAssertEqual([nsString lengthOfBytesUsingEncoding:testEncoding],                     [gpbString lengthOfBytesUsingEncoding:testEncoding],                     @"%@ %@", nsString, gpbString);      ++i;    }  }}- (void)testHash {  size_t i = 0;  for (NSString *nsString in nsStrings_) {    GPBString *gpbString = gpbStrings_[i];    XCTAssertEqual([nsString hash], [gpbString hash], @"%@ %@", nsString,                   gpbString);    ++i;  }}- (void)testEquality {  size_t i = 0;  for (NSString *nsString in nsStrings_) {    GPBString *gpbString = gpbStrings_[i];    XCTAssertEqualObjects(nsString, gpbString);    ++i;  }}- (void)testCharacterAtIndex {  size_t i = 0;  for (NSString *nsString in nsStrings_) {    GPBString *gpbString = gpbStrings_[i];    NSUInteger length = [nsString length];    for (size_t j = 0; j < length; ++j) {      unichar nsChar = [nsString characterAtIndex:j];      unichar pbChar = [gpbString characterAtIndex:j];      XCTAssertEqual(nsChar, pbChar, @"%@ %@ %zu", nsString, gpbString, j);    }    ++i;  }}- (void)testCopy {  size_t i = 0;  for (NSString *nsString in nsStrings_) {    GPBString *gpbString = [[gpbStrings_[i] copy] autorelease];    XCTAssertEqualObjects(nsString, gpbString);    ++i;  }}- (void)testMutableCopy {  size_t i = 0;  for (NSString *nsString in nsStrings_) {    GPBString *gpbString = [[gpbStrings_[i] mutableCopy] autorelease];    XCTAssertEqualObjects(nsString, gpbString);    ++i;  }}- (void)testGetBytes {  // Do an attempt at a reasonably exhaustive test of get bytes.  // Get bytes with options other than 0 should always fall through to Apple  // code so we don't bother testing that path.  size_t i = 0;  char pbBuffer[256];  char nsBuffer[256];  int count = 0;  for (NSString *nsString in nsStrings_) {    GPBString *gpbString = gpbStrings_[i];    for (int j = 0; j < 100; ++j) {      // [NSString getBytes:maxLength:usedLength:encoding:options:range:remainingRange]      // does not return reliable results if the maxLength argument is 0,      // or range is 0,0.      // Radar 16385183      NSUInteger length = [nsString length];      NSUInteger maxBufferCount = (arc4random() % (length + 3)) + 1;      NSUInteger rangeStart = arc4random() % length;      NSUInteger rangeLength = arc4random() % (length - rangeStart);      NSRange range = NSMakeRange(rangeStart, rangeLength);      NSStringEncoding encodings[] = {        NSASCIIStringEncoding,        NSUTF8StringEncoding,        NSUTF16StringEncoding,      };      for (size_t k = 0; k < GPBARRAYSIZE(encodings); ++k) {        NSStringEncoding encoding = encodings[k];        NSUInteger pbUsedBufferCount = 0;        NSUInteger nsUsedBufferCount = 0;        NSRange pbLeftOver = NSMakeRange(0, 0);        NSRange nsLeftOver = NSMakeRange(0, 0);        BOOL pbGotBytes = [gpbString getBytes:pbBuffer                                    maxLength:maxBufferCount                                   usedLength:&pbUsedBufferCount                                     encoding:encoding                                      options:0                                        range:range                               remainingRange:&pbLeftOver];        BOOL nsGotBytes = [nsString getBytes:nsBuffer                                   maxLength:maxBufferCount                                  usedLength:&nsUsedBufferCount                                    encoding:encoding                                     options:0                                       range:range                              remainingRange:&nsLeftOver];        XCTAssertEqual(            (bool)pbGotBytes, (bool)nsGotBytes,            @"PB %d '%@' vs '%@' Encoding:%tu MaxLength: %tu Range: %@ "            @"Used: %tu, %tu LeftOver %@, %@)",            count, gpbString, nsString, encoding, maxBufferCount,            NSStringFromRange(range), pbUsedBufferCount, nsUsedBufferCount,            NSStringFromRange(pbLeftOver), NSStringFromRange(nsLeftOver));        XCTAssertEqual(            pbUsedBufferCount, nsUsedBufferCount,            @"PB %d '%@' vs '%@' Encoding:%tu MaxLength: %tu Range: %@ "            @"Used: %tu, %tu LeftOver %@, %@)",            count, gpbString, nsString, encoding, maxBufferCount,            NSStringFromRange(range), pbUsedBufferCount, nsUsedBufferCount,            NSStringFromRange(pbLeftOver), NSStringFromRange(nsLeftOver));        XCTAssertEqual(            pbLeftOver.location, nsLeftOver.location,            @"PB %d '%@' vs '%@' Encoding:%tu MaxLength: %tu Range: %@ "            @"Used: %tu, %tu LeftOver %@, %@)",            count, gpbString, nsString, encoding, maxBufferCount,            NSStringFromRange(range), pbUsedBufferCount, nsUsedBufferCount,            NSStringFromRange(pbLeftOver), NSStringFromRange(nsLeftOver));        XCTAssertEqual(            pbLeftOver.length, nsLeftOver.length,            @"PB %d '%@' vs '%@' Encoding:%tu MaxLength: %tu Range: %@ "            @"Used: %tu, %tu LeftOver %@, %@)",            count, gpbString, nsString, encoding, maxBufferCount,            NSStringFromRange(range), pbUsedBufferCount, nsUsedBufferCount,            NSStringFromRange(pbLeftOver), NSStringFromRange(nsLeftOver));        ++count;      }    }    ++i;  }}- (void)testLengthAndGetBytes {  // This test exists as an attempt to ferret out a bug.  // http://b/13516532  size_t i = 0;  char pbBuffer[256];  char nsBuffer[256];  for (NSString *nsString in nsStrings_) {    GPBString *gpbString = gpbStrings_[i++];    NSUInteger nsLength =        [nsString lengthOfBytesUsingEncoding:NSUTF8StringEncoding];    NSUInteger pbLength =        [gpbString lengthOfBytesUsingEncoding:NSUTF8StringEncoding];    XCTAssertEqual(nsLength, pbLength, @"%@ %@", nsString, gpbString);    NSUInteger pbUsedBufferCount = 0;    NSUInteger nsUsedBufferCount = 0;    NSRange pbLeftOver = NSMakeRange(0, 0);    NSRange nsLeftOver = NSMakeRange(0, 0);    NSRange range = NSMakeRange(0, [gpbString length]);    BOOL pbGotBytes = [gpbString getBytes:pbBuffer                                maxLength:sizeof(pbBuffer)                               usedLength:&pbUsedBufferCount                                 encoding:NSUTF8StringEncoding                                  options:0                                    range:range                           remainingRange:&pbLeftOver];    BOOL nsGotBytes = [nsString getBytes:nsBuffer                               maxLength:sizeof(nsBuffer)                              usedLength:&nsUsedBufferCount                                encoding:NSUTF8StringEncoding                                 options:0                                   range:range                          remainingRange:&nsLeftOver];    XCTAssertTrue(pbGotBytes, @"%@", gpbString);    XCTAssertTrue(nsGotBytes, @"%@", nsString);    XCTAssertEqual(pbUsedBufferCount, pbLength, @"%@", gpbString);    XCTAssertEqual(nsUsedBufferCount, nsLength, @"%@", nsString);  }}@end
 |