Merge branch 'stable-2.16' into stable-3.0

* stable-2.16:
  Upgrade bazlets to latest stable-2.16

Change-Id: Ic4215588deb0cebc23fe5a83c7c379d4a09926f5
diff --git a/BUILD b/BUILD
index 75f3820..bca433e 100644
--- a/BUILD
+++ b/BUILD
@@ -11,6 +11,7 @@
     "@aopalliance//jar",
     "@dbcp//jar",
     "@guava//jar",
+    "@guava-failureaccess//jar",
     "@guice//jar",
     "@guice-assistedinject//jar",
     "@javaewah//jar",
@@ -86,11 +87,8 @@
     exports = EXECUTOR_DEPS + PLUGIN_DEPS + PLUGIN_TEST_DEPS + [
         ":gc-conductor__plugin",
         ":gc-executor_lib",
-        "@byte-buddy//jar",
         "@duct_tape//jar",
         "@jna//jar",
-        "@mockito//jar",
-        "@objenesis//jar",
         "@testcontainers-database-commons//jar",
         "@testcontainers-jdbc//jar",
         "@testcontainers-postgres//jar",
diff --git a/WORKSPACE b/WORKSPACE
index b5e816f..f1c2c65 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -3,26 +3,15 @@
 load("//:bazlets.bzl", "load_bazlets")
 
 load_bazlets(
-    commit = "56c9f4ed6dbe3c88f793851c88389637f3714a5d",
+    commit = "7a9ae377b519934c87184cc05845663ed708b69c",
     #local_path = "/home/<user>/projects/bazlets",
 )
 
-# Snapshot Plugin API
-#load(
-#    "@com_googlesource_gerrit_bazlets//:gerrit_api_maven_local.bzl",
-#    "gerrit_api_maven_local",
-#)
-
-# Load snapshot Plugin API
-#gerrit_api_maven_local()
-
-# Release Plugin API
 load(
     "@com_googlesource_gerrit_bazlets//:gerrit_api.bzl",
     "gerrit_api",
 )
 
-# Load release Plugin API
 gerrit_api()
 
 load("//:external_plugin_deps.bzl", "external_plugin_deps")
diff --git a/external_plugin_deps.bzl b/external_plugin_deps.bzl
index 96504a2..746d014 100644
--- a/external_plugin_deps.bzl
+++ b/external_plugin_deps.bzl
@@ -2,42 +2,11 @@
 
 def external_plugin_deps():
     maven_jar(
-        name = "mockito",
-        artifact = "org.mockito:mockito-core:2.28.2",
-        sha1 = "91110215a8cb9b77a46e045ee758f77d79167cc0",
-        deps = [
-            "@byte-buddy//jar",
-            "@byte-buddy-agent//jar",
-            "@objenesis//jar",
-        ],
-    )
-
-    BYTE_BUDDY_VERSION = "1.9.10"
-
-    maven_jar(
-        name = "byte-buddy",
-        artifact = "net.bytebuddy:byte-buddy:" + BYTE_BUDDY_VERSION,
-        sha1 = "211a2b4d3df1eeef2a6cacf78d74a1f725e7a840",
-    )
-
-    maven_jar(
-        name = "byte-buddy-agent",
-        artifact = "net.bytebuddy:byte-buddy-agent:" + BYTE_BUDDY_VERSION,
-        sha1 = "9674aba5ee793e54b864952b001166848da0f26b",
-    )
-
-    maven_jar(
         name = "duct_tape",
         artifact = "org.rnorth.duct-tape:duct-tape:1.0.8",
         sha1 = "92edc22a9ab2f3e17c9bf700aaee377d50e8b530",
     )
 
-    maven_jar(
-        name = "objenesis",
-        artifact = "org.objenesis:objenesis:2.6",
-        sha1 = "639033469776fd37c08358c6b92a4761feb2af4b",
-    )
-
     SLF4J_VERS = "1.7.26"
 
     maven_jar(
@@ -91,23 +60,29 @@
     )
 
     maven_jar(
-        name = "guava",
-        artifact = "com.google.guava:guava:26.0-jre",
-        sha1 = "6a806eff209f36f635f943e16d97491f00f6bfab",
+        name = "guava-failureaccess",
+        artifact = "com.google.guava:failureaccess:1.0.1",
+        sha1 = "1dcf1de382a0bf95a3d8b0849546c88bac1292c9",
     )
 
-    GUICE_VERS = "4.2.1"
+    maven_jar(
+        name = "guava",
+        artifact = "com.google.guava:guava:27.0.1-jre",
+        sha1 = "bd41a290787b5301e63929676d792c507bbc00ae",
+    )
+
+    GUICE_VERS = "4.2.2"
 
     maven_jar(
         name = "guice",
         artifact = "com.google.inject:guice:" + GUICE_VERS,
-        sha1 = "f77dfd89318fe3ff293bafceaa75fbf66e4e4b10",
+        sha1 = "6dacbe18e5eaa7f6c9c36db33b42e7985e94ce77",
     )
 
     maven_jar(
         name = "guice-assistedinject",
         artifact = "com.google.inject.extensions:guice-assistedinject:" + GUICE_VERS,
-        sha1 = "d327e4aee7c96f08cd657c17da231a1f4a8999ac",
+        sha1 = "c33fb10080d58446f752b4fcfff8a5fabb80a449",
     )
 
     maven_jar(
@@ -125,8 +100,8 @@
     maven_jar(
         name = "jgit",
         artifact =
-            "org.eclipse.jgit:org.eclipse.jgit:5.1.12.201910011832-r",
-        sha1 = "62c60aa985aa8dcfa6ad7308d130c319a1d01073",
+            "org.eclipse.jgit:org.eclipse.jgit:5.3.6.201910020505-r",
+        sha1 = "0b9085bd16c630412bfa50bcc509dcedfbbe16d3",
     )
 
     maven_jar(
diff --git a/src/main/resources/Documentation/build.md b/src/main/resources/Documentation/build.md
index 3643444..24ec423 100644
--- a/src/main/resources/Documentation/build.md
+++ b/src/main/resources/Documentation/build.md
@@ -7,7 +7,7 @@
 * In Gerrit tree.
 
 Standalone build mode is recommended, as this mode doesn't require local Gerrit
-tree to exist.
+tree to exist. This plugin has a side component, gc-executor, to build as well.
 
 Successfully running some of the tests requires Docker,
 which are skipped if Docker is not available.
@@ -55,6 +55,7 @@
 
 to generate the required files and then import the project.
 
+## Building gc-executor
 
 To build the executor, issue the following command:
 
@@ -65,11 +66,21 @@
 The output is created in:
 
 ```
-  /bazel-bin/gc-executor_deploy.jar
+  bazel-bin/gc-executor_deploy.jar
 ```
 
 This jar should be renamed to gc-executor.jar before deployment.
 
+Once the executor is built, the resulting postgresql jar file like below
+should be manually copied over to the gerrit site /lib folder; on macOS:
+
+```
+  bazel-out/darwin-fastbuild/bin/gc-executor.runfiles/gc_executor/external/postgresql/jar/postgresql-42.2.5.jar
+```
+
+That file has to be in accordance with potentially existing database driver
+files under site's /lib, for proper account_patch_reviews support.
+
 ## Build in Gerrit tree
 
 Clone or link this plugin to the plugins directory of Gerrit's
diff --git a/src/test/README.md b/src/test/README.md
index 885522e..858ef4c 100644
--- a/src/test/README.md
+++ b/src/test/README.md
@@ -6,7 +6,7 @@
 ```
 
 To start using the files under these directories above, consider the
-[instructions](https://gerrit-documentation.storage.googleapis.com/Documentation/2.16.19/dev-e2e-tests.html)
+[instructions](https://gerrit-documentation.storage.googleapis.com/Documentation/3.0.9/dev-e2e-tests.html)
 on how to use Gerrit core's Gatling framework. These are about running
 non-core test scenarios such as this plugin one below:
 
diff --git a/src/test/resources/com/ericsson/gerrit/plugins/gcconductor/scenarios/CheckProjectStatisticsAfterGc.json b/src/test/resources/com/ericsson/gerrit/plugins/gcconductor/scenarios/CheckProjectStatisticsUpToGc.json
similarity index 100%
rename from src/test/resources/com/ericsson/gerrit/plugins/gcconductor/scenarios/CheckProjectStatisticsAfterGc.json
rename to src/test/resources/com/ericsson/gerrit/plugins/gcconductor/scenarios/CheckProjectStatisticsUpToGc.json
diff --git a/src/test/resources/com/ericsson/gerrit/plugins/gcconductor/scenarios/CreateChangesTriggeringGc.json b/src/test/resources/com/ericsson/gerrit/plugins/gcconductor/scenarios/CreateChangesTriggeringGc.json
index c267ab3..b4ee549 100644
--- a/src/test/resources/com/ericsson/gerrit/plugins/gcconductor/scenarios/CreateChangesTriggeringGc.json
+++ b/src/test/resources/com/ericsson/gerrit/plugins/gcconductor/scenarios/CreateChangesTriggeringGc.json
@@ -1,6 +1,6 @@
 [
   {
     "url": "http://HOSTNAME:HTTP_PORT/a/changes/",
-    "project": "_PROJECT"
+    "project": "PROJECT"
   }
 ]
diff --git a/src/test/scala/com/ericsson/gerrit/plugins/gcconductor/scenarios/CheckProjectStatisticsAfterGc.scala b/src/test/scala/com/ericsson/gerrit/plugins/gcconductor/scenarios/CheckProjectStatisticsUpToGc.scala
similarity index 77%
rename from src/test/scala/com/ericsson/gerrit/plugins/gcconductor/scenarios/CheckProjectStatisticsAfterGc.scala
rename to src/test/scala/com/ericsson/gerrit/plugins/gcconductor/scenarios/CheckProjectStatisticsUpToGc.scala
index fa43e22..2487a85 100644
--- a/src/test/scala/com/ericsson/gerrit/plugins/gcconductor/scenarios/CheckProjectStatisticsAfterGc.scala
+++ b/src/test/scala/com/ericsson/gerrit/plugins/gcconductor/scenarios/CheckProjectStatisticsUpToGc.scala
@@ -20,8 +20,14 @@
 import io.gatling.core.structure.ScenarioBuilder
 import io.gatling.http.Predef._
 
-class CheckProjectStatisticsAfterGc extends ProjectSimulation {
-  private val data: FeederBuilder = jsonFile(resource).convert(keys).queue
+import scala.concurrent.duration._
+
+class CheckProjectStatisticsUpToGc extends ProjectSimulation {
+  private val data: FeederBuilder = jsonFile(resource).convert(keys).circular
+  lazy val MaxSecondsForGcToComplete = 20
+  val ChecksPerSecond = 4
+
+  override def relativeRuntimeWeight: Int = MaxSecondsForGcToComplete / SecondsPerWeightUnit
 
   def this(default: String) {
     this()
@@ -36,6 +42,6 @@
 
   setUp(
     test.inject(
-      atOnceUsers(1)
+      constantUsersPerSec(ChecksPerSecond) during (MaxSecondsForGcToComplete seconds),
     )).protocols(httpProtocol)
 }
diff --git a/src/test/scala/com/ericsson/gerrit/plugins/gcconductor/scenarios/CreateChangesTriggeringGc.scala b/src/test/scala/com/ericsson/gerrit/plugins/gcconductor/scenarios/CreateChangesTriggeringGc.scala
index a61b376..014e17f 100644
--- a/src/test/scala/com/ericsson/gerrit/plugins/gcconductor/scenarios/CreateChangesTriggeringGc.scala
+++ b/src/test/scala/com/ericsson/gerrit/plugins/gcconductor/scenarios/CreateChangesTriggeringGc.scala
@@ -22,28 +22,31 @@
 
 import scala.concurrent.duration._
 
-class CreateChangesTriggeringGc extends GerritSimulation {
+class CreateChangesTriggeringGc extends ProjectSimulation {
   private val data: FeederBuilder = jsonFile(resource).convert(keys).circular
-  private val default: String = name
   private val numberKey = "_number"
 
-  private lazy val DefaultSecondsToNextEvaluation = 60
-  private lazy val DefaultSecondsToNextGcDequeue = 60
+  lazy val DefaultSecondsToNextEvaluation = 60
   private lazy val DefaultLooseObjectsToEnqueueGc = 400
   private lazy val LooseObjectsPerChange = 2
-  private lazy val ChangesPerSecond = 4
-  private val ChangesForLastEvaluation = 1
+  private lazy val ChangesMultiplier = 8
+  lazy val changesPerSecond: Int = 4 * ChangesMultiplier
+  val ChangesForLastEvaluation: Int = single
 
-  private lazy val secondsForLastEvaluation = SecondsPerWeightUnit * 2
-  private lazy val secondsForLastGcExecution = secondsForLastEvaluation * 2
-  private lazy val changesToEnqueueGc = DefaultLooseObjectsToEnqueueGc / LooseObjectsPerChange
-  private lazy val secondsToChanges = changesToEnqueueGc / ChangesPerSecond
+  lazy val secondsForLastEvaluation: Int = SecondsPerWeightUnit
+  private lazy val changesToEnqueueGc = DefaultLooseObjectsToEnqueueGc * ChangesMultiplier / LooseObjectsPerChange
+  lazy val secondsToChanges: Int = changesToEnqueueGc / changesPerSecond
   private lazy val maxSecondsToEnqueueGc = secondsToChanges + DefaultSecondsToNextEvaluation + secondsForLastEvaluation
-  private lazy val maxSecondsToExecuteGc = maxSecondsToEnqueueGc + DefaultSecondsToNextGcDequeue + secondsForLastGcExecution
 
-  override def relativeRuntimeWeight: Int = maxSecondsToExecuteGc / SecondsPerWeightUnit
+  override def relativeRuntimeWeight: Int = maxSecondsToEnqueueGc / SecondsPerWeightUnit
 
-  private val test: ScenarioBuilder = scenario(unique)
+  def this(default: String, deleteChanges: DeleteChangesAfterGc) {
+    this()
+    this.default = default
+    this.deleteChanges = deleteChanges
+  }
+
+  val test: ScenarioBuilder = scenario(unique)
     .feed(data)
     .exec(httpRequest
       .body(ElFileBody(body)).asJson
@@ -53,36 +56,26 @@
       session
     })
 
-  private val createProject = new CreateProject(default)
-  private val checkStatsAfterGc = new CheckProjectStatisticsAfterGc(default)
-  private val deleteChanges = new DeleteChangesAfterGc
-  private val deleteProject = new DeleteProject(default)
+  private val checkStatsUpToGc = new CheckProjectStatisticsUpToGc(default)
+  private var deleteChanges = new DeleteChangesAfterGc
 
   setUp(
-    createProject.test.inject(
-      nothingFor(stepWaitTime(createProject) seconds),
-      atOnceUsers(1)
-    ),
     test.inject(
       nothingFor(stepWaitTime(this) seconds),
-      constantUsersPerSec(ChangesPerSecond) during (secondsToChanges seconds),
+      constantUsersPerSec(changesPerSecond) during (secondsToChanges seconds),
       nothingFor(DefaultSecondsToNextEvaluation seconds),
       nothingFor(secondsForLastEvaluation / 2 seconds),
       atOnceUsers(ChangesForLastEvaluation),
       nothingFor(secondsForLastEvaluation / 2 seconds)
     ),
-    checkStatsAfterGc.test.inject(
-      nothingFor(stepWaitTime(checkStatsAfterGc) seconds),
-      atOnceUsers(1)
+    checkStatsUpToGc.test.inject(
+      nothingFor(stepWaitTime(checkStatsUpToGc) seconds),
+      constantUsersPerSec(checkStatsUpToGc.ChecksPerSecond) during (checkStatsUpToGc.MaxSecondsForGcToComplete seconds)
     ),
     deleteChanges.test.inject(
       nothingFor(stepWaitTime(deleteChanges) seconds),
-      constantUsersPerSec(ChangesPerSecond) during (secondsToChanges seconds),
+      constantUsersPerSec(changesPerSecond) during (secondsToChanges seconds),
       atOnceUsers(ChangesForLastEvaluation)
     ),
-    deleteProject.test.inject(
-      nothingFor(stepWaitTime(deleteProject) seconds),
-      atOnceUsers(1)
-    ),
   ).protocols(httpProtocol)
 }
diff --git a/src/test/scala/com/ericsson/gerrit/plugins/gcconductor/scenarios/CreateChangesTriggeringGcWithProject.scala b/src/test/scala/com/ericsson/gerrit/plugins/gcconductor/scenarios/CreateChangesTriggeringGcWithProject.scala
new file mode 100644
index 0000000..d248703
--- /dev/null
+++ b/src/test/scala/com/ericsson/gerrit/plugins/gcconductor/scenarios/CreateChangesTriggeringGcWithProject.scala
@@ -0,0 +1,57 @@
+// 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.ericsson.gerrit.plugins.gcconductor.scenarios
+
+import com.google.gerrit.scenarios._
+import io.gatling.core.Predef.{atOnceUsers, nothingFor, _}
+
+import scala.concurrent.duration._
+
+class CreateChangesTriggeringGcWithProject extends GerritSimulation {
+  private val default: String = name
+
+  private val createProject = new CreateProject(default)
+  private val deleteChanges = new DeleteChangesAfterGc
+  private val createChanges = new CreateChangesTriggeringGc(default, deleteChanges)
+  private val checkStatsUpToGc = new CheckProjectStatisticsUpToGc(default)
+  private val deleteProject = new DeleteProject(default)
+
+  setUp(
+    createProject.test.inject(
+      nothingFor(stepWaitTime(createProject) seconds),
+      atOnceUsers(single)
+    ),
+    createChanges.test.inject(
+      nothingFor(stepWaitTime(createChanges) seconds),
+      constantUsersPerSec(createChanges.changesPerSecond) during (createChanges.secondsToChanges seconds),
+      nothingFor(createChanges.DefaultSecondsToNextEvaluation seconds),
+      nothingFor(createChanges.secondsForLastEvaluation / 2 seconds),
+      atOnceUsers(createChanges.ChangesForLastEvaluation)
+    ),
+    checkStatsUpToGc.test.inject(
+      nothingFor(stepWaitTime(checkStatsUpToGc) seconds),
+      constantUsersPerSec(checkStatsUpToGc.ChecksPerSecond) during (checkStatsUpToGc.MaxSecondsForGcToComplete seconds)
+    ),
+    deleteChanges.test.inject(
+      nothingFor(stepWaitTime(deleteChanges) seconds),
+      constantUsersPerSec(createChanges.changesPerSecond) during (createChanges.secondsToChanges seconds),
+      atOnceUsers(createChanges.ChangesForLastEvaluation)
+    ),
+    deleteProject.test.inject(
+      nothingFor(stepWaitTime(deleteProject) seconds),
+      atOnceUsers(single)
+    ),
+  ).protocols(httpProtocol)
+}