View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2008 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.TestRunContext;
33  import com.eviware.soapui.model.testsuite.TestRunner;
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 + 
89  					", expected " + 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, TestRunner testRunner, TestRunContext runContext)
125 		{
126 			Map<TestStep,TestSample> samplesMap = new HashMap<TestStep, TestSample>();
127 			List<TestStepResult> results = testRunner.getResults();
128 			
129 			for( int c = 0; c < results.size(); c++ )
130 			{
131 				TestStepResult result = results.get( c );
132 				if( result == null )
133 				{
134 					log.warn( "Result [" + c + "] is null in TestCase [" + testCase.getName() + "]" );
135 					continue;
136 				}
137 				
138 				TestStep testStep = result.getTestStep();
139 				
140 				if( !samplesMap.containsKey( testStep ))
141 				{
142 					samplesMap.put( testStep, new TestSample( testStep ) );
143 				}
144 				
145 				samplesMap.get( testStep ).addTestStepResult( result );
146 			}
147 			
148 			TestCase testCase = loadTest.getTestCase();
149 			
150 			TestSample [] samples = new TestSample[testCase.getTestStepCount()];
151 			for( int c = 0; c < samples.length; c++ )
152 			{
153 				samples[c] = samplesMap.get( testCase.getTestStepAt( c ));
154 			}
155 
156 			addSamples( samples );
157 		}
158 	}
159 
160 	public List<TestSample[]> getSamples()
161 	{
162 		return samples;
163 	}
164 
165 	public void release()
166 	{
167 		loadTest.removeLoadTestRunListener( testRunListener );
168 		loadTest.getTestCase().getTestSuite().removeTestSuiteListener( testSuiteListener );
169 		
170 		for( TestStep testStep : loadTest.getTestCase().getTestStepList() )
171 		{
172 			testStep.removePropertyChangeListener( propertyChangeListener );
173 		}
174 	}
175 	
176 	/***
177 	 * Holder for a TestSample
178 	 * 
179 	 * @author ole.matzura
180 	 */
181 	
182 	public static final class TestSample
183 	{
184 		private final TestStep testStep;
185 		private List<TestStepResult> results;
186 
187 		public TestSample( TestStep testStep )
188 		{
189 			this.testStep = testStep;
190 		}
191 		
192 		public void addTestStepResult( TestStepResult result )
193 		{
194 			if( result.getTestStep() != testStep )
195 				throw new RuntimeException( "Trying to add sample for false testStep [" + result.getTestStep().getName() + "], " +
196 						"expecting [" + testStep.getName() + "]" );
197 			
198 			if( results == null ) 
199 				results = new ArrayList<TestStepResult>();
200 			
201 			results.add( result );
202 		}
203 		
204 		public List<TestStepResult> getResults()
205 		{
206 			return results;
207 		}
208 		
209 		public int getResultCount()
210 		{
211 			return results == null ? 0 : results.size();
212 		}
213 		
214 		public long getResultAverage()
215 		{
216 			if( results == null )
217 				return 0;
218 			
219 			if( results.size() == 1 )
220 				return results.get( 0 ).getTimeTaken();
221 			
222 			long sum = 0;
223 			for( TestStepResult result : results )
224 				sum += result.getTimeTaken();
225 			
226 			return sum / results.size();
227 		}
228 	}
229 	
230 	private class InternalTestSuiteListener extends TestSuiteListenerAdapter
231 	{
232 		public void testStepAdded(TestStep testStep, int index)
233 		{
234 			if( testStep.getTestCase() == testCase )
235 			{
236 				testStep.addPropertyChangeListener( TestStep.NAME_PROPERTY, propertyChangeListener );
237 				
238 				// insert null entry in existing samples
239 				for( int i = 0; i < samples.size(); i++ )
240 				{
241 					TestSample [] testSamples = samples.get( i );
242 					TestSample[] newSamples = new TestSample[testSamples.length+1];
243 					for( int c = 0; c < testSamples.length; c++ )
244 					{
245 						if( c < index )
246 						{
247 							newSamples[c] = testSamples[c];
248 						}
249 						else
250 						{
251 							newSamples[c+1] = testSamples[c];
252 						}
253 					}
254 					
255 					samples.set( i, newSamples );
256 				}
257 				
258 				fireTableStructureChanged();
259 			}
260 		}
261 
262 		public void testStepRemoved(TestStep testStep, int index)
263 		{
264 			if( testStep.getTestCase() == testCase )
265 			{
266 				testStep.removePropertyChangeListener( propertyChangeListener );
267 				
268 				// remove from samples
269 				for( int i = 0; i < samples.size(); i++ )
270 				{
271 					TestSample [] testSamples = samples.get( i );
272 					TestSample[] newSamples = new TestSample[testSamples.length-1];
273 					for( int c = 0; c < testSamples.length; c++ )
274 					{
275 						if( c < index )
276 						{
277 							newSamples[c] = testSamples[c];
278 						}
279 						else if( c > index )
280 						{
281 							newSamples[c-1] = testSamples[c];
282 						}
283 					}
284 					
285 					samples.set( i, newSamples );
286 				}
287 				
288 				fireTableStructureChanged();
289 			}
290 		}
291 	}
292 
293 	private class InternalPropertyChangeListener implements PropertyChangeListener
294 	{
295 		public void propertyChange(PropertyChangeEvent evt)
296 		{
297 			fireTableStructureChanged();
298 		}}
299 	
300 }