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.ResponseValidatorProvider;
import com.griddynamics.jagger.engine.e1.collector.invocation.InvocationListener;
import com.griddynamics.jagger.invoker.Invoker;
import com.griddynamics.jagger.invoker.QueryPoolLoadBalancer;
import com.griddynamics.jagger.invoker.RandomLoadBalancer;
import com.griddynamics.jagger.invoker.RoundRobinPairSupplierFactory;
import com.griddynamics.jagger.invoker.v2.DefaultHttpInvoker;
import com.griddynamics.jagger.invoker.v2.DefaultInvokerProvider;
import com.griddynamics.jagger.user.test.configurations.auxiliary.Id;
import com.griddynamics.jagger.user.test.configurations.loadbalancer.JLoadBalancer;
import java.util.List;
import static com.griddynamics.jagger.user.test.configurations.loadbalancer.JLoadBalancer.DefaultLoadBalancer.ROUND_ROBIN;
/**
* @brief Definition of the load test - describes test data sources and the protocol, used during load test
* @n
* @par Details:
* @details Test definition is the base component of the @ref section_writing_test_load_scenario "load test description". With the help of the internal Builder class it allows to setup: @n
* @li source of the endpoints (where to apply load)
* @li source of queries (what parameters of the load to set)
* @li how to pair endpoints ans queries (one by one, round robin, random, unique, etc)
* @li what protocol to use for the communication with the system under test (SUT)
* @li how to validate SUT responses
* @li what additional user defined actions to execute during communication with SUT
*
* 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 JTestDefinition {
private final String id;
private final Iterable endpoints;
private final String comment;
private final Iterable queries;
private final Provider<Invoker> invoker;
private final List<ResponseValidatorProvider> validators;
private final List<Provider<InvocationListener>> listeners;
private final QueryPoolLoadBalancer loadBalancer;
private JTestDefinition(Builder builder) {
this.id = builder.id.value();
this.endpoints = builder.endpointsProvider;
this.comment = (builder.comment == null) ? "" : builder.comment;
this.queries = builder.queries;
this.invoker = builder.invoker;
this.validators = builder.validators;
this.listeners = builder.listeners;
this.loadBalancer = builder.loadBalancer;
}
/**
* Builder of the JTestDefinition
* @n
* @param id - Unique id of the test definition
* @param endpointsProvider - Source of the test data: endpoint - where load will be applied
* @n
* @details Constructor parameters are mandatory for the JTestDefinition. All parameters, set by setters are optional
* @n
*/
public static Builder builder(Id id, Iterable endpointsProvider) {
return new Builder(id, endpointsProvider);
}
public static class Builder {
private final Id id;
private final Iterable endpointsProvider;
private String comment = "";
private Iterable queries;
private Provider<Invoker> invoker = DefaultInvokerProvider.of(DefaultHttpInvoker.class);
private List<ResponseValidatorProvider> validators = Lists.newArrayList();
private List<Provider<InvocationListener>> listeners = Lists.newArrayList();
private QueryPoolLoadBalancer loadBalancer;
private Builder(Id id, Iterable endpointsProvider) {
this.id = id;
this.endpointsProvider = endpointsProvider;
this.loadBalancer = JLoadBalancer.builder(ROUND_ROBIN).withRandomSeed(31).build();
}
/**
* Optional: Sets human readable comment for the test definition
*
* @param comment the comment of the test definition
*/
public Builder withComment(String comment) {
this.comment = comment;
return this;
}
/**
* Optional: Sets queries (what load will be applied during performance test) for the tests using this test prototype
*
* @param queryProvider iterable queries.
* @see com.griddynamics.jagger.invoker.v2.JHttpQuery for example.
*/
public Builder withQueryProvider(Iterable queryProvider) {
this.queries = queryProvider;
return this;
}
/**
* Optional: Sets load balancer aka distributor (how to pair endpoints and queries) (subtypes of {@link QueryPoolLoadBalancer}).
* Default is {@link RandomLoadBalancer} with {@link RoundRobinPairSupplierFactory}
*
* Available implementations and usage example: @ref Main_Distributors_group
*
* @param loadBalancer load balancer.
*/
public Builder withLoadBalancer(QueryPoolLoadBalancer loadBalancer) {
this.loadBalancer = loadBalancer;
return this;
}
/**
* Optional: Sets subtypes of {@link com.griddynamics.jagger.invoker.Invoker}
*
* Instances of this invoker will be used during Jagger test execution to send requests to the System under test. @n
* Example:
* @code
* .withInvoker(DefaultInvokerProvider.of(DefaultHttpInvoker.class))
* @endcode
*/
public Builder withInvoker(Provider<Invoker> invoker) {
this.invoker = invoker;
return this;
}
/**
* Optional: Adds a list of subtypes of {@link com.griddynamics.jagger.engine.e1.collector.ResponseValidatorProvider}
* Instances of those subtypes will be used to validate responses during Jagger test execution @n
* Example:
* @code
* addValidator(new ExampleResponseValidatorProvider("we are always good"))
* @endcode
* @see com.griddynamics.jagger.engine.e1.collector.ExampleResponseValidatorProvider for example
*/
public Builder addValidators(List<ResponseValidatorProvider> validators) {
this.validators.addAll(validators);
return this;
}
/**
* Optional: Adds a subtype of {@link com.griddynamics.jagger.engine.e1.collector.ResponseValidatorProvider}
* Instances of those subtypes will be used to validate responses during Jagger test execution
* @n
* Example:
* @code
* addValidator(new ExampleResponseValidatorProvider("we are always good"))
* @endcode
* @see com.griddynamics.jagger.engine.e1.collector.ExampleResponseValidatorProvider for example
*/
public Builder addValidator(ResponseValidatorProvider validator) {
this.validators.add(validator);
return this;
}
/**
* Optional: Adds instances of subtypes of {@link com.griddynamics.jagger.engine.e1.Provider<InvocationListener>}
* @b IMPORTANT: listener code will be executed during every invocation = every request to SUT
* @n
* Try to avoid slow operations in invocation listener code. They will slow down your workload
* @n
* Example:
* @code
* addListeners(Arrays.asList(new NotNullInvocationListener()))
* @endcode
* @see com.griddynamics.jagger.engine.e1.collector.invocation.NotNullInvocationListener for example
*/
public Builder addListeners(List<Provider<InvocationListener>> listeners) {
this.listeners.addAll(listeners);
return this;
}
/**
* Optional: Adds a subtype instance of {@link com.griddynamics.jagger.engine.e1.Provider<InvocationListener>}
* @b IMPORTANT: listener code will be executed during every invocation = every request to SUT
* @n
* Try to avoid slow operations in invocation listener code. They will slow down your workload
* @n
* Example:
* @code
* addListener(new NotNullInvocationListener())
* @endcode
* @see com.griddynamics.jagger.engine.e1.collector.invocation.NotNullInvocationListener for example
*/
public Builder addListener(Provider<InvocationListener> listener) {
this.listeners.add(listener);
return this;
}
/**
* Creates the object of JTestDefinition type with custom parameters.
*
* @return JTestDefinition object.
*/
public JTestDefinition build() {
return new JTestDefinition(this);
}
}
public String getId() {
return id;
}
public String getDescription() {
return comment;
}
public Iterable getEndpoints() {
return endpoints;
}
public Iterable getQueries() {
return queries;
}
public Provider<Invoker> getInvoker() {
return invoker;
}
public String getComment() {
return comment;
}
public List<ResponseValidatorProvider> getValidators() {
return validators;
}
public List<Provider<InvocationListener>> getListeners() {
return listeners;
}
public QueryPoolLoadBalancer getLoadBalancer() {
return loadBalancer;
}
}