Forum Discussion

euthenia's avatar
euthenia
Occasional Contributor
13 years ago

Custom component help

I'm trying to create a custom Stepped Rate generator based on the Fixed Rate generator. The idea is that you set a starting rate, plus an increase and interval and then the generator ups the current rate by the increase amount every interval. I'm having some issues with it though... If I set the parameters, start the test and just leave things as they are all seems to work OK but if I then change the starting rate (which resets the current rate to the new starting rate) then following on from that the starting rate starts to automatically increase even though my script is not changing the property value at all.

Any ideas what's wrong? The script is as follows:

import com.eviware.loadui.api.events.PropertyEvent
import com.eviware.loadui.util.layout.DelayedFormattedString

import java.util.concurrent.TimeUnit

long currentRate = 0

//Properties
createProperty( 'stepLength', Long, 10 ) { value ->
stepDelay = Math.max( 1, (long)(stepSecondsPerUnit * value) )
stepDisplay.setArgs( stepIncrease.value, value, stepUnit.value )
scheduleIncrease()
}
createProperty( 'stepUnit', String, 'Sec' ) { value ->
if ( value == "Sec" )
stepSecondsPerUnit = 1
else if ( value == "Min" )
stepSecondsPerUnit = 60
else if ( value == "Hour" )
stepSecondsPerUnit = 360
stepDisplay.setArgs( stepIncrease.value, stepLength.value, value )
scheduleIncrease()
}
createProperty( 'stepIncrease', Long, 10) { value ->
stepDisplay.setArgs( value, stepLength.value, stepUnit.value )
scheduleIncrease()
}

createProperty( 'rate', Long, 10 ) { value ->
log.info("Starting rate changed to: " + rate.value)
currentRate = rate.value.longValue()
delay = Math.max( 1, (long)(milisecondsPerUnit/currentRate) )
display.setArgs( currentRate, unit.value )
schedule()
}
createProperty( 'unit', String, 'Sec' ) { value ->
if ( value == "Sec" )
milisecondsPerUnit = 1000000
else if ( value == "Min" )
milisecondsPerUnit = 60000000
else if ( value == "Hour" )
milisecondsPerUnit = 3600000000
display.setArgs( currentRate, value )
schedule()
}
onReplace( stateProperty ) { value ->
if( value )
{
scheduleIncrease()
schedule()
}
else
{
future?.cancel( true )
stepFuture?.cancel( true )
}
}

createProperty( 'burstSize', Long, 1 )

currentRate = rate.value.longValue()
milisecondsPerUnit = 1000000
delay = milisecondsPerUnit/currentRate

stepSecondsPerUnit = 1
stepDelay = stepSecondsPerUnit * stepLength.value

display = new DelayedFormattedString( '%d / %s', 200, currentRate, unit.value )
stepDisplay = new DelayedFormattedString( '%d every %d %s', 200, stepIncrease.value, stepLength.value, stepUnit.value )

triggerBurst = {
for( i in 1..burstSize.value )
{
trigger()
}
}

triggerIncrease = {
log.info("Current rate: " + currentRate + ", stepIncrease: " + stepIncrease.value)
currentRate += stepIncrease.value
delay = milisecondsPerUnit/currentRate
display.setArgs( currentRate, unit.value )
schedule()
}

onRelease = {
display.release()
stepDisplay.release()
}
future = null
stepFuture = null

schedule = {
if (stateProperty.value) {
future?.cancel(true);
future = scheduleAtFixedRate( { triggerBurst() }, delay.longValue(), delay.longValue(), TimeUnit.MICROSECONDS )
}
}

scheduleIncrease = {
if (running && stateProperty.value) {
stepFuture?.cancel(true);
stepFuture = scheduleAtFixedRate( { triggerIncrease() }, stepDelay.longValue(), stepDelay.longValue(), TimeUnit.SECONDS )
}
}

addEventListener( PropertyEvent ) { event ->
if ( event.event == PropertyEvent.Event.VALUE ) {
if( event.property == unit ) {
if ( unit.value == "Sec" )
milisecondsPerUnit = 1000000
if ( unit.value == "Min" )
milisecondsPerUnit = 60000000
if ( unit.value == "Hour" )
milisecondsPerUnit = 3600000000
}
if( event.property == stepUnit ) {
if ( stepUnit.value == "Sec" )
stepSecondsPerUnit = 1
if ( stepUnit.value == "Min" )
stepSecondsPerUnit = 60
if ( stepUnit.value == "Hour" )
stepSecondsPerUnit = 360
}
if (event.property == stateProperty && !stateProperty.value)
{
future?.cancel(true)
stepFuture?.cancel(true)
}
if (stateProperty.value)
{
future?.cancel(true)
stepFuture?.cancel(true)
}
if( rate.value != null && rate.value > 0 ) {
currentRate = rate.value.longValue()
delay = milisecondsPerUnit/currentRate
if ( delay < 1 )
delay = 1
display.setArgs( currentRate, unit.value )
schedule()
}
if( stepLength.value != null && stepLength.value > 0 ) {
stepDelay = stepSecondsPerUnit * stepLength.value
if ( stepDelay < 1 )
stepDelay = 1
stepDisplay.setArgs( stepIncrease.value, stepLength.value, stepUnit.value )
scheduleIncrease()
}
}
}

