Add {Create|Delete}ChangeUsingMultiGerrits scenarios

Reuse core's GerritSimulation ability to now support optional http
request bodies. Start using the new 'project' and 'number' request keys,
which can also be set either automatically or environmentally ([1]).

For CreateChangeUsingMultiGerrit to be able to create changes, rely on
that body support to now create projects with create_empty_commit
enabled.

Have CreateChangeUsingMultiGerrit use the added
DeleteChangeUsingMultiGerrit1 to automatically delete created changes.
The test project gets automatically created and deleted by the scenario,
as usual now.

[1] https://gerrit-review.googlesource.com/Documentation/dev-e2e-tests.html#_environment_properties

Change-Id: I79a00043024f558d5fffd36e81665c17974aa258
diff --git a/src/test/resources/com/googlesource/gerrit/plugins/multisite/scenarios/CreateChangeUsingMultiGerrit-body.json b/src/test/resources/com/googlesource/gerrit/plugins/multisite/scenarios/CreateChangeUsingMultiGerrit-body.json
new file mode 100644
index 0000000..23bf26c
--- /dev/null
+++ b/src/test/resources/com/googlesource/gerrit/plugins/multisite/scenarios/CreateChangeUsingMultiGerrit-body.json
@@ -0,0 +1,5 @@
+{
+  "project": "${project}",
+  "branch": "master",
+  "subject": "Change"
+}
diff --git a/src/test/resources/com/googlesource/gerrit/plugins/multisite/scenarios/CreateChangeUsingMultiGerrit.json b/src/test/resources/com/googlesource/gerrit/plugins/multisite/scenarios/CreateChangeUsingMultiGerrit.json
new file mode 100644
index 0000000..c267ab3
--- /dev/null
+++ b/src/test/resources/com/googlesource/gerrit/plugins/multisite/scenarios/CreateChangeUsingMultiGerrit.json
@@ -0,0 +1,6 @@
+[
+  {
+    "url": "http://HOSTNAME:HTTP_PORT/a/changes/",
+    "project": "_PROJECT"
+  }
+]
diff --git a/src/test/resources/com/googlesource/gerrit/plugins/multisite/scenarios/CreateProjectUsingMultiGerrit-body.json b/src/test/resources/com/googlesource/gerrit/plugins/multisite/scenarios/CreateProjectUsingMultiGerrit-body.json
new file mode 100644
index 0000000..bcf4708
--- /dev/null
+++ b/src/test/resources/com/googlesource/gerrit/plugins/multisite/scenarios/CreateProjectUsingMultiGerrit-body.json
@@ -0,0 +1,3 @@
+{
+  "create_empty_commit": "true"
+}
diff --git a/src/test/resources/com/googlesource/gerrit/plugins/multisite/scenarios/DeleteChangeUsingMultiGerrit1.json b/src/test/resources/com/googlesource/gerrit/plugins/multisite/scenarios/DeleteChangeUsingMultiGerrit1.json
new file mode 100644
index 0000000..1190bbc
--- /dev/null
+++ b/src/test/resources/com/googlesource/gerrit/plugins/multisite/scenarios/DeleteChangeUsingMultiGerrit1.json
@@ -0,0 +1,6 @@
+[
+  {
+    "url": "http://HOSTNAME:HTTP_PORT1/a/changes/",
+    "number": "_NUMBER"
+  }
+]
diff --git a/src/test/scala/com/googlesource/gerrit/plugins/multisite/scenarios/CloneUsingMultiGerrit1.scala b/src/test/scala/com/googlesource/gerrit/plugins/multisite/scenarios/CloneUsingMultiGerrit1.scala
index 9297907..e55ff2f 100644
--- a/src/test/scala/com/googlesource/gerrit/plugins/multisite/scenarios/CloneUsingMultiGerrit1.scala
+++ b/src/test/scala/com/googlesource/gerrit/plugins/multisite/scenarios/CloneUsingMultiGerrit1.scala
@@ -22,7 +22,7 @@
 import scala.concurrent.duration._
 
 class CloneUsingMultiGerrit1 extends GitSimulation {
-  private val data: FileBasedFeederBuilder[Any]#F#F = jsonFile(resource).convert(url).queue
+  private val data: FileBasedFeederBuilder[Any]#F#F = jsonFile(resource).convert(keys).queue
   private var default: String = name
 
   def this(default: String) {
diff --git a/src/test/scala/com/googlesource/gerrit/plugins/multisite/scenarios/CreateChangeUsingMultiGerrit.scala b/src/test/scala/com/googlesource/gerrit/plugins/multisite/scenarios/CreateChangeUsingMultiGerrit.scala
new file mode 100644
index 0000000..d2b6c4c
--- /dev/null
+++ b/src/test/scala/com/googlesource/gerrit/plugins/multisite/scenarios/CreateChangeUsingMultiGerrit.scala
@@ -0,0 +1,61 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.googlesource.gerrit.plugins.multisite.scenarios
+
+import com.google.gerrit.scenarios.GerritSimulation
+import io.gatling.core.Predef.{atOnceUsers, _}
+import io.gatling.core.feeder.FileBasedFeederBuilder
+import io.gatling.core.structure.ScenarioBuilder
+import io.gatling.http.Predef._
+
+import scala.concurrent.duration._
+
+class CreateChangeUsingMultiGerrit extends GerritSimulation {
+  private val data: FileBasedFeederBuilder[Any]#F#F = jsonFile(resource).convert(keys).queue
+  private val default: String = name
+  private val numberKey = "_number"
+
+  val test: ScenarioBuilder = scenario(unique)
+    .feed(data)
+    .exec(httpRequest
+      .body(ElFileBody(body)).asJson
+      .check(regex("\"" + numberKey + "\":(\\d+),").saveAs(numberKey)))
+    .exec(session => {
+      deleteChange.number = Some(session(numberKey).as[Int])
+      session
+    })
+
+  private val createProject = new CreateProjectUsingMultiGerrit(default)
+  private val deleteProject = new DeleteProjectUsingMultiGerrit(default)
+  private val deleteChange = new DeleteChangeUsingMultiGerrit1
+
+  setUp(
+    createProject.test.inject(
+      atOnceUsers(1)
+    ),
+    test.inject(
+      nothingFor(21 seconds),
+      atOnceUsers(1)
+    ),
+    deleteChange.test.inject(
+      nothingFor(40 seconds),
+      atOnceUsers(1)
+    ),
+    deleteProject.test.inject(
+      nothingFor(60 seconds),
+      atOnceUsers(1)
+    ),
+  ).protocols(httpProtocol)
+}
diff --git a/src/test/scala/com/googlesource/gerrit/plugins/multisite/scenarios/CreateProjectUsingMultiGerrit.scala b/src/test/scala/com/googlesource/gerrit/plugins/multisite/scenarios/CreateProjectUsingMultiGerrit.scala
index 721d581..857b031 100644
--- a/src/test/scala/com/googlesource/gerrit/plugins/multisite/scenarios/CreateProjectUsingMultiGerrit.scala
+++ b/src/test/scala/com/googlesource/gerrit/plugins/multisite/scenarios/CreateProjectUsingMultiGerrit.scala
@@ -20,7 +20,7 @@
 import io.gatling.core.structure.ScenarioBuilder
 
 class CreateProjectUsingMultiGerrit extends ProjectSimulation {
-  private val data: FileBasedFeederBuilder[Any]#F#F = jsonFile(resource).convert(url).queue
+  private val data: FileBasedFeederBuilder[Any]#F#F = jsonFile(resource).convert(keys).queue
 
   def this(default: String) {
     this()
@@ -29,7 +29,7 @@
 
   val test: ScenarioBuilder = scenario(unique)
     .feed(data)
-    .exec(httpRequest)
+    .exec(httpRequest.body(RawFileBody(body)).asJson)
 
   setUp(
     test.inject(
diff --git a/src/test/scala/com/googlesource/gerrit/plugins/multisite/scenarios/DeleteChangeUsingMultiGerrit1.scala b/src/test/scala/com/googlesource/gerrit/plugins/multisite/scenarios/DeleteChangeUsingMultiGerrit1.scala
new file mode 100644
index 0000000..9a139f6
--- /dev/null
+++ b/src/test/scala/com/googlesource/gerrit/plugins/multisite/scenarios/DeleteChangeUsingMultiGerrit1.scala
@@ -0,0 +1,47 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.googlesource.gerrit.plugins.multisite.scenarios
+
+import com.google.gerrit.scenarios.GerritSimulation
+import io.gatling.core.Predef.{atOnceUsers, _}
+import io.gatling.core.feeder.FileBasedFeederBuilder
+import io.gatling.core.structure.ScenarioBuilder
+import io.gatling.http.Predef.http
+
+class DeleteChangeUsingMultiGerrit1 extends GerritSimulation {
+  private val data: FileBasedFeederBuilder[Any]#F#F = jsonFile(resource).convert(keys).queue
+  var number: Option[Int] = None
+
+  override def replaceOverride(in: String): String = {
+    replaceProperty("http_port1", 8082, in)
+  }
+
+  val test: ScenarioBuilder = scenario(unique)
+    .feed(data)
+    .exec(session => {
+      if (number.nonEmpty) {
+        session.set("number", number.get)
+      } else {
+        session
+      }
+    })
+    .exec(http(unique).delete("${url}${number}"))
+
+  setUp(
+    test.inject(
+      atOnceUsers(1)
+    ),
+  ).protocols(httpProtocol)
+}
diff --git a/src/test/scala/com/googlesource/gerrit/plugins/multisite/scenarios/DeleteProjectUsingMultiGerrit.scala b/src/test/scala/com/googlesource/gerrit/plugins/multisite/scenarios/DeleteProjectUsingMultiGerrit.scala
index 674f1b3..71c21bb 100644
--- a/src/test/scala/com/googlesource/gerrit/plugins/multisite/scenarios/DeleteProjectUsingMultiGerrit.scala
+++ b/src/test/scala/com/googlesource/gerrit/plugins/multisite/scenarios/DeleteProjectUsingMultiGerrit.scala
@@ -20,7 +20,7 @@
 import io.gatling.core.structure.ScenarioBuilder
 
 class DeleteProjectUsingMultiGerrit extends ProjectSimulation {
-  private val data: FileBasedFeederBuilder[Any]#F#F = jsonFile(resource).convert(url).queue
+  private val data: FileBasedFeederBuilder[Any]#F#F = jsonFile(resource).convert(keys).queue
 
   def this(default: String) {
     this()