View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2007 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
7    *
8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
11   */
12  
13  package com.eviware.soapui.impl.wsdl.loadtest.strategy;
14  
15  import javax.swing.JComponent;
16  import javax.swing.JLabel;
17  import javax.swing.JPanel;
18  import javax.swing.JTextField;
19  import javax.swing.text.Document;
20  
21  import org.apache.log4j.Logger;
22  import org.apache.xmlbeans.XmlObject;
23  
24  import com.eviware.soapui.impl.wsdl.loadtest.WsdlLoadTest;
25  import com.eviware.soapui.model.testsuite.LoadTestRunContext;
26  import com.eviware.soapui.model.testsuite.LoadTestRunner;
27  import com.eviware.soapui.model.testsuite.TestRunContext;
28  import com.eviware.soapui.model.testsuite.TestRunner;
29  import com.eviware.soapui.support.DocumentListenerAdapter;
30  import com.eviware.soapui.support.UISupport;
31  import com.eviware.soapui.support.swing.ComponentBag;
32  import com.eviware.soapui.support.xml.XmlObjectConfigurationBuilder;
33  import com.eviware.soapui.support.xml.XmlObjectConfigurationReader;
34  import com.jgoodies.forms.builder.ButtonBarBuilder;
35  
36  /***
37   * Simple LoadStrategy that just runs until canceled without any delays
38   * 
39   * @author Ole.Matzura
40   */
41  
42  public class VarianceLoadStrategy extends AbstractLoadStrategy 
43  {
44  	private final static Logger log = Logger.getLogger(VarianceLoadStrategy.class);
45  	
46  	public static final String STRATEGY_TYPE = "Variance";
47  	private static final String INTERVAL_ELEMENT = "interval";
48  	private static final String VARIANCE_ELEMENT = "variance";
49  	private static final int DEFAULT_INTERVAL = 60000;
50  	private static final float DEFAULT_VARIANCE = 0.5F;
51  	
52  	private JPanel configPanel;
53  	
54  	private long interval = DEFAULT_INTERVAL;
55  	private float variance = DEFAULT_VARIANCE;
56  	private JTextField intervalField;
57  	private JTextField varianceField;
58  	private JLabel infoLabel;
59  	private long baseThreadCount;
60  	private long startTime;
61  	private ComponentBag stateDependantComponents = new ComponentBag();
62  
63  	public VarianceLoadStrategy()
64  	{
65  		super( STRATEGY_TYPE );
66  
67  		interval = DEFAULT_INTERVAL;
68  		variance = DEFAULT_VARIANCE;
69  	}
70  
71  	public VarianceLoadStrategy(XmlObject config)
72  	{
73  		super( STRATEGY_TYPE );
74  		
75  		XmlObjectConfigurationReader reader = new XmlObjectConfigurationReader( config );
76  		interval = reader.readLong( INTERVAL_ELEMENT, DEFAULT_INTERVAL );
77  		variance = reader.readFloat( VARIANCE_ELEMENT, DEFAULT_VARIANCE );
78  	}
79  
80  	public JComponent getConfigurationPanel()
81  	{
82  		if( configPanel == null )
83  		{
84  			ButtonBarBuilder builder = new ButtonBarBuilder();
85  			
86  			intervalField = new JTextField( 4 );
87  			UISupport.setPreferredHeight( intervalField, 18 );
88  			intervalField.setHorizontalAlignment( JTextField.RIGHT );
89  			intervalField.setText( String.valueOf( interval/1000 ));
90  			intervalField.setToolTipText( "Sets the interval between variances in seconds" );
91  			intervalField.getDocument().addDocumentListener( new DocumentListenerAdapter(){
92  
93  				public void update( Document doc )
94  				{
95  					try
96  					{
97  						interval = Long.parseLong(intervalField.getText())*1000;
98  						notifyConfigurationChanged();
99  					}
100 					catch (NumberFormatException e)
101 					{
102 					}
103 				}}
104 				);
105 			
106 			builder.addFixed( new JLabel( "Interval" ));
107 			builder.addRelatedGap();
108 			
109 			builder.addFixed( intervalField );
110 			builder.addRelatedGap();
111 
112 			varianceField = new JTextField( 3 );
113 			UISupport.setPreferredHeight( varianceField, 18 );
114 			varianceField.setHorizontalAlignment( JTextField.RIGHT );
115 			varianceField.setText( String.valueOf( variance ));
116 			varianceField.setToolTipText( "Specifies the relative magnitude of a variance" );
117 			varianceField.getDocument().addDocumentListener( new DocumentListenerAdapter(){
118 
119 				public void update( Document doc )
120 				{
121 					try
122 					{
123 						variance = Float.parseFloat(varianceField.getText());
124 						notifyConfigurationChanged();
125 					}
126 					catch (NumberFormatException e)
127 					{
128 					}
129 				}}
130 				);
131 			
132 			builder.addFixed( new JLabel( "Variance" ));
133 			builder.addRelatedGap();
134 			builder.addFixed( varianceField);
135 			builder.addRelatedGap();
136 			
137 			infoLabel = new JLabel();
138 			builder.addFixed( infoLabel );
139 			
140 			configPanel = builder.getPanel();
141 			
142 			stateDependantComponents.add( intervalField );
143 			stateDependantComponents.add( varianceField );
144 		}
145 
146 		return configPanel;
147 	}
148 
149 	public XmlObject getConfig()
150 	{
151 		XmlObjectConfigurationBuilder builder = new XmlObjectConfigurationBuilder();
152 		builder.add( INTERVAL_ELEMENT, interval );
153       builder.add( VARIANCE_ELEMENT, variance );
154       return builder.finish();
155 	}
156 
157 	/***
158 	 * Factory for VarianceLoadStrategy class
159 	 * 
160 	 * @author Ole.Matzura
161 	 */
162 
163 	public static class Factory implements LoadStrategyFactory
164 	{
165 		public String getType()
166 		{
167 			return STRATEGY_TYPE;
168 		}
169 
170 		public LoadStrategy build(XmlObject config)
171 		{
172 			return new VarianceLoadStrategy( config );
173 		}
174 
175 		public LoadStrategy create()
176 		{
177 			return new VarianceLoadStrategy();
178 		}
179 	}
180 
181 	public void beforeLoadTest(LoadTestRunner loadTestRunner, LoadTestRunContext context)
182 	{
183 		baseThreadCount = ((WsdlLoadTest)loadTestRunner.getLoadTest()).getThreadCount();
184 		startTime = System.currentTimeMillis();
185 		stateDependantComponents.setEnabled( false );
186 	}
187 
188 	public void beforeTestCase( LoadTestRunner loadTestRunner, LoadTestRunContext context, TestRunner testRunner, TestRunContext runContext)
189 	{
190 		double timePassed = (System.currentTimeMillis() - startTime)%interval;
191 		float threadCount = baseThreadCount;
192 		
193 		// initial increase?
194 		double quarter = (double)interval/4;
195 		
196 		if( timePassed < quarter )
197 		{
198 			threadCount += (int) Math.round(((timePassed/quarter)*variance*threadCount));
199 		}
200 		// decrease?
201 		else if( timePassed < quarter*2)
202 		{
203 			threadCount += (int) Math.round(((1-((timePassed%quarter)/quarter))*variance*threadCount));
204 		}
205 		else if( timePassed < quarter*3)
206 		{
207 			threadCount -= (int) Math.round((((timePassed%quarter)/quarter)*variance*threadCount));
208 		}
209 		// final increase
210 		else 
211 		{
212 			threadCount -= (int) Math.round(((1-((timePassed%quarter)/quarter))*variance*threadCount));
213 		}
214 		
215 		if( threadCount < 1 )
216 			threadCount = 1;
217 		
218 		WsdlLoadTest wsdlLoadTest = ((WsdlLoadTest)loadTestRunner.getLoadTest());
219 		if( wsdlLoadTest.getThreadCount() != (int)threadCount )
220 		{
221 			log.debug( "Changing threadcount to " + threadCount );
222 			wsdlLoadTest.setThreadCount( (int) threadCount );
223 		}
224 	}
225 	
226 	public void afterLoadTest(LoadTestRunner testRunner, LoadTestRunContext context)
227 	{
228 		WsdlLoadTest wsdlLoadTest = (WsdlLoadTest) testRunner.getLoadTest();
229 		wsdlLoadTest.setThreadCount( baseThreadCount );
230 		stateDependantComponents.setEnabled( true );
231 	}
232 	
233 	public boolean allowThreadCountChangeDuringRun()
234 	{
235 		return false;
236 	}
237 }