Skip to content

Commit

Permalink
reorganize tests; add tests; minor fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
guillermooo committed Nov 28, 2015
1 parent b6ca2dc commit 3f2c6b5
Show file tree
Hide file tree
Showing 15 changed files with 213 additions and 80 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ notifications:
language: node_js

node_js:
- "0.12"
- "4.1.1"

install:
- npm install
Expand Down
4 changes: 2 additions & 2 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ var paths = {
tests_js: [
// test with dependencies on 'vscode' do not run
"out/test/extension.test.js",
"out/test/lexer.test.js",
"out/test/scanner.test.js"
"out/test/cmd_line/lexer.test.js",
"out/test/cmd_line/scanner.test.js",
]
};

Expand Down
4 changes: 2 additions & 2 deletions src/cmd_line/commands/quit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ export class QuitCommand extends node.CommandBase {
}

execute() : void {
this.quit(this.activeTextEditor);
this.quit();
}

private quit(textEditor : vscode.TextEditor) {
private quit() {
// See https://github.com/Microsoft/vscode/issues/723
if ((this.activeTextEditor.document.isDirty || this.activeTextEditor.document.isUntitled)
&& !this.arguments.bang) {
Expand Down
1 change: 0 additions & 1 deletion src/cmd_line/lexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,6 @@ module LexerFunctions {
} else {
state.backup();
tokens.push(emitToken(TokenType.CommandName, state));
state.skipWhiteSpace();
while (!state.isAtEof) {
state.next();
}
Expand Down
2 changes: 1 addition & 1 deletion src/cmd_line/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class ParserState {
this.lex(input);
}

lex(input : string) {
private lex(input : string) {
this.tokens = lexer.lex(input);
}

Expand Down
9 changes: 7 additions & 2 deletions src/cmd_line/scanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,16 @@ export class Scanner {
if (this.isAtEof) {
return;
}
while (true) {
while (!this.isAtEof) {
var c = this.next();
if (c === " " || c === "\t") {
continue;
}
break;
}
this.backup();
if (c !== Scanner.EOF && c !== ' ' && c !== '\t') {
this.backup();
}
this.ignore();
}

Expand All @@ -99,6 +101,9 @@ export class Scanner {
expectOneOf(...values : string[]) : void {
let match = values.filter(s => this.input.substr(this.pos).startsWith(s));
if (match.length !== 1) {
if (match.length > 1) {
throw new Error("too many maches");
}
throw new Error("Unexpected character.");
}
this.pos += match[0].length;
Expand Down
6 changes: 4 additions & 2 deletions src/cmd_line/subparsers/quit.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as node from "../commands/quit";
import {Scanner} from '../scanner';
import {VimError, ErrorCode} from '../../error';

export function parseQuitCommandArgs(args : string) : node.QuitCommand {
if (!args) {
Expand All @@ -10,12 +11,13 @@ export function parseQuitCommandArgs(args : string) : node.QuitCommand {
const c = scanner.next();
if (c === '!') {
scannedArgs.bang = true;
scanner.ignore();
} else if (c !== ' ') {
throw new Error('bad command');
throw VimError.fromCode(ErrorCode.E488);
}
scanner.skipWhiteSpace();
if (!scanner.isAtEof) {
throw new Error('bad command');
throw VimError.fromCode(ErrorCode.E488);
}
return new node.QuitCommand(scannedArgs);
}
6 changes: 4 additions & 2 deletions src/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ interface VimErrors {

export enum ErrorCode {
E37 = 37,
E32 = 32
E32 = 32,
E488 = 488
}

const errors : VimErrors = {
32: "No file name",
37: "No write since last change (add ! to override)"
37: "No write since last change (add ! to override)",
488: "Trailing characters"
};


Expand Down
14 changes: 10 additions & 4 deletions test/lexer.test.ts → test/cmd_line/lexer.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// The module 'assert' provides assertion methods from node
import * as assert from 'assert';
import * as lexer from '../src/cmd_line/lexer';
import {Token, TokenType} from '../src/cmd_line/token';
import * as lexer from '../../src/cmd_line/lexer';
import {Token, TokenType} from '../../src/cmd_line/token';

suite("Cmd line tests - lexing", () => {
suite("command-line lexer", () => {

test("can lex empty string", () => {
var tokens = lexer.lex("");
Expand Down Expand Up @@ -78,9 +78,15 @@ suite("Cmd line tests - lexing", () => {
test("can lex command args", () => {
var tokens = lexer.lex("w something");
assert.equal(tokens[0].content, new Token(TokenType.CommandName, "w").content);
assert.equal(tokens[1].content, new Token(TokenType.CommandArgs, "something").content);
assert.equal(tokens[1].content, new Token(TokenType.CommandArgs, " something").content);
});

test("can lex command args with leading whitespace", () => {
var tokens = lexer.lex("q something");
assert.equal(tokens[0].content, new Token(TokenType.CommandName, "q").content);
assert.equal(tokens[1].content, new Token(TokenType.CommandArgs, " something").content);
});

test("can lex long command name and args", () => {
var tokens = lexer.lex("write12 something here");
assert.equal(tokens[0].content, new Token(TokenType.CommandName, "write").content);
Expand Down
8 changes: 4 additions & 4 deletions test/parser.test.ts → test/cmd_line/parser.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as assert from 'assert';
import * as parser from '../src/cmd_line/parser';
import * as node from '../src/cmd_line/node';
import * as token from '../src/cmd_line/token';
import * as parser from '../../src/cmd_line/parser';
import * as node from '../../src/cmd_line/node';
import * as token from '../../src/cmd_line/token';

suite("Cmd line tests - parser", () => {
suite("command-line parser", () => {

test("can parse empty string", () => {
var cmd = parser.parse("");
Expand Down
96 changes: 96 additions & 0 deletions test/cmd_line/scanner.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import * as assert from 'assert';
import {Scanner} from '../../src/cmd_line/scanner';

suite("command line scanner", () => {

test("ctor", () => {
var state = new Scanner("dog");
assert.equal(state.input, "dog");
});

test("can detect EOF with empty input", () => {
var state = new Scanner("");
assert.ok(state.isAtEof);
});

test("next() returns EOF at EOF", () => {
var state = new Scanner("");
assert.equal(state.next(), Scanner.EOF);
assert.equal(state.next(), Scanner.EOF);
assert.equal(state.next(), Scanner.EOF);
});

test("can scan", () => {
var state = new Scanner("dog");
assert.equal(state.next(), "d");
assert.equal(state.next(), "o");
assert.equal(state.next(), "g");
assert.equal(state.next(), Scanner.EOF);
});

test("can emit", () => {
var state = new Scanner("dog cat");
state.next();
state.next();
state.next();
assert.equal(state.emit(), "dog");
state.next();
state.next();
state.next();
state.next();
assert.equal(state.emit(), " cat");
});

test("can ignore", () => {
var state = new Scanner("dog cat");
state.next();
state.next();
state.next();
state.next();
state.ignore();
state.next();
state.next();
state.next();
assert.equal(state.emit(), "cat");
});

test("can skip whitespace", () => {
var state = new Scanner("dog cat");
state.next();
state.next();
state.next();
state.ignore();
state.skipWhiteSpace();
assert.equal(state.next(), "c");
});

test("can skip whitespace with one char before EOF", () => {
var state = new Scanner("dog c");
state.next();
state.next();
state.next();
state.ignore();
state.skipWhiteSpace();
assert.equal(state.next(), "c");
});

test("can skip whitespace at EOF", () => {
var state = new Scanner("dog ");
state.next();
state.next();
state.next();
state.ignore();
state.skipWhiteSpace();
assert.equal(state.next(), Scanner.EOF);
});

test("can expect one of a set", () => {
var state = new Scanner("dog cat");
state.expectOneOf("dog", "mule", "monkey");
});

test("can expect only one of a set", () => {
var state = new Scanner("dog cat");
assert.throws(() => state.expectOneOf("mule", "monkey"));
});
});
44 changes: 44 additions & 0 deletions test/cmd_line/subparser.quit.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// The module 'assert' provides assertion methods from node
import * as assert from 'assert';

import {commandParsers} from '../../src/cmd_line/subparser';

suite(":quit args parser", () => {

test("has all aliases", () => {
assert.equal(commandParsers.quit.name, commandParsers.q.name);
});

test("can parse empty args", () => {
var args = commandParsers.quit("");
assert.equal(args.arguments.bang, undefined);
assert.equal(args.arguments.range, undefined);
});

test("ignores trailing white space", () => {
var args = commandParsers.quit(" ");
assert.equal(args.arguments.bang, undefined);
assert.equal(args.arguments.range, undefined);
});

test("can parse !", () => {
var args = commandParsers.quit("!");
assert.ok(args.arguments.bang);
assert.equal(args.arguments.range, undefined);
});

test("throws if space before !", () => {
assert.throws(() => commandParsers.quit(" !"));
});

test("ignores space after !", () => {

var args = commandParsers.quit("! ");
assert.equal(args.arguments.bang, true);
assert.equal(args.arguments.range, undefined);
});

test("throws if bad input", () => {
assert.throws(() => commandParsers.quit("x"));
});
});
6 changes: 3 additions & 3 deletions test/subparser.test.ts → test/cmd_line/subparser.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// The module 'assert' provides assertion methods from node
import * as assert from 'assert';

import {commandParsers} from '../src/cmd_line/subparser';
import {commandParsers} from '../../src/cmd_line/subparser';

suite("subparsers - :write args", () => {
suite(":write args parser", () => {

test("parsers for :write are set up correctly", () => {
test("has all aliases", () => {
assert.equal(commandParsers.write.name, commandParsers.w.name);
});

Expand Down
35 changes: 35 additions & 0 deletions test/error.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// The module 'assert' provides assertion methods from node
import * as assert from 'assert';
import {VimError, ErrorCode} from '../src/error';

suite("ErrorCode", () => {

test("contains known errors", () => {
assert.equal(ErrorCode.E32, 32);
assert.equal(ErrorCode.E37, 37);
assert.equal(ErrorCode.E488, 488);
});
});

suite("vimError", () => {

test("ctor", () => {
const e = new VimError(100, "whoof!");
assert.equal(e.code, 100);
assert.equal(e.message, "whoof!");
});

test("can instantiate known errors", () => {
var e = VimError.fromCode(ErrorCode.E32);
assert.equal(e.code, 32);
assert.equal(e.message, "No file name");

e = VimError.fromCode(ErrorCode.E37);
assert.equal(e.code, 37);
assert.equal(e.message, "No write since last change (add ! to override)");

e = VimError.fromCode(ErrorCode.E488);
assert.equal(e.code, 488);
assert.equal(e.message, "Trailing characters");
});
});
Loading

0 comments on commit 3f2c6b5

Please sign in to comment.