diff --git a/gatling/pom.xml b/gatling/pom.xml new file mode 100644 index 0000000000..273797d76c --- /dev/null +++ b/gatling/pom.xml @@ -0,0 +1,110 @@ + + + 4.0.0 + org.baeldung + gatling + 1.0-SNAPSHOT + + + 1.8 + 1.8 + 2.11.7 + UTF-8 + 2.2.0 + 3.2.2 + + + + + + io.gatling + gatling-app + ${gatling.version} + + + io.gatling + gatling-recorder + ${gatling.version} + + + io.gatling.highcharts + gatling-charts-highcharts + ${gatling.version} + + + org.scala-lang + scala-library + ${scala.version} + + + + + + + io.gatling.highcharts + gatling-charts-highcharts + + + io.gatling + gatling-app + + + io.gatling + gatling-recorder + + + org.scala-lang + scala-library + + + + + src/test/scala + + + + net.alchim31.maven + scala-maven-plugin + ${scala-maven-plugin.version} + + + + + + net.alchim31.maven + scala-maven-plugin + + + + testCompile + + + + -Ybackend:GenBCode + -Ydelambdafy:method + -target:jvm-1.8 + -deprecation + -feature + -unchecked + -language:implicitConversions + -language:postfixOps + + + + + + + io.gatling + gatling-maven-plugin + ${gatling.version} + + + test + execute + + + + + + diff --git a/gatling/src/test/resources/gatling.conf b/gatling/src/test/resources/gatling.conf new file mode 100644 index 0000000000..8bfa0ed366 --- /dev/null +++ b/gatling/src/test/resources/gatling.conf @@ -0,0 +1,127 @@ +######################### +# 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 + + 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 = 60000 # Timeout when establishing a connection + #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 + #acceptAnyCertificate = true # When set to true, doesn't validate SSL certificates + #httpClientCodecMaxInitialLineLength = 4096 # Maximum length of the initial line of the response (e.g. "HTTP/1.0 200 OK") + #httpClientCodecMaxHeaderSize = 8192 # Maximum size, in bytes, of each request's headers + #httpClientCodecMaxChunkSize = 8192 # Maximum length of the content or each chunk + #webSocketMaxFrameSize = 10240000 # Maximum frame payload 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 JDK 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) + #usePooledMemory = true # if Gatling should use pooled memory + #tcpNoDelay = true + #soReuseAddress = false + #soLinger = -1 + #soSndBuf = -1 + #soRcvBuf = -1 + } + dns { + #queryTimeout = 5000 # Timeout of each DNS query in millis + #maxQueriesPerResolve = 3 # Maximum allowed number of DNS queries for a given name resolution + } + } + 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 + } + } +} diff --git a/gatling/src/test/resources/logback.xml b/gatling/src/test/resources/logback.xml new file mode 100644 index 0000000000..b9ba6255a0 --- /dev/null +++ b/gatling/src/test/resources/logback.xml @@ -0,0 +1,22 @@ + + + + + + %d{HH:mm:ss.SSS} [%-5level] %logger{15} - %msg%n%rEx + false + + + + + + + + + + + + + + + diff --git a/gatling/src/test/resources/recorder.conf b/gatling/src/test/resources/recorder.conf new file mode 100644 index 0000000000..969b9e8668 --- /dev/null +++ b/gatling/src/test/resources/recorder.conf @@ -0,0 +1,53 @@ +recorder { + core { + #mode = "Proxy" + #encoding = "utf-8" # The encoding used for reading/writing request bodies and the generated simulation + #outputFolder = "" # The folder where generated simulation will we written + #package = "" # The package's name of the generated simulation + #className = "RecordedSimulation" # The name of the generated Simulation class + #thresholdForPauseCreation = 100 # The minimum time, in milliseconds, that must pass between requests to trigger a pause creation + #saveConfig = false # When set to true, the configuration from the Recorder GUI overwrites this configuration + #headless = false # When set to true, run the Recorder in headless mode instead of the GUI + #harFilePath = "" # The path of the HAR file to convert + } + filters { + #filterStrategy = "Disabled" # The selected filter resources filter strategy (currently supported : "Disabled", "BlackList", "WhiteList") + #whitelist = [] # The list of ressources patterns that are part of the Recorder's whitelist + #blacklist = [] # The list of ressources patterns that are part of the Recorder's blacklist + } + http { + #automaticReferer = true # When set to false, write the referer + enable 'disableAutoReferer' in the generated simulation + #followRedirect = true # When set to false, write redirect requests + enable 'disableFollowRedirect' in the generated simulation + #removeCacheHeaders = true # When set to true, removes from the generated requests headers leading to request caching + #inferHtmlResources = true # When set to true, add inferred resources + set 'inferHtmlResources' with the configured blacklist/whitelist in the generated simulation + #checkResponseBodies = false # When set to true, save response bodies as files and add raw checks in the generated simulation + } + proxy { + #port = 8000 # Local port used by Gatling's Proxy for HTTP/HTTPS + https { + #mode = "SelfSignedCertificate" # The selected "HTTPS mode" (currently supported : "SelfSignedCertificate", "ProvidedKeyStore", "GatlingCertificateAuthority", "CustomCertificateAuthority") + keyStore { + #path = "" # The path of the custom key store + #password = "" # The password for this key store + #type = "JKS" # The type of the key store (currently supported: "JKS") + } + certificateAuthority { + #certificatePath = "" # The path of the custom certificate + #privateKeyPath = "" # The certificate's private key path + } + } + outgoing { + #host = "" # The outgoing proxy's hostname + #username = "" # The username to use to connect to the outgoing proxy + #password = "" # The password corresponding to the user to use to connect to the outgoing proxy + #port = 0 # The HTTP port to use to connect to the outgoing proxy + #sslPort = 0 # If set, The HTTPS port to use to connect to the outgoing proxy + } + } + netty { + #maxInitialLineLength = 10000 # Maximum length of the initial line of the response (e.g. "HTTP/1.0 200 OK") + #maxHeaderSize = 20000 # Maximum size, in bytes, of each request's headers + #maxChunkSize = 8192 # Maximum length of the content or each chunk + #maxContentLength = 100000000 # Maximum length of the aggregated content of each response + } +} diff --git a/gatling/src/test/scala/Engine.scala b/gatling/src/test/scala/Engine.scala new file mode 100644 index 0000000000..32c85fbe45 --- /dev/null +++ b/gatling/src/test/scala/Engine.scala @@ -0,0 +1,13 @@ +import io.gatling.app.Gatling +import io.gatling.core.config.GatlingPropertiesBuilder + +object Engine extends App { + + val props = new GatlingPropertiesBuilder + props.dataDirectory(IDEPathHelper.dataDirectory.toString) + props.resultsDirectory(IDEPathHelper.resultsDirectory.toString) + props.bodiesDirectory(IDEPathHelper.bodiesDirectory.toString) + props.binariesDirectory(IDEPathHelper.mavenBinariesDirectory.toString) + + Gatling.fromMap(props.build) +} diff --git a/gatling/src/test/scala/IDEPathHelper.scala b/gatling/src/test/scala/IDEPathHelper.scala new file mode 100644 index 0000000000..0abf6a42ef --- /dev/null +++ b/gatling/src/test/scala/IDEPathHelper.scala @@ -0,0 +1,22 @@ +import java.nio.file.Path + +import io.gatling.commons.util.PathHelper._ + +object IDEPathHelper { + + val gatlingConfUrl: Path = getClass.getClassLoader.getResource("gatling.conf").toURI + val projectRootDir = gatlingConfUrl.ancestor(3) + + val mavenSourcesDirectory = projectRootDir / "src" / "test" / "scala" + val mavenResourcesDirectory = projectRootDir / "src" / "test" / "resources" + val mavenTargetDirectory = projectRootDir / "target" + val mavenBinariesDirectory = mavenTargetDirectory / "test-classes" + + val dataDirectory = mavenResourcesDirectory / "data" + val bodiesDirectory = mavenResourcesDirectory / "bodies" + + val recorderOutputDirectory = mavenSourcesDirectory + val resultsDirectory = mavenTargetDirectory / "gatling" + + val recorderConfigFile = mavenResourcesDirectory / "recorder.conf" +} diff --git a/gatling/src/test/scala/Recorder.scala b/gatling/src/test/scala/Recorder.scala new file mode 100644 index 0000000000..6ad320618b --- /dev/null +++ b/gatling/src/test/scala/Recorder.scala @@ -0,0 +1,12 @@ +import io.gatling.recorder.GatlingRecorder +import io.gatling.recorder.config.RecorderPropertiesBuilder + +object Recorder extends App { + + val props = new RecorderPropertiesBuilder + props.simulationOutputFolder(IDEPathHelper.recorderOutputDirectory.toString) + props.simulationPackage("org.baeldung") + props.bodiesFolder(IDEPathHelper.bodiesDirectory.toString) + + GatlingRecorder.fromMap(props.build, Some(IDEPathHelper.recorderConfigFile)) +} diff --git a/gatling/src/test/scala/org/baeldung/RecordedSimulation.scala b/gatling/src/test/scala/org/baeldung/RecordedSimulation.scala new file mode 100644 index 0000000000..cdbef1bf3c --- /dev/null +++ b/gatling/src/test/scala/org/baeldung/RecordedSimulation.scala @@ -0,0 +1,46 @@ +package org.baeldung + +import scala.concurrent.duration._ + +import io.gatling.core.Predef._ +import io.gatling.http.Predef._ +import io.gatling.jdbc.Predef._ + +class RecordedSimulation extends Simulation { + + val httpProtocol = http + .baseURL("http://computer-database.gatling.io") + .inferHtmlResources(BlackList(""".*\.css""", """.*\.js""", """.*\.ico"""), WhiteList()) + .acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8") + .acceptEncodingHeader("gzip, deflate") + .acceptLanguageHeader("it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3") + .userAgentHeader("Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0") + + + + + + val scn = scenario("RecordedSimulation") + .exec(http("request_0") + .get("/")) + .pause(5) + .exec(http("request_1") + .get("/computers?f=amstrad")) + .pause(4) + .exec(http("request_2") + .get("/computers/412")) + .pause(2) + .exec(http("request_3") + .get("/")) + .pause(2) + .exec(http("request_4") + .get("/computers?p=1")) + .pause(1) + .exec(http("request_5") + .get("/computers?p=2")) + .pause(2) + .exec(http("request_6") + .get("/computers?p=3")) + + setUp(scn.inject(atOnceUsers(1))).protocols(httpProtocol) +}