'use strict';

const { mustCall, mustNotCall, skip, isWindows, isIBMi } = require('../common');
const assert = require('assert');
const { createServer } = require('net');
const { isMainThread } = require('worker_threads');

if (!isMainThread) {
  skip('process.execve is not available in Workers');
} else if (isWindows || isIBMi) {
  skip('process.execve is not available in Windows or IBM i');
}

if (process.argv[2] === 'replaced') {
  const port = parseInt(process.env.PORT, 10);
  assert.ok(Number.isInteger(port));

  const server = createServer();
  server.on('error', mustNotCall());
  server.listen(port, mustCall(() => {
    server.close();
  }));
} else {
  // Create a new socket server
  const server = createServer();

  server.on('close', mustNotCall());
  server.listen(0, mustCall(() => {
    const port = server.address().port;

    // Try to create a second server on the same port. It should fail.
    const server2 = createServer();

    server2.on('error', mustCall(() => {
      process.execve(
        process.execPath,
        [process.execPath, __filename, 'replaced'],
        { ...process.env, PORT: port.toString() }
      );

      // If process.execve succeed, this should never be executed.
      assert.fail('process.execve failed');
    }));

    server2.listen(port, mustCall(() => {
      assert.fail('server2.listen unexpectedly succeeded');
    }));
  }));
}
