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