mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
fix test cases
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { EscapeSequenceParser, IParserTerminal, ParserState } from './EscapeSequenceParser';
|
||||
import { EscapeSequenceParser, ParserState, IDcsHandler } from './EscapeSequenceParser';
|
||||
import * as chai from 'chai';
|
||||
|
||||
function r(a: number, b: number): string[] {
|
||||
@@ -10,13 +10,7 @@ function r(a: number, b: number): string[] {
|
||||
return arr;
|
||||
}
|
||||
|
||||
interface ITestTerminal extends IParserTerminal {
|
||||
calls: any[];
|
||||
clear: () => void;
|
||||
compare: (value: any) => void;
|
||||
}
|
||||
|
||||
let testTerminal: ITestTerminal = {
|
||||
let testTerminal: any = {
|
||||
calls: [],
|
||||
clear: function (): void {
|
||||
this.calls = [];
|
||||
@@ -33,14 +27,14 @@ let testTerminal: ITestTerminal = {
|
||||
actionExecute: function (flag: string): void {
|
||||
this.calls.push(['exe', flag]);
|
||||
},
|
||||
actionCSI: function (collected: string, params: number[], flag: string): void {
|
||||
this.calls.push(['csi', collected, params, flag]);
|
||||
actionCSI: function (collect: string, params: number[], flag: string): void {
|
||||
this.calls.push(['csi', collect, params, flag]);
|
||||
},
|
||||
actionESC: function (collected: string, flag: string): void {
|
||||
this.calls.push(['esc', collected, flag]);
|
||||
actionESC: function (collect: string, flag: string): void {
|
||||
this.calls.push(['esc', collect, flag]);
|
||||
},
|
||||
actionDCSHook: function (collected: string, params: number[], flag: string): void {
|
||||
this.calls.push(['dcs hook', collected, params, flag]);
|
||||
actionDCSHook: function (collect: string, params: number[], flag: string): void {
|
||||
this.calls.push(['dcs hook', collect, params, flag]);
|
||||
},
|
||||
actionDCSPrint: function (data: string, start: number, end: number): void {
|
||||
this.calls.push(['dcs put', data.substring(start, end)]);
|
||||
@@ -50,6 +44,18 @@ let testTerminal: ITestTerminal = {
|
||||
}
|
||||
};
|
||||
|
||||
class DcsTest implements IDcsHandler {
|
||||
hook(collect: string, params: number[], flag: number): void {
|
||||
testTerminal.actionDCSHook(collect, params, String.fromCharCode(flag));
|
||||
}
|
||||
put(data: string, start: number, end: number): void {
|
||||
testTerminal.actionDCSPrint(data, start, end);
|
||||
}
|
||||
unhook(): void {
|
||||
testTerminal.actionDCSUnhook();
|
||||
}
|
||||
}
|
||||
|
||||
let states: number[] = [
|
||||
ParserState.GROUND,
|
||||
ParserState.ESCAPE,
|
||||
@@ -68,54 +74,46 @@ let states: number[] = [
|
||||
];
|
||||
let state: any;
|
||||
|
||||
let parser = new EscapeSequenceParser(testTerminal);
|
||||
parser.registerPrintHandler(testTerminal.print.bind(testTerminal));
|
||||
let parser = new EscapeSequenceParser();
|
||||
parser.setPrintHandler(testTerminal.print.bind(testTerminal));
|
||||
parser.setCsiHandlerFallback((...params: any[]) => {
|
||||
testTerminal.actionCSI(params[0], params[1], String.fromCharCode(params[2]));
|
||||
});
|
||||
parser.setEscHandlerFallback((...params: any[]) => {
|
||||
testTerminal.actionESC(params[0], String.fromCharCode(params[1]));
|
||||
});
|
||||
parser.setExecuteHandlerFallback((...params: any[]) => {
|
||||
testTerminal.actionExecute(String.fromCharCode(params[0]));
|
||||
});
|
||||
parser.setOscHandlerFallback((...params: any[]) => {
|
||||
if (params[0] === -1) testTerminal.actionOSC(params[1]); // handle error condition silently
|
||||
else testTerminal.actionOSC(params[0] + ';' + params[1]);
|
||||
});
|
||||
parser.setDcsHandlerFallback(new DcsTest);
|
||||
// FIXME: to be removed
|
||||
parser.setPrefixHandler(()=>{});
|
||||
|
||||
|
||||
describe('EscapeSequenceParser', function(): void {
|
||||
|
||||
describe('Parser init and methods', function(): void {
|
||||
it('parser init', function (): void {
|
||||
let p = new EscapeSequenceParser({});
|
||||
chai.expect(p.term).a('object');
|
||||
chai.expect(p.term.actionPrint).a('function');
|
||||
chai.expect(p.term.actionOSC).a('function');
|
||||
chai.expect(p.term.actionExecute).a('function');
|
||||
chai.expect(p.term.actionCSI).a('function');
|
||||
chai.expect(p.term.actionESC).a('function');
|
||||
chai.expect(p.term.actionDCSHook).a('function');
|
||||
chai.expect(p.term.actionDCSPrint).a('function');
|
||||
chai.expect(p.term.actionDCSUnhook).a('function');
|
||||
p.parse('\x1b[31mHello World!');
|
||||
});
|
||||
it('terminal callbacks', function (): void {
|
||||
chai.expect(parser.term).equal(testTerminal);
|
||||
chai.expect(parser.term.actionPrint).equal(testTerminal.print);
|
||||
chai.expect(parser.term.actionOSC).equal(testTerminal.actionOSC);
|
||||
chai.expect(parser.term.actionExecute).equal(testTerminal.actionExecute);
|
||||
chai.expect(parser.term.actionCSI).equal(testTerminal.actionCSI);
|
||||
chai.expect(parser.term.actionESC).equal(testTerminal.actionESC);
|
||||
chai.expect(parser.term.actionDCSHook).equal(testTerminal.actionDCSHook);
|
||||
chai.expect(parser.term.actionDCSPrint).equal(testTerminal.actionDCSPrint);
|
||||
chai.expect(parser.term.actionDCSUnhook).equal(testTerminal.actionDCSUnhook);
|
||||
});
|
||||
it('inital states', function (): void {
|
||||
chai.expect(parser.initialState).equal(0);
|
||||
chai.expect(parser.currentState).equal(0);
|
||||
chai.expect(parser.initialState).equal(ParserState.GROUND);
|
||||
chai.expect(parser.currentState).equal(ParserState.GROUND);
|
||||
chai.expect(parser.osc).equal('');
|
||||
chai.expect(parser.params).eql([0]);
|
||||
chai.expect(parser.collected).equal('');
|
||||
chai.expect(parser.collect).equal('');
|
||||
});
|
||||
it('reset states', function (): void {
|
||||
parser.currentState = 124;
|
||||
parser.osc = '#';
|
||||
parser.params = [123];
|
||||
parser.collected = '#';
|
||||
parser.collect = '#';
|
||||
|
||||
parser.reset();
|
||||
chai.expect(parser.currentState).equal(ParserState.GROUND);
|
||||
chai.expect(parser.osc).equal('');
|
||||
chai.expect(parser.params).eql([0]);
|
||||
chai.expect(parser.collected).equal('');
|
||||
chai.expect(parser.collect).equal('');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -182,12 +180,12 @@ describe('EscapeSequenceParser', function(): void {
|
||||
parser.currentState = state;
|
||||
parser.osc = '#';
|
||||
parser.params = [23];
|
||||
parser.collected = '#';
|
||||
parser.collect = '#';
|
||||
parser.parse('\x1b');
|
||||
chai.expect(parser.currentState).equal(ParserState.ESCAPE);
|
||||
chai.expect(parser.osc).equal('');
|
||||
chai.expect(parser.params).eql([0]);
|
||||
chai.expect(parser.collected).equal('');
|
||||
chai.expect(parser.collect).equal('');
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
@@ -239,7 +237,7 @@ describe('EscapeSequenceParser', function(): void {
|
||||
parser.currentState = ParserState.ESCAPE;
|
||||
parser.parse(collect[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.ESCAPE_INTERMEDIATE);
|
||||
chai.expect(parser.collected).equal(collect[i]);
|
||||
chai.expect(parser.collect).equal(collect[i]);
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
@@ -275,7 +273,7 @@ describe('EscapeSequenceParser', function(): void {
|
||||
parser.currentState = ParserState.ESCAPE_INTERMEDIATE;
|
||||
parser.parse(collect[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.ESCAPE_INTERMEDIATE);
|
||||
chai.expect(parser.collected).equal(collect[i]);
|
||||
chai.expect(parser.collect).equal(collect[i]);
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
@@ -298,24 +296,24 @@ describe('EscapeSequenceParser', function(): void {
|
||||
parser.currentState = ParserState.ESCAPE;
|
||||
parser.osc = '#';
|
||||
parser.params = [123];
|
||||
parser.collected = '#';
|
||||
parser.collect = '#';
|
||||
parser.parse('[');
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_ENTRY);
|
||||
chai.expect(parser.osc).equal('');
|
||||
chai.expect(parser.params).eql([0]);
|
||||
chai.expect(parser.collected).equal('');
|
||||
chai.expect(parser.collect).equal('');
|
||||
parser.reset();
|
||||
// C1
|
||||
for (state in states) {
|
||||
parser.currentState = state;
|
||||
parser.osc = '#';
|
||||
parser.params = [123];
|
||||
parser.collected = '#';
|
||||
parser.collect = '#';
|
||||
parser.parse('\x9b');
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_ENTRY);
|
||||
chai.expect(parser.osc).equal('');
|
||||
chai.expect(parser.params).eql([0]);
|
||||
chai.expect(parser.collected).equal('');
|
||||
chai.expect(parser.collect).equal('');
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
@@ -376,7 +374,7 @@ describe('EscapeSequenceParser', function(): void {
|
||||
parser.currentState = ParserState.CSI_ENTRY;
|
||||
parser.parse(collect[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_PARAM);
|
||||
chai.expect(parser.collected).equal(collect[i]);
|
||||
chai.expect(parser.collect).equal(collect[i]);
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
@@ -441,7 +439,7 @@ describe('EscapeSequenceParser', function(): void {
|
||||
parser.currentState = ParserState.CSI_ENTRY;
|
||||
parser.parse(collect[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_INTERMEDIATE);
|
||||
chai.expect(parser.collected).equal(collect[i]);
|
||||
chai.expect(parser.collect).equal(collect[i]);
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
@@ -452,7 +450,7 @@ describe('EscapeSequenceParser', function(): void {
|
||||
parser.currentState = ParserState.CSI_PARAM;
|
||||
parser.parse(collect[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_INTERMEDIATE);
|
||||
chai.expect(parser.collected).equal(collect[i]);
|
||||
chai.expect(parser.collect).equal(collect[i]);
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
@@ -478,7 +476,7 @@ describe('EscapeSequenceParser', function(): void {
|
||||
parser.currentState = ParserState.CSI_INTERMEDIATE;
|
||||
parser.parse(collect[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_INTERMEDIATE);
|
||||
chai.expect(parser.collected).equal(collect[i]);
|
||||
chai.expect(parser.collect).equal(collect[i]);
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
@@ -695,7 +693,7 @@ describe('EscapeSequenceParser', function(): void {
|
||||
parser.currentState = ParserState.DCS_ENTRY;
|
||||
parser.parse(collect[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_PARAM);
|
||||
chai.expect(parser.collected).equal(collect[i]);
|
||||
chai.expect(parser.collect).equal(collect[i]);
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
@@ -777,7 +775,7 @@ describe('EscapeSequenceParser', function(): void {
|
||||
parser.currentState = ParserState.DCS_ENTRY;
|
||||
parser.parse(collect[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_INTERMEDIATE);
|
||||
chai.expect(parser.collected).equal(collect[i]);
|
||||
chai.expect(parser.collect).equal(collect[i]);
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
@@ -788,7 +786,7 @@ describe('EscapeSequenceParser', function(): void {
|
||||
parser.currentState = ParserState.DCS_PARAM;
|
||||
parser.parse(collect[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_INTERMEDIATE);
|
||||
chai.expect(parser.collected).equal(collect[i]);
|
||||
chai.expect(parser.collect).equal(collect[i]);
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
@@ -812,7 +810,7 @@ describe('EscapeSequenceParser', function(): void {
|
||||
parser.currentState = ParserState.DCS_INTERMEDIATE;
|
||||
parser.parse(collect[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_INTERMEDIATE);
|
||||
chai.expect(parser.collected).equal(collect[i]);
|
||||
chai.expect(parser.collect).equal(collect[i]);
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
@@ -823,7 +821,7 @@ describe('EscapeSequenceParser', function(): void {
|
||||
parser.currentState = ParserState.DCS_INTERMEDIATE;
|
||||
parser.parse('\x20' + chars[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_IGNORE);
|
||||
chai.expect(parser.collected).equal('\x20');
|
||||
chai.expect(parser.collect).equal('\x20');
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
@@ -990,9 +988,9 @@ describe('EscapeSequenceParser', function(): void {
|
||||
parser.reset();
|
||||
testTerminal.clear();
|
||||
parser.currentState = ParserState.DCS_PASSTHROUGH;
|
||||
parser.parse('€öäü');
|
||||
parser.parse('\x901;2;3+$a€öäü');
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_PASSTHROUGH);
|
||||
testTerminal.compare([['dcs put', '€öäü']]);
|
||||
testTerminal.compare([['dcs hook', '+$', [1, 2, 3], 'a'], ['dcs put', '€öäü']]);
|
||||
parser.reset();
|
||||
testTerminal.clear();
|
||||
});
|
||||
@@ -1007,64 +1005,5 @@ describe('EscapeSequenceParser', function(): void {
|
||||
testTerminal.clear();
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
let errorTerminal1 = function(): void {};
|
||||
errorTerminal1.prototype = testTerminal;
|
||||
let errTerminal1 = new errorTerminal1();
|
||||
errTerminal1.actionError = function(e: any): void {
|
||||
this.calls.push(['error', e]);
|
||||
};
|
||||
let errParser1 = new EscapeSequenceParser(errTerminal1);
|
||||
errParser1.registerPrintHandler(testTerminal.actionPrint.bind(errorTerminal1));
|
||||
|
||||
let errorTerminal2 = function(): void {};
|
||||
errorTerminal2.prototype = testTerminal;
|
||||
let errTerminal2 = new errorTerminal2();
|
||||
errTerminal2.actionError = function(e: any): any {
|
||||
this.calls.push(['error', e]);
|
||||
return true; // --> abort parsing
|
||||
};
|
||||
let errParser2 = new EscapeSequenceParser(errTerminal2);
|
||||
errParser2.registerPrintHandler(testTerminal.actionPrint.bind(errorTerminal2));
|
||||
|
||||
describe('error tests', function(): void {
|
||||
it('CSI_PARAM unicode error - actionError output w/o abort', function (): void {
|
||||
errParser1.parse('\x1b[<31;5€normal print');
|
||||
errTerminal1.compare([
|
||||
['error', {
|
||||
abort: false,
|
||||
position: 7,
|
||||
code: '€'.charCodeAt(0),
|
||||
currentState: 4,
|
||||
print: -1,
|
||||
dcs: -1,
|
||||
osc: '',
|
||||
collected: '<',
|
||||
params: [31, 5]}],
|
||||
['print', 'normal print']
|
||||
]);
|
||||
parser.reset();
|
||||
testTerminal.clear();
|
||||
});
|
||||
it('CSI_PARAM unicode error - actionError output with abort', function (): void {
|
||||
errParser2.parse('\x1b[<31;5€no print');
|
||||
errTerminal2.compare([
|
||||
['error', {
|
||||
abort: false,
|
||||
position: 7,
|
||||
code: '€'.charCodeAt(0),
|
||||
currentState: 4,
|
||||
print: -1,
|
||||
dcs: -1,
|
||||
osc: '',
|
||||
collected: '<',
|
||||
params: [31, 5]}]
|
||||
]);
|
||||
parser.reset();
|
||||
testTerminal.clear();
|
||||
});
|
||||
});
|
||||
*/
|
||||
|
||||
// TODO: error conditions, higher order: set/clear of callbacks, custom sequences
|
||||
});
|
||||
+30
-24
@@ -295,9 +295,9 @@ export class EscapeSequenceParser implements IEscapeSequenceParser {
|
||||
readonly transitions: TransitionTable;
|
||||
|
||||
// buffers over several parse calls
|
||||
protected _osc: string;
|
||||
protected _params: number[];
|
||||
protected _collect: string;
|
||||
public osc: string;
|
||||
public params: number[];
|
||||
public collect: string;
|
||||
|
||||
// callback slots
|
||||
protected _printHandler: IPrintHandler;
|
||||
@@ -325,9 +325,9 @@ export class EscapeSequenceParser implements IEscapeSequenceParser {
|
||||
this.initialState = ParserState.GROUND;
|
||||
this.currentState = this.initialState;
|
||||
this.transitions = transitions;
|
||||
this._osc = '';
|
||||
this._params = [0];
|
||||
this._collect = '';
|
||||
this.osc = '';
|
||||
this.params = [0];
|
||||
this.collect = '';
|
||||
|
||||
// set default fallback handlers
|
||||
this._printHandlerFb = (data, start, end): void => {};
|
||||
@@ -362,7 +362,7 @@ export class EscapeSequenceParser implements IEscapeSequenceParser {
|
||||
if (this._executeHandlers[flag.charCodeAt(0)]) delete this._executeHandlers[flag.charCodeAt(0)];
|
||||
}
|
||||
setExecuteHandlerFallback(callback: (...params: any[]) => void): void {
|
||||
this._escHandlerFb = callback;
|
||||
this._executeHandlerFb = callback;
|
||||
}
|
||||
|
||||
setCsiHandler(flag: string, callback: ICsiHandler): void {
|
||||
@@ -419,9 +419,9 @@ export class EscapeSequenceParser implements IEscapeSequenceParser {
|
||||
|
||||
reset(): void {
|
||||
this.currentState = this.initialState;
|
||||
this._osc = '';
|
||||
this._params = [0];
|
||||
this._collect = '';
|
||||
this.osc = '';
|
||||
this.params = [0];
|
||||
this.collect = '';
|
||||
}
|
||||
|
||||
parse(data: string): void {
|
||||
@@ -433,9 +433,9 @@ export class EscapeSequenceParser implements IEscapeSequenceParser {
|
||||
// local buffers
|
||||
let print = -1;
|
||||
let dcs = -1;
|
||||
let osc = this._osc;
|
||||
let collect = this._collect;
|
||||
let params = this._params;
|
||||
let osc = this.osc;
|
||||
let collect = this.collect;
|
||||
let params = this.params;
|
||||
let table: Uint8Array | number[] = this.transitions.table;
|
||||
let dcsHandler: IDcsHandler | null = this._activeDcsHandler;
|
||||
let ident: string = '';
|
||||
@@ -568,9 +568,11 @@ export class EscapeSequenceParser implements IEscapeSequenceParser {
|
||||
dcs = (~dcs) ? dcs : i;
|
||||
break;
|
||||
case ParserAction.DCS_UNHOOK:
|
||||
if (~dcs) dcsHandler.put(data, dcs, i);
|
||||
dcsHandler.unhook();
|
||||
dcsHandler = null;
|
||||
if (dcsHandler) {
|
||||
if (~dcs) dcsHandler.put(data, dcs, i);
|
||||
dcsHandler.unhook();
|
||||
dcsHandler = null;
|
||||
}
|
||||
if (code === 0x1b) transition |= ParserState.ESCAPE;
|
||||
osc = '';
|
||||
params = [0];
|
||||
@@ -590,10 +592,14 @@ export class EscapeSequenceParser implements IEscapeSequenceParser {
|
||||
case ParserAction.OSC_END:
|
||||
if (osc && code !== 0x18 && code !== 0x1a) {
|
||||
let idx = osc.indexOf(';');
|
||||
let identifier = parseInt(osc.substring(0, idx));
|
||||
let content = osc.substring(idx + 1);
|
||||
if (this._oscHandlers[identifier]) this._oscHandlers[identifier](content);
|
||||
else this._oscHandlerFb(identifier, content);
|
||||
if (idx === -1) {
|
||||
this._oscHandlerFb(-1, osc); // this is an error
|
||||
} else {
|
||||
let identifier = parseInt(osc.substring(0, idx));
|
||||
let content = osc.substring(idx + 1);
|
||||
if (this._oscHandlers[identifier]) this._oscHandlers[identifier](content);
|
||||
else this._oscHandlerFb(identifier, content);
|
||||
}
|
||||
}
|
||||
if (code === 0x1b) transition |= ParserState.ESCAPE;
|
||||
osc = '';
|
||||
@@ -608,14 +614,14 @@ export class EscapeSequenceParser implements IEscapeSequenceParser {
|
||||
// push leftover pushable buffers to terminal
|
||||
if (currentState === ParserState.GROUND && ~print) {
|
||||
this._printHandler(data, print, data.length);
|
||||
} else if (currentState === ParserState.DCS_PASSTHROUGH && ~dcs) {
|
||||
} else if (currentState === ParserState.DCS_PASSTHROUGH && ~dcs && dcsHandler) {
|
||||
dcsHandler.put(data, dcs, data.length);
|
||||
}
|
||||
|
||||
// save non pushable buffers
|
||||
this._osc = osc;
|
||||
this._collect = collect;
|
||||
this._params = params;
|
||||
this.osc = osc;
|
||||
this.collect = collect;
|
||||
this.params = params;
|
||||
|
||||
// save active dcs handler reference
|
||||
this._activeDcsHandler = dcsHandler;
|
||||
|
||||
Reference in New Issue
Block a user