Path: blob/main/src/vs/base/test/common/buffer.test.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import assert from 'assert';6import { timeout } from '../../common/async.js';7import { bufferedStreamToBuffer, bufferToReadable, bufferToStream, decodeBase64, decodeHex, encodeBase64, encodeHex, newWriteableBufferStream, readableToBuffer, streamToBuffer, VSBuffer } from '../../common/buffer.js';8import { peekStream } from '../../common/stream.js';9import { ensureNoDisposablesAreLeakedInTestSuite } from './utils.js';1011suite('Buffer', () => {1213ensureNoDisposablesAreLeakedInTestSuite();1415test('issue #71993 - VSBuffer#toString returns numbers', () => {16const data = new Uint8Array([1, 2, 3, 'h'.charCodeAt(0), 'i'.charCodeAt(0), 4, 5]).buffer;17const buffer = VSBuffer.wrap(new Uint8Array(data, 3, 2));18assert.deepStrictEqual(buffer.toString(), 'hi');19});2021test('bufferToReadable / readableToBuffer', () => {22const content = 'Hello World';23const readable = bufferToReadable(VSBuffer.fromString(content));2425assert.strictEqual(readableToBuffer(readable).toString(), content);26});2728test('bufferToStream / streamToBuffer', async () => {29const content = 'Hello World';30const stream = bufferToStream(VSBuffer.fromString(content));3132assert.strictEqual((await streamToBuffer(stream)).toString(), content);33});3435test('bufferedStreamToBuffer', async () => {36const content = 'Hello World';37const stream = await peekStream(bufferToStream(VSBuffer.fromString(content)), 1);3839assert.strictEqual((await bufferedStreamToBuffer(stream)).toString(), content);40});4142test('bufferWriteableStream - basics (no error)', async () => {43const stream = newWriteableBufferStream();4445const chunks: VSBuffer[] = [];46stream.on('data', data => {47chunks.push(data);48});4950let ended = false;51stream.on('end', () => {52ended = true;53});5455const errors: Error[] = [];56stream.on('error', error => {57errors.push(error);58});5960await timeout(0);61stream.write(VSBuffer.fromString('Hello'));62await timeout(0);63stream.end(VSBuffer.fromString('World'));6465assert.strictEqual(chunks.length, 2);66assert.strictEqual(chunks[0].toString(), 'Hello');67assert.strictEqual(chunks[1].toString(), 'World');68assert.strictEqual(ended, true);69assert.strictEqual(errors.length, 0);70});7172test('bufferWriteableStream - basics (error)', async () => {73const stream = newWriteableBufferStream();7475const chunks: VSBuffer[] = [];76stream.on('data', data => {77chunks.push(data);78});7980let ended = false;81stream.on('end', () => {82ended = true;83});8485const errors: Error[] = [];86stream.on('error', error => {87errors.push(error);88});8990await timeout(0);91stream.write(VSBuffer.fromString('Hello'));92await timeout(0);93stream.error(new Error());94stream.end();9596assert.strictEqual(chunks.length, 1);97assert.strictEqual(chunks[0].toString(), 'Hello');98assert.strictEqual(ended, true);99assert.strictEqual(errors.length, 1);100});101102test('bufferWriteableStream - buffers data when no listener', async () => {103const stream = newWriteableBufferStream();104105await timeout(0);106stream.write(VSBuffer.fromString('Hello'));107await timeout(0);108stream.end(VSBuffer.fromString('World'));109110const chunks: VSBuffer[] = [];111stream.on('data', data => {112chunks.push(data);113});114115let ended = false;116stream.on('end', () => {117ended = true;118});119120const errors: Error[] = [];121stream.on('error', error => {122errors.push(error);123});124125assert.strictEqual(chunks.length, 1);126assert.strictEqual(chunks[0].toString(), 'HelloWorld');127assert.strictEqual(ended, true);128assert.strictEqual(errors.length, 0);129});130131test('bufferWriteableStream - buffers errors when no listener', async () => {132const stream = newWriteableBufferStream();133134await timeout(0);135stream.write(VSBuffer.fromString('Hello'));136await timeout(0);137stream.error(new Error());138139const chunks: VSBuffer[] = [];140stream.on('data', data => {141chunks.push(data);142});143144const errors: Error[] = [];145stream.on('error', error => {146errors.push(error);147});148149let ended = false;150stream.on('end', () => {151ended = true;152});153154stream.end();155156assert.strictEqual(chunks.length, 1);157assert.strictEqual(chunks[0].toString(), 'Hello');158assert.strictEqual(ended, true);159assert.strictEqual(errors.length, 1);160});161162test('bufferWriteableStream - buffers end when no listener', async () => {163const stream = newWriteableBufferStream();164165await timeout(0);166stream.write(VSBuffer.fromString('Hello'));167await timeout(0);168stream.end(VSBuffer.fromString('World'));169170let ended = false;171stream.on('end', () => {172ended = true;173});174175const chunks: VSBuffer[] = [];176stream.on('data', data => {177chunks.push(data);178});179180const errors: Error[] = [];181stream.on('error', error => {182errors.push(error);183});184185assert.strictEqual(chunks.length, 1);186assert.strictEqual(chunks[0].toString(), 'HelloWorld');187assert.strictEqual(ended, true);188assert.strictEqual(errors.length, 0);189});190191test('bufferWriteableStream - nothing happens after end()', async () => {192const stream = newWriteableBufferStream();193194const chunks: VSBuffer[] = [];195stream.on('data', data => {196chunks.push(data);197});198199await timeout(0);200stream.write(VSBuffer.fromString('Hello'));201await timeout(0);202stream.end(VSBuffer.fromString('World'));203204let dataCalledAfterEnd = false;205stream.on('data', data => {206dataCalledAfterEnd = true;207});208209let errorCalledAfterEnd = false;210stream.on('error', error => {211errorCalledAfterEnd = true;212});213214let endCalledAfterEnd = false;215stream.on('end', () => {216endCalledAfterEnd = true;217});218219await timeout(0);220stream.write(VSBuffer.fromString('Hello'));221await timeout(0);222stream.error(new Error());223await timeout(0);224stream.end(VSBuffer.fromString('World'));225226assert.strictEqual(dataCalledAfterEnd, false);227assert.strictEqual(errorCalledAfterEnd, false);228assert.strictEqual(endCalledAfterEnd, false);229230assert.strictEqual(chunks.length, 2);231assert.strictEqual(chunks[0].toString(), 'Hello');232assert.strictEqual(chunks[1].toString(), 'World');233});234235test('bufferWriteableStream - pause/resume (simple)', async () => {236const stream = newWriteableBufferStream();237238const chunks: VSBuffer[] = [];239stream.on('data', data => {240chunks.push(data);241});242243let ended = false;244stream.on('end', () => {245ended = true;246});247248const errors: Error[] = [];249stream.on('error', error => {250errors.push(error);251});252253stream.pause();254255await timeout(0);256stream.write(VSBuffer.fromString('Hello'));257await timeout(0);258stream.end(VSBuffer.fromString('World'));259260assert.strictEqual(chunks.length, 0);261assert.strictEqual(errors.length, 0);262assert.strictEqual(ended, false);263264stream.resume();265266assert.strictEqual(chunks.length, 1);267assert.strictEqual(chunks[0].toString(), 'HelloWorld');268assert.strictEqual(ended, true);269assert.strictEqual(errors.length, 0);270});271272test('bufferWriteableStream - pause/resume (pause after first write)', async () => {273const stream = newWriteableBufferStream();274275const chunks: VSBuffer[] = [];276stream.on('data', data => {277chunks.push(data);278});279280let ended = false;281stream.on('end', () => {282ended = true;283});284285const errors: Error[] = [];286stream.on('error', error => {287errors.push(error);288});289290await timeout(0);291stream.write(VSBuffer.fromString('Hello'));292293stream.pause();294295await timeout(0);296stream.end(VSBuffer.fromString('World'));297298assert.strictEqual(chunks.length, 1);299assert.strictEqual(chunks[0].toString(), 'Hello');300assert.strictEqual(errors.length, 0);301assert.strictEqual(ended, false);302303stream.resume();304305assert.strictEqual(chunks.length, 2);306assert.strictEqual(chunks[0].toString(), 'Hello');307assert.strictEqual(chunks[1].toString(), 'World');308assert.strictEqual(ended, true);309assert.strictEqual(errors.length, 0);310});311312test('bufferWriteableStream - pause/resume (error)', async () => {313const stream = newWriteableBufferStream();314315const chunks: VSBuffer[] = [];316stream.on('data', data => {317chunks.push(data);318});319320let ended = false;321stream.on('end', () => {322ended = true;323});324325const errors: Error[] = [];326stream.on('error', error => {327errors.push(error);328});329330stream.pause();331332await timeout(0);333stream.write(VSBuffer.fromString('Hello'));334await timeout(0);335stream.error(new Error());336stream.end();337338assert.strictEqual(chunks.length, 0);339assert.strictEqual(ended, false);340assert.strictEqual(errors.length, 0);341342stream.resume();343344assert.strictEqual(chunks.length, 1);345assert.strictEqual(chunks[0].toString(), 'Hello');346assert.strictEqual(ended, true);347assert.strictEqual(errors.length, 1);348});349350test('bufferWriteableStream - destroy', async () => {351const stream = newWriteableBufferStream();352353const chunks: VSBuffer[] = [];354stream.on('data', data => {355chunks.push(data);356});357358let ended = false;359stream.on('end', () => {360ended = true;361});362363const errors: Error[] = [];364stream.on('error', error => {365errors.push(error);366});367368stream.destroy();369370await timeout(0);371stream.write(VSBuffer.fromString('Hello'));372await timeout(0);373stream.end(VSBuffer.fromString('World'));374375assert.strictEqual(chunks.length, 0);376assert.strictEqual(ended, false);377assert.strictEqual(errors.length, 0);378});379380test('Performance issue with VSBuffer#slice #76076', function () { // TODO@alexdima this test seems to fail in web (https://github.com/microsoft/vscode/issues/114042)381// Buffer#slice creates a view382if (typeof Buffer !== 'undefined') {383const buff = Buffer.from([10, 20, 30, 40]);384const b2 = buff.slice(1, 3);385assert.strictEqual(buff[1], 20);386assert.strictEqual(b2[0], 20);387388buff[1] = 17; // modify buff AND b2389assert.strictEqual(buff[1], 17);390assert.strictEqual(b2[0], 17);391}392393// TypedArray#slice creates a copy394{395const unit = new Uint8Array([10, 20, 30, 40]);396const u2 = unit.slice(1, 3);397assert.strictEqual(unit[1], 20);398assert.strictEqual(u2[0], 20);399400unit[1] = 17; // modify unit, NOT b2401assert.strictEqual(unit[1], 17);402assert.strictEqual(u2[0], 20);403}404405// TypedArray#subarray creates a view406{407const unit = new Uint8Array([10, 20, 30, 40]);408const u2 = unit.subarray(1, 3);409assert.strictEqual(unit[1], 20);410assert.strictEqual(u2[0], 20);411412unit[1] = 17; // modify unit AND b2413assert.strictEqual(unit[1], 17);414assert.strictEqual(u2[0], 17);415}416});417418test('indexOf', () => {419const haystack = VSBuffer.fromString('abcaabbccaaabbbccc');420assert.strictEqual(haystack.indexOf(VSBuffer.fromString('')), 0);421assert.strictEqual(haystack.indexOf(VSBuffer.fromString('a'.repeat(100))), -1);422423assert.strictEqual(haystack.indexOf(VSBuffer.fromString('a')), 0);424assert.strictEqual(haystack.indexOf(VSBuffer.fromString('c')), 2);425426assert.strictEqual(haystack.indexOf(VSBuffer.fromString('abcaa')), 0);427assert.strictEqual(haystack.indexOf(VSBuffer.fromString('caaab')), 8);428assert.strictEqual(haystack.indexOf(VSBuffer.fromString('ccc')), 15);429430assert.strictEqual(haystack.indexOf(VSBuffer.fromString('cccb')), -1);431});432433test('wrap', () => {434const actual = new Uint8Array([1, 2, 3]);435const wrapped = VSBuffer.wrap(actual);436assert.strictEqual(wrapped.byteLength, 3);437assert.deepStrictEqual(Array.from(wrapped.buffer), [1, 2, 3]);438});439440test('fromString', () => {441const value = 'Hello World';442const buff = VSBuffer.fromString(value);443assert.strictEqual(buff.toString(), value);444});445446test('fromByteArray', () => {447const array = [1, 2, 3, 4, 5];448const buff = VSBuffer.fromByteArray(array);449assert.strictEqual(buff.byteLength, array.length);450assert.deepStrictEqual(Array.from(buff.buffer), array);451});452453test('concat', () => {454const chunks = [455VSBuffer.fromString('abc'),456VSBuffer.fromString('def'),457VSBuffer.fromString('ghi')458];459460// Test without total length461const result1 = VSBuffer.concat(chunks);462assert.strictEqual(result1.toString(), 'abcdefghi');463464// Test with total length465const result2 = VSBuffer.concat(chunks, 9);466assert.strictEqual(result2.toString(), 'abcdefghi');467});468469test('clone', () => {470const original = VSBuffer.fromString('test');471const clone = original.clone();472473assert.notStrictEqual(original.buffer, clone.buffer);474assert.deepStrictEqual(Array.from(original.buffer), Array.from(clone.buffer));475});476477test('slice', () => {478const buff = VSBuffer.fromString('Hello World');479480const slice1 = buff.slice(0, 5);481assert.strictEqual(slice1.toString(), 'Hello');482483const slice2 = buff.slice(6);484assert.strictEqual(slice2.toString(), 'World');485});486487test('set', () => {488const buff = VSBuffer.alloc(5);489490// Test setting from VSBuffer491buff.set(VSBuffer.fromString('ab'), 0);492assert.strictEqual(buff.toString().substring(0, 2), 'ab');493494// Test setting from Uint8Array495buff.set(new Uint8Array([99, 100]), 2); // 'cd'496assert.strictEqual(buff.toString().substring(2, 4), 'cd');497498// Test invalid input499assert.throws(() => {500buff.set({} as any);501});502});503504test('equals', () => {505const buff1 = VSBuffer.fromString('test');506const buff2 = VSBuffer.fromString('test');507const buff3 = VSBuffer.fromString('different');508const buff4 = VSBuffer.fromString('tes1');509510assert.strictEqual(buff1.equals(buff1), true);511assert.strictEqual(buff1.equals(buff2), true);512assert.strictEqual(buff1.equals(buff3), false);513assert.strictEqual(buff1.equals(buff4), false);514});515516test('read/write methods', () => {517const buff = VSBuffer.alloc(8);518519// Test UInt32BE520buff.writeUInt32BE(0x12345678, 0);521assert.strictEqual(buff.readUInt32BE(0), 0x12345678);522523// Test UInt32LE524buff.writeUInt32LE(0x12345678, 4);525assert.strictEqual(buff.readUInt32LE(4), 0x12345678);526527// Test UInt8528const buff2 = VSBuffer.alloc(1);529buff2.writeUInt8(123, 0);530assert.strictEqual(buff2.readUInt8(0), 123);531});532533suite('encoding', () => {534/*535Generated with:536537const crypto = require('crypto');538539for (let i = 0; i < 16; i++) {540const buf = crypto.randomBytes(i);541console.log(`[new Uint8Array([${Array.from(buf).join(', ')}]), '${buf.toString('base64')}'],`)542}543544*/545546const testCases: [Uint8Array, base64: string, hex: string][] = [547[new Uint8Array([]), '', ''],548[new Uint8Array([77]), 'TQ==', '4d'],549[new Uint8Array([230, 138]), '5oo=', 'e68a'],550[new Uint8Array([104, 98, 82]), 'aGJS', '686252'],551[new Uint8Array([92, 114, 57, 209]), 'XHI50Q==', '5c7239d1'],552[new Uint8Array([238, 51, 1, 240, 124]), '7jMB8Hw=', 'ee3301f07c'],553[new Uint8Array([96, 54, 130, 79, 47, 179]), 'YDaCTy+z', '6036824f2fb3'],554[new Uint8Array([91, 22, 68, 217, 68, 117, 116]), 'WxZE2UR1dA==', '5b1644d9447574'],555[new Uint8Array([184, 227, 214, 171, 244, 175, 141, 53]), 'uOPWq/SvjTU=', 'b8e3d6abf4af8d35'],556[new Uint8Array([53, 98, 93, 130, 71, 117, 191, 137, 156]), 'NWJdgkd1v4mc', '35625d824775bf899c'],557[new Uint8Array([154, 156, 60, 102, 232, 197, 92, 25, 124, 98]), 'mpw8ZujFXBl8Yg==', '9a9c3c66e8c55c197c62'],558[new Uint8Array([152, 131, 106, 234, 17, 183, 164, 245, 252, 67, 26]), 'mINq6hG3pPX8Qxo=', '98836aea11b7a4f5fc431a'],559[new Uint8Array([232, 254, 194, 234, 16, 42, 86, 135, 117, 61, 179, 4]), '6P7C6hAqVod1PbME', 'e8fec2ea102a5687753db304'],560[new Uint8Array([4, 199, 85, 172, 125, 171, 172, 219, 61, 47, 78, 155, 127]), 'BMdVrH2rrNs9L06bfw==', '04c755ac7dabacdb3d2f4e9b7f'],561[new Uint8Array([189, 67, 62, 189, 87, 171, 27, 164, 87, 142, 126, 113, 23, 182]), 'vUM+vVerG6RXjn5xF7Y=', 'bd433ebd57ab1ba4578e7e7117b6'],562[new Uint8Array([153, 156, 145, 240, 228, 200, 199, 158, 40, 167, 97, 52, 217, 148, 43]), 'mZyR8OTIx54op2E02ZQr', '999c91f0e4c8c79e28a76134d9942b'],563];564565test('encodes base64', () => {566for (const [bytes, expected] of testCases) {567assert.strictEqual(encodeBase64(VSBuffer.wrap(bytes)), expected);568}569});570571test('decodes, base64', () => {572for (const [expected, encoded] of testCases) {573assert.deepStrictEqual(new Uint8Array(decodeBase64(encoded).buffer), expected);574}575});576577test('encodes hex', () => {578for (const [bytes, , expected] of testCases) {579assert.strictEqual(encodeHex(VSBuffer.wrap(bytes)), expected);580}581});582583test('decodes, hex', () => {584for (const [expected, , encoded] of testCases) {585assert.deepStrictEqual(new Uint8Array(decodeHex(encoded).buffer), expected);586}587});588589test('throws error on invalid encoding', () => {590assert.throws(() => decodeBase64('invalid!'));591assert.throws(() => decodeHex('invalid!'));592});593});594});595596597