11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst common = require('../common');
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci// The following tests validate base functionality for the fs.promises
61cb0ef41Sopenharmony_ci// FileHandle.readFile method.
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ciconst fs = require('fs');
91cb0ef41Sopenharmony_ciconst {
101cb0ef41Sopenharmony_ci  open,
111cb0ef41Sopenharmony_ci  readFile,
121cb0ef41Sopenharmony_ci  writeFile,
131cb0ef41Sopenharmony_ci  truncate,
141cb0ef41Sopenharmony_ci} = fs.promises;
151cb0ef41Sopenharmony_ciconst path = require('path');
161cb0ef41Sopenharmony_ciconst tmpdir = require('../common/tmpdir');
171cb0ef41Sopenharmony_ciconst tick = require('../common/tick');
181cb0ef41Sopenharmony_ciconst assert = require('assert');
191cb0ef41Sopenharmony_ciconst tmpDir = tmpdir.path;
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_citmpdir.refresh();
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_ciasync function validateReadFile() {
241cb0ef41Sopenharmony_ci  const filePath = path.resolve(tmpDir, 'tmp-read-file.txt');
251cb0ef41Sopenharmony_ci  const fileHandle = await open(filePath, 'w+');
261cb0ef41Sopenharmony_ci  const buffer = Buffer.from('Hello world'.repeat(100), 'utf8');
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci  const fd = fs.openSync(filePath, 'w+');
291cb0ef41Sopenharmony_ci  fs.writeSync(fd, buffer, 0, buffer.length);
301cb0ef41Sopenharmony_ci  fs.closeSync(fd);
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ci  const readFileData = await fileHandle.readFile();
331cb0ef41Sopenharmony_ci  assert.deepStrictEqual(buffer, readFileData);
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci  await fileHandle.close();
361cb0ef41Sopenharmony_ci}
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ciasync function validateReadFileProc() {
391cb0ef41Sopenharmony_ci  // Test to make sure reading a file under the /proc directory works. Adapted
401cb0ef41Sopenharmony_ci  // from test-fs-read-file-sync-hostname.js.
411cb0ef41Sopenharmony_ci  // Refs:
421cb0ef41Sopenharmony_ci  // - https://groups.google.com/forum/#!topic/nodejs-dev/rxZ_RoH1Gn0
431cb0ef41Sopenharmony_ci  // - https://github.com/nodejs/node/issues/21331
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci  // Test is Linux-specific.
461cb0ef41Sopenharmony_ci  if (!common.isLinux)
471cb0ef41Sopenharmony_ci    return;
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci  const fileHandle = await open('/proc/sys/kernel/hostname', 'r');
501cb0ef41Sopenharmony_ci  const hostname = await fileHandle.readFile();
511cb0ef41Sopenharmony_ci  assert.ok(hostname.length > 0);
521cb0ef41Sopenharmony_ci}
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ciasync function doReadAndCancel() {
551cb0ef41Sopenharmony_ci  // Signal aborted from the start
561cb0ef41Sopenharmony_ci  {
571cb0ef41Sopenharmony_ci    const filePathForHandle = path.resolve(tmpDir, 'dogs-running.txt');
581cb0ef41Sopenharmony_ci    const fileHandle = await open(filePathForHandle, 'w+');
591cb0ef41Sopenharmony_ci    try {
601cb0ef41Sopenharmony_ci      const buffer = Buffer.from('Dogs running'.repeat(10000), 'utf8');
611cb0ef41Sopenharmony_ci      fs.writeFileSync(filePathForHandle, buffer);
621cb0ef41Sopenharmony_ci      const signal = AbortSignal.abort();
631cb0ef41Sopenharmony_ci      await assert.rejects(readFile(fileHandle, common.mustNotMutateObjectDeep({ signal })), {
641cb0ef41Sopenharmony_ci        name: 'AbortError'
651cb0ef41Sopenharmony_ci      });
661cb0ef41Sopenharmony_ci    } finally {
671cb0ef41Sopenharmony_ci      await fileHandle.close();
681cb0ef41Sopenharmony_ci    }
691cb0ef41Sopenharmony_ci  }
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci  // Signal aborted on first tick
721cb0ef41Sopenharmony_ci  {
731cb0ef41Sopenharmony_ci    const filePathForHandle = path.resolve(tmpDir, 'dogs-running1.txt');
741cb0ef41Sopenharmony_ci    const fileHandle = await open(filePathForHandle, 'w+');
751cb0ef41Sopenharmony_ci    const buffer = Buffer.from('Dogs running'.repeat(10000), 'utf8');
761cb0ef41Sopenharmony_ci    fs.writeFileSync(filePathForHandle, buffer);
771cb0ef41Sopenharmony_ci    const controller = new AbortController();
781cb0ef41Sopenharmony_ci    const { signal } = controller;
791cb0ef41Sopenharmony_ci    process.nextTick(() => controller.abort());
801cb0ef41Sopenharmony_ci    await assert.rejects(readFile(fileHandle, common.mustNotMutateObjectDeep({ signal })), {
811cb0ef41Sopenharmony_ci      name: 'AbortError'
821cb0ef41Sopenharmony_ci    }, 'tick-0');
831cb0ef41Sopenharmony_ci    await fileHandle.close();
841cb0ef41Sopenharmony_ci  }
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci  // Signal aborted right before buffer read
871cb0ef41Sopenharmony_ci  {
881cb0ef41Sopenharmony_ci    const newFile = path.resolve(tmpDir, 'dogs-running2.txt');
891cb0ef41Sopenharmony_ci    const buffer = Buffer.from('Dogs running'.repeat(1000), 'utf8');
901cb0ef41Sopenharmony_ci    fs.writeFileSync(newFile, buffer);
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci    const fileHandle = await open(newFile, 'r');
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_ci    const controller = new AbortController();
951cb0ef41Sopenharmony_ci    const { signal } = controller;
961cb0ef41Sopenharmony_ci    tick(1, () => controller.abort());
971cb0ef41Sopenharmony_ci    await assert.rejects(fileHandle.readFile(common.mustNotMutateObjectDeep({ signal, encoding: 'utf8' })), {
981cb0ef41Sopenharmony_ci      name: 'AbortError'
991cb0ef41Sopenharmony_ci    }, 'tick-1');
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci    await fileHandle.close();
1021cb0ef41Sopenharmony_ci  }
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci  // Validate file size is within range for reading
1051cb0ef41Sopenharmony_ci  {
1061cb0ef41Sopenharmony_ci    // Variable taken from https://github.com/nodejs/node/blob/1377163f3351/lib/internal/fs/promises.js#L5
1071cb0ef41Sopenharmony_ci    const kIoMaxLength = 2 ** 31 - 1;
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci    if (!tmpdir.hasEnoughSpace(kIoMaxLength)) {
1101cb0ef41Sopenharmony_ci      // truncate() will fail with ENOSPC if there is not enough space.
1111cb0ef41Sopenharmony_ci      common.printSkipMessage(`Not enough space in ${tmpDir}`);
1121cb0ef41Sopenharmony_ci    } else {
1131cb0ef41Sopenharmony_ci      const newFile = path.resolve(tmpDir, 'dogs-running3.txt');
1141cb0ef41Sopenharmony_ci      await writeFile(newFile, Buffer.from('0'));
1151cb0ef41Sopenharmony_ci      await truncate(newFile, kIoMaxLength + 1);
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci      const fileHandle = await open(newFile, 'r');
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci      await assert.rejects(fileHandle.readFile(), {
1201cb0ef41Sopenharmony_ci        name: 'RangeError',
1211cb0ef41Sopenharmony_ci        code: 'ERR_FS_FILE_TOO_LARGE'
1221cb0ef41Sopenharmony_ci      });
1231cb0ef41Sopenharmony_ci      await fileHandle.close();
1241cb0ef41Sopenharmony_ci    }
1251cb0ef41Sopenharmony_ci  }
1261cb0ef41Sopenharmony_ci}
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_civalidateReadFile()
1291cb0ef41Sopenharmony_ci  .then(validateReadFileProc)
1301cb0ef41Sopenharmony_ci  .then(doReadAndCancel)
1311cb0ef41Sopenharmony_ci  .then(common.mustCall());
132