From 3799f595d39142353a6d4558fffdf76a45a1fa61 Mon Sep 17 00:00:00 2001 From: praingeard Date: Mon, 23 Dec 2019 23:39:33 +0100 Subject: [PATCH] feat(#85): use of workspace.fs --- src/breakpointManager.ts | 20 ++- src/debugInfo.ts | 274 +++++++++++++++-------------- src/fsUAEDebug.ts | 179 ++++++++++--------- src/test/breakpointManager.test.ts | 4 +- src/test/debugInfo.test.ts | 14 +- 5 files changed, 257 insertions(+), 234 deletions(-) diff --git a/src/breakpointManager.ts b/src/breakpointManager.ts index 683af4de..8abdf4d5 100644 --- a/src/breakpointManager.ts +++ b/src/breakpointManager.ts @@ -40,16 +40,18 @@ export class BreakpointManager { this.pendingBreakpoints.push(breakpoint); } - private fillBreakpointWithSegAddress(debugBp: GdbBreakpoint, path: string, line: number): boolean { - if (this.debugInfo) { - let values = this.debugInfo.getAddressSeg(path, line); - if (values) { - debugBp.segmentId = values[0]; - debugBp.offset = values[1]; - return true; + private fillBreakpointWithSegAddress(debugBp: GdbBreakpoint, path: string, line: number): Promise { + return new Promise(async (resolve, _reject) => { + if (this.debugInfo) { + let values = await this.debugInfo.getAddressSeg(path, line); + if (values) { + debugBp.segmentId = values[0]; + debugBp.offset = values[1]; + resolve(true); + } } - } - return false; + resolve(false); + }); } public checkPendingBreakpointsAddresses() { diff --git a/src/debugInfo.ts b/src/debugInfo.ts index 0818a0b1..b6a075ef 100644 --- a/src/debugInfo.ts +++ b/src/debugInfo.ts @@ -1,5 +1,4 @@ import { Hunk, HunkParser, SourceLine, HunkType, Symbol } from './amigaHunkParser'; -import * as fs from 'fs'; import * as path from 'path'; import * as vscode from 'vscode'; import { FileProxy } from './fsProxy'; @@ -40,38 +39,40 @@ export class DebugInfo { return codeDataArray; } - public getSymbols(filename: string | undefined): Array<[Symbol, number | undefined]> { - let symbols = Array<[Symbol, number | undefined]>(); - let normFilename = filename; - if (normFilename) { - normFilename = FileProxy.normalize(normFilename); - } - for (let i = 0; i < this.hunks.length; i++) { - let hunk = this.hunks[i]; - if (hunk.symbols) { - if (normFilename) { - let sourceFiles = hunk.lineDebugInfo; - if (sourceFiles) { - for (let j = 0; j < sourceFiles.length; j++) { - let srcFile = sourceFiles[j]; - // Is there a path replacement - let name = this.resolveFileName(srcFile.name); - if (this.areSameSourceFileNames(name, normFilename)) { - for (let s of hunk.symbols) { - symbols.push([s, hunk.segmentsId]); + public getSymbols(filename: string | undefined): Promise> { + return new Promise(async (resolve, _reject) => { + let symbols = Array<[Symbol, number | undefined]>(); + let normFilename = filename; + if (normFilename) { + normFilename = FileProxy.normalize(normFilename); + } + for (let i = 0; i < this.hunks.length; i++) { + let hunk = this.hunks[i]; + if (hunk.symbols) { + if (normFilename) { + let sourceFiles = hunk.lineDebugInfo; + if (sourceFiles) { + for (let j = 0; j < sourceFiles.length; j++) { + let srcFile = sourceFiles[j]; + // Is there a path replacement + let name = await this.resolveFileName(srcFile.name); + if (this.areSameSourceFileNames(name, normFilename)) { + for (let s of hunk.symbols) { + symbols.push([s, hunk.segmentsId]); + } + break; } - break; } } - } - } else { - for (let s of hunk.symbols) { - symbols.push([s, hunk.segmentsId]); + } else { + for (let s of hunk.symbols) { + symbols.push([s, hunk.segmentsId]); + } } } } - } - return symbols; + resolve(symbols); + }); } protected tryFindLine(filename: string, lines: Array, offset: number): ([string, number] | null) { @@ -99,92 +100,105 @@ export class DebugInfo { } } - private getSourceLineText(filename: string, line: number): [string, string | null] { - let resolvedFileName = this.resolveFileName(filename); - let contents: Array | undefined = this.sourceFilesCacheMap.get(resolvedFileName); - if (!contents) { - // Load source file - contents = fs.readFileSync(resolvedFileName).toString().split(/\r\n|\r|\n/g); - this.sourceFilesCacheMap.set(resolvedFileName, contents); - } - if (contents && (line < contents.length)) { - return [resolvedFileName, contents[line]]; - } - return [resolvedFileName, null]; + private getSourceLineText(filename: string, line: number): Promise<[string, string | null]> { + return new Promise(async (resolve, reject) => { + let resolvedFileName = await this.resolveFileName(filename); + let contents: Array | undefined = this.sourceFilesCacheMap.get(resolvedFileName); + if (!contents) { + // Load source file + let fileProxy = new FileProxy(Uri.file(resolvedFileName)); + let fileContentsString = await fileProxy.readFileText(); + contents = fileContentsString.split(/\r\n|\r|\n/g); + this.sourceFilesCacheMap.set(resolvedFileName, contents); + } + if (contents && (line < contents.length)) { + resolve([resolvedFileName, contents[line]]); + } + resolve([resolvedFileName, null]); + }); } - public resolveFileLine(segId: number, offset: number): ([string, number, string | null] | null) { - if (segId >= this.hunks.length) { - return null; - } - let hunk = this.hunks[segId]; - let sourceLineText = null; - - let source_files = hunk.lineDebugInfo; - if (source_files) { - for (let i = 0; i < source_files.length; i++) { - let srcFile = source_files[i]; - //if offset > src_file.base_offset { - // continue; - //} - let data = this.tryFindLine(srcFile.name, srcFile.lines, offset); - if (data) { - // transform the file path to a local one - let resolvedFileName = this.resolveFileName(data[0]); - if (data[1] > 0) { - [resolvedFileName, sourceLineText] = this.getSourceLineText(resolvedFileName, data[1] - 1); + public resolveFileLine(segId: number, offset: number): Promise<([string, number, string | null] | null)> { + return new Promise(async (resolve, reject) => { + if (segId >= this.hunks.length) { + resolve(null); + } + let hunk = this.hunks[segId]; + let sourceLineText = null; + + let source_files = hunk.lineDebugInfo; + if (source_files) { + for (let i = 0; i < source_files.length; i++) { + let srcFile = source_files[i]; + //if offset > src_file.base_offset { + // continue; + //} + let data = this.tryFindLine(srcFile.name, srcFile.lines, offset); + if (data) { + // transform the file path to a local one + let resolvedFileName = await this.resolveFileName(data[0]); + if (data[1] > 0) { + [resolvedFileName, sourceLineText] = await this.getSourceLineText(resolvedFileName, data[1] - 1); + } + resolve([resolvedFileName, data[1], sourceLineText]); } - return [resolvedFileName, data[1], sourceLineText]; } } - } - return null; + resolve(null); + }); } - findFileInWorkspace(filename: string): string { - // fall back to the first workspace - let folders = vscode.workspace.workspaceFolders; - if (folders) { - for (let folder of folders) { - let folderPath = path.join(folder.uri.fsPath, filename); - if (fs.existsSync(folderPath)) { - return folderPath; + private findFileInWorkspace(filename: string): Promise { + return new Promise(async (resolve, _reject) => { + // fall back to the first workspace + let folders = vscode.workspace.workspaceFolders; + if (folders) { + for (let folder of folders) { + let folderPath = path.join(folder.uri.fsPath, filename); + let fileProxy = new FileProxy(Uri.file(folderPath)); + if (await fileProxy.exists()) { + resolve(folderPath); + } } } - } - return filename; + resolve(filename); + }); } - private resolveFileName(filename: string): string { - let resolvedFileName = this.resolvedSourceFilesNames.get(filename); - if (!resolvedFileName) { - resolvedFileName = filename; - if (this.pathReplacements) { - for (let key of Array.from(this.pathReplacements.keys())) { - if (resolvedFileName.indexOf(key) >= 0) { - let value = this.pathReplacements.get(key); - if (value) { - resolvedFileName = resolvedFileName.replace(key, value); - break; + private resolveFileName(filename: string): Promise { + return new Promise(async (resolve, reject) => { + let resolvedFileName = this.resolvedSourceFilesNames.get(filename); + if (!resolvedFileName) { + resolvedFileName = filename; + if (this.pathReplacements) { + for (let key of Array.from(this.pathReplacements.keys())) { + if (resolvedFileName.indexOf(key) >= 0) { + let value = this.pathReplacements.get(key); + if (value) { + resolvedFileName = resolvedFileName.replace(key, value); + break; + } } } } - } - // search the file in the workspace - resolvedFileName = this.findFileInWorkspace(resolvedFileName); - if (this.sourcesRootPaths && !fs.existsSync(resolvedFileName)) { - for (let rootPath of this.sourcesRootPaths) { - let checkedPath = path.join(rootPath, resolvedFileName); - if (fs.existsSync(checkedPath)) { - resolvedFileName = checkedPath; - break; + // search the file in the workspace + resolvedFileName = await this.findFileInWorkspace(resolvedFileName); + let fProxy = new FileProxy(Uri.file(resolvedFileName)); + if (this.sourcesRootPaths && !await fProxy.exists()) { + for (let rootPath of this.sourcesRootPaths) { + let checkedPath = path.join(rootPath, resolvedFileName); + let checkedProxy = new FileProxy(Uri.file(checkedPath)); + if (await checkedProxy.exists()) { + resolvedFileName = checkedPath; + break; + } } } + resolvedFileName = FileProxy.normalize(resolvedFileName); + this.resolvedSourceFilesNames.set(filename, resolvedFileName); } - resolvedFileName = FileProxy.normalize(resolvedFileName); - this.resolvedSourceFilesNames.set(filename, resolvedFileName); - } - return resolvedFileName; + resolve(resolvedFileName); + }); } public areSameSourceFileNames(sourceA: string, sourceB: string): boolean { @@ -194,47 +208,51 @@ export class DebugInfo { return path.basename(sourceB) === path.basename(sourceA); } - public getAddressSeg(filename: string, fileLine: number): ([number, number] | null) { - let normFilename = FileProxy.normalize(filename); - for (let i = 0; i < this.hunks.length; i++) { - let hunk = this.hunks[i]; - let sourceFiles = hunk.lineDebugInfo; - if (sourceFiles) { - for (let j = 0; j < sourceFiles.length; j++) { - let srcFile = sourceFiles[j]; - // Is there a path replacement - let name = this.resolveFileName(srcFile.name); - if (this.areSameSourceFileNames(name, normFilename)) { - for (let k = 0; k < srcFile.lines.length; k++) { - let line = srcFile.lines[k]; - if (line.line === fileLine) { - return [i, line.offset]; + public getAddressSeg(filename: string, fileLine: number): Promise<([number, number] | null)> { + return new Promise(async (resolve, _reject) => { + let normFilename = FileProxy.normalize(filename); + for (let i = 0; i < this.hunks.length; i++) { + let hunk = this.hunks[i]; + let sourceFiles = hunk.lineDebugInfo; + if (sourceFiles) { + for (let j = 0; j < sourceFiles.length; j++) { + let srcFile = sourceFiles[j]; + // Is there a path replacement + let name = await this.resolveFileName(srcFile.name); + if (this.areSameSourceFileNames(name, normFilename)) { + for (let k = 0; k < srcFile.lines.length; k++) { + let line = srcFile.lines[k]; + if (line.line === fileLine) { + resolve([i, line.offset]); + } } } } } } - } - return null; + resolve(null); + }); } - public getAllSegmentIds(filename: string): number[] { - let segIds: number[] = []; - let normFilename = FileProxy.normalize(filename); - for (let i = 0; i < this.hunks.length; i++) { - let hunk = this.hunks[i]; - let sourceFiles = hunk.lineDebugInfo; - if (sourceFiles) { - for (let j = 0; j < sourceFiles.length; j++) { - let srcFile = sourceFiles[j]; - // Is there a path replacement - let name = this.resolveFileName(srcFile.name); - if (this.areSameSourceFileNames(name, normFilename)) { - segIds.push(i); + public getAllSegmentIds(filename: string): Promise { + return new Promise(async (resolve, _reject) => { + let segIds: number[] = []; + let normFilename = FileProxy.normalize(filename); + for (let i = 0; i < this.hunks.length; i++) { + let hunk = this.hunks[i]; + let sourceFiles = hunk.lineDebugInfo; + if (sourceFiles) { + for (let j = 0; j < sourceFiles.length; j++) { + let srcFile = sourceFiles[j]; + // Is there a path replacement + let name = await this.resolveFileName(srcFile.name); + if (this.areSameSourceFileNames(name, normFilename)) { + segIds.push(i); + } } } } - } - return segIds; + resolve(segIds); + }); } } diff --git a/src/fsUAEDebug.ts b/src/fsUAEDebug.ts index 5de1b9dc..f8d7ebea 100644 --- a/src/fsUAEDebug.ts +++ b/src/fsUAEDebug.ts @@ -526,109 +526,112 @@ export class FsUAEDebugSession extends DebugSession implements DebugVariableReso }); } - protected stackTraceRequest(response: DebugProtocol.StackTraceResponse, args: DebugProtocol.StackTraceArguments): void { - if (this.debugInfo) { - const dbgInfo = this.debugInfo; - const thread = this.gdbProxy.getThread(args.threadId); - if (thread) { - this.gdbProxy.stack(thread).then(async stk => { - let stackFrames = []; - let updatedView = false; - for (let f of stk.frames) { - if ((!updatedView) && (thread.getThreadId() === GdbAmigaSysThreadId.CPU)) { - // Update the cpu view - this.updateDisassembledView(f.pc, 100); - updatedView = true; - } - let stackFrameDone = false; - let pc = f.pc.toString(16); - if (f.segmentId >= 0) { - let values = dbgInfo.resolveFileLine(f.segmentId, f.offset); - if (values) { - let line = values[2]; - if (line) { - let idx = line.indexOf(';'); - if (idx > 0) { - line = line.substring(0, idx); + protected stackTraceRequest(response: DebugProtocol.StackTraceResponse, args: DebugProtocol.StackTraceArguments): Promise { + return new Promise(async (resolve, _reject) => { + if (this.debugInfo) { + const dbgInfo = this.debugInfo; + const thread = this.gdbProxy.getThread(args.threadId); + if (thread) { + this.gdbProxy.stack(thread).then(async stk => { + let stackFrames = []; + let updatedView = false; + for (let f of stk.frames) { + if ((!updatedView) && (thread.getThreadId() === GdbAmigaSysThreadId.CPU)) { + // Update the cpu view + this.updateDisassembledView(f.pc, 100); + updatedView = true; + } + let stackFrameDone = false; + let pc = f.pc.toString(16); + if (f.segmentId >= 0) { + let values = await dbgInfo.resolveFileLine(f.segmentId, f.offset); + if (values) { + let line = values[2]; + if (line) { + let idx = line.indexOf(';'); + if (idx > 0) { + line = line.substring(0, idx); + } + line = pc + ": " + line.trim().replace(/\s\s+/g, ' '); + } else { + line = pc; } - line = pc + ": " + line.trim().replace(/\s\s+/g, ' '); - } else { - line = pc; + stackFrames.push(new StackFrame(f.index, line, this.createSource(values[0]), values[1], 1)); + stackFrameDone = true; } - stackFrames.push(new StackFrame(f.index, line, this.createSource(values[0]), values[1], 1)); - stackFrameDone = true; } - } - if (!stackFrameDone) { - let line: string = pc; - if (thread.getThreadId() === GdbAmigaSysThreadId.CPU) { - let dCode = this.disassembledCache.get(f.pc); - if (dCode) { - line = dCode; - } else { - // Get the disassembled line - line += ": "; - if (this.capstone) { + if (!stackFrameDone) { + let line: string = pc; + if (thread.getThreadId() === GdbAmigaSysThreadId.CPU) { + let dCode = this.disassembledCache.get(f.pc); + if (dCode) { + line = dCode; + } else { + // Get the disassembled line + line += ": "; + if (this.capstone) { + let memory = await this.gdbProxy.getMemory(f.pc, 10).catch((err) => { + console.error("Error ignored: " + err.getMessage()); + }); + if (memory) { + let disassembled = await this.capstone.disassemble(memory); + let lines = disassembled.split(/\r\n|\r|\n/g); + let selectedLine = lines[0]; + for (let l of lines) { + if (l.trim().length > 0) { + selectedLine = l; + break; + } + } + let elms = selectedLine.split(" "); + if (elms.length > 2) { + selectedLine = elms[2]; + } + line += selectedLine.trim().replace(/\s\s+/g, ' '); + } + } + this.disassembledCache.set(f.pc, line); + } + } else if (thread.getThreadId() === GdbAmigaSysThreadId.COP) { + let dCopperCode = this.disassembledCopperCache.get(f.pc); + if (dCopperCode) { + line = dCopperCode; + } else { + // Get the disassembled line + line += ": "; let memory = await this.gdbProxy.getMemory(f.pc, 10).catch((err) => { console.error("Error ignored: " + err.getMessage()); }); if (memory) { - let disassembled = await this.capstone.disassemble(memory); - let lines = disassembled.split(/\r\n|\r|\n/g); - let selectedLine = lines[0]; - for (let l of lines) { - if (l.trim().length > 0) { - selectedLine = l; - break; - } - } - let elms = selectedLine.split(" "); - if (elms.length > 2) { - selectedLine = elms[2]; - } - line += selectedLine.trim().replace(/\s\s+/g, ' '); + let cDis = new CopperDisassembler(memory); + line = line + cDis.disassemble()[0].toString().split(" ")[0]; + this.disassembledCopperCache.set(f.pc, line); } } - this.disassembledCache.set(f.pc, line); } - } else if (thread.getThreadId() === GdbAmigaSysThreadId.COP) { - let dCopperCode = this.disassembledCopperCache.get(f.pc); - if (dCopperCode) { - line = dCopperCode; - } else { - // Get the disassembled line - line += ": "; - let memory = await this.gdbProxy.getMemory(f.pc, 10).catch((err) => { - console.error("Error ignored: " + err.getMessage()); - }); - if (memory) { - let cDis = new CopperDisassembler(memory); - line = line + cDis.disassemble()[0].toString().split(" ")[0]; - this.disassembledCopperCache.set(f.pc, line); - } + // The the stack frame from the manager + let stackFrame = await this.debugDisassembledManager.getStackFrame(f.index, f.pc, line, (thread.getThreadId() === GdbAmigaSysThreadId.COP)); + if (stackFrame) { + stackFrames.push(stackFrame); } } - // The the stack frame from the manager - let stackFrame = await this.debugDisassembledManager.getStackFrame(f.index, f.pc, line, (thread.getThreadId() === GdbAmigaSysThreadId.COP)); - if (stackFrame) { - stackFrames.push(stackFrame); - } } - } - response.body = { - stackFrames: stackFrames, - totalFrames: stk.count - }; - this.sendResponse(response); - }).catch((err) => { - this.sendStringErrorResponse(response, err.message); - }); + response.body = { + stackFrames: stackFrames, + totalFrames: stk.count + }; + this.sendResponse(response); + }).catch((err) => { + this.sendStringErrorResponse(response, err.message); + }); + } else { + this.sendStringErrorResponse(response, "Unknown thread"); + } } else { - this.sendStringErrorResponse(response, "Unknown thread"); + this.sendStringErrorResponse(response, "No debug info loaded"); } - } else { - this.sendStringErrorResponse(response, "No debug info loaded"); - } + resolve(); + }); } protected scopesRequest(response: DebugProtocol.ScopesResponse, args: DebugProtocol.ScopesArguments): void { diff --git a/src/test/breakpointManager.test.ts b/src/test/breakpointManager.test.ts index 7bc52aa2..63842ed8 100644 --- a/src/test/breakpointManager.test.ts +++ b/src/test/breakpointManager.test.ts @@ -43,7 +43,7 @@ describe('Breakpoint Manager', () => { let offset = 2; context('Source existing', () => { beforeEach(function () { - when(mockedDebugInfo.getAddressSeg(SOURCE_PATH, sourceLine)).thenReturn([segId, offset]); + when(mockedDebugInfo.getAddressSeg(SOURCE_PATH, sourceLine)).thenResolve([segId, offset]); }); context('has debug info', () => { beforeEach(function () { @@ -154,7 +154,7 @@ describe('Breakpoint Manager', () => { let segId = 1; let offset = 2; bpManager.setDebugInfo(instance(mockedDebugInfo)); - when(mockedDebugInfo.getAddressSeg(SOURCE_PATH, sourceLine)).thenReturn([segId, offset]); + when(mockedDebugInfo.getAddressSeg(SOURCE_PATH, sourceLine)).thenResolve([segId, offset]); when(mockedGdbProxy.setBreakpoint(anything())).thenReject(err); bpManager.addPendingBreakpoint(bp); expect(bpManager.getPendingBreakpoints().length).to.be.equal(1); diff --git a/src/test/debugInfo.test.ts b/src/test/debugInfo.test.ts index 5c4ba026..ee9bf584 100644 --- a/src/test/debugInfo.test.ts +++ b/src/test/debugInfo.test.ts @@ -18,8 +18,8 @@ describe("Debug Info", function () { pathReplacements.set("/Users/papa/developpements/amiga/projects/helloworld", sourceRootPath); let di = new DebugInfo(pathReplacements); await di.loadInfo(Uri.file(programFilename)); - expect(di.getAddressSeg(sourceFilename, 32)).to.be.eql([0, 0]); - expect(di.getAddressSeg(sourceFilename, 33)).to.be.eql([0, 4]); + expect(await di.getAddressSeg(sourceFilename, 32)).to.be.eql([0, 0]); + expect(await di.getAddressSeg(sourceFilename, 33)).to.be.eql([0, 4]); }); it("Should resolve the line number", async function () { const PROJECT_ROOT = Path.join(__dirname, '..', '..'); @@ -29,7 +29,7 @@ describe("Debug Info", function () { pathReplacements.set("/Users/papa/developpements/amiga/projects/helloworld", sourceRootPath); let di = new DebugInfo(pathReplacements); await expect(di.loadInfo(Uri.file(programFilename))).to.be.eventually.equal(true); - expect(di.resolveFileLine(0, 4)).to.be.eql([FileProxy.normalize(sourceRootPath + Path.sep + "gencop.s"), 33, " clr.l d0 ; les registres sont des long - il faut les nettoyer avec un .l"]); + await expect(di.resolveFileLine(0, 4)).to.be.eventually.eql([FileProxy.normalize(sourceRootPath + Path.sep + "gencop.s"), 33, " clr.l d0 ; les registres sont des long - il faut les nettoyer avec un .l"]); }); it("Should return all segments from a file", async function () { const PROJECT_ROOT = Path.join(__dirname, '..', '..'); @@ -40,7 +40,7 @@ describe("Debug Info", function () { pathReplacements.set("/Users/papa/developpements/amiga/projects/helloworld", sourceRootPath); let di = new DebugInfo(pathReplacements); await expect(di.loadInfo(Uri.file(programFilename))).to.be.eventually.equal(true); - expect(di.getAllSegmentIds(sourceFilename)).to.be.eql([0]); + await expect(di.getAllSegmentIds(sourceFilename)).to.be.eventually.eql([0]); }); it("Should raise an error if the file is not found", async function () { let di = new DebugInfo(); @@ -62,7 +62,7 @@ describe("Debug Info", function () { let pathReplacements = new Map(); let di = new DebugInfo(pathReplacements, [sourceRootPath]); await expect(di.loadInfo(Uri.file(programFilename))).to.be.eventually.equal(true); - expect(di.resolveFileLine(0, 1024)).to.be.eql([FileProxy.normalize(sourceRootPath + Path.sep + "hello.c"), 9, " printf(\"10 * %d = %d\\n\", i, mul_by_ten(i));"]); + await expect(di.resolveFileLine(0, 1024)).to.be.eventually.eql([FileProxy.normalize(sourceRootPath + Path.sep + "hello.c"), 9, " printf(\"10 * %d = %d\\n\", i, mul_by_ten(i));"]); }); it("Should find the segment address for a C file", async function () { const PROJECT_ROOT = Path.join(__dirname, '..', '..'); @@ -72,9 +72,9 @@ describe("Debug Info", function () { let pathReplacements = new Map(); let di = new DebugInfo(pathReplacements, [sourceRootPath]); await di.loadInfo(Uri.file(programFilename)); - expect(di.getAddressSeg(sourceFilename, 9)).to.be.eql([0, 986]); + await expect(di.getAddressSeg(sourceFilename, 9)).to.be.eventually.eql([0, 986]); // Without path - expect(di.getAddressSeg('hello.c', 9)).to.be.eql([0, 986]); + await expect(di.getAddressSeg('hello.c', 9)).to.be.eventually.eql([0, 986]); }); }); \ No newline at end of file