Skip to content

Commit

Permalink
Fix race in executeLine and waitForPrompt
Browse files Browse the repository at this point in the history
  • Loading branch information
kraenhansen committed Oct 2, 2024
1 parent a281b85 commit daa25b0
Showing 1 changed file with 26 additions and 35 deletions.
61 changes: 26 additions & 35 deletions packages/e2e-tests/test/test-shell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,39 +183,19 @@ export class TestShell {
return this._process;
}

async waitForPrompt(start = 0): Promise<void> {
await eventually(() => {
const output = this._output.slice(start);
/**
* Wait for the last line of the output to become a prompt and resolve with it
*/
async waitForPrompt(start = 0): Promise<string> {
return this.eventually(() => {
const output = this._output.slice(start).trim();
const lines = output.split('\n');
const found = !!lines
.filter((l) => PROMPT_PATTERN.exec(l)) // a line that is the prompt must at least match the pattern
.find((l) => {
// in some situations the prompt occurs multiple times in the line (but only in tests!)
const prompts = l
.trim()
.replace(/>$/g, '')
.split('>')
.map((m) => m.trim());
// if there are multiple prompt parts they must all equal
if (prompts.length > 1) {
for (const p of prompts) {
if (p !== prompts[0]) {
return false;
}
}
}
return true;
});
if (!found) {
throw new assert.AssertionError({
message: 'expected prompt',
expected: PROMPT_PATTERN.toString(),
actual:
this._output.slice(0, start) +
'[prompt search starts here]' +
output,
});
}
const lastLine = lines[lines.length - 1];
assert(
PROMPT_PATTERN.test(lastLine),
`Expected a prompt (last line was "${lastLine}")`
);
return lastLine;
});
}

Expand Down Expand Up @@ -311,10 +291,21 @@ export class TestShell {
}

async executeLine(line: string): Promise<string> {
const previousOutputLength = this._output.length;
// Waiting for a prompt to appear since the last execution
await this.waitForPrompt(this._previousOutputLength);
// Keeping an the length of the output to return only output as result of the input
const outputLengthBefore = this._output.length;
this.writeInputLine(line);
await this.waitForPrompt(previousOutputLength);
return this._output.slice(previousOutputLength);
// Wait for the execution and a new prompt to appear
const prompt = await this.waitForPrompt(outputLengthBefore);
// Store the output (excluding the following prompt)
const output = this._output.slice(
outputLengthBefore,
this._output.length - prompt.length - 1
);
// Storing the output for future executions
this._previousOutputLength = outputLengthBefore + output.length;
return output;
}

async executeLineWithJSONResult(line: string): Promise<any> {
Expand Down

0 comments on commit daa25b0

Please sign in to comment.