Skip to content

Commit 0b4e0f6

Browse files
author
Przemek Bruski
committed
smarter action shuffler
1 parent 7df94df commit 0b4e0f6

File tree

8 files changed

+100
-6
lines changed

8 files changed

+100
-6
lines changed

build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ dependencies {
4343
implementation("org.apache.commons:commons-math3:3.6.1")
4444
implementation("com.atlassian.performance.tools:concurrency:[1.0.0,2.0.0)")
4545
implementation("com.atlassian.performance:selenium-js:[1.0.0,2.0.0)")
46+
47+
runtimeOnly("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
48+
4649
listOf(
4750
"api",
4851
"core",

gradle/dependency-locks/default.lockfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ org.apache.logging.log4j:log4j-slf4j-impl:2.10.0
2626
org.checkerframework:checker-compat-qual:2.0.0
2727
org.codehaus.mojo:animal-sniffer-annotations:1.14
2828
org.glassfish:javax.json:1.1
29+
org.jetbrains.kotlin:kotlin-reflect:1.2.70
2930
org.jetbrains.kotlin:kotlin-stdlib-common:1.2.70
3031
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.70
3132
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.70

gradle/dependency-locks/runtimeClasspath.lockfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ org.apache.logging.log4j:log4j-slf4j-impl:2.10.0
2626
org.checkerframework:checker-compat-qual:2.0.0
2727
org.codehaus.mojo:animal-sniffer-annotations:1.14
2828
org.glassfish:javax.json:1.1
29+
org.jetbrains.kotlin:kotlin-reflect:1.2.70
2930
org.jetbrains.kotlin:kotlin-stdlib-common:1.2.70
3031
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.70
3132
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.70
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
# This is a Gradle generated file for dependency locking.
22
# Manual edits can break the build and are not advised.
33
# This file is expected to be part of source control.
4+
org.jetbrains.kotlin:kotlin-reflect:1.2.70
5+
org.jetbrains.kotlin:kotlin-stdlib-common:1.2.70
6+
org.jetbrains.kotlin:kotlin-stdlib:1.2.70
7+
org.jetbrains:annotations:13.0

gradle/dependency-locks/testRuntimeClasspath.lockfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ org.checkerframework:checker-compat-qual:2.0.0
3939
org.codehaus.mojo:animal-sniffer-annotations:1.14
4040
org.glassfish:javax.json:1.1
4141
org.hamcrest:hamcrest-core:1.3
42+
org.jetbrains.kotlin:kotlin-reflect:1.2.70
4243
org.jetbrains.kotlin:kotlin-stdlib-common:1.2.70
4344
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.70
4445
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.70
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
# This is a Gradle generated file for dependency locking.
22
# Manual edits can break the build and are not advised.
33
# This file is expected to be part of source control.
4+
org.jetbrains.kotlin:kotlin-reflect:1.2.70
5+
org.jetbrains.kotlin:kotlin-stdlib-common:1.2.70
6+
org.jetbrains.kotlin:kotlin-stdlib:1.2.70
7+
org.jetbrains:annotations:13.0
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package com.atlassian.performance.tools.jiraactions.api.scenario
2+
3+
import com.atlassian.performance.tools.jiraactions.api.SeededRandom
4+
import com.atlassian.performance.tools.jiraactions.api.WebJira
5+
import com.atlassian.performance.tools.jiraactions.api.action.Action
6+
import com.atlassian.performance.tools.jiraactions.api.action.BrowseProjectsAction
7+
import com.atlassian.performance.tools.jiraactions.api.action.CreateIssueAction
8+
import com.atlassian.performance.tools.jiraactions.api.action.SearchJqlAction
9+
import com.atlassian.performance.tools.jiraactions.api.measure.ActionMeter
10+
import com.atlassian.performance.tools.jiraactions.api.memories.IssueKeyMemory
11+
import com.atlassian.performance.tools.jiraactions.api.memories.JqlMemory
12+
import com.atlassian.performance.tools.jiraactions.api.page.IssuePage
13+
import kotlin.reflect.KClass
14+
15+
class ActionShuffler {
16+
private class FixedJqlMemory(val jql: String) : JqlMemory {
17+
override fun observe(issuePage: IssuePage) {
18+
throw UnsupportedOperationException()
19+
}
20+
21+
override fun recall(): String? {
22+
return jql
23+
}
24+
25+
override fun remember(memories: Collection<String>) {
26+
throw UnsupportedOperationException()
27+
}
28+
}
29+
30+
companion object {
31+
fun createRandomisedScenario(seededRandom: SeededRandom, actionProportions: Map<Action, Int>,
32+
issueKeyMemoriser: Action): List<Action> {
33+
//createIssue needs a project - browserProject goes first
34+
//viewIssue needs to have issues - createIssues goes second
35+
return createRandomisedScenario(seededRandom, actionProportions, issueKeyMemoriser, BrowseProjectsAction::class, CreateIssueAction::class)
36+
}
37+
38+
fun findIssueKeysWithJql(jira: WebJira, meter: ActionMeter, issueKeyMemory: IssueKeyMemory): SearchJqlAction {
39+
return SearchJqlAction(
40+
jira = jira,
41+
meter = meter,
42+
jqlMemory = FixedJqlMemory("project is not EMPTY"),
43+
issueKeyMemory = issueKeyMemory
44+
)
45+
}
46+
47+
private fun createRandomisedScenario(seededRandom: SeededRandom, actionProportions: Map<Action, Int>,
48+
issueKeyDiscoverer: Action, vararg actions: KClass<out Action>): List<Action> {
49+
val initialActions = findActions(actionProportions, *actions)
50+
51+
val scenario: MutableList<Action> = mutableListOf()
52+
53+
val actionProportionsToRandomise = deductActionCount(actionProportions, initialActions)
54+
actionProportionsToRandomise.entries.forEach { scenario.addMultiple(element = it.key, repeats = it.value) }
55+
scenario.shuffle(seededRandom.random)
56+
57+
//viewIssue needs to remember isssues - issueKeyDiscoverer goes after all actions
58+
scenario.addAll(0, initialActions.plus(issueKeyDiscoverer))
59+
return scenario
60+
}
61+
62+
private fun findActions(actionProportions: Map<Action, Int>, vararg actions: KClass<out Action>): List<Action> {
63+
return actions
64+
.mapNotNull { findAction(actionProportions, it) }
65+
}
66+
67+
private fun deductActionCount(actionProportions: Map<Action, Int>, actions: List<Action>): MutableMap<Action, Int> {
68+
val modifiedActionProportions = actionProportions.toMutableMap()
69+
70+
actions.forEach {
71+
val originalCount = actionProportions.getValue(it)
72+
modifiedActionProportions[it] = originalCount-1
73+
}
74+
return modifiedActionProportions
75+
}
76+
77+
private fun <T : Action> findAction(actionProportions: Map<Action, Int>, kClass: KClass<T>): T? {
78+
return actionProportions.keys.find { kClass.isInstance(it) } as T?
79+
}
80+
}
81+
}

src/main/kotlin/com/atlassian/performance/tools/jiraactions/api/scenario/JiraCoreScenario.kt

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ class JiraCoreScenario constructor() : Scenario {
2727
val jqlMemory = AdaptiveJqlMemory(seededRandom)
2828
val issueMemory = AdaptiveIssueMemory(issueKeyMemory, seededRandom)
2929

30-
val scenario: MutableList<Action> = mutableListOf()
31-
3230
val createIssue = CreateIssueAction(
3331
jira = jira,
3432
meter = meter,
@@ -41,6 +39,9 @@ class JiraCoreScenario constructor() : Scenario {
4139
jqlMemory = jqlMemory,
4240
issueKeyMemory = issueKeyMemory
4341
)
42+
43+
val findInitialIssues = ActionShuffler.findIssueKeysWithJql(jira, meter, issueKeyMemory)
44+
4445
val viewIssue = ViewIssueAction(
4546
jira = jira,
4647
meter = meter,
@@ -75,7 +76,7 @@ class JiraCoreScenario constructor() : Scenario {
7576

7677
val actionProportions = mapOf(
7778
createIssue to 5,
78-
searchWithJql to 20,
79+
searchWithJql to 19,
7980
viewIssue to 55,
8081
projectSummary to 5,
8182
viewDashboard to 10,
@@ -84,9 +85,7 @@ class JiraCoreScenario constructor() : Scenario {
8485
browseProjects to 5
8586
)
8687

87-
actionProportions.entries.forEach { scenario.addMultiple(element = it.key, repeats = it.value) }
88-
scenario.shuffle(seededRandom.random)
89-
return scenario
88+
return ActionShuffler.createRandomisedScenario(seededRandom, actionProportions, findInitialIssues)
9089
}
9190

9291
private fun initializeIssueKeyMemory(seededRandom: SeededRandom) {

0 commit comments

Comments
 (0)