blob: b223bbaccdd3ac2c61660ed969162e9363018187 [file] [log] [blame]
/*
* Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
package kotlinx.coroutines.experimental.channels
import com.devexperts.dxlab.lincheck.*
import com.devexperts.dxlab.lincheck.execution.*
import java.util.*
typealias ExecutionBuilder = (List<MutableList<Actor>>, List<ActorGenerator>) -> Unit
/**
* Example of usage:
*
* ```
* StressOptions().injectExecution { actors, methods ->
* actors[0].add(actorMethod(methods, "receive1"))
* actors[0].add(actorMethod(methods, "receive2"))
*
* actors[1].add(actorMethod(methods, "send2"))
* actors[1].add(actorMethod(methods, "send1"))
* }
*
* ```
*
* Will produce
* ```
* Actors per thread:
* [receive1(), receive2()]
* [send2(), send1()]
* ```
* at the first iteration.
*
* DSL will be improved when this method will be used frequently
*/
fun Options<*, *>.injectExecution(behaviourBuilder: ExecutionBuilder): Options<*, *> {
injectedBehaviour.add(behaviourBuilder)
executionGenerator(FixedBehaviourInjectorExecutionGenerator::class.java)
return this
}
fun actorMethod(generators: List<ActorGenerator>, name: String): Actor =
generators.find { it.generate().method.name.contains(name) }?.generate() ?: error("Actor method $name is not found in ${generators.map { it.generate().method.name }}")
private val injectedBehaviour: Queue<ExecutionBuilder> = ArrayDeque<ExecutionBuilder>()
class FixedBehaviourInjectorExecutionGenerator(testConfiguration: CTestConfiguration, testStructure: CTestStructure)
: ExecutionGenerator(testConfiguration, testStructure) {
private val randomGenerator = RandomExecutionGenerator(testConfiguration, testStructure)
override fun nextExecution(): List<List<Actor>> {
val injector = injectedBehaviour.poll()
if (injector != null) {
val parallelGroup = ArrayList(testStructure.actorGenerators)
val actorsPerThread = ArrayList<MutableList<Actor>>()
for (i in testConfiguration.threadConfigurations.indices) {
actorsPerThread.add(ArrayList())
}
injector.invoke(actorsPerThread, parallelGroup)
return actorsPerThread
}
return randomGenerator.nextExecution()
}
}
// Ad-hoc fixed execution injection for lin-checker
class FixedBehaviourExecutionGenerator(testConfiguration: CTestConfiguration, testStructure: CTestStructure)
: ExecutionGenerator(testConfiguration, testStructure) {
override fun nextExecution(): List<List<Actor>> {
val parallelGroup = ArrayList(testStructure.actorGenerators)
val actorsPerThread = ArrayList<MutableList<Actor>>()
for (i in testConfiguration.threadConfigurations.indices) {
actorsPerThread.add(ArrayList())
}
actorsPerThread[0].add(actorMethod(parallelGroup, "receive1"))
actorsPerThread[0].add(actorMethod(parallelGroup, "receive2"))
actorsPerThread[0].add(actorMethod(parallelGroup, "close1"))
actorsPerThread[1].add(actorMethod(parallelGroup, "send2"))
actorsPerThread[1].add(actorMethod(parallelGroup, "send1"))
return actorsPerThread
}
}