/** * Copyright (c) 2019 The xterm.js authors. All rights reserved. * @license MIT */ import { assert } from 'chai'; import { WriteBuffer } from './WriteBuffer'; // eslint-disable-next-line @typescript-eslint/naming-convention declare let Buffer: any; function toBytes(s: string): Uint8Array { return Buffer.from(s); } function fromBytes(bytes: Uint8Array): string { return bytes.toString(); } describe('WriteBuffer', () => { let wb: WriteBuffer; let stack: (string | Uint8Array)[] = []; let cbStack: string[] = []; beforeEach(() => { stack = []; cbStack = []; wb = new WriteBuffer(data => { stack.push(data); }); }); describe('write input', () => { it('string', done => { wb.write('a._'); wb.write('b.x', () => { cbStack.push('b'); }); wb.write('c._'); wb.write('d.x', () => { cbStack.push('d'); }); wb.write('e', () => { assert.deepEqual(stack, ['a._', 'b.x', 'c._', 'd.x', 'e']); assert.deepEqual(cbStack, ['b', 'd']); done(); }); }); it('bytes', done => { wb.write(toBytes('a._')); wb.write(toBytes('b.x'), () => { cbStack.push('b'); }); wb.write(toBytes('c._')); wb.write(toBytes('d.x'), () => { cbStack.push('d'); }); wb.write(toBytes('e'), () => { assert.deepEqual(stack.map(val => typeof val === 'string' ? '' : fromBytes(val)), ['a._', 'b.x', 'c._', 'd.x', 'e']); assert.deepEqual(cbStack, ['b', 'd']); done(); }); }); it('string/bytes mixed', done => { wb.write('a._'); wb.write('b.x', () => { cbStack.push('b'); }); wb.write(toBytes('c._')); wb.write(toBytes('d.x'), () => { cbStack.push('d'); }); wb.write(toBytes('e'), () => { assert.deepEqual(stack.map(val => typeof val === 'string' ? val : fromBytes(val)), ['a._', 'b.x', 'c._', 'd.x', 'e']); assert.deepEqual(cbStack, ['b', 'd']); done(); }); }); it('write callback works for empty chunks', done => { wb.write('a', () => { cbStack.push('a'); }); wb.write('', () => { cbStack.push('b'); }); wb.write(toBytes('c'), () => { cbStack.push('c'); }); wb.write(new Uint8Array(0), () => { cbStack.push('d'); }); wb.write('e', () => { assert.deepEqual(stack.map(val => typeof val === 'string' ? val : fromBytes(val)), ['a', '', 'c', '', 'e']); assert.deepEqual(cbStack, ['a', 'b', 'c', 'd']); done(); }); }); it('writeSync', done => { wb.write('a', () => { cbStack.push('a'); }); wb.write('b', () => { cbStack.push('b'); }); wb.write('c', () => { cbStack.push('c'); }); wb.writeSync('d'); assert.deepEqual(stack, ['a', 'b', 'c', 'd']); assert.deepEqual(cbStack, ['a', 'b', 'c']); wb.write('x', () => { cbStack.push('x'); }); wb.write('', () => { assert.deepEqual(stack, ['a', 'b', 'c', 'd', 'x', '']); assert.deepEqual(cbStack, ['a', 'b', 'c', 'x']); done(); }); }); it('writeSync called from action does not overflow callstack - issue #3265', () => { wb = new WriteBuffer(data => { const num = parseInt(data as string); if (num < 1000000) { wb.writeSync('' + (num + 1)); } }); wb.writeSync('1'); }); it('writeSync maxSubsequentCalls argument', () => { let last: string = ''; wb = new WriteBuffer(data => { last = data as string; const num = parseInt(data as string); if (num < 1000000) { wb.writeSync('' + (num + 1), 10); } }); wb.writeSync('1', 10); assert.equal(last, '11'); // 1 + 10 sub calls = 11 }); }); });