Skip to content

Commit b2309bc

Browse files
committed
test: add cpSync error handling test
Add test to ensure fs.cpSync properly handles directory iteration errors without causing process abort.
1 parent 73171e8 commit b2309bc

File tree

1 file changed

+86
-0
lines changed

1 file changed

+86
-0
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
'use strict';
2+
3+
// Test that fs.cpSync properly handles directory iteration errors
4+
// instead of causing process abort.
5+
//
6+
// This test ensures that when directory_iterator construction fails
7+
// (e.g., due to permission issues or malformed paths), the error
8+
// is properly converted to a JavaScript exception rather than
9+
// triggering std::terminate or __libcpp_verbose_abort.
10+
11+
const common = require('../common');
12+
const { cpSync, mkdirSync, writeFileSync } = require('fs');
13+
const { join } = require('path');
14+
const assert = require('assert');
15+
const tmpdir = require('../common/tmpdir');
16+
17+
tmpdir.refresh();
18+
19+
// Test 1: Copying from non-existent directory should throw, not abort
20+
{
21+
const nonExistent = join(tmpdir.path, 'does-not-exist');
22+
const dest = join(tmpdir.path, 'dest1');
23+
24+
assert.throws(
25+
() => cpSync(nonExistent, dest, { recursive: true }),
26+
{
27+
code: 'ENOENT',
28+
message: /ENOENT/
29+
},
30+
'cpSync should throw ENOENT for non-existent source directory'
31+
);
32+
}
33+
34+
// Test 2: Copying directory with unreadable subdirectory
35+
// (This test is platform-specific and may be skipped on Windows)
36+
if (!common.isWindows) {
37+
const srcDir = join(tmpdir.path, 'src-unreadable');
38+
const unreadableSubdir = join(srcDir, 'unreadable');
39+
const dest = join(tmpdir.path, 'dest2');
40+
41+
mkdirSync(srcDir);
42+
mkdirSync(unreadableSubdir);
43+
writeFileSync(join(unreadableSubdir, 'file.txt'), 'content');
44+
45+
try {
46+
require('fs').chmodSync(unreadableSubdir, 0o000);
47+
48+
// Should throw error, not abort
49+
assert.throws(
50+
() => cpSync(srcDir, dest, { recursive: true }),
51+
{
52+
code: 'EACCES',
53+
},
54+
'cpSync should throw EACCES for unreadable directory'
55+
);
56+
} finally {
57+
// Restore permissions for cleanup
58+
require('fs').chmodSync(unreadableSubdir, 0o755);
59+
}
60+
}
61+
62+
// Test 3: Basic successful copy to ensure fix doesn't break normal operation
63+
{
64+
const srcDir = join(tmpdir.path, 'src-normal');
65+
const dest = join(tmpdir.path, 'dest-normal');
66+
67+
mkdirSync(srcDir);
68+
writeFileSync(join(srcDir, 'file1.txt'), 'content1');
69+
mkdirSync(join(srcDir, 'subdir'));
70+
writeFileSync(join(srcDir, 'subdir', 'file2.txt'), 'content2');
71+
72+
// Should not throw
73+
cpSync(srcDir, dest, { recursive: true });
74+
75+
const fs = require('fs');
76+
assert.ok(fs.existsSync(join(dest, 'file1.txt')));
77+
assert.ok(fs.existsSync(join(dest, 'subdir', 'file2.txt')));
78+
assert.strictEqual(
79+
fs.readFileSync(join(dest, 'file1.txt'), 'utf8'),
80+
'content1'
81+
);
82+
assert.strictEqual(
83+
fs.readFileSync(join(dest, 'subdir', 'file2.txt'), 'utf8'),
84+
'content2'
85+
);
86+
}

0 commit comments

Comments
 (0)