addon-sdk/source/test/test-buffer.js

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 /*
     7  * Many of these tests taken from Joyent's Node
     8  * https://github.com/joyent/node/blob/master/test/simple/test-buffer.js
     9  */
    11 // Copyright Joyent, Inc. and other Node contributors.
    12 //
    13 // Permission is hereby granted, free of charge, to any person obtaining a
    14 // copy of this software and associated documentation files (the
    15 // "Software"), to deal in the Software without restriction, including
    16 // without limitation the rights to use, copy, modify, merge, publish,
    17 // distribute, sublicense, and/or sell copies of the Software, and to permit
    18 // persons to whom the Software is furnished to do so, subject to the
    19 // following conditions:
    20 //
    21 // The above copyright notice and this permission notice shall be included
    22 // in all copies or substantial portions of the Software.
    23 //
    24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
    25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
    27 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
    28 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
    29 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
    30 // USE OR OTHER DEALINGS IN THE SOFTWARE.
    32 const { Buffer, TextEncoder, TextDecoder } = require('sdk/io/buffer');
    33 const { safeMerge } = require('sdk/util/object');
    35 const ENCODINGS = ['utf-8', 'utf-16le', 'utf-16be'];
    37 exports.testBufferMain = function (assert) {
    38   let b = Buffer('abcdef');
    40   // try to create 0-length buffers
    41   new Buffer('');
    42   new Buffer(0);
    43   // test encodings supported by node;
    44   // this is different than what node supports, details
    45   // in buffer.js
    46   ENCODINGS.forEach(enc => {
    47     new Buffer('', enc);
    48     assert.pass('Creating a buffer with ' + enc + ' does not throw');
    49   });
    51   ENCODINGS.forEach(function(encoding) {
    52     // Does not work with utf8
    53     if (encoding === 'utf-8') return;
    54     var b = new Buffer(10);
    55     b.write('あいうえお', encoding);
    56     assert.equal(b.toString(encoding), 'あいうえお',
    57       'encode and decodes buffer with ' + encoding);
    58   });
    60   // invalid encoding for Buffer.toString
    61   assert.throws(() => {
    62     b.toString('invalid');
    63   }, TypeError, 'invalid encoding for Buffer.toString');
    65   // try to toString() a 0-length slice of a buffer, both within and without the
    66   // valid buffer range
    67   assert.equal(new Buffer('abc').toString('utf8', 0, 0), '',
    68     'toString 0-length buffer, valid range');
    69   assert.equal(new Buffer('abc').toString('utf8', -100, -100), '',
    70     'toString 0-length buffer, invalid range');
    71   assert.equal(new Buffer('abc').toString('utf8', 100, 100), '',
    72     'toString 0-length buffer, invalid range');
    74   // try toString() with a object as a encoding
    75   assert.equal(new Buffer('abc').toString({toString: function() {
    76     return 'utf8';
    77   }}), 'abc', 'toString with object as an encoding');
    79   // test for buffer overrun
    80   var buf = new Buffer([0, 0, 0, 0, 0]); // length: 5
    81   var sub = buf.slice(0, 4); // length: 4
    82   var written = sub.write('12345', 'utf8');
    83   assert.equal(written, 4, 'correct bytes written in slice');
    84   assert.equal(buf[4], 0, 'correct origin buffer value');
    86   // Check for fractional length args, junk length args, etc.
    87   // https://github.com/joyent/node/issues/1758
    88   Buffer(3.3).toString(); // throws bad argument error in commit 43cb4ec
    89   assert.equal(Buffer(-1).length, 0);
    90   assert.equal(Buffer(NaN).length, 0);
    91   assert.equal(Buffer(3.3).length, 3);
    92   assert.equal(Buffer({length: 3.3}).length, 3);
    93   assert.equal(Buffer({length: 'BAM'}).length, 0);
    95   // Make sure that strings are not coerced to numbers.
    96   assert.equal(Buffer('99').length, 2);
    97   assert.equal(Buffer('13.37').length, 5);
    98 };
   100 exports.testIsEncoding = function (assert) {
   101   ENCODINGS.map(encoding => {
   102     assert.ok(Buffer.isEncoding(encoding),
   103       'Buffer.isEncoding ' + encoding + ' truthy');
   104   });
   105   ['not-encoding', undefined, null, 100, {}].map(encoding => {
   106     assert.ok(!Buffer.isEncoding(encoding),
   107       'Buffer.isEncoding ' + encoding + ' falsy');
   108   });
   109 };
   111 exports.testBufferCopy = function (assert) {
   112   // counter to ensure unique value is always copied
   113   var cntr = 0;
   114   var b = Buffer(1024); // safe constructor
   116   assert.strictEqual(1024, b.length);
   117   b[0] = -1;
   118   assert.strictEqual(b[0], 255);
   120   var shimArray = [];
   121   for (var i = 0; i < 1024; i++) {
   122     b[i] = i % 256;
   123     shimArray[i] = i % 256;
   124   }
   126   compareBuffers(assert, b, shimArray, 'array notation');
   128   var c = new Buffer(512);
   129   assert.strictEqual(512, c.length);
   130   // copy 512 bytes, from 0 to 512.
   131   b.fill(++cntr);
   132   c.fill(++cntr);
   133   var copied = b.copy(c, 0, 0, 512);
   134   assert.strictEqual(512, copied,
   135     'copied ' + copied + ' bytes from b into c');
   137   compareBuffers(assert, b, c, 'copied to other buffer');
   139   // copy c into b, without specifying sourceEnd
   140   b.fill(++cntr);
   141   c.fill(++cntr);
   142   var copied = c.copy(b, 0, 0);
   143   assert.strictEqual(c.length, copied,
   144     'copied ' + copied + ' bytes from c into b w/o sourceEnd');
   145   compareBuffers(assert, b, c,
   146     'copied to other buffer without specifying sourceEnd');
   148   // copy c into b, without specifying sourceStart
   149   b.fill(++cntr);
   150   c.fill(++cntr);
   151   var copied = c.copy(b, 0);
   152   assert.strictEqual(c.length, copied,
   153     'copied ' + copied + ' bytes from c into b w/o sourceStart');
   154   compareBuffers(assert, b, c,
   155     'copied to other buffer without specifying sourceStart');
   157   // copy longer buffer b to shorter c without targetStart
   158   b.fill(++cntr);
   159   c.fill(++cntr);
   161   var copied = b.copy(c);
   162   assert.strictEqual(c.length, copied,
   163     'copied ' + copied + ' bytes from b into c w/o targetStart');
   164   compareBuffers(assert, b, c,
   165     'copy long buffer to shorter buffer without targetStart');
   167   // copy starting near end of b to c
   168   b.fill(++cntr);
   169   c.fill(++cntr);
   170   var copied = b.copy(c, 0, b.length - Math.floor(c.length / 2));
   171   assert.strictEqual(Math.floor(c.length / 2), copied,
   172     'copied ' + copied + ' bytes from end of b into beg. of c');
   174   let successStatus = true;
   175   for (var i = 0; i < Math.floor(c.length / 2); i++) {
   176     if (b[b.length - Math.floor(c.length / 2) + i] !== c[i])
   177       successStatus = false;
   178   }
   180   for (var i = Math.floor(c.length /2) + 1; i < c.length; i++) {
   181     if (c[c.length-1] !== c[i])
   182       successStatus = false;
   183   }
   184   assert.ok(successStatus,
   185     'Copied bytes from end of large buffer into beginning of small buffer');
   187   // try to copy 513 bytes, and check we don't overrun c
   188   b.fill(++cntr);
   189   c.fill(++cntr);
   190   var copied = b.copy(c, 0, 0, 513);
   191   assert.strictEqual(c.length, copied,
   192     'copied ' + copied + ' bytes from b trying to overrun c');
   193   compareBuffers(assert, b, c,
   194     'copying to buffer that would overflow');
   196   // copy 768 bytes from b into b
   197   b.fill(++cntr);
   198   b.fill(++cntr, 256);
   199   var copied = b.copy(b, 0, 256, 1024);
   200   assert.strictEqual(768, copied,
   201     'copied ' + copied + ' bytes from b into b');
   203   compareBuffers(assert, b, shimArray.map(()=>cntr),
   204     'copy partial buffer to itself');
   206   // copy string longer than buffer length (failure will segfault)
   207   var bb = new Buffer(10);
   208   bb.fill('hello crazy world');
   210   // copy throws at negative sourceStart
   211   assert.throws(function() {
   212     Buffer(5).copy(Buffer(5), 0, -1);
   213   }, RangeError, 'buffer copy throws at negative sourceStart');
   215   // check sourceEnd resets to targetEnd if former is greater than the latter
   216   b.fill(++cntr);
   217   c.fill(++cntr);
   218   var copied = b.copy(c, 0, 0, 1025);
   219   assert.strictEqual(copied, c.length,
   220     'copied ' + copied + ' bytes from b into c');
   221   compareBuffers(assert, b, c, 'copying should reset sourceEnd if targetEnd if sourceEnd > targetEnd');
   223   // throw with negative sourceEnd
   224   assert.throws(function() {
   225     b.copy(c, 0, 0, -1);
   226   }, RangeError, 'buffer copy throws at negative sourceEnd');
   228   // when sourceStart is greater than sourceEnd, zero copied
   229   assert.equal(b.copy(c, 0, 100, 10), 0);
   231   // when targetStart > targetLength, zero copied
   232   assert.equal(b.copy(c, 512, 0, 10), 0);
   234   // try to copy 0 bytes worth of data into an empty buffer
   235   b.copy(new Buffer(0), 0, 0, 0);
   237   // try to copy 0 bytes past the end of the target buffer
   238   b.copy(new Buffer(0), 1, 1, 1);
   239   b.copy(new Buffer(1), 1, 1, 1);
   241   // try to copy 0 bytes from past the end of the source buffer
   242   b.copy(new Buffer(1), 0, 2048, 2048);
   243 };
   245 exports.testBufferWrite = function (assert) {
   246   let b = Buffer(1024);
   247   b.fill(0);
   249   assert.throws(() => {
   250     b.write('test string', 0, 5, 'invalid');
   251   }, TypeError, 'invalid encoding with buffer write throws');
   252   // try to write a 0-length string beyond the end of b
   253   assert.throws(function() {
   254     b.write('', 2048);
   255   }, RangeError, 'writing a 0-length string beyond buffer throws');
   256   // throw when writing to negative offset
   257   assert.throws(function() {
   258     b.write('a', -1);
   259   }, RangeError, 'writing negative offset on buffer throws');
   261   // throw when writing past bounds from the pool
   262   assert.throws(function() {
   263     b.write('a', 2048);
   264   }, RangeError, 'writing past buffer bounds from pool throws');
   266   // testing for smart defaults and ability to pass string values as offset
   268   // previous write API was the following:
   269   // write(string, encoding, offset, length)
   270   // this is planned on being removed in node v0.13,
   271   // we will not support it
   272   var writeTest = new Buffer('abcdes');
   273   writeTest.write('n', 'utf8');
   274 //  writeTest.write('o', 'utf8', '1');
   275   writeTest.write('d', '2', 'utf8');
   276   writeTest.write('e', 3, 'utf8');
   277 //  writeTest.write('j', 'utf8', 4);
   278   assert.equal(writeTest.toString(), 'nbdees',
   279     'buffer write API alternative syntax works');
   280 };
   282 exports.testBufferWriteEncoding = function (assert) {
   284   // Node #1210 Test UTF-8 string includes null character
   285   var buf = new Buffer('\0');
   286   assert.equal(buf.length, 1);
   287   buf = new Buffer('\0\0');
   288   assert.equal(buf.length, 2);
   290   buf = new Buffer(2);
   291   var written = buf.write(''); // 0byte
   292   assert.equal(written, 0);
   293   written = buf.write('\0'); // 1byte (v8 adds null terminator)
   294   assert.equal(written, 1);
   295   written = buf.write('a\0'); // 1byte * 2
   296   assert.equal(written, 2);
   297   // TODO, these tests write 0, possibly due to character encoding
   298 /*
   299   written = buf.write('あ'); // 3bytes
   300   assert.equal(written, 0);
   301   written = buf.write('\0あ'); // 1byte + 3bytes
   302   assert.equal(written, 1);
   303 */
   304   written = buf.write('\0\0あ'); // 1byte * 2 + 3bytes
   305   buf = new Buffer(10);
   306   written = buf.write('あいう'); // 3bytes * 3 (v8 adds null terminator)
   307   assert.equal(written, 9);
   308   written = buf.write('あいう\0'); // 3bytes * 3 + 1byte
   309   assert.equal(written, 10);
   310 };
   312 exports.testBufferWriteWithMaxLength = function (assert) {
   313   // Node #243 Test write() with maxLength
   314   var buf = new Buffer(4);
   315   buf.fill(0xFF);
   316   var written = buf.write('abcd', 1, 2, 'utf8');
   317   assert.equal(written, 2);
   318   assert.equal(buf[0], 0xFF);
   319   assert.equal(buf[1], 0x61);
   320   assert.equal(buf[2], 0x62);
   321   assert.equal(buf[3], 0xFF);
   323   buf.fill(0xFF);
   324   written = buf.write('abcd', 1, 4);
   325   assert.equal(written, 3);
   326   assert.equal(buf[0], 0xFF);
   327   assert.equal(buf[1], 0x61);
   328   assert.equal(buf[2], 0x62);
   329   assert.equal(buf[3], 0x63);
   331   buf.fill(0xFF);
   332   // Ignore legacy API
   333   /*
   334      written = buf.write('abcd', 'utf8', 1, 2); // legacy style
   335      console.log(buf);
   336      assert.equal(written, 2);
   337      assert.equal(buf[0], 0xFF);
   338      assert.equal(buf[1], 0x61);
   339      assert.equal(buf[2], 0x62);
   340      assert.equal(buf[3], 0xFF);
   341      */
   342 };
   344 exports.testBufferSlice = function (assert) {
   345   var asciiString = 'hello world';
   346   var offset = 100;
   347   var b = Buffer(1024);
   348   b.fill(0);
   350   for (var i = 0; i < asciiString.length; i++) {
   351     b[i] = asciiString.charCodeAt(i);
   352   }
   353   var asciiSlice = b.toString('utf8', 0, asciiString.length);
   354   assert.equal(asciiString, asciiSlice);
   356   var written = b.write(asciiString, offset, 'utf8');
   357   assert.equal(asciiString.length, written);
   358   asciiSlice = b.toString('utf8', offset, offset + asciiString.length);
   359   assert.equal(asciiString, asciiSlice);
   361   var sliceA = b.slice(offset, offset + asciiString.length);
   362   var sliceB = b.slice(offset, offset + asciiString.length);
   363   compareBuffers(assert, sliceA, sliceB,
   364     'slicing is idempotent');
   366   let sliceTest = true;
   367   for (var j = 0; j < 100; j++) {
   368     var slice = b.slice(100, 150);
   369     if (50 !== slice.length)
   370       sliceTest = false;
   371     for (var i = 0; i < 50; i++) {
   372       if (b[100 + i] !== slice[i])
   373         sliceTest = false;
   374     }
   375   }
   376   assert.ok(sliceTest, 'massive slice runs do not affect buffer');
   378   // Single argument slice
   379   let testBuf = new Buffer('abcde');
   380   assert.equal('bcde', testBuf.slice(1).toString(), 'single argument slice');
   382   // slice(0,0).length === 0
   383   assert.equal(0, Buffer('hello').slice(0, 0).length, 'slice(0,0) === 0');
   385   var buf = new Buffer('0123456789');
   386   assert.equal(buf.slice(-10, 10), '0123456789', 'buffer slice range correct');
   387   assert.equal(buf.slice(-20, 10), '0123456789', 'buffer slice range correct');
   388   assert.equal(buf.slice(-20, -10), '', 'buffer slice range correct');
   389   assert.equal(buf.slice(0, -1), '012345678', 'buffer slice range correct');
   390   assert.equal(buf.slice(2, -2), '234567', 'buffer slice range correct');
   391   assert.equal(buf.slice(0, 65536), '0123456789', 'buffer slice range correct');
   392   assert.equal(buf.slice(65536, 0), '', 'buffer slice range correct');
   394   let sliceTest = true;
   395   for (var i = 0, s = buf.toString(); i < buf.length; ++i) {
   396     if (buf.slice(-i) != s.slice(-i)) sliceTest = false;
   397     if (buf.slice(0, -i) != s.slice(0, -i)) sliceTest = false;
   398   }
   399   assert.ok(sliceTest, 'buffer.slice should be consistent');
   401   // Make sure modifying a sliced buffer, affects original and vice versa
   402   b.fill(0);
   403   let sliced = b.slice(0, 10);
   404   let babyslice = sliced.slice(0, 5);
   406   for (let i = 0; i < sliced.length; i++)
   407     sliced[i] = 'jetpack'.charAt(i);
   409   compareBuffers(assert, b, sliced,
   410     'modifying sliced buffer affects original');
   412   compareBuffers(assert, b, babyslice,
   413     'modifying sliced buffer affects child-sliced buffer');
   415   for (let i = 0; i < sliced.length; i++)
   416     b[i] = 'odinmonkey'.charAt(i);
   418   compareBuffers(assert, b, sliced,
   419     'modifying original buffer affects sliced');
   421   compareBuffers(assert, b, babyslice,
   422     'modifying original buffer affects grandchild sliced buffer');
   423 };
   425 exports.testSlicingParents = function (assert) {
   426   let root = Buffer(5);
   427   let child = root.slice(0, 4);
   428   let grandchild = child.slice(0, 3);
   430   assert.equal(root.parent, undefined, 'a new buffer should not have a parent');
   432   // make sure a zero length slice doesn't set the .parent attribute
   433   assert.equal(root.slice(0,0).parent, undefined,
   434     '0-length slice should not have a parent');
   436   assert.equal(child.parent, root,
   437     'a valid slice\'s parent should be the original buffer (child)');
   439   assert.equal(grandchild.parent, root,
   440     'a valid slice\'s parent should be the original buffer (grandchild)');
   441 };
   443 exports.testIsBuffer = function (assert) {
   444   let buffer = new Buffer('content', 'utf8');
   445   assert.ok(Buffer.isBuffer(buffer), 'isBuffer truthy on buffers');
   446   assert.ok(!Buffer.isBuffer({}), 'isBuffer falsy on objects');
   447   assert.ok(!Buffer.isBuffer(new Uint8Array()),
   448     'isBuffer falsy on Uint8Array');
   449   assert.ok(Buffer.isBuffer(buffer.slice(0)), 'Buffer#slice should be a new buffer');
   450 };
   452 exports.testBufferConcat = function (assert) {
   453   let zero = [];
   454   let one = [ new Buffer('asdf') ];
   455   let long = [];
   456   for (let i = 0; i < 10; i++) long.push(new Buffer('asdf'));
   458   let flatZero = Buffer.concat(zero);
   459   let flatOne = Buffer.concat(one);
   460   let flatLong = Buffer.concat(long);
   461   let flatLongLen = Buffer.concat(long, 40);
   463   assert.equal(flatZero.length, 0);
   464   assert.equal(flatOne.toString(), 'asdf');
   465   assert.equal(flatOne, one[0]);
   466   assert.ok(flatLong.toString(), (new Array(10+1).join('asdf')));
   467   assert.equal(flatLongLen.toString(), (new Array(10+1).join('asdf')));
   468 };
   470 exports.testBufferByteLength = function (assert) {
   471   let str = '\u00bd + \u00bc = \u00be';
   472   assert.equal(Buffer.byteLength(str), 12,
   473     'correct byteLength of string');
   475   assert.equal(14, Buffer.byteLength('Il était tué'));
   476   assert.equal(14, Buffer.byteLength('Il était tué', 'utf8'));
   477   // We do not currently support these encodings
   478   /*
   479   ['ucs2', 'ucs-2', 'utf16le', 'utf-16le'].forEach(function(encoding) {
   480   assert.equal(24, Buffer.byteLength('Il était tué', encoding));
   481   });
   482   assert.equal(12, Buffer.byteLength('Il était tué', 'ascii'));
   483   assert.equal(12, Buffer.byteLength('Il était tué', 'binary'));
   484   */
   485 };
   487 exports.testTextEncoderDecoder = function (assert) {
   488   assert.ok(TextEncoder, 'TextEncoder exists');
   489   assert.ok(TextDecoder, 'TextDecoder exists');
   490 };
   492 exports.testOverflowedBuffers = function (assert) {
   493   assert.throws(function() {
   494     new Buffer(0xFFFFFFFF);
   495   }, RangeError, 'correctly throws buffer overflow');
   497   assert.throws(function() {
   498     new Buffer(0xFFFFFFFFF);
   499   }, RangeError, 'correctly throws buffer overflow');
   501   assert.throws(function() {
   502     var buf = new Buffer(8);
   503     buf.readFloatLE(0xffffffff);
   504   }, RangeError, 'correctly throws buffer overflow with readFloatLE');
   506   assert.throws(function() {
   507     var buf = new Buffer(8);
   508     buf.writeFloatLE(0.0, 0xffffffff);
   509   }, RangeError, 'correctly throws buffer overflow with writeFloatLE');
   511   //ensure negative values can't get past offset
   512   assert.throws(function() {
   513     var buf = new Buffer(8);
   514     buf.readFloatLE(-1);
   515   }, RangeError, 'correctly throws with readFloatLE negative values');
   517   assert.throws(function() {
   518     var buf = new Buffer(8);
   519     buf.writeFloatLE(0.0, -1);
   520   }, RangeError, 'correctly throws with writeFloatLE with negative values');
   522   assert.throws(function() {
   523     var buf = new Buffer(8);
   524     buf.readFloatLE(-1);
   525   }, RangeError, 'correctly throws with readFloatLE with negative values');
   526 };
   528 exports.testReadWriteDataTypeErrors = function (assert) {
   529   var buf = new Buffer(0);
   530   assert.throws(function() { buf.readUInt8(0); }, RangeError,
   531     'readUInt8(0) throws');
   532   assert.throws(function() { buf.readInt8(0); }, RangeError,
   533     'readInt8(0) throws');
   535   [16, 32].forEach(function(bits) {
   536     var buf = new Buffer(bits / 8 - 1);
   537     assert.throws(function() { buf['readUInt' + bits + 'BE'](0); },
   538       RangeError,
   539       'readUInt' + bits + 'BE');
   541     assert.throws(function() { buf['readUInt' + bits + 'LE'](0); },
   542       RangeError,
   543       'readUInt' + bits + 'LE');
   545     assert.throws(function() { buf['readInt' + bits + 'BE'](0); },
   546       RangeError,
   547       'readInt' + bits + 'BE()');
   549     assert.throws(function() { buf['readInt' + bits + 'LE'](0); },
   550       RangeError,
   551       'readInt' + bits + 'LE()');
   552   });
   553 };
   555 safeMerge(exports, require('./buffers/test-write-types'));
   556 safeMerge(exports, require('./buffers/test-read-types'));
   558 function compareBuffers (assert, buf1, buf2, message) {
   559   let status = true;
   560   for (let i = 0; i < Math.min(buf1.length, buf2.length); i++) {
   561     if (buf1[i] !== buf2[i])
   562       status = false;
   563   }
   564   assert.ok(status, 'buffer successfully copied: ' + message);
   565 }
   566 require('sdk/test').run(exports);

mercurial