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

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:74aab9ad2bf6
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/. */
4
5
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 */
10
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.
31
32 const { Buffer, TextEncoder, TextDecoder } = require('sdk/io/buffer');
33 const { safeMerge } = require('sdk/util/object');
34
35 const ENCODINGS = ['utf-8', 'utf-16le', 'utf-16be'];
36
37 exports.testBufferMain = function (assert) {
38 let b = Buffer('abcdef');
39
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 });
50
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 });
59
60 // invalid encoding for Buffer.toString
61 assert.throws(() => {
62 b.toString('invalid');
63 }, TypeError, 'invalid encoding for Buffer.toString');
64
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');
73
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');
78
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');
85
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);
94
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 };
99
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 };
110
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
115
116 assert.strictEqual(1024, b.length);
117 b[0] = -1;
118 assert.strictEqual(b[0], 255);
119
120 var shimArray = [];
121 for (var i = 0; i < 1024; i++) {
122 b[i] = i % 256;
123 shimArray[i] = i % 256;
124 }
125
126 compareBuffers(assert, b, shimArray, 'array notation');
127
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');
136
137 compareBuffers(assert, b, c, 'copied to other buffer');
138
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');
147
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');
156
157 // copy longer buffer b to shorter c without targetStart
158 b.fill(++cntr);
159 c.fill(++cntr);
160
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');
166
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');
173
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 }
179
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');
186
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');
195
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');
202
203 compareBuffers(assert, b, shimArray.map(()=>cntr),
204 'copy partial buffer to itself');
205
206 // copy string longer than buffer length (failure will segfault)
207 var bb = new Buffer(10);
208 bb.fill('hello crazy world');
209
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');
214
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');
222
223 // throw with negative sourceEnd
224 assert.throws(function() {
225 b.copy(c, 0, 0, -1);
226 }, RangeError, 'buffer copy throws at negative sourceEnd');
227
228 // when sourceStart is greater than sourceEnd, zero copied
229 assert.equal(b.copy(c, 0, 100, 10), 0);
230
231 // when targetStart > targetLength, zero copied
232 assert.equal(b.copy(c, 512, 0, 10), 0);
233
234 // try to copy 0 bytes worth of data into an empty buffer
235 b.copy(new Buffer(0), 0, 0, 0);
236
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);
240
241 // try to copy 0 bytes from past the end of the source buffer
242 b.copy(new Buffer(1), 0, 2048, 2048);
243 };
244
245 exports.testBufferWrite = function (assert) {
246 let b = Buffer(1024);
247 b.fill(0);
248
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');
260
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');
265
266 // testing for smart defaults and ability to pass string values as offset
267
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 };
281
282 exports.testBufferWriteEncoding = function (assert) {
283
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);
289
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 };
311
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);
322
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);
330
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 };
343
344 exports.testBufferSlice = function (assert) {
345 var asciiString = 'hello world';
346 var offset = 100;
347 var b = Buffer(1024);
348 b.fill(0);
349
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);
355
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);
360
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');
365
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');
377
378 // Single argument slice
379 let testBuf = new Buffer('abcde');
380 assert.equal('bcde', testBuf.slice(1).toString(), 'single argument slice');
381
382 // slice(0,0).length === 0
383 assert.equal(0, Buffer('hello').slice(0, 0).length, 'slice(0,0) === 0');
384
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');
393
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');
400
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);
405
406 for (let i = 0; i < sliced.length; i++)
407 sliced[i] = 'jetpack'.charAt(i);
408
409 compareBuffers(assert, b, sliced,
410 'modifying sliced buffer affects original');
411
412 compareBuffers(assert, b, babyslice,
413 'modifying sliced buffer affects child-sliced buffer');
414
415 for (let i = 0; i < sliced.length; i++)
416 b[i] = 'odinmonkey'.charAt(i);
417
418 compareBuffers(assert, b, sliced,
419 'modifying original buffer affects sliced');
420
421 compareBuffers(assert, b, babyslice,
422 'modifying original buffer affects grandchild sliced buffer');
423 };
424
425 exports.testSlicingParents = function (assert) {
426 let root = Buffer(5);
427 let child = root.slice(0, 4);
428 let grandchild = child.slice(0, 3);
429
430 assert.equal(root.parent, undefined, 'a new buffer should not have a parent');
431
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');
435
436 assert.equal(child.parent, root,
437 'a valid slice\'s parent should be the original buffer (child)');
438
439 assert.equal(grandchild.parent, root,
440 'a valid slice\'s parent should be the original buffer (grandchild)');
441 };
442
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 };
451
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'));
457
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);
462
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 };
469
470 exports.testBufferByteLength = function (assert) {
471 let str = '\u00bd + \u00bc = \u00be';
472 assert.equal(Buffer.byteLength(str), 12,
473 'correct byteLength of string');
474
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 };
486
487 exports.testTextEncoderDecoder = function (assert) {
488 assert.ok(TextEncoder, 'TextEncoder exists');
489 assert.ok(TextDecoder, 'TextDecoder exists');
490 };
491
492 exports.testOverflowedBuffers = function (assert) {
493 assert.throws(function() {
494 new Buffer(0xFFFFFFFF);
495 }, RangeError, 'correctly throws buffer overflow');
496
497 assert.throws(function() {
498 new Buffer(0xFFFFFFFFF);
499 }, RangeError, 'correctly throws buffer overflow');
500
501 assert.throws(function() {
502 var buf = new Buffer(8);
503 buf.readFloatLE(0xffffffff);
504 }, RangeError, 'correctly throws buffer overflow with readFloatLE');
505
506 assert.throws(function() {
507 var buf = new Buffer(8);
508 buf.writeFloatLE(0.0, 0xffffffff);
509 }, RangeError, 'correctly throws buffer overflow with writeFloatLE');
510
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');
516
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');
521
522 assert.throws(function() {
523 var buf = new Buffer(8);
524 buf.readFloatLE(-1);
525 }, RangeError, 'correctly throws with readFloatLE with negative values');
526 };
527
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');
534
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');
540
541 assert.throws(function() { buf['readUInt' + bits + 'LE'](0); },
542 RangeError,
543 'readUInt' + bits + 'LE');
544
545 assert.throws(function() { buf['readInt' + bits + 'BE'](0); },
546 RangeError,
547 'readInt' + bits + 'BE()');
548
549 assert.throws(function() { buf['readInt' + bits + 'LE'](0); },
550 RangeError,
551 'readInt' + bits + 'LE()');
552 });
553 };
554
555 safeMerge(exports, require('./buffers/test-write-types'));
556 safeMerge(exports, require('./buffers/test-read-types'));
557
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