1+ /*
2+ * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3+ */
4+
5+ package kotlinx.coroutines.experimental.channels
6+
7+ import com.devexperts.dxlab.lincheck.*
8+ import com.devexperts.dxlab.lincheck.execution.*
9+ import java.util.*
10+
11+ typealias ExecutionBuilder = (List <MutableList <Actor >>, List <ActorGenerator >) -> Unit
12+
13+ /* *
14+ * Example of usage:
15+ *
16+ * ```
17+ * StressOptions().injectExecution { actors, methods ->
18+ * actors[0].add(actorMethod(methods, "receive1"))
19+ * actors[0].add(actorMethod(methods, "receive2"))
20+ *
21+ * actors[1].add(actorMethod(methods, "send2"))
22+ * actors[1].add(actorMethod(methods, "send1"))
23+ * }
24+ *
25+ * ```
26+ *
27+ * Will produce
28+ * ```
29+ * Actors per thread:
30+ * [receive1(), receive2()]
31+ * [send2(), send1()]
32+ * ```
33+ * at the first iteration.
34+ *
35+ * DSL will be improved when this method will be used frequently
36+ */
37+ fun Options <* , * >.injectExecution (behaviourBuilder : ExecutionBuilder ): Options <* , * > {
38+ injectedBehaviour.add(behaviourBuilder)
39+ executionGenerator(FixedBehaviourInjectorExecutionGenerator ::class .java)
40+ return this
41+ }
42+
43+ fun actorMethod (generators : List <ActorGenerator >, name : String ): Actor =
44+ generators.find { it.generate().method.name.contains(name) }?.generate() ? : error(" Actor method $name is not found in ${generators.map { it.generate().method.name }} " )
45+
46+ private val injectedBehaviour: Queue <ExecutionBuilder > = ArrayDeque <ExecutionBuilder >()
47+
48+ class FixedBehaviourInjectorExecutionGenerator (testConfiguration : CTestConfiguration , testStructure : CTestStructure )
49+ : ExecutionGenerator (testConfiguration, testStructure) {
50+
51+ private val randomGenerator = RandomExecutionGenerator (testConfiguration, testStructure)
52+
53+ override fun nextExecution (): List <List <Actor >> {
54+ val injector = injectedBehaviour.poll()
55+ if (injector != null ) {
56+ val parallelGroup = ArrayList (testStructure.actorGenerators)
57+ val actorsPerThread = ArrayList <MutableList <Actor >>()
58+ for (i in testConfiguration.threadConfigurations.indices) {
59+ actorsPerThread.add(ArrayList ())
60+ }
61+
62+ injector.invoke(actorsPerThread, parallelGroup)
63+ return actorsPerThread
64+ }
65+
66+ return randomGenerator.nextExecution()
67+ }
68+ }
69+
70+ // Ad-hoc fixed execution injection for lin-checker
71+ class FixedBehaviourExecutionGenerator (testConfiguration : CTestConfiguration , testStructure : CTestStructure )
72+ : ExecutionGenerator (testConfiguration, testStructure) {
73+
74+ override fun nextExecution (): List <List <Actor >> {
75+ val parallelGroup = ArrayList (testStructure.actorGenerators)
76+ val actorsPerThread = ArrayList <MutableList <Actor >>()
77+ for (i in testConfiguration.threadConfigurations.indices) {
78+ actorsPerThread.add(ArrayList ())
79+ }
80+
81+
82+ actorsPerThread[0 ].add(actorMethod(parallelGroup, " receive1" ))
83+ actorsPerThread[0 ].add(actorMethod(parallelGroup, " receive2" ))
84+ actorsPerThread[0 ].add(actorMethod(parallelGroup, " close1" ))
85+
86+ actorsPerThread[1 ].add(actorMethod(parallelGroup, " send2" ))
87+ actorsPerThread[1 ].add(actorMethod(parallelGroup, " send1" ))
88+
89+ return actorsPerThread
90+ }
91+ }
0 commit comments