/*
* -----------------------------------------------------------------------\
* 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.scenario;
import org.perfcake.PerfCakeException;
import org.perfcake.message.MessageTemplate;
import org.perfcake.message.correlator.Correlator;
import org.perfcake.message.generator.MessageGenerator;
import org.perfcake.message.receiver.Receiver;
import org.perfcake.message.sender.MessageSenderManager;
import org.perfcake.message.sequence.SequenceManager;
import org.perfcake.reporting.ReportManager;
import org.perfcake.util.Utils;
import org.perfcake.validation.ValidationException;
import org.perfcake.validation.ValidationManager;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.List;
/**
* Encapsulates whole test execution, contains all information necessary to run the test.
*
* @author <a href="mailto:pavel.macik@gmail.com">Pavel Macík</a>
* @author <a href="mailto:marvenec@gmail.com">Martin Večeřa</a>
*/
public class Scenario {
/**
* Logger for this class.
*/
private static final Logger log = LogManager.getLogger(Scenario.class);
/**
* Message generator.
*/
private MessageGenerator generator;
/**
* Manager of message senders.
*/
private MessageSenderManager messageSenderManager;
/**
* Report manager.
*/
private ReportManager reportManager;
/**
* Store of the messages.
*/
private List<MessageTemplate> messageStore;
/**
* Validation manager.
*/
private ValidationManager validationManager;
/**
* Sequence manager.
*/
private SequenceManager sequenceManager;
/**
* Correlates received messages with the sent ones. Null means that it is unused.
*/
private Correlator correlator = null;
/**
* Receives messages from a different message channel. Null means that it is unused.
*/
private Receiver receiver = null;
/**
* Initializes the scenario execution.
*
* @throws org.perfcake.PerfCakeException
* When it was not possible to fully initialize the scenario.
*/
public void init() throws PerfCakeException {
if (log.isTraceEnabled()) {
log.trace("Scenario initialization...");
}
Utils.initTimeStamps();
generator.setReportManager(reportManager);
generator.setValidationManager(validationManager);
generator.setSequenceManager(sequenceManager);
generator.setCorrelator(correlator);
try {
generator.init(messageSenderManager, messageStore);
} catch (final Exception e) {
throw new PerfCakeException("Cannot initialize message generator: ", e);
}
}
/**
* Executes the scenario. This mainly means to send the messages.
*
* @throws PerfCakeException
* When it was not possible to execute the scenario.
*/
public void run() throws PerfCakeException {
if (log.isTraceEnabled()) {
log.trace("Running scenario...");
}
if (receiver != null) {
if (correlator == null) {
throw new PerfCakeException("A correlator must be set in order to use a receiver.");
}
receiver.setCorrelator(correlator);
receiver.start();
}
if (validationManager.isEnabled()) {
validationManager.startValidation();
}
try {
generator.generate();
} catch (final Exception e) {
throw new PerfCakeException("Error generating messages: ", e);
}
}
/**
* Stops the scenario execution.
*/
public void stop() {
reportManager.stop();
if (receiver != null) {
receiver.stop();
}
}
/**
* Finalizes the scenario.
*
* @throws PerfCakeException
* When it was not possible to perform all finalization operations.
*/
public void close() throws PerfCakeException {
if (generator != null) {
generator.close();
}
try {
validationManager.waitForValidation();
} catch (final InterruptedException ie) {
throw new PerfCakeException("Could not finish messages response validation properly: ", ie);
}
if (receiver != null) {
receiver.stop();
}
if (log.isTraceEnabled()) {
if (validationManager.isAllMessagesValid()) {
log.trace("Scenario finished successfully!");
} else {
log.trace("Scenario finished but there were validation errors.");
throw new ValidationException("Some messages did not pass validation, please check validation log.");
}
}
}
/**
* Checks if all threads used for message generating were terminated successfully.
*
* @return True if all threads were terminated.
*/
public boolean areAllThreadsTerminated() {
return generator.getActiveThreadsCount() <= 0;
}
/**
* Gets the current {@link org.perfcake.model.Scenario.Generator}.
*
* @return The current {@link org.perfcake.model.Scenario.Generator}.
*/
MessageGenerator getGenerator() {
return generator;
}
/**
* Sets the {@link org.perfcake.model.Scenario.Generator} for the scenario.
*
* @param generator
* The {@link org.perfcake.model.Scenario.Generator} to be set.
*/
void setGenerator(final MessageGenerator generator) {
this.generator = generator;
}
/**
* Gets the current {@link org.perfcake.message.sender.MessageSenderManager}.
*
* @return The current {@link org.perfcake.message.sender.MessageSenderManager}.
*/
MessageSenderManager getMessageSenderManager() {
return messageSenderManager;
}
/**
* Sets the {@link org.perfcake.message.sender.MessageSenderManager}.
*
* @param messageSenderManager
* The {@link org.perfcake.message.sender.MessageSenderManager} to be set.
*/
void setMessageSenderManager(final MessageSenderManager messageSenderManager) {
this.messageSenderManager = messageSenderManager;
}
/**
* Gets the current {@link org.perfcake.reporting.ReportManager}.
*
* @return The current {@link org.perfcake.reporting.ReportManager}.
*/
ReportManager getReportManager() {
return reportManager;
}
/**
* Sets the {@link org.perfcake.reporting.ReportManager}.
*
* @param reportManager
* The {@link org.perfcake.reporting.ReportManager} to be set.
*/
void setReportManager(final ReportManager reportManager) {
this.reportManager = reportManager;
}
/**
* Gets the current message store.
*
* @return The current message store.
*/
List<MessageTemplate> getMessageStore() {
return messageStore;
}
/**
* Sets the message store.
*
* @param messageStore
* The message store to be set.
*/
void setMessageStore(final List<MessageTemplate> messageStore) {
this.messageStore = messageStore;
}
/**
* Sets the {@link org.perfcake.validation.ValidationManager}.
*
* @param validationManager
* The {@link org.perfcake.validation.ValidationManager} to be set.
*/
void setValidationManager(final ValidationManager validationManager) {
this.validationManager = validationManager;
}
/**
* Gets the current {@link org.perfcake.validation.ValidationManager}.
*
* @return The current {@link org.perfcake.validation.ValidationManager}.
*/
ValidationManager getValidationManager() {
return validationManager;
}
/**
* Sets the current {@link SequenceManager}.
*
* @param sequenceManager
* The {@link SequenceManager} to be set.
*/
void setSequenceManager(final SequenceManager sequenceManager) {
this.sequenceManager = sequenceManager;
}
/**
* Gets the current {@link SequenceManager}.
*
* @return The current {@link SequenceManager}.
*/
SequenceManager getSequenceManager() {
return sequenceManager;
}
/**
* Gets the {@link Correlator} used to correlate received messages with sent ones. It is needed only when a separate message channel is used
* for receiving messages. Null means that correlator is not used.
*
* @return The correlator used in the current test run.
*/
Correlator getCorrelator() {
return correlator;
}
/**
* Sets the {@link Correlator} used to correlate received messages with sent ones. It is needed only when a separate message channel is used
* for receiving messages. Null means that correlator is not used.
*
* @param correlator
* The correlator to be used in the current test run.
*/
void setCorrelator(final Correlator correlator) {
this.correlator = correlator;
}
/**
* Gets the {@link Receiver} used to receive response messages from a separate message channel. A correlator is needed to match
* requests and responses together. Null means that the receiver is not used.
*
* @return The receiver used to receive responses from a separate message channel.
*/
Receiver getReceiver() {
return receiver;
}
/**
* Sets the {@link Receiver} used to receive response messages from a separate message channel. A correlator is needed to match
* requests and responses together. Null means that the receiver is not used.
*
* @param receiver
* The receiver to be used to receive responses from a separate message channel.
*/
void setReceiver(final Receiver receiver) {
this.receiver = receiver;
}
}