GPBStringTests.m 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 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. #import <XCTest/XCTest.h>
  31. #import "GPBCodedInputStream_PackagePrivate.h"
  32. #ifndef GPBARRAYSIZE
  33. #define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))))
  34. #endif // GPBARRAYSIZE
  35. @interface TestClass : NSObject
  36. @property(nonatomic, retain) NSString *foo;
  37. @end
  38. @implementation TestClass
  39. @synthesize foo;
  40. @end
  41. @interface GPBStringTests : XCTestCase {
  42. NSMutableArray *nsStrings_;
  43. NSMutableArray *gpbStrings_;
  44. }
  45. @end
  46. @implementation GPBStringTests
  47. - (void)setUp {
  48. [super setUp];
  49. const char *strings[] = {
  50. "ascii string",
  51. "non-ascii string \xc3\xa9", // e with acute accent
  52. "\xe2\x99\xa1", // White Heart
  53. "mix \xe2\x99\xa4 string", // White Spade
  54. // Decomposed forms from http://www.unicode.org/reports/tr15/
  55. // 1.2 Singletons
  56. "\xe2\x84\xa8 = A\xcc\x8a = \xc3\x85", "\xe2\x84\xa6 = \xce\xa9",
  57. // 1.2 Canonical Composites
  58. "A\xcc\x8a = \xc3\x85",
  59. "o\xcc\x82 = \xc3\xb4",
  60. // 1.2 Multiple Combining Marks
  61. "s\xcc\xa3\xcc\x87 = \xe1\xb9\xa9",
  62. "\xe1\xb8\x8b\xcc\xa3 = d\xcc\xa3\xcc\x87 = \xe1\xb8\x8d \xcc\x87",
  63. "q\xcc\x87\xcc\xa3 = q\xcc\xa3\xcc\x87",
  64. // BOM
  65. "\xEF\xBB\xBF String with BOM",
  66. "String with \xEF\xBB\xBF in middle",
  67. "String with end bom \xEF\xBB\xBF",
  68. "\xEF\xBB\xBF\xe2\x99\xa1", // BOM White Heart
  69. "\xEF\xBB\xBF\xEF\xBB\xBF String with Two BOM",
  70. // Supplementary Plane
  71. "\xf0\x9d\x84\x9e", // MUSICAL SYMBOL G CLEF
  72. // Tags
  73. "\xf3\xa0\x80\x81", // Language Tag
  74. // Variation Selectors
  75. "\xf3\xa0\x84\x80", // VARIATION SELECTOR-17
  76. // Specials
  77. "\xef\xbb\xbf\xef\xbf\xbd\xef\xbf\xbf",
  78. // Left To Right/Right To Left
  79. // http://unicode.org/reports/tr9/
  80. // Hello! <RTL marker>!Merhaba<LTR marker>
  81. "Hello! \xE2\x80\x8F!\xd9\x85\xd8\xb1\xd8\xad\xd8\xa8\xd8\xa7\xE2\x80\x8E",
  82. "\xE2\x80\x8E LTR At Start",
  83. "LTR At End\xE2\x80\x8E",
  84. "\xE2\x80\x8F RTL At Start",
  85. "RTL At End\xE2\x80\x8F",
  86. "\xE2\x80\x8E\xE2\x80\x8E Double LTR \xE2\x80\x8E\xE2\x80\x8E",
  87. "\xE2\x80\x8F\xE2\x80\x8F Double RTL \xE2\x80\x8F\xE2\x80\x8F",
  88. "\xE2\x80\x8F\xE2\x80\x8E LTR-RTL LTR-RTL \xE2\x80\x8E\xE2\x80\x8F",
  89. };
  90. size_t stringsSize = GPBARRAYSIZE(strings);
  91. size_t numberUnicodeStrings = 17375;
  92. nsStrings_ = [[NSMutableArray alloc]
  93. initWithCapacity:stringsSize + numberUnicodeStrings];
  94. gpbStrings_ = [[NSMutableArray alloc]
  95. initWithCapacity:stringsSize + numberUnicodeStrings];
  96. for (size_t i = 0; i < stringsSize; ++i) {
  97. size_t length = strlen(strings[i]);
  98. NSString *nsString = [[NSString alloc] initWithBytes:strings[i]
  99. length:length
  100. encoding:NSUTF8StringEncoding];
  101. [nsStrings_ addObject:nsString];
  102. [nsString release];
  103. GPBString *gpbString = GPBCreateGPBStringWithUTF8(strings[i], length);
  104. [gpbStrings_ addObject:gpbString];
  105. [gpbString release];
  106. }
  107. // Generate all UTF8 characters in a variety of strings
  108. // UTF8-1 - 1 Byte UTF 8 chars
  109. int length = 0x7F + 1;
  110. char *buffer = (char *)calloc(length, 1);
  111. for (int i = 0; i < length; ++i) {
  112. buffer[i] = (char)i;
  113. }
  114. NSString *nsString = [[NSString alloc] initWithBytes:buffer
  115. length:length
  116. encoding:NSUTF8StringEncoding];
  117. [nsStrings_ addObject:nsString];
  118. [nsString release];
  119. GPBString *gpbString = GPBCreateGPBStringWithUTF8(buffer, length);
  120. [gpbStrings_ addObject:gpbString];
  121. [gpbString release];
  122. // UTF8-2 - 2 Byte UTF 8 chars
  123. int pointLength = 0xbf - 0x80 + 1;
  124. length = pointLength * 2;
  125. buffer = (char *)calloc(length, 1);
  126. for (int i = 0xc2; i <= 0xdf; ++i) {
  127. char *bufferPtr = buffer;
  128. for (int j = 0x80; j <= 0xbf; ++j) {
  129. (*bufferPtr++) = (char)i;
  130. (*bufferPtr++) = (char)j;
  131. }
  132. nsString = [[NSString alloc] initWithBytes:buffer
  133. length:length
  134. encoding:NSUTF8StringEncoding];
  135. [nsStrings_ addObject:nsString];
  136. [nsString release];
  137. gpbString = GPBCreateGPBStringWithUTF8(buffer, length);
  138. [gpbStrings_ addObject:gpbString];
  139. [gpbString release];
  140. }
  141. free(buffer);
  142. // UTF8-3 - 3 Byte UTF 8 chars
  143. length = pointLength * 3;
  144. buffer = (char *)calloc(length, 1);
  145. for (int i = 0xa0; i <= 0xbf; ++i) {
  146. char *bufferPtr = buffer;
  147. for (int j = 0x80; j <= 0xbf; ++j) {
  148. (*bufferPtr++) = (char)0xE0;
  149. (*bufferPtr++) = (char)i;
  150. (*bufferPtr++) = (char)j;
  151. }
  152. nsString = [[NSString alloc] initWithBytes:buffer
  153. length:length
  154. encoding:NSUTF8StringEncoding];
  155. [nsStrings_ addObject:nsString];
  156. [nsString release];
  157. gpbString = GPBCreateGPBStringWithUTF8(buffer, length);
  158. [gpbStrings_ addObject:gpbString];
  159. [gpbString release];
  160. }
  161. for (int i = 0xe1; i <= 0xec; ++i) {
  162. for (int j = 0x80; j <= 0xbf; ++j) {
  163. char *bufferPtr = buffer;
  164. for (int k = 0x80; k <= 0xbf; ++k) {
  165. (*bufferPtr++) = (char)i;
  166. (*bufferPtr++) = (char)j;
  167. (*bufferPtr++) = (char)k;
  168. }
  169. nsString = [[NSString alloc] initWithBytes:buffer
  170. length:length
  171. encoding:NSUTF8StringEncoding];
  172. [nsStrings_ addObject:nsString];
  173. [nsString release];
  174. gpbString = GPBCreateGPBStringWithUTF8(buffer, length);
  175. [gpbStrings_ addObject:gpbString];
  176. [gpbString release];
  177. }
  178. }
  179. for (int i = 0x80; i <= 0x9f; ++i) {
  180. char *bufferPtr = buffer;
  181. for (int j = 0x80; j <= 0xbf; ++j) {
  182. (*bufferPtr++) = (char)0xED;
  183. (*bufferPtr++) = (char)i;
  184. (*bufferPtr++) = (char)j;
  185. }
  186. nsString = [[NSString alloc] initWithBytes:buffer
  187. length:length
  188. encoding:NSUTF8StringEncoding];
  189. [nsStrings_ addObject:nsString];
  190. [nsString release];
  191. gpbString = GPBCreateGPBStringWithUTF8(buffer, length);
  192. [gpbStrings_ addObject:gpbString];
  193. [gpbString release];
  194. }
  195. for (int i = 0xee; i <= 0xef; ++i) {
  196. for (int j = 0x80; j <= 0xbf; ++j) {
  197. char *bufferPtr = buffer;
  198. for (int k = 0x80; k <= 0xbf; ++k) {
  199. (*bufferPtr++) = (char)i;
  200. (*bufferPtr++) = (char)j;
  201. (*bufferPtr++) = (char)k;
  202. }
  203. nsString = [[NSString alloc] initWithBytes:buffer
  204. length:length
  205. encoding:NSUTF8StringEncoding];
  206. [nsStrings_ addObject:nsString];
  207. [nsString release];
  208. gpbString = GPBCreateGPBStringWithUTF8(buffer, length);
  209. [gpbStrings_ addObject:gpbString];
  210. [gpbString release];
  211. }
  212. }
  213. free(buffer);
  214. // UTF8-4 - 4 Byte UTF 8 chars
  215. length = pointLength * 4;
  216. buffer = (char *)calloc(length, 1);
  217. for (int i = 0x90; i <= 0xbf; ++i) {
  218. for (int j = 0x80; j <= 0xbf; ++j) {
  219. char *bufferPtr = buffer;
  220. for (int k = 0x80; k <= 0xbf; ++k) {
  221. (*bufferPtr++) = (char)0xF0;
  222. (*bufferPtr++) = (char)i;
  223. (*bufferPtr++) = (char)j;
  224. (*bufferPtr++) = (char)k;
  225. }
  226. nsString = [[NSString alloc] initWithBytes:buffer
  227. length:length
  228. encoding:NSUTF8StringEncoding];
  229. [nsStrings_ addObject:nsString];
  230. [nsString release];
  231. gpbString = GPBCreateGPBStringWithUTF8(buffer, length);
  232. [gpbStrings_ addObject:gpbString];
  233. [gpbString release];
  234. }
  235. }
  236. for (int i = 0xf1; i <= 0xf3; ++i) {
  237. for (int j = 0x80; j <= 0xbf; ++j) {
  238. for (int k = 0x80; k <= 0xbf; ++k) {
  239. char *bufferPtr = buffer;
  240. for (int m = 0x80; m <= 0xbf; ++m) {
  241. (*bufferPtr++) = (char)i;
  242. (*bufferPtr++) = (char)j;
  243. (*bufferPtr++) = (char)k;
  244. (*bufferPtr++) = (char)m;
  245. }
  246. nsString = [[NSString alloc] initWithBytes:buffer
  247. length:length
  248. encoding:NSUTF8StringEncoding];
  249. [nsStrings_ addObject:nsString];
  250. [nsString release];
  251. gpbString = GPBCreateGPBStringWithUTF8(buffer, length);
  252. [gpbStrings_ addObject:gpbString];
  253. [gpbString release];
  254. }
  255. }
  256. }
  257. for (int i = 0x80; i <= 0x8f; ++i) {
  258. for (int j = 0x80; j <= 0xbf; ++j) {
  259. char *bufferPtr = buffer;
  260. for (int k = 0x80; k <= 0xbf; ++k) {
  261. (*bufferPtr++) = (char)0xF4;
  262. (*bufferPtr++) = (char)i;
  263. (*bufferPtr++) = (char)j;
  264. (*bufferPtr++) = (char)k;
  265. }
  266. nsString = [[NSString alloc] initWithBytes:buffer
  267. length:length
  268. encoding:NSUTF8StringEncoding];
  269. [nsStrings_ addObject:nsString];
  270. [nsString release];
  271. gpbString = GPBCreateGPBStringWithUTF8(buffer, length);
  272. [gpbStrings_ addObject:gpbString];
  273. [gpbString release];
  274. }
  275. }
  276. free(buffer);
  277. }
  278. - (void)tearDown {
  279. [nsStrings_ release];
  280. [gpbStrings_ release];
  281. [super tearDown];
  282. }
  283. - (void)testLength {
  284. size_t i = 0;
  285. for (NSString *nsString in nsStrings_) {
  286. GPBString *gpbString = gpbStrings_[i];
  287. XCTAssertEqual([nsString length], [gpbString length], @"%@ %@", nsString,
  288. gpbString);
  289. ++i;
  290. }
  291. }
  292. - (void)testLengthOfBytesUsingEncoding {
  293. NSStringEncoding encodings[] = {
  294. NSUTF8StringEncoding,
  295. NSASCIIStringEncoding,
  296. NSISOLatin1StringEncoding,
  297. NSMacOSRomanStringEncoding,
  298. NSUTF16StringEncoding,
  299. NSUTF32StringEncoding,
  300. };
  301. for (size_t j = 0; j < GPBARRAYSIZE(encodings); ++j) {
  302. NSStringEncoding testEncoding = encodings[j];
  303. size_t i = 0;
  304. for (NSString *nsString in nsStrings_) {
  305. GPBString *gpbString = gpbStrings_[i];
  306. XCTAssertEqual([nsString lengthOfBytesUsingEncoding:testEncoding],
  307. [gpbString lengthOfBytesUsingEncoding:testEncoding],
  308. @"%@ %@", nsString, gpbString);
  309. ++i;
  310. }
  311. }
  312. }
  313. - (void)testHash {
  314. size_t i = 0;
  315. for (NSString *nsString in nsStrings_) {
  316. GPBString *gpbString = gpbStrings_[i];
  317. XCTAssertEqual([nsString hash], [gpbString hash], @"%@ %@", nsString,
  318. gpbString);
  319. ++i;
  320. }
  321. }
  322. - (void)testEquality {
  323. size_t i = 0;
  324. for (NSString *nsString in nsStrings_) {
  325. GPBString *gpbString = gpbStrings_[i];
  326. XCTAssertEqualObjects(nsString, gpbString);
  327. ++i;
  328. }
  329. }
  330. - (void)testCharacterAtIndex {
  331. size_t i = 0;
  332. for (NSString *nsString in nsStrings_) {
  333. GPBString *gpbString = gpbStrings_[i];
  334. NSUInteger length = [nsString length];
  335. for (size_t j = 0; j < length; ++j) {
  336. unichar nsChar = [nsString characterAtIndex:j];
  337. unichar pbChar = [gpbString characterAtIndex:j];
  338. XCTAssertEqual(nsChar, pbChar, @"%@ %@ %zu", nsString, gpbString, j);
  339. }
  340. ++i;
  341. }
  342. }
  343. - (void)testCopy {
  344. size_t i = 0;
  345. for (NSString *nsString in nsStrings_) {
  346. GPBString *gpbString = [[gpbStrings_[i] copy] autorelease];
  347. XCTAssertEqualObjects(nsString, gpbString);
  348. ++i;
  349. }
  350. }
  351. - (void)testMutableCopy {
  352. size_t i = 0;
  353. for (NSString *nsString in nsStrings_) {
  354. GPBString *gpbString = [[gpbStrings_[i] mutableCopy] autorelease];
  355. XCTAssertEqualObjects(nsString, gpbString);
  356. ++i;
  357. }
  358. }
  359. - (void)testGetBytes {
  360. // Do an attempt at a reasonably exhaustive test of get bytes.
  361. // Get bytes with options other than 0 should always fall through to Apple
  362. // code so we don't bother testing that path.
  363. size_t i = 0;
  364. char pbBuffer[256];
  365. char nsBuffer[256];
  366. int count = 0;
  367. for (NSString *nsString in nsStrings_) {
  368. GPBString *gpbString = gpbStrings_[i];
  369. for (int j = 0; j < 100; ++j) {
  370. // [NSString getBytes:maxLength:usedLength:encoding:options:range:remainingRange]
  371. // does not return reliable results if the maxLength argument is 0,
  372. // or range is 0,0.
  373. // Radar 16385183
  374. NSUInteger length = [nsString length];
  375. NSUInteger maxBufferCount = (arc4random() % (length + 3)) + 1;
  376. NSUInteger rangeStart = arc4random() % length;
  377. NSUInteger rangeLength = arc4random() % (length - rangeStart);
  378. NSRange range = NSMakeRange(rangeStart, rangeLength);
  379. NSStringEncoding encodings[] = {
  380. NSASCIIStringEncoding,
  381. NSUTF8StringEncoding,
  382. NSUTF16StringEncoding,
  383. };
  384. for (size_t k = 0; k < GPBARRAYSIZE(encodings); ++k) {
  385. NSStringEncoding encoding = encodings[k];
  386. NSUInteger pbUsedBufferCount = 0;
  387. NSUInteger nsUsedBufferCount = 0;
  388. NSRange pbLeftOver = NSMakeRange(0, 0);
  389. NSRange nsLeftOver = NSMakeRange(0, 0);
  390. BOOL pbGotBytes = [gpbString getBytes:pbBuffer
  391. maxLength:maxBufferCount
  392. usedLength:&pbUsedBufferCount
  393. encoding:encoding
  394. options:0
  395. range:range
  396. remainingRange:&pbLeftOver];
  397. BOOL nsGotBytes = [nsString getBytes:nsBuffer
  398. maxLength:maxBufferCount
  399. usedLength:&nsUsedBufferCount
  400. encoding:encoding
  401. options:0
  402. range:range
  403. remainingRange:&nsLeftOver];
  404. XCTAssertEqual(
  405. (bool)pbGotBytes, (bool)nsGotBytes,
  406. @"PB %d '%@' vs '%@' Encoding:%tu MaxLength: %tu Range: %@ "
  407. @"Used: %tu, %tu LeftOver %@, %@)",
  408. count, gpbString, nsString, encoding, maxBufferCount,
  409. NSStringFromRange(range), pbUsedBufferCount, nsUsedBufferCount,
  410. NSStringFromRange(pbLeftOver), NSStringFromRange(nsLeftOver));
  411. XCTAssertEqual(
  412. pbUsedBufferCount, nsUsedBufferCount,
  413. @"PB %d '%@' vs '%@' Encoding:%tu MaxLength: %tu Range: %@ "
  414. @"Used: %tu, %tu LeftOver %@, %@)",
  415. count, gpbString, nsString, encoding, maxBufferCount,
  416. NSStringFromRange(range), pbUsedBufferCount, nsUsedBufferCount,
  417. NSStringFromRange(pbLeftOver), NSStringFromRange(nsLeftOver));
  418. XCTAssertEqual(
  419. pbLeftOver.location, nsLeftOver.location,
  420. @"PB %d '%@' vs '%@' Encoding:%tu MaxLength: %tu Range: %@ "
  421. @"Used: %tu, %tu LeftOver %@, %@)",
  422. count, gpbString, nsString, encoding, maxBufferCount,
  423. NSStringFromRange(range), pbUsedBufferCount, nsUsedBufferCount,
  424. NSStringFromRange(pbLeftOver), NSStringFromRange(nsLeftOver));
  425. XCTAssertEqual(
  426. pbLeftOver.length, nsLeftOver.length,
  427. @"PB %d '%@' vs '%@' Encoding:%tu MaxLength: %tu Range: %@ "
  428. @"Used: %tu, %tu LeftOver %@, %@)",
  429. count, gpbString, nsString, encoding, maxBufferCount,
  430. NSStringFromRange(range), pbUsedBufferCount, nsUsedBufferCount,
  431. NSStringFromRange(pbLeftOver), NSStringFromRange(nsLeftOver));
  432. ++count;
  433. }
  434. }
  435. ++i;
  436. }
  437. }
  438. - (void)testLengthAndGetBytes {
  439. // This test exists as an attempt to ferret out a bug.
  440. // http://b/13516532
  441. size_t i = 0;
  442. char pbBuffer[256];
  443. char nsBuffer[256];
  444. for (NSString *nsString in nsStrings_) {
  445. GPBString *gpbString = gpbStrings_[i++];
  446. NSUInteger nsLength =
  447. [nsString lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
  448. NSUInteger pbLength =
  449. [gpbString lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
  450. XCTAssertEqual(nsLength, pbLength, @"%@ %@", nsString, gpbString);
  451. NSUInteger pbUsedBufferCount = 0;
  452. NSUInteger nsUsedBufferCount = 0;
  453. NSRange pbLeftOver = NSMakeRange(0, 0);
  454. NSRange nsLeftOver = NSMakeRange(0, 0);
  455. NSRange range = NSMakeRange(0, [gpbString length]);
  456. BOOL pbGotBytes = [gpbString getBytes:pbBuffer
  457. maxLength:sizeof(pbBuffer)
  458. usedLength:&pbUsedBufferCount
  459. encoding:NSUTF8StringEncoding
  460. options:0
  461. range:range
  462. remainingRange:&pbLeftOver];
  463. BOOL nsGotBytes = [nsString getBytes:nsBuffer
  464. maxLength:sizeof(nsBuffer)
  465. usedLength:&nsUsedBufferCount
  466. encoding:NSUTF8StringEncoding
  467. options:0
  468. range:range
  469. remainingRange:&nsLeftOver];
  470. XCTAssertTrue(pbGotBytes, @"%@", gpbString);
  471. XCTAssertTrue(nsGotBytes, @"%@", nsString);
  472. XCTAssertEqual(pbUsedBufferCount, pbLength, @"%@", gpbString);
  473. XCTAssertEqual(nsUsedBufferCount, nsLength, @"%@", nsString);
  474. }
  475. }
  476. @end