1、合并上游最新单元测试代码

This commit is contained in:
xuhong 2024-07-03 18:00:11 +08:00
parent 7696f66b2a
commit 4450b8d832
13 changed files with 3310 additions and 741 deletions

6
.mocharc.yml Normal file
View File

@ -0,0 +1,6 @@
color: true
recursive: true
require: "ts-node/register"
spec:
- "**/*.test.ts"
ui: "tdd"

5
.nycrc.yml Normal file
View File

@ -0,0 +1,5 @@
extends: "@istanbuljs/nyc-config-typescript"
all: true
reporter:
- text
- lcovonly

2900
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1119,6 +1119,8 @@
},
"scripts": {
"vscode:prepublish": "tsc -p ./",
"test": "mocha",
"coverage": "nyc npm test",
"compile": "tsc -watch -p ./"
},
"dependencies": {
@ -1130,12 +1132,14 @@
"stream-json": "^1.7.3"
},
"devDependencies": {
"@istanbuljs/nyc-config-typescript": "^1.0.2",
"@types/mocha": "^5.2.6",
"@types/node": "^11.11.3",
"@types/vscode": "^1.54.0",
"mocha": "^9.1.3",
"nyc": "^15.1.0",
"tslint": "^5.20.1",
"typescript": "^3.9.3",
"vscode-test": "1.3.0"
"ts-node": "^10.8.0"
}
}

55
src/path_kind.ts Executable file
View File

@ -0,0 +1,55 @@
import * as Path from "path";
export abstract class PathKind {
protected abstract readonly path: typeof Path.posix | typeof Path.win32;
public abstract readonly caseSensitive: boolean;
// The path.posix.normalize routine will not convert Win32 path separators
// to POSIX separators, so we explictily convert any Win32 path separators
// to POSIX style separators. The path.win32.normalize routine will accept
// either Win32 or POSIX style separators and will normalize them to the
// Win32 style. Thus, if we convert all path separators to POSIX style and
// then normalize, this will work for both systems.
public normalize(p: string): string {
return this.path.normalize(p.replace(/\\/g, "/"));
}
public normalizeDir(p: string): string {
p = this.normalize(p);
if (! p.endsWith(this.path.sep))
p = this.path.join(p, this.path.sep);
return p;
}
public join(...paths: string[]): string {
return this.normalize(this.path.join(...paths));
}
public isAbsolute(p: string): boolean {
return this.path.isAbsolute(this.normalize(p));
}
}
export class PathWin32 extends PathKind {
protected readonly path: typeof Path.posix | typeof Path.win32 = Path.win32;
public readonly caseSensitive: boolean = false;
private static instance: PathWin32;
private constructor() { super(); }
public static getInstance(): PathWin32 {
if (! this.instance)
this.instance = new PathWin32();
return this.instance;
}
}
export class PathPosix extends PathKind {
protected readonly path: typeof Path.posix | typeof Path.win32 = Path.posix;
public readonly caseSensitive: boolean = true;
private static instance: PathPosix;
private constructor() { super(); }
public static getInstance(): PathPosix {
if (! this.instance)
this.instance = new PathPosix();
return this.instance;
}
}

107
src/source_file_map.ts Executable file
View File

@ -0,0 +1,107 @@
import { PathKind, PathWin32, PathPosix } from "./path_kind";
interface Mapping {
"remote": string;
"local": string;
}
export class SourceFileMap {
private sortedMappings: { [key in keyof Mapping]: Mapping[] } = {remote: [], local: []};
private nativePath: PathKind;
private remoteCwd: string|undefined;
constructor (map: { [index: string]: string }, remoteCwd?: string) {
const mappings: Mapping[] = [];
this.remoteCwd = remoteCwd;
this.nativePath = this.getNativePath();
for (let [remotePrefix, localPrefix] of Object.entries(map)) {
// Normalize local path, adding trailing separator if missing.
localPrefix = this.nativePath.normalizeDir(localPrefix);
// Try to detect remote path.
const debuggerPath: PathKind = this.toPathKind(remotePrefix);
// Normalize remote path, adding trailing separator if missing.
remotePrefix = debuggerPath.normalizeDir(remotePrefix);
mappings.push({remote: remotePrefix, local: localPrefix});
}
// Sort with longest paths first in case some paths are subsets, so that
// we match the most appropriate (e.g., with path prefixes of '/home'
// and '/home/foo', and a complete path of '/home/foo/bar.c', we should
// match the '/home/foo' path prefix instead of '/home'.
this.sortedMappings.local = [...mappings].sort((a: Mapping, b: Mapping) => b.local.length - a.local.length);
this.sortedMappings.remote = [...mappings].sort((a: Mapping, b: Mapping) => b.remote.length - a.remote.length);
}
// The native path selection is isolated here to allow for easy unit testing
// allowing non-native path types to be tested by overriding this method in
// a subclass in the test harness.
protected getNativePath(): PathKind {
if (process.platform == "win32")
return PathWin32.getInstance();
else
return PathPosix.getInstance();
}
private toPathKind(unknownPath: string): PathKind {
const pathPosix: PathKind = PathPosix.getInstance();
const pathWin32: PathKind = PathWin32.getInstance();
if (pathPosix.isAbsolute(unknownPath) ||
(this.remoteCwd && pathPosix.isAbsolute(this.remoteCwd)))
{
return pathPosix;
} else {
return pathWin32;
}
}
private pathMatch(key: keyof Mapping, caseSensitive: boolean, path: string): Mapping | undefined {
for (const mapping of this.sortedMappings[key]) {
let matched: boolean;
if (caseSensitive)
matched = path.startsWith(mapping[key]);
else
matched = path.toLowerCase().startsWith(mapping[key].toLowerCase());
if (matched)
return mapping;
}
return undefined;
}
public toLocalPath(remotePath: string): string {
// Try to detect remote path.
const debuggerPath: PathKind = this.toPathKind(remotePath);
const normalizedRemotePath: string = debuggerPath.normalize(remotePath);
const mapping: Mapping | undefined =
this.pathMatch("remote", debuggerPath.caseSensitive, normalizedRemotePath);
if (mapping) {
const pathSuffix = normalizedRemotePath.substring(mapping.remote.length);
return this.nativePath.join(mapping.local, pathSuffix);
}
// No mapping found, so return unmapped path.
return remotePath;
}
public toRemotePath (localPath: string): string {
const normalizedLocalPath = this.nativePath.normalize(localPath);
const mapping: Mapping | undefined =
this.pathMatch("local", this.nativePath.caseSensitive, normalizedLocalPath);
if (mapping) {
const pathSuffix = normalizedLocalPath.substring(mapping.local.length);
// Try to detect remote path.
const debuggerPath = this.toPathKind(mapping.remote);
return debuggerPath.join(mapping.remote, pathSuffix);
}
// No mapping found, so return unmapped path.
return localPath;
}
}

View File

@ -1,24 +0,0 @@
import * as path from 'path';
import { runTests } from 'vscode-test';
async function main() {
try {
// The folder containing the Extension Manifest package.json
// Passed to `--extensionDevelopmentPath`
const extensionDevelopmentPath = path.resolve(__dirname, '../../');
// The path to the extension test runner script
// Passed to --extensionTestsPath
const extensionTestsPath = path.resolve(__dirname, './suite/index');
// Download VS Code, unzip it and run the integration test
await runTests({ extensionDevelopmentPath, extensionTestsPath });
} catch (err) {
console.error(err);
console.error('Failed to run tests');
process.exit(1);
}
}
main();

View File

@ -1,37 +0,0 @@
import * as path from 'path';
import * as Mocha from 'mocha';
import * as glob from 'glob';
export function run(): Promise<void> {
// Create the mocha test
const mocha = new Mocha({
ui: 'tdd',
useColors: true
});
const testsRoot = path.resolve(__dirname, '..');
return new Promise((c, e) => {
glob('**/**.test.js', { cwd: testsRoot }, (err, files) => {
if (err) {
return e(err);
}
// Add files to the test suite
files.forEach(f => mocha.addFile(path.resolve(testsRoot, f)));
try {
// Run the mocha test
mocha.run(failures => {
if (failures > 0) {
e(new Error(`${failures} tests failed.`));
} else {
c();
}
});
} catch (err) {
e(err);
}
});
});
}

View File

