Gatling exec with session - scala

I need to make a request in Gatling, in which I'm able to access session items (without the expression language). I need to do this, because I want to inject data into a ByteArrayBody request from a csv feeder. To demonstrate my problem, I have a small example (without the actual need of the session).
The following scenario runs fine:
val scnBase: ScenarioBuilder = scenario("Test scneario").repeat(1){
exec(http("Http Test test").get("http://google.de/"))
}
But that one doesn't (I get the exception There were no requests sent during the simulation, reports won't be generated):
val scnBase: ScenarioBuilder = scenario("Test scneario").repeat(1){
exec(session => {
http("Http Test test").get("http://google.de/")
session
})
}
I run my simulations in IntelliJ (which worked fine so far) and in the following (here minimized) simulation file:
package test.scala
import java.text.SimpleDateFormat
import java.util.Date
import io.gatling.core.Predef._
import io.gatling.core.body.ByteArrayBody
import io.gatling.core.structure.ScenarioBuilder
import io.gatling.http.Predef._
import io.gatling.http.protocol.HttpProtocolBuilder
import org.slf4j.LoggerFactory
import test.scala.TerminalTesterRequest.url
import test.scala.requests._
import test.scala.util.CharsetConverter
import scala.concurrent.duration._
import scala.language.postfixOps
class MySimulation extends Simulation {
//base URL (actually this URL is different, but it's not important)
val ecmsServerUri = "http://0.0.0.0"
//base Protocol
val httpProtocol: HttpProtocolBuilder = http
.baseUrl(ecmsServerUri)
.inferHtmlResources(BlackList(""".*\.js""", """.*\.css""", """.*\.gif""", """.*\.jpeg""", """.*\.jpg""", """.*\.ico""", """.*\.woff""", """.*\.(t|o)tf""", """.*\.png"""), WhiteList())
.acceptHeader("*/*")
.acceptEncodingHeader("gzip, deflate")
.acceptLanguageHeader("en,en-US;q=0.7,de-DE;q=0.3")
.userAgentHeader("Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 2.0.50727.8762)")
val scnBase: ScenarioBuilder = scenario("Test scneario").repeat(1){
exec(session => {
http("Http Test test").get("http://google.de/")
session
})
}
setUp(
scnBase.inject(constantUsersPerSec(1) during(1 seconds)).protocols(httpProtocol)
).maxDuration(5 minutes)
}
How can I run an exec request with the information of the session (or at least the data from the feeder)? I'm using Gatling 3.1.1

Build whatever you need in a function and put the result in the session, then refer that value in the actual request
val feeder = csv("foo.csv")
scenario("Test scenario")
.feed(feeder)
.exec(buildPostData)
.exec(http("Http Test test")
.post(createApiURL)
.body(ByteArrayBody("${postData}"))
.check(status.is(200))
)
def buildPostData: Expression[Session] = session => {
val postData: Array[Byte] =
... // getting values from csv record: session("csvHeader").as[String]
session.set("postData", postData)
}

Related

Inteliij IDEA : Gatling getting j.l.NullPointerException while running simple script

