Merge branch 'stable-2.15' into stable-2.16
* stable-2.15:
Update log4j2 version to 2.17.0
Update log4j2 version to 2.16.0 to fix CVE-2021-44228
Change-Id: Id6f7e2cefd185136464180f685bbbe6d6a0e4cd4
diff --git a/.bazelversion b/.bazelversion
index 9084fa2..fd2a018 100644
--- a/.bazelversion
+++ b/.bazelversion
@@ -1 +1 @@
-1.1.0
+3.1.0
diff --git a/.gitignore b/.gitignore
index 78857a0..4e7cb7d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,12 @@
+# LC_COLLATE=C sort
+/.apt_generated/
/.classpath
/.primary_build_tool
/.project
/.settings/
/bazel-*
+/bin/gc-executor-pid
/eclipse-out/
-/.apt_generated/
+/gc-executor.jar
+/gc.config
+/startup.log
diff --git a/BUILD b/BUILD
index cb02518..5ddfab4 100644
--- a/BUILD
+++ b/BUILD
@@ -7,26 +7,23 @@
"gerrit_plugin",
)
-CONDUCTOR_DEPS = [
- "@postgresql//jar",
+EXECUTOR_DEPS = [
+ "@aopalliance//jar",
"@dbcp//jar",
- "@pool//jar",
-]
-
-EXECUTOR_DEPS = CONDUCTOR_DEPS + [
- "@jgit//jar",
- "@javaewah//jar",
"@guava//jar",
"@guice//jar",
"@guice-assistedinject//jar",
+ "@javaewah//jar",
"@javax_inject//jar",
- "@aopalliance//jar",
- "@slf4j-api//jar",
- "@slf4j-ext//jar",
- "@log4j-slf4j-impl//jar",
+ "@jgit//jar",
"@log4j-api//jar",
"@log4j-core//jar",
+ "@log4j-slf4j-impl//jar",
+ "@pool//jar",
+ "@postgresql//jar",
"@retry//jar",
+ "@slf4j-api//jar",
+ "@slf4j-ext//jar",
]
gerrit_plugin(
@@ -47,7 +44,6 @@
["src/main/resources/**/*"],
exclude = ["src/main/resources/log4j2.xml"],
),
- deps = CONDUCTOR_DEPS,
)
java_library(
@@ -91,7 +87,10 @@
":gc-conductor__plugin",
":gc-executor_lib",
"@byte-buddy//jar",
+ "@docker-java-api//jar",
+ "@docker-java-transport//jar",
"@duct_tape//jar",
+ "@jackson-annotations//jar",
"@jna//jar",
"@mockito//jar",
"@objenesis//jar",
diff --git a/WORKSPACE b/WORKSPACE
index e9bd838..0c20233 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -3,7 +3,7 @@
load("//:bazlets.bzl", "load_bazlets")
load_bazlets(
- commit = "9af263722b7eafe99af079d6ef7cf1de23e6f8d7",
+ commit = "6c39deb06f58bb62162ccb6865964f531739f512",
#local_path = "/home/<user>/projects/bazlets",
)
diff --git a/external_plugin_deps.bzl b/external_plugin_deps.bzl
index 7d9fdd6..db6208b 100644
--- a/external_plugin_deps.bzl
+++ b/external_plugin_deps.bzl
@@ -28,8 +28,8 @@
maven_jar(
name = "duct_tape",
- artifact = "org.rnorth.duct-tape:duct-tape:1.0.7",
- sha1 = "a26b5d90d88c91321dc7a3734ea72d2fc019ebb6",
+ artifact = "org.rnorth.duct-tape:duct-tape:1.0.8",
+ sha1 = "92edc22a9ab2f3e17c9bf700aaee377d50e8b530",
)
maven_jar(
@@ -38,18 +38,18 @@
sha1 = "639033469776fd37c08358c6b92a4761feb2af4b",
)
- SLF4J_VERS = "1.7.26"
+ SLF4J_VERS = "1.7.30"
maven_jar(
name = "slf4j-api",
artifact = "org.slf4j:slf4j-api:" + SLF4J_VERS,
- sha1 = "77100a62c2e6f04b53977b9f541044d7d722693d",
+ sha1 = "b5a4b6d16ab13e34a88fae84c35cd5d68cac922c",
)
maven_jar(
name = "slf4j-ext",
artifact = "org.slf4j:slf4j-ext:" + SLF4J_VERS,
- sha1 = "31cdf122e000322e9efcb38913e9ab07825b17ef",
+ sha1 = "595d5dabfeb29244b8c91776898cee78299080d5",
)
LOG4J2_VERS = "2.17.0"
@@ -74,8 +74,8 @@
maven_jar(
name = "postgresql",
- artifact = "org.postgresql:postgresql:42.2.4",
- sha1 = "dff98730c28a4b3a3263f0cf4abb9a3392f815a7",
+ artifact = "org.postgresql:postgresql:42.2.5",
+ sha1 = "951b7eda125f3137538a94e2cbdcf744088ad4c2",
)
maven_jar(
@@ -92,22 +92,22 @@
maven_jar(
name = "guava",
- artifact = "com.google.guava:guava:25.1-jre",
- sha1 = "6c57e4b22b44e89e548b5c9f70f0c45fe10fb0b4",
+ artifact = "com.google.guava:guava:26.0-jre",
+ sha1 = "6a806eff209f36f635f943e16d97491f00f6bfab",
)
- GUICE_VERS = "4.2.0"
+ GUICE_VERS = "4.2.1"
maven_jar(
name = "guice",
artifact = "com.google.inject:guice:" + GUICE_VERS,
- sha1 = "25e1f4c1d528a1cffabcca0d432f634f3132f6c8",
+ sha1 = "f77dfd89318fe3ff293bafceaa75fbf66e4e4b10",
)
maven_jar(
name = "guice-assistedinject",
artifact = "com.google.inject.extensions:guice-assistedinject:" + GUICE_VERS,
- sha1 = "e7270305960ad7db56f7e30cb9df6be9ff1cfb45",
+ sha1 = "d327e4aee7c96f08cd657c17da231a1f4a8999ac",
)
maven_jar(
@@ -125,8 +125,8 @@
maven_jar(
name = "jgit",
artifact =
- "org.eclipse.jgit:org.eclipse.jgit:4.11.9.201909030838-r",
- sha1 = "3bc74ffed6186bf2fc37404216e5ef16f904d0b0",
+ "org.eclipse.jgit:org.eclipse.jgit:5.1.16.202106041830-r",
+ sha1 = "1b32273b9b8326a14355374702799b6cd4a94050",
)
maven_jar(
@@ -149,32 +149,54 @@
maven_jar(
name = "jna",
- artifact = "net.java.dev.jna:jna:5.2.0",
- sha1 = "ed8b772eb077a9cb50e44e90899c66a9a6c00e67",
+ artifact = "net.java.dev.jna:jna:5.5.0",
+ sha1 = "0e0845217c4907822403912ad6828d8e0b256208",
)
- TESTCONTAINERS_VERS = "1.12.3"
+ DOCKER_JAVA_VERS = "3.2.5"
+
+ maven_jar(
+ name = "docker-java-api",
+ artifact = "com.github.docker-java:docker-java-api:" + DOCKER_JAVA_VERS,
+ sha1 = "8fe5c5e39f940ce58620e77cedc0a2a52d76f9d8",
+ )
+
+ maven_jar(
+ name = "docker-java-transport",
+ artifact = "com.github.docker-java:docker-java-transport:" + DOCKER_JAVA_VERS,
+ sha1 = "27af0ee7ebc2f5672e23ea64769497b5d55ce3ac",
+ )
+
+ # https://github.com/docker-java/docker-java/blob/3.2.5/pom.xml#L61
+ # <=> DOCKER_JAVA_VERS
+ maven_jar(
+ name = "jackson-annotations",
+ artifact = "com.fasterxml.jackson.core:jackson-annotations:2.10.3",
+ sha1 = "0f63b3b1da563767d04d2e4d3fc1ae0cdeffebe7",
+ )
+
+ TESTCONTAINERS_VERS = "1.15.0"
maven_jar(
name = "testcontainers",
artifact = "org.testcontainers:testcontainers:" + TESTCONTAINERS_VERS,
- sha1 = "e424a4549640e120acceac641ac909fcda58bf62",
+ sha1 = "b627535b444d88e7b14953bb953d80d9b7b3bd76",
)
maven_jar(
name = "testcontainers-database-commons",
artifact = "org.testcontainers:database-commons:" + TESTCONTAINERS_VERS,
- sha1 = "69a857af8c90be1f2ba6d7f70a59bd5687854e8f",
+ sha1 = "bc52637643da33f8fadfb6220cb59a7d8da37325",
)
maven_jar(
name = "testcontainers-jdbc",
artifact = "org.testcontainers:jdbc:" + TESTCONTAINERS_VERS,
- sha1 = "8f86e3ebf31b3a0439ba537bba770b5be219b55b",
+ sha1 = "3626ed0746c94b337b1872afa90331bf9e2e6e16",
)
maven_jar(
name = "testcontainers-postgres",
artifact = "org.testcontainers:postgresql:" + TESTCONTAINERS_VERS,
- sha1 = "946fc6dc021b0b760da3fd005d2fd871fce10be4",
+ sha1 = "25daf6c0dd1d52e4a1b899c5b3e07b71d382c7ba",
)
diff --git a/src/main/java/com/ericsson/gerrit/plugins/gcconductor/EvaluationTask.java b/src/main/java/com/ericsson/gerrit/plugins/gcconductor/EvaluationTask.java
index e8aba71..43803e4 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/gcconductor/EvaluationTask.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/gcconductor/EvaluationTask.java
@@ -197,7 +197,7 @@
private Collection<Ref> getAllRefs(FileRepository repo) throws IOException {
RefDatabase refdb = repo.getRefDatabase();
- Collection<Ref> refs = refdb.getRefs(RefDatabase.ALL).values();
+ Collection<Ref> refs = refdb.getRefs();
List<Ref> addl = refdb.getAdditionalRefs();
if (!addl.isEmpty()) {
List<Ref> all = new ArrayList<>(refs.size() + addl.size());
diff --git a/src/main/java/com/ericsson/gerrit/plugins/gcconductor/command/ShowQueue.java b/src/main/java/com/ericsson/gerrit/plugins/gcconductor/command/ShowQueue.java
index fe41af0..4cd7417 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/gcconductor/command/ShowQueue.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/gcconductor/command/ShowQueue.java
@@ -19,9 +19,9 @@
import com.ericsson.gerrit.plugins.gcconductor.GcQueue;
import com.ericsson.gerrit.plugins.gcconductor.RepositoryInfo;
import com.google.common.base.Strings;
-import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.extensions.annotations.RequiresCapability;
+import com.google.gerrit.server.util.time.TimeUtil;
import com.google.gerrit.sshd.AdminHighPriorityCommand;
import com.google.gerrit.sshd.CommandMetaData;
import com.google.gerrit.sshd.SshCommand;
diff --git a/src/main/java/com/ericsson/gerrit/plugins/gcconductor/evaluator/Evaluator.java b/src/main/java/com/ericsson/gerrit/plugins/gcconductor/evaluator/Evaluator.java
index 5ae7fac..eda5f96 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/gcconductor/evaluator/Evaluator.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/gcconductor/evaluator/Evaluator.java
@@ -31,8 +31,8 @@
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
@@ -48,7 +48,7 @@
private static final Logger log = LoggerFactory.getLogger(Evaluator.class);
private static final ThreadLocal<String> uploadRepositoryPath = new ThreadLocal<String>() {};
- private final ScheduledThreadPoolExecutor executor;
+ private final ExecutorService executor;
private final EvaluationTask.Factory evaluationTaskFactory;
private final GitRepositoryManager repoManager;
private final Map<String, Long> timestamps;
@@ -59,7 +59,7 @@
@Inject
Evaluator(
- @EvaluatorExecutor ScheduledThreadPoolExecutor executor,
+ @EvaluatorExecutor ExecutorService executor,
EvaluationTask.Factory evaluationTaskFactory,
GitRepositoryManager repoManager,
EvaluatorConfig config,
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index e0049aa..4f2a958 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -52,7 +52,7 @@
The configuration can be passed to the gc executor jar by using:
```
- java -DconfigFile=/path/to/config_file.config -jar executor.jar
+ java -DconfigFile=/path/to/gc.config -jar gc-executor.jar
```
### File `gc.config`
@@ -62,7 +62,6 @@
file is modified, gc executor needs to be restarted in order to be able to use the
new values.
-
#### Sample `gc.config`:
```
@@ -73,6 +72,7 @@
javaOptions = -Xmx32g
javaOptions = -XX:+UseG1GC
javaOptions = -XX:MaxGCPauseMillis=2000
+
[core]
executors = 2
pickOwnHostOnly = false
@@ -178,10 +178,10 @@
### GC execution
-Executors can be started/stopped using gcctl.sh script.
+Executors can be started/stopped using the gc_ctl script.
```
- /opt/gerrit/gc-conductor/gcctl.sh {start|stop|restart|status|check}
+ /opt/gerrit/gc-conductor/bin/gc_ctl {start|stop|restart|status|check}
```
[Back to @PLUGIN@ documentation index][index]
diff --git a/src/test/README.md b/src/test/README.md
new file mode 100644
index 0000000..885522e
--- /dev/null
+++ b/src/test/README.md
@@ -0,0 +1,27 @@
+# About this directory structure
+
+```bash
+ ./resources/com
+ ./scala
+```
+
+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)
+on how to use Gerrit core's Gatling framework. These are about running
+non-core test scenarios such as this plugin one below:
+
+```bash
+ sbt "gatling:testOnly com.ericsson.gerrit.plugins.gcconductor.scenarios.CreateChangesTriggeringGc"
+
+```
+
+This is a scenario that can serve as an example for how to start testing
+this plugin, along with its executor component. Both of these components
+should be locally installed along with default configuration. Plugin's
+gc-executor component is assumed to be running alongside Gerrit.
+
+Scenario scala source files and their companion json resource ones are
+stored under the usual src/test directories. That structure follows the
+scala package one from the scenario classes. The core framework expects
+such a directory structure for both the scala and resources (json data)
+files.
diff --git a/src/test/java/com/ericsson/gerrit/plugins/gcconductor/evaluator/EvaluatorTest.java b/src/test/java/com/ericsson/gerrit/plugins/gcconductor/evaluator/EvaluatorTest.java
index 7dc403b..c51d2a8 100644
--- a/src/test/java/com/ericsson/gerrit/plugins/gcconductor/evaluator/EvaluatorTest.java
+++ b/src/test/java/com/ericsson/gerrit/plugins/gcconductor/evaluator/EvaluatorTest.java
@@ -29,7 +29,7 @@
import java.io.File;
import java.io.IOException;
import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.ExecutorService;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Repository;
@@ -49,7 +49,7 @@
@Mock private GitRepositoryManager repoManager;
@Mock private Repository repository;
@Mock private Repository repositoryOther;
- @Mock private ScheduledThreadPoolExecutor executor;
+ @Mock private ExecutorService executor;
@Mock private EvaluatorConfig config;
@Mock private Config gerritConfig;
diff --git a/src/test/resources/com/ericsson/gerrit/plugins/gcconductor/scenarios/CheckProjectStatisticsAfterGc.json b/src/test/resources/com/ericsson/gerrit/plugins/gcconductor/scenarios/CheckProjectStatisticsAfterGc.json
new file mode 100644
index 0000000..e9df002
--- /dev/null
+++ b/src/test/resources/com/ericsson/gerrit/plugins/gcconductor/scenarios/CheckProjectStatisticsAfterGc.json
@@ -0,0 +1,5 @@
+[
+ {
+ "url": "http://HOSTNAME:HTTP_PORT/a/projects/PROJECT/statistics.git"
+ }
+]
diff --git a/src/test/resources/com/ericsson/gerrit/plugins/gcconductor/scenarios/CreateChangesTriggeringGc-body.json b/src/test/resources/com/ericsson/gerrit/plugins/gcconductor/scenarios/CreateChangesTriggeringGc-body.json
new file mode 100644
index 0000000..23bf26c
--- /dev/null
+++ b/src/test/resources/com/ericsson/gerrit/plugins/gcconductor/scenarios/CreateChangesTriggeringGc-body.json
@@ -0,0 +1,5 @@
+{
+ "project": "${project}",
+ "branch": "master",
+ "subject": "Change"
+}
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
new file mode 100644
index 0000000..c267ab3
--- /dev/null
+++ b/src/test/resources/com/ericsson/gerrit/plugins/gcconductor/scenarios/CreateChangesTriggeringGc.json
@@ -0,0 +1,6 @@
+[
+ {
+ "url": "http://HOSTNAME:HTTP_PORT/a/changes/",
+ "project": "_PROJECT"
+ }
+]
diff --git a/src/test/resources/com/ericsson/gerrit/plugins/gcconductor/scenarios/DeleteChangesAfterGc.json b/src/test/resources/com/ericsson/gerrit/plugins/gcconductor/scenarios/DeleteChangesAfterGc.json
new file mode 100644
index 0000000..a371757
--- /dev/null
+++ b/src/test/resources/com/ericsson/gerrit/plugins/gcconductor/scenarios/DeleteChangesAfterGc.json
@@ -0,0 +1,5 @@
+[
+ {
+ "url": "http://HOSTNAME:HTTP_PORT/a/changes/"
+ }
+]
diff --git a/src/test/resources/log4j2.xml b/src/test/resources/log4j2.xml
index 7ee8d38..7f63ec5 100644
--- a/src/test/resources/log4j2.xml
+++ b/src/test/resources/log4j2.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" shutdownHook="disable">
<Properties>
- <Property name="log.path">opt/gerrit/review_site/logs/gc</Property>
+ <Property name="log.path">/opt/gerrit/review_site/logs/gc</Property>
</Properties>
<Appenders>
<RollingFile name="RollingFile" fileName="${log.path}/gc.log"
diff --git a/src/test/scala/com/ericsson/gerrit/plugins/gcconductor/scenarios/CheckProjectStatisticsAfterGc.scala b/src/test/scala/com/ericsson/gerrit/plugins/gcconductor/scenarios/CheckProjectStatisticsAfterGc.scala
new file mode 100644
index 0000000..fa43e22
--- /dev/null
+++ b/src/test/scala/com/ericsson/gerrit/plugins/gcconductor/scenarios/CheckProjectStatisticsAfterGc.scala
@@ -0,0 +1,41 @@
+// 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.ProjectSimulation
+import io.gatling.core.Predef._
+import io.gatling.core.feeder.FeederBuilder
+import io.gatling.core.structure.ScenarioBuilder
+import io.gatling.http.Predef._
+
+class CheckProjectStatisticsAfterGc extends ProjectSimulation {
+ private val data: FeederBuilder = jsonFile(resource).convert(keys).queue
+
+ def this(default: String) {
+ this()
+ this.default = default
+ }
+
+ val test: ScenarioBuilder = scenario(unique)
+ .feed(data)
+ .exec(http(unique).get("${url}")
+ .check(regex("\"number_of_loose_objects\": (\\d+),")
+ .is("0")))
+
+ setUp(
+ test.inject(
+ atOnceUsers(1)
+ )).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
new file mode 100644
index 0000000..a61b376
--- /dev/null
+++ b/src/test/scala/com/ericsson/gerrit/plugins/gcconductor/scenarios/CreateChangesTriggeringGc.scala
@@ -0,0 +1,88 @@
+// 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 io.gatling.core.feeder.FeederBuilder
+import io.gatling.core.structure.ScenarioBuilder
+import io.gatling.http.Predef._
+
+import scala.concurrent.duration._
+
+class CreateChangesTriggeringGc extends GerritSimulation {
+ 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
+ private lazy val DefaultLooseObjectsToEnqueueGc = 400
+ private lazy val LooseObjectsPerChange = 2
+ private lazy val ChangesPerSecond = 4
+ private val ChangesForLastEvaluation = 1
+
+ private lazy val secondsForLastEvaluation = SecondsPerWeightUnit * 2
+ private lazy val secondsForLastGcExecution = secondsForLastEvaluation * 2
+ private lazy val changesToEnqueueGc = DefaultLooseObjectsToEnqueueGc / LooseObjectsPerChange
+ private lazy val secondsToChanges = changesToEnqueueGc / ChangesPerSecond
+ private lazy val maxSecondsToEnqueueGc = secondsToChanges + DefaultSecondsToNextEvaluation + secondsForLastEvaluation
+ private lazy val maxSecondsToExecuteGc = maxSecondsToEnqueueGc + DefaultSecondsToNextGcDequeue + secondsForLastGcExecution
+
+ override def relativeRuntimeWeight: Int = maxSecondsToExecuteGc / SecondsPerWeightUnit
+
+ private val test: ScenarioBuilder = scenario(unique)
+ .feed(data)
+ .exec(httpRequest
+ .body(ElFileBody(body)).asJson
+ .check(regex("\"" + numberKey + "\":(\\d+),").saveAs(numberKey)))
+ .exec(session => {
+ deleteChanges.upToNumber = session(numberKey).as[Int]
+ session
+ })
+
+ private val createProject = new CreateProject(default)
+ private val checkStatsAfterGc = new CheckProjectStatisticsAfterGc(default)
+ private val deleteChanges = new DeleteChangesAfterGc
+ private val deleteProject = new DeleteProject(default)
+
+ setUp(
+ createProject.test.inject(
+ nothingFor(stepWaitTime(createProject) seconds),
+ atOnceUsers(1)
+ ),
+ test.inject(
+ nothingFor(stepWaitTime(this) 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)
+ ),
+ deleteChanges.test.inject(
+ nothingFor(stepWaitTime(deleteChanges) 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/DeleteChangesAfterGc.scala b/src/test/scala/com/ericsson/gerrit/plugins/gcconductor/scenarios/DeleteChangesAfterGc.scala
new file mode 100644
index 0000000..d72f635
--- /dev/null
+++ b/src/test/scala/com/ericsson/gerrit/plugins/gcconductor/scenarios/DeleteChangesAfterGc.scala
@@ -0,0 +1,42 @@
+// 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.GerritSimulation
+import io.gatling.core.Predef._
+import io.gatling.core.feeder.FeederBuilder
+import io.gatling.core.structure.ScenarioBuilder
+import io.gatling.http.Predef.http
+
+class DeleteChangesAfterGc extends GerritSimulation {
+ private val data: FeederBuilder = jsonFile(resource).convert(keys).circular
+ private val numberKey = "number"
+ var upToNumber = 1
+
+ private lazy val OrderOfChangesToDelete = 200
+ private lazy val PerSecond = 4
+ private lazy val secondsToDeleted = OrderOfChangesToDelete / PerSecond
+
+ override def relativeRuntimeWeight: Int = (secondsToDeleted + SecondsPerWeightUnit) / SecondsPerWeightUnit
+
+ val test: ScenarioBuilder = scenario(unique)
+ .feed(data)
+ .exec(session => {
+ val numbered: Session = session.set(numberKey, upToNumber)
+ upToNumber -= 1
+ numbered
+ })
+ .exec(http(unique).delete("${url}${" + numberKey + "}"))
+}
diff --git a/tools/BUILD b/tools/BUILD
new file mode 100644
index 0000000..1fa2160
--- /dev/null
+++ b/tools/BUILD
@@ -0,0 +1 @@
+# Empty file - bazel treat directories with BUILD file as a package
\ No newline at end of file