@zenfs/core 1.3.6 → 1.4.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/memory.d.ts +4 -4
- package/dist/backends/memory.js +4 -4
- package/dist/backends/overlay.d.ts +5 -2
- package/dist/backends/overlay.js +7 -10
- package/dist/backends/port/fs.js +1 -4
- package/dist/config.js +4 -8
- package/dist/context.d.ts +32 -0
- package/dist/context.js +23 -0
- package/dist/credentials.d.ts +5 -5
- package/dist/credentials.js +10 -6
- package/dist/emulation/async.d.ts +90 -89
- package/dist/emulation/async.js +76 -75
- package/dist/emulation/dir.d.ts +3 -1
- package/dist/emulation/dir.js +6 -7
- package/dist/emulation/index.d.ts +1 -1
- package/dist/emulation/index.js +1 -1
- package/dist/emulation/promises.d.ts +50 -48
- package/dist/emulation/promises.js +78 -77
- package/dist/emulation/shared.d.ts +35 -8
- package/dist/emulation/shared.js +37 -11
- package/dist/emulation/sync.d.ts +63 -62
- package/dist/emulation/sync.js +72 -73
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/stats.d.ts +2 -1
- package/dist/stats.js +5 -4
- package/package.json +3 -5
- package/scripts/test.js +78 -17
- package/tests/assignment.ts +1 -1
- package/tests/common/context.test.ts +19 -0
- package/tests/{devices.test.ts → common/devices.test.ts} +3 -3
- package/tests/{handle.test.ts → common/handle.test.ts} +1 -1
- package/tests/common/mounts.test.ts +36 -0
- package/tests/{mutex.test.ts → common/mutex.test.ts} +3 -3
- package/tests/common/path.test.ts +34 -0
- package/tests/common.ts +4 -3
- package/tests/fs/dir.test.ts +11 -11
- package/tests/fs/directory.test.ts +17 -17
- package/tests/fs/errors.test.ts +29 -39
- package/tests/fs/watch.test.ts +2 -2
- package/tests/setup/context.ts +9 -0
- package/tests/setup/cow+fetch.ts +1 -1
- package/tests/setup/memory.ts +1 -1
- package/tests/{setup/common.ts → setup.ts} +6 -5
- package/src/backends/backend.ts +0 -161
- package/src/backends/fetch.ts +0 -180
- package/src/backends/file_index.ts +0 -206
- package/src/backends/memory.ts +0 -45
- package/src/backends/overlay.ts +0 -560
- package/src/backends/port/fs.ts +0 -329
- package/src/backends/port/readme.md +0 -54
- package/src/backends/port/rpc.ts +0 -167
- package/src/backends/readme.md +0 -3
- package/src/backends/store/fs.ts +0 -667
- package/src/backends/store/readme.md +0 -9
- package/src/backends/store/simple.ts +0 -154
- package/src/backends/store/store.ts +0 -189
- package/src/config.ts +0 -227
- package/src/credentials.ts +0 -49
- package/src/devices.ts +0 -521
- package/src/emulation/async.ts +0 -834
- package/src/emulation/cache.ts +0 -86
- package/src/emulation/config.ts +0 -21
- package/src/emulation/constants.ts +0 -182
- package/src/emulation/dir.ts +0 -138
- package/src/emulation/index.ts +0 -8
- package/src/emulation/path.ts +0 -440
- package/src/emulation/promises.ts +0 -1140
- package/src/emulation/shared.ts +0 -172
- package/src/emulation/streams.ts +0 -34
- package/src/emulation/sync.ts +0 -863
- package/src/emulation/watchers.ts +0 -194
- package/src/error.ts +0 -307
- package/src/file.ts +0 -631
- package/src/filesystem.ts +0 -174
- package/src/index.ts +0 -35
- package/src/inode.ts +0 -128
- package/src/mixins/async.ts +0 -230
- package/src/mixins/index.ts +0 -5
- package/src/mixins/mutexed.ts +0 -257
- package/src/mixins/readonly.ts +0 -96
- package/src/mixins/shared.ts +0 -25
- package/src/mixins/sync.ts +0 -58
- package/src/polyfills.ts +0 -21
- package/src/stats.ts +0 -405
- package/src/utils.ts +0 -276
- package/tests/mounts.test.ts +0 -18
- package/tests/path.test.ts +0 -34
package/scripts/test.js
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { execSync } from 'node:child_process';
|
|
4
|
-
import { existsSync } from 'node:fs';
|
|
4
|
+
import { existsSync, mkdirSync, rmSync, globSync } from 'node:fs';
|
|
5
5
|
import { join } from 'node:path';
|
|
6
6
|
import { parseArgs } from 'node:util';
|
|
7
7
|
|
|
8
8
|
const { values: options, positionals } = parseArgs({
|
|
9
9
|
options: {
|
|
10
10
|
help: { short: 'h', type: 'boolean', default: false },
|
|
11
|
-
verbose: { type: 'boolean', default: false },
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
verbose: { short: 'w', type: 'boolean', default: false },
|
|
12
|
+
quiet: { short: 'q', type: 'boolean', default: false },
|
|
13
|
+
test: { short: 't', type: 'string' },
|
|
14
|
+
force: { short: 'f', type: 'boolean', default: false },
|
|
15
|
+
auto: { short: 'a', type: 'boolean', default: false },
|
|
16
|
+
build: { short: 'b', type: 'boolean', default: false },
|
|
17
|
+
common: { short: 'c', type: 'boolean', default: false },
|
|
14
18
|
},
|
|
15
19
|
allowPositionals: true,
|
|
16
20
|
});
|
|
@@ -18,32 +22,89 @@ const { values: options, positionals } = parseArgs({
|
|
|
18
22
|
if (options.help) {
|
|
19
23
|
console.log(`zenfs-test [...options] <...paths>
|
|
20
24
|
|
|
21
|
-
|
|
25
|
+
Paths: The setup files to run tests on
|
|
22
26
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
Options:
|
|
28
|
+
--help, -h Outputs this help message
|
|
29
|
+
--verbose,-w Output verbose messages
|
|
30
|
+
--quiet, -q Don't output normal messages
|
|
31
|
+
--test,-t <glob> Which test(s) to run
|
|
32
|
+
--force, -f Whether to use --test-force-exit
|
|
33
|
+
--auto, -a Automatically detect setup files
|
|
34
|
+
--build, -b Run the npm build script prior to running tests
|
|
35
|
+
--common, -c Also run tests not specific to any backend
|
|
36
|
+
`);
|
|
29
37
|
process.exit();
|
|
30
38
|
}
|
|
31
39
|
|
|
32
|
-
if (options.verbose)
|
|
40
|
+
if (options.quiet && options.verbose) {
|
|
41
|
+
console.error('ERROR: Can not specify --verbose and --quiet');
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
options.verbose && options.force && console.debug('Forcing tests to exit (--test-force-exit)');
|
|
46
|
+
|
|
47
|
+
if (options.build) {
|
|
48
|
+
!options.quiet && console.log('Building...');
|
|
49
|
+
try {
|
|
50
|
+
execSync('npm run build');
|
|
51
|
+
} catch {
|
|
52
|
+
console.warn('Build failed, continuing without it.');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
33
55
|
|
|
34
56
|
if (!existsSync(join(import.meta.dirname, '../dist'))) {
|
|
35
|
-
console.
|
|
57
|
+
console.error('ERROR: Missing build. If you are using an installed package, please submit a bug report.');
|
|
36
58
|
process.exit(1);
|
|
37
59
|
}
|
|
38
60
|
|
|
61
|
+
if (options.auto) {
|
|
62
|
+
let sum = 0;
|
|
63
|
+
|
|
64
|
+
for (const pattern of ['**/tests/setup/*.ts', '**/tests/setup-*.ts']) {
|
|
65
|
+
const files = await globSync(pattern);
|
|
66
|
+
sum += files.length;
|
|
67
|
+
positionals.push(...files);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
!options.quiet && console.log(`Auto-detected ${sum} test setup files`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const coverage = join(import.meta.dirname, '../.coverage');
|
|
74
|
+
if (existsSync(coverage)) rmSync(coverage, { recursive: true });
|
|
75
|
+
mkdirSync(coverage);
|
|
76
|
+
process.env.NODE_V8_COVERAGE = coverage;
|
|
77
|
+
|
|
78
|
+
if (options.common) {
|
|
79
|
+
!options.quiet && console.log('Running common tests...');
|
|
80
|
+
try {
|
|
81
|
+
execSync("tsx --test --experimental-test-coverage 'tests/**/!(fs)/*.test.ts'", {
|
|
82
|
+
stdio: ['ignore', options.verbose ? 'inherit' : 'ignore', 'inherit'],
|
|
83
|
+
});
|
|
84
|
+
} catch {
|
|
85
|
+
console.error('Common tests failed');
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
39
89
|
const testsGlob = join(import.meta.dirname, `../tests/fs/${options.test || '*'}.test.ts`);
|
|
40
90
|
|
|
41
91
|
for (const setupFile of positionals) {
|
|
42
|
-
if (options.verbose) console.debug('Running tests for:', setupFile);
|
|
43
|
-
process.env.SETUP = setupFile;
|
|
44
92
|
if (!existsSync(setupFile)) {
|
|
45
|
-
console.
|
|
93
|
+
!options.quiet && console.warn('Skipping tests for non-existent setup file:', setupFile);
|
|
46
94
|
continue;
|
|
47
95
|
}
|
|
48
|
-
|
|
96
|
+
|
|
97
|
+
!options.quiet && console.debug('Running tests using setup:', setupFile);
|
|
98
|
+
process.env.SETUP = setupFile;
|
|
99
|
+
|
|
100
|
+
try {
|
|
101
|
+
execSync(['tsx --test --experimental-test-coverage', options.force ? '--test-force-exit' : '', testsGlob, process.env.CMD].join(' '), {
|
|
102
|
+
stdio: ['ignore', options.verbose ? 'inherit' : 'ignore', 'inherit'],
|
|
103
|
+
});
|
|
104
|
+
} catch {
|
|
105
|
+
!options.quiet && console.error('Tests failed:', setupFile);
|
|
106
|
+
}
|
|
49
107
|
}
|
|
108
|
+
|
|
109
|
+
execSync('npx c8 report --reporter=text', { stdio: 'inherit' });
|
|
110
|
+
rmSync('.coverage', { recursive: true });
|
package/tests/assignment.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
Notes on omissions and exclusions:
|
|
8
8
|
- __promisify__ is omitted as it is metadata
|
|
9
9
|
- native is omitted as zenfs isn't native
|
|
10
|
-
- ReadStream and WriteStream are excluded since they are
|
|
10
|
+
- ReadStream and WriteStream are excluded since they are polyfilled from another module
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import { fs as zen } from '../src/index.js';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { suite, test } from 'node:test';
|
|
2
|
+
import assert from 'node:assert';
|
|
3
|
+
import { bindContext } from '../../dist/context.js';
|
|
4
|
+
import * as fs from '../../dist/emulation/index.js';
|
|
5
|
+
|
|
6
|
+
fs.mkdirSync('/new_root');
|
|
7
|
+
const c_fs = bindContext('/new_root');
|
|
8
|
+
|
|
9
|
+
suite('Context', () => {
|
|
10
|
+
test('create a file', () => {
|
|
11
|
+
c_fs.writeFileSync('/example.txt', 'not in real root!');
|
|
12
|
+
assert.deepEqual(fs.readdirSync('/'), ['new_root']);
|
|
13
|
+
assert.deepEqual(fs.readdirSync('/new_root'), ['example.txt']);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test('break-out fails', () => {
|
|
17
|
+
assert.deepEqual(c_fs.readdirSync('/../../'), ['example.txt']);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { suite, test } from 'node:test';
|
|
2
2
|
import assert from 'node:assert';
|
|
3
|
-
import { configure } from '
|
|
4
|
-
import * as fs from '
|
|
5
|
-
import { S_IFCHR, S_IFMT } from '
|
|
3
|
+
import { configure } from '../../dist/config.js';
|
|
4
|
+
import * as fs from '../../dist/emulation/index.js';
|
|
5
|
+
import { S_IFCHR, S_IFMT } from '../../dist/emulation/constants.js';
|
|
6
6
|
|
|
7
7
|
await configure({
|
|
8
8
|
addDevices: true,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import assert from 'node:assert';
|
|
2
2
|
import { suite, test } from 'node:test';
|
|
3
|
-
import { constants, type FileHandle, open } from '
|
|
3
|
+
import { constants, type FileHandle, open } from '../../dist/emulation/promises.js';
|
|
4
4
|
|
|
5
5
|
const content = 'The cake is a lie',
|
|
6
6
|
appended = '\nAnother lie';
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
import { suite, test } from 'node:test';
|
|
3
|
+
import { configure } from '../../dist/config.js';
|
|
4
|
+
import * as fs from '../../dist/emulation/index.js';
|
|
5
|
+
import { InMemory } from '../../dist/index.js';
|
|
6
|
+
|
|
7
|
+
suite('Mounts', () => {
|
|
8
|
+
test('Mount in nested directory', async () => {
|
|
9
|
+
await configure({
|
|
10
|
+
mounts: {
|
|
11
|
+
'/nested/dir': InMemory,
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
assert.deepStrictEqual(fs.readdirSync('/'), ['nested']);
|
|
16
|
+
assert.deepStrictEqual(fs.readdirSync('/nested'), ['dir']);
|
|
17
|
+
|
|
18
|
+
// cleanup
|
|
19
|
+
fs.umount('/nested/dir');
|
|
20
|
+
fs.rmSync('/nested', { recursive: true, force: true });
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('Race conditions', async () => {
|
|
24
|
+
await configure({
|
|
25
|
+
mounts: {
|
|
26
|
+
one: InMemory,
|
|
27
|
+
two: InMemory,
|
|
28
|
+
three: InMemory,
|
|
29
|
+
four: InMemory,
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
assert.equal(fs.mounts.size, 5); // 4 + default `/` mount
|
|
34
|
+
assert.equal(fs.readdirSync('/').length, 4);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { wait } from 'utilium';
|
|
2
|
-
import { Mutexed } from '
|
|
3
|
-
import { StoreFS } from '
|
|
4
|
-
import { InMemoryStore } from '
|
|
2
|
+
import { Mutexed } from '../../dist/mixins/mutexed.js';
|
|
3
|
+
import { StoreFS } from '../../dist/backends/store/fs.js';
|
|
4
|
+
import { InMemoryStore } from '../../dist/backends/memory.js';
|
|
5
5
|
import { suite, test } from 'node:test';
|
|
6
6
|
import assert from 'node:assert';
|
|
7
7
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
import { suite, test } from 'node:test';
|
|
3
|
+
import { basename, dirname, extname, join, normalize, resolve } from '../../dist/emulation/path.js';
|
|
4
|
+
|
|
5
|
+
suite('Path emulation', () => {
|
|
6
|
+
test('resolve', () => {
|
|
7
|
+
assert.equal(resolve('somepath'), '/somepath');
|
|
8
|
+
assert.equal(resolve('/another', 'path'), '/another/path');
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test('join', () => {
|
|
12
|
+
assert.equal(join('/path', 'to', 'file.txt'), '/path/to/file.txt');
|
|
13
|
+
assert.equal(join('/path/', 'to', '/file.txt'), '/path/to/file.txt');
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test('normalize', () => {
|
|
17
|
+
assert.equal(normalize('/path/to/../file.txt'), '/path/file.txt');
|
|
18
|
+
assert.equal(normalize('/path/to/./file.txt'), '/path/to/file.txt');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test('basename', () => {
|
|
22
|
+
assert.equal(basename('/path/to/file.txt'), 'file.txt');
|
|
23
|
+
assert.equal(basename('/path/to/file.txt', '.txt'), 'file');
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('dirname', () => {
|
|
27
|
+
assert.equal(dirname('/path/to/file.txt'), '/path/to');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('extname', () => {
|
|
31
|
+
assert.equal(extname('/path/to/file.txt'), '.txt');
|
|
32
|
+
assert.equal(extname('/path/to/file'), '');
|
|
33
|
+
});
|
|
34
|
+
});
|
package/tests/common.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { join, resolve } from 'node:path';
|
|
2
|
-
import { fs } from '../dist/index.js';
|
|
2
|
+
import { fs as defaultFS } from '../dist/index.js';
|
|
3
|
+
export type * from '../dist/emulation/index.js';
|
|
3
4
|
|
|
4
5
|
const setupPath = resolve(process.env.SETUP || join(import.meta.dirname, 'setup/memory.ts'));
|
|
5
6
|
|
|
6
|
-
await import(setupPath).catch(error => {
|
|
7
|
+
const setup = await import(setupPath).catch(error => {
|
|
7
8
|
console.log('Failed to import test setup:');
|
|
8
9
|
throw error;
|
|
9
10
|
});
|
|
10
11
|
|
|
11
|
-
export
|
|
12
|
+
export const fs = (setup.fs || defaultFS) as typeof defaultFS;
|
package/tests/fs/dir.test.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import assert, { rejects } from 'node:assert';
|
|
2
2
|
import { suite, test } from 'node:test';
|
|
3
|
-
import { fs } from '../common.js';
|
|
3
|
+
import { fs, type Dirent } from '../common.js';
|
|
4
4
|
|
|
5
5
|
const testFile = 'test-file.txt';
|
|
6
6
|
fs.writeFileSync(testFile, 'Sample content');
|
|
@@ -59,7 +59,7 @@ suite('Dirent', () => {
|
|
|
59
59
|
|
|
60
60
|
suite('Dir', () => {
|
|
61
61
|
test('read()', async () => {
|
|
62
|
-
const dir =
|
|
62
|
+
const dir = fs.opendirSync(testDirPath);
|
|
63
63
|
|
|
64
64
|
const dirent1 = await dir.read();
|
|
65
65
|
assert(dirent1 instanceof fs.Dirent);
|
|
@@ -76,7 +76,7 @@ suite('Dir', () => {
|
|
|
76
76
|
});
|
|
77
77
|
|
|
78
78
|
test('readSync()', () => {
|
|
79
|
-
const dir =
|
|
79
|
+
const dir = fs.opendirSync(testDirPath);
|
|
80
80
|
|
|
81
81
|
const dirent1 = dir.readSync();
|
|
82
82
|
assert(dirent1 instanceof fs.Dirent);
|
|
@@ -93,20 +93,20 @@ suite('Dir', () => {
|
|
|
93
93
|
});
|
|
94
94
|
|
|
95
95
|
test('close()', async () => {
|
|
96
|
-
const dir =
|
|
96
|
+
const dir = fs.opendirSync(testDirPath);
|
|
97
97
|
await dir.close();
|
|
98
98
|
rejects(dir.read(), 'Can not use closed Dir');
|
|
99
99
|
});
|
|
100
100
|
|
|
101
101
|
test('closeSync()', () => {
|
|
102
|
-
const dir =
|
|
102
|
+
const dir = fs.opendirSync(testDirPath);
|
|
103
103
|
dir.closeSync();
|
|
104
104
|
assert.throws(() => dir.readSync(), 'Can not use closed Dir');
|
|
105
105
|
});
|
|
106
106
|
|
|
107
107
|
test('asynchronous iteration', async () => {
|
|
108
|
-
const dir =
|
|
109
|
-
const dirents:
|
|
108
|
+
const dir = fs.opendirSync(testDirPath);
|
|
109
|
+
const dirents: Dirent[] = [];
|
|
110
110
|
|
|
111
111
|
for await (const dirent of dir) {
|
|
112
112
|
dirents.push(dirent);
|
|
@@ -119,26 +119,26 @@ suite('Dir', () => {
|
|
|
119
119
|
});
|
|
120
120
|
|
|
121
121
|
test('read after directory is closed', async () => {
|
|
122
|
-
const dir =
|
|
122
|
+
const dir = fs.opendirSync(testDirPath);
|
|
123
123
|
await dir.close();
|
|
124
124
|
await assert.rejects(dir.read(), 'Can not use closed Dir');
|
|
125
125
|
});
|
|
126
126
|
|
|
127
127
|
test('readSync after directory is closed', () => {
|
|
128
|
-
const dir =
|
|
128
|
+
const dir = fs.opendirSync(testDirPath);
|
|
129
129
|
dir.closeSync();
|
|
130
130
|
assert.throws(() => dir.readSync(), 'Can not use closed Dir');
|
|
131
131
|
});
|
|
132
132
|
|
|
133
133
|
test('close multiple times', async () => {
|
|
134
|
-
const dir =
|
|
134
|
+
const dir = fs.opendirSync(testDirPath);
|
|
135
135
|
await dir.close();
|
|
136
136
|
await dir.close(); // Should not throw an error
|
|
137
137
|
assert(dir['closed']);
|
|
138
138
|
});
|
|
139
139
|
|
|
140
140
|
test('closeSync multiple times', () => {
|
|
141
|
-
const dir =
|
|
141
|
+
const dir = fs.opendirSync(testDirPath);
|
|
142
142
|
dir.closeSync();
|
|
143
143
|
dir.closeSync(); // Should not throw an error
|
|
144
144
|
assert(dir['closed']);
|
|
@@ -40,27 +40,27 @@ suite('Directories', () => {
|
|
|
40
40
|
});
|
|
41
41
|
|
|
42
42
|
test('mkdir, recursive', async () => {
|
|
43
|
-
assert(
|
|
44
|
-
assert(
|
|
45
|
-
assert(
|
|
43
|
+
assert.equal(await fs.promises.mkdir('/recursiveP/A/B', { recursive: true, mode: 0o755 }), '/recursiveP');
|
|
44
|
+
assert.equal(await fs.promises.mkdir('/recursiveP/A/B/C/D', { recursive: true, mode: 0o777 }), '/recursiveP/A/B/C');
|
|
45
|
+
assert.equal(await fs.promises.mkdir('/recursiveP/A/B/C/D', { recursive: true, mode: 0o700 }), undefined);
|
|
46
46
|
|
|
47
|
-
assert((await fs.promises.stat('/recursiveP')).mode
|
|
48
|
-
assert((await fs.promises.stat('/recursiveP/A')).mode
|
|
49
|
-
assert((await fs.promises.stat('/recursiveP/A/B')).mode
|
|
50
|
-
assert((await fs.promises.stat('/recursiveP/A/B/C')).mode
|
|
51
|
-
assert((await fs.promises.stat('/recursiveP/A/B/C/D')).mode
|
|
47
|
+
assert.equal((await fs.promises.stat('/recursiveP')).mode, fs.constants.S_IFDIR | 0o755);
|
|
48
|
+
assert.equal((await fs.promises.stat('/recursiveP/A')).mode, fs.constants.S_IFDIR | 0o755);
|
|
49
|
+
assert.equal((await fs.promises.stat('/recursiveP/A/B')).mode, fs.constants.S_IFDIR | 0o755);
|
|
50
|
+
assert.equal((await fs.promises.stat('/recursiveP/A/B/C')).mode, fs.constants.S_IFDIR | 0o777);
|
|
51
|
+
assert.equal((await fs.promises.stat('/recursiveP/A/B/C/D')).mode, fs.constants.S_IFDIR | 0o777);
|
|
52
52
|
});
|
|
53
53
|
|
|
54
54
|
test('mkdirSync, recursive', () => {
|
|
55
|
-
assert(fs.mkdirSync('/recursiveS/A/B', { recursive: true, mode: 0o755 })
|
|
56
|
-
assert(fs.mkdirSync('/recursiveS/A/B/C/D', { recursive: true, mode: 0o777 })
|
|
57
|
-
assert(fs.mkdirSync('/recursiveS/A/B/C/D', { recursive: true, mode: 0o700 })
|
|
58
|
-
|
|
59
|
-
assert(fs.statSync('/recursiveS').mode
|
|
60
|
-
assert(fs.statSync('/recursiveS/A').mode
|
|
61
|
-
assert(fs.statSync('/recursiveS/A/B').mode
|
|
62
|
-
assert(fs.statSync('/recursiveS/A/B/C').mode
|
|
63
|
-
assert(fs.statSync('/recursiveS/A/B/C/D').mode
|
|
55
|
+
assert.equal(fs.mkdirSync('/recursiveS/A/B', { recursive: true, mode: 0o755 }), '/recursiveS');
|
|
56
|
+
assert.equal(fs.mkdirSync('/recursiveS/A/B/C/D', { recursive: true, mode: 0o777 }), '/recursiveS/A/B/C');
|
|
57
|
+
assert.equal(fs.mkdirSync('/recursiveS/A/B/C/D', { recursive: true, mode: 0o700 }), undefined);
|
|
58
|
+
|
|
59
|
+
assert.equal(fs.statSync('/recursiveS').mode, fs.constants.S_IFDIR | 0o755);
|
|
60
|
+
assert.equal(fs.statSync('/recursiveS/A').mode, fs.constants.S_IFDIR | 0o755);
|
|
61
|
+
assert.equal(fs.statSync('/recursiveS/A/B').mode, fs.constants.S_IFDIR | 0o755);
|
|
62
|
+
assert.equal(fs.statSync('/recursiveS/A/B/C').mode, fs.constants.S_IFDIR | 0o777);
|
|
63
|
+
assert.equal(fs.statSync('/recursiveS/A/B/C/D').mode, fs.constants.S_IFDIR | 0o777);
|
|
64
64
|
});
|
|
65
65
|
|
|
66
66
|
test('readdirSync without permission', () => {
|
package/tests/fs/errors.test.ts
CHANGED
|
@@ -1,23 +1,10 @@
|
|
|
1
1
|
import assert from 'node:assert';
|
|
2
|
-
import { suite
|
|
3
|
-
import { ErrnoError } from '../../dist/error.js';
|
|
2
|
+
import test, { suite } from 'node:test';
|
|
3
|
+
import type { ErrnoError } from '../../dist/error.js';
|
|
4
4
|
import { fs } from '../common.js';
|
|
5
5
|
|
|
6
6
|
const existingFile = '/exit.js';
|
|
7
7
|
|
|
8
|
-
async function expectError(fn: (...args: any[]) => unknown, path: string, ...args: any[]) {
|
|
9
|
-
let error: ErrnoError | undefined;
|
|
10
|
-
try {
|
|
11
|
-
await fn(path, ...args);
|
|
12
|
-
} catch (err: any) {
|
|
13
|
-
assert(err instanceof ErrnoError);
|
|
14
|
-
error = err;
|
|
15
|
-
}
|
|
16
|
-
assert(error);
|
|
17
|
-
assert.equal(error.path, path);
|
|
18
|
-
assert(error.message.includes(path));
|
|
19
|
-
}
|
|
20
|
-
|
|
21
8
|
suite('Error messages', () => {
|
|
22
9
|
const path = '/non-existent';
|
|
23
10
|
|
|
@@ -26,28 +13,31 @@ suite('Error messages', () => {
|
|
|
26
13
|
assert.equal(error.bufferSize(), 4 + JSON.stringify(error.toJSON()).length);
|
|
27
14
|
});
|
|
28
15
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
test('
|
|
33
|
-
test('
|
|
34
|
-
test('
|
|
35
|
-
test('
|
|
36
|
-
test('
|
|
37
|
-
test('
|
|
38
|
-
test('
|
|
39
|
-
test('
|
|
40
|
-
test('
|
|
41
|
-
test('
|
|
42
|
-
test('
|
|
43
|
-
test('
|
|
44
|
-
test('
|
|
45
|
-
test('
|
|
46
|
-
test('
|
|
47
|
-
test('
|
|
48
|
-
test('
|
|
49
|
-
test('
|
|
50
|
-
test('
|
|
51
|
-
test('
|
|
52
|
-
test('
|
|
16
|
+
const missing = { path, message: new RegExp(path) };
|
|
17
|
+
const existing = { path: existingFile, message: new RegExp(existingFile) };
|
|
18
|
+
|
|
19
|
+
test('stat', () => assert.rejects(() => fs.promises.stat(path), missing));
|
|
20
|
+
test('mkdir', () => assert.rejects(() => fs.promises.mkdir(existingFile, 0o666), existing));
|
|
21
|
+
test('rmdir', () => assert.rejects(() => fs.promises.rmdir(path), missing));
|
|
22
|
+
test('rmdir', () => assert.rejects(() => fs.promises.rmdir(existingFile), existing));
|
|
23
|
+
test('rename', () => assert.rejects(() => fs.promises.rename(path, 'foo'), missing));
|
|
24
|
+
test('open', () => assert.rejects(() => fs.promises.open(path, 'r'), missing));
|
|
25
|
+
test('readdir', () => assert.rejects(() => fs.promises.readdir(path), missing));
|
|
26
|
+
test('unlink', () => assert.rejects(() => fs.promises.unlink(path), missing));
|
|
27
|
+
test('link', () => assert.rejects(() => fs.promises.link(path, 'foo'), missing));
|
|
28
|
+
test('chmod', () => assert.rejects(() => fs.promises.chmod(path, 0o666), missing));
|
|
29
|
+
test('lstat', () => assert.rejects(() => fs.promises.lstat(path), missing));
|
|
30
|
+
test('readlink', () => assert.rejects(() => fs.promises.readlink(path), missing));
|
|
31
|
+
test('statSync', () => assert.throws(() => fs.statSync(path), missing));
|
|
32
|
+
test('mkdirSync', () => assert.throws(() => fs.mkdirSync(existingFile, 0o666), existing));
|
|
33
|
+
test('rmdirSync', () => assert.throws(() => fs.rmdirSync(path), missing));
|
|
34
|
+
test('rmdirSync', () => assert.throws(() => fs.rmdirSync(existingFile), existing));
|
|
35
|
+
test('renameSync', () => assert.throws(() => fs.renameSync(path, 'foo'), missing));
|
|
36
|
+
test('openSync', () => assert.throws(() => fs.openSync(path, 'r'), missing));
|
|
37
|
+
test('readdirSync', () => assert.throws(() => fs.readdirSync(path), missing));
|
|
38
|
+
test('unlinkSync', () => assert.throws(() => fs.unlinkSync(path), missing));
|
|
39
|
+
test('linkSync', () => assert.throws(() => fs.linkSync(path, 'foo'), missing));
|
|
40
|
+
test('chmodSync', () => assert.throws(() => fs.chmodSync(path, 0o666), missing));
|
|
41
|
+
test('lstatSync', () => assert.throws(() => fs.lstatSync(path), missing));
|
|
42
|
+
test('readlinkSync', () => assert.throws(() => fs.readlinkSync(path), missing));
|
|
53
43
|
});
|
package/tests/fs/watch.test.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import assert from 'node:assert';
|
|
2
2
|
import { suite, test } from 'node:test';
|
|
3
|
-
import { fs } from '../common.js';
|
|
3
|
+
import { fs, type Stats } from '../common.js';
|
|
4
4
|
|
|
5
5
|
const testDir = '/test-watch-dir';
|
|
6
6
|
const testFile = `${testDir}/test.txt`;
|
|
@@ -33,7 +33,7 @@ suite('Watch Features', () => {
|
|
|
33
33
|
});
|
|
34
34
|
|
|
35
35
|
test('fs.watchFile should detect changes to a file', async () => {
|
|
36
|
-
const listener = (curr:
|
|
36
|
+
const listener = (curr: Stats, prev: Stats) => {
|
|
37
37
|
assert(curr.mtimeMs != prev.mtimeMs);
|
|
38
38
|
fs.unwatchFile(testFile, listener);
|
|
39
39
|
};
|
package/tests/setup/cow+fetch.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { readFileSync } from 'node:fs';
|
|
|
3
3
|
import { createServer } from 'node:http';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
import { configureSingle, Fetch, InMemory, Overlay } from '../../dist/index.js';
|
|
6
|
-
import { data, tmp } from '
|
|
6
|
+
import { data, tmp } from '../setup.js';
|
|
7
7
|
|
|
8
8
|
const port = 26514,
|
|
9
9
|
index = tmp + '/index.json';
|
package/tests/setup/memory.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { join, relative } from 'node:path';
|
|
2
2
|
import { statSync, readFileSync, readdirSync, existsSync, mkdirSync } from 'node:fs';
|
|
3
|
-
import { fs } from '
|
|
3
|
+
import { fs as _fs } from '../dist/index.js';
|
|
4
|
+
import type { BoundContext } from '../dist/context.js';
|
|
4
5
|
|
|
5
|
-
export const data = join(import.meta.dirname, '
|
|
6
|
+
export const data = join(import.meta.dirname, 'data');
|
|
6
7
|
|
|
7
|
-
export const tmp = join(import.meta.dirname, '
|
|
8
|
+
export const tmp = join(import.meta.dirname, 'tmp');
|
|
8
9
|
|
|
9
10
|
if (!existsSync(tmp)) {
|
|
10
11
|
mkdirSync(tmp);
|
|
11
12
|
}
|
|
12
13
|
|
|
13
|
-
export function copy(_path: string) {
|
|
14
|
+
export function copy(_path: string, fs: typeof _fs | BoundContext = _fs) {
|
|
14
15
|
const path = relative(data, _path) || '/';
|
|
15
16
|
const stats = statSync(_path);
|
|
16
17
|
|
|
@@ -23,6 +24,6 @@ export function copy(_path: string) {
|
|
|
23
24
|
fs.mkdirSync(path);
|
|
24
25
|
}
|
|
25
26
|
for (const file of readdirSync(_path)) {
|
|
26
|
-
copy(join(_path, file));
|
|
27
|
+
copy(join(_path, file), fs);
|
|
27
28
|
}
|
|
28
29
|
}
|