Gatling generator2 issue #6927 (#6934)

* Initial commit, Generates everything necessary to run a performnace test against a swagger api.  Just have to fill out the CSV feeder files with your data.

* adding samples and gatling-petstore.sh file

* Extending the AbstractScalaCodeGen

* Checking in the CodegenConfig file as it is needed to generate

* removing escaped reserved words

* Changed model to be able to make all variables utilize an underscore while json fields are still just the variable name

* Changing underscore to var as interpolation can not start with a _ in scala

* Fixing path params

* allow you to pass in a system property to define which config to use as a workload profile, use rate and instance multipliers to scale up and down your test, added ramp down after the test is completed, added global assertions.

* Addressing PR feedback

* missed semi-colon

* Bringing everything up to date with the renames that were suggested
This commit is contained in:
ryandavis84 2018-01-07 04:18:36 -05:00 committed by William Cheng
parent 97ad90578d
commit 6d2d4298df
103 changed files with 2338 additions and 0 deletions

31
bin/scala-gatling-petstore.sh Executable file
View File

@ -0,0 +1,31 @@
#!/bin/sh
SCRIPT="$0"
while [ -h "$SCRIPT" ] ; do
ls=`ls -ld "$SCRIPT"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
SCRIPT="$link"
else
SCRIPT=`dirname "$SCRIPT"`/"$link"
fi
done
if [ ! -d "${APP_DIR}" ]; then
APP_DIR=`dirname "$SCRIPT"`/..
APP_DIR=`cd "${APP_DIR}"; pwd`
fi
executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar"
if [ ! -f "$executable" ]
then
mvn clean package
fi
# if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="$@ generate -t modules/swagger-codegen/src/main/resources/ScalaGatling -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l scala-gatling -o samples/client/petstore/scala-gatling"
java $JAVA_OPTS -jar $executable $ags

View File

@ -0,0 +1,345 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.*;
import io.swagger.models.*;
import io.swagger.models.parameters.*;
import io.swagger.models.properties.*;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.util.*;
import java.io.File;
public class ScalaGatlingCodegen extends AbstractScalaCodegen implements CodegenConfig {
// source folder where to write the files
protected String sourceFolder = "src" + File.separator + "gatling" + File.separator + "scala";
protected String resourceFolder = "src" + File.separator + "gatling" + File.separator + "resources";
protected String confFolder = resourceFolder + File.separator + "conf";
protected String dataFolder = resourceFolder + File.separator + "data";
protected String apiVersion = "1.0.0";
/**
* Configures the type of generator.
*
* @return the CodegenType for this generator
* @see io.swagger.codegen.CodegenType
*/
public CodegenType getTag() {
return CodegenType.CLIENT;
}
/**
* Configures a friendly name for the generator. This will be used by the generator
* to select the library with the -l flag.
*
* @return the friendly name for the generator
*/
public String getName() {
return "scala-gatling";
}
/**
* Returns human-friendly help for the generator. Provide the consumer with help
* tips, parameters here
*
* @return A string value for the help message
*/
public String getHelp() {
return "Generates a gatling simulation library.";
}
public ScalaGatlingCodegen() {
super();
// set the output folder here
outputFolder = "generated-code/gatling";
/**
* Api classes. You can write classes for each Api file with the apiTemplateFiles map.
* as with models, add multiple entries with different extensions for multiple files per
* class
*/
apiTemplateFiles.put(
"api.mustache", // the template to use
"Simulation.scala"); // the extension for each file to write
modelTemplateFiles.put("model.mustache", ".scala");
/**
* Template Location. This is the location which templates will be read from. The generator
* will use the resource stream to attempt to read the templates.
*/
templateDir = "ScalaGatling";
/**
* Api Package. Optional, if needed, this can be used in templates
*/
apiPackage = "io.swagger.client.api";
/**
* Model Package. Optional, if needed, this can be used in templates
*/
modelPackage = "io.swagger.client.model";
/**
* Additional Properties. These values can be passed to the templates and
* are available in models, apis, and supporting files
*/
additionalProperties.put("apiVersion", apiVersion);
/**
* Supporting Files. You can write single files for the generator with the
* entire object tree available. If the input file has a suffix of `.mustache
* it will be processed by the template engine. Otherwise, it will be copied
*/
supportingFiles.add(new SupportingFile("build.gradle",
"",
"build.gradle"));
supportingFiles.add(new SupportingFile("logback.xml",
confFolder,
"logback.xml"));
supportingFiles.add(new SupportingFile("default.conf.mustache",
confFolder,
"default.conf"));
supportingFiles.add(new SupportingFile("default.conf.mustache",
confFolder,
"CI.conf"));
supportingFiles.add(new SupportingFile("default.conf.mustache",
confFolder,
"CD.conf"));
supportingFiles.add(new SupportingFile("default.conf.mustache",
confFolder,
"stress.conf"));
supportingFiles.add(new SupportingFile("default.conf.mustache",
confFolder,
"baseline.conf"));
supportingFiles.add(new SupportingFile("default.conf.mustache",
confFolder,
"longevity.conf"));
importMapping.remove("List");
importMapping.remove("Set");
importMapping.remove("Map");
importMapping.put("Date", "java.util.Date");
importMapping.put("ListBuffer", "scala.collection.mutable.ListBuffer");
typeMapping = new HashMap<String, String>();
typeMapping.put("enum", "NSString");
typeMapping.put("array", "List");
typeMapping.put("set", "Set");
typeMapping.put("boolean", "Boolean");
typeMapping.put("string", "String");
typeMapping.put("int", "Int");
typeMapping.put("long", "Long");
typeMapping.put("float", "Float");
typeMapping.put("byte", "Byte");
typeMapping.put("short", "Short");
typeMapping.put("char", "Char");
typeMapping.put("double", "Double");
typeMapping.put("object", "Any");
typeMapping.put("file", "File");
typeMapping.put("binary", "String");
typeMapping.put("ByteArray", "String");
typeMapping.put("date-time", "Date");
typeMapping.put("DateTime", "Date");
instantiationTypes.put("array", "ListBuffer");
instantiationTypes.put("map", "HashMap");
setReservedWordsLowerCase(
Arrays.asList(
// local variable names used in API methods (endpoints)
"path", "contentTypes", "contentType", "queryParams", "headerParams",
"formParams", "postBody", "mp", "basePath", "apiInvoker",
// scala reserved words
"abstract", "case", "catch", "class", "def", "do", "else", "extends",
"false", "final", "finally", "for", "forSome", "if", "implicit",
"import", "lazy", "match", "new", "null", "object", "override", "package",
"private", "protected", "return", "sealed", "super", "this", "throw",
"trait", "try", "true", "type", "val", "var", "while", "with", "yield")
);
}
/**
* Gatling does not need the models to have escaped words as it builds models dynamically instead of through
* an instance of the object.
*
* @return the escaped term
*/
@Override
public String escapeReservedWord(String name) {
return name;
}
/**
* Location to write model files. You can use the modelPackage() as defined when the class is
* instantiated
*/
public String modelFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar);
}
/**
* Location to write api files. You can use the apiPackage() as defined when the class is
* instantiated
*/
@Override
public String apiFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar);
}
/**
* Modifies the swagger doc to make mustache easier to use
*
* @param swagger
*/
@Override
public void preprocessSwagger(Swagger swagger) {
for (String pathname : swagger.getPaths().keySet()) {
Path path = swagger.getPath(pathname);
if (path.getOperations() == null) {
continue;
}
for (Operation operation : path.getOperations()) {
if (!operation.getVendorExtensions().keySet().contains("x-gatling-path")) {
if (pathname.contains("{")) {
String gatlingPath = pathname.replaceAll("\\{", "\\$\\{");
operation.setVendorExtension("x-gatling-path", gatlingPath);
} else {
operation.setVendorExtension("x-gatling-path", pathname);
}
}
Set<Parameter> headerParameters = new HashSet<>();
Set<Parameter> formParameters = new HashSet<>();
Set<Parameter> queryParameters = new HashSet<>();
Set<Parameter> pathParameters = new HashSet<>();
for (Parameter parameter : operation.getParameters()) {
if (parameter.getIn().equalsIgnoreCase("header")) {
headerParameters.add(parameter);
}
if (parameter.getIn().equalsIgnoreCase("formData")) {
formParameters.add(parameter);
}
if (parameter.getIn().equalsIgnoreCase("query")) {
queryParameters.add(parameter);
}
if (parameter.getIn().equalsIgnoreCase("path")) {
pathParameters.add(parameter);
}
if (parameter.getIn().equalsIgnoreCase("body")) {
BodyParameter bodyParameter = (BodyParameter) parameter;
Model model = bodyParameter.getSchema();
if (model instanceof RefModel) {
String[] refArray = model.getReference().split("\\/");
operation.setVendorExtension("x-gatling-body-object", refArray[refArray.length - 1] + ".toStringBody");
Set<String> bodyFeederParams = new HashSet<>();
Set<String> sessionBodyVars = new HashSet<>();
for (Map.Entry<String, Model> modelEntry : swagger.getDefinitions().entrySet()) {
if (refArray[refArray.length - 1].equalsIgnoreCase(modelEntry.getKey())) {
for (Map.Entry<String, Property> propertyEntry : modelEntry.getValue().getProperties().entrySet()) {
bodyFeederParams.add(propertyEntry.getKey());
sessionBodyVars.add("\"${" + propertyEntry.getKey() + "}\"");
}
}
}
operation.setVendorExtension("x-gatling-body-feeder", operation.getOperationId() + "BodyFeeder");
operation.setVendorExtension("x-gatling-body-feeder-params", StringUtils.join(sessionBodyVars, ","));
try {
FileUtils.writeStringToFile(new File(outputFolder + File.separator + dataFolder + File.separator + operation.getOperationId() + "-" + "BodyParams.csv"), StringUtils.join(bodyFeederParams, ","));
} catch (IOException ioe) {
LOGGER.error("Could not create feeder file for operationId" + operation.getOperationId(), ioe);
}
} else if (model instanceof ArrayModel) {
operation.setVendorExtension("x-gatling-body-object", "StringBody(\"[]\")");
} else {
operation.setVendorExtension("x-gatling-body-object", "StringBody(\"{}\")");
}
}
}
prepareGatlingData(operation, headerParameters, "header");
prepareGatlingData(operation, formParameters, "form");
prepareGatlingData(operation, queryParameters, "query");
prepareGatlingData(operation, pathParameters, "path");
}
}
}
/**
* Creates all the necessary swagger vendor extensions and feeder files for gatling
*
* @param operation Swagger Operation
* @param parameters Swagger Parameters
* @param parameterType Swagger Parameter Type
*/
private void prepareGatlingData(Operation operation, Set<Parameter> parameters, String parameterType) {
if (parameters.size() > 0) {
List<String> parameterNames = new ArrayList<>();
List<Object> vendorList = new ArrayList<>();
for (Parameter parameter : parameters) {
Map<String, Object> extensionMap = new HashMap<>();
extensionMap.put("gatlingParamName", parameter.getName());
extensionMap.put("gatlingParamValue", "${" + parameter.getName() + "}");
vendorList.add(extensionMap);
parameterNames.add(parameter.getName());
}
operation.setVendorExtension("x-gatling-" + parameterType.toLowerCase() + "-params", vendorList);
operation.setVendorExtension("x-gatling-" + parameterType.toLowerCase() + "-feeder", operation.getOperationId() + parameterType.toUpperCase() + "Feeder");
try {
FileUtils.writeStringToFile(new File(outputFolder + File.separator + dataFolder + File.separator + operation.getOperationId() + "-" + parameterType.toLowerCase() + "Params.csv"), StringUtils.join(parameterNames, ","));
} catch (IOException ioe) {
LOGGER.error("Could not create feeder file for operationId" + operation.getOperationId(), ioe);
}
}
}
/**
* Optional - type declaration. This is a String which is used by the templates to instantiate your
* types. There is typically special handling for different property types
*
* @return a string value used as the `dataType` field for model templates, `returnType` for api templates
*/
@Override
public String getTypeDeclaration(Property p) {
if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
Property inner = ap.getItems();
return getSwaggerType(p) + "[" + getTypeDeclaration(inner) + "]";
} else if (p instanceof MapProperty) {
MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties();
return getSwaggerType(p) + "[String, " + getTypeDeclaration(inner) + "]";
}
return super.getTypeDeclaration(p);
}
/**
* Optional - swagger type conversion. This is used to map swagger types in a `Property` into
* either language specific types via `typeMapping` or into complex models if there is not a mapping.
*
* @return a string value of the type or complex model for this property
* @see io.swagger.models.properties.Property
*/
@Override
public String getSwaggerType(Property p) {
String swaggerType = super.getSwaggerType(p);
String type = null;
if (typeMapping.containsKey(swaggerType)) {
type = typeMapping.get(swaggerType);
if (languageSpecificPrimitives.contains(type))
return toModelName(type);
} else
type = swaggerType;
return toModelName(type);
}
}

