-
-
Notifications
You must be signed in to change notification settings - Fork 427
/
SendCachedEnvelopeIntegrationTest.kt
119 lines (97 loc) · 3.88 KB
/
SendCachedEnvelopeIntegrationTest.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package io.sentry.android.core
import com.nhaarman.mockitokotlin2.any
import com.nhaarman.mockitokotlin2.eq
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.never
import com.nhaarman.mockitokotlin2.verify
import com.nhaarman.mockitokotlin2.whenever
import io.sentry.IHub
import io.sentry.ILogger
import io.sentry.SendCachedEnvelopeFireAndForgetIntegration.SendFireAndForget
import io.sentry.SendCachedEnvelopeFireAndForgetIntegration.SendFireAndForgetFactory
import io.sentry.SentryLevel.DEBUG
import org.awaitility.kotlin.await
import java.util.concurrent.ExecutionException
import java.util.concurrent.TimeUnit.MILLISECONDS
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.test.Test
class SendCachedEnvelopeIntegrationTest {
private class Fixture {
val hub: IHub = mock()
val options = SentryAndroidOptions()
val logger = mock<ILogger>()
val factory = mock<SendFireAndForgetFactory>()
val flag = AtomicBoolean(true)
val sender = mock<SendFireAndForget>()
fun getSut(
cacheDirPath: String? = "abc",
hasStartupCrashMarker: Boolean = false,
hasSender: Boolean = true,
delaySend: Long = 0L,
taskFails: Boolean = false
): SendCachedEnvelopeIntegration {
options.cacheDirPath = cacheDirPath
options.setLogger(logger)
options.isDebug = true
whenever(sender.send()).then {
Thread.sleep(delaySend)
if (taskFails) {
throw ExecutionException(RuntimeException("Something went wrong"))
}
flag.set(false)
}
whenever(factory.hasValidPath(any(), any())).thenCallRealMethod()
whenever(factory.create(any(), any())).thenReturn(
if (hasSender) {
sender
} else {
null
}
)
return SendCachedEnvelopeIntegration(factory, hasStartupCrashMarker)
}
}
private val fixture = Fixture()
@Test
fun `when cacheDirPath is not set, does nothing`() {
val sut = fixture.getSut(cacheDirPath = null)
sut.register(fixture.hub, fixture.options)
verify(fixture.factory, never()).create(any(), any())
}
@Test
fun `when factory returns null, does nothing`() {
val sut = fixture.getSut(hasSender = false)
sut.register(fixture.hub, fixture.options)
verify(fixture.factory).create(any(), any())
verify(fixture.sender, never()).send()
}
@Test
fun `when has factory and cacheDirPath set, submits task into queue`() {
val sut = fixture.getSut()
sut.register(fixture.hub, fixture.options)
await.untilFalse(fixture.flag)
verify(fixture.sender).send()
}
@Test
fun `when has startup crash marker, awaits the task on the calling thread`() {
val sut = fixture.getSut(hasStartupCrashMarker = true)
sut.register(fixture.hub, fixture.options)
// we do not need to await here, because it's executed synchronously
verify(fixture.sender).send()
}
@Test
fun `when synchronous send times out, continues the task on a background thread`() {
val sut = fixture.getSut(hasStartupCrashMarker = true, delaySend = 1000)
fixture.options.startupCrashFlushTimeoutMillis = 100
sut.register(fixture.hub, fixture.options)
// first wait until synchronous send times out and check that the logger was hit in the catch block
await.atLeast(500, MILLISECONDS)
verify(fixture.logger).log(
eq(DEBUG),
eq("Synchronous send timed out, continuing in the background.")
)
// then wait until the async send finishes in background
await.untilFalse(fixture.flag)
verify(fixture.sender).send()
}
}