Files
node/test/parallel/test-vfs-fd.js
T
Matteo Collina 49ad95045a vfs: unflag
Enable node:vfs by default. --no-experimental-vfs disables node:vfs
exposure and --vfs-load.

Assisted-by: pi
Signed-off-by: Matteo Collina <hello@matteocollina.com>
PR-URL: https://github.com/nodejs/node/pull/66318
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
2026-10-15 07:53:03 +00:00

340 lines
8.2 KiB
JavaScript

// Flags: --disable-warning=ExperimentalWarning
'use strict';
const common = require('../common');
const assert = require('assert');
const vfs = require('node:vfs');
// Test openSync and closeSync
{
const myVfs = vfs.create();
myVfs.writeFileSync('/file.txt', 'hello world');
const fd = myVfs.openSync('/file.txt');
assert.ok((fd & 0x40000000) !== 0, 'VFS fd should have bit 30 set');
myVfs.closeSync(fd);
}
// Test openSync with non-existent file
{
const myVfs = vfs.create();
assert.throws(() => {
myVfs.openSync('/nonexistent.txt');
}, { code: 'ENOENT' });
}
// Test openSync with directory
{
const myVfs = vfs.create();
myVfs.mkdirSync('/mydir', { recursive: true });
assert.throws(() => {
myVfs.openSync('/mydir');
}, { code: 'EISDIR' });
}
// Test closeSync with invalid fd
{
const myVfs = vfs.create();
assert.throws(() => {
myVfs.closeSync(12345);
}, { code: 'EBADF' });
}
// Test readSync
{
const myVfs = vfs.create();
myVfs.writeFileSync('/file.txt', 'hello world');
const fd = myVfs.openSync('/file.txt');
const buffer = Buffer.alloc(5);
const bytesRead = myVfs.readSync(fd, buffer, 0, 5, 0);
assert.strictEqual(bytesRead, 5);
assert.strictEqual(buffer.toString(), 'hello');
myVfs.closeSync(fd);
}
// Test readSync with position tracking
{
const myVfs = vfs.create();
myVfs.writeFileSync('/file.txt', 'hello world');
const fd = myVfs.openSync('/file.txt');
const buffer1 = Buffer.alloc(5);
const buffer2 = Buffer.alloc(6);
// Read first 5 bytes
let bytesRead = myVfs.readSync(fd, buffer1, 0, 5, null);
assert.strictEqual(bytesRead, 5);
assert.strictEqual(buffer1.toString(), 'hello');
// Continue reading (position should advance)
bytesRead = myVfs.readSync(fd, buffer2, 0, 6, null);
assert.strictEqual(bytesRead, 6);
assert.strictEqual(buffer2.toString(), ' world');
myVfs.closeSync(fd);
}
// Test readSync with Node's current-position sentinel
{
const myVfs = vfs.create();
myVfs.writeFileSync('/file.txt', 'hello world');
const fd = myVfs.openSync('/file.txt');
const buffer1 = Buffer.alloc(5);
const buffer2 = Buffer.alloc(6);
let bytesRead = myVfs.readSync(fd, buffer1, 0, 5, -1);
assert.strictEqual(bytesRead, 5);
assert.strictEqual(buffer1.toString(), 'hello');
bytesRead = myVfs.readSync(fd, buffer2, 0, 6, -1);
assert.strictEqual(bytesRead, 6);
assert.strictEqual(buffer2.toString(), ' world');
myVfs.closeSync(fd);
}
// Test readSync with explicit position
{
const myVfs = vfs.create();
myVfs.writeFileSync('/file.txt', 'hello world');
const fd = myVfs.openSync('/file.txt');
const buffer = Buffer.alloc(5);
// Read from position 6 (start of "world")
const bytesRead = myVfs.readSync(fd, buffer, 0, 5, 6);
assert.strictEqual(bytesRead, 5);
assert.strictEqual(buffer.toString(), 'world');
myVfs.closeSync(fd);
}
// Test readSync at end of file
{
const myVfs = vfs.create();
myVfs.writeFileSync('/file.txt', 'short');
const fd = myVfs.openSync('/file.txt');
const buffer = Buffer.alloc(10);
// Read from position beyond file
const bytesRead = myVfs.readSync(fd, buffer, 0, 10, 100);
assert.strictEqual(bytesRead, 0);
myVfs.closeSync(fd);
}
// Test readSync with invalid fd
{
const myVfs = vfs.create();
const buffer = Buffer.alloc(10);
assert.throws(() => {
myVfs.readSync(99999, buffer, 0, 10, 0);
}, { code: 'EBADF' });
}
// Test fstatSync
{
const myVfs = vfs.create();
myVfs.writeFileSync('/file.txt', 'hello world');
const fd = myVfs.openSync('/file.txt');
const stats = myVfs.fstatSync(fd);
assert.strictEqual(stats.isFile(), true);
assert.strictEqual(stats.isDirectory(), false);
assert.strictEqual(stats.size, 11);
myVfs.closeSync(fd);
}
// Test fstatSync with invalid fd
{
const myVfs = vfs.create();
assert.throws(() => {
myVfs.fstatSync(99999);
}, { code: 'EBADF' });
}
// Test async open and close
{
const myVfs = vfs.create();
myVfs.writeFileSync('/async-file.txt', 'async content');
myVfs.open('/async-file.txt', common.mustCall((err, fd) => {
assert.strictEqual(err, null);
assert.ok((fd & 0x40000000) !== 0);
myVfs.close(fd, common.mustCall((err) => {
assert.strictEqual(err, null);
}));
}));
}
// Test async open with error
{
const myVfs = vfs.create();
myVfs.open('/nonexistent.txt', common.mustCall((err, fd) => {
assert.strictEqual(err.code, 'ENOENT');
assert.strictEqual(fd, undefined);
}));
}
// Test async close with invalid fd
{
const myVfs = vfs.create();
myVfs.close(99999, common.mustCall((err) => {
assert.strictEqual(err.code, 'EBADF');
}));
}
// Test async read
{
const myVfs = vfs.create();
myVfs.writeFileSync('/read-test.txt', 'read content');
myVfs.open('/read-test.txt', common.mustCall((err, fd) => {
assert.strictEqual(err, null);
const buffer = Buffer.alloc(4);
myVfs.read(fd, buffer, 0, 4, 0, common.mustCall((err, bytesRead, buf) => {
assert.strictEqual(err, null);
assert.strictEqual(bytesRead, 4);
assert.strictEqual(buf, buffer);
assert.strictEqual(buffer.toString(), 'read');
myVfs.close(fd, common.mustCall());
}));
}));
}
// Test async read with position tracking
{
const myVfs = vfs.create();
myVfs.writeFileSync('/track-test.txt', 'ABCDEFGHIJ');
myVfs.open('/track-test.txt', common.mustCall((err, fd) => {
assert.strictEqual(err, null);
const buffer1 = Buffer.alloc(3);
const buffer2 = Buffer.alloc(3);
myVfs.read(fd, buffer1, 0, 3, null, common.mustCall((err, bytesRead, buf) => {
assert.strictEqual(err, null);
assert.strictEqual(bytesRead, 3);
assert.strictEqual(buffer1.toString(), 'ABC');
// Continue reading without explicit position
myVfs.read(fd, buffer2, 0, 3, null, common.mustCall((err, bytesRead, buf) => {
assert.strictEqual(err, null);
assert.strictEqual(bytesRead, 3);
assert.strictEqual(buffer2.toString(), 'DEF');
myVfs.close(fd, common.mustCall());
}));
}));
}));
}
// Test async read with invalid fd
{
const myVfs = vfs.create();
const buffer = Buffer.alloc(10);
myVfs.read(99999, buffer, 0, 10, 0, common.mustCall((err, bytesRead, buf) => {
assert.strictEqual(err.code, 'EBADF');
}));
}
// Test async fstat
{
const myVfs = vfs.create();
myVfs.writeFileSync('/fstat-test.txt', '12345');
myVfs.open('/fstat-test.txt', common.mustCall((err, fd) => {
assert.strictEqual(err, null);
myVfs.fstat(fd, common.mustCall((err, stats) => {
assert.strictEqual(err, null);
assert.strictEqual(stats.isFile(), true);
assert.strictEqual(stats.size, 5);
myVfs.close(fd, common.mustCall());
}));
}));
}
// Test async fstat with invalid fd
{
const myVfs = vfs.create();
myVfs.fstat(99999, common.mustCall((err, stats) => {
assert.strictEqual(err.code, 'EBADF');
}));
}
// Test that separate VFS instances have separate fd spaces
{
const vfs1 = vfs.create();
const vfs2 = vfs.create();
vfs1.writeFileSync('/file1.txt', 'content1');
vfs2.writeFileSync('/file2.txt', 'content2');
const fd1 = vfs1.openSync('/file1.txt');
const fd2 = vfs2.openSync('/file2.txt');
// Both should get valid fds
assert.ok((fd1 & 0x40000000) !== 0);
assert.ok((fd2 & 0x40000000) !== 0);
// Read from fd1 using vfs1
const buf1 = Buffer.alloc(8);
const read1 = vfs1.readSync(fd1, buf1, 0, 8, 0);
assert.strictEqual(read1, 8);
assert.strictEqual(buf1.toString(), 'content1');
// Read from fd2 using vfs2
const buf2 = Buffer.alloc(8);
const read2 = vfs2.readSync(fd2, buf2, 0, 8, 0);
assert.strictEqual(read2, 8);
assert.strictEqual(buf2.toString(), 'content2');
vfs1.closeSync(fd1);
vfs2.closeSync(fd2);
}
// Test multiple opens of same file
{
const myVfs = vfs.create();
myVfs.writeFileSync('/multi.txt', 'multi content');
const fd1 = myVfs.openSync('/multi.txt');
const fd2 = myVfs.openSync('/multi.txt');
assert.notStrictEqual(fd1, fd2);
const buf1 = Buffer.alloc(5);
const buf2 = Buffer.alloc(5);
myVfs.readSync(fd1, buf1, 0, 5, 0);
myVfs.readSync(fd2, buf2, 0, 5, 0);
assert.strictEqual(buf1.toString(), 'multi');
assert.strictEqual(buf2.toString(), 'multi');
myVfs.closeSync(fd1);
myVfs.closeSync(fd2);
}