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