1// Flags: --experimental-abortcontroller 2'use strict'; 3 4const common = require('../common'); 5 6// The following tests validate base functionality for the fs.promises 7// FileHandle.readFile method. 8 9const fs = require('fs'); 10const { 11 open, 12 readFile, 13 writeFile, 14 truncate, 15} = fs.promises; 16const path = require('path'); 17const tmpdir = require('../common/tmpdir'); 18const tick = require('../common/tick'); 19const assert = require('assert'); 20const tmpDir = tmpdir.path; 21 22tmpdir.refresh(); 23 24async function validateReadFile() { 25 const filePath = path.resolve(tmpDir, 'tmp-read-file.txt'); 26 const fileHandle = await open(filePath, 'w+'); 27 const buffer = Buffer.from('Hello world'.repeat(100), 'utf8'); 28 29 const fd = fs.openSync(filePath, 'w+'); 30 fs.writeSync(fd, buffer, 0, buffer.length); 31 fs.closeSync(fd); 32 33 const readFileData = await fileHandle.readFile(); 34 assert.deepStrictEqual(buffer, readFileData); 35 36 await fileHandle.close(); 37} 38 39async function validateReadFileProc() { 40 // Test to make sure reading a file under the /proc directory works. Adapted 41 // from test-fs-read-file-sync-hostname.js. 42 // Refs: 43 // - https://groups.google.com/forum/#!topic/nodejs-dev/rxZ_RoH1Gn0 44 // - https://github.com/nodejs/node/issues/21331 45 46 // Test is Linux-specific. 47 if (!common.isLinux) 48 return; 49 50 const fileHandle = await open('/proc/sys/kernel/hostname', 'r'); 51 const hostname = await fileHandle.readFile(); 52 assert.ok(hostname.length > 0); 53} 54 55async function doReadAndCancel() { 56 // Signal aborted from the start 57 { 58 const filePathForHandle = path.resolve(tmpDir, 'dogs-running.txt'); 59 const fileHandle = await open(filePathForHandle, 'w+'); 60 const buffer = Buffer.from('Dogs running'.repeat(10000), 'utf8'); 61 fs.writeFileSync(filePathForHandle, buffer); 62 const controller = new AbortController(); 63 const { signal } = controller; 64 controller.abort(); 65 await assert.rejects(readFile(fileHandle, { signal }), { 66 name: 'AbortError' 67 }); 68 await fileHandle.close(); 69 } 70 71 // Signal aborted on first tick 72 { 73 const filePathForHandle = path.resolve(tmpDir, 'dogs-running1.txt'); 74 const fileHandle = await open(filePathForHandle, 'w+'); 75 const buffer = Buffer.from('Dogs running'.repeat(10000), 'utf8'); 76 fs.writeFileSync(filePathForHandle, buffer); 77 const controller = new AbortController(); 78 const { signal } = controller; 79 process.nextTick(() => controller.abort()); 80 await assert.rejects(readFile(fileHandle, { signal }), { 81 name: 'AbortError' 82 }, 'tick-0'); 83 await fileHandle.close(); 84 } 85 86 // Signal aborted right before buffer read 87 { 88 const newFile = path.resolve(tmpDir, 'dogs-running2.txt'); 89 const buffer = Buffer.from('Dogs running'.repeat(1000), 'utf8'); 90 fs.writeFileSync(newFile, buffer); 91 92 const fileHandle = await open(newFile, 'r'); 93 94 const controller = new AbortController(); 95 const { signal } = controller; 96 tick(1, () => controller.abort()); 97 await assert.rejects(fileHandle.readFile({ signal, encoding: 'utf8' }), { 98 name: 'AbortError' 99 }, 'tick-1'); 100 101 await fileHandle.close(); 102 } 103 104 // Validate file size is within range for reading 105 { 106 // Variable taken from https://github.com/nodejs/node/blob/master/lib/internal/fs/promises.js#L5 107 const kIoMaxLength = 2 ** 31 - 1; 108 109 const newFile = path.resolve(tmpDir, 'dogs-running3.txt'); 110 await writeFile(newFile, Buffer.from('0')); 111 await truncate(newFile, kIoMaxLength + 1); 112 113 const fileHandle = await open(newFile, 'r'); 114 115 await assert.rejects(fileHandle.readFile(), { 116 name: 'RangeError', 117 code: 'ERR_FS_FILE_TOO_LARGE' 118 }); 119 await fileHandle.close(); 120 } 121} 122 123validateReadFile() 124 .then(validateReadFileProc) 125 .then(doReadAndCancel) 126 .then(common.mustCall()); 127