/******************************************************************************* * Copyright (c) 2000, 2015 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.text.tests.performance; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Locale; import org.eclipse.jdt.text.tests.JdtTextTestPlugin; import org.eclipse.test.performance.Dimension; import org.eclipse.test.performance.Performance; import org.eclipse.test.performance.PerformanceMeter; import org.eclipse.core.runtime.Platform; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.ui.texteditor.spelling.SpellingService; import org.eclipse.ui.editors.text.EditorsUI; import junit.extensions.TestSetup; import junit.framework.Test; import junit.framework.TestCase; /** * Superclass of Text performance test cases. * * @since 3.1 */ public class TextPerformanceTestCase extends TestCase { public static class DebugSetup extends TestSetup { public DebugSetup(Test test) { super(test); } @Override protected void setUp() throws Exception { DEBUG= true; } @Override protected void tearDown() throws Exception { DEBUG= false; } } static boolean DEBUG= false; private static final SimpleDateFormat DATE_FORMAT= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS Z", Locale.US); /** containing plug-in id */ private static final String PLUGIN_ID= JdtTextTestPlugin.PLUGIN_ID; /** boolean option, a value of <code>"true"</code> enables overriding of the number of runs */ private static final String OVERRIDE_RUNS_OPTION= "/debug/performance/OverrideRuns"; /** integer option, its value overrides the number of warm-up runs */ private static final String OVERRIDE_WARM_UP_RUNS_OPTION= "/debug/performance/OverrideWarmUpRuns"; /** integer option, its value overrides the number of measured runs */ private static final String OVERRIDE_MEASURED_RUNS_OPTION= "/debug/performance/OverrideMeasuredRuns"; /** <code>true</code> iff the number of runs should be overridden */ private static final boolean OVERRIDE_RUNS= Boolean.toString(true).equals(Platform.getDebugOption(PLUGIN_ID + OVERRIDE_RUNS_OPTION)); /** overridden number of warm-up runs */ private static final int OVERRIDE_WARM_UP_RUNS= intValueOf(Platform.getDebugOption(PLUGIN_ID + OVERRIDE_WARM_UP_RUNS_OPTION), 2); /** overridden number of measured runs */ private static final int OVERRIDE_MEASURED_RUNS= intValueOf(Platform.getDebugOption(PLUGIN_ID + OVERRIDE_MEASURED_RUNS_OPTION), 2); /** custom number of warm-up runs */ private int fCustomWarmUpRuns= -1; /** custom number of measured runs */ private int fCustomMeasuredRuns= -1; /** created performance meters */ private List<PerformanceMeter> fPerformanceMeters; /** {@link KeyboardProbe} singleton */ private static KeyboardProbe fgKeyboardProbe; /** base scenario id */ private String fBaseScenarioId; /* * @see TestCase#TestCase() */ public TextPerformanceTestCase() { super(); } /* * @see TestCase#TestCase(String) */ public TextPerformanceTestCase(String name) { super(name); } /* * @see junit.framework.TestCase#setUp() * @since 3.1 */ @Override protected void setUp() throws Exception { super.setUp(); EditorTestHelper.forceFocus(); EditorsUI.getPreferenceStore().putValue(SpellingService.PREFERENCE_SPELLING_ENABLED, IPreferenceStore.FALSE); if (DEBUG) System.out.println(DATE_FORMAT.format(new Date()) + ": " + getClass().getName() + "." + getName()); } /* * @see junit.framework.TestCase#tearDown() */ @Override protected void tearDown() throws Exception { super.tearDown(); EditorsUI.getPreferenceStore().setToDefault(SpellingService.PREFERENCE_SPELLING_ENABLED); if (fPerformanceMeters != null) for (Iterator<PerformanceMeter> iter= fPerformanceMeters.iterator(); iter.hasNext();) iter.next().dispose(); // if (DEBUG) // System.out.println(DATE_FORMAT.format(new Date()) + ": tearDown " + getClass().getName() + "." + getName()); } /** * @return number of warm-up runs, must have been set before */ protected final int getWarmUpRuns() { assertTrue(fCustomWarmUpRuns >= 0); if (OVERRIDE_RUNS) return OVERRIDE_WARM_UP_RUNS; return fCustomWarmUpRuns; } /** * Sets the number of warm-up runs. Can be overridden. * * @param runs number of warm-up runs */ protected final void setWarmUpRuns(int runs) { fCustomWarmUpRuns= runs; } /** * @return number of measured runs, must have been set before */ protected final int getMeasuredRuns() { assertTrue(fCustomMeasuredRuns >= 0); if (OVERRIDE_RUNS) return OVERRIDE_MEASURED_RUNS; return fCustomMeasuredRuns; } /** * Sets the number of measured runs. Can be overridden. * * @param runs number of measured runs */ protected final void setMeasuredRuns(int runs) { fCustomMeasuredRuns= runs; } /** * @return the default scenario id for this test */ protected final String getDefaultScenarioId() { return Performance.getDefault().getDefaultScenarioId(this); } /** * Returns the base scenario id for this test which has the default * scenario id as its default. * * @return the base scenario id */ protected final String getBaseScenarioId() { if (fBaseScenarioId == null) fBaseScenarioId= Performance.getDefault().getDefaultScenarioId(this); return fBaseScenarioId; } /** * Sets the base scenario id for this test. * * @param baseScenarioId the base scenario id */ protected final void setBaseScenarioId(String baseScenarioId) { fBaseScenarioId= baseScenarioId; } /** * Create a performance meter with the base scenario id. The * performance meter will be disposed on {@link #tearDown()}. * * @return the created performance meter */ protected PerformanceMeter createPerformanceMeter() { return createPerformanceMeter(""); } /** * Create a performance meter with the given sub-scenario id. The * performance meter will be disposed on {@link #tearDown()}. * * @param subScenarioId the sub-scenario id * @return the created performance meter */ protected final PerformanceMeter createPerformanceMeter(String subScenarioId) { return internalCreatePerformanceMeter(getBaseScenarioId() + subScenarioId); } /** * Create a performance meter with the base scenario id and mark the * scenario to be included into the component performance summary. The * summary shows the given dimension of the scenario and labels the * scenario with the short name. The performance meter will be disposed * on {@link #tearDown()}. * * @param shortName a short (shorter than 40 characters) descriptive * name of the scenario * @param dimension the dimension to show in the summary * @return the created performance meter */ protected final PerformanceMeter createPerformanceMeterForSummary(String shortName, Dimension dimension) { return createPerformanceMeterForSummary("", shortName, dimension); } /** * Create a performance meter with the given sub-scenario id and mark * the scenario to be included into the component performance summary. * The summary shows the given dimension of the scenario and labels the * scenario with the short name. The performance meter will be disposed * on {@link #tearDown()}. * * @param subScenarioId the sub-scenario id * @param shortName a short (shorter than 40 characters) descriptive * name of the scenario * @param dimension the dimension to show in the summary * @return the created performance meter */ protected final PerformanceMeter createPerformanceMeterForSummary(String subScenarioId, String shortName, Dimension dimension) { PerformanceMeter performanceMeter= createPerformanceMeter(subScenarioId); Performance.getDefault().tagAsSummary(performanceMeter, shortName, dimension); return performanceMeter; } /** * Create a performance meter with the base scenario id and mark the * scenario to be included into the global performance summary. The * summary shows the given dimension of the scenario and labels the * scenario with the short name. The performance meter will be disposed * on {@link #tearDown()}. * * @param shortName a short (shorter than 40 characters) descriptive * name of the scenario * @param dimension the dimension to show in the summary * @return the created performance meter */ protected final PerformanceMeter createPerformanceMeterForGlobalSummary(String shortName, Dimension dimension) { return createPerformanceMeterForGlobalSummary("", shortName, dimension); } /** * Create a performance meter with the given sub-scenario id and mark * the scenario to be included into the global performance summary. The * summary shows the given dimension of the scenario and labels the * scenario with the short name. The performance meter will be disposed * on {@link #tearDown()}. * * @param subScenarioId the sub-scenario id * @param shortName a short (shorter than 40 characters) descriptive * name of the scenario * @param dimension the dimension to show in the summary * @return the created performance meter */ protected final PerformanceMeter createPerformanceMeterForGlobalSummary(String subScenarioId, String shortName, Dimension dimension) { PerformanceMeter performanceMeter= createPerformanceMeter(subScenarioId); Performance.getDefault().tagAsGlobalSummary(performanceMeter, shortName, dimension); return performanceMeter; } /** * Create an invocation counting performance meter that will count the * number of invocations of the given methods. The performance meter * will be disposed on {@link #tearDown()}. * * @param methods the methods whose invocations will be counted * @return the created performance meter */ protected final InvocationCountPerformanceMeter createInvocationCountPerformanceMeter(Method[] methods) { return createInvocationCountPerformanceMeter("", methods); } /** * Create an invocation counting performance meter with the given * sub-scenario id. The performance meter will count the number of * invocations of the given methods. The performance meter will be * disposed on {@link #tearDown()}. * * @param subScenarioId the sub-scenario id * @param methods the methods whose invocations will be counted * @return the created performance meter */ protected final InvocationCountPerformanceMeter createInvocationCountPerformanceMeter(String subScenarioId, Method[] methods) { InvocationCountPerformanceMeter performanceMeter= new InvocationCountPerformanceMeter(getBaseScenarioId() + subScenarioId, methods); addPerformanceMeter(performanceMeter); return performanceMeter; } /** * Create an invocation counting performance meter that will count the * number of invocations of the given constructors. The performance meter * will be disposed on {@link #tearDown()}. * * @param constructors the constructors whose invocations will be counted * @return the created performance meter */ protected final InvocationCountPerformanceMeter createInvocationCountPerformanceMeter(Constructor<?>[] constructors) { return createInvocationCountPerformanceMeter("", constructors); } /** * Create an invocation counting performance meter with the given * sub-scenario id. The performance meter will count the number of * invocations of the given constructors. The performance meter will be * disposed on {@link #tearDown()}. * * @param subScenarioId the sub-scenario id * @param constructors the constructors whose invocations will be counted * @return the created performance meter */ protected final InvocationCountPerformanceMeter createInvocationCountPerformanceMeter(String subScenarioId, Constructor<?>[] constructors) { InvocationCountPerformanceMeter performanceMeter= new InvocationCountPerformanceMeter(getBaseScenarioId() + subScenarioId, constructors); addPerformanceMeter(performanceMeter); return performanceMeter; } /** * Commits the measurements captured by all performance meters created * through one of this class' factory methods. */ protected final void commitAllMeasurements() { if (fPerformanceMeters != null) for (Iterator<PerformanceMeter> iter= fPerformanceMeters.iterator(); iter.hasNext();) iter.next().commit(); } /** * Asserts default properties of the measurements captured by the given * performance meter. * * @param performanceMeter the performance meter * @throws RuntimeException if the properties do not hold */ protected final void assertPerformance(PerformanceMeter performanceMeter) { Performance.getDefault().assertPerformance(performanceMeter); } /** * Asserts default properties of the measurements captured by all * performance meters created through one of this class' factory * methods. * * @throws RuntimeException if the properties do not hold */ protected final void assertAllPerformance() { if (fPerformanceMeters != null) for (Iterator<PerformanceMeter> iter= fPerformanceMeters.iterator(); iter.hasNext();) assertPerformance(iter.next()); } /** * Returns the null performance meter singleton. * * @return the null performance meter singleton */ protected static final PerformanceMeter getNullPerformanceMeter() { return Performance.getDefault().getNullPerformanceMeter(); } /** * Returns the keyboard probe singleton. * * @return the keyboard probe singleton. */ protected static final KeyboardProbe getKeyboardProbe() { if (fgKeyboardProbe == null) { fgKeyboardProbe= new KeyboardProbe(); fgKeyboardProbe.initialize(); } return fgKeyboardProbe; } /* * @see PerformanceTestCase#setComment(int, String) * @since 3.1 */ protected final void explainDegradation(String explanation, PerformanceMeter performanceMeter) { Performance performance= Performance.getDefault(); performance.setComment(performanceMeter, Performance.EXPLAINS_DEGRADATION_COMMENT, explanation); } /** * Create a performance meter with the given scenario id. The * performance meter will be disposed on {@link #tearDown()}. * * @param scenarioId the scenario id * @return the created performance meter */ private PerformanceMeter internalCreatePerformanceMeter(String scenarioId) { PerformanceMeter performanceMeter= Performance.getDefault().createPerformanceMeter(scenarioId); addPerformanceMeter(performanceMeter); return performanceMeter; } /** * Add the given performance meter to the managed performance meters. * * @param performanceMeter the performance meter */ private void addPerformanceMeter(PerformanceMeter performanceMeter) { if (fPerformanceMeters == null) fPerformanceMeters= new ArrayList<>(); fPerformanceMeters.add(performanceMeter); } /** * Returns the integer value of the given string unless the string * cannot be interpreted as such, in this case the given default is * returned. * * @param stringValue the string to be interpreted as integer * @param defaultValue the default integer value * @return the integer value */ private static int intValueOf(String stringValue, int defaultValue) { try { if (stringValue != null) return Integer.valueOf(stringValue).intValue(); } catch (NumberFormatException e) { // use default } return defaultValue; } }