Skip to content

Commit 6ce2c7d

Browse files
Convert TestKitBase and TestProbe to async (#5852)
Co-authored-by: Aaron Stannard <[email protected]>
1 parent bbcbf34 commit 6ce2c7d

File tree

2 files changed

+175
-54
lines changed

2 files changed

+175
-54
lines changed

src/core/Akka.TestKit/TestKitBase.cs

Lines changed: 108 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
using Akka.Actor.Setup;
1616
using Akka.Configuration;
1717
using Akka.Event;
18-
using Akka.Pattern;
18+
using Akka.TestKit.Extensions;
1919
using Akka.TestKit.Internal;
2020
using Akka.Util;
2121
using Akka.Util.Internal;
@@ -189,6 +189,7 @@ protected void InitializeTest(ActorSystem system, ActorSystemSetup config, strin
189189
}
190190

191191
[MethodImpl(MethodImplOptions.AggressiveInlining)]
192+
// Do not convert this method to async, it is being called inside the constructor.
192193
private static void WaitUntilTestActorIsReady(IActorRef testActor)
193194
{
194195
var deadline = TimeSpan.FromSeconds(5);
@@ -485,10 +486,32 @@ public TimeSpan GetTimeoutOrDefault(TimeSpan? timeout)
485486
/// </summary>
486487
/// <param name="duration">Optional. The duration to wait for shutdown. Default is 5 seconds multiplied with the config value "akka.test.timefactor".</param>
487488
/// <param name="verifySystemShutdown">if set to <c>true</c> an exception will be thrown on failure.</param>
488-
public virtual void Shutdown(TimeSpan? duration = null, bool verifySystemShutdown = false)
489-
{
490-
Shutdown(_testState.System, duration, verifySystemShutdown);
491-
}
489+
/// <param name="cancellationToken"><see cref="CancellationToken"/> to cancel the operation</param>
490+
/// <exception cref="TimeoutException">TBD</exception>
491+
public virtual void Shutdown(
492+
TimeSpan? duration = null,
493+
bool verifySystemShutdown = false,
494+
CancellationToken cancellationToken = default)
495+
=> ShutdownAsync(_testState.System, duration, verifySystemShutdown, cancellationToken)
496+
.ConfigureAwait(false).GetAwaiter().GetResult();
497+
498+
/// <summary>
499+
/// Shuts down the specified system.
500+
/// On failure debug output will be logged about the remaining actors in the system.
501+
/// If verifySystemShutdown is true, then an exception will be thrown on failure.
502+
/// </summary>
503+
/// <param name="system">The system to shutdown.</param>
504+
/// <param name="duration">The duration to wait for shutdown. Default is 5 seconds multiplied with the config value "akka.test.timefactor"</param>
505+
/// <param name="verifySystemShutdown">if set to <c>true</c> an exception will be thrown on failure.</param>
506+
/// <param name="cancellationToken"><see cref="CancellationToken"/> to cancel the operation</param>
507+
/// <exception cref="TimeoutException">TBD</exception>
508+
protected virtual void Shutdown(
509+
ActorSystem system,
510+
TimeSpan? duration = null,
511+
bool verifySystemShutdown = false,
512+
CancellationToken cancellationToken = default)
513+
=> ShutdownAsync(system, duration, verifySystemShutdown, cancellationToken)
514+
.ConfigureAwait(false).GetAwaiter().GetResult();
492515

493516
/// <summary>
494517
/// Shuts down the specified system.
@@ -498,20 +521,24 @@ public virtual void Shutdown(TimeSpan? duration = null, bool verifySystemShutdow
498521
/// <param name="system">The system to shutdown.</param>
499522
/// <param name="duration">The duration to wait for shutdown. Default is 5 seconds multiplied with the config value "akka.test.timefactor"</param>
500523
/// <param name="verifySystemShutdown">if set to <c>true</c> an exception will be thrown on failure.</param>
524+
/// <param name="cancellationToken"><see cref="CancellationToken"/> to cancel the operation</param>
501525
/// <exception cref="TimeoutException">TBD</exception>
502-
protected virtual void Shutdown(ActorSystem system, TimeSpan? duration = null, bool verifySystemShutdown = false)
526+
protected virtual async Task ShutdownAsync(
527+
ActorSystem system,
528+
TimeSpan? duration = null,
529+
bool verifySystemShutdown = false,
530+
CancellationToken cancellationToken = default)
503531
{
504-
if (system == null) system = _testState.System;
532+
system ??= _testState.System;
505533

506534
var durationValue = duration.GetValueOrDefault(Dilated(TimeSpan.FromSeconds(5)).Min(TimeSpan.FromSeconds(10)));
507535

508-
var wasShutdownDuringWait = system.Terminate().Wait(durationValue);
536+
var wasShutdownDuringWait = await system.Terminate().AwaitWithTimeout(durationValue, cancellationToken);
509537
if(!wasShutdownDuringWait)
510538
{
511539
const string msg = "Failed to stop [{0}] within [{1}] \n{2}";
512540
if(verifySystemShutdown)
513541
throw new TimeoutException(string.Format(msg, system.Name, durationValue, ""));
514-
//TODO: replace "" with system.PrintTree()
515542
system.Log.Warning(msg, system.Name, durationValue, ""); //TODO: replace "" with system.PrintTree()
516543
}
517544
}
@@ -522,46 +549,109 @@ protected virtual void Shutdown(ActorSystem system, TimeSpan? duration = null, b
522549
/// <param name="props">Child actor props</param>
523550
/// <param name="name">Child actor name</param>
524551
/// <param name="supervisorStrategy">Supervisor strategy for the child actor</param>
552+
/// <param name="cancellationToken"><see cref="CancellationToken"/> to cancel the operation</param>
525553
/// <returns></returns>
526-
public IActorRef ChildActorOf(Props props, string name, SupervisorStrategy supervisorStrategy)
554+
public IActorRef ChildActorOf(
555+
Props props,
556+
string name,
557+
SupervisorStrategy supervisorStrategy,
558+
CancellationToken cancellationToken = default)
559+
=> ChildActorOfAsync(props, name, supervisorStrategy, cancellationToken)
560+
.ConfigureAwait(false).GetAwaiter().GetResult();
561+
562+
/// <summary>
563+
/// Spawns an actor as a child of this test actor, and returns the child's IActorRef
564+
/// </summary>
565+
/// <param name="props">Child actor props</param>
566+
/// <param name="name">Child actor name</param>
567+
/// <param name="supervisorStrategy">Supervisor strategy for the child actor</param>
568+
/// <param name="cancellationToken"><see cref="CancellationToken"/> to cancel the operation</param>
569+
/// <returns></returns>
570+
public async Task<IActorRef> ChildActorOfAsync(
571+
Props props,
572+
string name,
573+
SupervisorStrategy supervisorStrategy,
574+
CancellationToken cancellationToken = default)
527575
{
528576
TestActor.Tell(new TestActor.Spawn(props, name, supervisorStrategy));
529-
return ExpectMsg<IActorRef>();
577+
return await ExpectMsgAsync<IActorRef>(cancellationToken: cancellationToken)
578+
.ConfigureAwait(false);
530579
}
531-
580+
532581
/// <summary>
533582
/// Spawns an actor as a child of this test actor with an auto-generated name, and returns the child's ActorRef.
534583
/// </summary>
535584
/// <param name="props">Child actor props</param>
536585
/// <param name="supervisorStrategy">Supervisor strategy for the child actor</param>
586+
/// <param name="cancellationToken"><see cref="CancellationToken"/> to cancel the operation</param>
537587
/// <returns></returns>
538-
public IActorRef ChildActorOf(Props props, SupervisorStrategy supervisorStrategy)
588+
public IActorRef ChildActorOf(
589+
Props props, SupervisorStrategy supervisorStrategy, CancellationToken cancellationToken = default)
590+
=> ChildActorOfAsync(props, supervisorStrategy, cancellationToken)
591+
.ConfigureAwait(false).GetAwaiter().GetResult();
592+
593+
/// <summary>
594+
/// Spawns an actor as a child of this test actor with an auto-generated name, and returns the child's ActorRef.
595+
/// </summary>
596+
/// <param name="props">Child actor props</param>
597+
/// <param name="supervisorStrategy">Supervisor strategy for the child actor</param>
598+
/// <param name="cancellationToken"><see cref="CancellationToken"/> to cancel the operation</param>
599+
/// <returns></returns>
600+
public async Task<IActorRef> ChildActorOfAsync(
601+
Props props, SupervisorStrategy supervisorStrategy, CancellationToken cancellationToken = default)
539602
{
540603
TestActor.Tell(new TestActor.Spawn(props, Option<string>.None, supervisorStrategy));
541-
return ExpectMsg<IActorRef>();
604+
return await ExpectMsgAsync<IActorRef>(cancellationToken: cancellationToken)
605+
.ConfigureAwait(false);
542606
}
607+
608+
/// <summary>
609+
/// Spawns an actor as a child of this test actor with a stopping supervisor strategy, and returns the child's ActorRef.
610+
/// </summary>
611+
/// <param name="props">Child actor props</param>
612+
/// <param name="name">Child actor name</param>
613+
/// <param name="cancellationToken"><see cref="CancellationToken"/> to cancel the operation</param>
614+
/// <returns></returns>
615+
public IActorRef ChildActorOf(Props props, string name, CancellationToken cancellationToken = default)
616+
=> ChildActorOfAsync(props, name, cancellationToken)
617+
.ConfigureAwait(false).GetAwaiter().GetResult();
543618

544619
/// <summary>
545620
/// Spawns an actor as a child of this test actor with a stopping supervisor strategy, and returns the child's ActorRef.
546621
/// </summary>
547622
/// <param name="props">Child actor props</param>
548623
/// <param name="name">Child actor name</param>
624+
/// <param name="cancellationToken"><see cref="CancellationToken"/> to cancel the operation</param>
549625
/// <returns></returns>
550-
public IActorRef ChildActorOf(Props props, string name)
626+
public async Task<IActorRef> ChildActorOfAsync(
627+
Props props, string name, CancellationToken cancellationToken = default)
551628
{
552629
TestActor.Tell(new TestActor.Spawn(props, name, Option<SupervisorStrategy>.None));
553-
return ExpectMsg<IActorRef>();
630+
return await ExpectMsgAsync<IActorRef>(cancellationToken: cancellationToken)
631+
.ConfigureAwait(false);
554632
}
555633

556634
/// <summary>
557635
/// Spawns an actor as a child of this test actor with an auto-generated name and stopping supervisor strategy, returning the child's ActorRef.
558636
/// </summary>
559637
/// <param name="props">Child actor props</param>
638+
/// <param name="cancellationToken"><see cref="CancellationToken"/> to cancel the operation</param>
639+
/// <returns></returns>
640+
public IActorRef ChildActorOf(Props props, CancellationToken cancellationToken = default)
641+
=> ChildActorOfAsync(props, cancellationToken)
642+
.ConfigureAwait(false).GetAwaiter().GetResult();
643+
644+
/// <summary>
645+
/// Spawns an actor as a child of this test actor with an auto-generated name and stopping supervisor strategy, returning the child's ActorRef.
646+
/// </summary>
647+
/// <param name="props">Child actor props</param>
648+
/// <param name="cancellationToken"><see cref="CancellationToken"/> to cancel the operation</param>
560649
/// <returns></returns>
561-
public IActorRef ChildActorOf(Props props)
650+
public async Task<IActorRef> ChildActorOfAsync(Props props, CancellationToken cancellationToken = default)
562651
{
563652
TestActor.Tell(new TestActor.Spawn(props, Option<string>.None, Option<SupervisorStrategy>.None));
564-
return ExpectMsg<IActorRef>();
653+
return await ExpectMsgAsync<IActorRef>(cancellationToken: cancellationToken)
654+
.ConfigureAwait(false);
565655
}
566656

567657
/// <summary>

src/core/Akka.TestKit/TestProbe.cs

Lines changed: 67 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
using System;
99
using System.Collections.Generic;
10+
using System.Threading;
11+
using System.Threading.Tasks;
1012
using Akka.Actor;
1113
using Akka.Dispatch.SysMsg;
1214
using Akka.Util;
@@ -167,70 +169,99 @@ public void SendSystemMessage(ISystemMessage message, IActorRef sender)
167169
/// <summary>
168170
/// Spawns an actor as a child of this test actor, and returns the child's ActorRef.
169171
/// </summary>
170-
/// <param name="props"></param>
171172
/// <param name="name"></param>
172173
/// <param name="supervisorStrategy"></param>
174+
/// <param name="cancellationToken"><see cref="CancellationToken"/> to cancel the operation</param>
173175
/// <returns></returns>
174-
public IActorRef ChildActorOf(Props props, String name, SupervisorStrategy supervisorStrategy)
175-
{
176-
return ((TestKitBase)this).ChildActorOf(props, name, supervisorStrategy);
177-
}
176+
public IActorRef ChildActorOf<T>(
177+
string name,
178+
SupervisorStrategy supervisorStrategy,
179+
CancellationToken cancellationToken = default)
180+
where T : ActorBase
181+
=> ChildActorOfAsync(Props.Create<T>(), name, supervisorStrategy, cancellationToken)
182+
.ConfigureAwait(false).GetAwaiter().GetResult();
178183

179-
public IActorRef ChildActorOf<T>(String name, SupervisorStrategy supervisorStrategy)
184+
/// <summary>
185+
/// Spawns an actor as a child of this test actor, and returns the child's ActorRef.
186+
/// </summary>
187+
/// <param name="name"></param>
188+
/// <param name="supervisorStrategy"></param>
189+
/// <param name="cancellationToken"><see cref="CancellationToken"/> to cancel the operation</param>
190+
/// <returns></returns>
191+
public async Task<IActorRef> ChildActorOfAsync<T>(
192+
string name,
193+
SupervisorStrategy supervisorStrategy,
194+
CancellationToken cancellationToken = default)
180195
where T : ActorBase
181-
{
182-
return ((TestKitBase)this).ChildActorOf(Props.Create<T>(), name, supervisorStrategy);
183-
}
196+
=> await ChildActorOfAsync(Props.Create<T>(), name, supervisorStrategy, cancellationToken)
197+
.ConfigureAwait(false);
198+
184199

185200
/// <summary>
186201
/// Spawns an actor as a child of this test actor, and returns the child's ActorRef.
187202
/// </summary>
188-
/// <param name="props"></param>
189203
/// <param name="supervisorStrategy"></param>
204+
/// <param name="cancellationToken"><see cref="CancellationToken"/> to cancel the operation</param>
190205
/// <returns></returns>
191-
public IActorRef ChildActorOf(Props props, SupervisorStrategy supervisorStrategy)
192-
{
193-
return ((TestKitBase)this).ChildActorOf(props, supervisorStrategy);
194-
}
206+
public IActorRef ChildActorOf<T>(
207+
SupervisorStrategy supervisorStrategy, CancellationToken cancellationToken = default)
208+
where T : ActorBase
209+
=> ChildActorOfAsync(Props.Create<T>(), supervisorStrategy, cancellationToken)
210+
.ConfigureAwait(false).GetAwaiter().GetResult();
195211

196-
public IActorRef ChildActorOf<T>(SupervisorStrategy supervisorStrategy)
212+
/// <summary>
213+
/// Spawns an actor as a child of this test actor, and returns the child's ActorRef.
214+
/// </summary>
215+
/// <param name="supervisorStrategy"></param>
216+
/// <param name="cancellationToken"><see cref="CancellationToken"/> to cancel the operation</param>
217+
/// <returns></returns>
218+
public async Task<IActorRef> ChildActorOfAsync<T>(
219+
SupervisorStrategy supervisorStrategy, CancellationToken cancellationToken = default)
197220
where T : ActorBase
198-
{
199-
return ((TestKitBase)this).ChildActorOf(Props.Create<T>(), supervisorStrategy);
200-
}
221+
=> await ChildActorOfAsync(Props.Create<T>(), supervisorStrategy, cancellationToken)
222+
.ConfigureAwait(false);
201223

202224
/// <summary>
203225
/// Spawns an actor as a child of this test actor, and returns the child's ActorRef.
204226
/// </summary>
205-
/// <param name="props"></param>
206227
/// <param name="name"></param>
228+
/// <param name="cancellationToken"><see cref="CancellationToken"/> to cancel the operation</param>
207229
/// <returns></returns>
208-
public IActorRef ChildActorOf(Props props, String name)
209-
{
210-
return ((TestKitBase)this).ChildActorOf(props, name);
211-
}
230+
public IActorRef ChildActorOf<T>(string name, CancellationToken cancellationToken = default)
231+
where T : ActorBase
232+
=> ChildActorOfAsync(Props.Create<T>(), name, cancellationToken)
233+
.ConfigureAwait(false).GetAwaiter().GetResult();
212234

213-
public IActorRef ChildActorOf<T>(String name)
235+
/// <summary>
236+
/// Spawns an actor as a child of this test actor, and returns the child's ActorRef.
237+
/// </summary>
238+
/// <param name="name"></param>
239+
/// <param name="cancellationToken"><see cref="CancellationToken"/> to cancel the operation</param>
240+
/// <returns></returns>
241+
public async Task<IActorRef> ChildActorOfAsync<T>(string name, CancellationToken cancellationToken = default)
214242
where T : ActorBase
215-
{
216-
return ((TestKitBase)this).ChildActorOf(Props.Create<T>(), name);
217-
}
243+
=> await ChildActorOfAsync(Props.Create<T>(), name, cancellationToken)
244+
.ConfigureAwait(false);
218245

219246
/// <summary>
220247
/// Spawns an actor as a child of this test actor, and returns the child's ActorRef.
221248
/// </summary>
222-
/// <param name="props"></param>
249+
/// <param name="cancellationToken"><see cref="CancellationToken"/> to cancel the operation</param>
223250
/// <returns></returns>
224-
public IActorRef ChildActorOf(Props props)
225-
{
226-
return ((TestKitBase)this).ChildActorOf(props);
227-
}
251+
public IActorRef ChildActorOf<T>(CancellationToken cancellationToken = default)
252+
where T : ActorBase
253+
=> ChildActorOfAsync(Props.Create<T>(), cancellationToken)
254+
.ConfigureAwait(false).GetAwaiter().GetResult();
228255

229-
public IActorRef ChildActorOf<T>()
256+
/// <summary>
257+
/// Spawns an actor as a child of this test actor, and returns the child's ActorRef.
258+
/// </summary>
259+
/// <param name="cancellationToken"><see cref="CancellationToken"/> to cancel the operation</param>
260+
/// <returns></returns>
261+
public async Task<IActorRef> ChildActorOfAsync<T>(CancellationToken cancellationToken = default)
230262
where T : ActorBase
231-
{
232-
return ((TestKitBase)this).ChildActorOf(Props.Create<T>());
233-
}
263+
=> await ChildActorOfAsync(Props.Create<T>(), cancellationToken)
264+
.ConfigureAwait(false);
234265

235266
/// <summary>
236267
/// Sends a system message to the test probe

0 commit comments

Comments
 (0)