• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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