You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@usergrid.apache.org by to...@apache.org on 2015/08/03 22:31:02 UTC
[18/21] incubator-usergrid git commit: USERGRID-871: add audit
simulations
USERGRID-871: add audit simulations
Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/32fefb98
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/32fefb98
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/32fefb98
Branch: refs/heads/two-dot-o-dev
Commit: 32fefb98cf5c0a5885e5453a1a3183deaa65c708
Parents: 3976ff9
Author: Mike Dunker <md...@apigee.com>
Authored: Fri Jul 31 22:24:33 2015 -0700
Committer: Mike Dunker <md...@apigee.com>
Committed: Fri Jul 31 22:24:33 2015 -0700
----------------------------------------------------------------------
.../loadtests/runAuditGetCollectionEntities.sh | 71 ++++++++++
.../runAuditVerifyCollectionEntities.sh | 71 ++++++++++
.../datagenerators/FeederGenerator.scala | 60 ++++++---
.../usergrid/enums/ConfigProperties.scala | 8 +-
.../apache/usergrid/enums/ScenarioType.scala | 4 +-
.../apache/usergrid/helpers/Extractors.scala | 7 +
.../org/apache/usergrid/helpers/Setup.scala | 27 ++++
.../usergrid/scenarios/AuditScenarios.scala | 133 +++++++++++++++++++
.../scenarios/EntityCollectionScenarios.scala | 5 +-
.../org/apache/usergrid/settings/Settings.scala | 97 +++++++++++++-
.../usergrid/simulations/AuditSimulation.scala | 68 ++++++++++
stack/loadtests/src/test/resources/dummy.csv | 1 -
.../src/test/resources/dummyAuditUuid.csv | 1 +
.../loadtests/src/test/resources/dummyUuid.csv | 1 +
14 files changed, 526 insertions(+), 28 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/32fefb98/stack/loadtests/runAuditGetCollectionEntities.sh
----------------------------------------------------------------------
diff --git a/stack/loadtests/runAuditGetCollectionEntities.sh b/stack/loadtests/runAuditGetCollectionEntities.sh
new file mode 100755
index 0000000..f34ea54
--- /dev/null
+++ b/stack/loadtests/runAuditGetCollectionEntities.sh
@@ -0,0 +1,71 @@
+#!/bin/bash
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+die() { echo "$@" 1>&2 ; exit 1; }
+
+####
+#This is a script to simplify running gatling tests. It will default several parameters, invoke the maven plugins
+#Then aggregate the results
+####
+[ "$#" -ge 4 ] || die "At least 4 arguments required, $# provided. Example is $0 URL RAMP_USERS RAMP_TIME(seconds) AUDIT_UUID_FILENAME"
+
+URL="$1"
+RAMP_USERS="$2"
+RAMP_TIME="$3"
+AUDIT_UUID_FILENAME="$4"
+
+shift 4
+
+#Compile everything
+mvn compile
+
+#Set the app id to be a date epoch for uniqueness
+#APP=$(date +%s)
+ADMIN_USER=superuser
+ADMIN_PASSWORD=test
+ORG=gatling
+APP=millionentities
+SCENARIO_TYPE=auditGetCollectionEntities
+SEARCH_LIMIT=1000
+
+AUTH_TYPE=token
+TOKEN_TYPE=management
+
+#Execute the test
+mvn gatling:execute \
+-Dorg=${ORG} \
+-Dapp=${APP} \
+-Dbaseurl=${URL} \
+-DadminUser=${ADMIN_USER} \
+-DadminPassword=${ADMIN_PASSWORD} \
+-DrampUsers=${RAMP_USERS} \
+-DrampTime=${RAMP_TIME} \
+-DscenarioType=${SCENARIO_TYPE} \
+-DauthType=${AUTH_TYPE} \
+-DtokenType=${TOKEN_TYPE} \
+-DauditUuidFilename=${AUDIT_UUID_FILENAME} \
+-DsearchLimit=${SEARCH_LIMIT} \
+-Dgatling.simulationClass=org.apache.usergrid.simulations.AuditSimulation
+
+
+
+#Now move all the reports
+#AGGREGATE_DIR="target/aggregate-$(date +%s)"
+
+#mkdir -p ${AGGREGATE_DIR}
+
+#copy to the format of target/aggregate(date)/(simnulationame)-simulation.log
+#find target -name "simulation.log" -exec cp {} ${AGGREGATE_DIR}/$(basename $(dirname {} ))-simulation.log \;
+
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/32fefb98/stack/loadtests/runAuditVerifyCollectionEntities.sh
----------------------------------------------------------------------
diff --git a/stack/loadtests/runAuditVerifyCollectionEntities.sh b/stack/loadtests/runAuditVerifyCollectionEntities.sh
new file mode 100755
index 0000000..f0af5de
--- /dev/null
+++ b/stack/loadtests/runAuditVerifyCollectionEntities.sh
@@ -0,0 +1,71 @@
+#!/bin/bash
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+die() { echo "$@" 1>&2 ; exit 1; }
+
+####
+#This is a script to simplify running gatling tests. It will default several parameters, invoke the maven plugins
+#Then aggregate the results
+####
+[ "$#" -ge 4 ] || die "At least 4 arguments required, $# provided. Example is $0 URL RAMP_USERS RAMP_TIME(seconds) AUDIT_UUID_FILENAME [FAILED_UUID_FILENAME]"
+
+URL="$1"
+RAMP_USERS="$2"
+RAMP_TIME="$3"
+AUDIT_UUID_FILENAME="$4"
+FAILED_UUID_FILENAME="$5"
+
+shift 5
+
+#Compile everything
+mvn compile
+
+#Set the app id to be a date epoch for uniqueness
+#APP=$(date +%s)
+ADMIN_USER=superuser
+ADMIN_PASSWORD=test
+ORG=gatling
+APP=millionentities
+SCENARIO_TYPE=auditVerifyCollectionEntities
+
+AUTH_TYPE=token
+TOKEN_TYPE=management
+
+#Execute the test
+mvn gatling:execute \
+-Dorg=${ORG} \
+-Dapp=${APP} \
+-Dbaseurl=${URL} \
+-DadminUser=${ADMIN_USER} \
+-DadminPassword=${ADMIN_PASSWORD} \
+-DrampUsers=${RAMP_USERS} \
+-DrampTime=${RAMP_TIME} \
+-DscenarioType=${SCENARIO_TYPE} \
+-DauthType=${AUTH_TYPE} \
+-DtokenType=${TOKEN_TYPE} \
+-DauditUuidFilename=${AUDIT_UUID_FILENAME} \
+-DfailedUuidFilename=${FAILED_UUID_FILENAME} \
+-Dgatling.simulationClass=org.apache.usergrid.simulations.AuditSimulation
+
+
+
+#Now move all the reports
+#AGGREGATE_DIR="target/aggregate-$(date +%s)"
+
+#mkdir -p ${AGGREGATE_DIR}
+
+#copy to the format of target/aggregate(date)/(simnulationame)-simulation.log
+#find target -name "simulation.log" -exec cp {} ${AGGREGATE_DIR}/$(basename $(dirname {} ))-simulation.log \;
+
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/32fefb98/stack/loadtests/src/main/scala/org/apache/usergrid/datagenerators/FeederGenerator.scala
----------------------------------------------------------------------
diff --git a/stack/loadtests/src/main/scala/org/apache/usergrid/datagenerators/FeederGenerator.scala b/stack/loadtests/src/main/scala/org/apache/usergrid/datagenerators/FeederGenerator.scala
index 09030f5..61641de 100755
--- a/stack/loadtests/src/main/scala/org/apache/usergrid/datagenerators/FeederGenerator.scala
+++ b/stack/loadtests/src/main/scala/org/apache/usergrid/datagenerators/FeederGenerator.scala
@@ -19,9 +19,10 @@ package org.apache.usergrid.datagenerators
import java.util.UUID
import java.util.concurrent.atomic.AtomicInteger
import io.gatling.core.Predef._
-import org.apache.usergrid.helpers.Utils
+import org.apache.usergrid.helpers.{Setup, Utils}
import org.apache.usergrid.settings.Settings
import scala.collection.mutable.ArrayBuffer
+import scala.io.Source
object FeederGenerator {
@@ -231,26 +232,51 @@ object FeederGenerator {
}
}
- /*
- def generateCustomEntityFeeder(numEntities: Int, entityType: String, prefix: String, seed: Int = 1): Feeder[String] =
- new Feeder[String] {
- var counter = new AtomicInteger(seed)
+ def collectionNameFeeder: Feeder[String] = new Feeder[String] {
+ val list: List[String] = Setup.getCollectionsList
+ var counter = new AtomicInteger(0)
- // runs forever -- users detect when data is done using validEntity field
- override def hasNext: Boolean = true
+ override def hasNext: Boolean = true
- override def next(): Map[String, String] = {
- val i = counter.getAndIncrement()
- val entityName = prefix.concat(i.toString)
- val entity = EntityDataGenerator.generateEntity(entityType, entityName)
- val entityUrl = Settings.baseCollectionUrl + "/" + entityName
- val validEntity = if (i >= seed + numEntities) "no" else "yes"
+ override def next(): Map[String, String] = {
+ val i = counter.getAndIncrement()
+ val collectionName = if (i < list.length) list(i) else ""
+ val validEntity = if (i >= list.length) "no" else "yes"
- Map("entityName" -> entityName, "entity" -> entity, "entityUrl" -> entityUrl, "validEntity" -> validEntity)
- }
- }
+ Map("collectionName" -> collectionName, "validEntity" -> validEntity)
+ }
+ }
- */
+ def collectionCsvFeeder: Feeder[String] = new Feeder[String] {
+ val csvLines = if (Settings.feedAuditUuids) Source.fromFile(Settings.feedAuditUuidFilename).getLines().toArray else Array[String]()
+ val csvLinesLen = csvLines.length
+ var counter = new AtomicInteger(0)
+
+ override def hasNext: Boolean = true
+
+ def getNextLine: String = {
+ do {
+ val i = counter.getAndIncrement()
+ if (i >= csvLinesLen) return null
+
+ val line = csvLines(i)
+ if (line != Settings.auditUuidsHeader) return line
+
+ } while (true)
+
+ null
+ }
+
+ override def next: Map[String, String] = {
+ val line = getNextLine
+ val validEntity = if (line == null) "no" else "yes"
+ val array = if (line != null) line.split(",") else null
+ val collectionName = if (line != null) array(0) else ""
+ val uuid = if (line != null) array(1) else ""
+
+ Map("collectionName" -> collectionName, "uuid" -> uuid, "validEntity" -> validEntity)
+ }
+ }
def generateCustomEntityInfiniteFeeder(seed: Int = Settings.entitySeed, entityType: String = Settings.entityType, prefix: String = Settings.entityPrefix): Iterator[String] = {
Iterator.from(seed).map(i=>EntityDataGenerator.generateEntity(entityType, prefix.concat(i.toString)))
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/32fefb98/stack/loadtests/src/main/scala/org/apache/usergrid/enums/ConfigProperties.scala
----------------------------------------------------------------------
diff --git a/stack/loadtests/src/main/scala/org/apache/usergrid/enums/ConfigProperties.scala b/stack/loadtests/src/main/scala/org/apache/usergrid/enums/ConfigProperties.scala
index 7e6cf55..75228a7 100644
--- a/stack/loadtests/src/main/scala/org/apache/usergrid/enums/ConfigProperties.scala
+++ b/stack/loadtests/src/main/scala/org/apache/usergrid/enums/ConfigProperties.scala
@@ -51,6 +51,8 @@ object ConfigProperties {
val EntityWorkerCount = "entityWorkerCount"
val EntityWorkerNum = "entityWorkerNum"
val UuidFilename = "uuidFilename"
+ val AuditUuidFilename = "auditUuidFilename"
+ val FailedUuidFilename = "failedUuidFilename"
val SandboxCollection = "sandboxCollection"
val PurgeUsers = "purgeUsers"
@@ -59,7 +61,7 @@ object ConfigProperties {
NumDevices,Collection,RampTime,Throttle,RpsTarget,RpsRampTime,HoldDuration,PushNotifier,PushProvider,EntityPrefix,
EntityType,EntitySeed,SearchLimit,SearchQuery,EndConditionType,EndMinutes,EndRequestCount,OrgCreationUsername,
OrgCreationName,OrgCreationEmail,OrgCreationPassword,UpdateProperty,UpdateValue,EntityWorkerCount,EntityWorkerNum,
- UuidFilename,SandboxCollection,PurgeUsers)
+ UuidFilename,AuditUuidFilename,FailedUuidFilename,SandboxCollection,PurgeUsers)
def isValid(str: String): Boolean = {
Values.contains(str)
@@ -113,7 +115,9 @@ object ConfigProperties {
case UpdateValue => new Date().toString
case EntityWorkerCount => 0
case EntityWorkerNum => 0
- case UuidFilename => "dummy.csv"
+ case UuidFilename => "dummyUuid.csv"
+ case AuditUuidFilename => "dummyAuditUuid.csv"
+ case FailedUuidFilename => "/tmp/dummy.csv"
case SandboxCollection => false
case PurgeUsers => 100
}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/32fefb98/stack/loadtests/src/main/scala/org/apache/usergrid/enums/ScenarioType.scala
----------------------------------------------------------------------
diff --git a/stack/loadtests/src/main/scala/org/apache/usergrid/enums/ScenarioType.scala b/stack/loadtests/src/main/scala/org/apache/usergrid/enums/ScenarioType.scala
index 760c837..76fae7b 100644
--- a/stack/loadtests/src/main/scala/org/apache/usergrid/enums/ScenarioType.scala
+++ b/stack/loadtests/src/main/scala/org/apache/usergrid/enums/ScenarioType.scala
@@ -8,9 +8,11 @@ object ScenarioType {
val UpdateEntities = "updateEntities"
val UuidRandomInfinite = "uuidRandomInfinite"
val GetByNameSequential = "getByNameSequential"
+ val AuditGetCollectionEntities = "auditGetCollectionEntities"
+ val AuditVerifyCollectionEntities = "auditVerifyCollectionEntities"
val Values = Seq(GetAllByCursor,NameRandomInfinite,LoadEntities,DeleteEntities,UpdateEntities,UuidRandomInfinite,
- GetByNameSequential)
+ GetByNameSequential,AuditGetCollectionEntities,AuditVerifyCollectionEntities)
def isValid(str: String): Boolean = {
Values.contains(str)
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/32fefb98/stack/loadtests/src/main/scala/org/apache/usergrid/helpers/Extractors.scala
----------------------------------------------------------------------
diff --git a/stack/loadtests/src/main/scala/org/apache/usergrid/helpers/Extractors.scala b/stack/loadtests/src/main/scala/org/apache/usergrid/helpers/Extractors.scala
index e970fbd..221c0a7 100644
--- a/stack/loadtests/src/main/scala/org/apache/usergrid/helpers/Extractors.scala
+++ b/stack/loadtests/src/main/scala/org/apache/usergrid/helpers/Extractors.scala
@@ -51,6 +51,13 @@ object Extractors {
}
/**
+ * Will extract the uuids from the get collection response.
+ */
+ def extractCollectionUuids(saveAsName: String) = {
+ jsonPath("$.entities[*]").ofType[Map[String,Any]].findAll.transformOption(extract => { extract.orElse(Some(Seq.empty)) }).saveAs(saveAsName)
+ }
+
+ /**
* tries to extract the cursor from the session, if it exists, it returns true. if it's the default, returns false
* @param nameInSession The name of the variable in the session
* @return
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/32fefb98/stack/loadtests/src/main/scala/org/apache/usergrid/helpers/Setup.scala
----------------------------------------------------------------------
diff --git a/stack/loadtests/src/main/scala/org/apache/usergrid/helpers/Setup.scala b/stack/loadtests/src/main/scala/org/apache/usergrid/helpers/Setup.scala
index 727c295..37428ac 100644
--- a/stack/loadtests/src/main/scala/org/apache/usergrid/helpers/Setup.scala
+++ b/stack/loadtests/src/main/scala/org/apache/usergrid/helpers/Setup.scala
@@ -22,11 +22,13 @@ package org.apache.usergrid.helpers
import com.fasterxml.jackson.databind.ObjectMapper
import com.ning.http.client.{ListenableFuture, AsyncHttpClient,Response}
+import io.gatling.jsonpath.JsonPath
import org.apache.usergrid.datagenerators.FeederGenerator
import org.apache.usergrid.enums.TokenType
import org.apache.usergrid.settings.Settings
import scala.collection.mutable.ArrayBuffer
+import scala.util.parsing.json.JSON
object Setup {
var managementToken:String = null
@@ -109,6 +111,31 @@ object Setup {
statusCode
}
+ def getCollectionsList: List[String] = {
+ val appInfoGet = client
+ .prepareGet(s"${Settings.baseAppUrl}")
+ .setHeader("Cache-Control", "no-cache")
+ .setHeader("Accept", "application/json; charset=UTF-8")
+ .setHeader("Authorization", s"Bearer $getManagementToken")
+ .build()
+
+ val getResponse = client.executeRequest(appInfoGet).get()
+ val topLevel: Map[String, Any] = JSON.parseFull(getResponse.getResponseBody).get.asInstanceOf[Map[String,Any]]
+ val entities: List[Map[String, Any]] = topLevel("entities").asInstanceOf[List[Map[String,Any]]]
+ //println(s"entities: $entities")
+ val firstEntity: Map[String, Any] = entities.head
+ //println(s"firstEntity: $firstEntity")
+ val metadata: Map[String, Any] = firstEntity("metadata").asInstanceOf[Map[String, Any]]
+ //println(s"metadata: $metadata")
+ val collections: Map[String, Any] = metadata("collections").asInstanceOf[Map[String, Any]]
+ //println(s"collections: $collections")
+
+ val collectionsList: List[String] = (collections map { case (key, value) => key }).toList
+ //println(collectionsList)
+
+ collectionsList
+ }
+
def sandboxCollection(): Integer = {
val sandboxCollectionPost = client
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/32fefb98/stack/loadtests/src/main/scala/org/apache/usergrid/scenarios/AuditScenarios.scala
----------------------------------------------------------------------
diff --git a/stack/loadtests/src/main/scala/org/apache/usergrid/scenarios/AuditScenarios.scala b/stack/loadtests/src/main/scala/org/apache/usergrid/scenarios/AuditScenarios.scala
new file mode 100644
index 0000000..b58ee07
--- /dev/null
+++ b/stack/loadtests/src/main/scala/org/apache/usergrid/scenarios/AuditScenarios.scala
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.usergrid.scenarios
+
+import io.gatling.core.Predef._
+import io.gatling.core.feeder.RecordSeqFeederBuilder
+import io.gatling.http.Predef._
+import org.apache.usergrid.datagenerators.FeederGenerator
+import org.apache.usergrid.enums.{AuthType, EndConditionType}
+import org.apache.usergrid.helpers.Extractors._
+import org.apache.usergrid.helpers.Utils
+import org.apache.usergrid.settings.{Headers, Settings}
+
+/**
+ * Provides CRUD methods for audits
+ */
+object AuditScenarios {
+
+ //The value for the cursor
+ val SessionVarCursor: String = "cursor"
+ val SessionVarUuid: String = "entityUuid"
+ val SessionVarCollectionName: String = "collectionName"
+ val SessionVarCollectionUuids: String = "collectionUuids"
+
+ def collectionGetUrl(useCursor: Boolean): String = {
+ val url = "/${" + SessionVarCollectionName + "}?" +
+ (if (useCursor) "cursor=${" + SessionVarCursor + "}&" else "") +
+ (if (Settings.searchQuery != "") s"ql=${Settings.searchQuery}&" else "") +
+ (if (Settings.searchLimit > 0) s"limit=${Settings.searchLimit}&" else "")
+
+ // remove trailing & or ?
+ url.dropRight(1)
+ }
+
+ val getCollectionsWithoutCursor = exec(
+ http("GET collections")
+ .get(collectionGetUrl(false))
+ .headers(Headers.authToken)
+ .check(status.is(200), extractCollectionUuids(SessionVarCollectionUuids), maybeExtractCursor(SessionVarCursor)))
+ .foreach("${" + SessionVarCollectionUuids + "}", "singleUuid") {
+ exec(session => {
+ val uuidObj = session("singleUuid").as[Map[String,Any]]
+ val uuid = uuidObj("uuid").asInstanceOf[String]
+ val collectionName = session(SessionVarCollectionName).as[String]
+ Settings.addAuditUuid(uuid, collectionName)
+ session
+ })
+ }
+
+ val getCollectionsWithCursor = exec(
+ http("GET collections")
+ .get(collectionGetUrl(true))
+ .headers(Headers.authToken)
+ .check(status.is(200), extractCollectionUuids(SessionVarCollectionUuids), maybeExtractCursor(SessionVarCursor)))
+ .foreach("${" + SessionVarCollectionUuids + "}", "singleUuid") {
+ exec(session => {
+ val uuidObj = session("singleUuid").as[Map[String,Any]]
+ val uuid = uuidObj("uuid").asInstanceOf[String]
+ val collectionName = session(SessionVarCollectionName).as[String]
+ Settings.addAuditUuid(uuid, collectionName)
+ session
+ })
+ }
+
+ val getAllCollections = scenario("Get all collections")
+ .exec(injectTokenIntoSession())
+ .exec(injectAuthType())
+ .asLongAs(session => session("validEntity").asOption[String].map(validEntity => validEntity != "no").getOrElse[Boolean](true)) {
+ feed(FeederGenerator.collectionNameFeeder)
+ .exec{
+ session => if (session("validEntity").as[String] == "yes") { println("Getting collection " + session("collectionName").as[String]) }
+ session
+ }
+ .doIf(session => session("validEntity").as[String] == "yes") {
+ exec(getCollectionsWithoutCursor)
+ .asLongAs(stringParamExists(SessionVarCursor)) {
+ exec(getCollectionsWithCursor)
+ }
+ }
+ }
+
+ val getCollectionEntity = exec(
+ http("GET collection entity")
+ .get("/${collectionName}?ql=uuid=${uuid}")
+ .headers(Headers.authToken)
+ .check(status.is(200), jsonPath("$.count").saveAs("count")))
+ .exec(session => {
+ val count = session("count").as[String].toInt
+ val uuid = session("uuid").as[String]
+ val collectionName = session(SessionVarCollectionName).as[String]
+
+ // save items not found
+ if (count < 1) {
+ Settings.addAuditUuid(uuid, collectionName)
+ Settings.incAuditNotFound()
+ println(s"NOT FOUND: $collectionName.$uuid")
+ } else if (count > 1) {
+ Settings.addAuditUuid(uuid, collectionName)
+ Settings.incAuditBadResponse()
+ println(s"INVALID RESPONSE (count=$count): $collectionName.$uuid")
+ } else {
+ // println(s"FOUND: $collectionName.$uuid")
+ Settings.incAuditSuccess()
+ }
+
+ session
+ })
+
+ val verifyCollections = scenario("Verify collections")
+ .exec(injectTokenIntoSession())
+ .exec(injectAuthType())
+ .asLongAs(session => session("validEntity").asOption[String].map(validEntity => validEntity != "no").getOrElse[Boolean](true)) {
+ feed(FeederGenerator.collectionCsvFeeder)
+ .doIf(session => session("validEntity").as[String] == "yes") {
+ exec(getCollectionEntity)
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/32fefb98/stack/loadtests/src/main/scala/org/apache/usergrid/scenarios/EntityCollectionScenarios.scala
----------------------------------------------------------------------
diff --git a/stack/loadtests/src/main/scala/org/apache/usergrid/scenarios/EntityCollectionScenarios.scala b/stack/loadtests/src/main/scala/org/apache/usergrid/scenarios/EntityCollectionScenarios.scala
index 5f679ec..a760931 100644
--- a/stack/loadtests/src/main/scala/org/apache/usergrid/scenarios/EntityCollectionScenarios.scala
+++ b/stack/loadtests/src/main/scala/org/apache/usergrid/scenarios/EntityCollectionScenarios.scala
@@ -48,16 +48,17 @@ object EntityCollectionScenarios {
}
def entityGetByNameUrl(entityName: String): String = {
- val url = s"/${Settings.collection}/$entityName"
- url
+ s"/${Settings.collection}/$entityName"
}
def randomEntityNameUrl(prefix: String = Settings.entityPrefix, numEntities: Int = Settings.numEntities, seed: Int = Settings.entitySeed): String = {
+
Utils.randomEntityNameUrl(prefix, numEntities, seed, Settings.baseCollectionUrl)
}
def uuidFeeder(): RecordSeqFeederBuilder[String] = {
+
csv(Settings.feedUuidFilename).random
}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/32fefb98/stack/loadtests/src/main/scala/org/apache/usergrid/settings/Settings.scala
----------------------------------------------------------------------
diff --git a/stack/loadtests/src/main/scala/org/apache/usergrid/settings/Settings.scala b/stack/loadtests/src/main/scala/org/apache/usergrid/settings/Settings.scala
index e4be5c8..3c1c2e2 100755
--- a/stack/loadtests/src/main/scala/org/apache/usergrid/settings/Settings.scala
+++ b/stack/loadtests/src/main/scala/org/apache/usergrid/settings/Settings.scala
@@ -17,6 +17,7 @@
package org.apache.usergrid.settings
import java.io.{PrintWriter, FileOutputStream}
+import java.util.concurrent.atomic.AtomicInteger
import javax.xml.bind.DatatypeConverter
import io.gatling.http.Predef._
import io.gatling.http.config.HttpProtocolBuilder
@@ -149,12 +150,32 @@ object Settings {
val numEntities:Int = entitiesPerWorkerFloor + extraEntity
// UUID log file, have to go through this because creating a csv feeder with an invalid csv file fails at maven compile time
- private val dummyCsv = ConfigProperties.getDefault(ConfigProperties.UuidFilename).toString
+ private val dummyTestCsv = ConfigProperties.getDefault(ConfigProperties.UuidFilename).toString
+ private val dummyAuditCsv = ConfigProperties.getDefault(ConfigProperties.AuditUuidFilename).toString
+ private val dummyAuditFailedCsv = ConfigProperties.getDefault(ConfigProperties.FailedUuidFilename).toString
+
private val uuidFilename = initStrSetting(ConfigProperties.UuidFilename)
- val captureUuids = uuidFilename != dummyCsv && (scenarioType == ScenarioType.LoadEntities || scenarioType == ScenarioType.GetByNameSequential)
- val feedUuids = uuidFilename != dummyCsv && scenarioType == ScenarioType.UuidRandomInfinite
- val captureUuidFilename = if (captureUuids) uuidFilename else dummyCsv
- val feedUuidFilename = if (feedUuids) uuidFilename else dummyCsv
+ private val auditUuidFilename = initStrSetting(ConfigProperties.AuditUuidFilename)
+ private val failedUuidFilename = initStrSetting(ConfigProperties.FailedUuidFilename)
+
+ // feeds require valid files, even if test won't be run
+ val feedUuids = uuidFilename != dummyTestCsv && scenarioType == ScenarioType.UuidRandomInfinite
+ val feedUuidFilename = uuidFilename
+
+ val feedAuditUuids = uuidFilename != dummyAuditCsv && scenarioType == ScenarioType.AuditVerifyCollectionEntities
+ val feedAuditUuidFilename = auditUuidFilename
+
+ // also uses uuidFilename
+ val captureUuids = uuidFilename != dummyTestCsv && (scenarioType == ScenarioType.LoadEntities || scenarioType == ScenarioType.GetByNameSequential)
+ val captureUuidFilename = uuidFilename
+
+ val captureAuditUuids = (auditUuidFilename != dummyAuditCsv && scenarioType == ScenarioType.AuditGetCollectionEntities) ||
+ (failedUuidFilename != dummyAuditFailedCsv && scenarioType == ScenarioType.AuditVerifyCollectionEntities)
+ println(s"auditUuidFilename=$auditUuidFilename")
+ println(s"captureAuditUuids=$captureAuditUuids")
+ val captureAuditUuidFilename = if (scenarioType == ScenarioType.AuditVerifyCollectionEntities) failedUuidFilename else auditUuidFilename
+ println(s"captureAuditUuidFilename=$captureAuditUuidFilename")
+
val purgeUsers:Int = initIntSetting(ConfigProperties.PurgeUsers)
private var uuidMap: Map[Int, String] = Map()
@@ -179,6 +200,32 @@ object Settings {
}
}
+
+ val auditUuidsHeader = "collection,uuid"
+
+ // key: uuid, value: collection
+ private var auditUuidMap: Map[String,String] = Map()
+ def addAuditUuid(uuid: String, collection: String): Unit = {
+ if (captureAuditUuids) auditUuidMap += (uuid -> collection)
+ }
+
+ def writeAuditUuidsToFile(uuidDesc: String): Unit = {
+ if (captureAuditUuids) {
+ println(s"Sorting and writing ${auditUuidMap.size} ${uuidDesc} UUIDs in CSV file ${captureAuditUuidFilename}")
+ val writer = {
+ val fos = new FileOutputStream(captureAuditUuidFilename)
+ new PrintWriter(fos, false)
+ }
+ writer.println(auditUuidsHeader)
+ val uuidList: List[(String, String)] = auditUuidMap.toList.sortBy(l => (l._2, l._1))
+ uuidList.foreach { l =>
+ writer.println(s"${l._2},${l._1}")
+ }
+ writer.flush()
+ writer.close()
+ }
+ }
+
def getUserFeeder:Array[Map[String, String]]= {
FeederGenerator.generateUserWithGeolocationFeeder(totalUsers, userLocationRadius, centerLatitude, centerLongitude)
}
@@ -201,9 +248,48 @@ object Settings {
(System.currentTimeMillis() - testStartTime) < (endMinutes.toLong*60L*1000L)
}
+ private val countAuditSuccess = new AtomicInteger(0)
+ private val countAuditNotFound = new AtomicInteger(0)
+ private val countAuditBadResponse = new AtomicInteger(0)
+
+ def incAuditSuccess(): Unit = {
+ countAuditSuccess.incrementAndGet()
+ }
+
+ def incAuditNotFound(): Unit = {
+ countAuditNotFound.incrementAndGet()
+ }
+
+ def incAuditBadResponse(): Unit = {
+ countAuditBadResponse.incrementAndGet()
+ }
+
+ def printAuditResults(): Unit = {
+ if (scenarioType == ScenarioType.AuditVerifyCollectionEntities) {
+ val countSuccess = countAuditSuccess.get
+ val countNotFound = countAuditNotFound.get
+ val countBadResponse = countAuditBadResponse.get
+ val countTotal = countSuccess + countNotFound + countBadResponse
+
+ println()
+ println("-----------------------------------------------------------------------------")
+ println("AUDIT RESULTS")
+ println("-----------------------------------------------------------------------------")
+ println()
+ println(s"Successful: ${countSuccess}")
+ println(s"Not Found: ${countNotFound}")
+ println(s"Bad Response: ${countBadResponse}")
+ println(s"Total: ${countTotal}")
+ println()
+ println("-----------------------------------------------------------------------------")
+ println()
+ }
+ }
+
def printSettingsSummary(): Unit = {
val authTypeStr = authType + (if (authType == AuthType.Token) s"($tokenType)" else "")
val endConditionStr = if (endConditionType == EndConditionType.MinutesElapsed) s"$endMinutes minutes elapsed" else s"$endRequestCount requests"
+ println()
println("-----------------------------------------------------------------------------")
println("SIMULATION SETTINGS")
println("-----------------------------------------------------------------------------")
@@ -222,6 +308,7 @@ object Settings {
println(s"End Condition:$endConditionStr")
println()
println("-----------------------------------------------------------------------------")
+ println()
}
printSettingsSummary()
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/32fefb98/stack/loadtests/src/main/scala/org/apache/usergrid/simulations/AuditSimulation.scala
----------------------------------------------------------------------
diff --git a/stack/loadtests/src/main/scala/org/apache/usergrid/simulations/AuditSimulation.scala b/stack/loadtests/src/main/scala/org/apache/usergrid/simulations/AuditSimulation.scala
new file mode 100755
index 0000000..48b5f60
--- /dev/null
+++ b/stack/loadtests/src/main/scala/org/apache/usergrid/simulations/AuditSimulation.scala
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.usergrid.simulations
+
+import io.gatling.core.Predef._
+import io.gatling.core.structure.ScenarioBuilder
+import org.apache.usergrid.enums.ScenarioType
+import org.apache.usergrid.helpers.Setup
+import org.apache.usergrid.scenarios.{AuditScenarios, EntityCollectionScenarios}
+import org.apache.usergrid.settings.Settings
+
+/**
+ * Audit simulations.
+ *
+ */
+class AuditSimulation extends Simulation {
+
+ def getScenario(scenarioType: String): ScenarioBuilder = {
+ scenarioType match {
+ case ScenarioType.AuditGetCollectionEntities => AuditScenarios.getAllCollections
+ case ScenarioType.AuditVerifyCollectionEntities => AuditScenarios.verifyCollections
+ }
+ }
+
+ before{
+ }
+
+ Settings.setTestStartTime()
+ if (ScenarioType.isValid(Settings.scenarioType)) {
+ val scenario: ScenarioBuilder = getScenario(Settings.scenarioType)
+ setUp(
+ scenario
+ .inject(
+ rampUsers(Settings.rampUsers) over Settings.rampTime
+ ).protocols(Settings.httpConf.acceptHeader("application/json"))
+ )
+ } else {
+ println(s"Audit scenario type ${Settings.scenarioType} not found.")
+ }
+
+ after {
+ if (Settings.captureAuditUuids) {
+ val uuidDesc = Settings.scenarioType match {
+ case ScenarioType.AuditGetCollectionEntities => "found"
+ case ScenarioType.AuditVerifyCollectionEntities => "failed"
+ }
+ Settings.writeAuditUuidsToFile(uuidDesc)
+ }
+ Settings.printSettingsSummary()
+ Settings.printAuditResults()
+ }
+
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/32fefb98/stack/loadtests/src/test/resources/dummy.csv
----------------------------------------------------------------------
diff --git a/stack/loadtests/src/test/resources/dummy.csv b/stack/loadtests/src/test/resources/dummy.csv
deleted file mode 100644
index 187f36b..0000000
--- a/stack/loadtests/src/test/resources/dummy.csv
+++ /dev/null
@@ -1 +0,0 @@
-name,uuid
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/32fefb98/stack/loadtests/src/test/resources/dummyAuditUuid.csv
----------------------------------------------------------------------
diff --git a/stack/loadtests/src/test/resources/dummyAuditUuid.csv b/stack/loadtests/src/test/resources/dummyAuditUuid.csv
new file mode 100644
index 0000000..fc9f2fb
--- /dev/null
+++ b/stack/loadtests/src/test/resources/dummyAuditUuid.csv
@@ -0,0 +1 @@
+collection,uuid
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/32fefb98/stack/loadtests/src/test/resources/dummyUuid.csv
----------------------------------------------------------------------
diff --git a/stack/loadtests/src/test/resources/dummyUuid.csv b/stack/loadtests/src/test/resources/dummyUuid.csv
new file mode 100644
index 0000000..187f36b
--- /dev/null
+++ b/stack/loadtests/src/test/resources/dummyUuid.csv
@@ -0,0 +1 @@
+name,uuid