Skip to content
File

Blob: src/workerd/api/node/tests/path-test.js

javascript628 lines
1// Copyright (c) 2023 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4import { ok, strictEqual, throws } from 'node:assert';
5 
6import { default as path } from 'node:path';
7 
8export const test_path = {
9 test(ctrl, env, ctx) {
10 // Test thrown TypeErrors
11 const typeErrorTests = [true, false, 7, null, {}, undefined, [], NaN];
12 
13 function fail(fn) {
14 const args = Array.from(arguments).slice(1);
15 
16 throws(
17 () => {
18 fn.apply(null, args);
19 },
20 { code: 'ERR_INVALID_ARG_TYPE', name: 'TypeError' }
21 );
22 }
23 
24 typeErrorTests.forEach((test) => {
25 [path.posix].forEach((namespace) => {
26 fail(namespace.join, test);
27 fail(namespace.resolve, test);
28 fail(namespace.normalize, test);
29 fail(namespace.isAbsolute, test);
30 fail(namespace.relative, test, 'foo');
31 fail(namespace.relative, 'foo', test);
32 fail(namespace.parse, test);
33 fail(namespace.dirname, test);
34 fail(namespace.basename, test);
35 fail(namespace.extname, test);
36 
37 // Undefined is a valid value as the second argument to basename
38 if (test !== undefined) {
39 fail(namespace.basename, 'foo', test);
40 }
41 });
42 });
43 
44 // path.sep tests
45 // windows
46 strictEqual(path.win32.sep, '\\');
47 // posix
48 strictEqual(path.posix.sep, '/');
49 
50 // path.delimiter tests
51 // windows
52 strictEqual(path.win32.delimiter, ';');
53 // posix
54 strictEqual(path.posix.delimiter, ':');
55 
56 strictEqual(path, path.posix);
57 },
58};
59 
60export const test_path_zero_length_strings = {
61 test(ctrl, env, ctx) {
62 // Join will internally ignore all the zero-length strings and it will return
63 // '.' if the joined string is a zero-length string.
64 strictEqual(path.posix.join(''), '.');
65 strictEqual(path.posix.join('', ''), '.');
66 strictEqual(path.join('/'), '/');
67 strictEqual(path.join('/', ''), '/');
68 
69 // Normalize will return '.' if the input is a zero-length string
70 strictEqual(path.posix.normalize(''), '.');
71 strictEqual(path.normalize('/'), '/');
72 
73 // Since '' is not a valid path in any of the common environments, return false
74 strictEqual(path.posix.isAbsolute(''), false);
75 
76 // Resolve, internally ignores all the zero-length strings and returns the
77 // current working directory
78 strictEqual(path.resolve(''), '/');
79 strictEqual(path.resolve('', ''), '/');
80 
81 // Relative, internally calls resolve. So, '' is actually the current directory
82 strictEqual(path.relative('', '/'), '');
83 strictEqual(path.relative('/', ''), '');
84 strictEqual(path.relative('/', '/'), '');
85 },
86};
87 
88// Ref: https://github.com/nodejs/node/blob/4d6d7d644be4f10f90e5c9c66563736112fffbff/test/parallel/test-path-resolve.js
89export const test_path_resolve = {
90 test(ctrl, env, ctx) {
91 const failures = [];
92 const posixyCwd = '/';
93 
94 const resolveTests = [
95 [['/var/lib', '../', 'file/'], '/var/file'],
96 [['/var/lib', '/../', 'file/'], '/file'],
97 [['a/b/c/', '../../..'], posixyCwd],
98 [['.'], posixyCwd],
99 [['/some/dir', '.', '/absolute/'], '/absolute'],
100 [['/foo/tmp.3/', '../tmp.3/cycles/root.js'], '/foo/tmp.3/cycles/root.js'],
101 ];
102 resolveTests.forEach(([test, expected]) => {
103 const actual = path.resolve.apply(null, test);
104 const message = `path.posix.resolve(${test.map(JSON.stringify).join(',')})\n expect=${JSON.stringify(
105 expected
106 )}\n actual=${JSON.stringify(actual)}`;
107 if (actual !== expected) failures.push(message);
108 });
109 strictEqual(failures.length, 0, failures.join('\n'));
110 },
111};
112 
113// Ref: https://github.com/nodejs/node/blob/4d6d7d644be4f10f90e5c9c66563736112fffbff/test/parallel/test-path-relative.js
114export const test_path_relative = {
115 test(ctrl, env, ctx) {
116 const failures = [];
117 
118 const relativeTests = [
119 ['/var/lib', '/var', '..'],
120 ['/var/lib', '/bin', '../../bin'],
121 ['/var/lib', '/var/lib', ''],
122 ['/var/lib', '/var/apache', '../apache'],
123 ['/var/', '/var/lib', 'lib'],
124 ['/', '/var/lib', 'var/lib'],
125 ['/foo/test', '/foo/test/bar/package.json', 'bar/package.json'],
126 ['/Users/a/web/b/test/mails', '/Users/a/web/b', '../..'],
127 ['/foo/bar/baz-quux', '/foo/bar/baz', '../baz'],
128 ['/foo/bar/baz', '/foo/bar/baz-quux', '../baz-quux'],
129 ['/baz-quux', '/baz', '../baz'],
130 ['/baz', '/baz-quux', '../baz-quux'],
131 ['/page1/page2/foo', '/', '../../..'],
132 ];
133 relativeTests.forEach((test) => {
134 const actual = path.relative(test[0], test[1]);
135 const expected = test[2];
136 if (actual !== expected) {
137 const message = `path.posix.relative(${test
138 .slice(0, 2)
139 .map(JSON.stringify)
140 .join(',')})\n expect=${JSON.stringify(
141 expected
142 )}\n actual=${JSON.stringify(actual)}`;
143 failures.push(`\n${message}`);
144 }
145 });
146 strictEqual(failures.length, 0, failures.join(''));
147 },
148};
149 
150export const test_path_parse_format = {
151 test(ctrl, env, ctx) {
152 const unixPaths = [
153 // [path, root]
154 ['/home/user/dir/file.txt', '/'],
155 ['/home/user/a dir/another File.zip', '/'],
156 ['/home/user/a dir//another&File.', '/'],
157 ['/home/user/a$$$dir//another File.zip', '/'],
158 ['user/dir/another File.zip', ''],
159 ['file', ''],
160 ['.\\file', ''],
161 ['./file', ''],
162 ['C:\\foo', ''],
163 ['/', '/'],
164 ['', ''],
165 ['.', ''],
166 ['..', ''],
167 ['/foo', '/'],
168 ['/foo.', '/'],
169 ['/foo.bar', '/'],
170 ['/.', '/'],
171 ['/.foo', '/'],
172 ['/.foo.bar', '/'],
173 ['/foo/bar.baz', '/'],
174 ];
175 
176 const unixSpecialCaseFormatTests = [
177 [{ dir: 'some/dir' }, 'some/dir/'],
178 [{ base: 'index.html' }, 'index.html'],
179 [{ root: '/' }, '/'],
180 [{ name: 'index', ext: '.html' }, 'index.html'],
181 [{ dir: 'some/dir', name: 'index', ext: '.html' }, 'some/dir/index.html'],
182 [{ root: '/', name: 'index', ext: '.html' }, '/index.html'],
183 [{}, ''],
184 ];
185 
186 const errors = [
187 { method: 'parse', input: [null] },
188 { method: 'parse', input: [{}] },
189 { method: 'parse', input: [true] },
190 { method: 'parse', input: [1] },
191 { method: 'parse', input: [] },
192 { method: 'format', input: [null] },
193 { method: 'format', input: [''] },
194 { method: 'format', input: [true] },
195 { method: 'format', input: [1] },
196 ];
197 
198 checkParseFormat(unixPaths);
199 checkErrors();
200 checkFormat(unixSpecialCaseFormatTests);
201 
202 // Test removal of trailing path separators
203 const trailingTests = [
204 ['./', { root: '', dir: '', base: '.', ext: '', name: '.' }],
205 ['//', { root: '/', dir: '/', base: '', ext: '', name: '' }],
206 ['///', { root: '/', dir: '/', base: '', ext: '', name: '' }],
207 ['/foo///', { root: '/', dir: '/', base: 'foo', ext: '', name: 'foo' }],
208 [
209 '/foo///bar.baz',
210 { root: '/', dir: '/foo//', base: 'bar.baz', ext: '.baz', name: 'bar' },
211 ],
212 ];
213 const failures = [];
214 trailingTests.forEach((test) => {
215 const actual = path.parse(test[0]);
216 const expected = test[1];
217 const message = `path.posix.parse(${JSON.stringify(test[0])})\n expect=${JSON.stringify(
218 expected
219 )}\n actual=${JSON.stringify(actual)}`;
220 const actualKeys = Object.keys(actual);
221 const expectedKeys = Object.keys(expected);
222 let failed = actualKeys.length !== expectedKeys.length;
223 if (!failed) {
224 for (let i = 0; i < actualKeys.length; ++i) {
225 const key = actualKeys[i];
226 if (!expectedKeys.includes(key) || actual[key] !== expected[key]) {
227 failed = true;
228 break;
229 }
230 }
231 }
232 if (failed) failures.push(`\n${message}`);
233 });
234 strictEqual(failures.length, 0, failures.join(''));
235 
236 function checkErrors() {
237 errors.forEach(({ method, input }) => {
238 throws(
239 () => {
240 path[method].apply(path, input);
241 },
242 {
243 code: 'ERR_INVALID_ARG_TYPE',
244 name: 'TypeError',
245 }
246 );
247 });
248 }
249 
250 function checkParseFormat(paths) {
251 paths.forEach(([element, root]) => {
252 const output = path.parse(element);
253 strictEqual(typeof output.root, 'string');
254 strictEqual(typeof output.dir, 'string');
255 strictEqual(typeof output.base, 'string');
256 strictEqual(typeof output.ext, 'string');
257 strictEqual(typeof output.name, 'string');
258 strictEqual(path.format(output), element);
259 strictEqual(output.root, root);
260 ok(output.dir.startsWith(output.root));
261 strictEqual(output.dir, output.dir ? path.dirname(element) : '');
262 strictEqual(output.base, path.basename(element));
263 strictEqual(output.ext, path.extname(element));
264 });
265 }
266 
267 function checkFormat(testCases) {
268 testCases.forEach(([element, expect]) => {
269 strictEqual(path.format(element), expect);
270 });
271 
272 [null, undefined, 1, true, false, 'string'].forEach((pathObject) => {
273 throws(
274 () => {
275 path.format(pathObject);
276 },
277 {
278 code: 'ERR_INVALID_ARG_TYPE',
279 name: 'TypeError',
280 }
281 );
282 });
283 }
284 
285 // See https://github.com/nodejs/node/issues/44343
286 strictEqual(path.format({ name: 'x', ext: 'png' }), 'x.png');
287 strictEqual(path.format({ name: 'x', ext: '.png' }), 'x.png');
288 },
289};
290 
291export const test_path_normalize = {
292 test(ctrl, env, ctx) {
293 strictEqual(
294 path.win32.normalize('./fixtures///b/../b/c.js'),
295 'fixtures\\b\\c.js'
296 );
297 strictEqual(path.win32.normalize('/foo/../../../bar'), '\\bar');
298 strictEqual(path.win32.normalize('a//b//../b'), 'a\\b');
299 strictEqual(path.win32.normalize('a//b//./c'), 'a\\b\\c');
300 strictEqual(path.win32.normalize('a//b//.'), 'a\\b');
301 strictEqual(
302 path.win32.normalize('//server/share/dir/file.ext'),
303 '\\\\server\\share\\dir\\file.ext'
304 );
305 strictEqual(path.win32.normalize('/a/b/c/../../../x/y/z'), '\\x\\y\\z');
306 strictEqual(path.win32.normalize('C:'), 'C:.');
307 strictEqual(path.win32.normalize('C:..\\abc'), 'C:..\\abc');
308 strictEqual(
309 path.win32.normalize('C:..\\..\\abc\\..\\def'),
310 'C:..\\..\\def'
311 );
312 strictEqual(path.win32.normalize('C:\\.'), 'C:\\');
313 strictEqual(path.win32.normalize('file:stream'), 'file:stream');
314 strictEqual(path.win32.normalize('bar\\foo..\\..\\'), 'bar\\');
315 strictEqual(path.win32.normalize('bar\\foo..\\..'), 'bar');
316 strictEqual(path.win32.normalize('bar\\foo..\\..\\baz'), 'bar\\baz');
317 strictEqual(path.win32.normalize('bar\\foo..\\'), 'bar\\foo..\\');
318 strictEqual(path.win32.normalize('bar\\foo..'), 'bar\\foo..');
319 strictEqual(path.win32.normalize('..\\foo..\\..\\..\\bar'), '..\\..\\bar');
320 strictEqual(
321 path.win32.normalize('..\\...\\..\\.\\...\\..\\..\\bar'),
322 '..\\..\\bar'
323 );
324 strictEqual(
325 path.win32.normalize('../../../foo/../../../bar'),
326 '..\\..\\..\\..\\..\\bar'
327 );
328 strictEqual(
329 path.win32.normalize('../../../foo/../../../bar/../../'),
330 '..\\..\\..\\..\\..\\..\\'
331 );
332 strictEqual(
333 path.win32.normalize('../foobar/barfoo/foo/../../../bar/../../'),
334 '..\\..\\'
335 );
336 strictEqual(
337 path.win32.normalize('../.../../foobar/../../../bar/../../baz'),
338 '..\\..\\..\\..\\baz'
339 );
340 strictEqual(path.win32.normalize('foo/bar\\baz'), 'foo\\bar\\baz');
341 
342 strictEqual(
343 path.posix.normalize('./fixtures///b/../b/c.js'),
344 'fixtures/b/c.js'
345 );
346 strictEqual(path.posix.normalize('/foo/../../../bar'), '/bar');
347 strictEqual(path.posix.normalize('a//b//../b'), 'a/b');
348 strictEqual(path.posix.normalize('a//b//./c'), 'a/b/c');
349 strictEqual(path.posix.normalize('a//b//.'), 'a/b');
350 strictEqual(path.posix.normalize('/a/b/c/../../../x/y/z'), '/x/y/z');
351 strictEqual(path.posix.normalize('///..//./foo/.//bar'), '/foo/bar');
352 strictEqual(path.posix.normalize('bar/foo../../'), 'bar/');
353 strictEqual(path.posix.normalize('bar/foo../..'), 'bar');
354 strictEqual(path.posix.normalize('bar/foo../../baz'), 'bar/baz');
355 strictEqual(path.posix.normalize('bar/foo../'), 'bar/foo../');
356 strictEqual(path.posix.normalize('bar/foo..'), 'bar/foo..');
357 strictEqual(path.posix.normalize('../foo../../../bar'), '../../bar');
358 strictEqual(path.posix.normalize('../.../.././.../../../bar'), '../../bar');
359 strictEqual(
360 path.posix.normalize('../../../foo/../../../bar'),
361 '../../../../../bar'
362 );
363 strictEqual(
364 path.posix.normalize('../../../foo/../../../bar/../../'),
365 '../../../../../../'
366 );
367 strictEqual(
368 path.posix.normalize('../foobar/barfoo/foo/../../../bar/../../'),
369 '../../'
370 );
371 strictEqual(
372 path.posix.normalize('../.../../foobar/../../../bar/../../baz'),
373 '../../../../baz'
374 );
375 strictEqual(path.posix.normalize('foo/bar\\baz'), 'foo/bar\\baz');
376 },
377};
378 
379export const test_path_join = {
380 test(ctrl, env, ctx) {
381 const failures = [];
382 const _backslashRE = /\\/g;
383 
384 const joinTests = [
385 [['.', 'x/b', '..', '/b/c.js'], 'x/b/c.js'],
386 [[], '.'],
387 [['/.', 'x/b', '..', '/b/c.js'], '/x/b/c.js'],
388 [['/foo', '../../../bar'], '/bar'],
389 [['foo', '../../../bar'], '../../bar'],
390 [['foo/', '../../../bar'], '../../bar'],
391 [['foo/x', '../../../bar'], '../bar'],
392 [['foo/x', './bar'], 'foo/x/bar'],
393 [['foo/x/', './bar'], 'foo/x/bar'],
394 [['foo/x/', '.', 'bar'], 'foo/x/bar'],
395 [['./'], './'],
396 [['.', './'], './'],
397 [['.', '.', '.'], '.'],
398 [['.', './', '.'], '.'],
399 [['.', '/./', '.'], '.'],
400 [['.', '/////./', '.'], '.'],
401 [['.'], '.'],
402 [['', '.'], '.'],
403 [['', 'foo'], 'foo'],
404 [['foo', '/bar'], 'foo/bar'],
405 [['', '/foo'], '/foo'],
406 [['', '', '/foo'], '/foo'],
407 [['', '', 'foo'], 'foo'],
408 [['foo', ''], 'foo'],
409 [['foo/', ''], 'foo/'],
410 [['foo', '', '/bar'], 'foo/bar'],
411 [['./', '..', '/foo'], '../foo'],
412 [['./', '..', '..', '/foo'], '../../foo'],
413 [['.', '..', '..', '/foo'], '../../foo'],
414 [['', '..', '..', '/foo'], '../../foo'],
415 [['/'], '/'],
416 [['/', '.'], '/'],
417 [['/', '..'], '/'],
418 [['/', '..', '..'], '/'],
419 [[''], '.'],
420 [['', ''], '.'],
421 [[' /foo'], ' /foo'],
422 [[' ', 'foo'], ' /foo'],
423 [[' ', '.'], ' '],
424 [[' ', '/'], ' /'],
425 [[' ', ''], ' '],
426 [['/', 'foo'], '/foo'],
427 [['/', '/foo'], '/foo'],
428 [['/', '//foo'], '/foo'],
429 [['/', '', '/foo'], '/foo'],
430 [['', '/', 'foo'], '/foo'],
431 [['', '/', '/foo'], '/foo'],
432 ];
433 
434 joinTests.forEach((test) => {
435 const actual = path.join.apply(null, test[0]);
436 const expected = test[1];
437 // eslint-disable-next-line no-undef
438 if (actual !== expected && actualAlt !== expected) {
439 const delimiter = test[0].map(JSON.stringify).join(',');
440 const message = `path.posix.join(${delimiter})\n expect=${JSON.stringify(
441 expected
442 )}\n actual=${JSON.stringify(actual)}`;
443 failures.push(`\n${message}`);
444 }
445 });
446 strictEqual(failures.length, 0, failures.join(''));
447 },
448};
449 
450export const test_path_isabsolute = {
451 test(ctrl, env, ctx) {
452 strictEqual(path.posix.isAbsolute('/home/foo'), true);
453 strictEqual(path.posix.isAbsolute('/home/foo/..'), true);
454 strictEqual(path.posix.isAbsolute('bar/'), false);
455 strictEqual(path.posix.isAbsolute('./baz'), false);
456 strictEqual(path.isAbsolute('/home/foo'), true);
457 strictEqual(path.isAbsolute('/home/foo/..'), true);
458 strictEqual(path.isAbsolute('bar/'), false);
459 strictEqual(path.isAbsolute('./baz'), false);
460 },
461};
462 
463export const test_path_extname = {
464 test(ctrl, env, ctx) {
465 const failures = [];
466 const _slashRE = /\//g;
467 
468 [
469 ['', ''],
470 ['/path/to/file', ''],
471 ['/path/to/file.ext', '.ext'],
472 ['/path.to/file.ext', '.ext'],
473 ['/path.to/file', ''],
474 ['/path.to/.file', ''],
475 ['/path.to/.file.ext', '.ext'],
476 ['/path/to/f.ext', '.ext'],
477 ['/path/to/..ext', '.ext'],
478 ['/path/to/..', ''],
479 ['file', ''],
480 ['file.ext', '.ext'],
481 ['.file', ''],
482 ['.file.ext', '.ext'],
483 ['/file', ''],
484 ['/file.ext', '.ext'],
485 ['/.file', ''],
486 ['/.file.ext', '.ext'],
487 ['.path/file.ext', '.ext'],
488 ['file.ext.ext', '.ext'],
489 ['file.', '.'],
490 ['.', ''],
491 ['./', ''],
492 ['.file.ext', '.ext'],
493 ['.file', ''],
494 ['.file.', '.'],
495 ['.file..', '.'],
496 ['..', ''],
497 ['../', ''],
498 ['..file.ext', '.ext'],
499 ['..file', '.file'],
500 ['..file.', '.'],
501 ['..file..', '.'],
502 ['...', '.'],
503 ['...ext', '.ext'],
504 ['....', '.'],
505 ['file.ext/', '.ext'],
506 ['file.ext//', '.ext'],
507 ['file/', ''],
508 ['file//', ''],
509 ['file./', '.'],
510 ['file.//', '.'],
511 ].forEach((test) => {
512 const expected = test[1];
513 const actual = path.extname(test[0]);
514 const message = `path.posix.extname(${JSON.stringify(test[0])})\n expect=${JSON.stringify(
515 expected
516 )}\n actual=${JSON.stringify(actual)}`;
517 if (actual !== expected) failures.push(`\n${message}`);
518 });
519 
520 strictEqual(failures.length, 0, failures.join(''));
521 
522 // On *nix, backslash is a valid name component like any other character.
523 strictEqual(path.posix.extname('.\\'), '');
524 strictEqual(path.posix.extname('..\\'), '.\\');
525 strictEqual(path.posix.extname('file.ext\\'), '.ext\\');
526 strictEqual(path.posix.extname('file.ext\\\\'), '.ext\\\\');
527 strictEqual(path.posix.extname('file\\'), '');
528 strictEqual(path.posix.extname('file\\\\'), '');
529 strictEqual(path.posix.extname('file.\\'), '.\\');
530 strictEqual(path.posix.extname('file.\\\\'), '.\\\\');
531 },
532};
533 
534export const test_path_dirname = {
535 test(ctrl, env, ctx) {
536 strictEqual(path.posix.dirname('/a/b/'), '/a');
537 strictEqual(path.posix.dirname('/a/b'), '/a');
538 strictEqual(path.posix.dirname('/a'), '/');
539 strictEqual(path.posix.dirname(''), '.');
540 strictEqual(path.posix.dirname('/'), '/');
541 strictEqual(path.posix.dirname('////'), '/');
542 strictEqual(path.posix.dirname('//a'), '//');
543 strictEqual(path.posix.dirname('foo'), '.');
544 strictEqual(path.dirname('/a/b/'), '/a');
545 strictEqual(path.dirname('/a/b'), '/a');
546 strictEqual(path.dirname('/a'), '/');
547 strictEqual(path.dirname(''), '.');
548 strictEqual(path.dirname('/'), '/');
549 strictEqual(path.dirname('////'), '/');
550 strictEqual(path.dirname('//a'), '//');
551 strictEqual(path.dirname('foo'), '.');
552 },
553};
554 
555export const test_path_basename = {
556 test(ctrl, env, ctx) {
557 strictEqual(path.basename('.js', '.js'), '');
558 strictEqual(path.basename('js', '.js'), 'js');
559 strictEqual(path.basename('file.js', '.ts'), 'file.js');
560 strictEqual(path.basename('file', '.js'), 'file');
561 strictEqual(path.basename('file.js.old', '.js.old'), 'file');
562 strictEqual(path.basename(''), '');
563 strictEqual(path.basename('/dir/basename.ext'), 'basename.ext');
564 strictEqual(path.basename('/basename.ext'), 'basename.ext');
565 strictEqual(path.basename('basename.ext'), 'basename.ext');
566 strictEqual(path.basename('basename.ext/'), 'basename.ext');
567 strictEqual(path.basename('basename.ext//'), 'basename.ext');
568 strictEqual(path.basename('aaa/bbb', '/bbb'), 'bbb');
569 strictEqual(path.basename('aaa/bbb', 'a/bbb'), 'bbb');
570 strictEqual(path.basename('aaa/bbb', 'bbb'), 'bbb');
571 strictEqual(path.basename('aaa/bbb//', 'bbb'), 'bbb');
572 strictEqual(path.basename('aaa/bbb', 'bb'), 'b');
573 strictEqual(path.basename('aaa/bbb', 'b'), 'bb');
574 strictEqual(path.basename('/aaa/bbb', '/bbb'), 'bbb');
575 strictEqual(path.basename('/aaa/bbb', 'a/bbb'), 'bbb');
576 strictEqual(path.basename('/aaa/bbb', 'bbb'), 'bbb');
577 strictEqual(path.basename('/aaa/bbb//', 'bbb'), 'bbb');
578 strictEqual(path.basename('/aaa/bbb', 'bb'), 'b');
579 strictEqual(path.basename('/aaa/bbb', 'b'), 'bb');
580 strictEqual(path.basename('/aaa/bbb'), 'bbb');
581 strictEqual(path.basename('/aaa/'), 'aaa');
582 strictEqual(path.basename('/aaa/b'), 'b');
583 strictEqual(path.basename('/a/b'), 'b');
584 strictEqual(path.basename('//a'), 'a');
585 strictEqual(path.basename('a', 'a'), '');
586 
587 // On unix a backslash is just treated as any other character.
588 strictEqual(
589 path.posix.basename('\\dir\\basename.ext'),
590 '\\dir\\basename.ext'
591 );
592 strictEqual(path.posix.basename('\\basename.ext'), '\\basename.ext');
593 strictEqual(path.posix.basename('basename.ext'), 'basename.ext');
594 strictEqual(path.posix.basename('basename.ext\\'), 'basename.ext\\');
595 strictEqual(path.posix.basename('basename.ext\\\\'), 'basename.ext\\\\');
596 strictEqual(path.posix.basename('foo'), 'foo');
597 
598 // POSIX filenames may include control characters
599 // c.f. http://www.dwheeler.com/essays/fixing-unix-linux-filenames.html
600 const controlCharFilename = `Icon${String.fromCharCode(13)}`;
601 strictEqual(
602 path.posix.basename(`/a/b/${controlCharFilename}`),
603 controlCharFilename
604 );
605 },
606};
607 
608export const make_sure_posix_win32_works = {
609 async test() {
610 {
611 const pathModule = await import('node:path/win32');
612 strictEqual(typeof pathModule.default.resolve, 'function');
613 strictEqual(
614 typeof process.getBuiltinModule('node:path/win32').resolve,
615 'function'
616 );
617 }
618 {
619 const pathModule = await import('node:path/posix');
620 strictEqual(typeof pathModule.default.resolve, 'function');
621 strictEqual(
622 typeof process.getBuiltinModule('node:path/posix').resolve,
623 'function'
624 );
625 }
626 },
627};