-
Notifications
You must be signed in to change notification settings - Fork 1k
/
TestActorRefBase.cs
331 lines (283 loc) · 11.9 KB
/
TestActorRefBase.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
//-----------------------------------------------------------------------
// <copyright file="TestActorRefBase.cs" company="Akka.NET Project">
// Copyright (C) 2009-2022 Lightbend Inc. <http://www.lightbend.com>
// Copyright (C) 2013-2022 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
//-----------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Akka.Actor;
using Akka.Dispatch;
using Akka.Dispatch.SysMsg;
using Akka.TestKit.Internal;
using Akka.Util;
namespace Akka.TestKit
{
/// <summary>
/// This is the base class for TestActorRefs
/// </summary>
/// <typeparam name="TActor">The type of actor</typeparam>
public abstract class TestActorRefBase<TActor> : ICanTell, IEquatable<IActorRef>, IInternalActorRef where TActor : ActorBase
{
private readonly InternalTestActorRef _internalRef;
/// <summary>
/// TBD
/// </summary>
/// <param name="system">TBD</param>
/// <param name="actorProps">TBD</param>
/// <param name="supervisor">TBD</param>
/// <param name="name">TBD</param>
protected TestActorRefBase(ActorSystem system, Props actorProps, IActorRef supervisor=null, string name=null)
{
_internalRef = InternalTestActorRef.Create(system, actorProps, supervisor, name);
}
/// <summary>
/// Directly inject messages into actor receive behavior. Any exceptions
/// thrown will be available to you, while still being able to use
/// become/unbecome.
/// Note: This method violates the actor model and could cause unpredictable
/// behavior. For example, a Receive call to an actor could run simultaneously
/// (2 simultaneous threads running inside the actor) with the actor's handling
/// of a previous Tell call.
/// </summary>
/// <param name="message">The message.</param>
/// <param name="sender">The sender.</param>
public void Receive(object message, IActorRef sender = null)
{
_internalRef.Receive(message, sender);
}
/// <summary>
/// Directly inject messages into actor ReceiveAsync behavior. Any exceptions
/// thrown will be available to you, while still being able to use
/// become/unbecome.
/// Note: This method violates the actor model and could cause unpredictable
/// behavior. For example, a Receive call to an actor could run simultaneously
/// (2 simultaneous threads running inside the actor) with the actor's handling
/// of a previous Tell call.
/// </summary>
/// <param name="message">The message.</param>
/// <param name="sender">The sender.</param>
public Task ReceiveAsync(object message, IActorRef sender = null)
{
return _internalRef.ReceiveAsync(message, sender);
}
/// <summary>
/// TBD
/// </summary>
public IActorRef Ref
{
get { return _internalRef; }
}
/// <summary>
/// TBD
/// </summary>
protected InternalTestActorRef InternalRef
{
get { return _internalRef; }
}
/// <summary>
/// TBD
/// </summary>
public TActor UnderlyingActor
{
get { return (TActor) _internalRef.UnderlyingActor; }
}
/// <summary>
/// Gets the path of this instance
/// </summary>
public ActorPath Path { get { return _internalRef.Path; } }
/// <summary>
/// Sends a message to this actor.
/// If this call is made from within an actor, the current actor will be the sender.
/// If the call is made from a test class that is based on TestKit, TestActor will
/// will be the sender;
/// otherwise <see cref="ActorRefs.NoSender"/> will be set as sender.
/// </summary>
/// <param name="message">The message.</param>
public void Tell(object message)
{
_internalRef.Tell(message);
}
/// <summary>
/// Forwards a message to this actor.
/// If this call is made from within an actor, the current actor will be the sender.
/// If the call is made from a test class that is based on TestKit, TestActor will
/// will be the sender;
/// </summary>
/// <param name="message">The message.</param>
public void Forward(object message)
{
_internalRef.Forward(message);
}
/// <summary>
/// Sends a message to this actor with the specified sender.
/// </summary>
/// <param name="message">The message.</param>
/// <param name="sender">The sender</param>
public void Tell(object message, IActorRef sender)
{
_internalRef.Tell(message, sender);
}
/// <summary>
/// Registers this actor to be a death monitor of the provided ActorRef
/// This means that this actor will get a Terminated()-message when the provided actor
/// is permanently terminated.
/// Returns the same ActorRef that is provided to it, to allow for cleaner invocations.
/// </summary>
/// <param name="subject">The subject to watch.</param>
/// <returns>Returns the same ActorRef that is provided to it, to allow for cleaner invocations.</returns>
public void Watch(IActorRef subject)
{
_internalRef.Watch(subject);
}
/// <summary>
/// Deregisters this actor from being a death monitor of the provided ActorRef
/// This means that this actor will not get a Terminated()-message when the provided actor
/// is permanently terminated.
/// Returns the same ActorRef that is provided to it, to allow for cleaner invocations.
/// </summary>
/// <returns>Returns the same ActorRef that is provided to it, to allow for cleaner invocations.</returns>
/// <param name="subject">The subject to unwatch.</param>
public void Unwatch(IActorRef subject)
{
_internalRef.Unwatch(subject);
}
public override string ToString()
{
return _internalRef.ToString();
}
public override bool Equals(object obj)
{
return _internalRef.Equals(obj);
}
public override int GetHashCode()
{
return _internalRef.GetHashCode();
}
public int CompareTo(object obj)
{
return ((IComparable) _internalRef).CompareTo(obj);
}
public bool Equals(IActorRef other)
{
return _internalRef.Equals(other);
}
/// <summary>
/// Compares a specified <see cref="TestActorRefBase{TActor}"/> to an <see cref="IActorRef"/> for equality.
/// </summary>
/// <param name="testActorRef">The test actor used for comparison</param>
/// <param name="actorRef">The actor used for comparison</param>
/// <returns><c>true</c> if both actors are equal; otherwise <c>false</c></returns>
public static bool operator ==(TestActorRefBase<TActor> testActorRef, IActorRef actorRef)
{
if(ReferenceEquals(testActorRef, null)) return ReferenceEquals(actorRef, null);
return testActorRef.Equals(actorRef);
}
/// <summary>
/// Compares a specified <see cref="TestActorRefBase{TActor}"/> to an <see cref="IActorRef"/> for inequality.
/// </summary>
/// <param name="testActorRef">The test actor used for comparison</param>
/// <param name="actorRef">The actor used for comparison</param>
/// <returns><c>true</c> if both actors are not equal; otherwise <c>false</c></returns>
public static bool operator !=(TestActorRefBase<TActor> testActorRef, IActorRef actorRef)
{
if(ReferenceEquals(testActorRef, null)) return !ReferenceEquals(actorRef, null);
return !testActorRef.Equals(actorRef);
}
/// <summary>
/// Compares a specified <see cref="IActorRef"/> to an <see cref="TestActorRefBase{TActor}"/> for equality.
/// </summary>
/// <param name="actorRef">The actor used for comparison</param>
/// <param name="testActorRef">The test actor used for comparison</param>
/// <returns><c>true</c> if both actors are equal; otherwise <c>false</c></returns>
public static bool operator ==(IActorRef actorRef, TestActorRefBase<TActor> testActorRef)
{
if(ReferenceEquals(testActorRef, null)) return ReferenceEquals(actorRef, null);
return testActorRef.Equals(actorRef);
}
/// <summary>
/// Compares a specified <see cref="IActorRef"/> to an <see cref="TestActorRefBase{TActor}"/> for inequality.
/// </summary>
/// <param name="actorRef">The actor used for comparison</param>
/// <param name="testActorRef">The test actor used for comparison</param>
/// <returns><c>true</c> if both actors are not equal; otherwise <c>false</c></returns>
public static bool operator !=(IActorRef actorRef, TestActorRefBase<TActor> testActorRef)
{
if(ReferenceEquals(testActorRef, null)) return !ReferenceEquals(actorRef, null);
return !testActorRef.Equals(actorRef);
}
/// <summary>
/// TBD
/// </summary>
/// <param name="actorRef">TBD</param>
/// <returns>TBD</returns>
public static IActorRef ToActorRef(TestActorRefBase<TActor> actorRef)
{
return actorRef._internalRef;
}
//ActorRef implementations
int IComparable<IActorRef>.CompareTo(IActorRef other)
{
return _internalRef.CompareTo(other);
}
bool IEquatable<IActorRef>.Equals(IActorRef other)
{
return _internalRef.Equals(other);
}
ActorPath IActorRef.Path { get { return _internalRef.Path; } }
void ICanTell.Tell(object message, IActorRef sender)
{
_internalRef.Tell(message, sender);
}
ISurrogate ISurrogated.ToSurrogate(ActorSystem system)
{
return _internalRef.ToSurrogate(system);
}
bool IActorRefScope.IsLocal { get { return _internalRef.IsLocal; } }
IInternalActorRef IInternalActorRef.Parent { get { return _internalRef.Parent; } }
IActorRefProvider IInternalActorRef.Provider { get { return _internalRef.Provider; } }
bool IInternalActorRef.IsTerminated { get { return _internalRef.IsTerminated; } }
IActorRef IInternalActorRef.GetChild(IReadOnlyList<string> name)
{
return _internalRef.GetChild(name);
}
void IInternalActorRef.Resume(Exception causedByFailure)
{
_internalRef.Resume(causedByFailure);
}
void IInternalActorRef.Start()
{
_internalRef.Start();
}
void IInternalActorRef.Stop()
{
_internalRef.Stop();
}
void IInternalActorRef.Restart(Exception cause)
{
_internalRef.Restart(cause);
}
void IInternalActorRef.Suspend()
{
_internalRef.Suspend();
}
/// <summary>
/// TBD
/// </summary>
/// <param name="message">TBD</param>
/// <param name="sender">TBD</param>
public void SendSystemMessage(ISystemMessage message, IActorRef sender)
{
_internalRef.SendSystemMessage(message);
}
/// <summary>
/// TBD
/// </summary>
/// <param name="message">TBD</param>
public void SendSystemMessage(ISystemMessage message)
{
_internalRef.SendSystemMessage(message);
}
}
}