diff --git a/test/parallel/test-module-stat.js b/test/parallel/test-module-stat.js new file mode 100644 index 00000000000000..eaaeb898afd603 --- /dev/null +++ b/test/parallel/test-module-stat.js @@ -0,0 +1,25 @@ +'use strict'; +require('../common'); + +// This tests Module._stat. + +const Module = require('module'); +const fs = require('fs'); +const tmpdir = require('../common/tmpdir'); +const { ok, strictEqual } = require('assert'); +const { join } = require('path'); + +const directory = join(tmpdir.path, 'directory'); +const doesNotExist = join(tmpdir.path, 'does-not-exist'); +const file = join(tmpdir.path, 'file.js'); + +tmpdir.refresh(); +fs.writeFileSync(file, "module.exports = { a: 'b' }"); +fs.mkdirSync(directory); + +strictEqual(Module._stat(directory), 1); // Returns 1 for directories. +strictEqual(Module._stat(file), 0); // Returns 0 for files. +ok(Module._stat(doesNotExist) < 0); // Returns a negative integer for any other kind of strings. + +// TODO(RaisinTen): Add tests that make sure that Module._stat() does not crash when called +// with a non-string data type. It crashes currently. diff --git a/test/parallel/test-vfs.js b/test/parallel/test-vfs.js new file mode 100644 index 00000000000000..c4842be3a839d0 --- /dev/null +++ b/test/parallel/test-vfs.js @@ -0,0 +1,88 @@ +'use strict'; +const common = require('../common'); + +// This tests the creation of a vfs by monkey-patching fs and Module._stat. + +const Module = require('module'); +const fs = require('fs'); +const tmpdir = require('../common/tmpdir'); +const { deepStrictEqual, ok, strictEqual, throws } = require('assert'); +const { join } = require('path'); + +const directory = join(tmpdir.path, 'directory'); +const doesNotExist = join(tmpdir.path, 'does-not-exist'); +const file = join(tmpdir.path, 'file.js'); + +tmpdir.refresh(); +fs.writeFileSync(file, "module.exports = { a: 'b' }"); +fs.mkdirSync(directory); + +strictEqual(Module._stat(directory), 1); +ok(Module._stat(doesNotExist) < 0); +strictEqual(Module._stat(file), 0); + +const vfsDirectory = join(process.execPath, 'directory'); +const vfsDoesNotExist = join(process.execPath, 'does-not-exist'); +const vfsFile = join(process.execPath, 'file.js'); + +ok(Module._stat(vfsDirectory) < 0); +ok(Module._stat(vfsDoesNotExist) < 0); +ok(Module._stat(vfsFile) < 0); + +deepStrictEqual(require(file), { a: 'b' }); +throws(() => require(vfsFile), { code: 'MODULE_NOT_FOUND' }); + +common.expectWarning( + 'ExperimentalWarning', + 'Module._stat is an experimental feature. This feature could change at any time'); + +process.on('warning', common.mustCall()); + +const originalStat = Module._stat; +Module._stat = function(filename) { + if (!filename.startsWith(process.execPath)) { + return originalStat(filename); + } + + if (filename === process.execPath) { + return 1; + } + + switch (filename) { + case vfsDirectory: + return 1; + case vfsDoesNotExist: + return -2; + case vfsFile: + return 0; + } +}; + +const originalReadFileSync = fs.readFileSync; +// TODO(aduh95): We'd like to have a better way to achieve this without monkey-patching fs. +fs.readFileSync = function readFileSync(pathArgument, options) { + if (!pathArgument.startsWith(process.execPath)) { + return originalReadFileSync.apply(this, arguments); + } + if (pathArgument === vfsFile) { + return "module.exports = { x: 'y' };"; + } + throw new Error(); +}; + +fs.realpathSync = function realpathSync(pathArgument, options) { + return pathArgument; +}; + +strictEqual(Module._stat(directory), 1); +ok(Module._stat(doesNotExist) < 0); +strictEqual(Module._stat(file), 0); + +strictEqual(Module._stat(vfsDirectory), 1); +ok(Module._stat(vfsDoesNotExist) < 0); +strictEqual(Module._stat(vfsFile), 0); + +strictEqual(Module._stat(process.execPath), 1); + +deepStrictEqual(require(file), { a: 'b' }); +deepStrictEqual(require(vfsFile), { x: 'y' });