Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // (node) realpath in JS (version 2) -- this is a unit test (put in node/test/simple)
- process.mixin(require("../common"));
- var normalize = path.normalize
- normalizeArray = path.normalizeArray;
- function D(msg, x) {
- if (x === undefined) { p(msg); }
- else { error(String(msg)+' '+inspect(x)); }
- }
- fs.realpathSync = function (path) {
- var seen_links = {}, knownHards = {}, buf, i = 0, part, x, stats;
- if (path.charAt(0) !== '/') {
- var cwd = process.cwd().split('/');
- path = cwd.concat(path.split('/'));
- path = normalizeArray(path);
- i = cwd.length;
- buf = [].concat(cwd);
- } else {
- path = normalizeArray(path.split('/'));
- buf = [''];
- }
- D('-->', path.join('/'));
- for (; i<path.length; i++) {
- part = path.slice(0, i+1).join('/'); D('part --> '+ part);
- if (part.length !== 0) {
- var knownHard = (part in knownHards);
- if (knownHard) {
- buf.push(path[i]);
- }
- else {
- stats = fs.lstatSync(part); D('stat', part);
- if (stats.isSymbolicLink()) {
- x = stats.dev.toString(32)+":"+stats.ino.toString(32);
- if (x in seen_links)
- throw new Error("cyclic link at "+part);
- seen_links[x] = true;
- part = fs.readlinkSync(part); D(' resolved -->', part);
- if (part.charAt(0) === '/') {
- // absolute
- path = normalizeArray(part.split('/'));
- buf = [''];
- i = 0;
- }
- else {
- // relative
- Array.prototype.splice.apply(path, [i, 1].concat(part.split('/')));
- part = normalizeArray(path);
- D(' path A -->', path.join('/'));
- D(' path B -->', part.join('/'));
- var y = 0, L = Math.max(path.length, part.length), delta;
- for (; y<L && path[y] === part[y]; y++);
- if (y !== L) {
- path = part;
- delta = i-y;
- i = y-1; // resolve new node if needed
- if (delta > 0) buf.splice(y, delta);
- D(' delta -->', delta);
- }
- else {
- i--; // resolve new node if needed
- }
- }
- }
- else {
- D(' push -->', path[i]);
- buf.push(path[i]);
- D(' buf -->', buf.join('/'));
- knownHards[buf.join('/')] = true;
- }
- }
- }
- }
- buf = buf.join('/');
- if (!(buf in knownHards)) {
- D('buf not in knownHards | buf -->', buf);
- buf += '/' + path[i+1];
- }
- //buf = normalizeArray(buf).join('/');
- D('<-- ', buf);
- return buf;
- }
- fs.realpath = function (path, callback) {
- var seen_links = {}, knownHards = {}, buf = [''], i = 0, part, x;
- if (path.charAt(0) !== '/') {
- // assumes cwd is canonical
- var cwd = process.cwd().split('/');
- path = cwd.concat(path.split('/'));
- path = normalizeArray(path);
- i = cwd.length-1;
- buf = [].concat(cwd);
- }
- else {
- path = normalizeArray(path.split('/'));
- }
- D('-->', path.join('/'));
- function done(err) {
- if (!err) {
- buf = buf.join('/');
- if (!(buf in knownHards)) {
- D('buf not in knownHards | buf -->', buf);
- //buf += '/' + path[i+1];
- }
- //buf = normalizeArray(buf).join('/');
- D('<-- ', buf);
- }
- callback(err, buf);
- }
- function next() {
- if (++i === path.length)
- return done();
- part = path.slice(0, i+1).join('/'); D('part -->', part);
- if (part.length === 0)
- return next();
- var knownHard = (part in knownHards);
- if (knownHard) {
- buf.push(path[i]);
- next();
- }
- else {
- fs.lstat(part, function(err, stats){
- if (err) return done(err);
- if (stats.isSymbolicLink()) {
- x = stats.dev.toString(32)+":"+stats.ino.toString(32);
- if (x in seen_links)
- return done(new Error("cyclic link at "+part));
- seen_links[x] = true;
- fs.readlink(part, function(err, npart){ D(' resolved -->', part);
- if (err) return done(err);
- part = npart;
- if (part.charAt(0) === '/') {
- // absolute
- path = normalizeArray(part.split('/'));
- buf = [''];
- i = 0;
- }
- else {
- // relative
- Array.prototype.splice.apply(path, [i, 1].concat(part.split('/')));
- part = normalizeArray(path);
- D(' path A -->', path.join('/'));
- D(' path B -->', part.join('/'));
- var y = 0, L = Math.max(path.length, part.length), delta;
- for (; y<L && path[y] === part[y]; y++);
- if (y !== L) {
- path = part;
- delta = i-y;
- i = y-1; // resolve new node if needed
- if (delta > 0) buf.splice(y, delta);
- D(' delta -->', delta);
- }
- else {
- i--; // resolve new node if needed
- }
- }
- next();
- }); // fs.readlink
- }
- else {
- D(' push -->', path[i]);
- buf.push(path[i]);
- D(' buf -->', buf.join('/'));
- knownHards[buf.join('/')] = true;
- next();
- }
- }); // fs.lstat
- }
- }
- next();
- }
- // ----------------------------------------------------------------------------
- var async_completed = 0, async_expected = 0, unlink = [];
- function asynctest(testBlock, args, callback, assertBlock) {
- async_expected++;
- testBlock.apply(testBlock, args.concat([function(err){
- var ignoreError = false;
- if (assertBlock) {
- try {
- ignoreError = assertBlock.apply(assertBlock,
- Array.prototype.slice.call(arguments));
- }
- catch (e) {
- err = e;
- }
- }
- async_completed++;
- callback(ignoreError ? null : err);
- }]));
- }
- // sub-tests:
- function test_deep_relative_file_symlink(callback) {
- var expected = path.join(fixturesDir, 'cycles', 'root.js');
- var linkData1 = "../../cycles/root.js";
- var linkPath1 = path.join(fixturesDir, "nested-index", 'one', 'symlink1.js');
- try {fs.unlinkSync(linkPath1);}catch(e){}
- fs.symlinkSync(linkData1, linkPath1);
- var linkData2 = "../one/symlink1.js";
- var entry = path.join(fixturesDir, "nested-index", 'two', 'symlink1-b.js');
- try {fs.unlinkSync(entry);}catch(e){}
- fs.symlinkSync(linkData2, entry);
- unlink.push(linkPath1);
- unlink.push(entry);
- assert.equal(fs.realpathSync(entry), expected);
- asynctest(fs.realpath, [entry], callback, function(err, result){
- assert.equal(result, expected,
- 'got '+inspect(result)+' expected '+inspect(expected));
- });
- }
- function test_deep_relative_dir_symlink(callback) {
- var expected = path.join(fixturesDir, 'cycles', 'folder');
- var linkData1b = "../../cycles/folder";
- var linkPath1b = path.join(fixturesDir, "nested-index", 'one', 'symlink1-dir');
- try {fs.unlinkSync(linkPath1b);}catch(e){}
- fs.symlinkSync(linkData1b, linkPath1b);
- var linkData2b = "../one/symlink1-dir";
- var entry = path.join(fixturesDir, "nested-index", 'two', 'symlink12-dir');
- try {fs.unlinkSync(entry);}catch(e){}
- fs.symlinkSync(linkData2b, entry);
- unlink.push(linkPath1b);
- unlink.push(entry);
- assert.equal(fs.realpathSync(entry), expected);
- asynctest(fs.realpath, [entry], callback, function(err, result){
- assert.equal(result, expected,
- 'got '+inspect(result)+' expected '+inspect(expected));
- });
- }
- function test_cyclic_link_protection(callback) {
- var entry = fixturesDir+'/cycles/realpath-3a';
- [
- [entry, '../cycles/realpath-3b'],
- [fixturesDir+'/cycles/realpath-3b', '../cycles/realpath-3c'],
- [fixturesDir+'/cycles/realpath-3c', '../cycles/realpath-3a'],
- ].forEach(function(t) {
- try {fs.unlinkSync(t[0]);}catch(e){}
- fs.symlinkSync(t[1], t[0]);
- unlink.push(t[0]);
- });
- assert.throws(function(){ fs.realpathSync(entry); });
- asynctest(fs.realpath, [entry], callback, function(err, result){
- assert.ok(err && true);
- return true;
- });
- }
- // 4. relative input
- function test_relative_input_cwd(callback) {
- var p = fixturesDir.lastIndexOf('/');
- var entrydir = fixturesDir.substr(0, p);
- var entry = fixturesDir.substr(p+1)+'/cycles/realpath-3a';
- var expected = fixturesDir+'/cycles/root.js';
- [
- [entry, '../cycles/realpath-3b'],
- [fixturesDir+'/cycles/realpath-3b', '../cycles/realpath-3c'],
- [fixturesDir+'/cycles/realpath-3c', 'root.js'],
- ].forEach(function(t) {
- var fn = t[0];
- if (fn.charAt(0) !== '/') fn = entrydir + '/' + fn;
- try {fs.unlinkSync(fn);}catch(e){}
- fs.symlinkSync(t[1], fn);
- unlink.push(fn);
- });
- var origcwd = process.cwd();
- process.chdir(entrydir);
- assert.equal(fs.realpathSync(entry), expected);
- asynctest(fs.realpath, [entry], callback, function(err, result){
- process.chdir(origcwd);
- assert.equal(result, expected,
- 'got '+inspect(result)+' expected '+inspect(expected));
- return true;
- });
- }
- function test_deep_symlink_mix(callback) {
- // todo: check to see that fixturesDir is not rooted in the
- // same directory as our test symlink.
- // obtain our current realpath using bash (so we can test ourselves)
- exec("cd '"+fixturesDir.replace("'","\\'")+"' && pwd -P",
- function(err, stdout, stderr)
- {
- if (err) return callback(err);
- var fixturesAbsDir = stdout.trim();
- /*
- /tmp/node-test-realpath-f1 -> ../tmp/node-test-realpath-d1/foo
- /tmp/node-test-realpath-d1 -> ../node-test-realpath-d2
- /tmp/node-test-realpath-d2/foo -> ../node-test-realpath-f2
- /tmp/node-test-realpath-f2
- -> /node/test/fixtures/nested-index/one/realpath-c
- /node/test/fixtures/nested-index/one/realpath-c
- -> /node/test/fixtures/nested-index/two/realpath-c
- /node/test/fixtures/nested-index/two/realpath-c -> ../../cycles/root.js
- /node/test/fixtures/cycles/root.js (hard)
- */
- var entry = '/tmp/node-test-realpath-f1';
- try {fs.unlinkSync('/tmp/node-test-realpath-d2/foo');}catch(e){}
- try {fs.rmdirSync('/tmp/node-test-realpath-d2');}catch(e){}
- fs.mkdirSync('/tmp/node-test-realpath-d2', 0700);
- try {
- [
- [entry, '../tmp/node-test-realpath-d1/foo'],
- ['/tmp/node-test-realpath-d1', '../tmp/node-test-realpath-d2'],
- ['/tmp/node-test-realpath-d2/foo', '../node-test-realpath-f2'],
- ['/tmp/node-test-realpath-f2', fixturesAbsDir+'/nested-index/one/realpath-c'],
- [fixturesAbsDir+'/nested-index/one/realpath-c', fixturesAbsDir+'/nested-index/two/realpath-c'],
- [fixturesAbsDir+'/nested-index/two/realpath-c', '../../cycles/root.js'],
- ].forEach(function(t) {
- //debug('setting up '+t[0]+' -> '+t[1]);
- try {fs.unlinkSync(t[0]);}catch(e){}
- fs.symlinkSync(t[1], t[0]);
- unlink.push(t[0]);
- });
- } finally {
- unlink.push('/tmp/node-test-realpath-d2');
- }
- var expected = fixturesAbsDir+'/cycles/root.js';
- assert.equal(fs.realpathSync(entry), expected);
- asynctest(fs.realpath, [entry], callback, function(err, result){
- assert.equal(result, expected,
- 'got '+inspect(result)+' expected '+inspect(expected));
- return true;
- });
- });
- }
- // ----------------------------------------------------------------------------
- // todo: test shallow symlinks (file & dir)
- // todo: test non-symlinks (file & dir)
- // todo: test error on cyclic symlinks
- var tests = [
- test_deep_relative_file_symlink,
- test_deep_relative_dir_symlink,
- test_cyclic_link_protection,
- test_relative_input_cwd,
- test_deep_symlink_mix,
- ];
- var numtests = tests.length;
- function runNextTest(err) {
- if (err) throw err;
- var test = tests.shift()
- if (!test) puts(numtests+' subtests completed OK for fs.realpath');
- else test(runNextTest);
- }
- runNextTest();
- process.addListener("exit", function () {
- //unlink.forEach(function(path){ try {fs.unlinkSync(path);}catch(e){} });
- assert.equal(async_completed, async_expected);
- });
Add Comment
Please, Sign In to add comment