1'use strict'; 2 3const common = require('../common'); 4 5// The following tests validate base functionality for the fs.promises 6// FileHandle.read method. 7 8const fs = require('fs'); 9const { open } = fs.promises; 10const path = require('path'); 11const fixtures = require('../common/fixtures'); 12const tmpdir = require('../common/tmpdir'); 13const assert = require('assert'); 14const tmpDir = tmpdir.path; 15 16async function read(fileHandle, buffer, offset, length, position, options) { 17 return options.useConf ? 18 fileHandle.read({ buffer, offset, length, position }) : 19 fileHandle.read(buffer, offset, length, position); 20} 21 22async function validateRead(data, file, options) { 23 const filePath = path.resolve(tmpDir, file); 24 const buffer = Buffer.from(data, 'utf8'); 25 26 const fd = fs.openSync(filePath, 'w+'); 27 const fileHandle = await open(filePath, 'w+'); 28 const streamFileHandle = await open(filePath, 'w+'); 29 30 fs.writeSync(fd, buffer, 0, buffer.length); 31 fs.closeSync(fd); 32 33 fileHandle.on('close', common.mustCall()); 34 const readAsyncHandle = 35 await read(fileHandle, Buffer.alloc(11), 0, 11, 0, options); 36 assert.deepStrictEqual(data.length, readAsyncHandle.bytesRead); 37 if (data.length) 38 assert.deepStrictEqual(buffer, readAsyncHandle.buffer); 39 await fileHandle.close(); 40 41 const stream = fs.createReadStream(null, { fd: streamFileHandle }); 42 let streamData = Buffer.alloc(0); 43 for await (const chunk of stream) 44 streamData = Buffer.from(chunk); 45 assert.deepStrictEqual(buffer, streamData); 46 if (data.length) 47 assert.deepStrictEqual(streamData, readAsyncHandle.buffer); 48 await streamFileHandle.close(); 49} 50 51async function validateLargeRead(options) { 52 // Reading beyond file length (3 in this case) should return no data. 53 // This is a test for a bug where reads > uint32 would return data 54 // from the current position in the file. 55 const filePath = fixtures.path('x.txt'); 56 const fileHandle = await open(filePath, 'r'); 57 const pos = 0xffffffff + 1; // max-uint32 + 1 58 const readHandle = 59 await read(fileHandle, Buffer.alloc(1), 0, 1, pos, options); 60 61 assert.strictEqual(readHandle.bytesRead, 0); 62} 63 64async function validateReadNoParams() { 65 const filePath = fixtures.path('x.txt'); 66 const fileHandle = await open(filePath, 'r'); 67 // Should not throw 68 await fileHandle.read(); 69} 70 71// Validates that the zero position is respected after the position has been 72// moved. The test iterates over the xyz chars twice making sure that the values 73// are read from the correct position. 74async function validateReadWithPositionZero() { 75 const opts = { useConf: true }; 76 const filePath = fixtures.path('x.txt'); 77 const fileHandle = await open(filePath, 'r'); 78 const expectedSequence = ['x', 'y', 'z']; 79 80 for (let i = 0; i < expectedSequence.length * 2; i++) { 81 const len = 1; 82 const pos = i % 3; 83 const buf = Buffer.alloc(len); 84 const { bytesRead } = await read(fileHandle, buf, 0, len, pos, opts); 85 assert.strictEqual(bytesRead, len); 86 assert.strictEqual(buf.toString(), expectedSequence[pos]); 87 } 88} 89 90async function validateReadLength(len) { 91 const buf = Buffer.alloc(4); 92 const opts = { useConf: true }; 93 const filePath = fixtures.path('x.txt'); 94 const fileHandle = await open(filePath, 'r'); 95 const { bytesRead } = await read(fileHandle, buf, 0, len, 0, opts); 96 assert.strictEqual(bytesRead, len); 97} 98 99 100(async function() { 101 tmpdir.refresh(); 102 await validateRead('Hello world', 'read-file', { useConf: false }); 103 await validateRead('', 'read-empty-file', { useConf: false }); 104 await validateRead('Hello world', 'read-file-conf', { useConf: true }); 105 await validateRead('', 'read-empty-file-conf', { useConf: true }); 106 await validateLargeRead({ useConf: false }); 107 await validateLargeRead({ useConf: true }); 108 await validateReadNoParams(); 109 await validateReadWithPositionZero(); 110 await validateReadLength(0); 111 await validateReadLength(1); 112})().then(common.mustCall()); 113