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 31/** 32 * @fileoverview Test cases for jspb's helper functions. 33 * 34 * Test suite is written using Jasmine -- see http://jasmine.github.io/ 35 * 36 * @author aappleby@google.com (Austin Appleby) 37 */ 38 39goog.require('goog.crypt'); 40goog.require('goog.crypt.base64'); 41goog.require('jspb.BinaryConstants'); 42goog.require('jspb.BinaryWriter'); 43goog.require('jspb.utils'); 44 45 46/** 47 * @param {number} x 48 * @return {number} 49 */ 50function truncate(x) { 51 var temp = new Float32Array(1); 52 temp[0] = x; 53 return temp[0]; 54} 55 56 57/** 58 * Converts an 64-bit integer in split representation to a 64-bit hash string 59 * (8 bits encoded per character). 60 * @param {number} bitsLow The low 32 bits of the split 64-bit integer. 61 * @param {number} bitsHigh The high 32 bits of the split 64-bit integer. 62 * @return {string} The encoded hash string, 8 bits per character. 63 */ 64function toHashString(bitsLow, bitsHigh) { 65 return String.fromCharCode((bitsLow >>> 0) & 0xFF, 66 (bitsLow >>> 8) & 0xFF, 67 (bitsLow >>> 16) & 0xFF, 68 (bitsLow >>> 24) & 0xFF, 69 (bitsHigh >>> 0) & 0xFF, 70 (bitsHigh >>> 8) & 0xFF, 71 (bitsHigh >>> 16) & 0xFF, 72 (bitsHigh >>> 24) & 0xFF); 73} 74 75 76describe('binaryUtilsTest', function() { 77 /** 78 * Tests lossless binary-to-decimal conversion. 79 */ 80 it('testDecimalConversion', function() { 81 // Check some magic numbers. 82 var result = 83 jspb.utils.joinUnsignedDecimalString(0x89e80001, 0x8ac72304); 84 expect(result).toEqual('10000000000000000001'); 85 86 result = jspb.utils.joinUnsignedDecimalString(0xacd05f15, 0x1b69b4b); 87 expect(result).toEqual('123456789123456789'); 88 89 result = jspb.utils.joinUnsignedDecimalString(0xeb1f0ad2, 0xab54a98c); 90 expect(result).toEqual('12345678901234567890'); 91 92 result = jspb.utils.joinUnsignedDecimalString(0xe3b70cb1, 0x891087b8); 93 expect(result).toEqual('9876543210987654321'); 94 95 // Check limits. 96 result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00000000); 97 expect(result).toEqual('0'); 98 99 result = jspb.utils.joinUnsignedDecimalString(0xFFFFFFFF, 0xFFFFFFFF); 100 expect(result).toEqual('18446744073709551615'); 101 102 // Check each bit of the low dword. 103 for (var i = 0; i < 32; i++) { 104 var low = (1 << i) >>> 0; 105 result = jspb.utils.joinUnsignedDecimalString(low, 0); 106 expect(result).toEqual('' + Math.pow(2, i)); 107 } 108 109 // Check the first 20 bits of the high dword. 110 for (var i = 0; i < 20; i++) { 111 var high = (1 << i) >>> 0; 112 result = jspb.utils.joinUnsignedDecimalString(0, high); 113 expect(result).toEqual('' + Math.pow(2, 32 + i)); 114 } 115 116 // V8's internal double-to-string conversion is inaccurate for values above 117 // 2^52, even if they're representable integers - check the rest of the bits 118 // manually against the correct string representations of 2^N. 119 120 result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00100000); 121 expect(result).toEqual('4503599627370496'); 122 123 result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00200000); 124 expect(result).toEqual('9007199254740992'); 125 126 result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00400000); 127 expect(result).toEqual('18014398509481984'); 128 129 result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00800000); 130 expect(result).toEqual('36028797018963968'); 131 132 result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x01000000); 133 expect(result).toEqual('72057594037927936'); 134 135 result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x02000000); 136 expect(result).toEqual('144115188075855872'); 137 138 result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x04000000); 139 expect(result).toEqual('288230376151711744'); 140 141 result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x08000000); 142 expect(result).toEqual('576460752303423488'); 143 144 result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x10000000); 145 expect(result).toEqual('1152921504606846976'); 146 147 result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x20000000); 148 expect(result).toEqual('2305843009213693952'); 149 150 result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x40000000); 151 expect(result).toEqual('4611686018427387904'); 152 153 result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x80000000); 154 expect(result).toEqual('9223372036854775808'); 155 }); 156 157 158 /** 159 * Going from hash strings to decimal strings should also be lossless. 160 */ 161 it('testHashToDecimalConversion', function() { 162 var result; 163 var convert = jspb.utils.hash64ToDecimalString; 164 165 result = convert(toHashString(0x00000000, 0x00000000), false); 166 expect(result).toEqual('0'); 167 168 result = convert(toHashString(0x00000000, 0x00000000), true); 169 expect(result).toEqual('0'); 170 171 result = convert(toHashString(0xFFFFFFFF, 0xFFFFFFFF), false); 172 expect(result).toEqual('18446744073709551615'); 173 174 result = convert(toHashString(0xFFFFFFFF, 0xFFFFFFFF), true); 175 expect(result).toEqual('-1'); 176 177 result = convert(toHashString(0x00000000, 0x80000000), false); 178 expect(result).toEqual('9223372036854775808'); 179 180 result = convert(toHashString(0x00000000, 0x80000000), true); 181 expect(result).toEqual('-9223372036854775808'); 182 183 result = convert(toHashString(0xacd05f15, 0x01b69b4b), false); 184 expect(result).toEqual('123456789123456789'); 185 186 result = convert(toHashString(~0xacd05f15 + 1, ~0x01b69b4b), true); 187 expect(result).toEqual('-123456789123456789'); 188 189 // And converting arrays of hashes should work the same way. 190 result = jspb.utils.hash64ArrayToDecimalStrings([ 191 toHashString(0xFFFFFFFF, 0xFFFFFFFF), 192 toHashString(0x00000000, 0x80000000), 193 toHashString(0xacd05f15, 0x01b69b4b)], false); 194 expect(result.length).toEqual(3); 195 expect(result[0]).toEqual('18446744073709551615'); 196 expect(result[1]).toEqual('9223372036854775808'); 197 expect(result[2]).toEqual('123456789123456789'); 198 }); 199 200 /* 201 * Going from decimal strings to hash strings should be lossless. 202 */ 203 it('testDecimalToHashConversion', function() { 204 var result; 205 var convert = jspb.utils.decimalStringToHash64; 206 207 result = convert('0'); 208 expect(result).toEqual(goog.crypt.byteArrayToString( 209 [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])); 210 211 result = convert('-1'); 212 expect(result).toEqual(goog.crypt.byteArrayToString( 213 [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])); 214 215 result = convert('18446744073709551615'); 216 expect(result).toEqual(goog.crypt.byteArrayToString( 217 [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])); 218 219 result = convert('9223372036854775808'); 220 expect(result).toEqual(goog.crypt.byteArrayToString( 221 [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80])); 222 223 result = convert('-9223372036854775808'); 224 expect(result).toEqual(goog.crypt.byteArrayToString( 225 [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80])); 226 227 result = convert('123456789123456789'); 228 expect(result).toEqual(goog.crypt.byteArrayToString( 229 [0x15, 0x5F, 0xD0, 0xAC, 0x4B, 0x9B, 0xB6, 0x01])); 230 231 result = convert('-123456789123456789'); 232 expect(result).toEqual(goog.crypt.byteArrayToString( 233 [0xEB, 0xA0, 0x2F, 0x53, 0xB4, 0x64, 0x49, 0xFE])); 234 }); 235 236 /** 237 * Going from hash strings to hex strings should be lossless. 238 */ 239 it('testHashToHexConversion', function() { 240 var result; 241 var convert = jspb.utils.hash64ToHexString; 242 243 result = convert(toHashString(0x00000000, 0x00000000)); 244 expect(result).toEqual('0x0000000000000000'); 245 246 result = convert(toHashString(0xFFFFFFFF, 0xFFFFFFFF)); 247 expect(result).toEqual('0xffffffffffffffff'); 248 249 result = convert(toHashString(0x12345678, 0x9ABCDEF0)); 250 expect(result).toEqual('0x9abcdef012345678'); 251 }); 252 253 254 /** 255 * Going from hex strings to hash strings should be lossless. 256 */ 257 it('testHexToHashConversion', function() { 258 var result; 259 var convert = jspb.utils.hexStringToHash64; 260 261 result = convert('0x0000000000000000'); 262 expect(result).toEqual(goog.crypt.byteArrayToString( 263 [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])); 264 265 result = convert('0xffffffffffffffff'); 266 expect(result).toEqual(goog.crypt.byteArrayToString( 267 [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])); 268 269 // Hex string is big-endian, hash string is little-endian. 270 result = convert('0x123456789ABCDEF0'); 271 expect(result).toEqual(goog.crypt.byteArrayToString( 272 [0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12])); 273 274 // Capitalization should not matter. 275 result = convert('0x0000abcdefABCDEF'); 276 expect(result).toEqual(goog.crypt.byteArrayToString( 277 [0xEF, 0xCD, 0xAB, 0xEF, 0xCD, 0xAB, 0x00, 0x00])); 278 }); 279 280 281 /** 282 * Going from numbers to hash strings should be lossless for up to 53 bits of 283 * precision. 284 */ 285 it('testNumberToHashConversion', function() { 286 var result; 287 var convert = jspb.utils.numberToHash64; 288 289 result = convert(0x0000000000000); 290 expect(jspb.utils.hash64ToHexString(result)).toEqual('0x0000000000000000'); 291 292 result = convert(0xFFFFFFFFFFFFF); 293 expect(jspb.utils.hash64ToHexString(result)).toEqual('0x000fffffffffffff'); 294 295 result = convert(0x123456789ABCD); 296 expect(jspb.utils.hash64ToHexString(result)).toEqual('0x000123456789abcd'); 297 298 result = convert(0xDCBA987654321); 299 expect(jspb.utils.hash64ToHexString(result)).toEqual('0x000dcba987654321'); 300 301 // 53 bits of precision should not be truncated. 302 result = convert(0x10000000000001); 303 expect(jspb.utils.hash64ToHexString(result)).toEqual('0x0010000000000001'); 304 305 // 54 bits of precision should be truncated. 306 result = convert(0x20000000000001); 307 expect(jspb.utils.hash64ToHexString(result)) 308 .not.toEqual('0x0020000000000001'); 309 }); 310 311 312 /** 313 * Sanity check the behavior of Javascript's strings when doing funny things 314 * with unicode characters. 315 */ 316 it('sanityCheckUnicodeStrings', function() { 317 var strings = new Array(65536); 318 319 // All possible unsigned 16-bit values should be storable in a string, they 320 // shouldn't do weird things with the length of the string, and they should 321 // come back out of the string unchanged. 322 for (var i = 0; i < 65536; i++) { 323 strings[i] = 'a' + String.fromCharCode(i) + 'a'; 324 expect(strings[i].length).toEqual(3); 325 expect(strings[i].charCodeAt(1)).toEqual(i); 326 } 327 328 // Each unicode character should compare equal to itself and not equal to a 329 // different unicode character. 330 for (var i = 0; i < 65536; i++) { 331 expect(strings[i] == strings[i]).toEqual(true); 332 expect(strings[i] == strings[(i + 1) % 65536]).toEqual(false); 333 } 334 }); 335 336 337 /** 338 * Tests conversion from 32-bit floating point numbers to split64 numbers. 339 */ 340 it('testFloat32ToSplit64', function() { 341 var f32_eps = jspb.BinaryConstants.FLOAT32_EPS; 342 var f32_min = jspb.BinaryConstants.FLOAT32_MIN; 343 var f32_max = jspb.BinaryConstants.FLOAT32_MAX; 344 var f32_max_safe_int = jspb.utils.joinFloat32(0x4b7fffff, 0); 345 var f32_pi = Math.fround(Math.PI); 346 347 // NaN. 348 jspb.utils.splitFloat32(NaN); 349 expect(isNaN(jspb.utils.joinFloat32( 350 jspb.utils.split64Low, jspb.utils.split64High))) 351 .toEqual(true); 352 353 /** 354 * @param {number} x 355 * @param {number=} opt_bits 356 */ 357 function test(x, opt_bits) { 358 jspb.utils.splitFloat32(x); 359 if (opt_bits !== undefined) { 360 if (opt_bits != jspb.utils.split64Low) throw 'fail!'; 361 } 362 expect(truncate(x)) 363 .toEqual(jspb.utils.joinFloat32( 364 jspb.utils.split64Low, jspb.utils.split64High)); 365 } 366 367 // Positive and negative infinity. 368 test(Infinity, 0x7f800000); 369 test(-Infinity, 0xff800000); 370 371 // Positive and negative zero. 372 test(0, 0x00000000); 373 test(-0, 0x80000000); 374 375 // Positive and negative epsilon. 376 test(f32_eps, 0x00000001); 377 test(-f32_eps, 0x80000001); 378 379 // Positive and negative min. 380 test(f32_min, 0x00800000); 381 test(-f32_min, 0x80800000); 382 383 // Positive and negative max. 384 test(f32_max, 0x7F7FFFFF); 385 test(-f32_max, 0xFF7FFFFF); 386 387 // Positive and negative max_safe_int. 388 test(f32_max_safe_int, 0x4B7FFFFF); 389 test(-f32_max_safe_int, 0xCB7FFFFF); 390 391 // Pi. 392 test(f32_pi, 0x40490fdb); 393 394 // Various positive values. 395 var cursor = f32_eps * 10; 396 while (cursor != Infinity) { 397 test(cursor); 398 cursor *= 1.1; 399 } 400 401 // Various negative values. 402 cursor = -f32_eps * 10; 403 while (cursor != -Infinity) { 404 test(cursor); 405 cursor *= 1.1; 406 } 407 }); 408 409 410 /** 411 * Tests conversion from 64-bit floating point numbers to split64 numbers. 412 */ 413 it('testFloat64ToSplit64', function() { 414 var f64_eps = jspb.BinaryConstants.FLOAT64_EPS; 415 var f64_min = jspb.BinaryConstants.FLOAT64_MIN; 416 var f64_max = jspb.BinaryConstants.FLOAT64_MAX; 417 418 // NaN. 419 jspb.utils.splitFloat64(NaN); 420 expect(isNaN(jspb.utils.joinFloat64( 421 jspb.utils.split64Low, jspb.utils.split64High))) 422 .toEqual(true); 423 424 /** 425 * @param {number} x 426 * @param {number=} opt_highBits 427 * @param {number=} opt_lowBits 428 */ 429 function test(x, opt_highBits, opt_lowBits) { 430 jspb.utils.splitFloat64(x); 431 if (opt_highBits !== undefined) { 432 var split64High = jspb.utils.split64High; 433 expect(opt_highBits.toString(16)).toEqual(split64High.toString(16)); 434 } 435 if (opt_lowBits !== undefined) { 436 var split64Low = jspb.utils.split64Low; 437 expect(opt_lowBits.toString(16)).toEqual(split64Low.toString(16)); 438 } 439 expect( 440 jspb.utils.joinFloat64(jspb.utils.split64Low, jspb.utils.split64High)) 441 .toEqual(x); 442 } 443 444 // Positive and negative infinity. 445 test(Infinity, 0x7ff00000, 0x00000000); 446 test(-Infinity, 0xfff00000, 0x00000000); 447 448 // Positive and negative zero. 449 test(0, 0x00000000, 0x00000000); 450 test(-0, 0x80000000, 0x00000000); 451 452 test(1, 0x3FF00000, 0x00000000); 453 test(2, 0x40000000, 0x00000000); 454 455 // Positive and negative epsilon. 456 test(f64_eps, 0x00000000, 0x00000001); 457 test(-f64_eps, 0x80000000, 0x00000001); 458 459 // Positive and negative min. 460 test(f64_min, 0x00100000, 0x00000000); 461 test(-f64_min, 0x80100000, 0x00000000); 462 463 // Positive and negative max. 464 test(f64_max, 0x7FEFFFFF, 0xFFFFFFFF); 465 test(-f64_max, 0xFFEFFFFF, 0xFFFFFFFF); 466 467 test(Number.MAX_SAFE_INTEGER, 0x433FFFFF, 0xFFFFFFFF); 468 test(Number.MIN_SAFE_INTEGER, 0xC33FFFFF, 0xFFFFFFFF); 469 470 // Test various edge cases with mantissa of all 1, all 0, or just the 471 // highest or lowest significant bit. 472 test(4503599627370497, 0x43300000, 0x00000001); 473 test(6755399441055744, 0x43380000, 0x00000000); 474 test(1.348269851146737e+308, 0x7FE80000, 0x00000000); 475 test(1.9999999999999998, 0x3FFFFFFF, 0xFFFFFFFF); 476 test(2.225073858507201e-308, 0x000FFFFF, 0xFFFFFFFF); 477 test(Math.PI, 0x400921fb, 0x54442d18); 478 test(jspb.BinaryConstants.FLOAT32_MIN, 0x38100000, 0x00000000); 479 480 // Various positive values. 481 var cursor = f64_eps * 10; 482 while (cursor != Infinity) { 483 test(cursor); 484 cursor *= 1.1; 485 } 486 487 // Various negative values. 488 cursor = -f64_eps * 10; 489 while (cursor != -Infinity) { 490 test(cursor); 491 cursor *= 1.1; 492 } 493 }); 494 495 /** 496 * Tests zigzag conversions. 497 */ 498 it('can encode and decode zigzag 64', function() { 499 function stringToHiLoPair(str) { 500 jspb.utils.splitDecimalString(str); 501 return { 502 lo: jspb.utils.split64Low >>> 0, 503 hi: jspb.utils.split64High >>> 0 504 }; 505 } 506 function makeHiLoPair(lo, hi) { 507 return {lo: lo >>> 0, hi: hi >>> 0}; 508 } 509 // Test cases directly from the protobuf dev guide. 510 // https://engdoc.corp.google.com/eng/howto/protocolbuffers/developerguide/encoding.shtml?cl=head#types 511 var testCases = [ 512 {original: stringToHiLoPair('0'), zigzag: stringToHiLoPair('0')}, 513 {original: stringToHiLoPair('-1'), zigzag: stringToHiLoPair('1')}, 514 {original: stringToHiLoPair('1'), zigzag: stringToHiLoPair('2')}, 515 {original: stringToHiLoPair('-2'), zigzag: stringToHiLoPair('3')}, 516 { 517 original: stringToHiLoPair('2147483647'), 518 zigzag: stringToHiLoPair('4294967294') 519 }, 520 { 521 original: stringToHiLoPair('-2147483648'), 522 zigzag: stringToHiLoPair('4294967295') 523 }, 524 // 64-bit extremes 525 { 526 original: stringToHiLoPair('9223372036854775807'), 527 zigzag: stringToHiLoPair('18446744073709551614') 528 }, 529 { 530 original: stringToHiLoPair('-9223372036854775808'), 531 zigzag: stringToHiLoPair('18446744073709551615') 532 }, 533 ]; 534 for (const c of testCases) { 535 expect(jspb.utils.toZigzag64(c.original.lo, c.original.hi, makeHiLoPair)) 536 .toEqual(c.zigzag); 537 expect(jspb.utils.fromZigzag64(c.zigzag.lo, c.zigzag.hi, makeHiLoPair)) 538 .toEqual(c.original); 539 } 540 }); 541 542 543 /** 544 * Tests counting packed varints. 545 */ 546 it('testCountVarints', function() { 547 var values = []; 548 for (var i = 1; i < 1000000000; i *= 1.1) { 549 values.push(Math.floor(i)); 550 } 551 552 var writer = new jspb.BinaryWriter(); 553 writer.writePackedUint64(1, values); 554 555 var buffer = new Uint8Array(writer.getResultBuffer()); 556 557 // We should have two more varints than we started with - one for the field 558 // tag, one for the packed length. 559 expect(jspb.utils.countVarints(buffer, 0, buffer.length)) 560 .toEqual(values.length + 2); 561 }); 562 563 564 /** 565 * Tests counting matching varint fields. 566 */ 567 it('testCountVarintFields', function() { 568 var writer = new jspb.BinaryWriter(); 569 570 var count = 0; 571 for (var i = 1; i < 1000000000; i *= 1.1) { 572 writer.writeUint64(1, Math.floor(i)); 573 count++; 574 } 575 writer.writeString(2, 'terminator'); 576 577 var buffer = new Uint8Array(writer.getResultBuffer()); 578 expect(jspb.utils.countVarintFields(buffer, 0, buffer.length, 1)) 579 .toEqual(count); 580 581 writer = new jspb.BinaryWriter(); 582 583 count = 0; 584 for (var i = 1; i < 1000000000; i *= 1.1) { 585 writer.writeUint64(123456789, Math.floor(i)); 586 count++; 587 } 588 writer.writeString(2, 'terminator'); 589 590 buffer = new Uint8Array(writer.getResultBuffer()); 591 expect(jspb.utils.countVarintFields(buffer, 0, buffer.length, 123456789)) 592 .toEqual(count); 593 }); 594 595 596 /** 597 * Tests counting matching fixed32 fields. 598 */ 599 it('testCountFixed32Fields', function() { 600 var writer = new jspb.BinaryWriter(); 601 602 var count = 0; 603 for (var i = 1; i < 1000000000; i *= 1.1) { 604 writer.writeFixed32(1, Math.floor(i)); 605 count++; 606 } 607 writer.writeString(2, 'terminator'); 608 609 var buffer = new Uint8Array(writer.getResultBuffer()); 610 expect(jspb.utils.countFixed32Fields(buffer, 0, buffer.length, 1)) 611 .toEqual(count); 612 613 writer = new jspb.BinaryWriter(); 614 615 count = 0; 616 for (var i = 1; i < 1000000000; i *= 1.1) { 617 writer.writeFixed32(123456789, Math.floor(i)); 618 count++; 619 } 620 writer.writeString(2, 'terminator'); 621 622 buffer = new Uint8Array(writer.getResultBuffer()); 623 expect(jspb.utils.countFixed32Fields(buffer, 0, buffer.length, 123456789)) 624 .toEqual(count); 625 }); 626 627 628 /** 629 * Tests counting matching fixed64 fields. 630 */ 631 it('testCountFixed64Fields', function() { 632 var writer = new jspb.BinaryWriter(); 633 634 var count = 0; 635 for (var i = 1; i < 1000000000; i *= 1.1) { 636 writer.writeDouble(1, i); 637 count++; 638 } 639 writer.writeString(2, 'terminator'); 640 641 var buffer = new Uint8Array(writer.getResultBuffer()); 642 expect(jspb.utils.countFixed64Fields(buffer, 0, buffer.length, 1)) 643 .toEqual(count); 644 645 writer = new jspb.BinaryWriter(); 646 647 count = 0; 648 for (var i = 1; i < 1000000000; i *= 1.1) { 649 writer.writeDouble(123456789, i); 650 count++; 651 } 652 writer.writeString(2, 'terminator'); 653 654 buffer = new Uint8Array(writer.getResultBuffer()); 655 expect(jspb.utils.countFixed64Fields(buffer, 0, buffer.length, 123456789)) 656 .toEqual(count); 657 }); 658 659 660 /** 661 * Tests counting matching delimited fields. 662 */ 663 it('testCountDelimitedFields', function() { 664 var writer = new jspb.BinaryWriter(); 665 666 var count = 0; 667 for (var i = 1; i < 1000; i *= 1.1) { 668 writer.writeBytes(1, [Math.floor(i)]); 669 count++; 670 } 671 writer.writeString(2, 'terminator'); 672 673 var buffer = new Uint8Array(writer.getResultBuffer()); 674 expect(jspb.utils.countDelimitedFields(buffer, 0, buffer.length, 1)) 675 .toEqual(count); 676 677 writer = new jspb.BinaryWriter(); 678 679 count = 0; 680 for (var i = 1; i < 1000; i *= 1.1) { 681 writer.writeBytes(123456789, [Math.floor(i)]); 682 count++; 683 } 684 writer.writeString(2, 'terminator'); 685 686 buffer = new Uint8Array(writer.getResultBuffer()); 687 expect(jspb.utils.countDelimitedFields(buffer, 0, buffer.length, 123456789)) 688 .toEqual(count); 689 }); 690 691 692 /** 693 * Tests byte format for debug strings. 694 */ 695 it('testDebugBytesToTextFormat', function() { 696 expect(jspb.utils.debugBytesToTextFormat(null)).toEqual('""'); 697 expect(jspb.utils.debugBytesToTextFormat([ 698 0, 16, 255 699 ])).toEqual('"\\x00\\x10\\xff"'); 700 }); 701 702 703 /** 704 * Tests converting byte blob sources into byte blobs. 705 */ 706 it('testByteSourceToUint8Array', function() { 707 var convert = jspb.utils.byteSourceToUint8Array; 708 709 var sourceData = []; 710 for (var i = 0; i < 256; i++) { 711 sourceData.push(i); 712 } 713 714 var sourceBytes = new Uint8Array(sourceData); 715 var sourceBuffer = sourceBytes.buffer; 716 var sourceBase64 = goog.crypt.base64.encodeByteArray(sourceData); 717 var sourceString = goog.crypt.byteArrayToString(sourceData); 718 719 function check(result) { 720 expect(result.constructor).toEqual(Uint8Array); 721 expect(result.length).toEqual(sourceData.length); 722 for (var i = 0; i < result.length; i++) { 723 expect(result[i]).toEqual(sourceData[i]); 724 } 725 } 726 727 // Converting Uint8Arrays into Uint8Arrays should be a no-op. 728 expect(convert(sourceBytes)).toEqual(sourceBytes); 729 730 // Converting Array<numbers> into Uint8Arrays should work. 731 check(convert(sourceData)); 732 733 // Converting ArrayBuffers into Uint8Arrays should work. 734 check(convert(sourceBuffer)); 735 736 // Converting base64-encoded strings into Uint8Arrays should work. 737 check(convert(sourceBase64)); 738 }); 739}); 740