Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test gets skipped with pattern: os == 'android'
- Manifest: toolkit/modules/subprocess/test/xpcshell/xpcshell.toml
/* eslint-disable mozilla/no-arbitrary-setTimeout */
"use strict";
add_task(async function test_subprocess_connectRunning() {
if (AppConstants.platform === "win") {
Assert.throws(
() => Subprocess.connectRunning([42, 58, 63]),
/Not implemented/
);
return;
}
let tempFile = Services.dirsvc.get("TmpD", Ci.nsIFile);
tempFile.append("test-subprocess-connectRunning.txt");
if (tempFile.exists()) {
tempFile.remove(true);
}
registerCleanupFunction(async function () {
tempFile.remove(true);
});
let running = await Subprocess.call({
command: await Subprocess.pathSearch("tee"),
arguments: [tempFile.path],
environment: {},
stderr: "pipe",
});
let { getSubprocessImplForTest } = ChromeUtils.importESModule(
"resource://gre/modules/Subprocess.sys.mjs"
);
let worker = getSubprocessImplForTest().Process.getWorker();
let fds = await worker.call("getFds", [running.id]);
let wrongConnect = Subprocess.connectRunning(fds);
await Assert.rejects(
wrongConnect,
function (error) {
return /Attempt to connect FDs already handled by Subprocess/.test(
error.message
);
},
"Cannot reuse existing FDs in connectRunning"
);
// The test needs to dup() the FDs because of how "tee" is launched above:
// when Subprocess.call() launched "tee" there will be Pipe created that
// obviously refers to OS level FDs. When connectRunning() will be executed
// then there will also be Pipe object created referencing the FDs. This
// leads to a situation where 'running.{stdin,stdout}' and
// 'proc.{stdin,stdout}' are sharing the same OS level FDs. Thus dup() is
// required to make sure operations on those are done correctly. Especially
// a Pipe on the JS side wraps the FD in a unix.Fd() which ensures a close()
// is done so close() twice on the same FD is wrong.
let { libc } = ChromeUtils.importESModule(
"resource://gre/modules/subprocess/subprocess_unix.sys.mjs"
);
// unix.Fd() here should ensure there's a close() done.
const duped_fds = fds.map(e => libc.dup(e));
let proc = await Subprocess.connectRunning(duped_fds);
equal(proc.pid, null, "Already running process pid is null");
let contents = "lorem ipsum";
let writeOp = proc.stdin.write(contents);
equal(
(await writeOp).bytesWritten,
contents.length,
"Contents correctly written to stdin"
);
let readOp = running.stdout.readString(contents.length);
equal(await readOp, contents, "Pipes communication is functional");
await running.kill();
ok(tempFile.exists(), "temp file was written to");
equal(
await IOUtils.readUTF8(tempFile.path),
contents,
"Contents correctly written to temp file"
);
await proc.kill();
});
add_task(async function test_cleaned_up() {
let { getSubprocessImplForTest } = ChromeUtils.importESModule(
"resource://gre/modules/Subprocess.sys.mjs"
);
let worker = getSubprocessImplForTest().Process.getWorker();
let openFiles = await worker.call("getOpenFiles", []);
let processes = await worker.call("getProcesses", []);
equal(openFiles.size, 0, "No remaining open files");
equal(processes.size, 0, "No remaining processes");
});