Merge branch 'stable-3.1' into stable-3.2

* stable-3.1:
  BatchUpdateTest: Extend GerritBaseTests
  dev-bazel: Fix package name in example test invocation
  ReviewDbBatchUpdate: Fix typo in member name
  Enable to run online noteDb migration using multiple threads
  GerritSimulation: Support runtime factor property
  GerritSimulation: Add replaceOverride javadoc tags
  GerritSimulation: Support reusable step wait times

Change-Id: Ifdb0007187a3d772e0398c07aed3b4836e4a97a0
This commit is contained in:
Marco Miller
2020-05-01 16:58:40 -04:00
7 changed files with 75 additions and 11 deletions

View File

@@ -387,7 +387,7 @@ In IDE, set `-Dgerrit.logLevel=debug` as a VM argument. With `bazel`, pass
`GERRIT_LOG_LEVEL=debug` environment variable:
----
bazel test --test_filter=com.gerrit.server.notedb.ChangeNotesTest \
bazel test --test_filter=com.google.gerrit.server.notedb.ChangeNotesTest \
--test_env=GERRIT_LOG_LEVEL=debug \
javatests/com/google/gerrit/server:server_tests
----

View File

@@ -170,6 +170,17 @@ Further above, the `_PROJECT` keyword is prefixed with an underscore, which mean
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.
The following core property can be optionally set depending on the runtime environment. The test
environments used as reference for scenarios development assume its default value, `1.0`. For
slower or more complex execution environments, the value can be increased this way for example:
* `-Dcom.google.gerrit.scenarios.power_factor=1.5`
This will make the scenario steps take half more time to expect proper completion. A value smaller
than the default, say `0.8`, will make scenarios wait somewhat less than how they were developed.
Scenario development is often done using locally running Gerrit systems under test, which are
sometimes dockerized.
== How to run tests
Run all tests:

View File

