11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ciconst common = require('../common');
31cb0ef41Sopenharmony_ciconst assert = require('assert');
41cb0ef41Sopenharmony_ciconst { Worker, isMainThread } = require('worker_threads');
51cb0ef41Sopenharmony_ciconst { once } = require('events');
61cb0ef41Sopenharmony_ciconst fs = require('fs');
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ciif (!isMainThread)
91cb0ef41Sopenharmony_ci  common.skip('test needs to be able to freely set `trackUnmanagedFds`');
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ci// All the tests here are run sequentially, to avoid accidentally opening an fd
121cb0ef41Sopenharmony_ci// which another part of the test expects to be closed.
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ciconst preamble = `
151cb0ef41Sopenharmony_ciconst fs = require("fs");
161cb0ef41Sopenharmony_ciconst { parentPort } = require('worker_threads');
171cb0ef41Sopenharmony_ciconst __filename = ${JSON.stringify(__filename)};
181cb0ef41Sopenharmony_ciprocess.on('warning', (warning) => parentPort.postMessage({ warning }));
191cb0ef41Sopenharmony_ci`;
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ci(async () => {
221cb0ef41Sopenharmony_ci  // Consistency check: Without trackUnmanagedFds, FDs are *not* closed.
231cb0ef41Sopenharmony_ci  {
241cb0ef41Sopenharmony_ci    const w = new Worker(`${preamble}
251cb0ef41Sopenharmony_ci    parentPort.postMessage(fs.openSync(__filename));
261cb0ef41Sopenharmony_ci    `, { eval: true, trackUnmanagedFds: false });
271cb0ef41Sopenharmony_ci    const [ [ fd ] ] = await Promise.all([once(w, 'message'), once(w, 'exit')]);
281cb0ef41Sopenharmony_ci    assert(fd > 2);
291cb0ef41Sopenharmony_ci    fs.fstatSync(fd); // Does not throw.
301cb0ef41Sopenharmony_ci    fs.closeSync(fd);
311cb0ef41Sopenharmony_ci  }
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci  // With trackUnmanagedFds, FDs are closed automatically.
341cb0ef41Sopenharmony_ci  {
351cb0ef41Sopenharmony_ci    const w = new Worker(`${preamble}
361cb0ef41Sopenharmony_ci    parentPort.postMessage(fs.openSync(__filename));
371cb0ef41Sopenharmony_ci    `, { eval: true, trackUnmanagedFds: true });
381cb0ef41Sopenharmony_ci    const [ [ fd ] ] = await Promise.all([once(w, 'message'), once(w, 'exit')]);
391cb0ef41Sopenharmony_ci    assert(fd > 2);
401cb0ef41Sopenharmony_ci    assert.throws(() => fs.fstatSync(fd), { code: 'EBADF' });
411cb0ef41Sopenharmony_ci  }
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ci  // The same, but trackUnmanagedFds is used only as the implied default.
441cb0ef41Sopenharmony_ci  {
451cb0ef41Sopenharmony_ci    const w = new Worker(`${preamble}
461cb0ef41Sopenharmony_ci    parentPort.postMessage(fs.openSync(__filename));
471cb0ef41Sopenharmony_ci    `, { eval: true });
481cb0ef41Sopenharmony_ci    const [ [ fd ] ] = await Promise.all([once(w, 'message'), once(w, 'exit')]);
491cb0ef41Sopenharmony_ci    assert(fd > 2);
501cb0ef41Sopenharmony_ci    assert.throws(() => fs.fstatSync(fd), { code: 'EBADF' });
511cb0ef41Sopenharmony_ci  }
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci  // There is a warning when an fd is unexpectedly opened twice.
541cb0ef41Sopenharmony_ci  {
551cb0ef41Sopenharmony_ci    const w = new Worker(`${preamble}
561cb0ef41Sopenharmony_ci    parentPort.postMessage(fs.openSync(__filename));
571cb0ef41Sopenharmony_ci    parentPort.once('message', () => {
581cb0ef41Sopenharmony_ci      const reopened = fs.openSync(__filename);
591cb0ef41Sopenharmony_ci      fs.closeSync(reopened);
601cb0ef41Sopenharmony_ci    });
611cb0ef41Sopenharmony_ci    `, { eval: true, trackUnmanagedFds: true });
621cb0ef41Sopenharmony_ci    const [ fd ] = await once(w, 'message');
631cb0ef41Sopenharmony_ci    fs.closeSync(fd);
641cb0ef41Sopenharmony_ci    w.postMessage('');
651cb0ef41Sopenharmony_ci    const [ { warning } ] = await once(w, 'message');
661cb0ef41Sopenharmony_ci    assert.match(warning.message,
671cb0ef41Sopenharmony_ci                 /File descriptor \d+ opened in unmanaged mode twice/);
681cb0ef41Sopenharmony_ci  }
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci  // There is a warning when an fd is unexpectedly closed.
711cb0ef41Sopenharmony_ci  {
721cb0ef41Sopenharmony_ci    const w = new Worker(`${preamble}
731cb0ef41Sopenharmony_ci    parentPort.once('message', (fd) => {
741cb0ef41Sopenharmony_ci      fs.closeSync(fd);
751cb0ef41Sopenharmony_ci    });
761cb0ef41Sopenharmony_ci    `, { eval: true, trackUnmanagedFds: true });
771cb0ef41Sopenharmony_ci    w.postMessage(fs.openSync(__filename));
781cb0ef41Sopenharmony_ci    const [ { warning } ] = await once(w, 'message');
791cb0ef41Sopenharmony_ci    assert.match(warning.message,
801cb0ef41Sopenharmony_ci                 /File descriptor \d+ closed but not opened in unmanaged mode/);
811cb0ef41Sopenharmony_ci  }
821cb0ef41Sopenharmony_ci})().then(common.mustCall());
83