From 35a3393cf554f2bc7e63ca1275a9425232db4f18 Mon Sep 17 00:00:00 2001 From: Guille Date: Mon, 18 Mar 2019 11:23:47 +0200 Subject: [PATCH] Fixed scalability test for V13 version of the project (#750) (#754) Upgraded to Gatling 3 Inlined request bodies Fixed mostly combobox requests Updated readme Formatted the scala file --- README.md | 4 +- pom.xml | 6 +- .../bodies/BaristaFlow_0004_request.txt | 1 - .../bodies/BaristaFlow_0009_request.txt | 1 - .../bodies/BaristaFlow_0010_request.txt | 1 - .../bodies/BaristaFlow_0027_request.txt | 1 - .../bodies/BaristaFlow_0036_request.txt | 1 - .../bodies/BaristaFlow_0037_a_request.txt | 1 - .../bodies/BaristaFlow_0037_request.txt | 1 - .../bodies/BaristaFlow_0037b_request.txt | 1 - .../bodies/BaristaFlow_0038_a_request.txt | 1 - .../bodies/BaristaFlow_0038_request.txt | 1 - .../bodies/BaristaFlow_0038b_request.txt | 1 - .../bodies/BaristaFlow_0043_a_request.txt | 1 - .../bodies/BaristaFlow_0043_request.txt | 1 - .../bodies/BaristaFlow_0044_request.txt | 1 - .../bodies/BaristaFlow_0045_request.txt | 1 - src/test/scala/BaristaFlow.scala | 476 ++++++++++-------- 18 files changed, 258 insertions(+), 243 deletions(-) delete mode 100644 src/test/resources/bodies/BaristaFlow_0004_request.txt delete mode 100644 src/test/resources/bodies/BaristaFlow_0009_request.txt delete mode 100644 src/test/resources/bodies/BaristaFlow_0010_request.txt delete mode 100644 src/test/resources/bodies/BaristaFlow_0027_request.txt delete mode 100644 src/test/resources/bodies/BaristaFlow_0036_request.txt delete mode 100644 src/test/resources/bodies/BaristaFlow_0037_a_request.txt delete mode 100644 src/test/resources/bodies/BaristaFlow_0037_request.txt delete mode 100644 src/test/resources/bodies/BaristaFlow_0037b_request.txt delete mode 100644 src/test/resources/bodies/BaristaFlow_0038_a_request.txt delete mode 100644 src/test/resources/bodies/BaristaFlow_0038_request.txt delete mode 100644 src/test/resources/bodies/BaristaFlow_0038b_request.txt delete mode 100644 src/test/resources/bodies/BaristaFlow_0043_a_request.txt delete mode 100644 src/test/resources/bodies/BaristaFlow_0043_request.txt delete mode 100644 src/test/resources/bodies/BaristaFlow_0044_request.txt delete mode 100644 src/test/resources/bodies/BaristaFlow_0045_request.txt diff --git a/README.md b/README.md index 0f68831b0..658501289 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ In order to run the scalability tests locally: 1. Start a test from the command line: ```bash - mvn -Pscalability gatling:execute + mvn -Pscalability gatling:test ``` 1. Test results are stored into target folder (e.g. to ```target/gatling/BaristaFlow-1487784042461/index.html```) @@ -106,7 +106,7 @@ In order to run the scalability tests locally: 1. By default the scalability test starts 100 user sessions at a 100 ms interval for one repeat, all of which connect to a locally running Bakery app. These defaults can be overridden with the `gatling.sessionCount`, `gatling.sessionStartInterval` `gatling.sessionRepeats`, and `gatling.baseUrl` system properties. See an example execution for 300 users started within 50 s: ```bash - mvn -Pscalability gatling:execute -Dgatling.sessionCount=300 -Dgatling.sessionStartInterval=50 + mvn -Pscalability gatling:test -Dgatling.sessionCount=300 -Dgatling.sessionStartInterval=50 ``` Note: If you run Bakery with an in-memory database (like H2, which is the default), it will logically use more memory than when using an external database (like PostgreSQL). It is recommend to run scalability tests for Bakery only after you have configured it to use an external database. diff --git a/pom.xml b/pom.xml index fc5224201..3fc83d638 100644 --- a/pom.xml +++ b/pom.xml @@ -33,9 +33,9 @@ 3.0.0 2.21.0 - 2.3.1 - 2.2.4 - 3.3.2 + 3.0.2 + 3.0.1 + 3.4.4 v8.1.2 diff --git a/src/test/resources/bodies/BaristaFlow_0004_request.txt b/src/test/resources/bodies/BaristaFlow_0004_request.txt deleted file mode 100644 index 663211a65..000000000 --- a/src/test/resources/bodies/BaristaFlow_0004_request.txt +++ /dev/null @@ -1 +0,0 @@ -{"csrfToken":"${seckey}","rpc":[{"type":"publishedEventHandler","node":${gridId},"templateEventMethodName":"setDetailsVisible","templateEventMethodArgs":[null]},{"type":"publishedEventHandler","node":${gridId},"templateEventMethodName":"confirmUpdate","templateEventMethodArgs":[0]}],"syncId":${syncId},"clientId":${clientId}} \ No newline at end of file diff --git a/src/test/resources/bodies/BaristaFlow_0009_request.txt b/src/test/resources/bodies/BaristaFlow_0009_request.txt deleted file mode 100644 index c4a564f2e..000000000 --- a/src/test/resources/bodies/BaristaFlow_0009_request.txt +++ /dev/null @@ -1 +0,0 @@ -{"csrfToken":"${seckey}","rpc":[{"type":"event","node":${newButtonId},"event":"click","data":{"event.shiftKey":false,"event.metaKey":false,"event.detail":1,"event.ctrlKey":false,"event.clientX":1118,"event.clientY":92,"event.altKey":false,"event.button":0,"event.screenY":801,"event.screenX":4154}}],"syncId":${syncId},"clientId":${clientId}} diff --git a/src/test/resources/bodies/BaristaFlow_0010_request.txt b/src/test/resources/bodies/BaristaFlow_0010_request.txt deleted file mode 100644 index 9e9c7c2fb..000000000 --- a/src/test/resources/bodies/BaristaFlow_0010_request.txt +++ /dev/null @@ -1 +0,0 @@ -{"csrfToken":"${seckey}","rpc":[{"type":"event","node":${dialogId},"event":"opened-changed"},{"type":"mSync","node":${statusId},"feature":1,"property":"filter","value":""},{"type":"mSync","node":${statusId},"feature":1,"property":"opened","value":false},{"type":"mSync","node":${dueTimeId},"feature":1,"property":"filter","value":""},{"type":"mSync","node":${dueTimeId},"feature":1,"property":"opened","value":false},{"type":"mSync","node":${dueDateId},"feature":1,"property":"opened","value":false}],"syncId":${syncId},"clientId":${clientId}} \ No newline at end of file diff --git a/src/test/resources/bodies/BaristaFlow_0027_request.txt b/src/test/resources/bodies/BaristaFlow_0027_request.txt deleted file mode 100644 index f97a0ea06..000000000 --- a/src/test/resources/bodies/BaristaFlow_0027_request.txt +++ /dev/null @@ -1 +0,0 @@ -{"csrfToken":"${seckey}","rpc":[{"type":"mSync","node":${customerId},"feature":1,"property":"value","value":"dasdasd asdasdas"}],"syncId":${syncId},"clientId":${clientId}} diff --git a/src/test/resources/bodies/BaristaFlow_0036_request.txt b/src/test/resources/bodies/BaristaFlow_0036_request.txt deleted file mode 100644 index 7cae15c8f..000000000 --- a/src/test/resources/bodies/BaristaFlow_0036_request.txt +++ /dev/null @@ -1 +0,0 @@ -{"csrfToken":"${seckey}","rpc":[{"type":"mSync","node":${phoneId},"feature":1,"property":"value","value":"+358 123456"}],"syncId":${syncId},"clientId":${clientId}} diff --git a/src/test/resources/bodies/BaristaFlow_0037_a_request.txt b/src/test/resources/bodies/BaristaFlow_0037_a_request.txt deleted file mode 100644 index 36c89aaea..000000000 --- a/src/test/resources/bodies/BaristaFlow_0037_a_request.txt +++ /dev/null @@ -1 +0,0 @@ -{"csrfToken":"${seckey}","rpc":[{"type":"mSync","node":${productsId},"feature":1,"property":"filter","value":""},{"type":"mSync","node":${productsId},"feature":1,"property":"opened","value":true},{"type":"mSync","node":${productsId},"feature":1,"property":"selectedItem","value":null}],"syncId":${syncId},"clientId":${clientId}} \ No newline at end of file diff --git a/src/test/resources/bodies/BaristaFlow_0037_request.txt b/src/test/resources/bodies/BaristaFlow_0037_request.txt deleted file mode 100644 index 79a98e616..000000000 --- a/src/test/resources/bodies/BaristaFlow_0037_request.txt +++ /dev/null @@ -1 +0,0 @@ -{"csrfToken":"${seckey}","rpc":[{"type":"mSync","node":${productsId},"feature":1,"property":"selectedItem","value":{"key":"1","label":"Strawberry Bun"}},{"type":"mSync","node":${productsId},"feature":1,"property":"opened","value":false}],"syncId":${syncId},"clientId":${clientId}} \ No newline at end of file diff --git a/src/test/resources/bodies/BaristaFlow_0037b_request.txt b/src/test/resources/bodies/BaristaFlow_0037b_request.txt deleted file mode 100644 index af7f576b7..000000000 --- a/src/test/resources/bodies/BaristaFlow_0037b_request.txt +++ /dev/null @@ -1 +0,0 @@ -{"csrfToken":"${seckey}","rpc":[{"type":"mSync","node":${products1Id2},"feature":1,"property":"filter","value":""},{"type":"mSync","node":${products1Id2},"feature":1,"property":"opened","value":false}],"syncId":${syncId},"clientId":${clientId}} \ No newline at end of file diff --git a/src/test/resources/bodies/BaristaFlow_0038_a_request.txt b/src/test/resources/bodies/BaristaFlow_0038_a_request.txt deleted file mode 100644 index d1644e0e2..000000000 --- a/src/test/resources/bodies/BaristaFlow_0038_a_request.txt +++ /dev/null @@ -1 +0,0 @@ -{"csrfToken":"${seckey}","rpc":[{"type":"mSync","node":${products2Id},"feature":1,"property":"filter","value":""},{"type":"mSync","node":${products2Id},"feature":1,"property":"opened","value":true},{"type":"mSync","node":${products2Id},"feature":1,"property":"selectedItem","value":null}],"syncId":${syncId},"clientId":${clientId}} \ No newline at end of file diff --git a/src/test/resources/bodies/BaristaFlow_0038_request.txt b/src/test/resources/bodies/BaristaFlow_0038_request.txt deleted file mode 100644 index 2950e492f..000000000 --- a/src/test/resources/bodies/BaristaFlow_0038_request.txt +++ /dev/null @@ -1 +0,0 @@ -{"csrfToken":"${seckey}","rpc":[{"type":"mSync","node":${products2Id},"feature":1,"property":"selectedItem","value":{"key":"2","label":"Vanilla Cracker"}},{"type":"mSync","node":${products2Id},"feature":1,"property":"opened","value":false}],"syncId":${syncId},"clientId":${clientId}} \ No newline at end of file diff --git a/src/test/resources/bodies/BaristaFlow_0038b_request.txt b/src/test/resources/bodies/BaristaFlow_0038b_request.txt deleted file mode 100644 index 840ec2ecf..000000000 --- a/src/test/resources/bodies/BaristaFlow_0038b_request.txt +++ /dev/null @@ -1 +0,0 @@ -{"csrfToken":"${seckey}","rpc":[{"type":"mSync","node":${products1Id2},"feature":1,"property":"filter","value":""},{"type":"mSync","node":${products1Id2},"feature":1,"property":"opened","value":false},{"type":"mSync","node":${products2Id2},"feature":1,"property":"filter","value":""},{"type":"mSync","node":${products2Id2},"feature":1,"property":"opened","value":false}],"syncId":${syncId},"clientId":${clientId}} \ No newline at end of file diff --git a/src/test/resources/bodies/BaristaFlow_0043_a_request.txt b/src/test/resources/bodies/BaristaFlow_0043_a_request.txt deleted file mode 100644 index b905e56a4..000000000 --- a/src/test/resources/bodies/BaristaFlow_0043_a_request.txt +++ /dev/null @@ -1 +0,0 @@ -{"csrfToken":"${seckey}","rpc":[{"type":"mSync","node":${storeId},"feature":1,"property":"filter","value":""},{"type":"mSync","node":${storeId},"feature":1,"property":"opened","value":true},{"type":"mSync","node":${storeId},"feature":1,"property":"selectedItem","value":null}],"syncId":${syncId},"clientId":${clientId}} diff --git a/src/test/resources/bodies/BaristaFlow_0043_request.txt b/src/test/resources/bodies/BaristaFlow_0043_request.txt deleted file mode 100644 index b0aab3ca8..000000000 --- a/src/test/resources/bodies/BaristaFlow_0043_request.txt +++ /dev/null @@ -1 +0,0 @@ -{"csrfToken":"${seckey}","rpc":[{"type":"mSync","node":${storeId},"feature":1,"property":"selectedItem","value":{"key":"1","label":"Store"}},{"type":"mSync","node":${storeId},"feature":1,"property":"opened","value":false}],"syncId":${syncId},"clientId":${clientId}} \ No newline at end of file diff --git a/src/test/resources/bodies/BaristaFlow_0044_request.txt b/src/test/resources/bodies/BaristaFlow_0044_request.txt deleted file mode 100644 index 36980cc1e..000000000 --- a/src/test/resources/bodies/BaristaFlow_0044_request.txt +++ /dev/null @@ -1 +0,0 @@ -{"csrfToken":"${seckey}","rpc":[{"type":"event","node":${reviewId},"event":"click","data":{"event.shiftKey":false,"event.metaKey":false,"event.detail":1,"event.ctrlKey":false,"event.clientX":1108,"event.clientY":759,"event.altKey":false,"event.button":0,"event.screenY":1468,"event.screenX":4144}}],"syncId":${syncId},"clientId":${clientId}} diff --git a/src/test/resources/bodies/BaristaFlow_0045_request.txt b/src/test/resources/bodies/BaristaFlow_0045_request.txt deleted file mode 100644 index 9f0266c58..000000000 --- a/src/test/resources/bodies/BaristaFlow_0045_request.txt +++ /dev/null @@ -1 +0,0 @@ -{"csrfToken":"${seckey}","rpc":[{"type":"event","node":${saveId},"event":"click","data":{"event.shiftKey":false,"event.metaKey":false,"event.detail":1,"event.ctrlKey":false,"event.clientX":1108,"event.clientY":759,"event.altKey":false,"event.button":0,"event.screenY":1468,"event.screenX":4144}}],"syncId":${syncId},"clientId":${clientId}} \ No newline at end of file diff --git a/src/test/scala/BaristaFlow.scala b/src/test/scala/BaristaFlow.scala index 12564ec34..b20a52d0c 100644 --- a/src/test/scala/BaristaFlow.scala +++ b/src/test/scala/BaristaFlow.scala @@ -6,227 +6,257 @@ import io.gatling.jdbc.Predef._ class BaristaFlow extends Simulation { - def toInt(s: String): Option[Int] = { - try { - Some(s.toInt) - } catch { - case _: NumberFormatException => None - } - } - - // The URL of the system under test - val baseUrl: String = System.getProperty("gatling.baseUrl", "http://localhost:8080") - - // The total number of simulated user sessions - // NOTE: the number of concurrent sessions is lower because sessions start one by one - // with a given interval and some may finish before the last session starts. - val sessionCount: Int = toInt(System.getProperty("gatling.sessionCount", "")) match { - case Some(n) => n - case None => 100 // the default - } - - // The interval (in milliseconds) between starting new user sessions - val sessionStartInterval: Int = toInt(System.getProperty("gatling.sessionStartInterval", "")) match { - case Some(n) => n - case None => 100 // the default - } - - // The repeat count of the scenario, by default executed only once - val sessionRepeats: Int = toInt(System.getProperty("gatling.sessionRepeats", "")) match { - case Some(n) => n - case None => 1 // the default - } - - val httpProtocol = http - .baseURL(baseUrl) - .acceptHeader("*/*") - .acceptEncodingHeader("gzip, deflate") - .acceptLanguageHeader("en-US,en;q=0.5") - .userAgentHeader("Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:57.0) Gecko/20100101 Firefox/57.0") - - val headers_0 = Map( - "Accept" -> "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", - "Upgrade-Insecure-Requests" -> "1") - - val headers_4 = Map("Content-type" -> "application/json; charset=UTF-8") - - val initSyncAndClientIds = exec((session) => { - session.setAll( - "syncId" -> 0, - "clientId" -> 0 - ) - }) - - val url = "/" - val uidlUrl = url + "?v-r=uidl&v-uiId=${uiId}" - - val uIdExtract = regex(""""v-uiId":(\d+)""").saveAs("uiId") - val syncIdExtract = regex("""syncId":([0-9]*)""").saveAs("syncId") - val clientIdExtract = regex("""clientId":([0-9]*)""").saveAs("clientId") - val xsrfTokenExtract = regex("""Vaadin-Security-Key":\s?"([^"]*)""").saveAs("seckey") - - // Storefront from initial response - val gridIdExtract = regex("""node":(\d+),+"type":"put",+"key":"payload",+"feat":[0-9]*,+"value":\{+"type":"@id",+"payload":"grid"""").saveAs("gridId") - val dialogIdExtract = regex("""node":(\d+),+"type":"put",+"key":"payload",+"feat":[0-9]*,+"value":\{+"type":"@id",+"payload":"dialog"""").saveAs("dialogId") - val newButtonIdExtract = regex("""node":(\d+),+"type":"put",+"key":"payload",+"feat":[0-9]*,+"value":\{+"type":"@id",+"payload":"action"""").saveAs("newButtonId") - val customerIdExtract = regex("""node":(\d+),+"type":"put",+"key":"payload",+"feat":[0-9]*,+"value":\{+"type":"@id",+"payload":"customerName"""").saveAs("customerId") - val phoneIdExtract = regex("""node":(\d+),+"type":"put",+"key":"payload",+"feat":[0-9]*,+"value":\{+"type":"@id",+"payload":"customerNumber"""").saveAs("phoneId") - val reviewIdExtract = regex("""node":(\d+),+"type":"put",+"key":"payload",+"feat":[0-9]*,+"value":\{+"type":"@id",+"payload":"review"""").saveAs("reviewId") - val saveIdExtract = regex("""node":(\d+),+"type":"put",+"key":"payload",+"feat":[0-9]*,+"value":\{+"type":"@id",+"payload":"save"""").saveAs("saveId") - val saveStoreExtract = regex("""node":(\d+),+"type":"put",+"key":"payload",+"feat":[0-9]*,+"value":\{+"type":"@id",+"payload":"pickupLocation"""").saveAs("storeId") - val statusIdExtract = regex("""node":(\d+),+"type":"put",+"key":"payload",+"feat":[0-9]*,+"value":\{+"type":"@id",+"payload":"status"""").saveAs("statusId") - val dueTimeIdExtract = regex("""node":(\d+),+"type":"put",+"key":"payload",+"feat":[0-9]*,+"value":\{+"type":"@id",+"payload":"dueTime"""").saveAs("dueTimeId") - val dueDateIdExtract = regex("""node":(\d+),+"type":"put",+"key":"payload",+"feat":[0-9]*,+"value":\{+"type":"@id",+"payload":"dueDate"""").saveAs("dueDateId") - - // Order dialog - val amountIdExtract = regex("""node":(\d+),"type":"put","key":"payload","feat":[0-9]*,"value":\{"type":"@id","payload":"amount"""").saveAs("amountId") - val productsIdExtract = regex("""node":(\d+),"type":"put","key":"payload","feat":[0-9]*,"value":\{"type":"@id","payload":"products"""").saveAs("productsId") - val products2IdExtract = regex("""payload":"products.{2000,4000}node":(\d+),"type":"put","key":"payload","feat":[0-9]*,"value":\{"type":"@id","payload":"products"""").saveAs("products2Id") - val productsId1Extract2 = regex("""node":(\d+),"type":"put","key":"selectedItem","feat":[0-9],"value":\{"key":"[0-9]","label":"Strawberry Bun""").saveAs("products1Id2") - val productsId2Extract2 = regex("""node":(\d+),"type":"put","key":"selectedItem","feat":[0-9],"value":\{"key":"[0-9]","label":"Vanilla Cracker""").saveAs("products2Id2") - - - val scn = scenario("BaristaFlow") - .repeat(sessionRepeats) { - exec(http("Initial request") - .get(url) - .headers(headers_0) - .check(xsrfTokenExtract) - ) - .exec(initSyncAndClientIds) - .pause(8, 11) - - .exec(http("Login") - .post("/login") - .headers(headers_0) - .formParam("username", "barista@vaadin.com") - .formParam("password", "barista") - .formParam("prefix", "undefined") - .formParam("suffix", "undefined") - .check(uIdExtract) - .check(gridIdExtract) - .check(newButtonIdExtract) - .check(dialogIdExtract) - .check(syncIdExtract).check(clientIdExtract) - ) - .pause(2) - - .exec(http("First xhr, init grid") - .post(uidlUrl) - .headers(headers_4) - .body(ElFileBody("BaristaFlow_0004_request.txt")) - .check(syncIdExtract).check(clientIdExtract)) - .pause(4, 10) - - .exec(http("Click new order") - .post(uidlUrl) - .headers(headers_4) - .body(ElFileBody("BaristaFlow_0009_request.txt")) - .check(syncIdExtract).check(clientIdExtract) - .check(amountIdExtract) - .check(productsIdExtract) - .check(customerIdExtract) - .check(phoneIdExtract) - .check(reviewIdExtract) - .check(saveStoreExtract) - .check(statusIdExtract) - .check(dueTimeIdExtract) - .check(dueDateIdExtract) - ) - .pause(5) - - .exec(http("Selection changes") - .post(uidlUrl) - .headers(headers_4) - .body(ElFileBody("BaristaFlow_0010_request.txt")) - .check(syncIdExtract).check(clientIdExtract)) - .pause(2) - - .exec(http("Customer name") - .post(uidlUrl) - .headers(headers_4) - .body(ElFileBody("BaristaFlow_0027_request.txt")) - .check(syncIdExtract).check(clientIdExtract)) - .pause(5, 6) - - .exec(http("Phone number") - .post(uidlUrl) - .headers(headers_4) - .body(ElFileBody("BaristaFlow_0036_request.txt")) - .check(syncIdExtract).check(clientIdExtract)) - .pause(5, 6) - .exec(http("Product CB1 opened") - .post(uidlUrl) - .headers(headers_4) - .body(ElFileBody("BaristaFlow_0037_a_request.txt")) - .check(syncIdExtract).check(clientIdExtract)) - .pause(4, 6) - .exec(http("Select product") - .post(uidlUrl) - .headers(headers_4) - .body(ElFileBody("BaristaFlow_0037_request.txt")) - .check(syncIdExtract).check(clientIdExtract) - .check(productsId1Extract2) - .check(products2IdExtract) - ) - .pause(2) - .exec(http("Product CB1 closed") - .post(uidlUrl) - .headers(headers_4) - .body(ElFileBody("BaristaFlow_0037b_request.txt")) - .check(syncIdExtract).check(clientIdExtract)) - .pause(2) - .exec(http("Product CB2 opened") - .post(uidlUrl) - .headers(headers_4) - .body(ElFileBody("BaristaFlow_0038_a_request.txt")) - .check(syncIdExtract).check(clientIdExtract)) - .pause(5, 7) - .exec(http("Select 2. product") - .post(uidlUrl) - .headers(headers_4) - .body(ElFileBody("BaristaFlow_0038_request.txt")) - .check(syncIdExtract).check(clientIdExtract) - .check(productsId1Extract2) - .check(productsId2Extract2) - ) - .pause(2) - .exec(http("Product CB2 closed") - .post(uidlUrl) - .headers(headers_4) - .body(ElFileBody("BaristaFlow_0038b_request.txt")) - .check(syncIdExtract).check(clientIdExtract)) - .pause(5, 7) - .exec(http("Select Store opened") - .post(uidlUrl) - .headers(headers_4) - .body(ElFileBody("BaristaFlow_0043_a_request.txt")) - .check(syncIdExtract).check(clientIdExtract)) - .pause(2) - .exec(http("Select Store selected and closed") - .post(uidlUrl) - .headers(headers_4) - .body(ElFileBody("BaristaFlow_0043_request.txt")) - .check(syncIdExtract).check(clientIdExtract)) - .pause(2) - .exec(http("Click review order") - .post(uidlUrl) - .headers(headers_4) - .body(ElFileBody("BaristaFlow_0044_request.txt")) - .check(syncIdExtract).check(clientIdExtract) - .check(regex("""Order placed""")) - .check(saveIdExtract) - ) - .pause(2) - .exec(http("Click place order") - .post(uidlUrl) - .headers(headers_4) - .body(ElFileBody("BaristaFlow_0045_request.txt")) - .check(syncIdExtract).check(clientIdExtract) - .check(regex("""Order was created""")) - ) - .pause(2, 6) - } - - setUp(scn.inject(rampUsers(sessionCount) over sessionStartInterval)).protocols(httpProtocol) + def toInt(s: String): Option[Int] = { + try { + Some(s.toInt) + } catch { + case _: NumberFormatException => None + } + } + + // The URL of the system under test + val baseUrl: String = System.getProperty("gatling.baseUrl", "http://localhost:8080") + + // The total number of simulated user sessions + // NOTE: the number of concurrent sessions is lower because sessions start one by one + // with a given interval and some may finish before the last session starts. + val sessionCount: Int = toInt(System.getProperty("gatling.sessionCount", "")) match { + case Some(n) => n + case None => 100 // the default + } + + // The interval (in milliseconds) between starting new user sessions + val sessionStartInterval: Int = toInt(System.getProperty("gatling.sessionStartInterval", "")) match { + case Some(n) => n + case None => 100 // the default + } + + // The repeat count of the scenario, by default executed only once + val sessionRepeats: Int = toInt(System.getProperty("gatling.sessionRepeats", "")) match { + case Some(n) => n + case None => 1 // the default + } + + val httpProtocol = http + .baseUrl(baseUrl) + .acceptHeader("*/*") + .acceptEncodingHeader("gzip, deflate") + .acceptLanguageHeader("en-US,en;q=0.5") + .userAgentHeader("Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:57.0) Gecko/20100101 Firefox/57.0") + + val headers_0 = Map( + "Accept" -> "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", + "Upgrade-Insecure-Requests" -> "1") + + val headers_4 = Map("Content-type" -> "application/json; charset=UTF-8") + + val initSyncAndClientIds = exec((session) => { + session.setAll( + "syncId" -> 0, + "clientId" -> 0 + ) + }) + + val url = "/" + val uidlUrl = url + "?v-r=uidl&v-uiId=${uiId}" + + val uIdExtract = regex(""""v-uiId":(\d+)""").saveAs("uiId") + val syncIdExtract = regex("""syncId":([0-9]*)""").saveAs("syncId") + val clientIdExtract = regex("""clientId":([0-9]*)""").saveAs("clientId") + val xsrfTokenExtract = regex("""Vaadin-Security-Key":\s?"([^"]*)""").saveAs("seckey") + + // Storefront from initial response + val gridIdExtract = regex("""node":(\d+),+"type":"put",+"key":"payload",+"feat":[0-9]*,+"value":\{+"type":"@id",+"payload":"grid"""").saveAs("gridId") + val dialogIdExtract = regex("""node":(\d+),+"type":"put",+"key":"payload",+"feat":[0-9]*,+"value":\{+"type":"@id",+"payload":"dialog"""").saveAs("dialogId") + val newButtonIdExtract = regex("""node":(\d+),+"type":"put",+"key":"payload",+"feat":[0-9]*,+"value":\{+"type":"@id",+"payload":"action"""").saveAs("newButtonId") + val customerIdExtract = regex("""node":(\d+),+"type":"put",+"key":"payload",+"feat":[0-9]*,+"value":\{+"type":"@id",+"payload":"customerName"""").saveAs("customerId") + val phoneIdExtract = regex("""node":(\d+),+"type":"put",+"key":"payload",+"feat":[0-9]*,+"value":\{+"type":"@id",+"payload":"customerNumber"""").saveAs("phoneId") + val reviewIdExtract = regex("""node":(\d+),+"type":"put",+"key":"payload",+"feat":[0-9]*,+"value":\{+"type":"@id",+"payload":"review"""").saveAs("reviewId") + val saveIdExtract = regex("""node":(\d+),+"type":"put",+"key":"payload",+"feat":[0-9]*,+"value":\{+"type":"@id",+"payload":"save"""").saveAs("saveId") + val saveStoreExtract = regex("""node":(\d+),+"type":"put",+"key":"payload",+"feat":[0-9]*,+"value":\{+"type":"@id",+"payload":"pickupLocation"""").saveAs("storeId") + val statusIdExtract = regex("""node":(\d+),+"type":"put",+"key":"payload",+"feat":[0-9]*,+"value":\{+"type":"@id",+"payload":"status"""").saveAs("statusId") + val dueTimeIdExtract = regex("""node":(\d+),+"type":"put",+"key":"payload",+"feat":[0-9]*,+"value":\{+"type":"@id",+"payload":"dueTime"""").saveAs("dueTimeId") + val dueDateIdExtract = regex("""node":(\d+),+"type":"put",+"key":"payload",+"feat":[0-9]*,+"value":\{+"type":"@id",+"payload":"dueDate"""").saveAs("dueDateId") + + // Order dialog + val amountIdExtract = regex("""node":(\d+),"type":"put","key":"payload","feat":[0-9]*,"value":\{"type":"@id","payload":"amount"""").saveAs("amountId") + val productsIdExtract = regex("""node":(\d+),"type":"put","key":"payload","feat":[0-9]*,"value":\{"type":"@id","payload":"products"""").saveAs("productsId") + val products2IdExtract = regex("""payload":"products.{2000,4000}node":(\d+),"type":"put","key":"payload","feat":[0-9]*,"value":\{"type":"@id","payload":"products"""").saveAs("products2Id") + val productsId1Extract2 = regex("""node":(\d+),"type":"put","key":"selectedItem","feat":[0-9],"value":\{"key":"[0-9]","label":"Strawberry Bun""").saveAs("products1Id2") + val productsId2Extract2 = regex("""node":(\d+),"type":"put","key":"selectedItem","feat":[0-9],"value":\{"key":"[0-9]","label":"Vanilla Cracker""").saveAs("products2Id2") + val productsId3Extract = regex("""payload":"products.{2000,4000}payload":"products.{2000,4000}node":(\d+),"type":"put","key":"payload","feat":[0-9]*,"value":\{"type":"@id","payload":"products"""").saveAs("products3Id") + + var rpcPrefix = """{"csrfToken":"${seckey}","rpc":[""" + var rpcSuffix = """],"syncId":${syncId},"clientId":${clientId}}""" + + def createRpc(s: String): String = { + rpcPrefix + s + rpcSuffix + } + + val scn = scenario("BaristaFlow") + .repeat(sessionRepeats) { + exec(http("Initial request") + .get(url) + .headers(headers_0) + .check(xsrfTokenExtract) + ) + .exec(initSyncAndClientIds) + .pause(8, 11) + + .exec(http("Login") + .post("/login") + .headers(headers_0) + .formParam("username", "barista@vaadin.com") + .formParam("password", "barista") + .formParam("prefix", "undefined") + .formParam("suffix", "undefined") + .check(uIdExtract) + .check(gridIdExtract) + .check(newButtonIdExtract) + .check(dialogIdExtract) + .check(syncIdExtract).check(clientIdExtract) + ) + .pause(2) + + .exec(http("First xhr, init grid") + .post(uidlUrl) + .headers(headers_4) + .body(StringBody(createRpc("""{"type":"publishedEventHandler","node":${gridId},"templateEventMethodName":"setDetailsVisible","templateEventMethodArgs":[null]},{"type":"publishedEventHandler","node":${gridId},"templateEventMethodName":"confirmUpdate","templateEventMethodArgs":[0]}"""))).asJson + .check(syncIdExtract).check(clientIdExtract)) + .pause(4, 10) + + .exec(http("Click new order") + .post(uidlUrl) + .headers(headers_4) + .body(StringBody(createRpc("""{"type":"event","node":${newButtonId},"event":"click","data":{"event.shiftKey":false,"event.metaKey":false,"event.detail":1,"event.ctrlKey":false,"event.clientX":1118,"event.clientY":92,"event.altKey":false,"event.button":0,"event.screenY":801,"event.screenX":4154}}"""))).asJson + .check(syncIdExtract).check(clientIdExtract) + .check(amountIdExtract) + .check(productsIdExtract) + .check(customerIdExtract) + .check(phoneIdExtract) + .check(reviewIdExtract) + .check(saveStoreExtract) + .check(statusIdExtract) + .check(dueTimeIdExtract) + .check(dueDateIdExtract) + ) + .pause(5) + + .exec(http("Selection changes") + .post(uidlUrl) + .headers(headers_4) + .body(StringBody(createRpc("""{"type":"event","node":${dialogId},"event":"opened-changed"},{"type":"mSync","node":${statusId},"feature":1,"property":"filter","value":""},{"type":"mSync","node":${statusId},"feature":1,"property":"opened","value":false},{"type":"mSync","node":${dueTimeId},"feature":1,"property":"filter","value":""},{"type":"mSync","node":${dueTimeId},"feature":1,"property":"opened","value":false},{"type":"mSync","node":${dueDateId},"feature":1,"property":"opened","value":false}"""))).asJson + .check(syncIdExtract).check(clientIdExtract)) + .pause(2) + + .exec(http("Customer name") + .post(uidlUrl) + .headers(headers_4) + .body(StringBody(createRpc("""{"type":"mSync","node":${customerId},"feature":1,"property":"value","value":"dasdasd asdasdas"}"""))).asJson + .check(syncIdExtract).check(clientIdExtract)) + .pause(5, 6) + + .exec(http("Phone number") + .post(uidlUrl) + .headers(headers_4) + .body(StringBody(createRpc("""{"type":"mSync","node":${phoneId},"feature":1,"property":"value","value":"+358 123456"}"""))).asJson + .check(syncIdExtract).check(clientIdExtract)) + .pause(5, 6) + + // Product select 1 + .exec(http("Product CB1 opened") + .post(uidlUrl) + .headers(headers_4) + .body(StringBody(createRpc("""{"type":"publishedEventHandler","node":${productsId},"templateEventMethodName":"setRequestedRange","templateEventMethodArgs":[0,50,""]},{"type":"mSync","node":${productsId},"feature":1,"property":"opened","value":true}"""))).asJson + .check(syncIdExtract).check(clientIdExtract)) + .pause(1) + .exec(http("Product CB1 opened 2") + .post(uidlUrl) + .headers(headers_4) + .body(StringBody(createRpc("""{"type":"publishedEventHandler","node":${productsId},"templateEventMethodName":"confirmUpdate","templateEventMethodArgs":[1]}"""))).asJson + .check(syncIdExtract).check(clientIdExtract)) + .pause(3, 5) + .exec(http("Select product") + .post(uidlUrl) + .headers(headers_4) + .body(StringBody(createRpc("""{"type":"mSync","node":${productsId},"feature":1,"property":"selectedItem","value":{"key":"1","label":"Strawberry Bun"}},{"type":"mSync","node":${productsId},"feature":1,"property":"value","value":"1"},{"type":"mSync","node":${productsId},"feature":1,"property":"opened","value":false}"""))).asJson + .check(syncIdExtract).check(clientIdExtract) + .check(productsId1Extract2) + .check(products2IdExtract) + ) + .pause(2) + .exec(http("Product CB1 closed") + .post(uidlUrl) + .headers(headers_4) + .body(StringBody(createRpc("""{"type":"mSync","node":${products1Id2},"feature":1,"property":"filter","value":""},{"type":"mSync","node":${products1Id2},"feature":1,"property":"opened","value":false},{"type":"mSync","node":${products2Id},"feature":1,"property":"filter","value":""},{"type":"mSync","node":${products2Id},"feature":1,"property":"opened","value":false}"""))).asJson + .check(syncIdExtract).check(clientIdExtract)) + .pause(2) + // Product select 2 + + .exec(http("Product CB2 opened") + .post(uidlUrl) + .headers(headers_4) + .body(StringBody(createRpc("""{"type":"publishedEventHandler","node":${products2Id},"templateEventMethodName":"setRequestedRange","templateEventMethodArgs":[0,50,""]},{"type":"mSync","node":${products2Id},"feature":1,"property":"opened","value":true}"""))).asJson + .check(syncIdExtract).check(clientIdExtract)) + .pause(1) + .exec(http("Product CB2 opened 2") + .post(uidlUrl) + .headers(headers_4) + .body(StringBody(createRpc("""{"type":"publishedEventHandler","node":${products2Id},"templateEventMethodName":"confirmUpdate","templateEventMethodArgs":[1]}"""))).asJson + .check(syncIdExtract).check(clientIdExtract)) + .pause(3, 5) + .exec(http("Select product 2") + .post(uidlUrl) + .headers(headers_4) + .body(StringBody(createRpc("""{"type":"mSync","node":${products2Id},"feature":1,"property":"selectedItem","value":{"key":"2","label":"Vanilla Cracker"}},{"type":"mSync","node":${products2Id},"feature":1,"property":"value","value":"2"},{"type":"mSync","node":${products2Id},"feature":1,"property":"opened","value":false}"""))).asJson + .check(syncIdExtract).check(clientIdExtract) + .check(productsId2Extract2) + .check(productsId3Extract) + ) + .pause(2) + .exec(http("Product CB2 closed") + .post(uidlUrl) + .headers(headers_4) + .body(StringBody(createRpc("""{"type":"mSync","node":${products2Id2},"feature":1,"property":"filter","value":""},{"type":"mSync","node":${products2Id2},"feature":1,"property":"opened","value":false},{"type":"mSync","node":${products3Id},"feature":1,"property":"filter","value":""},{"type":"mSync","node":${products3Id},"feature":1,"property":"opened","value":false}"""))).asJson + .check(syncIdExtract).check(clientIdExtract)) + .pause(2) + + .exec(http("Select Store opened") + .post(uidlUrl) + .headers(headers_4) + .body(StringBody(createRpc("""{"type":"publishedEventHandler","node":${storeId},"templateEventMethodName":"setRequestedRange","templateEventMethodArgs":[0,50,""]},{"type":"mSync","node":${storeId},"feature":1,"property":"opened","value":true}"""))).asJson + .check(syncIdExtract).check(clientIdExtract)) + .pause(1) + .exec(http("Select Store opened 2") + .post(uidlUrl) + .headers(headers_4) + .body(StringBody(createRpc("""{"type":"publishedEventHandler","node":${storeId},"templateEventMethodName":"confirmUpdate","templateEventMethodArgs":[1]}"""))).asJson + .check(syncIdExtract).check(clientIdExtract)) + .pause(1) + .exec(http("Select Store selected and closed") + .post(uidlUrl) + .headers(headers_4) + .body(StringBody(createRpc("""{"type":"mSync","node":${storeId},"feature":1,"property":"selectedItem","value":{"key":"1","label":"Store"}},{"type":"mSync","node":${storeId},"feature":1,"property":"value","value":"1"},{"type":"mSync","node":${storeId},"feature":1,"property":"opened","value":false}"""))).asJson + .check(syncIdExtract).check(clientIdExtract)) + .pause(2) + .exec(http("Click review order") + .post(uidlUrl) + .headers(headers_4) + .body(StringBody(createRpc("""{"type":"event","node":${reviewId},"event":"click","data":{"event.shiftKey":false,"event.metaKey":false,"event.detail":1,"event.ctrlKey":false,"event.clientX":1108,"event.clientY":759,"event.altKey":false,"event.button":0,"event.screenY":1468,"event.screenX":4144}}"""))).asJson + .check(syncIdExtract).check(clientIdExtract) + .check(regex("""Order placed""")) + .check(saveIdExtract) + ) + .pause(2) + .exec(http("Click place order") + .post(uidlUrl) + .headers(headers_4) + .body(StringBody(createRpc("""{"type":"event","node":${saveId},"event":"click","data":{"event.shiftKey":false,"event.metaKey":false,"event.detail":1,"event.ctrlKey":false,"event.clientX":1108,"event.clientY":759,"event.altKey":false,"event.button":0,"event.screenY":1468,"event.screenX":4144}}"""))).asJson + .check(syncIdExtract).check(clientIdExtract) + .check(regex("""Order was created""")) + ) + .pause(2, 6) + } + + setUp(scn.inject(rampUsers(sessionCount) during (sessionStartInterval seconds))).protocols(httpProtocol) } \ No newline at end of file