Merge changes from topics "e2e-plugin-props", "e2e-project-names" into stable-2.16

* changes:
  e2e-tests: Add support for automated project names
  e2e-tests: Support non-core JAVA_OPTS overriding
diff --git a/Documentation/dev-e2e-tests.txt b/Documentation/dev-e2e-tests.txt
index 56668c7..f45e9e0 100644
--- a/Documentation/dev-e2e-tests.txt
+++ b/Documentation/dev-e2e-tests.txt
@@ -110,11 +110,11 @@
 ----
 [
   {
-    "url": "ssh://admin@HOSTNAME:SSH_PORT/loadtest-repo",
+    "url": "ssh://admin@HOSTNAME:SSH_PORT/_PROJECT",
     "cmd": "clone"
   },
   {
-    "url": "http://HOSTNAME:HTTP_PORT/loadtest-repo",
+    "url": "http://HOSTNAME:HTTP_PORT/_PROJECT",
     "cmd": "clone"
   }
 ]
@@ -154,7 +154,18 @@
 
 Above, the properties can be set with values matching specific deployment topologies under test.
 The example values shown above are the currently coded default ones. The framework could support
-differing or more properties over time. Plugin (non-core) scenarios may do so just as well.
+differing or more properties over time.
+
+Plugin or otherwise non-core scenarios may do so just as well. The core java package
+`com.google.gerrit.scenarios` from the example above has to be replaced with the one under which
+those scenario classes are. Such extending scenarios can also add extension-specific properties.
+Early examples of this can be found in the Gerrit
+`link:https://gerrit.googlesource.com/plugins/high-availability[high-availability]` and
+`link:https://gerrit.googlesource.com/plugins/multi-site[multi-site]` plugins test code.
+
+Further above, the `_PROJECT` keyword is prefixed with an underscore, which means that its value
+gets automatically generated by the scenario. Any property setting for it is therefore not
+applicable. Its usage differs from the non-prefixed `PROJECT` keyword, in that sense.
 
 == How to run tests
 
diff --git a/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/CloneUsingBothProtocols.json b/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/CloneUsingBothProtocols.json
index 1125687..2389124 100644
--- a/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/CloneUsingBothProtocols.json
+++ b/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/CloneUsingBothProtocols.json
@@ -1,10 +1,10 @@
 [
   {
-    "url": "ssh://admin@HOSTNAME:SSH_PORT/loadtest-repo",
+    "url": "ssh://admin@HOSTNAME:SSH_PORT/_PROJECT",
     "cmd": "clone"
   },
   {
-    "url": "http://HOSTNAME:HTTP_PORT/loadtest-repo",
+    "url": "http://HOSTNAME:HTTP_PORT/_PROJECT",
     "cmd": "clone"
   }
 ]
diff --git a/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/CreateProject.json b/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/CreateProject.json
index f1a38ae..40e5a45 100644
--- a/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/CreateProject.json
+++ b/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/CreateProject.json
@@ -1,5 +1,5 @@
 [
   {
-    "url": "http://HOSTNAME:HTTP_PORT/a/projects/loadtest-repo"
+    "url": "http://HOSTNAME:HTTP_PORT/a/projects/PROJECT"
   }
 ]
diff --git a/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/DeleteProject.json b/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/DeleteProject.json
index e5167b5..7cc8293 100644
--- a/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/DeleteProject.json
+++ b/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/DeleteProject.json
@@ -1,5 +1,5 @@
 [
   {
-    "url": "http://HOSTNAME:HTTP_PORT/a/projects/loadtest-repo/delete-project~delete"
+    "url": "http://HOSTNAME:HTTP_PORT/a/projects/PROJECT/delete-project~delete"
   }
 ]
