1'use strict'; 2 3const common = require('../common'); 4const assert = require('assert'); 5const fs = require('fs'); 6const promiseFs = require('fs').promises; 7const path = require('path'); 8const tmpdir = require('../common/tmpdir'); 9const { isDate } = require('util').types; 10const { inspect } = require('util'); 11 12tmpdir.refresh(); 13 14let testIndex = 0; 15 16function getFilename() { 17 const filename = path.join(tmpdir.path, `test-file-${++testIndex}`); 18 fs.writeFileSync(filename, 'test'); 19 return filename; 20} 21 22function verifyStats(bigintStats, numStats, allowableDelta) { 23 // allowableDelta: It's possible that the file stats are updated between the 24 // two stat() calls so allow for a small difference. 25 for (const key of Object.keys(numStats)) { 26 const val = numStats[key]; 27 if (isDate(val)) { 28 const time = val.getTime(); 29 const time2 = bigintStats[key].getTime(); 30 assert( 31 time - time2 <= allowableDelta, 32 `difference of ${key}.getTime() should <= ${allowableDelta}.\n` + 33 `Number version ${time}, BigInt version ${time2}n`); 34 } else if (key === 'mode') { 35 assert.strictEqual(bigintStats[key], BigInt(val)); 36 assert.strictEqual( 37 bigintStats.isBlockDevice(), 38 numStats.isBlockDevice() 39 ); 40 assert.strictEqual( 41 bigintStats.isCharacterDevice(), 42 numStats.isCharacterDevice() 43 ); 44 assert.strictEqual( 45 bigintStats.isDirectory(), 46 numStats.isDirectory() 47 ); 48 assert.strictEqual( 49 bigintStats.isFIFO(), 50 numStats.isFIFO() 51 ); 52 assert.strictEqual( 53 bigintStats.isFile(), 54 numStats.isFile() 55 ); 56 assert.strictEqual( 57 bigintStats.isSocket(), 58 numStats.isSocket() 59 ); 60 assert.strictEqual( 61 bigintStats.isSymbolicLink(), 62 numStats.isSymbolicLink() 63 ); 64 } else if (key.endsWith('Ms')) { 65 const nsKey = key.replace('Ms', 'Ns'); 66 const msFromBigInt = bigintStats[key]; 67 const nsFromBigInt = bigintStats[nsKey]; 68 const msFromBigIntNs = Number(nsFromBigInt / (10n ** 6n)); 69 const msFromNum = numStats[key]; 70 71 assert( 72 msFromNum - Number(msFromBigInt) <= allowableDelta, 73 `Number version ${key} = ${msFromNum}, ` + 74 `BigInt version ${key} = ${msFromBigInt}n, ` + 75 `Allowable delta = ${allowableDelta}`); 76 77 assert( 78 msFromNum - Number(msFromBigIntNs) <= allowableDelta, 79 `Number version ${key} = ${msFromNum}, ` + 80 `BigInt version ${nsKey} = ${nsFromBigInt}n` + 81 ` = ${msFromBigIntNs}ms, Allowable delta = ${allowableDelta}`); 82 } else if (Number.isSafeInteger(val)) { 83 assert.strictEqual( 84 bigintStats[key], BigInt(val), 85 `${inspect(bigintStats[key])} !== ${inspect(BigInt(val))}\n` + 86 `key=${key}, val=${val}` 87 ); 88 } else { 89 assert( 90 Number(bigintStats[key]) - val < 1, 91 `${key} is not a safe integer, difference should < 1.\n` + 92 `Number version ${val}, BigInt version ${bigintStats[key]}n`); 93 } 94 } 95} 96 97const runSyncTest = (func, arg) => { 98 const startTime = process.hrtime.bigint(); 99 const bigintStats = func(arg, { bigint: true }); 100 const numStats = func(arg); 101 const endTime = process.hrtime.bigint(); 102 const allowableDelta = Math.ceil(Number(endTime - startTime) / 1e6); 103 verifyStats(bigintStats, numStats, allowableDelta); 104}; 105 106{ 107 const filename = getFilename(); 108 runSyncTest(fs.statSync, filename); 109} 110 111if (!common.isWindows) { 112 const filename = getFilename(); 113 const link = `${filename}-link`; 114 fs.symlinkSync(filename, link); 115 runSyncTest(fs.lstatSync, link); 116} 117 118{ 119 const filename = getFilename(); 120 const fd = fs.openSync(filename, 'r'); 121 runSyncTest(fs.fstatSync, fd); 122 fs.closeSync(fd); 123} 124 125{ 126 assert.throws( 127 () => fs.statSync('does_not_exist'), 128 { code: 'ENOENT' }); 129 assert.strictEqual( 130 fs.statSync('does_not_exist', { throwIfNoEntry: false }), 131 undefined); 132} 133 134{ 135 assert.throws( 136 () => fs.lstatSync('does_not_exist'), 137 { code: 'ENOENT' }); 138 assert.strictEqual( 139 fs.lstatSync('does_not_exist', { throwIfNoEntry: false }), 140 undefined); 141} 142 143{ 144 assert.throws( 145 () => fs.fstatSync(9999), 146 { code: 'EBADF' }); 147 assert.throws( 148 () => fs.fstatSync(9999, { throwIfNoEntry: false }), 149 { code: 'EBADF' }); 150} 151 152const runCallbackTest = (func, arg, done) => { 153 const startTime = process.hrtime.bigint(); 154 func(arg, { bigint: true }, common.mustCall((err, bigintStats) => { 155 func(arg, common.mustCall((err, numStats) => { 156 const endTime = process.hrtime.bigint(); 157 const allowableDelta = Math.ceil(Number(endTime - startTime) / 1e6); 158 verifyStats(bigintStats, numStats, allowableDelta); 159 if (done) { 160 done(); 161 } 162 })); 163 })); 164}; 165 166{ 167 const filename = getFilename(); 168 runCallbackTest(fs.stat, filename); 169} 170 171if (!common.isWindows) { 172 const filename = getFilename(); 173 const link = `${filename}-link`; 174 fs.symlinkSync(filename, link); 175 runCallbackTest(fs.lstat, link); 176} 177 178{ 179 const filename = getFilename(); 180 const fd = fs.openSync(filename, 'r'); 181 runCallbackTest(fs.fstat, fd, () => { fs.closeSync(fd); }); 182} 183 184const runPromiseTest = async (func, arg) => { 185 const startTime = process.hrtime.bigint(); 186 const bigintStats = await func(arg, { bigint: true }); 187 const numStats = await func(arg); 188 const endTime = process.hrtime.bigint(); 189 const allowableDelta = Math.ceil(Number(endTime - startTime) / 1e6); 190 verifyStats(bigintStats, numStats, allowableDelta); 191}; 192 193{ 194 const filename = getFilename(); 195 runPromiseTest(promiseFs.stat, filename); 196} 197 198if (!common.isWindows) { 199 const filename = getFilename(); 200 const link = `${filename}-link`; 201 fs.symlinkSync(filename, link); 202 runPromiseTest(promiseFs.lstat, link); 203} 204 205(async function() { 206 const filename = getFilename(); 207 const handle = await promiseFs.open(filename, 'r'); 208 const startTime = process.hrtime.bigint(); 209 const bigintStats = await handle.stat({ bigint: true }); 210 const numStats = await handle.stat(); 211 const endTime = process.hrtime.bigint(); 212 const allowableDelta = Math.ceil(Number(endTime - startTime) / 1e6); 213 verifyStats(bigintStats, numStats, allowableDelta); 214 await handle.close(); 215})().then(common.mustCall()); 216