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