'use strict';
const common = require('../common');
if (process.config.variables.node_without_node_options)
  common.skip('missing NODE_OPTIONS support');

// Test options specified by env variable.

const assert = require('assert');
const exec = require('child_process').execFile;
const { Worker } = require('worker_threads');

const tmpdir = require('../common/tmpdir');
tmpdir.refresh();

const printA = require.resolve('../fixtures/printA.js');
const printSpaceA = require.resolve('../fixtures/print A.js');

expectNoWorker(` -r ${printA} `, 'A\nB\n');
expectNoWorker(`-r ${printA}`, 'A\nB\n');
expectNoWorker(`-r ${JSON.stringify(printA)}`, 'A\nB\n');
expectNoWorker(`-r ${JSON.stringify(printSpaceA)}`, 'A\nB\n');
expectNoWorker(`-r ${printA} -r ${printA}`, 'A\nB\n');
expectNoWorker(`   -r ${printA}    -r ${printA}`, 'A\nB\n');
expectNoWorker(`   --require ${printA}    --require ${printA}`, 'A\nB\n');
expect('--no-deprecation', 'B\n');
expect('--no-warnings', 'B\n');
expect('--no_warnings', 'B\n');
expect('--trace-warnings', 'B\n');
expect('--redirect-warnings=_', 'B\n');
expect('--trace-deprecation', 'B\n');
expect('--trace-sync-io', 'B\n');
expectNoWorker('--trace-events-enabled', 'B\n');
expect('--track-heap-objects', 'B\n');
expect('--throw-deprecation',
       /.*DeprecationWarning: Buffer\(\) is deprecated due to security and usability issues.*/,
       'new Buffer(42)',
       true);
expectNoWorker('--zero-fill-buffers', 'B\n');
expectNoWorker('--v8-pool-size=10', 'B\n');
expectNoWorker('--trace-event-categories node', 'B\n');
expectNoWorker(
  // eslint-disable-next-line no-template-curly-in-string
  '--trace-event-file-pattern {pid}-${rotation}.trace_events',
  'B\n'
);
// eslint-disable-next-line no-template-curly-in-string
expectNoWorker('--trace-event-file-pattern {pid}-${rotation}.trace_events ' +
       '--trace-event-categories node.async_hooks', 'B\n');
expect('--unhandled-rejections=none', 'B\n');

if (common.isLinux) {
  expect('--perf-basic-prof', 'B\n');
  expect('--perf-basic-prof-only-functions', 'B\n');

  if (['arm', 'x64'].includes(process.arch)) {
    expect('--perf-prof', 'B\n');
    expect('--perf-prof-unwinding-info', 'B\n');
  }
}

if (common.hasCrypto) {
  expectNoWorker('--use-openssl-ca', 'B\n');
  expectNoWorker('--use-bundled-ca', 'B\n');
  expectNoWorker('--openssl-config=_ossl_cfg', 'B\n');
}

// V8 options
expect('--abort_on-uncaught_exception', 'B\n');
expect('--disallow-code-generation-from-strings', 'B\n');
expect('--huge-max-old-generation-size', 'B\n');
expect('--jitless', 'B\n');
expect('--max-old-space-size=0', 'B\n');
expect('--stack-trace-limit=100',
       /(\s*at f \(\[(eval|worker eval)\]:1:\d*\)\r?\n)/,
       '(function f() { f(); })();',
       true);
// Unsupported on arm. See https://crbug.com/v8/8713.
if (!['arm', 'arm64'].includes(process.arch))
  expect('--interpreted-frames-native-stack', 'B\n');

// Workers can't eval as ES Modules. https://github.com/nodejs/node/issues/30682
expectNoWorker('--input-type=module',
               'B\n', 'console.log(await "B")');

function expectNoWorker(opt, want, command, wantsError) {
  expect(opt, want, command, wantsError, false);
}

function expect(
  opt, want, command = 'console.log("B")', wantsError = false, testWorker = true
) {
  const argv = ['-e', command];
  const opts = {
    cwd: tmpdir.path,
    env: Object.assign({}, process.env, { NODE_OPTIONS: opt }),
    maxBuffer: 1e6,
  };
  if (typeof want === 'string')
    want = new RegExp(want);

  const test = (type) => common.mustCall((err, stdout) => {
    const o = JSON.stringify(opt);
    if (wantsError) {
      assert.ok(err, `${type}: expected error for ${o}`);
      stdout = err.stack;
    } else {
      assert.ifError(err, `${type}: failed for ${o}`);
    }
    if (want.test(stdout)) return;

    assert.fail(
      `${type}: for ${o}, failed to find ${want} in: <\n${stdout}\n>`
    );
  });

  exec(process.execPath, argv, opts, test('child process'));
  if (testWorker)
    workerTest(opts, command, wantsError, test('worker'));
}

async function collectStream(readable) {
  readable.setEncoding('utf8');
  let data = '';
  for await (const chunk of readable) {
    data += chunk;
  }
  return data;
}

function workerTest(opts, command, wantsError, test) {
  let workerError = null;
  const worker = new Worker(command, {
    ...opts,
    execArgv: [],
    eval: true,
    stdout: true,
    stderr: true
  });
  worker.on('error', (err) => {
    workerError = err;
  });
  worker.on('exit', common.mustCall((code) => {
    assert.strictEqual(code, wantsError ? 1 : 0);
    collectStream(worker.stdout).then((stdout) => {
      test(workerError, stdout);
    });
  }));
}
