• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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