diff options
Diffstat (limited to 'tests/node_compat/test/parallel/test-fs-opendir.js')
-rw-r--r-- | tests/node_compat/test/parallel/test-fs-opendir.js | 300 |
1 files changed, 300 insertions, 0 deletions
diff --git a/tests/node_compat/test/parallel/test-fs-opendir.js b/tests/node_compat/test/parallel/test-fs-opendir.js new file mode 100644 index 000000000..75c4aa074 --- /dev/null +++ b/tests/node_compat/test/parallel/test-fs-opendir.js @@ -0,0 +1,300 @@ +// deno-fmt-ignore-file +// deno-lint-ignore-file + +// Copyright Joyent and Node contributors. All rights reserved. MIT license. +// Taken from Node 18.8.0 +// This file is automatically generated by "node/_tools/setup.ts". Do not modify this file manually + +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const fs = require('fs'); +const path = require('path'); + +const tmpdir = require('../common/tmpdir'); + +const testDir = tmpdir.path; +const files = ['empty', 'files', 'for', 'just', 'testing']; + +// Make sure tmp directory is clean +tmpdir.refresh(); + +// Create the necessary files +files.forEach(function(filename) { + fs.closeSync(fs.openSync(path.join(testDir, filename), 'w')); +}); + +function assertDirent(dirent) { + assert(dirent instanceof fs.Dirent); + assert.strictEqual(dirent.isFile(), true); + assert.strictEqual(dirent.isDirectory(), false); + // TODO(wafuwafu13): Support these method + // assert.strictEqual(dirent.isSocket(), false); + // assert.strictEqual(dirent.isBlockDevice(), false); + // assert.strictEqual(dirent.isCharacterDevice(), false); + // assert.strictEqual(dirent.isFIFO(), false); + assert.strictEqual(dirent.isSymbolicLink(), false); +} + +// NOTE: this error doesn't occur in Deno +const dirclosedError = { + code: 'ERR_DIR_CLOSED' +}; + +// NOTE: this error doesn't occur in Deno +const dirconcurrentError = { + code: 'ERR_DIR_CONCURRENT_OPERATION' +}; + +const invalidCallbackObj = { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError' +}; + +// Check the opendir Sync version +{ + const dir = fs.opendirSync(testDir); + const entries = files.map(() => { + const dirent = dir.readSync(); + assertDirent(dirent); + return dirent.name; + }); + assert.deepStrictEqual(files, entries.sort()); + + // dir.read should return null when no more entries exist + assert.strictEqual(dir.readSync(), null); + + // check .path + assert.strictEqual(dir.path, testDir); + + dir.closeSync(); + + // assert.throws(() => dir.readSync(), dirclosedError); + // assert.throws(() => dir.closeSync(), dirclosedError); +} + +// Check the opendir async version +fs.opendir(testDir, common.mustSucceed((dir) => { + let sync = true; + dir.read(common.mustSucceed((dirent) => { + assert(!sync); + + // Order is operating / file system dependent + assert(files.includes(dirent.name), `'files' should include ${dirent}`); + assertDirent(dirent); + + let syncInner = true; + dir.read(common.mustSucceed((dirent) => { + assert(!syncInner); + + dir.close(common.mustSucceed()); + })); + syncInner = false; + })); + sync = false; +})); + +// opendir() on file should throw ENOTDIR +assert.throws(function() { + fs.opendirSync(__filename); +}, /Error: ENOTDIR: not a directory/); + +assert.throws(function() { + fs.opendir(__filename); +}, /TypeError \[ERR_INVALID_ARG_TYPE\]: The "callback" argument must be of type function/); + +fs.opendir(__filename, common.mustCall(function(e) { + assert.strictEqual(e.code, 'ENOTDIR'); +})); + +[false, 1, [], {}, null, undefined].forEach((i) => { + assert.throws( + () => fs.opendir(i, common.mustNotCall()), + { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError' + } + ); + assert.throws( + () => fs.opendirSync(i), + { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError' + } + ); +}); + +// Promise-based tests +async function doPromiseTest() { + // Check the opendir Promise version + const dir = await fs.promises.opendir(testDir); + const entries = []; + + let i = files.length; + while (i--) { + const dirent = await dir.read(); + entries.push(dirent.name); + assertDirent(dirent); + } + + assert.deepStrictEqual(files, entries.sort()); + + // dir.read should return null when no more entries exist + assert.strictEqual(await dir.read(), null); + + await dir.close(); +} +doPromiseTest().then(common.mustCall()); + +// Async iterator +async function doAsyncIterTest() { + const entries = []; + for await (const dirent of await fs.promises.opendir(testDir)) { + entries.push(dirent.name); + assertDirent(dirent); + } + + assert.deepStrictEqual(files, entries.sort()); + + // Automatically closed during iterator +} +doAsyncIterTest().then(common.mustCall()); + +// Async iterators should do automatic cleanup + +async function doAsyncIterBreakTest() { + const dir = await fs.promises.opendir(testDir); + for await (const dirent of dir) { // eslint-disable-line no-unused-vars + break; + } + + // await assert.rejects(async () => dir.read(), dirclosedError); +} +doAsyncIterBreakTest().then(common.mustCall()); + +async function doAsyncIterReturnTest() { + const dir = await fs.promises.opendir(testDir); + await (async function() { + for await (const dirent of dir) { + return; + } + })(); + + // await assert.rejects(async () => dir.read(), dirclosedError); +} +doAsyncIterReturnTest().then(common.mustCall()); + +async function doAsyncIterThrowTest() { + const dir = await fs.promises.opendir(testDir); + try { + for await (const dirent of dir) { // eslint-disable-line no-unused-vars + throw new Error('oh no'); + } + } catch (err) { + if (err.message !== 'oh no') { + throw err; + } + } + + // await assert.rejects(async () => dir.read(), dirclosedError); +} +doAsyncIterThrowTest().then(common.mustCall()); + +// Check error thrown on invalid values of bufferSize +for (const bufferSize of [-1, 0, 0.5, 1.5, Infinity, NaN]) { + assert.throws( + () => fs.opendirSync(testDir, common.mustNotMutateObjectDeep({ bufferSize })), + { + code: 'ERR_OUT_OF_RANGE' + }); +} +for (const bufferSize of ['', '1', null]) { + assert.throws( + () => fs.opendirSync(testDir, common.mustNotMutateObjectDeep({ bufferSize })), + { + code: 'ERR_INVALID_ARG_TYPE' + }); +} + +// Check that passing a positive integer as bufferSize works +{ + const dir = fs.opendirSync(testDir, common.mustNotMutateObjectDeep({ bufferSize: 1024 })); + assertDirent(dir.readSync()); + dir.close(); +} + +// TODO(wafuwafu13): enable this +// // Check that when passing a string instead of function - throw an exception +// async function doAsyncIterInvalidCallbackTest() { +// const dir = await fs.promises.opendir(testDir); +// assert.throws(() => dir.close('not function'), invalidCallbackObj); +// } +// doAsyncIterInvalidCallbackTest().then(common.mustCall()); + +// Check first call to close() - should not report an error. +async function doAsyncIterDirClosedTest() { + const dir = await fs.promises.opendir(testDir); + await dir.close(); + // await assert.rejects(() => dir.close(), dirclosedError); +} +doAsyncIterDirClosedTest().then(common.mustCall()); + +// Check that readSync() and closeSync() during read() throw exceptions +async function doConcurrentAsyncAndSyncOps() { + const dir = await fs.promises.opendir(testDir); + const promise = dir.read(); + + // assert.throws(() => dir.closeSync(), dirconcurrentError); + // assert.throws(() => dir.readSync(), dirconcurrentError); + + await promise; + dir.closeSync(); +} +doConcurrentAsyncAndSyncOps().then(common.mustCall()); + +// TODO(wafuwafu13): enable this +// // Check read throw exceptions on invalid callback +// { +// const dir = fs.opendirSync(testDir); +// assert.throws(() => dir.read('INVALID_CALLBACK'), /ERR_INVALID_ARG_TYPE/); +// } + +// Check that concurrent read() operations don't do weird things. +async function doConcurrentAsyncOps() { + const dir = await fs.promises.opendir(testDir); + const promise1 = dir.read(); + const promise2 = dir.read(); + + assertDirent(await promise1); + assertDirent(await promise2); + dir.closeSync(); +} +doConcurrentAsyncOps().then(common.mustCall()); + +// Check that concurrent read() + close() operations don't do weird things. +async function doConcurrentAsyncMixedOps() { + const dir = await fs.promises.opendir(testDir); + const promise1 = dir.read(); + const promise2 = dir.close(); + + assertDirent(await promise1); + await promise2; +} +doConcurrentAsyncMixedOps().then(common.mustCall()); + +// Check if directory already closed - the callback should pass an error. +{ + const dir = fs.opendirSync(testDir); + dir.closeSync(); + dir.close(common.mustCall((error) => { + // assert.strictEqual(error.code, dirclosedError.code); + })); +} + +// Check if directory already closed - throw an promise exception. +{ + const dir = fs.opendirSync(testDir); + dir.closeSync(); + // assert.rejects(dir.close(), dirclosedError).then(common.mustCall()); +} |