1// Flags: --expose-internals 2'use strict'; 3const common = require('../common'); 4const fixtures = require('../common/fixtures'); 5const tmpdir = require('../common/tmpdir'); 6const assert = require('assert'); 7const fs = require('fs'); 8const { internalBinding } = require('internal/test/binding'); 9const { 10 UV_ENOENT, 11 UV_EEXIST 12} = internalBinding('uv'); 13const path = require('path'); 14const src = fixtures.path('a.js'); 15const dest = path.join(tmpdir.path, 'copyfile.out'); 16const { 17 COPYFILE_EXCL, 18 COPYFILE_FICLONE, 19 COPYFILE_FICLONE_FORCE, 20 UV_FS_COPYFILE_EXCL, 21 UV_FS_COPYFILE_FICLONE, 22 UV_FS_COPYFILE_FICLONE_FORCE 23} = fs.constants; 24 25function verify(src, dest) { 26 const srcData = fs.readFileSync(src, 'utf8'); 27 const srcStat = fs.statSync(src); 28 const destData = fs.readFileSync(dest, 'utf8'); 29 const destStat = fs.statSync(dest); 30 31 assert.strictEqual(srcData, destData); 32 assert.strictEqual(srcStat.mode, destStat.mode); 33 assert.strictEqual(srcStat.size, destStat.size); 34} 35 36tmpdir.refresh(); 37 38// Verify that flags are defined. 39assert.strictEqual(typeof COPYFILE_EXCL, 'number'); 40assert.strictEqual(typeof COPYFILE_FICLONE, 'number'); 41assert.strictEqual(typeof COPYFILE_FICLONE_FORCE, 'number'); 42assert.strictEqual(typeof UV_FS_COPYFILE_EXCL, 'number'); 43assert.strictEqual(typeof UV_FS_COPYFILE_FICLONE, 'number'); 44assert.strictEqual(typeof UV_FS_COPYFILE_FICLONE_FORCE, 'number'); 45assert.strictEqual(COPYFILE_EXCL, UV_FS_COPYFILE_EXCL); 46assert.strictEqual(COPYFILE_FICLONE, UV_FS_COPYFILE_FICLONE); 47assert.strictEqual(COPYFILE_FICLONE_FORCE, UV_FS_COPYFILE_FICLONE_FORCE); 48 49// Verify that files are overwritten when no flags are provided. 50fs.writeFileSync(dest, '', 'utf8'); 51const result = fs.copyFileSync(src, dest); 52assert.strictEqual(result, undefined); 53verify(src, dest); 54 55// Verify that files are overwritten with default flags. 56fs.copyFileSync(src, dest, 0); 57verify(src, dest); 58 59// Verify that UV_FS_COPYFILE_FICLONE can be used. 60fs.unlinkSync(dest); 61fs.copyFileSync(src, dest, UV_FS_COPYFILE_FICLONE); 62verify(src, dest); 63 64// Verify that COPYFILE_FICLONE_FORCE can be used. 65try { 66 fs.unlinkSync(dest); 67 fs.copyFileSync(src, dest, COPYFILE_FICLONE_FORCE); 68 verify(src, dest); 69} catch (err) { 70 assert.strictEqual(err.syscall, 'copyfile'); 71 assert(err.code === 'ENOTSUP' || err.code === 'ENOTTY' || 72 err.code === 'ENOSYS' || err.code === 'EXDEV'); 73 assert.strictEqual(err.path, src); 74 assert.strictEqual(err.dest, dest); 75} 76 77// Copies asynchronously. 78tmpdir.refresh(); // Don't use unlinkSync() since the last test may fail. 79fs.copyFile(src, dest, common.mustSucceed(() => { 80 verify(src, dest); 81 82 // Copy asynchronously with flags. 83 fs.copyFile(src, dest, COPYFILE_EXCL, common.mustCall((err) => { 84 if (err.code === 'ENOENT') { // Could be ENOENT or EEXIST 85 assert.strictEqual(err.message, 86 'ENOENT: no such file or directory, copyfile ' + 87 `'${src}' -> '${dest}'`); 88 assert.strictEqual(err.errno, UV_ENOENT); 89 assert.strictEqual(err.code, 'ENOENT'); 90 assert.strictEqual(err.syscall, 'copyfile'); 91 } else { 92 assert.strictEqual(err.message, 93 'EEXIST: file already exists, copyfile ' + 94 `'${src}' -> '${dest}'`); 95 assert.strictEqual(err.errno, UV_EEXIST); 96 assert.strictEqual(err.code, 'EEXIST'); 97 assert.strictEqual(err.syscall, 'copyfile'); 98 } 99 })); 100})); 101 102// Throws if callback is not a function. 103assert.throws(() => { 104 fs.copyFile(src, dest, 0, 0); 105}, { 106 code: 'ERR_INVALID_ARG_TYPE', 107 name: 'TypeError' 108}); 109 110// Throws if the source path is not a string. 111[false, 1, {}, [], null, undefined].forEach((i) => { 112 assert.throws( 113 () => fs.copyFile(i, dest, common.mustNotCall()), 114 { 115 code: 'ERR_INVALID_ARG_TYPE', 116 name: 'TypeError', 117 message: /src/ 118 } 119 ); 120 assert.throws( 121 () => fs.copyFile(src, i, common.mustNotCall()), 122 { 123 code: 'ERR_INVALID_ARG_TYPE', 124 name: 'TypeError', 125 message: /dest/ 126 } 127 ); 128 assert.throws( 129 () => fs.copyFileSync(i, dest), 130 { 131 code: 'ERR_INVALID_ARG_TYPE', 132 name: 'TypeError', 133 message: /src/ 134 } 135 ); 136 assert.throws( 137 () => fs.copyFileSync(src, i), 138 { 139 code: 'ERR_INVALID_ARG_TYPE', 140 name: 'TypeError', 141 message: /dest/ 142 } 143 ); 144}); 145 146assert.throws(() => { 147 fs.copyFileSync(src, dest, 'r'); 148}, { 149 code: 'ERR_INVALID_ARG_TYPE', 150 name: 'TypeError', 151 message: /mode/ 152}); 153 154assert.throws(() => { 155 fs.copyFileSync(src, dest, 8); 156}, { 157 code: 'ERR_OUT_OF_RANGE', 158 name: 'RangeError', 159}); 160 161assert.throws(() => { 162 fs.copyFile(src, dest, 'r', common.mustNotCall()); 163}, { 164 code: 'ERR_INVALID_ARG_TYPE', 165 name: 'TypeError', 166 message: /mode/ 167}); 168