1'use strict';
2// Flags: --expose-internals
3
4const common = require('../common');
5const tmpdir = require('../common/tmpdir');
6
7// The following tests validate aggregate errors are thrown correctly
8// when both an operation and close throw.
9
10const path = require('path');
11const {
12  readFile,
13  writeFile,
14  truncate,
15  lchmod,
16} = require('fs/promises');
17const {
18  FileHandle,
19} = require('internal/fs/promises');
20
21const assert = require('assert');
22const originalFd = Object.getOwnPropertyDescriptor(FileHandle.prototype, 'fd');
23
24let count = 0;
25async function createFile() {
26  const filePath = path.join(tmpdir.path, `op_errors_${++count}.txt`);
27  await writeFile(filePath, 'content');
28  return filePath;
29}
30
31async function checkOperationError(op) {
32  try {
33    const filePath = await createFile();
34    Object.defineProperty(FileHandle.prototype, 'fd', {
35      get: function() {
36        // Verify that close is called when an error is thrown
37        this.close = common.mustCall(this.close);
38        const opError = new Error('INTERNAL_ERROR');
39        opError.code = 123;
40        throw opError;
41      }
42    });
43
44    await assert.rejects(op(filePath), {
45      name: 'Error',
46      message: 'INTERNAL_ERROR',
47      code: 123,
48    });
49  } finally {
50    Object.defineProperty(FileHandle.prototype, 'fd', originalFd);
51  }
52}
53(async function() {
54  tmpdir.refresh();
55  await checkOperationError((filePath) => truncate(filePath));
56  await checkOperationError((filePath) => readFile(filePath));
57  await checkOperationError((filePath) => writeFile(filePath, '123'));
58  if (common.isOSX) {
59    await checkOperationError((filePath) => lchmod(filePath, 0o777));
60  }
61})().then(common.mustCall());
62