While I as executing below scala code as Gatling script from Intellij IDEA Ultimate
import java.net.URI
import java.util
import java.util.{Collections, Optional}
import com.tools.RequestSigner
import io.gatling.core.Predef._
import io.gatling.http.Predef._
class CheckResponseCode extends Simulation {
val httpConf = http.baseUrl("https://localhost:8080/")
.header("Accept", "application/json")
val jsonFileFeeder = jsonFile("data\\request.json")
val scn = scenario("get data")
.feed(jsonFileFeeder)
.exec(http("Get data")
.put("/test1")
.sign(new com.tools.RequestSigner()
.check(jsonPath("$..operation").saveAs("operationId"))
.check(status.is(202))
.check( bodyString.saveAs( "RESPONSE_DATA" ) ))
.exec( session => {
println("Some Restful Service Response Body:")
println(session("RESPONSE_DATA").as[String])
session
})
setUp(
scn.inject(atOnceUsers(1))
).protocols(httpConf)
}
I get to see below in the result :
---- Errors --------------------------------------------------------------------
> j.l.NullPointerException 1 (100.0%)
What can be reason behind these and where can I find th detailed stack trace ?
In whatever logback appender is configured in your logback.xml configuration file, typically in the console.

Akka Flow hangs when making http requests via connection pool

I'm using Akka 2.4.4 and trying to move from Apache HttpAsyncClient (unsuccessfully).
Below is simplified version of code that I use in my project.
The problem is that it hangs if I send more than 1-3 requests to the flow. So far after 6 hours of debugging I couldn't even locate the problem. I don't see exceptions, error logs, events in Decider. NOTHING :)
I tried reducing connection-timeout setting to 1s thinking that maybe it's waiting for response from the server but it didn't help.
What am I doing wrong ?
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.headers.Referer
import akka.http.scaladsl.model.{HttpRequest, HttpResponse}
import akka.http.scaladsl.settings.ConnectionPoolSettings
import akka.stream.Supervision.Decider
import akka.stream.scaladsl.{Sink, Source}
import akka.stream.{ActorAttributes, Supervision}
import com.typesafe.config.ConfigFactory
import scala.collection.immutable.{Seq => imSeq}
import scala.concurrent.{Await, Future}
import scala.concurrent.duration.Duration
import scala.util.Try
object Main {
implicit val system = ActorSystem("root")
implicit val executor = system.dispatcher
val config = ConfigFactory.load()
private val baseDomain = "www.google.com"
private val poolClientFlow = Http()(system).cachedHostConnectionPool[Any](baseDomain, 80, ConnectionPoolSettings(config))
private val decider: Decider = {
case ex =>
ex.printStackTrace()
Supervision.Stop
}
private def sendMultipleRequests[T](items: Seq[(HttpRequest, T)]): Future[Seq[(Try[HttpResponse], T)]] =
Source.fromIterator(() => items.toIterator)
.via(poolClientFlow)
.log("Logger")(log = myAdapter)
.recoverWith {
case ex =>
println(ex)
null
}
.withAttributes(ActorAttributes.supervisionStrategy(decider))
.runWith(Sink.seq)
.map { v =>
println(s"Got ${v.length} responses in Flow")
v.asInstanceOf[Seq[(Try[HttpResponse], T)]]
}
def main(args: Array[String]) {
val headers = imSeq(Referer("https://www.google.com/"))
val reqPair = HttpRequest(uri = "/intl/en/policies/privacy").withHeaders(headers) -> "some req ID"
val requests = List.fill(10)(reqPair)
val qwe = sendMultipleRequests(requests).map { case responses =>
println(s"Got ${responses.length} responses")
system.terminate()
}
Await.ready(system.whenTerminated, Duration.Inf)
}
}
Also what's up with proxy support ? Doesn't seem to work for me either.
You need to consume the body of the response fully so that the connection is made available for subsequent requests. If you don't care about the response entity at all, then you can just drain it to a Sink.ignore, something like this:
resp.entity.dataBytes.runWith(Sink.ignore)
By the default config, when using a host connection pool, the max connections is set to 4. Each pool has it's own queue where requests wait until one of the open connections becomes available. If that queue ever goes over 32 (default config, can be changed, must be a power of 2) then yo will start seeing failures. In your case, you only do 10 requests, so you don't hit that limit. But by not consuming the response entity you don't free up the connection and everything else just queues in behind, waiting for the connections to free up.

Authentication Issue & Check Regex Issue Using Gatling

Want to Perform Load testing on Salesforce Platform. But it seems there is an error in authentication as well as regex part.
I am using Gatling testing tool & scala programming here.
If you guide me how to do load testing on salesforce that would be plus.
This is my code:
package default
import scala.concurrent.duration._
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import io.gatling.jdbc.Predef._
import io.gatling.core.Predef._
class requestUser extends Simulation {
val httpProtocol = http.baseURL("http://login.salesforce.com")
val Test = exec(http("Login")
.get("/")
.basicAuth("abc#gmail.com", "Password+Token")
.formParam("sessionId","*******")
.formParam("orgId","***********")
)
.exec(http("acc")
.get("/path")
.basicAuth("abc#gmail.com", "Password+Token")
.check(status.is(200))
**.check(css("#content"))
.check(regex("""<div id ="header">Choose a Username</div>"""))
.check(regex("""<td class = "datacell">Jaipur</td>"""))**
)
.exec(http("home")
.post("/home/home.jsp")
.formParam("Post", "Test from Gatling")
.check(regex())
)
var scn = scenario("scn").exec(Test)
setUp(
scn.inject(rampUsers(1) over (10 seconds))
).protocols(httpProtocol)
}

