Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

smarter action shuffler #6

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package com.atlassian.performance.tools.jirasoftwareactions

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 com.atlassian.performance.tools.jiraactions.api.scenario.addMultiple
import com.atlassian.performance.tools.jirasoftwareactions.api.actions.BrowseBoardsAction
import java.util.function.Predicate
import kotlin.reflect.KClass

internal 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()
}

override fun recallByTag(filter: Predicate<String>): 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
//viewBoards needs to know about boards
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A unit test would be a better way to explain and protect such contracts.

BTW this function could be internal too.

return createRandomisedScenario(seededRandom, actionProportions, issueKeyMemoriser,
BrowseProjectsAction::class, CreateIssueAction::class, BrowseBoardsAction::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? {
return actionProportions.keys.find { kClass.isInstance(it) } as T?
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import com.atlassian.performance.tools.jiraactions.api.memories.adaptive.Adaptiv
import com.atlassian.performance.tools.jiraactions.api.memories.adaptive.AdaptiveJqlMemory
import com.atlassian.performance.tools.jiraactions.api.memories.adaptive.AdaptiveProjectMemory
import com.atlassian.performance.tools.jiraactions.api.scenario.Scenario
import com.atlassian.performance.tools.jiraactions.api.scenario.addMultiple
import com.atlassian.performance.tools.jirasoftwareactions.ActionShuffler
import com.atlassian.performance.tools.jirasoftwareactions.api.actions.BrowseBoardsAction
import com.atlassian.performance.tools.jirasoftwareactions.api.actions.ViewBacklogAction
import com.atlassian.performance.tools.jirasoftwareactions.api.actions.ViewBoardAction
Expand Down Expand Up @@ -45,6 +45,8 @@ class JiraSoftwareScenario : Scenario {
jqlMemory = jqlMemory,
issueKeyMemory = issueKeyMemory
)
val findInitialIssues = ActionShuffler.findIssueKeysWithJql(jira, meter, issueKeyMemory)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO it violates SRP. It doesn't seem to be the responsibility of shuffler to findIssueKeysWithJql.


val viewIssue = ViewIssueAction(
jira = jira,
meter = meter,
Expand Down Expand Up @@ -97,7 +99,7 @@ class JiraSoftwareScenario : Scenario {
) { it.issuesInBacklog != 0 }
val actionProportions = mapOf(
createIssue to 5,
searchWithJql to 20,
searchWithJql to 19,
viewIssue to 55,
projectSummary to 5,
viewDashboard to 10,
Expand All @@ -108,8 +110,7 @@ class JiraSoftwareScenario : Scenario {
viewBacklog to 10,
browseBoards to 2
)
actionProportions.entries.forEach { scenario.addMultiple(element = it.key, repeats = it.value) }
scenario.shuffle(seededRandom.random)
return scenario

return ActionShuffler.createRandomisedScenario(seededRandom, actionProportions, findInitialIssues)
}
}
}