io.rainfall.ScenarioRun Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of rainfall-core Show documentation
Show all versions of rainfall-core Show documentation
Rainfall-core is the core of the Rainfall framework
/*
* Copyright (c) 2014-2022 Aurélien Broszniowski
*
* 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 io.rainfall;
import io.rainfall.configuration.ConcurrencyConfig;
import io.rainfall.configuration.DistributedConfig;
import io.rainfall.configuration.ReportingConfig;
import io.rainfall.reporting.PeriodicReporter;
import io.rainfall.reporting.Reporter;
import io.rainfall.statistics.RuntimeStatisticsHolder;
import io.rainfall.statistics.StatisticsPeekHolder;
import io.rainfall.statistics.StatisticsThread;
import io.rainfall.utils.distributed.RainfallClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* @author Aurelien Broszniowski
*/
public class ScenarioRun> {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private Scenario scenario;
//TODO : is it possible to generify?
private Map, Configuration> configurations = new ConcurrentHashMap, Configuration>();
private List assertions = new ArrayList();
private Execution warmup = null;
private List executions = null;
private RuntimeStatisticsHolder statisticsHolder;
public ScenarioRun(final Scenario scenario) {
this.scenario = scenario;
initDefaultConfigurations();
}
private void initDefaultConfigurations() {
this.configurations.put(ConcurrencyConfig.class, new ConcurrencyConfig());
}
// Define warmup time
public ScenarioRun warmup(Execution execution) throws SyntaxException {
if (this.warmup != null) {
throw new SyntaxException("Warmup is already defined.");
}
this.warmup = execution;
return this;
}
// Add executions
public ScenarioRun executed(Execution... executions) throws SyntaxException {
if (this.executions != null) {
throw new SyntaxException("Executions are already defined.");
}
this.executions = Arrays.asList(executions);
return this;
}
// Add configuration
public ScenarioRun config(final Configuration... configs) {
for (Configuration config : configs) {
this.configurations.put(config.getClass(), config);
}
return this;
}
// Add assertion
public ScenarioRun assertion(final Assertion actual, final Assertion expected) {
this.assertions.add(new AssertionEvaluator(actual, expected));
return this;
}
// Start Scenario run
public StatisticsPeekHolder start() {
DistributedConfig distributedConfig = (DistributedConfig)configurations.get(DistributedConfig.class);
if (distributedConfig != null) {
startCluster(distributedConfig);
}
long start = System.currentTimeMillis();
//TODO : add generics ? cast?
ReportingConfig reportingConfig = (ReportingConfig)configurations.get(ReportingConfig.class);
try {
if (warmup != null) {
logger.error("This Warmup syntax is deprecated, please use the syntax: Runner.setUp(scenario)\n" +
" .executed(warmup(during(30, seconds)), during(60, seconds))");
RuntimeStatisticsHolder blankStatisticsHolder = new RuntimeStatisticsHolder(reportingConfig.getResults(), reportingConfig
.getResultsReported(), reportingConfig.getStatisticsCollectors());
logger.info("Executing warmup phase, please wait.");
warmup.execute(blankStatisticsHolder, scenario, configurations, assertions);
}
} catch (TestException e) {
throw new RuntimeException(e);
}
this.statisticsHolder = new RuntimeStatisticsHolder(reportingConfig.getResults(), reportingConfig.getResultsReported(),
reportingConfig.getStatisticsCollectors());
final Set> logReporters = reportingConfig.getLogReporters();
ScheduledExecutorService topOfSecondExecutor = Executors.newScheduledThreadPool(logReporters.size(), new CustomThreadFactory());
StatisticsThread stats = null;
StatisticsPeekHolder peek = null;
try {
stats = new StatisticsThread(statisticsHolder, reportingConfig, getDescription(),
reportingConfig.getStatisticsCollectors());
TimeUnit reportIntervalUnit = reportingConfig.getReportTimeUnit();
long reportIntervalMillis = reportIntervalUnit.toMillis(reportingConfig.getReportInterval());
Calendar myDate = Calendar.getInstance();
myDate.add(Calendar.SECOND, 1);
myDate.set(Calendar.MILLISECOND, 0);
Date afterOneSecond = myDate.getTime();
long delay = afterOneSecond.getTime() - System.currentTimeMillis() - 4;
for (final Reporter logReporter : logReporters) {
if (logReporter instanceof PeriodicReporter) {
topOfSecondExecutor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
final StatisticsPeekHolder statisticsPeekHolder = statisticsHolder.peek();
if (statisticsPeekHolder != null) {
logReporter.report(statisticsPeekHolder);
}
}
}, delay, ((PeriodicReporter)logReporter).getReportingIntervalInMillis(), TimeUnit.MILLISECONDS);
} else {
topOfSecondExecutor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
final StatisticsPeekHolder statisticsPeekHolder = statisticsHolder.peek();
if (statisticsPeekHolder != null) {
logReporter.report(statisticsPeekHolder);
}
}
}, delay, reportIntervalMillis, TimeUnit.MILLISECONDS);
}
}
for (final Execution execution : executions) {
execution.execute(statisticsHolder, scenario, configurations, assertions);
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (stats != null) {
peek = stats.shutdown();
}
long end = System.currentTimeMillis();
topOfSecondExecutor.shutdown();
try {
if (!topOfSecondExecutor.awaitTermination(1000, TimeUnit.MILLISECONDS)) {
topOfSecondExecutor.shutdownNow();
}
} catch (InterruptedException e) {
topOfSecondExecutor.shutdownNow();
}
}
if (distributedConfig != null) {
try {
stopCluster(distributedConfig, reportingConfig);
} catch (TestException e) {
throw new RuntimeException(e);
}
}
return peek;
}
private void startCluster(final DistributedConfig distributedConfig) {
try {
RainfallClient currentClient = new RainfallClient(distributedConfig.getMasterAddress());
distributedConfig.setCurrentClient(currentClient);
currentClient.start();
while (!currentClient.canStart() && currentClient.isAlive()) {
Thread.sleep(250);
}
if (!currentClient.canStart()) {
throw new RuntimeException("Rainfall client could not start", currentClient.getTestException().get());
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
private void stopCluster(final DistributedConfig distributedConfig, final ReportingConfig reportingConfig) throws TestException {
RainfallClient currentClient = distributedConfig.getCurrentClient();
try {
currentClient.sendReport(reportingConfig);
currentClient.join();
logger.debug("[Rainfall client {}] Test sent reports.", currentClient.getClientId());
TestException testException = currentClient.getTestException().get();
if (testException != null) {
throw testException;
}
} catch (InterruptedException e) {
throw new TestException("Rainfall cluster client interrupted", e);
} catch (IOException e) {
throw new TestException("Rainfall cluster client exception", e);
}
}
private List getDescription() {
List description = new ArrayList();
description.addAll(scenario.getDescription());
description.add("");
if (warmup != null) {
description.add("Warmup phase " + this.warmup.toString());
}
description.add("Execution of the scenario : ");
int step = 1;
for (Execution execution : executions) {
description.add(step + ") " + execution.toString());
}
description.add("");
for (Configuration configuration : configurations.values()) {
List descs = configuration.getDescription();
for (String desc : descs) {
description.add(desc);
}
}
return description;
}
public Scenario getScenario() {
return scenario;
}
public Configuration getConfiguration(Class configurationClass) {
return configurations.get(configurationClass);
}
public List getAssertions() {
return assertions;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy