From 1b2e3ab0b84b023eb8680636eeb69184bbfd933d Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Thu, 19 Dec 2024 13:28:01 -0600 Subject: [PATCH] Make TestKit startup timeouts configurable (#7423) * Added `startup-timeout` property to `TestKitSettings` * integrated testkit timeout into xUnit2 and testkit base close #7259 * API approvals and tests --- .../testkits/Akka.TestKit.Xunit2/TestKit.cs | 4 +-- ...APISpec.ApproveTestKit.DotNet.verified.txt | 1 + ...oreAPISpec.ApproveTestKit.Net.verified.txt | 1 + .../TestKit_Config_Tests.cs | 1 + .../Akka.TestKit/Configs/TestScheduler.conf | 1 + src/core/Akka.TestKit/Internal/Reference.conf | 4 +++ src/core/Akka.TestKit/TestKitBase.cs | 6 ++-- src/core/Akka.TestKit/TestKitSettings.cs | 33 +++++++++---------- 8 files changed, 28 insertions(+), 23 deletions(-) diff --git a/src/contrib/testkits/Akka.TestKit.Xunit2/TestKit.cs b/src/contrib/testkits/Akka.TestKit.Xunit2/TestKit.cs index 0c638a4043d..6f4d219761b 100644 --- a/src/contrib/testkits/Akka.TestKit.Xunit2/TestKit.cs +++ b/src/contrib/testkits/Akka.TestKit.Xunit2/TestKit.cs @@ -142,7 +142,7 @@ protected void InitializeLogger(ActorSystem system) { var extSystem = (ExtendedActorSystem)system; var logger = extSystem.SystemActorOf(Props.Create(() => new TestOutputLogger(Output)), "log-test"); - logger.Ask(new InitializeLogger(system.EventStream), TimeSpan.FromSeconds(3)) + logger.Ask(new InitializeLogger(system.EventStream), TestKitSettings.TestKitStartupTimeout) .ConfigureAwait(false).GetAwaiter().GetResult(); } } @@ -154,7 +154,7 @@ protected void InitializeLogger(ActorSystem system, string prefix) var extSystem = (ExtendedActorSystem)system; var logger = extSystem.SystemActorOf(Props.Create(() => new TestOutputLogger( string.IsNullOrEmpty(prefix) ? Output : new PrefixedOutput(Output, prefix))), "log-test"); - logger.Ask(new InitializeLogger(system.EventStream), TimeSpan.FromSeconds(3)) + logger.Ask(new InitializeLogger(system.EventStream), TestKitSettings.TestKitStartupTimeout) .ConfigureAwait(false).GetAwaiter().GetResult(); } } diff --git a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveTestKit.DotNet.verified.txt b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveTestKit.DotNet.verified.txt index 55cff536c32..8ea957fa160 100644 --- a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveTestKit.DotNet.verified.txt +++ b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveTestKit.DotNet.verified.txt @@ -522,6 +522,7 @@ namespace Akka.TestKit public bool LogTestKitCalls { get; } public System.TimeSpan SingleExpectDefault { get; } public System.TimeSpan TestEventFilterLeeway { get; } + public System.TimeSpan TestKitStartupTimeout { get; } public double TestTimeFactor { get; } } public class TestLatch diff --git a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveTestKit.Net.verified.txt b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveTestKit.Net.verified.txt index 681fff75319..92d61d46c37 100644 --- a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveTestKit.Net.verified.txt +++ b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveTestKit.Net.verified.txt @@ -522,6 +522,7 @@ namespace Akka.TestKit public bool LogTestKitCalls { get; } public System.TimeSpan SingleExpectDefault { get; } public System.TimeSpan TestEventFilterLeeway { get; } + public System.TimeSpan TestKitStartupTimeout { get; } public double TestTimeFactor { get; } } public class TestLatch diff --git a/src/core/Akka.TestKit.Tests/TestKit_Config_Tests.cs b/src/core/Akka.TestKit.Tests/TestKit_Config_Tests.cs index 11aa60c717e..c64abe904e9 100644 --- a/src/core/Akka.TestKit.Tests/TestKit_Config_Tests.cs +++ b/src/core/Akka.TestKit.Tests/TestKit_Config_Tests.cs @@ -21,6 +21,7 @@ public void DefaultValues_should_be_correct() TestKitSettings.SingleExpectDefault.ShouldBe(TimeSpan.FromSeconds(3)); TestKitSettings.TestEventFilterLeeway.ShouldBe(TimeSpan.FromSeconds(3)); TestKitSettings.TestTimeFactor.ShouldBe(1); + TestKitSettings.TestKitStartupTimeout.ShouldBe(TimeSpan.FromSeconds(5)); var callingThreadDispatcherTypeName = typeof(CallingThreadDispatcherConfigurator).FullName + ", " + typeof(CallingThreadDispatcher).Assembly.GetName().Name; Assert.False(Sys.Settings.Config.IsEmpty); Sys.Settings.Config.GetString("akka.test.calling-thread-dispatcher.type", null).ShouldBe(callingThreadDispatcherTypeName); diff --git a/src/core/Akka.TestKit/Configs/TestScheduler.conf b/src/core/Akka.TestKit/Configs/TestScheduler.conf index cfbcf17ea2c..4e1c983cd38 100644 --- a/src/core/Akka.TestKit/Configs/TestScheduler.conf +++ b/src/core/Akka.TestKit/Configs/TestScheduler.conf @@ -31,6 +31,7 @@ akka { # The timeout that is added as an implicit by DefaultTimeout trait # This is used for Ask-pattern default-timeout = 5s + calling-thread-dispatcher { type = "Akka.TestKit.CallingThreadDispatcherConfigurator, Akka.TestKit" diff --git a/src/core/Akka.TestKit/Internal/Reference.conf b/src/core/Akka.TestKit/Internal/Reference.conf index b5e18e3e159..cf079e06962 100644 --- a/src/core/Akka.TestKit/Internal/Reference.conf +++ b/src/core/Akka.TestKit/Internal/Reference.conf @@ -26,6 +26,10 @@ akka { # The timeout that is added as an implicit by DefaultTimeout trait # This is used for Ask-pattern default-timeout = 5s + + # The amount of time it takes the testkit to startup + # Increase this value if you're running many tests in parallel + startup-timeout = 5s calling-thread-dispatcher { type = "Akka.TestKit.CallingThreadDispatcherConfigurator, Akka.TestKit" diff --git a/src/core/Akka.TestKit/TestKitBase.cs b/src/core/Akka.TestKit/TestKitBase.cs index e8ac33f0f96..d6d3fc3f93c 100644 --- a/src/core/Akka.TestKit/TestKitBase.cs +++ b/src/core/Akka.TestKit/TestKitBase.cs @@ -173,7 +173,7 @@ protected virtual void InitializeTest(ActorSystem system, ActorSystemSetup confi var testActor = CreateTestActor(system, testActorName); // Wait for the testactor to start - WaitUntilTestActorIsReady(testActor); + WaitUntilTestActorIsReady(testActor, _testState.TestKitSettings); if (this is not INoImplicitSender) { @@ -193,9 +193,9 @@ protected virtual void InitializeTest(ActorSystem system, ActorSystemSetup confi [MethodImpl(MethodImplOptions.AggressiveInlining)] // Do not convert this method to async, it is being called inside the constructor. - private static void WaitUntilTestActorIsReady(IActorRef testActor) + private static void WaitUntilTestActorIsReady(IActorRef testActor, TestKitSettings settings) { - var deadline = TimeSpan.FromSeconds(5); + var deadline = settings.TestKitStartupTimeout; var stopwatch = Stopwatch.StartNew(); var ready = false; try diff --git a/src/core/Akka.TestKit/TestKitSettings.cs b/src/core/Akka.TestKit/TestKitSettings.cs index 82bd2da0a72..f31cd4b03c4 100644 --- a/src/core/Akka.TestKit/TestKitSettings.cs +++ b/src/core/Akka.TestKit/TestKitSettings.cs @@ -16,12 +16,6 @@ namespace Akka.TestKit /// public class TestKitSettings : IExtension { - private readonly TimeSpan _defaultTimeout; - private readonly TimeSpan _singleExpectDefault; - private readonly TimeSpan _testEventFilterLeeway; - private readonly double _timefactor; - private readonly bool _logTestKitCalls; - /// /// Initializes a new instance of the class. /// @@ -34,14 +28,15 @@ public TestKitSettings(Config config) if (config.IsNullOrEmpty()) throw ConfigurationException.NullOrEmptyConfig(); - _defaultTimeout = config.GetTimeSpan("akka.test.default-timeout", null, allowInfinite:false); - _singleExpectDefault = config.GetTimeSpan("akka.test.single-expect-default", null, allowInfinite: false); - _testEventFilterLeeway = config.GetTimeSpan("akka.test.filter-leeway", null, allowInfinite: false); - _timefactor = config.GetDouble("akka.test.timefactor", 0); - _logTestKitCalls = config.GetBoolean("akka.test.testkit.debug", false); + DefaultTimeout = config.GetTimeSpan("akka.test.default-timeout", null, allowInfinite:false); + SingleExpectDefault = config.GetTimeSpan("akka.test.single-expect-default", null, allowInfinite: false); + TestKitStartupTimeout = config.GetTimeSpan("akka.test.startup-timeout", null, allowInfinite: false); + TestEventFilterLeeway = config.GetTimeSpan("akka.test.filter-leeway", null, allowInfinite: false); + TestTimeFactor = config.GetDouble("akka.test.timefactor", 0); + LogTestKitCalls = config.GetBoolean("akka.test.testkit.debug", false); - if(_timefactor <= 0) - throw new ConfigurationException($@"Expected a positive value for ""akka.test.timefactor"" but found {_timefactor}"); + if(TestTimeFactor <= 0) + throw new ConfigurationException($@"Expected a positive value for ""akka.test.timefactor"" but found {TestTimeFactor}"); } @@ -49,13 +44,15 @@ public TestKitSettings(Config config) /// Gets the default timeout as specified in the setting akka.test.default-timeout. /// Typically used for Ask-timeouts. It is always finite. /// - public TimeSpan DefaultTimeout { get { return _defaultTimeout; } } + public TimeSpan DefaultTimeout { get; } /// Gets the config value "akka.test.single-expect-default". It is always finite. - public TimeSpan SingleExpectDefault { get { return _singleExpectDefault; } } + public TimeSpan SingleExpectDefault { get; } /// Gets the config value "akka.test.filter-leeway". It is always finite. - public TimeSpan TestEventFilterLeeway { get { return _testEventFilterLeeway; } } + public TimeSpan TestEventFilterLeeway { get; } + + public TimeSpan TestKitStartupTimeout { get; } /// /// Gets the timefactor by which all values are scaled by. @@ -70,12 +67,12 @@ public TestKitSettings(Config config) /// Testkit.Dilated /// /// - public double TestTimeFactor { get { return _timefactor; } } + public double TestTimeFactor { get; } /// /// If set to true calls to testkit will be logged. /// This is enabled by setting the configuration value "akka.test.testkit.debug" to a true. /// - public bool LogTestKitCalls { get { return _logTestKitCalls; } } + public bool LogTestKitCalls { get; } } }