11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst common = require('../common');
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci// This test ensures that fs.write accepts "named parameters" object
61cb0ef41Sopenharmony_ci// and doesn't interpret objects as strings
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ciconst assert = require('assert');
91cb0ef41Sopenharmony_ciconst fs = require('fs');
101cb0ef41Sopenharmony_ciconst path = require('path');
111cb0ef41Sopenharmony_ciconst tmpdir = require('../common/tmpdir');
121cb0ef41Sopenharmony_ciconst util = require('util');
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_citmpdir.refresh();
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ciconst destInvalid = path.resolve(tmpdir.path, 'rwopt_invalid');
171cb0ef41Sopenharmony_ciconst buffer = Buffer.from('zyx');
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_cifunction testInvalidCb(fd, expectedCode, buffer, options, callback) {
201cb0ef41Sopenharmony_ci  assert.throws(
211cb0ef41Sopenharmony_ci    () => fs.write(fd, buffer, common.mustNotMutateObjectDeep(options), common.mustNotCall()),
221cb0ef41Sopenharmony_ci    { code: expectedCode }
231cb0ef41Sopenharmony_ci  );
241cb0ef41Sopenharmony_ci  callback(0);
251cb0ef41Sopenharmony_ci}
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_cifunction testValidCb(buffer, options, index, callback) {
281cb0ef41Sopenharmony_ci  options = common.mustNotMutateObjectDeep(options);
291cb0ef41Sopenharmony_ci  const length = options?.length;
301cb0ef41Sopenharmony_ci  const offset = options?.offset;
311cb0ef41Sopenharmony_ci  const dest = path.resolve(tmpdir.path, `rwopt_valid_${index}`);
321cb0ef41Sopenharmony_ci  fs.open(dest, 'w', common.mustSucceed((fd) => {
331cb0ef41Sopenharmony_ci    fs.write(fd, buffer, options, common.mustSucceed((bytesWritten, bufferWritten) => {
341cb0ef41Sopenharmony_ci      const writeBufCopy = Uint8Array.prototype.slice.call(bufferWritten);
351cb0ef41Sopenharmony_ci      fs.close(fd, common.mustSucceed(() => {
361cb0ef41Sopenharmony_ci        fs.open(dest, 'r', common.mustSucceed((fd) => {
371cb0ef41Sopenharmony_ci          fs.read(fd, buffer, options, common.mustSucceed((bytesRead, bufferRead) => {
381cb0ef41Sopenharmony_ci            const readBufCopy = Uint8Array.prototype.slice.call(bufferRead);
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci            assert.ok(bytesWritten >= bytesRead);
411cb0ef41Sopenharmony_ci            if (length !== undefined && length !== null) {
421cb0ef41Sopenharmony_ci              assert.strictEqual(bytesWritten, length);
431cb0ef41Sopenharmony_ci              assert.strictEqual(bytesRead, length);
441cb0ef41Sopenharmony_ci            }
451cb0ef41Sopenharmony_ci            if (offset === undefined || offset === 0) {
461cb0ef41Sopenharmony_ci              assert.deepStrictEqual(writeBufCopy, readBufCopy);
471cb0ef41Sopenharmony_ci            }
481cb0ef41Sopenharmony_ci            assert.deepStrictEqual(bufferWritten, bufferRead);
491cb0ef41Sopenharmony_ci            fs.close(fd, common.mustSucceed(callback));
501cb0ef41Sopenharmony_ci          }));
511cb0ef41Sopenharmony_ci        }));
521cb0ef41Sopenharmony_ci      }));
531cb0ef41Sopenharmony_ci    }));
541cb0ef41Sopenharmony_ci  }));
551cb0ef41Sopenharmony_ci}
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci// Promisify to reduce flakiness
581cb0ef41Sopenharmony_ciconst testInvalid = util.promisify(testInvalidCb);
591cb0ef41Sopenharmony_ciconst testValid = util.promisify(testValidCb);
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ciasync function runTests(fd) {
621cb0ef41Sopenharmony_ci  // Test if first argument is not wrongly interpreted as ArrayBufferView|string
631cb0ef41Sopenharmony_ci  for (const badBuffer of [
641cb0ef41Sopenharmony_ci    undefined, null, true, 42, 42n, Symbol('42'), NaN, [], () => {},
651cb0ef41Sopenharmony_ci    Promise.resolve(new Uint8Array(1)),
661cb0ef41Sopenharmony_ci    common.mustNotCall(),
671cb0ef41Sopenharmony_ci    common.mustNotMutateObjectDeep({}),
681cb0ef41Sopenharmony_ci    {},
691cb0ef41Sopenharmony_ci    { buffer: 'amNotParam' },
701cb0ef41Sopenharmony_ci    { string: 'amNotParam' },
711cb0ef41Sopenharmony_ci    { buffer: new Uint8Array(1).buffer },
721cb0ef41Sopenharmony_ci    new Date(),
731cb0ef41Sopenharmony_ci    new String('notPrimitive'),
741cb0ef41Sopenharmony_ci    { [Symbol.toPrimitive]: (hint) => 'amObject' },
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci    // TODO(LiviaMedeiros): add the following after DEP0162 EOL
771cb0ef41Sopenharmony_ci    // { toString() { return 'amObject'; } },
781cb0ef41Sopenharmony_ci  ]) {
791cb0ef41Sopenharmony_ci    await testInvalid(fd, 'ERR_INVALID_ARG_TYPE', badBuffer, {});
801cb0ef41Sopenharmony_ci  }
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci  // First argument (buffer or string) is mandatory
831cb0ef41Sopenharmony_ci  await testInvalid(fd, 'ERR_INVALID_ARG_TYPE', undefined, undefined);
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ci  // Various invalid options
861cb0ef41Sopenharmony_ci  await testInvalid(fd, 'ERR_OUT_OF_RANGE', buffer, { length: 5 });
871cb0ef41Sopenharmony_ci  await testInvalid(fd, 'ERR_OUT_OF_RANGE', buffer, { offset: 5 });
881cb0ef41Sopenharmony_ci  await testInvalid(fd, 'ERR_OUT_OF_RANGE', buffer, { length: 1, offset: 3 });
891cb0ef41Sopenharmony_ci  await testInvalid(fd, 'ERR_OUT_OF_RANGE', buffer, { length: -1 });
901cb0ef41Sopenharmony_ci  await testInvalid(fd, 'ERR_OUT_OF_RANGE', buffer, { offset: -1 });
911cb0ef41Sopenharmony_ci  await testInvalid(fd, 'ERR_INVALID_ARG_TYPE', buffer, { offset: false });
921cb0ef41Sopenharmony_ci  await testInvalid(fd, 'ERR_INVALID_ARG_TYPE', buffer, { offset: true });
931cb0ef41Sopenharmony_ci  await testInvalid(fd, 'ERR_INVALID_ARG_TYPE', buffer, true);
941cb0ef41Sopenharmony_ci  await testInvalid(fd, 'ERR_INVALID_ARG_TYPE', buffer, '42');
951cb0ef41Sopenharmony_ci  await testInvalid(fd, 'ERR_INVALID_ARG_TYPE', buffer, Symbol('42'));
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_ci  // Test compatibility with fs.read counterpart
981cb0ef41Sopenharmony_ci  for (const [ index, options ] of [
991cb0ef41Sopenharmony_ci    null,
1001cb0ef41Sopenharmony_ci    {},
1011cb0ef41Sopenharmony_ci    { length: 1 },
1021cb0ef41Sopenharmony_ci    { position: 5 },
1031cb0ef41Sopenharmony_ci    { length: 1, position: 5 },
1041cb0ef41Sopenharmony_ci    { length: 1, position: -1, offset: 2 },
1051cb0ef41Sopenharmony_ci    { length: null },
1061cb0ef41Sopenharmony_ci    { position: null },
1071cb0ef41Sopenharmony_ci    { offset: 1 },
1081cb0ef41Sopenharmony_ci  ].entries()) {
1091cb0ef41Sopenharmony_ci    await testValid(buffer, options, index);
1101cb0ef41Sopenharmony_ci  }
1111cb0ef41Sopenharmony_ci}
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_cifs.open(destInvalid, 'w+', common.mustSucceed(async (fd) => {
1141cb0ef41Sopenharmony_ci  runTests(fd).then(common.mustCall(() => fs.close(fd, common.mustSucceed())));
1151cb0ef41Sopenharmony_ci}));
116