@ -1,207 +0,0 @@
import * as assert from 'assert';
import { parseMI, MINode } from '../../backend/mi_parse';
suite("MI Parse", () => {
test("Very simple out of band record", () => {
const parsed = parseMI(`*stopped`);
assert.ok(parsed);
assert.strictEqual(parsed.token, undefined);
assert.strictEqual(parsed.outOfBandRecord.length, 1);
assert.strictEqual(parsed.outOfBandRecord[0].isStream, false);
assert.strictEqual(parsed.outOfBandRecord[0].asyncClass, "stopped");
assert.strictEqual(parsed.outOfBandRecord[0].output.length, 0);
assert.strictEqual(parsed.resultRecords, undefined);
});
test("Simple out of band record", () => {
const parsed = parseMI(`4=thread-exited,id="3",group-id="i1"`);
assert.ok(parsed);
assert.equal(parsed.token, 4);
assert.equal(parsed.outOfBandRecord.length, 1);
assert.equal(parsed.outOfBandRecord[0].isStream, false);
assert.equal(parsed.outOfBandRecord[0].asyncClass, "thread-exited");
assert.equal(parsed.outOfBandRecord[0].output.length, 2);
assert.deepEqual(parsed.outOfBandRecord[0].output[0], ["id", "3"]);
assert.deepEqual(parsed.outOfBandRecord[0].output[1], ["group-id", "i1"]);
assert.equal(parsed.resultRecords, undefined);
});
test("Console stream output with new line", () => {
const parsed = parseMI(`~"[Thread 0x7fffe993a700 (LWP 11002) exited]\\n"`);
assert.ok(parsed);
assert.equal(parsed.token, undefined);
assert.equal(parsed.outOfBandRecord.length, 1);
assert.equal(parsed.outOfBandRecord[0].isStream, true);
assert.equal(parsed.outOfBandRecord[0].content, "[Thread 0x7fffe993a700 (LWP 11002) exited]\n");
assert.equal(parsed.resultRecords, undefined);
});
test("Unicode", () => {
let parsed = parseMI(`~"[Depuraci\\303\\263n de hilo usando libthread_db enabled]\\n"`);
assert.ok(parsed);
assert.equal(parsed.token, undefined);
assert.equal(parsed.outOfBandRecord.length, 1);
assert.equal(parsed.outOfBandRecord[0].isStream, true);
assert.equal(parsed.outOfBandRecord[0].content, "[Depuración de hilo usando libthread_db enabled]\n");
assert.equal(parsed.resultRecords, undefined);
parsed = parseMI(`~"4\\t std::cout << \\"\\345\\245\\275\\345\\245\\275\\345\\255\\246\\344\\271\\240\\357\\274\\214\\345\\244\\251\\345\\244\\251\\345\\220\\221\\344\\270\\212\\" << std::endl;\\n"`);
assert.ok(parsed);
assert.equal(parsed.token, undefined);
assert.equal(parsed.outOfBandRecord.length, 1);
assert.equal(parsed.outOfBandRecord[0].isStream, true);
assert.equal(parsed.outOfBandRecord[0].content, `4\t std::cout << "好好学习,天天向上" << std::endl;\n`);
assert.equal(parsed.resultRecords, undefined);
});
test("Empty line", () => {
const parsed = parseMI(``);
assert.ok(parsed);
assert.equal(parsed.token, undefined);
assert.equal(parsed.outOfBandRecord.length, 0);
assert.equal(parsed.resultRecords, undefined);
});
test("'(gdb)' line", () => {
const parsed = parseMI(`(gdb)`);
assert.ok(parsed);
assert.equal(parsed.token, undefined);
assert.equal(parsed.outOfBandRecord.length, 0);
assert.equal(parsed.resultRecords, undefined);
});
test("Simple result record", () => {
const parsed = parseMI(`1^running`);
assert.ok(parsed);
assert.equal(parsed.token, 1);
assert.equal(parsed.outOfBandRecord.length, 0);
assert.notEqual(parsed.resultRecords, undefined);
assert.equal(parsed.resultRecords.resultClass, "running");
assert.equal(parsed.resultRecords.results.length, 0);
});
test("Advanced out of band record (Breakpoint hit)", () => {
const parsed = parseMI(`*stopped,reason="breakpoint-hit",disp="keep",bkptno="1",frame={addr="0x00000000004e807f",func="D main",args=[{name="args",value="..."}],file="source/app.d",fullname="/path/to/source/app.d",line="157"},thread-id="1",stopped-threads="all",core="0"`);
assert.ok(parsed);
assert.equal(parsed.token, undefined);
assert.equal(parsed.outOfBandRecord.length, 1);
assert.equal(parsed.outOfBandRecord[0].isStream, false);
assert.equal(parsed.outOfBandRecord[0].asyncClass, "stopped");
assert.equal(parsed.outOfBandRecord[0].output.length, 7);
assert.deepEqual(parsed.outOfBandRecord[0].output[0], ["reason", "breakpoint-hit"]);
assert.deepEqual(parsed.outOfBandRecord[0].output[1], ["disp", "keep"]);
assert.deepEqual(parsed.outOfBandRecord[0].output[2], ["bkptno", "1"]);
const frame = [
["addr", "0x00000000004e807f"],
["func", "D main"],
["args", [[["name", "args"], ["value", "..."]]]],
["file", "source/app.d"],
["fullname", "/path/to/source/app.d"],
["line", "157"]
];
assert.deepEqual(parsed.outOfBandRecord[0].output[3], ["frame", frame]);
assert.deepEqual(parsed.outOfBandRecord[0].output[4], ["thread-id", "1"]);
assert.deepEqual(parsed.outOfBandRecord[0].output[5], ["stopped-threads", "all"]);
assert.deepEqual(parsed.outOfBandRecord[0].output[6], ["core", "0"]);
assert.equal(parsed.resultRecords, undefined);
});
test("Advanced result record", () => {
const parsed = parseMI(`2^done,asm_insns=[src_and_asm_line={line="134",file="source/app.d",fullname="/path/to/source/app.d",line_asm_insn=[{address="0x00000000004e7da4",func-name="_Dmain",offset="0",inst="push %rbp"},{address="0x00000000004e7da5",func-name="_Dmain",offset="1",inst="mov %rsp,%rbp"}]}]`);
assert.ok(parsed);
assert.equal(parsed.token, 2);
assert.equal(parsed.outOfBandRecord.length, 0);
assert.notEqual(parsed.resultRecords, undefined);
assert.equal(parsed.resultRecords.resultClass, "done");
assert.equal(parsed.resultRecords.results.length, 1);
const asmInsns = [
"asm_insns",
[
[
"src_and_asm_line",
[
["line", "134"],
["file", "source/app.d"],
["fullname", "/path/to/source/app.d"],
[
"line_asm_insn",
[
[
["address", "0x00000000004e7da4"],
["func-name", "_Dmain"],
["offset", "0"],
["inst", "push %rbp"]
],
[
["address", "0x00000000004e7da5"],
["func-name", "_Dmain"],
["offset", "1"],
["inst", "mov %rsp,%rbp"]
]
]
]
]
]
]
];
assert.deepEqual(parsed.resultRecords.results[0], asmInsns);
assert.equal(parsed.result("asm_insns.src_and_asm_line.line_asm_insn[1].address"), "0x00000000004e7da5");
});
test("valueof children", () => {
const obj = [
[
"frame",
[
["level", "0"],
["addr", "0x0000000000435f70"],
["func", "D main"],
["file", "source/app.d"],
["fullname", "/path/to/source/app.d"],
["line", "5"]
]
],
[
"frame",
[
["level", "1"],
["addr", "0x00000000004372d3"],
["func", "rt.dmain2._d_run_main()"]
]
],
[
"frame",
[
["level", "2"],
["addr", "0x0000000000437229"],
["func", "rt.dmain2._d_run_main()"]
]
]
];
assert.equal(MINode.valueOf(obj[0], "@frame.level"), "0");
assert.equal(MINode.valueOf(obj[0], "@frame.addr"), "0x0000000000435f70");
assert.equal(MINode.valueOf(obj[0], "@frame.func"), "D main");
assert.equal(MINode.valueOf(obj[0], "@frame.file"), "source/app.d");
assert.equal(MINode.valueOf(obj[0], "@frame.fullname"), "/path/to/source/app.d");
assert.equal(MINode.valueOf(obj[0], "@frame.line"), "5");
assert.equal(MINode.valueOf(obj[1], "@frame.level"), "1");
assert.equal(MINode.valueOf(obj[1], "@frame.addr"), "0x00000000004372d3");
assert.equal(MINode.valueOf(obj[1], "@frame.func"), "rt.dmain2._d_run_main()");
assert.equal(MINode.valueOf(obj[1], "@frame.file"), undefined);
assert.equal(MINode.valueOf(obj[1], "@frame.fullname"), undefined);
assert.equal(MINode.valueOf(obj[1], "@frame.line"), undefined);
});
test("empty string values", () => {
const parsed = parseMI(`15^done,register-names=["r0","pc","","xpsr","","control"]`);
const result = parsed.result('register-names');
assert.deepEqual(result, ["r0", "pc", "", "xpsr", "", "control"]);
});
test("empty string value first and last", () => {
const parsed = parseMI(`15^done,register-names=["","r0","pc","","xpsr","","control",""]`);
const result = parsed.result('register-names');
assert.deepEqual(result, ["","r0","pc","","xpsr","","control", ""]);
});
test("empty array values", () => {
const parsed = parseMI(`15^done,foo={x=[],y="y"}`);
assert.deepEqual(parsed.result('foo.x'), []);
assert.equal(parsed.result('foo.y'), "y");
});
test("empty object values", () => {
// GDB may send {} as empty array
const parsed = parseMI(`15^done,foo={x={},y="y"}`);
assert.deepEqual(parsed.result('foo.x'), []);
assert.equal(parsed.result('foo.y'), "y");
});
});

