diff options
author | 2023-07-27 23:23:54 -0300 | |
---|---|---|
committer | 2023-07-27 19:23:54 -0700 | |
commit | 7fa71dd032aa5dbbc531c5f113b63f7b0ae9e618 (patch) | |
tree | 0aef2dfcd95f722e7da75eb7077802ecf7edc6ec /test/js | |
parent | 52f39d728f44b153d771cdc2df4fbff8233ae1ea (diff) | |
download | bun-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.ts | 102 | ||||
-rw-r--r-- | test/js/third_party/prisma/prisma.test.ts | 2 |
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++; } |