Why akka http is not emiting responses for first N requests?

I'm trying to use akka-http in order to make http requests to a single host (e.g. "akka.io"). The problem is that the created flow (Http().cachedHostConnectionPool) starts emitting responses only after N http requests are made, where N is equal to max-connections.
import scala.util.Failure
import scala.util.Success
import com.typesafe.config.ConfigFactory
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.HttpRequest
import akka.http.scaladsl.model.Uri.apply
import akka.http.scaladsl.settings.ConnectionPoolSettings
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.Sink
import akka.stream.scaladsl.Source
object ConnectionPoolExample extends App {
implicit val system = ActorSystem()
implicit val executor = system.dispatcher
implicit val materializer = ActorMaterializer()
val config = ConfigFactory.load()
val connectionPoolSettings = ConnectionPoolSettings(config).withMaxConnections(10)
lazy val poolClientFlow = Http().cachedHostConnectionPool[Unit]("akka.io", 80, connectionPoolSettings)
val fakeSource = Source.fromIterator[Unit] { () => Iterator.continually { Thread.sleep(1000); () } }
val requests = fakeSource.map { _ => println("Creating request"); HttpRequest(uri = "/") -> (()) }
val responses = requests.via(poolClientFlow)
responses.runForeach {
case (tryResponse, jsonData) =>
tryResponse match {
case Success(httpResponse) =>
httpResponse.entity.dataBytes.runWith(Sink.ignore)
println(s"status: ${httpResponse.status}")
case Failure(e) => {
println(e)
}
}
}
}
The output looks like this:
Creating request
Creating request
Creating request
Creating request
Creating request
Creating request
Creating request
Creating request
Creating request
Creating request
status: 200 OK
Creating request
status: 200 OK
Creating request
status: 200 OK
...
I am failing to find any configuration parameters which would allow emitting responses as soon as they are ready and not when the pool is out of free connections.
Thanks!
The reason is that you block the client from doing other work by calling Thread.sleep—that method is simply forbidden inside reactive programs. The proper and simpler approach is to use Source.tick.

Passing parameter - number of users

I'm using gatling in linux terminal. When I pass parameter like described in github I get error:
value users is not a member of Integer
This is my code:
package mypackage
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import io.gatling.jdbc.Predef._
import io.gatling.http.Headers.Names._
import scala.concurrent.duration._
import bootstrap._
import assertions._
import util.Random
class MySimulation extends Simulation {
val usersCount = Integer.getInteger("users", 1)
val links = csv("links.csv").random
val httpProtocol = http
.baseURL("http://mywebsite.com:8080/")
.acceptCharsetHeader("ISO-8859-1,utf-8;q=0.7,*;q=0.7")
.acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
.acceptEncodingHeader("gzip, deflate")
.acceptLanguageHeader("fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3")
.disableFollowRedirect
val headers_1 = Map(
"Keep-Alive" -> "115")
val headers_3 = Map(
"Keep-Alive" -> "115",
"Content-Type" -> "application/x-www-form-urlencoded")
val scn = scenario("big project benchmark")
.repeat(50) {
feed(links)
.exec(
http("request_1")
.get("${pageUri}")
.headers(headers_1)).pause(1000 millisecond)
}
setUp(scn.inject(ramp(usersCount users) over (30 seconds)))
.protocols(httpProtocol)
.assertions(global.successfulRequests.percent.is(100), details("request_1").responseTime.max.lessThan(1000))
I start this in terminal using:
JAVA_OPTS="-Dusers=300" ./gatling.sh -s mypackage.mySimulation -on testing -sd test1
Please, be patient, because I'm totally new to scala and gatling. Thanks for any help.
The problem comes from the usersCount users part of the setUp.
In Scala, this is interpreted as usersCount.users which, in our case does not exist since Integer does not have a users method.
I think (but I'm not sure since I cannot test it right now), that you should make usersCount an Int like so: val usersCount: Int = Integer.getInteger("users", 1).toInt.
Hope this helps!
PS: The reason you should convert Integer to Int is because of implicit conversions. This is a really powerful feature of Scala.
PPS: The wiki documentation was valid for Gatling 1.X, it will be updated accordingly for Gatling 2.X