mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-04-16 06:18:42 +02:00
This reverts commit 92b8b58588.
Accidental merge on my part - the code is in decent shape, but isn't meant to go in for 3.0.
This commit is contained in:
@@ -14,7 +14,6 @@ import { WorkerScript } from "../../../src/Netscript/WorkerScript";
|
||||
import { NetscriptFunctions } from "../../../src/NetscriptFunctions";
|
||||
import type { PositiveInteger } from "../../../src/types";
|
||||
import { ErrorState } from "../../../src/ErrorHandling/ErrorState";
|
||||
import { getTerminalStdIO } from "../../../src/Terminal/StdIO/RedirectIO";
|
||||
|
||||
fixDoImportIssue();
|
||||
|
||||
@@ -37,7 +36,7 @@ async function expectErrorWhenRunningScript(
|
||||
for (const script of scripts) {
|
||||
Player.getHomeComputer().writeToScriptFile(script.filePath, script.code);
|
||||
}
|
||||
runScript(testScriptPath, [], Player.getHomeComputer(), getTerminalStdIO());
|
||||
runScript(testScriptPath, [], Player.getHomeComputer());
|
||||
const workerScript = workerScripts.get(1);
|
||||
if (!workerScript) {
|
||||
throw new Error(`Invalid worker script`);
|
||||
@@ -146,7 +145,7 @@ describe("runScript and runScriptFromScript", () => {
|
||||
ns.print(server.hostname);
|
||||
}`,
|
||||
);
|
||||
runScript(testScriptPath, [], Player.getHomeComputer(), getTerminalStdIO());
|
||||
runScript(testScriptPath, [], Player.getHomeComputer());
|
||||
const workerScript = workerScripts.get(1);
|
||||
if (!workerScript) {
|
||||
throw new Error(`Invalid worker script`);
|
||||
@@ -161,7 +160,7 @@ describe("runScript and runScriptFromScript", () => {
|
||||
});
|
||||
describe("Failure", () => {
|
||||
test("Script does not exist", () => {
|
||||
runScript(testScriptPath, [], Player.getHomeComputer(), getTerminalStdIO());
|
||||
runScript(testScriptPath, [], Player.getHomeComputer());
|
||||
expect((Terminal.outputHistory[1] as { text: string }).text).toContain(
|
||||
`Script ${testScriptPath} does not exist on home`,
|
||||
);
|
||||
@@ -173,7 +172,7 @@ describe("runScript and runScriptFromScript", () => {
|
||||
`export async function main(ns) {
|
||||
}`,
|
||||
);
|
||||
runScript(testScriptPath, [], server, getTerminalStdIO());
|
||||
runScript(testScriptPath, [], server);
|
||||
expect((Terminal.outputHistory[1] as { text: string }).text).toContain(
|
||||
`You do not have root access on ${server.hostname}`,
|
||||
);
|
||||
@@ -185,7 +184,7 @@ describe("runScript and runScriptFromScript", () => {
|
||||
{
|
||||
}`,
|
||||
);
|
||||
runScript(testScriptPath, [], Player.getHomeComputer(), getTerminalStdIO());
|
||||
runScript(testScriptPath, [], Player.getHomeComputer());
|
||||
expect((Terminal.outputHistory[1] as { text: string }).text).toContain(
|
||||
`Cannot calculate RAM usage of ${testScriptPath}`,
|
||||
);
|
||||
@@ -197,7 +196,7 @@ describe("runScript and runScriptFromScript", () => {
|
||||
ns.ramOverride(1024);
|
||||
}`,
|
||||
);
|
||||
runScript(testScriptPath, [], Player.getHomeComputer(), getTerminalStdIO());
|
||||
runScript(testScriptPath, [], Player.getHomeComputer());
|
||||
expect((Terminal.outputHistory[1] as { text: string }).text).toContain("This script requires 1.02TB of RAM");
|
||||
});
|
||||
test("Thrown error in main function", async () => {
|
||||
|
||||
@@ -59,12 +59,6 @@ function loadStandardServers() {
|
||||
"ramUsage": 1.6,
|
||||
"server": "home",
|
||||
"scriptKey": "script.js*[]",
|
||||
"stdin": null,
|
||||
"tailStdOut": null,
|
||||
"terminalStdOut": {
|
||||
"stdin": null,
|
||||
"stdout": null
|
||||
},
|
||||
"temporary": true,
|
||||
"dependencies": [
|
||||
{
|
||||
@@ -91,12 +85,6 @@ function loadStandardServers() {
|
||||
"ramUsage": 1.6,
|
||||
"server": "home",
|
||||
"scriptKey": "script.js*[]",
|
||||
"stdin": null,
|
||||
"tailStdOut": null,
|
||||
"terminalStdOut": {
|
||||
"stdin": null,
|
||||
"stdout": null
|
||||
},
|
||||
"title": "Awesome Script",
|
||||
"dependencies": [
|
||||
{
|
||||
|
||||
@@ -1,494 +0,0 @@
|
||||
import { Terminal } from "../../../src/Terminal";
|
||||
import { GetServer, prestigeAllServers } from "../../../src/Server/AllServers";
|
||||
import { Player } from "@player";
|
||||
import { type TextFilePath } from "../../../src/Paths/TextFilePath";
|
||||
import { type ScriptFilePath } from "../../../src/Paths/ScriptFilePath";
|
||||
import { LiteratureName, MessageFilename } from "@enums";
|
||||
import { fixDoImportIssue, initGameEnvironment } from "../Utilities";
|
||||
import { runScript } from "../../../src/Terminal/commands/runScript";
|
||||
import { getTerminalStdIO } from "../../../src/Terminal/StdIO/RedirectIO";
|
||||
|
||||
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
|
||||
fixDoImportIssue();
|
||||
initGameEnvironment();
|
||||
|
||||
describe("Terminal Pipes", () => {
|
||||
beforeEach(() => {
|
||||
prestigeAllServers();
|
||||
Player.init();
|
||||
Terminal.outputHistory = [];
|
||||
GetServer(Player.currentServer)?.textFiles.clear();
|
||||
GetServer(Player.currentServer)?.scripts.clear();
|
||||
});
|
||||
|
||||
describe("piping to files", () => {
|
||||
it("should handle piping to a file", async () => {
|
||||
const fileName = "output.txt";
|
||||
const command = `echo 'Hello World' > ${fileName}`;
|
||||
await Terminal.executeCommands(command);
|
||||
|
||||
const server = GetServer(Player.currentServer);
|
||||
const fileContent = server?.textFiles?.get(fileName as TextFilePath)?.text;
|
||||
|
||||
expect(JSON.stringify(Terminal.outputHistory)).toBe("[]");
|
||||
expect(fileContent).toBe("Hello World");
|
||||
});
|
||||
|
||||
it("should reject invalid text filenames", async () => {
|
||||
const invalidFileName = 'a".txt';
|
||||
const command = `echo 'Hello World' > ${invalidFileName}`;
|
||||
await Terminal.executeCommands(command);
|
||||
|
||||
const mostRecentOutput = Terminal.outputHistory[Terminal.outputHistory.length - 1];
|
||||
expect(mostRecentOutput?.text).toBe(`Invalid file path provided: ${invalidFileName}`);
|
||||
});
|
||||
|
||||
it("should reject invalid script filenames", async () => {
|
||||
const invalidFileName = 'a".js';
|
||||
const command = `echo 'Hello World' > ${invalidFileName}`;
|
||||
await Terminal.executeCommands(command);
|
||||
|
||||
const mostRecentOutput = Terminal.outputHistory[Terminal.outputHistory.length - 1];
|
||||
expect(mostRecentOutput?.text).toBe(`Invalid file path provided: ${invalidFileName}`);
|
||||
});
|
||||
|
||||
it("should append to a file when using >> operator", async () => {
|
||||
const fileName = "output.txt";
|
||||
const commandString = `echo first line >> ${fileName}; echo second line >> ${fileName}`;
|
||||
|
||||
await Terminal.executeCommands(commandString);
|
||||
|
||||
const server = GetServer(Player.currentServer);
|
||||
const fileContent = server?.textFiles?.get(fileName as TextFilePath)?.text;
|
||||
|
||||
expect(JSON.stringify(Terminal.outputHistory)).toBe("[]");
|
||||
expect(fileContent).toBe("first line\nsecond line");
|
||||
});
|
||||
|
||||
it("should overwrite a file when using > operator", async () => {
|
||||
const fileName = "output.txt";
|
||||
const commandString = `echo first line > ${fileName}; echo second line > ${fileName}`;
|
||||
|
||||
await Terminal.executeCommands(commandString);
|
||||
|
||||
const server = GetServer(Player.currentServer);
|
||||
const fileContent = server?.textFiles?.get(fileName as TextFilePath)?.text;
|
||||
expect(fileContent).toBe("second line");
|
||||
});
|
||||
|
||||
it("should only overwrite file contents once per > pipe", async () => {
|
||||
// Add file to server with content
|
||||
const outputFileName = "scriptOutput9.txt" as TextFilePath;
|
||||
const startingData = "startingData";
|
||||
const commandString = `echo ${startingData} > ${outputFileName}`;
|
||||
await Terminal.executeCommands(commandString);
|
||||
|
||||
const scriptName = "testScript.js" as ScriptFilePath;
|
||||
const scriptContent = `export async function main(ns) { ns.tprint(ns.args); await ns.sleep(100); ns.tprint(ns.args); }`;
|
||||
|
||||
// Add script to server
|
||||
await Terminal.executeCommands(`echo '${scriptContent}' > ${scriptName}`);
|
||||
|
||||
// Pass arguments to script via pipe
|
||||
const command = `run ${scriptName} test1 > ${outputFileName}`;
|
||||
await Terminal.executeCommands(command);
|
||||
await sleep(200);
|
||||
|
||||
const server = GetServer(Player.currentServer);
|
||||
const fileContent = server?.textFiles?.get(outputFileName)?.text;
|
||||
|
||||
expect(Terminal.outputHistory.length).toBe(1);
|
||||
expect(fileContent).toContain(`${scriptName}: ["test1"]\n${scriptName}: ["test1"]`);
|
||||
expect(fileContent).not.toContain(startingData);
|
||||
});
|
||||
|
||||
it("should only overwrite file contents once per > pipe when arguments are piped in", async () => {
|
||||
// Add file to server with content
|
||||
const outputFileName = "scriptOutput8.txt" as TextFilePath;
|
||||
const startingData = "startingData";
|
||||
const commandString = `echo ${startingData} > ${outputFileName}`;
|
||||
await Terminal.executeCommands(commandString);
|
||||
|
||||
const scriptName = "testScript.js" as ScriptFilePath;
|
||||
const scriptContent = `export async function main(ns) { ns.tprint(ns.getStdin().read()); await ns.sleep(100); ns.tprint(ns.getStdin().read()); }`;
|
||||
|
||||
// Add script to server
|
||||
await Terminal.executeCommands(`echo '${scriptContent}' > ${scriptName}`);
|
||||
|
||||
// Pass arguments to script via pipe
|
||||
const command = `echo test1 test2 | ${scriptName} > ${outputFileName}`;
|
||||
await Terminal.executeCommands(command);
|
||||
await sleep(200);
|
||||
|
||||
const server = GetServer(Player.currentServer);
|
||||
const fileContent = server?.textFiles?.get(outputFileName)?.text;
|
||||
|
||||
expect(Terminal.outputHistory.length).toBe(1);
|
||||
expect(fileContent).toContain(`${scriptName}: test1 test2\n${scriptName}: null`);
|
||||
expect(fileContent).not.toContain(startingData);
|
||||
});
|
||||
|
||||
it("should not permit overwriting a script file with content", async () => {
|
||||
const fileName = "output.js";
|
||||
const commandString = `echo 'Hello World' > ${fileName}; echo 'Malicious Content' > ${fileName}`;
|
||||
|
||||
await Terminal.executeCommands(commandString);
|
||||
|
||||
const server = GetServer(Player.currentServer);
|
||||
const fileContent = server?.scripts?.get(fileName as ScriptFilePath)?.content;
|
||||
|
||||
expect(fileContent).toContain("Hello World");
|
||||
});
|
||||
});
|
||||
|
||||
describe("piping multiple inputs", () => {
|
||||
it("should handle multiple commands with distinct pipes", async () => {
|
||||
const fileName1 = "output.txt";
|
||||
const fileName2 = "output2.txt";
|
||||
const commandString = `echo test > ${fileName1}; echo test2 > ${fileName2}`;
|
||||
await Terminal.executeCommands(commandString);
|
||||
|
||||
expect(JSON.stringify(Terminal.outputHistory)).toBe("[]");
|
||||
|
||||
const server = GetServer(Player.currentServer);
|
||||
const fileContent1 = server?.textFiles?.get(fileName1 as TextFilePath)?.text;
|
||||
expect(fileContent1).toBe("test");
|
||||
|
||||
const fileContent2 = server?.textFiles?.get(fileName2 as TextFilePath)?.text;
|
||||
expect(fileContent2).toBe("test2");
|
||||
});
|
||||
|
||||
it("passes all piped inputs to the output command", async () => {
|
||||
await Terminal.executeCommands("echo 1337 > file1.txt");
|
||||
const command = "cat file1.txt > file2.txt";
|
||||
await Terminal.executeCommands(command);
|
||||
await sleep(100);
|
||||
|
||||
const server = GetServer(Player.currentServer);
|
||||
const fileContent = server?.textFiles?.get("file2.txt" as TextFilePath)?.text;
|
||||
expect(fileContent).toBe("1337");
|
||||
});
|
||||
});
|
||||
|
||||
describe("cat and echo with pipes", () => {
|
||||
it("should pipe cat file contents to specified output", async () => {
|
||||
const fileName = "test4.txt";
|
||||
const fileContent = "This is a test file.";
|
||||
await Terminal.executeCommands(`echo '${fileContent}' > ${fileName}`);
|
||||
await Terminal.executeCommands(`cat '${fileName}' | cat`);
|
||||
|
||||
const server = GetServer(Player.currentServer);
|
||||
const newFileContent = server?.textFiles?.get(fileName as TextFilePath)?.text;
|
||||
expect(newFileContent).toBe(fileContent);
|
||||
|
||||
const lastOutput = Terminal.outputHistory[Terminal.outputHistory.length - 1];
|
||||
expect(lastOutput.text).toContain(fileContent);
|
||||
});
|
||||
|
||||
it("should pipe cat .lit file contents to specified output", async () => {
|
||||
const fileName = "test.txt";
|
||||
const server = GetServer(Player.currentServer);
|
||||
server?.messages.push(LiteratureName.HackersStartingHandbook);
|
||||
|
||||
await Terminal.executeCommands(`cat ${LiteratureName.HackersStartingHandbook} > ${fileName}`);
|
||||
await Terminal.executeCommands(`cat ${fileName} | cat `);
|
||||
|
||||
const newFileContent = server?.textFiles?.get(fileName as TextFilePath)?.text;
|
||||
expect(newFileContent).toContain("hacking is the most profitable way to earn money and progress");
|
||||
|
||||
const lastOutput = Terminal.outputHistory[Terminal.outputHistory.length - 1];
|
||||
expect(lastOutput.text).toContain("hacking is the most profitable way to earn money and progress");
|
||||
});
|
||||
|
||||
it("should pipe cat message file contents to specified output", async () => {
|
||||
const fileName = "test3.txt";
|
||||
const server = GetServer(Player.currentServer);
|
||||
server?.messages.push(MessageFilename.TruthGazer);
|
||||
|
||||
await Terminal.executeCommands(`cat ${MessageFilename.TruthGazer} > ${fileName}`);
|
||||
await Terminal.executeCommands(`cat ${fileName} | cat `);
|
||||
|
||||
const newFileContent = server?.textFiles?.get(fileName as TextFilePath)?.text;
|
||||
expect(newFileContent).toContain("__ESCAP3__");
|
||||
|
||||
const lastOutput = Terminal.outputHistory[Terminal.outputHistory.length - 1];
|
||||
expect(lastOutput.text).toContain("__ESCAP3__");
|
||||
});
|
||||
});
|
||||
|
||||
describe("piping to and from scripts", () => {
|
||||
it("should handle piping to a script file, and passing arguments into a script to run", async () => {
|
||||
const scriptName = "testScript2.js" as ScriptFilePath;
|
||||
const scriptContent = `export function main(ns) { ns.tprint('Input received: ', ns.getStdin().peek()); }`;
|
||||
|
||||
// Add script to server
|
||||
await Terminal.executeCommands(`echo "${scriptContent}" > ${scriptName}`);
|
||||
|
||||
const content = GetServer(Player.currentServer)?.scripts.get(scriptName)?.content;
|
||||
expect(content).toBe(scriptContent);
|
||||
|
||||
// Pass arguments to script via pipe
|
||||
const command = `echo 'data' | run ${scriptName}`;
|
||||
await Terminal.executeCommands(command);
|
||||
await sleep(100);
|
||||
|
||||
expect(Terminal.outputHistory[0]?.text).toContain(`Running script with 1 thread`);
|
||||
expect(Terminal.outputHistory[1]?.text).toEqual(`${scriptName}: Input received: data`);
|
||||
});
|
||||
|
||||
it("should piping content out of a script", async () => {
|
||||
const outputFileName = "scriptOutput4.txt" as TextFilePath;
|
||||
const scriptName = "testScript.js" as ScriptFilePath;
|
||||
const scriptContent = `export async function main(ns) { ns.tprint('Input received: ', ns.getStdin().peek()); }`;
|
||||
|
||||
// Add script to server
|
||||
await Terminal.executeCommands(`echo "${scriptContent}" > ${scriptName}`);
|
||||
|
||||
const content = GetServer(Player.currentServer)?.scripts.get(scriptName)?.content;
|
||||
expect(content).toBe(scriptContent);
|
||||
|
||||
// Pass arguments to script via pipe
|
||||
const command = `echo 'data' | ${scriptName} > ${outputFileName}`;
|
||||
await Terminal.executeCommands(command);
|
||||
await sleep(200);
|
||||
|
||||
const server = GetServer(Player.currentServer);
|
||||
const fileContent = server?.textFiles?.get(outputFileName)?.text;
|
||||
|
||||
expect(Terminal.outputHistory.length).toBe(1);
|
||||
expect(fileContent).toContain(`Input received: data`);
|
||||
});
|
||||
|
||||
it("should pipe content out of a script when the run command is used", async () => {
|
||||
const outputFileName = "scriptOutput3.txt" as TextFilePath;
|
||||
const scriptName = "testScript.js" as ScriptFilePath;
|
||||
const scriptContent = `export function main(ns) { ns.tprint('Args received: ', ns.args); }`;
|
||||
|
||||
// Add script to server
|
||||
await Terminal.executeCommands(`echo "${scriptContent}" > ${scriptName}`);
|
||||
|
||||
const content = GetServer(Player.currentServer)?.scripts.get(scriptName)?.content;
|
||||
expect(content).toBe(scriptContent);
|
||||
|
||||
// Pass arguments to script via pipe
|
||||
const command = `run ${scriptName} test1 arguments > ${outputFileName}`;
|
||||
await Terminal.executeCommands(command);
|
||||
await sleep(200);
|
||||
|
||||
const server = GetServer(Player.currentServer);
|
||||
const fileContent = server?.textFiles?.get(outputFileName)?.text;
|
||||
|
||||
expect(Terminal.outputHistory.length).toBe(1);
|
||||
expect(fileContent).toContain(`Args received: ["test1","arguments"]`);
|
||||
});
|
||||
|
||||
it("should correctly pipe each script's async output to its specified location", async () => {
|
||||
// Add file to server with content
|
||||
const outputFileName = "scriptOutput.txt" as TextFilePath;
|
||||
const outputFileName2 = "scriptOutput2.txt" as TextFilePath;
|
||||
|
||||
const scriptName = "testScript.js" as ScriptFilePath;
|
||||
const scriptContent = `export async function main(ns) { ns.tprint(ns.args); await ns.sleep(100); ns.tprint(ns.args); }`;
|
||||
|
||||
// Add script to server
|
||||
await Terminal.executeCommands(`echo '${scriptContent}' > ${scriptName}`);
|
||||
|
||||
// Pass arguments to script via pipe
|
||||
const command = `run ${scriptName} test1 test2 > ${outputFileName}; run ${scriptName} test3 test4 > ${outputFileName2}`;
|
||||
await Terminal.executeCommands(command);
|
||||
await sleep(300);
|
||||
|
||||
const server = GetServer(Player.currentServer);
|
||||
const fileContent = server?.textFiles?.get(outputFileName)?.text;
|
||||
const fileContent2 = server?.textFiles?.get(outputFileName2)?.text;
|
||||
|
||||
expect(Terminal.outputHistory.length).toBe(2);
|
||||
expect(fileContent).toContain(`${scriptName}: ["test1","test2"]\n${scriptName}: ["test1","test2"]`);
|
||||
expect(fileContent2).toContain(`${scriptName}: ["test3","test4"]\n${scriptName}: ["test3","test4"]`);
|
||||
});
|
||||
|
||||
it("should correctly pipe a script's async output to a specified destination script", async () => {
|
||||
// Add file to server with content
|
||||
const outputFileName = "scriptOutput.txt" as TextFilePath;
|
||||
|
||||
const scriptName = "testScript.js" as ScriptFilePath;
|
||||
const scriptName2 = "testScript2.js" as ScriptFilePath;
|
||||
const scriptContent = `export async function main(ns) { ns.tprint(ns.getStdin().peek()); await ns.sleep(80); ns.tprint(ns.getStdin().peek()); }`;
|
||||
const scriptContent2 = `export async function main(ns) { ns.tprint(ns.getStdin().read()); await ns.sleep(200); ns.tprint(ns.getStdin().read()); ns.tprint(ns.getStdin().read()); }`;
|
||||
|
||||
// Add script to server
|
||||
await Terminal.executeCommands(
|
||||
`echo '${scriptContent}' > ${scriptName}; echo '${scriptContent2}' > ${scriptName2}`,
|
||||
);
|
||||
|
||||
// Pass arguments to script via pipe
|
||||
const command = `echo 1 | ${scriptName} | ${scriptName2} > ${outputFileName}`;
|
||||
await Terminal.executeCommands(command);
|
||||
await sleep(300);
|
||||
|
||||
const server = GetServer(Player.currentServer);
|
||||
const fileContent = server?.textFiles?.get(outputFileName)?.text;
|
||||
|
||||
expect(Terminal.outputHistory.length).toBe(2);
|
||||
expect(fileContent).toContain(`${scriptName2}: ${scriptName}: 1\n${scriptName2}: NULL PORT DATA`);
|
||||
});
|
||||
|
||||
it("should correctly pipe each script's async output to its specified destination script", async () => {
|
||||
// Add file to server with content
|
||||
const outputFileName = "scriptOutput.txt" as TextFilePath;
|
||||
const outputFileName2 = "scriptOutput2.txt" as TextFilePath;
|
||||
|
||||
const scriptName = "testScript.js" as ScriptFilePath;
|
||||
const scriptName2 = "testScript2.js" as ScriptFilePath;
|
||||
const scriptName3 = "testScript3.js" as ScriptFilePath;
|
||||
const scriptName4 = "testScript4.js" as ScriptFilePath;
|
||||
const scriptContent = `export async function main(ns) { ns.tprint(ns.getStdin().peek()); await ns.sleep(80); ns.tprint(ns.getStdin().peek()); }`;
|
||||
const scriptContent2 = `export async function main(ns) { ns.tprint(ns.getStdin().read()); await ns.sleep(200); ns.tprint(ns.getStdin().read()); ns.tprint(ns.getStdin().read()); }`;
|
||||
|
||||
// Add script to server
|
||||
await Terminal.executeCommands(
|
||||
`echo '${scriptContent}' > ${scriptName}; echo '${scriptContent2}' > ${scriptName2}`,
|
||||
);
|
||||
await Terminal.executeCommands(`cat ${scriptName} > ${scriptName3}; cat ${scriptName2} > ${scriptName4};`);
|
||||
|
||||
// Pass arguments to script via pipe
|
||||
const command = `echo 1 | ${scriptName} | ${scriptName2} > ${outputFileName}; echo 2 | ${scriptName3} | ${scriptName4} > ${outputFileName2}`;
|
||||
await Terminal.executeCommands(command);
|
||||
await sleep(300);
|
||||
|
||||
const server = GetServer(Player.currentServer);
|
||||
const fileContent = server?.textFiles?.get(outputFileName)?.text;
|
||||
const fileContent2 = server?.textFiles?.get(outputFileName2)?.text;
|
||||
|
||||
expect(Terminal.outputHistory.length).toBe(4);
|
||||
expect(fileContent).toContain(`${scriptName2}: ${scriptName}: 1\n${scriptName2}: NULL PORT DATA`);
|
||||
expect(fileContent2).toContain(`${scriptName4}: ${scriptName3}: 2\n${scriptName4}: NULL PORT DATA`);
|
||||
});
|
||||
});
|
||||
|
||||
describe("input redirection", () => {
|
||||
it("should use file contents as input stream if input redirection < is used", async () => {
|
||||
const fileContent = "File input data";
|
||||
const fileName = "inputFile.txt";
|
||||
await Terminal.executeCommands(`echo '${fileContent}' > ${fileName}`);
|
||||
|
||||
const fileContentOnServer = GetServer(Player.currentServer)?.textFiles?.get(fileName as TextFilePath)?.text;
|
||||
expect(fileContentOnServer).toBe(fileContent);
|
||||
|
||||
const commandString = `cat < ${fileName} | cat `;
|
||||
await Terminal.executeCommands(commandString);
|
||||
|
||||
const lastOutput = Terminal.outputHistory[Terminal.outputHistory.length - 1];
|
||||
expect(lastOutput?.text).toBe(fileContent);
|
||||
});
|
||||
|
||||
it("should return an error if input redirection file does not exist", async () => {
|
||||
const fileName = "nonExistentFile.txt";
|
||||
const commandString = `cat < ${fileName}`;
|
||||
await Terminal.executeCommands(commandString);
|
||||
|
||||
const lastOutput = Terminal.outputHistory[Terminal.outputHistory.length - 2];
|
||||
expect(lastOutput?.text).toBe(`No file at path ${fileName}`);
|
||||
});
|
||||
|
||||
it("should return an error if the input redirection is not the first pipe in the chain", async () => {
|
||||
await Terminal.executeCommands(`echo 'Some data' | cat < inputFile.txt`);
|
||||
|
||||
const error = Terminal.outputHistory[0];
|
||||
expect(error?.text).toBe(
|
||||
`Error in pipe command: Invalid pipe command. Only the first command in a pipe chain can have input redirection '<'.`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it("should handle piping content to cat", async () => {
|
||||
const testContent = "This is a test.";
|
||||
const commandString = `echo "${testContent}" | cat`;
|
||||
await Terminal.executeCommands(commandString);
|
||||
await sleep(50);
|
||||
|
||||
expect(Terminal.outputHistory.length).toBe(1);
|
||||
expect(Terminal.outputHistory[0].text).toContain(testContent);
|
||||
});
|
||||
|
||||
it("should replace $! with the PID of the last script run", async () => {
|
||||
const scriptName = "testScript.js" as ScriptFilePath;
|
||||
const scriptContent = `export async function main(ns) { ns.print('Script is running'); await ns.sleep(100); }`;
|
||||
const server = GetServer(Player.currentServer);
|
||||
|
||||
// Add script to server
|
||||
await Terminal.executeCommands(`echo "${scriptContent}" > ${scriptName}`);
|
||||
await sleep(50);
|
||||
|
||||
// Run the script to set PipeState.pidOfLastScriptRun
|
||||
const runningScript = runScript(scriptName, [], server, getTerminalStdIO());
|
||||
const expectedPid = runningScript?.pid;
|
||||
await sleep(200);
|
||||
|
||||
const command = `echo $! > pidOutput.txt`;
|
||||
await Terminal.executeCommands(command);
|
||||
await sleep(50);
|
||||
const fileContent = server?.textFiles?.get("pidOutput.txt" as TextFilePath)?.text;
|
||||
|
||||
expect(Number(fileContent)).toBe(expectedPid);
|
||||
});
|
||||
|
||||
it("should replace $! with -1 if the prior command was not a run", async () => {
|
||||
const scriptName = "testScript.js" as ScriptFilePath;
|
||||
const scriptContent = `export async function main(ns) { ns.print("Script is running"); await ns.sleep(100); }`;
|
||||
const server = GetServer(Player.currentServer);
|
||||
|
||||
// Add script to server
|
||||
await Terminal.executeCommands(`echo '${scriptContent}' > ${scriptName}`);
|
||||
await sleep(50);
|
||||
|
||||
// Run the script to set PipeState.pidOfLastScriptRun
|
||||
await Terminal.executeCommands(`run ${scriptName}`);
|
||||
await sleep(200);
|
||||
|
||||
await Terminal.executeCommands(`echo "Not a run command"`);
|
||||
|
||||
const command = `echo $! > pidOutput.txt`;
|
||||
await Terminal.executeCommands(command);
|
||||
const fileContent = server?.textFiles?.get("pidOutput.txt" as TextFilePath)?.text;
|
||||
|
||||
expect(Number(fileContent)).toBe(-1);
|
||||
});
|
||||
|
||||
it("should pipe the tail output of scripts to stdout when specified with $!", async () => {
|
||||
const scriptContent = `export async function main(ns) {ns.print('foo');await ns.sleep(50);ns.print('test2');}`;
|
||||
const scriptName = "testScript.jsx" as ScriptFilePath;
|
||||
const tailOutputFileName = "tailOutput.txt" as TextFilePath;
|
||||
|
||||
// Add script to server
|
||||
await Terminal.executeCommands(`echo "${scriptContent}" > ${scriptName}`);
|
||||
|
||||
const fileContent = GetServer(Player.currentServer)?.scripts?.get(scriptName)?.content;
|
||||
expect(fileContent).toBe(scriptContent);
|
||||
|
||||
await Terminal.executeCommands(`run ${scriptName}; tail $! > ${tailOutputFileName}`);
|
||||
await sleep(200);
|
||||
|
||||
const outputFileContent = GetServer(Player.currentServer)?.textFiles?.get(tailOutputFileName)?.text;
|
||||
expect(outputFileContent).toContain("foo\nsleep: Sleeping for 0.050 seconds.\ntest2");
|
||||
});
|
||||
|
||||
it("should pipe the tail output of scripts to stdout", async () => {
|
||||
const scriptContent = `export async function main(ns) {ns.print('foo');await ns.sleep(50);ns.print('test2');}`;
|
||||
const scriptName = "testScript.jsx" as ScriptFilePath;
|
||||
const tailOutputFileName = "tailOutput.txt" as TextFilePath;
|
||||
|
||||
// Add script to server
|
||||
await Terminal.executeCommands(`echo "${scriptContent}" > ${scriptName}`);
|
||||
|
||||
const fileContent = GetServer(Player.currentServer)?.scripts?.get(scriptName)?.content;
|
||||
expect(fileContent).toBe(scriptContent);
|
||||
|
||||
await Terminal.executeCommands(`run ${scriptName}; tail ${scriptName} > ${tailOutputFileName}`);
|
||||
await sleep(200);
|
||||
|
||||
const outputFileContent = GetServer(Player.currentServer)?.textFiles?.get(tailOutputFileName)?.text;
|
||||
expect(outputFileContent).toContain("foo\nsleep: Sleeping for 0.050 seconds.\ntest2");
|
||||
});
|
||||
});
|
||||
@@ -1,207 +0,0 @@
|
||||
import { IOStream } from "../../../src/Terminal/StdIO/IOStream";
|
||||
import {
|
||||
findCommandsSplitByRedirects,
|
||||
getTerminalStdIO,
|
||||
handleCommand,
|
||||
parseRedirectedCommands,
|
||||
} from "../../../src/Terminal/StdIO/RedirectIO";
|
||||
import { Terminal } from "../../../src/Terminal";
|
||||
import { fixDoImportIssue, initGameEnvironment } from "../Utilities";
|
||||
import { GetServer, prestigeAllServers } from "../../../src/Server/AllServers";
|
||||
import { Player } from "@player";
|
||||
import { StdIO } from "../../../src/Terminal/StdIO/StdIO";
|
||||
import { TextFilePath } from "../../../src/Paths/TextFilePath";
|
||||
import { ScriptFilePath } from "../../../src/Paths/ScriptFilePath";
|
||||
import { Output } from "../../../src/Terminal/OutputTypes";
|
||||
import { ANSI_ESCAPE } from "../../../src/ui/React/ANSIITypography";
|
||||
|
||||
export const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
|
||||
fixDoImportIssue();
|
||||
initGameEnvironment();
|
||||
|
||||
describe("RedirectIOTests", () => {
|
||||
beforeEach(() => {
|
||||
prestigeAllServers();
|
||||
Player.init();
|
||||
Terminal.outputHistory = [];
|
||||
GetServer(Player.currentServer)?.textFiles.clear();
|
||||
GetServer(Player.currentServer)?.scripts.clear();
|
||||
});
|
||||
|
||||
it("should redirect output to the terminal correctly from a terminal StdIO", async () => {
|
||||
const data = "Hello, Terminal!";
|
||||
const terminalIO = getTerminalStdIO(null);
|
||||
terminalIO.write(data);
|
||||
await sleep(50);
|
||||
|
||||
expect(Terminal.outputHistory.length).toBe(1);
|
||||
expect(Terminal.outputHistory[0].text).toContain(data);
|
||||
});
|
||||
|
||||
it("findCommandsSplitByRedirects should split commands by pipes", () => {
|
||||
const commandString = "echo Hello > file.txt >> anotherFile.txt | echo World";
|
||||
const parsedCommands = commandString.split(" ");
|
||||
const result = findCommandsSplitByRedirects(parsedCommands);
|
||||
|
||||
expect(result[0]).toEqual(["echo", "Hello"]);
|
||||
expect(result[1]).toEqual([">", "file.txt"]);
|
||||
expect(result[2]).toEqual([">>", "anotherFile.txt"]);
|
||||
expect(result[3]).toEqual(["|", "echo", "World"]);
|
||||
expect(result.length).toBe(4);
|
||||
});
|
||||
|
||||
describe("handleCommand", () => {
|
||||
it("should handle echo command passing its args to stdout", async () => {
|
||||
const commandString = "echo Hello, World";
|
||||
const stdIO = new StdIO(null);
|
||||
handleCommand(stdIO, commandString.split(" "));
|
||||
await sleep(50);
|
||||
|
||||
expect(stdIO.stdout.empty()).toBe(false);
|
||||
const output = stdIO.stdout.read();
|
||||
expect(output).toBe("Hello, World");
|
||||
});
|
||||
|
||||
it("should handle writing stdin contents to files", async () => {
|
||||
const filename = "output.txt";
|
||||
const commandString = `> ${filename}`;
|
||||
const stdin = new IOStream();
|
||||
const stdIO = new StdIO(stdin);
|
||||
void handleCommand(stdIO, commandString.split(" "));
|
||||
stdin.write("File content line 1");
|
||||
stdin.write("File content line 2");
|
||||
|
||||
await sleep(50);
|
||||
const server = GetServer(Player.currentServer);
|
||||
const file = server?.textFiles.get(filename as TextFilePath);
|
||||
expect(file).toBeDefined();
|
||||
expect(file?.content).toBe("File content line 1\nFile content line 2");
|
||||
});
|
||||
});
|
||||
|
||||
describe("parseRedirectedCommands", () => {
|
||||
it("should append echo output redirected to a file", async () => {
|
||||
const filename = "appendOutput.txt";
|
||||
const commandString = `echo First Line >> ${filename} | echo Second Line >> ${filename}`;
|
||||
|
||||
await parseRedirectedCommands(commandString);
|
||||
|
||||
const server = GetServer(Player.currentServer);
|
||||
const file = server?.textFiles.get(filename as TextFilePath);
|
||||
expect(file).toBeDefined();
|
||||
expect(file?.content).toBe("First Line\nSecond Line");
|
||||
});
|
||||
|
||||
it("should prevent overwriting non-empty script files", async () => {
|
||||
const filename = "scriptOutput.js";
|
||||
const commandString = `echo Hello > ${filename} | echo World > ${filename}`;
|
||||
|
||||
await parseRedirectedCommands(commandString);
|
||||
|
||||
const server = GetServer(Player.currentServer);
|
||||
const file = server?.scripts.get(filename as ScriptFilePath);
|
||||
expect(file).toBeDefined();
|
||||
expect(file?.content).toBe("Hello");
|
||||
});
|
||||
});
|
||||
|
||||
describe("stdout from scripts", () => {
|
||||
it("should redirect tprint output from a running script to a file", async () => {
|
||||
const scriptName = "testScript.js";
|
||||
const filename = "scriptLog.txt";
|
||||
const scriptContent = `export function main(ns) { ns.tprint('Logging to file' ); }`;
|
||||
await Terminal.executeCommands(`echo "${scriptContent}" > ${scriptName}`);
|
||||
|
||||
const currentScripts = GetServer(Player.currentServer)?.scripts;
|
||||
const script = currentScripts?.get(scriptName as ScriptFilePath);
|
||||
expect(script?.content).toBe(scriptContent);
|
||||
|
||||
await Terminal.executeCommands(`run ${scriptName} >> ${filename}`);
|
||||
await sleep(50);
|
||||
|
||||
const server = GetServer(Player.currentServer);
|
||||
const file = server?.textFiles.get(filename as TextFilePath);
|
||||
expect(file?.content).toBe("testScript.js: Logging to file");
|
||||
});
|
||||
});
|
||||
|
||||
describe("stdin to scripts", () => {
|
||||
it("should provide stdin input to a running script", async () => {
|
||||
const scriptName = "inputScript.js";
|
||||
const scriptContent = `export async function main(ns) {
|
||||
const stdIn = await ns.getStdin();
|
||||
if (stdIn?.empty()) {
|
||||
ns.tprint('No input received yet');
|
||||
await stdIn.nextWrite();
|
||||
}
|
||||
const input = stdIn?.read();
|
||||
ns.tprint('Received input: ' + input);
|
||||
}`;
|
||||
await Terminal.executeCommands(`echo "${scriptContent}" > ${scriptName}`);
|
||||
|
||||
const inputData = "Hello from stdin!";
|
||||
await Terminal.executeCommands(`echo "${inputData}" | run ${scriptName}`);
|
||||
await sleep(50);
|
||||
|
||||
console.log(Terminal.outputHistory);
|
||||
const outputLog: Output[] = Terminal.outputHistory.filter(isOutput);
|
||||
const outputText: Output = outputLog.find((entry: Output) => entry.text?.includes("Received input:"));
|
||||
expect(outputText?.text).toEqual(`${scriptName}: Received input: ${inputData}`);
|
||||
});
|
||||
|
||||
it("should provide stdin input from a script to a running script", async () => {
|
||||
const scriptName = "inputScript.js";
|
||||
const scriptContent = `export async function main(ns) {
|
||||
const stdIn = await ns.getStdin();
|
||||
if (stdIn?.empty()) {
|
||||
ns.tprint('No input received yet');
|
||||
await stdIn.nextWrite();
|
||||
}
|
||||
const input = stdIn?.read();
|
||||
ns.tprint('Received input: ' + input);
|
||||
}`;
|
||||
await Terminal.executeCommands(`echo "${scriptContent}" > ${scriptName}`);
|
||||
|
||||
const inputData = "Hello from stdin!";
|
||||
await Terminal.executeCommands(`echo "${inputData}" | ${scriptName} | run ${scriptName}`);
|
||||
await sleep(50);
|
||||
|
||||
console.log(Terminal.outputHistory);
|
||||
const outputLog: Output[] = Terminal.outputHistory.filter(isOutput);
|
||||
const outputText: Output = outputLog.find((entry: Output) => entry.text?.includes("Received input:"));
|
||||
expect(outputText?.text).toEqual(`${scriptName}: Received input: ${scriptName}: Received input: ${inputData}`);
|
||||
});
|
||||
});
|
||||
|
||||
describe("cat and grep with redirected IO", () => {
|
||||
it("should be able to read files to the terminal", async () => {
|
||||
const filename = "appendOutput.txt";
|
||||
const setupCommandString = `echo First Line >> ${filename} | echo Second Line >> ${filename}`;
|
||||
|
||||
await parseRedirectedCommands(setupCommandString);
|
||||
|
||||
await parseRedirectedCommands(`echo 1 | cat ${filename}`);
|
||||
expect(Terminal.outputHistory.length).toBe(1);
|
||||
expect(Terminal.outputHistory[0].text).toBe("First Line\nSecond Line1");
|
||||
});
|
||||
|
||||
it("should be able to grep files read by cat", async () => {
|
||||
const filename = "appendOutput.txt";
|
||||
const setupCommandString = `echo First Line >> ${filename} | echo Second Line >> ${filename}`;
|
||||
|
||||
await parseRedirectedCommands(setupCommandString);
|
||||
|
||||
await parseRedirectedCommands(`cat ${filename} | grep Second`);
|
||||
|
||||
expect(Terminal.outputHistory.length).toBe(1);
|
||||
const log = Terminal.outputHistory[0];
|
||||
if (!isOutput(log)) throw new Error("Expected output to be of type Output");
|
||||
expect(log.text.replaceAll(ANSI_ESCAPE, "")).toBe("Second Line");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function isOutput(entry: unknown): entry is Output {
|
||||
return !!entry && typeof entry === "object" && entry instanceof Output;
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
import { cat } from "../../../src/Terminal/commands/cat";
|
||||
import { GetServerOrThrow, prestigeAllServers } from "../../../src/Server/AllServers";
|
||||
import { Player } from "@player";
|
||||
import { Terminal } from "../../../src/Terminal";
|
||||
import { StdIO } from "../../../src/Terminal/StdIO/StdIO";
|
||||
import { IOStream } from "../../../src/Terminal/StdIO/IOStream";
|
||||
import { TextFile } from "../../../src/TextFile";
|
||||
import { TextFilePath } from "../../../src/Paths/TextFilePath";
|
||||
import { LiteratureName, MessageFilename } from "@enums";
|
||||
import { Literatures } from "../../../src/Literature/Literatures";
|
||||
import { stringifyReactElement } from "../../../src/Terminal/StdIO/utils";
|
||||
import { Messages } from "../../../src/Message/MessageHelpers";
|
||||
|
||||
const fileName = "example.txt" as TextFilePath;
|
||||
const fileName2 = "example2.txt" as TextFilePath;
|
||||
const fileContent1 = "This is an example text file.";
|
||||
const fileContent2 = "This is another example text file.";
|
||||
|
||||
describe("cat command", () => {
|
||||
beforeEach(() => {
|
||||
prestigeAllServers();
|
||||
Player.init();
|
||||
Terminal.outputHistory = [];
|
||||
const server = GetServerOrThrow(Player.currentServer);
|
||||
server.textFiles.clear();
|
||||
server.scripts.clear();
|
||||
server.messages.length = 0; //Remove .lit and .msg files
|
||||
server.messages.push(LiteratureName.HackersStartingHandbook);
|
||||
server.messages.push(MessageFilename.Jumper0);
|
||||
const file = new TextFile(fileName, fileContent1);
|
||||
server.textFiles.set(fileName, file);
|
||||
const file2 = new TextFile(fileName2, fileContent2);
|
||||
server.textFiles.set(fileName2, file2);
|
||||
});
|
||||
|
||||
it("should retrieve file contents and pass to stdout", () => {
|
||||
const server = GetServerOrThrow(Player.currentServer);
|
||||
|
||||
const stdOut = new IOStream();
|
||||
const stdIO = new StdIO(null, stdOut);
|
||||
|
||||
cat([fileName, fileName2], server, stdIO);
|
||||
const output = stdOut.read();
|
||||
|
||||
expect(output).toBe(`${fileContent1}${fileContent2}`);
|
||||
});
|
||||
|
||||
it("should read from stdin when '-' is provided as an argument", () => {
|
||||
const server = GetServerOrThrow(Player.currentServer);
|
||||
const stdinStuff = "\nInput from stdin line 1";
|
||||
|
||||
const stdIn = new IOStream();
|
||||
stdIn.write(stdinStuff);
|
||||
const stdOut = new IOStream();
|
||||
const stdIO = new StdIO(stdIn, stdOut);
|
||||
|
||||
cat([fileName, "-", fileName2], server, stdIO);
|
||||
const output = stdOut.read();
|
||||
|
||||
expect(output).toBe(`${fileContent1}${stdinStuff}${fileContent2}`);
|
||||
});
|
||||
|
||||
it("should read from stdin and concat it last when '-' is not provided as an argument", () => {
|
||||
const server = GetServerOrThrow(Player.currentServer);
|
||||
|
||||
const stdIn = new IOStream();
|
||||
stdIn.write("Input from stdin line 1");
|
||||
const stdOut = new IOStream();
|
||||
const stdIO = new StdIO(stdIn, stdOut);
|
||||
|
||||
cat([fileName, fileName2], server, stdIO);
|
||||
const output = stdOut.read();
|
||||
|
||||
expect(output).toBe(`${fileContent1}${fileContent2}Input from stdin line 1`);
|
||||
});
|
||||
|
||||
it("should be able to read .lit files", () => {
|
||||
const server = GetServerOrThrow(Player.currentServer);
|
||||
|
||||
const stdOut = new IOStream();
|
||||
const stdIO = new StdIO(null, stdOut);
|
||||
|
||||
cat([`${LiteratureName.HackersStartingHandbook}`], server, stdIO);
|
||||
const output = stdOut.read();
|
||||
|
||||
const bodyText = stringifyReactElement(Literatures[LiteratureName.HackersStartingHandbook].text);
|
||||
const expectedOutput = `${Literatures[LiteratureName.HackersStartingHandbook].title}\n\n${bodyText}\n`;
|
||||
|
||||
expect(output).toBe(expectedOutput);
|
||||
expect(output).toContain("When starting out, hacking is the most profitable way to earn money and progress.");
|
||||
});
|
||||
|
||||
it("should be able to read msg files", () => {
|
||||
const server = GetServerOrThrow(Player.currentServer);
|
||||
|
||||
const stdOut = new IOStream();
|
||||
const stdIO = new StdIO(null, stdOut);
|
||||
|
||||
cat([`${MessageFilename.Jumper0}`], server, stdIO);
|
||||
const output = stdOut.read();
|
||||
|
||||
const text = Messages[MessageFilename.Jumper0].msg + "\n";
|
||||
|
||||
expect(output).toBe(text);
|
||||
});
|
||||
|
||||
it("should be able to concatenate lit and msg files", () => {
|
||||
const server = GetServerOrThrow(Player.currentServer);
|
||||
|
||||
const stdOut = new IOStream();
|
||||
const stdIO = new StdIO(null, stdOut);
|
||||
|
||||
cat([`${LiteratureName.HackersStartingHandbook}`, `${MessageFilename.Jumper0}`], server, stdIO);
|
||||
const output = stdOut.read();
|
||||
|
||||
const bodyText = stringifyReactElement(Literatures[LiteratureName.HackersStartingHandbook].text);
|
||||
const expectedLitOutput = `${Literatures[LiteratureName.HackersStartingHandbook].title}\n\n${bodyText}\n`;
|
||||
const expectedMsgOutput = Messages[MessageFilename.Jumper0].msg + "\n";
|
||||
const expectedOutput = `${expectedLitOutput}${expectedMsgOutput}`;
|
||||
|
||||
expect(output).toBe(expectedOutput);
|
||||
});
|
||||
|
||||
it("should be able to concatenate lit and msg files with stdin", () => {
|
||||
const server = GetServerOrThrow(Player.currentServer);
|
||||
|
||||
const stdIn = new IOStream();
|
||||
stdIn.write("Input from stdin line 1");
|
||||
const stdOut = new IOStream();
|
||||
const stdIO = new StdIO(stdIn, stdOut);
|
||||
|
||||
cat([`${LiteratureName.HackersStartingHandbook}`, "-", `${MessageFilename.Jumper0}`], server, stdIO);
|
||||
const output = stdOut.read();
|
||||
|
||||
const bodyText = stringifyReactElement(Literatures[LiteratureName.HackersStartingHandbook].text);
|
||||
const expectedLitOutput = `${Literatures[LiteratureName.HackersStartingHandbook].title}\n\n${bodyText}\n`;
|
||||
const expectedMsgOutput = Messages[MessageFilename.Jumper0].msg + "\n";
|
||||
const expectedOutput = `${expectedLitOutput}Input from stdin line 1${expectedMsgOutput}`;
|
||||
|
||||
expect(output).toBe(expectedOutput);
|
||||
});
|
||||
});
|
||||
@@ -1,85 +0,0 @@
|
||||
import { GetServerOrThrow, prestigeAllServers } from "../../../src/Server/AllServers";
|
||||
import { Player } from "@player";
|
||||
import { Terminal } from "../../../src/Terminal";
|
||||
import { StdIO } from "../../../src/Terminal/StdIO/StdIO";
|
||||
import { IOStream } from "../../../src/Terminal/StdIO/IOStream";
|
||||
import { TextFile } from "../../../src/TextFile";
|
||||
import { TextFilePath } from "../../../src/Paths/TextFilePath";
|
||||
import { grep } from "../../../src/Terminal/commands/grep";
|
||||
import { ScriptFilePath } from "../../../src/Paths/ScriptFilePath";
|
||||
import { Script } from "../../../src/Script/Script";
|
||||
import { stringify } from "../../../src/Terminal/StdIO/utils";
|
||||
|
||||
const fileName = "example.txt" as TextFilePath;
|
||||
const fileName2 = "example2.txt" as TextFilePath;
|
||||
const fileContent1 = "This is an example text file.\nThis is line 2 of file 1";
|
||||
const fileContent2 = "This is another example text file.\nThis is line 2 of file 2";
|
||||
|
||||
describe("grep command", () => {
|
||||
beforeEach(() => {
|
||||
prestigeAllServers();
|
||||
Player.init();
|
||||
Terminal.outputHistory = [];
|
||||
const server = GetServerOrThrow(Player.currentServer);
|
||||
server.textFiles.clear();
|
||||
server.scripts.clear();
|
||||
const file = new TextFile(fileName, fileContent1);
|
||||
server.textFiles.set(fileName, file);
|
||||
const file2 = new TextFile(fileName2, fileContent2);
|
||||
server.textFiles.set(fileName2, file2);
|
||||
});
|
||||
|
||||
it("should retrieve lines matching the pattern from the specified text file", () => {
|
||||
const server = GetServerOrThrow(Player.currentServer);
|
||||
|
||||
const stdOut = new IOStream();
|
||||
const stdIO = new StdIO(null, stdOut);
|
||||
|
||||
grep(["line 2", fileName], server, stdIO);
|
||||
const output = stdOut.read();
|
||||
|
||||
expect(Terminal.outputHistory).toEqual([]);
|
||||
expect(output).toBe(`example.txt:This is line 2 of file 1`);
|
||||
});
|
||||
|
||||
it("should retrieve lines matching the pattern from the specified script file", () => {
|
||||
const server = GetServerOrThrow(Player.currentServer);
|
||||
const scriptFileName = "script.js" as ScriptFilePath;
|
||||
const scriptContent = "console.log('Hello World');\n// This is line 2 of the script";
|
||||
const scriptFile = new Script(scriptFileName, scriptContent, server.hostname);
|
||||
server.scripts.set(scriptFileName, scriptFile);
|
||||
const stdOut = new IOStream();
|
||||
const stdIO = new StdIO(null, stdOut);
|
||||
|
||||
grep(["line 2", scriptFileName], server, stdIO);
|
||||
const output = stdOut.read();
|
||||
|
||||
expect(Terminal.outputHistory).toEqual([]);
|
||||
expect(output).toBe(`script.js:// This is line 2 of the script`);
|
||||
});
|
||||
|
||||
it("should retrieve lines matching the pattern from stdin", () => {
|
||||
const server = GetServerOrThrow(Player.currentServer);
|
||||
|
||||
const stdIn = new IOStream();
|
||||
stdIn.write("First line from stdin\nThis is line 2 from stdin\nThird line from stdin");
|
||||
stdIn.close();
|
||||
const stdOut = new IOStream();
|
||||
const stdIO = new StdIO(stdIn, stdOut);
|
||||
|
||||
grep(["line 2"], server, stdIO);
|
||||
const output = stdOut.read();
|
||||
|
||||
expect(Terminal.outputHistory).toEqual([]);
|
||||
expect(output).toBe(`This is line 2 from stdin`);
|
||||
});
|
||||
|
||||
it("should grep input piped from cat", async () => {
|
||||
await Terminal.executeCommands(`cat ${fileName} ${fileName2} | grep "line 2"`);
|
||||
const lastOutput = Terminal.outputHistory[Terminal.outputHistory.length - 1];
|
||||
// Output from cat will not have filenames, and will not add additional newlines between file contents
|
||||
expect(stringify(lastOutput.text, true)).toBe(
|
||||
`This is line 2 of file 1This is another example text file.\nThis is line 2 of file 2`,
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -82,12 +82,6 @@ exports[`load/saveAllServers 1`] = `
|
||||
"ramUsage": 1.6,
|
||||
"server": "home",
|
||||
"scriptKey": "script.js*[]",
|
||||
"stdin": null,
|
||||
"tailStdOut": null,
|
||||
"terminalStdOut": {
|
||||
"stdin": null,
|
||||
"stdout": null
|
||||
},
|
||||
"title": "Awesome Script",
|
||||
"threads": 1,
|
||||
"temporary": false
|
||||
|
||||
Reference in New Issue
Block a user