1// Flags: --expose-internals
2'use strict';
3
4const common = require('../common');
5
6const assert = require('assert');
7const path = require('path');
8const { writeFile, readFile } = require('fs').promises;
9const tmpdir = require('../common/tmpdir');
10const { internalBinding } = require('internal/test/binding');
11const fsBinding = internalBinding('fs');
12tmpdir.refresh();
13
14const fn = path.join(tmpdir.path, 'large-file');
15
16// Creating large buffer with random content
17const largeBuffer = Buffer.from(
18  Array.from({ length: 1024 ** 2 + 19 }, (_, index) => index)
19);
20
21async function createLargeFile() {
22  // Writing buffer to a file then try to read it
23  await writeFile(fn, largeBuffer);
24}
25
26async function validateReadFile() {
27  const readBuffer = await readFile(fn);
28  assert.strictEqual(readBuffer.equals(largeBuffer), true);
29}
30
31async function validateReadFileProc() {
32  // Test to make sure reading a file under the /proc directory works. Adapted
33  // from test-fs-read-file-sync-hostname.js.
34  // Refs:
35  // - https://groups.google.com/forum/#!topic/nodejs-dev/rxZ_RoH1Gn0
36  // - https://github.com/nodejs/node/issues/21331
37
38  // Test is Linux-specific.
39  if (!common.isLinux)
40    return;
41
42  const hostname = await readFile('/proc/sys/kernel/hostname');
43  assert.ok(hostname.length > 0);
44}
45
46function validateReadFileAbortLogicBefore() {
47  const signal = AbortSignal.abort();
48  assert.rejects(readFile(fn, { signal }), {
49    name: 'AbortError'
50  });
51}
52
53function validateReadFileAbortLogicDuring() {
54  const controller = new AbortController();
55  const signal = controller.signal;
56  process.nextTick(() => controller.abort());
57  assert.rejects(readFile(fn, { signal }), {
58    name: 'AbortError'
59  });
60}
61
62async function validateWrongSignalParam() {
63  // Verify that if something different than Abortcontroller.signal
64  // is passed, ERR_INVALID_ARG_TYPE is thrown
65
66  await assert.rejects(async () => {
67    const callback = common.mustNotCall();
68    await readFile(fn, { signal: 'hello' }, callback);
69  }, { code: 'ERR_INVALID_ARG_TYPE', name: 'TypeError' });
70
71}
72
73async function validateZeroByteLiar() {
74  const originalFStat = fsBinding.fstat;
75  fsBinding.fstat = common.mustCall(
76    () => (/* stat fields */ [0, 1, 2, 3, 4, 5, 6, 7, 0 /* size */])
77  );
78  const readBuffer = await readFile(fn);
79  assert.strictEqual(readBuffer.toString(), largeBuffer.toString());
80  fsBinding.fstat = originalFStat;
81}
82
83(async () => {
84  await createLargeFile();
85  await validateReadFile();
86  await validateReadFileProc();
87  await validateReadFileAbortLogicBefore();
88  await validateReadFileAbortLogicDuring();
89  await validateWrongSignalParam();
90  await validateZeroByteLiar();
91})().then(common.mustCall());
92