11cb0ef41Sopenharmony_ci// Flags: --preserve-symlinks
21cb0ef41Sopenharmony_ci'use strict';
31cb0ef41Sopenharmony_ciconst common = require('../common');
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ciif (!common.canCreateSymLink())
61cb0ef41Sopenharmony_ci  common.skip('insufficient privileges');
71cb0ef41Sopenharmony_ciif (!common.isMainThread)
81cb0ef41Sopenharmony_ci  common.skip('process.chdir is not available in Workers');
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ciconst assert = require('assert');
111cb0ef41Sopenharmony_ciconst { spawn } = require('child_process');
121cb0ef41Sopenharmony_ciconst fs = require('fs');
131cb0ef41Sopenharmony_ciconst path = require('path');
141cb0ef41Sopenharmony_ciconst process = require('process');
151cb0ef41Sopenharmony_ciconst { Worker } = require('worker_threads');
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ci// Setup: Copy fixtures to tmp directory.
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ciconst fixtures = require('../common/fixtures');
201cb0ef41Sopenharmony_ciconst tmpdir = require('../common/tmpdir');
211cb0ef41Sopenharmony_ciconst dirName = 'module-require-symlink';
221cb0ef41Sopenharmony_ciconst fixtureSource = fixtures.path(dirName);
231cb0ef41Sopenharmony_ciconst tmpDirTarget = path.join(tmpdir.path, dirName);
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci// Copy fixtureSource to linkTarget recursively.
261cb0ef41Sopenharmony_citmpdir.refresh();
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_cifunction copyDir(source, target) {
291cb0ef41Sopenharmony_ci  fs.mkdirSync(target);
301cb0ef41Sopenharmony_ci  fs.readdirSync(source).forEach((entry) => {
311cb0ef41Sopenharmony_ci    const fullPathSource = path.join(source, entry);
321cb0ef41Sopenharmony_ci    const fullPathTarget = path.join(target, entry);
331cb0ef41Sopenharmony_ci    const stats = fs.statSync(fullPathSource);
341cb0ef41Sopenharmony_ci    if (stats.isDirectory()) {
351cb0ef41Sopenharmony_ci      copyDir(fullPathSource, fullPathTarget);
361cb0ef41Sopenharmony_ci    } else {
371cb0ef41Sopenharmony_ci      fs.copyFileSync(fullPathSource, fullPathTarget);
381cb0ef41Sopenharmony_ci    }
391cb0ef41Sopenharmony_ci  });
401cb0ef41Sopenharmony_ci}
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_cicopyDir(fixtureSource, tmpDirTarget);
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci// Move to tmp dir and do everything with relative paths there so that the test
451cb0ef41Sopenharmony_ci// doesn't incorrectly fail due to a symlink somewhere else in the absolute
461cb0ef41Sopenharmony_ci// path.
471cb0ef41Sopenharmony_ciprocess.chdir(tmpdir.path);
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ciconst linkDir = path.join(dirName,
501cb0ef41Sopenharmony_ci                          'node_modules',
511cb0ef41Sopenharmony_ci                          'dep1',
521cb0ef41Sopenharmony_ci                          'node_modules',
531cb0ef41Sopenharmony_ci                          'dep2');
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ciconst linkTarget = path.join('..', '..', 'dep2');
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ciconst linkScript = './linkscript.js';
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ciconst linkScriptTarget = path.join(dirName, 'symlinked.js');
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_citest();
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_cifunction test() {
641cb0ef41Sopenharmony_ci  fs.symlinkSync(linkTarget, linkDir, 'dir');
651cb0ef41Sopenharmony_ci  fs.symlinkSync(linkScriptTarget, linkScript);
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci  // Load symlinked-module
681cb0ef41Sopenharmony_ci  const fooModule = require(path.join(tmpDirTarget, 'foo.js'));
691cb0ef41Sopenharmony_ci  assert.strictEqual(fooModule.dep1.bar.version, 'CORRECT_VERSION');
701cb0ef41Sopenharmony_ci  assert.strictEqual(fooModule.dep2.bar.version, 'CORRECT_VERSION');
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ci  // Load symlinked-script as main
731cb0ef41Sopenharmony_ci  const node = process.execPath;
741cb0ef41Sopenharmony_ci  const child = spawn(node, ['--preserve-symlinks', linkScript]);
751cb0ef41Sopenharmony_ci  child.on('close', function(code, signal) {
761cb0ef41Sopenharmony_ci    assert.strictEqual(code, 0);
771cb0ef41Sopenharmony_ci    assert(!signal);
781cb0ef41Sopenharmony_ci  });
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci  // Also verify that symlinks works for setting preserve via env variables
811cb0ef41Sopenharmony_ci  const childEnv = spawn(node, [linkScript], {
821cb0ef41Sopenharmony_ci    env: { ...process.env, NODE_PRESERVE_SYMLINKS: '1' }
831cb0ef41Sopenharmony_ci  });
841cb0ef41Sopenharmony_ci  childEnv.on('close', function(code, signal) {
851cb0ef41Sopenharmony_ci    assert.strictEqual(code, 0);
861cb0ef41Sopenharmony_ci    assert(!signal);
871cb0ef41Sopenharmony_ci  });
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci  // Also verify that symlinks works for setting preserve via env variables in
901cb0ef41Sopenharmony_ci  // Workers.
911cb0ef41Sopenharmony_ci  const worker = new Worker(linkScript, {
921cb0ef41Sopenharmony_ci    env: { ...process.env, NODE_PRESERVE_SYMLINKS: '1' }
931cb0ef41Sopenharmony_ci  });
941cb0ef41Sopenharmony_ci  worker.on('error', (err) => {
951cb0ef41Sopenharmony_ci    console.log('Worker failed');
961cb0ef41Sopenharmony_ci    throw err;
971cb0ef41Sopenharmony_ci  });
981cb0ef41Sopenharmony_ci  worker.on('exit', common.mustCall((code) => {
991cb0ef41Sopenharmony_ci    assert.strictEqual(code, 0);
1001cb0ef41Sopenharmony_ci  }));
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci  // Also verify that symlinks works for setting preserve via env variables in
1031cb0ef41Sopenharmony_ci  // Workers with explicit execArgv.
1041cb0ef41Sopenharmony_ci  const workerArgv = new Worker(linkScript, {
1051cb0ef41Sopenharmony_ci    execArgv: [],
1061cb0ef41Sopenharmony_ci    env: { ...process.env, NODE_PRESERVE_SYMLINKS: '1' }
1071cb0ef41Sopenharmony_ci  });
1081cb0ef41Sopenharmony_ci  workerArgv.on('error', (err) => {
1091cb0ef41Sopenharmony_ci    console.log('Worker with execArgv failed');
1101cb0ef41Sopenharmony_ci    throw err;
1111cb0ef41Sopenharmony_ci  });
1121cb0ef41Sopenharmony_ci  workerArgv.on('exit', common.mustCall((code) => {
1131cb0ef41Sopenharmony_ci    assert.strictEqual(code, 0);
1141cb0ef41Sopenharmony_ci  }));
1151cb0ef41Sopenharmony_ci}
116