mirror of
https://github.com/zebrajr/node.git
synced 2026-01-15 12:15:26 +00:00
test: add and use tmpdir.hasEnoughSpace()
In general, we assume that the tmpdir will provide sufficient space for most tests. Some tests, however, require hundreds of megabytes or even gigabytes of space, which often causes them to fail, especially on our macOS infrastructure. The most recent reliability report contains more than 20 related CI failures. This change adds a new function hasEnoughSpace() to the tmpdir module that uses statfsSync() to guess whether allocating a certain amount of space within the temporary directory will succeed. This change also updates the most frequently failing tests to use the new function such that the relevant parts of the tests are skipped if tmpdir has insufficient space. Refs: https://github.com/nodejs/reliability/issues/549 PR-URL: https://github.com/nodejs/node/pull/47767 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Moshe Atlow <moshe@atlow.co.il> Reviewed-By: Richard Lau <rlau@redhat.com>
This commit is contained in:
@@ -1030,6 +1030,15 @@ Avoid calling it more than once in an asynchronous context as one call
|
||||
might refresh the temporary directory of a different context, causing
|
||||
the test to fail somewhat mysteriously.
|
||||
|
||||
### `hasEnoughSpace(size)`
|
||||
|
||||
* `size` [\<number>][<number>] Required size, in bytes.
|
||||
|
||||
Returns `true` if the available blocks of the file system underlying `path`
|
||||
are likely sufficient to hold a single file of `size` bytes. This is useful for
|
||||
skipping tests that require hundreds of megabytes or even gigabytes of temporary
|
||||
files, but it is inaccurate and susceptible to race conditions.
|
||||
|
||||
## UDP pair helper
|
||||
|
||||
The `common/udppair` module exports a function `makeUDPPair` and a class
|
||||
|
||||
@@ -69,7 +69,13 @@ function onexit(useSpawn) {
|
||||
}
|
||||
}
|
||||
|
||||
function hasEnoughSpace(size) {
|
||||
const { bavail, bsize } = fs.statfsSync(tmpPath);
|
||||
return bavail >= Math.ceil(size / bsize);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
path: tmpPath,
|
||||
refresh,
|
||||
hasEnoughSpace,
|
||||
};
|
||||
|
||||
@@ -106,17 +106,22 @@ async function doReadAndCancel() {
|
||||
// Variable taken from https://github.com/nodejs/node/blob/1377163f3351/lib/internal/fs/promises.js#L5
|
||||
const kIoMaxLength = 2 ** 31 - 1;
|
||||
|
||||
const newFile = path.resolve(tmpDir, 'dogs-running3.txt');
|
||||
await writeFile(newFile, Buffer.from('0'));
|
||||
await truncate(newFile, kIoMaxLength + 1);
|
||||
if (!tmpdir.hasEnoughSpace(kIoMaxLength)) {
|
||||
// truncate() will fail with ENOSPC if there is not enough space.
|
||||
common.printSkipMessage(`Not enough space in ${tmpDir}`);
|
||||
} else {
|
||||
const newFile = path.resolve(tmpDir, 'dogs-running3.txt');
|
||||
await writeFile(newFile, Buffer.from('0'));
|
||||
await truncate(newFile, kIoMaxLength + 1);
|
||||
|
||||
const fileHandle = await open(newFile, 'r');
|
||||
const fileHandle = await open(newFile, 'r');
|
||||
|
||||
await assert.rejects(fileHandle.readFile(), {
|
||||
name: 'RangeError',
|
||||
code: 'ERR_FS_FILE_TOO_LARGE'
|
||||
});
|
||||
await fileHandle.close();
|
||||
await assert.rejects(fileHandle.readFile(), {
|
||||
name: 'RangeError',
|
||||
code: 'ERR_FS_FILE_TOO_LARGE'
|
||||
});
|
||||
await fileHandle.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,21 +52,27 @@ for (const e of fileInfo) {
|
||||
assert.deepStrictEqual(buf, e.contents);
|
||||
}));
|
||||
}
|
||||
// Test readFile size too large
|
||||
|
||||
// readFile() and readFileSync() should fail if the file is too big.
|
||||
{
|
||||
const kIoMaxLength = 2 ** 31 - 1;
|
||||
|
||||
const file = path.join(tmpdir.path, `${prefix}-too-large.txt`);
|
||||
fs.writeFileSync(file, Buffer.from('0'));
|
||||
fs.truncateSync(file, kIoMaxLength + 1);
|
||||
if (!tmpdir.hasEnoughSpace(kIoMaxLength)) {
|
||||
// truncateSync() will fail with ENOSPC if there is not enough space.
|
||||
common.printSkipMessage(`Not enough space in ${tmpdir.path}`);
|
||||
} else {
|
||||
const file = path.join(tmpdir.path, `${prefix}-too-large.txt`);
|
||||
fs.writeFileSync(file, Buffer.from('0'));
|
||||
fs.truncateSync(file, kIoMaxLength + 1);
|
||||
|
||||
fs.readFile(file, common.expectsError({
|
||||
code: 'ERR_FS_FILE_TOO_LARGE',
|
||||
name: 'RangeError',
|
||||
}));
|
||||
assert.throws(() => {
|
||||
fs.readFileSync(file);
|
||||
}, { code: 'ERR_FS_FILE_TOO_LARGE', name: 'RangeError' });
|
||||
fs.readFile(file, common.expectsError({
|
||||
code: 'ERR_FS_FILE_TOO_LARGE',
|
||||
name: 'RangeError',
|
||||
}));
|
||||
assert.throws(() => {
|
||||
fs.readFileSync(file);
|
||||
}, { code: 'ERR_FS_FILE_TOO_LARGE', name: 'RangeError' });
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -16,6 +16,10 @@ if (common.isAIX && (Number(cp.execSync('ulimit -f')) * 512) < kStringMaxLength)
|
||||
const tmpdir = require('../common/tmpdir');
|
||||
tmpdir.refresh();
|
||||
|
||||
if (!tmpdir.hasEnoughSpace(kStringMaxLength)) {
|
||||
common.skip(`Not enough space in ${tmpdir.path}`);
|
||||
}
|
||||
|
||||
const file = path.join(tmpdir.path, 'toobig.txt');
|
||||
const stream = fs.createWriteStream(file, {
|
||||
flags: 'a',
|
||||
|
||||
Reference in New Issue
Block a user