View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2009 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.data;
14  
15  import java.beans.PropertyChangeEvent;
16  import java.beans.PropertyChangeListener;
17  import java.util.ArrayList;
18  import java.util.HashMap;
19  import java.util.List;
20  import java.util.Map;
21  
22  import javax.swing.table.AbstractTableModel;
23  
24  import org.apache.log4j.Logger;
25  
26  import com.eviware.soapui.model.support.LoadTestRunListenerAdapter;
27  import com.eviware.soapui.model.support.TestSuiteListenerAdapter;
28  import com.eviware.soapui.model.testsuite.LoadTest;
29  import com.eviware.soapui.model.testsuite.LoadTestRunContext;
30  import com.eviware.soapui.model.testsuite.LoadTestRunner;
31  import com.eviware.soapui.model.testsuite.TestCase;
32  import com.eviware.soapui.model.testsuite.TestCaseRunContext;
33  import com.eviware.soapui.model.testsuite.TestCaseRunner;
34  import com.eviware.soapui.model.testsuite.TestStep;
35  import com.eviware.soapui.model.testsuite.TestStepResult;
36  
37  /***
38   * TableModel holding loadtest samples
39   */
40  
41  public class SamplesModel extends AbstractTableModel
42  {
43  	private final LoadTest loadTest;
44  	private List<TestSample[]> samples = new ArrayList<TestSample[]>();
45  	private InternalTestRunListener testRunListener;
46  	private InternalTestSuiteListener testSuiteListener;
47  	private InternalPropertyChangeListener propertyChangeListener;
48  	private TestCase testCase;
49  	private final static Logger log = Logger.getLogger( SamplesModel.class );
50  
51  	public SamplesModel( LoadTest loadTest )
52  	{
53  		this.loadTest = loadTest;
54  
55  		testRunListener = new InternalTestRunListener();
56  		testSuiteListener = new InternalTestSuiteListener();
57  		propertyChangeListener = new InternalPropertyChangeListener();
58  
59  		testCase = loadTest.getTestCase();
60  		loadTest.addLoadTestRunListener( testRunListener );
61  		testCase.getTestSuite().addTestSuiteListener( testSuiteListener );
62  
63  		for( TestStep testStep : testCase.getTestStepList() )
64  		{
65  			testStep.addPropertyChangeListener( TestStep.NAME_PROPERTY, propertyChangeListener );
66  		}
67  	}
68  
69  	public int getRowCount()
70  	{
71  		return samples.size();
72  	}
73  
74  	public int getColumnCount()
75  	{
76  		return testCase.getTestStepCount();
77  	}
78  
79  	public Object getValueAt( int rowIndex, int columnIndex )
80  	{
81  		TestSample[] testSamples = samples.get( rowIndex );
82  		return testSamples == null ? "discarded" : testSamples[columnIndex];
83  	}
84  
85  	public void addSamples( TestSample[] newSamples )
86  	{
87  		if( newSamples.length != getColumnCount() )
88  			throw new RuntimeException( "Invalid number of samples reported: " + newSamples.length + ", expected "
89  					+ getColumnCount() );
90  
91  		samples.add( newSamples );
92  
93  		fireTableRowsInserted( samples.size() - 1, samples.size() - 1 );
94  	}
95  
96  	public Class<?> getColumnClass( int columnIndex )
97  	{
98  		return TestSample.class;
99  	}
100 
101 	public String getColumnName( int column )
102 	{
103 		return testCase.getTestStepAt( column ).getName();
104 	}
105 
106 	public void clear()
107 	{
108 		int size = samples.size();
109 		if( size > 0 )
110 		{
111 			samples.clear();
112 			fireTableRowsDeleted( 0, size );
113 		}
114 	}
115 
116 	/***
117 	 * Listener for collecting samples
118 	 * 
119 	 * @author Ole.Matzura
120 	 */
121 
122 	private class InternalTestRunListener extends LoadTestRunListenerAdapter
123 	{
124 		public void afterTestCase( LoadTestRunner loadTestRunner, LoadTestRunContext context, TestCaseRunner testRunner,
125 				TestCaseRunContext runContext )
126 		{
127 			Map<TestStep, TestSample> samplesMap = new HashMap<TestStep, TestSample>();
128 			List<TestStepResult> results = testRunner.getResults();
129 
130 			for( int c = 0; c < results.size(); c++ )
131 			{
132 				TestStepResult result = results.get( c );
133 				if( result == null )
134 				{
135 					log.warn( "Result [" + c + "] is null in TestCase [" + testCase.getName() + "]" );
136 					continue;
137 				}
138 
139 				TestStep testStep = result.getTestStep();
140 
141 				if( !samplesMap.containsKey( testStep ) )
142 				{
143 					samplesMap.put( testStep, new TestSample( testStep ) );
144 				}
145 
146 				samplesMap.get( testStep ).addTestStepResult( result );
147 			}
148 
149 			TestCase testCase = loadTest.getTestCase();
150 
151 			TestSample[] samples = new TestSample[testCase.getTestStepCount()];
152 			for( int c = 0; c < samples.length; c++ )
153 			{
154 				samples[c] = samplesMap.get( testCase.getTestStepAt( c ) );
155 			}
156 
157 			addSamples( samples );
158 		}
159 	}
160 
161 	public List<TestSample[]> getSamples()
162 	{
163 		return samples;
164 	}
165 
166 	public void release()
167 	{
168 		loadTest.removeLoadTestRunListener( testRunListener );
169 		loadTest.getTestCase().getTestSuite().removeTestSuiteListener( testSuiteListener );
170 
171 		for( TestStep testStep : loadTest.getTestCase().getTestStepList() )
172 		{
173 			testStep.removePropertyChangeListener( propertyChangeListener );
174 		}
175 	}
176 
177 	/***
178 	 * Holder for a TestSample
179 	 * 
180 	 * @author ole.matzura
181 	 */
182 
183 	public static final class TestSample
184 	{
185 		private final TestStep testStep;
186 		private List<TestStepResult> results;
187 
188 		public TestSample( TestStep testStep )
189 		{
190 			this.testStep = testStep;
191 		}
192 
193 		public void addTestStepResult( TestStepResult result )
194 		{
195 			if( result.getTestStep() != testStep )
196 				throw new RuntimeException( "Trying to add sample for false testStep [" + result.getTestStep().getName()
197 						+ "], " + "expecting [" + testStep.getName() + "]" );
198 
199 			if( results == null )
200 				results = new ArrayList<TestStepResult>();
201 
202 			results.add( result );
203 		}
204 
205 		public List<TestStepResult> getResults()
206 		{
207 			return results;
208 		}
209 
210 		public int getResultCount()
211 		{
212 			return results == null ? 0 : results.size();
213 		}
214 
215 		public long getResultAverage()
216 		{
217 			if( results == null )
218 				return 0;
219 
220 			if( results.size() == 1 )
221 				return results.get( 0 ).getTimeTaken();
222 
223 			long sum = 0;
224 			for( TestStepResult result : results )
225 				sum += result.getTimeTaken();
226 
227 			return sum / results.size();
228 		}
229 	}
230 
231 	private class InternalTestSuiteListener extends TestSuiteListenerAdapter
232 	{
233 		public void testStepAdded( TestStep testStep, int index )
234 		{
235 			if( testStep.getTestCase() == testCase )
236 			{
237 				testStep.addPropertyChangeListener( TestStep.NAME_PROPERTY, propertyChangeListener );
238 
239 				// insert null entry in existing samples
240 				for( int i = 0; i < samples.size(); i++ )
241 				{
242 					TestSample[] testSamples = samples.get( i );
243 					TestSample[] newSamples = new TestSample[testSamples.length + 1];
244 					for( int c = 0; c < testSamples.length; c++ )
245 					{
246 						if( c < index )
247 						{
248 							newSamples[c] = testSamples[c];
249 						}
250 						else
251 						{
252 							newSamples[c + 1] = testSamples[c];
253 						}
254 					}
255 
256 					samples.set( i, newSamples );
257 				}
258 
259 				fireTableStructureChanged();
260 			}
261 		}
262 
263 		public void testStepRemoved( TestStep testStep, int index )
264 		{
265 			if( testStep.getTestCase() == testCase )
266 			{
267 				testStep.removePropertyChangeListener( propertyChangeListener );
268 
269 				// remove from samples
270 				for( int i = 0; i < samples.size(); i++ )
271 				{
272 					TestSample[] testSamples = samples.get( i );
273 					TestSample[] newSamples = new TestSample[testSamples.length - 1];
274 					for( int c = 0; c < testSamples.length; c++ )
275 					{
276 						if( c < index )
277 						{
278 							newSamples[c] = testSamples[c];
279 						}
280 						else if( c > index )
281 						{
282 							newSamples[c - 1] = testSamples[c];
283 						}
284 					}
285 
286 					samples.set( i, newSamples );
287 				}
288 
289 				fireTableStructureChanged();
290 			}
291 		}
292 	}
293 
294 	private class InternalPropertyChangeListener implements PropertyChangeListener
295 	{
296 		public void propertyChange( PropertyChangeEvent evt )
297 		{
298 			fireTableStructureChanged();
299 		}
300 	}
301 
302 }