aboutsummaryrefslogtreecommitdiff
path: root/test/js
diff options
context:
space:
mode:
authorGravatar Ciro Spaciari <ciro.spaciari@gmail.com> 2023-07-27 23:23:54 -0300
committerGravatar GitHub <noreply@github.com> 2023-07-27 19:23:54 -0700
commit7fa71dd032aa5dbbc531c5f113b63f7b0ae9e618 (patch)
tree0aef2dfcd95f722e7da75eb7077802ecf7edc6ec /test/js
parent52f39d728f44b153d771cdc2df4fbff8233ae1ea (diff)
downloadbun-7fa71dd032aa5dbbc531c5f113b63f7b0ae9e618.tar.gz
bun-7fa71dd032aa5dbbc531c5f113b63f7b0ae9e618.tar.zst
bun-7fa71dd032aa5dbbc531c5f113b63f7b0ae9e618.zip
Resolve watch directories outside main thread + async iterator and symlink fixes (#3846)
* linux working pending tests with FSEvents * add more tests, fix async iterator * remove unnecessary check * fix macos symlink on directories * remove indirection layer * todos * fixes and some permission test * fix opsie and make prisma test more reliable * rebase with main * add comptime check for macOS * oops * oops2 * fix symlinks cascade on FSEvents * use JSC.WorkPool * use withResolver, createFIFO and fix close event on async iterator * remove unused events --------- Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
Diffstat (limited to 'test/js')
-rw-r--r--test/js/node/watch/fs.watch.test.ts102
-rw-r--r--test/js/third_party/prisma/prisma.test.ts2
2 files changed, 100 insertions, 4 deletions
diff --git a/test/js/node/watch/fs.watch.test.ts b/test/js/node/watch/fs.watch.test.ts
index d228e5a22..5086ae1d8 100644
--- a/test/js/node/watch/fs.watch.test.ts
+++ b/test/js/node/watch/fs.watch.test.ts
@@ -374,9 +374,31 @@ describe("fs.watch", () => {
expect(promise).resolves.toBe("change");
});
- test("immediately closing works correctly", async () => {
- for (let i = 0; i < 100; i++) fs.watch(testDir, { persistent: true }).close();
- for (let i = 0; i < 100; i++) fs.watch(testDir, { persistent: false }).close();
+ test("should throw if no permission to watch the directory", async () => {
+ const filepath = path.join(testDir, "permission-dir");
+ fs.mkdirSync(filepath, { recursive: true });
+ await fs.promises.chmod(filepath, 0o200);
+ try {
+ const watcher = fs.watch(filepath);
+ watcher.close();
+ expect("unreacheable").toBe(false);
+ } catch (err: any) {
+ expect(err.message.indexOf("AccessDenied") !== -1).toBeTrue();
+ }
+ });
+
+ test("should throw if no permission to watch the file", async () => {
+ const filepath = path.join(testDir, "permission-file");
+ fs.writeFileSync(filepath, "hello.txt");
+ await fs.promises.chmod(filepath, 0o200);
+
+ try {
+ const watcher = fs.watch(filepath);
+ watcher.close();
+ expect("unreacheable").toBe(false);
+ } catch (err: any) {
+ expect(err.message.indexOf("AccessDenied") !== -1).toBeTrue();
+ }
});
});
@@ -502,6 +524,64 @@ describe("fs.promises.watch", () => {
})();
});
+ test("should work with symlink -> symlink -> dir", async () => {
+ const filepath = path.join(testDir, "sym-symlink-indirect");
+ const dest = path.join(testDir, "sym-symlink-dest");
+
+ fs.rmSync(filepath, { recursive: true, force: true });
+ fs.rmSync(dest, { recursive: true, force: true });
+ fs.mkdirSync(dest, { recursive: true });
+ await fs.promises.symlink(dest, filepath);
+ const indirect_sym = path.join(testDir, "sym-symlink-to-symlink-dir");
+ await fs.promises.symlink(filepath, indirect_sym);
+
+ const watcher = fs.promises.watch(indirect_sym);
+ const interval = setInterval(() => {
+ fs.writeFileSync(path.join(indirect_sym, "hello.txt"), "hello");
+ }, 10);
+
+ const promise = (async () => {
+ try {
+ for await (const event of watcher) {
+ return event.eventType;
+ }
+ } catch {
+ expect("unreacheable").toBe(false);
+ } finally {
+ clearInterval(interval);
+ }
+ })();
+ expect(promise).resolves.toBe("rename");
+ });
+
+ test("should work with symlink dir", async () => {
+ const filepath = path.join(testDir, "sym-symlink-dir");
+ const dest = path.join(testDir, "sym-symlink-dest");
+
+ fs.rmSync(filepath, { recursive: true, force: true });
+ fs.rmSync(dest, { recursive: true, force: true });
+ fs.mkdirSync(dest, { recursive: true });
+ await fs.promises.symlink(dest, filepath);
+
+ const watcher = fs.promises.watch(filepath);
+ const interval = setInterval(() => {
+ fs.writeFileSync(path.join(filepath, "hello.txt"), "hello");
+ }, 10);
+
+ const promise = (async () => {
+ try {
+ for await (const event of watcher) {
+ return event.eventType;
+ }
+ } catch {
+ expect("unreacheable").toBe(false);
+ } finally {
+ clearInterval(interval);
+ }
+ })();
+ expect(promise).resolves.toBe("rename");
+ });
+
test("should work with symlink", async () => {
const filepath = path.join(testDir, "sym-symlink.txt");
await fs.promises.symlink(path.join(testDir, "sym.txt"), filepath);
@@ -525,3 +605,19 @@ describe("fs.promises.watch", () => {
expect(promise).resolves.toBe("change");
});
});
+
+describe("immediately closing", () => {
+ test("works correctly with files", async () => {
+ const filepath = path.join(testDir, "close.txt");
+ for (let i = 0; i < 100; i++) fs.watch(filepath, { persistent: true }).close();
+ for (let i = 0; i < 100; i++) fs.watch(filepath, { persistent: false }).close();
+ });
+ test("works correctly with directories", async () => {
+ for (let i = 0; i < 100; i++) fs.watch(testDir, { persistent: true }).close();
+ for (let i = 0; i < 100; i++) fs.watch(testDir, { persistent: false }).close();
+ });
+ test("works correctly with recursive directories", async () => {
+ for (let i = 0; i < 100; i++) fs.watch(testDir, { persistent: true, recursive: true }).close();
+ for (let i = 0; i < 100; i++) fs.watch(testDir, { persistent: false, recursive: false }).close();
+ });
+});
diff --git a/test/js/third_party/prisma/prisma.test.ts b/test/js/third_party/prisma/prisma.test.ts
index d4e4b9cca..c77cfa52c 100644
--- a/test/js/third_party/prisma/prisma.test.ts
+++ b/test/js/third_party/prisma/prisma.test.ts
@@ -3,7 +3,7 @@ import { generateClient } from "./helper.ts";
import type { PrismaClient } from "./prisma/types.d.ts";
function* TestIDGenerator(): Generator<number> {
- let i = 0;
+ let i = Math.floor(Math.random() * 10000);
while (true) {
yield i++;
}