View File

@ -1,27 +1,28 @@
import * as assert from 'assert';
import { expandValue, isExpandable } from '../../backend/gdb_expansion';
import { VariableObject } from '../../backend/backend';
suite("GDB Value Expansion", () => {
const variableCreate = (variable) => { return { expanded: variable }; };
const variableCreate = (variable: string) => ({ expanded: variable });
test("Various values", () => {
assert.strictEqual(isExpandable(`false`), 0);
assert.equal(expandValue(variableCreate, `false`), "false");
assert.strictEqual(expandValue(variableCreate, `false`), "false");
assert.strictEqual(isExpandable(`5`), 0);
assert.equal(expandValue(variableCreate, `5`), "5");
assert.strictEqual(expandValue(variableCreate, `5`), "5");
assert.strictEqual(isExpandable(`"hello world!"`), 0);
assert.equal(expandValue(variableCreate, `"hello world!"`), `"hello world!"`);
assert.strictEqual(expandValue(variableCreate, `"hello world!"`), `"hello world!"`);
assert.strictEqual(isExpandable(`0x7fffffffe956 "foobar"`), 0);
assert.equal(expandValue(variableCreate, `0x7fffffffe956 "foobar"`), `"foobar"`);
assert.strictEqual(expandValue(variableCreate, `0x7fffffffe956 "foobar"`), `"foobar"`);
assert.strictEqual(isExpandable(`0x0`), 0);
assert.equal(expandValue(variableCreate, `0x0`), "<nullptr>");
assert.strictEqual(expandValue(variableCreate, `0x0`), "<nullptr>");
assert.strictEqual(isExpandable(`0x000000`), 0);
assert.equal(expandValue(variableCreate, `0x000000`), "<nullptr>");
assert.strictEqual(expandValue(variableCreate, `0x000000`), "<nullptr>");
assert.strictEqual(isExpandable(`{...}`), 2);
assert.equal(expandValue(variableCreate, `{...}`), "<...>");
assert.strictEqual(expandValue(variableCreate, `{...}`), "<...>");
assert.strictEqual(isExpandable(`0x00abc`), 2);
assert.equal(expandValue(variableCreate, `0x007ffff7ecb480`), "*0x007ffff7ecb480");
assert.strictEqual(expandValue(variableCreate, `0x007ffff7ecb480`), "*0x007ffff7ecb480");
assert.strictEqual(isExpandable(`{a = b, c = d}`), 1);
assert.deepEqual(expandValue(variableCreate, `{a = b, c = d}`), [
assert.deepStrictEqual(expandValue(variableCreate, `{a = b, c = d}`), [
{
name: "a",
value: "b",
@ -32,7 +33,7 @@ suite("GDB Value Expansion", () => {
variablesReference: 0
}]);
assert.strictEqual(isExpandable(`{[0] = 0x400730 "foo", [1] = 0x400735 "bar"}`), 1);
assert.deepEqual(expandValue(variableCreate, `{[0] = 0x400730 "foo", [1] = 0x400735 "bar"}`), [
assert.deepStrictEqual(expandValue(variableCreate, `{[0] = 0x400730 "foo", [1] = 0x400735 "bar"}`), [
{
name: "[0]",
value: "\"foo\"",
@ -43,7 +44,7 @@ suite("GDB Value Expansion", () => {
variablesReference: 0
}]);
assert.strictEqual(isExpandable(`{{a = b}}`), 1);
assert.deepEqual(expandValue(variableCreate, `{{a = b}}`), [
assert.deepStrictEqual(expandValue(variableCreate, `{{a = b}}`), [
{
name: "[0]",
value: "Object",
@ -58,7 +59,7 @@ suite("GDB Value Expansion", () => {
}
}
]);
assert.deepEqual(expandValue(variableCreate, `{1, 2, 3, 4}`), [
assert.deepStrictEqual(expandValue(variableCreate, `{1, 2, 3, 4}`), [
{
name: "[0]",
value: "1",
@ -79,11 +80,11 @@ suite("GDB Value Expansion", () => {
});
test("Error values", () => {
assert.strictEqual(isExpandable(`<No data fields>`), 0);
assert.equal(expandValue(variableCreate, `<No data fields>`), "<No data fields>");
assert.strictEqual(expandValue(variableCreate, `<No data fields>`), "<No data fields>");
});
test("Nested values", () => {
assert.strictEqual(isExpandable(`{a = {b = e}, c = d}`), 1);
assert.deepEqual(expandValue(variableCreate, `{a = {b = e}, c = d}`), [
assert.deepStrictEqual(expandValue(variableCreate, `{a = {b = e}, c = d}`), [
{
name: "a",
value: "Object",
@ -105,21 +106,21 @@ suite("GDB Value Expansion", () => {
test("Simple node", () => {
assert.strictEqual(isExpandable(`{a = false, b = 5, c = 0x0, d = "foobar"}`), 1);
const variables = expandValue(variableCreate, `{a = false, b = 5, c = 0x0, d = "foobar"}`);
assert.equal(variables.length, 4);
assert.equal(variables[0].name, "a");
assert.equal(variables[0].value, "false");
assert.equal(variables[1].name, "b");
assert.equal(variables[1].value, "5");
assert.equal(variables[2].name, "c");
assert.equal(variables[2].value, "<nullptr>");
assert.equal(variables[3].name, "d");
assert.equal(variables[3].value, `"foobar"`);
assert.strictEqual(variables.length, 4);
assert.strictEqual(variables[0].name, "a");
assert.strictEqual(variables[0].value, "false");
assert.strictEqual(variables[1].name, "b");
assert.strictEqual(variables[1].value, "5");
assert.strictEqual(variables[2].name, "c");
assert.strictEqual(variables[2].value, "<nullptr>");
assert.strictEqual(variables[3].name, "d");
assert.strictEqual(variables[3].value, `"foobar"`);
});
test("Complex node", () => {
const node = `{quit = false, _views = {{view = 0x7ffff7ece1e8, renderer = 0x7ffff7eccc50, world = 0x7ffff7ece480}}, deltaTimer = {_flagStarted = false, _timeStart = {length = 0}, _timeMeasured = {length = 0}}, _start = {callbacks = 0x0}, _stop = {callbacks = 0x0}}`;
assert.strictEqual(isExpandable(node), 1);
const variables = expandValue(variableCreate, node);
assert.deepEqual(variables, [
assert.deepStrictEqual(variables, [
{
name: "quit",
value: "false",
@ -227,7 +228,7 @@ suite("GDB Value Expansion", () => {
const node = `{_enableMipMaps = false, _minFilter = <incomplete type>, _magFilter = <incomplete type>, _wrapX = <incomplete type>, _wrapY = <incomplete type>, _inMode = 6408, _mode = 6408, _id = 1, _width = 1024, _height = 1024}`;
assert.strictEqual(isExpandable(node), 1);
const variables = expandValue(variableCreate, node);
assert.deepEqual(variables, [
assert.deepStrictEqual(variables, [
{
name: "_enableMipMaps",
value: "false",
@ -284,7 +285,7 @@ suite("GDB Value Expansion", () => {
const node = `{ name = {...} }`;
assert.strictEqual(isExpandable(node), 1);
const variables = expandValue(variableCreate, node);
assert.deepEqual(variables, [
assert.deepStrictEqual(variables, [
{
name: "name",
value: "...",
@ -296,7 +297,7 @@ suite("GDB Value Expansion", () => {
const node = `{ intval1 = 123, floatval1 = 123.456, intval2 = 3, floatval2 = 234.45 }`;
const variables = expandValue(variableCreate, node);
assert.deepEqual(variables, [
assert.deepStrictEqual(variables, [
{ name: "intval1", value: "123", variablesReference: 0 },
{ name: "floatval1", value: "123.456", variablesReference: 0 },
{ name: "intval2", value: "3", variablesReference: 0 },

View File

@ -0,0 +1,207 @@
import * as assert from 'assert';
import { parseMI, MINode } from '../../backend/mi_parse';
suite("MI Parse", () => {
test("Very simple out of band record", () => {
const parsed = parseMI(`*stopped`);
assert.ok(parsed);
assert.strictEqual(parsed.token, undefined);
assert.strictEqual(parsed.outOfBandRecord.length, 1);
assert.strictEqual(parsed.outOfBandRecord[0].isStream, false);
assert.strictEqual(parsed.outOfBandRecord[0].asyncClass, "stopped");
assert.strictEqual(parsed.outOfBandRecord[0].output.length, 0);
assert.strictEqual(parsed.resultRecords, undefined);
});
test("Simple out of band record", () => {
const parsed = parseMI(`4=thread-exited,id="3",group-id="i1"`);
assert.ok(parsed);
assert.strictEqual(parsed.token, 4);
assert.strictEqual(parsed.outOfBandRecord.length, 1);
assert.strictEqual(parsed.outOfBandRecord[0].isStream, false);
assert.strictEqual(parsed.outOfBandRecord[0].asyncClass, "thread-exited");
assert.strictEqual(parsed.outOfBandRecord[0].output.length, 2);
assert.deepStrictEqual(parsed.outOfBandRecord[0].output[0], ["id", "3"]);
assert.deepStrictEqual(parsed.outOfBandRecord[0].output[1], ["group-id", "i1"]);
assert.strictEqual(parsed.resultRecords, undefined);
});
test("Console stream output with new line", () => {
const parsed = parseMI(`~"[Thread 0x7fffe993a700 (LWP 11002) exited]\\n"`);
assert.ok(parsed);
assert.strictEqual(parsed.token, undefined);
assert.strictEqual(parsed.outOfBandRecord.length, 1);
assert.strictEqual(parsed.outOfBandRecord[0].isStream, true);
assert.strictEqual(parsed.outOfBandRecord[0].content, "[Thread 0x7fffe993a700 (LWP 11002) exited]\n");
assert.strictEqual(parsed.resultRecords, undefined);
});
test("Unicode", () => {
let parsed = parseMI(`~"[Depuraci\\303\\263n de hilo usando libthread_db enabled]\\n"`);
assert.ok(parsed);
assert.strictEqual(parsed.token, undefined);
assert.strictEqual(parsed.outOfBandRecord.length, 1);
assert.strictEqual(parsed.outOfBandRecord[0].isStream, true);
assert.strictEqual(parsed.outOfBandRecord[0].content, "[Depuración de hilo usando libthread_db enabled]\n");
assert.strictEqual(parsed.resultRecords, undefined);
parsed = parseMI(`~"4\\t std::cout << \\"\\345\\245\\275\\345\\245\\275\\345\\255\\246\\344\\271\\240\\357\\274\\214\\345\\244\\251\\345\\244\\251\\345\\220\\221\\344\\270\\212\\" << std::endl;\\n"`);
assert.ok(parsed);
assert.strictEqual(parsed.token, undefined);
assert.strictEqual(parsed.outOfBandRecord.length, 1);
assert.strictEqual(parsed.outOfBandRecord[0].isStream, true);
assert.strictEqual(parsed.outOfBandRecord[0].content, `4\t std::cout << "好好学习,天天向上" << std::endl;\n`);
assert.strictEqual(parsed.resultRecords, undefined);
});
test("Empty line", () => {
const parsed = parseMI(``);
assert.ok(parsed);
assert.strictEqual(parsed.token, undefined);
assert.strictEqual(parsed.outOfBandRecord.length, 0);
assert.strictEqual(parsed.resultRecords, undefined);
});
test("'(gdb)' line", () => {
const parsed = parseMI(`(gdb)`);
assert.ok(parsed);
assert.strictEqual(parsed.token, undefined);
assert.strictEqual(parsed.outOfBandRecord.length, 0);
assert.strictEqual(parsed.resultRecords, undefined);
});
test("Simple result record", () => {
const parsed = parseMI(`1^running`);
assert.ok(parsed);
assert.strictEqual(parsed.token, 1);
assert.strictEqual(parsed.outOfBandRecord.length, 0);
assert.notStrictEqual(parsed.resultRecords, undefined);
assert.strictEqual(parsed.resultRecords.resultClass, "running");
assert.strictEqual(parsed.resultRecords.results.length, 0);
});
test("Advanced out of band record (Breakpoint hit)", () => {
const parsed = parseMI(`*stopped,reason="breakpoint-hit",disp="keep",bkptno="1",frame={addr="0x00000000004e807f",func="D main",args=[{name="args",value="..."}],file="source/app.d",fullname="/path/to/source/app.d",line="157"},thread-id="1",stopped-threads="all",core="0"`);
assert.ok(parsed);
assert.strictEqual(parsed.token, undefined);
assert.strictEqual(parsed.outOfBandRecord.length, 1);
assert.strictEqual(parsed.outOfBandRecord[0].isStream, false);
assert.strictEqual(parsed.outOfBandRecord[0].asyncClass, "stopped");
assert.strictEqual(parsed.outOfBandRecord[0].output.length, 7);
assert.deepStrictEqual(parsed.outOfBandRecord[0].output[0], ["reason", "breakpoint-hit"]);
assert.deepStrictEqual(parsed.outOfBandRecord[0].output[1], ["disp", "keep"]);
assert.deepStrictEqual(parsed.outOfBandRecord[0].output[2], ["bkptno", "1"]);
const frame = [
["addr", "0x00000000004e807f"],
["func", "D main"],
["args", [[["name", "args"], ["value", "..."]]]],
["file", "source/app.d"],
["fullname", "/path/to/source/app.d"],
["line", "157"]
];
assert.deepStrictEqual(parsed.outOfBandRecord[0].output[3], ["frame", frame]);
assert.deepStrictEqual(parsed.outOfBandRecord[0].output[4], ["thread-id", "1"]);
assert.deepStrictEqual(parsed.outOfBandRecord[0].output[5], ["stopped-threads", "all"]);
assert.deepStrictEqual(parsed.outOfBandRecord[0].output[6], ["core", "0"]);
assert.strictEqual(parsed.resultRecords, undefined);
});
test("Advanced result record", () => {
const parsed = parseMI(`2^done,asm_insns=[src_and_asm_line={line="134",file="source/app.d",fullname="/path/to/source/app.d",line_asm_insn=[{address="0x00000000004e7da4",func-name="_Dmain",offset="0",inst="push %rbp"},{address="0x00000000004e7da5",func-name="_Dmain",offset="1",inst="mov %rsp,%rbp"}]}]`);
assert.ok(parsed);
assert.strictEqual(parsed.token, 2);
assert.strictEqual(parsed.outOfBandRecord.length, 0);
assert.notStrictEqual(parsed.resultRecords, undefined);
assert.strictEqual(parsed.resultRecords.resultClass, "done");
assert.strictEqual(parsed.resultRecords.results.length, 1);
const asmInsns = [
"asm_insns",
[
[
"src_and_asm_line",
[
["line", "134"],
["file", "source/app.d"],
["fullname", "/path/to/source/app.d"],
[
"line_asm_insn",
[
[
["address", "0x00000000004e7da4"],
["func-name", "_Dmain"],
["offset", "0"],
["inst", "push %rbp"]
],
[
["address", "0x00000000004e7da5"],
["func-name", "_Dmain"],
["offset", "1"],
["inst", "mov %rsp,%rbp"]
]
]
]
]
]
]
];
assert.deepStrictEqual(parsed.resultRecords.results[0], asmInsns);
assert.strictEqual(parsed.result("asm_insns.src_and_asm_line.line_asm_insn[1].address"), "0x00000000004e7da5");
});
test("valueof children", () => {
const obj = [
[
"frame",
[
["level", "0"],
["addr", "0x0000000000435f70"],
["func", "D main"],
["file", "source/app.d"],
["fullname", "/path/to/source/app.d"],
["line", "5"]
]
],
[
"frame",
[
["level", "1"],
["addr", "0x00000000004372d3"],
["func", "rt.dmain2._d_run_main()"]
]
],
[
"frame",
[
["level", "2"],
["addr", "0x0000000000437229"],
["func", "rt.dmain2._d_run_main()"]
]
]
];
assert.strictEqual(MINode.valueOf(obj[0], "@frame.level"), "0");
assert.strictEqual(MINode.valueOf(obj[0], "@frame.addr"), "0x0000000000435f70");
assert.strictEqual(MINode.valueOf(obj[0], "@frame.func"), "D main");
assert.strictEqual(MINode.valueOf(obj[0], "@frame.file"), "source/app.d");
assert.strictEqual(MINode.valueOf(obj[0], "@frame.fullname"), "/path/to/source/app.d");
assert.strictEqual(MINode.valueOf(obj[0], "@frame.line"), "5");
assert.strictEqual(MINode.valueOf(obj[1], "@frame.level"), "1");
assert.strictEqual(MINode.valueOf(obj[1], "@frame.addr"), "0x00000000004372d3");
assert.strictEqual(MINode.valueOf(obj[1], "@frame.func"), "rt.dmain2._d_run_main()");
assert.strictEqual(MINode.valueOf(obj[1], "@frame.file"), undefined);
assert.strictEqual(MINode.valueOf(obj[1], "@frame.fullname"), undefined);
assert.strictEqual(MINode.valueOf(obj[1], "@frame.line"), undefined);
});
test("empty string values", () => {
const parsed = parseMI(`15^done,register-names=["r0","pc","","xpsr","","control"]`);
const result = parsed.result('register-names');
assert.deepStrictEqual(result, ["r0", "pc", "", "xpsr", "", "control"]);
});
test("empty string value first and last", () => {
const parsed = parseMI(`15^done,register-names=["","r0","pc","","xpsr","","control",""]`);
const result = parsed.result('register-names');
assert.deepStrictEqual(result, ["", "r0", "pc", "", "xpsr", "", "control", ""]);
});
test("empty array values", () => {
const parsed = parseMI(`15^done,foo={x=[],y="y"}`);
assert.deepStrictEqual(parsed.result('foo.x'), []);
assert.strictEqual(parsed.result('foo.y'), "y");
});
test("empty object values", () => {
// GDB may send {} as empty array
const parsed = parseMI(`15^done,foo={x={},y="y"}`);
assert.deepStrictEqual(parsed.result('foo.x'), []);
assert.strictEqual(parsed.result('foo.y'), "y");
});
});

79
src/test/unit/path_kind.test.ts Executable file
View File

@ -0,0 +1,79 @@
import * as assert from 'assert';
import { PathKind, PathWin32, PathPosix } from "../../path_kind";
suite("Path Kind", () => {
const pathWin32: PathKind = PathWin32.getInstance();
const pathPosix: PathKind = PathPosix.getInstance();
test("Normalize", () => {
assert.strictEqual(pathWin32.normalize("C:/foo/bar"), "C:\\foo\\bar");
assert.strictEqual(pathWin32.normalize("C:\\foo\\bar"), "C:\\foo\\bar");
assert.strictEqual(pathWin32.normalize("C:/foo/bar/"), "C:\\foo\\bar\\");
assert.strictEqual(pathWin32.normalize("C:\\foo\\bar\\"), "C:\\foo\\bar\\");
assert.strictEqual(pathWin32.normalize("C:\\foo\\bar\\.."), "C:\\foo");
assert.strictEqual(pathWin32.normalize("C:\\foo\\bar\\..\\"), "C:\\foo\\");
assert.strictEqual(pathWin32.normalize("C:\\foo\\..\\bar"), "C:\\bar");
assert.strictEqual(pathWin32.normalize("C:\\foo\\..\\bar\\"), "C:\\bar\\");
assert.strictEqual(pathPosix.normalize("\\home\\foo\\bar"), "/home/foo/bar");
assert.strictEqual(pathPosix.normalize("/home/foo/bar"), "/home/foo/bar");
assert.strictEqual(pathPosix.normalize("\\home\\foo\\bar\\"), "/home/foo/bar/");
assert.strictEqual(pathPosix.normalize("/home/foo/bar/"), "/home/foo/bar/");
assert.strictEqual(pathPosix.normalize("/home/foo/bar/.."), "/home/foo");
assert.strictEqual(pathPosix.normalize("/home/foo/bar/../"), "/home/foo/");
assert.strictEqual(pathPosix.normalize("/home/foo/../bar"), "/home/bar");
assert.strictEqual(pathPosix.normalize("/home/foo/../bar/"), "/home/bar/");
});
test("Normalize Directory", () => {
assert.strictEqual(pathWin32.normalizeDir("C:/foo/bar"), "C:\\foo\\bar\\");
assert.strictEqual(pathWin32.normalizeDir("C:\\foo\\bar"), "C:\\foo\\bar\\");
assert.strictEqual(pathWin32.normalizeDir("C:/foo/bar/"), "C:\\foo\\bar\\");
assert.strictEqual(pathWin32.normalizeDir("C:\\foo\\bar\\"), "C:\\foo\\bar\\");
assert.strictEqual(pathWin32.normalizeDir("C:\\foo\\bar\\.."), "C:\\foo\\");
assert.strictEqual(pathWin32.normalizeDir("C:\\foo\\bar\\..\\"), "C:\\foo\\");
assert.strictEqual(pathWin32.normalizeDir("C:\\foo\\..\\bar"), "C:\\bar\\");
assert.strictEqual(pathWin32.normalizeDir("C:\\foo\\..\\bar\\"), "C:\\bar\\");
assert.strictEqual(pathPosix.normalizeDir("\\home\\foo\\bar"), "/home/foo/bar/");
assert.strictEqual(pathPosix.normalizeDir("/home/foo/bar"), "/home/foo/bar/");
assert.strictEqual(pathPosix.normalizeDir("\\home\\foo\\bar\\"), "/home/foo/bar/");
assert.strictEqual(pathPosix.normalizeDir("/home/foo/bar/"), "/home/foo/bar/");
assert.strictEqual(pathPosix.normalizeDir("/home/foo/bar/.."), "/home/foo/");
assert.strictEqual(pathPosix.normalizeDir("/home/foo/bar/../"), "/home/foo/");
assert.strictEqual(pathPosix.normalizeDir("/home/foo/../bar"), "/home/bar/");
assert.strictEqual(pathPosix.normalizeDir("/home/foo/../bar/"), "/home/bar/");
});
test("Join", () => {
assert.strictEqual(pathWin32.join("C:/foo", "bar/baz.c"), "C:\\foo\\bar\\baz.c");
assert.strictEqual(pathWin32.join("C:\\foo", "bar\\baz.c"), "C:\\foo\\bar\\baz.c");
assert.strictEqual(pathWin32.join("C:\\foo\\", "\\bar\\baz.c"), "C:\\foo\\bar\\baz.c");
assert.strictEqual(pathWin32.join("C:\\Foo\\", "\\Bar\\baz.c"), "C:\\Foo\\Bar\\baz.c");
assert.strictEqual(pathPosix.join("\\home\\foo", "bar\\baz.c"), "/home/foo/bar/baz.c");
assert.strictEqual(pathPosix.join("/home/foo", "bar/baz.c"), "/home/foo/bar/baz.c");
assert.strictEqual(pathPosix.join("/home/foo/", "/bar/baz.c"), "/home/foo/bar/baz.c");
assert.strictEqual(pathPosix.join("/home/Foo/", "/Bar/baz.c"), "/home/Foo/Bar/baz.c");
});
test("Is Absolute Path", () => {
assert.strictEqual(pathWin32.isAbsolute("C:/foo/bar"), true);
assert.strictEqual(pathWin32.isAbsolute("C:\\foo\\bar"), true);
assert.strictEqual(pathWin32.isAbsolute("C:/foo/bar/"), true);
assert.strictEqual(pathWin32.isAbsolute("C:\\foo\\bar\\"), true);
assert.strictEqual(pathWin32.isAbsolute("C:\\foo\\..\\bar"), true);
assert.strictEqual(pathWin32.isAbsolute("C:\\foo\\..\\bar\\"), true);
assert.strictEqual(pathWin32.isAbsolute("foo/bar"), false);
assert.strictEqual(pathWin32.isAbsolute("foo\\bar"), false);
assert.strictEqual(pathWin32.isAbsolute("foo/bar/"), false);
assert.strictEqual(pathWin32.isAbsolute("foo\\bar\\"), false);
assert.strictEqual(pathPosix.isAbsolute("\\home\\foo\\bar"), true);
assert.strictEqual(pathPosix.isAbsolute("/home/foo/bar"), true);
assert.strictEqual(pathPosix.isAbsolute("\\home\\foo\\bar\\"), true);
assert.strictEqual(pathPosix.isAbsolute("/home/foo/bar/"), true);
assert.strictEqual(pathPosix.isAbsolute("/home/foo/../bar"), true);
assert.strictEqual(pathPosix.isAbsolute("/home/foo/../bar/"), true);
assert.strictEqual(pathPosix.isAbsolute("foo\\bar"), false);
assert.strictEqual(pathPosix.isAbsolute("foo/bar"), false);
assert.strictEqual(pathPosix.isAbsolute("foo\\bar\\"), false);
assert.strictEqual(pathPosix.isAbsolute("foo/bar/"), false);
});
});

View File

@ -0,0 +1,361 @@
import * as assert from 'assert';
import { PathKind, PathWin32, PathPosix } from "../../path_kind";
import { SourceFileMap } from '../../source_file_map';
suite("Source File Map", () => {
test("No Mappings", () => {
const fileMap: SourceFileMap = new SourceFileMap({});
const filePaths: string[] = [
"C:\\foo\\src\\bar.c",
"C:/foo/src/bar.c",
"/home/foo/src/bar.c",
"/home/Foo/src/bar.C"
];
filePaths.forEach(filePath => {
assert.strictEqual(fileMap.toLocalPath(filePath), filePath);
assert.strictEqual(fileMap.toRemotePath(filePath), filePath);
});
});
test("Native Path is Local Path", () => {
// Check native path before we override it in subsequent tests.
class NativeSourceFileMap extends SourceFileMap {
public getNativePathTest(): PathKind {
return this.getNativePath();
}
}
const fileMap: NativeSourceFileMap = new NativeSourceFileMap({});
if (process.platform == "win32")
assert.ok(fileMap.getNativePathTest() instanceof PathWin32);
else
assert.ok(fileMap.getNativePathTest() instanceof PathPosix);
});
suite("Local Paths are POSIX", () => {
class PosixSourceFileMap extends SourceFileMap {
protected getNativePath(): PathKind {
return PathPosix.getInstance();
}
}
test("Without Trailing Separator", () => {
const fileMap: PosixSourceFileMap = new PosixSourceFileMap({
"C:\\foo": "/home/foo",
"foo": "home/foo"
}, "C:\\");
assert.strictEqual(fileMap.toLocalPath("C:\\foo\\src\\bar.c"), "/home/foo/src/bar.c");
assert.strictEqual(fileMap.toRemotePath("/home/foo/src/bar.c"), "C:\\foo\\src\\bar.c");
assert.strictEqual(fileMap.toLocalPath("foo\\src\\bar.c"), "home/foo/src/bar.c");
assert.strictEqual(fileMap.toRemotePath("home/foo/src/bar.c"), "foo\\src\\bar.c");
});
test("With Trailing Separator", () => {
const fileMap: PosixSourceFileMap = new PosixSourceFileMap({
"C:\\foo\\": "/home/foo/",
"foo\\": "home/foo/"
}, "C:\\");
assert.strictEqual(fileMap.toLocalPath("C:\\foo\\src\\bar.c"), "/home/foo/src/bar.c");
assert.strictEqual(fileMap.toRemotePath("/home/foo/src/bar.c"), "C:\\foo\\src\\bar.c");
assert.strictEqual(fileMap.toLocalPath("foo\\src\\bar.c"), "home/foo/src/bar.c");
assert.strictEqual(fileMap.toRemotePath("home/foo/src/bar.c"), "foo\\src\\bar.c");
});
test("Multiple Mappings", () => {
const fileMap: PosixSourceFileMap = new PosixSourceFileMap({
"C:\\fooA\\": "/home/foo1/",
"C:\\fooB\\": "/home/foo2/",
"C:\\fooC\\": "/home/foo3/",
"fooA\\": "home/foo1/",
"fooB\\": "home/foo2/",
"fooC\\": "home/foo3/"
}, "C:\\");
assert.strictEqual(fileMap.toLocalPath("C:\\fooA\\src\\bar.c"), "/home/foo1/src/bar.c");
assert.strictEqual(fileMap.toRemotePath("/home/foo1/src/bar.c"), "C:\\fooA\\src\\bar.c");
assert.strictEqual(fileMap.toLocalPath("C:\\fooB\\src\\bar.c"), "/home/foo2/src/bar.c");
assert.strictEqual(fileMap.toRemotePath("/home/foo2/src/bar.c"), "C:\\fooB\\src\\bar.c");
assert.strictEqual(fileMap.toLocalPath("C:\\fooC\\src\\bar.c"), "/home/foo3/src/bar.c");
assert.strictEqual(fileMap.toRemotePath("/home/foo3/src/bar.c"), "C:\\fooC\\src\\bar.c");
assert.strictEqual(fileMap.toLocalPath("fooA\\src\\bar.c"), "home/foo1/src/bar.c");
assert.strictEqual(fileMap.toRemotePath("home/foo1/src/bar.c"), "fooA\\src\\bar.c");
assert.strictEqual(fileMap.toLocalPath("fooB\\src\\bar.c"), "home/foo2/src/bar.c");
assert.strictEqual(fileMap.toRemotePath("home/foo2/src/bar.c"), "fooB\\src\\bar.c");
assert.strictEqual(fileMap.toLocalPath("fooC\\src\\bar.c"), "home/foo3/src/bar.c");
assert.strictEqual(fileMap.toRemotePath("home/foo3/src/bar.c"), "fooC\\src\\bar.c");
});
test("Case-Sensitive Paths", () => {
const fileMap: PosixSourceFileMap = new PosixSourceFileMap({
"C:\\foo\\": "/home/Foo/",
"foo\\": "home/Foo/"
}, "C:\\");
// Match
assert.strictEqual(fileMap.toRemotePath("/home/Foo/Src/Bar.c"), "C:\\foo\\Src\\Bar.c");
assert.strictEqual(fileMap.toRemotePath("home/Foo/Src/Bar.c"), "foo\\Src\\Bar.c");
// No Match
assert.strictEqual(fileMap.toRemotePath("/home/foo/Src/Bar.c"), "/home/foo/Src/Bar.c");
assert.strictEqual(fileMap.toRemotePath("home/foo/Src/Bar.c"), "home/foo/Src/Bar.c");
});
test("Case-Insensitive Paths", () => {
const fileMap: PosixSourceFileMap = new PosixSourceFileMap({
"C:\\foo\\": "/home/Foo/",
"foo\\": "home/Foo/"
}, "C:\\");
// Match
assert.strictEqual(fileMap.toLocalPath("C:\\foo\\Src\\Bar.c"), "/home/Foo/Src/Bar.c");
assert.strictEqual(fileMap.toLocalPath("c:\\Foo\\Src\\Bar.c"), "/home/Foo/Src/Bar.c");
assert.strictEqual(fileMap.toLocalPath("foo\\Src\\Bar.c"), "home/Foo/Src/Bar.c");
assert.strictEqual(fileMap.toLocalPath("Foo\\Src\\Bar.c"), "home/Foo/Src/Bar.c");
});
test("Local and Remote Path Types the Same", () => {
const fileMap: PosixSourceFileMap = new PosixSourceFileMap({
"/home/foo": "/home/zoo",
"home/foo": "home/zoo"
}, "/home");
// Match
assert.strictEqual(fileMap.toLocalPath("/home/foo/bar.c"), "/home/zoo/bar.c");
assert.strictEqual(fileMap.toRemotePath("/home/zoo/bar.c"), "/home/foo/bar.c");
assert.strictEqual(fileMap.toLocalPath("home/foo/bar.c"), "home/zoo/bar.c");
assert.strictEqual(fileMap.toRemotePath("home/zoo/bar.c"), "home/foo/bar.c");
// No Match
assert.strictEqual(fileMap.toLocalPath("/home/zoo/bar.c"), "/home/zoo/bar.c");
assert.strictEqual(fileMap.toRemotePath("/home/foo/bar.c"), "/home/foo/bar.c");
assert.strictEqual(fileMap.toLocalPath("home/zoo/bar.c"), "home/zoo/bar.c");
assert.strictEqual(fileMap.toRemotePath("home/foo/bar.c"), "home/foo/bar.c");
});
test("Non-Normalized Paths", () => {
const fileMap: PosixSourceFileMap = new PosixSourceFileMap({
"C:/foo/bar/baz/..": "/home/foo/../bar",
"foo/bar/baz/..": "home/foo/../bar"
}, "C:\\");
assert.strictEqual(fileMap.toRemotePath("/home/foo/bar/baz.c"), "/home/foo/bar/baz.c");
assert.strictEqual(fileMap.toRemotePath("/home/bar/baz.c"), "C:\\foo\\bar\\baz.c");
assert.strictEqual(fileMap.toRemotePath("/home/foo/../bar/baz.c"), "C:\\foo\\bar\\baz.c");
assert.strictEqual(fileMap.toLocalPath("C:\\foo\\bar\\baz\\zoo.c"), "/home/bar/baz/zoo.c");
assert.strictEqual(fileMap.toLocalPath("C:\\foo\\bar\\baz\\..\\zoo.c"), "/home/bar/zoo.c");
assert.strictEqual(fileMap.toLocalPath("C:\\foo\\bar\\baz.c"), "/home/bar/baz.c");
assert.strictEqual(fileMap.toRemotePath("home/foo/bar/baz.c"), "home/foo/bar/baz.c");
assert.strictEqual(fileMap.toRemotePath("home/bar/baz.c"), "foo\\bar\\baz.c");
assert.strictEqual(fileMap.toRemotePath("home/foo/../bar/baz.c"), "foo\\bar\\baz.c");
assert.strictEqual(fileMap.toLocalPath("foo\\bar\\baz\\zoo.c"), "home/bar/baz/zoo.c");
assert.strictEqual(fileMap.toLocalPath("foo\\bar\\baz\\..\\zoo.c"), "home/bar/zoo.c");
assert.strictEqual(fileMap.toLocalPath("foo\\bar\\baz.c"), "home/bar/baz.c");
});
test("Overlapping Paths", () => {
const fileMap: PosixSourceFileMap = new PosixSourceFileMap({
"C:\\foo": "/home/foo1",
"C:\\foo\\bar": "/home/foo2",
"C:\\zoo1": "/home/zoo",
"C:\\zoo2": "/home/zoo/bar",
"foo": "home/foo1",
"foo\\bar": "home/foo2",
"zoo1": "home/zoo",
"zoo2": "home/zoo/bar"
}, "C:\\");
assert.strictEqual(fileMap.toLocalPath("C:\\foo\\baz.c"), "/home/foo1/baz.c");
assert.strictEqual(fileMap.toLocalPath("C:\\foo\\bar\\baz.c"), "/home/foo2/baz.c");
assert.strictEqual(fileMap.toRemotePath("/home/zoo/baz.c"), "C:\\zoo1\\baz.c");
assert.strictEqual(fileMap.toRemotePath("/home/zoo/bar/baz.c"), "C:\\zoo2\\baz.c");
assert.strictEqual(fileMap.toLocalPath("foo\\baz.c"), "home/foo1/baz.c");
assert.strictEqual(fileMap.toLocalPath("foo\\bar\\baz.c"), "home/foo2/baz.c");
assert.strictEqual(fileMap.toRemotePath("home/zoo/baz.c"), "zoo1\\baz.c");
assert.strictEqual(fileMap.toRemotePath("home/zoo/bar/baz.c"), "zoo2\\baz.c");
});
test("No Remote CWD", () => {
const fileMap: PosixSourceFileMap = new PosixSourceFileMap({
"C:\\foo": "/home/foo1",
"C:\\foo\\bar": "/home/foo2",
"C:\\zoo1": "home/zoo1",
"C:\\zoo2": "home/zoo2/bar",
"foo": "home/foo1",
"foo\\bar": "home/foo2",
"/foo": "/home/foo1/bar",
"/foo/bar": "/home/foo2/bar",
"/zoo1": "home/zoo",
"/zoo2": "home/zoo/bar"
});
assert.strictEqual(fileMap.toLocalPath("C:\\foo\\baz.c"), "/home/foo1/baz.c");
assert.strictEqual(fileMap.toLocalPath("C:\\foo\\bar\\baz.c"), "/home/foo2/baz.c");
assert.strictEqual(fileMap.toLocalPath("C:\\zoo1\\baz.c"), "home/zoo1/baz.c");
assert.strictEqual(fileMap.toLocalPath("C:\\zoo2\\baz.c"), "home/zoo2/bar/baz.c");
assert.strictEqual(fileMap.toLocalPath("foo\\baz.c"), "home/foo1/baz.c");
assert.strictEqual(fileMap.toLocalPath("foo\\bar\\baz.c"), "home/foo2/baz.c");
assert.strictEqual(fileMap.toLocalPath("/foo/baz.c"), "/home/foo1/bar/baz.c");
assert.strictEqual(fileMap.toLocalPath("/foo/bar/baz.c"), "/home/foo2/bar/baz.c");
assert.strictEqual(fileMap.toLocalPath("/zoo1/baz.c"), "home/zoo/baz.c");
assert.strictEqual(fileMap.toLocalPath("/zoo2/baz.c"), "home/zoo/bar/baz.c");
assert.strictEqual(fileMap.toRemotePath("/home/foo1/baz.c"), "C:\\foo\\baz.c");
assert.strictEqual(fileMap.toRemotePath("/home/foo2/baz.c"), "C:\\foo\\bar\\baz.c");
assert.strictEqual(fileMap.toRemotePath("home/zoo1/baz.c"), "C:\\zoo1\\baz.c");
assert.strictEqual(fileMap.toRemotePath("home/zoo2/bar/baz.c"), "C:\\zoo2\\baz.c");
assert.strictEqual(fileMap.toRemotePath("home/foo1/baz.c"), "foo\\baz.c");
assert.strictEqual(fileMap.toRemotePath("home/foo2/baz.c"), "foo\\bar\\baz.c");
assert.strictEqual(fileMap.toRemotePath("/home/foo1/bar/baz.c"), "/foo/baz.c");
assert.strictEqual(fileMap.toRemotePath("/home/foo2/bar/baz.c"), "/foo/bar/baz.c");
assert.strictEqual(fileMap.toRemotePath("home/zoo/baz.c"), "/zoo1/baz.c");
assert.strictEqual(fileMap.toRemotePath("home/zoo/bar/baz.c"), "/zoo2/baz.c");
});
});
suite("Local Paths are Win32", () => {
class Win32SourceFileMap extends SourceFileMap {
protected getNativePath(): PathKind {
return PathWin32.getInstance();
}
}
test("Without Trailing Separator", () => {
const fileMap: Win32SourceFileMap = new Win32SourceFileMap({
"/home/foo": "C:\\foo",
"home/foo": "foo"
}, "/home");
assert.strictEqual(fileMap.toLocalPath("/home/foo/src/bar.c"), "C:\\foo\\src\\bar.c");
assert.strictEqual(fileMap.toRemotePath("C:\\foo\\src\\bar.c"), "/home/foo/src/bar.c");
assert.strictEqual(fileMap.toLocalPath("home/foo/src/bar.c"), "foo\\src\\bar.c");
assert.strictEqual(fileMap.toRemotePath("foo\\src\\bar.c"), "home/foo/src/bar.c");
});
test("With Trailing Separator", () => {
const fileMap: Win32SourceFileMap = new Win32SourceFileMap({
"/home/foo/": "C:\\foo\\",
"home/foo/": "foo\\"
}, "/home");
assert.strictEqual(fileMap.toLocalPath("/home/foo/src/bar.c"), "C:\\foo\\src\\bar.c");
assert.strictEqual(fileMap.toRemotePath("C:\\foo\\src\\bar.c"), "/home/foo/src/bar.c");
assert.strictEqual(fileMap.toLocalPath("home/foo/src/bar.c"), "foo\\src\\bar.c");
assert.strictEqual(fileMap.toRemotePath("foo\\src\\bar.c"), "home/foo/src/bar.c");
});
test("Multiple Mappings", () => {
const fileMap: Win32SourceFileMap = new Win32SourceFileMap({
"/home/foo1/": "C:\\fooA\\",
"/home/foo2/": "C:\\fooB\\",
"/home/foo3/": "C:\\fooC\\",
"home/foo1/": "fooA\\",
"home/foo2/": "fooB\\",
"home/foo3/": "fooC\\"
}, "/home");
assert.strictEqual(fileMap.toLocalPath("/home/foo1/src/bar.c"), "C:\\fooA\\src\\bar.c");
assert.strictEqual(fileMap.toRemotePath("C:\\fooA\\src\\bar.c"), "/home/foo1/src/bar.c");
assert.strictEqual(fileMap.toLocalPath("/home/foo2/src/bar.c"), "C:\\fooB\\src\\bar.c");
assert.strictEqual(fileMap.toRemotePath("C:\\fooB\\src\\bar.c"), "/home/foo2/src/bar.c");
assert.strictEqual(fileMap.toLocalPath("/home/foo3/src/bar.c"), "C:\\fooC\\src\\bar.c");
assert.strictEqual(fileMap.toRemotePath("C:\\fooC\\src\\bar.c"), "/home/foo3/src/bar.c");
assert.strictEqual(fileMap.toLocalPath("home/foo1/src/bar.c"), "fooA\\src\\bar.c");
assert.strictEqual(fileMap.toRemotePath("fooA\\src\\bar.c"), "home/foo1/src/bar.c");
assert.strictEqual(fileMap.toLocalPath("home/foo2/src/bar.c"), "fooB\\src\\bar.c");
assert.strictEqual(fileMap.toRemotePath("fooB\\src\\bar.c"), "home/foo2/src/bar.c");
assert.strictEqual(fileMap.toLocalPath("home/foo3/src/bar.c"), "fooC\\src\\bar.c");
assert.strictEqual(fileMap.toRemotePath("fooC\\src\\bar.c"), "home/foo3/src/bar.c");
});
test("Case-Sensitive Paths", () => {
const fileMap: Win32SourceFileMap = new Win32SourceFileMap({
"/home/Foo/": "C:\\foo\\",
"home/Foo/": "foo\\"
}, "/home");
// Match
assert.strictEqual(fileMap.toLocalPath("/home/Foo/Src/Bar.c"), "C:\\foo\\Src\\Bar.c");
assert.strictEqual(fileMap.toLocalPath("home/Foo/Src/Bar.c"), "foo\\Src\\Bar.c");
// No Match
assert.strictEqual(fileMap.toLocalPath("/home/foo/Src/Bar.c"), "/home/foo/Src/Bar.c");
assert.strictEqual(fileMap.toLocalPath("home/foo/Src/Bar.c"), "home/foo/Src/Bar.c");
});
test("Case-Insensitive Paths", () => {
const fileMap: Win32SourceFileMap = new Win32SourceFileMap({
"/home/Foo/": "C:\\foo\\",
"home/Foo/": "foo\\"
}, "/home");
// Match
assert.strictEqual(fileMap.toRemotePath("C:\\foo\\Src\\Bar.c"), "/home/Foo/Src/Bar.c");
assert.strictEqual(fileMap.toRemotePath("c:\\Foo\\Src\\Bar.c"), "/home/Foo/Src/Bar.c");
assert.strictEqual(fileMap.toRemotePath("foo\\Src\\Bar.c"), "home/Foo/Src/Bar.c");
assert.strictEqual(fileMap.toRemotePath("Foo\\Src\\Bar.c"), "home/Foo/Src/Bar.c");
});
test("Local and Remote Path Types the Same", () => {
const fileMap: Win32SourceFileMap = new Win32SourceFileMap({
"C:\\foo": "C:\\zoo",
"foo": "zoo"
}, "C:\\");
// Match
assert.strictEqual(fileMap.toLocalPath("C:\\foo\\bar.c"), "C:\\zoo\\bar.c");
assert.strictEqual(fileMap.toRemotePath("C:\\zoo\\bar.c"), "C:\\foo\\bar.c");
assert.strictEqual(fileMap.toLocalPath("foo\\bar.c"), "zoo\\bar.c");
assert.strictEqual(fileMap.toRemotePath("zoo\\bar.c"), "foo\\bar.c");
// No Match
assert.strictEqual(fileMap.toLocalPath("C:\\zoo\\bar.c"), "C:\\zoo\\bar.c");
assert.strictEqual(fileMap.toRemotePath("C:\\foo\\bar.c"), "C:\\foo\\bar.c");
assert.strictEqual(fileMap.toLocalPath("zoo\\bar.c"), "zoo\\bar.c");
assert.strictEqual(fileMap.toRemotePath("foo\\bar.c"), "foo\\bar.c");
});
test("Non-Normalized Paths", () => {
const fileMap: Win32SourceFileMap = new Win32SourceFileMap({
"/home/foo/../bar": "C:/foo/bar/baz/..",
"home/foo/../bar": "foo/bar/baz/.."
}, "/home");
assert.strictEqual(fileMap.toLocalPath("/home/foo/bar/baz.c"), "/home/foo/bar/baz.c");
assert.strictEqual(fileMap.toLocalPath("/home/bar/baz.c"), "C:\\foo\\bar\\baz.c");
assert.strictEqual(fileMap.toLocalPath("/home/foo/../bar/baz.c"), "C:\\foo\\bar\\baz.c");
assert.strictEqual(fileMap.toRemotePath("C:\\foo\\bar\\baz\\zoo.c"), "/home/bar/baz/zoo.c");
assert.strictEqual(fileMap.toRemotePath("C:\\foo\\bar\\baz\\..\\zoo.c"), "/home/bar/zoo.c");
assert.strictEqual(fileMap.toRemotePath("C:\\foo\\bar\\baz.c"), "/home/bar/baz.c");
assert.strictEqual(fileMap.toLocalPath("home/foo/bar/baz.c"), "home/foo/bar/baz.c");
assert.strictEqual(fileMap.toLocalPath("home/bar/baz.c"), "foo\\bar\\baz.c");
assert.strictEqual(fileMap.toLocalPath("home/foo/../bar/baz.c"), "foo\\bar\\baz.c");
assert.strictEqual(fileMap.toRemotePath("foo\\bar\\baz\\zoo.c"), "home/bar/baz/zoo.c");
assert.strictEqual(fileMap.toRemotePath("foo\\bar\\baz\\..\\zoo.c"), "home/bar/zoo.c");
assert.strictEqual(fileMap.toRemotePath("foo\\bar\\baz.c"), "home/bar/baz.c");
});
test("Overlapping Paths", () => {
const fileMap: Win32SourceFileMap = new Win32SourceFileMap({
"/home/foo": "C:\\foo1",
"/home/foo/bar": "C:\\foo2",
"/home/zoo1": "C:\\zoo",
"/home/zoo2": "C:\\zoo\\bar",
"home/foo": "foo1",
"home/foo/bar": "foo2",
"home/zoo1": "zoo",
"home/zoo2": "zoo\\bar"
}, "/home");
assert.strictEqual(fileMap.toLocalPath("/home/foo/baz.c"), "C:\\foo1\\baz.c");
assert.strictEqual(fileMap.toLocalPath("/home/foo/bar/baz.c"), "C:\\foo2\\baz.c");
assert.strictEqual(fileMap.toRemotePath("C:\\zoo\\baz.c"), "/home/zoo1/baz.c");
assert.strictEqual(fileMap.toRemotePath("C:\\zoo\\bar\\baz.c"), "/home/zoo2/baz.c");
assert.strictEqual(fileMap.toLocalPath("home/foo/baz.c"), "foo1\\baz.c");
assert.strictEqual(fileMap.toLocalPath("home/foo/bar/baz.c"), "foo2\\baz.c");
assert.strictEqual(fileMap.toRemotePath("zoo\\baz.c"), "home/zoo1/baz.c");
assert.strictEqual(fileMap.toRemotePath("zoo\\bar\\baz.c"), "home/zoo2/baz.c");
});
test("No Remote CWD", () => {
const fileMap: Win32SourceFileMap = new Win32SourceFileMap({
"C:\\foo": "C:\\foo1",
"C:\\foo\\bar": "C:\\foo2",
"C:\\zoo1": "home\\zoo1",
"C:\\zoo2": "home\\zoo2\\bar",
"foo": "home\\foo1",
"foo\\bar": "home\\foo2",
"/foo": "C:\\foo1/bar",
"/foo/bar": "C:\\foo2\\bar",
"/zoo1": "home\\zoo",
"/zoo2": "home\\zoo\\bar"
});
assert.strictEqual(fileMap.toLocalPath("C:\\foo\\baz.c"), "C:\\foo1\\baz.c");
assert.strictEqual(fileMap.toLocalPath("C:\\foo\\bar\\baz.c"), "C:\\foo2\\baz.c");
assert.strictEqual(fileMap.toLocalPath("C:\\zoo1\\baz.c"), "home\\zoo1\\baz.c");
assert.strictEqual(fileMap.toLocalPath("C:\\zoo2\\baz.c"), "home\\zoo2\\bar\\baz.c");
assert.strictEqual(fileMap.toLocalPath("foo\\baz.c"), "home\\foo1\\baz.c");
assert.strictEqual(fileMap.toLocalPath("foo\\bar\\baz.c"), "home\\foo2\\baz.c");
assert.strictEqual(fileMap.toLocalPath("/foo/baz.c"), "C:\\foo1\\bar\\baz.c");
assert.strictEqual(fileMap.toLocalPath("/foo/bar/baz.c"), "C:\\foo2\\bar\\baz.c");
assert.strictEqual(fileMap.toLocalPath("/zoo1/baz.c"), "home\\zoo\\baz.c");
assert.strictEqual(fileMap.toLocalPath("/zoo2/baz.c"), "home\\zoo\\bar\\baz.c");
assert.strictEqual(fileMap.toRemotePath("C:\\foo1\\baz.c"), "C:\\foo\\baz.c");
assert.strictEqual(fileMap.toRemotePath("C:\\foo2/baz.c"), "C:\\foo\\bar\\baz.c");
assert.strictEqual(fileMap.toRemotePath("home\\zoo1\\baz.c"), "C:\\zoo1\\baz.c");
assert.strictEqual(fileMap.toRemotePath("home\\zoo2\\bar\\baz.c"), "C:\\zoo2\\baz.c");
assert.strictEqual(fileMap.toRemotePath("home\\foo1\\baz.c"), "foo\\baz.c");
assert.strictEqual(fileMap.toRemotePath("home\\foo2\\baz.c"), "foo\\bar\\baz.c");
assert.strictEqual(fileMap.toRemotePath("C:\\foo1\\bar\\baz.c"), "/foo/baz.c");
assert.strictEqual(fileMap.toRemotePath("C:\\foo2\\bar\\baz.c"), "/foo/bar/baz.c");
assert.strictEqual(fileMap.toRemotePath("home\\zoo\\baz.c"), "/zoo1/baz.c");
assert.strictEqual(fileMap.toRemotePath("home\\zoo\\bar\\baz.c"), "/zoo2/baz.c");
});
});
});