fix test cases

This commit is contained in:
Jörg Breitbart
2018-04-30 15:38:17 +02:00
parent b158176862
commit 645cd2eb2c
2 changed files with 94 additions and 149 deletions
@@ -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
View File
@@ -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;