1// Flags: --experimental-abortcontroller 2'use strict'; 3 4const common = require('../common'); 5 6// The following tests validate base functionality for the fs.promises 7// FileHandle.writeFile method. 8 9const fs = require('fs'); 10const { open, writeFile } = fs.promises; 11const path = require('path'); 12const { Readable } = require('stream'); 13const tmpdir = require('../common/tmpdir'); 14const assert = require('assert'); 15const tmpDir = tmpdir.path; 16 17tmpdir.refresh(); 18 19async function validateWriteFile() { 20 const filePathForHandle = path.resolve(tmpDir, 'tmp-write-file2.txt'); 21 const fileHandle = await open(filePathForHandle, 'w+'); 22 try { 23 const buffer = Buffer.from('Hello world'.repeat(100), 'utf8'); 24 25 await fileHandle.writeFile(buffer); 26 const readFileData = fs.readFileSync(filePathForHandle); 27 assert.deepStrictEqual(buffer, readFileData); 28 } finally { 29 await fileHandle.close(); 30 } 31} 32 33// Signal aborted while writing file 34async function doWriteAndCancel() { 35 const filePathForHandle = path.resolve(tmpDir, 'dogs-running.txt'); 36 const fileHandle = await open(filePathForHandle, 'w+'); 37 try { 38 const buffer = Buffer.from('dogs running'.repeat(512 * 1024), 'utf8'); 39 const controller = new AbortController(); 40 const { signal } = controller; 41 process.nextTick(() => controller.abort()); 42 await assert.rejects(writeFile(fileHandle, buffer, { signal }), { 43 name: 'AbortError' 44 }); 45 } finally { 46 await fileHandle.close(); 47 } 48} 49 50const dest = path.resolve(tmpDir, 'tmp.txt'); 51const otherDest = path.resolve(tmpDir, 'tmp-2.txt'); 52const stream = Readable.from(['a', 'b', 'c']); 53const stream2 = Readable.from(['ümlaut', ' ', 'sechzig']); 54const iterable = { 55 expected: 'abc', 56 *[Symbol.iterator]() { 57 yield 'a'; 58 yield 'b'; 59 yield 'c'; 60 } 61}; 62function iterableWith(value) { 63 return { 64 *[Symbol.iterator]() { 65 yield value; 66 } 67 }; 68} 69const bufferIterable = { 70 expected: 'abc', 71 *[Symbol.iterator]() { 72 yield Buffer.from('a'); 73 yield Buffer.from('b'); 74 yield Buffer.from('c'); 75 } 76}; 77const asyncIterable = { 78 expected: 'abc', 79 async* [Symbol.asyncIterator]() { 80 yield 'a'; 81 yield 'b'; 82 yield 'c'; 83 } 84}; 85 86async function doWriteStream() { 87 const fileHandle = await open(dest, 'w+'); 88 try { 89 await fileHandle.writeFile(stream); 90 const expected = 'abc'; 91 const data = fs.readFileSync(dest, 'utf-8'); 92 assert.deepStrictEqual(data, expected); 93 } finally { 94 await fileHandle.close(); 95 } 96} 97 98async function doWriteStreamWithCancel() { 99 const controller = new AbortController(); 100 const { signal } = controller; 101 process.nextTick(() => controller.abort()); 102 const fileHandle = await open(otherDest, 'w+'); 103 try { 104 await assert.rejects( 105 fileHandle.writeFile(stream, { signal }), 106 { name: 'AbortError' } 107 ); 108 } finally { 109 await fileHandle.close(); 110 } 111} 112 113async function doWriteIterable() { 114 const fileHandle = await open(dest, 'w+'); 115 try { 116 await fileHandle.writeFile(iterable); 117 const data = fs.readFileSync(dest, 'utf-8'); 118 assert.deepStrictEqual(data, iterable.expected); 119 } finally { 120 await fileHandle.close(); 121 } 122} 123 124async function doWriteInvalidIterable() { 125 const fileHandle = await open(dest, 'w+'); 126 try { 127 await Promise.all( 128 [42, 42n, {}, Symbol('42'), true, undefined, null, NaN].map((value) => 129 assert.rejects( 130 fileHandle.writeFile(iterableWith(value)), 131 { code: 'ERR_INVALID_ARG_TYPE' } 132 ) 133 ) 134 ); 135 } finally { 136 await fileHandle.close(); 137 } 138} 139 140async function doWriteIterableWithEncoding() { 141 const fileHandle = await open(dest, 'w+'); 142 try { 143 await fileHandle.writeFile(stream2, 'latin1'); 144 const expected = 'ümlaut sechzig'; 145 const data = fs.readFileSync(dest, 'latin1'); 146 assert.deepStrictEqual(data, expected); 147 } finally { 148 await fileHandle.close(); 149 } 150} 151 152async function doWriteBufferIterable() { 153 const fileHandle = await open(dest, 'w+'); 154 try { 155 await fileHandle.writeFile(bufferIterable); 156 const data = fs.readFileSync(dest, 'utf-8'); 157 assert.deepStrictEqual(data, bufferIterable.expected); 158 } finally { 159 await fileHandle.close(); 160 } 161} 162 163async function doWriteAsyncIterable() { 164 const fileHandle = await open(dest, 'w+'); 165 try { 166 await fileHandle.writeFile(asyncIterable); 167 const data = fs.readFileSync(dest, 'utf-8'); 168 assert.deepStrictEqual(data, asyncIterable.expected); 169 } finally { 170 await fileHandle.close(); 171 } 172} 173 174async function doWriteInvalidValues() { 175 const fileHandle = await open(dest, 'w+'); 176 try { 177 await Promise.all( 178 [42, 42n, {}, Symbol('42'), true, undefined, null, NaN].map((value) => 179 assert.rejects( 180 fileHandle.writeFile(value), 181 { code: 'ERR_INVALID_ARG_TYPE' } 182 ) 183 ) 184 ); 185 } finally { 186 await fileHandle.close(); 187 } 188} 189 190(async () => { 191 await validateWriteFile(); 192 await doWriteAndCancel(); 193 await doWriteStream(); 194 await doWriteStreamWithCancel(); 195 await doWriteIterable(); 196 await doWriteInvalidIterable(); 197 await doWriteIterableWithEncoding(); 198 await doWriteBufferIterable(); 199 await doWriteAsyncIterable(); 200 await doWriteInvalidValues(); 201})().then(common.mustCall()); 202