BuildResultsElement.java revision 402794e73aed8611d62eb4b01cd155e2d76fcb87
1/*******************************************************************************
2 * Copyright (c) 2000, 2009 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 *     IBM Corporation - initial API and implementation
10 *******************************************************************************/
11package org.eclipse.test.internal.performance.results.model;
12
13import java.util.ArrayList;
14import java.util.List;
15import java.util.Vector;
16
17import org.eclipse.test.internal.performance.data.Dim;
18import org.eclipse.test.internal.performance.eval.StatisticsUtil;
19import org.eclipse.test.internal.performance.results.db.*;
20import org.eclipse.test.internal.performance.results.utils.Util;
21import org.eclipse.ui.views.properties.ComboBoxPropertyDescriptor;
22import org.eclipse.ui.views.properties.IPropertyDescriptor;
23import org.eclipse.ui.views.properties.PropertyDescriptor;
24import org.eclipse.ui.views.properties.TextPropertyDescriptor;
25
26public class BuildResultsElement extends ResultsElement {
27
28	// Property descriptors
29    static final String P_ID_BUILD_DATE = "BuildResultsElement.date"; //$NON-NLS-1$
30    static final String P_ID_BUILD_BASELINE = "BuildResultsElement.baseline"; //$NON-NLS-1$
31    static final String P_ID_BUILD_COMMENT = "BuildResultsElement.comment"; //$NON-NLS-1$
32    static final String P_ID_BUILD_SUMMARY_KIND = "BuildResultsElement.summarykind"; //$NON-NLS-1$
33    static final String P_ID_BUILD_IS_BASELINE = "BuildResultsElement.isbaseline"; //$NON-NLS-1$
34    static final String P_ID_BUILD_FAILURE = "BuildResultsElement.failure"; //$NON-NLS-1$
35    static final String P_ID_BUILD_DELTA = "BuildResultsElement.delta"; //$NON-NLS-1$
36    static final String P_ID_BUILD_ERROR = "BuildResultsElement.error"; //$NON-NLS-1$
37    static final String P_ID_BUILD_TTEST = "BuildResultsElement.ttest"; //$NON-NLS-1$
38
39    static final String P_STR_BUILD_DATE = "date"; //$NON-NLS-1$
40    static final String P_STR_BUILD_COMMENT = "comment"; //$NON-NLS-1$
41    static final String P_STR_BUILD_SUMMARY_KIND = "summary kind"; //$NON-NLS-1$
42    static final String P_STR_BUILD_IS_BASELINE = "is baseline"; //$NON-NLS-1$
43    static final String P_STR_BUILD_BASELINE = "baseline"; //$NON-NLS-1$
44    static final String P_STR_BUILD_FAILURE = "failure"; //$NON-NLS-1$
45    static final String P_STR_BUILD_DELTA = "delta with baseline"; //$NON-NLS-1$
46    static final String P_STR_BUILD_ERROR = "delta error"; //$NON-NLS-1$
47    static final String P_STR_BUILD_TTEST = "student's ttest"; //$NON-NLS-1$
48
49	private static final TextPropertyDescriptor BUILD_DATE_DESCRIPTOR = new TextPropertyDescriptor(P_ID_BUILD_DATE, P_STR_BUILD_DATE);
50	private static final TextPropertyDescriptor BUILD_COMMENT_DESCRIPTOR = new TextPropertyDescriptor(P_ID_BUILD_COMMENT, P_STR_BUILD_COMMENT);
51	private static final TextPropertyDescriptor BUILD_SUMMARY_DESCRIPTOR = new TextPropertyDescriptor(P_ID_BUILD_SUMMARY_KIND, P_STR_BUILD_SUMMARY_KIND);
52	private static final PropertyDescriptor BUILD_IS_BASELINE_DESCRIPTOR = new PropertyDescriptor(P_ID_BUILD_IS_BASELINE, P_STR_BUILD_IS_BASELINE);
53	private static final PropertyDescriptor BUILD_BASELINE_DESCRIPTOR = new PropertyDescriptor(P_ID_BUILD_BASELINE, P_STR_BUILD_BASELINE);
54	private static final TextPropertyDescriptor BUILD_TEST_FAILURE_DESCRIPTOR = new TextPropertyDescriptor(P_ID_BUILD_FAILURE, P_STR_BUILD_FAILURE);
55	private static final PropertyDescriptor BUILD_TEST_DELTA_DESCRIPTOR = new PropertyDescriptor(P_ID_BUILD_DELTA, P_STR_BUILD_DELTA);
56	private static final PropertyDescriptor BUILD_TEST_ERROR_DESCRIPTOR = new PropertyDescriptor(P_ID_BUILD_ERROR, P_STR_BUILD_ERROR);
57	private static final PropertyDescriptor BUILD_STUDENTS_TTEST_DESCRIPTOR = new PropertyDescriptor(P_ID_BUILD_TTEST, P_STR_BUILD_TTEST);
58
59    private static Vector DESCRIPTORS;
60    static Vector initDescriptors(int status) {
61		DESCRIPTORS = new Vector();
62		// Status category
63		DESCRIPTORS.add(getInfosDescriptor(status));
64		DESCRIPTORS.add(getWarningsDescriptor(status));
65		DESCRIPTORS.add(ERROR_DESCRIPTOR);
66		ERROR_DESCRIPTOR.setCategory("Status");
67		// Results category
68        DESCRIPTORS.add(BUILD_DATE_DESCRIPTOR);
69		BUILD_DATE_DESCRIPTOR.setCategory("Results");
70        DESCRIPTORS.add(BUILD_BASELINE_DESCRIPTOR);
71		BUILD_BASELINE_DESCRIPTOR.setCategory("Results");
72        DESCRIPTORS.add(BUILD_COMMENT_DESCRIPTOR);
73		BUILD_COMMENT_DESCRIPTOR.setCategory("Results");
74        DESCRIPTORS.add(BUILD_SUMMARY_DESCRIPTOR);
75		BUILD_SUMMARY_DESCRIPTOR.setCategory("Results");
76        DESCRIPTORS.add(BUILD_IS_BASELINE_DESCRIPTOR);
77		BUILD_IS_BASELINE_DESCRIPTOR.setCategory("Results");
78        DESCRIPTORS.add(BUILD_TEST_FAILURE_DESCRIPTOR);
79		BUILD_TEST_FAILURE_DESCRIPTOR.setCategory("Results");
80        DESCRIPTORS.add(BUILD_TEST_DELTA_DESCRIPTOR);
81		BUILD_TEST_DELTA_DESCRIPTOR.setCategory("Results");
82        DESCRIPTORS.add(BUILD_TEST_ERROR_DESCRIPTOR);
83		BUILD_TEST_ERROR_DESCRIPTOR.setCategory("Results");
84        DESCRIPTORS.add(BUILD_STUDENTS_TTEST_DESCRIPTOR);
85		BUILD_STUDENTS_TTEST_DESCRIPTOR.setCategory("Results");
86		// Survey category
87		DESCRIPTORS.add(COMMENT_DESCRIPTOR);
88		COMMENT_DESCRIPTOR.setCategory("Survey");
89        return DESCRIPTORS;
90	}
91    static ComboBoxPropertyDescriptor getInfosDescriptor(int status) {
92		List list = new ArrayList();
93		if ((status & SMALL_VALUE) != 0) {
94			list.add("This test and/or its variation has a small value, hence it may not be necessary to spend time on fixing it if a regression occurs");
95		}
96		if ((status & STUDENT_TTEST) != 0) {
97			list.add("The student-t test error on this test is over the threshold");
98		}
99		String[] infos = new String[list.size()];
100		if (list.size() > 0) {
101			list.toArray(infos);
102		}
103		ComboBoxPropertyDescriptor infoDescriptor = new ComboBoxPropertyDescriptor(P_ID_STATUS_INFO, P_STR_STATUS_INFO, infos);
104		infoDescriptor.setCategory("Status");
105		return infoDescriptor;
106	}
107    static PropertyDescriptor getWarningsDescriptor(int status) {
108		List list = new ArrayList();
109		if ((status & BIG_ERROR) != 0) {
110			list.add("The error on this test is over the 3% threshold, hence its result may not be really reliable");
111		}
112		if ((status & NOT_RELIABLE) != 0) {
113			list.add("The results history shows that the variation of its delta is over 20%, hence its result is surely not reliable");
114		}
115		if ((status & NOT_STABLE) != 0) {
116			list.add("The results history shows that the variation of its delta is between 10% and 20%, hence its result may not be really reliable");
117		}
118		if ((status & NO_BASELINE) != 0) {
119			list.add("There's no baseline to compare with");
120		}
121		if ((status & SINGLE_RUN) != 0) {
122			list.add("This test has only one run, hence no error can be computed to verify if it's stable enough to be reliable");
123		}
124		String[] warnings = new String[list.size()];
125		if (list.size() > 0) {
126			list.toArray(warnings);
127		}
128		ComboBoxPropertyDescriptor warningDescriptor = new ComboBoxPropertyDescriptor(P_ID_STATUS_WARNING, P_STR_STATUS_WARNING, warnings);
129		warningDescriptor.setCategory("Status");
130		return warningDescriptor;
131    }
132    static Vector getDescriptors() {
133    	return DESCRIPTORS;
134	}
135
136	    // Model info
137	boolean important;
138	boolean milestone;
139
140public BuildResultsElement(AbstractResults results, ResultsElement parent) {
141	super(results, parent);
142	initInfo();
143}
144
145public BuildResultsElement(String name, ResultsElement parent) {
146	super(name, parent);
147	initInfo();
148}
149
150public int compareTo(Object o) {
151	if (o instanceof BuildResultsElement && getName() != null) {
152		BuildResultsElement element = (BuildResultsElement)o;
153		if (element.getName() != null) {
154			String buildDate = Util.getBuildDate(element.name);
155			return Util.getBuildDate(this.name).compareTo(buildDate);
156		}
157	}
158	return super.compareTo(o);
159}
160
161ResultsElement createChild(AbstractResults testResults) {
162	return null;
163}
164
165private BuildResults getBuildResults() {
166	return (BuildResults) this.results;
167}
168
169public Object[] getChildren(Object o) {
170	if (this.results == null) {
171		return new Object[0];
172	}
173	if (this.children == null) {
174		initChildren();
175	}
176	return this.children;
177}
178
179public Object getEditableValue() {
180	if (this.results == null)  {
181		return "Build "+this.name;
182	}
183	return this.results.toString();
184}
185
186/* (non-Javadoc)
187 * @see org.eclipse.ui.views.properties.IPropertySource#getPropertyDescriptors()
188 */
189public IPropertyDescriptor[] getPropertyDescriptors() {
190	Vector descriptors = getDescriptors();
191	if (descriptors == null) {
192		descriptors = initDescriptors(getStatus());
193	}
194	int size = descriptors.size();
195	IPropertyDescriptor[] descriptorsArray = new IPropertyDescriptor[size];
196	descriptorsArray[0] = getInfosDescriptor(getStatus());
197	descriptorsArray[1] = getWarningsDescriptor(getStatus());
198	for (int i=2; i<size; i++) {
199		descriptorsArray[i] = (IPropertyDescriptor) descriptors.get(i);
200	}
201	return descriptorsArray;
202}
203
204/* (non-Javadoc)
205 * @see org.eclipse.ui.views.properties.IPropertySource#getPropertyValue(java.lang.Object)
206 */
207public Object getPropertyValue(Object propKey) {
208	BuildResults buildResults = getBuildResults();
209	if (buildResults != null) {
210		ConfigResults configResults = (ConfigResults) buildResults.getParent();
211		BuildResults baselineResults = configResults.getBaselineBuildResults(buildResults.getName());
212	    if (propKey.equals(P_ID_BUILD_DATE))
213	        return buildResults.getDate();
214	    if (propKey.equals(P_ID_BUILD_COMMENT))
215	        return buildResults.getComment();
216	    if (propKey.equals(P_ID_BUILD_SUMMARY_KIND)) {
217	    	int summaryKind = buildResults.getSummaryKind();
218			if (summaryKind == 1) {
219	    		return "global";
220	    	}
221	    	if (summaryKind >= 0) {
222	    		return "component";
223	    	}
224	    	return "none";
225	    }
226	    if (propKey.equals(P_ID_BUILD_IS_BASELINE))
227	        return new Boolean(buildResults.isBaseline());
228	    if (propKey.equals(P_ID_BUILD_FAILURE))
229	        return buildResults.getFailure();
230	    if (baselineResults != null) {
231		    if (propKey.equals(P_ID_BUILD_BASELINE)) {
232		        return baselineResults.getName();
233		    }
234			double buildValue = buildResults.getValue();
235			double baselineValue = baselineResults.getValue();
236			double delta = (baselineValue - buildValue) / baselineValue;
237			if (Double.isNaN(delta)) {
238			    if (propKey.equals(P_ID_BUILD_DELTA) || propKey.equals(P_ID_BUILD_ERROR)) {
239			        return new Double(Double.NaN);
240			    }
241			} else  if (propKey.equals(P_ID_BUILD_DELTA)) {
242				return new Double(delta);
243		    } else {
244				long baselineCount = baselineResults.getCount();
245				long currentCount = buildResults.getCount();
246				if (baselineCount > 1 && currentCount > 1) {
247					if (propKey.equals(P_ID_BUILD_TTEST)) {
248						double ttestValue = Util.computeTTest(baselineResults, buildResults);
249						int degreeOfFreedom = (int) (baselineResults.getCount()+buildResults.getCount()-2);
250						if (ttestValue >= 0 && StatisticsUtil.getStudentsT(degreeOfFreedom, StatisticsUtil.T90) >= ttestValue) {
251							return new Double(ttestValue);
252						}
253					}
254				    if (propKey.equals(P_ID_BUILD_ERROR)) {
255						double baselineError = baselineResults.getError();
256						double currentError = buildResults.getError();
257						double error = Double.isNaN(baselineError)
258								? currentError / baselineValue
259								: Math.sqrt(baselineError*baselineError + currentError*currentError) / baselineValue;
260				        return new Double(error);
261				    }
262				} else {
263				    if (propKey.equals(P_ID_BUILD_ERROR))
264				        return new Double(-1);
265				}
266			}
267	    }
268	}
269	if (propKey.equals(P_ID_STATUS_ERROR)) {
270		if ((getStatus() & BIG_DELTA) != 0) {
271			return "The delta on this test is over the 10% threshold, hence may indicate a possible regression.";
272		}
273	}
274	return super.getPropertyValue(propKey);
275}
276
277/**
278 * Return the statistics of the build along its history.
279 *
280 * @return An array of double built as follows:
281 * <ul>
282 * <li>0:	numbers of values</li>
283 * <li>1:	mean of values</li>
284 * <li>2:	standard deviation of these values</li>
285 * <li>3:	coefficient of variation of these values</li>
286 * </ul>
287 */
288double[] getStatistics() {
289	if (this.statistics  == null) {
290		this.statistics = ((ConfigResults)getBuildResults().getParent()).getStatistics(Util.BASELINE_BUILD_PREFIXES);
291	}
292	return this.statistics;
293}
294
295void initChildren() {
296	BuildResults buildResults = (BuildResults) this.results;
297	Dim[] dimensions = buildResults.getDimensions();
298	int length = dimensions.length;
299	this.children = new DimResultsElement[length];
300	for (int i=0; i<length; i++) {
301		this.children[i] = new DimResultsElement(this.results, this, dimensions[i]);
302	}
303}
304
305/*
306 * Init information
307 */
308void initInfo() {
309	this.milestone = Util.isMilestone(getName());
310	this.important = this.milestone || Util.getNextMilestone(this.name) == null;
311}
312
313void initStatus() {
314	if (this.results == null) {
315		if (this.parent.isInitialized()) {
316			if (((PerformanceResultsElement) this.parent).hasRead(this)) {
317				this.status = READ;
318			} else {
319				this.status = UNREAD;
320			}
321		} else {
322			this.status = UNKNOWN;
323		}
324	} else if (getBuildResults().isBaseline()) {
325		// TODO (frederic) report high variation in baseline results along history
326		this.status = READ;
327	} else {
328		initStatus(getBuildResults());
329	}
330}
331
332/**
333 * Returns whether the build is important to be shown.
334 * This is the case for milestone builds or for the last builds.
335 *
336 * @return <code>true</code>  or <code>false</code> .
337 */
338public boolean isImportant() {
339	return this.important;
340}
341
342/**
343 * Returns whether the build is a milestone one or not.
344 *
345 * @return <code>true</code>  or <code>false</code> .
346 */
347public boolean isMilestone() {
348	return this.milestone;
349}
350
351public boolean isRead() {
352	return (getStatus()  & STATE_MASK) == READ;
353}
354
355public boolean isUnknown() {
356	return (getStatus()  & STATE_MASK) == UNKNOWN;
357}
358
359/* (non-Javadoc)
360 * @see java.lang.Object#toString()
361 */
362public String toString() {
363	return getName();
364}
365public boolean isBefore(String build) {
366	if (this.results != null) {
367		return Util.getBuildDate(this.name).compareTo(Util.getBuildDate(build)) <= 0;
368	}
369	return true;
370}
371
372}
373