xref: /aosp_15_r20/external/kotlinx.coroutines/kotlinx-coroutines-debug/test/BlockHoundTest.kt (revision 7a7160fed73afa6648ef8aa100d4a336fe921d9a)
1 package kotlinx.coroutines.debug
2 
3 import kotlinx.coroutines.testing.*
4 import kotlinx.coroutines.*
5 import kotlinx.coroutines.channels.*
6 import org.junit.*
7 import reactor.blockhound.*
8 
9 @Suppress("UnusedEquals", "DeferredResultUnused", "BlockingMethodInNonBlockingContext")
10 class BlockHoundTest : TestBase() {
11 
12     @Before
initnull13     fun init() {
14         BlockHound.install()
15     }
16 
17     @Test(expected = BlockingOperationError::class)
<lambda>null18     fun testShouldDetectBlockingInDefault() = runTest {
19         withContext(Dispatchers.Default) {
20             Thread.sleep(1)
21         }
22     }
23 
24     @Test
<lambda>null25     fun testShouldNotDetectBlockingInIO() = runTest {
26         withContext(Dispatchers.IO) {
27             Thread.sleep(1)
28         }
29     }
30 
31     @Test
<lambda>null32     fun testShouldNotDetectNonblocking() = runTest {
33         withContext(Dispatchers.Default) {
34             val a = 1
35             val b = 2
36             assert(a + b == 3)
37         }
38     }
39 
40     @Test
<lambda>null41     fun testReusingThreads() = runTest {
42         val n = 100
43         repeat(n) {
44             async(Dispatchers.IO) {
45                 Thread.sleep(1)
46             }
47         }
48         repeat(n) {
49             async(Dispatchers.Default) {
50             }
51         }
52         repeat(n) {
53             async(Dispatchers.IO) {
54                 Thread.sleep(1)
55             }
56         }
57     }
58 
59     @Test
<lambda>null60     fun testBroadcastChannelNotBeingConsideredBlocking() = runTest {
61         withContext(Dispatchers.Default) {
62             // Copy of kotlinx.coroutines.channels.BufferedChannelTest.testSimple
63             val q = BroadcastChannel<Int>(1)
64             val s = q.openSubscription()
65             check(!q.isClosedForSend)
66             check(s.isEmpty)
67             check(!s.isClosedForReceive)
68             val sender = launch {
69                 q.send(1)
70                 q.send(2)
71             }
72             val receiver = launch {
73                 s.receive() == 1
74                 s.receive() == 2
75                 s.cancel()
76             }
77             sender.join()
78             receiver.join()
79         }
80     }
81 
82     @Test
<lambda>null83     fun testConflatedChannelNotBeingConsideredBlocking() = runTest {
84         withContext(Dispatchers.Default) {
85             val q = Channel<Int>(Channel.CONFLATED)
86             check(q.isEmpty)
87             check(!q.isClosedForReceive)
88             check(!q.isClosedForSend)
89             val sender = launch {
90                 q.send(1)
91             }
92             val receiver = launch {
93                 q.receive() == 1
94             }
95             sender.join()
96             receiver.join()
97         }
98     }
99 
100     @Test(expected = BlockingOperationError::class)
<lambda>null101     fun testReusingThreadsFailure() = runTest {
102         val n = 100
103         repeat(n) {
104             async(Dispatchers.IO) {
105                 Thread.sleep(1)
106             }
107         }
108         async(Dispatchers.Default) {
109             Thread.sleep(1)
110         }
111         repeat(n) {
112             async(Dispatchers.IO) {
113                 Thread.sleep(1)
114             }
115         }
116     }
117 }
118