@@ -23,6 +23,7 @@ import scala.concurrent.duration._
class CloneUsingBothProtocols extends GitSimulation {
private val data: FileBasedFeederBuilder[Any]#F#F = jsonFile(resource).convert(keys).queue
private val default: String = name
private val duration: Int = 2
override def replaceOverride(in: String): String = {
replaceKeyWith("_project", default, in)
@@ -37,14 +38,15 @@ class CloneUsingBothProtocols extends GitSimulation {
setUp(
createProject.test.inject(
nothingFor(stepWaitTime(createProject) seconds),
atOnceUsers(1)
),
test.inject(
nothingFor(2 seconds),
constantUsersPerSec(1) during (2 seconds)
nothingFor(stepWaitTime(this) seconds),
constantUsersPerSec(1) during (duration seconds)
),
deleteProject.test.inject(
nothingFor(6 seconds),
nothingFor(stepWaitTime(deleteProject) + duration seconds),
atOnceUsers(1)
),
).protocols(gitProtocol, httpProtocol)

View File

@@ -26,6 +26,8 @@ class CreateChange extends GerritSimulation {
private val default: String = name
private val numberKey = "_number"
override def relativeRuntimeWeight = 2
val test: ScenarioBuilder = scenario(unique)
.feed(data)
.exec(httpRequest
@@ -42,18 +44,19 @@ class CreateChange extends GerritSimulation {
setUp(
createProject.test.inject(
nothingFor(stepWaitTime(createProject) seconds),
atOnceUsers(1)
),
test.inject(
nothingFor(2 seconds),
nothingFor(stepWaitTime(this) seconds),
atOnceUsers(1)
),
deleteChange.test.inject(
nothingFor(6 seconds),
nothingFor(stepWaitTime(deleteChange) seconds),
atOnceUsers(1)
),
deleteProject.test.inject(
nothingFor(8 seconds),
nothingFor(stepWaitTime(deleteProject) seconds),
atOnceUsers(1)
),
).protocols(httpProtocol)

View File

@@ -23,6 +23,8 @@ class DeleteChange extends GerritSimulation {
private val data: FileBasedFeederBuilder[Any]#F#F = jsonFile(resource).convert(keys).queue
var number: Option[Int] = None
override def relativeRuntimeWeight = 2
val test: ScenarioBuilder = scenario(unique)
.feed(data)
.exec(session => {

View File

@@ -31,6 +31,26 @@ class GerritSimulation extends Simulation {
protected val body: String = s"$pathName-body.json"
protected val unique: String = name + "-" + this.hashCode()
private val powerFactor: Double = replaceProperty("power_factor", 1.0).toDouble
private val SecondsPerWeightUnit: Int = 2
val maxExecutionTime: Int = (SecondsPerWeightUnit * relativeRuntimeWeight * powerFactor).toInt
private var cumulativeWaitTime: Int = 0
/**
* How long a scenario step should wait before starting to execute.
* This is also registering that step's resulting wait time, so that time
* can be reused cumulatively by a potentially following scenario step.
* (Otherwise, the Gatling set-up scenario steps execute all at once.)
*
* @param scenario for which to return a wait time.
* @return that step's wait time as an Int.
*/
protected def stepWaitTime(scenario: GerritSimulation): Int = {
val currentWaitTime = cumulativeWaitTime
cumulativeWaitTime += scenario.maxExecutionTime
currentWaitTime
}
protected val httpRequest: HttpRequestBuilder = http(unique).post("${url}")
protected val httpProtocol: HttpProtocolBuilder = http.basicAuth(
conf.httpConfiguration.userName,
@@ -54,11 +74,15 @@ class GerritSimulation extends Simulation {
replaceProperty(term, term, in)
}
private def replaceProperty(term: String, default: Any): String = {
replaceProperty(term, default, term.toUpperCase)
}
protected def replaceProperty(term: String, default: Any, in: String): String = {
val property = pack + "." + term
var value = default
default match {
case _: String =>
case _: String | _: Double =>
val propertyValue = Option(System.getProperty(property))
if (propertyValue.nonEmpty) {
value = propertyValue.get
@@ -84,8 +108,26 @@ class GerritSimulation extends Simulation {
* override def replaceOverride(in: String): String = {
* // Simple e.g., replaceProperty("EXTENSION_JSON_KEY", "default", in)
* </pre>
*
* @param in which string to perform the replacements.
* @return the resulting String.
*/
def replaceOverride(in: String): String = {
in
}
/**
* Meant to be optionally overridden by (heavier) scenarios.
* This is the relative runtime weight of the scenario class or type,
* compared to other scenarios' own runtime weights.
*
* The default weight or unit of weight is the pre-assigned value below.
* This default applies to any scenario class that is not overriding it
* with a greater, relative runtime weight value. Overriding scenarios
* happen to relatively require more run time than siblings, prior to
* being expected as completed.
*
* @return the relative runtime weight of this scenario as an Int.
*/
def relativeRuntimeWeight = 1
}

View File

@@ -24,6 +24,8 @@ class ReplayRecordsFromFeeder extends GitSimulation {
private val data: FileBasedFeederBuilder[Any]#F#F = jsonFile(resource).convert(keys).circular
private val default: String = name
override def relativeRuntimeWeight = 30
override def replaceOverride(in: String): String = {
replaceKeyWith("_project", default, in)
}
@@ -36,22 +38,24 @@ class ReplayRecordsFromFeeder extends GitSimulation {
private val createProject = new CreateProject(default)
private val deleteProject = new DeleteProject(default)
private val maxBeforeDelete: Int = maxExecutionTime - deleteProject.maxExecutionTime
setUp(
createProject.test.inject(
nothingFor(stepWaitTime(createProject) seconds),
atOnceUsers(1)
),
test.inject(
nothingFor(4 seconds),
nothingFor(stepWaitTime(this) seconds),
atOnceUsers(10),
rampUsers(10) during (5 seconds),
constantUsersPerSec(20) during (15 seconds),
constantUsersPerSec(20) during (15 seconds) randomized
),
deleteProject.test.inject(
nothingFor(59 seconds),
nothingFor(maxBeforeDelete seconds),
atOnceUsers(1)
),
).protocols(gitProtocol, httpProtocol)
.maxDuration(61 seconds)
.maxDuration(maxExecutionTime seconds)
}