1
+ /*
2
+ * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3
+ */
4
+
5
+ package kotlinx.coroutines.flow
6
+
7
+ import kotlinx.atomicfu.*
8
+ import kotlinx.coroutines.*
9
+ import org.junit.*
10
+ import org.junit.Test
11
+ import kotlin.collections.ArrayList
12
+ import kotlin.test.*
13
+ import kotlin.time.*
14
+
15
+ @ExperimentalTime
16
+ class SharedFlowStressTest : TestBase () {
17
+ private val nProducers = 5
18
+ private val nConsumers = 3
19
+ private val nSeconds = 3 * stressTestMultiplier
20
+
21
+ private lateinit var sf: MutableSharedFlow <Long >
22
+ private lateinit var view: SharedFlow <Long >
23
+
24
+ @get:Rule
25
+ val producerDispatcher = ExecutorRule (nProducers)
26
+ @get:Rule
27
+ val consumerDispatcher = ExecutorRule (nConsumers)
28
+
29
+ private val totalProduced = atomic(0L )
30
+ private val totalConsumed = atomic(0L )
31
+
32
+ @Test
33
+ fun testStressReplay1 () =
34
+ testStress(1 , 0 )
35
+
36
+ @Test
37
+ fun testStressReplay1ExtraBuffer1 () =
38
+ testStress(1 , 1 )
39
+
40
+ @Test
41
+ fun testStressReplay2ExtraBuffer1 () =
42
+ testStress(2 , 1 )
43
+
44
+ private fun testStress (replay : Int , extraBufferCapacity : Int ) = runTest {
45
+ sf = MutableSharedFlow (replay, extraBufferCapacity)
46
+ view = sf.asSharedFlow()
47
+ val jobs = ArrayList <Job >()
48
+ jobs + = List (nProducers) { producerIndex ->
49
+ launch(producerDispatcher) {
50
+ var cur = producerIndex.toLong()
51
+ while (isActive) {
52
+ sf.emit(cur)
53
+ totalProduced.incrementAndGet()
54
+ cur + = nProducers
55
+ }
56
+ }
57
+ }
58
+ jobs + = List (nConsumers) { consumerIndex ->
59
+ launch(consumerDispatcher) {
60
+ while (isActive) {
61
+ view
62
+ .dropWhile { it % nConsumers != consumerIndex.toLong() }
63
+ .take(1 )
64
+ .collect {
65
+ check(it % nConsumers == consumerIndex.toLong())
66
+ totalConsumed.incrementAndGet()
67
+ }
68
+ }
69
+ }
70
+ }
71
+ var lastProduced = 0L
72
+ var lastConsumed = 0L
73
+ for (sec in 1 .. nSeconds) {
74
+ delay(1 .seconds)
75
+ val produced = totalProduced.value
76
+ val consumed = totalConsumed.value
77
+ println (" $sec sec: produced = $produced ; consumed = $consumed " )
78
+ assertNotEquals(lastProduced, produced)
79
+ assertNotEquals(lastConsumed, consumed)
80
+ lastProduced = produced
81
+ lastConsumed = consumed
82
+ }
83
+ jobs.forEach { it.cancel() }
84
+ jobs.forEach { it.join() }
85
+ println (" total: produced = ${totalProduced.value} ; consumed = ${totalConsumed.value} " )
86
+ }
87
+ }
0 commit comments