1'use strict'; 2const common = require('../common'); 3 4// This test ensures that fs.readFile correctly returns the 5// contents of varying-sized files. 6 7const tmpdir = require('../../test/common/tmpdir'); 8const assert = require('assert'); 9const fs = require('fs'); 10const path = require('path'); 11 12const prefix = `.removeme-fs-readfile-${process.pid}`; 13 14tmpdir.refresh(); 15 16const fileInfo = [ 17 { name: path.join(tmpdir.path, `${prefix}-1K.txt`), 18 len: 1024 }, 19 { name: path.join(tmpdir.path, `${prefix}-64K.txt`), 20 len: 64 * 1024 }, 21 { name: path.join(tmpdir.path, `${prefix}-64KLessOne.txt`), 22 len: (64 * 1024) - 1 }, 23 { name: path.join(tmpdir.path, `${prefix}-1M.txt`), 24 len: 1 * 1024 * 1024 }, 25 { name: path.join(tmpdir.path, `${prefix}-1MPlusOne.txt`), 26 len: (1 * 1024 * 1024) + 1 }, 27]; 28 29// Populate each fileInfo (and file) with unique fill. 30const sectorSize = 512; 31for (const e of fileInfo) { 32 e.contents = Buffer.allocUnsafe(e.len); 33 34 // This accounts for anything unusual in Node's implementation of readFile. 35 // Using e.g. 'aa...aa' would miss bugs like Node re-reading 36 // the same section twice instead of two separate sections. 37 for (let offset = 0; offset < e.len; offset += sectorSize) { 38 const fillByte = 256 * Math.random(); 39 const nBytesToFill = Math.min(sectorSize, e.len - offset); 40 e.contents.fill(fillByte, offset, offset + nBytesToFill); 41 } 42 43 fs.writeFileSync(e.name, e.contents); 44} 45// All files are now populated. 46 47// Test readFile on each size. 48for (const e of fileInfo) { 49 fs.readFile(e.name, common.mustCall((err, buf) => { 50 console.log(`Validating readFile on file ${e.name} of length ${e.len}`); 51 assert.ifError(err); 52 assert.deepStrictEqual(buf, e.contents); 53 })); 54} 55 56// readFile() and readFileSync() should fail if the file is too big. 57{ 58 const kIoMaxLength = 2 ** 31 - 1; 59 60 if (!tmpdir.hasEnoughSpace(kIoMaxLength)) { 61 // truncateSync() will fail with ENOSPC if there is not enough space. 62 common.printSkipMessage(`Not enough space in ${tmpdir.path}`); 63 } else { 64 const file = path.join(tmpdir.path, `${prefix}-too-large.txt`); 65 fs.writeFileSync(file, Buffer.from('0')); 66 fs.truncateSync(file, kIoMaxLength + 1); 67 68 fs.readFile(file, common.expectsError({ 69 code: 'ERR_FS_FILE_TOO_LARGE', 70 name: 'RangeError', 71 })); 72 assert.throws(() => { 73 fs.readFileSync(file); 74 }, { code: 'ERR_FS_FILE_TOO_LARGE', name: 'RangeError' }); 75 } 76} 77 78{ 79 // Test cancellation, before 80 const signal = AbortSignal.abort(); 81 fs.readFile(fileInfo[0].name, { signal }, common.mustCall((err, buf) => { 82 assert.strictEqual(err.name, 'AbortError'); 83 })); 84} 85{ 86 // Test cancellation, during read 87 const controller = new AbortController(); 88 const signal = controller.signal; 89 fs.readFile(fileInfo[0].name, { signal }, common.mustCall((err, buf) => { 90 assert.strictEqual(err.name, 'AbortError'); 91 })); 92 process.nextTick(() => controller.abort()); 93} 94{ 95 // Verify that if something different than Abortcontroller.signal 96 // is passed, ERR_INVALID_ARG_TYPE is thrown 97 assert.throws(() => { 98 const callback = common.mustNotCall(); 99 fs.readFile(fileInfo[0].name, { signal: 'hello' }, callback); 100 }, { code: 'ERR_INVALID_ARG_TYPE', name: 'TypeError' }); 101} 102