blob: b223bbaccdd3ac2c61660ed969162e9363018187 [file] [log] [blame]
Vsevolod Tolstopyatov7bd983f2018-07-25 12:36:23 +03001/*
2 * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3 */
4
5package kotlinx.coroutines.experimental.channels
6
7import com.devexperts.dxlab.lincheck.*
8import com.devexperts.dxlab.lincheck.execution.*
9import java.util.*
10
11typealias 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 */
37fun Options<*, *>.injectExecution(behaviourBuilder: ExecutionBuilder): Options<*, *> {
38 injectedBehaviour.add(behaviourBuilder)
39 executionGenerator(FixedBehaviourInjectorExecutionGenerator::class.java)
40 return this
41}
42
43fun 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
46private val injectedBehaviour: Queue<ExecutionBuilder> = ArrayDeque<ExecutionBuilder>()
47
48class 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
71class 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}