diff --git a/src/core/Akka.TestKit/EventFilter/IEventFilterApplier.cs b/src/core/Akka.TestKit/EventFilter/IEventFilterApplier.cs index 5c6f982d76b..fe47d462522 100644 --- a/src/core/Akka.TestKit/EventFilter/IEventFilterApplier.cs +++ b/src/core/Akka.TestKit/EventFilter/IEventFilterApplier.cs @@ -6,6 +6,7 @@ //----------------------------------------------------------------------- using System; +using System.Threading; using System.Threading.Tasks; namespace Akka.TestKit @@ -24,8 +25,9 @@ public interface IEventFilterApplier /// "akka.test.filter-leeway", see . /// /// The action. - void ExpectOne(Action action); - + /// + void ExpectOne(Action action, CancellationToken cancellationToken = default); + /// /// Executes and /// expects one event to be logged during the execution. @@ -34,8 +36,9 @@ public interface IEventFilterApplier /// "akka.test.filter-leeway", see . /// /// The action. - Task ExpectOneAsync(Action action); - + /// + Task ExpectOneAsync(Action action, CancellationToken cancellationToken = default); + /// /// Executes and /// expects one event to be logged during the execution. @@ -44,7 +47,8 @@ public interface IEventFilterApplier /// "akka.test.filter-leeway", see . /// /// The action. - Task ExpectOneAsync(Func actionAsync); + /// + Task ExpectOneAsync(Func actionAsync, CancellationToken cancellationToken = default); /// /// Executes and @@ -54,8 +58,9 @@ public interface IEventFilterApplier /// /// The time to wait for a log event after executing /// The action. - void ExpectOne(TimeSpan timeout, Action action); - + /// + void ExpectOne(TimeSpan timeout, Action action, CancellationToken cancellationToken = default); + /// /// Executes and /// expects one event to be logged during the execution. @@ -64,8 +69,9 @@ public interface IEventFilterApplier /// /// The time to wait for a log event after executing /// The action. - Task ExpectOneAsync(TimeSpan timeout, Action action); - + /// + Task ExpectOneAsync(TimeSpan timeout, Action action, CancellationToken cancellationToken = default); + /// /// Executes and expects the specified number /// of events to be logged during the execution. @@ -75,8 +81,9 @@ public interface IEventFilterApplier /// /// The expected number of events /// The action. - void Expect(int expectedCount, Action action); - + /// + void Expect(int expectedCount, Action action, CancellationToken cancellationToken = default); + /// /// Executes and expects the specified number /// of events to be logged during the execution. @@ -86,7 +93,8 @@ public interface IEventFilterApplier /// /// The expected number of events /// The action. - Task ExpectAsync(int expectedCount, Action action); + /// + Task ExpectAsync(int expectedCount, Action action, CancellationToken cancellationToken = default); /// /// Executes task and expects the specified number @@ -97,7 +105,8 @@ public interface IEventFilterApplier /// /// The expected number of events /// The async action. - Task ExpectAsync(int expectedCount, Func actionAsync); + /// + Task ExpectAsync(int expectedCount, Func actionAsync, CancellationToken cancellationToken = default); /// /// Executes task and expects the specified number @@ -109,7 +118,8 @@ public interface IEventFilterApplier /// The expected number of events /// The async action. /// - Task ExpectAsync(int expectedCount, Func actionAsync, TimeSpan? timeout); + /// + Task ExpectAsync(int expectedCount, Func actionAsync, TimeSpan? timeout, CancellationToken cancellationToken = default); /// /// Executes and expects the specified number @@ -121,8 +131,9 @@ public interface IEventFilterApplier /// The time to wait for log events after executing /// The expected number of events /// The action. - void Expect(int expectedCount, TimeSpan timeout, Action action); - + /// + void Expect(int expectedCount, TimeSpan timeout, Action action, CancellationToken cancellationToken = default); + /// /// Executes and expects the specified number /// of events to be logged during the execution. @@ -133,7 +144,8 @@ public interface IEventFilterApplier /// The time to wait for log events after executing /// The expected number of events /// The action. - Task ExpectAsync(int expectedCount, TimeSpan timeout, Action action); + /// + Task ExpectAsync(int expectedCount, TimeSpan timeout, Action action, CancellationToken cancellationToken = default); /// /// Executes and @@ -144,9 +156,10 @@ public interface IEventFilterApplier /// /// The return value of the function /// The function. + /// /// The returned value from . - T ExpectOne(Func func); - + T ExpectOne(Func func, CancellationToken cancellationToken = default); + /// /// Executes and /// expects one event to be logged during the execution. @@ -156,8 +169,9 @@ public interface IEventFilterApplier /// /// The return value of the function /// The function. + /// /// The returned value from . - Task ExpectOneAsync(Func func); + Task ExpectOneAsync(Func func, CancellationToken cancellationToken = default); /// /// Executes and @@ -168,9 +182,10 @@ public interface IEventFilterApplier /// The return value of the function /// The time to wait for a log event after executing /// The function. + /// /// The returned value from . - T ExpectOne(TimeSpan timeout, Func func); - + T ExpectOne(TimeSpan timeout, Func func, CancellationToken cancellationToken = default); + /// /// Executes and /// expects one event to be logged during the execution. @@ -180,8 +195,9 @@ public interface IEventFilterApplier /// The return value of the function /// The time to wait for a log event after executing /// The function. + /// /// The returned value from . - Task ExpectOneAsync(TimeSpan timeout, Func func); + Task ExpectOneAsync(TimeSpan timeout, Func func, CancellationToken cancellationToken = default); /// /// Executes and expects the specified number @@ -193,8 +209,9 @@ public interface IEventFilterApplier /// The return value of the function /// The expected number of events /// The function. + /// /// The returned value from . - T Expect(int expectedCount, Func func); + T Expect(int expectedCount, Func func, CancellationToken cancellationToken = default); /// /// Executes and expects the specified number @@ -207,8 +224,9 @@ public interface IEventFilterApplier /// The return value of the function /// The expected number of events /// The function. + /// /// The returned value from . - Task ExpectAsync(int expectedCount, Func func); + Task ExpectAsync(int expectedCount, Func func, CancellationToken cancellationToken = default); /// /// Executes and expects the specified number @@ -221,9 +239,10 @@ public interface IEventFilterApplier /// The time to wait for log events after executing /// The expected number of events /// The function. + /// /// The returned value from . - T Expect(int expectedCount, TimeSpan timeout, Func func); - + T Expect(int expectedCount, TimeSpan timeout, Func func, CancellationToken cancellationToken = default); + /// /// Executes and expects the specified number /// of events to be logged during the execution. @@ -235,38 +254,43 @@ public interface IEventFilterApplier /// The time to wait for log events after executing /// The expected number of events /// The function. + /// /// The returned value from . - Task ExpectAsync(int expectedCount, TimeSpan timeout, Func func); + Task ExpectAsync(int expectedCount, TimeSpan timeout, Func func, CancellationToken cancellationToken = default); /// /// Executes and prevent events from being logged during the execution. /// /// The return value of the function /// The function. + /// /// The returned value from . - T Mute(Func func); - + T Mute(Func func, CancellationToken cancellationToken = default); + /// /// Executes and prevent events from being logged during the execution. /// /// The return value of the function /// The function. + /// /// The returned value from . - Task MuteAsync(Func func); + Task MuteAsync(Func func, CancellationToken cancellationToken = default); /// /// Executes and prevent events from being logged during the execution. /// /// The function. + /// /// The returned value from . - void Mute(Action action); - + void Mute(Action action, CancellationToken cancellationToken = default); + /// /// Executes and prevent events from being logged during the execution. /// /// The function. + /// /// The returned value from . - Task MuteAsync(Action action); + Task MuteAsync(Action action, CancellationToken cancellationToken = default); /// /// Prevents events from being logged from now on. To allow events to be logged again, call diff --git a/src/core/Akka.TestKit/EventFilter/Internal/EventFilterApplier.cs b/src/core/Akka.TestKit/EventFilter/Internal/EventFilterApplier.cs index d575169640d..8ba59e65403 100644 --- a/src/core/Akka.TestKit/EventFilter/Internal/EventFilterApplier.cs +++ b/src/core/Akka.TestKit/EventFilter/Internal/EventFilterApplier.cs @@ -12,6 +12,7 @@ using Akka.Actor; using Akka.Event; using Akka.TestKit.TestEvent; +using Nito.AsyncEx.Synchronous; namespace Akka.TestKit.Internal { @@ -41,23 +42,33 @@ public InternalEventFilterApplier(TestKitBase testkit, ActorSystem system, IRead /// TBD /// /// TBD - public void ExpectOne(Action action) + /// + public void ExpectOne(Action action, CancellationToken cancellationToken = default) { - InternalExpect(action, _actorSystem, 1); + ExpectOneAsync(action, cancellationToken) + .WaitAndUnwrapException(); } - public Task ExpectOneAsync(Func actionAsync) + public async Task ExpectOneAsync(Func actionAsync, CancellationToken cancellationToken = default) { - return InternalExpectAsync(actionAsync, _actorSystem, 1); + await InternalExpectAsync(actionAsync, _actorSystem, 1, null, cancellationToken) + .ConfigureAwait(false); } /// - /// Async version of + /// Async version of /// /// - public async Task ExpectOneAsync(Action action) + /// + public async Task ExpectOneAsync(Action action, CancellationToken cancellationToken = default) { - await InternalExpectAsync(action, _actorSystem, 1); + await InternalExpectAsync( + action: action, + actorSystem: _actorSystem, + expectedCount: 1, + timeout: null, + cancellationToken: cancellationToken) + .ConfigureAwait(false); } /// @@ -65,18 +76,32 @@ public async Task ExpectOneAsync(Action action) /// /// TBD /// TBD - public void ExpectOne(TimeSpan timeout, Action action) + /// + public void ExpectOne( + TimeSpan timeout, + Action action, + CancellationToken cancellationToken = default) { - InternalExpect(action, _actorSystem, 1, timeout); + ExpectOneAsync(timeout, action, cancellationToken) + .WaitAndUnwrapException(); } /// - /// Async version of + /// Async version of /// /// - public async Task ExpectOneAsync(TimeSpan timeout, Action action) + public async Task ExpectOneAsync( + TimeSpan timeout, + Action action, + CancellationToken cancellationToken = default) { - await InternalExpectAsync(action, _actorSystem, 1, timeout); + await InternalExpectAsync( + action: action, + actorSystem: _actorSystem, + expectedCount: 1, + timeout: timeout, + cancellationToken: cancellationToken) + .ConfigureAwait(false); } /// @@ -84,31 +109,64 @@ public async Task ExpectOneAsync(TimeSpan timeout, Action action) /// /// TBD /// TBD - public void Expect(int expectedCount, Action action) + /// + public void Expect( + int expectedCount, + Action action, + CancellationToken cancellationToken = default) { - InternalExpect(action, _actorSystem, expectedCount, null); + ExpectAsync(expectedCount, action, cancellationToken) + .WaitAndUnwrapException(); } /// /// Async version of Expect /// - public Task ExpectAsync(int expectedCount, Func actionAsync) - => InternalExpectAsync(actionAsync, _actorSystem, expectedCount, null); + public async Task ExpectAsync( + int expectedCount, + Func actionAsync, + CancellationToken cancellationToken = default) + => await InternalExpectAsync( + actionAsync: actionAsync, + actorSystem: _actorSystem, + expectedCount: expectedCount, + timeout: null, + cancellationToken: cancellationToken) + .ConfigureAwait(false); /// /// Async version of Expect /// - public Task ExpectAsync(int expectedCount, Func actionAsync, TimeSpan? timeout) + public async Task ExpectAsync( + int expectedCount, + Func actionAsync, + TimeSpan? timeout, + CancellationToken cancellationToken = default) { - return InternalExpectAsync(actionAsync, _actorSystem, expectedCount, timeout); + await InternalExpectAsync( + actionAsync: actionAsync, + actorSystem: _actorSystem, + expectedCount: expectedCount, + timeout: timeout, + cancellationToken: cancellationToken) + .ConfigureAwait(false); } /// - /// Async version of + /// Async version of /// - public async Task ExpectAsync(int expectedCount, Action action) + public async Task ExpectAsync( + int expectedCount, + Action action, + CancellationToken cancellationToken = default) { - await InternalExpectAsync(action, _actorSystem, expectedCount, null); + await InternalExpectAsync( + action: action, + actorSystem: _actorSystem, + expectedCount: expectedCount, + timeout: null, + cancellationToken: cancellationToken) + .ConfigureAwait(false); } /// @@ -117,17 +175,33 @@ public async Task ExpectAsync(int expectedCount, Action action) /// TBD /// TBD /// TBD - public void Expect(int expectedCount, TimeSpan timeout, Action action) + /// + public void Expect( + int expectedCount, + TimeSpan timeout, + Action action, + CancellationToken cancellationToken = default) { - InternalExpect(action, _actorSystem, expectedCount, timeout); + ExpectAsync(expectedCount, timeout, action, cancellationToken) + .WaitAndUnwrapException(); } /// - /// Async version of + /// Async version of /// - public async Task ExpectAsync(int expectedCount, TimeSpan timeout, Action action) + public async Task ExpectAsync( + int expectedCount, + TimeSpan timeout, + Action action, + CancellationToken cancellationToken = default) { - await InternalExpectAsync(action, _actorSystem, expectedCount, timeout); + await InternalExpectAsync( + action: action, + actorSystem: _actorSystem, + expectedCount: expectedCount, + timeout: timeout, + cancellationToken: cancellationToken) + .ConfigureAwait(false); } /// @@ -135,18 +209,28 @@ public async Task ExpectAsync(int expectedCount, TimeSpan timeout, Action action /// /// TBD /// TBD + /// /// TBD - public T ExpectOne(Func func) + public T ExpectOne(Func func, CancellationToken cancellationToken = default) { - return Intercept(func, _actorSystem, null, 1); + return ExpectOneAsync(func, cancellationToken) + .WaitAndUnwrapException(); } /// /// Async version of ExpectOne /// - public async Task ExpectOneAsync(Func func) + public async Task ExpectOneAsync( + Func func, + CancellationToken cancellationToken = default) { - return await InterceptAsync(func, _actorSystem, null, 1); + return await InterceptAsync( + func: func, + system: _actorSystem, + timeout: null, + expectedOccurrences: 1, + cancellationToken: cancellationToken) + .ConfigureAwait(false); } /// @@ -155,18 +239,33 @@ public async Task ExpectOneAsync(Func func) /// TBD /// TBD /// TBD + /// /// TBD - public T ExpectOne(TimeSpan timeout, Func func) + public T ExpectOne( + TimeSpan timeout, + Func func, + CancellationToken cancellationToken = default) { - return Intercept(func, _actorSystem, timeout, 1); + return ExpectOneAsync(timeout, func, cancellationToken) + .WaitAndUnwrapException(); } /// /// Async version of ExpectOne /// - public async Task ExpectOneAsync(TimeSpan timeout, Func func) + public async Task ExpectOneAsync( + TimeSpan timeout, + Func func, + CancellationToken cancellationToken = default) { - return await InterceptAsync(func, _actorSystem, timeout, 1); + return await InterceptAsync( + func: func, + system: _actorSystem, + timeout: timeout, + expectedOccurrences: 1, + matchedEventHandler: null, + cancellationToken: cancellationToken) + .ConfigureAwait(false); } /// @@ -175,18 +274,33 @@ public async Task ExpectOneAsync(TimeSpan timeout, Func func) /// TBD /// TBD /// TBD + /// /// TBD - public T Expect(int expectedCount, Func func) + public T Expect( + int expectedCount, + Func func, + CancellationToken cancellationToken = default) { - return Intercept(func, _actorSystem, null, expectedCount); + return ExpectAsync(expectedCount, func, cancellationToken) + .WaitAndUnwrapException(); } /// /// Async version of Expect /// - public async Task ExpectAsync(int expectedCount, Func func) + public async Task ExpectAsync( + int expectedCount, + Func func, + CancellationToken cancellationToken = default) { - return await InterceptAsync(func, _actorSystem, null, expectedCount); + return await InterceptAsync( + func: func, + system: _actorSystem, + timeout: null, + expectedOccurrences: expectedCount, + matchedEventHandler: null, + cancellationToken: cancellationToken) + .ConfigureAwait(false); } /// @@ -196,19 +310,36 @@ public async Task ExpectAsync(int expectedCount, Func func) /// TBD /// TBD /// TBD + /// /// TBD - public T Expect(int expectedCount, TimeSpan timeout, Func func) + public T Expect( + int expectedCount, + TimeSpan timeout, + Func func, + CancellationToken cancellationToken = default) { - return Intercept(func, _actorSystem, timeout, expectedCount); + return ExpectAsync(expectedCount, timeout, func, cancellationToken) + .WaitAndUnwrapException(); } /// /// Async version of Expect /// Note: might not get awaited. /// - public async Task ExpectAsync(int expectedCount, TimeSpan timeout, Func func) + public async Task ExpectAsync( + int expectedCount, + TimeSpan timeout, + Func func, + CancellationToken cancellationToken = default) { - return await InterceptAsync(func, _actorSystem, timeout, expectedCount); + return await InterceptAsync( + func: func, + system: _actorSystem, + timeout: timeout, + expectedOccurrences: expectedCount, + matchedEventHandler: null, + cancellationToken: cancellationToken) + .ConfigureAwait(false); } /// @@ -216,35 +347,57 @@ public async Task ExpectAsync(int expectedCount, TimeSpan timeout, Func /// /// TBD /// TBD + /// /// TBD - public T Mute(Func func) + public T Mute(Func func, CancellationToken cancellationToken = default) { - return Intercept(func, _actorSystem, null, null); + return MuteAsync(func, cancellationToken) + .WaitAndUnwrapException(); } /// /// Async version of Mute /// - public async Task MuteAsync(Func func) + public async Task MuteAsync(Func func, CancellationToken cancellationToken = default) { - return await InterceptAsync(func, _actorSystem, null, null); + return await InterceptAsync( + func: func, + system: _actorSystem, + timeout: null, + expectedOccurrences: null, + matchedEventHandler: null, + cancellationToken: cancellationToken) + .ConfigureAwait(false); } /// /// TBD /// /// TBD - public void Mute(Action action) + /// + public void Mute(Action action, CancellationToken cancellationToken = default) { - Intercept(() => { action(); return null; }, _actorSystem, null, null); + MuteAsync(action, cancellationToken) + .WaitAndUnwrapException(); } /// /// Async version of Mute /// - public async Task MuteAsync(Action action) + public async Task MuteAsync(Action action, CancellationToken cancellationToken = default) { - await InterceptAsync(() => { action(); return null; }, _actorSystem, null, null); + await InterceptAsync( + func:async () => + { + action(); + return null; + }, + system: _actorSystem, + timeout: null, + expectedOccurrences: null, + matchedEventHandler: null, + cancellationToken: cancellationToken) + .ConfigureAwait(false); } /// @@ -277,78 +430,64 @@ public EventFilterFactory And /// TBD /// TBD /// TBD + /// /// TBD - protected T Intercept(Func func, ActorSystem system, TimeSpan? timeout, int? expectedOccurrences, MatchedEventHandler matchedEventHandler = null) + protected T Intercept( + Func func, + ActorSystem system, + TimeSpan? timeout, + int? expectedOccurrences, + MatchedEventHandler matchedEventHandler = null, + CancellationToken cancellationToken = default) { - var leeway = system.HasExtension() - ? TestKitExtension.For(system).TestEventFilterLeeway - : _testkit.TestKitSettings.TestEventFilterLeeway; - - var timeoutValue = timeout.HasValue ? _testkit.Dilated(timeout.Value) : leeway; - matchedEventHandler = matchedEventHandler ?? new MatchedEventHandler(); - system.EventStream.Publish(new Mute(_filters)); - try - { - foreach(var filter in _filters) - { - filter.EventMatched += matchedEventHandler.HandleEvent; - } - var result = func(); - - if(!AwaitDone(timeoutValue, expectedOccurrences, matchedEventHandler)) - { - var actualNumberOfEvents = matchedEventHandler.ReceivedCount; - string msg; - if(expectedOccurrences.HasValue) - { - var expectedNumberOfEvents = expectedOccurrences.Value; - if(actualNumberOfEvents < expectedNumberOfEvents) - msg = string.Format("Timeout ({0}) while waiting for messages. Only received {1}/{2} messages that matched filter [{3}]", timeoutValue, actualNumberOfEvents, expectedNumberOfEvents, string.Join(",", _filters).Replace("{", "{{").Replace("}", "}}")); - else - { - var tooMany = actualNumberOfEvents - expectedNumberOfEvents; - msg = string.Format("Received {0} {1} too many. Expected {2} {3} but received {4} that matched filter [{5}]", tooMany, GetMessageString(tooMany), expectedNumberOfEvents, GetMessageString(expectedNumberOfEvents), actualNumberOfEvents, string.Join(",", _filters).Replace("{", "{{").Replace("}", "}}")); - } - } - else - msg = string.Format("Timeout ({0}) while waiting for messages that matched filter [{1}]", timeoutValue, string.Join(",", _filters).Replace("{", "{{").Replace("}", "}}")); - - var assertionsProvider = system.HasExtension() - ? TestKitAssertionsExtension.For(system) - : TestKitAssertionsExtension.For(_testkit.Sys); - assertionsProvider.Assertions.Fail(msg); - } - return result; - } - finally - { - foreach(var filter in _filters) - { - filter.EventMatched -= matchedEventHandler.HandleEvent; - } - system.EventStream.Publish(new Unmute(_filters)); - } + return InterceptAsync( + func: func, + system: system, + timeout: timeout, + expectedOccurrences: expectedOccurrences, + matchedEventHandler: matchedEventHandler, + cancellationToken: cancellationToken) + .WaitAndUnwrapException(); } /// /// Async version of /// - protected Task InterceptAsync(Func func, ActorSystem system, TimeSpan? timeout, int? expectedOccurrences, MatchedEventHandler matchedEventHandler = null) - { - return InterceptAsync(() => Task.FromResult(func()), system, timeout, expectedOccurrences, matchedEventHandler); + protected async Task InterceptAsync( + Func func, + ActorSystem system, + TimeSpan? timeout, + int? expectedOccurrences, + MatchedEventHandler matchedEventHandler = null, + CancellationToken cancellationToken = default) + { + return await InterceptAsync( + func: () => Task.FromResult(func()), + system: system, + timeout: timeout, + expectedOccurrences: expectedOccurrences, + matchedEventHandler: matchedEventHandler, + cancellationToken: cancellationToken) + .ConfigureAwait(false); } /// /// Async version of /// - protected async Task InterceptAsync(Func> func, ActorSystem system, TimeSpan? timeout, int? expectedOccurrences, MatchedEventHandler matchedEventHandler = null) + protected async Task InterceptAsync( + Func> func, + ActorSystem system, + TimeSpan? timeout, + int? expectedOccurrences, + MatchedEventHandler matchedEventHandler = null, + CancellationToken cancellationToken = default) { var leeway = system.HasExtension() ? TestKitExtension.For(system).TestEventFilterLeeway : _testkit.TestKitSettings.TestEventFilterLeeway; var timeoutValue = timeout.HasValue ? _testkit.Dilated(timeout.Value) : leeway; - matchedEventHandler = matchedEventHandler ?? new MatchedEventHandler(); + matchedEventHandler ??= new MatchedEventHandler(); system.EventStream.Publish(new Mute(_filters)); try { @@ -358,7 +497,7 @@ protected async Task InterceptAsync(Func> func, ActorSystem system } var result = await func(); - if(!await AwaitDoneAsync(timeoutValue, expectedOccurrences, matchedEventHandler)) + if(!await AwaitDoneAsync(timeoutValue, expectedOccurrences, matchedEventHandler, cancellationToken)) { var actualNumberOfEvents = matchedEventHandler.ReceivedCount; string msg; @@ -366,15 +505,21 @@ protected async Task InterceptAsync(Func> func, ActorSystem system { var expectedNumberOfEvents = expectedOccurrences.Value; if(actualNumberOfEvents < expectedNumberOfEvents) - msg = string.Format("Timeout ({0}) while waiting for messages. Only received {1}/{2} messages that matched filter [{3}]", timeoutValue, actualNumberOfEvents, expectedNumberOfEvents, string.Join(",", _filters)); + msg = + $"Timeout ({timeoutValue}) while waiting for messages. " + + $"Only received {actualNumberOfEvents}/{expectedNumberOfEvents} messages " + + $"that matched filter [{string.Join(",", _filters)}]"; else { var tooMany = actualNumberOfEvents - expectedNumberOfEvents; - msg = string.Format("Received {0} {1} too many. Expected {2} {3} but received {4} that matched filter [{5}]", tooMany, GetMessageString(tooMany), expectedNumberOfEvents, GetMessageString(expectedNumberOfEvents), actualNumberOfEvents, string.Join(",", _filters)); + msg = + $"Received {tooMany} {GetMessageString(tooMany)} too many. " + + $"Expected {expectedNumberOfEvents} {GetMessageString(expectedNumberOfEvents)} " + + $"but received {actualNumberOfEvents} that matched filter [{string.Join(",", _filters)}]"; } } else - msg = string.Format("Timeout ({0}) while waiting for messages that matched filter [{1}]", timeoutValue, _filters); + msg = $"Timeout ({timeoutValue}) while waiting for messages that matched filter [{_filters}]"; var assertionsProvider = system.HasExtension() ? TestKitAssertionsExtension.For(system) @@ -399,44 +544,39 @@ protected async Task InterceptAsync(Func> func, ActorSystem system /// TBD /// TBD /// TBD + /// /// TBD - protected bool AwaitDone(TimeSpan timeout, int? expectedOccurrences, MatchedEventHandler matchedEventHandler) + protected bool AwaitDone( + TimeSpan timeout, + int? expectedOccurrences, + MatchedEventHandler matchedEventHandler, + CancellationToken cancellationToken = default) { - if (expectedOccurrences.HasValue) - { - var expected = expectedOccurrences.GetValueOrDefault(); - if (expected > 0) - { - _testkit.AwaitConditionNoThrow(() => matchedEventHandler.ReceivedCount >= expected, timeout); - return matchedEventHandler.ReceivedCount == expected; - } - else - { - // if expecting no events to arrive - assert that given condition will never match - var foundEvent = _testkit.AwaitConditionNoThrow(() => matchedEventHandler.ReceivedCount > 0, timeout); - return foundEvent == false; - } - } - return true; + return AwaitDoneAsync(timeout, expectedOccurrences, matchedEventHandler, cancellationToken) + .WaitAndUnwrapException(); } /// /// Async version of /// - protected async Task AwaitDoneAsync(TimeSpan timeout, int? expectedOccurrences, MatchedEventHandler matchedEventHandler) + protected async Task AwaitDoneAsync( + TimeSpan timeout, + int? expectedOccurrences, + MatchedEventHandler matchedEventHandler, + CancellationToken cancellationToken = default) { if(expectedOccurrences.HasValue) { var expected = expectedOccurrences.GetValueOrDefault(); if (expected > 0) { - await _testkit.AwaitConditionNoThrowAsync(() => matchedEventHandler.ReceivedCount >= expected, timeout); + await _testkit.AwaitConditionNoThrowAsync(() => matchedEventHandler.ReceivedCount >= expected, timeout, cancellationToken: cancellationToken); return matchedEventHandler.ReceivedCount == expected; } else { // if expecting no events to arrive - assert that given condition will never match - var foundEvent = await _testkit.AwaitConditionNoThrowAsync(() => matchedEventHandler.ReceivedCount > 0, timeout); + var foundEvent = await _testkit.AwaitConditionNoThrowAsync(() => matchedEventHandler.ReceivedCount > 0, timeout, cancellationToken: cancellationToken); return foundEvent == false; } } @@ -453,25 +593,36 @@ protected static string GetMessageString(int number) return number == 1 ? "message" : "messages"; } - private void InternalExpect(Action action, ActorSystem actorSystem, int expectedCount, TimeSpan? timeout = null) + private async Task InternalExpectAsync( + Func actionAsync, + ActorSystem actorSystem, + int expectedCount, + TimeSpan? timeout = null, + CancellationToken cancellationToken = default) { - Intercept(() => { action(); return null; }, actorSystem, timeout, expectedCount); - } - - /// - /// Async version of - /// - private async Task InternalExpectAsync(Func actionAsync, ActorSystem actorSystem, int expectedCount, TimeSpan? timeout = null) - { - await InterceptAsync(async () => { await actionAsync(); return Task.FromResult(null); }, actorSystem, timeout, expectedCount); + await InterceptAsync( + async () => + { + await actionAsync(); + return Task.FromResult(null); + }, actorSystem, timeout, expectedCount, cancellationToken: cancellationToken) + .ConfigureAwait(false); } - /// - /// Async version of - /// - private async Task InternalExpectAsync(Action action, ActorSystem actorSystem, int expectedCount, TimeSpan? timeout = null) - { - await InterceptAsync(() => { action(); return Task.FromResult(null); }, actorSystem, timeout, expectedCount); + private async Task InternalExpectAsync( + Action action, + ActorSystem actorSystem, + int expectedCount, + TimeSpan? timeout = null, + CancellationToken cancellationToken = default) + { + await InterceptAsync( + () => + { + action(); + return Task.FromResult(null); + }, actorSystem, timeout, expectedCount, cancellationToken: cancellationToken) + .ConfigureAwait(false); } /// @@ -537,7 +688,6 @@ public void Unmute() // // Finalizer calls Dispose(false) // Dispose(false); //} - public void Dispose() { @@ -547,7 +697,6 @@ public void Dispose() GC.SuppressFinalize(this); } - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// if set to true the method has been called directly or indirectly by a /// user's code. Managed and unmanaged resources will be disposed.