11cb0ef41Sopenharmony_ci// Copyright Joyent, Inc. and other Node contributors. 21cb0ef41Sopenharmony_ci// 31cb0ef41Sopenharmony_ci// Permission is hereby granted, free of charge, to any person obtaining a 41cb0ef41Sopenharmony_ci// copy of this software and associated documentation files (the 51cb0ef41Sopenharmony_ci// "Software"), to deal in the Software without restriction, including 61cb0ef41Sopenharmony_ci// without limitation the rights to use, copy, modify, merge, publish, 71cb0ef41Sopenharmony_ci// distribute, sublicense, and/or sell copies of the Software, and to permit 81cb0ef41Sopenharmony_ci// persons to whom the Software is furnished to do so, subject to the 91cb0ef41Sopenharmony_ci// following conditions: 101cb0ef41Sopenharmony_ci// 111cb0ef41Sopenharmony_ci// The above copyright notice and this permission notice shall be included 121cb0ef41Sopenharmony_ci// in all copies or substantial portions of the Software. 131cb0ef41Sopenharmony_ci// 141cb0ef41Sopenharmony_ci// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 151cb0ef41Sopenharmony_ci// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 161cb0ef41Sopenharmony_ci// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 171cb0ef41Sopenharmony_ci// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 181cb0ef41Sopenharmony_ci// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 191cb0ef41Sopenharmony_ci// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 201cb0ef41Sopenharmony_ci// USE OR OTHER DEALINGS IN THE SOFTWARE. 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci'use strict'; 231cb0ef41Sopenharmony_ciconst common = require('../common'); 241cb0ef41Sopenharmony_ciconst fixtures = require('../common/fixtures'); 251cb0ef41Sopenharmony_ciconst tmpdir = require('../common/tmpdir'); 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ciif (!common.isMainThread) 281cb0ef41Sopenharmony_ci common.skip('process.chdir is not available in Workers'); 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ciconst assert = require('assert'); 311cb0ef41Sopenharmony_ciconst fs = require('fs'); 321cb0ef41Sopenharmony_ciconst path = require('path'); 331cb0ef41Sopenharmony_cilet async_completed = 0; 341cb0ef41Sopenharmony_cilet async_expected = 0; 351cb0ef41Sopenharmony_ciconst unlink = []; 361cb0ef41Sopenharmony_ciconst skipSymlinks = !common.canCreateSymLink(); 371cb0ef41Sopenharmony_ciconst tmpDir = tmpdir.path; 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_citmpdir.refresh(); 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_cilet root = '/'; 421cb0ef41Sopenharmony_cilet assertEqualPath = assert.strictEqual; 431cb0ef41Sopenharmony_ciif (common.isWindows) { 441cb0ef41Sopenharmony_ci // Something like "C:\\" 451cb0ef41Sopenharmony_ci root = process.cwd().substr(0, 3); 461cb0ef41Sopenharmony_ci assertEqualPath = function(path_left, path_right, message) { 471cb0ef41Sopenharmony_ci assert 481cb0ef41Sopenharmony_ci .strictEqual(path_left.toLowerCase(), path_right.toLowerCase(), message); 491cb0ef41Sopenharmony_ci }; 501cb0ef41Sopenharmony_ci} 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ciprocess.nextTick(runTest); 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_cifunction tmp(p) { 551cb0ef41Sopenharmony_ci return path.join(tmpDir, p); 561cb0ef41Sopenharmony_ci} 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_ciconst targetsAbsDir = path.join(tmpDir, 'targets'); 591cb0ef41Sopenharmony_ciconst tmpAbsDir = tmpDir; 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci// Set up targetsAbsDir and expected subdirectories 621cb0ef41Sopenharmony_cifs.mkdirSync(targetsAbsDir); 631cb0ef41Sopenharmony_cifs.mkdirSync(path.join(targetsAbsDir, 'nested-index')); 641cb0ef41Sopenharmony_cifs.mkdirSync(path.join(targetsAbsDir, 'nested-index', 'one')); 651cb0ef41Sopenharmony_cifs.mkdirSync(path.join(targetsAbsDir, 'nested-index', 'two')); 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_cifunction asynctest(testBlock, args, callback, assertBlock) { 681cb0ef41Sopenharmony_ci async_expected++; 691cb0ef41Sopenharmony_ci testBlock.apply(testBlock, args.concat(function(err) { 701cb0ef41Sopenharmony_ci let ignoreError = false; 711cb0ef41Sopenharmony_ci if (assertBlock) { 721cb0ef41Sopenharmony_ci try { 731cb0ef41Sopenharmony_ci ignoreError = assertBlock.apply(assertBlock, arguments); 741cb0ef41Sopenharmony_ci } catch (e) { 751cb0ef41Sopenharmony_ci err = e; 761cb0ef41Sopenharmony_ci } 771cb0ef41Sopenharmony_ci } 781cb0ef41Sopenharmony_ci async_completed++; 791cb0ef41Sopenharmony_ci callback(ignoreError ? null : err); 801cb0ef41Sopenharmony_ci })); 811cb0ef41Sopenharmony_ci} 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_ci// sub-tests: 841cb0ef41Sopenharmony_cifunction test_simple_error_callback(realpath, realpathSync, cb) { 851cb0ef41Sopenharmony_ci realpath('/this/path/does/not/exist', common.mustCall(function(err, s) { 861cb0ef41Sopenharmony_ci assert(err); 871cb0ef41Sopenharmony_ci assert(!s); 881cb0ef41Sopenharmony_ci cb(); 891cb0ef41Sopenharmony_ci })); 901cb0ef41Sopenharmony_ci} 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_cifunction test_simple_error_cb_with_null_options(realpath, realpathSync, cb) { 931cb0ef41Sopenharmony_ci realpath('/this/path/does/not/exist', null, common.mustCall(function(err, s) { 941cb0ef41Sopenharmony_ci assert(err); 951cb0ef41Sopenharmony_ci assert(!s); 961cb0ef41Sopenharmony_ci cb(); 971cb0ef41Sopenharmony_ci })); 981cb0ef41Sopenharmony_ci} 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_cifunction test_simple_relative_symlink(realpath, realpathSync, callback) { 1011cb0ef41Sopenharmony_ci console.log('test_simple_relative_symlink'); 1021cb0ef41Sopenharmony_ci if (skipSymlinks) { 1031cb0ef41Sopenharmony_ci common.printSkipMessage('symlink test (no privs)'); 1041cb0ef41Sopenharmony_ci return callback(); 1051cb0ef41Sopenharmony_ci } 1061cb0ef41Sopenharmony_ci const entry = `${tmpDir}/symlink`; 1071cb0ef41Sopenharmony_ci const expected = `${tmpDir}/cycles/root.js`; 1081cb0ef41Sopenharmony_ci [ 1091cb0ef41Sopenharmony_ci [entry, `../${path.basename(tmpDir)}/cycles/root.js`], 1101cb0ef41Sopenharmony_ci ].forEach(function(t) { 1111cb0ef41Sopenharmony_ci try { fs.unlinkSync(t[0]); } catch { 1121cb0ef41Sopenharmony_ci // Continue regardless of error. 1131cb0ef41Sopenharmony_ci } 1141cb0ef41Sopenharmony_ci console.log('fs.symlinkSync(%j, %j, %j)', t[1], t[0], 'file'); 1151cb0ef41Sopenharmony_ci fs.symlinkSync(t[1], t[0], 'file'); 1161cb0ef41Sopenharmony_ci unlink.push(t[0]); 1171cb0ef41Sopenharmony_ci }); 1181cb0ef41Sopenharmony_ci const result = realpathSync(entry); 1191cb0ef41Sopenharmony_ci assertEqualPath(result, path.resolve(expected)); 1201cb0ef41Sopenharmony_ci asynctest(realpath, [entry], callback, function(err, result) { 1211cb0ef41Sopenharmony_ci assertEqualPath(result, path.resolve(expected)); 1221cb0ef41Sopenharmony_ci }); 1231cb0ef41Sopenharmony_ci} 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_cifunction test_simple_absolute_symlink(realpath, realpathSync, callback) { 1261cb0ef41Sopenharmony_ci console.log('test_simple_absolute_symlink'); 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_ci // This one should still run, even if skipSymlinks is set, 1291cb0ef41Sopenharmony_ci // because it uses a junction. 1301cb0ef41Sopenharmony_ci const type = skipSymlinks ? 'junction' : 'dir'; 1311cb0ef41Sopenharmony_ci 1321cb0ef41Sopenharmony_ci console.log('using type=%s', type); 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ci const entry = `${tmpAbsDir}/symlink`; 1351cb0ef41Sopenharmony_ci const expected = fixtures.path('nested-index', 'one'); 1361cb0ef41Sopenharmony_ci [ 1371cb0ef41Sopenharmony_ci [entry, expected], 1381cb0ef41Sopenharmony_ci ].forEach(function(t) { 1391cb0ef41Sopenharmony_ci try { fs.unlinkSync(t[0]); } catch { 1401cb0ef41Sopenharmony_ci // Continue regardless of error. 1411cb0ef41Sopenharmony_ci } 1421cb0ef41Sopenharmony_ci console.error('fs.symlinkSync(%j, %j, %j)', t[1], t[0], type); 1431cb0ef41Sopenharmony_ci fs.symlinkSync(t[1], t[0], type); 1441cb0ef41Sopenharmony_ci unlink.push(t[0]); 1451cb0ef41Sopenharmony_ci }); 1461cb0ef41Sopenharmony_ci const result = realpathSync(entry); 1471cb0ef41Sopenharmony_ci assertEqualPath(result, path.resolve(expected)); 1481cb0ef41Sopenharmony_ci asynctest(realpath, [entry], callback, function(err, result) { 1491cb0ef41Sopenharmony_ci assertEqualPath(result, path.resolve(expected)); 1501cb0ef41Sopenharmony_ci }); 1511cb0ef41Sopenharmony_ci} 1521cb0ef41Sopenharmony_ci 1531cb0ef41Sopenharmony_cifunction test_deep_relative_file_symlink(realpath, realpathSync, callback) { 1541cb0ef41Sopenharmony_ci console.log('test_deep_relative_file_symlink'); 1551cb0ef41Sopenharmony_ci if (skipSymlinks) { 1561cb0ef41Sopenharmony_ci common.printSkipMessage('symlink test (no privs)'); 1571cb0ef41Sopenharmony_ci return callback(); 1581cb0ef41Sopenharmony_ci } 1591cb0ef41Sopenharmony_ci 1601cb0ef41Sopenharmony_ci const expected = fixtures.path('cycles', 'root.js'); 1611cb0ef41Sopenharmony_ci const linkData1 = path 1621cb0ef41Sopenharmony_ci .relative(path.join(targetsAbsDir, 'nested-index', 'one'), 1631cb0ef41Sopenharmony_ci expected); 1641cb0ef41Sopenharmony_ci const linkPath1 = path.join(targetsAbsDir, 1651cb0ef41Sopenharmony_ci 'nested-index', 'one', 'symlink1.js'); 1661cb0ef41Sopenharmony_ci try { fs.unlinkSync(linkPath1); } catch { 1671cb0ef41Sopenharmony_ci // Continue regardless of error. 1681cb0ef41Sopenharmony_ci } 1691cb0ef41Sopenharmony_ci fs.symlinkSync(linkData1, linkPath1, 'file'); 1701cb0ef41Sopenharmony_ci 1711cb0ef41Sopenharmony_ci const linkData2 = '../one/symlink1.js'; 1721cb0ef41Sopenharmony_ci const entry = path.join(targetsAbsDir, 1731cb0ef41Sopenharmony_ci 'nested-index', 'two', 'symlink1-b.js'); 1741cb0ef41Sopenharmony_ci try { fs.unlinkSync(entry); } catch { 1751cb0ef41Sopenharmony_ci // Continue regardless of error. 1761cb0ef41Sopenharmony_ci } 1771cb0ef41Sopenharmony_ci fs.symlinkSync(linkData2, entry, 'file'); 1781cb0ef41Sopenharmony_ci unlink.push(linkPath1); 1791cb0ef41Sopenharmony_ci unlink.push(entry); 1801cb0ef41Sopenharmony_ci 1811cb0ef41Sopenharmony_ci assertEqualPath(realpathSync(entry), path.resolve(expected)); 1821cb0ef41Sopenharmony_ci asynctest(realpath, [entry], callback, function(err, result) { 1831cb0ef41Sopenharmony_ci assertEqualPath(result, path.resolve(expected)); 1841cb0ef41Sopenharmony_ci }); 1851cb0ef41Sopenharmony_ci} 1861cb0ef41Sopenharmony_ci 1871cb0ef41Sopenharmony_cifunction test_deep_relative_dir_symlink(realpath, realpathSync, callback) { 1881cb0ef41Sopenharmony_ci console.log('test_deep_relative_dir_symlink'); 1891cb0ef41Sopenharmony_ci if (skipSymlinks) { 1901cb0ef41Sopenharmony_ci common.printSkipMessage('symlink test (no privs)'); 1911cb0ef41Sopenharmony_ci return callback(); 1921cb0ef41Sopenharmony_ci } 1931cb0ef41Sopenharmony_ci const expected = fixtures.path('cycles', 'folder'); 1941cb0ef41Sopenharmony_ci const path1b = path.join(targetsAbsDir, 'nested-index', 'one'); 1951cb0ef41Sopenharmony_ci const linkPath1b = path.join(path1b, 'symlink1-dir'); 1961cb0ef41Sopenharmony_ci const linkData1b = path.relative(path1b, expected); 1971cb0ef41Sopenharmony_ci try { fs.unlinkSync(linkPath1b); } catch { 1981cb0ef41Sopenharmony_ci // Continue regardless of error. 1991cb0ef41Sopenharmony_ci } 2001cb0ef41Sopenharmony_ci fs.symlinkSync(linkData1b, linkPath1b, 'dir'); 2011cb0ef41Sopenharmony_ci 2021cb0ef41Sopenharmony_ci const linkData2b = '../one/symlink1-dir'; 2031cb0ef41Sopenharmony_ci const entry = path.join(targetsAbsDir, 2041cb0ef41Sopenharmony_ci 'nested-index', 'two', 'symlink12-dir'); 2051cb0ef41Sopenharmony_ci try { fs.unlinkSync(entry); } catch { 2061cb0ef41Sopenharmony_ci // Continue regardless of error. 2071cb0ef41Sopenharmony_ci } 2081cb0ef41Sopenharmony_ci fs.symlinkSync(linkData2b, entry, 'dir'); 2091cb0ef41Sopenharmony_ci unlink.push(linkPath1b); 2101cb0ef41Sopenharmony_ci unlink.push(entry); 2111cb0ef41Sopenharmony_ci 2121cb0ef41Sopenharmony_ci assertEqualPath(realpathSync(entry), path.resolve(expected)); 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_ci asynctest(realpath, [entry], callback, function(err, result) { 2151cb0ef41Sopenharmony_ci assertEqualPath(result, path.resolve(expected)); 2161cb0ef41Sopenharmony_ci }); 2171cb0ef41Sopenharmony_ci} 2181cb0ef41Sopenharmony_ci 2191cb0ef41Sopenharmony_cifunction test_cyclic_link_protection(realpath, realpathSync, callback) { 2201cb0ef41Sopenharmony_ci console.log('test_cyclic_link_protection'); 2211cb0ef41Sopenharmony_ci if (skipSymlinks) { 2221cb0ef41Sopenharmony_ci common.printSkipMessage('symlink test (no privs)'); 2231cb0ef41Sopenharmony_ci return callback(); 2241cb0ef41Sopenharmony_ci } 2251cb0ef41Sopenharmony_ci const entry = path.join(tmpDir, '/cycles/realpath-3a'); 2261cb0ef41Sopenharmony_ci [ 2271cb0ef41Sopenharmony_ci [entry, '../cycles/realpath-3b'], 2281cb0ef41Sopenharmony_ci [path.join(tmpDir, '/cycles/realpath-3b'), '../cycles/realpath-3c'], 2291cb0ef41Sopenharmony_ci [path.join(tmpDir, '/cycles/realpath-3c'), '../cycles/realpath-3a'], 2301cb0ef41Sopenharmony_ci ].forEach(function(t) { 2311cb0ef41Sopenharmony_ci try { fs.unlinkSync(t[0]); } catch { 2321cb0ef41Sopenharmony_ci // Continue regardless of error. 2331cb0ef41Sopenharmony_ci } 2341cb0ef41Sopenharmony_ci fs.symlinkSync(t[1], t[0], 'dir'); 2351cb0ef41Sopenharmony_ci unlink.push(t[0]); 2361cb0ef41Sopenharmony_ci }); 2371cb0ef41Sopenharmony_ci assert.throws(() => { 2381cb0ef41Sopenharmony_ci realpathSync(entry); 2391cb0ef41Sopenharmony_ci }, { code: 'ELOOP', name: 'Error' }); 2401cb0ef41Sopenharmony_ci asynctest( 2411cb0ef41Sopenharmony_ci realpath, [entry], callback, common.mustCall(function(err, result) { 2421cb0ef41Sopenharmony_ci assert.strictEqual(err.path, entry); 2431cb0ef41Sopenharmony_ci assert.strictEqual(result, undefined); 2441cb0ef41Sopenharmony_ci return true; 2451cb0ef41Sopenharmony_ci })); 2461cb0ef41Sopenharmony_ci} 2471cb0ef41Sopenharmony_ci 2481cb0ef41Sopenharmony_cifunction test_cyclic_link_overprotection(realpath, realpathSync, callback) { 2491cb0ef41Sopenharmony_ci console.log('test_cyclic_link_overprotection'); 2501cb0ef41Sopenharmony_ci if (skipSymlinks) { 2511cb0ef41Sopenharmony_ci common.printSkipMessage('symlink test (no privs)'); 2521cb0ef41Sopenharmony_ci return callback(); 2531cb0ef41Sopenharmony_ci } 2541cb0ef41Sopenharmony_ci const cycles = `${tmpDir}/cycles`; 2551cb0ef41Sopenharmony_ci const expected = realpathSync(cycles); 2561cb0ef41Sopenharmony_ci const folder = `${cycles}/folder`; 2571cb0ef41Sopenharmony_ci const link = `${folder}/cycles`; 2581cb0ef41Sopenharmony_ci let testPath = cycles; 2591cb0ef41Sopenharmony_ci testPath += '/folder/cycles'.repeat(10); 2601cb0ef41Sopenharmony_ci try { fs.unlinkSync(link); } catch { 2611cb0ef41Sopenharmony_ci // Continue regardless of error. 2621cb0ef41Sopenharmony_ci } 2631cb0ef41Sopenharmony_ci fs.symlinkSync(cycles, link, 'dir'); 2641cb0ef41Sopenharmony_ci unlink.push(link); 2651cb0ef41Sopenharmony_ci assertEqualPath(realpathSync(testPath), path.resolve(expected)); 2661cb0ef41Sopenharmony_ci asynctest(realpath, [testPath], callback, function(er, res) { 2671cb0ef41Sopenharmony_ci assertEqualPath(res, path.resolve(expected)); 2681cb0ef41Sopenharmony_ci }); 2691cb0ef41Sopenharmony_ci} 2701cb0ef41Sopenharmony_ci 2711cb0ef41Sopenharmony_cifunction test_relative_input_cwd(realpath, realpathSync, callback) { 2721cb0ef41Sopenharmony_ci console.log('test_relative_input_cwd'); 2731cb0ef41Sopenharmony_ci if (skipSymlinks) { 2741cb0ef41Sopenharmony_ci common.printSkipMessage('symlink test (no privs)'); 2751cb0ef41Sopenharmony_ci return callback(); 2761cb0ef41Sopenharmony_ci } 2771cb0ef41Sopenharmony_ci 2781cb0ef41Sopenharmony_ci // We need to calculate the relative path to the tmp dir from cwd 2791cb0ef41Sopenharmony_ci const entrydir = process.cwd(); 2801cb0ef41Sopenharmony_ci const entry = path.relative(entrydir, 2811cb0ef41Sopenharmony_ci path.join(`${tmpDir}/cycles/realpath-3a`)); 2821cb0ef41Sopenharmony_ci const expected = `${tmpDir}/cycles/root.js`; 2831cb0ef41Sopenharmony_ci [ 2841cb0ef41Sopenharmony_ci [entry, '../cycles/realpath-3b'], 2851cb0ef41Sopenharmony_ci [`${tmpDir}/cycles/realpath-3b`, '../cycles/realpath-3c'], 2861cb0ef41Sopenharmony_ci [`${tmpDir}/cycles/realpath-3c`, 'root.js'], 2871cb0ef41Sopenharmony_ci ].forEach(function(t) { 2881cb0ef41Sopenharmony_ci const fn = t[0]; 2891cb0ef41Sopenharmony_ci console.error('fn=%j', fn); 2901cb0ef41Sopenharmony_ci try { fs.unlinkSync(fn); } catch { 2911cb0ef41Sopenharmony_ci // Continue regardless of error. 2921cb0ef41Sopenharmony_ci } 2931cb0ef41Sopenharmony_ci const b = path.basename(t[1]); 2941cb0ef41Sopenharmony_ci const type = (b === 'root.js' ? 'file' : 'dir'); 2951cb0ef41Sopenharmony_ci console.log('fs.symlinkSync(%j, %j, %j)', t[1], fn, type); 2961cb0ef41Sopenharmony_ci fs.symlinkSync(t[1], fn, 'file'); 2971cb0ef41Sopenharmony_ci unlink.push(fn); 2981cb0ef41Sopenharmony_ci }); 2991cb0ef41Sopenharmony_ci 3001cb0ef41Sopenharmony_ci const origcwd = process.cwd(); 3011cb0ef41Sopenharmony_ci process.chdir(entrydir); 3021cb0ef41Sopenharmony_ci assertEqualPath(realpathSync(entry), path.resolve(expected)); 3031cb0ef41Sopenharmony_ci asynctest(realpath, [entry], callback, function(err, result) { 3041cb0ef41Sopenharmony_ci process.chdir(origcwd); 3051cb0ef41Sopenharmony_ci assertEqualPath(result, path.resolve(expected)); 3061cb0ef41Sopenharmony_ci return true; 3071cb0ef41Sopenharmony_ci }); 3081cb0ef41Sopenharmony_ci} 3091cb0ef41Sopenharmony_ci 3101cb0ef41Sopenharmony_cifunction test_deep_symlink_mix(realpath, realpathSync, callback) { 3111cb0ef41Sopenharmony_ci console.log('test_deep_symlink_mix'); 3121cb0ef41Sopenharmony_ci if (common.isWindows) { 3131cb0ef41Sopenharmony_ci // This one is a mix of files and directories, and it's quite tricky 3141cb0ef41Sopenharmony_ci // to get the file/dir links sorted out correctly. 3151cb0ef41Sopenharmony_ci common.printSkipMessage('symlink test (no privs)'); 3161cb0ef41Sopenharmony_ci return callback(); 3171cb0ef41Sopenharmony_ci } 3181cb0ef41Sopenharmony_ci 3191cb0ef41Sopenharmony_ci // /tmp/node-test-realpath-f1 -> $tmpDir/node-test-realpath-d1/foo 3201cb0ef41Sopenharmony_ci // /tmp/node-test-realpath-d1 -> $tmpDir/node-test-realpath-d2 3211cb0ef41Sopenharmony_ci // /tmp/node-test-realpath-d2/foo -> $tmpDir/node-test-realpath-f2 3221cb0ef41Sopenharmony_ci // /tmp/node-test-realpath-f2 3231cb0ef41Sopenharmony_ci // -> $tmpDir/targets/nested-index/one/realpath-c 3241cb0ef41Sopenharmony_ci // $tmpDir/targets/nested-index/one/realpath-c 3251cb0ef41Sopenharmony_ci // -> $tmpDir/targets/nested-index/two/realpath-c 3261cb0ef41Sopenharmony_ci // $tmpDir/targets/nested-index/two/realpath-c -> $tmpDir/cycles/root.js 3271cb0ef41Sopenharmony_ci // $tmpDir/targets/cycles/root.js (hard) 3281cb0ef41Sopenharmony_ci 3291cb0ef41Sopenharmony_ci const entry = tmp('node-test-realpath-f1'); 3301cb0ef41Sopenharmony_ci try { fs.unlinkSync(tmp('node-test-realpath-d2/foo')); } catch { 3311cb0ef41Sopenharmony_ci // Continue regardless of error. 3321cb0ef41Sopenharmony_ci } 3331cb0ef41Sopenharmony_ci try { fs.rmdirSync(tmp('node-test-realpath-d2')); } catch { 3341cb0ef41Sopenharmony_ci // Continue regardless of error. 3351cb0ef41Sopenharmony_ci } 3361cb0ef41Sopenharmony_ci fs.mkdirSync(tmp('node-test-realpath-d2'), 0o700); 3371cb0ef41Sopenharmony_ci try { 3381cb0ef41Sopenharmony_ci [ 3391cb0ef41Sopenharmony_ci [entry, `${tmpDir}/node-test-realpath-d1/foo`], 3401cb0ef41Sopenharmony_ci [tmp('node-test-realpath-d1'), 3411cb0ef41Sopenharmony_ci `${tmpDir}/node-test-realpath-d2`], 3421cb0ef41Sopenharmony_ci [tmp('node-test-realpath-d2/foo'), '../node-test-realpath-f2'], 3431cb0ef41Sopenharmony_ci [tmp('node-test-realpath-f2'), 3441cb0ef41Sopenharmony_ci `${targetsAbsDir}/nested-index/one/realpath-c`], 3451cb0ef41Sopenharmony_ci [`${targetsAbsDir}/nested-index/one/realpath-c`, 3461cb0ef41Sopenharmony_ci `${targetsAbsDir}/nested-index/two/realpath-c`], 3471cb0ef41Sopenharmony_ci [`${targetsAbsDir}/nested-index/two/realpath-c`, 3481cb0ef41Sopenharmony_ci `${tmpDir}/cycles/root.js`], 3491cb0ef41Sopenharmony_ci ].forEach(function(t) { 3501cb0ef41Sopenharmony_ci try { fs.unlinkSync(t[0]); } catch { 3511cb0ef41Sopenharmony_ci // Continue regardless of error. 3521cb0ef41Sopenharmony_ci } 3531cb0ef41Sopenharmony_ci fs.symlinkSync(t[1], t[0]); 3541cb0ef41Sopenharmony_ci unlink.push(t[0]); 3551cb0ef41Sopenharmony_ci }); 3561cb0ef41Sopenharmony_ci } finally { 3571cb0ef41Sopenharmony_ci unlink.push(tmp('node-test-realpath-d2')); 3581cb0ef41Sopenharmony_ci } 3591cb0ef41Sopenharmony_ci const expected = `${tmpAbsDir}/cycles/root.js`; 3601cb0ef41Sopenharmony_ci assertEqualPath(realpathSync(entry), path.resolve(expected)); 3611cb0ef41Sopenharmony_ci asynctest(realpath, [entry], callback, function(err, result) { 3621cb0ef41Sopenharmony_ci assertEqualPath(result, path.resolve(expected)); 3631cb0ef41Sopenharmony_ci return true; 3641cb0ef41Sopenharmony_ci }); 3651cb0ef41Sopenharmony_ci} 3661cb0ef41Sopenharmony_ci 3671cb0ef41Sopenharmony_cifunction test_non_symlinks(realpath, realpathSync, callback) { 3681cb0ef41Sopenharmony_ci console.log('test_non_symlinks'); 3691cb0ef41Sopenharmony_ci const entrydir = path.dirname(tmpAbsDir); 3701cb0ef41Sopenharmony_ci const entry = `${tmpAbsDir.substr(entrydir.length + 1)}/cycles/root.js`; 3711cb0ef41Sopenharmony_ci const expected = `${tmpAbsDir}/cycles/root.js`; 3721cb0ef41Sopenharmony_ci const origcwd = process.cwd(); 3731cb0ef41Sopenharmony_ci process.chdir(entrydir); 3741cb0ef41Sopenharmony_ci assertEqualPath(realpathSync(entry), path.resolve(expected)); 3751cb0ef41Sopenharmony_ci asynctest(realpath, [entry], callback, function(err, result) { 3761cb0ef41Sopenharmony_ci process.chdir(origcwd); 3771cb0ef41Sopenharmony_ci assertEqualPath(result, path.resolve(expected)); 3781cb0ef41Sopenharmony_ci return true; 3791cb0ef41Sopenharmony_ci }); 3801cb0ef41Sopenharmony_ci} 3811cb0ef41Sopenharmony_ci 3821cb0ef41Sopenharmony_ciconst upone = path.join(process.cwd(), '..'); 3831cb0ef41Sopenharmony_cifunction test_escape_cwd(realpath, realpathSync, cb) { 3841cb0ef41Sopenharmony_ci console.log('test_escape_cwd'); 3851cb0ef41Sopenharmony_ci asynctest(realpath, ['..'], cb, function(er, uponeActual) { 3861cb0ef41Sopenharmony_ci assertEqualPath( 3871cb0ef41Sopenharmony_ci upone, uponeActual, 3881cb0ef41Sopenharmony_ci `realpath("..") expected: ${path.resolve(upone)} actual:${uponeActual}`); 3891cb0ef41Sopenharmony_ci }); 3901cb0ef41Sopenharmony_ci} 3911cb0ef41Sopenharmony_ci 3921cb0ef41Sopenharmony_cifunction test_upone_actual(realpath, realpathSync, cb) { 3931cb0ef41Sopenharmony_ci console.log('test_upone_actual'); 3941cb0ef41Sopenharmony_ci const uponeActual = realpathSync('..'); 3951cb0ef41Sopenharmony_ci assertEqualPath(upone, uponeActual); 3961cb0ef41Sopenharmony_ci cb(); 3971cb0ef41Sopenharmony_ci} 3981cb0ef41Sopenharmony_ci 3991cb0ef41Sopenharmony_ci// Going up with .. multiple times 4001cb0ef41Sopenharmony_ci// . 4011cb0ef41Sopenharmony_ci// `-- a/ 4021cb0ef41Sopenharmony_ci// |-- b/ 4031cb0ef41Sopenharmony_ci// | `-- e -> .. 4041cb0ef41Sopenharmony_ci// `-- d -> .. 4051cb0ef41Sopenharmony_ci// realpath(a/b/e/d/a/b/e/d/a) ==> a 4061cb0ef41Sopenharmony_cifunction test_up_multiple(realpath, realpathSync, cb) { 4071cb0ef41Sopenharmony_ci console.error('test_up_multiple'); 4081cb0ef41Sopenharmony_ci if (skipSymlinks) { 4091cb0ef41Sopenharmony_ci common.printSkipMessage('symlink test (no privs)'); 4101cb0ef41Sopenharmony_ci return cb(); 4111cb0ef41Sopenharmony_ci } 4121cb0ef41Sopenharmony_ci const tmpdir = require('../common/tmpdir'); 4131cb0ef41Sopenharmony_ci tmpdir.refresh(); 4141cb0ef41Sopenharmony_ci fs.mkdirSync(tmp('a'), 0o755); 4151cb0ef41Sopenharmony_ci fs.mkdirSync(tmp('a/b'), 0o755); 4161cb0ef41Sopenharmony_ci fs.symlinkSync('..', tmp('a/d'), 'dir'); 4171cb0ef41Sopenharmony_ci unlink.push(tmp('a/d')); 4181cb0ef41Sopenharmony_ci fs.symlinkSync('..', tmp('a/b/e'), 'dir'); 4191cb0ef41Sopenharmony_ci unlink.push(tmp('a/b/e')); 4201cb0ef41Sopenharmony_ci 4211cb0ef41Sopenharmony_ci const abedabed = tmp('abedabed'.split('').join('/')); 4221cb0ef41Sopenharmony_ci const abedabed_real = tmp(''); 4231cb0ef41Sopenharmony_ci 4241cb0ef41Sopenharmony_ci const abedabeda = tmp('abedabeda'.split('').join('/')); 4251cb0ef41Sopenharmony_ci const abedabeda_real = tmp('a'); 4261cb0ef41Sopenharmony_ci 4271cb0ef41Sopenharmony_ci assertEqualPath(realpathSync(abedabeda), abedabeda_real); 4281cb0ef41Sopenharmony_ci assertEqualPath(realpathSync(abedabed), abedabed_real); 4291cb0ef41Sopenharmony_ci 4301cb0ef41Sopenharmony_ci realpath(abedabeda, function(er, real) { 4311cb0ef41Sopenharmony_ci assert.ifError(er); 4321cb0ef41Sopenharmony_ci assertEqualPath(abedabeda_real, real); 4331cb0ef41Sopenharmony_ci realpath(abedabed, function(er, real) { 4341cb0ef41Sopenharmony_ci assert.ifError(er); 4351cb0ef41Sopenharmony_ci assertEqualPath(abedabed_real, real); 4361cb0ef41Sopenharmony_ci cb(); 4371cb0ef41Sopenharmony_ci }); 4381cb0ef41Sopenharmony_ci }); 4391cb0ef41Sopenharmony_ci} 4401cb0ef41Sopenharmony_ci 4411cb0ef41Sopenharmony_ci 4421cb0ef41Sopenharmony_ci// Going up with .. multiple times with options = null 4431cb0ef41Sopenharmony_ci// . 4441cb0ef41Sopenharmony_ci// `-- a/ 4451cb0ef41Sopenharmony_ci// |-- b/ 4461cb0ef41Sopenharmony_ci// | `-- e -> .. 4471cb0ef41Sopenharmony_ci// `-- d -> .. 4481cb0ef41Sopenharmony_ci// realpath(a/b/e/d/a/b/e/d/a) ==> a 4491cb0ef41Sopenharmony_cifunction test_up_multiple_with_null_options(realpath, realpathSync, cb) { 4501cb0ef41Sopenharmony_ci console.error('test_up_multiple'); 4511cb0ef41Sopenharmony_ci if (skipSymlinks) { 4521cb0ef41Sopenharmony_ci common.printSkipMessage('symlink test (no privs)'); 4531cb0ef41Sopenharmony_ci return cb(); 4541cb0ef41Sopenharmony_ci } 4551cb0ef41Sopenharmony_ci const tmpdir = require('../common/tmpdir'); 4561cb0ef41Sopenharmony_ci tmpdir.refresh(); 4571cb0ef41Sopenharmony_ci fs.mkdirSync(tmp('a'), 0o755); 4581cb0ef41Sopenharmony_ci fs.mkdirSync(tmp('a/b'), 0o755); 4591cb0ef41Sopenharmony_ci fs.symlinkSync('..', tmp('a/d'), 'dir'); 4601cb0ef41Sopenharmony_ci unlink.push(tmp('a/d')); 4611cb0ef41Sopenharmony_ci fs.symlinkSync('..', tmp('a/b/e'), 'dir'); 4621cb0ef41Sopenharmony_ci unlink.push(tmp('a/b/e')); 4631cb0ef41Sopenharmony_ci 4641cb0ef41Sopenharmony_ci const abedabed = tmp('abedabed'.split('').join('/')); 4651cb0ef41Sopenharmony_ci const abedabed_real = tmp(''); 4661cb0ef41Sopenharmony_ci 4671cb0ef41Sopenharmony_ci const abedabeda = tmp('abedabeda'.split('').join('/')); 4681cb0ef41Sopenharmony_ci const abedabeda_real = tmp('a'); 4691cb0ef41Sopenharmony_ci 4701cb0ef41Sopenharmony_ci assertEqualPath(realpathSync(abedabeda), abedabeda_real); 4711cb0ef41Sopenharmony_ci assertEqualPath(realpathSync(abedabed), abedabed_real); 4721cb0ef41Sopenharmony_ci 4731cb0ef41Sopenharmony_ci realpath(abedabeda, null, function(er, real) { 4741cb0ef41Sopenharmony_ci assert.ifError(er); 4751cb0ef41Sopenharmony_ci assertEqualPath(abedabeda_real, real); 4761cb0ef41Sopenharmony_ci realpath(abedabed, null, function(er, real) { 4771cb0ef41Sopenharmony_ci assert.ifError(er); 4781cb0ef41Sopenharmony_ci assertEqualPath(abedabed_real, real); 4791cb0ef41Sopenharmony_ci cb(); 4801cb0ef41Sopenharmony_ci }); 4811cb0ef41Sopenharmony_ci }); 4821cb0ef41Sopenharmony_ci} 4831cb0ef41Sopenharmony_ci 4841cb0ef41Sopenharmony_ci// Absolute symlinks with children. 4851cb0ef41Sopenharmony_ci// . 4861cb0ef41Sopenharmony_ci// `-- a/ 4871cb0ef41Sopenharmony_ci// |-- b/ 4881cb0ef41Sopenharmony_ci// | `-- c/ 4891cb0ef41Sopenharmony_ci// | `-- x.txt 4901cb0ef41Sopenharmony_ci// `-- link -> /tmp/node-test-realpath-abs-kids/a/b/ 4911cb0ef41Sopenharmony_ci// realpath(root+'/a/link/c/x.txt') ==> root+'/a/b/c/x.txt' 4921cb0ef41Sopenharmony_cifunction test_abs_with_kids(realpath, realpathSync, cb) { 4931cb0ef41Sopenharmony_ci console.log('test_abs_with_kids'); 4941cb0ef41Sopenharmony_ci 4951cb0ef41Sopenharmony_ci // This one should still run, even if skipSymlinks is set, 4961cb0ef41Sopenharmony_ci // because it uses a junction. 4971cb0ef41Sopenharmony_ci const type = skipSymlinks ? 'junction' : 'dir'; 4981cb0ef41Sopenharmony_ci 4991cb0ef41Sopenharmony_ci console.log('using type=%s', type); 5001cb0ef41Sopenharmony_ci 5011cb0ef41Sopenharmony_ci const root = `${tmpAbsDir}/node-test-realpath-abs-kids`; 5021cb0ef41Sopenharmony_ci function cleanup() { 5031cb0ef41Sopenharmony_ci ['/a/b/c/x.txt', 5041cb0ef41Sopenharmony_ci '/a/link', 5051cb0ef41Sopenharmony_ci ].forEach(function(file) { 5061cb0ef41Sopenharmony_ci try { fs.unlinkSync(root + file); } catch { 5071cb0ef41Sopenharmony_ci // Continue regardless of error. 5081cb0ef41Sopenharmony_ci } 5091cb0ef41Sopenharmony_ci }); 5101cb0ef41Sopenharmony_ci ['/a/b/c', 5111cb0ef41Sopenharmony_ci '/a/b', 5121cb0ef41Sopenharmony_ci '/a', 5131cb0ef41Sopenharmony_ci '', 5141cb0ef41Sopenharmony_ci ].forEach(function(folder) { 5151cb0ef41Sopenharmony_ci try { fs.rmdirSync(root + folder); } catch { 5161cb0ef41Sopenharmony_ci // Continue regardless of error. 5171cb0ef41Sopenharmony_ci } 5181cb0ef41Sopenharmony_ci }); 5191cb0ef41Sopenharmony_ci } 5201cb0ef41Sopenharmony_ci 5211cb0ef41Sopenharmony_ci function setup() { 5221cb0ef41Sopenharmony_ci cleanup(); 5231cb0ef41Sopenharmony_ci ['', 5241cb0ef41Sopenharmony_ci '/a', 5251cb0ef41Sopenharmony_ci '/a/b', 5261cb0ef41Sopenharmony_ci '/a/b/c', 5271cb0ef41Sopenharmony_ci ].forEach(function(folder) { 5281cb0ef41Sopenharmony_ci console.log(`mkdir ${root}${folder}`); 5291cb0ef41Sopenharmony_ci fs.mkdirSync(root + folder, 0o700); 5301cb0ef41Sopenharmony_ci }); 5311cb0ef41Sopenharmony_ci fs.writeFileSync(`${root}/a/b/c/x.txt`, 'foo'); 5321cb0ef41Sopenharmony_ci fs.symlinkSync(`${root}/a/b`, `${root}/a/link`, type); 5331cb0ef41Sopenharmony_ci } 5341cb0ef41Sopenharmony_ci setup(); 5351cb0ef41Sopenharmony_ci const linkPath = `${root}/a/link/c/x.txt`; 5361cb0ef41Sopenharmony_ci const expectPath = `${root}/a/b/c/x.txt`; 5371cb0ef41Sopenharmony_ci const actual = realpathSync(linkPath); 5381cb0ef41Sopenharmony_ci // console.log({link:linkPath,expect:expectPath,actual:actual},'sync'); 5391cb0ef41Sopenharmony_ci assertEqualPath(actual, path.resolve(expectPath)); 5401cb0ef41Sopenharmony_ci asynctest(realpath, [linkPath], cb, function(er, actual) { 5411cb0ef41Sopenharmony_ci // console.log({link:linkPath,expect:expectPath,actual:actual},'async'); 5421cb0ef41Sopenharmony_ci assertEqualPath(actual, path.resolve(expectPath)); 5431cb0ef41Sopenharmony_ci cleanup(); 5441cb0ef41Sopenharmony_ci }); 5451cb0ef41Sopenharmony_ci} 5461cb0ef41Sopenharmony_ci 5471cb0ef41Sopenharmony_cifunction test_root(realpath, realpathSync, cb) { 5481cb0ef41Sopenharmony_ci assertEqualPath(root, realpathSync('/')); 5491cb0ef41Sopenharmony_ci realpath('/', function(err, result) { 5501cb0ef41Sopenharmony_ci assert.ifError(err); 5511cb0ef41Sopenharmony_ci assertEqualPath(root, result); 5521cb0ef41Sopenharmony_ci cb(); 5531cb0ef41Sopenharmony_ci }); 5541cb0ef41Sopenharmony_ci} 5551cb0ef41Sopenharmony_ci 5561cb0ef41Sopenharmony_cifunction test_root_with_null_options(realpath, realpathSync, cb) { 5571cb0ef41Sopenharmony_ci realpath('/', null, function(err, result) { 5581cb0ef41Sopenharmony_ci assert.ifError(err); 5591cb0ef41Sopenharmony_ci assertEqualPath(root, result); 5601cb0ef41Sopenharmony_ci cb(); 5611cb0ef41Sopenharmony_ci }); 5621cb0ef41Sopenharmony_ci} 5631cb0ef41Sopenharmony_ci 5641cb0ef41Sopenharmony_ci// ---------------------------------------------------------------------------- 5651cb0ef41Sopenharmony_ci 5661cb0ef41Sopenharmony_ciconst tests = [ 5671cb0ef41Sopenharmony_ci test_simple_error_callback, 5681cb0ef41Sopenharmony_ci test_simple_error_cb_with_null_options, 5691cb0ef41Sopenharmony_ci test_simple_relative_symlink, 5701cb0ef41Sopenharmony_ci test_simple_absolute_symlink, 5711cb0ef41Sopenharmony_ci test_deep_relative_file_symlink, 5721cb0ef41Sopenharmony_ci test_deep_relative_dir_symlink, 5731cb0ef41Sopenharmony_ci test_cyclic_link_protection, 5741cb0ef41Sopenharmony_ci test_cyclic_link_overprotection, 5751cb0ef41Sopenharmony_ci test_relative_input_cwd, 5761cb0ef41Sopenharmony_ci test_deep_symlink_mix, 5771cb0ef41Sopenharmony_ci test_non_symlinks, 5781cb0ef41Sopenharmony_ci test_escape_cwd, 5791cb0ef41Sopenharmony_ci test_upone_actual, 5801cb0ef41Sopenharmony_ci test_abs_with_kids, 5811cb0ef41Sopenharmony_ci test_up_multiple, 5821cb0ef41Sopenharmony_ci test_up_multiple_with_null_options, 5831cb0ef41Sopenharmony_ci test_root, 5841cb0ef41Sopenharmony_ci test_root_with_null_options, 5851cb0ef41Sopenharmony_ci]; 5861cb0ef41Sopenharmony_ciconst numtests = tests.length; 5871cb0ef41Sopenharmony_cilet testsRun = 0; 5881cb0ef41Sopenharmony_cifunction runNextTest(err) { 5891cb0ef41Sopenharmony_ci assert.ifError(err); 5901cb0ef41Sopenharmony_ci const test = tests.shift(); 5911cb0ef41Sopenharmony_ci if (!test) { 5921cb0ef41Sopenharmony_ci return console.log(`${numtests} subtests completed OK for fs.realpath`); 5931cb0ef41Sopenharmony_ci } 5941cb0ef41Sopenharmony_ci testsRun++; 5951cb0ef41Sopenharmony_ci test(fs.realpath, fs.realpathSync, common.mustSucceed(() => { 5961cb0ef41Sopenharmony_ci testsRun++; 5971cb0ef41Sopenharmony_ci test(fs.realpath.native, 5981cb0ef41Sopenharmony_ci fs.realpathSync.native, 5991cb0ef41Sopenharmony_ci common.mustCall(runNextTest)); 6001cb0ef41Sopenharmony_ci })); 6011cb0ef41Sopenharmony_ci} 6021cb0ef41Sopenharmony_ci 6031cb0ef41Sopenharmony_cifunction runTest() { 6041cb0ef41Sopenharmony_ci const tmpDirs = ['cycles', 'cycles/folder']; 6051cb0ef41Sopenharmony_ci tmpDirs.forEach(function(t) { 6061cb0ef41Sopenharmony_ci t = tmp(t); 6071cb0ef41Sopenharmony_ci fs.mkdirSync(t, 0o700); 6081cb0ef41Sopenharmony_ci }); 6091cb0ef41Sopenharmony_ci fs.writeFileSync(tmp('cycles/root.js'), "console.error('roooot!');"); 6101cb0ef41Sopenharmony_ci console.error('start tests'); 6111cb0ef41Sopenharmony_ci runNextTest(); 6121cb0ef41Sopenharmony_ci} 6131cb0ef41Sopenharmony_ci 6141cb0ef41Sopenharmony_ci 6151cb0ef41Sopenharmony_ciprocess.on('exit', function() { 6161cb0ef41Sopenharmony_ci assert.strictEqual(2 * numtests, testsRun); 6171cb0ef41Sopenharmony_ci assert.strictEqual(async_completed, async_expected); 6181cb0ef41Sopenharmony_ci}); 619