11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst common = require('../common');
41cb0ef41Sopenharmony_ciconst assert = require('assert');
51cb0ef41Sopenharmony_ciconst fs = require('fs');
61cb0ef41Sopenharmony_ciconst promiseFs = require('fs').promises;
71cb0ef41Sopenharmony_ciconst path = require('path');
81cb0ef41Sopenharmony_ciconst tmpdir = require('../common/tmpdir');
91cb0ef41Sopenharmony_ciconst { isDate } = require('util').types;
101cb0ef41Sopenharmony_ciconst { inspect } = require('util');
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_citmpdir.refresh();
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_cilet testIndex = 0;
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_cifunction getFilename() {
171cb0ef41Sopenharmony_ci  const filename = path.join(tmpdir.path, `test-file-${++testIndex}`);
181cb0ef41Sopenharmony_ci  fs.writeFileSync(filename, 'test');
191cb0ef41Sopenharmony_ci  return filename;
201cb0ef41Sopenharmony_ci}
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_cifunction verifyStats(bigintStats, numStats, allowableDelta) {
231cb0ef41Sopenharmony_ci  // allowableDelta: It's possible that the file stats are updated between the
241cb0ef41Sopenharmony_ci  // two stat() calls so allow for a small difference.
251cb0ef41Sopenharmony_ci  for (const key of Object.keys(numStats)) {
261cb0ef41Sopenharmony_ci    const val = numStats[key];
271cb0ef41Sopenharmony_ci    if (isDate(val)) {
281cb0ef41Sopenharmony_ci      const time = val.getTime();
291cb0ef41Sopenharmony_ci      const time2 = bigintStats[key].getTime();
301cb0ef41Sopenharmony_ci      assert(
311cb0ef41Sopenharmony_ci        time - time2 <= allowableDelta,
321cb0ef41Sopenharmony_ci        `difference of ${key}.getTime() should <= ${allowableDelta}.\n` +
331cb0ef41Sopenharmony_ci        `Number version ${time}, BigInt version ${time2}n`);
341cb0ef41Sopenharmony_ci    } else if (key === 'mode') {
351cb0ef41Sopenharmony_ci      assert.strictEqual(bigintStats[key], BigInt(val));
361cb0ef41Sopenharmony_ci      assert.strictEqual(
371cb0ef41Sopenharmony_ci        bigintStats.isBlockDevice(),
381cb0ef41Sopenharmony_ci        numStats.isBlockDevice()
391cb0ef41Sopenharmony_ci      );
401cb0ef41Sopenharmony_ci      assert.strictEqual(
411cb0ef41Sopenharmony_ci        bigintStats.isCharacterDevice(),
421cb0ef41Sopenharmony_ci        numStats.isCharacterDevice()
431cb0ef41Sopenharmony_ci      );
441cb0ef41Sopenharmony_ci      assert.strictEqual(
451cb0ef41Sopenharmony_ci        bigintStats.isDirectory(),
461cb0ef41Sopenharmony_ci        numStats.isDirectory()
471cb0ef41Sopenharmony_ci      );
481cb0ef41Sopenharmony_ci      assert.strictEqual(
491cb0ef41Sopenharmony_ci        bigintStats.isFIFO(),
501cb0ef41Sopenharmony_ci        numStats.isFIFO()
511cb0ef41Sopenharmony_ci      );
521cb0ef41Sopenharmony_ci      assert.strictEqual(
531cb0ef41Sopenharmony_ci        bigintStats.isFile(),
541cb0ef41Sopenharmony_ci        numStats.isFile()
551cb0ef41Sopenharmony_ci      );
561cb0ef41Sopenharmony_ci      assert.strictEqual(
571cb0ef41Sopenharmony_ci        bigintStats.isSocket(),
581cb0ef41Sopenharmony_ci        numStats.isSocket()
591cb0ef41Sopenharmony_ci      );
601cb0ef41Sopenharmony_ci      assert.strictEqual(
611cb0ef41Sopenharmony_ci        bigintStats.isSymbolicLink(),
621cb0ef41Sopenharmony_ci        numStats.isSymbolicLink()
631cb0ef41Sopenharmony_ci      );
641cb0ef41Sopenharmony_ci    } else if (key.endsWith('Ms')) {
651cb0ef41Sopenharmony_ci      const nsKey = key.replace('Ms', 'Ns');
661cb0ef41Sopenharmony_ci      const msFromBigInt = bigintStats[key];
671cb0ef41Sopenharmony_ci      const nsFromBigInt = bigintStats[nsKey];
681cb0ef41Sopenharmony_ci      const msFromBigIntNs = Number(nsFromBigInt / (10n ** 6n));
691cb0ef41Sopenharmony_ci      const msFromNum = numStats[key];
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci      assert(
721cb0ef41Sopenharmony_ci        msFromNum - Number(msFromBigInt) <= allowableDelta,
731cb0ef41Sopenharmony_ci        `Number version ${key} = ${msFromNum}, ` +
741cb0ef41Sopenharmony_ci        `BigInt version ${key} = ${msFromBigInt}n, ` +
751cb0ef41Sopenharmony_ci        `Allowable delta = ${allowableDelta}`);
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci      assert(
781cb0ef41Sopenharmony_ci        msFromNum - Number(msFromBigIntNs) <= allowableDelta,
791cb0ef41Sopenharmony_ci        `Number version ${key} = ${msFromNum}, ` +
801cb0ef41Sopenharmony_ci        `BigInt version ${nsKey} = ${nsFromBigInt}n` +
811cb0ef41Sopenharmony_ci        ` = ${msFromBigIntNs}ms, Allowable delta = ${allowableDelta}`);
821cb0ef41Sopenharmony_ci    } else if (Number.isSafeInteger(val)) {
831cb0ef41Sopenharmony_ci      assert.strictEqual(
841cb0ef41Sopenharmony_ci        bigintStats[key], BigInt(val),
851cb0ef41Sopenharmony_ci        `${inspect(bigintStats[key])} !== ${inspect(BigInt(val))}\n` +
861cb0ef41Sopenharmony_ci        `key=${key}, val=${val}`
871cb0ef41Sopenharmony_ci      );
881cb0ef41Sopenharmony_ci    } else {
891cb0ef41Sopenharmony_ci      assert(
901cb0ef41Sopenharmony_ci        Number(bigintStats[key]) - val < 1,
911cb0ef41Sopenharmony_ci        `${key} is not a safe integer, difference should < 1.\n` +
921cb0ef41Sopenharmony_ci        `Number version ${val}, BigInt version ${bigintStats[key]}n`);
931cb0ef41Sopenharmony_ci    }
941cb0ef41Sopenharmony_ci  }
951cb0ef41Sopenharmony_ci}
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_ciconst runSyncTest = (func, arg) => {
981cb0ef41Sopenharmony_ci  const startTime = process.hrtime.bigint();
991cb0ef41Sopenharmony_ci  const bigintStats = func(arg, common.mustNotMutateObjectDeep({ bigint: true }));
1001cb0ef41Sopenharmony_ci  const numStats = func(arg);
1011cb0ef41Sopenharmony_ci  const endTime = process.hrtime.bigint();
1021cb0ef41Sopenharmony_ci  const allowableDelta = Math.ceil(Number(endTime - startTime) / 1e6);
1031cb0ef41Sopenharmony_ci  verifyStats(bigintStats, numStats, allowableDelta);
1041cb0ef41Sopenharmony_ci};
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci{
1071cb0ef41Sopenharmony_ci  const filename = getFilename();
1081cb0ef41Sopenharmony_ci  runSyncTest(fs.statSync, filename);
1091cb0ef41Sopenharmony_ci}
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ciif (!common.isWindows) {
1121cb0ef41Sopenharmony_ci  const filename = getFilename();
1131cb0ef41Sopenharmony_ci  const link = `${filename}-link`;
1141cb0ef41Sopenharmony_ci  fs.symlinkSync(filename, link);
1151cb0ef41Sopenharmony_ci  runSyncTest(fs.lstatSync, link);
1161cb0ef41Sopenharmony_ci}
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_ci{
1191cb0ef41Sopenharmony_ci  const filename = getFilename();
1201cb0ef41Sopenharmony_ci  const fd = fs.openSync(filename, 'r');
1211cb0ef41Sopenharmony_ci  runSyncTest(fs.fstatSync, fd);
1221cb0ef41Sopenharmony_ci  fs.closeSync(fd);
1231cb0ef41Sopenharmony_ci}
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ci{
1261cb0ef41Sopenharmony_ci  assert.throws(
1271cb0ef41Sopenharmony_ci    () => fs.statSync('does_not_exist'),
1281cb0ef41Sopenharmony_ci    { code: 'ENOENT' });
1291cb0ef41Sopenharmony_ci  assert.strictEqual(
1301cb0ef41Sopenharmony_ci    fs.statSync('does_not_exist', common.mustNotMutateObjectDeep({ throwIfNoEntry: false })),
1311cb0ef41Sopenharmony_ci    undefined);
1321cb0ef41Sopenharmony_ci}
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ci{
1351cb0ef41Sopenharmony_ci  assert.throws(
1361cb0ef41Sopenharmony_ci    () => fs.lstatSync('does_not_exist'),
1371cb0ef41Sopenharmony_ci    { code: 'ENOENT' });
1381cb0ef41Sopenharmony_ci  assert.strictEqual(
1391cb0ef41Sopenharmony_ci    fs.lstatSync('does_not_exist', common.mustNotMutateObjectDeep({ throwIfNoEntry: false })),
1401cb0ef41Sopenharmony_ci    undefined);
1411cb0ef41Sopenharmony_ci}
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_ci{
1441cb0ef41Sopenharmony_ci  assert.throws(
1451cb0ef41Sopenharmony_ci    () => fs.fstatSync(9999),
1461cb0ef41Sopenharmony_ci    { code: 'EBADF' });
1471cb0ef41Sopenharmony_ci  assert.throws(
1481cb0ef41Sopenharmony_ci    () => fs.fstatSync(9999, common.mustNotMutateObjectDeep({ throwIfNoEntry: false })),
1491cb0ef41Sopenharmony_ci    { code: 'EBADF' });
1501cb0ef41Sopenharmony_ci}
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_ciconst runCallbackTest = (func, arg, done) => {
1531cb0ef41Sopenharmony_ci  const startTime = process.hrtime.bigint();
1541cb0ef41Sopenharmony_ci  func(arg, common.mustNotMutateObjectDeep({ bigint: true }), common.mustCall((err, bigintStats) => {
1551cb0ef41Sopenharmony_ci    func(arg, common.mustCall((err, numStats) => {
1561cb0ef41Sopenharmony_ci      const endTime = process.hrtime.bigint();
1571cb0ef41Sopenharmony_ci      const allowableDelta = Math.ceil(Number(endTime - startTime) / 1e6);
1581cb0ef41Sopenharmony_ci      verifyStats(bigintStats, numStats, allowableDelta);
1591cb0ef41Sopenharmony_ci      if (done) {
1601cb0ef41Sopenharmony_ci        done();
1611cb0ef41Sopenharmony_ci      }
1621cb0ef41Sopenharmony_ci    }));
1631cb0ef41Sopenharmony_ci  }));
1641cb0ef41Sopenharmony_ci};
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ci{
1671cb0ef41Sopenharmony_ci  const filename = getFilename();
1681cb0ef41Sopenharmony_ci  runCallbackTest(fs.stat, filename);
1691cb0ef41Sopenharmony_ci}
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_ciif (!common.isWindows) {
1721cb0ef41Sopenharmony_ci  const filename = getFilename();
1731cb0ef41Sopenharmony_ci  const link = `${filename}-link`;
1741cb0ef41Sopenharmony_ci  fs.symlinkSync(filename, link);
1751cb0ef41Sopenharmony_ci  runCallbackTest(fs.lstat, link);
1761cb0ef41Sopenharmony_ci}
1771cb0ef41Sopenharmony_ci
1781cb0ef41Sopenharmony_ci{
1791cb0ef41Sopenharmony_ci  const filename = getFilename();
1801cb0ef41Sopenharmony_ci  const fd = fs.openSync(filename, 'r');
1811cb0ef41Sopenharmony_ci  runCallbackTest(fs.fstat, fd, () => { fs.closeSync(fd); });
1821cb0ef41Sopenharmony_ci}
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_ciconst runPromiseTest = async (func, arg) => {
1851cb0ef41Sopenharmony_ci  const startTime = process.hrtime.bigint();
1861cb0ef41Sopenharmony_ci  const bigintStats = await func(arg, common.mustNotMutateObjectDeep({ bigint: true }));
1871cb0ef41Sopenharmony_ci  const numStats = await func(arg);
1881cb0ef41Sopenharmony_ci  const endTime = process.hrtime.bigint();
1891cb0ef41Sopenharmony_ci  const allowableDelta = Math.ceil(Number(endTime - startTime) / 1e6);
1901cb0ef41Sopenharmony_ci  verifyStats(bigintStats, numStats, allowableDelta);
1911cb0ef41Sopenharmony_ci};
1921cb0ef41Sopenharmony_ci
1931cb0ef41Sopenharmony_ci{
1941cb0ef41Sopenharmony_ci  const filename = getFilename();
1951cb0ef41Sopenharmony_ci  runPromiseTest(promiseFs.stat, filename);
1961cb0ef41Sopenharmony_ci}
1971cb0ef41Sopenharmony_ci
1981cb0ef41Sopenharmony_ciif (!common.isWindows) {
1991cb0ef41Sopenharmony_ci  const filename = getFilename();
2001cb0ef41Sopenharmony_ci  const link = `${filename}-link`;
2011cb0ef41Sopenharmony_ci  fs.symlinkSync(filename, link);
2021cb0ef41Sopenharmony_ci  runPromiseTest(promiseFs.lstat, link);
2031cb0ef41Sopenharmony_ci}
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_ci(async function() {
2061cb0ef41Sopenharmony_ci  const filename = getFilename();
2071cb0ef41Sopenharmony_ci  const handle = await promiseFs.open(filename, 'r');
2081cb0ef41Sopenharmony_ci  const startTime = process.hrtime.bigint();
2091cb0ef41Sopenharmony_ci  const bigintStats = await handle.stat(common.mustNotMutateObjectDeep({ bigint: true }));
2101cb0ef41Sopenharmony_ci  const numStats = await handle.stat();
2111cb0ef41Sopenharmony_ci  const endTime = process.hrtime.bigint();
2121cb0ef41Sopenharmony_ci  const allowableDelta = Math.ceil(Number(endTime - startTime) / 1e6);
2131cb0ef41Sopenharmony_ci  verifyStats(bigintStats, numStats, allowableDelta);
2141cb0ef41Sopenharmony_ci  await handle.close();
2151cb0ef41Sopenharmony_ci})().then(common.mustCall());
216