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 2014/10/23 02:05:27 UTC

[1/2] Initial commit of move into it's own project so the tests can be developed and debugged within an IDE.

Repository: incubator-usergrid
Updated Branches:
  refs/heads/gatlingdev [created] bfc4d0fce


http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/loadtests/simulations/test/scala/org/apache/usergrid/simulations/PushTargetUserSimulation.scala
----------------------------------------------------------------------
diff --git a/stack/loadtests/simulations/test/scala/org/apache/usergrid/simulations/PushTargetUserSimulation.scala b/stack/loadtests/simulations/test/scala/org/apache/usergrid/simulations/PushTargetUserSimulation.scala
deleted file mode 100644
index fd565ba..0000000
--- a/stack/loadtests/simulations/test/scala/org/apache/usergrid/simulations/PushTargetUserSimulation.scala
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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
-
-import io.gatling.core.Predef._
-import io.gatling.http.Predef._
-import scala.concurrent.duration._
-
-class PushNotificationTargetUserSimulation extends Simulation {
-
-  val numUsers:Int = Settings.numUsers
-  val numEntities:Int = Settings.numEntities
-  val rampTime:Int = Settings.rampTime
-  val throttle:Int = Settings.throttle
-  val duration:Int = Settings.duration
-  val httpConf = Settings.httpConf
-    .acceptHeader("application/json")
-
-  val notifier = Settings.pushNotifier
-  val createDevice = DeviceScenarios.postDeviceWithNotifier400ok
-  val sendNotification = NotificationScenarios.sendNotification
-  val createUser = UserScenarios.postUser400ok
-  val deviceNameFeeder = FeederGenerator.generateEntityNameFeeder("device", numEntities).circular
-  val userFeeder = FeederGenerator.generateUserWithGeolocationFeeder(numEntities, Settings.userLocationRadius, Settings.centerLatitude, Settings.centerLongitude)
-
-  val scnToRun = scenario("Create Push Notification")
-    .feed(userFeeder)
-    .exec(createUser)
-    .pause(1000)
-    .exec(http("Check user and user devices")
-      .get("/users/${username}/devices")
-      .check(status.is(200))
-    )
-    .feed(deviceNameFeeder)
-    .exec(createDevice)
-    .pause(1000)
-    .exec(http("Check device connections")
-      .get("/devices/${entityName}/users")
-      .check(status.is(200))
-    )
-    .exec(http("Connect user with device")
-      .post("/users/${username}/devices/${entityName}")
-      .check(status.is(200))
-    )
-    .exec(http("Send Notification to All Devices")
-      .post("/users/${username}/notifications")
-      .body(StringBody("{\"payloads\":{\"" + notifier + "\":\"testmessage\"}}"))
-      .check(status.is(200))
-    )
-
-
-  setUp(scnToRun.inject(constantUsersPerSec(numUsers) during (duration)).throttle(reachRps(throttle) in (rampTime.seconds)).protocols(httpConf))
-
-}


[2/2] git commit: Initial commit of move into it's own project so the tests can be developed and debugged within an IDE.

Posted by to...@apache.org.
Initial commit of move into it's own project so the tests can be developed and debugged within an IDE.


Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/bfc4d0fc
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/bfc4d0fc
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/bfc4d0fc

Branch: refs/heads/gatlingdev
Commit: bfc4d0fce4dddb02e8d3bfdbea43ea67592c3f38
Parents: d183fbe
Author: Todd Nine <tn...@apigee.com>
Authored: Wed Oct 22 18:05:24 2014 -0600
Committer: Todd Nine <tn...@apigee.com>
Committed: Wed Oct 22 18:05:24 2014 -0600

----------------------------------------------------------------------
 stack/gatling/pom.xml                           | 135 ++++++++++++++++
 .../data-generators/EntityDataGenerator.scala   |  57 +++++++
 .../data-generators/FeederGenerator.scala       | 101 ++++++++++++
 .../scenarios/ApplicationScenarios.scala        |  45 ++++++
 .../scenarios/ConnectionScenarios.scala         |  30 ++++
 .../usergrid/scenarios/DeviceScenarios.scala    |  65 ++++++++
 .../usergrid/scenarios/GeoScenarios.scala       |  43 ++++++
 .../scenarios/NotificationScenarios.scala       |  71 +++++++++
 .../usergrid/scenarios/NotifierScenarios.scala  |  65 ++++++++
 .../scenarios/OrganizationScenarios.scala       |  42 +++++
 .../usergrid/scenarios/TokenScenarios.scala     |  59 +++++++
 .../usergrid/scenarios/UserScenarios.scala      |  50 ++++++
 .../org/apache/usergrid/settings/Headers.scala  |  43 ++++++
 .../org/apache/usergrid/settings/Settings.scala |  54 +++++++
 .../org/apache/usergrid/settings/Utils.scala    |  87 +++++++++++
 .../simulations/GetEntitySimulation.scala       |  42 +++++
 .../simulations/PostDevicesSimulation.scala     |  43 ++++++
 .../simulations/PostUsersSimulation.scala       |  48 ++++++
 ...PushNotificationTargetDeviceSimulation.scala |  54 +++++++
 .../PushNotificationTargetUserSimulation.scala  |  68 ++++++++
 stack/gatling/src/test/resources/gatling.conf   | 154 +++++++++++++++++++
 stack/gatling/src/test/resources/logback.xml    |  20 +++
 stack/gatling/src/test/resources/recorder.conf  |  37 +++++
 stack/gatling/src/test/scala/Engine.scala       |  16 ++
 .../gatling/src/test/scala/IDEPathHelper.scala  |  21 +++
 stack/gatling/src/test/scala/Recorder.scala     |  12 ++
 .../usergrid/scenarios/DeviceScenarios.scala    |   4 +-
 ...PushNotificationTargetDeviceSimulation.scala |  53 +++++++
 .../PushNotificationTargetUserSimulation.scala  |  67 ++++++++
 .../PushTargetDeviceSimulation.scala            |  53 -------
 .../simulations/PushTargetUserSimulation.scala  |  68 --------
 31 files changed, 1584 insertions(+), 123 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/gatling/pom.xml
