View Javadoc

1   /*
2    *  soapUI, copyright (C) 2006 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of the GNU Lesser General Public License as published by the Free Software Foundation; 
6    *  either version 2.1 of the License, or (at your option) any later version.
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 	public static final class TestSample
177 	{
178 		private final TestStep testStep;
179 		private List<TestStepResult> results;
180 
181 		public TestSample( TestStep testStep )
182 		{
183 			this.testStep = testStep;
184 		}
185 		
186 		public void addTestStepResult( TestStepResult result )
187 		{
188 			if( result.getTestStep() != testStep )
189 				throw new RuntimeException( "Trying to add sample for false testStep [" + result.getTestStep().getName() + "], " +
190 						"expecting [" + testStep.getName() + "]" );
191 			
192 			if( results == null ) 
193 				results = new ArrayList<TestStepResult>();
194 			
195 			results.add( result );
196 		}
197 		
198 		public List<TestStepResult> getResults()
199 		{
200 			return results;
201 		}
202 		
203 		public int getResultCount()
204 		{
205 			return results == null ? 0 : results.size();
206 		}
207 		
208 		public long getResultAverage()
209 		{
210 			if( results == null )
211 				return 0;
212 			
213 			if( results.size() == 1 )
214 				return results.get( 0 ).getTimeTaken();
215 			
216 			long sum = 0;
217 			for( TestStepResult result : results )
218 				sum += result.getTimeTaken();
219 			
220 			return sum / results.size();
221 		}
222 	}
223 	
224 	private class InternalTestSuiteListener extends TestSuiteListenerAdapter
225 	{
226 		public void testStepAdded(TestStep testStep, int index)
227 		{
228 			if( testStep.getTestCase() == testCase )
229 			{
230 				testStep.addPropertyChangeListener( TestStep.NAME_PROPERTY, propertyChangeListener );
231 				
232 				// insert null entry in existing samples
233 				for( int i = 0; i < samples.size(); i++ )
234 				{
235 					TestSample [] testSamples = samples.get( i );
236 					TestSample[] newSamples = new TestSample[testSamples.length+1];
237 					for( int c = 0; c < testSamples.length; c++ )
238 					{
239 						if( c < index )
240 						{
241 							newSamples[c] = testSamples[c];
242 						}
243 						else
244 						{
245 							newSamples[c+1] = testSamples[c];
246 						}
247 					}
248 					
249 					samples.set( i, newSamples );
250 				}
251 				
252 				fireTableStructureChanged();
253 			}
254 		}
255 
256 		public void testStepRemoved(TestStep testStep, int index)
257 		{
258 			if( testStep.getTestCase() == testCase )
259 			{
260 				testStep.removePropertyChangeListener( propertyChangeListener );
261 				
262 				// remove from samples
263 				for( int i = 0; i < samples.size(); i++ )
264 				{
265 					TestSample [] testSamples = samples.get( i );
266 					TestSample[] newSamples = new TestSample[testSamples.length-1];
267 					for( int c = 0; c < testSamples.length; c++ )
268 					{
269 						if( c < index )
270 						{
271 							newSamples[c] = testSamples[c];
272 						}
273 						else if( c > index )
274 						{
275 							newSamples[c-1] = testSamples[c];
276 						}
277 					}
278 					
279 					samples.set( i, newSamples );
280 				}
281 				
282 				fireTableStructureChanged();
283 			}
284 		}
285 	}
286 
287 	private class InternalPropertyChangeListener implements PropertyChangeListener
288 	{
289 		public void propertyChange(PropertyChangeEvent evt)
290 		{
291 			fireTableStructureChanged();
292 		}}
293 	
294 }