mirror of
https://github.com/nodejs/node.git
synced 2025-08-15 13:48:44 +02:00
test: split test-fs-cp.js
This test previously squeezed 70+ test cases into one single file and has been constantly crashing on Windows with exit code 3221226505 and no stack trace. As it is already marked as flaky there is no way to understand which test case is failing and the Windows CI was constantly orange. This patch splits the test cases into different files so it's easier to find out which case is exactly failing and to be skipped. PR-URL: https://github.com/nodejs/node/pull/59408 Refs: https://github.com/nodejs/node/issues/56794 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Zeyu "Alex" Yang <himself65@outlook.com> Reviewed-By: Daeyeon Jeong <daeyeon.dev@gmail.com> Reviewed-By: Filip Skokan <panva.ip@gmail.com>
This commit is contained in:
parent
ca76b39356
commit
aac7925801
77 changed files with 1585 additions and 1100 deletions
49
test/common/fs.js
Normal file
49
test/common/fs.js
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const { mustNotMutateObjectDeep } = require('.');
|
||||||
|
const { readdirSync } = require('node:fs');
|
||||||
|
const { join } = require('node:path');
|
||||||
|
const assert = require('node:assert');
|
||||||
|
const tmpdir = require('./tmpdir.js');
|
||||||
|
|
||||||
|
let dirc = 0;
|
||||||
|
function nextdir(dirname) {
|
||||||
|
return tmpdir.resolve(dirname || `copy_%${++dirc}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function assertDirEquivalent(dir1, dir2) {
|
||||||
|
const dir1Entries = [];
|
||||||
|
collectEntries(dir1, dir1Entries);
|
||||||
|
const dir2Entries = [];
|
||||||
|
collectEntries(dir2, dir2Entries);
|
||||||
|
assert.strictEqual(dir1Entries.length, dir2Entries.length);
|
||||||
|
for (const entry1 of dir1Entries) {
|
||||||
|
const entry2 = dir2Entries.find((entry) => {
|
||||||
|
return entry.name === entry1.name;
|
||||||
|
});
|
||||||
|
assert(entry2, `entry ${entry2.name} not copied`);
|
||||||
|
if (entry1.isFile()) {
|
||||||
|
assert(entry2.isFile(), `${entry2.name} was not file`);
|
||||||
|
} else if (entry1.isDirectory()) {
|
||||||
|
assert(entry2.isDirectory(), `${entry2.name} was not directory`);
|
||||||
|
} else if (entry1.isSymbolicLink()) {
|
||||||
|
assert(entry2.isSymbolicLink(), `${entry2.name} was not symlink`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function collectEntries(dir, dirEntries) {
|
||||||
|
const newEntries = readdirSync(dir, mustNotMutateObjectDeep({ withFileTypes: true }));
|
||||||
|
for (const entry of newEntries) {
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
collectEntries(join(dir, entry.name), dirEntries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dirEntries.push(...newEntries);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
nextdir,
|
||||||
|
assertDirEquivalent,
|
||||||
|
collectEntries,
|
||||||
|
};
|
|
@ -24,8 +24,14 @@ test-snapshot-incompatible: SKIP
|
||||||
test-async-context-frame: PASS, FLAKY
|
test-async-context-frame: PASS, FLAKY
|
||||||
# https://github.com/nodejs/node/issues/54534
|
# https://github.com/nodejs/node/issues/54534
|
||||||
test-runner-run-watch: PASS, FLAKY
|
test-runner-run-watch: PASS, FLAKY
|
||||||
# https://github.com/nodejs/node/issues/56794
|
# https://github.com/nodejs/node/pull/59408#issuecomment-3170650933
|
||||||
test-fs-cp: PASS, FLAKY
|
test-fs-cp-sync-error-on-exist: PASS, FLAKY
|
||||||
|
test-fs-cp-sync-copy-symlink-not-pointing-to-folder: PASS, FLAKY
|
||||||
|
test-fs-cp-sync-symlink-points-to-dest-error: PASS, FLAKY
|
||||||
|
test-fs-cp-sync-resolve-relative-symlinks-false: PASS, FLAKY
|
||||||
|
test-fs-cp-async-symlink-points-to-dest: PASS, FLAKY
|
||||||
|
test-fs-cp-sync-unicode-folder-names: PASS, FLAKY
|
||||||
|
test-fs-cp-sync-resolve-relative-symlinks-default: PASS, FLAKY
|
||||||
|
|
||||||
# https://github.com/nodejs/node/issues/56751
|
# https://github.com/nodejs/node/issues/56751
|
||||||
test-without-async-context-frame: PASS, FLAKY
|
test-without-async-context-frame: PASS, FLAKY
|
||||||
|
|
32
test/parallel/test-fs-cp-async-async-filter-function.mjs
Normal file
32
test/parallel/test-fs-cp-async-async-filter-function.mjs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
// This tests that cp() supports async filter function.
|
||||||
|
|
||||||
|
import { mustCall } from '../common/index.mjs';
|
||||||
|
import { nextdir, collectEntries } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp, statSync } from 'node:fs';
|
||||||
|
import { setTimeout } from 'node:timers/promises';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
const dest = nextdir();
|
||||||
|
cp(src, dest, {
|
||||||
|
filter: async (path) => {
|
||||||
|
await setTimeout(5, 'done');
|
||||||
|
const pathStat = statSync(path);
|
||||||
|
return pathStat.isDirectory() || path.endsWith('.js');
|
||||||
|
},
|
||||||
|
dereference: true,
|
||||||
|
recursive: true,
|
||||||
|
}, mustCall((err) => {
|
||||||
|
assert.strictEqual(err, null);
|
||||||
|
const destEntries = [];
|
||||||
|
collectEntries(dest, destEntries);
|
||||||
|
for (const entry of destEntries) {
|
||||||
|
assert.strictEqual(
|
||||||
|
entry.isDirectory() || entry.name.endsWith('.js'),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}));
|
|
@ -0,0 +1,22 @@
|
||||||
|
// This tests that cp() copies link if it does not point to folder in src.
|
||||||
|
|
||||||
|
import { mustCall, mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp, mkdirSync, readlinkSync, symlinkSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = nextdir();
|
||||||
|
mkdirSync(join(src, 'a', 'b'), mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
symlinkSync(src, join(src, 'a', 'c'));
|
||||||
|
const dest = nextdir();
|
||||||
|
mkdirSync(join(dest, 'a'), mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
symlinkSync(dest, join(dest, 'a', 'c'));
|
||||||
|
cp(src, dest, mustNotMutateObjectDeep({ recursive: true }), mustCall((err) => {
|
||||||
|
assert.strictEqual(err, null);
|
||||||
|
const link = readlinkSync(join(dest, 'a', 'c'));
|
||||||
|
assert.strictEqual(link, src);
|
||||||
|
}));
|
|
@ -0,0 +1,25 @@
|
||||||
|
// This tests that it does not fail if the same directory is copied to dest
|
||||||
|
// twice, when dereference is true, and force is false (fails silently).
|
||||||
|
|
||||||
|
import { mustCall, mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp, cpSync, lstatSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
const dest = nextdir();
|
||||||
|
const destFile = join(dest, 'a/b/README2.md');
|
||||||
|
cpSync(src, dest, mustNotMutateObjectDeep({ dereference: true, recursive: true }));
|
||||||
|
cp(src, dest, {
|
||||||
|
dereference: true,
|
||||||
|
recursive: true
|
||||||
|
}, mustCall((err) => {
|
||||||
|
assert.strictEqual(err, null);
|
||||||
|
const stat = lstatSync(destFile);
|
||||||
|
assert(stat.isFile());
|
||||||
|
}));
|
27
test/parallel/test-fs-cp-async-dereference-symlink.mjs
Normal file
27
test/parallel/test-fs-cp-async-dereference-symlink.mjs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
// This tests that cp() copies file itself, rather than symlink, when dereference is true.
|
||||||
|
|
||||||
|
import { mustCall, mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp, lstatSync, mkdirSync, symlinkSync, writeFileSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = nextdir();
|
||||||
|
mkdirSync(src, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
writeFileSync(join(src, 'foo.js'), 'foo', 'utf8');
|
||||||
|
symlinkSync(join(src, 'foo.js'), join(src, 'bar.js'));
|
||||||
|
|
||||||
|
const dest = nextdir();
|
||||||
|
mkdirSync(dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
const destFile = join(dest, 'foo.js');
|
||||||
|
|
||||||
|
cp(join(src, 'bar.js'), destFile, mustNotMutateObjectDeep({ dereference: true }),
|
||||||
|
mustCall((err) => {
|
||||||
|
assert.strictEqual(err, null);
|
||||||
|
const stat = lstatSync(destFile);
|
||||||
|
assert(stat.isFile());
|
||||||
|
})
|
||||||
|
);
|
|
@ -0,0 +1,21 @@
|
||||||
|
// This tests that cp() returns error if parent directory of symlink in dest points to src.
|
||||||
|
|
||||||
|
import { mustCall, mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp, mkdirSync, symlinkSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = nextdir();
|
||||||
|
mkdirSync(join(src, 'a'), mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
const dest = nextdir();
|
||||||
|
// Create symlink in dest pointing to src.
|
||||||
|
const destLink = join(dest, 'b');
|
||||||
|
mkdirSync(dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
symlinkSync(src, destLink);
|
||||||
|
cp(src, join(dest, 'b', 'c'), mustCall((err) => {
|
||||||
|
assert.strictEqual(err.code, 'ERR_FS_CP_EINVAL');
|
||||||
|
}));
|
17
test/parallel/test-fs-cp-async-dir-to-file.mjs
Normal file
17
test/parallel/test-fs-cp-async-dir-to-file.mjs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// This tests that cp() returns error if attempt is made to copy directory to file.
|
||||||
|
|
||||||
|
import { mustCall, mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp, mkdirSync } from 'node:fs';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = nextdir();
|
||||||
|
mkdirSync(src, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
const dest = fixtures.path('copy/kitchen-sink/README.md');
|
||||||
|
cp(src, dest, mustCall((err) => {
|
||||||
|
assert.strictEqual(err.code, 'ERR_FS_CP_DIR_TO_NON_DIR');
|
||||||
|
}));
|
22
test/parallel/test-fs-cp-async-error-on-exist.mjs
Normal file
22
test/parallel/test-fs-cp-async-error-on-exist.mjs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// This tests that cp() returns error if errorOnExist is true, force is false, and file or folder copied over.
|
||||||
|
|
||||||
|
import { mustCall, mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp, cpSync } from 'node:fs';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
const dest = nextdir();
|
||||||
|
cpSync(src, dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
cp(src, dest, {
|
||||||
|
dereference: true,
|
||||||
|
errorOnExist: true,
|
||||||
|
force: false,
|
||||||
|
recursive: true,
|
||||||
|
}, mustCall((err) => {
|
||||||
|
assert.strictEqual(err.code, 'ERR_FS_CP_EEXIST');
|
||||||
|
}));
|
17
test/parallel/test-fs-cp-async-file-to-dir.mjs
Normal file
17
test/parallel/test-fs-cp-async-file-to-dir.mjs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// This tests that cp() returns error if attempt is made to copy file to directory.
|
||||||
|
|
||||||
|
import { mustCall, mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp, mkdirSync } from 'node:fs';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink/README.md');
|
||||||
|
const dest = nextdir();
|
||||||
|
mkdirSync(dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
cp(src, dest, mustCall((err) => {
|
||||||
|
assert.strictEqual(err.code, 'ERR_FS_CP_NON_DIR_TO_DIR');
|
||||||
|
}));
|
19
test/parallel/test-fs-cp-async-file-to-file.mjs
Normal file
19
test/parallel/test-fs-cp-async-file-to-file.mjs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
// This tests that cp() allows file to be copied to a file path.
|
||||||
|
|
||||||
|
import { mustCall, mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp, lstatSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const srcFile = fixtures.path('copy/kitchen-sink/README.md');
|
||||||
|
const destFile = join(nextdir(), 'index.js');
|
||||||
|
cp(srcFile, destFile, mustNotMutateObjectDeep({ dereference: true }), mustCall((err) => {
|
||||||
|
assert.strictEqual(err, null);
|
||||||
|
const stat = lstatSync(destFile);
|
||||||
|
assert(stat.isFile());
|
||||||
|
}));
|
18
test/parallel/test-fs-cp-async-file-url.mjs
Normal file
18
test/parallel/test-fs-cp-async-file-url.mjs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// This tests that it accepts file URL as src and dest.
|
||||||
|
|
||||||
|
import { mustCall, mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp } from 'node:fs';
|
||||||
|
import { pathToFileURL } from 'node:url';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import { assertDirEquivalent, nextdir } from '../common/fs.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = './test/fixtures/copy/kitchen-sink';
|
||||||
|
const dest = nextdir();
|
||||||
|
cp(pathToFileURL(src), pathToFileURL(dest), mustNotMutateObjectDeep({ recursive: true }),
|
||||||
|
mustCall((err) => {
|
||||||
|
assert.strictEqual(err, null);
|
||||||
|
assertDirEquivalent(src, dest);
|
||||||
|
}));
|
26
test/parallel/test-fs-cp-async-filter-child-folder.mjs
Normal file
26
test/parallel/test-fs-cp-async-filter-child-folder.mjs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
// This tests that cp() should not throw exception if child folder is filtered out.
|
||||||
|
|
||||||
|
import { mustCall, mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp, cpSync, mkdirSync, writeFileSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = nextdir();
|
||||||
|
mkdirSync(join(src, 'test-cp'), mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
|
||||||
|
const dest = nextdir();
|
||||||
|
mkdirSync(dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
writeFileSync(join(dest, 'test-cp'), 'test-content', mustNotMutateObjectDeep({ mode: 0o444 }));
|
||||||
|
|
||||||
|
const opts = {
|
||||||
|
filter: (path) => !path.includes('test-cp'),
|
||||||
|
recursive: true,
|
||||||
|
};
|
||||||
|
cp(src, dest, opts, mustCall((err) => {
|
||||||
|
assert.strictEqual(err, null);
|
||||||
|
}));
|
||||||
|
cpSync(src, dest, opts);
|
31
test/parallel/test-fs-cp-async-filter-function.mjs
Normal file
31
test/parallel/test-fs-cp-async-filter-function.mjs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// This tests that cp() applies filter function.
|
||||||
|
|
||||||
|
import { mustCall } from '../common/index.mjs';
|
||||||
|
import { nextdir, collectEntries } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp, statSync } from 'node:fs';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
const dest = nextdir();
|
||||||
|
cp(src, dest, {
|
||||||
|
filter: (path) => {
|
||||||
|
const pathStat = statSync(path);
|
||||||
|
return pathStat.isDirectory() || path.endsWith('.js');
|
||||||
|
},
|
||||||
|
dereference: true,
|
||||||
|
recursive: true,
|
||||||
|
}, mustCall((err) => {
|
||||||
|
assert.strictEqual(err, null);
|
||||||
|
const destEntries = [];
|
||||||
|
collectEntries(dest, destEntries);
|
||||||
|
for (const entry of destEntries) {
|
||||||
|
assert.strictEqual(
|
||||||
|
entry.isDirectory() || entry.name.endsWith('.js'),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}));
|
14
test/parallel/test-fs-cp-async-identical-src-dest.mjs
Normal file
14
test/parallel/test-fs-cp-async-identical-src-dest.mjs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// This tests that cp() returns error when src and dest are identical.
|
||||||
|
|
||||||
|
import { mustCall } from '../common/index.mjs';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp } from 'node:fs';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
cp(src, src, mustCall((err) => {
|
||||||
|
assert.strictEqual(err.code, 'ERR_FS_CP_EINVAL');
|
||||||
|
}));
|
13
test/parallel/test-fs-cp-async-invalid-mode-range.mjs
Normal file
13
test/parallel/test-fs-cp-async-invalid-mode-range.mjs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// This tests that cp() throws if mode is out of range.
|
||||||
|
|
||||||
|
import '../common/index.mjs';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp } from 'node:fs';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => cp('a', 'b', { mode: -1 }, () => {}),
|
||||||
|
{ code: 'ERR_OUT_OF_RANGE' }
|
||||||
|
);
|
13
test/parallel/test-fs-cp-async-invalid-options-type.mjs
Normal file
13
test/parallel/test-fs-cp-async-invalid-options-type.mjs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// This tests that cp() throws if options is not object.
|
||||||
|
|
||||||
|
import '../common/index.mjs';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp } from 'node:fs';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => cp('a', 'b', 'hello', () => {}),
|
||||||
|
{ code: 'ERR_INVALID_ARG_TYPE' }
|
||||||
|
);
|
17
test/parallel/test-fs-cp-async-nested-files-folders.mjs
Normal file
17
test/parallel/test-fs-cp-async-nested-files-folders.mjs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// This tests that cp() copies a nested folder structure with files and folders.
|
||||||
|
|
||||||
|
import { mustCall, mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir, assertDirEquivalent } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp } from 'node:fs';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
const dest = nextdir();
|
||||||
|
cp(src, dest, mustNotMutateObjectDeep({ recursive: true }), mustCall((err) => {
|
||||||
|
assert.strictEqual(err, null);
|
||||||
|
assertDirEquivalent(src, dest);
|
||||||
|
}));
|
28
test/parallel/test-fs-cp-async-no-errors-force-false.mjs
Normal file
28
test/parallel/test-fs-cp-async-no-errors-force-false.mjs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
// This tests that it does not throw errors when directory is copied over and force is false.
|
||||||
|
|
||||||
|
import { mustCall, mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp, cpSync, lstatSync, mkdirSync, writeFileSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import { assertDirEquivalent, nextdir } from '../common/fs.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = nextdir();
|
||||||
|
mkdirSync(join(src, 'a', 'b'), mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
writeFileSync(join(src, 'README.md'), 'hello world', 'utf8');
|
||||||
|
const dest = nextdir();
|
||||||
|
cpSync(src, dest, mustNotMutateObjectDeep({ dereference: true, recursive: true }));
|
||||||
|
const initialStat = lstatSync(join(dest, 'README.md'));
|
||||||
|
cp(src, dest, {
|
||||||
|
dereference: true,
|
||||||
|
force: false,
|
||||||
|
recursive: true,
|
||||||
|
}, mustCall((err) => {
|
||||||
|
assert.strictEqual(err, null);
|
||||||
|
assertDirEquivalent(src, dest);
|
||||||
|
// File should not have been copied over, so access times will be identical:
|
||||||
|
const finalStat = lstatSync(join(dest, 'README.md'));
|
||||||
|
assert.strictEqual(finalStat.ctime.getTime(), initialStat.ctime.getTime());
|
||||||
|
}));
|
16
test/parallel/test-fs-cp-async-no-recursive.mjs
Normal file
16
test/parallel/test-fs-cp-async-no-recursive.mjs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// This tests that cp() returns error if directory copied without recursive flag.
|
||||||
|
|
||||||
|
import { mustCall } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp } from 'node:fs';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
const dest = nextdir();
|
||||||
|
cp(src, dest, mustCall((err) => {
|
||||||
|
assert.strictEqual(err.code, 'ERR_FS_EISDIR');
|
||||||
|
}));
|
23
test/parallel/test-fs-cp-async-overwrites-force-true.mjs
Normal file
23
test/parallel/test-fs-cp-async-overwrites-force-true.mjs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// This tests that it overwrites existing files if force is true.
|
||||||
|
|
||||||
|
import { mustCall, mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import { assertDirEquivalent, nextdir } from '../common/fs.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
const dest = nextdir();
|
||||||
|
mkdirSync(dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
writeFileSync(join(dest, 'README.md'), '# Goodbye', 'utf8');
|
||||||
|
|
||||||
|
cp(src, dest, mustNotMutateObjectDeep({ recursive: true }), mustCall((err) => {
|
||||||
|
assert.strictEqual(err, null);
|
||||||
|
assertDirEquivalent(src, dest);
|
||||||
|
const content = readFileSync(join(dest, 'README.md'), 'utf8');
|
||||||
|
assert.strictEqual(content.trim(), '# Hello');
|
||||||
|
}));
|
|
@ -0,0 +1,26 @@
|
||||||
|
// This tests that it makes file writeable when updating timestamp, if not writeable.
|
||||||
|
|
||||||
|
import { mustCall, mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp, lstatSync, mkdirSync, writeFileSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import { assertDirEquivalent, nextdir } from '../common/fs.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = nextdir();
|
||||||
|
mkdirSync(src, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
const dest = nextdir();
|
||||||
|
mkdirSync(dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
writeFileSync(join(src, 'foo.txt'), 'foo', mustNotMutateObjectDeep({ mode: 0o444 }));
|
||||||
|
cp(src, dest, {
|
||||||
|
preserveTimestamps: true,
|
||||||
|
recursive: true,
|
||||||
|
}, mustCall((err) => {
|
||||||
|
assert.strictEqual(err, null);
|
||||||
|
assertDirEquivalent(src, dest);
|
||||||
|
const srcStat = lstatSync(join(src, 'foo.txt'));
|
||||||
|
const destStat = lstatSync(join(dest, 'foo.txt'));
|
||||||
|
assert.strictEqual(srcStat.mtime.getTime(), destStat.mtime.getTime());
|
||||||
|
}));
|
24
test/parallel/test-fs-cp-async-preserve-timestamps.mjs
Normal file
24
test/parallel/test-fs-cp-async-preserve-timestamps.mjs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
// This tests that cp() copies timestamps from src to dest if preserveTimestamps is true.
|
||||||
|
|
||||||
|
import { mustCall } from '../common/index.mjs';
|
||||||
|
import { nextdir, assertDirEquivalent } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp, lstatSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
const dest = nextdir();
|
||||||
|
cp(src, dest, {
|
||||||
|
preserveTimestamps: true,
|
||||||
|
recursive: true
|
||||||
|
}, mustCall((err) => {
|
||||||
|
assert.strictEqual(err, null);
|
||||||
|
assertDirEquivalent(src, dest);
|
||||||
|
const srcStat = lstatSync(join(src, 'index.js'));
|
||||||
|
const destStat = lstatSync(join(dest, 'index.js'));
|
||||||
|
assert.strictEqual(srcStat.mtime.getTime(), destStat.mtime.getTime());
|
||||||
|
}));
|
25
test/parallel/test-fs-cp-async-same-dir-twice.mjs
Normal file
25
test/parallel/test-fs-cp-async-same-dir-twice.mjs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// This tests that it does not fail if the same directory is copied to dest
|
||||||
|
// twice, when dereference is true, and force is false (fails silently).
|
||||||
|
|
||||||
|
import { mustCall, mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp, cpSync, lstatSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
const dest = nextdir();
|
||||||
|
const destFile = join(dest, 'a/b/README2.md');
|
||||||
|
cpSync(src, dest, mustNotMutateObjectDeep({ dereference: true, recursive: true }));
|
||||||
|
cp(src, dest, {
|
||||||
|
dereference: true,
|
||||||
|
recursive: true
|
||||||
|
}, mustCall((err) => {
|
||||||
|
assert.strictEqual(err, null);
|
||||||
|
const stat = lstatSync(destFile);
|
||||||
|
assert(stat.isFile());
|
||||||
|
}));
|
|
@ -0,0 +1,29 @@
|
||||||
|
// This tests that cp() should not throw exception if dest is invalid but filtered out.
|
||||||
|
|
||||||
|
import { mustCall, mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp, cpSync, mkdirSync, writeFileSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
// Create dest as a file.
|
||||||
|
// Expect: cp skips the copy logic entirely and won't throw any exception in path validation process.
|
||||||
|
const src = join(nextdir(), 'bar');
|
||||||
|
mkdirSync(src, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
|
||||||
|
const destParent = nextdir();
|
||||||
|
const dest = join(destParent, 'bar');
|
||||||
|
mkdirSync(destParent, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
writeFileSync(dest, 'test-content', mustNotMutateObjectDeep({ mode: 0o444 }));
|
||||||
|
|
||||||
|
const opts = {
|
||||||
|
filter: (path) => !path.includes('bar'),
|
||||||
|
recursive: true,
|
||||||
|
};
|
||||||
|
cp(src, dest, opts, mustCall((err) => {
|
||||||
|
assert.strictEqual(err, null);
|
||||||
|
}));
|
||||||
|
cpSync(src, dest, opts);
|
34
test/parallel/test-fs-cp-async-socket.mjs
Normal file
34
test/parallel/test-fs-cp-async-socket.mjs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
// This tests that cp() returns an error if attempt is made to copy socket.
|
||||||
|
|
||||||
|
import * as common from '../common/index.mjs';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp, mkdirSync } from 'node:fs';
|
||||||
|
import { createServer } from 'node:net';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
|
||||||
|
const isWindows = process.platform === 'win32';
|
||||||
|
if (isWindows) {
|
||||||
|
common.skip('No socket support on Windows');
|
||||||
|
}
|
||||||
|
|
||||||
|
// See https://github.com/nodejs/node/pull/48409
|
||||||
|
if (common.isInsideDirWithUnusualChars) {
|
||||||
|
common.skip('Test is borken in directories with unusual characters');
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
{
|
||||||
|
const src = nextdir();
|
||||||
|
mkdirSync(src);
|
||||||
|
const dest = nextdir();
|
||||||
|
const sock = join(src, `${process.pid}.sock`);
|
||||||
|
const server = createServer();
|
||||||
|
server.listen(sock);
|
||||||
|
cp(sock, dest, common.mustCall((err) => {
|
||||||
|
assert.strictEqual(err.code, 'ERR_FS_CP_SOCKET');
|
||||||
|
server.close();
|
||||||
|
}));
|
||||||
|
}
|
12
test/parallel/test-fs-cp-async-subdirectory-of-self.mjs
Normal file
12
test/parallel/test-fs-cp-async-subdirectory-of-self.mjs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
// This tests that cp() returns error if attempt is made to copy to subdirectory of self.
|
||||||
|
|
||||||
|
import { mustCall } from '../common/index.mjs';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp } from 'node:fs';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
const dest = fixtures.path('copy/kitchen-sink/a');
|
||||||
|
cp(src, dest, mustCall((err) => {
|
||||||
|
assert.strictEqual(err.code, 'ERR_FS_CP_EINVAL');
|
||||||
|
}));
|
|
@ -0,0 +1,21 @@
|
||||||
|
// This tests that cp() returns error if symlink in dest points to location in src.
|
||||||
|
|
||||||
|
import { mustCall, mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp, mkdirSync, symlinkSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = nextdir();
|
||||||
|
mkdirSync(join(src, 'a', 'b'), mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
symlinkSync(join(src, 'a', 'b'), join(src, 'a', 'c'));
|
||||||
|
|
||||||
|
const dest = nextdir();
|
||||||
|
mkdirSync(join(dest, 'a'), mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
symlinkSync(src, join(dest, 'a', 'c'));
|
||||||
|
cp(src, dest, mustNotMutateObjectDeep({ recursive: true }), mustCall((err) => {
|
||||||
|
assert.strictEqual(err.code, 'ERR_FS_CP_SYMLINK_TO_SUBDIRECTORY');
|
||||||
|
}));
|
21
test/parallel/test-fs-cp-async-symlink-over-file.mjs
Normal file
21
test/parallel/test-fs-cp-async-symlink-over-file.mjs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// This tests that cp() returns EEXIST error if attempt is made to copy symlink over file.
|
||||||
|
|
||||||
|
import { mustCall, mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp, mkdirSync, symlinkSync, writeFileSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = nextdir();
|
||||||
|
mkdirSync(join(src, 'a', 'b'), mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
symlinkSync(join(src, 'a', 'b'), join(src, 'a', 'c'));
|
||||||
|
|
||||||
|
const dest = nextdir();
|
||||||
|
mkdirSync(join(dest, 'a'), mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
writeFileSync(join(dest, 'a', 'c'), 'hello', 'utf8');
|
||||||
|
cp(src, dest, mustNotMutateObjectDeep({ recursive: true }), mustCall((err) => {
|
||||||
|
assert.strictEqual(err.code, 'EEXIST');
|
||||||
|
}));
|
20
test/parallel/test-fs-cp-async-symlink-points-to-dest.mjs
Normal file
20
test/parallel/test-fs-cp-async-symlink-points-to-dest.mjs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// This tests that cp() returns error if symlink in src points to location in dest.
|
||||||
|
|
||||||
|
import { mustCall, mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp, cpSync, mkdirSync, symlinkSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = nextdir();
|
||||||
|
mkdirSync(src, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
const dest = nextdir();
|
||||||
|
mkdirSync(dest);
|
||||||
|
symlinkSync(dest, join(src, 'link'));
|
||||||
|
cpSync(src, dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
cp(src, dest, mustNotMutateObjectDeep({ recursive: true }), mustCall((err) => {
|
||||||
|
assert.strictEqual(err.code, 'ERR_FS_CP_EINVAL');
|
||||||
|
}));
|
31
test/parallel/test-fs-cp-async-with-mode-flags.mjs
Normal file
31
test/parallel/test-fs-cp-async-with-mode-flags.mjs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// This tests that it copies a nested folder structure with mode flags.
|
||||||
|
|
||||||
|
import { mustCall, mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cp, constants } from 'node:fs';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import { assertDirEquivalent, nextdir } from '../common/fs.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
const dest = nextdir();
|
||||||
|
cp(src, dest, mustNotMutateObjectDeep({
|
||||||
|
recursive: true,
|
||||||
|
mode: constants.COPYFILE_FICLONE_FORCE,
|
||||||
|
}), mustCall((err) => {
|
||||||
|
if (!err) {
|
||||||
|
// If the platform support `COPYFILE_FICLONE_FORCE` operation,
|
||||||
|
// it should reach to here.
|
||||||
|
assert.strictEqual(err, null);
|
||||||
|
assertDirEquivalent(src, dest);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the platform does not support `COPYFILE_FICLONE_FORCE` operation,
|
||||||
|
// it should enter this path.
|
||||||
|
assert.strictEqual(err.syscall, 'copyfile');
|
||||||
|
assert(err.code === 'ENOTSUP' || err.code === 'ENOTTY' ||
|
||||||
|
err.code === 'ENOSYS' || err.code === 'EXDEV');
|
||||||
|
}));
|
23
test/parallel/test-fs-cp-promises-async-error.mjs
Normal file
23
test/parallel/test-fs-cp-promises-async-error.mjs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// This tests that fs.promises.cp() allows async error to be caught.
|
||||||
|
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import fs from 'node:fs';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
const dest = nextdir();
|
||||||
|
await fs.promises.cp(src, dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
await assert.rejects(
|
||||||
|
fs.promises.cp(src, dest, {
|
||||||
|
dereference: true,
|
||||||
|
errorOnExist: true,
|
||||||
|
force: false,
|
||||||
|
recursive: true,
|
||||||
|
}),
|
||||||
|
{ code: 'ERR_FS_CP_EEXIST' }
|
||||||
|
);
|
21
test/parallel/test-fs-cp-promises-file-url.mjs
Normal file
21
test/parallel/test-fs-cp-promises-file-url.mjs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// This tests that fs.promises.cp() accepts file URL as src and dest.
|
||||||
|
|
||||||
|
import '../common/index.mjs';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { promises as fs } from 'node:fs';
|
||||||
|
import { pathToFileURL } from 'node:url';
|
||||||
|
import { assertDirEquivalent, nextdir } from '../common/fs.js';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
const dest = nextdir();
|
||||||
|
const p = await fs.cp(
|
||||||
|
pathToFileURL(src),
|
||||||
|
pathToFileURL(dest),
|
||||||
|
{ recursive: true }
|
||||||
|
);
|
||||||
|
assert.strictEqual(p, undefined);
|
||||||
|
assertDirEquivalent(src, dest);
|
15
test/parallel/test-fs-cp-promises-invalid-mode.mjs
Normal file
15
test/parallel/test-fs-cp-promises-invalid-mode.mjs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// This tests that fs.promises.cp() rejects if options.mode is invalid.
|
||||||
|
|
||||||
|
import '../common/index.mjs';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import fs from 'node:fs';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
await assert.rejects(
|
||||||
|
fs.promises.cp('a', 'b', {
|
||||||
|
mode: -1,
|
||||||
|
}),
|
||||||
|
{ code: 'ERR_OUT_OF_RANGE' }
|
||||||
|
);
|
36
test/parallel/test-fs-cp-promises-mode-flags.mjs
Normal file
36
test/parallel/test-fs-cp-promises-mode-flags.mjs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
// This tests that fs.promises.cp() copies a nested folder structure with mode flags.
|
||||||
|
// This test is based on fs.promises.copyFile() with `COPYFILE_FICLONE_FORCE`.
|
||||||
|
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { promises as fs, constants } from 'node:fs';
|
||||||
|
import { assertDirEquivalent, nextdir } from '../common/fs.js';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
const dest = nextdir();
|
||||||
|
let p = null;
|
||||||
|
let successFiClone = false;
|
||||||
|
try {
|
||||||
|
p = await fs.cp(src, dest, mustNotMutateObjectDeep({
|
||||||
|
recursive: true,
|
||||||
|
mode: constants.COPYFILE_FICLONE_FORCE,
|
||||||
|
}));
|
||||||
|
successFiClone = true;
|
||||||
|
} catch (err) {
|
||||||
|
// If the platform does not support `COPYFILE_FICLONE_FORCE` operation,
|
||||||
|
// it should enter this path.
|
||||||
|
assert.strictEqual(err.syscall, 'copyfile');
|
||||||
|
assert(err.code === 'ENOTSUP' || err.code === 'ENOTTY' ||
|
||||||
|
err.code === 'ENOSYS' || err.code === 'EXDEV');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (successFiClone) {
|
||||||
|
// If the platform support `COPYFILE_FICLONE_FORCE` operation,
|
||||||
|
// it should reach to here.
|
||||||
|
assert.strictEqual(p, undefined);
|
||||||
|
assertDirEquivalent(src, dest);
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
// This tests that fs.promises.cp() copies a nested folder structure with files and folders.
|
||||||
|
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir, assertDirEquivalent } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import fs from 'node:fs';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
const dest = nextdir();
|
||||||
|
const p = await fs.promises.cp(src, dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
assert.strictEqual(p, undefined);
|
||||||
|
assertDirEquivalent(src, dest);
|
13
test/parallel/test-fs-cp-promises-options-validation.mjs
Normal file
13
test/parallel/test-fs-cp-promises-options-validation.mjs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// This tests that fs.promises.cp() rejects if options is not object.
|
||||||
|
|
||||||
|
import '../common/index.mjs';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import fs from 'node:fs';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
await assert.rejects(
|
||||||
|
fs.promises.cp('a', 'b', () => {}),
|
||||||
|
{ code: 'ERR_INVALID_ARG_TYPE' }
|
||||||
|
);
|
28
test/parallel/test-fs-cp-sync-apply-filter-function.mjs
Normal file
28
test/parallel/test-fs-cp-sync-apply-filter-function.mjs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
// This tests that cpSync applies filter function.
|
||||||
|
import '../common/index.mjs';
|
||||||
|
import { nextdir, collectEntries } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync, statSync } from 'node:fs';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
const dest = nextdir();
|
||||||
|
cpSync(src, dest, {
|
||||||
|
filter: (path) => {
|
||||||
|
const pathStat = statSync(path);
|
||||||
|
return pathStat.isDirectory() || path.endsWith('.js');
|
||||||
|
},
|
||||||
|
dereference: true,
|
||||||
|
recursive: true,
|
||||||
|
});
|
||||||
|
const destEntries = [];
|
||||||
|
collectEntries(dest, destEntries);
|
||||||
|
for (const entry of destEntries) {
|
||||||
|
assert.strictEqual(
|
||||||
|
entry.isDirectory() || entry.name.endsWith('.js'),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
24
test/parallel/test-fs-cp-sync-async-filter-error.mjs
Normal file
24
test/parallel/test-fs-cp-sync-async-filter-error.mjs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
// This tests that cpSync throws error if filter function is asynchronous.
|
||||||
|
import '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync, statSync } from 'node:fs';
|
||||||
|
import { setTimeout } from 'node:timers/promises';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
const dest = nextdir();
|
||||||
|
assert.throws(() => {
|
||||||
|
cpSync(src, dest, {
|
||||||
|
filter: async (path) => {
|
||||||
|
await setTimeout(5, 'done');
|
||||||
|
const pathStat = statSync(path);
|
||||||
|
return pathStat.isDirectory() || path.endsWith('.js');
|
||||||
|
},
|
||||||
|
dereference: true,
|
||||||
|
recursive: true,
|
||||||
|
});
|
||||||
|
}, { code: 'ERR_INVALID_RETURN_VALUE' });
|
|
@ -0,0 +1,24 @@
|
||||||
|
// This tests that cpSync throws error if attempt is made to copy directory to file.
|
||||||
|
import { isInsideDirWithUnusualChars, mustNotMutateObjectDeep, skip } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync, mkdirSync } from 'node:fs';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
// See https://github.com/nodejs/node/pull/48409
|
||||||
|
if (isInsideDirWithUnusualChars) {
|
||||||
|
skip('Test is borken in directories with unusual characters');
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
{
|
||||||
|
const src = nextdir();
|
||||||
|
mkdirSync(src, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
const dest = fixtures.path('copy/kitchen-sink/README.md');
|
||||||
|
assert.throws(
|
||||||
|
() => cpSync(src, dest),
|
||||||
|
{ code: 'ERR_FS_CP_DIR_TO_NON_DIR' }
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
// This tests that cpSync throws error if directory copied without recursive flag.
|
||||||
|
import '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync } from 'node:fs';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
const dest = nextdir();
|
||||||
|
assert.throws(
|
||||||
|
() => cpSync(src, dest),
|
||||||
|
{ code: 'ERR_FS_EISDIR' }
|
||||||
|
);
|
|
@ -0,0 +1,22 @@
|
||||||
|
// This tests that cpSync throws error if attempt is made to copy file to directory.
|
||||||
|
import { mustNotMutateObjectDeep, isInsideDirWithUnusualChars, skip } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync, mkdirSync } from 'node:fs';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
// See https://github.com/nodejs/node/pull/48409
|
||||||
|
if (isInsideDirWithUnusualChars) {
|
||||||
|
skip('Test is borken in directories with unusual characters');
|
||||||
|
}
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink/README.md');
|
||||||
|
const dest = nextdir();
|
||||||
|
mkdirSync(dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
assert.throws(
|
||||||
|
() => cpSync(src, dest),
|
||||||
|
{ code: 'ERR_FS_CP_NON_DIR_TO_DIR' }
|
||||||
|
);
|
13
test/parallel/test-fs-cp-sync-copy-file-to-file-path.mjs
Normal file
13
test/parallel/test-fs-cp-sync-copy-file-to-file-path.mjs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// This tests that cpSync allows file to be copied to a file path.
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync, lstatSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
const srcFile = fixtures.path('copy/kitchen-sink/index.js');
|
||||||
|
const destFile = join(nextdir(), 'index.js');
|
||||||
|
cpSync(srcFile, destFile, mustNotMutateObjectDeep({ dereference: true }));
|
||||||
|
const stat = lstatSync(destFile);
|
||||||
|
assert(stat.isFile());
|
34
test/parallel/test-fs-cp-sync-copy-socket-error.mjs
Normal file
34
test/parallel/test-fs-cp-sync-copy-socket-error.mjs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
// This tests that cpSync throws an error if attempt is made to copy socket.
|
||||||
|
import * as common from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync, mkdirSync } from 'node:fs';
|
||||||
|
import { createServer } from 'node:net';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
|
||||||
|
const isWindows = process.platform === 'win32';
|
||||||
|
if (isWindows) {
|
||||||
|
common.skip('No socket support on Windows');
|
||||||
|
}
|
||||||
|
|
||||||
|
// See https://github.com/nodejs/node/pull/48409
|
||||||
|
if (common.isInsideDirWithUnusualChars) {
|
||||||
|
common.skip('Test is borken in directories with unusual characters');
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
{
|
||||||
|
const src = nextdir();
|
||||||
|
mkdirSync(src);
|
||||||
|
const dest = nextdir();
|
||||||
|
const sock = join(src, `${process.pid}.sock`);
|
||||||
|
const server = createServer();
|
||||||
|
server.listen(sock);
|
||||||
|
assert.throws(
|
||||||
|
() => cpSync(sock, dest),
|
||||||
|
{ code: 'ERR_FS_CP_SOCKET' }
|
||||||
|
);
|
||||||
|
server.close();
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
// This tests that cpSync copies link if it does not point to folder in src.
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync, mkdirSync, symlinkSync, readlinkSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = nextdir();
|
||||||
|
mkdirSync(join(src, 'a', 'b'), mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
symlinkSync(src, join(src, 'a', 'c'));
|
||||||
|
const dest = nextdir();
|
||||||
|
mkdirSync(join(dest, 'a'), mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
symlinkSync(dest, join(dest, 'a', 'c'));
|
||||||
|
cpSync(src, dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
const link = readlinkSync(join(dest, 'a', 'c'));
|
||||||
|
assert.strictEqual(link, src);
|
|
@ -0,0 +1,21 @@
|
||||||
|
// This tests that cpSync throws EEXIST error if attempt is made to copy symlink over file.
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync, mkdirSync, symlinkSync, writeFileSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = nextdir();
|
||||||
|
mkdirSync(join(src, 'a', 'b'), mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
symlinkSync(join(src, 'a', 'b'), join(src, 'a', 'c'));
|
||||||
|
|
||||||
|
const dest = nextdir();
|
||||||
|
mkdirSync(join(dest, 'a'), mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
writeFileSync(join(dest, 'a', 'c'), 'hello', 'utf8');
|
||||||
|
assert.throws(
|
||||||
|
() => cpSync(src, dest, mustNotMutateObjectDeep({ recursive: true })),
|
||||||
|
{ code: 'EEXIST' }
|
||||||
|
);
|
|
@ -0,0 +1,17 @@
|
||||||
|
// This tests that cpSync allows copying symlinks in src to locations in dest with
|
||||||
|
// existing symlinks not pointing to a directory.
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import { cpSync, mkdirSync, writeFileSync, symlinkSync } from 'node:fs';
|
||||||
|
import { resolve, join } from 'node:path';
|
||||||
|
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = nextdir();
|
||||||
|
const dest = nextdir();
|
||||||
|
mkdirSync(src, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
writeFileSync(`${src}/test.txt`, 'test');
|
||||||
|
symlinkSync(resolve(`${src}/test.txt`), join(src, 'link.txt'));
|
||||||
|
cpSync(src, dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
cpSync(src, dest, mustNotMutateObjectDeep({ recursive: true }));
|
14
test/parallel/test-fs-cp-sync-copy-to-subdirectory-error.mjs
Normal file
14
test/parallel/test-fs-cp-sync-copy-to-subdirectory-error.mjs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// This tests that cpSync throws error if attempt is made to copy to subdirectory of self.
|
||||||
|
import '../common/index.mjs';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync } from 'node:fs';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
const dest = fixtures.path('copy/kitchen-sink/a');
|
||||||
|
assert.throws(
|
||||||
|
() => cpSync(src, dest),
|
||||||
|
{ code: 'ERR_FS_CP_EINVAL' }
|
||||||
|
);
|
23
test/parallel/test-fs-cp-sync-dereference-directory.mjs
Normal file
23
test/parallel/test-fs-cp-sync-dereference-directory.mjs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// This tests that cpSync overrides target directory with what symlink points to, when dereference is true.
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir, assertDirEquivalent } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync, mkdirSync, writeFileSync, symlinkSync, lstatSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = nextdir();
|
||||||
|
const symlink = nextdir();
|
||||||
|
const dest = nextdir();
|
||||||
|
mkdirSync(src, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
writeFileSync(join(src, 'foo.js'), 'foo', 'utf8');
|
||||||
|
symlinkSync(src, symlink);
|
||||||
|
|
||||||
|
mkdirSync(dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
|
||||||
|
cpSync(symlink, dest, mustNotMutateObjectDeep({ dereference: true, recursive: true }));
|
||||||
|
const destStat = lstatSync(dest);
|
||||||
|
assert(!destStat.isSymbolicLink());
|
||||||
|
assertDirEquivalent(src, dest);
|
23
test/parallel/test-fs-cp-sync-dereference-file.mjs
Normal file
23
test/parallel/test-fs-cp-sync-dereference-file.mjs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// This tests that cpSync copies file itself, rather than symlink, when dereference is true.
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'assert';
|
||||||
|
|
||||||
|
import { cpSync, mkdirSync, writeFileSync, symlinkSync, lstatSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = nextdir();
|
||||||
|
mkdirSync(src, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
writeFileSync(join(src, 'foo.js'), 'foo', 'utf8');
|
||||||
|
symlinkSync(join(src, 'foo.js'), join(src, 'bar.js'));
|
||||||
|
|
||||||
|
const dest = nextdir();
|
||||||
|
mkdirSync(dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
const destFile = join(dest, 'foo.js');
|
||||||
|
|
||||||
|
cpSync(join(src, 'bar.js'), destFile, mustNotMutateObjectDeep({ dereference: true, recursive: true }));
|
||||||
|
const stat = lstatSync(destFile);
|
||||||
|
assert(stat.isFile());
|
20
test/parallel/test-fs-cp-sync-dereference-twice.mjs
Normal file
20
test/parallel/test-fs-cp-sync-dereference-twice.mjs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// This tests that cpSync does not fail if the same directory is copied to dest twice,
|
||||||
|
// when dereference is true, and force is false (fails silently).
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'assert';
|
||||||
|
|
||||||
|
import { cpSync, lstatSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
const dest = nextdir();
|
||||||
|
const destFile = join(dest, 'a/b/README2.md');
|
||||||
|
cpSync(src, dest, mustNotMutateObjectDeep({ dereference: true, recursive: true }));
|
||||||
|
cpSync(src, dest, mustNotMutateObjectDeep({ dereference: true, recursive: true }));
|
||||||
|
const stat = lstatSync(destFile);
|
||||||
|
assert(stat.isFile());
|
14
test/parallel/test-fs-cp-sync-dest-name-prefix-match.mjs
Normal file
14
test/parallel/test-fs-cp-sync-dest-name-prefix-match.mjs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// This tests that cpSync must not throw error if attempt is made to copy to dest
|
||||||
|
// directory with same prefix as src directory.
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import { cpSync, mkdirSync } from 'node:fs';
|
||||||
|
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = nextdir('prefix', tmpdir);
|
||||||
|
const dest = nextdir('prefix-a', tmpdir);
|
||||||
|
mkdirSync(src);
|
||||||
|
mkdirSync(dest);
|
||||||
|
cpSync(src, dest, mustNotMutateObjectDeep({ recursive: true }));
|
|
@ -0,0 +1,16 @@
|
||||||
|
// This tests that cpSync must not throw error if attempt is made to copy to dest
|
||||||
|
// directory if the parent of dest has same prefix as src directory.
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import { cpSync, mkdirSync } from 'node:fs';
|
||||||
|
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = nextdir('aa', tmpdir);
|
||||||
|
const destParent = nextdir('aaa', tmpdir);
|
||||||
|
const dest = nextdir('aaa/aabb', tmpdir);
|
||||||
|
mkdirSync(src);
|
||||||
|
mkdirSync(destParent);
|
||||||
|
mkdirSync(dest);
|
||||||
|
cpSync(src, dest, mustNotMutateObjectDeep({ recursive: true }));
|
15
test/parallel/test-fs-cp-sync-directory-not-exist-error.mjs
Normal file
15
test/parallel/test-fs-cp-sync-directory-not-exist-error.mjs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// This tests that cpSync throws an error when attempting to copy a dir that does not exist.
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync } from 'node:fs';
|
||||||
|
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = nextdir();
|
||||||
|
const dest = nextdir();
|
||||||
|
assert.throws(
|
||||||
|
() => cpSync(src, dest, mustNotMutateObjectDeep({ recursive: true })),
|
||||||
|
{ code: 'ENOENT' }
|
||||||
|
);
|
22
test/parallel/test-fs-cp-sync-error-on-exist.mjs
Normal file
22
test/parallel/test-fs-cp-sync-error-on-exist.mjs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// This tests that cpSync throws error if errorOnExist is true, force is false, and file or folder copied over.
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync } from 'node:fs';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
const dest = nextdir();
|
||||||
|
cpSync(src, dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
assert.throws(
|
||||||
|
() => cpSync(src, dest, {
|
||||||
|
dereference: true,
|
||||||
|
errorOnExist: true,
|
||||||
|
force: false,
|
||||||
|
recursive: true,
|
||||||
|
}),
|
||||||
|
{ code: 'ERR_FS_CP_EEXIST' }
|
||||||
|
);
|
14
test/parallel/test-fs-cp-sync-file-url.mjs
Normal file
14
test/parallel/test-fs-cp-sync-file-url.mjs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// This tests that cpSync accepts file URL as src and dest.
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir, assertDirEquivalent } from '../common/fs.js';
|
||||||
|
import { cpSync } from 'node:fs';
|
||||||
|
import { pathToFileURL } from 'node:url';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
const dest = nextdir();
|
||||||
|
cpSync(pathToFileURL(src), pathToFileURL(dest), mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
assertDirEquivalent(src, dest);
|
17
test/parallel/test-fs-cp-sync-filename-too-long-error.mjs
Normal file
17
test/parallel/test-fs-cp-sync-filename-too-long-error.mjs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// This tests that cpSync throws an error when attempting to copy a file with a name that is too long.
|
||||||
|
import '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync } from 'node:fs';
|
||||||
|
|
||||||
|
const isWindows = process.platform === 'win32';
|
||||||
|
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = 'a'.repeat(5000);
|
||||||
|
const dest = nextdir();
|
||||||
|
assert.throws(
|
||||||
|
() => cpSync(src, dest),
|
||||||
|
{ code: isWindows ? 'ENOENT' : 'ENAMETOOLONG' }
|
||||||
|
);
|
14
test/parallel/test-fs-cp-sync-incompatible-options-error.mjs
Normal file
14
test/parallel/test-fs-cp-sync-incompatible-options-error.mjs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// This tests that cpSync throws an error when both dereference and verbatimSymlinks are enabled.
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync } from 'node:fs';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
assert.throws(
|
||||||
|
() => cpSync(src, src, mustNotMutateObjectDeep({ dereference: true, verbatimSymlinks: true })),
|
||||||
|
{ code: 'ERR_INCOMPATIBLE_OPTION_PAIR' }
|
||||||
|
);
|
30
test/parallel/test-fs-cp-sync-mode-flags.mjs
Normal file
30
test/parallel/test-fs-cp-sync-mode-flags.mjs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
// This tests that cpSync copies a nested folder structure with mode flags.
|
||||||
|
// This test is based on fs.promises.copyFile() with `COPYFILE_FICLONE_FORCE`.
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir, assertDirEquivalent } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync, constants } from 'node:fs';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
const dest = nextdir();
|
||||||
|
try {
|
||||||
|
cpSync(src, dest, mustNotMutateObjectDeep({
|
||||||
|
recursive: true,
|
||||||
|
mode: constants.COPYFILE_FICLONE_FORCE,
|
||||||
|
}));
|
||||||
|
} catch (err) {
|
||||||
|
// If the platform does not support `COPYFILE_FICLONE_FORCE` operation,
|
||||||
|
// it should enter this path.
|
||||||
|
assert.strictEqual(err.syscall, 'copyfile');
|
||||||
|
assert(err.code === 'ENOTSUP' || err.code === 'ENOTTY' ||
|
||||||
|
err.code === 'ENOSYS' || err.code === 'EXDEV');
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the platform support `COPYFILE_FICLONE_FORCE` operation,
|
||||||
|
// it should reach to here.
|
||||||
|
assertDirEquivalent(src, dest);
|
12
test/parallel/test-fs-cp-sync-mode-invalid.mjs
Normal file
12
test/parallel/test-fs-cp-sync-mode-invalid.mjs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
// This tests that cpSync rejects if options.mode is invalid.
|
||||||
|
import '../common/index.mjs';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync } from 'node:fs';
|
||||||
|
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => cpSync('a', 'b', { mode: -1 }),
|
||||||
|
{ code: 'ERR_OUT_OF_RANGE' }
|
||||||
|
);
|
13
test/parallel/test-fs-cp-sync-nested-files-folders.mjs
Normal file
13
test/parallel/test-fs-cp-sync-nested-files-folders.mjs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// This tests that cpSync copies a nested folder structure with files and folders.
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir, assertDirEquivalent } from '../common/fs.js';
|
||||||
|
import { cpSync } from 'node:fs';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
const dest = nextdir();
|
||||||
|
cpSync(src, dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
assertDirEquivalent(src, dest);
|
21
test/parallel/test-fs-cp-sync-no-overwrite-force-false.mjs
Normal file
21
test/parallel/test-fs-cp-sync-no-overwrite-force-false.mjs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// This tests that cpSync does not throw errors when directory is copied over and force is false.
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir, assertDirEquivalent } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync, mkdirSync, writeFileSync, lstatSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = nextdir();
|
||||||
|
mkdirSync(join(src, 'a', 'b'), mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
writeFileSync(join(src, 'README.md'), 'hello world', 'utf8');
|
||||||
|
const dest = nextdir();
|
||||||
|
cpSync(src, dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
const initialStat = lstatSync(join(dest, 'README.md'));
|
||||||
|
cpSync(src, dest, mustNotMutateObjectDeep({ force: false, recursive: true }));
|
||||||
|
// File should not have been copied over, so access times will be identical:
|
||||||
|
assertDirEquivalent(src, dest);
|
||||||
|
const finalStat = lstatSync(join(dest, 'README.md'));
|
||||||
|
assert.strictEqual(finalStat.ctime.getTime(), initialStat.ctime.getTime());
|
12
test/parallel/test-fs-cp-sync-options-invalid-type-error.mjs
Normal file
12
test/parallel/test-fs-cp-sync-options-invalid-type-error.mjs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
// This tests that cpSync throws if options is not object.
|
||||||
|
import '../common/index.mjs';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync } from 'node:fs';
|
||||||
|
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => cpSync('a', 'b', () => {}),
|
||||||
|
{ code: 'ERR_INVALID_ARG_TYPE' }
|
||||||
|
);
|
19
test/parallel/test-fs-cp-sync-overwrite-force-true.mjs
Normal file
19
test/parallel/test-fs-cp-sync-overwrite-force-true.mjs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
// This tests that cpSync overwrites existing files if force is true.
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir, assertDirEquivalent } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync, mkdirSync, writeFileSync, readFileSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
const dest = nextdir();
|
||||||
|
mkdirSync(dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
writeFileSync(join(dest, 'README.md'), '# Goodbye', 'utf8');
|
||||||
|
cpSync(src, dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
assertDirEquivalent(src, dest);
|
||||||
|
const content = readFileSync(join(dest, 'README.md'), 'utf8');
|
||||||
|
assert.strictEqual(content.trim(), '# Hello');
|
|
@ -0,0 +1,26 @@
|
||||||
|
// This tests that cpSync throws error if parent directory of symlink in dest points to src.
|
||||||
|
import { mustNotMutateObjectDeep, isInsideDirWithUnusualChars, skip } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync, mkdirSync, symlinkSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
// See https://github.com/nodejs/node/pull/48409
|
||||||
|
if (isInsideDirWithUnusualChars) {
|
||||||
|
skip('Test is borken in directories with unusual characters');
|
||||||
|
}
|
||||||
|
|
||||||
|
const src = nextdir();
|
||||||
|
mkdirSync(join(src, 'a'), mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
const dest = nextdir();
|
||||||
|
// Create symlink in dest pointing to src.
|
||||||
|
const destLink = join(dest, 'b');
|
||||||
|
mkdirSync(dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
symlinkSync(src, destLink);
|
||||||
|
assert.throws(
|
||||||
|
() => cpSync(src, join(dest, 'b', 'c')),
|
||||||
|
{ code: 'ERR_FS_CP_EINVAL' }
|
||||||
|
);
|
|
@ -0,0 +1,24 @@
|
||||||
|
// This tests that cpSync makes file writeable when updating timestamp, if not writeable.
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir, assertDirEquivalent } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync, mkdirSync, writeFileSync, lstatSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import { setTimeout } from 'node:timers/promises';
|
||||||
|
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = nextdir();
|
||||||
|
mkdirSync(src, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
const dest = nextdir();
|
||||||
|
mkdirSync(dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
writeFileSync(join(src, 'foo.txt'), 'foo', mustNotMutateObjectDeep({ mode: 0o444 }));
|
||||||
|
// Small wait to make sure that destStat.mtime.getTime() would produce a time
|
||||||
|
// different from srcStat.mtime.getTime() if preserveTimestamps wasn't set to true
|
||||||
|
await setTimeout(5);
|
||||||
|
cpSync(src, dest, mustNotMutateObjectDeep({ preserveTimestamps: true, recursive: true }));
|
||||||
|
assertDirEquivalent(src, dest);
|
||||||
|
const srcStat = lstatSync(join(src, 'foo.txt'));
|
||||||
|
const destStat = lstatSync(join(dest, 'foo.txt'));
|
||||||
|
assert.strictEqual(srcStat.mtime.getTime(), destStat.mtime.getTime());
|
18
test/parallel/test-fs-cp-sync-preserve-timestamps.mjs
Normal file
18
test/parallel/test-fs-cp-sync-preserve-timestamps.mjs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// This tests that cpSync copies timestamps from src to dest if preserveTimestamps is true.
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir, assertDirEquivalent } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync, lstatSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
const dest = nextdir();
|
||||||
|
cpSync(src, dest, mustNotMutateObjectDeep({ preserveTimestamps: true, recursive: true }));
|
||||||
|
assertDirEquivalent(src, dest);
|
||||||
|
const srcStat = lstatSync(join(src, 'index.js'));
|
||||||
|
const destStat = lstatSync(join(dest, 'index.js'));
|
||||||
|
assert.strictEqual(srcStat.mtime.getTime(), destStat.mtime.getTime());
|
|
@ -0,0 +1,21 @@
|
||||||
|
// This tests that cpSync resolves relative symlinks to their absolute path by default.
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync, mkdirSync, writeFileSync, symlinkSync, readlinkSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = nextdir();
|
||||||
|
mkdirSync(src, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
writeFileSync(join(src, 'foo.js'), 'foo', 'utf8');
|
||||||
|
symlinkSync('foo.js', join(src, 'bar.js'));
|
||||||
|
|
||||||
|
const dest = nextdir();
|
||||||
|
mkdirSync(dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
|
||||||
|
cpSync(src, dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
const link = readlinkSync(join(dest, 'bar.js'));
|
||||||
|
assert.strictEqual(link, join(src, 'foo.js'));
|
|
@ -0,0 +1,21 @@
|
||||||
|
// This tests that cpSync resolves relative symlinks when verbatimSymlinks is false.
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync, mkdirSync, writeFileSync, symlinkSync, readlinkSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = nextdir();
|
||||||
|
mkdirSync(src, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
writeFileSync(join(src, 'foo.js'), 'foo', 'utf8');
|
||||||
|
symlinkSync('foo.js', join(src, 'bar.js'));
|
||||||
|
|
||||||
|
const dest = nextdir();
|
||||||
|
mkdirSync(dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
|
||||||
|
cpSync(src, dest, mustNotMutateObjectDeep({ recursive: true, verbatimSymlinks: false }));
|
||||||
|
const link = readlinkSync(join(dest, 'bar.js'));
|
||||||
|
assert.strictEqual(link, join(src, 'foo.js'));
|
14
test/parallel/test-fs-cp-sync-src-dest-identical-error.mjs
Normal file
14
test/parallel/test-fs-cp-sync-src-dest-identical-error.mjs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// This tests that cpSync throws error when src and dest are identical.
|
||||||
|
import '../common/index.mjs';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync } from 'node:fs';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
assert.throws(
|
||||||
|
() => cpSync(src, src),
|
||||||
|
{ code: 'ERR_FS_CP_EINVAL' }
|
||||||
|
);
|
25
test/parallel/test-fs-cp-sync-src-parent-of-dest-error.mjs
Normal file
25
test/parallel/test-fs-cp-sync-src-parent-of-dest-error.mjs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// This tests that cpSync throws error if attempt is made to copy src to dest when
|
||||||
|
// src is parent directory of the parent of dest.
|
||||||
|
import { mustNotMutateObjectDeep, isInsideDirWithUnusualChars, skip } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync, mkdirSync } from 'node:fs';
|
||||||
|
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
// See https://github.com/nodejs/node/pull/48409
|
||||||
|
if (isInsideDirWithUnusualChars) {
|
||||||
|
skip('Test is borken in directories with unusual characters');
|
||||||
|
}
|
||||||
|
|
||||||
|
const src = nextdir('a', tmpdir);
|
||||||
|
const destParent = nextdir('a/b', tmpdir);
|
||||||
|
const dest = nextdir('a/b/c', tmpdir);
|
||||||
|
mkdirSync(src);
|
||||||
|
mkdirSync(destParent);
|
||||||
|
mkdirSync(dest);
|
||||||
|
assert.throws(
|
||||||
|
() => cpSync(src, dest, mustNotMutateObjectDeep({ recursive: true })),
|
||||||
|
{ code: 'ERR_FS_CP_EINVAL' },
|
||||||
|
);
|
|
@ -0,0 +1,21 @@
|
||||||
|
// This tests that cpSync throws error if symlink in dest points to location in src.
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync, mkdirSync, symlinkSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = nextdir();
|
||||||
|
mkdirSync(join(src, 'a', 'b'), mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
symlinkSync(join(src, 'a', 'b'), join(src, 'a', 'c'));
|
||||||
|
|
||||||
|
const dest = nextdir();
|
||||||
|
mkdirSync(join(dest, 'a'), mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
symlinkSync(src, join(dest, 'a', 'c'));
|
||||||
|
assert.throws(
|
||||||
|
() => cpSync(src, dest, mustNotMutateObjectDeep({ recursive: true })),
|
||||||
|
{ code: 'ERR_FS_CP_SYMLINK_TO_SUBDIRECTORY' }
|
||||||
|
);
|
|
@ -0,0 +1,22 @@
|
||||||
|
// This tests that cpSync throws error if symlink in src points to location in dest.
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync, mkdirSync, symlinkSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = nextdir();
|
||||||
|
mkdirSync(src, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
const dest = nextdir();
|
||||||
|
mkdirSync(dest);
|
||||||
|
symlinkSync(dest, join(src, 'link'));
|
||||||
|
cpSync(src, dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
assert.throws(
|
||||||
|
() => cpSync(src, dest, mustNotMutateObjectDeep({ recursive: true })),
|
||||||
|
{
|
||||||
|
code: 'ERR_FS_CP_EINVAL'
|
||||||
|
}
|
||||||
|
);
|
13
test/parallel/test-fs-cp-sync-unicode-folder-names.mjs
Normal file
13
test/parallel/test-fs-cp-sync-unicode-folder-names.mjs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// This tests that cpSync copies a nested folder containing UTF characters.
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir, assertDirEquivalent } from '../common/fs.js';
|
||||||
|
import { cpSync } from 'node:fs';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/utf/新建文件夹');
|
||||||
|
const dest = nextdir();
|
||||||
|
cpSync(src, dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
assertDirEquivalent(src, dest);
|
17
test/parallel/test-fs-cp-sync-verbatim-symlinks-invalid.mjs
Normal file
17
test/parallel/test-fs-cp-sync-verbatim-symlinks-invalid.mjs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// This tests that cpSync throws error when verbatimSymlinks is not a boolean.
|
||||||
|
import '../common/index.mjs';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync } from 'node:fs';
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
import fixtures from '../common/fixtures.js';
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = fixtures.path('copy/kitchen-sink');
|
||||||
|
[1, [], {}, null, 1n, undefined, null, Symbol(), '', () => {}]
|
||||||
|
.forEach((verbatimSymlinks) => {
|
||||||
|
assert.throws(
|
||||||
|
() => cpSync(src, src, { verbatimSymlinks }),
|
||||||
|
{ code: 'ERR_INVALID_ARG_TYPE' }
|
||||||
|
);
|
||||||
|
});
|
21
test/parallel/test-fs-cp-sync-verbatim-symlinks-true.mjs
Normal file
21
test/parallel/test-fs-cp-sync-verbatim-symlinks-true.mjs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// This tests that cpSync does not resolve relative symlinks when verbatimSymlinks is true.
|
||||||
|
import { mustNotMutateObjectDeep } from '../common/index.mjs';
|
||||||
|
import { nextdir } from '../common/fs.js';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { cpSync, mkdirSync, writeFileSync, symlinkSync, readlinkSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
|
||||||
|
import tmpdir from '../common/tmpdir.js';
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const src = nextdir();
|
||||||
|
mkdirSync(src, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
writeFileSync(join(src, 'foo.js'), 'foo', 'utf8');
|
||||||
|
symlinkSync('foo.js', join(src, 'bar.js'));
|
||||||
|
|
||||||
|
const dest = nextdir();
|
||||||
|
mkdirSync(dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||||
|
|
||||||
|
cpSync(src, dest, mustNotMutateObjectDeep({ recursive: true, verbatimSymlinks: true }));
|
||||||
|
const link = readlinkSync(join(dest, 'bar.js'));
|
||||||
|
assert.strictEqual(link, 'foo.js');
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue