@@ -38,6 +38,30 @@ function nextdir() {
3838 assertDirEquivalent ( src , dest ) ;
3939}
4040
41+ // It copies a nested folder structure with mode flags.
42+ // This test is based on fs.promises.copyFile() with `COPYFILE_FICLONE_FORCE`.
43+ ( ( ) => {
44+ const src = './test/fixtures/copy/kitchen-sink' ;
45+ const dest = nextdir ( ) ;
46+ try {
47+ cpSync ( src , dest , mustNotMutateObjectDeep ( {
48+ recursive : true ,
49+ mode : fs . constants . COPYFILE_FICLONE_FORCE ,
50+ } ) ) ;
51+ } catch ( err ) {
52+ // If the platform does not support `COPYFILE_FICLONE_FORCE` operation,
53+ // it should enter this path.
54+ assert . strictEqual ( err . syscall , 'copyfile' ) ;
55+ assert ( err . code === 'ENOTSUP' || err . code === 'ENOTTY' ||
56+ err . code === 'ENOSYS' || err . code === 'EXDEV' ) ;
57+ return ;
58+ }
59+
60+ // If the platform support `COPYFILE_FICLONE_FORCE` operation,
61+ // it should reach to here.
62+ assertDirEquivalent ( src , dest ) ;
63+ } ) ( ) ;
64+
4165// It does not throw errors when directory is copied over and force is false.
4266{
4367 const src = nextdir ( ) ;
@@ -107,6 +131,14 @@ function nextdir() {
107131 } ) ;
108132}
109133
134+ // It rejects if options.mode is invalid.
135+ {
136+ assert . throws (
137+ ( ) => cpSync ( 'a' , 'b' , { mode : - 1 } ) ,
138+ { code : 'ERR_OUT_OF_RANGE' }
139+ ) ;
140+ }
141+
110142
111143// It throws an error when both dereference and verbatimSymlinks are enabled.
112144{
@@ -425,6 +457,31 @@ if (!isWindows) {
425457 } ) ) ;
426458}
427459
460+ // It copies a nested folder structure with mode flags.
461+ // This test is based on fs.promises.copyFile() with `COPYFILE_FICLONE_FORCE`.
462+ {
463+ const src = './test/fixtures/copy/kitchen-sink' ;
464+ const dest = nextdir ( ) ;
465+ cp ( src , dest , mustNotMutateObjectDeep ( {
466+ recursive : true ,
467+ mode : fs . constants . COPYFILE_FICLONE_FORCE ,
468+ } ) , mustCall ( ( err ) => {
469+ if ( ! err ) {
470+ // If the platform support `COPYFILE_FICLONE_FORCE` operation,
471+ // it should reach to here.
472+ assert . strictEqual ( err , null ) ;
473+ assertDirEquivalent ( src , dest ) ;
474+ return ;
475+ }
476+
477+ // If the platform does not support `COPYFILE_FICLONE_FORCE` operation,
478+ // it should enter this path.
479+ assert . strictEqual ( err . syscall , 'copyfile' ) ;
480+ assert ( err . code === 'ENOTSUP' || err . code === 'ENOTTY' ||
481+ err . code === 'ENOSYS' || err . code === 'EXDEV' ) ;
482+ } ) ) ;
483+ }
484+
428485// It does not throw errors when directory is copied over and force is false.
429486{
430487 const src = nextdir ( ) ;
@@ -799,6 +856,14 @@ if (!isWindows) {
799856 ) ;
800857}
801858
859+ // It throws if options is not object.
860+ {
861+ assert . throws (
862+ ( ) => cp ( 'a' , 'b' , { mode : - 1 } , ( ) => { } ) ,
863+ { code : 'ERR_OUT_OF_RANGE' }
864+ ) ;
865+ }
866+
802867// Promises implementation of copy.
803868
804869// It copies a nested folder structure with files and folders.
@@ -810,6 +875,35 @@ if (!isWindows) {
810875 assertDirEquivalent ( src , dest ) ;
811876}
812877
878+ // It copies a nested folder structure with mode flags.
879+ // This test is based on fs.promises.copyFile() with `COPYFILE_FICLONE_FORCE`.
880+ {
881+ const src = './test/fixtures/copy/kitchen-sink' ;
882+ const dest = nextdir ( ) ;
883+ let p = null ;
884+ let successFiClone = false ;
885+ try {
886+ p = await fs . promises . cp ( src , dest , mustNotMutateObjectDeep ( {
887+ recursive : true ,
888+ mode : fs . constants . COPYFILE_FICLONE_FORCE ,
889+ } ) ) ;
890+ successFiClone = true ;
891+ } catch ( err ) {
892+ // If the platform does not support `COPYFILE_FICLONE_FORCE` operation,
893+ // it should enter this path.
894+ assert . strictEqual ( err . syscall , 'copyfile' ) ;
895+ assert ( err . code === 'ENOTSUP' || err . code === 'ENOTTY' ||
896+ err . code === 'ENOSYS' || err . code === 'EXDEV' ) ;
897+ }
898+
899+ if ( successFiClone ) {
900+ // If the platform support `COPYFILE_FICLONE_FORCE` operation,
901+ // it should reach to here.
902+ assert . strictEqual ( p , undefined ) ;
903+ assertDirEquivalent ( src , dest ) ;
904+ }
905+ }
906+
813907// It accepts file URL as src and dest.
814908{
815909 const src = './test/fixtures/copy/kitchen-sink' ;
@@ -847,6 +941,16 @@ if (!isWindows) {
847941 ) ;
848942}
849943
944+ // It rejects if options.mode is invalid.
945+ {
946+ await assert . rejects (
947+ fs . promises . cp ( 'a' , 'b' , {
948+ mode : - 1 ,
949+ } ) ,
950+ { code : 'ERR_OUT_OF_RANGE' }
951+ ) ;
952+ }
953+
850954function assertDirEquivalent ( dir1 , dir2 ) {
851955 const dir1Entries = [ ] ;
852956 collectEntries ( dir1 , dir1Entries ) ;
0 commit comments