test: fix flaky test-fs-stream-construct

The test is marked flaky on ARM because it times out on Raspberry Pi
devices in CI. Split the single test file into four separate test files
to ease debugging. Add fs.close() to avoid timing out.

Fixes: https://github.com/nodejs/node/issues/33796

PR-URL: https://github.com/nodejs/node/pull/34203
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Robert Nagy <ronagy@icloud.com>
This commit is contained in:
Rich Trott committed 2020-07-06 17:32:24 -07:00
1 parent ee3416b055
commit 772fdb0cd3
6 files changed
+249 -214

No files matched your search

-2
View File
@@ -40,8 +40,6 @@ test-async-hooks-http-parser-destroy: PASS,FLAKY
# https://github.com/nodejs/node/pull/31178
test-crypto-dh-stateless: SKIP
test-crypto-keygen: SKIP
# https://github.com/nodejs/node/issues/33796
test-fs-stream-construct: PASS,FLAKY
[$system==solaris] # Also applies to SmartOS
@@ -0,0 +1,32 @@
'use strict';
const common = require('../common');
const fs = require('fs');
const assert = require('assert');
const tmpdir = require('../common/tmpdir');
tmpdir.refresh();
{
// Compat error.
function ReadStream(...args) {
fs.ReadStream.call(this, ...args);
}
Object.setPrototypeOf(ReadStream.prototype, fs.ReadStream.prototype);
Object.setPrototypeOf(ReadStream, fs.ReadStream);
ReadStream.prototype.open = common.mustCall(function ReadStream$open() {
const that = this;
fs.open(that.path, that.flags, that.mode, (err, fd) => {
that.emit('error', err);
});
});
const r = new ReadStream('/doesnotexist', { emitClose: true })
.on('error', common.mustCall((err) => {
assert.strictEqual(err.code, 'ENOENT');
assert.strictEqual(r.destroyed, true);
r.on('close', common.mustCall());
}));
}
@@ -0,0 +1,50 @@
'use strict';
const common = require('../common');
const fs = require('fs');
const assert = require('assert');
const debuglog = (arg) => {
console.log(new Date().toLocaleString(), arg);
};
const tmpdir = require('../common/tmpdir');
tmpdir.refresh();
{
// Compat error.
debuglog('start test');
function WriteStream(...args) {
debuglog('WriteStream constructor');
fs.WriteStream.call(this, ...args);
}
Object.setPrototypeOf(WriteStream.prototype, fs.WriteStream.prototype);
Object.setPrototypeOf(WriteStream, fs.WriteStream);
WriteStream.prototype.open = common.mustCall(function WriteStream$open() {
debuglog('WriteStream open() callback');
const that = this;
fs.open(that.path, that.flags, that.mode, (err, fd) => {
debuglog('inner fs open() callback');
that.emit('error', err);
});
});
fs.open(`${tmpdir.path}/dummy`, 'wx+', common.mustCall((err, fd) => {
debuglog('fs open() callback');
assert.ifError(err);
fs.close(fd, () => { debuglog(`closed ${fd}`); });
const w = new WriteStream(`${tmpdir.path}/dummy`,
{ flags: 'wx+', emitClose: true })
.on('error', common.mustCall((err) => {
debuglog('error event callback');
assert.strictEqual(err.code, 'EEXIST');
w.destroy();
w.on('close', common.mustCall(() => {
debuglog('close event callback');
}));
}));
}));
debuglog('waiting for callbacks');
}
@@ -0,0 +1,70 @@
'use strict';
const common = require('../common');
const fs = require('fs');
const assert = require('assert');
const fixtures = require('../common/fixtures');
const tmpdir = require('../common/tmpdir');
tmpdir.refresh();
{
// Compat with graceful-fs.
function ReadStream(...args) {
fs.ReadStream.call(this, ...args);
}
Object.setPrototypeOf(ReadStream.prototype, fs.ReadStream.prototype);
Object.setPrototypeOf(ReadStream, fs.ReadStream);
ReadStream.prototype.open = common.mustCall(function ReadStream$open() {
const that = this;
fs.open(that.path, that.flags, that.mode, (err, fd) => {
if (err) {
if (that.autoClose)
that.destroy();
that.emit('error', err);
} else {
that.fd = fd;
that.emit('open', fd);
that.read();
}
});
});
const r = new ReadStream(fixtures.path('x.txt'))
.on('open', common.mustCall((fd) => {
assert.strictEqual(fd, r.fd);
r.destroy();
}));
}
{
// Compat with graceful-fs.
function WriteStream(...args) {
fs.WriteStream.call(this, ...args);
}
Object.setPrototypeOf(WriteStream.prototype, fs.WriteStream.prototype);
Object.setPrototypeOf(WriteStream, fs.WriteStream);
WriteStream.prototype.open = common.mustCall(function WriteStream$open() {
const that = this;
fs.open(that.path, that.flags, that.mode, function(err, fd) {
if (err) {
that.destroy();
that.emit('error', err);
} else {
that.fd = fd;
that.emit('open', fd);
}
});
});
const w = new WriteStream(`${tmpdir.path}/dummy`)
.on('open', common.mustCall((fd) => {
assert.strictEqual(fd, w.fd);
w.destroy();
}));
}
@@ -0,0 +1,97 @@
'use strict';
const common = require('../common');
const fs = require('fs');
const assert = require('assert');
const fixtures = require('../common/fixtures');
const tmpdir = require('../common/tmpdir');
tmpdir.refresh();
{
// Compat with old node.
function ReadStream(...args) {
fs.ReadStream.call(this, ...args);
}
Object.setPrototypeOf(ReadStream.prototype, fs.ReadStream.prototype);
Object.setPrototypeOf(ReadStream, fs.ReadStream);
ReadStream.prototype.open = common.mustCall(function() {
fs.open(this.path, this.flags, this.mode, (er, fd) => {
if (er) {
if (this.autoClose) {
this.destroy();
}
this.emit('error', er);
return;
}
this.fd = fd;
this.emit('open', fd);
this.emit('ready');
});
});
let readyCalled = false;
let ticked = false;
const r = new ReadStream(fixtures.path('x.txt'))
.on('ready', common.mustCall(() => {
readyCalled = true;
// Make sure 'ready' is emitted in same tick as 'open'.
assert.strictEqual(ticked, false);
}))
.on('error', common.mustNotCall())
.on('open', common.mustCall((fd) => {
process.nextTick(() => {
ticked = true;
r.destroy();
});
assert.strictEqual(readyCalled, false);
assert.strictEqual(fd, r.fd);
}));
}
{
// Compat with old node.
function WriteStream(...args) {
fs.WriteStream.call(this, ...args);
}
Object.setPrototypeOf(WriteStream.prototype, fs.WriteStream.prototype);
Object.setPrototypeOf(WriteStream, fs.WriteStream);
WriteStream.prototype.open = common.mustCall(function() {
fs.open(this.path, this.flags, this.mode, (er, fd) => {
if (er) {
if (this.autoClose) {
this.destroy();
}
this.emit('error', er);
return;
}
this.fd = fd;
this.emit('open', fd);
this.emit('ready');
});
});
let readyCalled = false;
let ticked = false;
const w = new WriteStream(`${tmpdir.path}/dummy`)
.on('ready', common.mustCall(() => {
readyCalled = true;
// Make sure 'ready' is emitted in same tick as 'open'.
assert.strictEqual(ticked, false);
}))
.on('error', common.mustNotCall())
.on('open', common.mustCall((fd) => {
process.nextTick(() => {
ticked = true;
w.destroy();
});
assert.strictEqual(readyCalled, false);
assert.strictEqual(fd, w.fd);
}));
}
-212
View File
@@ -1,212 +0,0 @@
'use strict';
const common = require('../common');
const fs = require('fs');
const assert = require('assert');
const fixtures = require('../common/fixtures');
const tmpdir = require('../common/tmpdir');
tmpdir.refresh();
const examplePath = fixtures.path('x.txt');
{
// Compat with old node.
function ReadStream(...args) {
fs.ReadStream.call(this, ...args);
}
Object.setPrototypeOf(ReadStream.prototype, fs.ReadStream.prototype);
Object.setPrototypeOf(ReadStream, fs.ReadStream);
ReadStream.prototype.open = common.mustCall(function() {
fs.open(this.path, this.flags, this.mode, (er, fd) => {
if (er) {
if (this.autoClose) {
this.destroy();
}
this.emit('error', er);
return;
}
this.fd = fd;
this.emit('open', fd);
this.emit('ready');
});
});
let readyCalled = false;
let ticked = false;
const r = new ReadStream(examplePath)
.on('ready', common.mustCall(() => {
readyCalled = true;
// Make sure 'ready' is emitted in same tick as 'open'.
assert.strictEqual(ticked, false);
}))
.on('error', common.mustNotCall())
.on('open', common.mustCall((fd) => {
process.nextTick(() => {
ticked = true;
r.destroy();
});
assert.strictEqual(readyCalled, false);
assert.strictEqual(fd, r.fd);
}));
}
{
// Compat with old node.
function WriteStream(...args) {
fs.WriteStream.call(this, ...args);
}
Object.setPrototypeOf(WriteStream.prototype, fs.WriteStream.prototype);
Object.setPrototypeOf(WriteStream, fs.WriteStream);
WriteStream.prototype.open = common.mustCall(function() {
fs.open(this.path, this.flags, this.mode, (er, fd) => {
if (er) {
if (this.autoClose) {
this.destroy();
}
this.emit('error', er);
return;
}
this.fd = fd;
this.emit('open', fd);
this.emit('ready');
});
});
let readyCalled = false;
let ticked = false;
const w = new WriteStream(`${tmpdir.path}/dummy`)
.on('ready', common.mustCall(() => {
readyCalled = true;
// Make sure 'ready' is emitted in same tick as 'open'.
assert.strictEqual(ticked, false);
}))
.on('error', common.mustNotCall())
.on('open', common.mustCall((fd) => {
process.nextTick(() => {
ticked = true;
w.destroy();
});
assert.strictEqual(readyCalled, false);
assert.strictEqual(fd, w.fd);
}));
}
{
// Compat with graceful-fs.
function ReadStream(...args) {
fs.ReadStream.call(this, ...args);
}
Object.setPrototypeOf(ReadStream.prototype, fs.ReadStream.prototype);
Object.setPrototypeOf(ReadStream, fs.ReadStream);
ReadStream.prototype.open = common.mustCall(function ReadStream$open() {
const that = this;
fs.open(that.path, that.flags, that.mode, (err, fd) => {
if (err) {
if (that.autoClose)
that.destroy();
that.emit('error', err);
} else {
that.fd = fd;
that.emit('open', fd);
that.read();
}
});
});
const r = new ReadStream(examplePath)
.on('open', common.mustCall((fd) => {
assert.strictEqual(fd, r.fd);
r.destroy();
}));
}
{
// Compat with graceful-fs.
function WriteStream(...args) {
fs.WriteStream.call(this, ...args);
}
Object.setPrototypeOf(WriteStream.prototype, fs.WriteStream.prototype);
Object.setPrototypeOf(WriteStream, fs.WriteStream);
WriteStream.prototype.open = common.mustCall(function WriteStream$open() {
const that = this;
fs.open(that.path, that.flags, that.mode, function(err, fd) {
if (err) {
that.destroy();
that.emit('error', err);
} else {
that.fd = fd;
that.emit('open', fd);
}
});
});
const w = new WriteStream(`${tmpdir.path}/dummy2`)
.on('open', common.mustCall((fd) => {
assert.strictEqual(fd, w.fd);
w.destroy();
}));
}
{
// Compat error.
function ReadStream(...args) {
fs.ReadStream.call(this, ...args);
}
Object.setPrototypeOf(ReadStream.prototype, fs.ReadStream.prototype);
Object.setPrototypeOf(ReadStream, fs.ReadStream);
ReadStream.prototype.open = common.mustCall(function ReadStream$open() {
const that = this;
fs.open(that.path, that.flags, that.mode, (err, fd) => {
that.emit('error', err);
});
});
const r = new ReadStream('/doesnotexist', { emitClose: true })
.on('error', common.mustCall((err) => {
assert.strictEqual(err.code, 'ENOENT');
assert.strictEqual(r.destroyed, true);
r.on('close', common.mustCall());
}));
}
{
// Compat error.
function WriteStream(...args) {
fs.WriteStream.call(this, ...args);
}
Object.setPrototypeOf(WriteStream.prototype, fs.WriteStream.prototype);
Object.setPrototypeOf(WriteStream, fs.WriteStream);
WriteStream.prototype.open = common.mustCall(function WriteStream$open() {
const that = this;
fs.open(that.path, that.flags, that.mode, (err, fd) => {
that.emit('error', err);
});
});
fs.open(`${tmpdir.path}/dummy3`, 'wx+', common.mustCall((err) => {
assert(!err);
const w = new WriteStream(`${tmpdir.path}/dummy3`,
{ flags: 'wx+', emitClose: true })
.on('error', common.mustCall((err) => {
assert.strictEqual(err.code, 'EEXIST');
w.destroy();
w.on('close', common.mustCall());
}));
}));
}