• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Flags: --experimental-abortcontroller
2'use strict';
3
4const common = require('../common');
5
6// The following tests validate base functionality for the fs.promises
7// FileHandle.readFile method.
8
9const fs = require('fs');
10const {
11  open,
12  readFile,
13  writeFile,
14  truncate,
15} = fs.promises;
16const path = require('path');
17const tmpdir = require('../common/tmpdir');
18const tick = require('../common/tick');
19const assert = require('assert');
20const tmpDir = tmpdir.path;
21
22tmpdir.refresh();
23
24async function validateReadFile() {
25  const filePath = path.resolve(tmpDir, 'tmp-read-file.txt');
26  const fileHandle = await open(filePath, 'w+');
27  const buffer = Buffer.from('Hello world'.repeat(100), 'utf8');
28
29  const fd = fs.openSync(filePath, 'w+');
30  fs.writeSync(fd, buffer, 0, buffer.length);
31  fs.closeSync(fd);
32
33  const readFileData = await fileHandle.readFile();
34  assert.deepStrictEqual(buffer, readFileData);
35
36  await fileHandle.close();
37}
38
39async function validateReadFileProc() {
40  // Test to make sure reading a file under the /proc directory works. Adapted
41  // from test-fs-read-file-sync-hostname.js.
42  // Refs:
43  // - https://groups.google.com/forum/#!topic/nodejs-dev/rxZ_RoH1Gn0
44  // - https://github.com/nodejs/node/issues/21331
45
46  // Test is Linux-specific.
47  if (!common.isLinux)
48    return;
49
50  const fileHandle = await open('/proc/sys/kernel/hostname', 'r');
51  const hostname = await fileHandle.readFile();
52  assert.ok(hostname.length > 0);
53}
54
55async function doReadAndCancel() {
56  // Signal aborted from the start
57  {
58    const filePathForHandle = path.resolve(tmpDir, 'dogs-running.txt');
59    const fileHandle = await open(filePathForHandle, 'w+');
60    const buffer = Buffer.from('Dogs running'.repeat(10000), 'utf8');
61    fs.writeFileSync(filePathForHandle, buffer);
62    const controller = new AbortController();
63    const { signal } = controller;
64    controller.abort();
65    await assert.rejects(readFile(fileHandle, { signal }), {
66      name: 'AbortError'
67    });
68    await fileHandle.close();
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, { 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({ 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/master/lib/internal/fs/promises.js#L5
107    const kIoMaxLength = 2 ** 31 - 1;
108
109    const newFile = path.resolve(tmpDir, 'dogs-running3.txt');
110    await writeFile(newFile, Buffer.from('0'));
111    await truncate(newFile, kIoMaxLength + 1);
112
113    const fileHandle = await open(newFile, 'r');
114
115    await assert.rejects(fileHandle.readFile(), {
116      name: 'RangeError',
117      code: 'ERR_FS_FILE_TOO_LARGE'
118    });
119    await fileHandle.close();
120  }
121}
122
123validateReadFile()
124  .then(validateReadFileProc)
125  .then(doReadAndCancel)
126  .then(common.mustCall());
127