@zenfs/core 2.6.2 → 2.6.4
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/README.md +1 -1
- package/dist/backends/single_buffer.js +34 -11
- package/dist/context.js +1 -0
- package/dist/internal/contexts.d.ts +3 -1
- package/dist/internal/contexts.js +11 -1
- package/dist/internal/inode.d.ts +2 -0
- package/dist/internal/inode.js +2 -0
- package/dist/internal/rpc.d.ts +4 -4
- package/dist/node/async.d.ts +11 -1
- package/dist/node/async.js +14 -35
- package/dist/node/index.d.ts +1 -0
- package/dist/node/index.js +1 -0
- package/dist/node/promises.d.ts +17 -3
- package/dist/node/promises.js +32 -16
- package/dist/node/stats.d.ts +12 -0
- package/dist/node/stats.js +35 -6
- package/dist/node/sync.d.ts +39 -11
- package/dist/node/sync.js +41 -17
- package/dist/node/utf8stream.d.ts +99 -0
- package/dist/node/utf8stream.js +690 -0
- package/dist/utils.d.ts +10 -0
- package/dist/utils.js +17 -0
- package/dist/vfs/shared.js +9 -7
- package/package.json +14 -10
- package/scripts/test.js +15 -8
- package/tests/backend/single-buffer-rotate.worker.js +19 -0
- package/tests/backend/single-buffer.test.ts +106 -0
- package/tests/common/context.test.ts +38 -0
- package/tests/common/glob.test.ts +86 -1
- package/tests/common/utf8stream.test.ts +164 -0
- package/tests/common.ts +4 -2
- package/tests/fetch/fetch.ts +1 -1
- package/tests/fetch/run.sh +1 -1
- package/tests/fs/append.test.ts +1 -1
- package/tests/fs/concurrency.test.ts +1 -1
- package/tests/fs/dir.test.ts +1 -1
- package/tests/fs/directory.test.ts +3 -3
- package/tests/fs/errors.test.ts +1 -1
- package/tests/fs/exists.test.ts +3 -3
- package/tests/fs/links.test.ts +5 -5
- package/tests/fs/open.test.ts +5 -5
- package/tests/fs/permissions.test.ts +5 -5
- package/tests/fs/read.test.ts +3 -3
- package/tests/fs/readFile.test.ts +2 -2
- package/tests/fs/rename.test.ts +5 -5
- package/tests/fs/scaling.test.ts +1 -1
- package/tests/fs/stat.test.ts +32 -3
- package/tests/fs/streams.test.ts +1 -1
- package/tests/fs/tempdir.test.ts +1 -1
- package/tests/fs/times.test.ts +2 -2
- package/tests/fs/truncate.test.ts +1 -1
- package/tests/fs/watch.test.ts +1 -1
- package/tests/fs/write.test.ts +2 -2
- package/tests/fs/xattr.test.ts +1 -1
- package/tests/{native/setup.ts → native-setup.ts} +5 -5
- package/tests/setup/context.ts +1 -1
- package/tests/setup/cow.ts +1 -1
- package/tests/setup/index.ts +1 -1
- package/tests/setup/memory.ts +1 -1
- package/tests/setup/port.ts +1 -1
- package/tests/setup/single-buffer.ts +1 -1
- package/tests/setup.ts +1 -1
- package/tests/tsconfig.json +2 -1
- package/tests/native/run.sh +0 -3
package/tests/common.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
2
2
|
import { fs as defaultFS } from '@zenfs/core';
|
|
3
|
-
import type { NodeFS } from '@zenfs/core/node/types
|
|
3
|
+
import type { NodeFS } from '@zenfs/core/node/types';
|
|
4
4
|
import { join, resolve } from 'node:path';
|
|
5
5
|
import { styleText } from 'node:util';
|
|
6
6
|
import { setupLogs } from './logs.js';
|
|
@@ -41,7 +41,9 @@ export type TestFlag =
|
|
|
41
41
|
| 'xattr'
|
|
42
42
|
| 'times'
|
|
43
43
|
| 'tempdir'
|
|
44
|
-
| 'lchmod'
|
|
44
|
+
| 'lchmod'
|
|
45
|
+
| 'promises.exists'
|
|
46
|
+
| 'root';
|
|
45
47
|
|
|
46
48
|
/**
|
|
47
49
|
* Whether a backend supports a flag.
|
package/tests/fetch/fetch.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { configure, Fetch } from '@zenfs/core';
|
|
2
2
|
import { log } from 'kerium';
|
|
3
|
-
import type { TestFlag, TestFlagState } from '../common.
|
|
3
|
+
import type { TestFlag, TestFlagState } from '../common.ts';
|
|
4
4
|
import { baseUrl } from './config.js';
|
|
5
5
|
|
|
6
6
|
await configure({
|
package/tests/fetch/run.sh
CHANGED
package/tests/fs/append.test.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
3
|
import { suite, test } from 'node:test';
|
|
4
|
-
import { fs, config } from '../common.
|
|
4
|
+
import { fs, config } from '../common.ts';
|
|
5
5
|
|
|
6
6
|
const content = 'Sample content',
|
|
7
7
|
original = 'ABCD';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
3
|
import { suite, test } from 'node:test';
|
|
4
|
-
import { config, fs } from '../common.
|
|
4
|
+
import { config, fs } from '../common.ts';
|
|
5
5
|
|
|
6
6
|
suite('Concurrency', config('write', 'async'), () => {
|
|
7
7
|
test('parallel writeFile in the same directory does not lose entries #256', async () => {
|
package/tests/fs/dir.test.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { sync, type Dirent } from '@zenfs/core';
|
|
3
3
|
import assert, { rejects } from 'node:assert/strict';
|
|
4
4
|
import { suite, test } from 'node:test';
|
|
5
|
-
import { config, fs } from '../common.
|
|
5
|
+
import { config, fs } from '../common.ts';
|
|
6
6
|
|
|
7
7
|
const testFile = 'test-file.txt';
|
|
8
8
|
fs.writeFileSync(testFile, 'Sample content');
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
3
|
import { join } from 'node:path/posix';
|
|
4
4
|
import { suite, test } from 'node:test';
|
|
5
|
-
import { config, fs } from '../common.
|
|
5
|
+
import { config, fs } from '../common.ts';
|
|
6
6
|
|
|
7
7
|
const testDir = 'test-dir';
|
|
8
8
|
const testFiles = ['file1.txt', 'file2.txt', 'file3.txt'];
|
|
@@ -22,7 +22,7 @@ for (const dir of testDirectories) {
|
|
|
22
22
|
suite('Directories', config('directories'), () => {
|
|
23
23
|
test('mkdir', config('async'), async () => {
|
|
24
24
|
await fs.promises.mkdir('/one', 0o755);
|
|
25
|
-
assert(await fs.promises.
|
|
25
|
+
assert(await fs.promises.stat('/one', { throwIfNoEntry: false }));
|
|
26
26
|
await assert.rejects(fs.promises.mkdir('/one', 0o755), { code: 'EEXIST' });
|
|
27
27
|
});
|
|
28
28
|
|
|
@@ -30,7 +30,7 @@ suite('Directories', config('directories'), () => {
|
|
|
30
30
|
|
|
31
31
|
test('mkdir, nested', config('async'), async () => {
|
|
32
32
|
await assert.rejects(fs.promises.mkdir('/nested/dir'), { code: 'ENOENT', path: '/nested/dir' });
|
|
33
|
-
assert(!(await fs.promises.
|
|
33
|
+
assert(!(await fs.promises.stat('/nested/dir', { throwIfNoEntry: false })));
|
|
34
34
|
});
|
|
35
35
|
|
|
36
36
|
test('mkdir, recursive', config('async'), async () => {
|
package/tests/fs/errors.test.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
3
|
import test, { suite } from 'node:test';
|
|
4
|
-
import { config, fs } from '../common.
|
|
4
|
+
import { config, fs } from '../common.ts';
|
|
5
5
|
|
|
6
6
|
const existingFile = '/exit.js';
|
|
7
7
|
const path = '/non-existent';
|
package/tests/fs/exists.test.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
3
|
import { suite, test } from 'node:test';
|
|
4
|
-
import { config, fs } from '../common.
|
|
4
|
+
import { config, fs } from '../common.ts';
|
|
5
5
|
|
|
6
6
|
suite('exists', () => {
|
|
7
7
|
const f = 'x.txt';
|
|
8
8
|
|
|
9
|
-
test('return true for an existing file', config('async'), async () => {
|
|
9
|
+
test('return true for an existing file', config('async', 'promises.exists'), async () => {
|
|
10
10
|
const exists = await fs.promises.exists(f);
|
|
11
11
|
assert(exists);
|
|
12
12
|
});
|
|
13
13
|
|
|
14
|
-
test('return false for a non-existent file', config('async'), async () => {
|
|
14
|
+
test('return false for a non-existent file', config('async', 'promises.exists'), async () => {
|
|
15
15
|
const exists = await fs.promises.exists(f + '-NO');
|
|
16
16
|
assert(!exists);
|
|
17
17
|
});
|
package/tests/fs/links.test.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { join } from '@zenfs/core/path';
|
|
3
3
|
import assert from 'node:assert/strict';
|
|
4
4
|
import { suite, test } from 'node:test';
|
|
5
|
-
import { config, fs } from '../common.
|
|
5
|
+
import { config, fs } from '../common.ts';
|
|
6
6
|
|
|
7
7
|
suite('Links', config('symlinks'), () => {
|
|
8
8
|
const target = '/a1.js',
|
|
@@ -64,8 +64,8 @@ suite('Links', config('symlinks'), () => {
|
|
|
64
64
|
|
|
65
65
|
test('unlink', async () => {
|
|
66
66
|
await fs.promises.unlink(symlink);
|
|
67
|
-
assert(!(await fs.promises.
|
|
68
|
-
assert(await fs.promises.
|
|
67
|
+
assert(!(await fs.promises.stat(symlink, { throwIfNoEntry: false })));
|
|
68
|
+
assert(await fs.promises.stat(target, { throwIfNoEntry: false }));
|
|
69
69
|
});
|
|
70
70
|
|
|
71
71
|
test('link', config('links'), async () => {
|
|
@@ -99,7 +99,7 @@ suite('Links', config('symlinks'), () => {
|
|
|
99
99
|
// A link pointing at a directory satisfies a recursive mkdir and is left as a link
|
|
100
100
|
assert.equal(await fs.promises.mkdir('/mkdir-link', { recursive: true }), undefined);
|
|
101
101
|
assert((await fs.promises.lstat('/mkdir-link')).isSymbolicLink());
|
|
102
|
-
assert(!(await fs.promises.
|
|
102
|
+
assert(!(await fs.promises.stat('/mkdir-missing', { throwIfNoEntry: false })));
|
|
103
103
|
});
|
|
104
104
|
|
|
105
105
|
test('mkdir follows symlinks for intermediate components', config('async'), async () => {
|
|
@@ -113,7 +113,7 @@ suite('Links', config('symlinks'), () => {
|
|
|
113
113
|
|
|
114
114
|
// Node reports the link itself here, unlike `mkdirSync` which reports the requested path with ENOENT
|
|
115
115
|
await assert.rejects(fs.promises.mkdir('/mkdir-dangling/x', { recursive: true }), { code: 'ENOTDIR', path: '/mkdir-dangling' });
|
|
116
|
-
assert(!(await fs.promises.
|
|
116
|
+
assert(!(await fs.promises.stat('/mkdir-missing', { throwIfNoEntry: false })));
|
|
117
117
|
});
|
|
118
118
|
|
|
119
119
|
test('mkdirSync does not follow a symlink at the final component', config('sync'), () => {
|
package/tests/fs/open.test.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
3
|
import { suite, test } from 'node:test';
|
|
4
|
-
import { config, fs } from '../common.
|
|
4
|
+
import { config, fs } from '../common.ts';
|
|
5
5
|
|
|
6
6
|
suite('Opening files', () => {
|
|
7
7
|
const filename = 'a.js';
|
|
@@ -12,12 +12,12 @@ suite('Opening files', () => {
|
|
|
12
12
|
});
|
|
13
13
|
|
|
14
14
|
test('open file with mode "r"', config('async'), async () => {
|
|
15
|
-
|
|
16
|
-
assert(fd >= -Infinity);
|
|
15
|
+
await using handle = await fs.promises.open(filename, 'r');
|
|
16
|
+
assert(handle.fd >= -Infinity);
|
|
17
17
|
});
|
|
18
18
|
|
|
19
19
|
test('open file with mode "rs"', config('async'), async () => {
|
|
20
|
-
|
|
21
|
-
assert(fd >= -Infinity);
|
|
20
|
+
await using handle = await fs.promises.open(filename, 'rs');
|
|
21
|
+
assert(handle.fd >= -Infinity);
|
|
22
22
|
});
|
|
23
23
|
});
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
2
2
|
import { R_OK, W_OK, X_OK } from '@zenfs/core/constants';
|
|
3
|
-
import { defaultContext } from '@zenfs/core/internal/contexts
|
|
4
|
-
import { hasAccess } from '@zenfs/core/internal/inode
|
|
3
|
+
import { defaultContext } from '@zenfs/core/internal/contexts';
|
|
4
|
+
import { hasAccess } from '@zenfs/core/internal/inode';
|
|
5
5
|
import { join } from '@zenfs/core/path';
|
|
6
6
|
import type { Exception } from 'kerium';
|
|
7
7
|
import assert from 'node:assert/strict';
|
|
8
8
|
import { suite, test } from 'node:test';
|
|
9
9
|
import { encodeUTF8 } from 'utilium';
|
|
10
|
-
import { config, fs } from '../common.
|
|
10
|
+
import { config, fs } from '../common.ts';
|
|
11
11
|
|
|
12
12
|
const asyncMode = 0o777;
|
|
13
13
|
const syncMode = 0o644;
|
|
@@ -25,7 +25,7 @@ suite('Permissions', config('permissions'), () => {
|
|
|
25
25
|
});
|
|
26
26
|
|
|
27
27
|
test('fchmod', config('sync', 'async'), async () => {
|
|
28
|
-
|
|
28
|
+
await using handle = await fs.promises.open(file, 'a', 0o644);
|
|
29
29
|
|
|
30
30
|
await handle.chmod(asyncMode);
|
|
31
31
|
const stats = await handle.stat();
|
|
@@ -58,7 +58,7 @@ suite('Permissions', config('permissions'), () => {
|
|
|
58
58
|
|
|
59
59
|
function checkError(access: number) {
|
|
60
60
|
return function (error: Exception) {
|
|
61
|
-
assert(error
|
|
61
|
+
assert(Error.isError(error));
|
|
62
62
|
assert(!hasAccess(defaultContext, stats!, access));
|
|
63
63
|
};
|
|
64
64
|
}
|
package/tests/fs/read.test.ts
CHANGED
|
@@ -5,7 +5,7 @@ import assert from 'node:assert/strict';
|
|
|
5
5
|
import type { OpenMode, PathLike } from 'node:fs';
|
|
6
6
|
import { suite, test } from 'node:test';
|
|
7
7
|
import { promisify } from 'node:util';
|
|
8
|
-
import { config, fs } from '../common.
|
|
8
|
+
import { config, fs } from '../common.ts';
|
|
9
9
|
|
|
10
10
|
const filepath = 'x.txt';
|
|
11
11
|
const expected = 'xyz\n';
|
|
@@ -13,7 +13,7 @@ const ellipses = '…'.repeat(10_000);
|
|
|
13
13
|
|
|
14
14
|
suite('read', () => {
|
|
15
15
|
test('read file asynchronously', config('async'), async () => {
|
|
16
|
-
|
|
16
|
+
await using handle = await fs.promises.open(filepath, 'r');
|
|
17
17
|
const { bytesRead, buffer } = await handle.read(Buffer.alloc(expected.length), 0, expected.length, 0);
|
|
18
18
|
assert.equal(bytesRead, expected.length);
|
|
19
19
|
assert.equal(buffer.toString(), expected);
|
|
@@ -46,7 +46,7 @@ suite('read', () => {
|
|
|
46
46
|
const bufferSync = Buffer.alloc(expected.length);
|
|
47
47
|
|
|
48
48
|
test('read file from handle asynchronously', config('async'), async () => {
|
|
49
|
-
|
|
49
|
+
await using handle = await fs.promises.open(filepath, 'r');
|
|
50
50
|
const { bytesRead } = await handle.read(bufferAsync, 0, expected.length, 0);
|
|
51
51
|
|
|
52
52
|
assert.equal(bytesRead, expected.length);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
3
|
import { suite, test } from 'node:test';
|
|
4
|
-
import { config, fs } from '../common.
|
|
4
|
+
import { config, fs } from '../common.ts';
|
|
5
5
|
|
|
6
6
|
suite('Reading', () => {
|
|
7
7
|
test('Cannot read a file with an invalid encoding', config('sync'), () => {
|
|
@@ -9,7 +9,7 @@ suite('Reading', () => {
|
|
|
9
9
|
});
|
|
10
10
|
|
|
11
11
|
test('Reading past the end of a file should not be an error', config('async'), async () => {
|
|
12
|
-
|
|
12
|
+
await using handle = await fs.promises.open('a.js', 'r');
|
|
13
13
|
const { bytesRead } = await handle.read(new Uint8Array(10), 0, 10, 10000);
|
|
14
14
|
assert.equal(bytesRead, 0);
|
|
15
15
|
});
|
package/tests/fs/rename.test.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
3
|
import { suite, test } from 'node:test';
|
|
4
|
-
import { config, fs } from '../common.
|
|
4
|
+
import { config, fs } from '../common.ts';
|
|
5
5
|
|
|
6
6
|
suite('Rename', config('rename'), () => {
|
|
7
7
|
/**
|
|
@@ -26,8 +26,8 @@ suite('Rename', config('rename'), () => {
|
|
|
26
26
|
const subContents = await fs.promises.readdir(dir + '/_rename_me');
|
|
27
27
|
assert.equal(subContents.length, 1);
|
|
28
28
|
|
|
29
|
-
assert(await fs.promises.
|
|
30
|
-
assert(await fs.promises.
|
|
29
|
+
assert(await fs.promises.stat(dir + '/file.dat', { throwIfNoEntry: false }));
|
|
30
|
+
assert(await fs.promises.stat(dir + '/_rename_me/lol.txt', { throwIfNoEntry: false }));
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
test('rename directory', config('async'), async () => {
|
|
@@ -46,7 +46,7 @@ suite('Rename', config('rename'), () => {
|
|
|
46
46
|
|
|
47
47
|
await check_directory(newDir);
|
|
48
48
|
|
|
49
|
-
assert(!(await fs.promises.
|
|
49
|
+
assert(!(await fs.promises.stat(oldDir, { throwIfNoEntry: false })));
|
|
50
50
|
|
|
51
51
|
await fs.promises.mkdir(oldDir);
|
|
52
52
|
await populate(oldDir);
|
|
@@ -67,7 +67,7 @@ suite('Rename', config('rename'), () => {
|
|
|
67
67
|
await fs.promises.rename(one, two);
|
|
68
68
|
|
|
69
69
|
assert.equal(await fs.promises.readFile(two, 'utf8'), 'hey');
|
|
70
|
-
assert(!(await fs.promises.
|
|
70
|
+
assert(!(await fs.promises.stat(one, { throwIfNoEntry: false })));
|
|
71
71
|
});
|
|
72
72
|
|
|
73
73
|
test('File to Directory and Directory to File Rename', config('sync', 'async'), async () => {
|
package/tests/fs/scaling.test.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { sync } from '@zenfs/core';
|
|
3
3
|
import assert from 'node:assert/strict';
|
|
4
4
|
import { suite, test } from 'node:test';
|
|
5
|
-
import { config, fs } from '../common.
|
|
5
|
+
import { config, fs } from '../common.ts';
|
|
6
6
|
|
|
7
7
|
const n_files = 130;
|
|
8
8
|
const huge_size = 0x1000000;
|
package/tests/fs/stat.test.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
2
|
-
import { defaultContext, hasAccess } from '@zenfs/core';
|
|
2
|
+
import { defaultContext, hasAccess, type Stats } from '@zenfs/core';
|
|
3
3
|
import assert from 'node:assert/strict';
|
|
4
4
|
import { suite, test } from 'node:test';
|
|
5
|
-
import { config, fs } from '../common.
|
|
5
|
+
import { config, fs } from '../common.ts';
|
|
6
6
|
|
|
7
7
|
suite('Stats', () => {
|
|
8
8
|
const existing_file = 'x.txt';
|
|
@@ -35,7 +35,7 @@ suite('Stats', () => {
|
|
|
35
35
|
fs.close(fd);
|
|
36
36
|
});
|
|
37
37
|
|
|
38
|
-
test('hasAccess for non-root access', config('sync', 'permissions'), () => {
|
|
38
|
+
test('hasAccess for non-root access', config('sync', 'permissions', 'root'), () => {
|
|
39
39
|
const newFile = 'new.txt';
|
|
40
40
|
|
|
41
41
|
fs.writeFileSync(newFile, 'hello', { mode: 0o640 });
|
|
@@ -72,6 +72,35 @@ suite('Stats', () => {
|
|
|
72
72
|
Object.assign(defaultContext.credentials, prevCredentials);
|
|
73
73
|
});
|
|
74
74
|
|
|
75
|
+
const missing = '/does-not-exist';
|
|
76
|
+
|
|
77
|
+
test('statSync throws for a missing entry', config('sync'), () => {
|
|
78
|
+
assert.throws(() => fs.statSync(missing), { code: 'ENOENT' });
|
|
79
|
+
assert.throws(() => fs.statSync(missing, { throwIfNoEntry: true }), { code: 'ENOENT' });
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test('statSync with throwIfNoEntry: false', config('sync'), () => {
|
|
83
|
+
assert.equal(fs.statSync(missing, { throwIfNoEntry: false }), undefined);
|
|
84
|
+
assert.equal(fs.statSync(existing_file + '/nope', { throwIfNoEntry: false }), undefined);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test('lstatSync with throwIfNoEntry: false', config('sync'), () => {
|
|
88
|
+
assert.throws(() => fs.lstatSync(missing), { code: 'ENOENT' });
|
|
89
|
+
assert.equal(fs.lstatSync(missing, { throwIfNoEntry: false }), undefined);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test('stat with throwIfNoEntry: false', config('async'), async () => {
|
|
93
|
+
await assert.rejects(fs.promises.stat(missing), { code: 'ENOENT' });
|
|
94
|
+
assert.equal(await fs.promises.stat(missing, { throwIfNoEntry: false }), undefined);
|
|
95
|
+
assert.equal(await fs.promises.stat(existing_file + '/nope', { throwIfNoEntry: false }), undefined);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
test('stat callback with throwIfNoEntry: false', config('async'), async () => {
|
|
99
|
+
const { promise, resolve, reject } = Promise.withResolvers<Stats | undefined>();
|
|
100
|
+
fs.stat(missing, { throwIfNoEntry: false }, (error, stats) => (error ? reject(error) : resolve(stats)));
|
|
101
|
+
assert.equal(await promise, undefined);
|
|
102
|
+
});
|
|
103
|
+
|
|
75
104
|
test('stat file', config('async'), async () => {
|
|
76
105
|
const stats = await fs.promises.stat(existing_file);
|
|
77
106
|
assert(!stats.isDirectory());
|
package/tests/fs/streams.test.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
3
|
import { suite, test } from 'node:test';
|
|
4
|
-
import { config, fs } from '../common.
|
|
4
|
+
import { config, fs } from '../common.ts';
|
|
5
5
|
|
|
6
6
|
// Top-level initialization
|
|
7
7
|
const testFilePath = 'test-file.txt';
|
package/tests/fs/tempdir.test.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
2
2
|
import { test, suite } from 'node:test';
|
|
3
|
-
import { config, fs } from '../common.
|
|
3
|
+
import { config, fs } from '../common.ts';
|
|
4
4
|
import assert from 'node:assert/strict';
|
|
5
5
|
import { basename } from 'node:path/posix';
|
|
6
6
|
|
package/tests/fs/times.test.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { Exception } from 'kerium';
|
|
|
4
4
|
import assert from 'node:assert/strict';
|
|
5
5
|
import { suite, test } from 'node:test';
|
|
6
6
|
import { wait } from 'utilium';
|
|
7
|
-
import { config, fs } from '../common.
|
|
7
|
+
import { config, fs } from '../common.ts';
|
|
8
8
|
|
|
9
9
|
const path = 'x.txt';
|
|
10
10
|
|
|
@@ -33,7 +33,7 @@ suite('Times', config('times'), () => {
|
|
|
33
33
|
assert.deepEqual(unixTimestamps(await fs.promises.stat(path)), times);
|
|
34
34
|
|
|
35
35
|
await fs.promises.utimes('foobarbaz', atime, mtime).catch((error: Exception) => {
|
|
36
|
-
assert(error
|
|
36
|
+
assert(Error.isError(error));
|
|
37
37
|
assert.equal(error.code, 'ENOENT');
|
|
38
38
|
});
|
|
39
39
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
3
|
import { suite, test } from 'node:test';
|
|
4
|
-
import { config, fs } from '../common.
|
|
4
|
+
import { config, fs } from '../common.ts';
|
|
5
5
|
|
|
6
6
|
const path: string = 'truncate-file.txt',
|
|
7
7
|
size = 1024 * 16,
|
package/tests/fs/watch.test.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import type { Stats } from '@zenfs/core';
|
|
3
3
|
import assert from 'node:assert/strict';
|
|
4
4
|
import { suite, test } from 'node:test';
|
|
5
|
-
import { config, fs } from '../common.
|
|
5
|
+
import { config, fs } from '../common.ts';
|
|
6
6
|
|
|
7
7
|
const testDir = '/test-watch-dir';
|
|
8
8
|
const testFile = testDir + '/test.txt';
|
package/tests/fs/write.test.ts
CHANGED
|
@@ -3,8 +3,8 @@ import assert from 'node:assert/strict';
|
|
|
3
3
|
import { readFileSync } from 'node:fs';
|
|
4
4
|
import { join } from 'node:path/posix';
|
|
5
5
|
import { suite, test } from 'node:test';
|
|
6
|
-
import { config, fs } from '../common.
|
|
7
|
-
import { data as dataPath } from '../setup.
|
|
6
|
+
import { config, fs } from '../common.ts';
|
|
7
|
+
import { data as dataPath } from '../setup.ts';
|
|
8
8
|
|
|
9
9
|
const fileName = 'write.txt';
|
|
10
10
|
const utf8example = readFileSync(join(dataPath, 'utf8.txt'), 'utf8');
|
package/tests/fs/xattr.test.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { Buffer } from 'buffer';
|
|
3
3
|
import assert from 'node:assert/strict';
|
|
4
4
|
import { suite, test } from 'node:test';
|
|
5
|
-
import { config, fs } from '../common.
|
|
5
|
+
import { config, fs } from '../common.ts';
|
|
6
6
|
|
|
7
7
|
suite('Extended Attributes', config('xattr'), () => {
|
|
8
8
|
const testFile = 'xattr-test.txt';
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
/* Run the FS test suite against native node:fs.
|
|
3
3
|
Since the tests use absolute paths, everything is contained to a scratch directory using chroot-style path mapping. */
|
|
4
4
|
import * as native from 'node:fs';
|
|
5
|
-
import type { TestFlag, TestFlagState } from '
|
|
5
|
+
import type { TestFlag, TestFlagState } from './common.ts';
|
|
6
6
|
import { isAbsolute, join, relative, resolve } from 'node:path';
|
|
7
7
|
import { fileURLToPath } from 'node:url';
|
|
8
|
-
import { copySync, data, tmp } from '
|
|
8
|
+
import { copySync, data, tmp } from './setup.ts';
|
|
9
9
|
import { styleText } from 'node:util';
|
|
10
|
+
import { isRoot } from 'utilium/node';
|
|
10
11
|
|
|
11
12
|
// The tests assume modes are used as-is, but native fs applies the process umask
|
|
12
13
|
process.umask(0);
|
|
@@ -205,9 +206,6 @@ for (const [key, value] of Object.entries(native.promises)) {
|
|
|
205
206
|
promises.watch = (...args: Parameters<typeof native.promises.watch>) =>
|
|
206
207
|
native.promises.watch(...(mapArgs('watch', args) as Parameters<typeof native.promises.watch>));
|
|
207
208
|
|
|
208
|
-
// ZenFS API extension
|
|
209
|
-
promises.exists = (path: PathLike) => Promise.resolve(native.existsSync(toNative(path)));
|
|
210
|
-
|
|
211
209
|
wrapped.promises = promises;
|
|
212
210
|
|
|
213
211
|
export const fs = wrapped as unknown as typeof native;
|
|
@@ -220,6 +218,8 @@ export const flags: Partial<Record<TestFlag, TestFlagState>> = {
|
|
|
220
218
|
lchmod: process.platform == 'darwin',
|
|
221
219
|
// The suite uses ZenFS' own extended attribute API, which `node:fs` does not have
|
|
222
220
|
xattr: false,
|
|
221
|
+
'promises.exists': false,
|
|
222
|
+
root: isRoot || 'skip',
|
|
223
223
|
};
|
|
224
224
|
|
|
225
225
|
copySync(data, fs);
|
package/tests/setup/context.ts
CHANGED
package/tests/setup/cow.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { configureSingle, CopyOnWrite, fs, InMemory, resolveMountConfig } from '@zenfs/core';
|
|
2
|
-
import { copySync, data } from '../setup.
|
|
2
|
+
import { copySync, data } from '../setup.ts';
|
|
3
3
|
|
|
4
4
|
fs.umount('/');
|
|
5
5
|
const readable = await resolveMountConfig({ backend: InMemory, label: 'ro' });
|
package/tests/setup/index.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { readFileSync } from 'node:fs';
|
|
|
2
2
|
import { join } from 'node:path/posix';
|
|
3
3
|
import { configureSingle, CopyOnWrite, InMemory, InMemoryStore, mounts, Readonly, StoreFS } from '@zenfs/core';
|
|
4
4
|
import { S_IFDIR } from '@zenfs/core/constants';
|
|
5
|
-
import { copySync, data } from '../setup.
|
|
5
|
+
import { copySync, data } from '../setup.ts';
|
|
6
6
|
|
|
7
7
|
copySync(data);
|
|
8
8
|
|
package/tests/setup/memory.ts
CHANGED
package/tests/setup/port.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { InMemory, Port, configureSingle, fs, resolveMountConfig, resolveRemoteMount, sync } from '@zenfs/core';
|
|
2
2
|
import { after, afterEach } from 'node:test';
|
|
3
3
|
import { MessageChannel } from 'node:worker_threads';
|
|
4
|
-
import { copySync, data } from '../setup.
|
|
4
|
+
import { copySync, data } from '../setup.ts';
|
|
5
5
|
|
|
6
6
|
const { port1: localPort, port2: remotePort } = new MessageChannel();
|
|
7
7
|
|
package/tests/setup.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
2
2
|
import { fs as _fs } from '@zenfs/core';
|
|
3
|
+
import type { NodeFS } from '@zenfs/core/node/types';
|
|
3
4
|
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync } from 'node:fs';
|
|
4
5
|
import { join, relative } from 'node:path';
|
|
5
|
-
import type { NodeFS } from '@zenfs/core/node/types.js';
|
|
6
6
|
|
|
7
7
|
export const data = join(import.meta.dirname, 'data');
|
|
8
8
|
|
package/tests/tsconfig.json
CHANGED
package/tests/native/run.sh
DELETED