onAction( "START" ) {
scheduleIncrease()
schedule()
}

onAction( "STOP" ) {
future?.cancel( true )
stepFuture?.cancel( true )
}

//Layout
layout {
box(layout: 'wrap 3, ins 0' ) {
property( property:rate, label:'Starting rate', min:1 )
property( property:unit, label:'Unit', options:['Sec','Min','Hour'] )
separator()
property( property:stepIncrease, label:'Increase', min:1 )
property( property:stepLength, label:'Interval', min:1 )
property( property:stepUnit, label:'Unit', options:['Sec','Min','Hour'] )
}
separator( vertical:true )
box( widget:'display', layout: 'wrap 1, align right' ) {
node( label:'Rate', fString:display, constraints:'wmin 75' )
node( label:'Increase By', fString:stepDisplay, constraints:'wmin 75' )
}
}

//Compact Layout
compactLayout {
box( widget:'display' ) {
node( label:'Rate', fString:display )
node( label:'Increase by', fString:stepDisplay )
}
}

//Settings
settings( label: "General" ) {
property( property: burstSize, label:'Burst size' )
}

//Start scheduler
if ( unit.value == "Sec" )
milisecondsPerUnit = 1000000
if ( unit.value == "Min" )
milisecondsPerUnit = 60000000
if ( unit.value == "Hour" )
milisecondsPerUnit = 3600000000

if ( stepUnit.value == "Sec" )
stepSecondsPerUnit = 1
if ( stepUnit.value == "Min" )
stepSecondsPerUnit = 60
if ( stepUnit.value == "Hour" )
stepSecondsPerUnit = 360

currentRate = rate.value.longValue()
delay = milisecondsPerUnit/currentRate
stepDelay = stepSecondsPerUnit * stepLength.value

if (running)
{
scheduleIncrease()
schedule();
}

2 Replies

  • SmartBear_Suppo's avatar
    SmartBear_Suppo
    SmartBear Alumni (Retired)
    euthenia wrote:
    Hi!

    Nice to see a fellow component developer!

    First of all, for your attached script to work, you need to include a header in it, similar to the one below:
    /**
    * @name Stepped Rate
    * @category generators
    * @nonBlocking true
    */


    What's important above is @category runner. You probably know this already since you got the component to show up in loadUI.


    I have tried to reproduce the problem, but I'm unable to. I'm trying this:

    1. Set your component to Starting rate 1, Increase 1 and Interval 10.
    2. Play project (everything works).
    3. While playing, change starting rate to 3.
    4. Actual rate is set to 3 automatically and increases from there. Starting rate stays at 3, as far as I can tell.

    I'd be glad to help if I could reproduce this.

    Regards

    Henrik
    SmartBear Software
  • euthenia's avatar
    euthenia
    Occasional Contributor
    SmartBear Support wrote:
    euthenia wrote:
    Hi!

    Nice to see a fellow component developer!

    First of all, for your attached script to work, you need to include a header in it, similar to the one below:
    /**
    * @name Stepped Rate
    * @category generators
    * @nonBlocking true
    */


    What's important above is @category runner. You probably know this already since you got the component to show up in loadUI.


    I have tried to reproduce the problem, but I'm unable to. I'm trying this:

    1. Set your component to Starting rate 1, Increase 1 and Interval 10.
    2. Play project (everything works).
    3. While playing, change starting rate to 3.
    4. Actual rate is set to 3 automatically and increases from there. Starting rate stays at 3, as far as I can tell.

    I'd be glad to help if I could reproduce this.

    Regards

    Henrik
    SmartBear Software


    Thanks for the reply. I do actually have a header in my component - I just omitted it when I pasted the code in to my original post. Interesting that you don't seem to have the same problem as me... What I've tried is:

    1. Set starting rate to 1, unit to 'Sec', increase to 7, interval to 3 and interval units to 'Sec'.
    2. Hit play and let it tick up a bit.
    3. Change the starting rate (either change it to some other value and leave it there or just move it and move it back).
    4. The actual rate is reset to the starting rate.
    5. The starting rate now starts increasing by itself.

    I've added some logging in the component to see what is happening. If you have the log showing, you should see logging of the form 'Current rate: x, stepIncrease: y' each time the interval elapses, and should only see logging of the form 'Starting rate changed to: x' when the starting rate is manually changed. I'm getting lots of logging about the starting rate changing when I haven't made any change to it myself. As I said, this only happens if I change the starting rate while the test is running.

    It's not the end of the world for me as for my purposes I don't think that I would be changing the settings while a test is running, but it limits the usefulness of the component somewhat and means that I'd be hesitant to submit it to you for featuring in the custom component gallery because it's badly behaved.

    I'm using loadUI 1.5.0 by the way as we ideally need to be using released software rather than a nightly build.