----------------------------------------------------------------------
diff --git a/stack/gatling/pom.xml b/stack/gatling/pom.xml
new file mode 100644
index 0000000..3d748cc
--- /dev/null
+++ b/stack/gatling/pom.xml
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>org.apache.usergrid</groupId>
+	<artifactId>gatling</artifactId>
+	<version>1.0-SNAPSHOT</version>
+
+	<repositories>
+		<repository>
+			<id>sonatype</id>
+			<name>Sonatype OSS</name>
+			<url>https://oss.sonatype.org/content/groups/public</url>
+			<releases>
+				<updatePolicy>never</updatePolicy>
+			</releases>
+			<snapshots>
+				<enabled>true</enabled>
+			</snapshots>
+		</repository>
+	</repositories>
+	<pluginRepositories>
+		<pluginRepository>
+			<id>sonatype</id>
+			<name>Sonatype OSS</name>
+			<url>https://oss.sonatype.org/content/groups/public</url>
+			<snapshots>
+				<enabled>true</enabled>
+			</snapshots>
+		</pluginRepository>
+	</pluginRepositories>
+
+	<properties>
+		<maven.compiler.source>1.7</maven.compiler.source>
+		<maven.compiler.target>1.6</maven.compiler.target>
+		<scala.version>2.10.4</scala.version>
+		<encoding>UTF-8</encoding>
+
+		<gatling.version>2.0.0</gatling.version>
+		<gatling-highcharts.version>2.0.0</gatling-highcharts.version>
+
+		<scala-maven-plugin.version>3.1.6</scala-maven-plugin.version>
+	</properties>
+
+	<dependencyManagement>
+		<dependencies>
+			<dependency>
+				<groupId>io.gatling</groupId>
+				<artifactId>gatling-app</artifactId>
+				<version>${gatling.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>io.gatling</groupId>
+				<artifactId>gatling-recorder</artifactId>
+				<version>${gatling.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>io.gatling.highcharts</groupId>
+				<artifactId>gatling-charts-highcharts</artifactId>
+				<version>${gatling-highcharts.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>org.scala-lang</groupId>
+				<artifactId>scala-library</artifactId>
+				<version>${scala.version}</version>
+			</dependency>
+		</dependencies>
+	</dependencyManagement>
+
+	<dependencies>
+		<dependency>
+			<groupId>io.gatling.highcharts</groupId>
+			<artifactId>gatling-charts-highcharts</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>io.gatling</groupId>
+			<artifactId>gatling-app</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>io.gatling</groupId>
+			<artifactId>gatling-recorder</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.scala-lang</groupId>
+			<artifactId>scala-library</artifactId>
+		</dependency>
+	</dependencies>
+
+	<build>
+		<sourceDirectory>src/main/scala</sourceDirectory>
+		<testSourceDirectory>src/test/scala</testSourceDirectory>
+		<pluginManagement>
+			<plugins>
+				<plugin>
+					<groupId>net.alchim31.maven</groupId>
+					<artifactId>scala-maven-plugin</artifactId>
+					<version>${scala-maven-plugin.version}</version>
+				</plugin>
+				<plugin>
+					<groupId>io.gatling</groupId>
+					<artifactId>gatling-maven-plugin</artifactId>
+					<version>${gatling.version}</version>
+				</plugin>
+			</plugins>
+		</pluginManagement>
+		<plugins>
+			<plugin>
+				<groupId>net.alchim31.maven</groupId>
+				<artifactId>scala-maven-plugin</artifactId>
+				<executions>
+					<execution>
+						<goals>
+							<goal>compile</goal>
+							<goal>testCompile</goal>
+						</goals>
+						<configuration>
+							<args>
+								<arg>-target:jvm-1.6</arg>
+								<arg>-deprecation</arg>
+								<arg>-feature</arg>
+								<arg>-unchecked</arg>
+								<arg>-language:implicitConversions</arg>
+								<arg>-language:postfixOps</arg>
+							</args>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+			<plugin>
+				<groupId>io.gatling</groupId>
+				<artifactId>gatling-maven-plugin</artifactId>
+			</plugin>
+		</plugins>
+	</build>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/gatling/src/main/scala/org/apache/usergrid/data-generators/EntityDataGenerator.scala
----------------------------------------------------------------------
diff --git a/stack/gatling/src/main/scala/org/apache/usergrid/data-generators/EntityDataGenerator.scala b/stack/gatling/src/main/scala/org/apache/usergrid/data-generators/EntityDataGenerator.scala
new file mode 100755
index 0000000..b1a7a90
--- /dev/null
+++ b/stack/gatling/src/main/scala/org/apache/usergrid/data-generators/EntityDataGenerator.scala
@@ -0,0 +1,57 @@
+/*
+ * 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
+
+import scala.collection.mutable.ArrayBuffer
+
+object EntityDataGenerator {
+
+  def generateBlockUserLists(numUsers: Int): Map[String, String] = {
+
+    var blocks: ArrayBuffer[String] = new ArrayBuffer[String]
+    var blockedBy: ArrayBuffer[String] = new ArrayBuffer[String]
+
+    for (numBlock <- 1 to Utils.generateRandomInt(1, 7)) {
+      blocks += "user".concat(Utils.generateRandomInt(1, numUsers).toString)
+    }
+
+    for (numBlockedBy <- 1 to Utils.generateRandomInt(1, 7)) {
+      blockedBy += "user".concat(Utils.generateRandomInt(1, numUsers).toString)
+    }
+
+    return Map("blocks" -> blocks.toArray.mkString(","), "blockedBy" -> blockedBy.toArray.mkString(","))
+
+  }
+
+  def generateUser(userId: Int): Map[String,String] = {
+
+    return Map("username" -> "user".concat(userId.toString),
+      "profileId" -> Utils.generateRandomInt(10000, 1000000).toString,
+      "displayName" -> Utils.generateRandomInt(10000, 1000000).toString,
+      "showAge" -> Utils.generateRandomInt(0, 1).toString,
+      "ethnicity" -> Utils.generateRandomInt(1, 15).toString,
+      "relationshipStatus" -> Utils.generateRandomInt(1, 4).toString,
+      "headline" -> "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
+      "aboutMe" -> "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
+      "age" -> Utils.generateRandomInt(18, 65).toString,
+      "height" -> Utils.generateRandomInt(48, 84).toString,
+      "weight" -> Utils.generateRandomInt(120, 350).toString,
+      "seen" -> Utils.generateRandomInt(50, 100000).toString
+    )
+  }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/gatling/src/main/scala/org/apache/usergrid/data-generators/FeederGenerator.scala
----------------------------------------------------------------------
diff --git a/stack/gatling/src/main/scala/org/apache/usergrid/data-generators/FeederGenerator.scala b/stack/gatling/src/main/scala/org/apache/usergrid/data-generators/FeederGenerator.scala
new file mode 100755
index 0000000..ffe324c
--- /dev/null
+++ b/stack/gatling/src/main/scala/org/apache/usergrid/data-generators/FeederGenerator.scala
@@ -0,0 +1,101 @@
+/*
+ * 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
+
+import io.gatling.core.Predef._
+import scala.collection.mutable.ArrayBuffer
+
+object FeederGenerator {
+
+  def generateUserWithGeolocationFeeder(numUsers: Int, radius: Double, centerLatitude: Double, centerLongitude: Double): Array[Map[String, String]] = {
+    var userArray: ArrayBuffer[Map[String, String]] = new ArrayBuffer[Map[String, String]]
+    for (userCount <- 1 to numUsers) {
+      var user: Map[String, String] = EntityDataGenerator.generateUser(userCount)
+      var geolocation: Map[String, String] = Utils.generateRandomGeolocation(radius, centerLatitude, centerLongitude)
+      var blockLists: Map[String, String] = EntityDataGenerator.generateBlockUserLists(numUsers)
+
+      user = user ++ geolocation ++ blockLists
+
+      userArray += user
+    }
+    return userArray.toArray
+  }
+
+  def generateGeolocationFeeder(radius: Double, centerLatitude: Double, centerLongitude: Double): Feeder[String] = {
+
+    val geolocationFeeder = new Feeder[String] {
+
+      // always return true as this feeder can be polled infinitively
+      override def hasNext = true
+
+      override def next: Map[String, String] = {
+        var geolocation: Map[String, String] = Utils.generateRandomGeolocation(radius, centerLatitude, centerLongitude)
+        Map("latitude" -> geolocation("latitude"), "longitude" -> geolocation("longitude"))
+      }
+    }
+
+    return geolocationFeeder
+
+  }
+
+  def generateGeolocationWithQueryFeeder(radius: Double, centerLatitude: Double, centerLongitude: Double): Feeder[String] = {
+
+    val geolocationFeeder = new Feeder[String] {
+
+      // always return true as this feeder can be polled infinitively
+      override def hasNext = true
+
+      override def next: Map[String, String] = {
+        var geolocation: Map[String, String] = Utils.generateRandomGeolocation(radius, centerLatitude, centerLongitude)
+        var queryParams = Utils.generateRandomQueryString
+        Map("latitude" -> geolocation("latitude"), "longitude" -> geolocation("longitude"), "queryParams" -> queryParams)
+      }
+    }
+
+    return geolocationFeeder
+
+  }
+
+  def generateUserConnectionFeeder(numUsers: Int): Feeder[String] = {
+
+    val userIdFeeder = new Feeder[String] {
+
+      // always return true as this feeder can be polled infinitively
+      override def hasNext = true
+
+      override def next: Map[String, String] = {
+        Map("user1" -> "user".concat(Utils.generateRandomInt(1, numUsers).toString), "user2" -> "user".concat(Utils.generateRandomInt(1, numUsers).toString))
+      }
+    }
+
+    return userIdFeeder
+
+  }
+
+  def generateEntityNameFeeder(prefix: String, numEntities: Int): Array[Map[String, String]] = {
+
+    var nameArray: ArrayBuffer[Map[String, String]] = new ArrayBuffer[Map[String, String]]
+
+    for (entityCount <- 1 to numEntities) {
+      nameArray += Map("entityName" -> prefix.concat(entityCount.toString))
+    }
+
+    return nameArray.toArray
+
+  }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/ApplicationScenarios.scala
----------------------------------------------------------------------
diff --git a/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/ApplicationScenarios.scala b/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/ApplicationScenarios.scala
new file mode 100755
index 0000000..f5f7901
--- /dev/null
+++ b/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/ApplicationScenarios.scala
@@ -0,0 +1,45 @@
+/*
+ * 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
+
+import io.gatling.core.Predef._
+import io.gatling.http.Predef._
+
+/**
+ * Performs organization registration
+ *
+ *
+ * Expects:
+ *
+ * authToken The auth token to use when creating the application
+ * orgName The organization name
+ *
+ * Produces:
+ *
+ * appName The name of the created application
+ */
+object ApplicationScenarios {
+
+  val createApplication = exec(http("Create Application")
+    .post("/management/organizations/${org}/applications")
+    .headers(Headers.jsonAuthorized)
+    .body(StringBody("{\"name\":\"" + Settings.app + "\"}"))
+    .check(status.is(200))
+
+    )
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/ConnectionScenarios.scala
----------------------------------------------------------------------
diff --git a/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/ConnectionScenarios.scala b/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/ConnectionScenarios.scala
new file mode 100755
index 0000000..ba2449f
--- /dev/null
+++ b/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/ConnectionScenarios.scala
@@ -0,0 +1,30 @@
+/*
+ * 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
+
+import io.gatling.core.Predef._
+import io.gatling.http.Predef._
+
+object ConnectionScenarios {
+
+  val postConnection = exec(
+    http("POST connection")
+      .post("/users/${user1}/likes/users/${user2}")
+      .check(status.is(200))
+  )
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/DeviceScenarios.scala
----------------------------------------------------------------------
diff --git a/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/DeviceScenarios.scala b/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/DeviceScenarios.scala
new file mode 100755
index 0000000..e86bd42
--- /dev/null
+++ b/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/DeviceScenarios.scala
@@ -0,0 +1,65 @@
+/*
+ * 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
+
+import io.gatling.core.Predef._
+import io.gatling.http.Predef._
+
+/**
+ *
+ * Creates a new device
+ *
+ * Expects:
+ *
+ * authToken The auth token to use when creating the application
+ * orgName The name of the org
+ * appName The name of the app
+ * notifierName The name of the created notifier
+ *
+ * Produces:
+ *
+ * deviceName the name of the device created
+ *
+ */
+object DeviceScenarios {
+
+  /**
+   * Create a device
+   */
+  val postDeviceWithNotifier = exec(http("Create device with notifier")
+    .post("/devices")
+    .body(StringBody("{\"name\":\"${entityName}\"," +
+      "\"deviceModel\":\"Fake Device\"," +
+      " \"deviceOSVerion\":\"Negative Version\", " +
+      "\"${notifier}.notifier.id\":\"${entityName}\"}"))
+    .check(status.is(200), jsonPath("$.entities[0].uuid").saveAs("deviceId")))
+
+  val postDeviceWithNotifier400ok = exec(http("Create device with notifier")
+    .post("/devices")
+    .body(StringBody("{\"name\":\"${entityName}\"," +
+    "\"deviceModel\":\"Fake Device\"," +
+    " \"deviceOSVerion\":\"Negative Version\", " +
+    "\"${notifier}.notifier.id\":\"${entityName}\"}"))
+    .check(status.in(200 to 400), jsonPath("$.entities[0].uuid").saveAs("deviceId")))
+
+  /**
+   * TODO: Add a device to a user, which would expect a user in the session
+   */
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/GeoScenarios.scala
----------------------------------------------------------------------
diff --git a/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/GeoScenarios.scala b/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/GeoScenarios.scala
new file mode 100755
index 0000000..94bf0af
--- /dev/null
+++ b/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/GeoScenarios.scala
@@ -0,0 +1,43 @@
+/*
+ * 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
+
+import io.gatling.core.Predef._
+import io.gatling.http.Predef._
+
+object GeoScenarios {
+
+  val getGeolocation = exec(
+      http("GET geolocated user")
+        .get("/users?ql=location%20within%20" + Settings.geosearchRadius + "%20of%20${latitude},${longitude}")
+        .check(status.is(200))
+    )
+
+  val getGeolocationWithQuery = exec(
+      http("GET geolocated user with query")
+        .get("/users?ql=${queryParams}%20AND%20location%20within%20" + Settings.geosearchRadius + "%20of%20${latitude},${longitude}")
+        .check(status.is(200))
+    )
+
+  val updateGeolocation = exec(
+    http("PUT user location")
+      .put("/users/user" + Utils.generateRandomInt(1, Settings.numUsers))
+      .body(StringBody("{\"location\":{\"latitude\":\"${latitude}\",\"longitude\":\"${longitude}\"}}"))
+      .check(status.is(200))
+  )
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/NotificationScenarios.scala
----------------------------------------------------------------------
diff --git a/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/NotificationScenarios.scala b/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/NotificationScenarios.scala
new file mode 100755
index 0000000..91d6754
--- /dev/null
+++ b/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/NotificationScenarios.scala
@@ -0,0 +1,71 @@
+/*
+ * 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
+
+import java.io.File
+import java.nio.file.{Paths, Files}
+
+import io.gatling.core.Predef._
+import io.gatling.http.Predef._
+import scala.concurrent.duration._
+
+import scala.io.Source
+
+/**
+ *
+ * Creates a new device
+ *
+ * Expects:
+ *
+ * authToken The auth token to use when creating the application
+ * orgName The name of the org
+ * appName The name of the app
+ * notifierName The name of the created notifier
+ * deviceName the name of the device created to send the notification to
+ *
+ * Produces:
+ *
+ * N/A
+ *
+ *
+ */
+object NotificationScenarios {
+
+
+  /**
+   * send the notification now
+   */
+  val sendNotification = exec(http("Send Single Notification")
+      .post("/devices/${entityName}/notifications")
+      .body(StringBody("{\"payloads\":{\"${notifier}\":\"testmessage\"}}"))
+      .check(status.is(200))
+    )
+
+  val sendNotificationToUser= exec(http("Send Notification to All Devices")
+    .post("/users/${user}/notifications")
+    .body(StringBody("{\"payloads\":{\"${notifier}\":\"testmessage\"}}"))
+    .check(status.is(200))
+  )
+
+  /**
+   * TODO: Add posting to users, which would expect a user in the session
+   */
+
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/NotifierScenarios.scala
----------------------------------------------------------------------
diff --git a/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/NotifierScenarios.scala b/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/NotifierScenarios.scala
new file mode 100755
index 0000000..0c2fc0c
--- /dev/null
+++ b/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/NotifierScenarios.scala
@@ -0,0 +1,65 @@
+/*
+ * 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
+
+import io.gatling.core.Predef._
+import io.gatling.http.Predef._
+import scala.concurrent.duration._
+
+/**
+ *
+ * Creates a new no-op notifier
+ *
+ *
+ * Expects:
+ *
+ * authToken The auth token to use when creating the application
+ * orgName The name of the org
+ * appName The name of the app
+ *
+ * Produces:
+ *
+ * notifierName The name of the created notifier
+ *
+ */
+object NotifierScenarios {
+  
+  val notifier = Settings.pushNotifier
+  val provider = Settings.pushProvider
+
+  /**
+   * Create a notifier
+   */
+  val createNotifier = exec(
+      session => {
+        session.set("notifier", notifier)
+        session.set("provider", provider)
+      }
+    )
+
+    .exec(http("Create Notifier")
+    .post("/notifiers")
+    .body(StringBody("{\"name\":\"${notifier}\",\"provider\":\"${provider}\"}"))
+    //remnants of trying to upload an apple certificate
+//    .param("name", "${notifierName}")
+//    .param("provider", "apple")
+//    .param("environment", "mock")
+//    .fileBody("p12Certificate", Map).fileBody(pkcs12Cert)
+    .check(status.is(200)))
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/OrganizationScenarios.scala
----------------------------------------------------------------------
diff --git a/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/OrganizationScenarios.scala b/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/OrganizationScenarios.scala
new file mode 100755
index 0000000..7c411b0
--- /dev/null
+++ b/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/OrganizationScenarios.scala
@@ -0,0 +1,42 @@
+/*
+ * 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
+
+import io.gatling.core.Predef._
+import io.gatling.http.Predef._
+import scala.concurrent.duration._
+
+/**
+ * Performs organization registration
+ *
+ *
+ * Produces:
+ *
+ * orgName The name of the created organization
+ * userName  The user name of the admin to log in with
+ * password The password of the admin to use
+ */
+object OrganizationScenarios {
+
+  //register the org with the randomly generated org
+  val createOrgAndAdmin = exec(http("Create Organization")
+  .post("/management/organizations")
+  .headers(Headers.jsonAnonymous)
+  .body(StringBody("{\"organization\":\"" + Settings.org + "\",\"username\":\"${username}\",\"name\":\"${username}\",\"email\":\"${username}@apigee.com\",\"password\":\"${password}\"}"))
+  .check(status.is(200)))
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/TokenScenarios.scala
----------------------------------------------------------------------
diff --git a/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/TokenScenarios.scala b/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/TokenScenarios.scala
new file mode 100755
index 0000000..9dff0df
--- /dev/null
+++ b/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/TokenScenarios.scala
@@ -0,0 +1,59 @@
+/*
+ * 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
+
+import io.gatling.core.Predef._
+import io.gatling.http.Predef._
+import scala.concurrent.duration._
+
+/**
+ * Class that will get the token and insert it into the test session.
+ * Assumes that  the following values are present in the session.
+ *
+ * Expects:
+ *
+ * userName  The user name to log in with
+ * password The password to use
+ *
+ * Produces:
+ *
+ * authToken A valid access token if the login attempt is successful
+ */
+
+object TokenScenarios {
+
+
+  val getManagementToken =
+    exec(
+      http("POST Org Token")
+        .post("/management/token")
+        .headers(Headers.jsonAnonymous)
+        //pass in the the username and password, store the "access_token" json response element as the var "authToken" in the session
+        .body(StringBody("{\"username\":\"${username}\",\"password\":\"${password}\",\"grant_type\":\"password\"}"))
+        .check(jsonPath("access_token")
+        .saveAs("authToken"))
+    )
+
+  val getUserToken =
+    exec(
+      http("POST user token")
+        .post("/token")
+        .body(StringBody("{\"grant_type\":\"password\",\"username\":\"${user1}\",\"password\":\"password\"}"))
+        .check(status.is(200))
+    )
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/UserScenarios.scala
----------------------------------------------------------------------
diff --git a/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/UserScenarios.scala b/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/UserScenarios.scala
new file mode 100755
index 0000000..843bc2e
--- /dev/null
+++ b/stack/gatling/src/main/scala/org/apache/usergrid/scenarios/UserScenarios.scala
@@ -0,0 +1,50 @@
+/*
+ * 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
+
+import io.gatling.core.Predef._
+import io.gatling.http.Predef._
+
+object UserScenarios {
+
+  val getRandomUser = exec(
+    http("GET user")
+      .get("/users/user" + Utils.generateRandomInt(1, Settings.numEntities))
+      .check(status.is(200))
+  )
+
+  val postUser = exec(
+    http("POST geolocated Users")
+      .post("/users")
+      .body(StringBody("{\"location\":{\"latitude\":\"${latitude}\",\"longitude\":\"${longitude}\"},\"username\":\"${username}\"," +
+      "\"displayName\":\"${displayName}\",\"age\":\"${age}\",\"seen\":\"${seen}\",\"weight\":\"${weight}\"," +
+      "\"height\":\"${height}\",\"aboutMe\":\"${aboutMe}\",\"profileId\":\"${profileId}\",\"headline\":\"${headline}\"," +
+      "\"showAge\":\"${showAge}\",\"relationshipStatus\":\"${relationshipStatus}\",\"ethnicity\":\"${ethnicity}\",\"password\":\"password\"}"))
+      .check(status.is(200))
+  )
+
+  val postUser400ok = exec(
+    http("POST geolocated Users")
+      .post("/users")
+      .body(StringBody("{\"location\":{\"latitude\":\"${latitude}\",\"longitude\":\"${longitude}\"},\"username\":\"${username}\"," +
+      "\"displayName\":\"${displayName}\",\"age\":\"${age}\",\"seen\":\"${seen}\",\"weight\":\"${weight}\"," +
+      "\"height\":\"${height}\",\"aboutMe\":\"${aboutMe}\",\"profileId\":\"${profileId}\",\"headline\":\"${headline}\"," +
+      "\"showAge\":\"${showAge}\",\"relationshipStatus\":\"${relationshipStatus}\",\"ethnicity\":\"${ethnicity}\",\"password\":\"password\"}"))
+      .check(status.in(200 to 400))
+  )
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/gatling/src/main/scala/org/apache/usergrid/settings/Headers.scala
----------------------------------------------------------------------
diff --git a/stack/gatling/src/main/scala/org/apache/usergrid/settings/Headers.scala b/stack/gatling/src/main/scala/org/apache/usergrid/settings/Headers.scala
new file mode 100755
index 0000000..319bdcf
--- /dev/null
+++ b/stack/gatling/src/main/scala/org/apache/usergrid/settings/Headers.scala
@@ -0,0 +1,43 @@
+/*
+ * 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
+
+/**
+ *
+ */
+object Headers {
+
+  /**
+   * Headers for anonymous posts
+   */
+  val jsonAnonymous = Map(
+    "Cache-Control" -> """no-cache""",
+    "Content-Type" -> """application/json; charset=UTF-8"""
+  )
+
+  /**
+   * Headers for authorized users with token and json content type
+   */
+  val jsonAuthorized = Map(
+    "Cache-Control" -> """no-cache""",
+    "Content-Type" -> """application/json; charset=UTF-8""",
+    "Authorization" -> "Bearer ${authToken}"
+  )
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/gatling/src/main/scala/org/apache/usergrid/settings/Settings.scala
----------------------------------------------------------------------
diff --git a/stack/gatling/src/main/scala/org/apache/usergrid/settings/Settings.scala b/stack/gatling/src/main/scala/org/apache/usergrid/settings/Settings.scala
new file mode 100755
index 0000000..5588b67
--- /dev/null
+++ b/stack/gatling/src/main/scala/org/apache/usergrid/settings/Settings.scala
@@ -0,0 +1,54 @@
+/*
+ * 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
+
+import io.gatling.core.Predef._
+import io.gatling.http.Predef._
+import scala.concurrent.duration._
+
+object Settings {
+
+  // Target settings
+  val org = System.getProperty("org")
+  val app = System.getProperty("app")
+  val baseUrl = System.getProperty("baseurl")
+  val httpConf = http.baseURL(baseUrl + "/" + org + "/" + app)
+
+  // Simulation settings
+  val numUsers:Int = Integer.getInteger("numUsers", 10).toInt
+  val numEntities:Int = Integer.getInteger("numEntities", 5000).toInt
+  val numDevices:Int = Integer.getInteger("numDevices", 2000).toInt
+
+  val rampTime:Int = Integer.getInteger("rampTime", 0).toInt // in seconds
+  val duration:Int = Integer.getInteger("duration", 300).toInt // in seconds
+  val throttle:Int = Integer.getInteger("throttle", 50).toInt // in seconds
+
+  // Geolocation settings
+  val centerLatitude:Double = 37.442348 // latitude of center point
+  val centerLongitude:Double = -122.138268 // longitude of center point
+  val userLocationRadius:Double = 32000 // location of requesting user in meters
+  val geosearchRadius:Int = 8000 // search area in meters
+
+  // Push Notification settings
+  val pushNotifier = System.getProperty("notifier")
+  val pushProvider = System.getProperty("provider")
+
+  def createRandomPushNotifier:String = {
+    return Utils.generateUniqueName("notifier")
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/gatling/src/main/scala/org/apache/usergrid/settings/Utils.scala
----------------------------------------------------------------------
diff --git a/stack/gatling/src/main/scala/org/apache/usergrid/settings/Utils.scala b/stack/gatling/src/main/scala/org/apache/usergrid/settings/Utils.scala
new file mode 100755
index 0000000..396f0b9
--- /dev/null
+++ b/stack/gatling/src/main/scala/org/apache/usergrid/settings/Utils.scala
@@ -0,0 +1,87 @@
+/*
+ * 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
+
+import scala.util.Random
+import scala.math
+import Array._
+
+/**
+ *
+ * Utility for creating various data elements
+ *
+ */
+object Utils {
+
+  private val RNG = new Random
+
+  /**
+   * Generate a new uuid and replace the '-' with empty
+   */
+  def generateUUIDString(): String = {
+    return java.util.UUID.randomUUID.toString.replace("-", "")
+  }
+
+  /**
+   * Generate a unique string with a prefix
+   *
+   * @param prefix
+   * @return
+   */
+  def generateUniqueName(prefix : String): String = {
+     return prefix + generateUUIDString()
+  }
+
+  // random number in between [a...b]
+  def generateRandomInt(lowerBound: Int, upperBound: Int) = RNG.nextInt(upperBound - lowerBound) + lowerBound
+
+  def generateRandomGeolocation(radius: Double, centerLatitude: Double, centerLongitude: Double):Map[String, String] = {
+
+    var rd = radius / 111300 // Convert Radius from meters to degrees.
+    var u = RNG.nextFloat()
+    var v = RNG.nextFloat()
+    var q = math.sqrt(u) * rd
+    var w = q * rd
+    var t = 2 * math.Pi * v
+    var x = math.cos(t) * w
+    var y = math.sin(t) * w
+    var xp = x/math.cos(centerLatitude)
+    var latitude = (y + centerLatitude).toString
+    var longitude = (xp + centerLongitude).toString
+    var geolocation: Map[String, String] = Map("latitude"->latitude,"longitude"->longitude)
+
+    return geolocation
+  }
+
+  def generateRandomQueryString: String = {
+
+    val queryParams = Array("age", "height", "weight")
+    var queryString = ""
+
+    for (numParams <- 1 to generateRandomInt(1, queryParams.length)) {
+      queryString = "age=" + Utils.generateRandomInt(18, 65).toString
+      if (numParams == 2) {
+        queryString += "%20AND%20height=" + Utils.generateRandomInt(48, 84).toString
+      } else if (numParams == 3) {
+        queryString += "%20AND%20weight=" + Utils.generateRandomInt(120, 350).toString
+      }
+    }
+
+    return queryString
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/gatling/src/main/scala/org/apache/usergrid/simulations/GetEntitySimulation.scala
----------------------------------------------------------------------
diff --git a/stack/gatling/src/main/scala/org/apache/usergrid/simulations/GetEntitySimulation.scala b/stack/gatling/src/main/scala/org/apache/usergrid/simulations/GetEntitySimulation.scala
new file mode 100644
index 0000000..46d5abe
--- /dev/null
+++ b/stack/gatling/src/main/scala/org/apache/usergrid/simulations/GetEntitySimulation.scala
@@ -0,0 +1,42 @@
+/*
+ * 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.http.Predef._
+ import org.apache.usergrid.{UserScenarios, Settings, FeederGenerator}
+ import scala.concurrent.duration._
+
+class GetEntitySimulation extends Simulation {
+
+  // Target settings
+  val httpConf = Settings.httpConf
+
+  // Simulation settings
+  val numUsers:Int = Settings.numUsers
+  val numEntities:Int = Settings.numEntities
+  val rampTime:Int = Settings.rampTime
+  val throttle:Int = Settings.throttle
+
+  val feeder = FeederGenerator.generateEntityNameFeeder("user", numEntities).circular
+
+  val scnToRun = scenario("GET entity")
+    .exec(UserScenarios.getRandomUser)
+
+  setUp(scnToRun.inject(atOnceUsers(numUsers)).throttle(reachRps(throttle) in (rampTime.seconds)).protocols(httpConf)).maxDuration(Settings.duration)
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/gatling/src/main/scala/org/apache/usergrid/simulations/PostDevicesSimulation.scala
----------------------------------------------------------------------
diff --git a/stack/gatling/src/main/scala/org/apache/usergrid/simulations/PostDevicesSimulation.scala b/stack/gatling/src/main/scala/org/apache/usergrid/simulations/PostDevicesSimulation.scala
new file mode 100755
index 0000000..394144b
--- /dev/null
+++ b/stack/gatling/src/main/scala/org/apache/usergrid/simulations/PostDevicesSimulation.scala
@@ -0,0 +1,43 @@
+/*
+ * 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.http.Predef._
+ import org.apache.usergrid.{DeviceScenarios, FeederGenerator, Settings}
+ import scala.concurrent.duration._
+
+class PostDevicesSimulation extends Simulation {
+
+  // Target settings
+  val httpConf = Settings.httpConf
+
+  // Simulation settings
+  val numUsers:Int = Settings.numUsers
+  val numEntities:Int = Settings.numEntities
+  val rampTime:Int = Settings.rampTime
+  val throttle:Int = Settings.throttle
+
+  val feeder = FeederGenerator.generateEntityNameFeeder("device", numEntities)
+
+  val scnToRun = scenario("POST device")
+    .feed(feeder)
+    .exec(DeviceScenarios.postDeviceWithNotifier)
+
+  setUp(scnToRun.inject(atOnceUsers(numUsers)).throttle(reachRps(throttle) in (rampTime.seconds)).protocols(httpConf))
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/gatling/src/main/scala/org/apache/usergrid/simulations/PostUsersSimulation.scala
----------------------------------------------------------------------
diff --git a/stack/gatling/src/main/scala/org/apache/usergrid/simulations/PostUsersSimulation.scala b/stack/gatling/src/main/scala/org/apache/usergrid/simulations/PostUsersSimulation.scala
new file mode 100755
index 0000000..aef394c
--- /dev/null
+++ b/stack/gatling/src/main/scala/org/apache/usergrid/simulations/PostUsersSimulation.scala
@@ -0,0 +1,48 @@
+/*
+ * 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 org.apache.usergrid.{UserScenarios, FeederGenerator, Settings}
+
+import scala.concurrent.duration._
+
+class PostUsersSimulation extends Simulation {
+
+  // Target settings
+  val httpConf = Settings.httpConf
+
+  // Simulation settings
+  val numUsers:Int = Settings.numUsers
+  val rampTime:Int = Settings.rampTime
+  val throttle:Int = Settings.throttle
+
+  // Geolocation settings
+  val centerLatitude:Double = Settings.centerLatitude
+  val centerLongitude:Double = Settings.centerLongitude
+  val userLocationRadius:Double = Settings.userLocationRadius
+  val geosearchRadius:Int = Settings.geosearchRadius
+
+  val feeder = FeederGenerator.generateUserWithGeolocationFeeder(numUsers, userLocationRadius, centerLatitude, centerLongitude).queue
+
+  val scnToRun = scenario("POST geolocated users")
+    .feed(feeder)
+    .exec(UserScenarios.postUser)
+
+  setUp(scnToRun.inject(atOnceUsers(numUsers)).throttle(reachRps(throttle) in (rampTime.seconds)).protocols(httpConf))
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/gatling/src/main/scala/org/apache/usergrid/simulations/PushNotificationTargetDeviceSimulation.scala
----------------------------------------------------------------------
diff --git a/stack/gatling/src/main/scala/org/apache/usergrid/simulations/PushNotificationTargetDeviceSimulation.scala b/stack/gatling/src/main/scala/org/apache/usergrid/simulations/PushNotificationTargetDeviceSimulation.scala
new file mode 100755
index 0000000..2e6a2ba
--- /dev/null
+++ b/stack/gatling/src/main/scala/org/apache/usergrid/simulations/PushNotificationTargetDeviceSimulation.scala
@@ -0,0 +1,54 @@
+/*
+ * 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.http.Predef._
+ import org.apache.usergrid._
+ import scala.concurrent.duration._
+
+/**
+ *
+ * Simple test for setting up multiple orgs and creating push notifications
+ *
+ */
+class PushNotificationTargetDeviceSimulation extends Simulation {
+
+  val numUsers:Int = Settings.numUsers
+  val numEntities:Int = Settings.numEntities
+  val rampTime:Int = Settings.rampTime
+  val throttle:Int = Settings.throttle
+  val duration:Int = Settings.duration  
+  val httpConf = Settings.httpConf
+    .acceptHeader("application/json")
+
+  val createNotifier = NotifierScenarios.createNotifier
+  val createDevice = DeviceScenarios.postDeviceWithNotifier
+  val sendNotification = NotificationScenarios.sendNotification
+
+  val deviceNameFeeder = FeederGenerator.generateEntityNameFeeder("device", numEntities).circular
+
+  val scnToRun = scenario("Create Push Notification")    
+    .during(duration.seconds) {
+      feed(deviceNameFeeder)
+      .exec(sendNotification)
+    }
+
+
+  setUp(scnToRun.inject(atOnceUsers(numUsers)).throttle(reachRps(throttle) in (rampTime.seconds)).protocols(httpConf))
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/gatling/src/main/scala/org/apache/usergrid/simulations/PushNotificationTargetUserSimulation.scala
----------------------------------------------------------------------
diff --git a/stack/gatling/src/main/scala/org/apache/usergrid/simulations/PushNotificationTargetUserSimulation.scala b/stack/gatling/src/main/scala/org/apache/usergrid/simulations/PushNotificationTargetUserSimulation.scala
new file mode 100644
index 0000000..acef447
--- /dev/null
+++ b/stack/gatling/src/main/scala/org/apache/usergrid/simulations/PushNotificationTargetUserSimulation.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.http.Predef._
+ import org.apache.usergrid._
+ import scala.concurrent.duration._
+
+class PushNotificationTargetUserSimulation extends Simulation {
+
+  val numUsers:Int = Settings.numUsers
+  val numEntities:Int = Settings.numEntities
+  val rampTime:Int = Settings.rampTime
+  val throttle:Int = Settings.throttle
+  val duration:Int = Settings.duration
+  val httpConf = Settings.httpConf.acceptHeader("application/json")
+
+  val notifier = Settings.pushNotifier
+  val createDevice = DeviceScenarios.postDeviceWithNotifier400ok
+  val sendNotification = NotificationScenarios.sendNotification
+  val createUser = UserScenarios.postUser400ok
+  val deviceNameFeeder = FeederGenerator.generateEntityNameFeeder("device", numEntities).circular
+  val userFeeder = FeederGenerator.generateUserWithGeolocationFeeder(numEntities, Settings.userLocationRadius, Settings.centerLatitude, Settings.centerLongitude)
+
+  val scnToRun = scenario("Create Push Notification")
+    .feed(userFeeder)
+    .exec(createUser)
+//    .pause(1000)
+    .exec(http("Check user and user devices")
+      .get("/users/${username}/devices")
+      .check(status.is(200))
+    )
+    .feed(deviceNameFeeder)
+    .exec(createDevice)
+//    .pause(1000)
+    .exec(http("Check device connections")
+      .get("/devices/${entityName}/users")
+      .check(status.is(200))
+    )
+    .exec(http("Connect user with device")
+      .post("/users/${username}/devices/${deviceId}")
+      .check(status.is(200))
+    )
+    .exec(http("Send Notification to All Devices")
+      .post("/users/${username}/notifications")
+      .body(StringBody("{\"payloads\":{\"" + notifier + "\":\"testmessage\"}}"))
+      .check(status.is(200))
+    )
+
+
+  setUp(scnToRun.inject(constantUsersPerSec(numUsers) during (duration)).throttle(reachRps(throttle) in (rampTime.seconds)).protocols(httpConf))
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/gatling/src/test/resources/gatling.conf
----------------------------------------------------------------------
diff --git a/stack/gatling/src/test/resources/gatling.conf b/stack/gatling/src/test/resources/gatling.conf
new file mode 100644
index 0000000..1455242
--- /dev/null
+++ b/stack/gatling/src/test/resources/gatling.conf
@@ -0,0 +1,154 @@
+#########################
+# Gatling Configuration #
+#########################
+
+# This file contains all the settings configurable for Gatling with their default values
+
+gatling {
+  core {
+    #outputDirectoryBaseName = "" # The prefix for each simulation result folder (then suffixed by the report generation timestamp)
+    #runDescription = ""          # The description for this simulation run, displayed in each report
+    #encoding = "utf-8"           # Encoding to use throughout Gatling for file and string manipulation
+    #simulationClass = ""         # The FQCN of the simulation to run (when used in conjunction with noReports, the simulation for which assertions will be validated)
+    #disableCompiler = false      # When set to true, skip compiling and load an already compiled simulation (used in conjunction with simulationClass)
+    #mute = false                 # When set to true, don't ask for simulation name nor run description (currently only used by Gatling SBT plugin)
+
+    extract {
+      regex {
+        #cacheMaxCapacity = 200 # Cache size for the compiled regexes, set to 0 to disable caching
+      }
+      xpath {
+        #cacheMaxCapacity = 200 # Cache size for the compiled XPath queries,  set to 0 to disable caching
+      }
+      jsonPath {
+        #cacheMaxCapacity = 200 # Cache size for the compiled jsonPath queries, set to 0 to disable caching
+        #preferJackson = false  # When set to true, prefer Jackson over Boon for JSON-related operations
+        jackson {
+          #allowComments = false           # Allow comments in JSON files
+          #allowUnquotedFieldNames = false # Allow unquoted JSON fields names
+          #allowSingleQuotes = false       # Allow single quoted JSON field names
+        }
+
+      }
+      css {
+        #cacheMaxCapacity = 200 # Cache size for the compiled CSS selectors queries,  set to 0 to disable caching
+      }
+    }
+
+    timeOut {
+      #simulation = 8640000 # Absolute timeout, in seconds, of a simulation
+    }
+    directory {
+      #data = user-files/data                    # Folder where user's data (e.g. files used by Feeders) is located
+      #requestBodies = user-files/request-bodies # Folder where request bodies are located
+      #simulations = user-files/simulations      # Folder where the bundle's simulations are located
+      simulations = src/main/scala              # Folder where the bundle's simulations are located
+      #reportsOnly = ""                          # If set, name of report folder to look for in order to generate its report
+      #binaries = ""                             # If set, name of the folder where compiles classes are located
+      #results = results                         # Name of the folder where all reports folder are located
+    }
+    zinc {
+      #jvmArgs = "-Xss10M" # JVM args passed to Zinc (in charge of compiling Gatling Simulations)
+    }
+  }
+  charting {
+    #noReports = false       # When set to true, don't generate HTML reports
+    #maxPlotPerSeries = 1000 # Number of points per graph in Gatling reports
+    #accuracy = 10           # Accuracy, in milliseconds, of the report's stats
+    indicators {
+      #lowerBound = 800      # Lower bound for the requests' response time to track in the reports and the console summary
+      #higherBound = 1200    # Higher bound for the requests' response time to track in the reports and the console summary
+      #percentile1 = 95      # Value for the first percentile to track in the reports, the console summary and GraphiteDataWriter
+      #percentile2 = 99      # Value for the second percentile to track in the reports, the console summary and GraphiteDataWriter
+    }
+  }
+  http {
+    #elFileBodiesCacheMaxCapacity = 200        # Cache size for request body EL templates, set to 0 to disable
+    #rawFileBodiesCacheMaxCapacity = 200       # Cache size for request body Raw templates, set to 0 to disable
+    #fetchedCssCacheMaxCapacity = 200          # Cache size for CSS parsed content, set to 0 to disable
+    #fetchedHtmlCacheMaxCapacity = 200         # Cache size for HTML parsed content, set to 0 to disable
+    #redirectPerUserCacheMaxCapacity = 200     # Per virtual user cache size for permanent redirects, set to 0 to disable
+    #expirePerUserCacheMaxCapacity = 200       # Per virtual user cache size for permanent 'Expire' headers, set to 0 to disable
+    #lastModifiedPerUserCacheMaxCapacity = 200 # Per virtual user cache size for permanent 'Last-Modified' headers, set to 0 to disable
+    #etagPerUserCacheMaxCapacity = 200         # Per virtual user cache size for permanent ETag headers, set to 0 to disable
+    #warmUpUrl = "http://goo.gl/pq1Xwu"        # The URL to use to warm-up the HTTP stack (blank means disabled)
+    ssl {
+      trustStore {
+        #type = ""      # Type of SSLContext's TrustManagers store
+        #file = ""      # Location of SSLContext's TrustManagers store
+        #password = ""  # Password for SSLContext's TrustManagers store
+        #algorithm = "" # Algorithm used by SSLContext's TrustManagers store
+      }
+      keyStore {
+        #type = ""      # Type of SSLContext's KeyManagers store
+        #file = ""      # Location of SSLContext's KeyManagers store
+        #password = ""  # Password for SSLContext's KeyManagers store
+        #algorithm = "" # Algorithm used SSLContext's KeyManagers store
+      }
+    }
+    ahc {
+      #allowPoolingConnections = true             # Allow pooling HTTP connections (keep-alive header automatically added)
+      #allowPoolingSslConnections = true          # Allow pooling HTTPS connections (keep-alive header automatically added)
+      #compressionEnforced = false                # Enforce gzip/deflate when Accept-Encoding header is not defined
+      #connectTimeout = 60000                     # Timeout when establishing a connection
+      #pooledConnectionIdleTimeout = 60000        # Timeout when a connection stays unused in the pool
+      #readTimeout = 60000                        # Timeout when a used connection stays idle
+      #connectionTTL = -1                         # Max duration a connection can stay open (-1 means no limit)
+      #ioThreadMultiplier = 2                     # Number of Netty worker threads per core
+      #maxConnectionsPerHost = -1                 # Max number of connections per host (-1 means no limit)
+      #maxConnections = -1                        # Max number of connections (-1 means no limit)
+      #maxRetry = 0                               # Number of times that a request should be tried again
+      #requestTimeout = 60000                     # Timeout of the requests
+      #useProxyProperties = false                 # When set to true, supports standard Proxy System properties
+      #webSocketTimeout = 60000                   # Timeout when a used websocket connection stays idle
+      #useRelativeURIsWithConnectProxies = true   # When set to true, use relative URIs when talking with an SSL proxy or a WebSocket proxy
+      #acceptAnyCertificate = true                # When set to true, doesn't validate SSL certificates
+      #httpClientCodecMaxInitialLineLength = 4096 # Maximum length of the initial line of the response (e.g. "HTTP/1.0 200 OK")
+      #httpClientCodecMaxHeaderSize = 8192        # Maximum size, in bytes, of each request's headers
+      #httpClientCodecMaxChunkSize = 8192         # Maximum length of the content or each chunk
+      #keepEncodingHeader = true                  # Don't drop Encoding response header after decoding
+      #webSocketMaxFrameSize = 10240              # Maximum frame payload size
+    }
+  }
+  data {
+    #writers = "console, file" # The lists of DataWriters to which Gatling write simulation data (currently supported : "console", "file", "graphite", "jdbc")
+    #reader = file             # The DataReader used by the charting engine for reading simulation results
+    console {
+      #light = false           # When set to true, displays a light version without detailed request stats
+    }
+    file {
+      #bufferSize = 8192       # FileDataWriter's internal data buffer size, in bytes
+    }
+    leak {
+      #noActivityTimeout = 30  # Period, in seconds, for which Gatling may have no activity before considering a leak may be happening
+    }
+    jdbc {
+      db {
+        #url = "jdbc:mysql://localhost:3306/temp" # The JDBC URL used by the JDBC DataWriter
+        #username = "root"                        # The database user used by the JDBC DataWriter
+        #password = "123123q"                     # The password for the specified user
+      }
+      #bufferSize = 20                            # The size for each batch of SQL inserts to send to the database
+      create {
+        #createRunRecordTable = "CREATE TABLE IF NOT EXISTS `RunRecords` ( `id` INT NOT NULL AUTO_INCREMENT , `runDate` DATETIME NULL , `simulationId` VARCHAR(45) NULL , `runDescription` VARCHAR(45) NULL , PRIMARY KEY (`id`) )"
+        #createRequestRecordTable = "CREATE TABLE IF NOT EXISTS `RequestRecords` (`id` int(11) NOT NULL AUTO_INCREMENT, `runId` int DEFAULT NULL, `scenario` varchar(45) DEFAULT NULL, `userId` VARCHAR(20) NULL, `name` varchar(50) DEFAULT NULL, `requestStartDate` bigint DEFAULT NULL, `requestEndDate` bigint DEFAULT NULL, `responseStartDate` bigint DEFAULT NULL, `responseEndDate` bigint DEFAULT NULL, `status` varchar(2) DEFAULT NULL, `message` varchar(4500) DEFAULT NULL, `responseTime` bigint DEFAULT NULL, PRIMARY KEY (`id`) )"
+        #createScenarioRecordTable = "CREATE TABLE IF NOT EXISTS `ScenarioRecords` (`id` int(11) NOT NULL AUTO_INCREMENT, `runId` int DEFAULT NULL, `scenarioName` varchar(45) DEFAULT NULL, `userId` VARCHAR(20) NULL, `event` varchar(50) DEFAULT NULL, `startDate` bigint DEFAULT NULL, `endDate` bigint DEFAULT NULL, PRIMARY KEY (`id`) )"
+        #createGroupRecordTable = "CREATE TABLE IF NOT EXISTS `GroupRecords` (`id` int(11) NOT NULL AUTO_INCREMENT, `runId` int DEFAULT NULL, `scenarioName` varchar(45) DEFAULT NULL, `userId` VARCHAR(20) NULL, `entryDate` bigint DEFAULT NULL, `exitDate` bigint DEFAULT NULL, `status` varchar(2) DEFAULT NULL, PRIMARY KEY (`id`) )"
+      }
+      insert {
+        #insertRunRecord = "INSERT INTO RunRecords (runDate, simulationId, runDescription) VALUES (?,?,?)"
+        #insertRequestRecord = "INSERT INTO RequestRecords (runId, scenario, userId, name, requestStartDate, requestEndDate, responseStartDate, responseEndDate, status, message, responseTime) VALUES (?,?,?,?,?,?,?,?,?,?,?)"
+        #insertScenarioRecord = "INSERT INTO ScenarioRecords (runId, scenarioName, userId, event, startDate, endDate) VALUES (?,?,?,?,?,?)"
+        #insertGroupRecord = "INSERT INTO GroupRecords (runId, scenarioName, userId, entryDate, exitDate, status) VALUES (?,?,?,?,?,?)"
+      }
+    }
+    graphite {
+      #light = false              # only send the all* stats
+      #host = "localhost"         # The host where the Carbon server is located
+      #port = 2003                # The port to which the Carbon server listens to
+      #protocol = "tcp"           # The protocol used to send data to Carbon (currently supported : "tcp", "udp")
+      #rootPathPrefix = "gatling" # The common prefix of all metrics sent to Graphite
+      #bufferSize = 8192          # GraphiteDataWriter's internal data buffer size, in bytes
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/gatling/src/test/resources/logback.xml
----------------------------------------------------------------------
diff --git a/stack/gatling/src/test/resources/logback.xml b/stack/gatling/src/test/resources/logback.xml
new file mode 100644
index 0000000..aa637a8
--- /dev/null
+++ b/stack/gatling/src/test/resources/logback.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+
+	<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+		<encoder>
+			<pattern>%d{HH:mm:ss.SSS} [%-5level] %logger{15} - %msg%n%rEx</pattern>
+			<immediateFlush>false</immediateFlush>
+		</encoder>
+	</appender>
+
+	<!-- Uncomment for logging ALL HTTP request and responses -->
+	<!-- 	<logger name="io.gatling.http.ahc.AsyncHandlerActor" level="TRACE" /> -->
+	<!-- Uncomment for logging ONLY FAILED HTTP request and responses -->
+	<!-- 	<logger name="io.gatling.http.ahc.AsyncHandlerActor" level="DEBUG" /> -->
+
+	<root level="WARN">
+		<appender-ref ref="CONSOLE" />
+	</root>
+
+</configuration>

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/gatling/src/test/resources/recorder.conf
----------------------------------------------------------------------
diff --git a/stack/gatling/src/test/resources/recorder.conf b/stack/gatling/src/test/resources/recorder.conf
new file mode 100644
index 0000000..6c2366e
--- /dev/null
+++ b/stack/gatling/src/test/resources/recorder.conf
@@ -0,0 +1,37 @@
+recorder {
+  core {
+    #encoding = "utf-8"               # The encoding used for reading/writing request bodies and the generated simulation
+    #outputFolder = ""                # The folder where generated simulation will we written
+    #package = ""                     # The package's name of the generated simulation
+    #className = "RecordedSimulation" # The name of the generated Simulation class
+    #thresholdForPauseCreation = 100  # The minimum time, in milliseconds, that must pass between requests to trigger a pause creation
+    #saveConfig = false               # When set to true, the configuration from the Recorder GUI overwrites this configuration
+  }
+  filters {
+    #filterStrategy = "Disabled" # The selected filter resources filter strategy (currently supported : "Disabled", "BlackList", "WhiteList")
+    #whitelist = []              # The list of ressources patterns that are part of the Recorder's whitelist
+    #blacklist = []              # The list of ressources patterns that are part of the Recorder's blacklist
+  }
+  http {
+    #automaticReferer = true       # When set to false, write the referer + enable 'disableAutoReferer' in the generated simulation
+    #followRedirect = true         # When set to false, write redirect requests + enable 'disableFollowRedirect' in the generated simulation
+    #removeConditionalCache = true # When set to true, removes from the generated requests headers leading to request caching
+    #inferHtmlResources = true     # When set to true, add inferred resources + set 'inferHtmlResources' with the configured blacklist/whitelist in the generated simulation
+  }
+  proxy {
+    #port = 8000     # Local port used by Gatling's Proxy for HTTP/HTTPS
+    outgoing {
+      #host = ""     # The outgoing proxy's hostname
+      #username = "" # The username to use to connect to the outgoing proxy
+      #password = "" # The password corresponding to the user to use to connect to the outgoing proxy
+      #port = 0      # The HTTP port to use to connect to the outgoing proxy
+      #sslPort = 0   # If set, The HTTPS port to use to connect to the outgoing proxy
+    }
+  }
+  netty {
+    #maxInitialLineLength = 10000 # Maximum length of the initial line of the response (e.g. "HTTP/1.0 200 OK")
+    #maxHeaderSize = 20000        # Maximum size, in bytes, of each request's headers
+    #maxChunkSize = 8192          # Maximum length of the content or each chunk
+    #maxContentLength = 100000000 # Maximum length of the aggregated content of each response
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/gatling/src/test/scala/Engine.scala
----------------------------------------------------------------------
diff --git a/stack/gatling/src/test/scala/Engine.scala b/stack/gatling/src/test/scala/Engine.scala
new file mode 100644
index 0000000..b6dfa44
--- /dev/null
+++ b/stack/gatling/src/test/scala/Engine.scala
@@ -0,0 +1,16 @@
+import io.gatling.app.Gatling
+import io.gatling.core.config.GatlingPropertiesBuilder
+
+object Engine extends App {
+
+	val props = new GatlingPropertiesBuilder
+	props.disableCompiler
+	props.dataDirectory(IDEPathHelper.dataDirectory.toString)
+	props.resultsDirectory(IDEPathHelper.resultsDirectory.toString)
+	props.requestBodiesDirectory(IDEPathHelper.requestBodiesDirectory.toString)
+	props.binariesDirectory(IDEPathHelper.mavenBinariesDirectory.toString)
+
+  props.simulationClass("org.apache.usergrid.simulations.PushNotificationTargetUserSimulation")
+
+	Gatling.fromMap(props.build)
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/gatling/src/test/scala/IDEPathHelper.scala
----------------------------------------------------------------------
diff --git a/stack/gatling/src/test/scala/IDEPathHelper.scala b/stack/gatling/src/test/scala/IDEPathHelper.scala
new file mode 100644
index 0000000..988b616
--- /dev/null
+++ b/stack/gatling/src/test/scala/IDEPathHelper.scala
@@ -0,0 +1,21 @@
+import scala.tools.nsc.io.File
+import scala.tools.nsc.io.Path.string2path
+
+object IDEPathHelper {
+
+	val gatlingConfUrl = getClass.getClassLoader.getResource("gatling.conf").getPath
+	val projectRootDir = File(gatlingConfUrl).parents(2)
+
+	val mavenSourcesDirectory = projectRootDir / "src" / "test" / "scala"
+	val mavenResourcesDirectory = projectRootDir / "src" / "test" / "resources"
+	val mavenTargetDirectory = projectRootDir / "target"
+	val mavenBinariesDirectory = mavenTargetDirectory / "test-classes"
+
+	val dataDirectory = mavenResourcesDirectory / "data"
+	val requestBodiesDirectory = mavenResourcesDirectory / "request-bodies"
+
+	val recorderOutputDirectory = mavenSourcesDirectory
+	val resultsDirectory = mavenTargetDirectory / "results"
+
+	val recorderConfigFile = (mavenResourcesDirectory / "recorder.conf").toFile
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/gatling/src/test/scala/Recorder.scala
----------------------------------------------------------------------
diff --git a/stack/gatling/src/test/scala/Recorder.scala b/stack/gatling/src/test/scala/Recorder.scala
new file mode 100644
index 0000000..b132063
--- /dev/null
+++ b/stack/gatling/src/test/scala/Recorder.scala
@@ -0,0 +1,12 @@
+import io.gatling.recorder.config.RecorderPropertiesBuilder
+import io.gatling.recorder.controller.RecorderController
+
+object Recorder extends App {
+
+	val props = new RecorderPropertiesBuilder
+	props.simulationOutputFolder(IDEPathHelper.recorderOutputDirectory.toString)
+	props.simulationPackage("org.apache.usergrid")
+	props.requestBodiesFolder(IDEPathHelper.requestBodiesDirectory.toString)
+
+	RecorderController(props.build, Some(IDEPathHelper.recorderConfigFile))
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/loadtests/simulations/test/scala/org/apache/usergrid/scenarios/DeviceScenarios.scala
----------------------------------------------------------------------
diff --git a/stack/loadtests/simulations/test/scala/org/apache/usergrid/scenarios/DeviceScenarios.scala b/stack/loadtests/simulations/test/scala/org/apache/usergrid/scenarios/DeviceScenarios.scala
index d8d8af0..e86bd42 100755
--- a/stack/loadtests/simulations/test/scala/org/apache/usergrid/scenarios/DeviceScenarios.scala
+++ b/stack/loadtests/simulations/test/scala/org/apache/usergrid/scenarios/DeviceScenarios.scala
@@ -46,7 +46,7 @@ object DeviceScenarios {
       "\"deviceModel\":\"Fake Device\"," +
       " \"deviceOSVerion\":\"Negative Version\", " +
       "\"${notifier}.notifier.id\":\"${entityName}\"}"))
-    .check(status.is(200)))
+    .check(status.is(200), jsonPath("$.entities[0].uuid").saveAs("deviceId")))
 
   val postDeviceWithNotifier400ok = exec(http("Create device with notifier")
     .post("/devices")
@@ -54,7 +54,7 @@ object DeviceScenarios {
     "\"deviceModel\":\"Fake Device\"," +
     " \"deviceOSVerion\":\"Negative Version\", " +
     "\"${notifier}.notifier.id\":\"${entityName}\"}"))
-    .check(status.in(200 to 400)))
+    .check(status.in(200 to 400), jsonPath("$.entities[0].uuid").saveAs("deviceId")))
 
   /**
    * TODO: Add a device to a user, which would expect a user in the session

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/loadtests/simulations/test/scala/org/apache/usergrid/simulations/PushNotificationTargetDeviceSimulation.scala
----------------------------------------------------------------------
diff --git a/stack/loadtests/simulations/test/scala/org/apache/usergrid/simulations/PushNotificationTargetDeviceSimulation.scala b/stack/loadtests/simulations/test/scala/org/apache/usergrid/simulations/PushNotificationTargetDeviceSimulation.scala
new file mode 100755
index 0000000..66b3c5d
--- /dev/null
+++ b/stack/loadtests/simulations/test/scala/org/apache/usergrid/simulations/PushNotificationTargetDeviceSimulation.scala
@@ -0,0 +1,53 @@
+/*
+ * 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
+
+import io.gatling.core.Predef._
+import io.gatling.http.Predef._
+import scala.concurrent.duration._
+
+/**
+ *
+ * Simple test for setting up multiple orgs and creating push notifications
+ *
+ */
+class PushNotificationTargetDeviceSimulation extends Simulation {
+
+  val numUsers:Int = Settings.numUsers
+  val numEntities:Int = Settings.numEntities
+  val rampTime:Int = Settings.rampTime
+  val throttle:Int = Settings.throttle
+  val duration:Int = Settings.duration  
+  val httpConf = Settings.httpConf
+    .acceptHeader("application/json")
+
+  val createNotifier = NotifierScenarios.createNotifier
+  val createDevice = DeviceScenarios.postDeviceWithNotifier
+  val sendNotification = NotificationScenarios.sendNotification
+
+  val deviceNameFeeder = FeederGenerator.generateEntityNameFeeder("device", numEntities).circular
+
+  val scnToRun = scenario("Create Push Notification")    
+    .during(duration.seconds) {
+      feed(deviceNameFeeder)
+      .exec(sendNotification)
+    }
+
+
+  setUp(scnToRun.inject(atOnceUsers(numUsers)).throttle(reachRps(throttle) in (rampTime.seconds)).protocols(httpConf))
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/loadtests/simulations/test/scala/org/apache/usergrid/simulations/PushNotificationTargetUserSimulation.scala
----------------------------------------------------------------------
diff --git a/stack/loadtests/simulations/test/scala/org/apache/usergrid/simulations/PushNotificationTargetUserSimulation.scala b/stack/loadtests/simulations/test/scala/org/apache/usergrid/simulations/PushNotificationTargetUserSimulation.scala
new file mode 100644
index 0000000..67ee20a
--- /dev/null
+++ b/stack/loadtests/simulations/test/scala/org/apache/usergrid/simulations/PushNotificationTargetUserSimulation.scala
@@ -0,0 +1,67 @@
+/*
+ * 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
+
+import io.gatling.core.Predef._
+import io.gatling.http.Predef._
+import scala.concurrent.duration._
+
+class PushNotificationTargetUserSimulation extends Simulation {
+
+  val numUsers:Int = Settings.numUsers
+  val numEntities:Int = Settings.numEntities
+  val rampTime:Int = Settings.rampTime
+  val throttle:Int = Settings.throttle
+  val duration:Int = Settings.duration
+  val httpConf = Settings.httpConf.acceptHeader("application/json")
+
+  val notifier = Settings.pushNotifier
+  val createDevice = DeviceScenarios.postDeviceWithNotifier400ok
+  val sendNotification = NotificationScenarios.sendNotification
+  val createUser = UserScenarios.postUser400ok
+  val deviceNameFeeder = FeederGenerator.generateEntityNameFeeder("device", numEntities).circular
+  val userFeeder = FeederGenerator.generateUserWithGeolocationFeeder(numEntities, Settings.userLocationRadius, Settings.centerLatitude, Settings.centerLongitude)
+
+  val scnToRun = scenario("Create Push Notification")
+    .feed(userFeeder)
+    .exec(createUser)
+//    .pause(1000)
+    .exec(http("Check user and user devices")
+      .get("/users/${username}/devices")
+      .check(status.is(200))
+    )
+    .feed(deviceNameFeeder)
+    .exec(createDevice)
+//    .pause(1000)
+    .exec(http("Check device connections")
+      .get("/devices/${entityName}/users")
+      .check(status.is(200))
+    )
+    .exec(http("Connect user with device")
+      .post("/users/${username}/devices/${deviceId}")
+      .check(status.is(200))
+    )
+    .exec(http("Send Notification to All Devices")
+      .post("/users/${username}/notifications")
+      .body(StringBody("{\"payloads\":{\"" + notifier + "\":\"testmessage\"}}"))
+      .check(status.is(200))
+    )
+
+
+  setUp(scnToRun.inject(constantUsersPerSec(numUsers) during (duration)).throttle(reachRps(throttle) in (rampTime.seconds)).protocols(httpConf))
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bfc4d0fc/stack/loadtests/simulations/test/scala/org/apache/usergrid/simulations/PushTargetDeviceSimulation.scala
----------------------------------------------------------------------
diff --git a/stack/loadtests/simulations/test/scala/org/apache/usergrid/simulations/PushTargetDeviceSimulation.scala b/stack/loadtests/simulations/test/scala/org/apache/usergrid/simulations/PushTargetDeviceSimulation.scala
deleted file mode 100755
index 66b3c5d..0000000
--- a/stack/loadtests/simulations/test/scala/org/apache/usergrid/simulations/PushTargetDeviceSimulation.scala
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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
-
-import io.gatling.core.Predef._
-import io.gatling.http.Predef._
-import scala.concurrent.duration._
-
-/**
- *
- * Simple test for setting up multiple orgs and creating push notifications
- *
- */
-class PushNotificationTargetDeviceSimulation extends Simulation {
-
-  val numUsers:Int = Settings.numUsers
-  val numEntities:Int = Settings.numEntities
-  val rampTime:Int = Settings.rampTime
-  val throttle:Int = Settings.throttle
-  val duration:Int = Settings.duration  
-  val httpConf = Settings.httpConf
-    .acceptHeader("application/json")
-
-  val createNotifier = NotifierScenarios.createNotifier
-  val createDevice = DeviceScenarios.postDeviceWithNotifier
-  val sendNotification = NotificationScenarios.sendNotification
-
-  val deviceNameFeeder = FeederGenerator.generateEntityNameFeeder("device", numEntities).circular
-
-  val scnToRun = scenario("Create Push Notification")    
-    .during(duration.seconds) {
-      feed(deviceNameFeeder)
-      .exec(sendNotification)
-    }
-
-
-  setUp(scnToRun.inject(atOnceUsers(numUsers)).throttle(reachRps(throttle) in (rampTime.seconds)).protocols(httpConf))
-
-}