package org.radargun.stages.test; import java.util.Map; import org.radargun.config.Init; import org.radargun.config.Path; import org.radargun.config.Property; import org.radargun.config.PropertyHelper; import org.radargun.config.Stage; import org.radargun.reporting.Report; import org.radargun.stages.AbstractDistStage; import org.radargun.stats.BasicStatistics; import org.radargun.stats.Statistics; import org.radargun.utils.TimeConverter; /** * @author Radim Vansa <rvansa@redhat.com> */ @Stage(doc = "Base for tests.") public abstract class BaseTestStage extends AbstractDistStage { @Property(doc = "Name of the test as used for reporting. Default is 'Test'.") public String testName = "Test"; @Property(doc = "By default, each stage creates a new test. If this property is set to true," + "results are amended to existing test (as iterations). Default is false.") public boolean amendTest = false; @Property(converter = TimeConverter.class, doc = "Benchmark duration. You have to set either this or 'totalNumOperations'.") public long duration = 0; @Property(doc = "The total number of operations to perform during the test. You have to set either this or 'duration'.") public long numOperations = 0; @Property(name = "statistics", doc = "Type of gathered statistics. Default are the 'default' statistics " + "(fixed size memory footprint for each operation).", complexConverter = Statistics.Converter.class) public Statistics statisticsPrototype = new BasicStatistics(); @Property(doc = "Property, which value will be used to identify individual iterations (e.g. num-threads).") public String iterationProperty; @Property(doc = "If this performance condition was not satisfied during this test, the current repeat will be exited. Default is none.", complexConverter = PerformanceCondition.Converter.class) public PerformanceCondition repeatCondition; @Property(doc = "Merge statistics from all threads on single node to one record, instead of storing them all in-memory. Default is false.") public boolean mergeThreadStats = false; protected int testIteration; // first iteration we should use for setting the statistics @Init public void check() { if ((duration > 0 && numOperations > 0) || (duration == 0 && numOperations == 0)) { throw new IllegalArgumentException("Set either the test duration or totalNumOperations."); } if (duration < 0) { throw new IllegalArgumentException("Test duration must be positive."); } if (numOperations < 0) { throw new IllegalArgumentException("Test totalNumOperations must be positive. " + numOperations); } } protected Report.Test getTest(boolean allowExisting) { return getTest(allowExisting, testName); } protected Report.Test getTest(boolean allowExisting, String testName) { if (testName == null || testName.isEmpty()) { log.warn("No test name - results are not recorded"); return null; } else if (testName.equalsIgnoreCase("warmup")) { log.info("This test was executed as a warmup"); return null; } else { Report report = masterState.getReport(); return report.createTest(testName, iterationProperty, allowExisting); } } protected int getTestIteration() { return testIteration; } protected String resolveIterationValue() { if (iterationProperty != null) { Map<String, Path> properties = PropertyHelper.getProperties(getClass(), true, false, true); String propertyString = PropertyHelper.getPropertyString(properties.get(iterationProperty), this); if (propertyString == null) { throw new IllegalStateException("Unable to resolve iteration property '" + iterationProperty + "'."); } return propertyString; } return null; } protected boolean checkRepeatCondition(Statistics aggregated) { if (repeatCondition == null) { return true; } try { if (repeatCondition.evaluate(aggregated)) { log.info("Loop-condition condition was satisfied, continuing the loop."); return true; } else { log.info("Loop-condition condition not satisfied, terminating the loop"); return false; } } catch (Exception e) { log.info("Loop-condition has thrown exception, terminating the loop", e); return false; } } }