Skip to content

Commit

Permalink
smarter action shuffler
Browse files Browse the repository at this point in the history
  • Loading branch information
Przemek Bruski committed Feb 15, 2020
1 parent f2491fb commit d9a2e73
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.atlassian.performance.tools.jiraactions.api.scenario

import com.atlassian.performance.tools.jiraactions.api.SeededRandom
import com.atlassian.performance.tools.jiraactions.api.WebJira
import com.atlassian.performance.tools.jiraactions.api.action.Action
import com.atlassian.performance.tools.jiraactions.api.action.BrowseProjectsAction
import com.atlassian.performance.tools.jiraactions.api.action.CreateIssueAction
import com.atlassian.performance.tools.jiraactions.api.action.SearchJqlAction
import com.atlassian.performance.tools.jiraactions.api.measure.ActionMeter
import com.atlassian.performance.tools.jiraactions.api.memories.IssueKeyMemory
import com.atlassian.performance.tools.jiraactions.api.memories.JqlMemory
import com.atlassian.performance.tools.jiraactions.api.page.IssuePage
import kotlin.reflect.KClass

private class ActionShuffler {
private class FixedJqlMemory(val jql: String) : JqlMemory {
override fun observe(issuePage: IssuePage) {
throw UnsupportedOperationException()
}

override fun recall(): String? {
return jql
}

override fun remember(memories: Collection<String>) {
throw UnsupportedOperationException()
}
}

companion object {
fun createRandomisedScenario(seededRandom: SeededRandom, actionProportions: Map<Action, Int>,
issueKeyMemoriser: Action): List<Action> {
//createIssue needs a project - browserProject goes first
//viewIssue needs to have issues - createIssues goes second
return createRandomisedScenario(seededRandom, actionProportions, issueKeyMemoriser, BrowseProjectsAction::class, CreateIssueAction::class)
}

fun findIssueKeysWithJql(jira: WebJira, meter: ActionMeter, issueKeyMemory: IssueKeyMemory): SearchJqlAction {
return SearchJqlAction(
jira = jira,
meter = meter,
jqlMemory = FixedJqlMemory("project is not EMPTY"),
issueKeyMemory = issueKeyMemory
)
}

private fun createRandomisedScenario(seededRandom: SeededRandom, actionProportions: Map<Action, Int>,
issueKeyDiscoverer: Action, vararg actions: KClass<out Action>): List<Action> {
val initialActions = findActions(actionProportions, *actions)

val scenario: MutableList<Action> = mutableListOf()

val actionProportionsToRandomise = deductActionCount(actionProportions, initialActions)
actionProportionsToRandomise.entries.forEach { scenario.addMultiple(element = it.key, repeats = it.value) }
scenario.shuffle(seededRandom.random)

//viewIssue needs to remember isssues - issueKeyDiscoverer goes after all actions
scenario.addAll(0, initialActions.plus(issueKeyDiscoverer))
return scenario
}

private fun findActions(actionProportions: Map<Action, Int>, vararg actions: KClass<out Action>): List<Action> {
return actions
.mapNotNull { findAction(actionProportions, it) }
}

private fun deductActionCount(actionProportions: Map<Action, Int>, actions: List<Action>): MutableMap<Action, Int> {
val modifiedActionProportions = actionProportions.toMutableMap()

actions.forEach {
val originalCount = actionProportions.getValue(it)
modifiedActionProportions[it] = originalCount-1
}
return modifiedActionProportions
}

private fun <T : Action> findAction(actionProportions: Map<Action, Int>, kClass: KClass<T>): T? {
@Suppress("UNCHECKED_CAST")
return actionProportions.keys.find { kClass.java.isInstance(it) } as T?
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ class JiraCoreScenario constructor() : Scenario {
val jqlMemory = AdaptiveJqlMemory(seededRandom)
val issueMemory = AdaptiveIssueMemory(issueKeyMemory, seededRandom)

val scenario: MutableList<Action> = mutableListOf()

val createIssue = CreateIssueAction(
jira = jira,
meter = meter,
Expand All @@ -41,6 +39,9 @@ class JiraCoreScenario constructor() : Scenario {
jqlMemory = jqlMemory,
issueKeyMemory = issueKeyMemory
)

val findInitialIssues = ActionShuffler.findIssueKeysWithJql(jira, meter, issueKeyMemory)

val viewIssue = ViewIssueAction(
jira = jira,
meter = meter,
Expand Down Expand Up @@ -75,7 +76,7 @@ class JiraCoreScenario constructor() : Scenario {

val actionProportions = mapOf(
createIssue to 5,
searchWithJql to 20,
searchWithJql to 19,
viewIssue to 55,
projectSummary to 5,
viewDashboard to 10,
Expand All @@ -84,9 +85,7 @@ class JiraCoreScenario constructor() : Scenario {
browseProjects to 5
)

actionProportions.entries.forEach { scenario.addMultiple(element = it.key, repeats = it.value) }
scenario.shuffle(seededRandom.random)
return scenario
return ActionShuffler.createRandomisedScenario(seededRandom, actionProportions, findInitialIssues)
}

private fun initializeIssueKeyMemory(seededRandom: SeededRandom) {
Expand Down

0 comments on commit d9a2e73

Please sign in to comment.