@@ -83,32 +83,20 @@ public async Task ExpectNoMessageAsync(TimeSpan? timeAllowed = null, Cancellatio
8383 public async Task < object ? > GetNextMessageAsync ( TimeSpan ? timeAllowed = null ,
8484 CancellationToken cancellationToken = default )
8585 {
86- var cts = CancellationTokenSource . CreateLinkedTokenSource ( cancellationToken ) ;
87- cts . CancelAfter ( timeAllowed ?? TimeSpan . FromSeconds ( 1 ) ) ;
88-
89- try
90- {
91- var item = await _channel . Reader . ReadAsync ( cts . Token ) ;
92- Sender = item . Sender ;
86+ var item = await ReceiveNextAsync ( timeAllowed , cancellationToken ) ;
9387
94- return item . Message ;
95- }
96- catch ( OperationCanceledException )
97- {
98- var seconds = ( timeAllowed ?? TimeSpan . FromSeconds ( 1 ) ) . TotalSeconds . ToString ( "0.###" ) ;
99- throw new TestKitException ( $ "Waited { seconds } seconds but failed to receive a message") ;
100- }
88+ return item . Message ;
10189 }
10290
10391 /// <inheritdoc />
10492 public async Task < T > GetNextMessageAsync < T > ( TimeSpan ? timeAllowed = null ,
10593 CancellationToken cancellationToken = default )
10694 {
107- var output = await GetNextMessageAsync ( timeAllowed , cancellationToken ) ;
95+ var item = await ReceiveNextAsync ( timeAllowed , cancellationToken ) ;
10896
109- if ( output is not T typed )
97+ if ( item . Message is not T typed )
11098 {
111- throw new TestKitException ( $ "Message expected type { typeof ( T ) } , actual type { output ? . GetType ( ) } ") ;
99+ throw new TestKitException ( $ "Message expected type { typeof ( T ) } , actual type { item . Message ? . GetType ( ) } ") ;
112100 }
113101
114102 return typed ;
@@ -195,4 +183,129 @@ public Task<T> RequestAsync<T>(PID target, object message, TimeSpan timeAllowed)
195183 Context . RequestAsync < T > ( target , message , timeAllowed ) ;
196184
197185 public static implicit operator PID ? ( TestProbe tp ) => tp . Context . Self ;
186+
187+ private async Task < MessageAndSender > ReceiveNextAsync ( TimeSpan ? timeAllowed ,
188+ CancellationToken cancellationToken )
189+ {
190+ var cts = CancellationTokenSource . CreateLinkedTokenSource ( cancellationToken ) ;
191+ cts . CancelAfter ( timeAllowed ?? TimeSpan . FromSeconds ( 1 ) ) ;
192+
193+ try
194+ {
195+ var item = await _channel . Reader . ReadAsync ( cts . Token ) ;
196+ Sender = item . Sender ;
197+ return item ;
198+ }
199+ catch ( OperationCanceledException )
200+ {
201+ var seconds = ( timeAllowed ?? TimeSpan . FromSeconds ( 1 ) ) . TotalSeconds . ToString ( "0.###" ) ;
202+ throw new TestKitException ( $ "Waited { seconds } seconds but failed to receive a message") ;
203+ }
204+ }
205+
206+ /// <inheritdoc />
207+ public async Task < T > GetNextSystemMessageAsync < T > ( TimeSpan ? timeAllowed = null ,
208+ CancellationToken cancellationToken = default ) where T : SystemMessage
209+ {
210+ var item = await ReceiveNextAsync ( timeAllowed , cancellationToken ) ;
211+
212+ if ( item . Message is not SystemMessage )
213+ {
214+ throw new TestKitException (
215+ $ "Expected system message of type { typeof ( T ) } , but received user message of type { item . Message ? . GetType ( ) } ") ;
216+ }
217+
218+ if ( item . Message is not T typed )
219+ {
220+ throw new TestKitException ( $ "Message expected type { typeof ( T ) } , actual type { item . Message . GetType ( ) } ") ;
221+ }
222+
223+ return typed ;
224+ }
225+
226+ /// <inheritdoc />
227+ public async Task < T > GetNextUserMessageAsync < T > ( TimeSpan ? timeAllowed = null ,
228+ CancellationToken cancellationToken = default )
229+ {
230+ var item = await ReceiveNextAsync ( timeAllowed , cancellationToken ) ;
231+
232+ if ( item . Message is SystemMessage sys )
233+ {
234+ throw new TestKitException (
235+ $ "Expected user message of type { typeof ( T ) } , but received system message of type { sys . GetType ( ) } ") ;
236+ }
237+
238+ if ( item . Message is not T typed )
239+ {
240+ throw new TestKitException ( $ "Message expected type { typeof ( T ) } , actual type { item . Message ? . GetType ( ) } ") ;
241+ }
242+
243+ return typed ;
244+ }
245+
246+ /// <inheritdoc />
247+ public async Task < T > GetNextSystemMessageAsync < T > ( Func < T , bool > when , TimeSpan ? timeAllowed = null ,
248+ CancellationToken cancellationToken = default ) where T : SystemMessage
249+ {
250+ var output = await GetNextSystemMessageAsync < T > ( timeAllowed , cancellationToken ) ;
251+
252+ if ( ! when ( output ) )
253+ {
254+ throw new TestKitException ( "Condition not met" ) ;
255+ }
256+
257+ return output ;
258+ }
259+
260+ /// <inheritdoc />
261+ public async Task < T > GetNextUserMessageAsync < T > ( Func < T , bool > when , TimeSpan ? timeAllowed = null ,
262+ CancellationToken cancellationToken = default )
263+ {
264+ var output = await GetNextUserMessageAsync < T > ( timeAllowed , cancellationToken ) ;
265+
266+ if ( ! when ( output ) )
267+ {
268+ throw new TestKitException ( "Condition not met" ) ;
269+ }
270+
271+ return output ;
272+ }
273+
274+ /// <inheritdoc />
275+ public async Task ExpectNextSystemMessageAsync < T > ( TimeSpan ? timeAllowed = null ,
276+ CancellationToken cancellationToken = default ) where T : SystemMessage =>
277+ _ = await GetNextSystemMessageAsync < T > ( timeAllowed , cancellationToken ) ;
278+
279+ /// <inheritdoc />
280+ public async Task ExpectNextUserMessageAsync < T > ( TimeSpan ? timeAllowed = null ,
281+ CancellationToken cancellationToken = default ) =>
282+ _ = await GetNextUserMessageAsync < T > ( timeAllowed , cancellationToken ) ;
283+
284+ /// <inheritdoc />
285+ public async Task ExpectNextSystemMessageAsync < T > ( Func < T , bool > when , TimeSpan ? timeAllowed = null ,
286+ CancellationToken cancellationToken = default ) where T : SystemMessage =>
287+ _ = await GetNextSystemMessageAsync ( when , timeAllowed , cancellationToken ) ;
288+
289+ /// <inheritdoc />
290+ public async Task ExpectNextUserMessageAsync < T > ( Func < T , bool > when , TimeSpan ? timeAllowed = null ,
291+ CancellationToken cancellationToken = default ) =>
292+ _ = await GetNextUserMessageAsync ( when , timeAllowed , cancellationToken ) ;
293+
294+ /// <inheritdoc />
295+ public async Task ExpectEmptyMailboxAsync ( TimeSpan ? timeAllowed = null ,
296+ CancellationToken cancellationToken = default )
297+ {
298+ var self = Context . Self ;
299+
300+ if ( timeAllowed . HasValue )
301+ {
302+ await RequestAsync < Touched > ( self , new Touch ( ) , timeAllowed . Value ) ;
303+ }
304+ else
305+ {
306+ await RequestAsync < Touched > ( self , new Touch ( ) , cancellationToken ) ;
307+ }
308+
309+ await GetNextUserMessageAsync < Touch > ( timeAllowed , cancellationToken ) ;
310+ }
198311}
0 commit comments