Beginner- Gatling2.0.0-M3a - Session variables / Local Variables set and pass through in param and templates http (Compilation error)

Hai,
I try to set local variables to add in param and then session variables to replace in templates . but getting error.

My Template:

{
“requestHeader”: {
“serviceContext”: {
“serviceId”: “${serviceId}”,
“token”: “${token}”,
“nonce”: “${nonce}”,
“otpToken”: “${otpToken}”
},
“clientContext”: {
“country”: “${country}”,
“channel”: “${channel}”,
“userName”: “${userName}”,
“password”: “${password}”
},
“userContext”: {
“userId”: ${userId},
“sessionId”: “${sessionId}”,
“language”: “${language}”
}
}

}

My Scala code:

package basic
import io.gatling.core.Predef._
import io.gatling.core.session.Expression
import io.gatling.http.Predef._
import io.gatling.jdbc.Predef._
import io.gatling.http.Headers.Names._
import io.gatling.http.Headers.Values._
import scala.concurrent.duration._
import bootstrap._
import assertions._

class LoginSimulation extends Simulation {

//Variables
var serviceId=“12345”
println(serviceId)
var token:String=null
// var nonce:String=null
// var otpToken:String=null
//
// var country:String = null
// var channel :String= null
// var userName:String = null
// var password :String= null
//
// var userId :String= null
// var sessionId :String= null
// var language:String = null
//
// var LoginuserId :String= null
// var Loginpassword :String= null
// var captcha:String = null
// var securityNonce:String = null

val httpProtocol = http
.baseURL(“https://localhost:8080”)
.acceptHeader(“application/json, text/javascript, /; q=0.01”)
.acceptEncodingHeader(“gzip, deflate”)
.acceptLanguageHeader(“en-US,en;q=0.5”)
.connection(“keep-alive”)
.userAgentHeader(“Mozilla/5.0 (Windows NT 6.1; WOW64; rv:19.0) Gecko/20100101 Firefox/19.0”)

val headers_1 = Map(
“”“Cache-Control”"" → “”“no-cache”"",
“”“Content-Type”"" → “”“application/json; charset=UTF-8"”",
“”“Pragma”"" → “”“no-cache”"",
“”“X-Requested-With”"" → “”“XMLHttpRequest”"")

// val rand = math.random.toString();

val scn = scenario(“Login-Logout”)

.exec(
session => {
session.set(“serviceId”,"")
session.set(“token”,"")
session.set(“nonce”,"")
session.set(“otpToken”,"")
session.set(“country”,"")
session.set(“channel”,"")
session.set(“userName”,"")
session.set(“password”,"")
session.set(“userId”,"")
session.set(“sessionId”,"")
session.set(“language”,"")
println(session)
session
})

//initlogin
.exec(http(“initLogin”)
.post("/services/security/initLogin?rand="+math.random.toString())
.headers(headers_1)
.param(“authenticity_token”,$token)
.body(ELFileBody(“InitLogin_request.txt”))
.check(status.is(200))
)
.pause(5)
.feed(csv(“user_credentials.csv”))
.exec(http(“Login”)
.post("/services/security/login?rand="+math.random.toString())
.headers(headers_1)
.param(“username”, “${username}”)
.body(ELFileBody(“Login_request.txt”))
.check(status.is(200))
)
.pause(6)
//logout
.exec(http(“Logout”)
.post("/services/security/logout?rand="+math.random.toString())
.headers(headers_1)
.body(ELFileBody(“Logout_request.txt”))
.check(status.is(200))
)
setUp(scn.inject(atOnce(1 user))).protocols(httpProtocol)
}

-Bala

The compilation error message should be very explicit, did you properly check it out?

.param(“authenticity_token”,$token) // problem here, $token should be “$token”

Hey,
that works.

Also Session object i changed like below for multiple values.

.exec(
session => {
session.setAll(“serviceId” → “bar”,
“token” → “”,
“nonce” → “”,
“otpToken” → “”,
“country” → “”,
“channel” → “”,
“userName” → “”,
“password” → “”,
“userId” → “”,
“sessionId” → “”,
“language” → “”,
“hashUserId” → “”,
“encryptPwd” → “”,
“captcha” → “”,
“securityNonce”->""

)
})
It works.

I believe .saveAs() using i can overwite session values for my multiple http requests.

Yep, and/or using a feeder.

Hai,
1 more doubt. Below code is we are using password encryption in jmeter. how can i use this in gatling.

import org.apache.commons.codec.digest.DigestUtils;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.encodings.PKCS1Encoding;
import org.bouncycastle.crypto.engines.RSAEngine;
import org.apache.commons.lang.StringUtils;
import org.bouncycastle.util.encoders.Hex;
import java.math.BigInteger;

//set hashed userId
var userId = vars.get(“USER”);
var hashUser = DigestUtils.shaHex(userId);
vars.put(“hashUserId”, hashUser);

var nonceValue =vars.get(“securityNonce”);
var exponentValue = vars.get(“e2eRsaExponent”);
var modulusValue = vars.get(“e2eRsaModulus”);
var password = vars.get(“PASSWORD”);

log.info("nonceValue = " + nonceValue);
log.info("exponentValue = " + exponentValue);
log.info("modulusValue = " + modulusValue);
log.info("PASSWORD = " + password);

var ex = new BigInteger(exponentValue, 16);
var mo = new BigInteger(modulusValue, 16);
var keyParameters = new RSAKeyParameters(false, mo, ex);
var rsaEngine = new PKCS1Encoding(new RSAEngine());
rsaEngine.init(true, keyParameters);
if(StringUtils.isNotBlank(nonceValue)){
password = nonceValue +password;
log.info("PASSWORD2 = " + password);
}
var encKey = rsaEngine.processBlock(password.getBytes(), 0, password.getBytes().length);
var codedPassword = new String(Hex.encode(encKey), “UTF-8”);
log.info(“encryptPwd=”+codedPassword);
vars.put(“encryptPwd”, codedPassword);

What is “vars”?

You probably want to store those attributes in the session and do that in a session function: https://github.com/excilys/gatling/wiki/Session#functions

Hai I changed JMETER scripts to java and converted to scala.

Code:

package basic

import org.apache.commons.codec.digest.DigestUtils
import org.bouncycastle.crypto.InvalidCipherTextException
import org.bouncycastle.crypto.params.RSAKeyParameters
import org.bouncycastle.crypto.encodings.PKCS1Encoding
import org.bouncycastle.crypto.engines.RSAEngine
import org.apache.commons.lang.StringUtils
import org.bouncycastle.util.encoders.Hex
import java.io.UnsupportedEncodingException
import java.math.BigInteger
import EncryptPassword._
import scala.reflect.{BeanProperty, BooleanBeanProperty}

object EncryptPassword {

def main(args: Array[String]) {
val enc = new EncryptPassword()
enc.setUserId(“test1”)
enc.setPassword(“test123”)
enc.setNonceValue(“nonceValue”)
enc.setExponentValue(“exponentValue”)
enc.setModulusValue(“e2eRsaModulus”)
val hashuser = enc.getUserIdHash
val hashpass = enc.getHashPassword
println(“hashuser:” + hashuser)
println(“hashpwd:” + hashpass)
}
}

class EncryptPassword {

@BeanProperty
var password: String = _

@BeanProperty
var userId: String = _

@BeanProperty
var nonceValue: String = _

@BeanProperty
var exponentValue: String = _

@BeanProperty
var modulusValue: String = _

private def getHashPassword(): String = {
val ex = new BigInteger(exponentValue, 16)
val mo = new BigInteger(modulusValue, 16)
val keyParameters = new RSAKeyParameters(false, mo, ex)
val rsaEngine = new PKCS1Encoding(new RSAEngine())
rsaEngine.init(true, keyParameters)
if (StringUtils.isNotBlank(nonceValue)) {
password = nonceValue + password
}
var encKey: Array[Byte] = null
var codedPassword = “”
try {
encKey = rsaEngine.processBlock(password.getBytes, 0, password.getBytes.length)
codedPassword = new String(Hex.encode(encKey), “UTF-8”)
} catch {
case e: InvalidCipherTextException => e.printStackTrace()
case e: UnsupportedEncodingException => e.printStackTrace()
}
codedPassword
}

private def getUserIdHash(): String = DigestUtils.shaHex(userId)

}

You’re trying to use Gatling EL inside session functions and this is not possible. If you try to do that “$userId” and “$hashuser” will just be raw Strings.
Please read the warning note here: https://github.com/excilys/gatling/wiki/Session#el

Check out how Validation works: https://github.com/excilys/gatling/wiki/Gatling%202#validation

Then, the EncryptPassword call has to be INSIDE the session function.

Then, get rid of those @BeanProperty, you have no use of a POJO here.

class EncryptPassword(password: String, userId: String, nonceValue: String, exponentValue: String, modulusValue: String)

.exec(session =>
for {

userId ← session(“userId”).validation[String]
password ← session(“password”).validation[String]
securityNonce ← session(“securityNonce”).validation[String]
e2eRsaExponent ← session(“e2eRsaExponent”).validation[String]
e2eRsaModulus ← session(“e2eRsaModulus”).validation[String]
enc = new EncryptPassword(password, userId, securityNonce, e2eRsaExponent, e2eRsaModulus)

hashuser = enc.getUserIdHash
hashpass = enc.getHashPassword
} yield session.setAll(“hashuser” → hashuser, “hashpass” → hashpass)

Now i am getting compilation Error:

12:51:53.490 [ERROR] i.g.a.ZincCompiler$ -LoginSimulation.scala:69: value validation is not a member of io.gatling.core.session.SessionAttribute
12:51:53.490 [ERROR] i.g.a.ZincCompiler$ - userId ← session(“userId”).validation[String]

Code:

class LoginSimulation extends Simulation {

val httpProtocol = http
.baseURL(“https://localhost:443”)
.acceptHeader(“application/json”)
.acceptEncodingHeader(“gzip, deflate”)

val headers_1 = Map(
“”“Cache-Control”"" → “”“no-store”"",
“”“Content-Type”"" → “”“application/json”"",
“”“Pragma”"" → “”“no-cache”""
)

val scn = scenario(“Login-Logout”)

val httpProtocol = http
.baseURL(“https://localhost:443”)
.acceptHeader(“application/json”)
.acceptEncodingHeader(“gzip, deflate”)

val headers_1 = Map(
“”“Cache-Control”"" → “”“no-store”"",
“”“Content-Type”"" → “”“application/json”"",
“”“Pragma”"" → “”“no-cache”""
)

val scn = scenario(“BMWSG-Login-Logout”)

.exec(
session => {
session.setAll(“serviceId” → “serviceID”,
“token” → “”,
“nonce” → “”,
“otpToken” → “”,
“country” → “SG”,
“channel” → “SG”,
“userName” → “user”,
“password” → “password”,
“userId” → “”,
“sessionId” → “”,
“language” → “en”,
“hashUserId” → “”,
“encryptPwd” → “”,
“captcha” → “”,
“securityNonce” → “”,
“e2eRsaExponent” → “”,
“e2eRsaModulus” → “”
)
})

//initlogin
.feed(csv(“user_credentials.csv”))
.exec(http(“initLogin”)
.post("/bsoi-sg/services/security/initLogin?rand=" + math.random.toString())
.headers(headers_1)
//.param(“username”, “${userId}”)
//.param(“authenticity_token”,"$token")
.body(ELFileBody(“InitLogin_request.txt”))
.check(status.is(200),
jsonPath("$.initLoginResponse.initLogin.securityNonce").exists.saveAs(“securityNonce”),
jsonPath("$.$.initLoginResponse.initLogin.sessionId").exists.saveAs(“sessionId”),
jsonPath("$.initLoginResponse.initLogin.securityParam.e2eRsaExponent").exists.saveAs(“e2eRsaExponent”),
jsonPath("$.initLoginResponse.initLogin.securityParam.e2eRsaModulus").exists.saveAs(“e2eRsaModulus”),
jsonPath("$.initLoginResponse.responseHeader.nonce").exists.saveAs(“nonce”)
)
)

.exec(session =>
for {
userId ← session(“userId”).validation[String]
password ← session(“password”).validation[String]
securityNonce ← session(“securityNonce”).validation[String]
e2eRsaExponent ← session(“e2eRsaExponent”).validation[String]
e2eRsaModulus ← session(“e2eRsaModulus”).validation[String]
enc = new EncryptPassword(password, userId, securityNonce, e2eRsaExponent, e2eRsaModulus)
hashUserId = enc.getUserIdHash
encryptPwd = enc.getHashPassword
} yield session.setAll(“hashUserId” → hashUserId, “encryptPwd” → encryptPwd)
)

setUp(scn.inject(atOnce(1 user))).protocols(httpProtocol)

}

Validate

Hai It works.

Can you tell how to use requestInfoExtractor,responseInfoExtractor . i am getting error.

value requestInfoExtractor is not a member of io.gatling.http.config.HttpProtocolBuilder
possible cause: maybe a semicolon is missing before `value requestInfoExtractor’?
21:13:12.452 [ERROR] i.g.a.ZincCompiler$ - .requestInfoExtractor(request => {Request => List[requestUrl,requestRawUrl]

Code:

val httpProtocol = http
.baseURL(“https://localhost:8080”)
.acceptHeader(“application/json”)
.acceptEncodingHeader(“gzip, deflate”)
.requestInfoExtractor(request => {Request => List[requestUrl,requestRawUrl]
})
.responseInfoExtractor(response => {List[responseStatusCode,responseStatusText]
})
.disableResponseChunksDiscarding