@zenfs/core 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/backends/backend.js +6 -5
- package/dist/backends/cow.d.ts +2 -2
- package/dist/backends/cow.js +39 -58
- package/dist/backends/fetch.js +27 -29
- package/dist/backends/passthrough.d.ts +2 -3
- package/dist/backends/passthrough.js +84 -199
- package/dist/backends/port.d.ts +16 -3
- package/dist/backends/port.js +61 -30
- package/dist/backends/single_buffer.d.ts +52 -46
- package/dist/backends/single_buffer.js +462 -219
- package/dist/backends/store/fs.d.ts +16 -10
- package/dist/backends/store/fs.js +227 -242
- package/dist/backends/store/store.d.ts +3 -3
- package/dist/backends/store/store.js +11 -10
- package/dist/config.d.ts +2 -2
- package/dist/config.js +10 -11
- package/dist/internal/devices.d.ts +2 -2
- package/dist/internal/devices.js +39 -49
- package/dist/internal/error.d.ts +9 -204
- package/dist/internal/error.js +19 -288
- package/dist/internal/file_index.d.ts +1 -1
- package/dist/internal/file_index.js +9 -9
- package/dist/internal/filesystem.d.ts +23 -8
- package/dist/internal/index.d.ts +1 -1
- package/dist/internal/index.js +1 -1
- package/dist/internal/index_fs.d.ts +2 -2
- package/dist/internal/index_fs.js +19 -19
- package/dist/internal/inode.d.ts +81 -103
- package/dist/internal/inode.js +336 -195
- package/dist/mixins/async.js +32 -28
- package/dist/mixins/mutexed.d.ts +4 -4
- package/dist/mixins/mutexed.js +39 -39
- package/dist/mixins/readonly.d.ts +2 -2
- package/dist/mixins/readonly.js +20 -20
- package/dist/mixins/sync.js +2 -2
- package/dist/polyfills.js +1 -1
- package/dist/readline.js +1 -1
- package/dist/utils.d.ts +8 -5
- package/dist/utils.js +14 -17
- package/dist/vfs/acl.d.ts +8 -8
- package/dist/vfs/acl.js +66 -47
- package/dist/vfs/async.d.ts +2 -2
- package/dist/vfs/async.js +6 -8
- package/dist/vfs/dir.d.ts +1 -1
- package/dist/vfs/dir.js +3 -4
- package/dist/vfs/file.js +33 -24
- package/dist/vfs/flags.js +3 -3
- package/dist/vfs/ioctl.d.ts +8 -7
- package/dist/vfs/ioctl.js +132 -27
- package/dist/vfs/promises.d.ts +3 -3
- package/dist/vfs/promises.js +200 -235
- package/dist/vfs/shared.d.ts +1 -12
- package/dist/vfs/shared.js +7 -35
- package/dist/vfs/streams.js +9 -9
- package/dist/vfs/sync.d.ts +1 -2
- package/dist/vfs/sync.js +158 -170
- package/dist/vfs/watchers.js +8 -8
- package/dist/vfs/xattr.js +89 -106
- package/package.json +4 -2
- package/scripts/test.js +2 -2
- package/tests/assignment.ts +1 -1
- package/tests/backend/port.test.ts +4 -4
- package/tests/backend/single-buffer.test.ts +39 -10
- package/tests/backend/single-buffer.worker.js +30 -0
- package/tests/common/context.test.ts +2 -2
- package/tests/common/mutex.test.ts +9 -9
- package/tests/fetch/fetch.ts +1 -1
- package/tests/fs/append.test.ts +4 -4
- package/tests/fs/directory.test.ts +25 -25
- package/tests/fs/errors.test.ts +15 -19
- package/tests/fs/links.test.ts +3 -2
- package/tests/fs/open.test.ts +4 -21
- package/tests/fs/permissions.test.ts +8 -13
- package/tests/fs/read.test.ts +10 -9
- package/tests/fs/readFile.test.ts +8 -24
- package/tests/fs/rename.test.ts +4 -9
- package/tests/fs/stat.test.ts +2 -2
- package/tests/fs/times.test.ts +6 -6
- package/tests/fs/truncate.test.ts +8 -36
- package/tests/fs/watch.test.ts +10 -10
- package/tests/fs/write.test.ts +77 -13
- package/tests/fs/xattr.test.ts +7 -7
- package/tests/logs.js +2 -2
- package/tests/setup/port.ts +6 -0
- package/dist/internal/log.d.ts +0 -139
- package/dist/internal/log.js +0 -219
- package/tests/fs/writeFile.test.ts +0 -70
package/tests/fs/errors.test.ts
CHANGED
|
@@ -1,36 +1,32 @@
|
|
|
1
1
|
import assert from 'node:assert/strict';
|
|
2
2
|
import test, { suite } from 'node:test';
|
|
3
3
|
import { fs } from '../common.js';
|
|
4
|
-
import type { ErrnoError } from '../../dist/index.js';
|
|
5
4
|
|
|
6
5
|
const existingFile = '/exit.js';
|
|
7
6
|
|
|
8
7
|
suite('Error messages', () => {
|
|
9
8
|
const path = '/non-existent';
|
|
10
9
|
|
|
11
|
-
fs.promises.stat(path).catch((error: ErrnoError) => {
|
|
12
|
-
assert.equal(error.bufferSize(), 4 + JSON.stringify(error.toJSON()).length);
|
|
13
|
-
});
|
|
14
|
-
|
|
15
10
|
const missing = { path, code: 'ENOENT' };
|
|
16
|
-
const existing = { path: existingFile };
|
|
11
|
+
const existing = { path: existingFile, code: 'EEXIST' };
|
|
12
|
+
const notDir = { path: existingFile, code: 'ENOTDIR' };
|
|
17
13
|
|
|
18
|
-
test('stat', () => assert.rejects(() => fs.promises.stat(path), missing));
|
|
19
|
-
test('mkdir', () => assert.rejects(() => fs.promises.mkdir(existingFile, 0o666), existing));
|
|
20
|
-
test('rmdir', () => assert.rejects(() => fs.promises.rmdir(path), missing));
|
|
21
|
-
test('rmdir', () => assert.rejects(() => fs.promises.rmdir(existingFile),
|
|
22
|
-
test('rename', () => assert.rejects(() => fs.promises.rename(path, 'foo'), missing));
|
|
23
|
-
test('open', () => assert.rejects(() => fs.promises.open(path, 'r'), missing));
|
|
24
|
-
test('readdir', () => assert.rejects(() => fs.promises.readdir(path), missing));
|
|
25
|
-
test('unlink', () => assert.rejects(() => fs.promises.unlink(path), missing));
|
|
26
|
-
test('link', () => assert.rejects(() => fs.promises.link(path, 'foo'), missing));
|
|
27
|
-
test('chmod', () => assert.rejects(() => fs.promises.chmod(path, 0o666), missing));
|
|
28
|
-
test('lstat', () => assert.rejects(() => fs.promises.lstat(path), missing));
|
|
29
|
-
test('readlink', () => assert.rejects(() => fs.promises.readlink(path), missing));
|
|
14
|
+
test('stat', async () => await assert.rejects(() => fs.promises.stat(path), missing));
|
|
15
|
+
test('mkdir', async () => await assert.rejects(() => fs.promises.mkdir(existingFile, 0o666), existing));
|
|
16
|
+
test('rmdir (missing)', async () => await assert.rejects(() => fs.promises.rmdir(path), missing));
|
|
17
|
+
test('rmdir (existing)', async () => await assert.rejects(() => fs.promises.rmdir(existingFile), notDir));
|
|
18
|
+
test('rename', async () => await assert.rejects(() => fs.promises.rename(path, 'foo'), missing));
|
|
19
|
+
test('open', async () => await assert.rejects(() => fs.promises.open(path, 'r'), missing));
|
|
20
|
+
test('readdir', async () => await assert.rejects(() => fs.promises.readdir(path), missing));
|
|
21
|
+
test('unlink', async () => await assert.rejects(() => fs.promises.unlink(path), missing));
|
|
22
|
+
test('link', async () => await assert.rejects(() => fs.promises.link(path, 'foo'), missing));
|
|
23
|
+
test('chmod', async () => await assert.rejects(() => fs.promises.chmod(path, 0o666), missing));
|
|
24
|
+
test('lstat', async () => await assert.rejects(() => fs.promises.lstat(path), missing));
|
|
25
|
+
test('readlink', async () => await assert.rejects(() => fs.promises.readlink(path), missing));
|
|
30
26
|
test('statSync', () => assert.throws(() => fs.statSync(path), missing));
|
|
31
27
|
test('mkdirSync', () => assert.throws(() => fs.mkdirSync(existingFile, 0o666), existing));
|
|
32
28
|
test('rmdirSync', () => assert.throws(() => fs.rmdirSync(path), missing));
|
|
33
|
-
test('rmdirSync', () => assert.throws(() => fs.rmdirSync(existingFile),
|
|
29
|
+
test('rmdirSync', () => assert.throws(() => fs.rmdirSync(existingFile), notDir));
|
|
34
30
|
test('renameSync', () => assert.throws(() => fs.renameSync(path, 'foo'), missing));
|
|
35
31
|
test('openSync', () => assert.throws(() => fs.openSync(path, 'r'), missing));
|
|
36
32
|
test('readdirSync', () => assert.throws(() => fs.readdirSync(path), missing));
|
package/tests/fs/links.test.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import type { Exception } from 'kerium';
|
|
1
2
|
import assert from 'node:assert/strict';
|
|
2
3
|
import { suite, test } from 'node:test';
|
|
3
4
|
import { join } from '../../dist/path.js';
|
|
4
5
|
import { fs } from '../common.js';
|
|
5
|
-
import type { ErrnoError } from '../../dist/index.js';
|
|
6
6
|
|
|
7
7
|
suite('Links', () => {
|
|
8
8
|
const target = '/a1.js',
|
|
@@ -21,6 +21,7 @@ suite('Links', () => {
|
|
|
21
21
|
test('readlink', async () => {
|
|
22
22
|
const destination = await fs.promises.readlink(symlink);
|
|
23
23
|
assert.equal(destination, target);
|
|
24
|
+
assert.throws(() => fs.readlinkSync(destination));
|
|
24
25
|
});
|
|
25
26
|
|
|
26
27
|
test('read target contents', async () => {
|
|
@@ -59,7 +60,7 @@ suite('Links', () => {
|
|
|
59
60
|
});
|
|
60
61
|
|
|
61
62
|
test('link', async t => {
|
|
62
|
-
const _ = await fs.promises.link(target, hardlink).catch((e:
|
|
63
|
+
const _ = await fs.promises.link(target, hardlink).catch((e: Exception) => {
|
|
63
64
|
if (e.code == 'ENOSYS') return e;
|
|
64
65
|
throw e;
|
|
65
66
|
});
|
package/tests/fs/open.test.ts
CHANGED
|
@@ -1,30 +1,13 @@
|
|
|
1
1
|
import assert from 'node:assert/strict';
|
|
2
2
|
import { suite, test } from 'node:test';
|
|
3
|
-
import { ErrnoError } from '../../dist/index.js';
|
|
4
3
|
import { fs } from '../common.js';
|
|
5
4
|
|
|
6
|
-
suite('
|
|
5
|
+
suite('Opening files', () => {
|
|
7
6
|
const filename = 'a.js';
|
|
8
7
|
|
|
9
|
-
test('throw ENOENT when opening non-existent file
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
fs.openSync('/path/to/file/that/does/not/exist', 'r');
|
|
13
|
-
} catch (error: any) {
|
|
14
|
-
assert(error instanceof ErrnoError);
|
|
15
|
-
assert.equal(error?.code, 'ENOENT');
|
|
16
|
-
caughtException = true;
|
|
17
|
-
}
|
|
18
|
-
assert(caughtException);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
test('throw ENOENT when opening non-existent file (async)', async () => {
|
|
22
|
-
try {
|
|
23
|
-
await fs.promises.open('/path/to/file/that/does/not/exist', 'r');
|
|
24
|
-
} catch (error: any) {
|
|
25
|
-
assert(error instanceof ErrnoError);
|
|
26
|
-
assert.equal(error?.code, 'ENOENT');
|
|
27
|
-
}
|
|
8
|
+
test('throw ENOENT when opening non-existent file', async () => {
|
|
9
|
+
assert.throws(() => fs.openSync('/path/to/file/that/does/not/exist', 'r'), { code: 'ENOENT' });
|
|
10
|
+
await assert.rejects(fs.promises.open('/path/to/file/that/does/not/exist', 'r'), { code: 'ENOENT' });
|
|
28
11
|
});
|
|
29
12
|
|
|
30
13
|
test('open file with mode "r"', async () => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { Exception } from 'kerium';
|
|
1
2
|
import assert from 'node:assert/strict';
|
|
2
3
|
import { suite, test } from 'node:test';
|
|
3
4
|
import { encodeUTF8 } from 'utilium';
|
|
4
|
-
import { ErrnoError } from '../../dist/index.js';
|
|
5
5
|
import { defaultContext } from '../../dist/internal/contexts.js';
|
|
6
6
|
import { join } from '../../dist/path.js';
|
|
7
7
|
import { R_OK, W_OK, X_OK } from '../../dist/vfs/constants.js';
|
|
@@ -48,19 +48,16 @@ suite('Permissions', () => {
|
|
|
48
48
|
});
|
|
49
49
|
|
|
50
50
|
async function test_item(path: string): Promise<void> {
|
|
51
|
-
const stats = await fs.promises.stat(path).catch((error:
|
|
52
|
-
assert(error instanceof
|
|
51
|
+
const stats = await fs.promises.stat(path).catch((error: Exception) => {
|
|
52
|
+
assert(error instanceof Exception);
|
|
53
53
|
assert.equal(error.code, 'EACCES');
|
|
54
54
|
});
|
|
55
|
-
if (!stats)
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
55
|
+
if (!stats) return;
|
|
58
56
|
assert(stats.hasAccess(X_OK));
|
|
59
57
|
|
|
60
58
|
function checkError(access: number) {
|
|
61
|
-
return function (error:
|
|
62
|
-
assert(error instanceof
|
|
63
|
-
assert(error);
|
|
59
|
+
return function (error: Exception) {
|
|
60
|
+
assert(error instanceof Exception);
|
|
64
61
|
assert(!stats!.hasAccess(access));
|
|
65
62
|
};
|
|
66
63
|
}
|
|
@@ -80,12 +77,10 @@ suite('Permissions', () => {
|
|
|
80
77
|
await fs.promises.unlink(testFile).catch(checkError(W_OK));
|
|
81
78
|
} else {
|
|
82
79
|
const handle = await fs.promises.open(path, 'a').catch(checkError(W_OK));
|
|
83
|
-
if (!handle)
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
80
|
+
if (!handle) return;
|
|
86
81
|
await handle.close();
|
|
87
82
|
}
|
|
88
|
-
assert(stats.hasAccess(
|
|
83
|
+
assert(stats.hasAccess(W_OK));
|
|
89
84
|
}
|
|
90
85
|
|
|
91
86
|
const copy = { ...defaultContext.credentials };
|
package/tests/fs/read.test.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { Buffer } from 'buffer';
|
|
1
2
|
import assert from 'node:assert/strict';
|
|
2
3
|
import { suite, test } from 'node:test';
|
|
3
4
|
import { fs } from '../common.js';
|
|
4
|
-
import { Buffer } from 'buffer';
|
|
5
5
|
|
|
6
6
|
const filepath = 'x.txt';
|
|
7
7
|
const expected = 'xyz\n';
|
|
8
|
+
const ellipses = '…'.repeat(10_000);
|
|
8
9
|
|
|
9
10
|
suite('read', () => {
|
|
10
11
|
test('read file asynchronously', async () => {
|
|
@@ -22,25 +23,25 @@ suite('read', () => {
|
|
|
22
23
|
assert.equal(bytesRead, expected.length);
|
|
23
24
|
assert.equal(buffer.toString(), expected);
|
|
24
25
|
});
|
|
25
|
-
});
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
test('Read a file and check its binary bytes (asynchronous)', async () => {
|
|
27
|
+
test('Read a file and check its binary bytes asynchronously', async () => {
|
|
29
28
|
const buff = await fs.promises.readFile('elipses.txt');
|
|
29
|
+
assert.equal(buff.length, 30_000);
|
|
30
|
+
assert.equal(buff.toString(), ellipses);
|
|
30
31
|
assert.equal((buff[1] << 8) | buff[0], 32994);
|
|
31
32
|
});
|
|
32
33
|
|
|
33
|
-
test('Read a file and check its binary bytes
|
|
34
|
+
test('Read a file and check its binary bytes synchronously', () => {
|
|
34
35
|
const buff = fs.readFileSync('elipses.txt');
|
|
36
|
+
assert.equal(buff.length, 30_000);
|
|
37
|
+
assert.equal(buff.toString(), ellipses);
|
|
35
38
|
assert.equal((buff[1] << 8) | buff[0], 32994);
|
|
36
39
|
});
|
|
37
|
-
});
|
|
38
40
|
|
|
39
|
-
suite('read buffer', () => {
|
|
40
41
|
const bufferAsync = Buffer.alloc(expected.length);
|
|
41
42
|
const bufferSync = Buffer.alloc(expected.length);
|
|
42
43
|
|
|
43
|
-
test('read file asynchronously', async () => {
|
|
44
|
+
test('read file from handle asynchronously', async () => {
|
|
44
45
|
const handle = await fs.promises.open(filepath, 'r');
|
|
45
46
|
const { bytesRead } = await handle.read(bufferAsync, 0, expected.length, 0);
|
|
46
47
|
|
|
@@ -48,7 +49,7 @@ suite('read buffer', () => {
|
|
|
48
49
|
assert.equal(bufferAsync.toString(), expected);
|
|
49
50
|
});
|
|
50
51
|
|
|
51
|
-
test('read file synchronously', () => {
|
|
52
|
+
test('read file from handle synchronously', () => {
|
|
52
53
|
const fd = fs.openSync(filepath, 'r');
|
|
53
54
|
const bytesRead = fs.readSync(fd, bufferSync, 0, expected.length, 0);
|
|
54
55
|
|
|
@@ -4,7 +4,7 @@ import { fs } from '../common.js';
|
|
|
4
4
|
|
|
5
5
|
suite('Reading', () => {
|
|
6
6
|
test('Cannot read a file with an invalid encoding', () => {
|
|
7
|
-
assert.throws(() => fs.readFileSync('a.js', '
|
|
7
|
+
assert.throws(() => fs.readFileSync('a.js', 'wrong-encoding' as BufferEncoding));
|
|
8
8
|
});
|
|
9
9
|
|
|
10
10
|
test('Reading past the end of a file should not be an error', async () => {
|
|
@@ -12,9 +12,7 @@ suite('Reading', () => {
|
|
|
12
12
|
const { bytesRead } = await handle.read(new Uint8Array(10), 0, 10, 10000);
|
|
13
13
|
assert.equal(bytesRead, 0);
|
|
14
14
|
});
|
|
15
|
-
});
|
|
16
15
|
|
|
17
|
-
suite('Read and Unlink', () => {
|
|
18
16
|
const dir = 'test-readfile-unlink';
|
|
19
17
|
const file = 'test-readfile-unlink/test.bin';
|
|
20
18
|
const data = new Uint8Array(512).fill(42);
|
|
@@ -34,33 +32,19 @@ suite('Read and Unlink', () => {
|
|
|
34
32
|
await fs.promises.unlink(file);
|
|
35
33
|
await fs.promises.rmdir(dir);
|
|
36
34
|
});
|
|
37
|
-
});
|
|
38
35
|
|
|
39
|
-
|
|
40
|
-
const fn = 'empty.txt';
|
|
41
|
-
|
|
42
|
-
test('read file asynchronously', async () => {
|
|
43
|
-
const data: Uint8Array = await fs.promises.readFile(fn);
|
|
44
|
-
assert(data != undefined);
|
|
45
|
-
});
|
|
36
|
+
const fileName = 'empty.txt';
|
|
46
37
|
|
|
47
|
-
test('read file
|
|
48
|
-
|
|
49
|
-
assert.equal(
|
|
38
|
+
test('read file', async () => {
|
|
39
|
+
assert.equal((await fs.promises.readFile(fileName)).toString(), '');
|
|
40
|
+
assert.equal(fs.readFileSync(fileName).toString(), '');
|
|
50
41
|
});
|
|
51
42
|
|
|
52
|
-
test('read file
|
|
53
|
-
|
|
54
|
-
assert(
|
|
43
|
+
test('read file with utf-8 encoding', async () => {
|
|
44
|
+
assert.equal(await fs.promises.readFile(fileName, 'utf8'), '');
|
|
45
|
+
assert.equal(fs.readFileSync(fileName, 'utf8'), '');
|
|
55
46
|
});
|
|
56
47
|
|
|
57
|
-
test('read file with utf-8 encoding synchronously', () => {
|
|
58
|
-
const data: string = fs.readFileSync(fn, 'utf8');
|
|
59
|
-
assert.equal(data, '');
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
suite('fs file reading', () => {
|
|
64
48
|
test('read file synchronously and verify the content', () => {
|
|
65
49
|
const content = fs.readFileSync('elipses.txt', 'utf8');
|
|
66
50
|
|
package/tests/fs/rename.test.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import assert from 'node:assert/strict';
|
|
2
2
|
import { suite, test } from 'node:test';
|
|
3
|
-
import { ErrnoError } from '../../dist/index.js';
|
|
4
3
|
import { fs } from '../common.js';
|
|
5
4
|
|
|
6
5
|
suite('Rename', () => {
|
|
@@ -77,10 +76,8 @@ suite('Rename', () => {
|
|
|
77
76
|
await fs.promises.mkdir(dir);
|
|
78
77
|
await fs.promises.writeFile(file, 'file contents go here');
|
|
79
78
|
|
|
80
|
-
await fs.promises.rename(file, dir)
|
|
81
|
-
|
|
82
|
-
assert.match(error.code, /EISDIR|EPERM/);
|
|
83
|
-
});
|
|
79
|
+
await assert.rejects(fs.promises.rename(file, dir), { code: 'EISDIR' });
|
|
80
|
+
assert.throws(() => fs.renameSync(file, dir), { code: 'EISDIR' });
|
|
84
81
|
});
|
|
85
82
|
|
|
86
83
|
test('rename directory inside itself', async () => {
|
|
@@ -89,9 +86,7 @@ suite('Rename', () => {
|
|
|
89
86
|
|
|
90
87
|
await fs.promises.mkdir(renDir1);
|
|
91
88
|
|
|
92
|
-
await fs.promises.rename(renDir1, renDir2)
|
|
93
|
-
|
|
94
|
-
assert.equal(error.code, 'EBUSY');
|
|
95
|
-
});
|
|
89
|
+
await assert.rejects(fs.promises.rename(renDir1, renDir2), { code: 'EBUSY' });
|
|
90
|
+
assert.throws(() => fs.renameSync(renDir1, renDir2), { code: 'EBUSY' });
|
|
96
91
|
});
|
|
97
92
|
});
|
package/tests/fs/stat.test.ts
CHANGED
|
@@ -7,8 +7,8 @@ import { fs } from '../common.js';
|
|
|
7
7
|
suite('Stats', () => {
|
|
8
8
|
const existing_file = 'x.txt';
|
|
9
9
|
|
|
10
|
-
test('stat empty path', () => {
|
|
11
|
-
assert.rejects(fs.promises.stat(''));
|
|
10
|
+
test('stat empty path', async () => {
|
|
11
|
+
await assert.rejects(fs.promises.stat(''));
|
|
12
12
|
});
|
|
13
13
|
|
|
14
14
|
test('stat directory', async () => {
|
package/tests/fs/times.test.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { Exception } from 'kerium';
|
|
1
2
|
import assert from 'node:assert/strict';
|
|
2
3
|
import { suite, test } from 'node:test';
|
|
3
4
|
import { wait } from 'utilium';
|
|
4
|
-
import { ErrnoError } from '../../dist/index.js';
|
|
5
5
|
import type { StatsLike } from '../../dist/vfs/stats.js';
|
|
6
6
|
import { fs } from '../common.js';
|
|
7
7
|
|
|
@@ -19,7 +19,7 @@ export function unixTimestamps(stats: StatsLike<number>): Record<'atime' | 'mtim
|
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
suite('
|
|
22
|
+
suite('Times', () => {
|
|
23
23
|
async function runTest(atime: Date | number, mtime: Date | number): Promise<void> {
|
|
24
24
|
const times = {
|
|
25
25
|
atime: typeof atime == 'number' ? Math.floor(atime) : atime.getTime(),
|
|
@@ -30,8 +30,8 @@ suite('times', () => {
|
|
|
30
30
|
|
|
31
31
|
assert.deepEqual(unixTimestamps(await fs.promises.stat(path)), times);
|
|
32
32
|
|
|
33
|
-
await fs.promises.utimes('foobarbaz', atime, mtime).catch((error:
|
|
34
|
-
assert(error instanceof
|
|
33
|
+
await fs.promises.utimes('foobarbaz', atime, mtime).catch((error: Exception) => {
|
|
34
|
+
assert(error instanceof Exception);
|
|
35
35
|
assert.equal(error.code, 'ENOENT');
|
|
36
36
|
});
|
|
37
37
|
|
|
@@ -46,14 +46,14 @@ suite('times', () => {
|
|
|
46
46
|
try {
|
|
47
47
|
fs.utimesSync('foobarbaz', atime, mtime);
|
|
48
48
|
} catch (error: any) {
|
|
49
|
-
assert(error instanceof
|
|
49
|
+
assert(error instanceof Exception);
|
|
50
50
|
assert.equal(error.code, 'ENOENT');
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
try {
|
|
54
54
|
fs.futimesSync(-1, atime, mtime);
|
|
55
55
|
} catch (error: any) {
|
|
56
|
-
assert(error instanceof
|
|
56
|
+
assert(error instanceof Exception);
|
|
57
57
|
assert.equal(error.code, 'EBADF');
|
|
58
58
|
}
|
|
59
59
|
}
|
|
@@ -1,94 +1,66 @@
|
|
|
1
1
|
import assert from 'node:assert/strict';
|
|
2
2
|
import { suite, test } from 'node:test';
|
|
3
3
|
import { fs } from '../common.js';
|
|
4
|
-
import type { FileHandle } from '../../dist/vfs/promises.js';
|
|
5
4
|
|
|
6
5
|
const path: string = 'truncate-file.txt',
|
|
7
6
|
size = 1024 * 16,
|
|
8
7
|
data = new Uint8Array(size).fill('x'.charCodeAt(0));
|
|
9
8
|
|
|
10
|
-
suite('
|
|
11
|
-
test('
|
|
9
|
+
suite('Truncating', () => {
|
|
10
|
+
test('Sync path functions', () => {
|
|
12
11
|
fs.writeFileSync(path, data);
|
|
13
12
|
assert.equal(fs.statSync(path).size, size);
|
|
14
|
-
});
|
|
15
13
|
|
|
16
|
-
test('truncate to 1024', () => {
|
|
17
14
|
fs.truncateSync(path, 1024);
|
|
18
15
|
assert.equal(fs.statSync(path).size, 1024);
|
|
19
|
-
});
|
|
20
16
|
|
|
21
|
-
test('truncate to 0', () => {
|
|
22
17
|
fs.truncateSync(path);
|
|
23
18
|
assert.equal(fs.statSync(path).size, 0);
|
|
24
|
-
});
|
|
25
19
|
|
|
26
|
-
test('write', () => {
|
|
27
20
|
fs.writeFileSync(path, data);
|
|
28
21
|
assert.equal(fs.statSync(path).size, size);
|
|
29
22
|
});
|
|
30
23
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
fd = fs.openSync(path, 'r+');
|
|
34
|
-
});
|
|
24
|
+
test('FD functions', () => {
|
|
25
|
+
const fd = fs.openSync(path, 'r+');
|
|
35
26
|
|
|
36
|
-
test('ftruncate to 1024', () => {
|
|
37
27
|
fs.ftruncateSync(fd, 1024);
|
|
38
28
|
assert.equal(fs.fstatSync(fd).size, 1024);
|
|
39
|
-
});
|
|
40
29
|
|
|
41
|
-
test('ftruncate to 0', () => {
|
|
42
30
|
fs.ftruncateSync(fd);
|
|
43
31
|
assert.equal(fs.fstatSync(fd).size, 0);
|
|
44
|
-
});
|
|
45
32
|
|
|
46
|
-
test('close fd', () => {
|
|
47
33
|
fs.closeSync(fd);
|
|
48
34
|
});
|
|
49
|
-
|
|
50
|
-
suite('Truncate, async', () => {
|
|
35
|
+
|
|
51
36
|
const statSize = async (path: string) => (await fs.promises.stat(path)).size;
|
|
52
37
|
|
|
53
|
-
test('
|
|
38
|
+
test('Async path functions', async () => {
|
|
54
39
|
await fs.promises.writeFile(path, data);
|
|
55
40
|
|
|
56
41
|
assert.equal(await statSize(path), 1024 * 16);
|
|
57
|
-
});
|
|
58
42
|
|
|
59
|
-
test('truncate to 1024', async () => {
|
|
60
43
|
await fs.promises.truncate(path, 1024);
|
|
61
44
|
assert.equal(await statSize(path), 1024);
|
|
62
|
-
});
|
|
63
45
|
|
|
64
|
-
test('truncate to 0', async () => {
|
|
65
46
|
await fs.promises.truncate(path);
|
|
66
47
|
assert.equal(await statSize(path), 0);
|
|
67
|
-
});
|
|
68
48
|
|
|
69
|
-
test('write', async () => {
|
|
70
49
|
await fs.promises.writeFile(path, data);
|
|
71
50
|
assert.equal(await statSize(path), size);
|
|
72
51
|
});
|
|
73
52
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
handle = await fs.promises.open(path, 'w');
|
|
77
|
-
});
|
|
53
|
+
test('FileHandle', async () => {
|
|
54
|
+
const handle = await fs.promises.open(path, 'w');
|
|
78
55
|
|
|
79
|
-
test('handle.truncate to 1024', async () => {
|
|
80
56
|
await handle.truncate(1024);
|
|
81
57
|
await handle.sync();
|
|
82
58
|
assert.equal(await statSize(path), 1024);
|
|
83
|
-
});
|
|
84
59
|
|
|
85
|
-
test('handle.truncate to 0', async () => {
|
|
86
60
|
await handle.truncate();
|
|
87
61
|
await handle.sync();
|
|
88
62
|
assert.equal(await statSize(path), 0);
|
|
89
|
-
});
|
|
90
63
|
|
|
91
|
-
test('close handle', async () => {
|
|
92
64
|
await handle.close();
|
|
93
65
|
});
|
|
94
66
|
});
|
package/tests/fs/watch.test.ts
CHANGED
|
@@ -11,8 +11,8 @@ await fs.promises.writeFile(testFile, 'Initial content');
|
|
|
11
11
|
/**
|
|
12
12
|
* @todo convert using watcher to void discards pending ES proposal
|
|
13
13
|
*/
|
|
14
|
-
await suite('Watch
|
|
15
|
-
test('
|
|
14
|
+
await suite('Watch', () => {
|
|
15
|
+
test('Events emitted on file change', async () => {
|
|
16
16
|
const { promise, resolve } = Promise.withResolvers<[string, string]>();
|
|
17
17
|
|
|
18
18
|
using watcher = fs.watch(testFile, (eventType, filename) => {
|
|
@@ -27,7 +27,7 @@ await suite('Watch Features', () => {
|
|
|
27
27
|
assert.equal(filename, 'test.txt');
|
|
28
28
|
});
|
|
29
29
|
|
|
30
|
-
test('
|
|
30
|
+
test('Events are emitted on delete', async () => {
|
|
31
31
|
using watcher = fs.watch(testFile, (eventType, filename) => {
|
|
32
32
|
assert.equal(eventType, 'rename');
|
|
33
33
|
assert.equal(filename, 'test.txt');
|
|
@@ -37,7 +37,7 @@ await suite('Watch Features', () => {
|
|
|
37
37
|
await fs.promises.unlink(testFile);
|
|
38
38
|
});
|
|
39
39
|
|
|
40
|
-
test('
|
|
40
|
+
test('Changes are detected with watchFile()', async () => {
|
|
41
41
|
const listener = (curr: Stats, prev: Stats) => {
|
|
42
42
|
assert(curr.mtimeMs != prev.mtimeMs);
|
|
43
43
|
fs.unwatchFile(testFile, listener);
|
|
@@ -49,7 +49,7 @@ await suite('Watch Features', () => {
|
|
|
49
49
|
await fs.promises.writeFile(testFile, 'Changed content');
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
-
test('
|
|
52
|
+
test('unwatchFile() works', async () => {
|
|
53
53
|
let changeDetected = false;
|
|
54
54
|
|
|
55
55
|
const listener = () => {
|
|
@@ -66,7 +66,7 @@ await suite('Watch Features', () => {
|
|
|
66
66
|
assert(!changeDetected);
|
|
67
67
|
});
|
|
68
68
|
|
|
69
|
-
test('
|
|
69
|
+
test('Directories can be watched', async () => {
|
|
70
70
|
using watcher = fs.watch(testDir, (eventType, filename) => {
|
|
71
71
|
assert.equal(eventType, 'change');
|
|
72
72
|
assert.equal(filename, 'newFile.txt');
|
|
@@ -75,7 +75,7 @@ await suite('Watch Features', () => {
|
|
|
75
75
|
await fs.promises.writeFile(testDir + '/newFile.txt', 'Content');
|
|
76
76
|
});
|
|
77
77
|
|
|
78
|
-
test('
|
|
78
|
+
test('File renames are detected', async () => {
|
|
79
79
|
const oldFileName = 'oldFile.txt';
|
|
80
80
|
const newFileName = 'newFile.txt';
|
|
81
81
|
const oldFile = testDir + '/' + oldFileName;
|
|
@@ -102,7 +102,7 @@ await suite('Watch Features', () => {
|
|
|
102
102
|
await Promise.all([newFileResolver.promise, oldFileResolver.promise]);
|
|
103
103
|
});
|
|
104
104
|
|
|
105
|
-
test('
|
|
105
|
+
test('File deletions are detected', async () => {
|
|
106
106
|
const tempFile = `${testDir}/tempFile.txt`;
|
|
107
107
|
|
|
108
108
|
await fs.promises.writeFile(tempFile, 'Temporary content');
|
|
@@ -115,7 +115,7 @@ await suite('Watch Features', () => {
|
|
|
115
115
|
await fs.promises.unlink(tempFile);
|
|
116
116
|
});
|
|
117
117
|
|
|
118
|
-
test('
|
|
118
|
+
test('File deletions are detected by promises API', async () => {
|
|
119
119
|
const tempFile = `${testDir}/tempFile.txt`;
|
|
120
120
|
|
|
121
121
|
await fs.promises.writeFile(tempFile, 'Temporary content');
|
|
@@ -135,7 +135,7 @@ await suite('Watch Features', () => {
|
|
|
135
135
|
await promise;
|
|
136
136
|
});
|
|
137
137
|
|
|
138
|
-
test('
|
|
138
|
+
test('File creations are detected recursively', async () => {
|
|
139
139
|
const subDir = `${testDir}/sub-dir`;
|
|
140
140
|
const tempFile = `${subDir}/tempFile.txt`;
|
|
141
141
|
await fs.promises.mkdir(subDir);
|