1'use strict'; 2 3const common = require('../common'); 4 5// This test ensures that fs.write accepts "named parameters" object 6// and doesn't interpret objects as strings 7 8const assert = require('assert'); 9const fs = require('fs'); 10const path = require('path'); 11const tmpdir = require('../common/tmpdir'); 12const util = require('util'); 13 14tmpdir.refresh(); 15 16const destInvalid = path.resolve(tmpdir.path, 'rwopt_invalid'); 17const buffer = Buffer.from('zyx'); 18 19function testInvalidCb(fd, expectedCode, buffer, options, callback) { 20 assert.throws( 21 () => fs.write(fd, buffer, common.mustNotMutateObjectDeep(options), common.mustNotCall()), 22 { code: expectedCode } 23 ); 24 callback(0); 25} 26 27function testValidCb(buffer, options, index, callback) { 28 options = common.mustNotMutateObjectDeep(options); 29 const length = options?.length; 30 const offset = options?.offset; 31 const dest = path.resolve(tmpdir.path, `rwopt_valid_${index}`); 32 fs.open(dest, 'w', common.mustSucceed((fd) => { 33 fs.write(fd, buffer, options, common.mustSucceed((bytesWritten, bufferWritten) => { 34 const writeBufCopy = Uint8Array.prototype.slice.call(bufferWritten); 35 fs.close(fd, common.mustSucceed(() => { 36 fs.open(dest, 'r', common.mustSucceed((fd) => { 37 fs.read(fd, buffer, options, common.mustSucceed((bytesRead, bufferRead) => { 38 const readBufCopy = Uint8Array.prototype.slice.call(bufferRead); 39 40 assert.ok(bytesWritten >= bytesRead); 41 if (length !== undefined && length !== null) { 42 assert.strictEqual(bytesWritten, length); 43 assert.strictEqual(bytesRead, length); 44 } 45 if (offset === undefined || offset === 0) { 46 assert.deepStrictEqual(writeBufCopy, readBufCopy); 47 } 48 assert.deepStrictEqual(bufferWritten, bufferRead); 49 fs.close(fd, common.mustSucceed(callback)); 50 })); 51 })); 52 })); 53 })); 54 })); 55} 56 57// Promisify to reduce flakiness 58const testInvalid = util.promisify(testInvalidCb); 59const testValid = util.promisify(testValidCb); 60 61async function runTests(fd) { 62 // Test if first argument is not wrongly interpreted as ArrayBufferView|string 63 for (const badBuffer of [ 64 undefined, null, true, 42, 42n, Symbol('42'), NaN, [], () => {}, 65 Promise.resolve(new Uint8Array(1)), 66 common.mustNotCall(), 67 common.mustNotMutateObjectDeep({}), 68 {}, 69 { buffer: 'amNotParam' }, 70 { string: 'amNotParam' }, 71 { buffer: new Uint8Array(1).buffer }, 72 new Date(), 73 new String('notPrimitive'), 74 { [Symbol.toPrimitive]: (hint) => 'amObject' }, 75 76 // TODO(LiviaMedeiros): add the following after DEP0162 EOL 77 // { toString() { return 'amObject'; } }, 78 ]) { 79 await testInvalid(fd, 'ERR_INVALID_ARG_TYPE', badBuffer, {}); 80 } 81 82 // First argument (buffer or string) is mandatory 83 await testInvalid(fd, 'ERR_INVALID_ARG_TYPE', undefined, undefined); 84 85 // Various invalid options 86 await testInvalid(fd, 'ERR_OUT_OF_RANGE', buffer, { length: 5 }); 87 await testInvalid(fd, 'ERR_OUT_OF_RANGE', buffer, { offset: 5 }); 88 await testInvalid(fd, 'ERR_OUT_OF_RANGE', buffer, { length: 1, offset: 3 }); 89 await testInvalid(fd, 'ERR_OUT_OF_RANGE', buffer, { length: -1 }); 90 await testInvalid(fd, 'ERR_OUT_OF_RANGE', buffer, { offset: -1 }); 91 await testInvalid(fd, 'ERR_INVALID_ARG_TYPE', buffer, { offset: false }); 92 await testInvalid(fd, 'ERR_INVALID_ARG_TYPE', buffer, { offset: true }); 93 await testInvalid(fd, 'ERR_INVALID_ARG_TYPE', buffer, true); 94 await testInvalid(fd, 'ERR_INVALID_ARG_TYPE', buffer, '42'); 95 await testInvalid(fd, 'ERR_INVALID_ARG_TYPE', buffer, Symbol('42')); 96 97 // Test compatibility with fs.read counterpart 98 for (const [ index, options ] of [ 99 null, 100 {}, 101 { length: 1 }, 102 { position: 5 }, 103 { length: 1, position: 5 }, 104 { length: 1, position: -1, offset: 2 }, 105 { length: null }, 106 { position: null }, 107 { offset: 1 }, 108 ].entries()) { 109 await testValid(buffer, options, index); 110 } 111} 112 113fs.open(destInvalid, 'w+', common.mustSucceed(async (fd) => { 114 runTests(fd).then(common.mustCall(() => fs.close(fd, common.mustSucceed()))); 115})); 116