mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
* Call fsync() before closing file
* Fix race condition in tests due to incorrect stub.
The startFlows() function wasn't really being stubbed, so it was still being called. But there was no corresponding call to stopFlows().
In later tests, the check in Flows.init() was throwing the "Cannot init without a stop" error.
* Test coverage for fsync() calls
For issue #1478
* Revert "Fix race condition in tests due to incorrect stub."
This reverts commit 4f71d7851b
.
* Fix race condition in tests due to incorrect stub.
The startFlows() function wasn't really being stubbed, so it was still being called. But there was no corresponding call to stopFlows().
In later tests, the check in Flows.init() was throwing the "Cannot init without a stop" error.
* Fix intermittent test failure in Exec node.
Occasionally, the error text on stderr will come in more than one piece. The test only worked correctly if a single message was received.
This commit is contained in:
parent
f39d9d6f1b
commit
6baedf909d
@ -137,7 +137,8 @@
|
|||||||
"empty": "Existing __type__ file is empty",
|
"empty": "Existing __type__ file is empty",
|
||||||
"invalid": "Existing __type__ file is not valid json",
|
"invalid": "Existing __type__ file is not valid json",
|
||||||
"restore": "Restoring __type__ file backup : __path__",
|
"restore": "Restoring __type__ file backup : __path__",
|
||||||
"restore-fail": "Restoring __type__ file backup failed : __message__"
|
"restore-fail": "Restoring __type__ file backup failed : __message__",
|
||||||
|
"fsync-fail": "Flushing file __path__ to disk failed : __message__"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,8 +114,13 @@ function writeFile(path,content) {
|
|||||||
return when.promise(function(resolve,reject) {
|
return when.promise(function(resolve,reject) {
|
||||||
var stream = fs.createWriteStream(path);
|
var stream = fs.createWriteStream(path);
|
||||||
stream.on('open',function(fd) {
|
stream.on('open',function(fd) {
|
||||||
stream.end(content,'utf8',function() {
|
stream.write(content,'utf8',function() {
|
||||||
fs.fsync(fd,resolve);
|
fs.fsync(fd,function(err) {
|
||||||
|
if (err) {
|
||||||
|
log.warn(log._("storage.localfilesystem.fsync-fail",{path: path, message: err.toString()}));
|
||||||
|
}
|
||||||
|
stream.end(resolve);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
stream.on('error',function(err) {
|
stream.on('error',function(err) {
|
||||||
|
@ -544,6 +544,7 @@ describe('exec node', function() {
|
|||||||
it('should return an error for a failing command', function(done) {
|
it('should return an error for a failing command', function(done) {
|
||||||
var flow;
|
var flow;
|
||||||
var expected;
|
var expected;
|
||||||
|
var expectedFound = false;
|
||||||
if (osType === "Windows_NT") {
|
if (osType === "Windows_NT") {
|
||||||
// Cannot use mkdir because Windows mkdir command automatically creates non-existent directories.
|
// Cannot use mkdir because Windows mkdir command automatically creates non-existent directories.
|
||||||
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"ping /foo/bar/doo/dah", addpay:false, append:"", useSpawn:"true", oldrc:"false"},
|
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"ping /foo/bar/doo/dah", addpay:false, append:"", useSpawn:"true", oldrc:"false"},
|
||||||
@ -563,12 +564,18 @@ describe('exec node', function() {
|
|||||||
try {
|
try {
|
||||||
msg.should.have.property("payload");
|
msg.should.have.property("payload");
|
||||||
msg.payload.should.be.a.String();
|
msg.payload.should.be.a.String();
|
||||||
msg.payload.indexOf(expected).should.not.be.equal(-1);
|
if (msg.payload.indexOf(expected) >= 0) {
|
||||||
|
// The error text on the stderr stream might get sent in more than one piece.
|
||||||
|
// We only need to know that it occurred before the return code is sent,
|
||||||
|
// as checked below in node n4.
|
||||||
|
expectedFound = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch(err) { done(err); }
|
catch(err) { done(err); }
|
||||||
});
|
});
|
||||||
n4.on("input", function(msg) {
|
n4.on("input", function(msg) {
|
||||||
try {
|
try {
|
||||||
|
expectedFound.should.be.true;
|
||||||
msg.should.have.property("payload");
|
msg.should.have.property("payload");
|
||||||
msg.payload.should.have.property("code",1);
|
msg.payload.should.have.property("code",1);
|
||||||
done();
|
done();
|
||||||
|
@ -26,11 +26,11 @@ var registry = require("../../../../red/runtime/nodes/registry");
|
|||||||
|
|
||||||
describe("red/nodes/index", function() {
|
describe("red/nodes/index", function() {
|
||||||
before(function() {
|
before(function() {
|
||||||
sinon.stub(flows,"startFlows");
|
sinon.stub(index,"startFlows");
|
||||||
process.env.NODE_RED_HOME = path.resolve(path.join(__dirname,"..","..","..",".."))
|
process.env.NODE_RED_HOME = path.resolve(path.join(__dirname,"..","..","..",".."))
|
||||||
});
|
});
|
||||||
after(function() {
|
after(function() {
|
||||||
flows.startFlows.restore();
|
index.startFlows.restore();
|
||||||
delete process.env.NODE_RED_HOME;
|
delete process.env.NODE_RED_HOME;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -17,8 +17,10 @@
|
|||||||
var should = require("should");
|
var should = require("should");
|
||||||
var fs = require('fs-extra');
|
var fs = require('fs-extra');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
var sinon = require('sinon');
|
||||||
|
|
||||||
var localfilesystem = require("../../../../red/runtime/storage/localfilesystem");
|
var localfilesystem = require("../../../../red/runtime/storage/localfilesystem");
|
||||||
|
var log = require("../../../../red/runtime/log");
|
||||||
|
|
||||||
describe('LocalFileSystem', function() {
|
describe('LocalFileSystem', function() {
|
||||||
var userDir = path.join(__dirname,".testUserHome");
|
var userDir = path.join(__dirname,".testUserHome");
|
||||||
@ -279,6 +281,45 @@ describe('LocalFileSystem', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should fsync the flows file',function(done) {
|
||||||
|
var flowFile = 'test.json';
|
||||||
|
var flowFilePath = path.join(userDir,flowFile);
|
||||||
|
localfilesystem.init({userDir:userDir, flowFile:flowFilePath}).then(function() {
|
||||||
|
sinon.spy(fs,"fsync");
|
||||||
|
localfilesystem.saveFlows(testFlow).then(function() {
|
||||||
|
fs.fsync.callCount.should.eql(1);
|
||||||
|
fs.fsync.restore();
|
||||||
|
done();
|
||||||
|
}).otherwise(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).otherwise(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should log fsync errors and continue',function(done) {
|
||||||
|
var flowFile = 'test.json';
|
||||||
|
var flowFilePath = path.join(userDir,flowFile);
|
||||||
|
localfilesystem.init({userDir:userDir, flowFile:flowFilePath}).then(function() {
|
||||||
|
sinon.stub(fs,"fsync", function(fd, cb) {
|
||||||
|
cb(new Error());
|
||||||
|
});
|
||||||
|
sinon.spy(log,"warn");
|
||||||
|
localfilesystem.saveFlows(testFlow).then(function() {
|
||||||
|
log.warn.callCount.should.eql(1);
|
||||||
|
log.warn.restore();
|
||||||
|
fs.fsync.callCount.should.eql(1);
|
||||||
|
fs.fsync.restore();
|
||||||
|
done();
|
||||||
|
}).otherwise(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).otherwise(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should backup the flows file', function(done) {
|
it('should backup the flows file', function(done) {
|
||||||
var defaultFlowFile = 'flows_'+require('os').hostname()+'.json';
|
var defaultFlowFile = 'flows_'+require('os').hostname()+'.json';
|
||||||
var defaultFlowFilePath = path.join(userDir,defaultFlowFile);
|
var defaultFlowFilePath = path.join(userDir,defaultFlowFile);
|
||||||
|
Loading…
Reference in New Issue
Block a user