/*
* -----------------------------------------------------------------------\
* PerfCake
*
* Copyright (C) 2010 - 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* -----------------------------------------------------------------------/
*/
package org.perfcake.reporting;
import org.perfcake.PerfCakeConst;
import org.perfcake.PerfCakeException;
import org.perfcake.RunInfo;
import org.perfcake.TestSetup;
import org.perfcake.TestUtil;
import org.perfcake.common.Period;
import org.perfcake.common.PeriodType;
import org.perfcake.reporting.destination.Destination;
import org.perfcake.reporting.destination.c3chart.C3ChartData;
import org.perfcake.reporting.destination.c3chart.C3ChartDataFile;
import org.perfcake.reporting.destination.c3chart.C3ChartFactory;
import org.perfcake.reporting.reporter.Reporter;
import org.perfcake.util.ObjectFactory;
import org.apache.commons.io.FileUtils;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Properties;
import java.util.Random;
/**
* Verifies integration of ResponseTimeHistogramReporter and ChartDestination.
*
* @author <a href="mailto:marvenec@gmail.com">Martin Večeřa</a>
*/
@Test(groups = "integration")
public class HistogramChartIntegrationTest extends TestSetup {
@DataProvider(name = "attributes")
public Object[][] attributesDataProvider() {
return new Object[][] {
{ "*", false, true, 101, 5 },
{ "*, " + PerfCakeConst.WARM_UP_TAG, true, true, 142, 5 },
{ "perc*", false, false, 101, 5 },
{ "perc*, " + PerfCakeConst.WARM_UP_TAG, true, false, 142, 5 },
{ "Threads", false, true, 101, 2 },
{ "Threads, " + PerfCakeConst.WARM_UP_TAG, true, true, 142, 3 },
{ PerfCakeConst.WARM_UP_TAG, false, false, 0, 1 },
};
}
@Test(dataProvider = "attributes")
public void integrationTest(final String attributesRequired, final boolean hasWarmUp, final boolean hasThreadsAttribute, final int records, final int minAttributes) throws ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException, PerfCakeException, IOException {
final String dir = "target/hdr-charts";
final Properties reporterProperties = TestUtil.props("detail", "1", "precision", "1", "maxExpectedValue", "100", "correctionMode", "user",
"expectedValue", "2");
final Properties destinationProperties = TestUtil.props("yAxis", "HDR Response Time", "group", "hdr_resp", "name", "HDR Response Time (25 Threads)",
"attributes", attributesRequired, "autoCombine", "false", "chartHeight", "1000", "outputDir", dir);
final RunInfo ri = new RunInfo(new Period(PeriodType.ITERATION, 10000));
final Reporter r = (Reporter) ObjectFactory.summonInstance("org.perfcake.reporting.reporter.ResponseTimeHistogramReporter", reporterProperties);
final Destination d = (Destination) ObjectFactory.summonInstance("org.perfcake.reporting.destination.ChartDestination", destinationProperties);
final Random rnd = new Random();
r.setRunInfo(ri);
r.registerDestination(d, new Period(PeriodType.ITERATION, 100));
ri.addTag(PerfCakeConst.WARM_UP_TAG);
ri.start();
r.start();
while (ri.isRunning()) {
FakeMeasurementUnit mu = new FakeMeasurementUnit(ri.getNextIteration());
mu.setTime(rnd.nextInt(10000) > 9990 ? rnd.nextInt(10) + 6 : 2);
mu.startMeasure();
mu.appendResult(PerfCakeConst.THREADS_TAG, "10");
mu.stopMeasure();
if (ri.getIteration() == 4000 && ri.hasTag(PerfCakeConst.WARM_UP_TAG)) {
ri.removeTag(PerfCakeConst.WARM_UP_TAG);
ri.reset();
r.reset();
}
r.report(mu);
}
r.stop();
final C3ChartDataFile c3desc = C3ChartFactory.readChartMetaData(dir);
final C3ChartData c3data = C3ChartFactory.readChartData(dir);
// there are always enough attributes
Assert.assertTrue(c3desc.getChart().getAttributes().size() >= minAttributes);
// expect perc_warmUp
Assert.assertEquals(c3desc.getChart().getAttributes().stream().anyMatch(attribute -> attribute.startsWith("perc") && attribute.endsWith("_" + PerfCakeConst.WARM_UP_TAG)), attributesRequired.contains("*") && hasWarmUp);
// expect Threads
Assert.assertEquals(c3desc.getChart().getAttributes().contains("Threads"), hasThreadsAttribute);
// expect Threads_warmUp
Assert.assertEquals(c3desc.getChart().getAttributes().contains("Threads_" + PerfCakeConst.WARM_UP_TAG), hasThreadsAttribute && hasWarmUp);
// expect correct number of records depending on whether warmUp was recorded
// we can be tolerant as on slow running systems, we might get more or less records
Assert.assertTrue(c3data.getData().size() >= records - 2 && c3data.getData().size() <= records + 2);
FileUtils.deleteDirectory(new File(dir));
}
}