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 // corner cases 395 test(0.9999999762949594, 0x3f800000); 396 test(7.99999999999999, 0x41000000); 397 test(Math.sin(30 * Math.PI / 180), 0x3f000000); // sin(30 degrees) 398 399 // Various positive values. 400 var cursor = f32_eps * 10; 401 while (cursor != Infinity) { 402 test(cursor); 403 cursor *= 1.1; 404 } 405 406 // Various negative values. 407 cursor = -f32_eps * 10; 408 while (cursor != -Infinity) { 409 test(cursor); 410 cursor *= 1.1; 411 } 412 }); 413 414 415 /** 416 * Tests conversion from 64-bit floating point numbers to split64 numbers. 417 */ 418 it('testFloat64ToSplit64', function() { 419 var f64_eps = jspb.BinaryConstants.FLOAT64_EPS; 420 var f64_min = jspb.BinaryConstants.FLOAT64_MIN; 421 var f64_max = jspb.BinaryConstants.FLOAT64_MAX; 422 423 // NaN. 424 jspb.utils.splitFloat64(NaN); 425 expect(isNaN(jspb.utils.joinFloat64( 426 jspb.utils.split64Low, jspb.utils.split64High))) 427 .toEqual(true); 428 429 /** 430 * @param {number} x 431 * @param {number=} opt_highBits 432 * @param {number=} opt_lowBits 433 */ 434 function test(x, opt_highBits, opt_lowBits) { 435 jspb.utils.splitFloat64(x); 436 if (opt_highBits !== undefined) { 437 var split64High = jspb.utils.split64High; 438 expect(opt_highBits.toString(16)).toEqual(split64High.toString(16)); 439 } 440 if (opt_lowBits !== undefined) { 441 var split64Low = jspb.utils.split64Low; 442 expect(opt_lowBits.toString(16)).toEqual(split64Low.toString(16)); 443 } 444 expect( 445 jspb.utils.joinFloat64(jspb.utils.split64Low, jspb.utils.split64High)) 446 .toEqual(x); 447 } 448 449 // Positive and negative infinity. 450 test(Infinity, 0x7ff00000, 0x00000000); 451 test(-Infinity, 0xfff00000, 0x00000000); 452 453 // Positive and negative zero. 454 test(0, 0x00000000, 0x00000000); 455 test(-0, 0x80000000, 0x00000000); 456 457 test(1, 0x3FF00000, 0x00000000); 458 test(2, 0x40000000, 0x00000000); 459 460 // Positive and negative epsilon. 461 test(f64_eps, 0x00000000, 0x00000001); 462 test(-f64_eps, 0x80000000, 0x00000001); 463 464 // Positive and negative min. 465 test(f64_min, 0x00100000, 0x00000000); 466 test(-f64_min, 0x80100000, 0x00000000); 467 468 // Positive and negative max. 469 test(f64_max, 0x7FEFFFFF, 0xFFFFFFFF); 470 test(-f64_max, 0xFFEFFFFF, 0xFFFFFFFF); 471 472 test(Number.MAX_SAFE_INTEGER, 0x433FFFFF, 0xFFFFFFFF); 473 test(Number.MIN_SAFE_INTEGER, 0xC33FFFFF, 0xFFFFFFFF); 474 475 // Test various edge cases with mantissa of all 1, all 0, or just the 476 // highest or lowest significant bit. 477 test(4503599627370497, 0x43300000, 0x00000001); 478 test(6755399441055744, 0x43380000, 0x00000000); 479 test(1.348269851146737e+308, 0x7FE80000, 0x00000000); 480 test(1.9999999999999998, 0x3FFFFFFF, 0xFFFFFFFF); 481 test(2.225073858507201e-308, 0x000FFFFF, 0xFFFFFFFF); 482 test(Math.PI, 0x400921fb, 0x54442d18); 483 test(jspb.BinaryConstants.FLOAT32_MIN, 0x38100000, 0x00000000); 484 485 // Various positive values. 486 var cursor = f64_eps * 10; 487 while (cursor != Infinity) { 488 test(cursor); 489 cursor *= 1.1; 490 } 491 492 // Various negative values. 493 cursor = -f64_eps * 10; 494 while (cursor != -Infinity) { 495 test(cursor); 496 cursor *= 1.1; 497 } 498 }); 499 500 /** 501 * Tests zigzag conversions. 502 */ 503 it('can encode and decode zigzag 64', function() { 504 function stringToHiLoPair(str) { 505 jspb.utils.splitDecimalString(str); 506 return { 507 lo: jspb.utils.split64Low >>> 0, 508 hi: jspb.utils.split64High >>> 0 509 }; 510 } 511 function makeHiLoPair(lo, hi) { 512 return {lo: lo >>> 0, hi: hi >>> 0}; 513 } 514 // Test cases directly from the protobuf dev guide. 515 // https://engdoc.corp.google.com/eng/howto/protocolbuffers/developerguide/encoding.shtml?cl=head#types 516 var testCases = [ 517 {original: stringToHiLoPair('0'), zigzag: stringToHiLoPair('0')}, 518 {original: stringToHiLoPair('-1'), zigzag: stringToHiLoPair('1')}, 519 {original: stringToHiLoPair('1'), zigzag: stringToHiLoPair('2')}, 520 {original: stringToHiLoPair('-2'), zigzag: stringToHiLoPair('3')}, 521 { 522 original: stringToHiLoPair('2147483647'), 523 zigzag: stringToHiLoPair('4294967294') 524 }, 525 { 526 original: stringToHiLoPair('-2147483648'), 527 zigzag: stringToHiLoPair('4294967295') 528 }, 529 // 64-bit extremes 530 { 531 original: stringToHiLoPair('9223372036854775807'), 532 zigzag: stringToHiLoPair('18446744073709551614') 533 }, 534 { 535 original: stringToHiLoPair('-9223372036854775808'), 536 zigzag: stringToHiLoPair('18446744073709551615') 537 }, 538 ]; 539 for (const c of testCases) { 540 expect(jspb.utils.toZigzag64(c.original.lo, c.original.hi, makeHiLoPair)) 541 .toEqual(c.zigzag); 542 expect(jspb.utils.fromZigzag64(c.zigzag.lo, c.zigzag.hi, makeHiLoPair)) 543 .toEqual(c.original); 544 } 545 }); 546 547 548 /** 549 * Tests counting packed varints. 550 */ 551 it('testCountVarints', function() { 552 var values = []; 553 for (var i = 1; i < 1000000000; i *= 1.1) { 554 values.push(Math.floor(i)); 555 } 556 557 var writer = new jspb.BinaryWriter(); 558 writer.writePackedUint64(1, values); 559 560 var buffer = new Uint8Array(writer.getResultBuffer()); 561 562 // We should have two more varints than we started with - one for the field 563 // tag, one for the packed length. 564 expect(jspb.utils.countVarints(buffer, 0, buffer.length)) 565 .toEqual(values.length + 2); 566 }); 567 568 569 /** 570 * Tests counting matching varint fields. 571 */ 572 it('testCountVarintFields', function() { 573 var writer = new jspb.BinaryWriter(); 574 575 var count = 0; 576 for (var i = 1; i < 1000000000; i *= 1.1) { 577 writer.writeUint64(1, Math.floor(i)); 578 count++; 579 } 580 writer.writeString(2, 'terminator'); 581 582 var buffer = new Uint8Array(writer.getResultBuffer()); 583 expect(jspb.utils.countVarintFields(buffer, 0, buffer.length, 1)) 584 .toEqual(count); 585 586 writer = new jspb.BinaryWriter(); 587 588 count = 0; 589 for (var i = 1; i < 1000000000; i *= 1.1) { 590 writer.writeUint64(123456789, Math.floor(i)); 591 count++; 592 } 593 writer.writeString(2, 'terminator'); 594 595 buffer = new Uint8Array(writer.getResultBuffer()); 596 expect(jspb.utils.countVarintFields(buffer, 0, buffer.length, 123456789)) 597 .toEqual(count); 598 }); 599 600 601 /** 602 * Tests counting matching fixed32 fields. 603 */ 604 it('testCountFixed32Fields', function() { 605 var writer = new jspb.BinaryWriter(); 606 607 var count = 0; 608 for (var i = 1; i < 1000000000; i *= 1.1) { 609 writer.writeFixed32(1, Math.floor(i)); 610 count++; 611 } 612 writer.writeString(2, 'terminator'); 613 614 var buffer = new Uint8Array(writer.getResultBuffer()); 615 expect(jspb.utils.countFixed32Fields(buffer, 0, buffer.length, 1)) 616 .toEqual(count); 617 618 writer = new jspb.BinaryWriter(); 619 620 count = 0; 621 for (var i = 1; i < 1000000000; i *= 1.1) { 622 writer.writeFixed32(123456789, Math.floor(i)); 623 count++; 624 } 625 writer.writeString(2, 'terminator'); 626 627 buffer = new Uint8Array(writer.getResultBuffer()); 628 expect(jspb.utils.countFixed32Fields(buffer, 0, buffer.length, 123456789)) 629 .toEqual(count); 630 }); 631 632 633 /** 634 * Tests counting matching fixed64 fields. 635 */ 636 it('testCountFixed64Fields', function() { 637 var writer = new jspb.BinaryWriter(); 638 639 var count = 0; 640 for (var i = 1; i < 1000000000; i *= 1.1) { 641 writer.writeDouble(1, i); 642 count++; 643 } 644 writer.writeString(2, 'terminator'); 645 646 var buffer = new Uint8Array(writer.getResultBuffer()); 647 expect(jspb.utils.countFixed64Fields(buffer, 0, buffer.length, 1)) 648 .toEqual(count); 649 650 writer = new jspb.BinaryWriter(); 651 652 count = 0; 653 for (var i = 1; i < 1000000000; i *= 1.1) { 654 writer.writeDouble(123456789, i); 655 count++; 656 } 657 writer.writeString(2, 'terminator'); 658 659 buffer = new Uint8Array(writer.getResultBuffer()); 660 expect(jspb.utils.countFixed64Fields(buffer, 0, buffer.length, 123456789)) 661 .toEqual(count); 662 }); 663 664 665 /** 666 * Tests counting matching delimited fields. 667 */ 668 it('testCountDelimitedFields', function() { 669 var writer = new jspb.BinaryWriter(); 670 671 var count = 0; 672 for (var i = 1; i < 1000; i *= 1.1) { 673 writer.writeBytes(1, [Math.floor(i)]); 674 count++; 675 } 676 writer.writeString(2, 'terminator'); 677 678 var buffer = new Uint8Array(writer.getResultBuffer()); 679 expect(jspb.utils.countDelimitedFields(buffer, 0, buffer.length, 1)) 680 .toEqual(count); 681 682 writer = new jspb.BinaryWriter(); 683 684 count = 0; 685 for (var i = 1; i < 1000; i *= 1.1) { 686 writer.writeBytes(123456789, [Math.floor(i)]); 687 count++; 688 } 689 writer.writeString(2, 'terminator'); 690 691 buffer = new Uint8Array(writer.getResultBuffer()); 692 expect(jspb.utils.countDelimitedFields(buffer, 0, buffer.length, 123456789)) 693 .toEqual(count); 694 }); 695 696 697 /** 698 * Tests byte format for debug strings. 699 */ 700 it('testDebugBytesToTextFormat', function() { 701 expect(jspb.utils.debugBytesToTextFormat(null)).toEqual('""'); 702 expect(jspb.utils.debugBytesToTextFormat([ 703 0, 16, 255 704 ])).toEqual('"\\x00\\x10\\xff"'); 705 }); 706 707 708 /** 709 * Tests converting byte blob sources into byte blobs. 710 */ 711 it('testByteSourceToUint8Array', function() { 712 var convert = jspb.utils.byteSourceToUint8Array; 713 714 var sourceData = []; 715 for (var i = 0; i < 256; i++) { 716 sourceData.push(i); 717 } 718 719 var sourceBytes = new Uint8Array(sourceData); 720 var sourceBuffer = sourceBytes.buffer; 721 var sourceBase64 = goog.crypt.base64.encodeByteArray(sourceData); 722 var sourceString = goog.crypt.byteArrayToString(sourceData); 723 724 function check(result) { 725 expect(result.constructor).toEqual(Uint8Array); 726 expect(result.length).toEqual(sourceData.length); 727 for (var i = 0; i < result.length; i++) { 728 expect(result[i]).toEqual(sourceData[i]); 729 } 730 } 731 732 // Converting Uint8Arrays into Uint8Arrays should be a no-op. 733 expect(convert(sourceBytes)).toEqual(sourceBytes); 734 735 // Converting Array<numbers> into Uint8Arrays should work. 736 check(convert(sourceData)); 737 738 // Converting ArrayBuffers into Uint8Arrays should work. 739 check(convert(sourceBuffer)); 740 741 // Converting base64-encoded strings into Uint8Arrays should work. 742 check(convert(sourceBase64)); 743 }); 744}); 745