2014-09-01 11:22:04 +02:00
/ * *
2017-01-11 16:24:33 +01:00
* Copyright JS Foundation and other contributors , http : //js.foundation
2014-09-01 11:22:04 +02:00
*
* 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" ) ;
2019-07-10 00:32:22 +02:00
var delayNode = require ( "nr-test-utils" ) . require ( "@node-red/nodes/core/function/89-delay.js" ) ;
2018-03-02 05:41:16 +01:00
var helper = require ( "node-red-node-test-helper" ) ;
2014-09-01 11:22:04 +02:00
var GRACE _PERCENTAGE = 10 ;
var nanosToSeconds = 1000000000 ;
var millisToSeconds = 1000 ;
var secondsToMinutes = 60 ;
var secondsToHours = 3600 ;
var secondsToDays = 86400 ;
2015-03-22 10:38:42 +01:00
describe ( 'delay Node' , function ( ) {
2014-09-01 11:22:04 +02:00
beforeEach ( function ( done ) {
helper . startServer ( done ) ;
} ) ;
2015-03-22 10:38:42 +01:00
2014-09-01 11:22:04 +02:00
afterEach ( function ( done ) {
helper . unload ( ) ;
helper . stopServer ( done ) ;
} ) ;
it ( 'should be loaded' , function ( done ) {
2016-09-16 15:27:14 +02:00
var flow = [ { "id" : "delayNode1" , "type" : "delay" , "nbRateUnits" : "1" , "name" : "delayNode" , "pauseType" : "delay" , "timeout" : "5" , "timeoutUnits" : "seconds" , "rate" : "1" , "rateUnits" : "day" , "randomFirst" : "1" , "randomLast" : "5" , "randomUnits" : "seconds" , "drop" : false , "wires" : [ [ ] ] } ] ;
2014-09-01 11:22:04 +02:00
helper . load ( delayNode , flow , function ( ) {
var delayNode1 = helper . getNode ( "delayNode1" ) ;
delayNode1 . should . have . property ( 'name' , 'delayNode' ) ;
2015-03-22 10:38:42 +01:00
delayNode1 . should . have . property ( 'rate' , 86400000 ) ;
2014-09-01 11:22:04 +02:00
done ( ) ;
} ) ;
} ) ;
2015-03-22 10:38:42 +01:00
it ( 'should be able to set rate to hour' , function ( done ) {
2016-09-16 15:27:14 +02:00
var flow = [ { "id" : "delayNode1" , "type" : "delay" , "nbRateUnits" : "1" , "name" : "delayNode" , "pauseType" : "delay" , "timeout" : "5" , "timeoutUnits" : "seconds" , "rate" : "1" , "rateUnits" : "hour" , "randomFirst" : "1" , "randomLast" : "5" , "randomUnits" : "seconds" , "drop" : false , "wires" : [ [ ] ] } ] ;
2015-03-22 10:38:42 +01:00
helper . load ( delayNode , flow , function ( ) {
var delayNode1 = helper . getNode ( "delayNode1" ) ;
delayNode1 . should . have . property ( 'name' , 'delayNode' ) ;
delayNode1 . should . have . property ( 'rate' , 3600000 ) ;
done ( ) ;
} ) ;
} ) ;
it ( 'should be able to set rate to minute' , function ( done ) {
2016-09-16 15:27:14 +02:00
var flow = [ { "id" : "delayNode1" , "type" : "delay" , "nbRateUnits" : "1" , "name" : "delayNode" , "pauseType" : "delay" , "timeout" : "5" , "timeoutUnits" : "seconds" , "rate" : "1" , "rateUnits" : "minute" , "randomFirst" : "1" , "randomLast" : "5" , "randomUnits" : "seconds" , "drop" : false , "wires" : [ [ ] ] } ] ;
2015-03-22 10:38:42 +01:00
helper . load ( delayNode , flow , function ( ) {
var delayNode1 = helper . getNode ( "delayNode1" ) ;
delayNode1 . should . have . property ( 'name' , 'delayNode' ) ;
delayNode1 . should . have . property ( 'rate' , 60000 ) ;
done ( ) ;
} ) ;
} ) ;
2014-09-01 11:22:04 +02:00
var TimeUnitEnum = {
2016-04-23 22:06:48 +02:00
MILLIS : "milliseconds" ,
SECONDS : "seconds" ,
MINUTES : "minutes" ,
HOURS : "hours" ,
DAYS : "days"
2014-09-01 11:22:04 +02:00
}
2015-10-03 10:04:57 +02:00
2014-09-01 11:22:04 +02:00
/ * *
* Tells whether two numeric values are close enough to each other
* @ param actualValue - the value we ' re testing
* @ param expectedValue - the value we ' re matching the test value against
* @ param tolerancePercent - the percentage of tolerated deviation ( 0 means equals )
* /
function closeEnough ( actualValue , expectedValue , tolerancePercent ) {
var toReturn ;
var toleranceFraction = expectedValue * ( tolerancePercent / 100 ) ;
var minExpected = expectedValue - toleranceFraction ;
var maxExpected = expectedValue + toleranceFraction ;
2015-10-03 10:04:57 +02:00
2016-04-23 22:06:48 +02:00
if ( actualValue >= minExpected && actualValue <= maxExpected ) {
2014-09-01 11:22:04 +02:00
toReturn = true ;
} else {
toReturn = false ;
}
return toReturn ;
}
2015-10-03 10:04:57 +02:00
2014-09-01 11:22:04 +02:00
/ * *
* Runs a delay test
* @ param aTimeout - the timeout quantity
* @ param aTimeoutUnit - the unit of the timeout : milliseconds , seconds , minutes , hours , days
* /
function genericDelayTest ( aTimeout , aTimeoutUnit , done ) {
var flow = [ { "id" : "delayNode1" , "type" : "delay" , "name" : "delayNode" , "pauseType" : "delay" , "timeout" : aTimeout , "timeoutUnits" : aTimeoutUnit , "rate" : "1" , "rateUnits" : "second" , "randomFirst" : "1" , "randomLast" : "5" , "randomUnits" : "seconds" , "drop" : false , "wires" : [ [ "helperNode1" ] ] } ,
{ id : "helperNode1" , type : "helper" , wires : [ ] } ] ;
helper . load ( delayNode , flow , function ( ) {
var delayNode1 = helper . getNode ( "delayNode1" ) ;
var helperNode1 = helper . getNode ( "helperNode1" ) ;
helperNode1 . on ( "input" , function ( msg ) {
try {
var endTime = process . hrtime ( startTime ) ;
var runtimeNanos = ( ( endTime [ 0 ] * nanosToSeconds ) + endTime [ 1 ] ) ;
var runtimeSeconds = runtimeNanos / nanosToSeconds ;
var aTimeoutUnifiedToSeconds ;
2015-10-03 10:04:57 +02:00
2014-09-01 11:22:04 +02:00
// calculating the timeout in seconds
2016-04-23 22:06:48 +02:00
if ( aTimeoutUnit == TimeUnitEnum . MILLIS ) {
2014-09-01 11:22:04 +02:00
aTimeoutUnifiedToSeconds = aTimeout / millisToSeconds ;
2016-04-23 22:06:48 +02:00
} else if ( aTimeoutUnit == TimeUnitEnum . SECONDS ) {
2014-09-01 11:22:04 +02:00
aTimeoutUnifiedToSeconds = aTimeout ;
2016-04-23 22:06:48 +02:00
} else if ( aTimeoutUnit == TimeUnitEnum . MINUTES ) {
2014-09-01 11:22:04 +02:00
aTimeoutUnifiedToSeconds = aTimeout * secondsToMinutes ;
2016-04-23 22:06:48 +02:00
} else if ( aTimeoutUnit == TimeUnitEnum . HOURS ) {
2014-09-01 11:22:04 +02:00
aTimeoutUnifiedToSeconds = aTimeout * secondsToHours ;
2016-04-23 22:06:48 +02:00
} else if ( aTimeoutUnit == TimeUnitEnum . DAYS ) {
2014-09-01 11:22:04 +02:00
aTimeoutUnifiedToSeconds = aTimeout * secondsToDays ;
}
2015-10-03 10:04:57 +02:00
2016-04-23 22:06:48 +02:00
if ( closeEnough ( runtimeSeconds , aTimeoutUnifiedToSeconds , GRACE _PERCENTAGE ) ) {
2014-09-01 11:22:04 +02:00
done ( ) ;
} else {
try {
2016-04-23 22:06:48 +02:00
should . fail ( null , null , "Delayed runtime seconds " + runtimeSeconds + " was not close enough to exlected timeout seconds: " + aTimeoutUnifiedToSeconds ) ;
2014-09-01 11:22:04 +02:00
} catch ( err ) {
done ( err ) ;
}
}
} catch ( err ) {
done ( err ) ;
}
} ) ;
var startTime = process . hrtime ( ) ;
delayNode1 . receive ( { payload : "delayMe" } ) ;
} ) ;
}
2015-10-03 10:04:57 +02:00
2014-09-01 11:22:04 +02:00
/ * *
* We send a message , take a timestamp then when the message is received by the helper node , we take another timestamp .
* Then check if the message has been delayed by the expected amount .
* /
it ( 'delays the message in seconds' , function ( done ) {
genericDelayTest ( 0.5 , "seconds" , done ) ;
} ) ;
2015-10-03 10:04:57 +02:00
2014-09-01 11:22:04 +02:00
it ( 'delays the message in milliseconds' , function ( done ) {
genericDelayTest ( 500 , "milliseconds" , done ) ;
} ) ;
2015-10-03 10:04:57 +02:00
2014-09-01 11:22:04 +02:00
it ( 'delays the message in minutes' , function ( done ) { // this is also 0.5 seconds
genericDelayTest ( 0.00833 , "minutes" , done ) ;
} ) ;
2015-10-03 10:04:57 +02:00
2014-09-01 11:22:04 +02:00
it ( 'delays the message in hours' , function ( done ) { // this is also 0.5 seconds
genericDelayTest ( 0.0001388 , "hours" , done ) ;
} ) ;
2015-10-03 10:04:57 +02:00
2014-09-01 11:22:04 +02:00
it ( 'delays the message in days' , function ( done ) { // this is also 0.5 seconds
genericDelayTest ( 0.000005787 , "days" , done ) ;
} ) ;
2015-10-03 10:04:57 +02:00
2014-09-01 11:22:04 +02:00
/ * *
* Runs a rate limit test - only testing seconds !
* @ param aLimit - the message limit count
2016-09-16 15:27:14 +02:00
* @ param nbUnit - the multiple of the unit , aLimit Message for nbUnit Seconds
2014-09-01 11:22:04 +02:00
* @ param runtimeInMillis - when to terminate run and count messages received
* /
2016-09-16 15:27:14 +02:00
function genericRateLimitSECONDSTest ( aLimit , nbUnit , runtimeInMillis , done ) {
var flow = [ { "id" : "delayNode1" , "type" : "delay" , "nbRateUnits" : nbUnit , "name" : "delayNode" , "pauseType" : "rate" , "timeout" : 5 , "timeoutUnits" : "seconds" , "rate" : aLimit , "rateUnits" : "second" , "randomFirst" : "1" , "randomLast" : "5" , "randomUnits" : "seconds" , "drop" : false , "wires" : [ [ "helperNode1" ] ] } ,
2014-09-01 11:22:04 +02:00
{ id : "helperNode1" , type : "helper" , wires : [ ] } ] ;
helper . load ( delayNode , flow , function ( ) {
var delayNode1 = helper . getNode ( "delayNode1" ) ;
var helperNode1 = helper . getNode ( "helperNode1" ) ;
var receivedMessagesStack = [ ] ;
2014-09-08 15:26:35 +02:00
var rate = 1000 / aLimit ;
2015-10-03 10:04:57 +02:00
2014-09-08 15:26:35 +02:00
var receiveTimestamp ;
2015-10-03 10:04:57 +02:00
2014-09-01 11:22:04 +02:00
helperNode1 . on ( "input" , function ( msg ) {
2016-04-23 22:06:48 +02:00
if ( receiveTimestamp ) {
2014-09-08 15:26:35 +02:00
var elapse = process . hrtime ( receiveTimestamp ) ;
var receiveInterval = ( elapse [ 0 ] * 1000 ) + ( ( elapse [ 1 ] / nanosToSeconds ) * 1000 ) ;
receiveInterval . should . be . above ( rate * 0.9 ) ;
}
receiveTimestamp = process . hrtime ( ) ;
2014-09-01 11:22:04 +02:00
receivedMessagesStack . push ( msg ) ;
} ) ;
2015-10-03 10:04:57 +02:00
2014-09-01 11:22:04 +02:00
var possibleMaxMessageCount = Math . ceil ( aLimit * ( runtimeInMillis / 1000 ) + aLimit ) ; // +aLimit as at the start of the 2nd period, we're allowing the 3rd burst
2015-10-03 10:04:57 +02:00
2014-09-01 11:22:04 +02:00
var i = 0 ;
2016-04-23 22:06:48 +02:00
for ( ; i < possibleMaxMessageCount + 1 ; i ++ ) {
2014-09-01 11:22:04 +02:00
delayNode1 . receive ( { payload : i } ) ;
}
2015-10-03 10:04:57 +02:00
2014-09-01 11:22:04 +02:00
setTimeout ( function ( ) {
2014-09-08 15:26:35 +02:00
try {
receivedMessagesStack . length . should . be . lessThan ( possibleMaxMessageCount ) ;
2016-04-23 22:06:48 +02:00
for ( var j = 0 ; j < receivedMessagesStack . length ; j ++ ) {
if ( receivedMessagesStack [ j ] . payload === j ) {
if ( j === ( receivedMessagesStack . length - 1 ) ) { // last message, all matched so far
2014-09-08 15:26:35 +02:00
done ( ) ;
2014-09-01 11:22:04 +02:00
}
2014-09-08 15:26:35 +02:00
} else {
should . fail ( null , null , "Received messages were not received in order. Message was " + receivedMessagesStack [ i ] . payload + " on count " + i ) ;
}
2015-10-03 10:04:57 +02:00
}
2014-09-08 15:26:35 +02:00
} catch ( err ) {
done ( err ) ;
2014-09-01 11:22:04 +02:00
}
} , runtimeInMillis ) ;
} ) ;
}
2015-10-03 10:04:57 +02:00
2014-09-01 11:22:04 +02:00
it ( 'limits the message rate to 1 per second' , function ( done ) {
2016-09-16 15:27:14 +02:00
genericRateLimitSECONDSTest ( 1 , 1 , 1500 , done ) ;
2014-09-01 11:22:04 +02:00
} ) ;
2015-10-03 10:04:57 +02:00
2016-09-16 15:27:14 +02:00
it ( 'limits the message rate to 1 per 2 seconds' , function ( done ) {
2014-09-05 17:04:00 +02:00
this . timeout ( 6000 ) ;
2016-09-16 15:27:14 +02:00
genericRateLimitSECONDSTest ( 1 , 2 , 3000 , done ) ;
} ) ;
it ( 'limits the message rate to 2 per seconds, 2 seconds' , function ( done ) {
this . timeout ( 6000 ) ;
genericRateLimitSECONDSTest ( 2 , 1 , 2100 , done ) ;
2014-09-01 11:22:04 +02:00
} ) ;
2015-10-03 10:04:57 +02:00
2014-09-08 15:26:35 +02:00
/ * *
* Runs a rate limit test with drop support - only testing seconds !
* @ param aLimit - the message limit count
2016-09-16 15:27:14 +02:00
* @ param nbUnit - the multiple of the unit , aLimit Message for nbUnit Seconds
2014-09-08 15:26:35 +02:00
* @ param runtimeInMillis - when to terminate run and count messages received
* /
2016-09-16 15:27:14 +02:00
function dropRateLimitSECONDSTest ( aLimit , nbUnit , runtimeInMillis , done ) {
var flow = [ { "id" : "delayNode1" , "type" : "delay" , "name" : "delayNode" , "pauseType" : "rate" , "timeout" : 5 , "nbRateUnits" : nbUnit , "timeoutUnits" : "seconds" , "rate" : aLimit , "rateUnits" : "second" , "randomFirst" : "1" , "randomLast" : "5" , "randomUnits" : "seconds" , "drop" : true , "wires" : [ [ "helperNode1" ] ] } ,
2014-09-08 15:26:35 +02:00
{ id : "helperNode1" , type : "helper" , wires : [ ] } ] ;
helper . load ( delayNode , flow , function ( ) {
var delayNode1 = helper . getNode ( "delayNode1" ) ;
var helperNode1 = helper . getNode ( "helperNode1" ) ;
var receivedMessagesStack = [ ] ;
2015-10-03 10:04:57 +02:00
2019-10-25 12:47:55 +02:00
// Add a small grace to the calculated delay
var rate = 1000 / aLimit + 10 ;
2015-10-03 10:04:57 +02:00
2014-09-08 15:26:35 +02:00
var receiveTimestamp ;
2015-10-03 10:04:57 +02:00
2014-09-08 15:26:35 +02:00
helperNode1 . on ( "input" , function ( msg ) {
2016-04-23 22:06:48 +02:00
if ( receiveTimestamp ) {
2014-09-08 15:26:35 +02:00
var elapse = process . hrtime ( receiveTimestamp ) ;
var receiveInterval = ( elapse [ 0 ] * 1000 ) + ( ( elapse [ 1 ] / nanosToSeconds ) * 1000 ) ;
receiveInterval . should . be . above ( rate * 0.9 ) ;
}
receiveTimestamp = process . hrtime ( ) ;
receivedMessagesStack . push ( msg ) ;
} ) ;
2015-10-03 10:04:57 +02:00
2014-09-08 15:26:35 +02:00
var possibleMaxMessageCount = Math . ceil ( aLimit * ( runtimeInMillis / 1000 ) + aLimit ) ; // +aLimit as at the start of the 2nd period, we're allowing the 3rd burst
2015-10-03 10:04:57 +02:00
2014-09-08 15:26:35 +02:00
var i = 0 ;
delayNode1 . receive ( { payload : i } ) ;
i ++ ;
2016-04-23 22:06:48 +02:00
for ( ; i < possibleMaxMessageCount + 1 ; i ++ ) {
2014-09-08 15:26:35 +02:00
setTimeout ( function ( ) {
2016-04-23 22:06:48 +02:00
delayNode1 . receive ( { payload : i } ) ;
2014-09-08 15:26:35 +02:00
} , 2 * ( ( rate * i ) / possibleMaxMessageCount ) ) ;
}
2015-10-03 10:04:57 +02:00
2014-09-08 15:26:35 +02:00
//we need to send a message delayed so that it doesn't get dropped
setTimeout ( function ( ) {
delayNode1 . receive ( { payload : ++ i } ) ;
} , runtimeInMillis - 300 ) ; // should give enough time to squeeze another message in
2015-10-03 10:04:57 +02:00
2014-09-08 15:26:35 +02:00
setTimeout ( function ( ) {
try {
receivedMessagesStack . length . should . be . lessThan ( possibleMaxMessageCount + 1 ) ;
receivedMessagesStack . length . should . be . greaterThan ( 2 ) ; // ensure that we receive more than 1st and last message
receivedMessagesStack [ 0 ] . payload . should . be . exactly ( 0 ) ; // means we received the last message injected just before test termination
var foundAtLeastOneDrop = false ;
2016-04-23 22:06:48 +02:00
for ( var i = 0 ; i < receivedMessagesStack . length ; i ++ ) {
if ( i > 0 ) {
if ( receivedMessagesStack [ i ] . payload - receivedMessagesStack [ i - 1 ] . payload > 1 ) {
2014-09-08 15:26:35 +02:00
foundAtLeastOneDrop = true ;
}
}
}
2016-10-10 14:27:43 +02:00
foundAtLeastOneDrop . should . be . true ( ) ;
2014-09-08 15:26:35 +02:00
done ( ) ;
} catch ( err ) {
done ( err ) ;
}
} , runtimeInMillis ) ;
} ) ;
}
2015-10-03 10:04:57 +02:00
2014-09-08 15:26:35 +02:00
it ( 'limits the message rate to 1 per second, 4 seconds, with drop' , function ( done ) {
2014-09-05 17:04:00 +02:00
this . timeout ( 6000 ) ;
2016-09-16 15:27:14 +02:00
dropRateLimitSECONDSTest ( 1 , 1 , 4000 , done ) ;
} ) ;
it ( 'limits the message rate to 1 per 2 seconds, 4 seconds, with drop' , function ( done ) {
this . timeout ( 6000 ) ;
dropRateLimitSECONDSTest ( 1 , 2 , 4500 , done ) ;
2014-09-01 11:22:04 +02:00
} ) ;
2015-10-03 10:04:57 +02:00
2014-09-05 17:04:00 +02:00
it ( 'limits the message rate to 2 per second, 5 seconds, with drop' , function ( done ) {
this . timeout ( 6000 ) ;
2016-09-16 15:27:14 +02:00
dropRateLimitSECONDSTest ( 2 , 1 , 5000 , done ) ;
2014-09-01 11:22:04 +02:00
} ) ;
2015-10-03 10:04:57 +02:00
2014-09-01 11:22:04 +02:00
/ * *
* Returns true if the actualTimeout is gracefully in between the timeoutFrom and timeoutTo
* values . Gracefully means that inBetween could actually mean smaller / greater values
* than the timeout range so long as it ' s within an actual grace percentage .
* @ param timeoutFrom - The expected timeout range ( low number )
* @ param timeoutTo - The expected timeout range ( high number )
* @ param actualTimeout - The actual measured timeout value of test
* @ param allowedGracePercent - The percentage of grace allowed
* /
function inBetweenDelays ( timeoutFrom , timeoutTo , actualTimeout , allowedGracePercent ) {
2016-04-23 22:06:48 +02:00
if ( closeEnough ( actualTimeout , timeoutFrom , allowedGracePercent ) ) {
2014-09-01 11:22:04 +02:00
return true ;
2016-04-23 22:06:48 +02:00
} else if ( closeEnough ( actualTimeout , timeoutTo , allowedGracePercent ) ) {
2014-09-01 11:22:04 +02:00
return true ;
2016-04-23 22:06:48 +02:00
} else if ( timeoutFrom < actualTimeout && timeoutTo > actualTimeout ) {
2014-09-01 11:22:04 +02:00
return true ;
} else {
return false ;
}
}
2015-10-03 10:04:57 +02:00
2017-05-11 17:12:38 +02:00
/ * *
* Runs a VARIABLE DELAY test , checks if the delay is in between the given timeout values
* @ param aTimeoutFrom - the timeout quantity which is the minimal acceptable wait period
* @ param aTimeoutTo - the timeout quantity which is the maximum acceptable wait period
* @ param aTimeoutUnit - the unit of the timeout : milliseconds , seconds , minutes , hours , days
* @ param delay - the variable delay : milliseconds
* /
function variableDelayTest ( aTimeoutFrom , aTimeoutTo , aTimeoutUnit , delay , done ) {
2017-10-10 22:40:09 +02:00
var flow = [ { "id" : "delayNode1" , "type" : "delay" , "name" : "delayNode" , "pauseType" : "delayv" , "timeout" : 0.5 , "timeoutUnits" : "seconds" , "rate" : "1" , "rateUnits" : "second" , "randomFirst" : aTimeoutFrom , "randomLast" : aTimeoutTo , "randomUnits" : aTimeoutUnit , "drop" : false , "wires" : [ [ "helperNode1" ] ] } ,
2017-05-11 17:12:38 +02:00
{ id : "helperNode1" , type : "helper" , wires : [ ] } ] ;
helper . load ( delayNode , flow , function ( ) {
var delayNode1 = helper . getNode ( "delayNode1" ) ;
var helperNode1 = helper . getNode ( "helperNode1" ) ;
helperNode1 . on ( "input" , function ( msg ) {
try {
var endTime = process . hrtime ( startTime ) ;
var runtimeNanos = ( ( endTime [ 0 ] * nanosToSeconds ) + endTime [ 1 ] ) ;
var runtimeSeconds = runtimeNanos / nanosToSeconds ;
var aTimeoutFromUnifiedToSeconds ;
var aTimeoutToUnifiedToSeconds ;
// calculating the timeout in seconds
if ( aTimeoutUnit == TimeUnitEnum . MILLIS ) {
aTimeoutFromUnifiedToSeconds = aTimeoutFrom / millisToSeconds ;
aTimeoutToUnifiedToSeconds = aTimeoutTo / millisToSeconds ;
} else if ( aTimeoutUnit == TimeUnitEnum . SECONDS ) {
aTimeoutFromUnifiedToSeconds = aTimeoutFrom ;
aTimeoutToUnifiedToSeconds = aTimeoutTo ;
} else if ( aTimeoutUnit == TimeUnitEnum . MINUTES ) {
aTimeoutFromUnifiedToSeconds = aTimeoutFrom * secondsToMinutes ;
aTimeoutToUnifiedToSeconds = aTimeoutTo * secondsToMinutes ;
} else if ( aTimeoutUnit == TimeUnitEnum . HOURS ) {
aTimeoutFromUnifiedToSeconds = aTimeoutFrom * secondsToHours ;
aTimeoutToUnifiedToSeconds = aTimeoutTo * secondsToHours ;
} else if ( aTimeoutUnit == TimeUnitEnum . DAYS ) {
aTimeoutFromUnifiedToSeconds = aTimeoutFrom * secondsToDays ;
aTimeoutToUnifiedToSeconds = aTimeoutTo * secondsToDays ;
}
if ( inBetweenDelays ( aTimeoutFromUnifiedToSeconds , aTimeoutToUnifiedToSeconds , runtimeSeconds , GRACE _PERCENTAGE ) ) {
done ( ) ;
} else {
try {
should . fail ( null , null , "Delayed runtime seconds " + runtimeSeconds + " was not \"in between enough\" enough to expected values of: " + aTimeoutFromUnifiedToSeconds + " and " + aTimeoutToUnifiedToSeconds ) ;
} catch ( err ) {
done ( err ) ;
}
}
} catch ( err ) {
done ( err ) ;
}
} ) ;
var startTime = process . hrtime ( ) ;
delayNode1 . receive ( { payload : "delayMe" , delay : delay } ) ;
} ) ;
}
it ( 'variable delay set by msg.delay the message in milliseconds' , function ( done ) {
variableDelayTest ( "200" , "300" , "milliseconds" , 250 , done ) ;
} ) ;
2017-10-10 22:40:09 +02:00
it ( 'variable delay is the default if msg.delay not specified' , function ( done ) {
variableDelayTest ( "450" , "550" , "milliseconds" , null , done ) ;
} ) ;
it ( 'variable delay is zero if msg.delay is zero' , function ( done ) {
variableDelayTest ( "0" , "20" , "milliseconds" , 0 , done ) ;
2017-05-11 17:12:38 +02:00
} ) ;
it ( 'variable delay is zero if msg.delay is negative' , function ( done ) {
2017-10-10 22:40:09 +02:00
variableDelayTest ( "0" , "20" , "milliseconds" , - 250 , done ) ;
2017-05-11 17:12:38 +02:00
} ) ;
2014-09-01 11:22:04 +02:00
/ * *
* Runs a RANDOM DELAY test , checks if the delay is in between the given timeout values
* @ param aTimeoutFrom - the timeout quantity which is the minimal acceptable wait period
* @ param aTimeoutTo - the timeout quantity which is the maximum acceptable wait period
* @ param aTimeoutUnit - the unit of the timeout : milliseconds , seconds , minutes , hours , days
* /
function randomDelayTest ( aTimeoutFrom , aTimeoutTo , aTimeoutUnit , done ) {
var flow = [ { "id" : "delayNode1" , "type" : "delay" , "name" : "delayNode" , "pauseType" : "random" , "timeout" : 5 , "timeoutUnits" : "seconds" , "rate" : "1" , "rateUnits" : "second" , "randomFirst" : aTimeoutFrom , "randomLast" : aTimeoutTo , "randomUnits" : aTimeoutUnit , "drop" : false , "wires" : [ [ "helperNode1" ] ] } ,
{ id : "helperNode1" , type : "helper" , wires : [ ] } ] ;
helper . load ( delayNode , flow , function ( ) {
var delayNode1 = helper . getNode ( "delayNode1" ) ;
var helperNode1 = helper . getNode ( "helperNode1" ) ;
helperNode1 . on ( "input" , function ( msg ) {
try {
var endTime = process . hrtime ( startTime ) ;
var runtimeNanos = ( ( endTime [ 0 ] * nanosToSeconds ) + endTime [ 1 ] ) ;
var runtimeSeconds = runtimeNanos / nanosToSeconds ;
var aTimeoutFromUnifiedToSeconds ;
var aTimeoutToUnifiedToSeconds ;
2015-10-03 10:04:57 +02:00
2014-09-01 11:22:04 +02:00
// calculating the timeout in seconds
2016-04-23 22:06:48 +02:00
if ( aTimeoutUnit == TimeUnitEnum . MILLIS ) {
2014-09-01 11:22:04 +02:00
aTimeoutFromUnifiedToSeconds = aTimeoutFrom / millisToSeconds ;
aTimeoutToUnifiedToSeconds = aTimeoutTo / millisToSeconds ;
2016-04-23 22:06:48 +02:00
} else if ( aTimeoutUnit == TimeUnitEnum . SECONDS ) {
2014-09-01 11:22:04 +02:00
aTimeoutFromUnifiedToSeconds = aTimeoutFrom ;
aTimeoutToUnifiedToSeconds = aTimeoutTo ;
2016-04-23 22:06:48 +02:00
} else if ( aTimeoutUnit == TimeUnitEnum . MINUTES ) {
2014-09-01 11:22:04 +02:00
aTimeoutFromUnifiedToSeconds = aTimeoutFrom * secondsToMinutes ;
aTimeoutToUnifiedToSeconds = aTimeoutTo * secondsToMinutes ;
2016-04-23 22:06:48 +02:00
} else if ( aTimeoutUnit == TimeUnitEnum . HOURS ) {
2014-09-01 11:22:04 +02:00
aTimeoutFromUnifiedToSeconds = aTimeoutFrom * secondsToHours ;
aTimeoutToUnifiedToSeconds = aTimeoutTo * secondsToHours ;
2016-04-23 22:06:48 +02:00
} else if ( aTimeoutUnit == TimeUnitEnum . DAYS ) {
2014-09-01 11:22:04 +02:00
aTimeoutFromUnifiedToSeconds = aTimeoutFrom * secondsToDays ;
aTimeoutToUnifiedToSeconds = aTimeoutTo * secondsToDays ;
}
2015-10-03 10:04:57 +02:00
2016-04-23 22:06:48 +02:00
if ( inBetweenDelays ( aTimeoutFromUnifiedToSeconds , aTimeoutToUnifiedToSeconds , runtimeSeconds , GRACE _PERCENTAGE ) ) {
2014-09-01 11:22:04 +02:00
done ( ) ;
} else {
try {
2016-04-23 22:06:48 +02:00
should . fail ( null , null , "Delayed runtime seconds " + runtimeSeconds + " was not \"in between enough\" enough to expected values of: " + aTimeoutFromUnifiedToSeconds + " and " + aTimeoutToUnifiedToSeconds ) ;
2014-09-01 11:22:04 +02:00
} catch ( err ) {
done ( err ) ;
}
}
} catch ( err ) {
done ( err ) ;
}
} ) ;
var startTime = process . hrtime ( ) ;
delayNode1 . receive ( { payload : "delayMe" } ) ;
} ) ;
}
2015-10-03 10:04:57 +02:00
2014-09-01 11:22:04 +02:00
it ( 'randomly delays the message in seconds' , function ( done ) {
randomDelayTest ( 0.4 , 0.8 , "seconds" , done ) ;
} ) ;
2015-10-03 10:04:57 +02:00
2015-03-22 10:38:42 +01:00
it ( 'randomly delays the message in milliseconds' , function ( done ) {
2015-01-14 11:18:47 +01:00
randomDelayTest ( "400" , "800" , "milliseconds" , done ) ;
2014-09-01 11:22:04 +02:00
} ) ;
2015-10-03 10:04:57 +02:00
2014-09-01 11:22:04 +02:00
it ( 'randomly delays the message in minutes' , function ( done ) {
randomDelayTest ( 0.0066 , 0.0133 , "minutes" , done ) ;
} ) ;
2015-10-03 10:04:57 +02:00
2014-09-01 11:22:04 +02:00
it ( 'delays the message in hours' , function ( done ) {
randomDelayTest ( 0.000111111 , 0.000222222 , "hours" , done ) ;
} ) ;
2015-10-03 10:04:57 +02:00
2014-09-01 11:22:04 +02:00
it ( 'delays the message in days' , function ( done ) {
randomDelayTest ( 0.0000046296 , 0.0000092593 , "days" , done ) ;
} ) ;
2015-10-03 10:04:57 +02:00
2015-03-22 10:38:42 +01:00
it ( 'handles delay queue' , function ( done ) {
2016-04-24 18:41:22 +02:00
this . timeout ( 2000 ) ;
2016-09-16 15:27:14 +02:00
var flow = [ { id : "delayNode1" , type : "delay" , "name" : "delayNode" , "nbRateUnits" : "1" , "pauseType" : "queue" , "timeout" : 1 , "timeoutUnits" : "seconds" , "rate" : 4 , "rateUnits" : "second" , "randomFirst" : "1" , "randomLast" : "5" , "randomUnits" : "seconds" , "drop" : false , "wires" : [ [ "helperNode1" ] ] } ,
2015-03-22 10:38:42 +01:00
{ id : "helperNode1" , type : "helper" , wires : [ ] } ] ;
helper . load ( delayNode , flow , function ( ) {
var delayNode1 = helper . getNode ( "delayNode1" ) ;
var helperNode1 = helper . getNode ( "helperNode1" ) ;
2016-04-24 18:41:22 +02:00
var t = Date . now ( ) ;
2015-03-22 10:38:42 +01:00
helperNode1 . on ( "input" , function ( msg ) {
msg . should . have . a . property ( 'payload' ) ;
msg . should . have . a . property ( 'topic' ) ;
2016-04-24 18:41:22 +02:00
try {
if ( msg . topic === "_none_" ) {
msg . payload . should . equal ( 2 ) ;
2017-04-12 21:54:31 +02:00
( Date . now ( ) - t ) . should . be . approximately ( 500 , 200 ) ;
2016-04-24 18:41:22 +02:00
}
else if ( msg . topic === "A" ) {
msg . payload . should . equal ( 4 ) ;
2017-04-12 21:54:31 +02:00
( Date . now ( ) - t ) . should . be . approximately ( 750 , 200 ) ;
2016-04-24 18:41:22 +02:00
}
else {
msg . topic . should . equal ( "B" ) ;
msg . payload . should . equal ( 1 ) ;
2017-04-12 21:54:31 +02:00
( Date . now ( ) - t ) . should . be . approximately ( 1000 , 200 ) ;
2016-04-24 18:41:22 +02:00
done ( ) ;
}
} catch ( e ) {
done ( e ) ;
2015-03-22 10:38:42 +01:00
}
} ) ;
2016-04-24 18:41:22 +02:00
setTimeout ( function ( ) {
// send test messages
delayNode1 . receive ( { payload : 1 } ) ; // send something with blank topic
delayNode1 . receive ( { payload : 1 , topic : "A" } ) ; // and something with a fixed topic
delayNode1 . receive ( { payload : 1 , topic : "B" } ) ; // and something else with a fixed topic (3rd tick)
delayNode1 . receive ( { payload : 2 , topic : "A" } ) ; // these should replace them in queue
delayNode1 . receive ( { payload : 3 , topic : "A" } ) ; // ditto
delayNode1 . receive ( { payload : 2 } ) ; // so only this should get out on first tick
delayNode1 . receive ( { payload : 4 , topic : "A" } ) ; // and this one on second tick
} , 275 ) ; // wait one tick beofre starting.. (to test no messages in queue path.)
2015-03-22 10:38:42 +01:00
} ) ;
} ) ;
2016-03-20 18:46:12 +01:00
it ( 'handles timed queue' , function ( done ) {
2016-04-24 18:41:22 +02:00
this . timeout ( 2000 ) ;
var flow = [ { "id" : "delayNode1" , "type" : "delay" , "name" : "delayNode" , "pauseType" : "timed" , "timeout" : 1 , "timeoutUnits" : "seconds" , "rate" : 2 , "rateUnits" : "second" , "randomFirst" : "1" , "randomLast" : "5" , "randomUnits" : "seconds" , "drop" : false , "wires" : [ [ "helperNode1" ] ] } ,
2016-03-20 18:46:12 +01:00
{ id : "helperNode1" , type : "helper" , wires : [ ] } ] ;
helper . load ( delayNode , flow , function ( ) {
var delayNode1 = helper . getNode ( "delayNode1" ) ;
var helperNode1 = helper . getNode ( "helperNode1" ) ;
2016-04-24 18:41:22 +02:00
var t = Date . now ( ) ;
2016-03-20 18:46:12 +01:00
helperNode1 . on ( "input" , function ( msg ) {
2016-04-24 18:41:22 +02:00
msg . should . have . a . property ( 'payload' ) ;
msg . should . have . a . property ( 'topic' ) ;
try {
if ( msg . topic === "_none_" ) {
msg . payload . should . equal ( 2 ) ;
2017-04-12 21:54:31 +02:00
( Date . now ( ) - t ) . should . be . approximately ( 500 , 200 ) ;
2016-04-24 18:41:22 +02:00
}
else if ( msg . topic === "A" ) {
msg . payload . should . equal ( 4 ) ;
2017-04-12 21:54:31 +02:00
( Date . now ( ) - t ) . should . be . approximately ( 500 , 200 ) ;
2016-04-24 18:41:22 +02:00
}
else {
msg . topic . should . equal ( "B" ) ;
msg . payload . should . equal ( 1 ) ;
2017-04-12 21:54:31 +02:00
( Date . now ( ) - t ) . should . be . approximately ( 500 , 200 ) ;
2016-04-24 18:41:22 +02:00
done ( ) ;
}
} catch ( e ) {
done ( e ) ;
2016-03-20 18:46:12 +01:00
}
} ) ;
// send test messages
2016-04-24 18:41:22 +02:00
delayNode1 . receive ( { payload : 1 } ) ; // send something with blank topic
delayNode1 . receive ( { payload : 1 , topic : "A" } ) ; // and something with a fixed topic
delayNode1 . receive ( { payload : 1 , topic : "B" } ) ; // and something else with a fixed topic
delayNode1 . receive ( { payload : 2 , topic : "A" } ) ; // these should replace them in queue
delayNode1 . receive ( { payload : 3 , topic : "A" } ) ; // ditto
delayNode1 . receive ( { payload : 2 } ) ; // so all should go on first tick
delayNode1 . receive ( { payload : 4 , topic : "A" } ) ; // and nothing on second
2016-03-20 18:46:12 +01:00
} ) ;
} ) ;
2018-09-23 18:31:11 +02:00
it ( 'can flush delay queue' , function ( done ) {
this . timeout ( 2000 ) ;
var flow = [ { "id" : "delayNode1" , "type" : "delay" , "name" : "delayNode" , "pauseType" : "delay" , "timeout" : 1 , "timeoutUnits" : "seconds" , "rate" : 2 , "rateUnits" : "second" , "randomFirst" : "1" , "randomLast" : "5" , "randomUnits" : "seconds" , "drop" : false , "wires" : [ [ "helperNode1" ] ] } ,
{ id : "helperNode1" , type : "helper" , wires : [ ] } ] ;
helper . load ( delayNode , flow , function ( ) {
var delayNode1 = helper . getNode ( "delayNode1" ) ;
var helperNode1 = helper . getNode ( "helperNode1" ) ;
var t = Date . now ( ) ;
var c = 0 ;
helperNode1 . on ( "input" , function ( msg ) {
msg . should . have . a . property ( 'payload' ) ;
msg . should . have . a . property ( 'topic' ) ;
try {
if ( msg . topic === "foo" ) {
msg . payload . should . equal ( 1 ) ;
( Date . now ( ) - t ) . should . be . approximately ( 0 , 100 ) ;
c = c + 1 ;
}
else {
if ( msg . topic === "bar" ) {
msg . payload . should . equal ( 1 ) ;
( Date . now ( ) - t ) . should . be . approximately ( 0 , 100 ) ;
c = c + 1 ;
}
}
if ( c === 5 ) { done ( ) ; }
} catch ( e ) {
done ( e ) ;
}
} ) ;
// send test messages
delayNode1 . receive ( { payload : 1 , topic : "foo" } ) ; // send something with blank topic
setImmediate ( function ( ) { delayNode1 . receive ( { payload : 1 , topic : "bar" } ) ; } ) ; // send something with blank topic
setImmediate ( function ( ) { delayNode1 . receive ( { payload : 1 , topic : "bar" } ) ; } ) ; // send something with blank topic
setImmediate ( function ( ) { delayNode1 . receive ( { payload : 1 , topic : "bar" } ) ; } ) ; // send something with blank topic
setImmediate ( function ( ) { delayNode1 . receive ( { payload : 1 , topic : "bar" } ) ; } ) ; // send something with blank topic
setImmediate ( function ( ) { delayNode1 . receive ( { flush : true } ) ; } ) ; // reset the queue
} ) ;
} ) ;
it ( 'can reset delay queue' , function ( done ) {
this . timeout ( 2000 ) ;
var flow = [ { "id" : "delayNode1" , "type" : "delay" , "name" : "delayNode" , "pauseType" : "delay" , "timeout" : 1 , "timeoutUnits" : "seconds" , "rate" : 2 , "rateUnits" : "second" , "randomFirst" : "1" , "randomLast" : "5" , "randomUnits" : "seconds" , "drop" : false , "wires" : [ [ "helperNode1" ] ] } ,
{ id : "helperNode1" , type : "helper" , wires : [ ] } ] ;
helper . load ( delayNode , flow , function ( ) {
var delayNode1 = helper . getNode ( "delayNode1" ) ;
var helperNode1 = helper . getNode ( "helperNode1" ) ;
var t = Date . now ( ) ;
var c = 0 ;
helperNode1 . on ( "input" , function ( msg ) {
c = c + 1 ;
} ) ;
setTimeout ( function ( ) {
if ( c === 0 ) { done ( ) ; }
} , 700 ) ;
// send test messages
delayNode1 . receive ( { payload : 1 , topic : "foo" } ) ; // send something with blank topic
setImmediate ( function ( ) { delayNode1 . receive ( { payload : 1 , topic : "bar" } ) ; } ) ; // send something with blank topic
setImmediate ( function ( ) { delayNode1 . receive ( { payload : 1 , topic : "bar" } ) ; } ) ; // send something with blank topic
setImmediate ( function ( ) { delayNode1 . receive ( { payload : 1 , topic : "bar" } ) ; } ) ; // send something with blank topic
setImmediate ( function ( ) { delayNode1 . receive ( { payload : 1 , topic : "bar" } ) ; } ) ; // send something with blank topic
setImmediate ( function ( ) { delayNode1 . receive ( { reset : true } ) ; } ) ; // reset the queue
} ) ;
} ) ;
it ( 'can flush rate limit queue' , function ( done ) {
this . timeout ( 2000 ) ;
var flow = [ { "id" : "delayNode1" , "type" : "delay" , "name" : "delayNode" , "pauseType" : "rate" , "timeout" : 1 , "timeoutUnits" : "seconds" , "rate" : 2 , "rateUnits" : "second" , "randomFirst" : "1" , "randomLast" : "5" , "randomUnits" : "seconds" , "drop" : false , "wires" : [ [ "helperNode1" ] ] } ,
{ id : "helperNode1" , type : "helper" , wires : [ ] } ] ;
helper . load ( delayNode , flow , function ( ) {
var delayNode1 = helper . getNode ( "delayNode1" ) ;
var helperNode1 = helper . getNode ( "helperNode1" ) ;
var t = Date . now ( ) ;
var c = 0 ;
helperNode1 . on ( "input" , function ( msg ) {
msg . should . have . a . property ( 'payload' ) ;
msg . should . have . a . property ( 'topic' ) ;
try {
if ( msg . topic === "foo" ) {
msg . payload . should . equal ( 1 ) ;
( Date . now ( ) - t ) . should . be . approximately ( 0 , 100 ) ;
c = c + 1 ;
}
else {
if ( msg . topic === "bar" ) {
msg . payload . should . equal ( 1 ) ;
( Date . now ( ) - t ) . should . be . approximately ( 0 , 100 ) ;
c = c + 1 ;
}
}
if ( c === 5 ) { done ( ) ; }
} catch ( e ) {
done ( e ) ;
}
} ) ;
// send test messages
delayNode1 . receive ( { payload : 1 , topic : "foo" } ) ; // send something with blank topic
setImmediate ( function ( ) { delayNode1 . receive ( { payload : 1 , topic : "bar" } ) ; } ) ; // send something with blank topic
setImmediate ( function ( ) { delayNode1 . receive ( { payload : 1 , topic : "bar" } ) ; } ) ; // send something with blank topic
setImmediate ( function ( ) { delayNode1 . receive ( { payload : 1 , topic : "bar" } ) ; } ) ; // send something with blank topic
setImmediate ( function ( ) { delayNode1 . receive ( { payload : 1 , topic : "bar" } ) ; } ) ; // send something with blank topic
setImmediate ( function ( ) { delayNode1 . receive ( { flush : true } ) ; } ) ; // reset the queue
} ) ;
} ) ;
it ( 'can reset rate limit queue' , function ( done ) {
this . timeout ( 2000 ) ;
var flow = [ { "id" : "delayNode1" , "type" : "delay" , "name" : "delayNode" , "pauseType" : "rate" , "timeout" : 1 , "timeoutUnits" : "seconds" , "rate" : 2 , "rateUnits" : "second" , "randomFirst" : "1" , "randomLast" : "5" , "randomUnits" : "seconds" , "drop" : false , "wires" : [ [ "helperNode1" ] ] } ,
{ id : "helperNode1" , type : "helper" , wires : [ ] } ] ;
helper . load ( delayNode , flow , function ( ) {
var delayNode1 = helper . getNode ( "delayNode1" ) ;
var helperNode1 = helper . getNode ( "helperNode1" ) ;
var t = Date . now ( ) ;
var c = 0 ;
helperNode1 . on ( "input" , function ( msg ) {
msg . should . have . a . property ( 'payload' ) ;
msg . should . have . a . property ( 'topic' ) ;
try {
if ( msg . topic === "foo" ) {
msg . payload . should . equal ( 1 ) ;
( Date . now ( ) - t ) . should . be . approximately ( 0 , 100 ) ;
c = c + 1 ;
}
} catch ( e ) {
done ( e ) ;
}
} ) ;
setTimeout ( function ( ) {
if ( c === 1 ) { done ( ) ; }
} , 700 ) ;
// send test messages
delayNode1 . receive ( { payload : 1 , topic : "foo" } ) ; // send something with blank topic
setImmediate ( function ( ) { delayNode1 . receive ( { payload : 1 , topic : "bar" } ) ; } ) ; // send something with blank topic
setImmediate ( function ( ) { delayNode1 . receive ( { payload : 1 , topic : "bar" } ) ; } ) ; // send something with blank topic
setImmediate ( function ( ) { delayNode1 . receive ( { payload : 1 , topic : "bar" } ) ; } ) ; // send something with blank topic
setImmediate ( function ( ) { delayNode1 . receive ( { payload : 1 , topic : "bar" } ) ; } ) ; // send something with blank topic
setImmediate ( function ( ) { delayNode1 . receive ( { reset : true } ) ; } ) ; // reset the queue
} ) ;
} ) ;
2014-09-01 11:22:04 +02:00
} ) ;