├── .editorconfig ├── .gitignore ├── .release-it.json ├── .travis.yml ├── LICENSE ├── README.adoc ├── bootstrap.sh ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── nb-actions.xml ├── sample-project ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── src │ └── gatling │ ├── resources │ └── search.csv │ └── simulations │ └── SampleSimulation.scala ├── src ├── main │ ├── groovy │ │ └── com │ │ │ └── github │ │ │ └── lkishalmi │ │ │ └── gradle │ │ │ └── gatling │ │ │ ├── GatlingPlugin.groovy │ │ │ ├── GatlingPluginExtension.groovy │ │ │ ├── GatlingRunTask.groovy │ │ │ ├── JvmConfigurable.groovy │ │ │ └── LogbackConfigTaskAction.groovy │ └── resources │ │ └── META-INF │ │ └── gradle-plugins │ │ └── com.github.lkishalmi.gatling.properties └── test │ ├── groovy │ ├── functional │ │ ├── GradleCompatibilitySpec.groovy │ │ ├── LogbackConfigTaskActionTest.groovy │ │ ├── WhenCompileSimulationSpec.groovy │ │ ├── WhenRunFailingSimulationSpec.groovy │ │ ├── WhenRunSimulationSpec.groovy │ │ └── WhenRunSimulationSysPropsJvmArgsSpec.groovy │ ├── helper │ │ ├── GatlingDebug.groovy │ │ ├── GatlingFuncSpec.groovy │ │ ├── GatlingSpec.groovy │ │ └── GatlingUnitSpec.groovy │ └── unit │ │ ├── GatlingPluginTest.groovy │ │ └── GatlingRunTaskTest.groovy │ └── resources │ ├── gatling-debug │ └── src │ │ └── gatling │ │ ├── resources │ │ └── .gitkeep │ │ └── simulations │ │ └── GatlingDebugSimulation.scala │ └── gradle-layout │ └── src │ ├── gatling │ ├── resources │ │ └── search.csv │ └── simulations │ │ └── computerdatabase │ │ ├── BasicSimulation.scala │ │ └── advanced │ │ └── AdvancedSimulationStep03.scala │ ├── main │ └── java │ │ └── computerdatabase │ │ └── MainUtils.java │ └── test │ └── java │ └── computerdatabase │ └── TestUtils.java └── travis_build.sh /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | indent_style = space 9 | 10 | [*.groovy] 11 | indent_size = 4 12 | max_line_length=180 13 | 14 | [*.{yml,yaml,conf,json,avsc,gradle}] 15 | indent_size = 2 16 | 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /src/test/resources/gradle-layout/userHome 2 | /.idea 3 | /gradle-gatling-plugin.iml 4 | .gradle 5 | build/ 6 | 7 | *.iml 8 | out 9 | 10 | # Ignore Gradle GUI config 11 | gradle-app.setting 12 | 13 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 14 | !gradle-wrapper.jar 15 | 16 | .DS_Store -------------------------------------------------------------------------------- /.release-it.json: -------------------------------------------------------------------------------- 1 | { 2 | "git": { 3 | "requireCommits": true, 4 | "commit": false, 5 | "push": true, 6 | "tag": true 7 | }, 8 | 9 | "npm": { 10 | "publish": false 11 | }, 12 | 13 | "github": { 14 | "release": true 15 | }, 16 | 17 | "plugins": { 18 | "@release-it/conventional-changelog": { 19 | "preset": "angular" 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | 3 | dist: xenial 4 | 5 | jdk: 6 | - openjdk8 7 | 8 | before_cache: 9 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock 10 | - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ 11 | cache: 12 | directories: 13 | - $HOME/.gradle/caches/ 14 | - $HOME/.gradle/wrapper/ 15 | 16 | script: ./travis_build.sh 17 | 18 | deploy: 19 | - provider: script 20 | skip_cleanup: true 21 | script: ./gradlew publishPlugin -Pgradle.publish.key=${GRADLE_PUBLISH_KEY} -Pgradle.publish.secret=${GRADLE_PUBLISH_SECRET} -Dorg.gradle.project.version=${TRAVIS_TAG} 22 | on: 23 | tags: true 24 | repo: ${TRAVIS_REPO_SLUG} 25 | 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | = Deprecated: Gatling Plugin for Gradle 2 | :gatlingToolVersion: 3.3.1 3 | :scalaVersion: 2.12.8 4 | :tip-caption: :bulb: 5 | :note-caption: :information_source: 6 | :important-caption: :heavy_exclamation_mark: 7 | :caution-caption: :fire: 8 | :warning-caption: :warning: 9 | 10 | [WARNING] 11 | ==== 12 | Gatling officially supports https://github.com/gatling/gatling-gradle-plugin[Gradle]. 13 | 14 | This plugin is deprecated and unsupported. 15 | ==== 16 | -------------------------------------------------------------------------------- /bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ $# -ne 1 ]; then 4 | echo "Usage: bootstrap.sh SAMPLE_PROJECT_FOLDER" 5 | exit 1 6 | fi 7 | 8 | DEST=$1 9 | 10 | if [ -a $DEST ]; then 11 | echo "$DEST already exists" 12 | exit 2 13 | fi 14 | 15 | mkdir -p $DEST 16 | cd $DEST 17 | 18 | git init 19 | git remote add origin https://github.com/lkishalmi/gradle-gatling-plugin.git 20 | git config core.sparseCheckout true 21 | echo "sample-project/" >> .git/info/sparse-checkout 22 | git pull origin master 23 | 24 | mv sample-project/* . 25 | rm -rf .git sample-project 26 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java-gradle-plugin' 3 | id 'groovy' 4 | id 'com.gradle.plugin-publish' version '0.11.0' 5 | id 'maven-publish' 6 | } 7 | 8 | description = 'Gatling Plugin for Gradle' 9 | 10 | sourceCompatibility = '1.8' 11 | targetCompatibility = '1.8' 12 | 13 | repositories { 14 | jcenter() 15 | } 16 | 17 | dependencies { 18 | testImplementation('org.spockframework:spock-core:1.3-groovy-2.4') { 19 | exclude module: 'groovy-all' 20 | } 21 | testImplementation 'commons-io:commons-io:2.5' 22 | testImplementation 'com.github.stefanbirkner:system-rules:1.19.0' 23 | } 24 | 25 | test { 26 | testLogging { 27 | events "passed", "skipped", "failed" 28 | exceptionFormat "full" 29 | showStandardStreams = false 30 | } 31 | } 32 | 33 | pluginBundle { 34 | website = 'https://github.com/lkishalmi/gradle-gatling-plugin' 35 | vcsUrl = 'https://github.com/lkishalmi/gradle-gatling-plugin' 36 | description = 'Gatling Simulation Execution' 37 | tags = ['gatling', 'load test', 'stress test', 'performance test', 'scala'] 38 | 39 | plugins { 40 | gatlingPlugin { 41 | displayName = 'Gatling Simulation Execution' 42 | id = 'com.github.lkishalmi.gatling' 43 | } 44 | } 45 | } 46 | 47 | validatePlugins.failOnWarning = false 48 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | group=com.github.lkishalmi.gatling 2 | org.gradle.daemon=true 3 | netbeans.license=apache20 -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkishalmi/gradle-gatling-plugin/b9a320dc11ea6d57280ef00c55a42779abe0b928/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Aug 31 21:54:57 EEST 2016 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /nb-actions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -Pversion=${input:Version,0.4.x} 6 | clean 7 | publishPlugins 8 | 9 | 10 | -------------------------------------------------------------------------------- /sample-project/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.github.lkishalmi.gatling" version "3.3.4" 3 | } 4 | 5 | repositories { 6 | jcenter() 7 | } 8 | -------------------------------------------------------------------------------- /sample-project/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkishalmi/gradle-gatling-plugin/b9a320dc11ea6d57280ef00c55a42779abe0b928/sample-project/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /sample-project/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /sample-project/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /sample-project/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /sample-project/src/gatling/resources/search.csv: -------------------------------------------------------------------------------- 1 | searchCriterion,searchComputerName 2 | Macbook,MacBook Pro 3 | eee,ASUS Eee PC 1005PE -------------------------------------------------------------------------------- /sample-project/src/gatling/simulations/SampleSimulation.scala: -------------------------------------------------------------------------------- 1 | import scala.concurrent.duration._ 2 | 3 | import io.gatling.core.Predef._ 4 | import io.gatling.http.Predef._ 5 | 6 | class SampleSimulation extends Simulation { 7 | 8 | object Search { 9 | 10 | val feeder = csv("search.csv").random 11 | 12 | val search = exec( 13 | http("Home") 14 | .get("/") 15 | ).pause(1) 16 | .feed(feeder) 17 | .exec( 18 | http("Search") 19 | .get("/computers?f=${searchCriterion}") 20 | .check(css("a:contains('${searchComputerName}')", "href").saveAs("computerURL")) 21 | ) 22 | .pause(1) 23 | .exec( 24 | http("Select") 25 | .get("${computerURL}") 26 | .check(status.is(200)) 27 | ) 28 | .pause(1) 29 | } 30 | 31 | val httpProtocol = http 32 | .baseUrl("http://computer-database.gatling.io") 33 | .acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8") 34 | .doNotTrackHeader("1") 35 | .acceptLanguageHeader("en-US,en;q=0.5") 36 | .acceptEncodingHeader("gzip, deflate") 37 | .userAgentHeader("Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20100101 Firefox/16.0") 38 | 39 | val users = scenario("Users").exec(Search.search) 40 | 41 | setUp(users.inject(rampUsers(1) during (1 seconds))).protocols(httpProtocol) 42 | } 43 | -------------------------------------------------------------------------------- /src/main/groovy/com/github/lkishalmi/gradle/gatling/GatlingPlugin.groovy: -------------------------------------------------------------------------------- 1 | package com.github.lkishalmi.gradle.gatling 2 | 3 | import org.gradle.api.GradleException 4 | import org.gradle.api.Plugin 5 | import org.gradle.api.Project 6 | import org.gradle.api.plugins.scala.ScalaPlugin 7 | import org.gradle.util.GradleVersion 8 | import org.gradle.util.VersionNumber 9 | 10 | /** 11 | * 12 | * @author Laszlo Kishalmi 13 | */ 14 | class GatlingPlugin implements Plugin { 15 | 16 | public static def GATLING_EXTENSION_NAME = 'gatling' 17 | 18 | public static def GATLING_RUN_TASK_NAME = 'gatlingRun' 19 | 20 | static String GATLING_TASK_NAME_PREFIX = "$GATLING_RUN_TASK_NAME-" 21 | 22 | private Project project 23 | 24 | void apply(Project project) { 25 | 26 | if (VersionNumber.parse(GradleVersion.current().version).major < 4) { 27 | throw new GradleException("Current Gradle version (${GradleVersion.current().version}) is unsupported. Minimal supported version is 4.0") 28 | } 29 | 30 | this.project = project 31 | 32 | project.pluginManager.apply ScalaPlugin 33 | 34 | GatlingPluginExtension gatlingExt = project.extensions.create(GATLING_EXTENSION_NAME, GatlingPluginExtension, project) 35 | 36 | createConfiguration(gatlingExt) 37 | 38 | createGatlingTask(GATLING_RUN_TASK_NAME, null) 39 | 40 | project.tasks.getByName("processGatlingResources").doLast(new LogbackConfigTaskAction()) 41 | 42 | project.tasks.addRule("Pattern: $GATLING_RUN_TASK_NAME-: Executes single Gatling simulation.") { String taskName -> 43 | if (taskName.startsWith(GATLING_TASK_NAME_PREFIX)) { 44 | createGatlingTask(taskName, (taskName - GATLING_TASK_NAME_PREFIX)) 45 | } 46 | } 47 | } 48 | 49 | void createGatlingTask(String taskName, String simulationFQN = null) { 50 | def task = project.tasks.create(name: taskName, 51 | dependsOn: project.tasks.gatlingClasses, type: GatlingRunTask, 52 | description: "Execute Gatling simulation", group: "Gatling") 53 | 54 | if (simulationFQN) { 55 | task.configure { 56 | simulations = { 57 | include "${simulationFQN.replace('.', '/')}.scala" 58 | } 59 | } 60 | } 61 | } 62 | 63 | void createConfiguration(GatlingPluginExtension gatlingExt) { 64 | project.sourceSets { 65 | gatling { 66 | scala.srcDirs = [gatlingExt.SIMULATIONS_DIR] 67 | resources.srcDirs = [gatlingExt.RESOURCES_DIR] 68 | } 69 | } 70 | 71 | project.configurations { 72 | gatling { visible = false } 73 | gatlingImplementation.extendsFrom(gatling) 74 | } 75 | 76 | project.dependencies { 77 | gatlingRuntimeOnly project.sourceSets.gatling.output 78 | } 79 | 80 | project.afterEvaluate { Project p -> 81 | p.dependencies { 82 | implementation "org.scala-lang:scala-library:${p.extensions.getByType(GatlingPluginExtension).scalaVersion}" 83 | gatlingImplementation "org.scala-lang:scala-library:${p.extensions.getByType(GatlingPluginExtension).scalaVersion}" 84 | gatling "io.gatling.highcharts:gatling-charts-highcharts:${p.extensions.getByType(GatlingPluginExtension).toolVersion}" 85 | 86 | if (gatlingExt.includeMainOutput) { 87 | gatlingImplementation project.sourceSets.main.output 88 | } 89 | if (gatlingExt.includeTestOutput) { 90 | gatlingImplementation project.sourceSets.test.output 91 | } 92 | } 93 | } 94 | } 95 | } 96 | 97 | -------------------------------------------------------------------------------- /src/main/groovy/com/github/lkishalmi/gradle/gatling/GatlingPluginExtension.groovy: -------------------------------------------------------------------------------- 1 | package com.github.lkishalmi.gradle.gatling 2 | 3 | import org.gradle.api.Project 4 | 5 | class GatlingPluginExtension implements JvmConfigurable { 6 | 7 | static final String GATLING_MAIN_CLASS = 'io.gatling.app.Gatling' 8 | 9 | static final String SIMULATIONS_DIR = "src/gatling/simulations" 10 | 11 | static final String RESOURCES_DIR = "src/gatling/resources" 12 | 13 | static final String GATLING_TOOL_VERSION = '3.3.1' 14 | 15 | static final String SCALA_VERSION = '2.12.8' 16 | 17 | static final Closure DEFAULT_SIMULATIONS = { include("**/*Simulation*.scala") } 18 | 19 | def toolVersion = GATLING_TOOL_VERSION 20 | 21 | def scalaVersion = SCALA_VERSION 22 | 23 | Closure simulations = DEFAULT_SIMULATIONS 24 | 25 | Boolean includeMainOutput = true 26 | Boolean includeTestOutput = true 27 | 28 | String logLevel = "WARN" 29 | 30 | private final Project project 31 | 32 | GatlingPluginExtension(Project project) { 33 | this.project = project 34 | this.jvmArgs = DEFAULT_JVM_ARGS 35 | this.systemProperties = DEFAULT_SYSTEM_PROPS 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/groovy/com/github/lkishalmi/gradle/gatling/GatlingRunTask.groovy: -------------------------------------------------------------------------------- 1 | package com.github.lkishalmi.gradle.gatling 2 | 3 | import org.gradle.api.Action 4 | import org.gradle.api.DefaultTask 5 | import org.gradle.api.file.FileTree 6 | import org.gradle.api.tasks.InputFiles 7 | import org.gradle.api.tasks.OutputDirectory 8 | import org.gradle.api.tasks.TaskAction 9 | import org.gradle.api.tasks.TaskExecutionException 10 | import org.gradle.process.ExecResult 11 | import org.gradle.process.JavaExecSpec 12 | 13 | import java.nio.file.Path 14 | import java.nio.file.Paths 15 | 16 | class GatlingRunTask extends DefaultTask implements JvmConfigurable { 17 | 18 | Closure simulations 19 | 20 | @OutputDirectory 21 | File gatlingReportDir = project.file("${project.reportsDir}/gatling") 22 | 23 | @InputFiles 24 | FileTree getSimulationSources() { 25 | def simulationFilter = this.simulations ?: project.gatling.simulations 26 | return project.sourceSets.gatling.scala.matching(simulationFilter) 27 | } 28 | 29 | List createGatlingArgs() { 30 | 31 | File scalaClasses = project.sourceSets.gatling.output.classesDirs.filter { 32 | it.parentFile.name == 'scala' 33 | }.singleFile 34 | 35 | return ['-bf', scalaClasses.absolutePath, 36 | "-rsf", "${project.sourceSets.gatling.output.resourcesDir}", 37 | "-rf", gatlingReportDir.absolutePath] 38 | } 39 | 40 | Iterable simulationFilesToFQN() { 41 | 42 | def scalaSrcDirs = project.sourceSets.gatling.scala.srcDirs.collect { Paths.get(it.absolutePath) } 43 | def scalaFiles = getSimulationSources().collect { Paths.get(it.absolutePath) } 44 | 45 | return scalaFiles.collect { Path srcFile -> 46 | scalaSrcDirs.find { srcFile.startsWith(it) }.relativize(srcFile).join(".") - ".scala" 47 | } 48 | } 49 | 50 | @TaskAction 51 | void gatlingRun() { 52 | def gatlingExt = project.extensions.getByType(GatlingPluginExtension) 53 | 54 | Map results = simulationFilesToFQN().collectEntries { String simulationClzName -> 55 | [(simulationClzName): project.javaexec({ JavaExecSpec exec -> 56 | exec.main = GatlingPluginExtension.GATLING_MAIN_CLASS 57 | exec.classpath = project.configurations.gatlingRuntimeClasspath 58 | 59 | exec.jvmArgs this.jvmArgs ?: gatlingExt.jvmArgs 60 | exec.systemProperties System.properties 61 | exec.systemProperties this.systemProperties ?: gatlingExt.systemProperties 62 | 63 | exec.args this.createGatlingArgs() 64 | exec.args "-s", simulationClzName 65 | 66 | exec.standardInput = System.in 67 | 68 | exec.ignoreExitValue = true 69 | } as Action)] 70 | } 71 | 72 | Map failed = results.findAll { it.value.exitValue != 0 } 73 | 74 | if (!failed.isEmpty()) { 75 | throw new TaskExecutionException(this, new RuntimeException("There're failed simulations: ${failed.keySet().sort().join(", ")}")) 76 | } 77 | 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/groovy/com/github/lkishalmi/gradle/gatling/JvmConfigurable.groovy: -------------------------------------------------------------------------------- 1 | package com.github.lkishalmi.gradle.gatling 2 | 3 | trait JvmConfigurable { 4 | 5 | static final List DEFAULT_JVM_ARGS = [ 6 | '-Xmx1G', 7 | '-XX:+HeapDumpOnOutOfMemoryError', 8 | '-XX:+UseG1GC', 9 | '-XX:MaxGCPauseMillis=30', 10 | '-XX:G1HeapRegionSize=16m', 11 | '-XX:InitiatingHeapOccupancyPercent=75', 12 | '-XX:+ParallelRefProcEnabled', 13 | '-XX:+PerfDisableSharedMem', 14 | '-XX:+OptimizeStringConcat' 15 | ] 16 | 17 | static final Map DEFAULT_SYSTEM_PROPS = ["java.net.preferIPv4Stack": true, "java.net.preferIPv6Addresses": false] 18 | 19 | List jvmArgs 20 | 21 | Map systemProperties 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/groovy/com/github/lkishalmi/gradle/gatling/LogbackConfigTaskAction.groovy: -------------------------------------------------------------------------------- 1 | package com.github.lkishalmi.gradle.gatling 2 | 3 | import org.gradle.api.Action 4 | import org.gradle.api.Task 5 | 6 | class LogbackConfigTaskAction implements Action { 7 | static def template(String logLevel) { 8 | """ 9 | 10 | 11 | 12 | %d{HH:mm:ss.SSS} [%-5level] %logger{15} - %msg%n%rEx 13 | 14 | false 15 | 16 | 17 | 18 | 19 | """ 20 | } 21 | 22 | void execute(Task gatlingRunTask) { 23 | def gatlingExt = gatlingRunTask.project.extensions.getByType(GatlingPluginExtension) 24 | if (!gatlingRunTask.project.file("${GatlingPluginExtension.RESOURCES_DIR}/logback.xml").exists()) { 25 | new File(gatlingRunTask.project.buildDir, "resources/gatling/logback.xml").with { 26 | parentFile.mkdirs() 27 | text = template(gatlingExt.logLevel) 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/gradle-plugins/com.github.lkishalmi.gatling.properties: -------------------------------------------------------------------------------- 1 | implementation-class=com.github.lkishalmi.gradle.gatling.GatlingPlugin -------------------------------------------------------------------------------- /src/test/groovy/functional/GradleCompatibilitySpec.groovy: -------------------------------------------------------------------------------- 1 | package functional 2 | 3 | import helper.GatlingFuncSpec 4 | import org.gradle.testkit.runner.BuildResult 5 | import org.gradle.testkit.runner.GradleRunner 6 | import spock.lang.Unroll 7 | 8 | import static org.gradle.testkit.runner.TaskOutcome.SUCCESS 9 | 10 | class GradleCompatibilitySpec extends GatlingFuncSpec { 11 | 12 | BuildResult executeGradleTaskWithVersion(String task, String gradleVersion, boolean shouldFail) { 13 | def runner = GradleRunner.create().forwardOutput() 14 | .withProjectDir(projectDir.root) 15 | .withArguments("--stacktrace", task) 16 | .withPluginClasspath() 17 | .withDebug(true) 18 | .withGradleVersion(gradleVersion) 19 | 20 | if (shouldFail) { 21 | return runner.buildAndFail() 22 | } else { 23 | return runner.build() 24 | } 25 | } 26 | 27 | @Unroll 28 | void 'should succeed for version #gradleVersion that greater than 4.0'() { 29 | given: 30 | prepareTest() 31 | when: 32 | BuildResult result = executeGradleTaskWithVersion('tasks', gradleVersion, false) 33 | then: 34 | result.task(":tasks").outcome == SUCCESS 35 | where: 36 | gradleVersion << ["4.0.1", "4.10.2", "5.0", "5.6.4", "6.0", "6.3"] 37 | } 38 | 39 | @Unroll 40 | void 'should fail for version #gradleVersion that less than 4.0'() { 41 | given: 42 | prepareTest() 43 | when: 44 | BuildResult result = executeGradleTaskWithVersion('tasks', gradleVersion, true) 45 | then: 46 | result.output.contains("Current Gradle version (${gradleVersion}) is unsupported. Minimal supported version is 4.0") 47 | where: 48 | gradleVersion << ["3.5", "3.0", "2.9"] 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/test/groovy/functional/LogbackConfigTaskActionTest.groovy: -------------------------------------------------------------------------------- 1 | package functional 2 | 3 | import helper.GatlingFuncSpec 4 | import org.gradle.testkit.runner.BuildResult 5 | 6 | import static org.gradle.testkit.runner.TaskOutcome.SUCCESS 7 | 8 | class LogbackConfigTaskActionTest extends GatlingFuncSpec { 9 | 10 | static def PROCESS_GATLING_RESOURCES_TASK_NAME = "processGatlingResources" 11 | 12 | File logbackConfig 13 | 14 | XmlSlurper xml = new XmlSlurper() 15 | 16 | def setup() { 17 | prepareTest() 18 | logbackConfig = new File(buildDir, "resources/gatling/logback.xml".toString()) 19 | } 20 | 21 | def "should create sample logback using logLevel from extension"() { 22 | when: 23 | BuildResult result = executeGradle(PROCESS_GATLING_RESOURCES_TASK_NAME) 24 | then: 25 | result.task(":$PROCESS_GATLING_RESOURCES_TASK_NAME").outcome == SUCCESS 26 | and: 27 | logbackConfig.exists() 28 | and: 29 | xml.parse(logbackConfig).root.@level == "WARN" 30 | } 31 | 32 | def "should override logLevel via extension"() { 33 | given: 34 | buildFile << 'gatling { logLevel = "QQQQ" }' 35 | when: 36 | BuildResult result = executeGradle(PROCESS_GATLING_RESOURCES_TASK_NAME) 37 | then: 38 | result.task(":$PROCESS_GATLING_RESOURCES_TASK_NAME").outcome == SUCCESS 39 | and: 40 | logbackConfig.exists() 41 | and: 42 | xml.parse(logbackConfig).root.@level == "QQQQ" 43 | } 44 | 45 | def "should not create sample logback.xml when it exists"() { 46 | given: "" 47 | new File(projectDir.root, "src/gatling/resources/logback.xml") << """""" 48 | when: 49 | BuildResult result = executeGradle(PROCESS_GATLING_RESOURCES_TASK_NAME) 50 | then: 51 | result.task(":$PROCESS_GATLING_RESOURCES_TASK_NAME").outcome == SUCCESS 52 | and: 53 | logbackConfig.exists() 54 | and: 55 | xml.parse(logbackConfig).@attr == "value" 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/test/groovy/functional/WhenCompileSimulationSpec.groovy: -------------------------------------------------------------------------------- 1 | package functional 2 | 3 | import helper.GatlingFuncSpec 4 | import org.gradle.testkit.runner.BuildResult 5 | import org.gradle.testkit.runner.UnexpectedBuildFailure 6 | import spock.lang.Ignore 7 | import spock.lang.Unroll 8 | 9 | import static org.gradle.testkit.runner.TaskOutcome.SUCCESS 10 | 11 | class WhenCompileSimulationSpec extends GatlingFuncSpec { 12 | 13 | static def GATLING_CLASSES_TASK_NAME = "gatlingClasses" 14 | 15 | def setup() { 16 | prepareTest() 17 | } 18 | 19 | def "should compile"() { 20 | when: 21 | BuildResult result = executeGradle(GATLING_CLASSES_TASK_NAME) 22 | then: "compiled successfully" 23 | result.task(":$GATLING_CLASSES_TASK_NAME").outcome == SUCCESS 24 | and: "only layout specific simulations were compiled" 25 | def classesDir = new File(buildDir, "classes/scala/gatling") 26 | classesDir.exists() 27 | and: "only layout specific resources are copied" 28 | def resourcesDir = new File(buildDir, "resources/gatling") 29 | resourcesDir.exists() 30 | new File(resourcesDir, "search.csv").exists() 31 | and: "main classes are compiled" 32 | def mainDir = new File(buildDir, "classes/java/main") 33 | mainDir.exists() 34 | and: "test classes are compiled" 35 | def testDir = new File(buildDir, "classes/java/test") 36 | testDir.exists() 37 | } 38 | 39 | @Unroll 40 | def "should not compile without #dir"() { 41 | setup: 42 | assert new File(projectDir.root, dir).deleteDir() 43 | when: 44 | executeGradle(GATLING_CLASSES_TASK_NAME) 45 | then: 46 | def e = thrown(UnexpectedBuildFailure) 47 | and: 48 | e.buildResult.output.contains(message) 49 | where: 50 | layout || dir || message 51 | 'gradle' | 'src/main' | "TestUtils.java:5: error: cannot find symbol" 52 | 'gradle' | 'src/test' | "not found: value TestUtils" 53 | } 54 | 55 | def "should not compile without required dependencies"() { 56 | given: 57 | buildFile.text = """ 58 | plugins { id 'com.github.lkishalmi.gatling' } 59 | repositories { jcenter() } 60 | """ 61 | when: 62 | executeGradle(GATLING_CLASSES_TASK_NAME) 63 | then: 64 | def e = thrown(UnexpectedBuildFailure) 65 | and: 66 | e.buildResult.output.contains("object lang is not a member of package org.apache.commons") 67 | } 68 | 69 | def "should not compile with main and test output excluded"() { 70 | given: 71 | buildFile << """ 72 | gatling { 73 | includeMainOutput = false 74 | includeTestOutput = false 75 | } 76 | """ 77 | when: 78 | executeGradle(GATLING_CLASSES_TASK_NAME) 79 | then: 80 | def e = thrown(UnexpectedBuildFailure) 81 | and: 82 | e.buildResult.output.contains("object MainUtils is not a member of package computerdatabase") 83 | } 84 | 85 | def "should not compile with test output excluded"() { 86 | given: 87 | buildFile << "gatling { includeTestOutput = false }" 88 | when: 89 | executeGradle(GATLING_CLASSES_TASK_NAME) 90 | then: 91 | def e = thrown(UnexpectedBuildFailure) 92 | and: 93 | e.buildResult.output.contains("not found: value TestUtils") 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/test/groovy/functional/WhenRunFailingSimulationSpec.groovy: -------------------------------------------------------------------------------- 1 | package functional 2 | 3 | import helper.GatlingFuncSpec 4 | import org.gradle.testkit.runner.UnexpectedBuildFailure 5 | 6 | import static com.github.lkishalmi.gradle.gatling.GatlingPlugin.GATLING_RUN_TASK_NAME 7 | import static org.gradle.testkit.runner.TaskOutcome.FAILED 8 | import static org.gradle.testkit.runner.TaskOutcome.SUCCESS 9 | 10 | class WhenRunFailingSimulationSpec extends GatlingFuncSpec { 11 | 12 | def setup() { 13 | prepareTest() 14 | } 15 | 16 | def "should execute all simulations even if one fails because of gatling assertions"() { 17 | given: 18 | buildFile << """ 19 | gatling { 20 | simulations = { 21 | include 'computerdatabase/AFailedSimulation.scala' 22 | include 'computerdatabase/BasicSimulation.scala' 23 | } 24 | } 25 | """ 26 | and: "add incorrect simulation" 27 | new File(srcDir, "computerdatabase/AFailedSimulation.scala").text = """ 28 | package computerdatabase 29 | import io.gatling.core.Predef._ 30 | import io.gatling.http.Predef._ 31 | class AFailedSimulation extends Simulation { 32 | val httpConf = http.baseUrl("http://qwe.asd.io") 33 | val scn = scenario("Scenario Name").exec(http("request_1").get("/")) 34 | setUp(scn.inject(atOnceUsers(1)).protocols(httpConf)).assertions( 35 | global.successfulRequests.percent.gt(99) 36 | ) 37 | } 38 | """ 39 | when: 40 | executeGradle(GATLING_RUN_TASK_NAME) 41 | then: 42 | UnexpectedBuildFailure ex = thrown(UnexpectedBuildFailure) 43 | ex.buildResult.task(":$GATLING_RUN_TASK_NAME").outcome == FAILED 44 | and: "only single simulation reported as failed" 45 | ex.buildResult.output.readLines().any { 46 | it.endsWith("There're failed simulations: computerdatabase.AFailedSimulation") 47 | } 48 | and: "all simulations were run" 49 | with(new File(buildDir, "reports/gatling")) { reports -> 50 | reports.exists() && reports.listFiles().size() == 2 51 | reports.listFiles().find { it.name.startsWith("basicsimulation") } != null 52 | reports.listFiles().find { it.name.startsWith("afailedsimulation") } != null 53 | new File(reports.listFiles().find { it.name.startsWith("afailedsimulation") }, "simulation.log").text.contains("UnknownHostException: qwe.asd.io") 54 | } 55 | } 56 | 57 | def "should ignore if simulation without assertions fails with HTTP requests"() { 58 | given: 59 | buildFile << """ 60 | gatling { 61 | simulations = { 62 | include 'computerdatabase/AFailedSimulation.scala' 63 | include 'computerdatabase/BasicSimulation.scala' 64 | } 65 | } 66 | """ 67 | and: "add incorrect simulation" 68 | new File(srcDir, "computerdatabase/AFailedSimulation.scala").text = """ 69 | package computerdatabase 70 | import io.gatling.core.Predef._ 71 | import io.gatling.http.Predef._ 72 | class AFailedSimulation extends Simulation { 73 | val httpConf = http.baseUrl("http://qwe.asd.io") 74 | val scn = scenario("Scenario Name").exec(http("request_1").get("/")) 75 | setUp(scn.inject(atOnceUsers(1)).protocols(httpConf)) 76 | } 77 | """ 78 | when: 79 | def buildResult = executeGradle(GATLING_RUN_TASK_NAME) 80 | then: 81 | buildResult.task(":$GATLING_RUN_TASK_NAME").outcome == SUCCESS 82 | and: 83 | with(new File(buildDir, "reports/gatling")) { reports -> 84 | reports.exists() && reports.listFiles().size() == 2 85 | reports.listFiles().find { it.name.startsWith("basicsimulation") } != null 86 | reports.listFiles().find { it.name.startsWith("afailedsimulation") } != null 87 | new File(reports.listFiles().find { it.name.startsWith("afailedsimulation") }, "simulation.log").text.contains("UnknownHostException: qwe.asd.io") 88 | } 89 | } 90 | 91 | def "should execute all simulations even if one fails because of gatling runtime"() { 92 | given: 93 | buildFile << """ 94 | gatling { 95 | simulations = { 96 | include 'computerdatabase/BasicSimulation.scala' 97 | include 'computerdatabase/AFailedSimulation.scala' 98 | } 99 | } 100 | """ 101 | and: "add incorrect simulation" 102 | new File(srcDir, "computerdatabase/AFailedSimulation.scala").text = """ 103 | package computerdatabase 104 | import io.gatling.core.Predef._ 105 | import io.gatling.http.Predef._ 106 | class AFailedSimulation extends Simulation {} 107 | """ 108 | when: 109 | executeGradle(GATLING_RUN_TASK_NAME) 110 | then: 111 | UnexpectedBuildFailure ex = thrown(UnexpectedBuildFailure) 112 | ex.buildResult.task(":$GATLING_RUN_TASK_NAME").outcome == FAILED 113 | and: "only single simulation reported as failed" 114 | ex.buildResult.output.readLines().any { 115 | it.endsWith("There're failed simulations: computerdatabase.AFailedSimulation") 116 | } 117 | and: 118 | with(new File(buildDir, "reports/gatling")) { reports -> 119 | reports.exists() && reports.listFiles().size() == 1 120 | reports.listFiles().find { it.name.startsWith("basicsimulation") } != null 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/test/groovy/functional/WhenRunSimulationSpec.groovy: -------------------------------------------------------------------------------- 1 | package functional 2 | 3 | import helper.GatlingFuncSpec 4 | import org.gradle.testkit.runner.BuildResult 5 | 6 | import static com.github.lkishalmi.gradle.gatling.GatlingPlugin.GATLING_RUN_TASK_NAME 7 | import static org.gradle.testkit.runner.TaskOutcome.SUCCESS 8 | import static org.gradle.testkit.runner.TaskOutcome.UP_TO_DATE 9 | 10 | class WhenRunSimulationSpec extends GatlingFuncSpec { 11 | 12 | def "should execute all simulations by default"() { 13 | setup: 14 | prepareTest() 15 | when: 16 | BuildResult result = executeGradle(GATLING_RUN_TASK_NAME) 17 | then: "default tasks were executed successfully" 18 | result.task(":$GATLING_RUN_TASK_NAME").outcome == SUCCESS 19 | result.task(":gatlingClasses").outcome == SUCCESS 20 | and: "all simulations were run" 21 | def reports = new File(buildDir, "reports/gatling") 22 | reports.exists() && reports.listFiles().size() == 2 23 | and: "logs doesn't contain INFO" 24 | !result.output.split().any { it.contains("INFO") } 25 | } 26 | 27 | def "should execute only #simulation when initiated by rule"() { 28 | setup: 29 | prepareTest() 30 | when: 31 | BuildResult result = executeGradle("$GATLING_RUN_TASK_NAME-computerdatabase.BasicSimulation") 32 | then: "custom task was run successfully" 33 | result.task(":$GATLING_RUN_TASK_NAME-computerdatabase.BasicSimulation").outcome == SUCCESS 34 | and: "only one simulation was executed" 35 | new File(buildDir, "reports/gatling").listFiles().size() == 1 36 | and: "logs doesn't contain INFO" 37 | !result.output.split().any { it.contains("INFO") } 38 | } 39 | 40 | def "should allow Gatling config override"() { 41 | given: 42 | prepareTest() 43 | and: "override config by disabling reports" 44 | new File(new File(projectDir.root, "src/gatling/resources"), "gatling.conf") << """ 45 | gatling.charting.noReports = true 46 | """ 47 | when: 48 | BuildResult result = executeGradle(GATLING_RUN_TASK_NAME) 49 | then: 50 | result.task(":$GATLING_RUN_TASK_NAME").outcome == SUCCESS 51 | and: "no reports generated" 52 | with(new File(buildDir, "reports/gatling").listFiles()) { reports -> 53 | reports.size() == 2 54 | reports.find { it.name.startsWith("basicsimulation") } != null 55 | reports.find { it.name.startsWith("basicsimulation") }.listFiles().collect { it.name } == ["simulation.log"] 56 | reports.find { it.name.startsWith("advancedsimulationstep03") } != null 57 | reports.find { it.name.startsWith("advancedsimulationstep03") }.listFiles().collect { it.name } == ["simulation.log"] 58 | 59 | } 60 | } 61 | 62 | def "should not fail when layout is incorrect"() { 63 | setup: 64 | prepareTest(null) 65 | when: 66 | BuildResult result = executeGradle(GATLING_RUN_TASK_NAME) 67 | then: "default tasks were executed successfully" 68 | result.task(":$GATLING_RUN_TASK_NAME").outcome == SUCCESS 69 | result.task(":gatlingClasses").outcome == UP_TO_DATE 70 | and: "no simulations compiled" 71 | !new File(buildDir, "classes/gatling").exists() 72 | and: "no simulations run" 73 | with(new File(buildDir, "reports/gatling")) { 74 | it.exists() 75 | it.list().size() == 0 76 | } 77 | } 78 | 79 | def "should not run gatling if no changes to source code"() { 80 | given: 81 | prepareTest() 82 | buildFile << """ 83 | gatling { simulations = { include 'computerdatabase/BasicSimulation.scala' } } 84 | """ 85 | when: '1st time' 86 | BuildResult result = executeGradle("$GATLING_RUN_TASK_NAME") 87 | then: 88 | result.task(":compileGatlingScala").outcome == SUCCESS 89 | result.task(":$GATLING_RUN_TASK_NAME").outcome == SUCCESS 90 | 91 | when: '2nd time no changes' 92 | result = executeGradle("$GATLING_RUN_TASK_NAME") 93 | then: 94 | result.task(":compileGatlingScala").outcome == UP_TO_DATE 95 | result.task(":$GATLING_RUN_TASK_NAME").outcome == UP_TO_DATE 96 | 97 | when: '3r time with changes' 98 | new File(new File(srcDir, "computerdatabase"), "BasicSimulation.scala") << """ 99 | case class MyClz(str: String) // some fake code to change source file 100 | """ 101 | result = executeGradle("$GATLING_RUN_TASK_NAME") 102 | then: 103 | result.task(":compileGatlingScala").outcome == SUCCESS 104 | result.task(":$GATLING_RUN_TASK_NAME").outcome == SUCCESS 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/test/groovy/functional/WhenRunSimulationSysPropsJvmArgsSpec.groovy: -------------------------------------------------------------------------------- 1 | package functional 2 | 3 | import com.github.lkishalmi.gradle.gatling.GatlingPluginExtension 4 | import helper.GatlingDebug 5 | import helper.GatlingFuncSpec 6 | import org.gradle.testkit.runner.BuildResult 7 | import org.junit.Rule 8 | import org.junit.contrib.java.lang.system.EnvironmentVariables 9 | import org.junit.contrib.java.lang.system.RestoreSystemProperties 10 | 11 | import static com.github.lkishalmi.gradle.gatling.GatlingPlugin.GATLING_RUN_TASK_NAME 12 | 13 | class WhenRunSimulationSysPropsJvmArgsSpec extends GatlingFuncSpec { 14 | 15 | @Rule 16 | public final RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties() 17 | 18 | @Rule 19 | public final EnvironmentVariables environmentVariables = new EnvironmentVariables() 20 | 21 | def setup() { 22 | prepareTest("/gatling-debug") 23 | new File(new File(projectDir.root, "src/gatling/resources"), "gatling.conf").text = "gatling.data.writers = []" 24 | } 25 | 26 | def "should set memory limits from jvmArgs of gatling extension"() { 27 | when: "default Xmx from gatling extension" 28 | BuildResult result = executeGradle(GATLING_RUN_TASK_NAME) 29 | then: 30 | with(new GatlingDebug(result)) { 31 | heap.max == 1024 * 1024 * 1024// 1GB 32 | } 33 | 34 | when: "override via gatling extension" 35 | buildFile << """ 36 | gatling { 37 | jvmArgs = ['-Xms32m'] 38 | } 39 | """ 40 | and: 41 | result = executeGradle("--rerun-tasks", GATLING_RUN_TASK_NAME) 42 | then: 43 | with(new GatlingDebug(result)) { 44 | heap.min == 32 * 1024 * 1024 45 | } 46 | } 47 | 48 | def "should configure jvmArgs from extension"() { 49 | when: "default jvmArgs from gatling extension" 50 | BuildResult result = executeGradle(GATLING_RUN_TASK_NAME) 51 | then: 52 | with(new GatlingDebug(result)) { 53 | jvmArgs.sort() == GatlingPluginExtension.DEFAULT_JVM_ARGS.findAll { it.startsWith("-X") }.sort() 54 | } 55 | 56 | when: "override via gatling extension" 57 | buildFile << """ 58 | gatling { 59 | jvmArgs = ['-Xms32m', '-XX:+UseG1GC'] 60 | } 61 | """ 62 | and: 63 | result = executeGradle("--rerun-tasks", GATLING_RUN_TASK_NAME) 64 | then: 65 | with(new GatlingDebug(result)) { 66 | jvmArgs.sort() == ['-Xms32m', '-XX:+UseG1GC'].sort() 67 | } 68 | } 69 | 70 | def "should override jvmArgs from gatlingRun properties"() { 71 | when: "override via gatlingRun" 72 | buildFile << """ 73 | gatling { 74 | jvmArgs = ['-Xms32m', '-XX:+AggressiveOpts'] 75 | } 76 | gatlingRun { 77 | jvmArgs = ['-Xms128m', '-XX:+UseG1GC'] 78 | } 79 | """ 80 | and: 81 | def result = executeGradle(GATLING_RUN_TASK_NAME) 82 | then: 83 | with(new GatlingDebug(result)) { 84 | jvmArgs.sort() == ['-Xms128m', '-XX:+UseG1GC'].sort() 85 | } 86 | } 87 | 88 | def "should configure system properties from extension"() { 89 | when: "defalts from extension" 90 | def result = executeGradle(GATLING_RUN_TASK_NAME) 91 | then: 92 | with(new GatlingDebug(result)) { 93 | systemProperties.keySet().intersect(GatlingPluginExtension.DEFAULT_SYSTEM_PROPS.keySet()).size() == GatlingPluginExtension.DEFAULT_SYSTEM_PROPS.size() 94 | } 95 | 96 | when: "override via extension" 97 | buildFile << """ 98 | gatling { 99 | systemProperties = ['gradle_gatling_1': 'aaa', 'gradle_gatling_2' : 'bbb'] 100 | } 101 | """ 102 | and: 103 | result = executeGradle("--rerun-tasks", GATLING_RUN_TASK_NAME) 104 | then: 105 | with(new GatlingDebug(result)) { 106 | systemProperties.keySet().findAll { it.startsWith("gradle_gatling_") } == ['gradle_gatling_1', 'gradle_gatling_2'] as Set 107 | systemProperties["gradle_gatling_1"] == "aaa" 108 | systemProperties["gradle_gatling_2"] == "bbb" 109 | 110 | systemProperties.keySet().intersect(GatlingPluginExtension.DEFAULT_SYSTEM_PROPS.keySet()).size() == 0 111 | } 112 | } 113 | 114 | def "should extend system properties from extension"() { 115 | } 116 | 117 | def "should extend system properties from gatlingRun properties"() { 118 | given: "override via gatlingRun" 119 | buildFile << """ 120 | gatling { 121 | systemProperties = ['gradle_gatling_1': 'aaa', 'gradle_gatling_2' : 'bbb'] 122 | } 123 | gatlingRun { 124 | systemProperties = ['gradle_gatling_2' : 'qwerty', 'gradle_gatling_3' : 'ccc'] 125 | } 126 | """ 127 | when: 128 | def result = executeGradle(GATLING_RUN_TASK_NAME) 129 | then: 130 | with(new GatlingDebug(result)) { 131 | systemProperties.keySet().findAll { it.startsWith("gradle_gatling_") } == ['gradle_gatling_2', 'gradle_gatling_3'] as Set 132 | systemProperties["gradle_gatling_2"] == "qwerty" 133 | } 134 | } 135 | 136 | def "should pass env vars upstream"() { 137 | given: 138 | environmentVariables.set("GRADLE_GATLING_ENV_UPSTREAM", "env_upstream_value") 139 | when: 140 | def result = executeGradle(GATLING_RUN_TASK_NAME) 141 | then: 142 | with(new GatlingDebug(result)) { 143 | env["GRADLE_GATLING_ENV_UPSTREAM"] == "env_upstream_value" 144 | } 145 | } 146 | 147 | def "should pass system properties upstream"() { 148 | given: 149 | System.setProperty("gradle_gatling_sys_upstream", "sys_upstream_value") 150 | when: 151 | def result = executeGradle(GATLING_RUN_TASK_NAME) 152 | then: 153 | with(new GatlingDebug(result)) { 154 | systemProperties["gradle_gatling_sys_upstream"] == "sys_upstream_value" 155 | } 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /src/test/groovy/helper/GatlingDebug.groovy: -------------------------------------------------------------------------------- 1 | package helper 2 | 3 | import com.github.lkishalmi.gradle.gatling.GatlingPlugin 4 | import groovy.json.JsonSlurper 5 | import org.gradle.testkit.runner.BuildResult 6 | import org.gradle.testkit.runner.TaskOutcome 7 | 8 | class GatlingDebug { 9 | 10 | Map systemProperties 11 | Map env 12 | 13 | List jvmArgs 14 | List argv 15 | 16 | Map heap 17 | 18 | GatlingDebug(BuildResult buildResult) { 19 | assert buildResult.task(":$GatlingPlugin.GATLING_RUN_TASK_NAME").outcome == TaskOutcome.SUCCESS 20 | 21 | def lines = buildResult.output.readLines().findAll { it.startsWith("@@@@") } 22 | assert lines.size() == 4 23 | 24 | def jsonSlurper = new JsonSlurper() 25 | 26 | this.heap = jsonSlurper.parseText(lines.find { it.startsWith("@@@@.heap") } - "@@@@.heap ") 27 | this.jvmArgs = jsonSlurper.parseText(lines.find { it.startsWith("@@@@.jvm") } - "@@@@.jvm ") 28 | this.systemProperties = jsonSlurper.parseText((lines.find { it.startsWith("@@@@.sys") } - "@@@@.sys ")) 29 | this.env = jsonSlurper.parseText((lines.find { it.startsWith("@@@@.env") } - "@@@@.env ")) 30 | 31 | this.argv = this.systemProperties["sun.java.command"].split("\\s") as List 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/groovy/helper/GatlingFuncSpec.groovy: -------------------------------------------------------------------------------- 1 | package helper 2 | 3 | import org.gradle.testkit.runner.BuildResult 4 | import org.gradle.testkit.runner.GradleRunner 5 | 6 | abstract class GatlingFuncSpec extends GatlingSpec { 7 | 8 | static def GATLING_HOST_NAME_SYS_PROP = "-Dgatling.hostName=HTTP://COMPUTER-DATABASE.GATLING.IO" 9 | 10 | void prepareTest(String fixtureDir = "/gradle-layout") { 11 | createBuildFolder(fixtureDir) 12 | generateBuildScripts() 13 | } 14 | 15 | BuildResult executeGradle(String... gradleArgs) { 16 | GradleRunner.create().forwardOutput() 17 | .withProjectDir(projectDir.getRoot()) 18 | .withArguments(["--stacktrace", GATLING_HOST_NAME_SYS_PROP] + (gradleArgs as List)) 19 | .withPluginClasspath() 20 | .withDebug(true) 21 | .build() 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/groovy/helper/GatlingSpec.groovy: -------------------------------------------------------------------------------- 1 | package helper 2 | 3 | import org.junit.Rule 4 | import org.junit.rules.TemporaryFolder 5 | import spock.lang.Specification 6 | 7 | import static org.apache.commons.io.FileUtils.copyDirectory 8 | 9 | abstract class GatlingSpec extends Specification { 10 | @Rule 11 | public final TemporaryFolder projectDir = new TemporaryFolder() 12 | 13 | File srcDir 14 | 15 | File buildDir 16 | 17 | File buildFile 18 | 19 | def createBuildFolder(String fixtureDir) { 20 | if (fixtureDir) { 21 | copyDirectory(new File(this.class.getResource(fixtureDir).file), projectDir.root) 22 | } 23 | srcDir = new File(projectDir.root, "src/gatling/simulations") 24 | buildDir = new File(projectDir.root, "build") 25 | } 26 | 27 | def generateBuildScripts() { 28 | buildFile = projectDir.newFile("build.gradle") 29 | buildFile.text = """ 30 | plugins { id 'com.github.lkishalmi.gatling' } 31 | repositories { jcenter() } 32 | dependencies { gatling group: 'commons-lang', name: 'commons-lang', version: '2.6' } 33 | """ 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/groovy/helper/GatlingUnitSpec.groovy: -------------------------------------------------------------------------------- 1 | package helper 2 | 3 | import com.github.lkishalmi.gradle.gatling.GatlingPluginExtension 4 | import com.github.lkishalmi.gradle.gatling.GatlingRunTask 5 | import org.gradle.api.Project 6 | import org.gradle.testfixtures.ProjectBuilder 7 | 8 | import static com.github.lkishalmi.gradle.gatling.GatlingPlugin.GATLING_RUN_TASK_NAME 9 | 10 | abstract class GatlingUnitSpec extends GatlingSpec { 11 | Project project 12 | 13 | GatlingPluginExtension gatlingExt 14 | 15 | GatlingRunTask gatlingRunTask 16 | 17 | def setup() { 18 | createBuildFolder("/gradle-layout") 19 | 20 | project = ProjectBuilder.builder().withProjectDir(projectDir.root).build() 21 | project.pluginManager.apply 'com.github.lkishalmi.gatling' 22 | 23 | gatlingExt = project.extensions.getByType(GatlingPluginExtension) 24 | gatlingRunTask = project.tasks.getByName(GATLING_RUN_TASK_NAME) as GatlingRunTask 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/test/groovy/unit/GatlingPluginTest.groovy: -------------------------------------------------------------------------------- 1 | package unit 2 | 3 | import com.github.lkishalmi.gradle.gatling.GatlingPluginExtension 4 | import com.github.lkishalmi.gradle.gatling.GatlingRunTask 5 | import com.github.lkishalmi.gradle.gatling.LogbackConfigTaskAction 6 | import helper.GatlingUnitSpec 7 | import org.gradle.language.jvm.tasks.ProcessResources 8 | 9 | class GatlingPluginTest extends GatlingUnitSpec { 10 | 11 | def "should create gatling configurations"() { 12 | expect: 13 | ['gatling', 'gatlingCompile', 'gatlingRuntime', 'gatlingImplementation', 'gatlingRuntimeOnly'].every { 14 | project.configurations.getByName(it) != null 15 | } 16 | } 17 | 18 | def "should create gatling extension for project "() { 19 | expect: 20 | with(gatlingExt) { 21 | it instanceof GatlingPluginExtension 22 | it.simulations == DEFAULT_SIMULATIONS 23 | it.jvmArgs == DEFAULT_JVM_ARGS 24 | it.systemProperties == DEFAULT_SYSTEM_PROPS 25 | it.logLevel == "WARN" 26 | } 27 | } 28 | 29 | def "should add gatling dependencies with default version"() { 30 | when: 31 | project.evaluate() 32 | then: 33 | project.configurations.getByName("gatling").allDependencies.find { 34 | it.name == "gatling-charts-highcharts" && it.version == GatlingPluginExtension.GATLING_TOOL_VERSION 35 | } 36 | project.configurations.getByName("gatlingImplementation").allDependencies.find { 37 | it.name == "scala-library" && it.version == GatlingPluginExtension.SCALA_VERSION 38 | } 39 | project.configurations.getByName("implementation").allDependencies.find { 40 | it.name == "scala-library" && it.version == GatlingPluginExtension.SCALA_VERSION 41 | } 42 | } 43 | 44 | def "should allow overriding gatling version via extension"() { 45 | when: 46 | project.gatling { toolVersion = '3.0.0-RC1' } 47 | and: 48 | project.evaluate() 49 | then: 50 | project.configurations.getByName("gatling").allDependencies.find { 51 | it.name == "gatling-charts-highcharts" && it.version == "3.0.0-RC1" 52 | } 53 | } 54 | 55 | def "should allow overriding scala version via extension"() { 56 | when: 57 | project.gatling { scalaVersion = '2.11.3' } 58 | and: 59 | project.evaluate() 60 | then: 61 | project.configurations.getByName("gatlingImplementation").allDependencies.find { 62 | it.name == "scala-library" && it.version == "2.11.3" 63 | } 64 | project.configurations.getByName("implementation").allDependencies.find { 65 | it.name == "scala-library" && it.version == "2.11.3" 66 | } 67 | } 68 | 69 | def "should create gatlingRun task"() { 70 | expect: 71 | with(gatlingRunTask) { 72 | it instanceof GatlingRunTask 73 | it.simulations == null 74 | it.jvmArgs == null 75 | it.systemProperties == null 76 | } 77 | } 78 | 79 | def "should create processGatlingResources task"() { 80 | expect: 81 | with(project.tasks.getByName("processGatlingResources")) { 82 | it instanceof ProcessResources 83 | it != null 84 | it.actions.find { it.action instanceof LogbackConfigTaskAction } != null 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/test/groovy/unit/GatlingRunTaskTest.groovy: -------------------------------------------------------------------------------- 1 | package unit 2 | 3 | import com.github.lkishalmi.gradle.gatling.GatlingPluginExtension 4 | import helper.GatlingUnitSpec 5 | import org.codehaus.groovy.runtime.typehandling.GroovyCastException 6 | import spock.lang.Unroll 7 | 8 | import static com.github.lkishalmi.gradle.gatling.GatlingPluginExtension.SIMULATIONS_DIR 9 | import static org.apache.commons.io.FileUtils.copyFileToDirectory 10 | import static org.apache.commons.io.FileUtils.moveFileToDirectory 11 | 12 | class GatlingRunTaskTest extends GatlingUnitSpec { 13 | 14 | def "should resolve simulations using default filter"() { 15 | when: 16 | def gatlingRunSimulations = gatlingRunTask.simulationFilesToFQN() 17 | then: 18 | gatlingRunSimulations.size() == 2 19 | and: 20 | "computerdatabase.advanced.AdvancedSimulationStep03" in gatlingRunSimulations 21 | and: 22 | "computerdatabase.BasicSimulation" in gatlingRunSimulations 23 | } 24 | 25 | def "should resolve simulations using custom filter"() { 26 | given: 27 | project.gatling.simulations = { include "**/*AdvancedSimulation*" } 28 | when: 29 | def gatlingRunSimulations = gatlingRunTask.simulationFilesToFQN() 30 | then: 31 | gatlingRunSimulations == ["computerdatabase.advanced.AdvancedSimulationStep03"] 32 | } 33 | 34 | def "should resolve simulations using gatlingRun filter"() { 35 | given: 36 | project.gatling.simulations = GatlingPluginExtension.DEFAULT_SIMULATIONS 37 | and: 38 | project.gatlingRun.simulations = { include "**/*AdvancedSimulation*" } 39 | when: 40 | def gatlingRunSimulations = gatlingRunTask.simulationFilesToFQN() 41 | then: 42 | gatlingRunSimulations == ["computerdatabase.advanced.AdvancedSimulationStep03"] 43 | } 44 | 45 | @Unroll 46 | def "should fail if extension filter is not a closure but #val"() { 47 | when: 48 | project.gatling.simulations = val 49 | then: 50 | def ex = thrown(GroovyCastException) 51 | ex.message.contains(val.toString()) 52 | where: 53 | val << ["", "qwerty", ["1", "2"]] 54 | } 55 | 56 | @Unroll 57 | def "should fail if gatlingRun filter not a closure but #val"() { 58 | when: 59 | project.gatlingRun.simulations = val 60 | then: 61 | def ex = thrown(GroovyCastException) 62 | ex.message.contains(val.toString()) 63 | where: 64 | val << ["", "qwerty", ["1", "2"]] 65 | } 66 | 67 | def "should override simulations dirs via sourceSet"() { 68 | given: 69 | def overridenSrc = "test/gatling/scala" 70 | 71 | when: 'using source dirs without simulations' 72 | project.sourceSets { 73 | gatling.scala.srcDirs = [overridenSrc] 74 | } 75 | then: 76 | gatlingRunTask.simulationFilesToFQN().size() == 0 77 | 78 | when: 'put simulations into overridden source dir' 79 | copyFileToDirectory(new File(projectDir.root, "${SIMULATIONS_DIR}/computerdatabase/BasicSimulation.scala"), 80 | new File(projectDir.root, "$overridenSrc/computerdatabase")) 81 | then: 82 | gatlingRunTask.simulationFilesToFQN() == ["computerdatabase.BasicSimulation"] 83 | } 84 | 85 | def "should extend simulations dirs via sourceSet"() { 86 | given: 87 | def overridenSrc = "test/gatling/scala" 88 | 89 | when: 'source dirs without simulations' 90 | project.sourceSets { 91 | gatling.scala.srcDir overridenSrc 92 | } 93 | then: 94 | gatlingRunTask.simulationFilesToFQN().size() == 2 95 | 96 | when: "hide one simulation" 97 | moveFileToDirectory(new File(projectDir.root, "${SIMULATIONS_DIR}/computerdatabase/BasicSimulation.scala"), 98 | projectDir.root, true) 99 | then: 100 | gatlingRunTask.simulationFilesToFQN() == ["computerdatabase.advanced.AdvancedSimulationStep03"] 101 | 102 | when: 'move simulation back to overridden source dir' 103 | moveFileToDirectory(new File(projectDir.root, "BasicSimulation.scala"), new File(projectDir.root, "$overridenSrc/computerdatabase"), true) 104 | then: 105 | gatlingRunTask.simulationFilesToFQN().size() == 2 106 | } 107 | 108 | def "should not find missing simulations via gatling extension"() { 109 | when: 'default src layout' 110 | project.gatling.simulations = { 111 | include "computerdatabase/BasicSimulation.scala" 112 | include "some.missing.file" 113 | } 114 | then: 115 | gatlingRunTask.simulationFilesToFQN() == ["computerdatabase.BasicSimulation"] 116 | 117 | when: 'custom src layout' 118 | project.sourceSets { 119 | gatling.scala.srcDirs = ["missing/gatling"] 120 | } 121 | then: 122 | gatlingRunTask.simulationFilesToFQN().size() == 0 123 | } 124 | 125 | def "should not find missing simulations via gatlingRun"() { 126 | when: 'default src layout' 127 | project.gatlingRun.simulations = { 128 | include "computerdatabase/BasicSimulation.scala" 129 | include "some.missing.file" 130 | } 131 | then: 132 | gatlingRunTask.simulationFilesToFQN() == ["computerdatabase.BasicSimulation"] 133 | 134 | when: 'custom src layout' 135 | project.sourceSets { 136 | gatling.scala.srcDirs = ["missing/gatling"] 137 | } 138 | then: 139 | gatlingRunTask.simulationFilesToFQN().size() == 0 140 | } 141 | 142 | 143 | } 144 | -------------------------------------------------------------------------------- /src/test/resources/gatling-debug/src/gatling/resources/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkishalmi/gradle-gatling-plugin/b9a320dc11ea6d57280ef00c55a42779abe0b928/src/test/resources/gatling-debug/src/gatling/resources/.gitkeep -------------------------------------------------------------------------------- /src/test/resources/gatling-debug/src/gatling/simulations/GatlingDebugSimulation.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2018 GatlingCorp (https://gatling.io) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import io.gatling.core.Predef._ 18 | import io.gatling.http.Predef._ 19 | import scala.collection.JavaConverters._ 20 | import java.lang.management.ManagementFactory 21 | import java.lang.management.RuntimeMXBean 22 | import java.util 23 | 24 | class GatlingDebugSimulation extends Simulation { 25 | 26 | import org.json4s._ 27 | import org.json4s.jackson.JsonMethods._ 28 | import org.json4s.jackson.Serialization 29 | import org.json4s.jackson.Serialization._ 30 | 31 | implicit val formats = DefaultFormats 32 | 33 | private val heapMemory = ManagementFactory.getMemoryMXBean.getHeapMemoryUsage 34 | 35 | println(s"""@@@@.heap {"min": ${heapMemory.getInit}, "max": ${heapMemory.getMax}}""") 36 | 37 | private val jvmArgs = ManagementFactory.getRuntimeMXBean.getInputArguments 38 | 39 | println(s"@@@@.jvm ${write(jvmArgs.asScala.filterNot(_.startsWith("-D")))}}") 40 | 41 | println(s"@@@@.env ${write(System.getenv.asScala)}}") 42 | 43 | println(s"@@@@.sys ${write(System.getProperties.asScala)}}") 44 | 45 | setUp(scenario("Scenario Name").pause(1).inject(atOnceUsers(0))) 46 | } 47 | -------------------------------------------------------------------------------- /src/test/resources/gradle-layout/src/gatling/resources/search.csv: -------------------------------------------------------------------------------- 1 | searchCriterion,searchComputerName 2 | Macbook,MacBook Pro 3 | eee,ASUS Eee PC 1005PE -------------------------------------------------------------------------------- /src/test/resources/gradle-layout/src/gatling/simulations/computerdatabase/BasicSimulation.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2018 GatlingCorp (https://gatling.io) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package computerdatabase 18 | import io.gatling.core.Predef._ 19 | import io.gatling.http.Predef._ 20 | import scala.concurrent.duration._ 21 | import org.apache.commons.lang.StringUtils.lowerCase 22 | 23 | class BasicSimulation extends Simulation { 24 | 25 | val httpConf = http 26 | .baseUrl(lowerCase(TestUtils.hostName())) // Here is the root for all relative URLs 27 | .acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8") // Here are the common headers 28 | .doNotTrackHeader("1") 29 | .acceptLanguageHeader("en-US,en;q=0.5") 30 | .acceptEncodingHeader("gzip, deflate") 31 | .userAgentHeader("Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20100101 Firefox/16.0") 32 | 33 | val scn = scenario("Scenario Name") // A scenario is a chain of requests and pauses 34 | .exec(http("request_1").get("/")) 35 | .pause(1) // Note that Gatling has recorded real time pauses 36 | .exec(http("request_2").get("/computers?f=macbook")) 37 | .pause(1) 38 | .exec(http("request_3").get("/computers/6")) 39 | 40 | setUp(scn.inject(atOnceUsers(1)).protocols(httpConf)).assertions( 41 | global.successfulRequests.percent.gt(99) 42 | ) 43 | } 44 | -------------------------------------------------------------------------------- /src/test/resources/gradle-layout/src/gatling/simulations/computerdatabase/advanced/AdvancedSimulationStep03.scala: -------------------------------------------------------------------------------- 1 | package computerdatabase.advanced 2 | 3 | import org.apache.commons.lang.StringUtils.lowerCase 4 | import io.gatling.core.Predef._ 5 | import io.gatling.http.Predef._ 6 | import scala.concurrent.duration._ 7 | 8 | class AdvancedSimulationStep03 extends Simulation { 9 | 10 | object Search { 11 | 12 | // We need dynamic data so that all users don't play the same and we end up with a behavior completely different from the live system (caching, JIT...) 13 | // ==> Feeders! 14 | 15 | val feeder = csv("search.csv").random // default is queue, so for this test, we use random to avoid feeder starvation 16 | 17 | val search = exec(http("Home").get("/")) 18 | .pause(1) 19 | .feed(feeder) // every time a user passes here, a record is popped from the feeder and injected into the user's session 20 | .exec(http("Search") 21 | .get("/computers?f=${searchCriterion}") // use session data thanks to Gatling's EL 22 | .check(css("a:contains('${searchComputerName}')", "href"))) // use a CSS selector with an EL, save the result of the capture group 23 | } 24 | 25 | val httpConf = http 26 | .baseUrl(lowerCase(computerdatabase.MainUtils.hostName())) 27 | .acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8") 28 | .doNotTrackHeader("1") 29 | .acceptLanguageHeader("en-US,en;q=0.5") 30 | .acceptEncodingHeader("gzip, deflate") 31 | .userAgentHeader("Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20100101 Firefox/16.0") 32 | 33 | val users = scenario("Users").exec(Search.search) 34 | 35 | setUp(users.inject(atOnceUsers(1))).protocols(httpConf).assertions( 36 | global.successfulRequests.percent.gt(99) 37 | ) 38 | } 39 | -------------------------------------------------------------------------------- /src/test/resources/gradle-layout/src/main/java/computerdatabase/MainUtils.java: -------------------------------------------------------------------------------- 1 | package computerdatabase; 2 | 3 | public class MainUtils { 4 | public static String hostName() { 5 | return System.getProperty("gatling.hostName"); 6 | } 7 | } -------------------------------------------------------------------------------- /src/test/resources/gradle-layout/src/test/java/computerdatabase/TestUtils.java: -------------------------------------------------------------------------------- 1 | package computerdatabase; 2 | 3 | public class TestUtils { 4 | public static String hostName() { 5 | return MainUtils.hostName(); 6 | } 7 | } -------------------------------------------------------------------------------- /travis_build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ev 3 | 4 | if [ -z "${TRAVIS_TAG}" ]; then 5 | ./gradlew check 6 | fi 7 | --------------------------------------------------------------------------------