11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ci// This tests to make sure that modules with symlinked circular dependencies
41cb0ef41Sopenharmony_ci// do not blow out the module cache and recurse forever. See issue
51cb0ef41Sopenharmony_ci// https://github.com/nodejs/node/pull/5950 for context. PR #5950 attempted
61cb0ef41Sopenharmony_ci// to solve a problem with symlinked peer dependencies by caching using the
71cb0ef41Sopenharmony_ci// symlink path. Unfortunately, that breaks the case tested in this module
81cb0ef41Sopenharmony_ci// because each symlinked module, despite pointing to the same code on disk,
91cb0ef41Sopenharmony_ci// is loaded and cached as a separate module instance, which blows up the
101cb0ef41Sopenharmony_ci// cache and leads to a recursion bug.
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ci// This test should pass in Node.js v4 and v5. It should pass in Node.js v6
131cb0ef41Sopenharmony_ci// after https://github.com/nodejs/node/pull/5950 has been reverted.
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_ciconst common = require('../common');
161cb0ef41Sopenharmony_ciconst assert = require('assert');
171cb0ef41Sopenharmony_ciconst path = require('path');
181cb0ef41Sopenharmony_ciconst fs = require('fs');
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ci// {tmpDir}
211cb0ef41Sopenharmony_ci// ├── index.js
221cb0ef41Sopenharmony_ci// └── node_modules
231cb0ef41Sopenharmony_ci//     ├── moduleA
241cb0ef41Sopenharmony_ci//     │   ├── index.js
251cb0ef41Sopenharmony_ci//     │   └── node_modules
261cb0ef41Sopenharmony_ci//     │       └── moduleB -> {tmpDir}/node_modules/moduleB
271cb0ef41Sopenharmony_ci//     └── moduleB
281cb0ef41Sopenharmony_ci//         ├── index.js
291cb0ef41Sopenharmony_ci//         └── node_modules
301cb0ef41Sopenharmony_ci//         └── moduleA -> {tmpDir}/node_modules/moduleA
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ciconst tmpdir = require('../common/tmpdir');
331cb0ef41Sopenharmony_citmpdir.refresh();
341cb0ef41Sopenharmony_ciconst tmpDir = tmpdir.path;
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ciconst node_modules = path.join(tmpDir, 'node_modules');
371cb0ef41Sopenharmony_ciconst moduleA = path.join(node_modules, 'moduleA');
381cb0ef41Sopenharmony_ciconst moduleB = path.join(node_modules, 'moduleB');
391cb0ef41Sopenharmony_ciconst moduleA_link = path.join(moduleB, 'node_modules', 'moduleA');
401cb0ef41Sopenharmony_ciconst moduleB_link = path.join(moduleA, 'node_modules', 'moduleB');
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_cifs.mkdirSync(node_modules);
431cb0ef41Sopenharmony_cifs.mkdirSync(moduleA);
441cb0ef41Sopenharmony_cifs.mkdirSync(moduleB);
451cb0ef41Sopenharmony_cifs.mkdirSync(path.join(moduleA, 'node_modules'));
461cb0ef41Sopenharmony_cifs.mkdirSync(path.join(moduleB, 'node_modules'));
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_citry {
491cb0ef41Sopenharmony_ci  fs.symlinkSync(moduleA, moduleA_link);
501cb0ef41Sopenharmony_ci  fs.symlinkSync(moduleB, moduleB_link);
511cb0ef41Sopenharmony_ci} catch (err) {
521cb0ef41Sopenharmony_ci  if (err.code !== 'EPERM') throw err;
531cb0ef41Sopenharmony_ci  common.skip('insufficient privileges for symlinks');
541cb0ef41Sopenharmony_ci}
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_cifs.writeFileSync(path.join(tmpDir, 'index.js'),
571cb0ef41Sopenharmony_ci                 'module.exports = require(\'moduleA\');', 'utf8');
581cb0ef41Sopenharmony_cifs.writeFileSync(path.join(moduleA, 'index.js'),
591cb0ef41Sopenharmony_ci                 'module.exports = {b: require(\'moduleB\')};', 'utf8');
601cb0ef41Sopenharmony_cifs.writeFileSync(path.join(moduleB, 'index.js'),
611cb0ef41Sopenharmony_ci                 'module.exports = {a: require(\'moduleA\')};', 'utf8');
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci// Ensure that the symlinks are not followed forever...
641cb0ef41Sopenharmony_ciconst obj = require(path.join(tmpDir, 'index'));
651cb0ef41Sopenharmony_ciassert.ok(obj);
661cb0ef41Sopenharmony_ciassert.ok(obj.b);
671cb0ef41Sopenharmony_ciassert.ok(obj.b.a);
681cb0ef41Sopenharmony_ciassert.ok(!obj.b.a.b);
69