diff options
Diffstat (limited to 'tests/node_compat/test/parallel/test-fs-utimes.js')
-rw-r--r-- | tests/node_compat/test/parallel/test-fs-utimes.js | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/tests/node_compat/test/parallel/test-fs-utimes.js b/tests/node_compat/test/parallel/test-fs-utimes.js new file mode 100644 index 000000000..f24e27f36 --- /dev/null +++ b/tests/node_compat/test/parallel/test-fs-utimes.js @@ -0,0 +1,218 @@ +// deno-fmt-ignore-file +// deno-lint-ignore-file + +// Copyright Joyent and Node contributors. All rights reserved. MIT license. +// Taken from Node 18.12.1 +// This file is automatically generated by `tests/node_compat/runner/setup.ts`. Do not modify this file manually. + +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const util = require('util'); +const fs = require('fs'); +const url = require('url'); + +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); + +const lpath = `${tmpdir.path}/symlink`; +fs.symlinkSync('unoent-entry', lpath); + +function stat_resource(resource, statSync = fs.statSync) { + if (typeof resource === 'string') { + return statSync(resource); + } + const stats = fs.fstatSync(resource); + // Ensure mtime has been written to disk + // except for directories on AIX where it cannot be synced + if ((common.isAIX || common.isIBMi) && stats.isDirectory()) + return stats; + fs.fsyncSync(resource); + return fs.fstatSync(resource); +} + +function check_mtime(resource, mtime, statSync) { + mtime = fs._toUnixTimestamp(mtime); + const stats = stat_resource(resource, statSync); + const real_mtime = fs._toUnixTimestamp(stats.mtime); + return mtime - real_mtime; +} + +function expect_errno(syscall, resource, err, errno) { + assert( + err && (err.code === errno || err.code === 'ENOSYS'), + `FAILED: expect_errno ${util.inspect(arguments)}` + ); +} + +function expect_ok(syscall, resource, err, atime, mtime, statSync) { + const mtime_diff = check_mtime(resource, mtime, statSync); + assert( + // Check up to single-second precision. + // Sub-second precision is OS and fs dependant. + !err && (mtime_diff < 2) || err && err.code === 'ENOSYS', + `FAILED: expect_ok ${util.inspect(arguments)} + check_mtime: ${mtime_diff}` + ); +} + +const stats = fs.statSync(tmpdir.path); + +const asPath = (path) => path; +const asUrl = (path) => url.pathToFileURL(path); + +const cases = [ + [asPath, new Date('1982-09-10 13:37')], + [asPath, new Date()], + [asPath, 123456.789], + [asPath, stats.mtime], + [asPath, '123456', -1], + [asPath, new Date('2017-04-08T17:59:38.008Z')], + [asUrl, new Date()], +]; + +runTests(cases.values()); + +function runTests(iter) { + const { value, done } = iter.next(); + if (done) return; + + // Support easy setting same or different atime / mtime values. + const [pathType, atime, mtime = atime] = value; + + let fd; + // + // test async code paths + // + fs.utimes(pathType(tmpdir.path), atime, mtime, common.mustCall((err) => { + expect_ok('utimes', tmpdir.path, err, atime, mtime); + + fs.lutimes(pathType(lpath), atime, mtime, common.mustCall((err) => { + expect_ok('lutimes', lpath, err, atime, mtime, fs.lstatSync); + + fs.utimes(pathType('foobarbaz'), atime, mtime, common.mustCall((err) => { + expect_errno('utimes', 'foobarbaz', err, 'ENOENT'); + + // don't close this fd + if (common.isWindows) { + fd = fs.openSync(tmpdir.path, 'r+'); + } else { + fd = fs.openSync(tmpdir.path, 'r'); + } + + fs.futimes(fd, atime, mtime, common.mustCall((err) => { + expect_ok('futimes', fd, err, atime, mtime); + + syncTests(); + + setImmediate(common.mustCall(runTests), iter); + })); + })); + })); + })); + + // + // test synchronized code paths, these functions throw on failure + // + function syncTests() { + fs.utimesSync(pathType(tmpdir.path), atime, mtime); + expect_ok('utimesSync', tmpdir.path, undefined, atime, mtime); + + fs.lutimesSync(pathType(lpath), atime, mtime); + expect_ok('lutimesSync', lpath, undefined, atime, mtime, fs.lstatSync); + + // Some systems don't have futimes + // if there's an error, it should be ENOSYS + try { + fs.futimesSync(fd, atime, mtime); + expect_ok('futimesSync', fd, undefined, atime, mtime); + } catch (ex) { + expect_errno('futimesSync', fd, ex, 'ENOSYS'); + } + + let err; + try { + fs.utimesSync(pathType('foobarbaz'), atime, mtime); + } catch (ex) { + err = ex; + } + expect_errno('utimesSync', 'foobarbaz', err, 'ENOENT'); + + err = undefined; + } +} + +const expectTypeError = { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError' +}; +// utimes-only error cases +{ + assert.throws( + () => fs.utimes(0, new Date(), new Date(), common.mustNotCall()), + expectTypeError + ); + assert.throws( + () => fs.utimesSync(0, new Date(), new Date()), + expectTypeError + ); +} + +// shared error cases +[false, {}, [], null, undefined].forEach((i) => { + assert.throws( + () => fs.utimes(i, new Date(), new Date(), common.mustNotCall()), + expectTypeError + ); + assert.throws( + () => fs.utimesSync(i, new Date(), new Date()), + expectTypeError + ); + assert.throws( + () => fs.futimes(i, new Date(), new Date(), common.mustNotCall()), + expectTypeError + ); + assert.throws( + () => fs.futimesSync(i, new Date(), new Date()), + expectTypeError + ); +}); + +const expectRangeError = { + code: 'ERR_OUT_OF_RANGE', + name: 'RangeError', + message: 'The value of "fd" is out of range. ' + + 'It must be >= 0 && <= 2147483647. Received -1' +}; +// futimes-only error cases +{ + assert.throws( + () => fs.futimes(-1, new Date(), new Date(), common.mustNotCall()), + expectRangeError + ); + assert.throws( + () => fs.futimesSync(-1, new Date(), new Date()), + expectRangeError + ); +} |