mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
af71ae649b
* initial support of BATCH node * add concat mode & fix for docs and js code * add tests for BATCH node * minor correction of typo * allow interval in float * fixed message catalog * add test for too many pending messages & related fixes * update info document on batchMaxKeptMsgsCount * fixed close callback * fixed info document * add initial topics entry of concat mode
339 lines
13 KiB
JavaScript
339 lines
13 KiB
JavaScript
/**
|
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
**/
|
|
|
|
var should = require("should");
|
|
var batchNode = require("../../../../nodes/core/logic/19-batch.js");
|
|
var helper = require("../../helper.js");
|
|
var RED = require("../../../../red/red.js");
|
|
|
|
describe('BATCH node', function() {
|
|
this.timeout(8000);
|
|
|
|
before(function(done) {
|
|
helper.startServer(done);
|
|
});
|
|
|
|
afterEach(function() {
|
|
helper.unload();
|
|
RED.settings.batchMaxKeptMsgsCount = 0;
|
|
});
|
|
|
|
it('should be loaded with defaults', function(done) {
|
|
var flow = [{id:"n1", type:"batch", name: "BatchNode", wires:[["n2"]]},
|
|
{id:"n2", type:"helper"}];
|
|
helper.load(batchNode, flow, function() {
|
|
var n1 = helper.getNode("n1");
|
|
n1.should.have.property('name', 'BatchNode');
|
|
done();
|
|
});
|
|
});
|
|
|
|
function check_parts(msg, id, idx, count) {
|
|
msg.should.have.property("parts");
|
|
var parts = msg.parts;
|
|
parts.should.have.property("id", id);
|
|
parts.should.have.property("index", idx);
|
|
parts.should.have.property("count", count);
|
|
}
|
|
|
|
function check_data(n1, n2, results, done) {
|
|
var id = undefined;
|
|
var ix0 = 0; // seq no
|
|
var ix1 = 0; // loc. in seq
|
|
var seq = undefined;
|
|
n2.on("input", function(msg) {
|
|
try {
|
|
if (seq === undefined) {
|
|
seq = results[ix0];
|
|
}
|
|
var val = seq[ix1];
|
|
msg.should.have.property("payload", val);
|
|
if (id === undefined) {
|
|
id = msg.parts.id;
|
|
}
|
|
check_parts(msg, id, ix1, seq.length);
|
|
ix1++;
|
|
if (ix1 === seq.length) {
|
|
ix0++;
|
|
ix1 = 0;
|
|
seq = undefined;
|
|
id = undefined;
|
|
if (ix0 === results.length) {
|
|
done();
|
|
}
|
|
}
|
|
}
|
|
catch (e) {
|
|
done(e);
|
|
}
|
|
});
|
|
}
|
|
|
|
function check_count(flow, results, done) {
|
|
try {
|
|
helper.load(batchNode, flow, function() {
|
|
var n1 = helper.getNode("n1");
|
|
var n2 = helper.getNode("n2");
|
|
check_data(n1, n2, results, done);
|
|
for(var i = 0; i < 6; i++) {
|
|
n1.receive({payload: i});
|
|
}
|
|
});
|
|
}
|
|
catch (e) {
|
|
done(e);
|
|
}
|
|
}
|
|
|
|
function delayed_send(receiver, index, count, delay) {
|
|
if (index < count) {
|
|
setTimeout(function() {
|
|
receiver.receive({payload: index});
|
|
delayed_send(receiver, index+1, count, delay);
|
|
}, delay);
|
|
}
|
|
}
|
|
|
|
function check_interval(flow, results, delay, done) {
|
|
helper.load(batchNode, flow, function() {
|
|
var n1 = helper.getNode("n1");
|
|
var n2 = helper.getNode("n2");
|
|
check_data(n1, n2, results, done);
|
|
delayed_send(n1, 0, 4, delay);
|
|
});
|
|
}
|
|
|
|
function check_concat(flow, results, inputs, done) {
|
|
try {
|
|
helper.load(batchNode, flow, function() {
|
|
var n1 = helper.getNode("n1");
|
|
var n2 = helper.getNode("n2");
|
|
check_data(n1, n2, results, done);
|
|
for(var data of inputs) {
|
|
var msg = {
|
|
topic: data[0],
|
|
payload: data[1],
|
|
parts: {
|
|
id: data[0],
|
|
index: data[2],
|
|
count: data[3]
|
|
}
|
|
};
|
|
n1.receive(msg);
|
|
}
|
|
});
|
|
}
|
|
catch (e) {
|
|
done(e);
|
|
}
|
|
}
|
|
|
|
describe('mode: count', function() {
|
|
|
|
it('should create seq. with count', function(done) {
|
|
var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "count", count: 2, overwrap: 0, interval: 10, allowEmptySequence: false, topics: [], wires:[["n2"]]},
|
|
{id:"n2", type:"helper"}];
|
|
var results = [
|
|
[0, 1],
|
|
[2, 3],
|
|
[4, 5]
|
|
];
|
|
check_count(flow, results, done);
|
|
});
|
|
|
|
it('should create seq. with count and overwrap', function(done) {
|
|
var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "count", count: 3, overwrap: 2, interval: 10, allowEmptySequence: false, topics: [], wires:[["n2"]]},
|
|
{id:"n2", type:"helper"}];
|
|
var results = [
|
|
[0, 1, 2],
|
|
[1, 2, 3],
|
|
[2, 3, 4],
|
|
[3, 4, 5]
|
|
];
|
|
check_count(flow, results, done);
|
|
});
|
|
|
|
it('should handle too many pending messages', function(done) {
|
|
var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "count", count: 5, overwrap: 0, interval: 10, allowEmptySequence: false, topics: [], wires:[["n2"]]},
|
|
{id:"n2", type:"helper"}];
|
|
helper.load(batchNode, flow, function() {
|
|
var n1 = helper.getNode("n1");
|
|
var n2 = helper.getNode("n2");
|
|
RED.settings.batchMaxKeptMsgsCount = 2;
|
|
setTimeout(function() {
|
|
var logEvents = helper.log().args.filter(function (evt) {
|
|
return evt[0].type == "batch";
|
|
});
|
|
var evt = logEvents[0][0];
|
|
evt.should.have.property('id', "n1");
|
|
evt.should.have.property('type', "batch");
|
|
evt.should.have.property('msg', "batch.too-many");
|
|
done();
|
|
}, 150);
|
|
for(var i = 0; i < 3; i++) {
|
|
n1.receive({payload: i});
|
|
}
|
|
});
|
|
});
|
|
|
|
});
|
|
|
|
describe('mode: interval', function() {
|
|
|
|
it('should create seq. with interval', function(done) {
|
|
var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "interval", count: 0, overwrap: 0, interval: 1, allowEmptySequence: false, topics: [], wires:[["n2"]]},
|
|
{id:"n2", type:"helper"}];
|
|
var results = [
|
|
[0, 1],
|
|
[2, 3]
|
|
];
|
|
check_interval(flow, results, 450, done);
|
|
});
|
|
|
|
it('should create seq. with interval (in float)', function(done) {
|
|
var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "interval", count: 0, overwrap: 0, interval: 0.5, allowEmptySequence: false, topics: [], wires:[["n2"]]},
|
|
{id:"n2", type:"helper"}];
|
|
var results = [
|
|
[0, 1],
|
|
[2, 3]
|
|
];
|
|
check_interval(flow, results, 225, done);
|
|
});
|
|
|
|
it('should create seq. with interval & not send empty seq', function(done) {
|
|
var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "interval", count: 0, overwrap: 0, interval: 1, allowEmptySequence: false, topics: [], wires:[["n2"]]},
|
|
{id:"n2", type:"helper"}];
|
|
var results = [
|
|
// 1300, 2600, 3900, 5200,
|
|
[0], [1], [2], [3]
|
|
];
|
|
check_interval(flow, results, 1300, done);
|
|
});
|
|
|
|
it('should create seq. with interval & send empty seq', function(done) {
|
|
var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "interval", count: 0, overwrap: 0, interval: 1, allowEmptySequence: true, topics: [], wires:[["n2"]]},
|
|
{id:"n2", type:"helper"}];
|
|
var results = [
|
|
// 1300, 2600, 3900, 5200,
|
|
[null], [0], [1], [2], [null], [3]
|
|
];
|
|
check_interval(flow, results, 1300, done);
|
|
});
|
|
|
|
it('should handle too many pending messages', function(done) {
|
|
var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "interval", count: 0, overwrap: 0, interval: 1, allowEmptySequence: false, topics: [], wires:[["n2"]]},
|
|
{id:"n2", type:"helper"}];
|
|
helper.load(batchNode, flow, function() {
|
|
var n1 = helper.getNode("n1");
|
|
var n2 = helper.getNode("n2");
|
|
RED.settings.batchMaxKeptMsgsCount = 2;
|
|
setTimeout(function() {
|
|
var logEvents = helper.log().args.filter(function (evt) {
|
|
return evt[0].type == "batch";
|
|
});
|
|
var evt = logEvents[0][0];
|
|
evt.should.have.property('id', "n1");
|
|
evt.should.have.property('type', "batch");
|
|
evt.should.have.property('msg', "batch.too-many");
|
|
done();
|
|
}, 150);
|
|
for(var i = 0; i < 3; i++) {
|
|
n1.receive({payload: i});
|
|
}
|
|
});
|
|
});
|
|
|
|
});
|
|
|
|
describe('mode: concat', function() {
|
|
|
|
it('should concat two seq. (series)', function(done) {
|
|
var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "concat", count: 0, overwrap: 0, interval: 1, allowEmptySequence: false, topics: [{topic: "TA"}, {topic: "TB"}], wires:[["n2"]]},
|
|
{id:"n2", type:"helper"}];
|
|
var results = [
|
|
[2, 3, 0, 1]
|
|
];
|
|
var inputs = [
|
|
["TB", 0, 0, 2],
|
|
["TB", 1, 1, 2],
|
|
["TA", 2, 0, 2],
|
|
["TA", 3, 1, 2]
|
|
];
|
|
check_concat(flow, results, inputs, done);
|
|
});
|
|
|
|
it('should concat two seq. (mixed)', function(done) {
|
|
var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "concat", count: 0, overwrap: 0, interval: 1, allowEmptySequence: false, topics: [{topic: "TA"}, {topic: "TB"}], wires:[["n2"]]},
|
|
{id:"n2", type:"helper"}];
|
|
var results = [
|
|
[2, 3, 0, 1]
|
|
];
|
|
var inputs = [
|
|
["TA", 2, 0, 2],
|
|
["TB", 0, 0, 2],
|
|
["TA", 3, 1, 2],
|
|
["TB", 1, 1, 2]
|
|
];
|
|
check_concat(flow, results, inputs, done);
|
|
});
|
|
|
|
it('should concat three seq.', function(done) {
|
|
var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "concat", count: 0, overwrap: 0, interval: 1, allowEmptySequence: false, topics: [{topic: "TA"}, {topic: "TB"}, {topic: "TC"}], wires:[["n2"]]},
|
|
{id:"n2", type:"helper"}];
|
|
var results = [
|
|
[2, 3, 0, 1, 4]
|
|
];
|
|
var inputs = [
|
|
["TC", 4, 0, 1],
|
|
["TB", 0, 0, 2],
|
|
["TB", 1, 1, 2],
|
|
["TA", 2, 0, 2],
|
|
["TA", 3, 1, 2]
|
|
];
|
|
check_concat(flow, results, inputs, done);
|
|
});
|
|
|
|
it('should handle too many pending messages', function(done) {
|
|
var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "concat", count: 0, overwrap: 0, interval: 1, allowEmptySequence: false, topics: [{topic: "TA"}, {topic: "TB"}], wires:[["n2"]]},
|
|
{id:"n2", type:"helper"}];
|
|
helper.load(batchNode, flow, function() {
|
|
var n1 = helper.getNode("n1");
|
|
var n2 = helper.getNode("n2");
|
|
RED.settings.batchMaxKeptMsgsCount = 2;
|
|
setTimeout(function() {
|
|
var logEvents = helper.log().args.filter(function (evt) {
|
|
return evt[0].type == "batch";
|
|
});
|
|
var evt = logEvents[0][0];
|
|
evt.should.have.property('id', "n1");
|
|
evt.should.have.property('type', "batch");
|
|
evt.should.have.property('msg', "batch.too-many");
|
|
done();
|
|
}, 150);
|
|
var C = 3;
|
|
for(var i = 0; i < C; i++) {
|
|
var parts_a = {index:i, count:C, id:"A"};
|
|
var parts_b = {index:i, count:C, id:"B"};
|
|
n1.receive({payload: i, topic: "TA", parts:parts_a});
|
|
n1.receive({payload: i, topic: "TB", parts:parts_b});
|
|
}
|
|
});
|
|
});
|
|
|
|
});
|
|
|
|
});
|