diff --git a/e2e-tests/src/test/scala/com/google/gerrit/scenarios/CloneUsingBothProtocols.scala b/e2e-tests/src/test/scala/com/google/gerrit/scenarios/CloneUsingBothProtocols.scala
index 182ac48..86a336d 100644
--- a/e2e-tests/src/test/scala/com/google/gerrit/scenarios/CloneUsingBothProtocols.scala
+++ b/e2e-tests/src/test/scala/com/google/gerrit/scenarios/CloneUsingBothProtocols.scala
@@ -22,13 +22,18 @@
 
 class CloneUsingBothProtocols extends GitSimulation {
   private val data: FileBasedFeederBuilder[Any]#F#F = jsonFile(resource).convert(url).queue
+  private val default: String = name
+
+  override def replaceOverride(in: String): String = {
+    replaceKeyWith("_project", default, in)
+  }
 
   private val test: ScenarioBuilder = scenario(name)
       .feed(data)
       .exec(gitRequest)
 
-  private val createProject = new CreateProject
-  private val deleteProject = new DeleteProject
+  private val createProject = new CreateProject(default)
+  private val deleteProject = new DeleteProject(default)
 
   setUp(
     createProject.test.inject(
diff --git a/e2e-tests/src/test/scala/com/google/gerrit/scenarios/CreateProject.scala b/e2e-tests/src/test/scala/com/google/gerrit/scenarios/CreateProject.scala
index 13d3519..931ff02 100644
--- a/e2e-tests/src/test/scala/com/google/gerrit/scenarios/CreateProject.scala
+++ b/e2e-tests/src/test/scala/com/google/gerrit/scenarios/CreateProject.scala
@@ -18,9 +18,14 @@
 import io.gatling.core.feeder.FileBasedFeederBuilder
 import io.gatling.core.structure.ScenarioBuilder
 
-class CreateProject extends GerritSimulation {
+class CreateProject extends ProjectSimulation {
   private val data: FileBasedFeederBuilder[Any]#F#F = jsonFile(resource).convert(url).queue
 
+  def this(default: String) {
+    this()
+    this.default = default
+  }
+
   val test: ScenarioBuilder = scenario(name)
       .feed(data)
       .exec(httpRequest)
diff --git a/e2e-tests/src/test/scala/com/google/gerrit/scenarios/DeleteProject.scala b/e2e-tests/src/test/scala/com/google/gerrit/scenarios/DeleteProject.scala
index 70b901d..bf13f83 100644
--- a/e2e-tests/src/test/scala/com/google/gerrit/scenarios/DeleteProject.scala
+++ b/e2e-tests/src/test/scala/com/google/gerrit/scenarios/DeleteProject.scala
@@ -18,9 +18,14 @@
 import io.gatling.core.feeder.FileBasedFeederBuilder
 import io.gatling.core.structure.ScenarioBuilder
 
-class DeleteProject extends GerritSimulation {
+class DeleteProject extends ProjectSimulation {
   private val data: FileBasedFeederBuilder[Any]#F#F = jsonFile(resource).convert(url).queue
 
+  def this(default: String) {
+    this()
+    this.default = default
+  }
+
   val test: ScenarioBuilder = scenario(name)
       .feed(data)
       .exec(httpRequest)
diff --git a/e2e-tests/src/test/scala/com/google/gerrit/scenarios/GerritSimulation.scala b/e2e-tests/src/test/scala/com/google/gerrit/scenarios/GerritSimulation.scala
index a159977..d47af01 100644
--- a/e2e-tests/src/test/scala/com/google/gerrit/scenarios/GerritSimulation.scala
+++ b/e2e-tests/src/test/scala/com/google/gerrit/scenarios/GerritSimulation.scala
@@ -35,13 +35,13 @@
 
   protected val url: PartialFunction[(String, Any), Any] = {
     case ("url", url) =>
-      var in = replaceProperty("hostname", "localhost", url.toString)
+      var in = replaceOverride(url.toString)
+      in = replaceProperty("hostname", "localhost", in)
       in = replaceProperty("http_port", 8080, in)
       replaceProperty("ssh_port", 29418, in)
   }
 
-  private def replaceProperty(term: String, default: Any, in: String): String = {
-    val key: String = term.toUpperCase
+  protected def replaceProperty(term: String, default: Any, in: String): String = {
     val property = pack + "." + term
     var value = default
     default match {
@@ -53,6 +53,26 @@
       case _: Integer =>
         value = Integer.getInteger(property, default.asInstanceOf[Integer])
     }
+    replaceKeyWith(term, value, in)
+  }
+
+  protected def replaceKeyWith(term: String, value: Any, in: String): String = {
+    val key: String = term.toUpperCase
     in.replaceAllLiterally(key, value.toString)
   }
+
+  /**
+   * Meant to be optionally overridden by plugins or other extensions.
+   * Such potential overriding methods, such as the example below,
+   * typically return resulting call(s) to [[replaceProperty()]].
+   * This is usually similar to how [[url]] is implemented above.
+   *
+   * <pre>
+   * override def replaceOverride(in: String): String = {
+   * // Simple e.g., replaceProperty("EXTENSION_JSON_KEY", "default", in)
+   * </pre>
+   */
+  def replaceOverride(in: String): String = {
+    in
+  }
 }
diff --git a/e2e-tests/src/test/scala/com/google/gerrit/scenarios/ProjectSimulation.scala b/e2e-tests/src/test/scala/com/google/gerrit/scenarios/ProjectSimulation.scala
new file mode 100644
index 0000000..141c3cf
--- /dev/null
+++ b/e2e-tests/src/test/scala/com/google/gerrit/scenarios/ProjectSimulation.scala
@@ -0,0 +1,23 @@
+// 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.google.gerrit.scenarios
+
+class ProjectSimulation extends GerritSimulation {
+  protected var default: String = "project"
+
+  override def replaceOverride(in: String): String = {
+    replaceProperty("project", default, in)
+  }
+}