View File

@ -19,6 +19,7 @@ io.swagger.codegen.languages.ErlangServerCodegen
io.swagger.codegen.languages.FinchServerCodegen
io.swagger.codegen.languages.FlashClientCodegen
io.swagger.codegen.languages.FlaskConnexionCodegen
io.swagger.codegen.languages.ScalaGatlingCodegen
io.swagger.codegen.languages.GoClientCodegen
io.swagger.codegen.languages.GoServerCodegen
io.swagger.codegen.languages.GroovyClientCodegen

View File

@ -0,0 +1,147 @@
package {{package}}
import {{modelPackage}}._
import com.typesafe.config.ConfigFactory
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import io.gatling.core.structure.PopulationBuilder
import java.io.File
import scala.collection.mutable
class {{classname}}Simulation extends Simulation {
def getCurrentDirectory = new File("").getAbsolutePath
def userDataDirectory = getCurrentDirectory + "/src/gatling/resources/data"
// basic test setup
val configName = System.getProperty("testConfig", "baseline")
val config = ConfigFactory.load(configName).withFallback(ConfigFactory.load("default"))
val durationSeconds = config.getInt("performance.durationSeconds")
val rampUpSeconds = config.getInt("performance.rampUpSeconds")
val rampDownSeconds = config.getInt("performance.rampDownSeconds")
val authentication = config.getString("performance.authorizationHeader")
val acceptHeader = config.getString("performance.acceptType")
val contentTypeHeader = config.getString("performance.contentType")
val rateMultiplier = config.getDouble("performance.rateMultiplier")
val instanceMultiplier = config.getDouble("performance.instanceMultiplier")
// global assertion data
val globalResponseTimeMinLTE = config.getInt("performance.global.assertions.responseTime.min.lte")
val globalResponseTimeMinGTE = config.getInt("performance.global.assertions.responseTime.min.gte")
val globalResponseTimeMaxLTE = config.getInt("performance.global.assertions.responseTime.max.lte")
val globalResponseTimeMaxGTE = config.getInt("performance.global.assertions.responseTime.max.gte")
val globalResponseTimeMeanLTE = config.getInt("performance.global.assertions.responseTime.mean.lte")
val globalResponseTimeMeanGTE = config.getInt("performance.global.assertions.responseTime.mean.gte")
val globalResponseTimeFailedRequestsPercentLTE = config.getDouble("performance.global.assertions.failedRequests.percent.lte")
val globalResponseTimeFailedRequestsPercentGTE = config.getDouble("performance.global.assertions.failedRequests.percent.gte")
val globalResponseTimeSuccessfulRequestsPercentLTE = config.getDouble("performance.global.assertions.successfulRequests.percent.lte")
val globalResponseTimeSuccessfulRequestsPercentGTE = config.getDouble("performance.global.assertions.successfulRequests.percent.gte")
// Setup http protocol configuration
val httpConf = http
.baseURL("{{basePath}}")
.doNotTrackHeader("1")
.acceptLanguageHeader("en-US,en;q=0.5")
.acceptEncodingHeader("gzip, deflate")
.userAgentHeader("Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0")
.acceptHeader(acceptHeader)
.contentTypeHeader(contentTypeHeader)
// set authorization header if it has been modified from config
if(!authentication.equals("~MANUAL_ENTRY")){
httpConf.authorizationHeader(authentication)
}
// Setup all the operations per second for the test to ultimately be generated from configs
{{#operations}}
{{#operation}}
val {{operationId}}PerSecond = config.getDouble("performance.operationsPerSecond.{{operationId}}") * rateMultiplier * instanceMultiplier
{{/operation}}
{{/operations}}
val scenarioBuilders: mutable.MutableList[PopulationBuilder] = new mutable.MutableList[PopulationBuilder]()
// Set up CSV feeders
{{#operations}}
{{#operation}}
{{#vendorExtensions.x-gatling-query-feeder}}
val {{vendorExtensions.x-gatling-query-feeder}} = csv(userDataDirectory + File.separator + "{{operationId}}-queryParams.csv").random
{{/vendorExtensions.x-gatling-query-feeder}}
{{#vendorExtensions.x-gatling-header-feeder}}
val {{vendorExtensions.x-gatling-header-feeder}} = csv(userDataDirectory + File.separator + "{{operationId}}-headerParams.csv").random
{{/vendorExtensions.x-gatling-header-feeder}}
{{#vendorExtensions.x-gatling-form-feeder}}
val {{vendorExtensions.x-gatling-form-feeder}} = csv(userDataDirectory + File.separator + "{{operationId}}-formParams.csv").random
{{/vendorExtensions.x-gatling-form-feeder}}
{{#vendorExtensions.x-gatling-path-feeder}}
val {{vendorExtensions.x-gatling-path-feeder}} = csv(userDataDirectory + File.separator + "{{operationId}}-pathParams.csv").random
{{/vendorExtensions.x-gatling-path-feeder}}
{{#vendorExtensions.x-gatling-body-feeder}}
val {{vendorExtensions.x-gatling-body-feeder}} = csv(userDataDirectory + File.separator + "{{operationId}}-bodyParams.csv", escapeChar = '\\').random
{{/vendorExtensions.x-gatling-body-feeder}}
{{/operation}}
{{/operations}}
// Setup all scenarios
{{#operations}}
{{#operation}}
{{#description}}/* {{{description}}} */{{/description}}
val scn{{operationId}} = scenario("{{operationId}}Simulation")
{{#vendorExtensions.x-gatling-query-feeder}}
.feed({{vendorExtensions.x-gatling-query-feeder}})
{{/vendorExtensions.x-gatling-query-feeder}}
{{#vendorExtensions.x-gatling-header-feeder}}
.feed({{vendorExtensions.x-gatling-header-feeder}})
{{/vendorExtensions.x-gatling-header-feeder}}
{{#vendorExtensions.x-gatling-form-feeder}}
.feed({{vendorExtensions.x-gatling-form-feeder}})
{{/vendorExtensions.x-gatling-form-feeder}}
{{#vendorExtensions.x-gatling-body-feeder}}
.feed({{vendorExtensions.x-gatling-body-feeder}})
{{/vendorExtensions.x-gatling-body-feeder}}
{{#vendorExtensions.x-gatling-path-feeder}}
.feed({{vendorExtensions.x-gatling-path-feeder}})
{{/vendorExtensions.x-gatling-path-feeder}}
.exec(http("{{operationId}}")
.httpRequest("{{httpMethod}}","{{{vendorExtensions.x-gatling-path}}}")
{{#vendorExtensions.x-gatling-query-params}}
.queryParam("{{gatlingParamName}}","{{gatlingParamValue}}")
{{/vendorExtensions.x-gatling-query-params}}
{{#vendorExtensions.x-gatling-header-params}}
.header("{{gatlingParamName}}","{{gatlingParamValue}}")
{{/vendorExtensions.x-gatling-header-params}}
{{#vendorExtensions.x-gatling-form-params}}
.formParam("{{gatlingParamName}}","{{gatlingParamValue}}")
{{/vendorExtensions.x-gatling-form-params}}
{{#vendorExtensions.x-gatling-body-object}}
.body(StringBody({{{vendorExtensions.x-gatling-body-object}}}{{#vendorExtensions.x-gatling-body-feeder-params}}({{{vendorExtensions.x-gatling-body-feeder-params}}}){{/vendorExtensions.x-gatling-body-feeder-params}}))
{{/vendorExtensions.x-gatling-body-object}})
// Run scn{{operationId}} with warm up and reach a constant rate for entire duration
scenarioBuilders += scn{{operationId}}.inject(
rampUsersPerSec(1) to({{operationId}}PerSecond) during(rampUpSeconds),
constantUsersPerSec({{operationId}}PerSecond) during(durationSeconds),
rampUsersPerSec({{operationId}}PerSecond) to(1) during(rampDownSeconds)
)
{{/operation}}
{{/operations}}
setUp(
scenarioBuilders.toList
).protocols(httpConf).assertions(
global.responseTime.min.lte(globalResponseTimeMinLTE),
global.responseTime.min.gte(globalResponseTimeMinGTE),
global.responseTime.max.lte(globalResponseTimeMaxLTE),
global.responseTime.max.gte(globalResponseTimeMaxGTE),
global.responseTime.mean.lte(globalResponseTimeMeanLTE),
global.responseTime.mean.gte(globalResponseTimeMeanGTE),
global.failedRequests.percent.lte(globalResponseTimeFailedRequestsPercentLTE),
global.failedRequests.percent.gte(globalResponseTimeFailedRequestsPercentGTE),
global.successfulRequests.percent.lte(globalResponseTimeSuccessfulRequestsPercentLTE),
global.successfulRequests.percent.gte(globalResponseTimeSuccessfulRequestsPercentGTE)
)
}

View File

@ -0,0 +1,29 @@
plugins {
id 'com.github.lkishalmi.gatling' version '0.4.1'
}
repositories {
mavenCentral()
}
dependencies {
}
apply plugin: "com.github.lkishalmi.gatling"
gatling {
toolVersion = '2.3.0'
jvmArgs = ['-server', '-XX:+UseThreadPriorities',
'-XX:ThreadPriorityPolicy=42',
'-Xms2048M', '-Xmx2048M', '-Xmn500M',
'-XX:+HeapDumpOnOutOfMemoryError',
'-XX:+AggressiveOpts',
'-XX:+OptimizeStringConcat',
'-XX:+UseFastAccessorMethods',
'-XX:+UseParNewGC',
'-XX:+UseConcMarkSweepGC',
'-XX:+CMSParallelRemarkEnabled',
'-Djava.net.preferIPv4Stack=true',
'-Djava.net.preferIPv6Addresses=false']
}

View File

@ -0,0 +1,51 @@
performance {
authorizationHeader = "~MANUAL_ENTRY~"
rampUpSeconds = 60
rampDownSeconds = 60
durationSeconds = 360
contentType = "application/json"
acceptType = "application/json"
rateMultiplier = 1
instanceMultiplier = 1
operationsPerSecond {
{{#apiInfo}}
{{#apis}}
{{#operations}}
{{#operation}}
{{operationId}} = 1
{{/operation}}
{{/operations}}
{{/apis}}
{{/apiInfo}}
}
global {
assertions {
responseTime {
min {
lte = 30000
gte = 0
}
max {
lte = 30000
gte = 0
}
mean {
lte = 30000
gte = 0
}
}
failedRequests {
percent {
lte = 5
gte = 0
}
}
successfulRequests {
percent {
lte = 100
gte = 0
}
}
}
}
}

View File

@ -0,0 +1,132 @@
#########################
# Gatling Configuration #
#########################
# This file contains all the settings configurable for Gatling with their default values
gatling {
core {
outputDirectoryBaseName = "" # The prefix for each simulation result folder (then suffixed by the report generation timestamp)
runDescription = "" # The description for this simulation run, displayed in each report
encoding = "utf-8" # Encoding to use throughout Gatling for file and string manipulation
simulationClass = "" # The FQCN of the simulation to run (when used in conjunction with noReports, the simulation for which assertions will be validated)
mute = false # When set to true, don't ask for simulation name nor run description (currently only used by Gatling SBT plugin)
elFileBodiesCacheMaxCapacity = 200 # Cache size for request body EL templates, set to 0 to disable
rawFileBodiesCacheMaxCapacity = 200 # Cache size for request body Raw templates, set to 0 to disable
rawFileBodiesInMemoryMaxSize = 1000 # Below this limit, raw file bodies will be cached in memory
pebbleFileBodiesCacheMaxCapacity = 200 # Cache size for request body Peeble templates, set to 0 to disable
extract {
regex {
cacheMaxCapacity = 200 # Cache size for the compiled regexes, set to 0 to disable caching
}
xpath {
cacheMaxCapacity = 200 # Cache size for the compiled XPath queries, set to 0 to disable caching
}
jsonPath {
cacheMaxCapacity = 200 # Cache size for the compiled jsonPath queries, set to 0 to disable caching
preferJackson = false # When set to true, prefer Jackson over Boon for JSON-related operations
}
css {
cacheMaxCapacity = 200 # Cache size for the compiled CSS selectors queries, set to 0 to disable caching
}
}
directory {
data = user-files/data # Folder where user's data (e.g. files used by Feeders) is located
bodies = user-files/bodies # Folder where bodies are located
simulations = user-files/simulations # Folder where the bundle's simulations are located
reportsOnly = "" # If set, name of report folder to look for in order to generate its report
binaries = "" # If set, name of the folder where compiles classes are located: Defaults to GATLING_HOME/target.
results = results # Name of the folder where all reports folder are located
}
}
charting {
noReports = false # When set to true, don't generate HTML reports
maxPlotPerSeries = 1000 # Number of points per graph in Gatling reports
useGroupDurationMetric = false # Switch group timings from cumulated response time to group duration.
indicators {
lowerBound = 800 # Lower bound for the requests' response time to track in the reports and the console summary
higherBound = 1200 # Higher bound for the requests' response time to track in the reports and the console summary
percentile1 = 50 # Value for the 1st percentile to track in the reports, the console summary and Graphite
percentile2 = 75 # Value for the 2nd percentile to track in the reports, the console summary and Graphite
percentile3 = 95 # Value for the 3rd percentile to track in the reports, the console summary and Graphite
percentile4 = 99 # Value for the 4th percentile to track in the reports, the console summary and Graphite
}
}
http {
fetchedCssCacheMaxCapacity = 200 # Cache size for CSS parsed content, set to 0 to disable
fetchedHtmlCacheMaxCapacity = 200 # Cache size for HTML parsed content, set to 0 to disable
perUserCacheMaxCapacity = 200 # Per virtual user cache size, set to 0 to disable
warmUpUrl = "http://gatling.io" # The URL to use to warm-up the HTTP stack (blank means disabled)
enableGA = true # Very light Google Analytics, please support
ssl {
keyStore {
type = "" # Type of SSLContext's KeyManagers store
file = "" # Location of SSLContext's KeyManagers store
password = "" # Password for SSLContext's KeyManagers store
algorithm = "" # Algorithm used SSLContext's KeyManagers store
}
trustStore {
type = "" # Type of SSLContext's TrustManagers store
file = "" # Location of SSLContext's TrustManagers store
password = "" # Password for SSLContext's TrustManagers store
algorithm = "" # Algorithm used by SSLContext's TrustManagers store
}
}
ahc {
keepAlive = true # Allow pooling HTTP connections (keep-alive header automatically added)
connectTimeout = 10000 # Timeout when establishing a connection
handshakeTimeout = 10000 # Timeout when performing TLS hashshake
pooledConnectionIdleTimeout = 60000 # Timeout when a connection stays unused in the pool
readTimeout = 60000 # Timeout when a used connection stays idle
maxRetry = 2 # Number of times that a request should be tried again
requestTimeout = 60000 # Timeout of the requests
disableHttpsEndpointIdentificationAlgorithm = true # When set to true, don't enable SSL algorithm on the SSLEngine
useInsecureTrustManager = true # Use an insecure TrustManager that trusts all server certificates
httpClientCodecMaxChunkSize = 8192 # Maximum length of the content or each chunk
httpClientCodecInitialBufferSize = 128 # Initial HttpClientCodec buffer size
sslEnabledProtocols = [TLSv1.2, TLSv1.1, TLSv1] # Array of enabled protocols for HTTPS, if empty use the JDK defaults
sslEnabledCipherSuites = [] # Array of enabled cipher suites for HTTPS, if empty use the AHC defaults
sslSessionCacheSize = 0 # SSLSession cache size, set to 0 to use JDK's default
sslSessionTimeout = 0 # SSLSession timeout in seconds, set to 0 to use JDK's default (24h)
useOpenSsl = false # if OpenSSL should be used instead of JSSE (requires tcnative jar)
useNativeTransport = false # if native transport should be used instead of Java NIO (requires netty-transport-native-epoll, currently Linux only)
tcpNoDelay = true
soReuseAddress = false
soLinger = -1
soSndBuf = -1
soRcvBuf = -1
allocator = "pooled" # switch to unpooled for unpooled ByteBufAllocator
maxThreadLocalCharBufferSize = 200000 # Netty's default is 16k
}
dns {
queryTimeout = 5000 # Timeout of each DNS query in millis
maxQueriesPerResolve = 6 # Maximum allowed number of DNS queries for a given name resolution
}
}
jms {
replyTimeoutScanPeriod = 1000 # scan period for timedout reply messages
}
data {
writers = [console, file] # The list of DataWriters to which Gatling write simulation data (currently supported : console, file, graphite, jdbc)
console {
light = false # When set to true, displays a light version without detailed request stats
}
file {
bufferSize = 8192 # FileDataWriter's internal data buffer size, in bytes
}
leak {
noActivityTimeout = 30 # Period, in seconds, for which Gatling may have no activity before considering a leak may be happening
}
graphite {
light = false # only send the all* stats
host = "localhost" # The host where the Carbon server is located
port = 2003 # The port to which the Carbon server listens to (2003 is default for plaintext, 2004 is default for pickle)
protocol = "tcp" # The protocol used to send data to Carbon (currently supported : "tcp", "udp")
rootPathPrefix = "gatling" # The common prefix of all metrics sent to Graphite
bufferSize = 8192 # GraphiteDataWriter's internal data buffer size, in bytes
writeInterval = 1 # GraphiteDataWriter's write interval, in seconds
}
}
}

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%-5level] %logger{15} - %msg%n%rEx</pattern>
</encoder>
<immediateFlush>false</immediateFlush>
</appender>
<!-- Uncomment for logging ALL HTTP request and responses -->
<!-- <logger name="io.gatling.http.ahc" level="TRACE" /> -->
<!-- <logger name="io.gatling.http.response" level="TRACE" /> -->
<!-- Uncomment for logging ONLY FAILED HTTP request and responses -->
<!-- <logger name="io.gatling.http.ahc" level="DEBUG" /> -->
<!-- <logger name="io.gatling.http.response" level="DEBUG" /> -->
<root level="WARN">
<appender-ref ref="CONSOLE" />
</root>
</configuration>

View File

@ -0,0 +1,26 @@
{{>licenseInfo}}
package {{package}}
{{#imports}}import {{import}}
{{/imports}}
{{#models}}
{{#model}}
case class {{classname}} (
{{#vars}}
{{#description}}
/* {{{description}}} */
{{/description}}
_{{{name}}}: {{^required}}Option[{{/required}}{{datatype}}{{^required}}]{{/required}}{{#hasMore}},{{/hasMore}}
{{/vars}}
)
object {{classname}} {
def toStringBody({{#vars}}var_{{name}}: {{^required}}{{/required}}Object{{^required}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/vars}}) =
s"""
| {
| {{#vars}}"{{{name}}}":$var_{{{name}}}{{#hasMore}},{{/hasMore}}{{/vars}}
| }
""".stripMargin
}
{{/model}}
{{/models}}

View File

@ -0,0 +1,8 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
public final class BuildConfig {
public final static boolean DEBUG = Boolean.parseBoolean(null);
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
public final class Manifest {
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
public final class R {
}

View File

@ -0,0 +1,8 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
public final class BuildConfig {
public final static boolean DEBUG = Boolean.parseBoolean(null);
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
public final class Manifest {
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
public final class R {
}

View File

@ -0,0 +1,8 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
public final class BuildConfig {
public final static boolean DEBUG = Boolean.parseBoolean(null);
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
public final class Manifest {
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
public final class R {
}

View File

@ -0,0 +1,8 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
public final class BuildConfig {
public final static boolean DEBUG = Boolean.parseBoolean(null);
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
public final class Manifest {
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
public final class R {
}

View File

@ -0,0 +1,8 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
public final class BuildConfig {
public final static boolean DEBUG = Boolean.parseBoolean(null);
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
public final class Manifest {
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
public final class R {
}

View File

@ -0,0 +1,8 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
public final class BuildConfig {
public final static boolean DEBUG = Boolean.parseBoolean(null);
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
public final class Manifest {
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
public final class R {
}

View File

@ -0,0 +1,8 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
public final class BuildConfig {
public final static boolean DEBUG = Boolean.parseBoolean(null);
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
public final class Manifest {
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
public final class R {
}

View File

@ -0,0 +1,8 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
public final class BuildConfig {
public final static boolean DEBUG = Boolean.parseBoolean(null);
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
public final class Manifest {
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
public final class R {
}

View File

@ -0,0 +1,8 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
public final class BuildConfig {
public final static boolean DEBUG = Boolean.parseBoolean(null);
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
public final class Manifest {
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
public final class R {
}

View File

@ -0,0 +1,8 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
public final class BuildConfig {
public final static boolean DEBUG = Boolean.parseBoolean(null);
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
public final class Manifest {
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
public final class R {
}

View File

@ -0,0 +1,8 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
public final class BuildConfig {
public final static boolean DEBUG = Boolean.parseBoolean(null);
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
public final class Manifest {
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
public final class R {
}

View File

@ -0,0 +1,8 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
public final class BuildConfig {
public final static boolean DEBUG = Boolean.parseBoolean(null);
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
public final class Manifest {
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
public final class R {
}

View File

@ -0,0 +1,8 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
public final class BuildConfig {
public final static boolean DEBUG = Boolean.parseBoolean(null);
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
public final class Manifest {
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
public final class R {
}

View File

@ -0,0 +1,8 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
public final class BuildConfig {
public final static boolean DEBUG = Boolean.parseBoolean(null);
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
public final class Manifest {
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
public final class R {
}

View File

@ -0,0 +1,8 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
public final class BuildConfig {
public final static boolean DEBUG = Boolean.parseBoolean(null);
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
public final class Manifest {
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
public final class R {
}

View File

@ -0,0 +1,8 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
public final class BuildConfig {
public final static boolean DEBUG = Boolean.parseBoolean(null);
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
public final class Manifest {
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
public final class R {
}

View File

@ -0,0 +1,8 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
public final class BuildConfig {
public final static boolean DEBUG = Boolean.parseBoolean(null);
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
public final class Manifest {
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
public final class R {
}

View File

@ -0,0 +1,8 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
public final class BuildConfig {
public final static boolean DEBUG = Boolean.parseBoolean(null);
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
public final class Manifest {
}

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package io.swagger.client;
/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
public final class R {
}

View File

@ -0,0 +1,23 @@
# Swagger Codegen Ignore
# Generated by swagger-codegen https://github.com/swagger-api/swagger-codegen
# Use this file to prevent files from being overwritten by the generator.
# The patterns follow closely to .gitignore or .dockerignore.
# As an example, the C# client generator defines ApiClient.cs.
# You can make changes and tell Swagger Codgen to ignore just this file by uncommenting the following line:
#ApiClient.cs
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
#foo/*/qux
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
#foo/**/qux
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
# You can also negate patterns with an exclamation (!).
# For example, you can ignore all files in a docs folder with the file extension .md:
#docs/*.md
# Then explicitly reverse the ignore rule for a single file:
#!docs/README.md

View File

@ -0,0 +1 @@
2.3.0-SNAPSHOT

View File

@ -0,0 +1,29 @@
plugins {
id 'com.github.lkishalmi.gatling' version '0.4.1'
}
repositories {
mavenCentral()
}
dependencies {
}
apply plugin: "com.github.lkishalmi.gatling"
gatling {
toolVersion = '2.3.0'
jvmArgs = ['-server', '-XX:+UseThreadPriorities',
'-XX:ThreadPriorityPolicy=42',
'-Xms2048M', '-Xmx2048M', '-Xmn500M',
'-XX:+HeapDumpOnOutOfMemoryError',
'-XX:+AggressiveOpts',
'-XX:+OptimizeStringConcat',
'-XX:+UseFastAccessorMethods',
'-XX:+UseParNewGC',
'-XX:+UseConcMarkSweepGC',
'-XX:+CMSParallelRemarkEnabled',
'-Djava.net.preferIPv4Stack=true',
'-Djava.net.preferIPv6Addresses=false']
}

View File

@ -0,0 +1,62 @@
performance {
authorizationHeader = "~MANUAL_ENTRY~"
rampUpSeconds = 60
rampDownSeconds = 60
durationSeconds = 360
contentType = "application/json"
acceptType = "application/json"
rateMultiplier = 1
instanceMultiplier = 1
operationsPerSecond {
addPet = 1
deletePet = 1
findPetsByStatus = 1
findPetsByTags = 1
getPetById = 1
updatePet = 1
updatePetWithForm = 1
uploadFile = 1
deleteOrder = 1
getInventory = 1
getOrderById = 1
placeOrder = 1
createUser = 1
createUsersWithArrayInput = 1
createUsersWithListInput = 1
deleteUser = 1
getUserByName = 1
loginUser = 1
logoutUser = 1
updateUser = 1
}
global {
assertions {
responseTime {
min {
lte = 30000
gte = 0
}
max {
lte = 30000
gte = 0
}
mean {
lte = 30000
gte = 0
}
}
failedRequests {
percent {
lte = 5
gte = 0
}
}
successfulRequests {
percent {
lte = 100
gte = 0
}
}
}
}
}

View File

@ -0,0 +1,62 @@
performance {
authorizationHeader = "~MANUAL_ENTRY~"
rampUpSeconds = 60
rampDownSeconds = 60
durationSeconds = 360
contentType = "application/json"
acceptType = "application/json"
rateMultiplier = 1
instanceMultiplier = 1
operationsPerSecond {
addPet = 1
deletePet = 1
findPetsByStatus = 1
findPetsByTags = 1
getPetById = 1
updatePet = 1
updatePetWithForm = 1
uploadFile = 1
deleteOrder = 1
getInventory = 1
getOrderById = 1
placeOrder = 1
createUser = 1
createUsersWithArrayInput = 1
createUsersWithListInput = 1
deleteUser = 1
getUserByName = 1
loginUser = 1
logoutUser = 1
updateUser = 1
}
global {
assertions {
responseTime {
min {
lte = 30000
gte = 0
}
max {
lte = 30000
gte = 0
}
mean {
lte = 30000
gte = 0
}
}
failedRequests {
percent {
lte = 5
gte = 0
}
}
successfulRequests {
percent {
lte = 100
gte = 0
}
}
}
}
}

View File

@ -0,0 +1,62 @@
performance {
authorizationHeader = "~MANUAL_ENTRY~"
rampUpSeconds = 60
rampDownSeconds = 60
durationSeconds = 360
contentType = "application/json"
acceptType = "application/json"
rateMultiplier = 1
instanceMultiplier = 1
operationsPerSecond {
addPet = 1
deletePet = 1
findPetsByStatus = 1
findPetsByTags = 1
getPetById = 1
updatePet = 1
updatePetWithForm = 1
uploadFile = 1
deleteOrder = 1
getInventory = 1
getOrderById = 1
placeOrder = 1
createUser = 1
createUsersWithArrayInput = 1
createUsersWithListInput = 1
deleteUser = 1
getUserByName = 1
loginUser = 1
logoutUser = 1
updateUser = 1
}
global {
assertions {
responseTime {
min {
lte = 30000
gte = 0
}
max {
lte = 30000
gte = 0
}
mean {
lte = 30000
gte = 0
}
}
failedRequests {
percent {
lte = 5
gte = 0
}
}
successfulRequests {
percent {
lte = 100
gte = 0
}
}
}
}
}

View File

@ -0,0 +1,62 @@
performance {
authorizationHeader = "~MANUAL_ENTRY~"
rampUpSeconds = 60
rampDownSeconds = 60
durationSeconds = 360
contentType = "application/json"
acceptType = "application/json"
rateMultiplier = 1
instanceMultiplier = 1
operationsPerSecond {
addPet = 1
deletePet = 1
findPetsByStatus = 1
findPetsByTags = 1
getPetById = 1
updatePet = 1
updatePetWithForm = 1
uploadFile = 1
deleteOrder = 1
getInventory = 1
getOrderById = 1
placeOrder = 1
createUser = 1
createUsersWithArrayInput = 1
createUsersWithListInput = 1
deleteUser = 1
getUserByName = 1
loginUser = 1
logoutUser = 1
updateUser = 1
}
global {
assertions {
responseTime {
min {
lte = 30000
gte = 0
}
max {
lte = 30000
gte = 0
}
mean {
lte = 30000
gte = 0
}
}
failedRequests {
percent {
lte = 5
gte = 0
}
}
successfulRequests {
percent {
lte = 100
gte = 0
}
}
}
}
}

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%-5level] %logger{15} - %msg%n%rEx</pattern>
</encoder>
<immediateFlush>false</immediateFlush>
</appender>
<!-- Uncomment for logging ALL HTTP request and responses -->
<!-- <logger name="io.gatling.http.ahc" level="TRACE" /> -->
<!-- <logger name="io.gatling.http.response" level="TRACE" /> -->
<!-- Uncomment for logging ONLY FAILED HTTP request and responses -->
<!-- <logger name="io.gatling.http.ahc" level="DEBUG" /> -->
<!-- <logger name="io.gatling.http.response" level="DEBUG" /> -->
<root level="WARN">
<appender-ref ref="CONSOLE" />
</root>
</configuration>

View File

@ -0,0 +1,62 @@
performance {
authorizationHeader = "~MANUAL_ENTRY~"
rampUpSeconds = 60
rampDownSeconds = 60
durationSeconds = 360
contentType = "application/json"
acceptType = "application/json"
rateMultiplier = 1
instanceMultiplier = 1
operationsPerSecond {
addPet = 1
deletePet = 1
findPetsByStatus = 1
findPetsByTags = 1
getPetById = 1
updatePet = 1
updatePetWithForm = 1
uploadFile = 1
deleteOrder = 1
getInventory = 1
getOrderById = 1
placeOrder = 1
createUser = 1
createUsersWithArrayInput = 1
createUsersWithListInput = 1
deleteUser = 1
getUserByName = 1
loginUser = 1
logoutUser = 1
updateUser = 1
}
global {
assertions {
responseTime {
min {
lte = 30000
gte = 0
}
max {
lte = 30000
gte = 0
}
mean {
lte = 30000
gte = 0
}
}
failedRequests {
percent {
lte = 5
gte = 0
}
}
successfulRequests {
percent {
lte = 100
gte = 0
}
}
}
}
}

View File

@ -0,0 +1,62 @@
performance {
authorizationHeader = "~MANUAL_ENTRY~"
rampUpSeconds = 60
rampDownSeconds = 60
durationSeconds = 360
contentType = "application/json"
acceptType = "application/json"
rateMultiplier = 1
instanceMultiplier = 1
operationsPerSecond {
addPet = 1
deletePet = 1
findPetsByStatus = 1
findPetsByTags = 1
getPetById = 1
updatePet = 1
updatePetWithForm = 1
uploadFile = 1
deleteOrder = 1
getInventory = 1
getOrderById = 1
placeOrder = 1
createUser = 1
createUsersWithArrayInput = 1
createUsersWithListInput = 1
deleteUser = 1
getUserByName = 1
loginUser = 1
logoutUser = 1
updateUser = 1
}
global {
assertions {
responseTime {
min {
lte = 30000
gte = 0
}
max {
lte = 30000
gte = 0
}
mean {
lte = 30000
gte = 0
}
}
failedRequests {
percent {
lte = 5
gte = 0
}
}
successfulRequests {
percent {
lte = 100
gte = 0
}
}
}
}
}

View File

@ -0,0 +1 @@
photoUrls,name,id,category,tags,status
1 photoUrls name id category tags status

View File

@ -0,0 +1 @@
firstName,lastName,password,userStatus,phone,id,email,username
1 firstName lastName password userStatus phone id email username

View File

@ -0,0 +1 @@
username
1 username

View File

@ -0,0 +1 @@
username,password
1 username password

View File

@ -0,0 +1 @@
petId,quantity,id,shipDate,complete,status
1 petId quantity id shipDate complete status

View File

@ -0,0 +1 @@
photoUrls,name,id,category,tags,status
1 photoUrls name id category tags status

View File

@ -0,0 +1 @@
name,status
1 name status

View File

@ -0,0 +1 @@
firstName,lastName,password,userStatus,phone,id,email,username
1 firstName lastName password userStatus phone id email username

View File

@ -0,0 +1 @@
username
1 username

View File

@ -0,0 +1 @@
file,additionalMetadata
1 file additionalMetadata

View File

@ -0,0 +1,223 @@
package io.swagger.client.api
import io.swagger.client.model._
import com.typesafe.config.ConfigFactory
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import io.gatling.core.structure.PopulationBuilder
import java.io.File
import scala.collection.mutable
class PetApiSimulation extends Simulation {
def getCurrentDirectory = new File("").getAbsolutePath
def userDataDirectory = getCurrentDirectory + "/src/gatling/resources/data"
// basic test setup
val configName = System.getProperty("testConfig", "baseline")
val config = ConfigFactory.load(configName).withFallback(ConfigFactory.load("default"))
val durationSeconds = config.getInt("performance.durationSeconds")
val rampUpSeconds = config.getInt("performance.rampUpSeconds")
val rampDownSeconds = config.getInt("performance.rampDownSeconds")
val authentication = config.getString("performance.authorizationHeader")
val acceptHeader = config.getString("performance.acceptType")
val contentTypeHeader = config.getString("performance.contentType")
val rateMultiplier = config.getDouble("performance.rateMultiplier")
val instanceMultiplier = config.getDouble("performance.instanceMultiplier")
// global assertion data
val globalResponseTimeMinLTE = config.getInt("performance.global.assertions.responseTime.min.lte")
val globalResponseTimeMinGTE = config.getInt("performance.global.assertions.responseTime.min.gte")
val globalResponseTimeMaxLTE = config.getInt("performance.global.assertions.responseTime.max.lte")
val globalResponseTimeMaxGTE = config.getInt("performance.global.assertions.responseTime.max.gte")
val globalResponseTimeMeanLTE = config.getInt("performance.global.assertions.responseTime.mean.lte")
val globalResponseTimeMeanGTE = config.getInt("performance.global.assertions.responseTime.mean.gte")
val globalResponseTimeFailedRequestsPercentLTE = config.getDouble("performance.global.assertions.failedRequests.percent.lte")
val globalResponseTimeFailedRequestsPercentGTE = config.getDouble("performance.global.assertions.failedRequests.percent.gte")
val globalResponseTimeSuccessfulRequestsPercentLTE = config.getDouble("performance.global.assertions.successfulRequests.percent.lte")
val globalResponseTimeSuccessfulRequestsPercentGTE = config.getDouble("performance.global.assertions.successfulRequests.percent.gte")
// Setup http protocol configuration
val httpConf = http
.baseURL("http://petstore.swagger.io/v2")
.doNotTrackHeader("1")
.acceptLanguageHeader("en-US,en;q=0.5")
.acceptEncodingHeader("gzip, deflate")
.userAgentHeader("Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0")
.acceptHeader(acceptHeader)
.contentTypeHeader(contentTypeHeader)
// set authorization header if it has been modified from config
if(!authentication.equals("~MANUAL_ENTRY")){
httpConf.authorizationHeader(authentication)
}
// Setup all the operations per second for the test to ultimately be generated from configs
val addPetPerSecond = config.getDouble("performance.operationsPerSecond.addPet") * rateMultiplier * instanceMultiplier
val deletePetPerSecond = config.getDouble("performance.operationsPerSecond.deletePet") * rateMultiplier * instanceMultiplier
val findPetsByStatusPerSecond = config.getDouble("performance.operationsPerSecond.findPetsByStatus") * rateMultiplier * instanceMultiplier
val findPetsByTagsPerSecond = config.getDouble("performance.operationsPerSecond.findPetsByTags") * rateMultiplier * instanceMultiplier
val getPetByIdPerSecond = config.getDouble("performance.operationsPerSecond.getPetById") * rateMultiplier * instanceMultiplier
val updatePetPerSecond = config.getDouble("performance.operationsPerSecond.updatePet") * rateMultiplier * instanceMultiplier
val updatePetWithFormPerSecond = config.getDouble("performance.operationsPerSecond.updatePetWithForm") * rateMultiplier * instanceMultiplier
val uploadFilePerSecond = config.getDouble("performance.operationsPerSecond.uploadFile") * rateMultiplier * instanceMultiplier
val scenarioBuilders: mutable.MutableList[PopulationBuilder] = new mutable.MutableList[PopulationBuilder]()
// Set up CSV feeders
val addPetBodyFeeder = csv(userDataDirectory + File.separator + "addPet-bodyParams.csv", escapeChar = '\\').random
val deletePetHEADERFeeder = csv(userDataDirectory + File.separator + "deletePet-headerParams.csv").random
val deletePetPATHFeeder = csv(userDataDirectory + File.separator + "deletePet-pathParams.csv").random
val findPetsByStatusQUERYFeeder = csv(userDataDirectory + File.separator + "findPetsByStatus-queryParams.csv").random
val findPetsByTagsQUERYFeeder = csv(userDataDirectory + File.separator + "findPetsByTags-queryParams.csv").random
val getPetByIdPATHFeeder = csv(userDataDirectory + File.separator + "getPetById-pathParams.csv").random
val updatePetBodyFeeder = csv(userDataDirectory + File.separator + "updatePet-bodyParams.csv", escapeChar = '\\').random
val updatePetWithFormFORMFeeder = csv(userDataDirectory + File.separator + "updatePetWithForm-formParams.csv").random
val updatePetWithFormPATHFeeder = csv(userDataDirectory + File.separator + "updatePetWithForm-pathParams.csv").random
val uploadFileFORMFeeder = csv(userDataDirectory + File.separator + "uploadFile-formParams.csv").random
val uploadFilePATHFeeder = csv(userDataDirectory + File.separator + "uploadFile-pathParams.csv").random
// Setup all scenarios
val scnaddPet = scenario("addPetSimulation")
.feed(addPetBodyFeeder)
.exec(http("addPet")
.httpRequest("POST","/pet")
.body(StringBody(Pet.toStringBody("${id}","${category}","${name}","${tags}","${status}","${photoUrls}")))
)
// Run scnaddPet with warm up and reach a constant rate for entire duration
scenarioBuilders += scnaddPet.inject(
rampUsersPerSec(1) to(addPetPerSecond) during(rampUpSeconds),
constantUsersPerSec(addPetPerSecond) during(durationSeconds),
rampUsersPerSec(addPetPerSecond) to(1) during(rampDownSeconds)
)
val scndeletePet = scenario("deletePetSimulation")
.feed(deletePetHEADERFeeder)
.feed(deletePetPATHFeeder)
.exec(http("deletePet")
.httpRequest("DELETE","/pet/${petId}")
.header("api_key","${api_key}")
)
// Run scndeletePet with warm up and reach a constant rate for entire duration
scenarioBuilders += scndeletePet.inject(
rampUsersPerSec(1) to(deletePetPerSecond) during(rampUpSeconds),
constantUsersPerSec(deletePetPerSecond) during(durationSeconds),
rampUsersPerSec(deletePetPerSecond) to(1) during(rampDownSeconds)
)
val scnfindPetsByStatus = scenario("findPetsByStatusSimulation")
.feed(findPetsByStatusQUERYFeeder)
.exec(http("findPetsByStatus")
.httpRequest("GET","/pet/findByStatus")
.queryParam("status","${status}")
)
// Run scnfindPetsByStatus with warm up and reach a constant rate for entire duration
scenarioBuilders += scnfindPetsByStatus.inject(
rampUsersPerSec(1) to(findPetsByStatusPerSecond) during(rampUpSeconds),
constantUsersPerSec(findPetsByStatusPerSecond) during(durationSeconds),
rampUsersPerSec(findPetsByStatusPerSecond) to(1) during(rampDownSeconds)
)
val scnfindPetsByTags = scenario("findPetsByTagsSimulation")
.feed(findPetsByTagsQUERYFeeder)
.exec(http("findPetsByTags")
.httpRequest("GET","/pet/findByTags")
.queryParam("tags","${tags}")
)
// Run scnfindPetsByTags with warm up and reach a constant rate for entire duration
scenarioBuilders += scnfindPetsByTags.inject(
rampUsersPerSec(1) to(findPetsByTagsPerSecond) during(rampUpSeconds),
constantUsersPerSec(findPetsByTagsPerSecond) during(durationSeconds),
rampUsersPerSec(findPetsByTagsPerSecond) to(1) during(rampDownSeconds)
)
val scngetPetById = scenario("getPetByIdSimulation")
.feed(getPetByIdPATHFeeder)
.exec(http("getPetById")
.httpRequest("GET","/pet/${petId}")
)
// Run scngetPetById with warm up and reach a constant rate for entire duration
scenarioBuilders += scngetPetById.inject(
rampUsersPerSec(1) to(getPetByIdPerSecond) during(rampUpSeconds),
constantUsersPerSec(getPetByIdPerSecond) during(durationSeconds),
rampUsersPerSec(getPetByIdPerSecond) to(1) during(rampDownSeconds)
)
val scnupdatePet = scenario("updatePetSimulation")
.feed(updatePetBodyFeeder)
.exec(http("updatePet")
.httpRequest("PUT","/pet")
.body(StringBody(Pet.toStringBody("${id}","${category}","${name}","${tags}","${status}","${photoUrls}")))
)
// Run scnupdatePet with warm up and reach a constant rate for entire duration
scenarioBuilders += scnupdatePet.inject(
rampUsersPerSec(1) to(updatePetPerSecond) during(rampUpSeconds),
constantUsersPerSec(updatePetPerSecond) during(durationSeconds),
rampUsersPerSec(updatePetPerSecond) to(1) during(rampDownSeconds)
)
val scnupdatePetWithForm = scenario("updatePetWithFormSimulation")
.feed(updatePetWithFormFORMFeeder)
.feed(updatePetWithFormPATHFeeder)
.exec(http("updatePetWithForm")
.httpRequest("POST","/pet/${petId}")
.formParam("name","${name}")
.formParam("status","${status}")
)
// Run scnupdatePetWithForm with warm up and reach a constant rate for entire duration
scenarioBuilders += scnupdatePetWithForm.inject(
rampUsersPerSec(1) to(updatePetWithFormPerSecond) during(rampUpSeconds),
constantUsersPerSec(updatePetWithFormPerSecond) during(durationSeconds),
rampUsersPerSec(updatePetWithFormPerSecond) to(1) during(rampDownSeconds)
)
val scnuploadFile = scenario("uploadFileSimulation")
.feed(uploadFileFORMFeeder)
.feed(uploadFilePATHFeeder)
.exec(http("uploadFile")
.httpRequest("POST","/pet/${petId}/uploadImage")
.formParam("file","${file}")
.formParam("additionalMetadata","${additionalMetadata}")
)
// Run scnuploadFile with warm up and reach a constant rate for entire duration
scenarioBuilders += scnuploadFile.inject(
rampUsersPerSec(1) to(uploadFilePerSecond) during(rampUpSeconds),
constantUsersPerSec(uploadFilePerSecond) during(durationSeconds),
rampUsersPerSec(uploadFilePerSecond) to(1) during(rampDownSeconds)
)
setUp(
scenarioBuilders.toList
).protocols(httpConf).assertions(
global.responseTime.min.lte(globalResponseTimeMinLTE),
global.responseTime.min.gte(globalResponseTimeMinGTE),
global.responseTime.max.lte(globalResponseTimeMaxLTE),
global.responseTime.max.gte(globalResponseTimeMaxGTE),
global.responseTime.mean.lte(globalResponseTimeMeanLTE),
global.responseTime.mean.gte(globalResponseTimeMeanGTE),
global.failedRequests.percent.lte(globalResponseTimeFailedRequestsPercentLTE),
global.failedRequests.percent.gte(globalResponseTimeFailedRequestsPercentGTE),
global.successfulRequests.percent.lte(globalResponseTimeSuccessfulRequestsPercentLTE),
global.successfulRequests.percent.gte(globalResponseTimeSuccessfulRequestsPercentGTE)
)
}

View File

@ -0,0 +1,143 @@
package io.swagger.client.api
import io.swagger.client.model._
import com.typesafe.config.ConfigFactory
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import io.gatling.core.structure.PopulationBuilder
import java.io.File
import scala.collection.mutable
class StoreApiSimulation extends Simulation {
def getCurrentDirectory = new File("").getAbsolutePath
def userDataDirectory = getCurrentDirectory + "/src/gatling/resources/data"
// basic test setup
val configName = System.getProperty("testConfig", "baseline")
val config = ConfigFactory.load(configName).withFallback(ConfigFactory.load("default"))
val durationSeconds = config.getInt("performance.durationSeconds")
val rampUpSeconds = config.getInt("performance.rampUpSeconds")
val rampDownSeconds = config.getInt("performance.rampDownSeconds")
val authentication = config.getString("performance.authorizationHeader")
val acceptHeader = config.getString("performance.acceptType")
val contentTypeHeader = config.getString("performance.contentType")
val rateMultiplier = config.getDouble("performance.rateMultiplier")
val instanceMultiplier = config.getDouble("performance.instanceMultiplier")
// global assertion data
val globalResponseTimeMinLTE = config.getInt("performance.global.assertions.responseTime.min.lte")
val globalResponseTimeMinGTE = config.getInt("performance.global.assertions.responseTime.min.gte")
val globalResponseTimeMaxLTE = config.getInt("performance.global.assertions.responseTime.max.lte")
val globalResponseTimeMaxGTE = config.getInt("performance.global.assertions.responseTime.max.gte")
val globalResponseTimeMeanLTE = config.getInt("performance.global.assertions.responseTime.mean.lte")
val globalResponseTimeMeanGTE = config.getInt("performance.global.assertions.responseTime.mean.gte")
val globalResponseTimeFailedRequestsPercentLTE = config.getDouble("performance.global.assertions.failedRequests.percent.lte")
val globalResponseTimeFailedRequestsPercentGTE = config.getDouble("performance.global.assertions.failedRequests.percent.gte")
val globalResponseTimeSuccessfulRequestsPercentLTE = config.getDouble("performance.global.assertions.successfulRequests.percent.lte")
val globalResponseTimeSuccessfulRequestsPercentGTE = config.getDouble("performance.global.assertions.successfulRequests.percent.gte")
// Setup http protocol configuration
val httpConf = http
.baseURL("http://petstore.swagger.io/v2")
.doNotTrackHeader("1")
.acceptLanguageHeader("en-US,en;q=0.5")
.acceptEncodingHeader("gzip, deflate")
.userAgentHeader("Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0")
.acceptHeader(acceptHeader)
.contentTypeHeader(contentTypeHeader)
// set authorization header if it has been modified from config
if(!authentication.equals("~MANUAL_ENTRY")){
httpConf.authorizationHeader(authentication)
}
// Setup all the operations per second for the test to ultimately be generated from configs
val deleteOrderPerSecond = config.getDouble("performance.operationsPerSecond.deleteOrder") * rateMultiplier * instanceMultiplier
val getInventoryPerSecond = config.getDouble("performance.operationsPerSecond.getInventory") * rateMultiplier * instanceMultiplier
val getOrderByIdPerSecond = config.getDouble("performance.operationsPerSecond.getOrderById") * rateMultiplier * instanceMultiplier
val placeOrderPerSecond = config.getDouble("performance.operationsPerSecond.placeOrder") * rateMultiplier * instanceMultiplier
val scenarioBuilders: mutable.MutableList[PopulationBuilder] = new mutable.MutableList[PopulationBuilder]()
// Set up CSV feeders
val deleteOrderPATHFeeder = csv(userDataDirectory + File.separator + "deleteOrder-pathParams.csv").random
val getOrderByIdPATHFeeder = csv(userDataDirectory + File.separator + "getOrderById-pathParams.csv").random
val placeOrderBodyFeeder = csv(userDataDirectory + File.separator + "placeOrder-bodyParams.csv", escapeChar = '\\').random
// Setup all scenarios
val scndeleteOrder = scenario("deleteOrderSimulation")
.feed(deleteOrderPATHFeeder)
.exec(http("deleteOrder")
.httpRequest("DELETE","/store/order/${orderId}")
)
// Run scndeleteOrder with warm up and reach a constant rate for entire duration
scenarioBuilders += scndeleteOrder.inject(
rampUsersPerSec(1) to(deleteOrderPerSecond) during(rampUpSeconds),
constantUsersPerSec(deleteOrderPerSecond) during(durationSeconds),
rampUsersPerSec(deleteOrderPerSecond) to(1) during(rampDownSeconds)
)
val scngetInventory = scenario("getInventorySimulation")
.exec(http("getInventory")
.httpRequest("GET","/store/inventory")
)
// Run scngetInventory with warm up and reach a constant rate for entire duration
scenarioBuilders += scngetInventory.inject(
rampUsersPerSec(1) to(getInventoryPerSecond) during(rampUpSeconds),
constantUsersPerSec(getInventoryPerSecond) during(durationSeconds),
rampUsersPerSec(getInventoryPerSecond) to(1) during(rampDownSeconds)
)
val scngetOrderById = scenario("getOrderByIdSimulation")
.feed(getOrderByIdPATHFeeder)
.exec(http("getOrderById")
.httpRequest("GET","/store/order/${orderId}")
)
// Run scngetOrderById with warm up and reach a constant rate for entire duration
scenarioBuilders += scngetOrderById.inject(
rampUsersPerSec(1) to(getOrderByIdPerSecond) during(rampUpSeconds),
constantUsersPerSec(getOrderByIdPerSecond) during(durationSeconds),
rampUsersPerSec(getOrderByIdPerSecond) to(1) during(rampDownSeconds)
)
val scnplaceOrder = scenario("placeOrderSimulation")
.feed(placeOrderBodyFeeder)
.exec(http("placeOrder")
.httpRequest("POST","/store/order")
.body(StringBody(Order.toStringBody("${id}","${shipDate}","${complete}","${quantity}","${status}","${petId}")))
)
// Run scnplaceOrder with warm up and reach a constant rate for entire duration
scenarioBuilders += scnplaceOrder.inject(
rampUsersPerSec(1) to(placeOrderPerSecond) during(rampUpSeconds),
constantUsersPerSec(placeOrderPerSecond) during(durationSeconds),
rampUsersPerSec(placeOrderPerSecond) to(1) during(rampDownSeconds)
)
setUp(
scenarioBuilders.toList
).protocols(httpConf).assertions(
global.responseTime.min.lte(globalResponseTimeMinLTE),
global.responseTime.min.gte(globalResponseTimeMinGTE),
global.responseTime.max.lte(globalResponseTimeMaxLTE),
global.responseTime.max.gte(globalResponseTimeMaxGTE),
global.responseTime.mean.lte(globalResponseTimeMeanLTE),
global.responseTime.mean.gte(globalResponseTimeMeanGTE),
global.failedRequests.percent.lte(globalResponseTimeFailedRequestsPercentLTE),
global.failedRequests.percent.gte(globalResponseTimeFailedRequestsPercentGTE),
global.successfulRequests.percent.lte(globalResponseTimeSuccessfulRequestsPercentLTE),
global.successfulRequests.percent.gte(globalResponseTimeSuccessfulRequestsPercentGTE)
)
}

View File

@ -0,0 +1,210 @@
package io.swagger.client.api
import io.swagger.client.model._
import com.typesafe.config.ConfigFactory
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import io.gatling.core.structure.PopulationBuilder
import java.io.File
import scala.collection.mutable
class UserApiSimulation extends Simulation {
def getCurrentDirectory = new File("").getAbsolutePath
def userDataDirectory = getCurrentDirectory + "/src/gatling/resources/data"
// basic test setup
val configName = System.getProperty("testConfig", "baseline")
val config = ConfigFactory.load(configName).withFallback(ConfigFactory.load("default"))
val durationSeconds = config.getInt("performance.durationSeconds")
val rampUpSeconds = config.getInt("performance.rampUpSeconds")
val rampDownSeconds = config.getInt("performance.rampDownSeconds")
val authentication = config.getString("performance.authorizationHeader")
val acceptHeader = config.getString("performance.acceptType")
val contentTypeHeader = config.getString("performance.contentType")
val rateMultiplier = config.getDouble("performance.rateMultiplier")
val instanceMultiplier = config.getDouble("performance.instanceMultiplier")
// global assertion data
val globalResponseTimeMinLTE = config.getInt("performance.global.assertions.responseTime.min.lte")
val globalResponseTimeMinGTE = config.getInt("performance.global.assertions.responseTime.min.gte")
val globalResponseTimeMaxLTE = config.getInt("performance.global.assertions.responseTime.max.lte")
val globalResponseTimeMaxGTE = config.getInt("performance.global.assertions.responseTime.max.gte")
val globalResponseTimeMeanLTE = config.getInt("performance.global.assertions.responseTime.mean.lte")
val globalResponseTimeMeanGTE = config.getInt("performance.global.assertions.responseTime.mean.gte")
val globalResponseTimeFailedRequestsPercentLTE = config.getDouble("performance.global.assertions.failedRequests.percent.lte")
val globalResponseTimeFailedRequestsPercentGTE = config.getDouble("performance.global.assertions.failedRequests.percent.gte")
val globalResponseTimeSuccessfulRequestsPercentLTE = config.getDouble("performance.global.assertions.successfulRequests.percent.lte")
val globalResponseTimeSuccessfulRequestsPercentGTE = config.getDouble("performance.global.assertions.successfulRequests.percent.gte")
// Setup http protocol configuration
val httpConf = http
.baseURL("http://petstore.swagger.io/v2")
.doNotTrackHeader("1")
.acceptLanguageHeader("en-US,en;q=0.5")
.acceptEncodingHeader("gzip, deflate")
.userAgentHeader("Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0")
.acceptHeader(acceptHeader)
.contentTypeHeader(contentTypeHeader)
// set authorization header if it has been modified from config
if(!authentication.equals("~MANUAL_ENTRY")){
httpConf.authorizationHeader(authentication)
}
// Setup all the operations per second for the test to ultimately be generated from configs
val createUserPerSecond = config.getDouble("performance.operationsPerSecond.createUser") * rateMultiplier * instanceMultiplier
val createUsersWithArrayInputPerSecond = config.getDouble("performance.operationsPerSecond.createUsersWithArrayInput") * rateMultiplier * instanceMultiplier
val createUsersWithListInputPerSecond = config.getDouble("performance.operationsPerSecond.createUsersWithListInput") * rateMultiplier * instanceMultiplier
val deleteUserPerSecond = config.getDouble("performance.operationsPerSecond.deleteUser") * rateMultiplier * instanceMultiplier
val getUserByNamePerSecond = config.getDouble("performance.operationsPerSecond.getUserByName") * rateMultiplier * instanceMultiplier
val loginUserPerSecond = config.getDouble("performance.operationsPerSecond.loginUser") * rateMultiplier * instanceMultiplier
val logoutUserPerSecond = config.getDouble("performance.operationsPerSecond.logoutUser") * rateMultiplier * instanceMultiplier
val updateUserPerSecond = config.getDouble("performance.operationsPerSecond.updateUser") * rateMultiplier * instanceMultiplier
val scenarioBuilders: mutable.MutableList[PopulationBuilder] = new mutable.MutableList[PopulationBuilder]()
// Set up CSV feeders
val createUserBodyFeeder = csv(userDataDirectory + File.separator + "createUser-bodyParams.csv", escapeChar = '\\').random
val deleteUserPATHFeeder = csv(userDataDirectory + File.separator + "deleteUser-pathParams.csv").random
val getUserByNamePATHFeeder = csv(userDataDirectory + File.separator + "getUserByName-pathParams.csv").random
val loginUserQUERYFeeder = csv(userDataDirectory + File.separator + "loginUser-queryParams.csv").random
val updateUserPATHFeeder = csv(userDataDirectory + File.separator + "updateUser-pathParams.csv").random
val updateUserBodyFeeder = csv(userDataDirectory + File.separator + "updateUser-bodyParams.csv", escapeChar = '\\').random
// Setup all scenarios
val scncreateUser = scenario("createUserSimulation")
.feed(createUserBodyFeeder)
.exec(http("createUser")
.httpRequest("POST","/user")
.body(StringBody(User.toStringBody("${password}","${id}","${lastName}","${firstName}","${email}","${userStatus}","${phone}","${username}")))
)
// Run scncreateUser with warm up and reach a constant rate for entire duration
scenarioBuilders += scncreateUser.inject(
rampUsersPerSec(1) to(createUserPerSecond) during(rampUpSeconds),
constantUsersPerSec(createUserPerSecond) during(durationSeconds),
rampUsersPerSec(createUserPerSecond) to(1) during(rampDownSeconds)
)
val scncreateUsersWithArrayInput = scenario("createUsersWithArrayInputSimulation")
.exec(http("createUsersWithArrayInput")
.httpRequest("POST","/user/createWithArray")
.body(StringBody(StringBody("[]")))
)
// Run scncreateUsersWithArrayInput with warm up and reach a constant rate for entire duration
scenarioBuilders += scncreateUsersWithArrayInput.inject(
rampUsersPerSec(1) to(createUsersWithArrayInputPerSecond) during(rampUpSeconds),
constantUsersPerSec(createUsersWithArrayInputPerSecond) during(durationSeconds),
rampUsersPerSec(createUsersWithArrayInputPerSecond) to(1) during(rampDownSeconds)
)
val scncreateUsersWithListInput = scenario("createUsersWithListInputSimulation")
.exec(http("createUsersWithListInput")
.httpRequest("POST","/user/createWithList")
.body(StringBody(StringBody("[]")))
)
// Run scncreateUsersWithListInput with warm up and reach a constant rate for entire duration
scenarioBuilders += scncreateUsersWithListInput.inject(
rampUsersPerSec(1) to(createUsersWithListInputPerSecond) during(rampUpSeconds),
constantUsersPerSec(createUsersWithListInputPerSecond) during(durationSeconds),
rampUsersPerSec(createUsersWithListInputPerSecond) to(1) during(rampDownSeconds)
)
val scndeleteUser = scenario("deleteUserSimulation")
.feed(deleteUserPATHFeeder)
.exec(http("deleteUser")
.httpRequest("DELETE","/user/${username}")
)
// Run scndeleteUser with warm up and reach a constant rate for entire duration
scenarioBuilders += scndeleteUser.inject(
rampUsersPerSec(1) to(deleteUserPerSecond) during(rampUpSeconds),
constantUsersPerSec(deleteUserPerSecond) during(durationSeconds),
rampUsersPerSec(deleteUserPerSecond) to(1) during(rampDownSeconds)
)
val scngetUserByName = scenario("getUserByNameSimulation")
.feed(getUserByNamePATHFeeder)
.exec(http("getUserByName")
.httpRequest("GET","/user/${username}")
)
// Run scngetUserByName with warm up and reach a constant rate for entire duration
scenarioBuilders += scngetUserByName.inject(
rampUsersPerSec(1) to(getUserByNamePerSecond) during(rampUpSeconds),
constantUsersPerSec(getUserByNamePerSecond) during(durationSeconds),
rampUsersPerSec(getUserByNamePerSecond) to(1) during(rampDownSeconds)
)
val scnloginUser = scenario("loginUserSimulation")
.feed(loginUserQUERYFeeder)
.exec(http("loginUser")
.httpRequest("GET","/user/login")
.queryParam("username","${username}")
.queryParam("password","${password}")
)
// Run scnloginUser with warm up and reach a constant rate for entire duration
scenarioBuilders += scnloginUser.inject(
rampUsersPerSec(1) to(loginUserPerSecond) during(rampUpSeconds),
constantUsersPerSec(loginUserPerSecond) during(durationSeconds),
rampUsersPerSec(loginUserPerSecond) to(1) during(rampDownSeconds)
)
val scnlogoutUser = scenario("logoutUserSimulation")
.exec(http("logoutUser")
.httpRequest("GET","/user/logout")
)
// Run scnlogoutUser with warm up and reach a constant rate for entire duration
scenarioBuilders += scnlogoutUser.inject(
rampUsersPerSec(1) to(logoutUserPerSecond) during(rampUpSeconds),
constantUsersPerSec(logoutUserPerSecond) during(durationSeconds),
rampUsersPerSec(logoutUserPerSecond) to(1) during(rampDownSeconds)
)
val scnupdateUser = scenario("updateUserSimulation")
.feed(updateUserBodyFeeder)
.feed(updateUserPATHFeeder)
.exec(http("updateUser")
.httpRequest("PUT","/user/${username}")
.body(StringBody(User.toStringBody("${password}","${id}","${lastName}","${firstName}","${email}","${userStatus}","${phone}","${username}")))
)
// Run scnupdateUser with warm up and reach a constant rate for entire duration
scenarioBuilders += scnupdateUser.inject(
rampUsersPerSec(1) to(updateUserPerSecond) during(rampUpSeconds),
constantUsersPerSec(updateUserPerSecond) during(durationSeconds),
rampUsersPerSec(updateUserPerSecond) to(1) during(rampDownSeconds)
)
setUp(
scenarioBuilders.toList
).protocols(httpConf).assertions(
global.responseTime.min.lte(globalResponseTimeMinLTE),
global.responseTime.min.gte(globalResponseTimeMinGTE),
global.responseTime.max.lte(globalResponseTimeMaxLTE),
global.responseTime.max.gte(globalResponseTimeMaxGTE),
global.responseTime.mean.lte(globalResponseTimeMeanLTE),
global.responseTime.mean.gte(globalResponseTimeMeanGTE),
global.failedRequests.percent.lte(globalResponseTimeFailedRequestsPercentLTE),
global.failedRequests.percent.gte(globalResponseTimeFailedRequestsPercentGTE),
global.successfulRequests.percent.lte(globalResponseTimeSuccessfulRequestsPercentLTE),
global.successfulRequests.percent.gte(globalResponseTimeSuccessfulRequestsPercentGTE)
)
}

View File

@ -0,0 +1,17 @@
package io.swagger.client.model
case class ApiResponse (
_code: Option[Integer],
_type: Option[String],
_message: Option[String]
)
object ApiResponse {
def toStringBody(var_code: Object, var_type: Object, var_message: Object) =
s"""
| {
| "code":$var_code,"type":$var_type,"message":$var_message
| }
""".stripMargin
}

View File

@ -0,0 +1,16 @@
package io.swagger.client.model
case class Category (
_id: Option[Long],
_name: Option[String]
)
object Category {
def toStringBody(var_id: Object, var_name: Object) =
s"""
| {
| "id":$var_id,"name":$var_name
| }
""".stripMargin
}

View File

@ -0,0 +1,22 @@
package io.swagger.client.model
import java.util.Date
case class Order (
_id: Option[Long],
_petId: Option[Long],
_quantity: Option[Integer],
_shipDate: Option[Date],
/* Order Status */
_status: Option[String],
_complete: Option[Boolean]
)
object Order {
def toStringBody(var_id: Object, var_petId: Object, var_quantity: Object, var_shipDate: Object, var_status: Object, var_complete: Object) =
s"""
| {
| "id":$var_id,"petId":$var_petId,"quantity":$var_quantity,"shipDate":$var_shipDate,"status":$var_status,"complete":$var_complete
| }
""".stripMargin
}

Some files were not shown because too many files have changed in this diff Show More