package com.griddynamics.jagger.user.test.configurations; import com.google.common.collect.Lists; import com.griddynamics.jagger.engine.e1.Provider; import com.griddynamics.jagger.engine.e1.collector.loadscenario.ExampleLoadScenarioListener; import com.griddynamics.jagger.engine.e1.collector.loadscenario.LoadScenarioListener; import com.griddynamics.jagger.user.test.configurations.auxiliary.Id; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; /** * @brief Describes the execution sequence of the load tests during single run * @n * @par Details: * @details JLoadScenario describes the execution sequence of the load tests. Only single load scenario can be executed at a time @n * Project can contain multiple load scenarios @n * What load scenario to execute is defined by 'jagger.load.scenario.id.to.execute' property@n * You can set it via system properties or in the 'environment.properties' file @n * @n * See @ref section_writing_test_load_scenario for more details @n * @n * More information on the parameter of the test definition, you can find in the Builder documentation @n * @n * Code example: * @dontinclude SimpleJLoadScenarioProvider.java * @skip begin: following section is used for docu generation - Load test scenario configuration * @until end: following section is used for docu generation - Load test scenario configuration */ public class JLoadScenario { private final String id; private final List<JParallelTestsGroup> testGroups; private final List<Double> percentileValues; private final List<Provider<LoadScenarioListener>> listeners; private JLoadScenario(Builder builder) { this.id = builder.id.value(); this.testGroups = builder.testGroups; this.percentileValues = builder.percentileValues; this.listeners = builder.listeners; } /** Builder of the JLoadScenario * @n * @details Constructor parameters are mandatory for the JLoadScenario. All parameters, set by setters are optional * @n * @param id - Unique id of the load scenario * @param testGroups - List of JParallelTestsGroup to execute */ public static Builder builder(Id id, List<JParallelTestsGroup> testGroups) { return new Builder(id, testGroups); } /** Builder of the JLoadScenario * @n * @details Constructor parameters are mandatory for the JLoadScenario. All parameters, set by setters are optional * @n * @param id - Unique id of the load scenario * @param testGroup - Load scenario should contain at least one test group * @param testGroups - List of JParallelTestsGroup to execute */ public static Builder builder(Id id, JParallelTestsGroup testGroup, JParallelTestsGroup... testGroups) { List<JParallelTestsGroup> jParallelTestsGroupList = new ArrayList<>(); jParallelTestsGroupList.add(testGroup); Collections.addAll(jParallelTestsGroupList, testGroups); return new Builder(id, jParallelTestsGroupList); } public static class Builder { private final Id id; private final List<JParallelTestsGroup> testGroups; private List<Double> percentileValues; private List<Provider<LoadScenarioListener>> listeners = Lists.newArrayList(); public Builder(Id id, List<JParallelTestsGroup> testGroups) { this.id = id; this.testGroups = testGroups; } /** * Optional: Sets list of latency percentile values * * @param percentileValues latency percentile values */ public Builder withLatencyPercentiles(List<Double> percentileValues) { Objects.requireNonNull(percentileValues); percentileValues.stream().filter(percentile -> percentile <= 0.0 || percentile >= 100.0) .findAny() .ifPresent(badPercentile -> { throw new IllegalArgumentException("Percentile value must be > 0 and < 100. Provided value is " + badPercentile); }); this.percentileValues = percentileValues; return this; } /** * Optional: Adds instances of subtypes of {@link com.griddynamics.jagger.engine.e1.Provider< LoadScenarioListener >} * These listeners are executed before and after test suite. * Example: * @code * addListener(new ExampleLoadScenarioListener()) * @endcode * @see ExampleLoadScenarioListener for example */ public Builder addListener(Provider<LoadScenarioListener> listener) { this.listeners.add(listener); return this; } /** * Optional: Adds instances of subtypes of {@link com.griddynamics.jagger.engine.e1.Provider< LoadScenarioListener >} * These listeners are executed before and after test suite. * Example: * @code * addListeners(Arrays.asList(new ExampleLoadScenarioListener())) * @endcode * @see ExampleLoadScenarioListener for example */ public Builder addListeners(List<Provider<LoadScenarioListener>> listeners) { this.listeners.addAll(listeners); return this; } /** * Creates the object of JLoadScenario type with custom parameters. * * @return JLoadScenario object. */ public JLoadScenario build() { if (testGroups.stream().map(JParallelTestsGroup::getId).collect(Collectors.toSet()).size() < testGroups.size()) { throw new IllegalStateException("JParallelTestsGroup ids inside one JLoadScenario are not all unique"); } return new JLoadScenario(this); } } public List<JParallelTestsGroup> getTestGroups() { return testGroups; } public String getId() { return id; } public List<Double> getPercentileValues() { return percentileValues; } public List<Provider<LoadScenarioListener>> getListeners() { return listeners; } }