11cb0ef41Sopenharmony_ciimport * as common from '../common/index.mjs';
21cb0ef41Sopenharmony_ciimport * as fixtures from '../common/fixtures.mjs';
31cb0ef41Sopenharmony_ciimport fs from 'fs';
41cb0ef41Sopenharmony_ciimport assert from 'assert';
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_ci// This test ensures that "position" argument is correctly validated
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ciconst filepath = fixtures.path('x.txt');
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ciconst buffer = Buffer.from('xyz\n');
111cb0ef41Sopenharmony_ciconst offset = 0;
121cb0ef41Sopenharmony_ciconst length = buffer.byteLength;
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ci// allowedErrors is an array of acceptable internal errors
151cb0ef41Sopenharmony_ci// For example, on some platforms read syscall might return -EFBIG or -EOVERFLOW
161cb0ef41Sopenharmony_ciasync function testValid(position, allowedErrors = []) {
171cb0ef41Sopenharmony_ci  return new Promise((resolve, reject) => {
181cb0ef41Sopenharmony_ci    fs.open(filepath, 'r', common.mustSucceed((fd) => {
191cb0ef41Sopenharmony_ci      let callCount = 3;
201cb0ef41Sopenharmony_ci      const handler = common.mustCall((err) => {
211cb0ef41Sopenharmony_ci        callCount--;
221cb0ef41Sopenharmony_ci        if (err && !allowedErrors.includes(err.code)) {
231cb0ef41Sopenharmony_ci          fs.close(fd, common.mustSucceed());
241cb0ef41Sopenharmony_ci          reject(err);
251cb0ef41Sopenharmony_ci        } else if (callCount === 0) {
261cb0ef41Sopenharmony_ci          fs.close(fd, common.mustSucceed(resolve));
271cb0ef41Sopenharmony_ci        }
281cb0ef41Sopenharmony_ci      }, callCount);
291cb0ef41Sopenharmony_ci      fs.read(fd, buffer, offset, length, position, handler);
301cb0ef41Sopenharmony_ci      fs.read(fd, { buffer, offset, length, position }, handler);
311cb0ef41Sopenharmony_ci      fs.read(fd, buffer, common.mustNotMutateObjectDeep({ offset, length, position }), handler);
321cb0ef41Sopenharmony_ci    }));
331cb0ef41Sopenharmony_ci  });
341cb0ef41Sopenharmony_ci}
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ciasync function testInvalid(code, position) {
371cb0ef41Sopenharmony_ci  return new Promise((resolve, reject) => {
381cb0ef41Sopenharmony_ci    fs.open(filepath, 'r', common.mustSucceed((fd) => {
391cb0ef41Sopenharmony_ci      try {
401cb0ef41Sopenharmony_ci        assert.throws(
411cb0ef41Sopenharmony_ci          () => fs.read(fd, buffer, offset, length, position, common.mustNotCall()),
421cb0ef41Sopenharmony_ci          { code }
431cb0ef41Sopenharmony_ci        );
441cb0ef41Sopenharmony_ci        assert.throws(
451cb0ef41Sopenharmony_ci          () => fs.read(fd, { buffer, offset, length, position }, common.mustNotCall()),
461cb0ef41Sopenharmony_ci          { code }
471cb0ef41Sopenharmony_ci        );
481cb0ef41Sopenharmony_ci        assert.throws(
491cb0ef41Sopenharmony_ci          () => fs.read(fd, buffer, common.mustNotMutateObjectDeep({ offset, length, position }), common.mustNotCall()),
501cb0ef41Sopenharmony_ci          { code }
511cb0ef41Sopenharmony_ci        );
521cb0ef41Sopenharmony_ci        resolve();
531cb0ef41Sopenharmony_ci      } catch (err) {
541cb0ef41Sopenharmony_ci        reject(err);
551cb0ef41Sopenharmony_ci      } finally {
561cb0ef41Sopenharmony_ci        fs.close(fd, common.mustSucceed());
571cb0ef41Sopenharmony_ci      }
581cb0ef41Sopenharmony_ci    }));
591cb0ef41Sopenharmony_ci  });
601cb0ef41Sopenharmony_ci}
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_ci{
631cb0ef41Sopenharmony_ci  await testValid(undefined);
641cb0ef41Sopenharmony_ci  await testValid(null);
651cb0ef41Sopenharmony_ci  await testValid(-1);
661cb0ef41Sopenharmony_ci  await testValid(-1n);
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci  await testValid(0);
691cb0ef41Sopenharmony_ci  await testValid(0n);
701cb0ef41Sopenharmony_ci  await testValid(1);
711cb0ef41Sopenharmony_ci  await testValid(1n);
721cb0ef41Sopenharmony_ci  await testValid(9);
731cb0ef41Sopenharmony_ci  await testValid(9n);
741cb0ef41Sopenharmony_ci  await testValid(Number.MAX_SAFE_INTEGER, [ 'EFBIG', 'EOVERFLOW' ]);
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci  await testValid(2n ** 63n - 1n - BigInt(length), [ 'EFBIG', 'EOVERFLOW' ]);
771cb0ef41Sopenharmony_ci  await testInvalid('ERR_OUT_OF_RANGE', 2n ** 63n);
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci  // TODO(LiviaMedeiros): test `2n ** 63n - BigInt(length)`
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci  await testInvalid('ERR_OUT_OF_RANGE', NaN);
821cb0ef41Sopenharmony_ci  await testInvalid('ERR_OUT_OF_RANGE', -Infinity);
831cb0ef41Sopenharmony_ci  await testInvalid('ERR_OUT_OF_RANGE', Infinity);
841cb0ef41Sopenharmony_ci  await testInvalid('ERR_OUT_OF_RANGE', -0.999);
851cb0ef41Sopenharmony_ci  await testInvalid('ERR_OUT_OF_RANGE', -(2n ** 64n));
861cb0ef41Sopenharmony_ci  await testInvalid('ERR_OUT_OF_RANGE', Number.MAX_SAFE_INTEGER + 1);
871cb0ef41Sopenharmony_ci  await testInvalid('ERR_OUT_OF_RANGE', Number.MAX_VALUE);
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci  for (const badTypeValue of [
901cb0ef41Sopenharmony_ci    false, true, '1', Symbol(1), {}, [], () => {}, Promise.resolve(1),
911cb0ef41Sopenharmony_ci  ]) {
921cb0ef41Sopenharmony_ci    await testInvalid('ERR_INVALID_ARG_TYPE', badTypeValue);
931cb0ef41Sopenharmony_ci  }
941cb0ef41Sopenharmony_ci}
95