Skip to content

Commit 09e2357

Browse files
committed
test: add VFS internals coverage tests
Add tests for internal VFS utility functions and provider base class to improve code coverage: - router.js: splitPath, getParentPath, getBaseName - provider.js: readonly EROFS checks for all write operations - provider.js: ERR_METHOD_NOT_IMPLEMENTED for unimplemented methods PR-URL: #61478
1 parent 306b825 commit 09e2357

1 file changed

Lines changed: 107 additions & 0 deletions

File tree

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// Flags: --expose-internals
2+
'use strict';
3+
4+
const common = require('../common');
5+
const assert = require('assert');
6+
7+
// Test internal VFS utility functions for coverage.
8+
9+
// === Router utility functions ===
10+
const {
11+
splitPath,
12+
getParentPath,
13+
getBaseName,
14+
isUnderMountPoint,
15+
getRelativePath,
16+
isAbsolutePath,
17+
} = require('internal/vfs/router');
18+
19+
// splitPath
20+
assert.deepStrictEqual(splitPath('/'), []);
21+
assert.deepStrictEqual(splitPath('/foo'), ['foo']);
22+
assert.deepStrictEqual(splitPath('/foo/bar'), ['foo', 'bar']);
23+
assert.deepStrictEqual(splitPath('/a/b/c/d'), ['a', 'b', 'c', 'd']);
24+
25+
// getParentPath
26+
assert.strictEqual(getParentPath('/'), null);
27+
assert.strictEqual(getParentPath('/foo'), '/');
28+
assert.strictEqual(getParentPath('/foo/bar'), '/foo');
29+
assert.strictEqual(getParentPath('/a/b/c'), '/a/b');
30+
31+
// getBaseName
32+
assert.strictEqual(getBaseName('/foo'), 'foo');
33+
assert.strictEqual(getBaseName('/foo/bar'), 'bar');
34+
assert.strictEqual(getBaseName('/a/b/c.txt'), 'c.txt');
35+
36+
// isAbsolutePath
37+
assert.strictEqual(isAbsolutePath('/foo'), true);
38+
assert.strictEqual(isAbsolutePath('foo'), false);
39+
assert.strictEqual(isAbsolutePath('./foo'), false);
40+
41+
// isUnderMountPoint (already tested indirectly but exercised here directly)
42+
assert.strictEqual(isUnderMountPoint('/mount', '/mount'), true);
43+
assert.strictEqual(isUnderMountPoint('/mount/file', '/mount'), true);
44+
assert.strictEqual(isUnderMountPoint('/mountx', '/mount'), false);
45+
assert.strictEqual(isUnderMountPoint('/other', '/mount'), false);
46+
// Root mount point
47+
assert.strictEqual(isUnderMountPoint('/anything', '/'), true);
48+
49+
// getRelativePath
50+
assert.strictEqual(getRelativePath('/mount', '/mount'), '/');
51+
assert.strictEqual(getRelativePath('/mount/file.js', '/mount'), '/file.js');
52+
assert.strictEqual(getRelativePath('/mount/a/b', '/mount'), '/a/b');
53+
// Root mount point
54+
assert.strictEqual(getRelativePath('/foo/bar', '/'), '/foo/bar');
55+
56+
// === Provider base class readonly checks ===
57+
const { VirtualProvider } = require('internal/vfs/provider');
58+
59+
class ReadonlyProvider extends VirtualProvider {
60+
get readonly() { return true; }
61+
}
62+
63+
const readonlyProvider = new ReadonlyProvider();
64+
65+
// All write operations should throw EROFS when readonly
66+
assert.throws(() => readonlyProvider.mkdirSync('/dir'), { code: 'EROFS' });
67+
assert.throws(() => readonlyProvider.rmdirSync('/dir'), { code: 'EROFS' });
68+
assert.throws(() => readonlyProvider.unlinkSync('/file'), { code: 'EROFS' });
69+
assert.throws(() => readonlyProvider.renameSync('/a', '/b'), { code: 'EROFS' });
70+
assert.throws(() => readonlyProvider.writeFileSync('/f', 'data'), { code: 'EROFS' });
71+
assert.throws(() => readonlyProvider.appendFileSync('/f', 'data'), { code: 'EROFS' });
72+
assert.throws(() => readonlyProvider.copyFileSync('/a', '/b'), { code: 'EROFS' });
73+
assert.throws(() => readonlyProvider.symlinkSync('/target', '/link'), { code: 'EROFS' });
74+
75+
// Async versions
76+
assert.rejects(readonlyProvider.mkdir('/dir'), { code: 'EROFS' }).then(common.mustCall());
77+
assert.rejects(readonlyProvider.rmdir('/dir'), { code: 'EROFS' }).then(common.mustCall());
78+
assert.rejects(readonlyProvider.unlink('/file'), { code: 'EROFS' }).then(common.mustCall());
79+
assert.rejects(readonlyProvider.rename('/a', '/b'), { code: 'EROFS' }).then(common.mustCall());
80+
assert.rejects(readonlyProvider.writeFile('/f', 'data'), { code: 'EROFS' }).then(common.mustCall());
81+
assert.rejects(readonlyProvider.appendFile('/f', 'data'), { code: 'EROFS' }).then(common.mustCall());
82+
assert.rejects(readonlyProvider.copyFile('/a', '/b'), { code: 'EROFS' }).then(common.mustCall());
83+
assert.rejects(readonlyProvider.symlink('/target', '/link'), { code: 'EROFS' }).then(common.mustCall());
84+
85+
// === Provider base class ERR_METHOD_NOT_IMPLEMENTED for non-readonly ===
86+
const baseProvider = new VirtualProvider();
87+
88+
// These should throw ERR_METHOD_NOT_IMPLEMENTED (not readonly, just unimplemented)
89+
assert.throws(() => baseProvider.mkdirSync('/dir'), { code: 'ERR_METHOD_NOT_IMPLEMENTED' });
90+
assert.throws(() => baseProvider.rmdirSync('/dir'), { code: 'ERR_METHOD_NOT_IMPLEMENTED' });
91+
assert.throws(() => baseProvider.unlinkSync('/file'), { code: 'ERR_METHOD_NOT_IMPLEMENTED' });
92+
assert.throws(() => baseProvider.renameSync('/a', '/b'), { code: 'ERR_METHOD_NOT_IMPLEMENTED' });
93+
assert.throws(() => baseProvider.symlinkSync('/t', '/l'), { code: 'ERR_METHOD_NOT_IMPLEMENTED' });
94+
assert.throws(() => baseProvider.readdirSync('/dir'), { code: 'ERR_METHOD_NOT_IMPLEMENTED' });
95+
assert.throws(() => baseProvider.readlinkSync('/link'), { code: 'ERR_METHOD_NOT_IMPLEMENTED' });
96+
assert.throws(() => baseProvider.watch('/path'), { code: 'ERR_METHOD_NOT_IMPLEMENTED' });
97+
assert.throws(() => baseProvider.watchAsync('/path'), { code: 'ERR_METHOD_NOT_IMPLEMENTED' });
98+
assert.throws(() => baseProvider.watchFile('/path'), { code: 'ERR_METHOD_NOT_IMPLEMENTED' });
99+
assert.throws(() => baseProvider.unwatchFile('/path'), { code: 'ERR_METHOD_NOT_IMPLEMENTED' });
100+
101+
// Async unimplemented methods
102+
assert.rejects(baseProvider.mkdir('/dir'), { code: 'ERR_METHOD_NOT_IMPLEMENTED' }).then(common.mustCall());
103+
assert.rejects(baseProvider.rmdir('/dir'), { code: 'ERR_METHOD_NOT_IMPLEMENTED' }).then(common.mustCall());
104+
assert.rejects(baseProvider.unlink('/file'), { code: 'ERR_METHOD_NOT_IMPLEMENTED' }).then(common.mustCall());
105+
assert.rejects(baseProvider.rename('/a', '/b'), { code: 'ERR_METHOD_NOT_IMPLEMENTED' }).then(common.mustCall());
106+
assert.rejects(baseProvider.readlink('/link'), { code: 'ERR_METHOD_NOT_IMPLEMENTED' }).then(common.mustCall());
107+
assert.rejects(baseProvider.symlink('/t', '/l'), { code: 'ERR_METHOD_NOT_IMPLEMENTED' }).then(common.mustCall());

0 commit comments

Comments
 (0)