Guest User

Untitled

a guest
May 20th, 2018
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.70 KB | None | 0 0
  1. // (node) realpath in JS (version 2) -- this is a unit test (put in node/test/simple)
  2. process.mixin(require("../common"));
  3.  
  4. var normalize = path.normalize
  5. normalizeArray = path.normalizeArray;
  6.  
  7. function D(msg, x) {
  8. if (x === undefined) { p(msg); }
  9. else { error(String(msg)+' '+inspect(x)); }
  10. }
  11.  
  12. fs.realpathSync = function (path) {
  13. var seen_links = {}, knownHards = {}, buf, i = 0, part, x, stats;
  14. if (path.charAt(0) !== '/') {
  15. var cwd = process.cwd().split('/');
  16. path = cwd.concat(path.split('/'));
  17. path = normalizeArray(path);
  18. i = cwd.length;
  19. buf = [].concat(cwd);
  20. } else {
  21. path = normalizeArray(path.split('/'));
  22. buf = [''];
  23. }
  24. D('-->', path.join('/'));
  25.  
  26. for (; i<path.length; i++) {
  27. part = path.slice(0, i+1).join('/'); D('part --> '+ part);
  28. if (part.length !== 0) {
  29. var knownHard = (part in knownHards);
  30. if (knownHard) {
  31. buf.push(path[i]);
  32. }
  33. else {
  34. stats = fs.lstatSync(part); D('stat', part);
  35. if (stats.isSymbolicLink()) {
  36. x = stats.dev.toString(32)+":"+stats.ino.toString(32);
  37. if (x in seen_links)
  38. throw new Error("cyclic link at "+part);
  39. seen_links[x] = true;
  40. part = fs.readlinkSync(part); D(' resolved -->', part);
  41. if (part.charAt(0) === '/') {
  42. // absolute
  43. path = normalizeArray(part.split('/'));
  44. buf = [''];
  45. i = 0;
  46. }
  47. else {
  48. // relative
  49. Array.prototype.splice.apply(path, [i, 1].concat(part.split('/')));
  50. part = normalizeArray(path);
  51. D(' path A -->', path.join('/'));
  52. D(' path B -->', part.join('/'));
  53. var y = 0, L = Math.max(path.length, part.length), delta;
  54. for (; y<L && path[y] === part[y]; y++);
  55. if (y !== L) {
  56. path = part;
  57. delta = i-y;
  58. i = y-1; // resolve new node if needed
  59. if (delta > 0) buf.splice(y, delta);
  60. D(' delta -->', delta);
  61. }
  62. else {
  63. i--; // resolve new node if needed
  64. }
  65. }
  66. }
  67. else {
  68. D(' push -->', path[i]);
  69. buf.push(path[i]);
  70. D(' buf -->', buf.join('/'));
  71. knownHards[buf.join('/')] = true;
  72. }
  73. }
  74. }
  75. }
  76.  
  77. buf = buf.join('/');
  78. if (!(buf in knownHards)) {
  79. D('buf not in knownHards | buf -->', buf);
  80. buf += '/' + path[i+1];
  81. }
  82.  
  83. //buf = normalizeArray(buf).join('/');
  84. D('<-- ', buf);
  85. return buf;
  86. }
  87.  
  88.  
  89. fs.realpath = function (path, callback) {
  90. var seen_links = {}, knownHards = {}, buf = [''], i = 0, part, x;
  91. if (path.charAt(0) !== '/') {
  92. // assumes cwd is canonical
  93. var cwd = process.cwd().split('/');
  94. path = cwd.concat(path.split('/'));
  95. path = normalizeArray(path);
  96. i = cwd.length-1;
  97. buf = [].concat(cwd);
  98. }
  99. else {
  100. path = normalizeArray(path.split('/'));
  101. }
  102. D('-->', path.join('/'));
  103.  
  104. function done(err) {
  105. if (!err) {
  106. buf = buf.join('/');
  107. if (!(buf in knownHards)) {
  108. D('buf not in knownHards | buf -->', buf);
  109. //buf += '/' + path[i+1];
  110. }
  111. //buf = normalizeArray(buf).join('/');
  112. D('<-- ', buf);
  113. }
  114. callback(err, buf);
  115. }
  116.  
  117. function next() {
  118. if (++i === path.length)
  119. return done();
  120.  
  121. part = path.slice(0, i+1).join('/'); D('part -->', part);
  122. if (part.length === 0)
  123. return next();
  124. var knownHard = (part in knownHards);
  125. if (knownHard) {
  126. buf.push(path[i]);
  127. next();
  128. }
  129. else {
  130. fs.lstat(part, function(err, stats){
  131. if (err) return done(err);
  132. if (stats.isSymbolicLink()) {
  133. x = stats.dev.toString(32)+":"+stats.ino.toString(32);
  134. if (x in seen_links)
  135. return done(new Error("cyclic link at "+part));
  136. seen_links[x] = true;
  137. fs.readlink(part, function(err, npart){ D(' resolved -->', part);
  138. if (err) return done(err);
  139. part = npart;
  140. if (part.charAt(0) === '/') {
  141. // absolute
  142. path = normalizeArray(part.split('/'));
  143. buf = [''];
  144. i = 0;
  145. }
  146. else {
  147. // relative
  148. Array.prototype.splice.apply(path, [i, 1].concat(part.split('/')));
  149. part = normalizeArray(path);
  150. D(' path A -->', path.join('/'));
  151. D(' path B -->', part.join('/'));
  152. var y = 0, L = Math.max(path.length, part.length), delta;
  153. for (; y<L && path[y] === part[y]; y++);
  154. if (y !== L) {
  155. path = part;
  156. delta = i-y;
  157. i = y-1; // resolve new node if needed
  158. if (delta > 0) buf.splice(y, delta);
  159. D(' delta -->', delta);
  160. }
  161. else {
  162. i--; // resolve new node if needed
  163. }
  164. }
  165. next();
  166. }); // fs.readlink
  167. }
  168. else {
  169. D(' push -->', path[i]);
  170. buf.push(path[i]);
  171. D(' buf -->', buf.join('/'));
  172. knownHards[buf.join('/')] = true;
  173. next();
  174. }
  175. }); // fs.lstat
  176. }
  177. }
  178. next();
  179. }
  180.  
  181.  
  182. // ----------------------------------------------------------------------------
  183.  
  184. var async_completed = 0, async_expected = 0, unlink = [];
  185.  
  186. function asynctest(testBlock, args, callback, assertBlock) {
  187. async_expected++;
  188. testBlock.apply(testBlock, args.concat([function(err){
  189. var ignoreError = false;
  190. if (assertBlock) {
  191. try {
  192. ignoreError = assertBlock.apply(assertBlock,
  193. Array.prototype.slice.call(arguments));
  194. }
  195. catch (e) {
  196. err = e;
  197. }
  198. }
  199. async_completed++;
  200. callback(ignoreError ? null : err);
  201. }]));
  202. }
  203.  
  204. // sub-tests:
  205.  
  206. function test_deep_relative_file_symlink(callback) {
  207. var expected = path.join(fixturesDir, 'cycles', 'root.js');
  208. var linkData1 = "../../cycles/root.js";
  209. var linkPath1 = path.join(fixturesDir, "nested-index", 'one', 'symlink1.js');
  210. try {fs.unlinkSync(linkPath1);}catch(e){}
  211. fs.symlinkSync(linkData1, linkPath1);
  212.  
  213. var linkData2 = "../one/symlink1.js";
  214. var entry = path.join(fixturesDir, "nested-index", 'two', 'symlink1-b.js');
  215. try {fs.unlinkSync(entry);}catch(e){}
  216. fs.symlinkSync(linkData2, entry);
  217. unlink.push(linkPath1);
  218. unlink.push(entry);
  219.  
  220. assert.equal(fs.realpathSync(entry), expected);
  221. asynctest(fs.realpath, [entry], callback, function(err, result){
  222. assert.equal(result, expected,
  223. 'got '+inspect(result)+' expected '+inspect(expected));
  224. });
  225. }
  226.  
  227. function test_deep_relative_dir_symlink(callback) {
  228. var expected = path.join(fixturesDir, 'cycles', 'folder');
  229. var linkData1b = "../../cycles/folder";
  230. var linkPath1b = path.join(fixturesDir, "nested-index", 'one', 'symlink1-dir');
  231. try {fs.unlinkSync(linkPath1b);}catch(e){}
  232. fs.symlinkSync(linkData1b, linkPath1b);
  233.  
  234. var linkData2b = "../one/symlink1-dir";
  235. var entry = path.join(fixturesDir, "nested-index", 'two', 'symlink12-dir');
  236. try {fs.unlinkSync(entry);}catch(e){}
  237. fs.symlinkSync(linkData2b, entry);
  238. unlink.push(linkPath1b);
  239. unlink.push(entry);
  240.  
  241. assert.equal(fs.realpathSync(entry), expected);
  242.  
  243. asynctest(fs.realpath, [entry], callback, function(err, result){
  244. assert.equal(result, expected,
  245. 'got '+inspect(result)+' expected '+inspect(expected));
  246. });
  247. }
  248.  
  249. function test_cyclic_link_protection(callback) {
  250. var entry = fixturesDir+'/cycles/realpath-3a';
  251. [
  252. [entry, '../cycles/realpath-3b'],
  253. [fixturesDir+'/cycles/realpath-3b', '../cycles/realpath-3c'],
  254. [fixturesDir+'/cycles/realpath-3c', '../cycles/realpath-3a'],
  255. ].forEach(function(t) {
  256. try {fs.unlinkSync(t[0]);}catch(e){}
  257. fs.symlinkSync(t[1], t[0]);
  258. unlink.push(t[0]);
  259. });
  260. assert.throws(function(){ fs.realpathSync(entry); });
  261. asynctest(fs.realpath, [entry], callback, function(err, result){
  262. assert.ok(err && true);
  263. return true;
  264. });
  265. }
  266.  
  267. // 4. relative input
  268. function test_relative_input_cwd(callback) {
  269. var p = fixturesDir.lastIndexOf('/');
  270. var entrydir = fixturesDir.substr(0, p);
  271. var entry = fixturesDir.substr(p+1)+'/cycles/realpath-3a';
  272. var expected = fixturesDir+'/cycles/root.js';
  273. [
  274. [entry, '../cycles/realpath-3b'],
  275. [fixturesDir+'/cycles/realpath-3b', '../cycles/realpath-3c'],
  276. [fixturesDir+'/cycles/realpath-3c', 'root.js'],
  277. ].forEach(function(t) {
  278. var fn = t[0];
  279. if (fn.charAt(0) !== '/') fn = entrydir + '/' + fn;
  280. try {fs.unlinkSync(fn);}catch(e){}
  281. fs.symlinkSync(t[1], fn);
  282. unlink.push(fn);
  283. });
  284. var origcwd = process.cwd();
  285. process.chdir(entrydir);
  286. assert.equal(fs.realpathSync(entry), expected);
  287. asynctest(fs.realpath, [entry], callback, function(err, result){
  288. process.chdir(origcwd);
  289. assert.equal(result, expected,
  290. 'got '+inspect(result)+' expected '+inspect(expected));
  291. return true;
  292. });
  293. }
  294.  
  295. function test_deep_symlink_mix(callback) {
  296. // todo: check to see that fixturesDir is not rooted in the
  297. // same directory as our test symlink.
  298. // obtain our current realpath using bash (so we can test ourselves)
  299. exec("cd '"+fixturesDir.replace("'","\\'")+"' && pwd -P",
  300. function(err, stdout, stderr)
  301. {
  302. if (err) return callback(err);
  303. var fixturesAbsDir = stdout.trim();
  304. /*
  305. /tmp/node-test-realpath-f1 -> ../tmp/node-test-realpath-d1/foo
  306. /tmp/node-test-realpath-d1 -> ../node-test-realpath-d2
  307. /tmp/node-test-realpath-d2/foo -> ../node-test-realpath-f2
  308. /tmp/node-test-realpath-f2
  309. -> /node/test/fixtures/nested-index/one/realpath-c
  310. /node/test/fixtures/nested-index/one/realpath-c
  311. -> /node/test/fixtures/nested-index/two/realpath-c
  312. /node/test/fixtures/nested-index/two/realpath-c -> ../../cycles/root.js
  313. /node/test/fixtures/cycles/root.js (hard)
  314. */
  315. var entry = '/tmp/node-test-realpath-f1';
  316. try {fs.unlinkSync('/tmp/node-test-realpath-d2/foo');}catch(e){}
  317. try {fs.rmdirSync('/tmp/node-test-realpath-d2');}catch(e){}
  318. fs.mkdirSync('/tmp/node-test-realpath-d2', 0700);
  319. try {
  320. [
  321. [entry, '../tmp/node-test-realpath-d1/foo'],
  322. ['/tmp/node-test-realpath-d1', '../tmp/node-test-realpath-d2'],
  323. ['/tmp/node-test-realpath-d2/foo', '../node-test-realpath-f2'],
  324. ['/tmp/node-test-realpath-f2', fixturesAbsDir+'/nested-index/one/realpath-c'],
  325. [fixturesAbsDir+'/nested-index/one/realpath-c', fixturesAbsDir+'/nested-index/two/realpath-c'],
  326. [fixturesAbsDir+'/nested-index/two/realpath-c', '../../cycles/root.js'],
  327. ].forEach(function(t) {
  328. //debug('setting up '+t[0]+' -> '+t[1]);
  329. try {fs.unlinkSync(t[0]);}catch(e){}
  330. fs.symlinkSync(t[1], t[0]);
  331. unlink.push(t[0]);
  332. });
  333. } finally {
  334. unlink.push('/tmp/node-test-realpath-d2');
  335. }
  336. var expected = fixturesAbsDir+'/cycles/root.js';
  337. assert.equal(fs.realpathSync(entry), expected);
  338. asynctest(fs.realpath, [entry], callback, function(err, result){
  339. assert.equal(result, expected,
  340. 'got '+inspect(result)+' expected '+inspect(expected));
  341. return true;
  342. });
  343. });
  344. }
  345.  
  346. // ----------------------------------------------------------------------------
  347. // todo: test shallow symlinks (file & dir)
  348. // todo: test non-symlinks (file & dir)
  349. // todo: test error on cyclic symlinks
  350.  
  351. var tests = [
  352. test_deep_relative_file_symlink,
  353. test_deep_relative_dir_symlink,
  354. test_cyclic_link_protection,
  355. test_relative_input_cwd,
  356. test_deep_symlink_mix,
  357. ];
  358. var numtests = tests.length;
  359. function runNextTest(err) {
  360. if (err) throw err;
  361. var test = tests.shift()
  362. if (!test) puts(numtests+' subtests completed OK for fs.realpath');
  363. else test(runNextTest);
  364. }
  365. runNextTest();
  366.  
  367. process.addListener("exit", function () {
  368. //unlink.forEach(function(path){ try {fs.unlinkSync(path);}catch(e){} });
  369. assert.equal(async_completed, async_expected);
  370. });
Add Comment
Please, Sign In to add comment