Skip to content
Browse files

Merge "CFID-143: Add gatling support for ACM and basic tests"

  • Loading branch information...
2 parents 2b088b4 + 11cdf72 commit 1b03bde39e5fd6ebb34b7fc6246cfa19b4f4b6c7 @tekul tekul committed with Gerrit Code Review Mar 21, 2012
View
105 gatling/src/main/scala/AcmBaseDataCreationSimulation.scala
@@ -0,0 +1,105 @@
+/**
+ * Cloud Foundry 2012.02.03 Beta
+ * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved.
+ *
+ * This product is licensed to you under the Apache License, Version 2.0 (the "License").
+ * You may not use this product except in compliance with the License.
+ *
+ * This product includes a number of subcomponents with
+ * separate copyright notices and license terms. Your use of these
+ * subcomponents is subject to the terms and conditions of the
+ * subcomponent's license, as noted in the LICENSE file.
+ */
+
+import com.excilys.ebi.gatling.core.feeder.Feeder
+import com.excilys.ebi.gatling.core.Predef._
+import com.excilys.ebi.gatling.core.scenario.configuration.Simulation
+import com.excilys.ebi.gatling.http.Predef._
+
+import acm.AcmApi._
+import acm.Config._
+import java.util.concurrent.atomic.AtomicInteger
+
+object AcmBaseData {
+ // Standard permissions for the "app space"
+ val stdPermissions = Seq("read_app", "update_app", "delete_app", "read_app_logs", "read_service",
+ "write_service", "add_user", "remove_user")
+
+ // Standard list of users and groups for use in ACLs etc
+ val acmUsers: Seq[String] = 1 to 1000 map (i => "acm_user_%s".format(i))
+
+ //val acmGroups: Seq[String] = 1 to 1000 map (i => "g-acm_group_%s".format(i))
+
+ // Feeder for plugging standard user names into actions
+ def acmUserFeeder = new Feeder {
+ var count = -1
+
+ def next = {
+ count += 1
+ Map("acm_user" -> acmUsers(count))
+ }
+ }
+}
+
+/**
+ * Populates an empty ACM database with user and group data
+ */
+class AcmBaseDataCreationSimulation extends Simulation {
+
+ import AcmBaseData._
+
+ val createStandardAppSpace = scenario("Create Standard App Space")
+ .exec(createPermissionSet("app_space", stdPermissions take 5))
+ .exec(updatePermissionSet("app_space", stdPermissions))
+
+ val createUsers = scenario("Create Standard Users")
+ .loop(chain
+ .feed(acmUserFeeder)
+ .exec(createUser("${acm_user}"))
+ ).times(1000)
+
+ val groupCount = new AtomicInteger(0)
+ val groupUsersCount = new AtomicInteger(0)
+ val MaxUsersPerGroup = 200
+
+ val createGroups = scenario("Create Standard Groups")
+ // Loop until we have enough users created
+ .loop(
+ chain.pause(1).exec(
+ http("Get Max Required User")
+ .get("/users/acm_user_%s".format(MaxUsersPerGroup))
+ .basicAuth(acmUser, acmPassword)
+ .check(status.saveAs("max_user_status")))
+ ).asLongAs((s: Session) => {
+ val status = s.getAttributeAsOption[Int]("max_user_status")
+// println("Status is " + status + "," + status.getClass)
+ status == None || status == Some(404)
+ })
+ .loop(
+ chain.exec((s: Session) => {
+ val nUsers = groupUsersCount.incrementAndGet() match {
+ case x if (x % MaxUsersPerGroup == 0) => MaxUsersPerGroup
+ case y => y % MaxUsersPerGroup
+ }
+ assert(nUsers > 0 && nUsers <= MaxUsersPerGroup)
+ val users = acmUsers.take(nUsers).mkString("\"", "\",\"", "\"")
+ s.setAttribute("group_count", groupCount.incrementAndGet())
+ .setAttribute("group_users", users)
+ })
+ .exec(
+ http("Create Standard Group")
+ .post("/groups/g-acm_group_${group_count}")
+ .body("""{"members": [${group_users}]}""")
+ .basicAuth(acmUser, acmPassword)
+ .check(status.is(200)))
+ ).times(1000)
+
+ def apply = {
+ Seq(
+ createStandardAppSpace.configure users 1 protocolConfig acmHttpConfig,
+ createUsers.configure users 1 protocolConfig acmHttpConfig,
+ createGroups.configure users 1 protocolConfig acmHttpConfig
+ )
+ }
+
+}
View
40 gatling/src/main/scala/AcmPermissionSetCreationSimulation.scala
@@ -0,0 +1,40 @@
+/**
+ * Cloud Foundry 2012.02.03 Beta
+ * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved.
+ *
+ * This product is licensed to you under the Apache License, Version 2.0 (the "License").
+ * You may not use this product except in compliance with the License.
+ *
+ * This product includes a number of subcomponents with
+ * separate copyright notices and license terms. Your use of these
+ * subcomponents is subject to the terms and conditions of the
+ * subcomponent's license, as noted in the LICENSE file.
+ */
+
+import com.excilys.ebi.gatling.core.Predef._
+import com.excilys.ebi.gatling.core.scenario.configuration.Simulation
+import com.excilys.ebi.gatling.core.structure.ChainBuilder
+
+
+import acm.AcmApi._
+import acm.Config._
+
+class AcmPermissionSetCreationSimulation extends Simulation {
+
+ /**
+ * recursive call to create a chain of n executors, creating sets with `start` to `start + n * incr`
+ */
+ def permissionSetCreationChain(cb: ChainBuilder, n: Int, start: Int, incr: Int=10): ChainBuilder = n match {
+ case 0 => cb
+ case _ => permissionSetCreationChain(cb.exec(createRandomPermissionSet(start)), n - 1, start + incr)
+ }
+
+ val createPermissionSets = scenario("Create Permission Sets")
+ .insertChain(permissionSetCreationChain(ChainBuilder.chain, 100, 1, 1))
+
+ def apply = {
+ Seq(
+ createPermissionSets.configure users 1 protocolConfig acmHttpConfig
+ )
+ }
+}
View
64 gatling/src/main/scala/AcmSmokeSimulation.scala
@@ -0,0 +1,64 @@
+/**
+ * Cloud Foundry 2012.02.03 Beta
+ * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved.
+ *
+ * This product is licensed to you under the Apache License, Version 2.0 (the "License").
+ * You may not use this product except in compliance with the License.
+ *
+ * This product includes a number of subcomponents with
+ * separate copyright notices and license terms. Your use of these
+ * subcomponents is subject to the terms and conditions of the
+ * subcomponent's license, as noted in the LICENSE file.
+ */
+
+import com.excilys.ebi.gatling.core.Predef._
+import com.excilys.ebi.gatling.http.Predef._
+
+import acm.Config._
+import acm.AcmApi._
+import java.util.concurrent.TimeUnit
+
+
+import AcmBaseData._
+
+
+class AcmSmokeSimulation extends Simulation {
+ val Duration = 60
+
+ /**
+ * Creates permission sets and with the specified number of randomly-named permissions,
+ * reads the permission set nReads times then deletes it
+ */
+ def createPermissionSets(nPermissions: Int, nReads: Int=100) = scenario("Permission Set creation with %s permissions".format(nPermissions))
+ .loop(
+ chain.exec(createRandomPermissionSet(nPermissions))
+ .loop(chain
+ .exec(getPermissionSet("${permission_set}"))
+ ).times(100)
+ .exec(deletePermissionSet("${permission_set}"))
+ ).during(Duration)
+
+ /**
+ * Creates n objects with nUsers assigned to each of the standard (base data) permissions
+ * Reads the object nReads times
+ */
+ def createObjects(n: Int, nUsers: Int, nGroups: Int, nReads: Int=100) = scenario("Bash ACM Object Creation")
+ .loop(
+ chain.exec(createObject(Seq("app_space"), stdPermissions map (s => (s, acmUsers.take(nUsers))) toMap))
+ .loop(
+ chain.exec(getObject("${acm_object_id}"))
+ .pause(10,100, TimeUnit.MILLISECONDS)
+ ).times(nReads)
+ ).during(Duration)
+
+ /**
+ * The main simulation method defining scenarios to be run, number of users.
+ */
+ def apply = {
+ Seq(
+ createPermissionSets(10).configure users 1 protocolConfig acmHttpConfig,
+ createObjects(10, 5, 2).configure users 1 protocolConfig acmHttpConfig
+ )
+ }
+
+}
View
123 gatling/src/main/scala/acm/AcmApi.scala
@@ -0,0 +1,123 @@
+/**
+ * Cloud Foundry 2012.02.03 Beta
+ * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved.
+ *
+ * This product is licensed to you under the Apache License, Version 2.0 (the "License").
+ * You may not use this product except in compliance with the License.
+ *
+ * This product includes a number of subcomponents with
+ * separate copyright notices and license terms. Your use of these
+ * subcomponents is subject to the terms and conditions of the
+ * subcomponent's license, as noted in the LICENSE file.
+ */
+package acm
+
+import com.excilys.ebi.gatling.core.Predef._
+import com.excilys.ebi.gatling.http.Predef._
+import com.excilys.ebi.gatling.core.session.Session
+import com.excilys.ebi.gatling.core.session.EvaluatableString
+import java.util.UUID._
+import com.excilys.ebi.gatling.core.action.builder.ActionBuilder
+
+/**
+ * Reusable ACM api calls
+ */
+object AcmApi {
+ val PermissionSet = "permission_set"
+ val ObjectId = "acm_object_id"
+ val GroupId = "acm_group_id"
+
+ val acmUser: EvaluatableString = s => Config.acm_user
+ val acmPassword: EvaluatableString = s => Config.acm_password
+
+ def createRandomPermissionSet(size: Int) =
+ http("Create %s Permission Set".format(size))
+ .post("/permission_sets")
+ .basicAuth(acmUser, acmPassword)
+ .body(genPermissions(size))
+ .asJSON()
+ .check(status.is(200), jsonPath("/name").saveAs(PermissionSet))
+
+ private def genPermissions(n: Int)(s: Session): String = {
+ val name = "perm_set_%s".format(randomUUID())
+ """{"name": "%s", "permissions": [%s]}""".format(name, formatSeq((1 to n) map (_ => "permission_%s".format(randomUUID()))))
+ }
+
+ def createPermissionSet(name: String, permissions: Seq[String], expectedStatus: Int = 200) =
+ http("Create Permission Set")
+ .post("/permission_sets")
+ .basicAuth(acmUser, acmPassword)
+ .body("""{"name": "%s", "permissions": [%s]}""".format(name, formatSeq(permissions)))
+ .asJSON()
+ .check(status.is(expectedStatus))
+
+ def getPermissionSet(name: String, expectedStatus: Int = 200) =
+ http("Get Permission Set")
+ .get("/permission_sets/%s".format(name))
+ .basicAuth(acmUser, acmPassword)
+ .check(status.is(expectedStatus))
+
+ def updatePermissionSet(name: String, permissions: Seq[String]) =
+ http("Update Permission Set")
+ .put("/permission_sets/%s".format(name))
+ .basicAuth(acmUser, acmPassword)
+ .body("""{"name": "%s", "permissions": [%s]}""".format(name, formatSeq(permissions)))
+ .asJSON()
+ .check(status.is(200))
+
+ def deletePermissionSet(name: String) =
+ http("Delete Permission Set")
+ .delete("/permission_sets/%s".format(name))
+ .basicAuth(acmUser, acmPassword)
+ .check(status.is(200))
+
+ def createUser(id: String) =
+ http("Create User")
+ .post("/users/%s".format(id))
+ .basicAuth(acmUser, acmPassword)
+ .check(status.is(200))
+
+ def getUser(id: String) =
+ http("Get User")
+ .get("/users/%s".format(id))
+ .basicAuth(acmUser, acmPassword)
+ .check(status.is(200))
+
+ def createObject(permissionSets: Seq[String], acl: Map[String, Seq[String]]) =
+ http("Create ACM Object")
+ .post("/objects")
+ .basicAuth(acmUser, acmPassword)
+ .body("""{"permission_sets": [%s], "acl": {%s} }""".format(formatSeq(permissionSets), formatAcl(acl)))
+ .asJSON()
+ .check(status.is(200), jsonPath("/id").saveAs(ObjectId))
+
+ def getObject(id: String) =
+ http("Get ACM Object")
+ .get("/objects/%s".format(id))
+ .basicAuth(acmUser, acmPassword)
+ .check(status.is(200))
+
+ def createGroup(id: Option[String], members: Seq[String]): ActionBuilder =
+ http("Create Group")
+ .post(id match {
+ case Some(s) => "/groups/%s".format(s)
+ case None => "/groups"
+ })
+ .body("""{"members": [%s]}""".format(formatSeq(members)))
+ .basicAuth(acmUser, acmPassword)
+ .check(status.is(200), jsonPath("/id").saveAs(GroupId))
+
+ def getGroup(id: String) =
+ http("Get Group")
+ .get("/groups/%s".format(id))
+ .basicAuth(acmUser, acmPassword)
+ .check(status.is(200))
+
+ private def formatSeq(strings: Seq[String]) = strings.mkString("\"", "\",\"", "\"")
+
+ private def formatAcl(acl: Map[String, Seq[String]]) =
+ acl map {
+ case (perm, users) => """ "%s": [%s] """.format(perm, formatSeq(users))
+ } mkString (",")
+
+}
View
31 gatling/src/main/scala/acm/Config.scala
@@ -0,0 +1,31 @@
+/**
+ * Cloud Foundry 2012.02.03 Beta
+ * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved.
+ *
+ * This product is licensed to you under the Apache License, Version 2.0 (the "License").
+ * You may not use this product except in compliance with the License.
+ *
+ * This product includes a number of subcomponents with
+ * separate copyright notices and license terms. Your use of these
+ * subcomponents is subject to the terms and conditions of the
+ * subcomponent's license, as noted in the LICENSE file.
+ */
+package acm
+
+
+import com.excilys.ebi.gatling.http.Predef.httpConfig
+
+/**
+ * Basic configuration for the ACM.
+ *
+ * Edit `urlBase` or set GATLING_ACM_BASE env variable to run against a different URL
+ */
+object Config {
+ val urlBase = sys.env.getOrElse("GATLING_ACM_BASE", "http://localhost:9090")
+
+ val acm_user = "acm_user"
+ val acm_password = "acm_password"
+
+ def acmHttpConfig = httpConfig.baseURL(urlBase)
+
+}

0 comments on commit 1b03bde

Please sign in to comment.
Something went wrong with that request. Please try again.