diff --git a/sentry-jul/src/test/kotlin/io/sentry/jul/SentryHandlerTest.kt b/sentry-jul/src/test/kotlin/io/sentry/jul/SentryHandlerTest.kt index 8f39c0d94a5..120bdcb3116 100644 --- a/sentry-jul/src/test/kotlin/io/sentry/jul/SentryHandlerTest.kt +++ b/sentry-jul/src/test/kotlin/io/sentry/jul/SentryHandlerTest.kt @@ -7,6 +7,7 @@ import io.sentry.SentryLogLevel import io.sentry.SentryOptions import io.sentry.checkEvent import io.sentry.checkLogs +import io.sentry.test.applyTestOptions import io.sentry.test.initForTest import io.sentry.transport.ITransport import java.time.Instant @@ -43,6 +44,7 @@ class SentryHandlerTest { val options = SentryOptions() options.dsn = "http://key@localhost/proj" options.setTransportFactory { _, _ -> transport } + applyTestOptions(options) contextTags?.forEach { options.addContextTag(it) } logger = Logger.getLogger("jul.SentryHandlerTest") handler = SentryHandler(options, configureWithLogManager, true) @@ -411,7 +413,7 @@ class SentryHandlerTest { fixture = Fixture(minimumLevel = Level.FINEST) fixture.logger.finest("testing trace level") - Sentry.flush(1000) + Sentry.flush(10) verify(fixture.transport) .send( @@ -427,7 +429,7 @@ class SentryHandlerTest { fixture = Fixture(minimumLevel = Level.FINE) fixture.logger.fine("testing trace level") - Sentry.flush(1000) + Sentry.flush(10) verify(fixture.transport) .send(checkLogs { event -> assertEquals(SentryLogLevel.DEBUG, event.items.first().level) }) @@ -438,7 +440,7 @@ class SentryHandlerTest { fixture = Fixture(minimumLevel = Level.CONFIG) fixture.logger.config("testing debug level") - Sentry.flush(1000) + Sentry.flush(10) verify(fixture.transport) .send(checkLogs { event -> assertEquals(SentryLogLevel.DEBUG, event.items.first().level) }) @@ -449,7 +451,7 @@ class SentryHandlerTest { fixture = Fixture(minimumLevel = Level.INFO) fixture.logger.info("testing info level") - Sentry.flush(1000) + Sentry.flush(10) verify(fixture.transport) .send(checkLogs { event -> assertEquals(SentryLogLevel.INFO, event.items.first().level) }) @@ -460,7 +462,7 @@ class SentryHandlerTest { fixture = Fixture(minimumLevel = Level.WARNING) fixture.logger.warning("testing warn level") - Sentry.flush(1000) + Sentry.flush(10) verify(fixture.transport) .send(checkLogs { event -> assertEquals(SentryLogLevel.WARN, event.items.first().level) }) @@ -471,7 +473,7 @@ class SentryHandlerTest { fixture = Fixture(minimumLevel = Level.SEVERE) fixture.logger.severe("testing error level") - Sentry.flush(1000) + Sentry.flush(10) verify(fixture.transport) .send(checkLogs { event -> assertEquals(SentryLogLevel.ERROR, event.items.first().level) }) diff --git a/sentry-log4j2/src/test/kotlin/io/sentry/log4j2/SentryAppenderTest.kt b/sentry-log4j2/src/test/kotlin/io/sentry/log4j2/SentryAppenderTest.kt index 9ddfdbd43be..57ad0d63003 100644 --- a/sentry-log4j2/src/test/kotlin/io/sentry/log4j2/SentryAppenderTest.kt +++ b/sentry-log4j2/src/test/kotlin/io/sentry/log4j2/SentryAppenderTest.kt @@ -248,7 +248,7 @@ class SentryAppenderTest { val logger = fixture.getSut(minimumLevel = Level.TRACE) logger.trace("testing trace level") - Sentry.flush(1000) + Sentry.flush(10) verify(fixture.transport) .send( @@ -267,7 +267,7 @@ class SentryAppenderTest { val logger = fixture.getSut(minimumLevel = Level.DEBUG) logger.debug("testing debug level") - Sentry.flush(1000) + Sentry.flush(10) verify(fixture.transport) .send(checkLogs { event -> assertEquals(SentryLogLevel.DEBUG, event.items.first().level) }) @@ -278,7 +278,7 @@ class SentryAppenderTest { val logger = fixture.getSut(minimumLevel = Level.INFO) logger.info("testing info level") - Sentry.flush(1000) + Sentry.flush(10) verify(fixture.transport) .send(checkLogs { event -> assertEquals(SentryLogLevel.INFO, event.items.first().level) }) @@ -289,7 +289,7 @@ class SentryAppenderTest { val logger = fixture.getSut(minimumLevel = Level.WARN) logger.warn("testing warn level") - Sentry.flush(1000) + Sentry.flush(10) verify(fixture.transport) .send(checkLogs { event -> assertEquals(SentryLogLevel.WARN, event.items.first().level) }) @@ -300,7 +300,7 @@ class SentryAppenderTest { val logger = fixture.getSut(minimumLevel = Level.ERROR) logger.error("testing error level") - Sentry.flush(1000) + Sentry.flush(10) verify(fixture.transport) .send(checkLogs { event -> assertEquals(SentryLogLevel.ERROR, event.items.first().level) }) @@ -311,7 +311,7 @@ class SentryAppenderTest { val logger = fixture.getSut(minimumLevel = Level.FATAL) logger.fatal("testing fatal level") - Sentry.flush(1000) + Sentry.flush(10) verify(fixture.transport) .send(checkLogs { event -> assertEquals(SentryLogLevel.FATAL, event.items.first().level) }) diff --git a/sentry-log4j2/src/test/resources/sentry.properties b/sentry-log4j2/src/test/resources/sentry.properties index 0163b4f2f84..b735bd74414 100644 --- a/sentry-log4j2/src/test/resources/sentry.properties +++ b/sentry-log4j2/src/test/resources/sentry.properties @@ -1,2 +1,4 @@ release=release from sentry.properties logs.enabled=true +shutdown-timeout=0 +session-flush-timeout=0 diff --git a/sentry-logback/src/test/kotlin/io/sentry/logback/SentryAppenderTest.kt b/sentry-logback/src/test/kotlin/io/sentry/logback/SentryAppenderTest.kt index ffe84ed55df..68e18190d19 100644 --- a/sentry-logback/src/test/kotlin/io/sentry/logback/SentryAppenderTest.kt +++ b/sentry-logback/src/test/kotlin/io/sentry/logback/SentryAppenderTest.kt @@ -18,6 +18,7 @@ import io.sentry.SentryLogLevel import io.sentry.SentryOptions import io.sentry.checkEvent import io.sentry.checkLogs +import io.sentry.test.applyTestOptions import io.sentry.test.initForTest import io.sentry.transport.ITransport import java.time.Instant @@ -68,6 +69,7 @@ class SentryAppenderTest { options.dsn = dsn options.isSendDefaultPii = sendDefaultPii options.logs.isEnabled = enableLogs + applyTestOptions(options) contextTags?.forEach { options.addContextTag(it) } appender.setOptions(options) appender.setMinimumBreadcrumbLevel(minimumBreadcrumbLevel) @@ -317,7 +319,7 @@ class SentryAppenderTest { fixture = Fixture(minimumLevel = Level.TRACE, enableLogs = true) fixture.logger.trace("testing trace level") - Sentry.flush(1000) + Sentry.flush(10) verify(fixture.transport) .send(checkLogs { logs -> assertEquals(SentryLogLevel.TRACE, logs.items.first().level) }) @@ -328,7 +330,7 @@ class SentryAppenderTest { fixture = Fixture(minimumLevel = Level.DEBUG, enableLogs = true) fixture.logger.debug("testing debug level") - Sentry.flush(1000) + Sentry.flush(10) verify(fixture.transport) .send(checkLogs { logs -> assertEquals(SentryLogLevel.DEBUG, logs.items.first().level) }) @@ -339,7 +341,7 @@ class SentryAppenderTest { fixture = Fixture(minimumLevel = Level.INFO, enableLogs = true) fixture.logger.info("testing info level") - Sentry.flush(1000) + Sentry.flush(10) verify(fixture.transport) .send(checkLogs { logs -> assertEquals(SentryLogLevel.INFO, logs.items.first().level) }) @@ -350,7 +352,7 @@ class SentryAppenderTest { fixture = Fixture(minimumLevel = Level.WARN, enableLogs = true) fixture.logger.warn("testing warn level") - Sentry.flush(1000) + Sentry.flush(10) verify(fixture.transport) .send(checkLogs { logs -> assertEquals(SentryLogLevel.WARN, logs.items.first().level) }) @@ -361,7 +363,7 @@ class SentryAppenderTest { fixture = Fixture(minimumLevel = Level.ERROR, enableLogs = true) fixture.logger.error("testing error level") - Sentry.flush(1000) + Sentry.flush(10) verify(fixture.transport) .send(checkLogs { logs -> assertEquals(SentryLogLevel.ERROR, logs.items.first().level) }) @@ -372,7 +374,7 @@ class SentryAppenderTest { fixture = Fixture(minimumLevel = Level.TRACE, enableLogs = true) fixture.logger.trace("Testing {} level", "TRACE") - Sentry.flush(1000) + Sentry.flush(10) verify(fixture.transport) .send( @@ -394,7 +396,7 @@ class SentryAppenderTest { fixture = Fixture(minimumLevel = Level.TRACE, enableLogs = true, encoder = encoder) fixture.logger.trace("Testing {} level", "TRACE") - Sentry.flush(1000) + Sentry.flush(10) verify(fixture.transport) .send( @@ -420,7 +422,7 @@ class SentryAppenderTest { ) fixture.logger.trace("Testing {} level", "TRACE") - Sentry.flush(1000) + Sentry.flush(10) verify(fixture.transport) .send( @@ -447,7 +449,7 @@ class SentryAppenderTest { ) fixture.logger.trace("Testing {} level", "TRACE") - Sentry.flush(1000) + Sentry.flush(10) verify(fixture.transport) .send( diff --git a/sentry-spring-boot-4/src/test/kotlin/io/sentry/spring/boot4/SentryAutoConfigurationTest.kt b/sentry-spring-boot-4/src/test/kotlin/io/sentry/spring/boot4/SentryAutoConfigurationTest.kt index 9aed094779b..cc3e22e7a19 100644 --- a/sentry-spring-boot-4/src/test/kotlin/io/sentry/spring/boot4/SentryAutoConfigurationTest.kt +++ b/sentry-spring-boot-4/src/test/kotlin/io/sentry/spring/boot4/SentryAutoConfigurationTest.kt @@ -81,7 +81,8 @@ import org.springframework.web.servlet.HandlerExceptionResolver class SentryAutoConfigurationTest { - private val contextRunner = + // Base context runner with performance optimizations + private val baseContextRunner = WebApplicationContextRunner() .withConfiguration( AutoConfigurations.of( @@ -89,6 +90,42 @@ class SentryAutoConfigurationTest { WebMvcAutoConfiguration::class.java, ) ) + .withPropertyValues( + // Speed up tests by reducing timeouts and disabling expensive operations + "sentry.shutdownTimeoutMillis=0", + "sentry.sessionFlushTimeoutMillis=0", + "sentry.flushTimeoutMillis=0", + "sentry.readTimeoutMillis=50", + "sentry.connectionTimeoutMillis=50", + "sentry.send-modules=false", // Disable expensive module sending + "sentry.attach-stacktrace=false", // Disable expensive stacktrace collection + "sentry.attach-threads=false", // Disable expensive thread info + "sentry.enable-backpressure-handling=false", + "sentry.enable-spotlight=false", + "sentry.debug=false", + "sentry.max-breadcrumbs=0", // Disable breadcrumb collection for performance + ) + + // Use the optimized base runner by default + private val contextRunner = + baseContextRunner.withUserConfiguration( + NoOpTransportConfiguration::class.java + ) // Use no-op transport to avoid network calls + + // Specialized context runners for different test categories + private val dsnEnabledRunner = + baseContextRunner + .withPropertyValues("sentry.dsn=http://key@localhost/proj") + .withUserConfiguration( + NoOpTransportConfiguration::class.java + ) // Use no-op transport to avoid network calls + + private val tracingEnabledRunner = + baseContextRunner + .withPropertyValues("sentry.dsn=http://key@localhost/proj", "sentry.traces-sample-rate=1.0") + .withUserConfiguration( + NoOpTransportConfiguration::class.java + ) // Use no-op transport to avoid network calls @Test fun `scopes is not created when auto-configuration dsn is not set`() { @@ -97,22 +134,17 @@ class SentryAutoConfigurationTest { @Test fun `scopes is created when dsn is provided`() { - contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run { - assertThat(it).hasSingleBean(IScopes::class.java) - } + dsnEnabledRunner.run { assertThat(it).hasSingleBean(IScopes::class.java) } } @Test fun `OptionsConfiguration is created if custom one with name sentryOptionsConfiguration is not provided`() { - contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run { - assertThat(it).hasSingleBean(Sentry.OptionsConfiguration::class.java) - } + dsnEnabledRunner.run { assertThat(it).hasSingleBean(Sentry.OptionsConfiguration::class.java) } } @Test fun `OptionsConfiguration with name sentryOptionsConfiguration is created if another one with different name is provided`() { - contextRunner - .withPropertyValues("sentry.dsn=http://key@localhost/proj") + dsnEnabledRunner .withUserConfiguration(CustomOptionsConfigurationConfiguration::class.java) .run { assertThat(it).getBeans(Sentry.OptionsConfiguration::class.java).hasSize(2) @@ -305,7 +337,7 @@ class SentryAutoConfigurationTest { @Test fun `sets SDK version on sent events`() { - contextRunner + baseContextRunner .withPropertyValues("sentry.dsn=http://key@localhost/proj") .withUserConfiguration(MockTransportConfiguration::class.java) .run { @@ -410,7 +442,7 @@ class SentryAutoConfigurationTest { @Test fun `sets release on SentryEvents if Git integration is configured`() { - contextRunner + baseContextRunner .withPropertyValues("sentry.dsn=http://key@localhost/proj") .withUserConfiguration( MockTransportConfiguration::class.java, @@ -429,7 +461,7 @@ class SentryAutoConfigurationTest { @Test fun `sets custom release on SentryEvents if release property is set and Git integration is configured`() { - contextRunner + baseContextRunner .withPropertyValues("sentry.dsn=http://key@localhost/proj", "sentry.release=my-release") .withUserConfiguration( MockTransportConfiguration::class.java, @@ -742,7 +774,7 @@ class SentryAutoConfigurationTest { @Test fun `when sentry-apache-http-client-5 is on the classpath, creates apache transport factory`() { - contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run { + baseContextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run { assertThat(it.getBean(SentryOptions::class.java).transportFactory) .isInstanceOf(ApacheHttpClientTransportFactory::class.java) } @@ -761,7 +793,7 @@ class SentryAutoConfigurationTest { @Test fun `when sentry-apache-http-client-5 is on the classpath and custom transport factory bean is set, does not create apache transport factory`() { - contextRunner + baseContextRunner .withPropertyValues("sentry.dsn=http://key@localhost/proj") .withUserConfiguration(MockTransportConfiguration::class.java) .run { @@ -1097,6 +1129,15 @@ class SentryAutoConfigurationTest { @Bean open fun sentryTransport() = transport } + @Configuration(proxyBeanMethods = false) + open class NoOpTransportConfiguration { + + @Bean + open fun noOpTransportFactory(): ITransportFactory { + return NoOpTransportFactory.getInstance() + } + } + @Configuration(proxyBeanMethods = false) open class CustomBeforeSendCallbackConfiguration { diff --git a/sentry-spring-boot-4/src/test/kotlin/io/sentry/spring/boot4/SentryLogbackAppenderAutoConfigurationTest.kt b/sentry-spring-boot-4/src/test/kotlin/io/sentry/spring/boot4/SentryLogbackAppenderAutoConfigurationTest.kt index 17e903d9a34..681932e6f89 100644 --- a/sentry-spring-boot-4/src/test/kotlin/io/sentry/spring/boot4/SentryLogbackAppenderAutoConfigurationTest.kt +++ b/sentry-spring-boot-4/src/test/kotlin/io/sentry/spring/boot4/SentryLogbackAppenderAutoConfigurationTest.kt @@ -5,6 +5,8 @@ import ch.qos.logback.classic.Logger import ch.qos.logback.classic.LoggerContext import ch.qos.logback.classic.spi.ILoggingEvent import ch.qos.logback.core.Appender +import io.sentry.ITransportFactory +import io.sentry.NoOpTransportFactory import io.sentry.logback.SentryAppender import kotlin.test.BeforeTest import kotlin.test.Test @@ -13,10 +15,13 @@ import org.slf4j.LoggerFactory import org.springframework.boot.autoconfigure.AutoConfigurations import org.springframework.boot.test.context.FilteredClassLoader import org.springframework.boot.test.context.runner.ApplicationContextRunner +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration class SentryLogbackAppenderAutoConfigurationTest { - private val contextRunner = + // Base context runner with performance optimizations + private val baseContextRunner = ApplicationContextRunner() .withConfiguration( AutoConfigurations.of( @@ -24,6 +29,35 @@ class SentryLogbackAppenderAutoConfigurationTest { SentryAutoConfiguration::class.java, ) ) + .withPropertyValues( + // Speed up tests by reducing timeouts and disabling expensive operations + "sentry.shutdownTimeoutMillis=0", + "sentry.sessionFlushTimeoutMillis=0", + "sentry.flushTimeoutMillis=0", + "sentry.readTimeoutMillis=50", + "sentry.connectionTimeoutMillis=50", + "sentry.send-modules=false", // Disable expensive module sending + "sentry.attach-stacktrace=false", // Disable expensive stacktrace collection + "sentry.attach-threads=false", // Disable expensive thread info + "sentry.enable-backpressure-handling=false", + "sentry.enable-spotlight=false", + "sentry.debug=false", + "sentry.max-breadcrumbs=0", // Disable breadcrumb collection for performance + ) + + // Use the optimized base runner by default + private val contextRunner = + baseContextRunner.withUserConfiguration( + NoOpTransportConfiguration::class.java + ) // Use no-op transport to avoid network calls + + // Specialized context runner for tests requiring DSN + private val dsnEnabledRunner = + baseContextRunner + .withPropertyValues("sentry.dsn=http://key@localhost/proj") + .withUserConfiguration( + NoOpTransportConfiguration::class.java + ) // Use no-op transport to avoid network calls private val rootLogger = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME) as Logger @@ -40,19 +74,15 @@ class SentryLogbackAppenderAutoConfigurationTest { @Test fun `configures SentryAppender`() { - contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run { + dsnEnabledRunner.run { assertThat(rootLogger.getAppenders(SentryAppender::class.java)).hasSize(1) } } @Test fun `configures SentryAppender for configured loggers`() { - contextRunner - .withPropertyValues( - "sentry.dsn=http://key@localhost/proj", - "sentry.logging.loggers[0]=foo.bar", - "sentry.logging.loggers[1]=baz", - ) + dsnEnabledRunner + .withPropertyValues("sentry.logging.loggers[0]=foo.bar", "sentry.logging.loggers[1]=baz") .run { val fooBarLogger = LoggerFactory.getLogger("foo.bar") as Logger val bazLogger = LoggerFactory.getLogger("baz") as Logger @@ -65,23 +95,20 @@ class SentryLogbackAppenderAutoConfigurationTest { @Test fun `configures SentryAppender for none of the loggers if so configured`() { - contextRunner - .withPropertyValues("sentry.dsn=http://key@localhost/proj", "sentry.logging.loggers=") - .run { - val fooBarLogger = LoggerFactory.getLogger("foo.bar") as Logger - val bazLogger = LoggerFactory.getLogger("baz") as Logger + dsnEnabledRunner.withPropertyValues("sentry.logging.loggers=").run { + val fooBarLogger = LoggerFactory.getLogger("foo.bar") as Logger + val bazLogger = LoggerFactory.getLogger("baz") as Logger - assertThat(rootLogger.getAppenders(SentryAppender::class.java)).hasSize(0) - assertThat(fooBarLogger.getAppenders(SentryAppender::class.java)).hasSize(0) - assertThat(bazLogger.getAppenders(SentryAppender::class.java)).hasSize(0) - } + assertThat(rootLogger.getAppenders(SentryAppender::class.java)).hasSize(0) + assertThat(fooBarLogger.getAppenders(SentryAppender::class.java)).hasSize(0) + assertThat(bazLogger.getAppenders(SentryAppender::class.java)).hasSize(0) + } } @Test fun `sets SentryAppender properties`() { - contextRunner + dsnEnabledRunner .withPropertyValues( - "sentry.dsn=http://key@localhost/proj", "sentry.logging.minimum-event-level=info", "sentry.logging.minimum-breadcrumb-level=debug", "sentry.logging.minimum-level=error", @@ -113,7 +140,7 @@ class SentryLogbackAppenderAutoConfigurationTest { sentryAppender.start() rootLogger.addAppender(sentryAppender) - contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run { + dsnEnabledRunner.run { val appenders = rootLogger.getAppenders(SentryAppender::class.java) assertThat(appenders).hasSize(1) assertThat(appenders.first().name).isEqualTo("customAppender") @@ -122,7 +149,7 @@ class SentryLogbackAppenderAutoConfigurationTest { @Test fun `does not configure SentryAppender when logback is not on the classpath`() { - contextRunner + baseContextRunner .withPropertyValues("sentry.dsn=http://key@localhost/proj") .withClassLoader(FilteredClassLoader(LoggerContext::class.java)) .run { assertThat(rootLogger.getAppenders(SentryAppender::class.java)).isEmpty() } @@ -130,11 +157,20 @@ class SentryLogbackAppenderAutoConfigurationTest { @Test fun `does not configure SentryAppender when sentry-logback module is not on the classpath`() { - contextRunner + baseContextRunner .withPropertyValues("sentry.dsn=http://key@localhost/proj") .withClassLoader(FilteredClassLoader(SentryAppender::class.java)) .run { assertThat(rootLogger.getAppenders(SentryAppender::class.java)).isEmpty() } } + + @Configuration(proxyBeanMethods = false) + open class NoOpTransportConfiguration { + + @Bean + open fun noOpTransportFactory(): ITransportFactory { + return NoOpTransportFactory.getInstance() + } + } } fun Logger.getAppenders(clazz: Class): List> { diff --git a/sentry-spring-boot-4/src/test/kotlin/io/sentry/spring/boot4/SentryWebfluxAutoConfigurationTest.kt b/sentry-spring-boot-4/src/test/kotlin/io/sentry/spring/boot4/SentryWebfluxAutoConfigurationTest.kt index fbb3aedf375..a338208d8e4 100644 --- a/sentry-spring-boot-4/src/test/kotlin/io/sentry/spring/boot4/SentryWebfluxAutoConfigurationTest.kt +++ b/sentry-spring-boot-4/src/test/kotlin/io/sentry/spring/boot4/SentryWebfluxAutoConfigurationTest.kt @@ -1,6 +1,8 @@ package io.sentry.spring.boot4 import io.micrometer.context.ThreadLocalAccessor +import io.sentry.ITransportFactory +import io.sentry.NoOpTransportFactory import io.sentry.spring7.webflux.SentryWebExceptionHandler import io.sentry.spring7.webflux.SentryWebFilter import io.sentry.spring7.webflux.SentryWebFilterWithThreadLocalAccessor @@ -10,10 +12,13 @@ import org.springframework.boot.autoconfigure.AutoConfigurations import org.springframework.boot.test.context.FilteredClassLoader import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner import org.springframework.boot.webflux.autoconfigure.WebFluxAutoConfiguration +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration import reactor.core.scheduler.Schedulers class SentryWebfluxAutoConfigurationTest { - private val contextRunner = + // Base context runner with performance optimizations + private val baseContextRunner = ReactiveWebApplicationContextRunner() .withConfiguration( AutoConfigurations.of( @@ -22,10 +27,39 @@ class SentryWebfluxAutoConfigurationTest { SentryAutoConfiguration::class.java, ) ) + .withPropertyValues( + // Speed up tests by reducing timeouts and disabling expensive operations + "sentry.shutdownTimeoutMillis=0", + "sentry.sessionFlushTimeoutMillis=0", + "sentry.flushTimeoutMillis=0", + "sentry.readTimeoutMillis=50", + "sentry.connectionTimeoutMillis=50", + "sentry.send-modules=false", // Disable expensive module sending + "sentry.attach-stacktrace=false", // Disable expensive stacktrace collection + "sentry.attach-threads=false", // Disable expensive thread info + "sentry.enable-backpressure-handling=false", + "sentry.enable-spotlight=false", + "sentry.debug=false", + "sentry.max-breadcrumbs=0", // Disable breadcrumb collection for performance + ) + + // Use the optimized base runner by default + private val contextRunner = + baseContextRunner.withUserConfiguration( + NoOpTransportConfiguration::class.java + ) // Use no-op transport to avoid network calls + + // Specialized context runner for tests requiring DSN + private val dsnEnabledRunner = + baseContextRunner + .withPropertyValues("sentry.dsn=http://key@localhost/proj") + .withUserConfiguration( + NoOpTransportConfiguration::class.java + ) // Use no-op transport to avoid network calls @Test fun `configures sentryWebFilter`() { - contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run { + dsnEnabledRunner.run { assertThat(it).hasSingleBean(SentryWebFilterWithThreadLocalAccessor::class.java) assertThat(it).doesNotHaveBean(SentryWebFilter::class.java) } @@ -33,9 +67,7 @@ class SentryWebfluxAutoConfigurationTest { @Test fun `configures exception handler`() { - contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run { - assertThat(it).hasSingleBean(SentryWebExceptionHandler::class.java) - } + dsnEnabledRunner.run { assertThat(it).hasSingleBean(SentryWebExceptionHandler::class.java) } } @Test @@ -59,28 +91,18 @@ class SentryWebfluxAutoConfigurationTest { @Test fun `configures web filter with ThreadLocalAccessor support if available and enabled`() { - contextRunner - .withPropertyValues( - "sentry.dsn=http://key@localhost/proj", - "sentry.reactive.thread-local-accessor-enabled=true", - ) - .run { - assertThat(it).hasSingleBean(SentryWebFilterWithThreadLocalAccessor::class.java) - assertThat(it).doesNotHaveBean(SentryWebFilter::class.java) - } + dsnEnabledRunner.withPropertyValues("sentry.reactive.thread-local-accessor-enabled=true").run { + assertThat(it).hasSingleBean(SentryWebFilterWithThreadLocalAccessor::class.java) + assertThat(it).doesNotHaveBean(SentryWebFilter::class.java) + } } @Test fun `does not configure web filter with ThreadLocalAccessor support if disabled`() { - contextRunner - .withPropertyValues( - "sentry.dsn=http://key@localhost/proj", - "sentry.reactive.thread-local-accessor-enabled=false", - ) - .run { - assertThat(it).doesNotHaveBean(SentryWebFilterWithThreadLocalAccessor::class.java) - assertThat(it).hasSingleBean(SentryWebFilter::class.java) - } + dsnEnabledRunner.withPropertyValues("sentry.reactive.thread-local-accessor-enabled=false").run { + assertThat(it).doesNotHaveBean(SentryWebFilterWithThreadLocalAccessor::class.java) + assertThat(it).hasSingleBean(SentryWebFilter::class.java) + } } @Test @@ -93,4 +115,13 @@ class SentryWebfluxAutoConfigurationTest { .withClassLoader(FilteredClassLoader(ThreadLocalAccessor::class.java)) .run { assertThat(it).doesNotHaveBean(SentryWebFilterWithThreadLocalAccessor::class.java) } } + + @Configuration(proxyBeanMethods = false) + open class NoOpTransportConfiguration { + + @Bean + open fun noOpTransportFactory(): ITransportFactory { + return NoOpTransportFactory.getInstance() + } + } } diff --git a/sentry-spring-boot-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryAutoConfigurationTest.kt b/sentry-spring-boot-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryAutoConfigurationTest.kt index 6c424c12321..1074a324465 100644 --- a/sentry-spring-boot-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryAutoConfigurationTest.kt +++ b/sentry-spring-boot-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryAutoConfigurationTest.kt @@ -83,7 +83,8 @@ import org.springframework.web.servlet.HandlerExceptionResolver class SentryAutoConfigurationTest { - private val contextRunner = + // Base context runner with performance optimizations + private val baseContextRunner = WebApplicationContextRunner() .withConfiguration( AutoConfigurations.of( @@ -91,6 +92,42 @@ class SentryAutoConfigurationTest { WebMvcAutoConfiguration::class.java, ) ) + .withPropertyValues( + // Speed up tests by reducing timeouts and disabling expensive operations + "sentry.shutdownTimeoutMillis=0", + "sentry.sessionFlushTimeoutMillis=0", + "sentry.flushTimeoutMillis=0", + "sentry.readTimeoutMillis=50", + "sentry.connectionTimeoutMillis=50", + "sentry.send-modules=false", // Disable expensive module sending + "sentry.attach-stacktrace=false", // Disable expensive stacktrace collection + "sentry.attach-threads=false", // Disable expensive thread info + "sentry.enable-backpressure-handling=false", + "sentry.enable-spotlight=false", + "sentry.debug=false", + "sentry.max-breadcrumbs=0", // Disable breadcrumb collection for performance + ) + + // Use the optimized base runner by default + private val contextRunner = + baseContextRunner.withUserConfiguration( + NoOpTransportConfiguration::class.java + ) // Use no-op transport to avoid network calls + + // Specialized context runners for different test categories + private val dsnEnabledRunner = + baseContextRunner + .withPropertyValues("sentry.dsn=http://key@localhost/proj") + .withUserConfiguration( + NoOpTransportConfiguration::class.java + ) // Use no-op transport to avoid network calls + + private val tracingEnabledRunner = + baseContextRunner + .withPropertyValues("sentry.dsn=http://key@localhost/proj", "sentry.traces-sample-rate=1.0") + .withUserConfiguration( + NoOpTransportConfiguration::class.java + ) // Use no-op transport to avoid network calls @Test fun `scopes is not created when auto-configuration dsn is not set`() { @@ -99,22 +136,17 @@ class SentryAutoConfigurationTest { @Test fun `scopes is created when dsn is provided`() { - contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run { - assertThat(it).hasSingleBean(IScopes::class.java) - } + dsnEnabledRunner.run { assertThat(it).hasSingleBean(IScopes::class.java) } } @Test fun `OptionsConfiguration is created if custom one with name sentryOptionsConfiguration is not provided`() { - contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run { - assertThat(it).hasSingleBean(Sentry.OptionsConfiguration::class.java) - } + dsnEnabledRunner.run { assertThat(it).hasSingleBean(Sentry.OptionsConfiguration::class.java) } } @Test fun `OptionsConfiguration with name sentryOptionsConfiguration is created if another one with different name is provided`() { - contextRunner - .withPropertyValues("sentry.dsn=http://key@localhost/proj") + dsnEnabledRunner .withUserConfiguration(CustomOptionsConfigurationConfiguration::class.java) .run { assertThat(it).getBeans(Sentry.OptionsConfiguration::class.java).hasSize(2) @@ -307,7 +339,7 @@ class SentryAutoConfigurationTest { @Test fun `sets SDK version on sent events`() { - contextRunner + baseContextRunner .withPropertyValues("sentry.dsn=http://key@localhost/proj") .withUserConfiguration(MockTransportConfiguration::class.java) .run { @@ -423,7 +455,7 @@ class SentryAutoConfigurationTest { @Test fun `sets release on SentryEvents if Git integration is configured`() { - contextRunner + baseContextRunner .withPropertyValues("sentry.dsn=http://key@localhost/proj") .withUserConfiguration( MockTransportConfiguration::class.java, @@ -442,7 +474,7 @@ class SentryAutoConfigurationTest { @Test fun `sets custom release on SentryEvents if release property is set and Git integration is configured`() { - contextRunner + baseContextRunner .withPropertyValues("sentry.dsn=http://key@localhost/proj", "sentry.release=my-release") .withUserConfiguration( MockTransportConfiguration::class.java, @@ -755,7 +787,7 @@ class SentryAutoConfigurationTest { @Test fun `when sentry-apache-http-client-5 is on the classpath, creates apache transport factory`() { - contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run { + baseContextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run { assertThat(it.getBean(SentryOptions::class.java).transportFactory) .isInstanceOf(ApacheHttpClientTransportFactory::class.java) } @@ -774,7 +806,7 @@ class SentryAutoConfigurationTest { @Test fun `when sentry-apache-http-client-5 is on the classpath and custom transport factory bean is set, does not create apache transport factory`() { - contextRunner + baseContextRunner .withPropertyValues("sentry.dsn=http://key@localhost/proj") .withUserConfiguration(MockTransportConfiguration::class.java) .run { @@ -1110,6 +1142,15 @@ class SentryAutoConfigurationTest { @Bean open fun sentryTransport() = transport } + @Configuration(proxyBeanMethods = false) + open class NoOpTransportConfiguration { + + @Bean + open fun noOpTransportFactory(): ITransportFactory { + return NoOpTransportFactory.getInstance() + } + } + @Configuration(proxyBeanMethods = false) open class CustomBeforeSendCallbackConfiguration { diff --git a/sentry-spring-boot-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryLogbackAppenderAutoConfigurationTest.kt b/sentry-spring-boot-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryLogbackAppenderAutoConfigurationTest.kt index 77712ac70c6..d8982d995c1 100644 --- a/sentry-spring-boot-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryLogbackAppenderAutoConfigurationTest.kt +++ b/sentry-spring-boot-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryLogbackAppenderAutoConfigurationTest.kt @@ -5,6 +5,8 @@ import ch.qos.logback.classic.Logger import ch.qos.logback.classic.LoggerContext import ch.qos.logback.classic.spi.ILoggingEvent import ch.qos.logback.core.Appender +import io.sentry.ITransportFactory +import io.sentry.NoOpTransportFactory import io.sentry.logback.SentryAppender import kotlin.test.BeforeTest import kotlin.test.Test @@ -13,10 +15,13 @@ import org.slf4j.LoggerFactory import org.springframework.boot.autoconfigure.AutoConfigurations import org.springframework.boot.test.context.FilteredClassLoader import org.springframework.boot.test.context.runner.ApplicationContextRunner +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration class SentryLogbackAppenderAutoConfigurationTest { - private val contextRunner = + // Base context runner with performance optimizations + private val baseContextRunner = ApplicationContextRunner() .withConfiguration( AutoConfigurations.of( @@ -24,6 +29,35 @@ class SentryLogbackAppenderAutoConfigurationTest { SentryAutoConfiguration::class.java, ) ) + .withPropertyValues( + // Speed up tests by reducing timeouts and disabling expensive operations + "sentry.shutdownTimeoutMillis=0", + "sentry.sessionFlushTimeoutMillis=0", + "sentry.flushTimeoutMillis=0", + "sentry.readTimeoutMillis=50", + "sentry.connectionTimeoutMillis=50", + "sentry.send-modules=false", // Disable expensive module sending + "sentry.attach-stacktrace=false", // Disable expensive stacktrace collection + "sentry.attach-threads=false", // Disable expensive thread info + "sentry.enable-backpressure-handling=false", + "sentry.enable-spotlight=false", + "sentry.debug=false", + "sentry.max-breadcrumbs=0", // Disable breadcrumb collection for performance + ) + + // Use the optimized base runner by default + private val contextRunner = + baseContextRunner.withUserConfiguration( + NoOpTransportConfiguration::class.java + ) // Use no-op transport to avoid network calls + + // Specialized context runner for tests requiring DSN + private val dsnEnabledRunner = + baseContextRunner + .withPropertyValues("sentry.dsn=http://key@localhost/proj") + .withUserConfiguration( + NoOpTransportConfiguration::class.java + ) // Use no-op transport to avoid network calls private val rootLogger = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME) as Logger @@ -40,19 +74,15 @@ class SentryLogbackAppenderAutoConfigurationTest { @Test fun `configures SentryAppender`() { - contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run { + dsnEnabledRunner.run { assertThat(rootLogger.getAppenders(SentryAppender::class.java)).hasSize(1) } } @Test fun `configures SentryAppender for configured loggers`() { - contextRunner - .withPropertyValues( - "sentry.dsn=http://key@localhost/proj", - "sentry.logging.loggers[0]=foo.bar", - "sentry.logging.loggers[1]=baz", - ) + dsnEnabledRunner + .withPropertyValues("sentry.logging.loggers[0]=foo.bar", "sentry.logging.loggers[1]=baz") .run { val fooBarLogger = LoggerFactory.getLogger("foo.bar") as Logger val bazLogger = LoggerFactory.getLogger("baz") as Logger @@ -65,23 +95,20 @@ class SentryLogbackAppenderAutoConfigurationTest { @Test fun `configures SentryAppender for none of the loggers if so configured`() { - contextRunner - .withPropertyValues("sentry.dsn=http://key@localhost/proj", "sentry.logging.loggers=") - .run { - val fooBarLogger = LoggerFactory.getLogger("foo.bar") as Logger - val bazLogger = LoggerFactory.getLogger("baz") as Logger + dsnEnabledRunner.withPropertyValues("sentry.logging.loggers=").run { + val fooBarLogger = LoggerFactory.getLogger("foo.bar") as Logger + val bazLogger = LoggerFactory.getLogger("baz") as Logger - assertThat(rootLogger.getAppenders(SentryAppender::class.java)).hasSize(0) - assertThat(fooBarLogger.getAppenders(SentryAppender::class.java)).hasSize(0) - assertThat(bazLogger.getAppenders(SentryAppender::class.java)).hasSize(0) - } + assertThat(rootLogger.getAppenders(SentryAppender::class.java)).hasSize(0) + assertThat(fooBarLogger.getAppenders(SentryAppender::class.java)).hasSize(0) + assertThat(bazLogger.getAppenders(SentryAppender::class.java)).hasSize(0) + } } @Test fun `sets SentryAppender properties`() { - contextRunner + dsnEnabledRunner .withPropertyValues( - "sentry.dsn=http://key@localhost/proj", "sentry.logging.minimum-event-level=info", "sentry.logging.minimum-breadcrumb-level=debug", "sentry.logging.minimum-level=error", @@ -113,7 +140,7 @@ class SentryLogbackAppenderAutoConfigurationTest { sentryAppender.start() rootLogger.addAppender(sentryAppender) - contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run { + dsnEnabledRunner.run { val appenders = rootLogger.getAppenders(SentryAppender::class.java) assertThat(appenders).hasSize(1) assertThat(appenders.first().name).isEqualTo("customAppender") @@ -122,7 +149,7 @@ class SentryLogbackAppenderAutoConfigurationTest { @Test fun `does not configure SentryAppender when logback is not on the classpath`() { - contextRunner + baseContextRunner .withPropertyValues("sentry.dsn=http://key@localhost/proj") .withClassLoader(FilteredClassLoader(LoggerContext::class.java)) .run { assertThat(rootLogger.getAppenders(SentryAppender::class.java)).isEmpty() } @@ -130,11 +157,20 @@ class SentryLogbackAppenderAutoConfigurationTest { @Test fun `does not configure SentryAppender when sentry-logback module is not on the classpath`() { - contextRunner + baseContextRunner .withPropertyValues("sentry.dsn=http://key@localhost/proj") .withClassLoader(FilteredClassLoader(SentryAppender::class.java)) .run { assertThat(rootLogger.getAppenders(SentryAppender::class.java)).isEmpty() } } + + @Configuration(proxyBeanMethods = false) + open class NoOpTransportConfiguration { + + @Bean + open fun noOpTransportFactory(): ITransportFactory { + return NoOpTransportFactory.getInstance() + } + } } fun Logger.getAppenders(clazz: Class): List> { diff --git a/sentry-spring-boot-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryWebfluxAutoConfigurationTest.kt b/sentry-spring-boot-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryWebfluxAutoConfigurationTest.kt index fd47317d1d2..6b67f2d6e91 100644 --- a/sentry-spring-boot-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryWebfluxAutoConfigurationTest.kt +++ b/sentry-spring-boot-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryWebfluxAutoConfigurationTest.kt @@ -1,6 +1,8 @@ package io.sentry.spring.boot.jakarta import io.micrometer.context.ThreadLocalAccessor +import io.sentry.ITransportFactory +import io.sentry.NoOpTransportFactory import io.sentry.spring.jakarta.webflux.SentryWebExceptionHandler import io.sentry.spring.jakarta.webflux.SentryWebFilter import io.sentry.spring.jakarta.webflux.SentryWebFilterWithThreadLocalAccessor @@ -10,10 +12,13 @@ import org.springframework.boot.autoconfigure.AutoConfigurations import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration import org.springframework.boot.test.context.FilteredClassLoader import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration import reactor.core.scheduler.Schedulers class SentryWebfluxAutoConfigurationTest { - private val contextRunner = + // Base context runner with performance optimizations + private val baseContextRunner = ReactiveWebApplicationContextRunner() .withConfiguration( AutoConfigurations.of( @@ -22,10 +27,39 @@ class SentryWebfluxAutoConfigurationTest { SentryAutoConfiguration::class.java, ) ) + .withPropertyValues( + // Speed up tests by reducing timeouts and disabling expensive operations + "sentry.shutdownTimeoutMillis=0", + "sentry.sessionFlushTimeoutMillis=0", + "sentry.flushTimeoutMillis=0", + "sentry.readTimeoutMillis=50", + "sentry.connectionTimeoutMillis=50", + "sentry.send-modules=false", // Disable expensive module sending + "sentry.attach-stacktrace=false", // Disable expensive stacktrace collection + "sentry.attach-threads=false", // Disable expensive thread info + "sentry.enable-backpressure-handling=false", + "sentry.enable-spotlight=false", + "sentry.debug=false", + "sentry.max-breadcrumbs=0", // Disable breadcrumb collection for performance + ) + + // Use the optimized base runner by default + private val contextRunner = + baseContextRunner.withUserConfiguration( + NoOpTransportConfiguration::class.java + ) // Use no-op transport to avoid network calls + + // Specialized context runner for tests requiring DSN + private val dsnEnabledRunner = + baseContextRunner + .withPropertyValues("sentry.dsn=http://key@localhost/proj") + .withUserConfiguration( + NoOpTransportConfiguration::class.java + ) // Use no-op transport to avoid network calls @Test fun `configures sentryWebFilter`() { - contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run { + dsnEnabledRunner.run { assertThat(it).hasSingleBean(SentryWebFilterWithThreadLocalAccessor::class.java) assertThat(it).doesNotHaveBean(SentryWebFilter::class.java) } @@ -33,9 +67,7 @@ class SentryWebfluxAutoConfigurationTest { @Test fun `configures exception handler`() { - contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run { - assertThat(it).hasSingleBean(SentryWebExceptionHandler::class.java) - } + dsnEnabledRunner.run { assertThat(it).hasSingleBean(SentryWebExceptionHandler::class.java) } } @Test @@ -59,28 +91,18 @@ class SentryWebfluxAutoConfigurationTest { @Test fun `configures web filter with ThreadLocalAccessor support if available and enabled`() { - contextRunner - .withPropertyValues( - "sentry.dsn=http://key@localhost/proj", - "sentry.reactive.thread-local-accessor-enabled=true", - ) - .run { - assertThat(it).hasSingleBean(SentryWebFilterWithThreadLocalAccessor::class.java) - assertThat(it).doesNotHaveBean(SentryWebFilter::class.java) - } + dsnEnabledRunner.withPropertyValues("sentry.reactive.thread-local-accessor-enabled=true").run { + assertThat(it).hasSingleBean(SentryWebFilterWithThreadLocalAccessor::class.java) + assertThat(it).doesNotHaveBean(SentryWebFilter::class.java) + } } @Test fun `does not configure web filter with ThreadLocalAccessor support if disabled`() { - contextRunner - .withPropertyValues( - "sentry.dsn=http://key@localhost/proj", - "sentry.reactive.thread-local-accessor-enabled=false", - ) - .run { - assertThat(it).doesNotHaveBean(SentryWebFilterWithThreadLocalAccessor::class.java) - assertThat(it).hasSingleBean(SentryWebFilter::class.java) - } + dsnEnabledRunner.withPropertyValues("sentry.reactive.thread-local-accessor-enabled=false").run { + assertThat(it).doesNotHaveBean(SentryWebFilterWithThreadLocalAccessor::class.java) + assertThat(it).hasSingleBean(SentryWebFilter::class.java) + } } @Test @@ -93,4 +115,13 @@ class SentryWebfluxAutoConfigurationTest { .withClassLoader(FilteredClassLoader(ThreadLocalAccessor::class.java)) .run { assertThat(it).doesNotHaveBean(SentryWebFilterWithThreadLocalAccessor::class.java) } } + + @Configuration(proxyBeanMethods = false) + open class NoOpTransportConfiguration { + + @Bean + open fun noOpTransportFactory(): ITransportFactory { + return NoOpTransportFactory.getInstance() + } + } } diff --git a/sentry-spring-boot/src/test/kotlin/io/sentry/spring/boot/SentryAutoConfigurationTest.kt b/sentry-spring-boot/src/test/kotlin/io/sentry/spring/boot/SentryAutoConfigurationTest.kt index 43331e8a267..45a182832d7 100644 --- a/sentry-spring-boot/src/test/kotlin/io/sentry/spring/boot/SentryAutoConfigurationTest.kt +++ b/sentry-spring-boot/src/test/kotlin/io/sentry/spring/boot/SentryAutoConfigurationTest.kt @@ -82,7 +82,8 @@ import org.springframework.web.servlet.HandlerExceptionResolver class SentryAutoConfigurationTest { - private val contextRunner = + // Base context runner with performance optimizations + private val baseContextRunner = WebApplicationContextRunner() .withConfiguration( AutoConfigurations.of( @@ -90,6 +91,42 @@ class SentryAutoConfigurationTest { WebMvcAutoConfiguration::class.java, ) ) + .withPropertyValues( + // Speed up tests by reducing timeouts and disabling expensive operations + "sentry.shutdownTimeoutMillis=0", + "sentry.sessionFlushTimeoutMillis=0", + "sentry.flushTimeoutMillis=0", + "sentry.readTimeoutMillis=50", + "sentry.connectionTimeoutMillis=50", + "sentry.send-modules=false", // Disable expensive module sending + "sentry.attach-stacktrace=false", // Disable expensive stacktrace collection + "sentry.attach-threads=false", // Disable expensive thread info + "sentry.enable-backpressure-handling=false", + "sentry.enable-spotlight=false", + "sentry.debug=false", + "sentry.max-breadcrumbs=0", // Disable breadcrumb collection for performance + ) + + // Use the optimized base runner by default + private val contextRunner = + baseContextRunner.withUserConfiguration( + NoOpTransportConfiguration::class.java + ) // Use no-op transport to avoid network calls + + // Specialized context runners for different test categories + private val dsnEnabledRunner = + baseContextRunner + .withPropertyValues("sentry.dsn=http://key@localhost/proj") + .withUserConfiguration( + NoOpTransportConfiguration::class.java + ) // Use no-op transport to avoid network calls + + private val tracingEnabledRunner = + baseContextRunner + .withPropertyValues("sentry.dsn=http://key@localhost/proj", "sentry.traces-sample-rate=1.0") + .withUserConfiguration( + NoOpTransportConfiguration::class.java + ) // Use no-op transport to avoid network calls @Test fun `scopes is not created when auto-configuration dsn is not set`() { @@ -98,22 +135,17 @@ class SentryAutoConfigurationTest { @Test fun `scopes is created when dsn is provided`() { - contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run { - assertThat(it).hasSingleBean(IScopes::class.java) - } + dsnEnabledRunner.run { assertThat(it).hasSingleBean(IScopes::class.java) } } @Test fun `OptionsConfiguration is created if custom one with name sentryOptionsConfiguration is not provided`() { - contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run { - assertThat(it).hasSingleBean(Sentry.OptionsConfiguration::class.java) - } + dsnEnabledRunner.run { assertThat(it).hasSingleBean(Sentry.OptionsConfiguration::class.java) } } @Test fun `OptionsConfiguration with name sentryOptionsConfiguration is created if another one with different name is provided`() { - contextRunner - .withPropertyValues("sentry.dsn=http://key@localhost/proj") + dsnEnabledRunner .withUserConfiguration(CustomOptionsConfigurationConfiguration::class.java) .run { assertThat(it).getBeans(Sentry.OptionsConfiguration::class.java).hasSize(2) @@ -130,19 +162,18 @@ class SentryAutoConfigurationTest { @Test fun `sentryOptionsConfiguration bean is configured before custom OptionsConfiguration`() { - contextRunner - .withPropertyValues("sentry.dsn=http://key@localhost/proj") + dsnEnabledRunner .withUserConfiguration(CustomOptionsConfigurationConfiguration::class.java) .run { val options = it.getBean(SentryOptions::class.java) assertThat(options.beforeSend).isNull() + assertThat(options.shutdownTimeoutMillis).isEqualTo(0) } } @Test fun `OptionsConfiguration is not created if custom one with name sentryOptionsConfiguration is provided`() { - contextRunner - .withPropertyValues("sentry.dsn=http://key@localhost/proj") + dsnEnabledRunner .withUserConfiguration(OverridingOptionsConfigurationConfiguration::class.java) .run { assertThat(it).hasSingleBean(Sentry.OptionsConfiguration::class.java) @@ -259,7 +290,7 @@ class SentryAutoConfigurationTest { @Test fun `when tracePropagationTargets are not set, default is returned`() { - contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run { + dsnEnabledRunner.run { val options = it.getBean(SentryProperties::class.java) assertThat(options.tracePropagationTargets).isNotNull().containsOnly(".*") } @@ -280,7 +311,7 @@ class SentryAutoConfigurationTest { @Test fun `when traces sample rate is set to null and tracing is enabled, traces sample rate should be set to 0`() { - contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run { + dsnEnabledRunner.run { val options = it.getBean(SentryProperties::class.java) assertThat(options.tracesSampleRate).isNull() } @@ -298,7 +329,7 @@ class SentryAutoConfigurationTest { @Test fun `sets sentryClientName property on SentryOptions`() { - contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run { + dsnEnabledRunner.run { assertThat(it.getBean(SentryOptions::class.java).sentryClientName) .isEqualTo("sentry.java.spring-boot/${BuildConfig.VERSION_NAME}") } @@ -306,7 +337,7 @@ class SentryAutoConfigurationTest { @Test fun `sets SDK version on sent events`() { - contextRunner + baseContextRunner .withPropertyValues("sentry.dsn=http://key@localhost/proj") .withUserConfiguration(MockTransportConfiguration::class.java) .run { @@ -422,7 +453,7 @@ class SentryAutoConfigurationTest { @Test fun `sets release on SentryEvents if Git integration is configured`() { - contextRunner + baseContextRunner .withPropertyValues("sentry.dsn=http://key@localhost/proj") .withUserConfiguration( MockTransportConfiguration::class.java, @@ -441,7 +472,7 @@ class SentryAutoConfigurationTest { @Test fun `sets custom release on SentryEvents if release property is set and Git integration is configured`() { - contextRunner + baseContextRunner .withPropertyValues("sentry.dsn=http://key@localhost/proj", "sentry.release=my-release") .withUserConfiguration( MockTransportConfiguration::class.java, @@ -532,9 +563,7 @@ class SentryAutoConfigurationTest { @Test fun `when tracing is enabled, creates tracing filter`() { - contextRunner - .withPropertyValues("sentry.dsn=http://key@localhost/proj", "sentry.traces-sample-rate=1.0") - .run { assertThat(it).hasBean("sentryTracingFilter") } + tracingEnabledRunner.run { assertThat(it).hasBean("sentryTracingFilter") } } @Test @@ -600,9 +629,7 @@ class SentryAutoConfigurationTest { @Test fun `when tracing is enabled creates AOP beans to support @SentryTransaction`() { - contextRunner - .withPropertyValues("sentry.dsn=http://key@localhost/proj", "sentry.traces-sample-rate=1.0") - .run { assertThat(it).hasSentryTransactionBeans() } + tracingEnabledRunner.run { assertThat(it).hasSentryTransactionBeans() } } @Test @@ -637,8 +664,7 @@ class SentryAutoConfigurationTest { @Test fun `when tracing is enabled and custom sentryTransactionPointcut is provided, sentryTransactionPointcut bean is not created`() { - contextRunner - .withPropertyValues("sentry.dsn=http://key@localhost/proj", "sentry.traces-sample-rate=1.0") + tracingEnabledRunner .withUserConfiguration(CustomSentryPerformancePointcutConfiguration::class.java) .run { assertThat(it).hasBean("sentryTransactionPointcut") @@ -649,9 +675,7 @@ class SentryAutoConfigurationTest { @Test fun `when tracing is enabled creates AOP beans to support @SentrySpan`() { - contextRunner - .withPropertyValues("sentry.dsn=http://key@localhost/proj", "sentry.traces-sample-rate=1.0") - .run { assertThat(it).hasSentrySpanBeans() } + tracingEnabledRunner.run { assertThat(it).hasSentrySpanBeans() } } @Test @@ -686,8 +710,7 @@ class SentryAutoConfigurationTest { @Test fun `when tracing is enabled and custom sentrySpanPointcut is provided, sentrySpanPointcut bean is not created`() { - contextRunner - .withPropertyValues("sentry.dsn=http://key@localhost/proj", "sentry.traces-sample-rate=1.0") + tracingEnabledRunner .withUserConfiguration(CustomSentryPerformancePointcutConfiguration::class.java) .run { assertThat(it).hasBean("sentrySpanPointcut") @@ -698,9 +721,9 @@ class SentryAutoConfigurationTest { @Test fun `when tracing is enabled and RestTemplate is on the classpath, SentrySpanRestTemplateCustomizer bean is created`() { - contextRunner - .withPropertyValues("sentry.dsn=http://key@localhost/proj", "sentry.traces-sample-rate=1.0") - .run { assertThat(it).hasSingleBean(SentrySpanRestTemplateCustomizer::class.java) } + tracingEnabledRunner.run { + assertThat(it).hasSingleBean(SentrySpanRestTemplateCustomizer::class.java) + } } @Test @@ -713,9 +736,9 @@ class SentryAutoConfigurationTest { @Test fun `when tracing is enabled and WebClient is on the classpath, SentrySpanWebClientCustomizer bean is created`() { - contextRunner - .withPropertyValues("sentry.dsn=http://key@localhost/proj", "sentry.traces-sample-rate=1.0") - .run { assertThat(it).hasSingleBean(SentrySpanWebClientCustomizer::class.java) } + tracingEnabledRunner.run { + assertThat(it).hasSingleBean(SentrySpanWebClientCustomizer::class.java) + } } @Test @@ -739,7 +762,7 @@ class SentryAutoConfigurationTest { @Test fun `when sentry-apache-http-client-5 is on the classpath, creates apache transport factory`() { - contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run { + baseContextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run { assertThat(it.getBean(SentryOptions::class.java).transportFactory) .isInstanceOf(ApacheHttpClientTransportFactory::class.java) } @@ -758,7 +781,7 @@ class SentryAutoConfigurationTest { @Test fun `when sentry-apache-http-client-5 is on the classpath and custom transport factory bean is set, does not create apache transport factory`() { - contextRunner + baseContextRunner .withPropertyValues("sentry.dsn=http://key@localhost/proj") .withUserConfiguration(MockTransportConfiguration::class.java) .run { @@ -1036,6 +1059,15 @@ class SentryAutoConfigurationTest { @Bean open fun sentryTransport() = transport } + @Configuration(proxyBeanMethods = false) + open class NoOpTransportConfiguration { + + @Bean + open fun noOpTransportFactory(): ITransportFactory { + return NoOpTransportFactory.getInstance() + } + } + @Configuration(proxyBeanMethods = false) open class CustomBeforeSendCallbackConfiguration { diff --git a/sentry-spring-boot/src/test/kotlin/io/sentry/spring/boot/SentryLogbackAppenderAutoConfigurationTest.kt b/sentry-spring-boot/src/test/kotlin/io/sentry/spring/boot/SentryLogbackAppenderAutoConfigurationTest.kt index d353b3629f1..f68cad0ff90 100644 --- a/sentry-spring-boot/src/test/kotlin/io/sentry/spring/boot/SentryLogbackAppenderAutoConfigurationTest.kt +++ b/sentry-spring-boot/src/test/kotlin/io/sentry/spring/boot/SentryLogbackAppenderAutoConfigurationTest.kt @@ -5,6 +5,8 @@ import ch.qos.logback.classic.Logger import ch.qos.logback.classic.LoggerContext import ch.qos.logback.classic.spi.ILoggingEvent import ch.qos.logback.core.Appender +import io.sentry.ITransportFactory +import io.sentry.NoOpTransportFactory import io.sentry.logback.SentryAppender import kotlin.test.BeforeTest import kotlin.test.Test @@ -13,10 +15,13 @@ import org.slf4j.LoggerFactory import org.springframework.boot.autoconfigure.AutoConfigurations import org.springframework.boot.test.context.FilteredClassLoader import org.springframework.boot.test.context.runner.ApplicationContextRunner +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration class SentryLogbackAppenderAutoConfigurationTest { - private val contextRunner = + // Base context runner with performance optimizations + private val baseContextRunner = ApplicationContextRunner() .withConfiguration( AutoConfigurations.of( @@ -24,6 +29,35 @@ class SentryLogbackAppenderAutoConfigurationTest { SentryAutoConfiguration::class.java, ) ) + .withPropertyValues( + // Speed up tests by reducing timeouts and disabling expensive operations + "sentry.shutdownTimeoutMillis=0", + "sentry.sessionFlushTimeoutMillis=0", + "sentry.flushTimeoutMillis=0", + "sentry.readTimeoutMillis=50", + "sentry.connectionTimeoutMillis=50", + "sentry.send-modules=false", // Disable expensive module sending + "sentry.attach-stacktrace=false", // Disable expensive stacktrace collection + "sentry.attach-threads=false", // Disable expensive thread info + "sentry.enable-backpressure-handling=false", + "sentry.enable-spotlight=false", + "sentry.debug=false", + "sentry.max-breadcrumbs=0", // Disable breadcrumb collection for performance + ) + + // Use the optimized base runner by default + private val contextRunner = + baseContextRunner.withUserConfiguration( + NoOpTransportConfiguration::class.java + ) // Use no-op transport to avoid network calls + + // Specialized context runner for tests requiring DSN + private val dsnEnabledRunner = + baseContextRunner + .withPropertyValues("sentry.dsn=http://key@localhost/proj") + .withUserConfiguration( + NoOpTransportConfiguration::class.java + ) // Use no-op transport to avoid network calls private val rootLogger = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME) as Logger @@ -40,19 +74,15 @@ class SentryLogbackAppenderAutoConfigurationTest { @Test fun `configures SentryAppender`() { - contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run { + dsnEnabledRunner.run { assertThat(rootLogger.getAppenders(SentryAppender::class.java)).hasSize(1) } } @Test fun `configures SentryAppender for configured loggers`() { - contextRunner - .withPropertyValues( - "sentry.dsn=http://key@localhost/proj", - "sentry.logging.loggers[0]=foo.bar", - "sentry.logging.loggers[1]=baz", - ) + dsnEnabledRunner + .withPropertyValues("sentry.logging.loggers[0]=foo.bar", "sentry.logging.loggers[1]=baz") .run { val fooBarLogger = LoggerFactory.getLogger("foo.bar") as Logger val bazLogger = LoggerFactory.getLogger("baz") as Logger @@ -65,23 +95,20 @@ class SentryLogbackAppenderAutoConfigurationTest { @Test fun `configures SentryAppender for none of the loggers if so configured`() { - contextRunner - .withPropertyValues("sentry.dsn=http://key@localhost/proj", "sentry.logging.loggers=") - .run { - val fooBarLogger = LoggerFactory.getLogger("foo.bar") as Logger - val bazLogger = LoggerFactory.getLogger("baz") as Logger + dsnEnabledRunner.withPropertyValues("sentry.logging.loggers=").run { + val fooBarLogger = LoggerFactory.getLogger("foo.bar") as Logger + val bazLogger = LoggerFactory.getLogger("baz") as Logger - assertThat(rootLogger.getAppenders(SentryAppender::class.java)).hasSize(0) - assertThat(fooBarLogger.getAppenders(SentryAppender::class.java)).hasSize(0) - assertThat(bazLogger.getAppenders(SentryAppender::class.java)).hasSize(0) - } + assertThat(rootLogger.getAppenders(SentryAppender::class.java)).hasSize(0) + assertThat(fooBarLogger.getAppenders(SentryAppender::class.java)).hasSize(0) + assertThat(bazLogger.getAppenders(SentryAppender::class.java)).hasSize(0) + } } @Test fun `sets SentryAppender properties`() { - contextRunner + dsnEnabledRunner .withPropertyValues( - "sentry.dsn=http://key@localhost/proj", "sentry.logging.minimum-event-level=info", "sentry.logging.minimum-breadcrumb-level=debug", "sentry.logging.minimum-level=error", @@ -113,7 +140,7 @@ class SentryLogbackAppenderAutoConfigurationTest { sentryAppender.start() rootLogger.addAppender(sentryAppender) - contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run { + dsnEnabledRunner.run { val appenders = rootLogger.getAppenders(SentryAppender::class.java) assertThat(appenders).hasSize(1) assertThat(appenders.first().name).isEqualTo("customAppender") @@ -122,7 +149,7 @@ class SentryLogbackAppenderAutoConfigurationTest { @Test fun `does not configure SentryAppender when logback is not on the classpath`() { - contextRunner + baseContextRunner .withPropertyValues("sentry.dsn=http://key@localhost/proj") .withClassLoader(FilteredClassLoader(LoggerContext::class.java)) .run { assertThat(rootLogger.getAppenders(SentryAppender::class.java)).isEmpty() } @@ -130,11 +157,20 @@ class SentryLogbackAppenderAutoConfigurationTest { @Test fun `does not configure SentryAppender when sentry-logback module is not on the classpath`() { - contextRunner + baseContextRunner .withPropertyValues("sentry.dsn=http://key@localhost/proj") .withClassLoader(FilteredClassLoader(SentryAppender::class.java)) .run { assertThat(rootLogger.getAppenders(SentryAppender::class.java)).isEmpty() } } + + @Configuration(proxyBeanMethods = false) + open class NoOpTransportConfiguration { + + @Bean + open fun noOpTransportFactory(): ITransportFactory { + return NoOpTransportFactory.getInstance() + } + } } fun Logger.getAppenders(clazz: Class): List> { diff --git a/sentry-spring-boot/src/test/kotlin/io/sentry/spring/boot/SentryWebfluxAutoConfigurationTest.kt b/sentry-spring-boot/src/test/kotlin/io/sentry/spring/boot/SentryWebfluxAutoConfigurationTest.kt index 320e8302b64..dea2c005881 100644 --- a/sentry-spring-boot/src/test/kotlin/io/sentry/spring/boot/SentryWebfluxAutoConfigurationTest.kt +++ b/sentry-spring-boot/src/test/kotlin/io/sentry/spring/boot/SentryWebfluxAutoConfigurationTest.kt @@ -1,5 +1,7 @@ package io.sentry.spring.boot +import io.sentry.ITransportFactory +import io.sentry.NoOpTransportFactory import io.sentry.spring.webflux.SentryWebExceptionHandler import io.sentry.spring.webflux.SentryWebFilter import kotlin.test.Test @@ -8,10 +10,13 @@ import org.springframework.boot.autoconfigure.AutoConfigurations import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration import org.springframework.boot.test.context.FilteredClassLoader import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration import reactor.core.scheduler.Schedulers class SentryWebfluxAutoConfigurationTest { - private val contextRunner = + // Base context runner with performance optimizations + private val baseContextRunner = ReactiveWebApplicationContextRunner() .withConfiguration( AutoConfigurations.of( @@ -20,19 +25,44 @@ class SentryWebfluxAutoConfigurationTest { SentryAutoConfiguration::class.java, ) ) + .withPropertyValues( + // Speed up tests by reducing timeouts and disabling expensive operations + "sentry.shutdownTimeoutMillis=0", + "sentry.sessionFlushTimeoutMillis=0", + "sentry.flushTimeoutMillis=0", + "sentry.readTimeoutMillis=50", + "sentry.connectionTimeoutMillis=50", + "sentry.send-modules=false", // Disable expensive module sending + "sentry.attach-stacktrace=false", // Disable expensive stacktrace collection + "sentry.attach-threads=false", // Disable expensive thread info + "sentry.enable-backpressure-handling=false", + "sentry.enable-spotlight=false", + "sentry.debug=false", + "sentry.max-breadcrumbs=0", // Disable breadcrumb collection for performance + ) + + // Use the optimized base runner by default + private val contextRunner = + baseContextRunner.withUserConfiguration( + NoOpTransportConfiguration::class.java + ) // Use no-op transport to avoid network calls + + // Specialized context runner for tests requiring DSN + private val dsnEnabledRunner = + baseContextRunner + .withPropertyValues("sentry.dsn=http://key@localhost/proj") + .withUserConfiguration( + NoOpTransportConfiguration::class.java + ) // Use no-op transport to avoid network calls @Test fun `configures sentryWebFilter`() { - contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run { - assertThat(it).hasSingleBean(SentryWebFilter::class.java) - } + dsnEnabledRunner.run { assertThat(it).hasSingleBean(SentryWebFilter::class.java) } } @Test fun `configures exception handler`() { - contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run { - assertThat(it).hasSingleBean(SentryWebExceptionHandler::class.java) - } + dsnEnabledRunner.run { assertThat(it).hasSingleBean(SentryWebExceptionHandler::class.java) } } @Test @@ -53,4 +83,13 @@ class SentryWebfluxAutoConfigurationTest { assertThat(it).doesNotHaveBean(SentryWebFilter::class.java) } } + + @Configuration(proxyBeanMethods = false) + open class NoOpTransportConfiguration { + + @Bean + open fun noOpTransportFactory(): ITransportFactory { + return NoOpTransportFactory.getInstance() + } + } } diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api index 85fdd34a503..30775f8ed7e 100644 --- a/sentry/api/sentry.api +++ b/sentry/api/sentry.api @@ -494,6 +494,8 @@ public final class io/sentry/ExternalOptions { public fun getRelease ()Ljava/lang/String; public fun getSendClientReports ()Ljava/lang/Boolean; public fun getServerName ()Ljava/lang/String; + public fun getSessionFlushTimeout ()Ljava/lang/Long; + public fun getShutdownTimeout ()Ljava/lang/Long; public fun getSpotlightConnectionUrl ()Ljava/lang/String; public fun getTags ()Ljava/util/Map; public fun getTracePropagationTargets ()Ljava/util/List; @@ -537,6 +539,8 @@ public final class io/sentry/ExternalOptions { public fun setSendDefaultPii (Ljava/lang/Boolean;)V public fun setSendModules (Ljava/lang/Boolean;)V public fun setServerName (Ljava/lang/String;)V + public fun setSessionFlushTimeout (Ljava/lang/Long;)V + public fun setShutdownTimeout (Ljava/lang/Long;)V public fun setSpotlightConnectionUrl (Ljava/lang/String;)V public fun setTag (Ljava/lang/String;Ljava/lang/String;)V public fun setTracesSampleRate (Ljava/lang/Double;)V diff --git a/sentry/src/main/java/io/sentry/ExternalOptions.java b/sentry/src/main/java/io/sentry/ExternalOptions.java index 3e40d05543d..cb1671b6f14 100644 --- a/sentry/src/main/java/io/sentry/ExternalOptions.java +++ b/sentry/src/main/java/io/sentry/ExternalOptions.java @@ -34,6 +34,8 @@ public final class ExternalOptions { private final @NotNull List contextTags = new CopyOnWriteArrayList<>(); private @Nullable String proguardUuid; private @Nullable Long idleTimeout; + private @Nullable Long shutdownTimeout; + private @Nullable Long sessionFlushTimeout; private final @NotNull Set> ignoredExceptionsForType = new CopyOnWriteArraySet<>(); private @Nullable List ignoredErrors; @@ -129,6 +131,8 @@ public final class ExternalOptions { options.addBundleId(bundleId); } options.setIdleTimeout(propertiesProvider.getLongProperty("idle-timeout")); + options.setShutdownTimeout(propertiesProvider.getLongProperty("shutdown-timeout")); + options.setSessionFlushTimeout(propertiesProvider.getLongProperty("session-flush-timeout")); options.setIgnoredErrors(propertiesProvider.getListOrNull("ignored-errors")); @@ -380,6 +384,22 @@ public void setIdleTimeout(final @Nullable Long idleTimeout) { this.idleTimeout = idleTimeout; } + public @Nullable Long getShutdownTimeout() { + return shutdownTimeout; + } + + public void setShutdownTimeout(final @Nullable Long shutdownTimeout) { + this.shutdownTimeout = shutdownTimeout; + } + + public @Nullable Long getSessionFlushTimeout() { + return sessionFlushTimeout; + } + + public void setSessionFlushTimeout(final @Nullable Long sessionFlushTimeout) { + this.sessionFlushTimeout = sessionFlushTimeout; + } + public @Nullable List getIgnoredErrors() { return ignoredErrors; } diff --git a/sentry/src/main/java/io/sentry/SentryOptions.java b/sentry/src/main/java/io/sentry/SentryOptions.java index 419094067a5..8dadf6452d6 100644 --- a/sentry/src/main/java/io/sentry/SentryOptions.java +++ b/sentry/src/main/java/io/sentry/SentryOptions.java @@ -3211,6 +3211,12 @@ public void merge(final @NotNull ExternalOptions options) { if (options.getIdleTimeout() != null) { setIdleTimeout(options.getIdleTimeout()); } + if (options.getShutdownTimeout() != null) { + setShutdownTimeoutMillis(options.getShutdownTimeout()); + } + if (options.getSessionFlushTimeout() != null) { + setSessionFlushTimeoutMillis(options.getSessionFlushTimeout()); + } for (String bundleId : options.getBundleIds()) { addBundleId(bundleId); } diff --git a/sentry/src/test/java/io/sentry/ExternalOptionsTest.kt b/sentry/src/test/java/io/sentry/ExternalOptionsTest.kt index ddb8e2cebf3..8002b4af231 100644 --- a/sentry/src/test/java/io/sentry/ExternalOptionsTest.kt +++ b/sentry/src/test/java/io/sentry/ExternalOptionsTest.kt @@ -175,6 +175,16 @@ class ExternalOptionsTest { withPropertiesFile("idle-timeout=2000") { assertEquals(2000L, it.idleTimeout) } } + @Test + fun `creates options with shutdownTimeout using external properties`() { + withPropertiesFile("shutdown-timeout=2000") { assertEquals(2000L, it.shutdownTimeout) } + } + + @Test + fun `creates options with sessionFlushTimeout using external properties`() { + withPropertiesFile("session-flush-timeout=2000") { assertEquals(2000L, it.sessionFlushTimeout) } + } + @Test fun `creates options with ignored exception types using external properties`() { val logger = mock() diff --git a/sentry/src/test/java/io/sentry/SentryOptionsTest.kt b/sentry/src/test/java/io/sentry/SentryOptionsTest.kt index 469b2f4b160..d396ce2124e 100644 --- a/sentry/src/test/java/io/sentry/SentryOptionsTest.kt +++ b/sentry/src/test/java/io/sentry/SentryOptionsTest.kt @@ -384,6 +384,8 @@ class SentryOptionsTest { externalOptions.addContextTag("requestId") externalOptions.proguardUuid = "1234" externalOptions.idleTimeout = 1500L + externalOptions.shutdownTimeout = 1499L + externalOptions.sessionFlushTimeout = 1498L externalOptions.bundleIds.addAll( listOf("12ea7a02-46ac-44c0-a5bb-6d1fd9586411 ", " faa3ab42-b1bd-4659-af8e-1682324aa744") ) @@ -433,6 +435,8 @@ class SentryOptionsTest { assertEquals(listOf("userId", "requestId"), options.contextTags) assertEquals("1234", options.proguardUuid) assertEquals(1500L, options.idleTimeout) + assertEquals(1499L, options.shutdownTimeoutMillis) + assertEquals(1498L, options.sessionFlushTimeoutMillis) assertEquals( setOf("12ea7a02-46ac-44c0-a5bb-6d1fd9586411", "faa3ab42-b1bd-4659-af8e-1682324aa744"), options.bundleIds,