1'use strict';
2
3// This test makes sure that `writeFile()` always writes from the current
4// position of the file, instead of truncating the file, when used with file
5// descriptors.
6
7const common = require('../common');
8const assert = require('assert');
9const fs = require('fs');
10const join = require('path').join;
11
12const tmpdir = require('../common/tmpdir');
13tmpdir.refresh();
14
15{
16  /* writeFileSync() test. */
17  const filename = join(tmpdir.path, 'test.txt');
18
19  /* Open the file descriptor. */
20  const fd = fs.openSync(filename, 'w');
21  try {
22    /* Write only five characters, so that the position moves to five. */
23    assert.strictEqual(fs.writeSync(fd, 'Hello'), 5);
24    assert.strictEqual(fs.readFileSync(filename).toString(), 'Hello');
25
26    /* Write some more with writeFileSync(). */
27    fs.writeFileSync(fd, 'World');
28
29    /* New content should be written at position five, instead of zero. */
30    assert.strictEqual(fs.readFileSync(filename).toString(), 'HelloWorld');
31  } finally {
32    fs.closeSync(fd);
33  }
34}
35
36const fdsToCloseOnExit = [];
37process.on('beforeExit', common.mustCall(() => {
38  for (const fd of fdsToCloseOnExit) {
39    try {
40      fs.closeSync(fd);
41    } catch {
42      // Failed to close, ignore
43    }
44  }
45}));
46
47{
48  /* writeFile() test. */
49  const file = join(tmpdir.path, 'test1.txt');
50
51  /* Open the file descriptor. */
52  fs.open(file, 'w', common.mustSucceed((fd) => {
53    fdsToCloseOnExit.push(fd);
54    /* Write only five characters, so that the position moves to five. */
55    fs.write(fd, 'Hello', common.mustSucceed((bytes) => {
56      assert.strictEqual(bytes, 5);
57      assert.strictEqual(fs.readFileSync(file).toString(), 'Hello');
58
59      /* Write some more with writeFile(). */
60      fs.writeFile(fd, 'World', common.mustSucceed(() => {
61        /* New content should be written at position five, instead of zero. */
62        assert.strictEqual(fs.readFileSync(file).toString(), 'HelloWorld');
63      }));
64    }));
65  }));
66}
67
68
69// Test read-only file descriptor
70{
71  const file = join(tmpdir.path, 'test.txt');
72
73  fs.open(file, 'r', common.mustSucceed((fd) => {
74    fdsToCloseOnExit.push(fd);
75    fs.writeFile(fd, 'World', common.expectsError(/EBADF/));
76  }));
77}
78
79// Test with an AbortSignal
80{
81  const controller = new AbortController();
82  const signal = controller.signal;
83  const file = join(tmpdir.path, 'test.txt');
84
85  fs.open(file, 'w', common.mustSucceed((fd) => {
86    fdsToCloseOnExit.push(fd);
87    fs.writeFile(fd, 'World', { signal }, common.expectsError({
88      name: 'AbortError'
89    }));
90  }));
91
92  controller.abort();
93}
94