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:
@@ -387,7 +387,7 @@ In IDE, set `-Dgerrit.logLevel=debug` as a VM argument. With `bazel`, pass
|
|||||||
`GERRIT_LOG_LEVEL=debug` environment variable:
|
`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 \
|
--test_env=GERRIT_LOG_LEVEL=debug \
|
||||||
javatests/com/google/gerrit/server:server_tests
|
javatests/com/google/gerrit/server:server_tests
|
||||||
----
|
----
|
||||||
|
|||||||
@@ -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
|
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.
|
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
|
== How to run tests
|
||||||
|
|
||||||
Run all tests:
|
Run all tests:
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import scala.concurrent.duration._
|
|||||||
class CloneUsingBothProtocols extends GitSimulation {
|
class CloneUsingBothProtocols extends GitSimulation {
|
||||||
private val data: FileBasedFeederBuilder[Any]#F#F = jsonFile(resource).convert(keys).queue
|
private val data: FileBasedFeederBuilder[Any]#F#F = jsonFile(resource).convert(keys).queue
|
||||||
private val default: String = name
|
private val default: String = name
|
||||||
|
private val duration: Int = 2
|
||||||
|
|
||||||
override def replaceOverride(in: String): String = {
|
override def replaceOverride(in: String): String = {
|
||||||
replaceKeyWith("_project", default, in)
|
replaceKeyWith("_project", default, in)
|
||||||
@@ -37,14 +38,15 @@ class CloneUsingBothProtocols extends GitSimulation {
|
|||||||
|
|
||||||
setUp(
|
setUp(
|
||||||
createProject.test.inject(
|
createProject.test.inject(
|
||||||
|
nothingFor(stepWaitTime(createProject) seconds),
|
||||||
atOnceUsers(1)
|
atOnceUsers(1)
|
||||||
),
|
),
|
||||||
test.inject(
|
test.inject(
|
||||||
nothingFor(2 seconds),
|
nothingFor(stepWaitTime(this) seconds),
|
||||||
constantUsersPerSec(1) during (2 seconds)
|
constantUsersPerSec(1) during (duration seconds)
|
||||||
),
|
),
|
||||||
deleteProject.test.inject(
|
deleteProject.test.inject(
|
||||||
nothingFor(6 seconds),
|
nothingFor(stepWaitTime(deleteProject) + duration seconds),
|
||||||
atOnceUsers(1)
|
atOnceUsers(1)
|
||||||
),
|
),
|
||||||
).protocols(gitProtocol, httpProtocol)
|
).protocols(gitProtocol, httpProtocol)
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ class CreateChange extends GerritSimulation {
|
|||||||
private val default: String = name
|
private val default: String = name
|
||||||
private val numberKey = "_number"
|
private val numberKey = "_number"
|
||||||
|
|
||||||
|
override def relativeRuntimeWeight = 2
|
||||||
|
|
||||||
val test: ScenarioBuilder = scenario(unique)
|
val test: ScenarioBuilder = scenario(unique)
|
||||||
.feed(data)
|
.feed(data)
|
||||||
.exec(httpRequest
|
.exec(httpRequest
|
||||||
@@ -42,18 +44,19 @@ class CreateChange extends GerritSimulation {
|
|||||||
|
|
||||||
setUp(
|
setUp(
|
||||||
createProject.test.inject(
|
createProject.test.inject(
|
||||||
|
nothingFor(stepWaitTime(createProject) seconds),
|
||||||
atOnceUsers(1)
|
atOnceUsers(1)
|
||||||
),
|
),
|
||||||
test.inject(
|
test.inject(
|
||||||
nothingFor(2 seconds),
|
nothingFor(stepWaitTime(this) seconds),
|
||||||
atOnceUsers(1)
|
atOnceUsers(1)
|
||||||
),
|
),
|
||||||
deleteChange.test.inject(
|
deleteChange.test.inject(
|
||||||
nothingFor(6 seconds),
|
nothingFor(stepWaitTime(deleteChange) seconds),
|
||||||
atOnceUsers(1)
|
atOnceUsers(1)
|
||||||
),
|
),
|
||||||
deleteProject.test.inject(
|
deleteProject.test.inject(
|
||||||
nothingFor(8 seconds),
|
nothingFor(stepWaitTime(deleteProject) seconds),
|
||||||
atOnceUsers(1)
|
atOnceUsers(1)
|
||||||
),
|
),
|
||||||
).protocols(httpProtocol)
|
).protocols(httpProtocol)
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ class DeleteChange extends GerritSimulation {
|
|||||||
private val data: FileBasedFeederBuilder[Any]#F#F = jsonFile(resource).convert(keys).queue
|
private val data: FileBasedFeederBuilder[Any]#F#F = jsonFile(resource).convert(keys).queue
|
||||||
var number: Option[Int] = None
|
var number: Option[Int] = None
|
||||||
|
|
||||||
|
override def relativeRuntimeWeight = 2
|
||||||
|
|
||||||
val test: ScenarioBuilder = scenario(unique)
|
val test: ScenarioBuilder = scenario(unique)
|
||||||
.feed(data)
|
.feed(data)
|
||||||
.exec(session => {
|
.exec(session => {
|
||||||
|
|||||||
@@ -31,6 +31,26 @@ class GerritSimulation extends Simulation {
|
|||||||
protected val body: String = s"$pathName-body.json"
|
protected val body: String = s"$pathName-body.json"
|
||||||
protected val unique: String = name + "-" + this.hashCode()
|
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 httpRequest: HttpRequestBuilder = http(unique).post("${url}")
|
||||||
protected val httpProtocol: HttpProtocolBuilder = http.basicAuth(
|
protected val httpProtocol: HttpProtocolBuilder = http.basicAuth(
|
||||||
conf.httpConfiguration.userName,
|
conf.httpConfiguration.userName,
|
||||||
@@ -54,11 +74,15 @@ class GerritSimulation extends Simulation {
|
|||||||
replaceProperty(term, term, in)
|
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 = {
|
protected def replaceProperty(term: String, default: Any, in: String): String = {
|
||||||
val property = pack + "." + term
|
val property = pack + "." + term
|
||||||
var value = default
|
var value = default
|
||||||
default match {
|
default match {
|
||||||
case _: String =>
|
case _: String | _: Double =>
|
||||||
val propertyValue = Option(System.getProperty(property))
|
val propertyValue = Option(System.getProperty(property))
|
||||||
if (propertyValue.nonEmpty) {
|
if (propertyValue.nonEmpty) {
|
||||||
value = propertyValue.get
|
value = propertyValue.get
|
||||||
@@ -84,8 +108,26 @@ class GerritSimulation extends Simulation {
|
|||||||
* override def replaceOverride(in: String): String = {
|
* override def replaceOverride(in: String): String = {
|
||||||
* // Simple e.g., replaceProperty("EXTENSION_JSON_KEY", "default", in)
|
* // Simple e.g., replaceProperty("EXTENSION_JSON_KEY", "default", in)
|
||||||
* </pre>
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param in which string to perform the replacements.
|
||||||
|
* @return the resulting String.
|
||||||
*/
|
*/
|
||||||
def replaceOverride(in: String): String = {
|
def replaceOverride(in: String): String = {
|
||||||
in
|
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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ class ReplayRecordsFromFeeder extends GitSimulation {
|
|||||||
private val data: FileBasedFeederBuilder[Any]#F#F = jsonFile(resource).convert(keys).circular
|
private val data: FileBasedFeederBuilder[Any]#F#F = jsonFile(resource).convert(keys).circular
|
||||||
private val default: String = name
|
private val default: String = name
|
||||||
|
|
||||||
|
override def relativeRuntimeWeight = 30
|
||||||
|
|
||||||
override def replaceOverride(in: String): String = {
|
override def replaceOverride(in: String): String = {
|
||||||
replaceKeyWith("_project", default, in)
|
replaceKeyWith("_project", default, in)
|
||||||
}
|
}
|
||||||
@@ -36,22 +38,24 @@ class ReplayRecordsFromFeeder extends GitSimulation {
|
|||||||
|
|
||||||
private val createProject = new CreateProject(default)
|
private val createProject = new CreateProject(default)
|
||||||
private val deleteProject = new DeleteProject(default)
|
private val deleteProject = new DeleteProject(default)
|
||||||
|
private val maxBeforeDelete: Int = maxExecutionTime - deleteProject.maxExecutionTime
|
||||||
|
|
||||||
setUp(
|
setUp(
|
||||||
createProject.test.inject(
|
createProject.test.inject(
|
||||||
|
nothingFor(stepWaitTime(createProject) seconds),
|
||||||
atOnceUsers(1)
|
atOnceUsers(1)
|
||||||
),
|
),
|
||||||
test.inject(
|
test.inject(
|
||||||
nothingFor(4 seconds),
|
nothingFor(stepWaitTime(this) seconds),
|
||||||
atOnceUsers(10),
|
atOnceUsers(10),
|
||||||
rampUsers(10) during (5 seconds),
|
rampUsers(10) during (5 seconds),
|
||||||
constantUsersPerSec(20) during (15 seconds),
|
constantUsersPerSec(20) during (15 seconds),
|
||||||
constantUsersPerSec(20) during (15 seconds) randomized
|
constantUsersPerSec(20) during (15 seconds) randomized
|
||||||
),
|
),
|
||||||
deleteProject.test.inject(
|
deleteProject.test.inject(
|
||||||
nothingFor(59 seconds),
|
nothingFor(maxBeforeDelete seconds),
|
||||||
atOnceUsers(1)
|
atOnceUsers(1)
|
||||||
),
|
),
|
||||||
).protocols(gitProtocol, httpProtocol)
|
).protocols(gitProtocol, httpProtocol)
|
||||||
.maxDuration(61 seconds)
|
.maxDuration(maxExecutionTime seconds)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user