• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2
3const common = require('../common');
4
5// The following tests validate base functionality for the fs.promises
6// FileHandle.readFile method.
7
8const fs = require('fs');
9const {
10  open,
11  readFile,
12  writeFile,
13  truncate,
14} = fs.promises;
15const path = require('path');
16const tmpdir = require('../common/tmpdir');
17const tick = require('../common/tick');
18const assert = require('assert');
19const tmpDir = tmpdir.path;
20
21tmpdir.refresh();
22
23async function validateReadFile() {
24  const filePath = path.resolve(tmpDir, 'tmp-read-file.txt');
25  const fileHandle = await open(filePath, 'w+');
26  const buffer = Buffer.from('Hello world'.repeat(100), 'utf8');
27
28  const fd = fs.openSync(filePath, 'w+');
29  fs.writeSync(fd, buffer, 0, buffer.length);
30  fs.closeSync(fd);
31
32  const readFileData = await fileHandle.readFile();
33  assert.deepStrictEqual(buffer, readFileData);
34
35  await fileHandle.close();
36}
37
38async function validateReadFileProc() {
39  // Test to make sure reading a file under the /proc directory works. Adapted
40  // from test-fs-read-file-sync-hostname.js.
41  // Refs:
42  // - https://groups.google.com/forum/#!topic/nodejs-dev/rxZ_RoH1Gn0
43  // - https://github.com/nodejs/node/issues/21331
44
45  // Test is Linux-specific.
46  if (!common.isLinux)
47    return;
48
49  const fileHandle = await open('/proc/sys/kernel/hostname', 'r');
50  const hostname = await fileHandle.readFile();
51  assert.ok(hostname.length > 0);
52}
53
54async function doReadAndCancel() {
55  // Signal aborted from the start
56  {
57    const filePathForHandle = path.resolve(tmpDir, 'dogs-running.txt');
58    const fileHandle = await open(filePathForHandle, 'w+');
59    try {
60      const buffer = Buffer.from('Dogs running'.repeat(10000), 'utf8');
61      fs.writeFileSync(filePathForHandle, buffer);
62      const signal = AbortSignal.abort();
63      await assert.rejects(readFile(fileHandle, common.mustNotMutateObjectDeep({ signal })), {
64        name: 'AbortError'
65      });
66    } finally {
67      await fileHandle.close();
68    }
69  }
70
71  // Signal aborted on first tick
72  {
73    const filePathForHandle = path.resolve(tmpDir, 'dogs-running1.txt');
74    const fileHandle = await open(filePathForHandle, 'w+');
75    const buffer = Buffer.from('Dogs running'.repeat(10000), 'utf8');
76    fs.writeFileSync(filePathForHandle, buffer);
77    const controller = new AbortController();
78    const { signal } = controller;
79    process.nextTick(() => controller.abort());
80    await assert.rejects(readFile(fileHandle, common.mustNotMutateObjectDeep({ signal })), {
81      name: 'AbortError'
82    }, 'tick-0');
83    await fileHandle.close();
84  }
85
86  // Signal aborted right before buffer read
87  {
88    const newFile = path.resolve(tmpDir, 'dogs-running2.txt');
89    const buffer = Buffer.from('Dogs running'.repeat(1000), 'utf8');
90    fs.writeFileSync(newFile, buffer);
91
92    const fileHandle = await open(newFile, 'r');
93
94    const controller = new AbortController();
95    const { signal } = controller;
96    tick(1, () => controller.abort());
97    await assert.rejects(fileHandle.readFile(common.mustNotMutateObjectDeep({ signal, encoding: 'utf8' })), {
98      name: 'AbortError'
99    }, 'tick-1');
100
101    await fileHandle.close();
102  }
103
104  // Validate file size is within range for reading
105  {
106    // Variable taken from https://github.com/nodejs/node/blob/1377163f3351/lib/internal/fs/promises.js#L5
107    const kIoMaxLength = 2 ** 31 - 1;
108
109    if (!tmpdir.hasEnoughSpace(kIoMaxLength)) {
110      // truncate() will fail with ENOSPC if there is not enough space.
111      common.printSkipMessage(`Not enough space in ${tmpDir}`);
112    } else {
113      const newFile = path.resolve(tmpDir, 'dogs-running3.txt');
114      await writeFile(newFile, Buffer.from('0'));
115      await truncate(newFile, kIoMaxLength + 1);
116
117      const fileHandle = await open(newFile, 'r');
118
119      await assert.rejects(fileHandle.readFile(), {
120        name: 'RangeError',
121        code: 'ERR_FS_FILE_TOO_LARGE'
122      });
123      await fileHandle.close();
124    }
125  }
126}
127
128validateReadFile()
129  .then(validateReadFileProc)
130  .then(doReadAndCancel)
131  .then(common.mustCall());
132