get tests to pass

Co-authored-by: Daniel Imms <daimms@microsoft.com>
This commit is contained in:
meganrogge
2021-04-01 13:17:53 -07:00
parent b074c2552a
commit c096633f91
7 changed files with 109 additions and 126 deletions
+5 -5
View File
@@ -56,25 +56,25 @@ describe('Terminal', () => {
// term.handler('fake');
// });
it('should fire the onCursorMove event', () => {
return new Promise(async r => {
return new Promise<void>(async r => {
term.onCursorMove(() => r());
await term.writeP('foo');
});
});
it('should fire the onLineFeed event', () => {
return new Promise(async r => {
return new Promise<void>(async r => {
term.onLineFeed(() => r());
await term.writeP('\n');
});
});
it('should fire a scroll event when scrollback is created', () => {
return new Promise(async r => {
return new Promise<void>(async r => {
term.onScroll(() => r());
await term.writeP('\n'.repeat(INIT_ROWS));
});
});
it('should fire a scroll event when scrollback is cleared', () => {
return new Promise(async r => {
return new Promise<void>(async r => {
await term.writeP('\n'.repeat(INIT_ROWS));
term.onScroll(() => r());
term.clear();
@@ -233,7 +233,7 @@ describe('Terminal', () => {
term.paste('\r\nfoo\nbar\r');
});
it('should respect bracketed paste mode', () => {
return new Promise(async r => {
return new Promise<void>(async r => {
term.onData(e => {
assert.equal(e, '\x1b[200~foo\x1b[201~');
r();
-1
View File
@@ -147,7 +147,6 @@ export class Terminal extends CoreTerminal implements ITerminal {
this.register(this._inputHandler.onRequestBell(() => this.bell()));
this.register(this._inputHandler.onRequestRefreshRows((start, end) => this.refresh(start, end)));
this.register(this._inputHandler.onRequestReset(() => this.reset()));
this.register(this._inputHandler.onRequestScroll((eraseAttr, isWrapped) => this._bufferService.scroll(eraseAttr, isWrapped || undefined)));
this.register(this._inputHandler.onRequestWindowsOptionsReport(type => this._reportWindowsOptions(type)));
this.register(this._inputHandler.onAnsiColorChange((event) => this._changeAnsiColor(event)));
this.register(forwardEvent(this._inputHandler.onCursorMove, this._onCursorMove));
+4 -1
View File
@@ -123,7 +123,10 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
this.register(forwardEvent(this._coreService.onData, this._onData));
this.register(forwardEvent(this._coreService.onBinary, this._onBinary));
this.register(this.optionsService.onOptionChange(key => this._updateOptions(key)));
this.register(this._bufferService.onScroll(event => this._onScroll.fire(event)));
this.register(this._bufferService.onScroll(event => {
this._onScroll.fire(event);
this._dirtyRowService.markRangeDirty(this._bufferService.buffer.scrollTop, this._bufferService.buffer.scrollBottom);
}));
// Setup WriteBuffer
this._writeBuffer = new WriteBuffer((data, promiseResult) => this._inputHandler.parse(data, promiseResult));
+96 -103
View File
@@ -71,115 +71,108 @@ describe('InputHandler', () => {
inputHandler = new TestInputHandler(bufferService, new MockCharsetService(), coreService, new MockDirtyRowService(), new MockLogService(), optionsService, new MockCoreMouseService(), new MockUnicodeService());
});
describe('Terminal InputHandler integration', () => {
function getLines(limit: number): string[] {
const res: string[] = [];
for (let i = 0; i < limit; ++i) {
res.push(bufferService.buffer.lines.get(i)!.translateToString(true));
}
return res;
}
function reset(): void {
bufferService.buffer.y = 0;
bufferService.buffer.x = 0;
}
// This suite cannot live in InputHandler unless Terminal.scroll moved into IBufferService
describe('SL/SR/DECIC/DECDC', () => {
it('SL (scrollLeft)', async () => {
inputHandler.parseP('12345'.repeat(6));
assert.deepEqual(getLines(6), ['12345', '2345', '2345', '2345', '2345', '2345']);
inputHandler.parseP('\x1b[0 @');
assert.deepEqual(getLines(6), ['12345', '345', '345', '345', '345', '345']);
inputHandler.parseP('\x1b[2 @');
assert.deepEqual(getLines(6), ['12345', '5', '5', '5', '5', '5']);
});
it('SR (scrollRight)', async () => {
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[ A');
assert.deepEqual(getLines(6), ['12345', ' 1234', ' 1234', ' 1234', ' 1234', ' 1234']);
inputHandler.parseP('\x1b[0 A');
assert.deepEqual(getLines(6), ['12345', ' 123', ' 123', ' 123', ' 123', ' 123']);
inputHandler.parseP('\x1b[2 A');
assert.deepEqual(getLines(6), ['12345', ' 1', ' 1', ' 1', ' 1', ' 1']);
});
it('insertColumns (DECIC)', async () => {
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[\'}');
assert.deepEqual(getLines(6), ['12345', '12 34', '12 34', '12 34', '12 34', '12 34']);
reset();
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[1\'}');
assert.deepEqual(getLines(6), ['12345', '12 34', '12 34', '12 34', '12 34', '12 34']);
reset();
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[2\'}');
assert.deepEqual(getLines(6), ['12345', '12 3', '12 3', '12 3', '12 3', '12 3']);
});
it('deleteColumns (DECDC)', async () => {
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[\'~');
assert.deepEqual(getLines(6), ['12345', '1245', '1245', '1245', '1245', '1245']);
reset();
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[1\'~');
assert.deepEqual(getLines(6), ['12345', '1245', '1245', '1245', '1245', '1245']);
reset();
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[2\'~');
assert.deepEqual(getLines(6), ['12345', '125', '125', '125', '125', '125']);
});
describe('SL/SR/DECIC/DECDC', () => {
beforeEach(() => {
bufferService.resize(5, 5);
optionsService.options.scrollback = 1;
bufferService.reset();
});
it('SL (scrollLeft)', async () => {
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[ @');
assert.deepEqual(getLines(bufferService, 6), ['12345', '2345', '2345', '2345', '2345', '2345']);
inputHandler.parseP('\x1b[0 @');
assert.deepEqual(getLines(bufferService, 6), ['12345', '345', '345', '345', '345', '345']);
inputHandler.parseP('\x1b[2 @');
assert.deepEqual(getLines(bufferService, 6), ['12345', '5', '5', '5', '5', '5']);
});
it('SR (scrollRight)', async () => {
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[ A');
assert.deepEqual(getLines(bufferService, 6), ['12345', ' 1234', ' 1234', ' 1234', ' 1234', ' 1234']);
inputHandler.parseP('\x1b[0 A');
assert.deepEqual(getLines(bufferService, 6), ['12345', ' 123', ' 123', ' 123', ' 123', ' 123']);
inputHandler.parseP('\x1b[2 A');
assert.deepEqual(getLines(bufferService, 6), ['12345', ' 1', ' 1', ' 1', ' 1', ' 1']);
});
it('insertColumns (DECIC)', async () => {
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[\'}');
assert.deepEqual(getLines(bufferService, 6), ['12345', '12 34', '12 34', '12 34', '12 34', '12 34']);
bufferService.reset();
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[1\'}');
assert.deepEqual(getLines(bufferService, 6), ['12345', '12 34', '12 34', '12 34', '12 34', '12 34']);
bufferService.reset();
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[2\'}');
assert.deepEqual(getLines(bufferService, 6), ['12345', '12 3', '12 3', '12 3', '12 3', '12 3']);
});
it('deleteColumns (DECDC)', async () => {
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[\'~');
assert.deepEqual(getLines(bufferService, 6), ['12345', '1245', '1245', '1245', '1245', '1245']);
bufferService.reset();
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[1\'~');
assert.deepEqual(getLines(bufferService, 6), ['12345', '1245', '1245', '1245', '1245', '1245']);
bufferService.reset();
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[2\'~');
assert.deepEqual(getLines(bufferService, 6), ['12345', '125', '125', '125', '125', '125']);
});
});
describe('BS with reverseWraparound set/unset', () => {
const ttyBS = '\x08 \x08'; // tty ICANON sends <BS SP BS> on pressing BS
describe('BS with reverseWraparound set/unset', () => {
const ttyBS = '\x08 \x08'; // tty ICANON sends <BS SP BS> on pressing BS
beforeEach(() => {
bufferService.resize(5, 5);
optionsService.options.scrollback = 1;
bufferService.reset();
});
describe('reverseWraparound set', () => {
it('should not reverse outside of scroll margins', async () => {
// prepare buffer content
inputHandler.parseP('#####abcdefghijklmnopqrstuvwxy');
assert.deepEqual(getLines(bufferService, 6), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', 'uvwxy']);
assert.equal(bufferService.buffers.active.ydisp, 1);
assert.equal(bufferService.buffers.active.x, 5);
assert.equal(bufferService.buffers.active.y, 4);
inputHandler.parseP(ttyBS.repeat(100));
assert.deepEqual(getLines(bufferService, 6), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', ' y']);
describe('reverseWraparound set', () => {
it('should not reverse outside of scroll margins', async () => {
// prepare buffer content
inputHandler.parseP('#####abcdefghijklmnopqrstuvwxy');
assert.deepEqual(getLines(5), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', 'uvwxy']);
assert.equal(bufferService.buffers.active.ydisp, 1);
assert.equal(bufferService.buffers.active.x, 5);
assert.equal(bufferService.buffers.active.y, 4);
inputHandler.parseP(ttyBS.repeat(100));
assert.deepEqual(getLines(5), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', ' y']);
inputHandler.parseP('\x1b[?45h');
inputHandler.parseP('uvwxy');
inputHandler.parseP('\x1b[?45h');
inputHandler.parseP('uvwxy');
// set top/bottom to 1/3 (0-based)
inputHandler.parseP('\x1b[2;4r');
// place cursor below scroll bottom
bufferService.buffers.active.x = 5;
bufferService.buffers.active.y = 4;
inputHandler.parseP(ttyBS.repeat(100));
assert.deepEqual(getLines(bufferService, 6), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', ' ']);
// set top/bottom to 1/3 (0-based)
inputHandler.parseP('\x1b[2;4r');
// place cursor below scroll bottom
bufferService.buffers.active.x = 5;
bufferService.buffers.active.y = 4;
inputHandler.parseP(ttyBS.repeat(100));
assert.deepEqual(getLines(5), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', ' ']);
inputHandler.parseP('uvwxy');
// place cursor within scroll margins
bufferService.buffers.active.x = 5;
bufferService.buffers.active.y = 3;
inputHandler.parseP(ttyBS.repeat(100));
assert.deepEqual(getLines(bufferService, 6), ['#####', 'abcde', ' ', ' ', ' ', 'uvwxy']);
assert.equal(bufferService.buffers.active.x, 0);
assert.equal(bufferService.buffers.active.y, bufferService.buffers.active.scrollTop); // stops at 0, scrollTop
inputHandler.parseP('uvwxy');
// place cursor within scroll margins
bufferService.buffers.active.x = 5;
bufferService.buffers.active.y = 3;
inputHandler.parseP(ttyBS.repeat(100));
assert.deepEqual(getLines(5), ['#####', 'abcde', ' ', ' ', ' ', 'uvwxy']);
assert.equal(bufferService.buffers.active.x, 0);
assert.equal(bufferService.buffers.active.y, bufferService.buffers.active.scrollTop); // stops at 0, scrollTop
inputHandler.parseP('fghijklmnopqrst');
// place cursor above scroll top
bufferService.buffers.active.x = 5;
bufferService.buffers.active.y = 0;
inputHandler.parseP(ttyBS.repeat(100));
assert.deepEqual(getLines(5), ['#####', ' ', 'fghij', 'klmno', 'pqrst', 'uvwxy']);
});
inputHandler.parseP('fghijklmnopqrst');
// place cursor above scroll top
bufferService.buffers.active.x = 5;
bufferService.buffers.active.y = 0;
inputHandler.parseP(ttyBS.repeat(100));
assert.deepEqual(getLines(bufferService, 6), ['#####', ' ', 'fghij', 'klmno', 'pqrst', 'uvwxy']);
});
});
});
+3 -5
View File
@@ -240,8 +240,6 @@ export class InputHandler extends Disposable implements IInputHandler {
public get onRequestRefreshRows(): IEvent<number, number> { return this._onRequestRefreshRows.event; }
private _onRequestReset = new EventEmitter<void>();
public get onRequestReset(): IEvent<void> { return this._onRequestReset.event; }
private _onRequestScroll = new EventEmitter<IAttributeData, boolean | void>();
public get onRequestScroll(): IEvent<IAttributeData, boolean | void> { return this._onRequestScroll.event; }
private _onRequestSyncScrollBar = new EventEmitter<void>();
public get onRequestSyncScrollBar(): IEvent<void> { return this._onRequestSyncScrollBar.event; }
private _onRequestWindowsOptionsReport = new EventEmitter<WindowsOptionsReportType>();
@@ -651,7 +649,7 @@ export class InputHandler extends Disposable implements IInputHandler {
buffer.y++;
if (buffer.y === buffer.scrollBottom + 1) {
buffer.y--;
this._onRequestScroll.fire(this._eraseAttrData(), true);
this._bufferService.scroll(this._eraseAttrData(), true);
} else {
if (buffer.y >= this._bufferService.rows) {
buffer.y = this._bufferService.rows - 1;
@@ -791,7 +789,7 @@ export class InputHandler extends Disposable implements IInputHandler {
buffer.y++;
if (buffer.y === buffer.scrollBottom + 1) {
buffer.y--;
this._onRequestScroll.fire(this._eraseAttrData());
this._bufferService.scroll(this._eraseAttrData());
} else if (buffer.y >= this._bufferService.rows) {
buffer.y = this._bufferService.rows - 1;
}
@@ -2987,7 +2985,7 @@ export class InputHandler extends Disposable implements IInputHandler {
this._bufferService.buffer.y++;
if (buffer.y === buffer.scrollBottom + 1) {
buffer.y--;
this._onRequestScroll.fire(this._eraseAttrData());
this._bufferService.scroll(this._eraseAttrData());
} else if (buffer.y >= this._bufferService.rows) {
buffer.y = this._bufferService.rows - 1;
}
-1
View File
@@ -357,7 +357,6 @@ export interface IAnsiColorChangeEvent {
*/
export interface IInputHandler {
onTitleChange: IEvent<string>;
onRequestScroll: IEvent<IAttributeData, boolean | void>;
parse(data: string | Uint8Array, promiseResult?: boolean): void | Promise<boolean>;
print(data: Uint32Array, start: number, end: number): void;
+1 -10
View File
@@ -3,13 +3,12 @@
* @license MIT
*/
import { IBufferService, IDirtyRowService, IInstantiationService, IOptionsService } from 'common/services/Services';
import { IBufferService, IOptionsService } from 'common/services/Services';
import { BufferSet } from 'common/buffer/BufferSet';
import { IBufferSet, IBuffer } from 'common/buffer/Types';
import { EventEmitter, IEvent } from 'common/EventEmitter';
import { Disposable } from 'common/Lifecycle';
import { IAttributeData, IBufferLine } from 'common/Types';
import { DirtyRowService } from 'common/services/DirtyRowService';
export const MINIMUM_COLS = 2; // Less than 2 can mess with wide chars
export const MINIMUM_ROWS = 1;
@@ -33,8 +32,6 @@ export class BufferService extends Disposable implements IBufferService {
/** An IBufferline to clone/copy from for new blank lines */
private _cachedBlankLine: IBufferLine | undefined;
private _dirtyRowService: IDirtyRowService | undefined;
constructor(
@IOptionsService private _optionsService: IOptionsService
) {
@@ -123,12 +120,6 @@ export class BufferService extends Disposable implements IBufferService {
buffer.ydisp = buffer.ybase;
}
// Flag rows that need updating
if (!this._dirtyRowService) {
this._dirtyRowService = new DirtyRowService(this);
}
this._dirtyRowService?.markRangeDirty(buffer.scrollTop, buffer.scrollBottom);
this._onScroll.fire(buffer.ydisp);
}