11package io.sentry
22
3- import io.sentry.test.DeferredExecutorService
43import io.sentry.test.getCtor
54import io.sentry.test.getProperty
65import io.sentry.test.injectForField
76import io.sentry.util.thread.ThreadChecker
7+ import java.util.Date
88import java.util.Timer
9- import java.util.concurrent.RejectedExecutionException
9+ import java.util.concurrent.TimeUnit
1010import kotlin.test.Test
1111import kotlin.test.assertEquals
1212import kotlin.test.assertFailsWith
@@ -36,7 +36,6 @@ class DefaultCompositePerformanceCollectorTest {
3636 val scopes: IScopes = mock()
3737 val options = SentryOptions ()
3838 var mockTimer: Timer ? = null
39- val deferredExecutorService = DeferredExecutorService ()
4039
4140 val mockCpuCollector: IPerformanceSnapshotCollector =
4241 object : IPerformanceSnapshotCollector {
@@ -54,16 +53,17 @@ class DefaultCompositePerformanceCollectorTest {
5453 fun getSut (
5554 memoryCollector : IPerformanceSnapshotCollector ? = JavaMemoryCollector (),
5655 cpuCollector : IPerformanceSnapshotCollector ? = mockCpuCollector,
57- executorService : ISentryExecutorService = deferredExecutorService,
56+ optionsConfiguration : Sentry .OptionsConfiguration <SentryOptions > =
57+ Sentry .OptionsConfiguration {},
5858 ): CompositePerformanceCollector {
5959 options.dsn
= " https://[email protected] /proj" 60- options.executorService = executorService
6160 if (cpuCollector != null ) {
6261 options.addPerformanceCollector(cpuCollector)
6362 }
6463 if (memoryCollector != null ) {
6564 options.addPerformanceCollector(memoryCollector)
6665 }
66+ optionsConfiguration.configure(options)
6767 transaction1 = SentryTracer (TransactionContext (" " , " " ), scopes)
6868 transaction2 = SentryTracer (TransactionContext (" " , " " ), scopes)
6969 val collector = DefaultCompositePerformanceCollector (options)
@@ -184,21 +184,66 @@ class DefaultCompositePerformanceCollectorTest {
184184
185185 @Test
186186 fun `collector times out after 30 seconds` () {
187- val collector = fixture.getSut()
187+ val mockDateProvider = mock<SentryDateProvider >()
188+ val dates =
189+ listOf (
190+ SentryNanotimeDate (
191+ Date ().apply { time = TimeUnit .SECONDS .toMillis(100 ) },
192+ TimeUnit .SECONDS .toNanos(100 ),
193+ ),
194+ SentryNanotimeDate (
195+ Date ().apply { time = TimeUnit .SECONDS .toMillis(131 ) },
196+ TimeUnit .SECONDS .toNanos(131 ),
197+ ),
198+ )
199+ whenever(mockDateProvider.now()).thenReturn(dates[0 ], dates[0 ], dates[0 ], dates[1 ])
200+ val collector = fixture.getSut { it.dateProvider = mockDateProvider }
188201 collector.start(fixture.transaction1)
202+ verify(fixture.mockTimer, never())!! .cancel()
203+
189204 // Let's sleep to make the collector get values
190205 Thread .sleep(300 )
191- verify(fixture.mockTimer, never())!! .cancel()
192206
193- // Let the timeout job stop the collector
194- fixture.deferredExecutorService.runAll()
207+ // When the collector gets the values, it checks the current date, set 31 seconds after the
208+ // begin. This means it should stop itself
195209 verify(fixture.mockTimer)!! .cancel()
196210
197211 // Data is deleted after the collector times out
198212 val data1 = collector.stop(fixture.transaction1)
199213 assertNull(data1)
200214 }
201215
216+ @Test
217+ fun `collector collects for 30 seconds` () {
218+ val mockDateProvider = mock<SentryDateProvider >()
219+ val dates =
220+ listOf (
221+ SentryNanotimeDate (
222+ Date ().apply { time = TimeUnit .SECONDS .toMillis(100 ) },
223+ TimeUnit .SECONDS .toNanos(100 ),
224+ ),
225+ SentryNanotimeDate (
226+ Date ().apply { time = TimeUnit .SECONDS .toMillis(130 ) },
227+ TimeUnit .SECONDS .toNanos(130 ),
228+ ),
229+ )
230+ whenever(mockDateProvider.now()).thenReturn(dates[0 ], dates[0 ], dates[0 ], dates[1 ])
231+ val collector = fixture.getSut { it.dateProvider = mockDateProvider }
232+ collector.start(fixture.transaction1)
233+ verify(fixture.mockTimer, never())!! .cancel()
234+
235+ // Let's sleep to make the collector get values
236+ Thread .sleep(300 )
237+
238+ // When the collector gets the values, it checks the current date, set 30 seconds after the
239+ // begin. This means it should continue without being cancelled
240+ verify(fixture.mockTimer, never())!! .cancel()
241+
242+ // Data is deleted after the collector times out
243+ val data1 = collector.stop(fixture.transaction1)
244+ assertNotNull(data1)
245+ }
246+
202247 @Test
203248 fun `collector has no IPerformanceCollector by default` () {
204249 val collector = fixture.getSut(null , null )
@@ -270,25 +315,6 @@ class DefaultCompositePerformanceCollectorTest {
270315 assertNull(collector.stop(fixture.transaction1))
271316 }
272317
273- @Test
274- fun `start does not throw on executor shut down` () {
275- val executorService = mock<ISentryExecutorService >()
276- whenever(executorService.schedule(any(), any())).thenThrow(RejectedExecutionException ())
277- val logger = mock<ILogger >()
278- fixture.options.setLogger(logger)
279- fixture.options.isDebug = true
280- val sut = fixture.getSut(executorService = executorService)
281- sut.start(fixture.transaction1)
282- verify(logger)
283- .log(
284- eq(SentryLevel .ERROR ),
285- eq(
286- " Failed to call the executor. Performance collector will not be automatically finished. Did you call Sentry.close()?"
287- ),
288- any(),
289- )
290- }
291-
292318 @Test
293319 fun `Continuous collectors are notified properly` () {
294320 val collector = mock<IPerformanceContinuousCollector >()
0 commit comments