Skip to content

Commit

Permalink
refactor: migrate Groovy tests in :src:functions to Kotlin
Browse files Browse the repository at this point in the history
  • Loading branch information
vlsi committed Dec 27, 2023
1 parent e5a08ec commit 38ac9a5
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 106 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,8 @@ private static String variablesToString(JMeterVariables jMeterVariables) {
return sb.toString();
}

private static String buildFunctionCallString(String functionName, Arguments args) {
@VisibleForTesting
static String buildFunctionCallString(String functionName, Arguments args) {
StringBuilder functionCall = new StringBuilder("${");
functionCall.append(functionName);
if (args.getArguments().size() > 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,52 +21,59 @@ import org.apache.jmeter.engine.util.CompoundVariable
import org.apache.jmeter.samplers.SampleResult
import org.apache.jmeter.threads.JMeterContextService
import org.apache.jmeter.threads.JMeterVariables
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assumptions.assumeTrue
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.MethodSource
import java.util.Locale

import spock.lang.IgnoreIf
import spock.lang.Specification
import spock.lang.Unroll
class ChangeCaseTest {
data class ExecuteCase(val input: String, val mode: String, val output: String)

@Unroll
class ChangeCaseSpec extends Specification {

// See https://github.com/apache/jmeter/issues/5723
@IgnoreIf({ 'i'.toUpperCase() != 'I' || 'I'.toLowerCase() != 'i' })
def "convert '#input' using mode #mode to '#output'"() {
given:
def changeCase = new ChangeCase()
def jMCtx = JMeterContextService.getContext()
def result = new SampleResult()
result.setResponseData("dummy data", null)
jMCtx.setVariables(new JMeterVariables())
jMCtx.setPreviousResult(result)
when:
changeCase.setParameters([new CompoundVariable(input), new CompoundVariable(mode)])
then:
output == changeCase.execute(result, null)
where:
input | mode | output
"simple" | "lower" | "simple"
"simple" | "upper" | "SIMPLE"
"simple" | "capitalize" | "Simple"
"simple" | "" | "SIMPLE"
" with space " | "lower" | " with space "
" with space " | "upper" | " WITH SPACE "
" with space " | "capitalize" | " with space "
"#_with-signs." | "lower" | "#_with-signs."
"#_with-signs." | "upper" | "#_WITH-SIGNS."
"#_with-signs." | "capitalize" | "#_with-signs."
"m4u file" | "lower" | "m4u file"
"m4u file" | "upper" | "M4U FILE"
"m4u file" | "capitalize" | "M4u file"
"WITH Ümläuts" | "lower" | "with ümläuts"
"WITH Ümläuts" | "upper" | "WITH ÜMLÄUTS"
"WITH Ümläuts" | "capitalize" | "WITH Ümläuts"
"+ - special space" | "lower" | "+ - special space"
"+ - special space" | "upper" | "+ - SPECIAL SPACE"
"+ - special space" | "capitalize" | "+ - special space"
" " | "lower" | " "
" " | "upper" | " "
" " | "capitalize" | " "
companion object {
@JvmStatic
fun executeCases() = listOf(
ExecuteCase("simple", "lower", "simple"),
ExecuteCase("simple", "upper", "SIMPLE"),
ExecuteCase("simple", "capitalize", "Simple"),
ExecuteCase("simple", "", "SIMPLE"),
ExecuteCase(" with space ", "lower", " with space "),
ExecuteCase(" with space ", "upper", " WITH SPACE "),
ExecuteCase(" with space ", "capitalize", " with space "),
ExecuteCase("#_with-signs.", "lower", "#_with-signs."),
ExecuteCase("#_with-signs.", "upper", "#_WITH-SIGNS."),
ExecuteCase("#_with-signs.", "capitalize", "#_with-signs."),
ExecuteCase("m4u file", "lower", "m4u file"),
ExecuteCase("m4u file", "upper", "M4U FILE"),
ExecuteCase("m4u file", "capitalize", "M4u file"),
ExecuteCase("WITH Ümläuts", "lower", "with ümläuts"),
ExecuteCase("WITH Ümläuts", "upper", "WITH ÜMLÄUTS"),
ExecuteCase("WITH Ümläuts", "capitalize", "WITH Ümläuts"),
ExecuteCase("+ - special space", "lower", "+ - special space"),
ExecuteCase("+ - special space", "upper", "+ - SPECIAL SPACE"),
ExecuteCase("+ - special space", "capitalize", "+ - special space"),
ExecuteCase(" ", "lower", " "),
ExecuteCase(" ", "upper", " "),
ExecuteCase(" ", "capitalize", " "),
).also {
assumeTrue(
"i".uppercase(Locale.getDefault()) == "I" && "I".lowercase(Locale.getDefault()) == "i",
"ChangeCase does not behave well in tr_TR locale, see https://github.com/apache/jmeter/issues/5723"
)
}
}

@ParameterizedTest
@MethodSource("executeCases")
fun changeCase(case: ExecuteCase) {
val changeCase = ChangeCase()
val jMCtx = JMeterContextService.getContext()
val result = SampleResult()
result.setResponseData("dummy data", null)
jMCtx.variables = JMeterVariables()
jMCtx.previousResult = result
changeCase.setParameters(listOf(CompoundVariable(case.input), CompoundVariable(case.mode)))

assertEquals(case.output, changeCase.execute(result, null))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,51 +15,57 @@
* limitations under the License.
*/

package org.apache.jmeter.functions;

import java.util.concurrent.CountDownLatch
package org.apache.jmeter.functions

import org.apache.jmeter.engine.util.CompoundVariable
import org.apache.jmeter.threads.JMeterContextService
import org.apache.jmeter.threads.JMeterVariables
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import java.util.concurrent.CountDownLatch
import kotlin.concurrent.thread

class IterationCounterTest {

import spock.lang.Specification
import spock.lang.Unroll
@Test
fun `Counter per thread counts for each thread`() {
val context = JMeterContextService.getContext()
context.variables = JMeterVariables()
val counter = IterationCounter()
counter.setParameters(listOf(CompoundVariable("true"), CompoundVariable("var")))

@Unroll
class IterationCounterSpec extends Specification {
thread(start = true) {
repeat(7) { counter.execute(null, null) }
}.join()

def "Counter per thread counts for each thread"() {
given:
def context = JMeterContextService.getContext()
context.setVariables(new JMeterVariables())
def counter = new IterationCounter()
counter.setParameters(Arrays.asList(new CompoundVariable("true"), new CompoundVariable("var")))
when:
Thread.start({ (1..10).each { counter.execute(null, null) } }).join()
(1..10).each { counter.execute(null, null) }
then:
context.getVariables().get("var") == "10"
repeat(10) { counter.execute(null, null) }

Assertions.assertEquals("10", context.variables.get("var")) {
"Only 10 executions happended in the current thread, so expecting 10. " +
"Note there were 7 iterations in a different thread, however the counter should be per-thread"
}
}

def "global Counter counts for all threads"() {
given:
def context = JMeterContextService.getContext()
context.setVariables(new JMeterVariables())
def counter = new IterationCounter()
counter.setParameters(Arrays.asList(new CompoundVariable("false"), new CompoundVariable("var")))
def nrOfThreads = 100
def latch = new CountDownLatch(nrOfThreads)
when:
(1..nrOfThreads).each {
Thread.start({
(1..1000).each { counter.execute(null, null) }
latch.countDown()
})
@Test
fun `global Counter counts for all threads`() {
val context = JMeterContextService.getContext()
context.variables = JMeterVariables()
val counter = IterationCounter()
counter.setParameters(listOf(CompoundVariable("false"), CompoundVariable("var")))
val nrOfThreads = 100
val latch = CountDownLatch(nrOfThreads)

repeat(nrOfThreads) {
thread(start = true) {
repeat(1000) { counter.execute(null, null) }
latch.countDown()
}
latch.await()
counter.execute(null, null)
then:
context.getVariables().get("var") == "100001"
}
latch.await()
counter.execute(null, null)

Assertions.assertEquals("100001", context.variables.get("var")) {
"$nrOfThreads should have increased the var by 1000, plus one in main thread"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,41 @@ package org.apache.jmeter.functions.gui

import org.apache.jmeter.config.Argument
import org.apache.jmeter.config.Arguments
import org.apache.jmeter.test.gui.DisabledIfHeadless
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.MethodSource

import spock.lang.IgnoreIf
import spock.lang.Specification
import spock.lang.Unroll
class FunctionHelperTest {
data class BuildCallCase(val functionName: String, val parameters: List<String>, val combined: String)

@Unroll
class FunctionHelperSpec extends Specification {
companion object {
@JvmStatic
fun buildCallCases() = listOf(
BuildCallCase("fname", listOf(), "\${fname}"),
BuildCallCase("fname", listOf("a"), "\${fname(a)}"),
BuildCallCase("fname", listOf("a,b"), "\${fname(a\\,b)}"),
BuildCallCase("fname", listOf("a,b,c"), "\${fname(a\\,b\\,c)}"),
BuildCallCase("fname", listOf("a", "b"), "\${fname(a,b)}"),
BuildCallCase("fname", listOf("a,b", "c"), "\${fname(a\\,b,c)}"),
BuildCallCase("fname", listOf("\\\${f(a,b)}"), "\${fname(\\\${f(a\\,b)})}"),
BuildCallCase("fname", listOf("\${f(a,b)},c,\${g(d,e)}", "h"), "\${fname(\${f(a,b)}\\,c\\,\${g(d,e)},h)}"),
BuildCallCase("fname", listOf("a,\${f(b,\${g(c,d)},e)},f", "h"), "\${fname(a\\,\${f(b,\${g(c,d)},e)}\\,f,h)}"),
)
}

@DisabledIfHeadless
@ParameterizedTest
@MethodSource("buildCallCases")
fun `construct correct call string for parameters #parameters`(case: BuildCallCase) {
val args = Arguments()
args.setArguments(case.parameters.map { Argument("dummy$it", it) })

@IgnoreIf({ System.properties['java.awt.headless'] as boolean })
def "construct correct call string for parameters #parameters"() {
setup:
def functionHelper = new FunctionHelper()
when:
def args = new Arguments()
args.setArguments(parameters.collect { new Argument("dummy${it}", it) })
then:
functionHelper.buildFunctionCallString(functionName, args).toString() == combined
where:
functionName | parameters | combined
"fname" | [] | "\${fname}"
"fname" | ["a"] | "\${fname(a)}"
"fname" | ["a,b"] | "\${fname(a\\,b)}"
"fname" | ["a,b,c"] | "\${fname(a\\,b\\,c)}"
"fname" | ["a", "b"] | "\${fname(a,b)}"
"fname" | ["a,b", "c"] | "\${fname(a\\,b,c)}"
"fname" | ["\\\${f(a,b)}"] | "\${fname(\\\${f(a\\,b)})}"
"fname" | ["\${f(a,b)},c,\${g(d,e)}", "h"] | "\${fname(\${f(a,b)}\\,c\\,\${g(d,e)},h)}"
"fname" | ["a,\${f(b,\${g(c,d)},e)},f", "h"] | "\${fname(a\\,\${f(b,\${g(c,d)},e)}\\,f,h)}"
assertEquals(
case.combined,
FunctionHelper.buildFunctionCallString(case.functionName, args).toString()
) {
"buildFunctionCallString(${case.functionName}, ${case.parameters})"
}
}
}

0 comments on commit 38ac9a5

Please sign in to comment.