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 assert = require('assert');
251cb0ef41Sopenharmony_ciconst path = require('path');
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ciconst winPaths = [
281cb0ef41Sopenharmony_ci  // [path, root]
291cb0ef41Sopenharmony_ci  ['C:\\path\\dir\\index.html', 'C:\\'],
301cb0ef41Sopenharmony_ci  ['C:\\another_path\\DIR\\1\\2\\33\\\\index', 'C:\\'],
311cb0ef41Sopenharmony_ci  ['another_path\\DIR with spaces\\1\\2\\33\\index', ''],
321cb0ef41Sopenharmony_ci  ['\\', '\\'],
331cb0ef41Sopenharmony_ci  ['\\foo\\C:', '\\'],
341cb0ef41Sopenharmony_ci  ['file', ''],
351cb0ef41Sopenharmony_ci  ['file:stream', ''],
361cb0ef41Sopenharmony_ci  ['.\\file', ''],
371cb0ef41Sopenharmony_ci  ['C:', 'C:'],
381cb0ef41Sopenharmony_ci  ['C:.', 'C:'],
391cb0ef41Sopenharmony_ci  ['C:..', 'C:'],
401cb0ef41Sopenharmony_ci  ['C:abc', 'C:'],
411cb0ef41Sopenharmony_ci  ['C:\\', 'C:\\'],
421cb0ef41Sopenharmony_ci  ['C:\\abc', 'C:\\' ],
431cb0ef41Sopenharmony_ci  ['', ''],
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci  // unc
461cb0ef41Sopenharmony_ci  ['\\\\server\\share\\file_path', '\\\\server\\share\\'],
471cb0ef41Sopenharmony_ci  ['\\\\server two\\shared folder\\file path.zip',
481cb0ef41Sopenharmony_ci   '\\\\server two\\shared folder\\'],
491cb0ef41Sopenharmony_ci  ['\\\\teela\\admin$\\system32', '\\\\teela\\admin$\\'],
501cb0ef41Sopenharmony_ci  ['\\\\?\\UNC\\server\\share', '\\\\?\\UNC\\'],
511cb0ef41Sopenharmony_ci];
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ciconst winSpecialCaseParseTests = [
541cb0ef41Sopenharmony_ci  ['t', { base: 't', name: 't', root: '', dir: '', ext: '' }],
551cb0ef41Sopenharmony_ci  ['/foo/bar', { root: '/', dir: '/foo', base: 'bar', ext: '', name: 'bar' }],
561cb0ef41Sopenharmony_ci];
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ciconst winSpecialCaseFormatTests = [
591cb0ef41Sopenharmony_ci  [{ dir: 'some\\dir' }, 'some\\dir\\'],
601cb0ef41Sopenharmony_ci  [{ base: 'index.html' }, 'index.html'],
611cb0ef41Sopenharmony_ci  [{ root: 'C:\\' }, 'C:\\'],
621cb0ef41Sopenharmony_ci  [{ name: 'index', ext: '.html' }, 'index.html'],
631cb0ef41Sopenharmony_ci  [{ dir: 'some\\dir', name: 'index', ext: '.html' }, 'some\\dir\\index.html'],
641cb0ef41Sopenharmony_ci  [{ root: 'C:\\', name: 'index', ext: '.html' }, 'C:\\index.html'],
651cb0ef41Sopenharmony_ci  [{}, ''],
661cb0ef41Sopenharmony_ci];
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ciconst unixPaths = [
691cb0ef41Sopenharmony_ci  // [path, root]
701cb0ef41Sopenharmony_ci  ['/home/user/dir/file.txt', '/'],
711cb0ef41Sopenharmony_ci  ['/home/user/a dir/another File.zip', '/'],
721cb0ef41Sopenharmony_ci  ['/home/user/a dir//another&File.', '/'],
731cb0ef41Sopenharmony_ci  ['/home/user/a$$$dir//another File.zip', '/'],
741cb0ef41Sopenharmony_ci  ['user/dir/another File.zip', ''],
751cb0ef41Sopenharmony_ci  ['file', ''],
761cb0ef41Sopenharmony_ci  ['.\\file', ''],
771cb0ef41Sopenharmony_ci  ['./file', ''],
781cb0ef41Sopenharmony_ci  ['C:\\foo', ''],
791cb0ef41Sopenharmony_ci  ['/', '/'],
801cb0ef41Sopenharmony_ci  ['', ''],
811cb0ef41Sopenharmony_ci  ['.', ''],
821cb0ef41Sopenharmony_ci  ['..', ''],
831cb0ef41Sopenharmony_ci  ['/foo', '/'],
841cb0ef41Sopenharmony_ci  ['/foo.', '/'],
851cb0ef41Sopenharmony_ci  ['/foo.bar', '/'],
861cb0ef41Sopenharmony_ci  ['/.', '/'],
871cb0ef41Sopenharmony_ci  ['/.foo', '/'],
881cb0ef41Sopenharmony_ci  ['/.foo.bar', '/'],
891cb0ef41Sopenharmony_ci  ['/foo/bar.baz', '/'],
901cb0ef41Sopenharmony_ci];
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ciconst unixSpecialCaseFormatTests = [
931cb0ef41Sopenharmony_ci  [{ dir: 'some/dir' }, 'some/dir/'],
941cb0ef41Sopenharmony_ci  [{ base: 'index.html' }, 'index.html'],
951cb0ef41Sopenharmony_ci  [{ root: '/' }, '/'],
961cb0ef41Sopenharmony_ci  [{ name: 'index', ext: '.html' }, 'index.html'],
971cb0ef41Sopenharmony_ci  [{ dir: 'some/dir', name: 'index', ext: '.html' }, 'some/dir/index.html'],
981cb0ef41Sopenharmony_ci  [{ root: '/', name: 'index', ext: '.html' }, '/index.html'],
991cb0ef41Sopenharmony_ci  [{}, ''],
1001cb0ef41Sopenharmony_ci];
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ciconst errors = [
1031cb0ef41Sopenharmony_ci  { method: 'parse', input: [null] },
1041cb0ef41Sopenharmony_ci  { method: 'parse', input: [{}] },
1051cb0ef41Sopenharmony_ci  { method: 'parse', input: [true] },
1061cb0ef41Sopenharmony_ci  { method: 'parse', input: [1] },
1071cb0ef41Sopenharmony_ci  { method: 'parse', input: [] },
1081cb0ef41Sopenharmony_ci  { method: 'format', input: [null] },
1091cb0ef41Sopenharmony_ci  { method: 'format', input: [''] },
1101cb0ef41Sopenharmony_ci  { method: 'format', input: [true] },
1111cb0ef41Sopenharmony_ci  { method: 'format', input: [1] },
1121cb0ef41Sopenharmony_ci];
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_cicheckParseFormat(path.win32, winPaths);
1151cb0ef41Sopenharmony_cicheckParseFormat(path.posix, unixPaths);
1161cb0ef41Sopenharmony_cicheckSpecialCaseParseFormat(path.win32, winSpecialCaseParseTests);
1171cb0ef41Sopenharmony_cicheckErrors(path.win32);
1181cb0ef41Sopenharmony_cicheckErrors(path.posix);
1191cb0ef41Sopenharmony_cicheckFormat(path.win32, winSpecialCaseFormatTests);
1201cb0ef41Sopenharmony_cicheckFormat(path.posix, unixSpecialCaseFormatTests);
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ci// Test removal of trailing path separators
1231cb0ef41Sopenharmony_ciconst trailingTests = [
1241cb0ef41Sopenharmony_ci  [ path.win32.parse,
1251cb0ef41Sopenharmony_ci    [['.\\', { root: '', dir: '', base: '.', ext: '', name: '.' }],
1261cb0ef41Sopenharmony_ci     ['\\\\', { root: '\\', dir: '\\', base: '', ext: '', name: '' }],
1271cb0ef41Sopenharmony_ci     ['\\\\', { root: '\\', dir: '\\', base: '', ext: '', name: '' }],
1281cb0ef41Sopenharmony_ci     ['c:\\foo\\\\\\',
1291cb0ef41Sopenharmony_ci      { root: 'c:\\', dir: 'c:\\', base: 'foo', ext: '', name: 'foo' }],
1301cb0ef41Sopenharmony_ci     ['D:\\foo\\\\\\bar.baz',
1311cb0ef41Sopenharmony_ci      { root: 'D:\\',
1321cb0ef41Sopenharmony_ci        dir: 'D:\\foo\\\\',
1331cb0ef41Sopenharmony_ci        base: 'bar.baz',
1341cb0ef41Sopenharmony_ci        ext: '.baz',
1351cb0ef41Sopenharmony_ci        name: 'bar' },
1361cb0ef41Sopenharmony_ci     ],
1371cb0ef41Sopenharmony_ci    ],
1381cb0ef41Sopenharmony_ci  ],
1391cb0ef41Sopenharmony_ci  [ path.posix.parse,
1401cb0ef41Sopenharmony_ci    [['./', { root: '', dir: '', base: '.', ext: '', name: '.' }],
1411cb0ef41Sopenharmony_ci     ['//', { root: '/', dir: '/', base: '', ext: '', name: '' }],
1421cb0ef41Sopenharmony_ci     ['///', { root: '/', dir: '/', base: '', ext: '', name: '' }],
1431cb0ef41Sopenharmony_ci     ['/foo///', { root: '/', dir: '/', base: 'foo', ext: '', name: 'foo' }],
1441cb0ef41Sopenharmony_ci     ['/foo///bar.baz',
1451cb0ef41Sopenharmony_ci      { root: '/', dir: '/foo//', base: 'bar.baz', ext: '.baz', name: 'bar' },
1461cb0ef41Sopenharmony_ci     ],
1471cb0ef41Sopenharmony_ci    ],
1481cb0ef41Sopenharmony_ci  ],
1491cb0ef41Sopenharmony_ci];
1501cb0ef41Sopenharmony_ciconst failures = [];
1511cb0ef41Sopenharmony_citrailingTests.forEach((test) => {
1521cb0ef41Sopenharmony_ci  const parse = test[0];
1531cb0ef41Sopenharmony_ci  const os = parse === path.win32.parse ? 'win32' : 'posix';
1541cb0ef41Sopenharmony_ci  test[1].forEach((test) => {
1551cb0ef41Sopenharmony_ci    const actual = parse(test[0]);
1561cb0ef41Sopenharmony_ci    const expected = test[1];
1571cb0ef41Sopenharmony_ci    const message = `path.${os}.parse(${JSON.stringify(test[0])})\n  expect=${
1581cb0ef41Sopenharmony_ci      JSON.stringify(expected)}\n  actual=${JSON.stringify(actual)}`;
1591cb0ef41Sopenharmony_ci    const actualKeys = Object.keys(actual);
1601cb0ef41Sopenharmony_ci    const expectedKeys = Object.keys(expected);
1611cb0ef41Sopenharmony_ci    let failed = (actualKeys.length !== expectedKeys.length);
1621cb0ef41Sopenharmony_ci    if (!failed) {
1631cb0ef41Sopenharmony_ci      for (let i = 0; i < actualKeys.length; ++i) {
1641cb0ef41Sopenharmony_ci        const key = actualKeys[i];
1651cb0ef41Sopenharmony_ci        if (!expectedKeys.includes(key) || actual[key] !== expected[key]) {
1661cb0ef41Sopenharmony_ci          failed = true;
1671cb0ef41Sopenharmony_ci          break;
1681cb0ef41Sopenharmony_ci        }
1691cb0ef41Sopenharmony_ci      }
1701cb0ef41Sopenharmony_ci    }
1711cb0ef41Sopenharmony_ci    if (failed)
1721cb0ef41Sopenharmony_ci      failures.push(`\n${message}`);
1731cb0ef41Sopenharmony_ci  });
1741cb0ef41Sopenharmony_ci});
1751cb0ef41Sopenharmony_ciassert.strictEqual(failures.length, 0, failures.join(''));
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_cifunction checkErrors(path) {
1781cb0ef41Sopenharmony_ci  errors.forEach(({ method, input }) => {
1791cb0ef41Sopenharmony_ci    assert.throws(() => {
1801cb0ef41Sopenharmony_ci      path[method].apply(path, input);
1811cb0ef41Sopenharmony_ci    }, {
1821cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE',
1831cb0ef41Sopenharmony_ci      name: 'TypeError'
1841cb0ef41Sopenharmony_ci    });
1851cb0ef41Sopenharmony_ci  });
1861cb0ef41Sopenharmony_ci}
1871cb0ef41Sopenharmony_ci
1881cb0ef41Sopenharmony_cifunction checkParseFormat(path, paths) {
1891cb0ef41Sopenharmony_ci  paths.forEach(([element, root]) => {
1901cb0ef41Sopenharmony_ci    const output = path.parse(element);
1911cb0ef41Sopenharmony_ci    assert.strictEqual(typeof output.root, 'string');
1921cb0ef41Sopenharmony_ci    assert.strictEqual(typeof output.dir, 'string');
1931cb0ef41Sopenharmony_ci    assert.strictEqual(typeof output.base, 'string');
1941cb0ef41Sopenharmony_ci    assert.strictEqual(typeof output.ext, 'string');
1951cb0ef41Sopenharmony_ci    assert.strictEqual(typeof output.name, 'string');
1961cb0ef41Sopenharmony_ci    assert.strictEqual(path.format(output), element);
1971cb0ef41Sopenharmony_ci    assert.strictEqual(output.root, root);
1981cb0ef41Sopenharmony_ci    assert(output.dir.startsWith(output.root));
1991cb0ef41Sopenharmony_ci    assert.strictEqual(output.dir, output.dir ? path.dirname(element) : '');
2001cb0ef41Sopenharmony_ci    assert.strictEqual(output.base, path.basename(element));
2011cb0ef41Sopenharmony_ci    assert.strictEqual(output.ext, path.extname(element));
2021cb0ef41Sopenharmony_ci  });
2031cb0ef41Sopenharmony_ci}
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_cifunction checkSpecialCaseParseFormat(path, testCases) {
2061cb0ef41Sopenharmony_ci  testCases.forEach(([element, expect]) => {
2071cb0ef41Sopenharmony_ci    assert.deepStrictEqual(path.parse(element), expect);
2081cb0ef41Sopenharmony_ci  });
2091cb0ef41Sopenharmony_ci}
2101cb0ef41Sopenharmony_ci
2111cb0ef41Sopenharmony_cifunction checkFormat(path, testCases) {
2121cb0ef41Sopenharmony_ci  testCases.forEach(([element, expect]) => {
2131cb0ef41Sopenharmony_ci    assert.strictEqual(path.format(element), expect);
2141cb0ef41Sopenharmony_ci  });
2151cb0ef41Sopenharmony_ci
2161cb0ef41Sopenharmony_ci  [null, undefined, 1, true, false, 'string'].forEach((pathObject) => {
2171cb0ef41Sopenharmony_ci    assert.throws(() => {
2181cb0ef41Sopenharmony_ci      path.format(pathObject);
2191cb0ef41Sopenharmony_ci    }, {
2201cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE',
2211cb0ef41Sopenharmony_ci      name: 'TypeError',
2221cb0ef41Sopenharmony_ci      message: 'The "pathObject" argument must be of type object.' +
2231cb0ef41Sopenharmony_ci               common.invalidArgTypeHelper(pathObject)
2241cb0ef41Sopenharmony_ci    });
2251cb0ef41Sopenharmony_ci  });
2261cb0ef41Sopenharmony_ci}
227