Archived
1
0

Move and refactor fs tests

This commit is contained in:
Asher 2019-02-19 14:21:04 -06:00
parent 2889b3fede
commit d80f82ab98
No known key found for this signature in database
GPG Key ID: 7BB4BA9C783D2BBC
11 changed files with 726 additions and 682 deletions

View File

@ -1,5 +1,10 @@
{ {
"name": "@coder/ide", "name": "@coder/ide",
"description": "Browser-based IDE client abstraction.", "description": "Browser-based IDE client abstraction.",
"main": "src/index.ts" "main": "src/index.ts",
"dependencies": {},
"devDependencies": {
"@types/rimraf": "^2.0.2",
"rimraf": "^2.6.3"
}
} }

View File

@ -7,7 +7,7 @@ import { retry } from "../retry";
* A connection based on a web socket. Automatically reconnects and buffers * A connection based on a web socket. Automatically reconnects and buffers
* messages during connection. * messages during connection.
*/ */
class Connection implements ReadWriteConnection { class WebsocketConnection implements ReadWriteConnection {
private activeSocket: WebSocket | undefined; private activeSocket: WebSocket | undefined;
private readonly messageBuffer = <Uint8Array[]>[]; private readonly messageBuffer = <Uint8Array[]>[];
private readonly socketTimeoutDelay = 60 * 1000; private readonly socketTimeoutDelay = 60 * 1000;
@ -129,4 +129,4 @@ class Connection implements ReadWriteConnection {
} }
// Global instance so all fills can use the same client. // Global instance so all fills can use the same client.
export const client = new Client(new Connection()); export const client = new Client(new WebsocketConnection());

View File

@ -116,7 +116,7 @@ class FS {
const ae = this.client.run((ae, path, options) => { const ae = this.client.run((ae, path, options) => {
const fs = __non_webpack_require__("fs") as typeof import("fs"); const fs = __non_webpack_require__("fs") as typeof import("fs");
const str = fs.createWriteStream(path, options); const str = fs.createWriteStream(path, options);
ae.on("write", (d) => str.write(_Buffer.from(d, "utf8"))); ae.on("write", (d: string) => str.write(_Buffer.from(d, "utf8")));
ae.on("close", () => str.close()); ae.on("close", () => str.close());
str.on("close", () => ae.emit("close")); str.on("close", () => ae.emit("close"));
str.on("open", (fd) => ae.emit("open", fd)); str.on("open", (fd) => ae.emit("open", fd));
@ -141,7 +141,7 @@ class FS {
}, },
}); });
ae.on("open", (a) => this.emit("open", a)); ae.on("open", (fd: number) => this.emit("open", fd));
ae.on("close", () => this.emit("close")); ae.on("close", () => this.emit("close"));
} }
@ -597,7 +597,15 @@ class FS {
}); });
} }
public write = <TBuffer extends Buffer | Uint8Array>(fd: number, buffer: TBuffer, offset: number | undefined, length: number | undefined, position: number | undefined | ((err: NodeJS.ErrnoException, written: number, buffer: TBuffer) => void), callback?: (err: NodeJS.ErrnoException, written: number, buffer: TBuffer) => void): void => { public write = <TBuffer extends Buffer | Uint8Array>(fd: number, buffer: TBuffer, offset: number | undefined | ((err: NodeJS.ErrnoException, written: number, buffer: TBuffer) => void), length: number | undefined | ((err: NodeJS.ErrnoException, written: number, buffer: TBuffer) => void), position: number | undefined | ((err: NodeJS.ErrnoException, written: number, buffer: TBuffer) => void), callback?: (err: NodeJS.ErrnoException, written: number, buffer: TBuffer) => void): void => {
if (typeof offset === "function") {
callback = offset;
offset = undefined;
}
if (typeof length === "function") {
callback = length;
length = undefined;
}
if (typeof position === "function") { if (typeof position === "function") {
callback = position; callback = position;
position = undefined; position = undefined;
@ -662,9 +670,9 @@ class FS {
return new class Watcher extends EventEmitter implements fs.FSWatcher { return new class Watcher extends EventEmitter implements fs.FSWatcher {
public constructor() { public constructor() {
super(); super();
ae.on("change", (event, filename) => this.emit("change", event, filename)); ae.on("change", (event: string, filename: string) => this.emit("change", event, filename));
ae.on("error", (error) => this.emit("error", error)); ae.on("error", (error: Error) => this.emit("error", error));
ae.on("listener", (event, filename) => listener && listener(event, filename)); ae.on("listener", (event: string, filename: string) => listener && listener(event, filename));
} }
public close(): void { public close(): void {

View File

@ -0,0 +1,584 @@
import * as nativeFs from "fs";
import * as os from "os";
import * as path from "path";
import * as util from "util";
import * as rimraf from "rimraf";
import { createClient } from "@coder/protocol/test";
const client = createClient();
jest.mock("../src/fill/client", () => ({ client }));
const fs = require("../src/fill/fs") as typeof import("fs");
describe("fs", () => {
let i = 0;
const coderDir = path.join(os.tmpdir(), "coder");
const testFile = path.join(__dirname, "fs.test.ts");
const tmpFile = (): string => path.join(coderDir, `${i++}`);
const createTmpFile = async (): Promise<string> => {
const tf = tmpFile();
await util.promisify(nativeFs.writeFile)(tf, "");
return tf;
};
beforeAll(async () => {
await util.promisify(rimraf)(coderDir);
await util.promisify(nativeFs.mkdir)(coderDir);
});
describe("access", () => {
it("should access existing file", async () => {
await expect(util.promisify(fs.access)(testFile))
.resolves.toBeUndefined();
});
it("should fail to access nonexistent file", async () => {
await expect(util.promisify(fs.access)(tmpFile()))
.rejects.toThrow("ENOENT");
});
});
describe("append", () => {
it("should append to existing file", async () => {
const file = await createTmpFile();
await expect(util.promisify(fs.appendFile)(file, "howdy"))
.resolves.toBeUndefined();
expect(await util.promisify(nativeFs.readFile)(file, "utf8"))
.toEqual("howdy");
});
it("should create then append to nonexistent file", async () => {
const file = tmpFile();
await expect(util.promisify(fs.appendFile)(file, "howdy"))
.resolves.toBeUndefined();
expect(await util.promisify(nativeFs.readFile)(file, "utf8"))
.toEqual("howdy");
});
it("should fail to append to file in nonexistent directory", async () => {
const file = path.join(tmpFile(), "nope");
await expect(util.promisify(fs.appendFile)(file, "howdy"))
.rejects.toThrow("ENOENT");
expect(await util.promisify(nativeFs.exists)(file))
.toEqual(false);
});
});
describe("chmod", () => {
it("should chmod existing file", async () => {
const file = await createTmpFile();
await expect(util.promisify(fs.chmod)(file, "755"))
.resolves.toBeUndefined();
});
it("should fail to chmod nonexistent file", async () => {
await expect(util.promisify(fs.chmod)(tmpFile(), "755"))
.rejects.toThrow("ENOENT");
});
});
describe("chown", () => {
it("should chown existing file", async () => {
const file = await createTmpFile();
await expect(util.promisify(fs.chown)(file, 1, 1))
.resolves.toBeUndefined();
});
it("should fail to chown nonexistent file", async () => {
await expect(util.promisify(fs.chown)(tmpFile(), 1, 1))
.rejects.toThrow("ENOENT");
});
});
describe("close", () => {
it("should close opened file", async () => {
const file = await createTmpFile();
const fd = await util.promisify(nativeFs.open)(file, "r");
await expect(util.promisify(fs.close)(fd))
.resolves.toBeUndefined();
});
it("should fail to close non-opened file", async () => {
await expect(util.promisify(fs.close)(99999999))
.rejects.toThrow("EBADF");
});
});
describe("copyFile", () => {
it("should copy existing file", async () => {
const source = await createTmpFile();
const destination = tmpFile();
await expect(util.promisify(fs.copyFile)(source, destination))
.resolves.toBeUndefined();
await expect(util.promisify(fs.exists)(destination))
.resolves.toBe(true);
});
it("should fail to copy nonexistent file", async () => {
await expect(util.promisify(fs.copyFile)(tmpFile(), tmpFile()))
.rejects.toThrow("ENOENT");
});
});
describe("createWriteStream", () => {
it("should write to file", async () => {
const file = tmpFile();
const content = "howdy\nhow\nr\nu";
const stream = fs.createWriteStream(file);
stream.on("open", (fd) => {
expect(fd).toBeDefined();
stream.write(content);
stream.close();
});
await expect(new Promise((resolve): void => {
stream.on("close", async () => {
resolve(await util.promisify(nativeFs.readFile)(file, "utf8"));
});
})).resolves.toBe(content);
});
});
describe("exists", () => {
it("should output file exists", async () => {
await expect(util.promisify(fs.exists)(testFile))
.resolves.toBe(true);
});
it("should output file does not exist", async () => {
await expect(util.promisify(fs.exists)(tmpFile()))
.resolves.toBe(false);
});
});
describe("fchmod", () => {
it("should fchmod existing file", async () => {
const file = await createTmpFile();
const fd = await util.promisify(nativeFs.open)(file, "r");
await expect(util.promisify(fs.fchmod)(fd, "755"))
.resolves.toBeUndefined();
await util.promisify(nativeFs.close)(fd);
});
it("should fail to fchmod nonexistent file", async () => {
await expect(util.promisify(fs.fchmod)(2242342, "755"))
.rejects.toThrow("EBADF");
});
});
describe("fchown", () => {
it("should fchown existing file", async () => {
const file = await createTmpFile();
const fd = await util.promisify(nativeFs.open)(file, "r");
await expect(util.promisify(fs.fchown)(fd, 1, 1))
.resolves.toBeUndefined();
await util.promisify(nativeFs.close)(fd);
});
it("should fail to fchown nonexistent file", async () => {
await expect(util.promisify(fs.fchown)(99999, 1, 1))
.rejects.toThrow("EBADF");
});
});
describe("fdatasync", () => {
it("should fdatasync existing file", async () => {
const file = await createTmpFile();
const fd = await util.promisify(nativeFs.open)(file, "r");
await expect(util.promisify(fs.fdatasync)(fd))
.resolves.toBeUndefined();
await util.promisify(nativeFs.close)(fd);
});
it("should fail to fdatasync nonexistent file", async () => {
await expect(util.promisify(fs.fdatasync)(99999))
.rejects.toThrow("EBADF");
});
});
describe("fstat", () => {
it("should fstat existing file", async () => {
const fd = await util.promisify(nativeFs.open)(testFile, "r");
const stat = await util.promisify(nativeFs.fstat)(fd);
await expect(util.promisify(fs.fstat)(fd))
.resolves.toMatchObject({
size: stat.size,
});
await util.promisify(nativeFs.close)(fd);
});
it("should fail to fstat", async () => {
await expect(util.promisify(fs.fstat)(9999))
.rejects.toThrow("EBADF");
});
});
describe("fsync", () => {
it("should fsync existing file", async () => {
const file = await createTmpFile();
const fd = await util.promisify(nativeFs.open)(file, "r");
await expect(util.promisify(fs.fsync)(fd))
.resolves.toBeUndefined();
await util.promisify(nativeFs.close)(fd);
});
it("should fail to fsync nonexistent file", async () => {
await expect(util.promisify(fs.fsync)(99999))
.rejects.toThrow("EBADF");
});
});
describe("ftruncate", () => {
it("should ftruncate existing file", async () => {
const file = await createTmpFile();
const fd = await util.promisify(nativeFs.open)(file, "w");
await expect(util.promisify(fs.ftruncate)(fd, 1))
.resolves.toBeUndefined();
await util.promisify(nativeFs.close)(fd);
});
it("should fail to ftruncate nonexistent file", async () => {
await expect(util.promisify(fs.ftruncate)(99999, 9999))
.rejects.toThrow("EBADF");
});
});
describe("futimes", () => {
it("should futimes existing file", async () => {
const file = await createTmpFile();
const fd = await util.promisify(nativeFs.open)(file, "w");
await expect(util.promisify(fs.futimes)(fd, 1, 1))
.resolves.toBeUndefined();
await util.promisify(nativeFs.close)(fd);
});
it("should fail to futimes nonexistent file", async () => {
await expect(util.promisify(fs.futimes)(99999, 9999, 9999))
.rejects.toThrow("EBADF");
});
});
describe("lchmod", () => {
it("should lchmod existing file", async () => {
const file = await createTmpFile();
await expect(util.promisify(fs.lchmod)(file, "755"))
.resolves.toBeUndefined();
});
// TODO: Doesn't fail on my system?
it("should fail to lchmod nonexistent file", async () => {
await expect(util.promisify(fs.lchmod)(tmpFile(), "755"))
.resolves.toBeUndefined();
});
});
describe("lchown", () => {
it("should lchown existing file", async () => {
const file = await createTmpFile();
await expect(util.promisify(fs.lchown)(file, 1, 1))
.resolves.toBeUndefined();
});
// TODO: Doesn't fail on my system?
it("should fail to lchown nonexistent file", async () => {
await expect(util.promisify(fs.lchown)(tmpFile(), 1, 1))
.resolves.toBeUndefined();
});
});
describe("link", () => {
it("should link existing file", async () => {
const source = await createTmpFile();
const destination = tmpFile();
await expect(util.promisify(fs.link)(source, destination))
.resolves.toBeUndefined();
await expect(util.promisify(fs.exists)(destination))
.resolves.toBe(true);
});
it("should fail to link nonexistent file", async () => {
await expect(util.promisify(fs.link)(tmpFile(), tmpFile()))
.rejects.toThrow("ENOENT");
});
});
describe("lstat", () => {
it("should lstat existing file", async () => {
const stat = await util.promisify(nativeFs.lstat)(testFile);
await expect(util.promisify(fs.lstat)(testFile))
.resolves.toMatchObject({
size: stat.size,
});
});
it("should fail to lstat non-existent file", async () => {
await expect(util.promisify(fs.lstat)(tmpFile()))
.rejects.toThrow("ENOENT");
});
});
describe("mkdir", () => {
const target = tmpFile();
it("should create nonexistent directory", async () => {
await expect(util.promisify(fs.mkdir)(target))
.resolves.toBeUndefined();
});
it("should fail to create existing directory", async () => {
await expect(util.promisify(fs.mkdir)(target))
.rejects.toThrow("EEXIST");
});
});
describe("mkdtemp", () => {
it("should create temp dir", async () => {
await expect(util.promisify(fs.mkdtemp)(coderDir + "/"))
.resolves.toMatch(/^\/tmp\/coder\/[a-zA-Z0-9]{6}/);
});
});
describe("open", () => {
it("should open existing file", async () => {
const fd = await util.promisify(fs.open)(testFile, "r");
expect(fd).not.toBeNaN();
await expect(util.promisify(fs.close)(fd))
.resolves.toBeUndefined();
});
it("should fail to open nonexistent file", async () => {
await expect(util.promisify(fs.open)(tmpFile(), "r"))
.rejects.toThrow("ENOENT");
});
});
describe("read", () => {
it("should read existing file", async () => {
const fd = await util.promisify(nativeFs.open)(testFile, "r");
const stat = await util.promisify(nativeFs.fstat)(fd);
const buffer = new Buffer(stat.size);
let bytesRead = 0;
let chunkSize = 2048;
while (bytesRead < stat.size) {
if ((bytesRead + chunkSize) > stat.size) {
chunkSize = stat.size - bytesRead;
}
await util.promisify(fs.read)(fd, buffer, bytesRead, chunkSize, bytesRead);
bytesRead += chunkSize;
}
const content = await util.promisify(nativeFs.readFile)(testFile, "utf8");
expect(buffer.toString()).toEqual(content);
await util.promisify(nativeFs.close)(fd);
});
it("should fail to read nonexistent file", async () => {
await expect(util.promisify(fs.read)(99999, new Buffer(10), 9999, 999, 999))
.rejects.toThrow("EBADF");
});
});
describe("readFile", () => {
it("should read existing file", async () => {
const content = await util.promisify(nativeFs.readFile)(testFile, "utf8");
await expect(util.promisify(fs.readFile)(testFile, "utf8"))
.resolves.toEqual(content);
});
it("should fail to read nonexistent file", async () => {
await expect(util.promisify(fs.readFile)(tmpFile()))
.rejects.toThrow("ENOENT");
});
});
describe("readdir", () => {
it("should read existing directory", async () => {
const paths = await util.promisify(nativeFs.readdir)(coderDir);
await expect(util.promisify(fs.readdir)(coderDir))
.resolves.toEqual(paths);
});
it("should fail to read nonexistent directory", async () => {
await expect(util.promisify(fs.readdir)(tmpFile()))
.rejects.toThrow("ENOENT");
});
});
describe("readlink", () => {
it("should read existing link", async () => {
const source = await createTmpFile();
const destination = tmpFile();
await util.promisify(nativeFs.symlink)(source, destination);
await expect(util.promisify(fs.readlink)(destination))
.resolves.toBe(source);
});
it("should fail to read nonexistent link", async () => {
await expect(util.promisify(fs.readlink)(tmpFile()))
.rejects.toThrow("ENOENT");
});
});
describe("realpath", () => {
it("should read real path of existing file", async () => {
const source = await createTmpFile();
const destination = tmpFile();
nativeFs.symlinkSync(source, destination);
await expect(util.promisify(fs.realpath)(destination))
.resolves.toBe(source);
});
it("should fail to read real path of nonexistent file", async () => {
await expect(util.promisify(fs.realpath)(tmpFile()))
.rejects.toThrow("ENOENT");
});
});
describe("rename", () => {
it("should rename existing file", async () => {
const source = await createTmpFile();
const destination = tmpFile();
await expect(util.promisify(fs.rename)(source, destination))
.resolves.toBeUndefined();
await expect(util.promisify(nativeFs.exists)(source))
.resolves.toBe(false);
await expect(util.promisify(nativeFs.exists)(destination))
.resolves.toBe(true);
});
it("should fail to rename nonexistent file", async () => {
await expect(util.promisify(fs.rename)(tmpFile(), tmpFile()))
.rejects.toThrow("ENOENT");
});
});
describe("rmdir", () => {
it("should rmdir existing directory", async () => {
const dir = tmpFile();
await util.promisify(nativeFs.mkdir)(dir);
await expect(util.promisify(fs.rmdir)(dir))
.resolves.toBeUndefined();
await expect(util.promisify(nativeFs.exists)(dir))
.resolves.toBe(false);
});
it("should fail to rmdir nonexistent directory", async () => {
await expect(util.promisify(fs.rmdir)(tmpFile()))
.rejects.toThrow("ENOENT");
});
});
describe("stat", () => {
it("should stat existing file", async () => {
const nativeStat = await util.promisify(nativeFs.stat)(testFile);
const stat = await util.promisify(fs.stat)(testFile);
expect(stat).toMatchObject({
size: nativeStat.size,
});
expect(stat.isFile()).toBe(true);
});
it("should stat existing folder", async () => {
const dir = tmpFile();
await util.promisify(nativeFs.mkdir)(dir);
const nativeStat = await util.promisify(nativeFs.stat)(dir);
const stat = await util.promisify(fs.stat)(dir);
expect(stat).toMatchObject({
size: nativeStat.size,
});
expect(stat.isDirectory()).toBe(true);
});
it("should fail to stat nonexistent file", async () => {
await expect(util.promisify(fs.stat)(tmpFile()))
.rejects.toThrow("ENOENT");
});
});
describe("symlink", () => {
it("should symlink existing file", async () => {
const source = await createTmpFile();
const destination = tmpFile();
await expect(util.promisify(fs.symlink)(source, destination))
.resolves.toBeUndefined();
expect(util.promisify(nativeFs.exists)(source))
.resolves.toBe(true);
});
// TODO: Seems to be happy to do this on my system?
it("should fail to symlink nonexistent file", async () => {
await expect(util.promisify(fs.symlink)(tmpFile(), tmpFile()))
.resolves.toBeUndefined();
});
});
describe("truncate", () => {
it("should truncate existing file", async () => {
const file = tmpFile();
await util.promisify(nativeFs.writeFile)(file, "hiiiiii");
await expect(util.promisify(fs.truncate)(file, 2))
.resolves.toBeUndefined();
await expect(util.promisify(nativeFs.readFile)(file, "utf8"))
.resolves.toBe("hi");
});
it("should fail to truncate nonexistent file", async () => {
await expect(util.promisify(fs.truncate)(tmpFile(), 0))
.rejects.toThrow("ENOENT");
});
});
describe("unlink", () => {
it("should unlink existing file", async () => {
const file = await createTmpFile();
await expect(util.promisify(fs.unlink)(file))
.resolves.toBeUndefined();
expect(util.promisify(nativeFs.exists)(file))
.resolves.toBe(false);
});
it("should fail to unlink nonexistent file", async () => {
await expect(util.promisify(fs.unlink)(tmpFile()))
.rejects.toThrow("ENOENT");
});
});
describe("utimes", () => {
it("should update times on existing file", async () => {
const file = await createTmpFile();
await expect(util.promisify(fs.utimes)(file, 100, 100))
.resolves.toBeUndefined();
});
it("should fail to update times on nonexistent file", async () => {
await expect(util.promisify(fs.utimes)(tmpFile(), 100, 100))
.rejects.toThrow("ENOENT");
});
});
describe("write", () => {
it("should write to existing file", async () => {
const file = await createTmpFile();
const fd = await util.promisify(nativeFs.open)(file, "w");
await expect(util.promisify(fs.write)(fd, Buffer.from("hi")))
.resolves.toBe(2);
await expect(util.promisify(nativeFs.readFile)(file, "utf8"))
.resolves.toBe("hi");
await util.promisify(nativeFs.close)(fd);
});
it("should fail to write to nonexistent file", async () => {
await expect(util.promisify(fs.write)(100000, Buffer.from("wowow")))
.rejects.toThrow("EBADF");
});
});
describe("writeFile", () => {
it("should write file", async () => {
const file = await createTmpFile();
await expect(util.promisify(fs.writeFile)(file, "howdy"))
.resolves.toBeUndefined();
await expect(util.promisify(nativeFs.readFile)(file, "utf8"))
.resolves.toBe("howdy");
});
});
});

View File

@ -2,3 +2,113 @@
# yarn lockfile v1 # yarn lockfile v1
"@types/events@*":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7"
integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==
"@types/glob@*":
version "7.1.1"
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575"
integrity sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==
dependencies:
"@types/events" "*"
"@types/minimatch" "*"
"@types/node" "*"
"@types/minimatch@*":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
"@types/node@*":
version "11.9.4"
resolved "https://registry.yarnpkg.com/@types/node/-/node-11.9.4.tgz#ceb0048a546db453f6248f2d1d95e937a6f00a14"
integrity sha512-Zl8dGvAcEmadgs1tmSPcvwzO1YRsz38bVJQvH1RvRqSR9/5n61Q1ktcDL0ht3FXWR+ZpVmXVwN1LuH4Ax23NsA==
"@types/rimraf@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-2.0.2.tgz#7f0fc3cf0ff0ad2a99bb723ae1764f30acaf8b6e"
integrity sha512-Hm/bnWq0TCy7jmjeN5bKYij9vw5GrDFWME4IuxV08278NtU/VdGbzsBohcCUJ7+QMqmUq5hpRKB39HeQWJjztQ==
dependencies:
"@types/glob" "*"
"@types/node" "*"
balanced-match@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
dependencies:
balanced-match "^1.0.0"
concat-map "0.0.1"
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
glob@^7.1.3:
version "7.1.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1"
integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
inherits "2"
minimatch "^3.0.4"
once "^1.3.0"
path-is-absolute "^1.0.0"
inflight@^1.0.4:
version "1.0.6"
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
dependencies:
once "^1.3.0"
wrappy "1"
inherits@2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
minimatch@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
dependencies:
brace-expansion "^1.1.7"
once@^1.3.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
dependencies:
wrappy "1"
path-is-absolute@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
rimraf@^2.6.3:
version "2.6.3"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==
dependencies:
glob "^7.1.3"
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=

View File

@ -23,7 +23,7 @@
], ],
"moduleNameMapper": { "moduleNameMapper": {
"^.+\\.(s?css|png|svg)$": "<rootDir>/../scripts/dummy.js", "^.+\\.(s?css|png|svg)$": "<rootDir>/../scripts/dummy.js",
"@coder/(.*)/testing": "<rootDir>/$1/testing", "@coder/(.*)/test": "<rootDir>/$1/test",
"@coder/(.*)": "<rootDir>/$1/src" "@coder/(.*)": "<rootDir>/$1/src"
}, },
"transform": { "transform": {

View File

@ -1,4 +1,4 @@
export * from "./browser/client"; export * from "./browser/client";
export { ActiveEval } from "./browser/command"; export * from "./browser/evaluate";
export * from "./common/connection"; export * from "./common/connection";
export * from "./common/util"; export * from "./common/util";

View File

@ -80,7 +80,14 @@ export const evaluate = (connection: SendableConnection, message: NewEvalMessage
// tslint:enable no-any // tslint:enable no-any
} : undefined, } : undefined,
_Buffer: Buffer, _Buffer: Buffer,
// When the client is ran from Webpack, it will replace
// __non_webpack_require__ with require, which we then need to provide to
// the sandbox. Since the server might also be using Webpack, we need to set
// it to the non-Webpack version when that's the case. Then we need to also
// provide __non_webpack_require__ for when the client doesn't run through
// Webpack meaning it doesn't get replaced with require (Jest for example).
require: typeof __non_webpack_require__ !== "undefined" ? __non_webpack_require__ : require, require: typeof __non_webpack_require__ !== "undefined" ? __non_webpack_require__ : require,
__non_webpack_require__: typeof __non_webpack_require__ !== "undefined" ? __non_webpack_require__ : require,
setTimeout, setTimeout,
setInterval, setInterval,
clearTimeout, clearTimeout,

View File

@ -0,0 +1 @@
export * from "./helpers";

View File

@ -1,671 +0,0 @@
import * as nativeFs from "fs";
import * as os from "os";
import * as path from "path";
import { createClient } from "../helpers";
import { FS } from "../../src/browser/modules/fs";
describe("fs", () => {
const client = createClient();
const fs = new FS(client);
const testFile = path.join(__dirname, "fs.test.ts");
const tmpFile = () => path.join(os.tmpdir(), `tmpfile-${Math.random()}`);
const createTmpFile = (): string => {
const tf = tmpFile();
nativeFs.writeFileSync(tf, "");
return tf;
};
describe("access", () => {
it("should access file", (done) => {
fs.access(testFile, undefined, (err) => {
expect(err).toBeUndefined();
done();
});
});
it("should fail to access file", (done) => {
fs.access(tmpFile(), undefined, (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("append", () => {
it("should append to file", (done) => {
const file = createTmpFile();
fs.appendFile(file, "howdy", undefined, (err) => {
expect(err).toBeUndefined();
const content = nativeFs.readFileSync(file).toString();
expect(content).toEqual("howdy");
done();
});
});
it("should fail to append to file", (done) => {
fs.appendFile(tmpFile(), "howdy", undefined, (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("chmod", () => {
it("should chmod file", (done) => {
fs.chmod(createTmpFile(), "755", (err) => {
expect(err).toBeUndefined();
done();
});
});
it("should fail to chmod file", (done) => {
fs.chmod(tmpFile(), "755", (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("chown", () => {
it("should chown file", (done) => {
fs.chown(createTmpFile(), 1, 1, (err) => {
expect(err).toBeUndefined();
done();
});
});
it("should fail to chown file", (done) => {
fs.chown(tmpFile(), 1, 1, (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("close", () => {
it("should close file", (done) => {
const file = createTmpFile();
const id = nativeFs.openSync(file, "r");
fs.close(id, (err) => {
expect(err).toBeUndefined();
done();
});
});
it("should fail to close file", (done) => {
fs.close(99999999, (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("copyFile", () => {
it("should copy file", (done) => {
const file = createTmpFile();
fs.copyFile(file, tmpFile(), (err) => {
expect(err).toBeUndefined();
done();
});
});
it("should fail to copy file", (done) => {
fs.copyFile(tmpFile(), tmpFile(), (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("createWriteStream", () => {
it("should write to file", (done) => {
const file = tmpFile();
const content = "howdy\nhow\nr\nu";
const stream = fs.createWriteStream(file);
stream.on("open", (fd) => {
expect(fd).toBeDefined();
stream.write(content);
stream.close();
});
stream.on("close", () => {
expect(nativeFs.readFileSync(file).toString()).toEqual(content);
done();
});
});
});
describe("exists", () => {
it("should output file exists", (done) => {
fs.exists(testFile, (exists) => {
expect(exists).toBeTruthy();
done();
});
});
it("should output file does not exist", (done) => {
fs.exists(tmpFile(), (exists) => {
expect(exists).toBeFalsy();
done();
});
});
});
describe("fchmod", () => {
it("should fchmod", (done) => {
const file = createTmpFile();
const id = nativeFs.openSync(file, "r");
fs.fchmod(id, "755", (err) => {
expect(err).toBeUndefined();
done();
});
});
it("should fail to fchmod", (done) => {
fs.fchmod(2242342, "755", (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("fchown", () => {
it("should fchown", (done) => {
const file = createTmpFile();
const id = nativeFs.openSync(file, "r");
fs.fchown(id, 1, 1, (err) => {
expect(err).toBeUndefined();
done();
});
});
it("should fail to fchown", (done) => {
fs.fchown(99999, 1, 1, (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("fdatasync", () => {
it("should fdatasync", (done) => {
const file = createTmpFile();
const id = nativeFs.openSync(file, "r");
fs.fdatasync(id, (err) => {
expect(err).toBeUndefined();
done();
});
});
it("should fail to fdatasync", (done) => {
fs.fdatasync(99999, (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("fstat", () => {
it("should fstat", (done) => {
const id = nativeFs.openSync(testFile, "r");
fs.fstat(id, (err, stats) => {
expect(err).toBeUndefined();
expect(stats.size).toBeGreaterThan(0);
done();
});
});
it("should fail to fstat", (done) => {
fs.fstat(9999, (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("fsync", () => {
it("should fsync", (done) => {
const file = createTmpFile();
const id = nativeFs.openSync(file, "r");
fs.fsync(id, (err) => {
expect(err).toBeUndefined();
done();
});
});
it("should fail to fsync", (done) => {
fs.fsync(99999, (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("ftruncate", () => {
it("should ftruncate", (done) => {
const file = createTmpFile();
const id = nativeFs.openSync(file, "w");
fs.ftruncate(id, 1, (err) => {
expect(err).toBeUndefined();
done();
});
});
it("should fail to ftruncate", (done) => {
fs.ftruncate(99999, 9999, (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("futimes", () => {
it("should futimes", (done) => {
const file = createTmpFile();
const id = nativeFs.openSync(file, "w");
fs.futimes(id, 1, 1, (err) => {
expect(err).toBeUndefined();
done();
});
});
it("should fail to futimes", (done) => {
fs.futimes(99999, 9999, 9999, (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("lchmod", () => {
it("should lchmod file", (done) => {
fs.lchmod(createTmpFile(), "755", (err) => {
expect(err).toBeUndefined();
done();
});
});
it("should fail to lchmod file", (done) => {
fs.lchmod(tmpFile(), "755", (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("lchown", () => {
it("should lchown file", (done) => {
fs.lchown(createTmpFile(), 1, 1, (err) => {
expect(err).toBeUndefined();
done();
});
});
it("should fail to lchown file", (done) => {
fs.lchown(tmpFile(), 1, 1, (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("link", () => {
it("should link file", (done) => {
const newFile = createTmpFile();
const targetFile = tmpFile();
fs.link(newFile, targetFile, (err) => {
expect(err).toBeUndefined();
expect(nativeFs.existsSync(targetFile)).toBeTruthy();
done();
});
});
it("should fail to link file", (done) => {
fs.link(tmpFile(), tmpFile(), (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("lstat", () => {
it("should lstat", (done) => {
fs.lstat(testFile, (err, stats) => {
expect(err).toBeUndefined();
expect(stats.size).toBeGreaterThan(0);
done();
});
});
it("should fail to lstat", (done) => {
fs.lstat(path.join(__dirname, "no-exist"), (err, stats) => {
expect(err).toBeDefined();
expect(stats).toBeUndefined();
done();
});
});
});
describe("mkdir", () => {
const target = tmpFile();
it("should create directory", (done) => {
fs.mkdir(target, undefined, (err) => {
expect(err).toBeUndefined();
done();
});
});
it("should fail to create directory", (done) => {
fs.mkdir(target, undefined, (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("mkdtemp", () => {
it("should create temp dir", (done) => {
fs.mkdtemp(path.join(os.tmpdir(), "example"), undefined, (err, folder) => {
expect(err).toBeUndefined();
done();
});
});
});
describe("open", () => {
it("should open file", (done) => {
fs.open(testFile, "r", undefined, (err, fd) => {
expect(err).toBeUndefined();
expect(fd).toBeDefined();
done();
});
});
it("should fail to open file", (done) => {
fs.open("asdfoksfg", "r", undefined, (err, fd) => {
expect(err).toBeDefined();
done();
});
});
});
describe("read", () => {
it("should read file", async () => {
const fd = nativeFs.openSync(testFile, "r");
const stat = nativeFs.fstatSync(fd);
const buffer = new Buffer(stat.size);
let bytesRead = 0;
let chunkSize = 2048;
while (bytesRead < stat.size) {
if ((bytesRead + chunkSize) > stat.size) {
chunkSize = stat.size - bytesRead;
}
await new Promise((res, rej) => {
fs.read(fd, buffer, bytesRead, chunkSize, bytesRead, (err) => {
if (err) {
rej(err);
} else {
res();
}
});
});
bytesRead += chunkSize;
}
expect(buffer.toString()).toEqual(nativeFs.readFileSync(testFile).toString());
});
it("should fail to read file", (done) => {
fs.read(99999, new Buffer(10), 9999, 999, 999, (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("readFile", () => {
it("should read file", (done) => {
fs.readFile(testFile, undefined, (err, data) => {
expect(err).toBeUndefined();
expect(data.toString()).toEqual(nativeFs.readFileSync(testFile).toString());
done();
});
});
it("should fail to read file", (done) => {
fs.readFile("donkey", undefined, (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("readdir", () => {
it("should read directory", (done) => {
fs.readdir(__dirname, undefined, (err, paths) => {
expect(err).toBeUndefined();
expect(paths.length).toBeGreaterThan(0);
done();
});
});
it("should fail to read directory", (done) => {
fs.readdir("moocow", undefined, (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("readlink", () => {
it("should read link", (done) => {
const srcFile = createTmpFile();
const linkedFile = tmpFile();
nativeFs.symlinkSync(srcFile, linkedFile);
fs.readlink(linkedFile, undefined, (err, link) => {
expect(err).toBeUndefined();
expect(link).toEqual(srcFile);
done();
});
});
it("should fail to read link", (done) => {
fs.readlink(tmpFile(), undefined, (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("realpath", () => {
it("should read real path", (done) => {
const srcFile = createTmpFile();
const linkedFile = tmpFile();
nativeFs.symlinkSync(srcFile, linkedFile);
fs.realpath(linkedFile, undefined, (err, link) => {
expect(err).toBeUndefined();
expect(link).toEqual(srcFile);
done();
});
});
it("should fail to read real path", (done) => {
fs.realpath(tmpFile(), undefined, (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("rename", () => {
it("should rename file", (done) => {
const srcFile = createTmpFile();
const targetFile = tmpFile();
fs.rename(srcFile, targetFile, (err) => {
expect(err).toBeUndefined();
expect(nativeFs.existsSync(targetFile)).toBeTruthy();
done();
});
});
it("should fail to rename file", (done) => {
fs.rename(tmpFile(), tmpFile(), (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("rmdir", () => {
it("should rmdir", (done) => {
const srcFile = tmpFile();
nativeFs.mkdirSync(srcFile);
fs.rmdir(srcFile, (err) => {
expect(err).toBeUndefined();
expect(nativeFs.existsSync(srcFile)).toBeFalsy();
done();
});
});
it("should fail to rmdir", (done) => {
fs.rmdir(tmpFile(), (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("stat", () => {
it("should stat file", (done) => {
fs.stat(testFile, (err, stats) => {
expect(err).toBeUndefined();
expect(stats.size).toBeGreaterThan(0);
expect(stats.isFile()).toBeTruthy();
expect(stats.isFIFO()).toBeFalsy();
done();
});
});
it("should stat folder", (done) => {
const dir = tmpFile();
nativeFs.mkdirSync(dir);
fs.stat(dir, (err, stats) => {
expect(err).toBeUndefined();
expect(stats.isDirectory()).toBeTruthy();
done();
});
});
it("should fail to stat", (done) => {
fs.stat(path.join(__dirname, "no-exist"), (err, stats) => {
expect(err).toBeDefined();
expect(stats).toBeUndefined();
done();
});
});
});
describe("symlink", () => {
it("should symlink file", (done) => {
const newFile = createTmpFile();
const targetFile = tmpFile();
fs.symlink(newFile, targetFile, "file", (err) => {
expect(err).toBeUndefined();
expect(nativeFs.existsSync(targetFile)).toBeTruthy();
done();
});
});
it("should fail to symlink file", (done) => {
fs.symlink(tmpFile(), tmpFile(), "file", (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("truncate", () => {
it("should truncate file", (done) => {
const newFile = tmpFile();
nativeFs.writeFileSync(newFile, "hiiiiii");
fs.truncate(newFile, 2, (err) => {
expect(err).toBeUndefined();
expect(nativeFs.statSync(newFile).size).toEqual(2);
done();
});
});
it("should fail to truncate file", (done) => {
fs.truncate(tmpFile(), 0, (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("unlink", () => {
it("should unlink file", (done) => {
const newFile = createTmpFile();
const targetFile = tmpFile();
nativeFs.symlinkSync(newFile, targetFile, "file");
fs.unlink(targetFile, (err) => {
expect(err).toBeUndefined();
done();
});
});
it("should fail to unlink file", (done) => {
fs.unlink(tmpFile(), (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("utimes", () => {
it("should update times on file", (done) => {
fs.utimes(createTmpFile(), 100, 100, (err) => {
expect(err).toBeUndefined();
done();
});
});
it("should fail to update times", (done) => {
fs.utimes(tmpFile(), 100, 100, (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("write", () => {
it("should write to file", (done) => {
const file = createTmpFile();
const fd = nativeFs.openSync(file, "w");
fs.write(fd, Buffer.from("hi"), undefined, undefined, undefined, (err, written) => {
expect(err).toBeUndefined();
expect(written).toEqual(2);
nativeFs.closeSync(fd);
expect(nativeFs.readFileSync(file).toString()).toEqual("hi");
done();
});
});
it("should fail to write to file", (done) => {
fs.write(100000, Buffer.from("wowow"), undefined, undefined, undefined, (err) => {
expect(err).toBeDefined();
done();
});
});
});
describe("writeFile", () => {
it("should write file", (done) => {
fs.writeFile(createTmpFile(), "howdy", undefined, (err) => {
expect(err).toBeUndefined();
done();
});
});
});
});