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 125const runCallbackTest = (func, arg, done) => { 126 const startTime = process.hrtime.bigint(); 127 func(arg, { bigint: true }, common.mustCall((err, bigintStats) => { 128 func(arg, common.mustCall((err, numStats) => { 129 const endTime = process.hrtime.bigint(); 130 const allowableDelta = Math.ceil(Number(endTime - startTime) / 1e6); 131 verifyStats(bigintStats, numStats, allowableDelta); 132 if (done) { 133 done(); 134 } 135 })); 136 })); 137}; 138 139{ 140 const filename = getFilename(); 141 runCallbackTest(fs.stat, filename); 142} 143 144if (!common.isWindows) { 145 const filename = getFilename(); 146 const link = `${filename}-link`; 147 fs.symlinkSync(filename, link); 148 runCallbackTest(fs.lstat, link); 149} 150 151{ 152 const filename = getFilename(); 153 const fd = fs.openSync(filename, 'r'); 154 runCallbackTest(fs.fstat, fd, () => { fs.closeSync(fd); }); 155} 156 157const runPromiseTest = async (func, arg) => { 158 const startTime = process.hrtime.bigint(); 159 const bigintStats = await func(arg, { bigint: true }); 160 const numStats = await func(arg); 161 const endTime = process.hrtime.bigint(); 162 const allowableDelta = Math.ceil(Number(endTime - startTime) / 1e6); 163 verifyStats(bigintStats, numStats, allowableDelta); 164}; 165 166{ 167 const filename = getFilename(); 168 runPromiseTest(promiseFs.stat, filename); 169} 170 171if (!common.isWindows) { 172 const filename = getFilename(); 173 const link = `${filename}-link`; 174 fs.symlinkSync(filename, link); 175 runPromiseTest(promiseFs.lstat, link); 176} 177 178(async function() { 179 const filename = getFilename(); 180 const handle = await promiseFs.open(filename, 'r'); 181 const startTime = process.hrtime.bigint(); 182 const bigintStats = await handle.stat({ bigint: true }); 183 const numStats = await handle.stat(); 184 const endTime = process.hrtime.bigint(); 185 const allowableDelta = Math.ceil(Number(endTime - startTime) / 1e6); 186 verifyStats(bigintStats, numStats, allowableDelta); 187 await handle.close(); 188})(); 189