diff --git a/test/parallel/test-fs-promises-file-handle-readFile.js b/test/parallel/test-fs-promises-file-handle-readFile.js index 4416744bf5189a..d1e724d201ee71 100644 --- a/test/parallel/test-fs-promises-file-handle-readFile.js +++ b/test/parallel/test-fs-promises-file-handle-readFile.js @@ -6,9 +6,15 @@ const common = require('../common'); // FileHandle.readFile method. const fs = require('fs'); -const { open } = fs.promises; +const { + open, + readFile, + writeFile, + truncate +} = fs.promises; const path = require('path'); const tmpdir = require('../common/tmpdir'); +const tick = require('../common/tick'); const assert = require('assert'); const tmpDir = tmpdir.path; @@ -45,6 +51,70 @@ async function validateReadFileProc() { assert.ok(hostname.length > 0); } +async function doReadAndCancel() { + // Signal aborted from the start + { + const filePathForHandle = path.resolve(tmpDir, 'dogs-running.txt'); + const fileHandle = await open(filePathForHandle, 'w+'); + const buffer = Buffer.from('Dogs running'.repeat(10000), 'utf8'); + fs.writeFileSync(filePathForHandle, buffer); + const controller = new AbortController(); + const { signal } = controller; + controller.abort(); + await assert.rejects(readFile(fileHandle, { signal }), { + name: 'AbortError' + }); + } + + // Signal aborted on first tick + { + const filePathForHandle = path.resolve(tmpDir, 'dogs-running1.txt'); + const fileHandle = await open(filePathForHandle, 'w+'); + const buffer = Buffer.from('Dogs running'.repeat(10000), 'utf8'); + fs.writeFileSync(filePathForHandle, buffer); + const controller = new AbortController(); + const { signal } = controller; + tick(1, () => controller.abort()); + await assert.rejects(readFile(fileHandle, { signal }), { + name: 'AbortError' + }); + } + + // Signal aborted right before buffer read + { + const newFile = path.resolve(tmpDir, 'dogs-running2.txt'); + const buffer = Buffer.from('Dogs running'.repeat(1000), 'utf8'); + fs.writeFileSync(newFile, buffer); + + const fileHandle = await open(newFile, 'r'); + + const controller = new AbortController(); + const { signal } = controller; + tick(2, () => controller.abort()); + await assert.rejects(fileHandle.readFile({ signal, encoding: 'utf8' }), { + name: 'AbortError' + }); + } + + // Validate file size is within range for reading + { + // Variable taken from https://github.com/nodejs/node/blob/master/lib/internal/fs/promises.js#L5 + const kIoMaxLength = 2 ** 31 - 1; + + const newFile = path.resolve(tmpDir, 'dogs-running3.txt'); + await writeFile(newFile, Buffer.from('0')); + await truncate(newFile, kIoMaxLength + 1); + + const fileHandle = await open(newFile, 'r'); + + await assert.rejects(fileHandle.readFile(), { + name: 'RangeError', + code: 'ERR_FS_FILE_TOO_LARGE' + }); + } +} + validateReadFile() - .then(() => validateReadFileProc()) + .then(validateReadFileProc) + .then(doReadAndCancel) .then(common.mustCall()); diff --git a/test/parallel/test-fs-promises-file-handle-writeFile.js b/test/parallel/test-fs-promises-file-handle-writeFile.js index 25b767a0abcf62..bd90a79149b5f1 100644 --- a/test/parallel/test-fs-promises-file-handle-writeFile.js +++ b/test/parallel/test-fs-promises-file-handle-writeFile.js @@ -3,10 +3,10 @@ const common = require('../common'); // The following tests validate base functionality for the fs.promises -// FileHandle.readFile method. +// FileHandle.writeFile method. const fs = require('fs'); -const { open } = fs.promises; +const { open, writeFile } = fs.promises; const path = require('path'); const tmpdir = require('../common/tmpdir'); const assert = require('assert'); @@ -26,5 +26,19 @@ async function validateWriteFile() { await fileHandle.close(); } +// Signal aborted while writing file +async function doWriteAndCancel() { + const filePathForHandle = path.resolve(tmpDir, 'dogs-running.txt'); + const fileHandle = await open(filePathForHandle, 'w+'); + const buffer = Buffer.from('dogs running'.repeat(10000), 'utf8'); + const controller = new AbortController(); + const { signal } = controller; + process.nextTick(() => controller.abort()); + await assert.rejects(writeFile(fileHandle, buffer, { signal }), { + name: 'AbortError' + }); +} + validateWriteFile() + .then(doWriteAndCancel) .then(common.mustCall()); diff --git a/test/parallel/test-fs-promises-writefile.js b/test/parallel/test-fs-promises-writefile.js index 5c13c503295682..7fbe12dda4dc2d 100644 --- a/test/parallel/test-fs-promises-writefile.js +++ b/test/parallel/test-fs-promises-writefile.js @@ -31,7 +31,7 @@ async function doWriteWithCancel() { } async function doAppend() { - await fsPromises.appendFile(dest, buffer2); + await fsPromises.appendFile(dest, buffer2, { flag: null }); const data = fs.readFileSync(dest); const buf = Buffer.concat([buffer, buffer2]); assert.deepStrictEqual(buf, data); diff --git a/test/parallel/test-fs-promises.js b/test/parallel/test-fs-promises.js index f23df685eac072..e01fc2ec6ad1e7 100644 --- a/test/parallel/test-fs-promises.js +++ b/test/parallel/test-fs-promises.js @@ -16,6 +16,7 @@ const { link, lchmod, lstat, + lutimes, mkdir, mkdtemp, open, @@ -140,6 +141,13 @@ async function getHandle(dest) { await handle.close(); } + // Use fallback buffer allocation when input not buffer + { + const handle = await getHandle(dest); + const ret = await handle.read(0, 0, 0, 0); + assert.strictEqual(ret.buffer.length, 16384); + } + // Bytes written to file match buffer { const handle = await getHandle(dest); @@ -226,6 +234,19 @@ async function getHandle(dest) { await handle.close(); } + // Set modification times with lutimes + { + const a_time = new Date(); + a_time.setMinutes(a_time.getMinutes() - 1); + const m_time = new Date(); + m_time.setHours(m_time.getHours() - 1); + await lutimes(dest, a_time, m_time); + const stats = await stat(dest); + + assert.strictEqual(a_time.toString(), stats.atime.toString()); + assert.strictEqual(m_time.toString(), stats.mtime.toString()); + } + // create symlink { const newPath = path.resolve(tmpDir, 'baz2.js'); @@ -270,6 +291,15 @@ async function getHandle(dest) { } } + // specify symlink type + { + const dir = path.join(tmpDir, nextdir()); + await symlink(tmpDir, dir, 'dir'); + const stats = await lstat(dir); + assert.strictEqual(stats.isSymbolicLink(), true); + await unlink(dir); + } + // create hard link { const newPath = path.resolve(tmpDir, 'baz2.js'); @@ -296,6 +326,14 @@ async function getHandle(dest) { await unlink(newFile); } + // Use fallback encoding when input is null + { + const newFile = path.resolve(tmpDir, 'dogs_running.js'); + await writeFile(newFile, 'dogs running', { encoding: null }); + const fileExists = fs.existsSync(newFile); + assert.strictEqual(fileExists, true); + } + // `mkdir` when options is number. { const dir = path.join(tmpDir, nextdir());