summaryrefslogtreecommitdiffstats
path: root/e2e-tests/src/test/scala/com/google/gerrit/scenarios/GerritSimulation.scala
blob: fc68f97019a2e1cf3c2471d75f0f1b877ea37a42 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// 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

import com.github.barbasa.gatling.git.GatlingGitConfiguration
import io.gatling.core.Predef._
import io.gatling.http.Predef.http
import io.gatling.http.protocol.HttpProtocolBuilder
import io.gatling.http.request.builder.HttpRequestBuilder

class GerritSimulation extends Simulation {
  implicit val conf: GatlingGitConfiguration = GatlingGitConfiguration()

  private val pack: String = this.getClass.getPackage.getName
  private val path: String = pack.replaceAllLiterally(".", "/")
  protected val name: String = this.getClass.getSimpleName
  private val pathName: String = s"data/$path/$name"
  protected val resource: String = s"$pathName.json"
  protected val body: String = s"$pathName-body.json"
  protected val unique: String = name + "-" + this.hashCode()
  protected val single = 1

  private val powerFactor: Double = replaceProperty("power_factor", 1.0).toDouble
  protected 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,
    conf.httpConfiguration.password)

  protected val keys: PartialFunction[(String, Any), Any] = {
    case ("url", url) =>
      var in = replaceOverride(url.toString)
      in = replaceProperty("hostname", "localhost", in)
      in = replaceProperty("http_port", 8080, in)
      replaceProperty("ssh_port", 29418, in)
    case ("number", number) =>
      val precedes = replaceKeyWith("_number", 0, number.toString)
      replaceProperty("number", 1, precedes)
    case ("project", project) =>
      var precedes = replaceKeyWith("_project", name, project.toString)
      precedes = replaceOverride(precedes)
      replaceProperty("project", precedes)
    case ("entries", entries) =>
      replaceProperty("projects_entries", "1", entries.toString)
  }

  private def replaceProperty(term: String, in: String): String = {
    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 | _: Double =>
        val propertyValue = Option(System.getProperty(property))
        if (propertyValue.nonEmpty) {
          value = propertyValue.get
        }
      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 [[keys]] is implemented above.
   *
   * <pre>
   * 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
}