11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ciconst common = require('../common');
31cb0ef41Sopenharmony_ci
41cb0ef41Sopenharmony_ci// This test ensures that fs.readFile correctly returns the
51cb0ef41Sopenharmony_ci// contents of varying-sized files.
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ciconst tmpdir = require('../../test/common/tmpdir');
81cb0ef41Sopenharmony_ciconst assert = require('assert');
91cb0ef41Sopenharmony_ciconst fs = require('fs');
101cb0ef41Sopenharmony_ciconst path = require('path');
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ciconst prefix = `.removeme-fs-readfile-${process.pid}`;
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_citmpdir.refresh();
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ciconst fileInfo = [
171cb0ef41Sopenharmony_ci  { name: path.join(tmpdir.path, `${prefix}-1K.txt`),
181cb0ef41Sopenharmony_ci    len: 1024 },
191cb0ef41Sopenharmony_ci  { name: path.join(tmpdir.path, `${prefix}-64K.txt`),
201cb0ef41Sopenharmony_ci    len: 64 * 1024 },
211cb0ef41Sopenharmony_ci  { name: path.join(tmpdir.path, `${prefix}-64KLessOne.txt`),
221cb0ef41Sopenharmony_ci    len: (64 * 1024) - 1 },
231cb0ef41Sopenharmony_ci  { name: path.join(tmpdir.path, `${prefix}-1M.txt`),
241cb0ef41Sopenharmony_ci    len: 1 * 1024 * 1024 },
251cb0ef41Sopenharmony_ci  { name: path.join(tmpdir.path, `${prefix}-1MPlusOne.txt`),
261cb0ef41Sopenharmony_ci    len: (1 * 1024 * 1024) + 1 },
271cb0ef41Sopenharmony_ci];
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci// Populate each fileInfo (and file) with unique fill.
301cb0ef41Sopenharmony_ciconst sectorSize = 512;
311cb0ef41Sopenharmony_cifor (const e of fileInfo) {
321cb0ef41Sopenharmony_ci  e.contents = Buffer.allocUnsafe(e.len);
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci  // This accounts for anything unusual in Node's implementation of readFile.
351cb0ef41Sopenharmony_ci  // Using e.g. 'aa...aa' would miss bugs like Node re-reading
361cb0ef41Sopenharmony_ci  // the same section twice instead of two separate sections.
371cb0ef41Sopenharmony_ci  for (let offset = 0; offset < e.len; offset += sectorSize) {
381cb0ef41Sopenharmony_ci    const fillByte = 256 * Math.random();
391cb0ef41Sopenharmony_ci    const nBytesToFill = Math.min(sectorSize, e.len - offset);
401cb0ef41Sopenharmony_ci    e.contents.fill(fillByte, offset, offset + nBytesToFill);
411cb0ef41Sopenharmony_ci  }
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ci  fs.writeFileSync(e.name, e.contents);
441cb0ef41Sopenharmony_ci}
451cb0ef41Sopenharmony_ci// All files are now populated.
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci// Test readFile on each size.
481cb0ef41Sopenharmony_cifor (const e of fileInfo) {
491cb0ef41Sopenharmony_ci  fs.readFile(e.name, common.mustCall((err, buf) => {
501cb0ef41Sopenharmony_ci    console.log(`Validating readFile on file ${e.name} of length ${e.len}`);
511cb0ef41Sopenharmony_ci    assert.ifError(err);
521cb0ef41Sopenharmony_ci    assert.deepStrictEqual(buf, e.contents);
531cb0ef41Sopenharmony_ci  }));
541cb0ef41Sopenharmony_ci}
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci// readFile() and readFileSync() should fail if the file is too big.
571cb0ef41Sopenharmony_ci{
581cb0ef41Sopenharmony_ci  const kIoMaxLength = 2 ** 31 - 1;
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci  if (!tmpdir.hasEnoughSpace(kIoMaxLength)) {
611cb0ef41Sopenharmony_ci    // truncateSync() will fail with ENOSPC if there is not enough space.
621cb0ef41Sopenharmony_ci    common.printSkipMessage(`Not enough space in ${tmpdir.path}`);
631cb0ef41Sopenharmony_ci  } else {
641cb0ef41Sopenharmony_ci    const file = path.join(tmpdir.path, `${prefix}-too-large.txt`);
651cb0ef41Sopenharmony_ci    fs.writeFileSync(file, Buffer.from('0'));
661cb0ef41Sopenharmony_ci    fs.truncateSync(file, kIoMaxLength + 1);
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci    fs.readFile(file, common.expectsError({
691cb0ef41Sopenharmony_ci      code: 'ERR_FS_FILE_TOO_LARGE',
701cb0ef41Sopenharmony_ci      name: 'RangeError',
711cb0ef41Sopenharmony_ci    }));
721cb0ef41Sopenharmony_ci    assert.throws(() => {
731cb0ef41Sopenharmony_ci      fs.readFileSync(file);
741cb0ef41Sopenharmony_ci    }, { code: 'ERR_FS_FILE_TOO_LARGE', name: 'RangeError' });
751cb0ef41Sopenharmony_ci  }
761cb0ef41Sopenharmony_ci}
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_ci{
791cb0ef41Sopenharmony_ci  // Test cancellation, before
801cb0ef41Sopenharmony_ci  const signal = AbortSignal.abort();
811cb0ef41Sopenharmony_ci  fs.readFile(fileInfo[0].name, { signal }, common.mustCall((err, buf) => {
821cb0ef41Sopenharmony_ci    assert.strictEqual(err.name, 'AbortError');
831cb0ef41Sopenharmony_ci  }));
841cb0ef41Sopenharmony_ci}
851cb0ef41Sopenharmony_ci{
861cb0ef41Sopenharmony_ci  // Test cancellation, during read
871cb0ef41Sopenharmony_ci  const controller = new AbortController();
881cb0ef41Sopenharmony_ci  const signal = controller.signal;
891cb0ef41Sopenharmony_ci  fs.readFile(fileInfo[0].name, { signal }, common.mustCall((err, buf) => {
901cb0ef41Sopenharmony_ci    assert.strictEqual(err.name, 'AbortError');
911cb0ef41Sopenharmony_ci  }));
921cb0ef41Sopenharmony_ci  process.nextTick(() => controller.abort());
931cb0ef41Sopenharmony_ci}
941cb0ef41Sopenharmony_ci{
951cb0ef41Sopenharmony_ci  // Verify that if something different than Abortcontroller.signal
961cb0ef41Sopenharmony_ci  // is passed, ERR_INVALID_ARG_TYPE is thrown
971cb0ef41Sopenharmony_ci  assert.throws(() => {
981cb0ef41Sopenharmony_ci    const callback = common.mustNotCall();
991cb0ef41Sopenharmony_ci    fs.readFile(fileInfo[0].name, { signal: 'hello' }, callback);
1001cb0ef41Sopenharmony_ci  }, { code: 'ERR_INVALID_ARG_TYPE', name: 'TypeError' });
1011cb0ef41Sopenharmony_ci}
102