You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. // Copyright Joyent, Inc. and other Node contributors.
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a
  4. // copy of this software and associated documentation files (the
  5. // "Software"), to deal in the Software without restriction, including
  6. // without limitation the rights to use, copy, modify, merge, publish,
  7. // distribute, sublicense, and/or sell copies of the Software, and to permit
  8. // persons to whom the Software is furnished to do so, subject to the
  9. // following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included
  12. // in all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  15. // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  16. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  17. // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  18. // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  19. // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  20. // USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. var assert = require('assert');
  22. var path = require('.');
  23. var isWindows = process.platform === 'win32';
  24. // Mock the node.js path
  25. var f = __dirname + '/simple/test-path.js';
  26. assert.equal(path.basename(f), 'test-path.js');
  27. assert.equal(path.basename(f, '.js'), 'test-path');
  28. assert.equal(path.basename(''), '');
  29. assert.equal(path.basename('/dir/basename.ext'), 'basename.ext');
  30. assert.equal(path.basename('/basename.ext'), 'basename.ext');
  31. assert.equal(path.basename('basename.ext'), 'basename.ext');
  32. assert.equal(path.basename('basename.ext/'), 'basename.ext');
  33. assert.equal(path.basename('basename.ext//'), 'basename.ext');
  34. if (isWindows) {
  35. // On Windows a backslash acts as a path separator.
  36. assert.equal(path.basename('\\dir\\basename.ext'), 'basename.ext');
  37. assert.equal(path.basename('\\basename.ext'), 'basename.ext');
  38. assert.equal(path.basename('basename.ext'), 'basename.ext');
  39. assert.equal(path.basename('basename.ext\\'), 'basename.ext');
  40. assert.equal(path.basename('basename.ext\\\\'), 'basename.ext');
  41. } else {
  42. // On unix a backslash is just treated as any other character.
  43. assert.equal(path.basename('\\dir\\basename.ext'), '\\dir\\basename.ext');
  44. assert.equal(path.basename('\\basename.ext'), '\\basename.ext');
  45. assert.equal(path.basename('basename.ext'), 'basename.ext');
  46. assert.equal(path.basename('basename.ext\\'), 'basename.ext\\');
  47. assert.equal(path.basename('basename.ext\\\\'), 'basename.ext\\\\');
  48. }
  49. // POSIX filenames may include control characters
  50. // c.f. http://www.dwheeler.com/essays/fixing-unix-linux-filenames.html
  51. if (!isWindows) {
  52. var controlCharFilename = 'Icon' + String.fromCharCode(13);
  53. assert.equal(path.basename('/a/b/' + controlCharFilename),
  54. controlCharFilename);
  55. }
  56. assert.equal(path.extname(f), '.js');
  57. assert.equal(path.dirname(f).substr(-11),
  58. isWindows ? 'test\\simple' : 'test/simple');
  59. assert.equal(path.dirname('/a/b/'), '/a');
  60. assert.equal(path.dirname('/a/b'), '/a');
  61. assert.equal(path.dirname('/a'), '/');
  62. assert.equal(path.dirname(''), '.');
  63. assert.equal(path.dirname('/'), '/');
  64. assert.equal(path.dirname('////'), '/');
  65. if (isWindows) {
  66. assert.equal(path.dirname('c:\\'), 'c:\\');
  67. assert.equal(path.dirname('c:\\foo'), 'c:\\');
  68. assert.equal(path.dirname('c:\\foo\\'), 'c:\\');
  69. assert.equal(path.dirname('c:\\foo\\bar'), 'c:\\foo');
  70. assert.equal(path.dirname('c:\\foo\\bar\\'), 'c:\\foo');
  71. assert.equal(path.dirname('c:\\foo\\bar\\baz'), 'c:\\foo\\bar');
  72. assert.equal(path.dirname('\\'), '\\');
  73. assert.equal(path.dirname('\\foo'), '\\');
  74. assert.equal(path.dirname('\\foo\\'), '\\');
  75. assert.equal(path.dirname('\\foo\\bar'), '\\foo');
  76. assert.equal(path.dirname('\\foo\\bar\\'), '\\foo');
  77. assert.equal(path.dirname('\\foo\\bar\\baz'), '\\foo\\bar');
  78. assert.equal(path.dirname('c:'), 'c:');
  79. assert.equal(path.dirname('c:foo'), 'c:');
  80. assert.equal(path.dirname('c:foo\\'), 'c:');
  81. assert.equal(path.dirname('c:foo\\bar'), 'c:foo');
  82. assert.equal(path.dirname('c:foo\\bar\\'), 'c:foo');
  83. assert.equal(path.dirname('c:foo\\bar\\baz'), 'c:foo\\bar');
  84. assert.equal(path.dirname('\\\\unc\\share'), '\\\\unc\\share');
  85. assert.equal(path.dirname('\\\\unc\\share\\foo'), '\\\\unc\\share\\');
  86. assert.equal(path.dirname('\\\\unc\\share\\foo\\'), '\\\\unc\\share\\');
  87. assert.equal(path.dirname('\\\\unc\\share\\foo\\bar'),
  88. '\\\\unc\\share\\foo');
  89. assert.equal(path.dirname('\\\\unc\\share\\foo\\bar\\'),
  90. '\\\\unc\\share\\foo');
  91. assert.equal(path.dirname('\\\\unc\\share\\foo\\bar\\baz'),
  92. '\\\\unc\\share\\foo\\bar');
  93. }
  94. assert.equal(path.extname(''), '');
  95. assert.equal(path.extname('/path/to/file'), '');
  96. assert.equal(path.extname('/path/to/file.ext'), '.ext');
  97. assert.equal(path.extname('/path.to/file.ext'), '.ext');
  98. assert.equal(path.extname('/path.to/file'), '');
  99. assert.equal(path.extname('/path.to/.file'), '');
  100. assert.equal(path.extname('/path.to/.file.ext'), '.ext');
  101. assert.equal(path.extname('/path/to/f.ext'), '.ext');
  102. assert.equal(path.extname('/path/to/..ext'), '.ext');
  103. assert.equal(path.extname('file'), '');
  104. assert.equal(path.extname('file.ext'), '.ext');
  105. assert.equal(path.extname('.file'), '');
  106. assert.equal(path.extname('.file.ext'), '.ext');
  107. assert.equal(path.extname('/file'), '');
  108. assert.equal(path.extname('/file.ext'), '.ext');
  109. assert.equal(path.extname('/.file'), '');
  110. assert.equal(path.extname('/.file.ext'), '.ext');
  111. assert.equal(path.extname('.path/file.ext'), '.ext');
  112. assert.equal(path.extname('file.ext.ext'), '.ext');
  113. assert.equal(path.extname('file.'), '.');
  114. assert.equal(path.extname('.'), '');
  115. assert.equal(path.extname('./'), '');
  116. assert.equal(path.extname('.file.ext'), '.ext');
  117. assert.equal(path.extname('.file'), '');
  118. assert.equal(path.extname('.file.'), '.');
  119. assert.equal(path.extname('.file..'), '.');
  120. assert.equal(path.extname('..'), '');
  121. assert.equal(path.extname('../'), '');
  122. assert.equal(path.extname('..file.ext'), '.ext');
  123. assert.equal(path.extname('..file'), '.file');
  124. assert.equal(path.extname('..file.'), '.');
  125. assert.equal(path.extname('..file..'), '.');
  126. assert.equal(path.extname('...'), '.');
  127. assert.equal(path.extname('...ext'), '.ext');
  128. assert.equal(path.extname('....'), '.');
  129. assert.equal(path.extname('file.ext/'), '.ext');
  130. assert.equal(path.extname('file.ext//'), '.ext');
  131. assert.equal(path.extname('file/'), '');
  132. assert.equal(path.extname('file//'), '');
  133. assert.equal(path.extname('file./'), '.');
  134. assert.equal(path.extname('file.//'), '.');
  135. if (isWindows) {
  136. // On windows, backspace is a path separator.
  137. assert.equal(path.extname('.\\'), '');
  138. assert.equal(path.extname('..\\'), '');
  139. assert.equal(path.extname('file.ext\\'), '.ext');
  140. assert.equal(path.extname('file.ext\\\\'), '.ext');
  141. assert.equal(path.extname('file\\'), '');
  142. assert.equal(path.extname('file\\\\'), '');
  143. assert.equal(path.extname('file.\\'), '.');
  144. assert.equal(path.extname('file.\\\\'), '.');
  145. } else {
  146. // On unix, backspace is a valid name component like any other character.
  147. assert.equal(path.extname('.\\'), '');
  148. assert.equal(path.extname('..\\'), '.\\');
  149. assert.equal(path.extname('file.ext\\'), '.ext\\');
  150. assert.equal(path.extname('file.ext\\\\'), '.ext\\\\');
  151. assert.equal(path.extname('file\\'), '');
  152. assert.equal(path.extname('file\\\\'), '');
  153. assert.equal(path.extname('file.\\'), '.\\');
  154. assert.equal(path.extname('file.\\\\'), '.\\\\');
  155. }
  156. // path.join tests
  157. var failures = [];
  158. var joinTests =
  159. // arguments result
  160. [[['.', 'x/b', '..', '/b/c.js'], 'x/b/c.js'],
  161. [['/.', 'x/b', '..', '/b/c.js'], '/x/b/c.js'],
  162. [['/foo', '../../../bar'], '/bar'],
  163. [['foo', '../../../bar'], '../../bar'],
  164. [['foo/', '../../../bar'], '../../bar'],
  165. [['foo/x', '../../../bar'], '../bar'],
  166. [['foo/x', './bar'], 'foo/x/bar'],
  167. [['foo/x/', './bar'], 'foo/x/bar'],
  168. [['foo/x/', '.', 'bar'], 'foo/x/bar'],
  169. [['./'], './'],
  170. [['.', './'], './'],
  171. [['.', '.', '.'], '.'],
  172. [['.', './', '.'], '.'],
  173. [['.', '/./', '.'], '.'],
  174. [['.', '/////./', '.'], '.'],
  175. [['.'], '.'],
  176. [['', '.'], '.'],
  177. [['', 'foo'], 'foo'],
  178. [['foo', '/bar'], 'foo/bar'],
  179. [['', '/foo'], '/foo'],
  180. [['', '', '/foo'], '/foo'],
  181. [['', '', 'foo'], 'foo'],
  182. [['foo', ''], 'foo'],
  183. [['foo/', ''], 'foo/'],
  184. [['foo', '', '/bar'], 'foo/bar'],
  185. [['./', '..', '/foo'], '../foo'],
  186. [['./', '..', '..', '/foo'], '../../foo'],
  187. [['.', '..', '..', '/foo'], '../../foo'],
  188. [['', '..', '..', '/foo'], '../../foo'],
  189. [['/'], '/'],
  190. [['/', '.'], '/'],
  191. [['/', '..'], '/'],
  192. [['/', '..', '..'], '/'],
  193. [[''], '.'],
  194. [['', ''], '.'],
  195. [[' /foo'], ' /foo'],
  196. [[' ', 'foo'], ' /foo'],
  197. [[' ', '.'], ' '],
  198. [[' ', '/'], ' /'],
  199. [[' ', ''], ' '],
  200. [['/', 'foo'], '/foo'],
  201. [['/', '/foo'], '/foo'],
  202. [['/', '//foo'], '/foo'],
  203. [['/', '', '/foo'], '/foo'],
  204. [['', '/', 'foo'], '/foo'],
  205. [['', '/', '/foo'], '/foo']
  206. ];
  207. // Windows-specific join tests
  208. if (isWindows) {
  209. joinTests = joinTests.concat(
  210. [// UNC path expected
  211. [['//foo/bar'], '//foo/bar/'],
  212. [['\\/foo/bar'], '//foo/bar/'],
  213. [['\\\\foo/bar'], '//foo/bar/'],
  214. // UNC path expected - server and share separate
  215. [['//foo', 'bar'], '//foo/bar/'],
  216. [['//foo/', 'bar'], '//foo/bar/'],
  217. [['//foo', '/bar'], '//foo/bar/'],
  218. // UNC path expected - questionable
  219. [['//foo', '', 'bar'], '//foo/bar/'],
  220. [['//foo/', '', 'bar'], '//foo/bar/'],
  221. [['//foo/', '', '/bar'], '//foo/bar/'],
  222. // UNC path expected - even more questionable
  223. [['', '//foo', 'bar'], '//foo/bar/'],
  224. [['', '//foo/', 'bar'], '//foo/bar/'],
  225. [['', '//foo/', '/bar'], '//foo/bar/'],
  226. // No UNC path expected (no double slash in first component)
  227. [['\\', 'foo/bar'], '/foo/bar'],
  228. [['\\', '/foo/bar'], '/foo/bar'],
  229. [['', '/', '/foo/bar'], '/foo/bar'],
  230. // No UNC path expected (no non-slashes in first component - questionable)
  231. [['//', 'foo/bar'], '/foo/bar'],
  232. [['//', '/foo/bar'], '/foo/bar'],
  233. [['\\\\', '/', '/foo/bar'], '/foo/bar'],
  234. [['//'], '/'],
  235. // No UNC path expected (share name missing - questionable).
  236. [['//foo'], '/foo'],
  237. [['//foo/'], '/foo/'],
  238. [['//foo', '/'], '/foo/'],
  239. [['//foo', '', '/'], '/foo/'],
  240. // No UNC path expected (too many leading slashes - questionable)
  241. [['///foo/bar'], '/foo/bar'],
  242. [['////foo', 'bar'], '/foo/bar'],
  243. [['\\\\\\/foo/bar'], '/foo/bar'],
  244. // Drive-relative vs drive-absolute paths. This merely describes the
  245. // status quo, rather than being obviously right
  246. [['c:'], 'c:.'],
  247. [['c:.'], 'c:.'],
  248. [['c:', ''], 'c:.'],
  249. [['', 'c:'], 'c:.'],
  250. [['c:.', '/'], 'c:./'],
  251. [['c:.', 'file'], 'c:file'],
  252. [['c:', '/'], 'c:/'],
  253. [['c:', 'file'], 'c:/file']
  254. ]);
  255. }
  256. // Run the join tests.
  257. joinTests.forEach(function(test) {
  258. var actual = path.join.apply(path, test[0]);
  259. var expected = isWindows ? test[1].replace(/\//g, '\\') : test[1];
  260. var message = 'path.join(' + test[0].map(JSON.stringify).join(',') + ')' +
  261. '\n expect=' + JSON.stringify(expected) +
  262. '\n actual=' + JSON.stringify(actual);
  263. if (actual !== expected) failures.push('\n' + message);
  264. // assert.equal(actual, expected, message);
  265. });
  266. assert.equal(failures.length, 0, failures.join(''));
  267. var joinThrowTests = [true, false, 7, null, {}, undefined, [], NaN];
  268. joinThrowTests.forEach(function(test) {
  269. assert.throws(function() {
  270. path.join(test);
  271. }, TypeError);
  272. assert.throws(function() {
  273. path.resolve(test);
  274. }, TypeError);
  275. });
  276. // path normalize tests
  277. if (isWindows) {
  278. assert.equal(path.normalize('./fixtures///b/../b/c.js'),
  279. 'fixtures\\b\\c.js');
  280. assert.equal(path.normalize('/foo/../../../bar'), '\\bar');
  281. assert.equal(path.normalize('a//b//../b'), 'a\\b');
  282. assert.equal(path.normalize('a//b//./c'), 'a\\b\\c');
  283. assert.equal(path.normalize('a//b//.'), 'a\\b');
  284. assert.equal(path.normalize('//server/share/dir/file.ext'),
  285. '\\\\server\\share\\dir\\file.ext');
  286. } else {
  287. assert.equal(path.normalize('./fixtures///b/../b/c.js'),
  288. 'fixtures/b/c.js');
  289. assert.equal(path.normalize('/foo/../../../bar'), '/bar');
  290. assert.equal(path.normalize('a//b//../b'), 'a/b');
  291. assert.equal(path.normalize('a//b//./c'), 'a/b/c');
  292. assert.equal(path.normalize('a//b//.'), 'a/b');
  293. }
  294. // path.resolve tests
  295. if (isWindows) {
  296. // windows
  297. var resolveTests =
  298. // arguments result
  299. [[['c:/blah\\blah', 'd:/games', 'c:../a'], 'c:\\blah\\a'],
  300. [['c:/ignore', 'd:\\a/b\\c/d', '\\e.exe'], 'd:\\e.exe'],
  301. [['c:/ignore', 'c:/some/file'], 'c:\\some\\file'],
  302. [['d:/ignore', 'd:some/dir//'], 'd:\\ignore\\some\\dir'],
  303. [['.'], process.cwd()],
  304. [['//server/share', '..', 'relative\\'], '\\\\server\\share\\relative'],
  305. [['c:/', '//'], 'c:\\'],
  306. [['c:/', '//dir'], 'c:\\dir'],
  307. [['c:/', '//server/share'], '\\\\server\\share\\'],
  308. [['c:/', '//server//share'], '\\\\server\\share\\'],
  309. [['c:/', '///some//dir'], 'c:\\some\\dir']
  310. ];
  311. } else {
  312. // Posix
  313. var resolveTests =
  314. // arguments result
  315. [[['/var/lib', '../', 'file/'], '/var/file'],
  316. [['/var/lib', '/../', 'file/'], '/file'],
  317. [['a/b/c/', '../../..'], process.cwd()],
  318. [['.'], process.cwd()],
  319. [['/some/dir', '.', '/absolute/'], '/absolute']];
  320. }
  321. var failures = [];
  322. resolveTests.forEach(function(test) {
  323. var actual = path.resolve.apply(path, test[0]);
  324. var expected = test[1];
  325. var message = 'path.resolve(' + test[0].map(JSON.stringify).join(',') + ')' +
  326. '\n expect=' + JSON.stringify(expected) +
  327. '\n actual=' + JSON.stringify(actual);
  328. if (actual !== expected) failures.push('\n' + message);
  329. // assert.equal(actual, expected, message);
  330. });
  331. assert.equal(failures.length, 0, failures.join(''));
  332. // path.isAbsolute tests
  333. if (isWindows) {
  334. assert.equal(path.isAbsolute('//server/file'), true);
  335. assert.equal(path.isAbsolute('\\\\server\\file'), true);
  336. assert.equal(path.isAbsolute('C:/Users/'), true);
  337. assert.equal(path.isAbsolute('C:\\Users\\'), true);
  338. assert.equal(path.isAbsolute('C:cwd/another'), false);
  339. assert.equal(path.isAbsolute('C:cwd\\another'), false);
  340. assert.equal(path.isAbsolute('directory/directory'), false);
  341. assert.equal(path.isAbsolute('directory\\directory'), false);
  342. } else {
  343. assert.equal(path.isAbsolute('/home/foo'), true);
  344. assert.equal(path.isAbsolute('/home/foo/..'), true);
  345. assert.equal(path.isAbsolute('bar/'), false);
  346. assert.equal(path.isAbsolute('./baz'), false);
  347. }
  348. // path.relative tests
  349. if (isWindows) {
  350. // windows
  351. var relativeTests =
  352. // arguments result
  353. [['c:/blah\\blah', 'd:/games', 'd:\\games'],
  354. ['c:/aaaa/bbbb', 'c:/aaaa', '..'],
  355. ['c:/aaaa/bbbb', 'c:/cccc', '..\\..\\cccc'],
  356. ['c:/aaaa/bbbb', 'c:/aaaa/bbbb', ''],
  357. ['c:/aaaa/bbbb', 'c:/aaaa/cccc', '..\\cccc'],
  358. ['c:/aaaa/', 'c:/aaaa/cccc', 'cccc'],
  359. ['c:/', 'c:\\aaaa\\bbbb', 'aaaa\\bbbb'],
  360. ['c:/aaaa/bbbb', 'd:\\', 'd:\\']];
  361. } else {
  362. // posix
  363. var relativeTests =
  364. // arguments result
  365. [['/var/lib', '/var', '..'],
  366. ['/var/lib', '/bin', '../../bin'],
  367. ['/var/lib', '/var/lib', ''],
  368. ['/var/lib', '/var/apache', '../apache'],
  369. ['/var/', '/var/lib', 'lib'],
  370. ['/', '/var/lib', 'var/lib']];
  371. }
  372. var failures = [];
  373. relativeTests.forEach(function(test) {
  374. var actual = path.relative(test[0], test[1]);
  375. var expected = test[2];
  376. var message = 'path.relative(' +
  377. test.slice(0, 2).map(JSON.stringify).join(',') +
  378. ')' +
  379. '\n expect=' + JSON.stringify(expected) +
  380. '\n actual=' + JSON.stringify(actual);
  381. if (actual !== expected) failures.push('\n' + message);
  382. });
  383. assert.equal(failures.length, 0, failures.join(''));
  384. // path.sep tests
  385. if (isWindows) {
  386. // windows
  387. assert.equal(path.sep, '\\');
  388. } else {
  389. // posix
  390. assert.equal(path.sep, '/');
  391. }
  392. // path.delimiter tests
  393. if (isWindows) {
  394. // windows
  395. assert.equal(path.delimiter, ';');
  396. } else {
  397. // posix
  398. assert.equal(path.delimiter, ':');
  399. }