mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Make exec node spawn and exec outputs more consistent
(with an option to revert if necessary) and new info docs
This commit is contained in:
parent
5cb37148c6
commit
a281b8c74e
@ -21,17 +21,24 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<label><i class="fa fa-plus"></i> <span data-i18n="exec.label.append"></span></label>
|
<label><i class="fa fa-plus"></i> <span data-i18n="exec.label.append"></span></label>
|
||||||
<input type="checkbox" id="node-input-addpay" style="display: inline-block; width: auto; vertical-align: top;">
|
<input type="checkbox" id="node-input-addpay" style="display:inline-block; width:auto; vertical-align:top;">
|
||||||
msg.payload
|
msg.payload
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<label for="node-input-append"> </label>
|
<label for="node-input-append"> </label>
|
||||||
<input type="text" id="node-input-append" data-i18n="[placeholder]exec.placeholder.extraparams">
|
<input type="text" id="node-input-append" data-i18n="[placeholder]exec.placeholder.extraparams">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label><i class="fa fa-sign-out"></i> <span data-i18n="exec.label.return"></span></label>
|
||||||
|
<select type="text" id="node-input-useSpawn" style="width:70%">
|
||||||
|
<option value="false" data-i18n="exec.opt.exec"></option>
|
||||||
|
<option value="true" data-i18n="exec.opt.spawn"></option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<label> </label>
|
<label> </label>
|
||||||
<input type="checkbox" id="node-input-useSpawn" placeholder="spawn" style="display: inline-block; width: auto; vertical-align: top;">
|
<input type="checkbox" id="node-input-oldrc" style="display:inline-block; width:auto; vertical-align:top;">
|
||||||
<label for="node-input-useSpawn" style="width:70%;"><span data-i18n="exec.spawn"></span></label>
|
<label for="node-input-oldrc" style="width:70%;"><span data-i18n="exec.oldrc"></span></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<label for="node-input-timer"><i class="fa fa-clock-o"></i> <span data-i18n="exec.label.timeout"></span></label>
|
<label for="node-input-timer"><i class="fa fa-clock-o"></i> <span data-i18n="exec.label.timeout"></span></label>
|
||||||
@ -74,11 +81,10 @@
|
|||||||
<dd>the standard error of the command.</dd>
|
<dd>the standard error of the command.</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>Return code
|
<li>Return code
|
||||||
<dl class="message-properties">
|
<dl class="message-properties">
|
||||||
<dt>payload <span class="property-type">number</span></dt>
|
<dt>payload <span class="property-type">object</span></dt>
|
||||||
<dd>the return code of the command.</dd>
|
<dd>an object containing the return code, and possibly <code>message</code>, <code>signal</code> properties.</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
@ -86,8 +92,10 @@
|
|||||||
<p>By default uses the <code>exec</code> system call which calls the command, waits for it to complete, and then
|
<p>By default uses the <code>exec</code> system call which calls the command, waits for it to complete, and then
|
||||||
returns the output. For example a successful command should have a return code of <code>{ code: 0 }</code>.</p>
|
returns the output. For example a successful command should have a return code of <code>{ code: 0 }</code>.</p>
|
||||||
<p>Optionally can use <code>spawn</code> instead, which returns the output from stdout and stderr
|
<p>Optionally can use <code>spawn</code> instead, which returns the output from stdout and stderr
|
||||||
as the command runs, usually one line at a time. On completion it then returns a numeric return code
|
as the command runs, usually one line at a time. On completion it then returns an object
|
||||||
on the 3rd port. For example, a successful command should return <code>0</code>.</p>
|
on the 3rd port. For example, a successful command should return <code>{ code: 0 }</code>.</p>
|
||||||
|
<p>Errors may return extra information on the 3rd port <code>msg.payload</code>, such as a <code>message</code> string,
|
||||||
|
<code>signal</code> string.</p>
|
||||||
<p>The command that is run is defined within the node, with an option to append <code>msg.payload</code> and a further set of parameters.</p>
|
<p>The command that is run is defined within the node, with an option to append <code>msg.payload</code> and a further set of parameters.</p>
|
||||||
<p>Commands or parameters with spaces should be enclosed in quotes - <code>"This is a single parameter"</code></p>
|
<p>Commands or parameters with spaces should be enclosed in quotes - <code>"This is a single parameter"</code></p>
|
||||||
<p>The returned <code>payload</code> is usually a <i>string</i>, unless non-UTF8 characters are detected, in which
|
<p>The returned <code>payload</code> is usually a <i>string</i>, unless non-UTF8 characters are detected, in which
|
||||||
@ -95,7 +103,8 @@
|
|||||||
<p>The node's status icon and PID will be visible while the node is active. Changes to this can be read by the <code>Status</code> node.</p>
|
<p>The node's status icon and PID will be visible while the node is active. Changes to this can be read by the <code>Status</code> node.</p>
|
||||||
<h4>Killing processes</h4>
|
<h4>Killing processes</h4>
|
||||||
<p>Sending <code>msg.kill</code> will kill a single active process. <code>msg.kill</code> should be a string containing
|
<p>Sending <code>msg.kill</code> will kill a single active process. <code>msg.kill</code> should be a string containing
|
||||||
the type of signal to be sent, for example, <code>SIGINT</code>, <code>SIGQUIT</code> or <code>SIGHUP</code>. Defaults to <code>SIGTERM</code> if set to an empty string.</p>
|
the type of signal to be sent, for example, <code>SIGINT</code>, <code>SIGQUIT</code> or <code>SIGHUP</code>.
|
||||||
|
Defaults to <code>SIGTERM</code> if set to an empty string.</p>
|
||||||
<p>If the node has more than one process running then <code>msg.pid</code> must also be set with the value of the PID to be killed.</p>
|
<p>If the node has more than one process running then <code>msg.pid</code> must also be set with the value of the PID to be killed.</p>
|
||||||
<p>Tip: if running a Python app you may need to use the <code>-u</code> parameter to stop the output being buffered.</p>
|
<p>Tip: if running a Python app you may need to use the <code>-u</code> parameter to stop the output being buffered.</p>
|
||||||
</script>
|
</script>
|
||||||
@ -108,8 +117,9 @@
|
|||||||
command: {value:""},
|
command: {value:""},
|
||||||
addpay: {value:true},
|
addpay: {value:true},
|
||||||
append: {value:""},
|
append: {value:""},
|
||||||
useSpawn: {value:""},
|
useSpawn: {value:"false"},
|
||||||
timer: {value:""},
|
timer: {value:""},
|
||||||
|
oldrc: {value:false},
|
||||||
name: {value:""}
|
name: {value:""}
|
||||||
},
|
},
|
||||||
inputs:1,
|
inputs:1,
|
||||||
@ -122,6 +132,11 @@
|
|||||||
},
|
},
|
||||||
labelStyle: function() {
|
labelStyle: function() {
|
||||||
return this.name?"node_label_italic":"";
|
return this.name?"node_label_italic":"";
|
||||||
|
},
|
||||||
|
oneditprepare: function() {
|
||||||
|
if ($("#node-input-useSpawn").val() === null) {
|
||||||
|
$("#node-input-useSpawn").val(this.useSpawn.toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -26,15 +26,16 @@ module.exports = function(RED) {
|
|||||||
if (n.addpay === undefined) { n.addpay = true; }
|
if (n.addpay === undefined) { n.addpay = true; }
|
||||||
this.addpay = n.addpay;
|
this.addpay = n.addpay;
|
||||||
this.append = (n.append || "").trim();
|
this.append = (n.append || "").trim();
|
||||||
this.useSpawn = n.useSpawn;
|
this.useSpawn = (n.useSpawn == "true");
|
||||||
this.timer = Number(n.timer || 0)*1000;
|
this.timer = Number(n.timer || 0)*1000;
|
||||||
this.activeProcesses = {};
|
this.activeProcesses = {};
|
||||||
|
this.oldrc = (n.oldrc || false).toString();
|
||||||
var node = this;
|
var node = this;
|
||||||
|
|
||||||
var cleanup = function(p) {
|
var cleanup = function(p) {
|
||||||
node.activeProcesses[p].kill();
|
node.activeProcesses[p].kill();
|
||||||
node.status({fill:"red",shape:"dot",text:"timeout"});
|
//node.status({fill:"red",shape:"dot",text:"timeout"});
|
||||||
node.error("Exec node timeout");
|
//node.error("Exec node timeout");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.on("input", function(msg) {
|
this.on("input", function(msg) {
|
||||||
@ -89,13 +90,17 @@ module.exports = function(RED) {
|
|||||||
node.send([null,RED.util.cloneMessage(msg),null]);
|
node.send([null,RED.util.cloneMessage(msg),null]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
child.on('close', function (code) {
|
child.on('close', function (code,signal) {
|
||||||
if (unknownCommand || (node.activeProcesses.hasOwnProperty(child.pid) && node.activeProcesses[child.pid] !== null)) {
|
if (unknownCommand || (node.activeProcesses.hasOwnProperty(child.pid) && node.activeProcesses[child.pid] !== null)) {
|
||||||
delete node.activeProcesses[child.pid];
|
delete node.activeProcesses[child.pid];
|
||||||
if (child.tout) { clearTimeout(child.tout); }
|
if (child.tout) { clearTimeout(child.tout); }
|
||||||
msg.payload = code;
|
msg.payload = code;
|
||||||
|
if (node.oldrc === "false") {
|
||||||
|
msg.payload = {code:code};
|
||||||
|
if (signal) { msg.payload.signal = signal; }
|
||||||
|
}
|
||||||
if (code === 0) { node.status({}); }
|
if (code === 0) { node.status({}); }
|
||||||
if (code === null) { node.status({fill:"red",shape:"dot",text:"timeout"}); }
|
if (code === null) { node.status({fill:"red",shape:"dot",text:"killed"}); }
|
||||||
else if (code < 0) { node.status({fill:"red",shape:"dot",text:"rc:"+code}); }
|
else if (code < 0) { node.status({fill:"red",shape:"dot",text:"rc:"+code}); }
|
||||||
else { node.status({fill:"yellow",shape:"dot",text:"rc:"+code}); }
|
else { node.status({fill:"yellow",shape:"dot",text:"rc:"+code}); }
|
||||||
node.send([null,null,RED.util.cloneMessage(msg)]);
|
node.send([null,null,RED.util.cloneMessage(msg)]);
|
||||||
@ -127,10 +132,12 @@ module.exports = function(RED) {
|
|||||||
//console.log('[exec] stdout: ' + stdout);
|
//console.log('[exec] stdout: ' + stdout);
|
||||||
//console.log('[exec] stderr: ' + stderr);
|
//console.log('[exec] stderr: ' + stderr);
|
||||||
if (error !== null) {
|
if (error !== null) {
|
||||||
msg3 = {payload:error};
|
msg3 = {payload:{code:error.code, message:error.message}};
|
||||||
node.status({fill:"red",shape:"dot",text:"error: "+error.code});
|
if (error.signal) { msg3.payload.signal = error.signal; }
|
||||||
//console.log('[exec] error: ' + error);
|
if (error.code === null) { node.status({fill:"red",shape:"dot",text:"killed"}); }
|
||||||
} else {
|
else { node.status({fill:"red",shape:"dot",text:"error:"+error.code}); }
|
||||||
|
node.log('error:' + error);
|
||||||
|
} else if (node.oldrc === "false") {
|
||||||
msg3 = {payload:{code:0}};
|
msg3 = {payload:{code:0}};
|
||||||
}
|
}
|
||||||
if (!msg3) { node.status({}); }
|
if (!msg3) { node.status({}); }
|
||||||
|
@ -43,6 +43,7 @@ describe('exec node', function() {
|
|||||||
n1.should.have.property("append", "");
|
n1.should.have.property("append", "");
|
||||||
n1.should.have.property("addpay",true);
|
n1.should.have.property("addpay",true);
|
||||||
n1.should.have.property("timer",0);
|
n1.should.have.property("timer",0);
|
||||||
|
n1.should.have.property("oldrc","false");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -50,11 +51,10 @@ describe('exec node', function() {
|
|||||||
describe('calling exec', function() {
|
describe('calling exec', function() {
|
||||||
|
|
||||||
it('should exec a simple command', function(done) {
|
it('should exec a simple command', function(done) {
|
||||||
var flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"echo", addpay:false, append:""},
|
var flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"echo", addpay:false, append:"", oldrc:"false"},
|
||||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
var spy = sinon.stub(child_process, 'exec',
|
var spy = sinon.stub(child_process, 'exec',
|
||||||
function(arg1, arg2, arg3, arg4) {
|
function(arg1, arg2, arg3, arg4) {
|
||||||
//console.log(arg1);
|
|
||||||
// arg3(error,stdout,stderr);
|
// arg3(error,stdout,stderr);
|
||||||
arg3(null,arg1,arg1.toUpperCase());
|
arg3(null,arg1,arg1.toUpperCase());
|
||||||
});
|
});
|
||||||
@ -67,7 +67,7 @@ describe('exec node', function() {
|
|||||||
var received = 0;
|
var received = 0;
|
||||||
var messages = [null,null,null];
|
var messages = [null,null,null];
|
||||||
var completeTest = function() {
|
var completeTest = function() {
|
||||||
received++;
|
received = received + 1;
|
||||||
if (received < 3) {
|
if (received < 3) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -79,7 +79,7 @@ describe('exec node', function() {
|
|||||||
|
|
||||||
msg = messages[1];
|
msg = messages[1];
|
||||||
msg.should.have.property("payload");
|
msg.should.have.property("payload");
|
||||||
msg.payload.should.be.a.String;
|
msg.payload.should.be.a.String();
|
||||||
msg.payload.should.equal("ECHO");
|
msg.payload.should.equal("ECHO");
|
||||||
|
|
||||||
msg = messages[2];
|
msg = messages[2];
|
||||||
@ -110,7 +110,7 @@ describe('exec node', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should exec a simple command with extra parameters', function(done) {
|
it('should exec a simple command with extra parameters', function(done) {
|
||||||
var flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"echo", addpay:true, append:"more"},
|
var flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"echo", addpay:true, append:"more", oldrc:"false"},
|
||||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
var spy = sinon.stub(child_process, 'exec',
|
var spy = sinon.stub(child_process, 'exec',
|
||||||
function(arg1, arg2, arg3, arg4) {
|
function(arg1, arg2, arg3, arg4) {
|
||||||
@ -163,7 +163,7 @@ describe('exec node', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to return a binary buffer', function(done) {
|
it('should be able to return a binary buffer', function(done) {
|
||||||
var flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"echo", addpay:true, append:"more"},
|
var flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"echo", addpay:true, append:"more", oldrc:"false"},
|
||||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
var spy = sinon.stub(child_process, 'exec',
|
var spy = sinon.stub(child_process, 'exec',
|
||||||
function(arg1, arg2, arg3, arg4) {
|
function(arg1, arg2, arg3, arg4) {
|
||||||
@ -197,10 +197,10 @@ describe('exec node', function() {
|
|||||||
var flow;
|
var flow;
|
||||||
if (osType === "Windows_NT") {
|
if (osType === "Windows_NT") {
|
||||||
// Although Windows timeout command is equivalent to sleep, this cannot be used because it promptly outputs a message.
|
// Although Windows timeout command is equivalent to sleep, this cannot be used because it promptly outputs a message.
|
||||||
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"ping", addpay:false, append:"192.0.2.0 -n 1 -w 1000 > NUL", timer:"0.3"},
|
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"ping", addpay:false, append:"192.0.2.0 -n 1 -w 1000 > NUL", timer:"0.3", oldrc:"false"},
|
||||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
} else {
|
} else {
|
||||||
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"sleep", addpay:false, append:"1", timer:"0.3"},
|
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"sleep", addpay:false, append:"1", timer:"0.3", oldrc:"false"},
|
||||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
}
|
}
|
||||||
helper.load(execNode, flow, function() {
|
helper.load(execNode, flow, function() {
|
||||||
@ -210,17 +210,17 @@ describe('exec node', function() {
|
|||||||
var n4 = helper.getNode("n4");
|
var n4 = helper.getNode("n4");
|
||||||
n4.on("input", function(msg) {
|
n4.on("input", function(msg) {
|
||||||
msg.should.have.property("payload");
|
msg.should.have.property("payload");
|
||||||
msg.payload.should.have.property("killed",true);
|
msg.payload.should.have.property("signal","SIGTERM");
|
||||||
//done();
|
//done();
|
||||||
});
|
});
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
var logEvents = helper.log().args.filter(function(evt) {
|
var logEvents = helper.log().args.filter(function(evt) {
|
||||||
return evt[0].type == "exec";
|
return evt[0].type == "exec";
|
||||||
});
|
});
|
||||||
var i = logEvents.length - 1;
|
var i = logEvents.length - 2;
|
||||||
//logEvents.should.have.length(1);
|
//logEvents.should.have.length(1);
|
||||||
logEvents[i][0].should.have.a.property('msg');
|
logEvents[0][0].should.have.a.property('msg');
|
||||||
logEvents[i][0].msg.toString().should.startWith("Exec node timeout");
|
logEvents[0][0].msg.toString().should.startWith("error:Error: Command");
|
||||||
done();
|
done();
|
||||||
},400);
|
},400);
|
||||||
n1.receive({});
|
n1.receive({});
|
||||||
@ -230,10 +230,10 @@ describe('exec node', function() {
|
|||||||
it('should be able to kill a long running command', function(done) {
|
it('should be able to kill a long running command', function(done) {
|
||||||
var flow;
|
var flow;
|
||||||
if (osType === "Windows_NT") {
|
if (osType === "Windows_NT") {
|
||||||
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"ping", addpay:false, append:"192.0.2.0 -n 1 -w 1000 > NUL", timer:"2"},
|
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"ping", addpay:false, append:"192.0.2.0 -n 1 -w 1000 > NUL", timer:"2", oldrc:"false"},
|
||||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
} else {
|
} else {
|
||||||
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"sleep", addpay:false, append:"1", timer:"2"},
|
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"sleep", addpay:false, append:"1", timer:"2", oldrc:"false"},
|
||||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
}
|
}
|
||||||
helper.load(execNode, flow, function() {
|
helper.load(execNode, flow, function() {
|
||||||
@ -244,7 +244,6 @@ describe('exec node', function() {
|
|||||||
n4.on("input", function(msg) {
|
n4.on("input", function(msg) {
|
||||||
try {
|
try {
|
||||||
msg.should.have.property("payload");
|
msg.should.have.property("payload");
|
||||||
msg.payload.should.have.property("killed",true);
|
|
||||||
msg.payload.should.have.property("signal","SIGTERM");
|
msg.payload.should.have.property("signal","SIGTERM");
|
||||||
done();
|
done();
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
@ -260,11 +259,12 @@ describe('exec node', function() {
|
|||||||
|
|
||||||
it('should be able to kill a long running command - SIGINT', function(done) {
|
it('should be able to kill a long running command - SIGINT', function(done) {
|
||||||
var flow;
|
var flow;
|
||||||
|
var sig = "SIGINT";
|
||||||
if (osType === "Windows_NT") {
|
if (osType === "Windows_NT") {
|
||||||
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"ping", addpay:false, append:"192.0.2.0 -n 1 -w 1000 > NUL", timer:"2"},
|
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"ping", addpay:false, append:"192.0.2.0 -n 1 -w 1000 > NUL", timer:"2", oldrc:"false"},
|
||||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
} else {
|
} else {
|
||||||
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"sleep", addpay:false, append:"1", timer:"2"},
|
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"sleep", addpay:false, append:"1", timer:"2", oldrc:"false"},
|
||||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
}
|
}
|
||||||
helper.load(execNode, flow, function() {
|
helper.load(execNode, flow, function() {
|
||||||
@ -275,8 +275,7 @@ describe('exec node', function() {
|
|||||||
n4.on("input", function(msg) {
|
n4.on("input", function(msg) {
|
||||||
try {
|
try {
|
||||||
msg.should.have.property("payload");
|
msg.should.have.property("payload");
|
||||||
msg.payload.should.have.property("killed",true);
|
msg.payload.should.have.property("signal",sig);
|
||||||
//msg.payload.should.have.property("signal","SIGINT");
|
|
||||||
done();
|
done();
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
done(err);
|
done(err);
|
||||||
@ -291,7 +290,7 @@ describe('exec node', function() {
|
|||||||
|
|
||||||
|
|
||||||
it('should return the rc for a failing command', function(done) {
|
it('should return the rc for a failing command', function(done) {
|
||||||
var flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"error", addpay:false, append:""},
|
var flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"error", addpay:false, append:"", oldrc:"false"},
|
||||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
var spy = sinon.stub(child_process, 'exec',
|
var spy = sinon.stub(child_process, 'exec',
|
||||||
function(arg1, arg2, arg3, arg4) {
|
function(arg1, arg2, arg3, arg4) {
|
||||||
@ -319,7 +318,7 @@ describe('exec node', function() {
|
|||||||
|
|
||||||
msg = messages[1];
|
msg = messages[1];
|
||||||
msg.should.have.property("payload");
|
msg.should.have.property("payload");
|
||||||
msg.payload.should.be.a.String;
|
msg.payload.should.be.a.String();
|
||||||
msg.payload.should.equal("ERROR");
|
msg.payload.should.equal("ERROR");
|
||||||
|
|
||||||
msg = messages[2];
|
msg = messages[2];
|
||||||
@ -358,11 +357,11 @@ describe('exec node', function() {
|
|||||||
var expected;
|
var expected;
|
||||||
if (osType === "Windows_NT") {
|
if (osType === "Windows_NT") {
|
||||||
// Need to use cmd to spawn a process because Windows echo command is a built-in command and cannot be spawned.
|
// Need to use cmd to spawn a process because Windows echo command is a built-in command and cannot be spawned.
|
||||||
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"cmd /C echo", addpay:true, append:"", useSpawn:true},
|
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"cmd /C echo", addpay:true, append:"", useSpawn:true, oldrc:"false"},
|
||||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
expected = "hello world\r\n";
|
expected = "hello world\r\n";
|
||||||
} else {
|
} else {
|
||||||
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"echo", addpay:true, append:"", useSpawn:true},
|
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"echo", addpay:true, append:"", useSpawn:true, oldrc:"false"},
|
||||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
expected = "hello world\n";
|
expected = "hello world\n";
|
||||||
}
|
}
|
||||||
@ -392,11 +391,11 @@ describe('exec node', function() {
|
|||||||
var flow;
|
var flow;
|
||||||
var expected;
|
var expected;
|
||||||
if (osType === "Windows_NT") {
|
if (osType === "Windows_NT") {
|
||||||
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"cmd /C echo", addpay:true, append:" deg C", useSpawn:true},
|
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"cmd /C echo", addpay:true, append:" deg C", useSpawn:true, oldrc:"false"},
|
||||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
expected = "12345 deg C\r\n";
|
expected = "12345 deg C\r\n";
|
||||||
} else {
|
} else {
|
||||||
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"echo", addpay:true, append:" deg C", useSpawn:true},
|
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"echo", addpay:true, append:" deg C", useSpawn:true, oldrc:"false"},
|
||||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
expected = "12345 deg C\n";
|
expected = "12345 deg C\n";
|
||||||
}
|
}
|
||||||
@ -421,11 +420,11 @@ describe('exec node', function() {
|
|||||||
var flow;
|
var flow;
|
||||||
var expected;
|
var expected;
|
||||||
if (osType === "Windows_NT") {
|
if (osType === "Windows_NT") {
|
||||||
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"cmd /C echo", addpay:true, append:"", useSpawn:true},
|
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"cmd /C echo", addpay:true, append:"", useSpawn:true, oldrc:"false"},
|
||||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
expected = 8;
|
expected = 6;
|
||||||
} else {
|
} else {
|
||||||
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"echo", addpay:true, append:"", useSpawn:true},
|
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"echo", addpay:true, append:"", useSpawn:true, oldrc:"false"},
|
||||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
expected = 7;
|
expected = 7;
|
||||||
}
|
}
|
||||||
@ -453,11 +452,11 @@ describe('exec node', function() {
|
|||||||
var flow;
|
var flow;
|
||||||
var expected;
|
var expected;
|
||||||
if (osType === "Windows_NT") {
|
if (osType === "Windows_NT") {
|
||||||
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"cmd /C echo this now works", addpay:false, append:"", useSpawn:true},
|
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"cmd /C echo this now works", addpay:false, append:"", useSpawn:true, oldrc:"false"},
|
||||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
expected = "this now works\r\n";
|
expected = "this now works\r\n";
|
||||||
} else {
|
} else {
|
||||||
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"echo this now works", addpay:false, append:"", useSpawn:true},
|
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"echo this now works", addpay:false, append:"", useSpawn:true, oldrc:"false"},
|
||||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
expected = "this now works\n";
|
expected = "this now works\n";
|
||||||
}
|
}
|
||||||
@ -482,8 +481,7 @@ describe('exec node', function() {
|
|||||||
msg = messages[1];
|
msg = messages[1];
|
||||||
msg.should.have.property("payload");
|
msg.should.have.property("payload");
|
||||||
should.exist(msg.payload);
|
should.exist(msg.payload);
|
||||||
msg.payload.should.be.a.Number();
|
msg.payload.should.have.property("code",0);
|
||||||
msg.payload.should.equal(0);
|
|
||||||
done();
|
done();
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
done(err);
|
done(err);
|
||||||
@ -503,9 +501,8 @@ describe('exec node', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!/^v0.10/.test(process.version)) {
|
|
||||||
it('should return an error for a bad command', function(done) {
|
it('should return an error for a bad command', function(done) {
|
||||||
var flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"madeupcommandshouldfail", addpay:false, append:"", useSpawn:true},
|
var flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"madeupcommandshouldfail", addpay:false, append:"", useSpawn:"true", oldrc:"false"},
|
||||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
helper.load(execNode, flow, function() {
|
helper.load(execNode, flow, function() {
|
||||||
var n1 = helper.getNode("n1");
|
var n1 = helper.getNode("n1");
|
||||||
@ -513,32 +510,24 @@ describe('exec node', function() {
|
|||||||
var n3 = helper.getNode("n3");
|
var n3 = helper.getNode("n3");
|
||||||
var n4 = helper.getNode("n4");
|
var n4 = helper.getNode("n4");
|
||||||
n4.on("input", function(msg) {
|
n4.on("input", function(msg) {
|
||||||
if (/^v0.10/.test(process.version)) {
|
|
||||||
msg.should.have.property("payload");
|
msg.should.have.property("payload");
|
||||||
msg.payload.should.be.a.Number();
|
msg.payload.should.have.property("code",-2);
|
||||||
msg.payload.should.be.below(0);
|
|
||||||
} else {
|
|
||||||
msg.should.have.property("payload");
|
|
||||||
msg.payload.should.be.a.Number();
|
|
||||||
msg.payload.should.be.below(0);
|
|
||||||
}
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
n1.receive({payload:null});
|
n1.receive({payload:null});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
||||||
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},
|
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"ping /foo/bar/doo/dah", addpay:false, append:"", useSpawn:"true", oldrc:"false"},
|
||||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
expected = "IP address must be specified.";
|
expected = "IP address must be specified.";
|
||||||
} else {
|
} else {
|
||||||
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"mkdir /foo/bar/doo/dah", addpay:false, append:"", useSpawn:true},
|
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"mkdir /foo/bar/doo/dah", addpay:false, append:"", useSpawn:"true", oldrc:"false"},
|
||||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
expected = "mkdir: /foo/bar/doo: No such file or directory\n";
|
expected = "mkdir: /foo/bar/doo: No such file or directory\n";
|
||||||
}
|
}
|
||||||
@ -553,7 +542,8 @@ describe('exec node', function() {
|
|||||||
msg.payload.should.equal(expected);
|
msg.payload.should.equal(expected);
|
||||||
});
|
});
|
||||||
n4.on("input", function(msg) {
|
n4.on("input", function(msg) {
|
||||||
msg.should.have.property("payload",1);
|
msg.should.have.property("payload");
|
||||||
|
msg.payload.should.have.property("code",1);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
n1.receive({payload:null});
|
n1.receive({payload:null});
|
||||||
@ -563,41 +553,34 @@ describe('exec node', function() {
|
|||||||
it('should be able to timeout a long running command', function(done) {
|
it('should be able to timeout a long running command', function(done) {
|
||||||
var flow;
|
var flow;
|
||||||
if (osType === "Windows_NT") {
|
if (osType === "Windows_NT") {
|
||||||
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"ping", addpay:false, append:"192.0.2.0 -n 1 -w 1000 > NUL", timer:"0.3"},
|
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"ping", addpay:false, append:"192.0.2.0 -n 1 -w 1000 > NUL", timer:"0.3", useSpawn:"true", oldrc:"false"},
|
||||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
} else {
|
} else {
|
||||||
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"sleep", addpay:false, append:"1", timer:"0.3", useSpawn:true},
|
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"sleep", addpay:false, append:"1", timer:"0.3", useSpawn:"true", oldrc:"false"},
|
||||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
}
|
}
|
||||||
helper.load(execNode, flow, function() {
|
helper.load(execNode, flow, function() {
|
||||||
var n1 = helper.getNode("n1");
|
var n1 = helper.getNode("n1");
|
||||||
var n2 = helper.getNode("n2");
|
var n2 = helper.getNode("n2");
|
||||||
var n3 = helper.getNode("n3");
|
var n3 = helper.getNode("n3");
|
||||||
var n4 = helper.getNode("n4");
|
var n4 = helper.getNode("n4");
|
||||||
n4.on("input", function(msg) {
|
n4.on("input", function(msg) {
|
||||||
msg.should.have.property("payload",null);
|
msg.should.have.property("payload");
|
||||||
//done();
|
msg.payload.should.have.property("code",null);
|
||||||
});
|
msg.payload.should.have.property("signal","SIGTERM");
|
||||||
setTimeout(function() {
|
done();
|
||||||
var logEvents = helper.log().args.filter(function(evt) {
|
});
|
||||||
return evt[0].type == "exec";
|
n1.receive({});
|
||||||
});
|
});
|
||||||
var i = logEvents.length - 1;
|
});
|
||||||
logEvents[i][0].should.have.a.property('msg');
|
|
||||||
logEvents[i][0].msg.toString().should.startWith("Exec node timeout");
|
it('should be able to kill a long running command', function(done) {
|
||||||
done();
|
var flow;
|
||||||
},400);
|
if (osType === "Windows_NT") {
|
||||||
n1.receive({});
|
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"ping", addpay:false, append:"192.0.2.0 -n 1 -w 1000 > NUL", timer:"2", oldrc:"false"},
|
||||||
});
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
});
|
} else {
|
||||||
|
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"sleep", addpay:false, append:"1", timer:"2", oldrc:"false"},
|
||||||
it('should be able to kill a long running command', function(done) {
|
|
||||||
var flow;
|
|
||||||
if (osType === "Windows_NT") {
|
|
||||||
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"ping", addpay:false, append:"192.0.2.0 -n 1 -w 1000 > NUL", timer:"2"},
|
|
||||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
|
||||||
} else {
|
|
||||||
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"sleep", addpay:false, append:"1", timer:"2"},
|
|
||||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
}
|
}
|
||||||
helper.load(execNode, flow, function() {
|
helper.load(execNode, flow, function() {
|
||||||
@ -607,7 +590,6 @@ describe('exec node', function() {
|
|||||||
var n4 = helper.getNode("n4");
|
var n4 = helper.getNode("n4");
|
||||||
n4.on("input", function(msg) {
|
n4.on("input", function(msg) {
|
||||||
msg.should.have.property("payload");
|
msg.should.have.property("payload");
|
||||||
msg.payload.should.have.property("killed",true);
|
|
||||||
msg.payload.should.have.property("signal","SIGTERM");
|
msg.payload.should.have.property("signal","SIGTERM");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -620,11 +602,13 @@ describe('exec node', function() {
|
|||||||
|
|
||||||
it('should be able to kill a long running command - SIGINT', function(done) {
|
it('should be able to kill a long running command - SIGINT', function(done) {
|
||||||
var flow;
|
var flow;
|
||||||
|
var sig = "SIGINT";
|
||||||
if (osType === "Windows_NT") {
|
if (osType === "Windows_NT") {
|
||||||
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"ping", addpay:false, append:"192.0.2.0 -n 1 -w 1000 > NUL", timer:"2"},
|
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"ping", addpay:false, append:"192.0.2.0 -n 1 -w 1000 > NUL", timer:"2", oldrc:"false"},
|
||||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
|
sig = "SIGTERM";
|
||||||
} else {
|
} else {
|
||||||
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"sleep", addpay:false, append:"1", timer:"2"},
|
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"sleep", addpay:false, append:"1", timer:"2", oldrc:"false"},
|
||||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
}
|
}
|
||||||
helper.load(execNode, flow, function() {
|
helper.load(execNode, flow, function() {
|
||||||
@ -634,8 +618,7 @@ describe('exec node', function() {
|
|||||||
var n4 = helper.getNode("n4");
|
var n4 = helper.getNode("n4");
|
||||||
n4.on("input", function(msg) {
|
n4.on("input", function(msg) {
|
||||||
msg.should.have.property("payload");
|
msg.should.have.property("payload");
|
||||||
msg.payload.should.have.property("killed",true);
|
msg.payload.should.have.property("signal",sig);
|
||||||
//msg.payload.should.have.property("signal","SIGINT");
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
|
Loading…
Reference in New Issue
Block a user