diff --git a/Src/PChecker/CheckerCore/Actors/Actor.cs b/Src/PChecker/CheckerCore/Actors/Actor.cs
deleted file mode 100644
index 1804591e2a..0000000000
--- a/Src/PChecker/CheckerCore/Actors/Actor.cs
+++ /dev/null
@@ -1,1005 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Threading.Tasks;
-using PChecker.Actors.EventQueues;
-using PChecker.Actors.Events;
-using PChecker.Actors.Exceptions;
-using PChecker.Actors.Handlers;
-using PChecker.Actors.Logging;
-using PChecker.Actors.Managers;
-using PChecker.Exceptions;
-using PChecker.IO.Debugging;
-using EventInfo = PChecker.Actors.Events.EventInfo;
-
-namespace PChecker.Actors
-{
- ///
- /// Type that implements an actor. Inherit from this class to declare a custom actor.
- ///
- public abstract class Actor
- {
- ///
- /// Cache of actor types to a map of event types to action declarations.
- ///
- private static readonly ConcurrentDictionary> ActionCache =
- new ConcurrentDictionary>();
-
- ///
- /// A set of lockable objects used to protect static initialization of the ActionCache while
- /// also enabling multithreaded initialization of different Actor types.
- ///
- private static readonly ConcurrentDictionary ActionCacheLocks =
- new ConcurrentDictionary();
-
- ///
- /// A cached array that contains a single event type.
- ///
- private static readonly Type[] SingleEventTypeArray = new Type[] { typeof(Event) };
-
- ///
- /// The runtime that executes this actor.
- ///
- internal ActorRuntime Runtime { get; private set; }
-
- ///
- /// Unique id that identifies this actor.
- ///
- protected internal ActorId Id { get; private set; }
-
- ///
- /// Manages the actor.
- ///
- internal IActorManager Manager { get; private set; }
-
- ///
- /// The inbox of the actor. Incoming events are enqueued here.
- /// Events are dequeued to be processed.
- ///
- private protected IEventQueue Inbox;
-
- ///
- /// Map from event types to cached action delegates.
- ///
- private protected readonly Dictionary ActionMap;
-
- ///
- /// The current status of the actor. It is marked volatile as
- /// the runtime can read it concurrently.
- ///
- private protected volatile Status CurrentStatus;
-
- ///
- /// Gets the name of the current state, if there is one.
- ///
- internal string CurrentStateName { get; private protected set; }
-
- ///
- /// Checks if the actor is halted.
- ///
- internal bool IsHalted => CurrentStatus is Status.Halted;
-
- ///
- /// Checks if a default handler is available.
- ///
- internal bool IsDefaultHandlerAvailable { get; private set; }
-
- ///
- /// Id used to identify subsequent operations performed by this actor. This value
- /// is initially either or the specified
- /// upon creation. This value is automatically set to the operation group id of the
- /// last dequeue or receive operation, if it is not . This
- /// value can also be manually set using the property.
- ///
- protected internal virtual Guid OperationGroupId
- {
- get => Manager.OperationGroupId;
-
- set
- {
- Manager.OperationGroupId = value;
- }
- }
-
- ///
- /// The installed runtime logger.
- ///
- protected TextWriter Logger => Runtime.Logger;
-
- ///
- /// The installed runtime json logger.
- ///
- protected JsonWriter JsonLogger => Runtime.JsonLogger;
-
- ///
- /// User-defined hashed state of the actor. Override to improve the
- /// accuracy of stateful techniques during testing.
- ///
- protected virtual int HashedState => 0;
-
- ///
- /// Initializes a new instance of the class.
- ///
- protected Actor()
- {
- ActionMap = new Dictionary();
- CurrentStatus = Status.Active;
- CurrentStateName = default;
- IsDefaultHandlerAvailable = false;
- }
-
- ///
- /// Configures the actor.
- ///
- internal void Configure(ActorRuntime runtime, ActorId id, IActorManager manager, IEventQueue inbox)
- {
- Runtime = runtime;
- Id = id;
- Manager = manager;
- Inbox = inbox;
- }
-
- ///
- /// Initializes the actor with the specified optional event.
- ///
- /// Optional event used for initialization.
- internal virtual async Task InitializeAsync(Event initialEvent)
- {
- // Invoke the custom initializer, if there is one.
- await InvokeUserCallbackAsync(UserCallbackType.OnInitialize, initialEvent);
- if (CurrentStatus is Status.Halting)
- {
- await HaltAsync(initialEvent);
- }
- }
-
- ///
- /// Creates a new actor of the specified type and with the specified optional
- /// . This can only be used to access
- /// its payload, and cannot be handled.
- ///
- /// Type of the actor.
- /// Optional initialization event.
- /// Optional id that can be used to identify this operation.
- /// The unique actor id.
- protected ActorId CreateActor(Type type, Event initialEvent = null, Guid opGroupId = default) =>
- Runtime.CreateActor(null, type, null, initialEvent, this, opGroupId);
-
- ///
- /// Creates a new actor of the specified type and name, and with the specified
- /// optional . This can only be used to
- /// access its payload, and cannot be handled.
- ///
- /// Type of the actor.
- /// Optional name used for logging.
- /// Optional initialization event.
- /// Optional id that can be used to identify this operation.
- /// The unique actor id.
- protected ActorId CreateActor(Type type, string name, Event initialEvent = null, Guid opGroupId = default) =>
- Runtime.CreateActor(null, type, name, initialEvent, this, opGroupId);
-
- ///
- /// Creates a new actor of the specified and name, using the specified
- /// unbound actor id, and passes the specified optional . This event
- /// can only be used to access its payload, and cannot be handled.
- ///
- /// Unbound actor id.
- /// Type of the actor.
- /// Optional name used for logging.
- /// Optional initialization event.
- /// Optional id that can be used to identify this operation.
- protected void CreateActor(ActorId id, Type type, string name, Event initialEvent = null, Guid opGroupId = default) =>
- Runtime.CreateActor(id, type, name, initialEvent, this, opGroupId);
-
- ///
- /// Sends an asynchronous to a target.
- ///
- /// The id of the target.
- /// The event to send.
- /// Optional id that can be used to identify this operation.
- protected void SendEvent(ActorId id, Event e, Guid opGroupId = default) =>
- Runtime.SendEvent(id, e, this, opGroupId);
-
- ///
- /// Waits to receive an of the specified type
- /// that satisfies an optional predicate.
- ///
- /// The event type.
- /// The optional predicate.
- /// The received event.
- protected internal Task ReceiveEventAsync(Type eventType, Func predicate = null)
- {
- Assert(CurrentStatus is Status.Active, "{0} invoked ReceiveEventAsync while halting.", Id);
- Runtime.NotifyReceiveCalled(this);
- return Inbox.ReceiveEventAsync(eventType, predicate);
- }
-
- ///
- /// Waits to receive an of the specified types.
- ///
- /// The event types to wait for.
- /// The received event.
- protected internal Task ReceiveEventAsync(params Type[] eventTypes)
- {
- Assert(CurrentStatus is Status.Active, "{0} invoked ReceiveEventAsync while halting.", Id);
- Runtime.NotifyReceiveCalled(this);
- return Inbox.ReceiveEventAsync(eventTypes);
- }
-
- ///
- /// Waits to receive an of the specified types
- /// that satisfy the specified predicates.
- ///
- /// Event types and predicates.
- /// The received event.
- protected internal Task ReceiveEventAsync(params Tuple>[] events)
- {
- Assert(CurrentStatus is Status.Active, "{0} invoked ReceiveEventAsync while halting.", Id);
- Runtime.NotifyReceiveCalled(this);
- return Inbox.ReceiveEventAsync(events);
- }
-
- ///
- /// Returns a nondeterministic boolean choice, that can be
- /// controlled during analysis or testing.
- ///
- /// The controlled nondeterministic choice.
- protected bool RandomBoolean() => Runtime.GetNondeterministicBooleanChoice(2, Id.Name, Id.Type);
-
- ///
- /// Returns a nondeterministic boolean choice, that can be
- /// controlled during analysis or testing. The value is used
- /// to generate a number in the range [0..maxValue), where 0
- /// triggers true.
- ///
- /// The max value.
- /// The controlled nondeterministic choice.
- protected bool RandomBoolean(int maxValue) =>
- Runtime.GetNondeterministicBooleanChoice(maxValue, Id.Name, Id.Type);
-
- ///
- /// Returns a nondeterministic integer, that can be controlled during
- /// analysis or testing. The value is used to generate an integer in
- /// the range [0..maxValue).
- ///
- /// The max value.
- /// The controlled nondeterministic integer.
- protected int RandomInteger(int maxValue) =>
- Runtime.GetNondeterministicIntegerChoice(maxValue, Id.Name, Id.Type);
-
- ///
- /// Invokes the specified monitor with the specified .
- ///
- /// Type of the monitor.
- /// Event to send to the monitor.
- protected void Monitor(Event e) => Monitor(typeof(T), e);
-
- ///
- /// Invokes the specified monitor with the specified event.
- ///
- /// Type of the monitor.
- /// The event to send.
- protected void Monitor(Type type, Event e)
- {
- Assert(e != null, "{0} is sending a null event.", Id);
- Runtime.Monitor(type, e, Id.Name, Id.Type, CurrentStateName);
- }
-
- ///
- /// Checks if the assertion holds, and if not, throws an exception.
- ///
- protected void Assert(bool predicate) => Runtime.Assert(predicate);
-
- ///
- /// Checks if the assertion holds, and if not, throws an exception.
- ///
- protected void Assert(bool predicate, string s, object arg0) =>
- Runtime.Assert(predicate, s, arg0);
-
- ///
- /// Checks if the assertion holds, and if not, throws an exception.
- ///
- protected void Assert(bool predicate, string s, object arg0, object arg1) =>
- Runtime.Assert(predicate, s, arg0, arg1);
-
- ///
- /// Checks if the assertion holds, and if not, throws an exception.
- ///
- protected void Assert(bool predicate, string s, object arg0, object arg1, object arg2) =>
- Runtime.Assert(predicate, s, arg0, arg1, arg2);
-
- ///
- /// Checks if the assertion holds, and if not, throws an exception.
- ///
- protected void Assert(bool predicate, string s, params object[] args) =>
- Runtime.Assert(predicate, s, args);
-
- ///
- /// Raises a to halt the actor at the end of the current action.
- ///
- protected virtual void RaiseHaltEvent()
- {
- Assert(CurrentStatus is Status.Active, "{0} invoked Halt while halting.", Id);
- CurrentStatus = Status.Halting;
- }
-
- ///
- /// Asynchronous callback that is invoked when the actor is initialized with an optional event.
- ///
- /// Optional event used for initialization.
- /// Task that represents the asynchronous operation.
- protected virtual Task OnInitializeAsync(Event initialEvent) => Task.CompletedTask;
-
- ///
- /// Asynchronous callback that is invoked when the actor successfully dequeues
- /// an event from its inbox. This method is not called when the dequeue happens
- /// via a receive statement.
- ///
- /// The event that was dequeued.
- protected virtual Task OnEventDequeuedAsync(Event e) => Task.CompletedTask;
-
- ///
- /// Asynchronous callback that is invoked when the actor finishes handling a dequeued
- /// event, unless the handler of the dequeued event caused the actor to halt (either
- /// normally or due to an exception). The actor will either become idle or dequeue
- /// the next event from its inbox.
- ///
- /// The event that was handled.
- protected virtual Task OnEventHandledAsync(Event e) => Task.CompletedTask;
-
- ///
- /// Asynchronous callback that is invoked when the actor receives an event that
- /// it is not prepared to handle. The callback is invoked first, after which the
- /// actor will necessarily throw an
- ///
- /// The event that was unhandled.
- /// The state when the event was dequeued.
- protected virtual Task OnEventUnhandledAsync(Event e, string state) => Task.CompletedTask;
-
- ///
- /// Asynchronous callback that is invoked when the actor handles an exception.
- ///
- /// The exception thrown by the actor.
- /// The event being handled when the exception was thrown.
- /// The action that the runtime should take.
- protected virtual Task OnExceptionHandledAsync(Exception ex, Event e) => Task.CompletedTask;
-
- ///
- /// Asynchronous callback that is invoked when the actor halts.
- ///
- /// The event being handled when the actor halted.
- /// Task that represents the asynchronous operation.
- protected virtual Task OnHaltAsync(Event e) => Task.CompletedTask;
-
- ///
- /// Enqueues the specified event and its metadata.
- ///
- internal EnqueueStatus Enqueue(Event e, Guid opGroupId, EventInfo info)
- {
- if (CurrentStatus is Status.Halted)
- {
- return EnqueueStatus.Dropped;
- }
-
- return Inbox.Enqueue(e, opGroupId, info);
- }
-
- ///
- /// Runs the event handler. The handler terminates if there is no next
- /// event to process or if the actor has halted.
- ///
- internal async Task RunEventHandlerAsync()
- {
- Event lastDequeuedEvent = null;
- while (CurrentStatus != Status.Halted && Runtime.IsRunning)
- {
- (var status, var e, var opGroupId, var info) = Inbox.Dequeue();
- if (opGroupId != Guid.Empty)
- {
- // Inherit the operation group id of the dequeued operation, if it is non-empty.
- Manager.OperationGroupId = opGroupId;
- }
-
- if (status is DequeueStatus.Success)
- {
- // Notify the runtime for a new event to handle. This is only used
- // during bug-finding and operation bounding, because the runtime
- // has to schedule an actor when a new operation is dequeued.
- Runtime.NotifyDequeuedEvent(this, e, info);
- await InvokeUserCallbackAsync(UserCallbackType.OnEventDequeued, e);
- lastDequeuedEvent = e;
- }
- else if (status is DequeueStatus.Raised)
- {
- // Only supported by types (e.g. StateMachine) that allow
- // the user to explicitly raise events.
- Runtime.NotifyHandleRaisedEvent(this, e);
- }
- else if (status is DequeueStatus.Default)
- {
- Runtime.LogWriter.LogDefaultEventHandler(Id, CurrentStateName);
-
- // If the default event was dequeued, then notify the runtime.
- // This is only used during bug-finding, because the runtime must
- // instrument a scheduling point between default event handlers.
- Runtime.NotifyDefaultEventDequeued(this);
- }
- else if (status is DequeueStatus.NotAvailable)
- {
- // Terminate the handler as there is no event available.
- break;
- }
-
- if (CurrentStatus is Status.Active)
- {
- // Handles the next event, if the actor is not halted.
- await HandleEventAsync(e);
- }
-
- if (!Inbox.IsEventRaised && lastDequeuedEvent != null && CurrentStatus != Status.Halted)
- {
- // Inform the user that the actor handled the dequeued event.
- await InvokeUserCallbackAsync(UserCallbackType.OnEventHandled, lastDequeuedEvent);
- lastDequeuedEvent = null;
- }
-
- if (CurrentStatus is Status.Halting)
- {
- // If the current status is halting, then halt the actor.
- await HaltAsync(e);
- }
- }
- }
-
- ///
- /// Handles the specified .
- ///
- private protected virtual async Task HandleEventAsync(Event e)
- {
- if (ActionMap.TryGetValue(e.GetType(), out var cachedAction) ||
- ActionMap.TryGetValue(typeof(WildCardEvent), out cachedAction))
- {
- Runtime.NotifyInvokedAction(this, cachedAction.MethodInfo, null, null, e);
- await InvokeActionAsync(cachedAction, e);
- }
- else if (e is HaltEvent)
- {
- // If it is the halt event, then change the actor status to halting.
- CurrentStatus = Status.Halting;
- }
- else
- {
- await InvokeUserCallbackAsync(UserCallbackType.OnEventUnhandled, e);
- if (CurrentStatus is Status.Active)
- {
- // If the event cannot be handled then report an error, else halt gracefully.
- var ex = new UnhandledEventException(e, default, "Unhandled Event");
- var isHalting = OnUnhandledEventExceptionHandler(ex, e);
- Assert(isHalting, "{0} received event '{1}' that cannot be handled.",
- Id, e.GetType().FullName);
- }
- }
- }
-
- ///
- /// Invokes the specified action delegate.
- ///
- private protected async Task InvokeActionAsync(CachedDelegate cachedAction, Event e)
- {
- try
- {
- if (cachedAction.IsAsync)
- {
- Task task = null;
- if (cachedAction.Handler is Func taskFuncWithEvent)
- {
- task = taskFuncWithEvent(e);
- }
- else if (cachedAction.Handler is Func taskFunc)
- {
- task = taskFunc();
- }
-
- Runtime.NotifyWaitTask(this, task);
-
- // We have no reliable stack for awaited operations.
- await task;
- }
- else if (cachedAction.Handler is Action actionWithEvent)
- {
- actionWithEvent(e);
- }
- else if (cachedAction.Handler is Action action)
- {
- action();
- }
- }
- catch (Exception ex) when (OnExceptionHandler(ex, cachedAction.MethodInfo.Name, e))
- {
- // User handled the exception.
- await OnExceptionHandledAsync(ex, e);
- }
- catch (Exception ex) when (!cachedAction.IsAsync && InvokeOnFailureExceptionFilter(cachedAction, ex))
- {
- // Use an exception filter to call OnFailure before the stack
- // has been unwound. If the exception filter does not fail-fast,
- // it returns false to process the exception normally.
- }
- catch (Exception ex)
- {
- await TryHandleActionInvocationExceptionAsync(ex, cachedAction.MethodInfo.Name);
- }
- }
-
- ///
- /// Invokes the specified event handler user callback.
- ///
- private protected async Task InvokeUserCallbackAsync(string callbackType, Event e, string currentState = default)
- {
- try
- {
- Task task = null;
- if (callbackType is UserCallbackType.OnInitialize)
- {
- task = OnInitializeAsync(e);
- }
- else if (callbackType is UserCallbackType.OnEventDequeued)
- {
- task = OnEventDequeuedAsync(e);
- }
- else if (callbackType is UserCallbackType.OnEventHandled)
- {
- task = OnEventHandledAsync(e);
- }
- else if (callbackType is UserCallbackType.OnEventUnhandled)
- {
- task = OnEventUnhandledAsync(e, currentState);
- }
-
- Runtime.NotifyWaitTask(this, task);
- await task;
- }
- catch (Exception ex) when (OnExceptionHandler(ex, callbackType, e))
- {
- // User handled the exception.
- await OnExceptionHandledAsync(ex, e);
- }
- catch (Exception ex)
- {
- // Reports the unhandled exception.
- await TryHandleActionInvocationExceptionAsync(ex, callbackType);
- }
- }
-
- ///
- /// An exception filter that calls,
- /// which can choose to fast-fail the app to get a full dump.
- ///
- /// The action being executed when the failure occurred.
- /// The exception being tested.
- private protected bool InvokeOnFailureExceptionFilter(CachedDelegate action, Exception ex)
- {
- // This is called within the exception filter so the stack has not yet been unwound.
- // If the call does not fail-fast, return false to process the exception normally.
- Runtime.RaiseOnFailureEvent(new ActionExceptionFilterException(action.MethodInfo.Name, ex));
- return false;
- }
-
- ///
- /// Tries to handle an exception thrown during an action invocation.
- ///
- private protected Task TryHandleActionInvocationExceptionAsync(Exception ex, string actionName)
- {
- var innerException = ex;
- while (innerException is TargetInvocationException)
- {
- innerException = innerException.InnerException;
- }
-
- if (innerException is AggregateException)
- {
- innerException = innerException.InnerException;
- }
-
- if (innerException is ExecutionCanceledException || innerException is TaskSchedulerException)
- {
- CurrentStatus = Status.Halted;
- Debug.WriteLine($" {innerException.GetType().Name} was thrown from {Id}.");
- }
- else
- {
- // Reports the unhandled exception.
- ReportUnhandledException(innerException, actionName);
- }
-
- return Task.CompletedTask;
- }
-
- ///
- /// Checks if the specified event is ignored.
- ///
- internal bool IsEventIgnored(Event e)
- {
- return false;
- }
-
- ///
- /// Returns the hashed state of this actor.
- ///
- internal virtual int GetHashedState()
- {
- unchecked
- {
- var hash = 19;
- hash = (hash * 31) + GetType().GetHashCode();
- hash = (hash * 31) + Id.Value.GetHashCode();
- hash = (hash * 31) + IsHalted.GetHashCode();
-
- hash = (hash * 31) + Manager.GetCachedState();
- hash = (hash * 31) + Inbox.GetCachedState();
-
- if (this.HashedState != 0)
- {
- // Adds the user-defined hashed state.
- hash = (hash * 31) + HashedState;
- }
-
- return hash;
- }
- }
-
- ///
- /// Extracts user declarations and sets up the event handlers.
- ///
- internal virtual void SetupEventHandlers()
- {
- if (!ActionCache.ContainsKey(GetType()))
- {
- var actorTypes = new Stack();
- for (var actorType = GetType(); typeof(Actor).IsAssignableFrom(actorType); actorType = actorType.BaseType)
- {
- actorTypes.Push(actorType);
- }
-
- // process base types in reverse order, so mosts derrived type is cached first.
- while (actorTypes.Count > 0)
- {
- SetupEventHandlers(actorTypes.Pop());
- }
- }
-
- // Now we have all derrived types cached, we can build the combined action map for this type.
- for (var actorType = GetType(); typeof(Actor).IsAssignableFrom(actorType); actorType = actorType.BaseType)
- {
- // Populates the map of event handlers for this actor instance.
- foreach (var kvp in ActionCache[actorType])
- {
- // use the most derrived action handler for a given event (ignoring any base handlers defined for the same event).
- if (!ActionMap.ContainsKey(kvp.Key))
- {
- // MethodInfo.Invoke catches the exception to wrap it in a TargetInvocationException.
- // This unwinds the stack before the ExecuteAction exception filter is invoked, so
- // call through a delegate instead (which is also much faster than Invoke).
- ActionMap.Add(kvp.Key, new CachedDelegate(kvp.Value, this));
- }
- }
- }
- }
-
- private void SetupEventHandlers(Type actorType)
- {
- // If this type has not already been setup in the ActionCache, then we need to try and grab the ActionCacheLock
- // for this type. First make sure we have one and only one lockable object for this type.
- var syncObject = ActionCacheLocks.GetOrAdd(actorType, _ => new object());
-
- // Locking this syncObject ensures only one thread enters the initialization code to update
- // the ActionCache for this specific Actor type.
- lock (syncObject)
- {
- if (ActionCache.ContainsKey(actorType))
- {
- // Note: even if we won the GetOrAdd, there is a tiny window of opportunity for another thread
- // to slip in and lock the syncObject before us, so we have to check the ActionCache again
- // here just in case.
- }
- else
- {
- // Events with already declared handlers.
- var handledEvents = new HashSet();
-
- // Map containing all action bindings.
- var actionBindings = new Dictionary();
- var doAttributes = actorType.GetCustomAttributes(typeof(OnEventDoActionAttribute), false)
- as OnEventDoActionAttribute[];
-
- foreach (var attr in doAttributes)
- {
- Assert(!handledEvents.Contains(attr.Event),
- "{0} declared multiple handlers for event '{1}'.",
- actorType.FullName, attr.Event);
- actionBindings.Add(attr.Event, new ActionEventHandlerDeclaration(attr.Action));
- handledEvents.Add(attr.Event);
- }
-
- var map = new Dictionary();
- foreach (var action in actionBindings)
- {
- if (!map.ContainsKey(action.Key))
- {
- map.Add(action.Key, GetActionWithName(action.Value.Name));
- }
- }
-
- // Caches the action declarations for this actor type.
- ActionCache.TryAdd(actorType, map);
- }
- }
- }
-
- ///
- /// Returns the set of all registered events (for code coverage).
- /// It does not include events that are deferred or ignored.
- ///
- internal HashSet GetAllRegisteredEvents()
- {
- return new HashSet(from key in ActionMap.Keys select key.FullName);
- }
-
- ///
- /// Returns the action with the specified name.
- ///
- private protected MethodInfo GetActionWithName(string actionName)
- {
- MethodInfo action;
- var actorType = GetType();
-
- do
- {
- var bindingFlags = BindingFlags.Public | BindingFlags.NonPublic |
- BindingFlags.Instance | BindingFlags.FlattenHierarchy;
- action = actorType.GetMethod(actionName, bindingFlags, Type.DefaultBinder, SingleEventTypeArray, null);
- if (action is null)
- {
- action = actorType.GetMethod(actionName, bindingFlags, Type.DefaultBinder, Array.Empty(), null);
- }
-
- actorType = actorType.BaseType;
- }
- while (action is null && actorType != typeof(StateMachine) && actorType != typeof(Actor));
-
- Assert(action != null, "Cannot detect action declaration '{0}' in '{1}'.", actionName, GetType().FullName);
- AssertActionValidity(action);
- return action;
- }
-
- ///
- /// Checks the validity of the specified action.
- ///
- private void AssertActionValidity(MethodInfo action)
- {
- var actionType = action.DeclaringType;
- var parameters = action.GetParameters();
- Assert(parameters.Length is 0 ||
- (parameters.Length is 1 && parameters[0].ParameterType == typeof(Event)),
- "Action '{0}' in '{1}' must either accept no parameters or a single parameter of type 'Event'.",
- action.Name, actionType.Name);
-
- // Check if the action is an 'async' method.
- if (action.GetCustomAttribute(typeof(AsyncStateMachineAttribute)) != null)
- {
- Assert(action.ReturnType == typeof(Task),
- "Async action '{0}' in '{1}' must have 'Task' return type.",
- action.Name, actionType.Name);
- }
- else
- {
- Assert(action.ReturnType == typeof(void),
- "Action '{0}' in '{1}' must have 'void' return type.",
- action.Name, actionType.Name);
- }
- }
-
- ///
- /// Returns the formatted strint to be used with a fair nondeterministic boolean choice.
- ///
- private protected virtual string FormatFairRandom(string callerMemberName, string callerFilePath, int callerLineNumber) =>
- string.Format(CultureInfo.InvariantCulture, "{0}_{1}_{2}_{3}",
- Id.Name, callerMemberName, callerFilePath, callerLineNumber.ToString());
-
- ///
- /// Wraps the unhandled exception inside an
- /// exception, and throws it to the user.
- ///
- private protected virtual void ReportUnhandledException(Exception ex, string actionName)
- {
- Runtime.WrapAndThrowException(ex, $"{0} (action '{1}')", Id, actionName);
- }
-
- ///
- /// Invokes user callback when the actor throws an exception.
- ///
- /// The exception thrown by the actor.
- /// The handler (outermost) that threw the exception.
- /// The event being handled when the exception was thrown.
- /// True if the exception was handled, else false if it should continue to get thrown.
- private protected bool OnExceptionHandler(Exception ex, string methodName, Event e)
- {
- if (ex is ExecutionCanceledException)
- {
- // Internal exception used during testing.
- return false;
- }
-
- Runtime.LogWriter.LogExceptionThrown(Id, CurrentStateName, methodName, ex);
-
- var outcome = OnException(ex, methodName, e);
- if (outcome is OnExceptionOutcome.ThrowException)
- {
- return false;
- }
- else if (outcome is OnExceptionOutcome.Halt)
- {
- CurrentStatus = Status.Halting;
- }
-
- Runtime.LogWriter.LogExceptionHandled(Id, CurrentStateName, methodName, ex);
- return true;
- }
-
- ///
- /// Invokes user callback when the actor receives an event that it cannot handle.
- ///
- /// The exception thrown by the actor.
- /// The unhandled event.
- /// True if the the actor should gracefully halt, else false if the exception
- /// should continue to get thrown.
- private protected bool OnUnhandledEventExceptionHandler(UnhandledEventException ex, Event e)
- {
- Runtime.LogWriter.LogExceptionThrown(Id, ex.CurrentStateName, string.Empty, ex);
-
- var outcome = OnException(ex, string.Empty, e);
- if (outcome is OnExceptionOutcome.ThrowException)
- {
- return false;
- }
-
- CurrentStatus = Status.Halting;
- Runtime.LogWriter.LogExceptionHandled(Id, ex.CurrentStateName, string.Empty, ex);
- return true;
- }
-
- ///
- /// User callback when the actor throws an exception. By default,
- /// the actor throws the exception causing the runtime to fail.
- ///
- /// The exception thrown by the actor.
- /// The handler (outermost) that threw the exception.
- /// The event being handled when the exception was thrown.
- /// The action that the runtime should take.
- protected virtual OnExceptionOutcome OnException(Exception ex, string methodName, Event e)
- {
- return OnExceptionOutcome.ThrowException;
- }
-
- ///
- /// Halts the actor.
- ///
- /// The event being handled when the actor halts.
- private protected Task HaltAsync(Event e)
- {
- CurrentStatus = Status.Halted;
-
- // Close the inbox, which will stop any subsequent enqueues.
- Inbox.Close();
-
- Runtime.LogWriter.LogHalt(Id, Inbox.Size);
-
- // Dispose any held resources.
- Inbox.Dispose();
-
- // Invoke user callback.
- return OnHaltAsync(e);
- }
-
- ///
- /// Determines whether the specified object is equal to the current object.
- ///
- public override bool Equals(object obj)
- {
- if (obj is Actor m &&
- GetType() == m.GetType())
- {
- return Id.Value == m.Id.Value;
- }
-
- return false;
- }
-
- ///
- /// Returns the hash code for this instance.
- ///
- public override int GetHashCode()
- {
- return Id.Value.GetHashCode();
- }
-
- ///
- /// Returns a string that represents the current actor.
- ///
- public override string ToString()
- {
- return Id.Name;
- }
-
- ///
- /// The status of the actor.
- ///
- private protected enum Status
- {
- ///
- /// The actor is active.
- ///
- Active = 0,
-
- ///
- /// The actor is halting.
- ///
- Halting,
-
- ///
- /// The actor is halted.
- ///
- Halted
- }
-
- ///
- /// The type of a user callback.
- ///
- private protected static class UserCallbackType
- {
- internal const string OnInitialize = nameof(OnInitializeAsync);
- internal const string OnEventDequeued = nameof(OnEventDequeuedAsync);
- internal const string OnEventHandled = nameof(OnEventHandledAsync);
- internal const string OnEventUnhandled = nameof(OnEventUnhandledAsync);
- internal const string OnExceptionHandled = nameof(OnExceptionHandledAsync);
- internal const string OnHalt = nameof(OnHaltAsync);
- }
-
- ///
- /// Attribute for declaring which action should be invoked
- /// to handle a dequeued event of the specified type.
- ///
- [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
- protected sealed class OnEventDoActionAttribute : Attribute
- {
- ///
- /// The type of the dequeued event.
- ///
- internal Type Event;
-
- ///
- /// The name of the action to invoke.
- ///
- internal string Action;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The type of the dequeued event.
- /// The name of the action to invoke.
- public OnEventDoActionAttribute(Type eventType, string actionName)
- {
- Event = eventType;
- Action = actionName;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/Actors/ActorFactory.cs b/Src/PChecker/CheckerCore/Actors/ActorFactory.cs
deleted file mode 100644
index 7f6929b45f..0000000000
--- a/Src/PChecker/CheckerCore/Actors/ActorFactory.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-using System;
-using System.Collections.Generic;
-using System.Linq.Expressions;
-
-namespace PChecker.Actors
-{
- ///
- /// Factory for creating actor instances.
- ///
- internal static class ActorFactory
- {
- ///
- /// Cache storing actors constructors.
- ///
- private static readonly Dictionary> ActorConstructorCache =
- new Dictionary>();
-
- ///
- /// Creates a new instance of the specified type.
- ///
- /// The type of the actors.
- /// The created actor instance.
- public static Actor Create(Type type)
- {
- Func constructor = null;
- lock (ActorConstructorCache)
- {
- if (!ActorConstructorCache.TryGetValue(type, out constructor))
- {
- var constructorInfo = type.GetConstructor(Type.EmptyTypes);
- if (constructorInfo == null)
- {
- throw new Exception("Could not find empty constructor for type " + type.FullName);
- }
-
- constructor = Expression.Lambda>(
- Expression.New(constructorInfo)).Compile();
- ActorConstructorCache.Add(type, constructor);
- }
- }
-
- return constructor();
- }
- }
-}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/Actors/ActorRuntime.cs b/Src/PChecker/CheckerCore/Actors/ActorRuntime.cs
deleted file mode 100644
index 1959d9c76e..0000000000
--- a/Src/PChecker/CheckerCore/Actors/ActorRuntime.cs
+++ /dev/null
@@ -1,728 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Threading.Tasks;
-using PChecker.Actors.EventQueues;
-using PChecker.Actors.Events;
-using PChecker.Actors.Exceptions;
-using PChecker.Actors.Logging;
-using PChecker.Actors.Managers;
-using PChecker.Random;
-using PChecker.Runtime;
-using PChecker.Specifications.Monitors;
-using EventInfo = PChecker.Actors.Events.EventInfo;
-
-namespace PChecker.Actors
-{
- ///
- /// Runtime for creating and executing actors.
- ///
- internal class ActorRuntime : CoyoteRuntime, IActorRuntime
- {
- ///
- /// Map from unique actor ids to actors.
- ///
- private readonly ConcurrentDictionary ActorMap;
-
- ///
- /// Responsible for writing to all registered objects.
- ///
- protected internal LogWriter LogWriter { get; private set; }
-
- ///
- /// Used to log text messages. Use
- /// to replace the logger with a custom one.
- ///
- public override TextWriter Logger => LogWriter.Logger;
-
- ///
- /// Used to log json trace outputs.
- ///
- public JsonWriter JsonLogger => LogWriter.JsonLogger;
-
- ///
- /// Callback that is fired when a Coyote event is dropped.
- ///
- public event OnEventDroppedHandler OnEventDropped;
-
- ///
- /// Initializes a new instance of the class.
- ///
- internal ActorRuntime(CheckerConfiguration checkerConfiguration, IRandomValueGenerator valueGenerator)
- : base(checkerConfiguration, valueGenerator)
- {
- ActorMap = new ConcurrentDictionary();
- LogWriter = new LogWriter(checkerConfiguration);
- }
-
- ///
- /// Creates a fresh actor id that has not yet been bound to any actor.
- ///
- public ActorId CreateActorId(Type type, string name = null) => new ActorId(type, name, this);
-
- ///
- /// Creates a actor id that is uniquely tied to the specified unique name. The
- /// returned actor id can either be a fresh id (not yet bound to any actor), or
- /// it can be bound to a previously created actor. In the second case, this actor
- /// id can be directly used to communicate with the corresponding actor.
- ///
- public virtual ActorId CreateActorIdFromName(Type type, string name) => new ActorId(type, name, this, true);
-
- ///
- /// Creates a new actor of the specified and with the specified
- /// optional . This event can only be used to access its payload,
- /// and cannot be handled.
- ///
- public virtual ActorId CreateActor(Type type, Event initialEvent = null, Guid opGroupId = default) =>
- CreateActor(null, type, null, initialEvent, null, opGroupId);
-
- ///
- /// Creates a new actor of the specified and name, and with the
- /// specified optional . This event can only be used to access
- /// its payload, and cannot be handled.
- ///
- public virtual ActorId CreateActor(Type type, string name, Event initialEvent = null, Guid opGroupId = default) =>
- CreateActor(null, type, name, initialEvent, null, opGroupId);
-
- ///
- /// Creates a new actor of the specified type, using the specified .
- /// This method optionally passes an to the new actor, which can only
- /// be used to access its payload, and cannot be handled.
- ///
- public virtual ActorId CreateActor(ActorId id, Type type, Event initialEvent = null, Guid opGroupId = default) =>
- CreateActor(id, type, null, initialEvent, null, opGroupId);
-
- ///
- /// Creates a new actor of the specified and with the specified
- /// optional . This event can only be used to access its payload,
- /// and cannot be handled. The method returns only when the actor is initialized and
- /// the (if any) is handled.
- ///
- public virtual Task CreateActorAndExecuteAsync(Type type, Event initialEvent = null, Guid opGroupId = default) =>
- CreateActorAndExecuteAsync(null, type, null, initialEvent, null, opGroupId);
-
- ///
- /// Creates a new actor of the specified and name, and with the
- /// specified optional . This event can only be used to access
- /// its payload, and cannot be handled. The method returns only when the actor is
- /// initialized and the (if any) is handled.
- ///
- public virtual Task CreateActorAndExecuteAsync(Type type, string name, Event initialEvent = null,
- Guid opGroupId = default) =>
- CreateActorAndExecuteAsync(null, type, name, initialEvent, null, opGroupId);
-
- ///
- /// Creates a new actor of the specified , using the specified unbound
- /// actor id, and passes the specified optional . This event can only
- /// be used to access its payload, and cannot be handled. The method returns only when
- /// the actor is initialized and the (if any)
- /// is handled.
- ///
- public virtual Task CreateActorAndExecuteAsync(ActorId id, Type type, Event initialEvent = null,
- Guid opGroupId = default) =>
- CreateActorAndExecuteAsync(id, type, null, initialEvent, null, opGroupId);
-
- ///
- /// Sends an asynchronous to an actor.
- ///
- public virtual void SendEvent(ActorId targetId, Event initialEvent, Guid opGroupId = default) =>
- SendEvent(targetId, initialEvent, null, opGroupId);
-
- ///
- /// Sends an to an actor. Returns immediately if the target was already
- /// running. Otherwise blocks until the target handles the event and reaches quiescense.
- ///
- public virtual Task SendEventAndExecuteAsync(ActorId targetId, Event initialEvent,
- Guid opGroupId = default) =>
- SendEventAndExecuteAsync(targetId, initialEvent, null, opGroupId);
-
- ///
- /// Returns the operation group id of the actor with the specified id. Returns
- /// if the id is not set, or if the is not associated with this runtime. During
- /// testing, the runtime asserts that the specified actor is currently executing.
- ///
- public virtual Guid GetCurrentOperationGroupId(ActorId currentActorId)
- {
- var actor = GetActorWithId(currentActorId);
- return actor is null ? Guid.Empty : actor.OperationGroupId;
- }
-
- ///
- /// Creates a new of the specified .
- ///
- internal virtual ActorId CreateActor(ActorId id, Type type, string name, Event initialEvent,
- Actor creator, Guid opGroupId)
- {
- var actor = CreateActor(id, type, name, creator, opGroupId);
- if (actor is StateMachine)
- {
- LogWriter.LogCreateStateMachine(actor.Id, creator?.Id.Name, creator?.Id.Type);
- }
- else
- {
- LogWriter.LogCreateActor(actor.Id, creator?.Id.Name, creator?.Id.Type);
- }
-
- RunActorEventHandler(actor, initialEvent, true);
- return actor.Id;
- }
-
- ///
- /// Creates a new of the specified . The method
- /// returns only when the actor is initialized and the (if any)
- /// is handled.
- ///
- internal virtual async Task CreateActorAndExecuteAsync(ActorId id, Type type, string name,
- Event initialEvent, Actor creator, Guid opGroupId)
- {
- var actor = CreateActor(id, type, name, creator, opGroupId);
- if (actor is StateMachine)
- {
- LogWriter.LogCreateStateMachine(actor.Id, creator?.Id.Name, creator?.Id.Type);
- }
- else
- {
- LogWriter.LogCreateActor(actor.Id, creator?.Id.Name, creator?.Id.Type);
- }
-
- await RunActorEventHandlerAsync(actor, initialEvent, true);
- return actor.Id;
- }
-
- ///
- /// Creates a new of the specified .
- ///
- private Actor CreateActor(ActorId id, Type type, string name, Actor creator, Guid opGroupId)
- {
- if (!type.IsSubclassOf(typeof(Actor)))
- {
- Assert(false, "Type '{0}' is not an actor.", type.FullName);
- }
-
- if (id is null)
- {
- id = new ActorId(type, name, this);
- }
- else if (id.Runtime != null && id.Runtime != this)
- {
- Assert(false, "Unbound actor id '{0}' was created by another runtime.", id.Value);
- }
- else if (id.Type != type.FullName)
- {
- Assert(false, "Cannot bind actor id '{0}' of type '{1}' to an actor of type '{2}'.",
- id.Value, id.Type, type.FullName);
- }
- else
- {
- id.Bind(this);
- }
-
- // The operation group id of the actor is set using the following precedence:
- // (1) To the specified actor creation operation group id, if it is non-empty.
- // (2) To the operation group id of the creator actor, if it exists.
- // (3) To the empty operation group id.
- if (opGroupId == Guid.Empty && creator != null)
- {
- opGroupId = creator.OperationGroupId;
- }
-
- var actor = ActorFactory.Create(type);
- IActorManager actorManager;
- if (actor is StateMachine stateMachine)
- {
- actorManager = new StateMachineManager(this, stateMachine, opGroupId);
- }
- else
- {
- actorManager = new ActorManager(this, actor, opGroupId);
- }
-
- IEventQueue eventQueue = new EventQueue(actorManager);
- actor.Configure(this, id, actorManager, eventQueue);
- actor.SetupEventHandlers();
-
- if (!ActorMap.TryAdd(id, actor))
- {
- var info = "This typically occurs if either the actor id was created by another runtime instance, " +
- "or if a actor id from a previous runtime generation was deserialized, but the current runtime " +
- "has not increased its generation value.";
- Assert(false, "An actor with id '{0}' was already created in generation '{1}'. {2}", id.Value, id.Generation, info);
- }
-
- return actor;
- }
-
- ///
- /// Sends an asynchronous to an actor.
- ///
- internal virtual void SendEvent(ActorId targetId, Event e, Actor sender, Guid opGroupId)
- {
- var enqueueStatus = EnqueueEvent(targetId, e, sender, opGroupId, out var target);
- if (enqueueStatus is EnqueueStatus.EventHandlerNotRunning)
- {
- RunActorEventHandler(target, null, false);
- }
- }
-
- ///
- /// Sends an asynchronous to an actor. Returns immediately if the target was
- /// already running. Otherwise blocks until the target handles the event and reaches quiescense.
- ///
- internal virtual async Task SendEventAndExecuteAsync(ActorId targetId, Event e, Actor sender,
- Guid opGroupId)
- {
- var enqueueStatus = EnqueueEvent(targetId, e, sender, opGroupId, out var target);
- if (enqueueStatus is EnqueueStatus.EventHandlerNotRunning)
- {
- await RunActorEventHandlerAsync(target, null, false);
- return true;
- }
-
- return enqueueStatus is EnqueueStatus.Dropped;
- }
-
- ///
- /// Enqueues an event to the actor with the specified id.
- ///
- private EnqueueStatus EnqueueEvent(ActorId targetId, Event e, Actor sender, Guid opGroupId, out Actor target)
- {
- if (e is null)
- {
- var message = sender != null ?
- string.Format("{0} is sending a null event.", sender.Id.ToString()) :
- "Cannot send a null event.";
- Assert(false, message);
- }
-
- if (targetId is null)
- {
- var message = (sender != null) ? $"{sender.Id.ToString()} is sending event {e.ToString()} to a null actor."
- : $"Cannot send event {e.ToString()} to a null actor.";
-
- Assert(false, message);
- }
-
- // The operation group id of this operation is set using the following precedence:
- // (1) To the specified send operation group id, if it is non-empty.
- // (2) To the operation group id of the sender actor, if it exists and is non-empty.
- // (3) To the empty operation group id.
- if (opGroupId == Guid.Empty && sender != null)
- {
- opGroupId = sender.OperationGroupId;
- }
-
- target = GetActorWithId(targetId);
- if (target is null || target.IsHalted)
- {
- LogWriter.LogSendEvent(targetId, sender?.Id.Name, sender?.Id.Type,
- (sender as StateMachine)?.CurrentStateName ?? string.Empty, e, opGroupId, isTargetHalted: true);
- TryHandleDroppedEvent(e, targetId);
- return EnqueueStatus.Dropped;
- }
-
- LogWriter.LogSendEvent(targetId, sender?.Id.Name, sender?.Id.Type,
- (sender as StateMachine)?.CurrentStateName ?? string.Empty, e, opGroupId, isTargetHalted: false);
-
- var enqueueStatus = target.Enqueue(e, opGroupId, null);
- if (enqueueStatus == EnqueueStatus.Dropped)
- {
- TryHandleDroppedEvent(e, targetId);
- }
-
- return enqueueStatus;
- }
-
- ///
- /// Runs a new asynchronous actor event handler.
- /// This is a fire and forget invocation.
- ///
- private void RunActorEventHandler(Actor actor, Event initialEvent, bool isFresh)
- {
- Task.Run(async () =>
- {
- try
- {
- if (isFresh)
- {
- await actor.InitializeAsync(initialEvent);
- }
-
- await actor.RunEventHandlerAsync();
- }
- catch (Exception ex)
- {
- IsRunning = false;
- RaiseOnFailureEvent(ex);
- }
- finally
- {
- if (actor.IsHalted)
- {
- ActorMap.TryRemove(actor.Id, out var _);
- }
- }
- });
- }
-
- ///
- /// Runs a new asynchronous actor event handler.
- ///
- private async Task RunActorEventHandlerAsync(Actor actor, Event initialEvent, bool isFresh)
- {
- try
- {
- if (isFresh)
- {
- await actor.InitializeAsync(initialEvent);
- }
-
- await actor.RunEventHandlerAsync();
- }
- catch (Exception ex)
- {
- IsRunning = false;
- RaiseOnFailureEvent(ex);
- return;
- }
- }
-
- ///
- internal override void TryCreateMonitor(Type type)
- {
- lock (Monitors)
- {
- if (Monitors.Any(m => m.GetType() == type))
- {
- // Idempotence: only one monitor per type can exist.
- return;
- }
- }
-
- Assert(type.IsSubclassOf(typeof(Monitor)), "Type '{0}' is not a subclass of Monitor.", type.FullName);
-
- var monitor = (Monitor)Activator.CreateInstance(type);
- monitor.Initialize(this);
- monitor.InitializeStateInformation();
-
- lock (Monitors)
- {
- Monitors.Add(monitor);
- }
-
- LogWriter.LogCreateMonitor(type.FullName);
-
- monitor.GotoStartState();
- }
-
- ///
- internal override bool GetNondeterministicBooleanChoice(int maxValue, string callerName, string callerType)
- {
- var result = false;
- if (ValueGenerator.Next(maxValue) == 0)
- {
- result = true;
- }
-
- LogWriter.LogRandom(result, callerName, callerType);
- return result;
- }
-
- ///
- internal override int GetNondeterministicIntegerChoice(int maxValue, string callerName, string callerType)
- {
- var result = ValueGenerator.Next(maxValue);
- LogWriter.LogRandom(result, callerName, callerType);
- return result;
- }
-
- ///
- /// Gets the actor of type with the specified id,
- /// or null if no such actor exists.
- ///
- private TActor GetActorWithId(ActorId id)
- where TActor : Actor =>
- id != null && ActorMap.TryGetValue(id, out var value) &&
- value is TActor actor ? actor : null;
-
- ///
- /// Notifies that an actor invoked an action.
- ///
- internal virtual void NotifyInvokedAction(Actor actor, MethodInfo action, string handlingStateName,
- string currentStateName, Event receivedEvent)
- {
- if (CheckerConfiguration.IsVerbose)
- {
- LogWriter.LogExecuteAction(actor.Id, handlingStateName, currentStateName, action.Name);
- }
- }
-
- ///
- /// Notifies that an actor dequeued an .
- ///
- internal virtual void NotifyDequeuedEvent(Actor actor, Event e, EventInfo eventInfo)
- {
- if (CheckerConfiguration.IsVerbose)
- {
- var stateName = actor is StateMachine stateMachine ? stateMachine.CurrentStateName : string.Empty;
- LogWriter.LogDequeueEvent(actor.Id, stateName, e);
- }
- }
-
- ///
- /// Notifies that an actor dequeued the default .
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal virtual void NotifyDefaultEventDequeued(Actor actor)
- {
- }
-
- ///
- /// Notifies that the inbox of the specified actor is about to be
- /// checked to see if the default event handler should fire.
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal virtual void NotifyDefaultEventHandlerCheck(Actor actor)
- {
- }
-
- ///
- /// Notifies that an actor raised an .
- ///
- internal virtual void NotifyRaisedEvent(Actor actor, Event e, EventInfo eventInfo)
- {
- if (CheckerConfiguration.IsVerbose)
- {
- var stateName = actor is StateMachine stateMachine ? stateMachine.CurrentStateName : string.Empty;
- LogWriter.LogRaiseEvent(actor.Id, stateName, e);
- }
- }
-
- ///
- /// Notifies that an actor is handling a raised .
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal virtual void NotifyHandleRaisedEvent(Actor actor, Event e)
- {
- }
-
- ///
- /// Notifies that an actor called
- /// or one of its overloaded methods.
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal virtual void NotifyReceiveCalled(Actor actor)
- {
- }
-
- ///
- /// Notifies that an actor enqueued an event that it was waiting to receive.
- ///
- internal virtual void NotifyReceivedEvent(Actor actor, Event e, EventInfo eventInfo)
- {
- if (CheckerConfiguration.IsVerbose)
- {
- var stateName = actor is StateMachine stateMachine ? stateMachine.CurrentStateName : string.Empty;
- LogWriter.LogReceiveEvent(actor.Id, stateName, e, wasBlocked: true);
- }
- }
-
- ///
- /// Notifies that an actor received an event without waiting because the event
- /// was already in the inbox when the actor invoked the receive statement.
- ///
- internal virtual void NotifyReceivedEventWithoutWaiting(Actor actor, Event e, EventInfo eventInfo)
- {
- if (CheckerConfiguration.IsVerbose)
- {
- var stateName = actor is StateMachine stateMachine ? stateMachine.CurrentStateName : string.Empty;
- LogWriter.LogReceiveEvent(actor.Id, stateName, e, wasBlocked: false);
- }
- }
-
- ///
- /// Notifies that an actor is waiting for the specified task to complete.
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal virtual void NotifyWaitTask(Actor actor, Task task)
- {
- }
-
- ///
- /// Notifies that an actor is waiting to receive an event of one of the specified types.
- ///
- internal virtual void NotifyWaitEvent(Actor actor, IEnumerable eventTypes)
- {
- if (CheckerConfiguration.IsVerbose)
- {
- var stateName = actor is StateMachine stateMachine ? stateMachine.CurrentStateName : string.Empty;
- var eventWaitTypesArray = eventTypes.ToArray();
- if (eventWaitTypesArray.Length == 1)
- {
- LogWriter.LogWaitEvent(actor.Id, stateName, eventWaitTypesArray[0]);
- }
- else
- {
- LogWriter.LogWaitEvent(actor.Id, stateName, eventWaitTypesArray);
- }
- }
- }
-
- ///
- /// Notifies that a state machine entered a state.
- ///
- internal virtual void NotifyEnteredState(StateMachine stateMachine)
- {
- if (CheckerConfiguration.IsVerbose)
- {
- LogWriter.LogStateTransition(stateMachine.Id, stateMachine.CurrentStateName, isEntry: true);
- }
- }
-
- ///
- /// Notifies that a state machine exited a state.
- ///
- internal virtual void NotifyExitedState(StateMachine stateMachine)
- {
- if (CheckerConfiguration.IsVerbose)
- {
- LogWriter.LogStateTransition(stateMachine.Id, stateMachine.CurrentStateName, isEntry: false);
- }
- }
-
- ///
- /// Notifies that a state machine invoked pop.
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal virtual void NotifyPopState(StateMachine stateMachine)
- {
- }
-
- ///
- /// Notifies that a state machine invoked an action.
- ///
- internal virtual void NotifyInvokedOnEntryAction(StateMachine stateMachine, MethodInfo action, Event receivedEvent)
- {
- if (CheckerConfiguration.IsVerbose)
- {
- LogWriter.LogExecuteAction(stateMachine.Id, stateMachine.CurrentStateName,
- stateMachine.CurrentStateName, action.Name);
- }
- }
-
- ///
- /// Notifies that a state machine invoked an action.
- ///
- internal virtual void NotifyInvokedOnExitAction(StateMachine stateMachine, MethodInfo action, Event receivedEvent)
- {
- if (CheckerConfiguration.IsVerbose)
- {
- LogWriter.LogExecuteAction(stateMachine.Id, stateMachine.CurrentStateName,
- stateMachine.CurrentStateName, action.Name);
- }
- }
-
- ///
- /// Notifies that a monitor entered a state.
- ///
- internal virtual void NotifyEnteredState(Monitor monitor)
- {
- if (CheckerConfiguration.IsVerbose)
- {
- var monitorState = monitor.CurrentStateNameWithTemperature;
- LogWriter.LogMonitorStateTransition(monitor.GetType().FullName, monitorState,
- true, monitor.GetHotState());
- }
- }
-
- ///
- /// Notifies that a monitor exited a state.
- ///
- internal virtual void NotifyExitedState(Monitor monitor)
- {
- if (CheckerConfiguration.IsVerbose)
- {
- var monitorState = monitor.CurrentStateNameWithTemperature;
- LogWriter.LogMonitorStateTransition(monitor.GetType().FullName, monitorState,
- false, monitor.GetHotState());
- }
- }
-
- ///
- /// Notifies that a monitor invoked an action.
- ///
- internal virtual void NotifyInvokedAction(Monitor monitor, MethodInfo action, string stateName, Event receivedEvent)
- {
- if (CheckerConfiguration.IsVerbose)
- {
- LogWriter.LogMonitorExecuteAction(monitor.GetType().FullName, action.Name, stateName);
- }
- }
-
- ///
- /// Notifies that a monitor raised an .
- ///
- internal virtual void NotifyRaisedEvent(Monitor monitor, Event e)
- {
- if (CheckerConfiguration.IsVerbose)
- {
- var monitorState = monitor.CurrentStateNameWithTemperature;
- LogWriter.LogMonitorRaiseEvent(monitor.GetType().FullName, monitorState, e);
- }
- }
-
- ///
- /// Notifies that a monitor found an error.
- ///
- internal void NotifyMonitorError(Monitor monitor)
- {
- if (CheckerConfiguration.IsVerbose)
- {
- var monitorState = monitor.CurrentStateNameWithTemperature;
- LogWriter.LogMonitorError(monitor.GetType().FullName, monitorState, monitor.GetHotState());
- }
- }
-
- ///
- /// Tries to handle the specified dropped .
- ///
- internal void TryHandleDroppedEvent(Event e, ActorId id) => OnEventDropped?.Invoke(e, id);
-
- ///
- public override TextWriter SetLogger(TextWriter logger) => LogWriter.SetLogger(logger);
-
- ///
- /// Sets the JsonLogger in LogWriter.cs
- ///
- /// jsonLogger instance
- public void SetJsonLogger(JsonWriter jsonLogger) => LogWriter.SetJsonLogger(jsonLogger);
-
- ///
- /// Use this method to register an .
- ///
- public void RegisterLog(IActorRuntimeLog log) => LogWriter.RegisterLog(log);
-
- ///
- /// Use this method to unregister a previously registered .
- ///
- public void RemoveLog(IActorRuntimeLog log) => LogWriter.RemoveLog(log);
-
- ///
- protected override void Dispose(bool disposing)
- {
- if (disposing)
- {
- Monitors.Clear();
- ActorMap.Clear();
- }
-
- base.Dispose(disposing);
- }
- }
-}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/Actors/EventQueues/EventQueue.cs b/Src/PChecker/CheckerCore/Actors/EventQueues/EventQueue.cs
deleted file mode 100644
index fa35a4758f..0000000000
--- a/Src/PChecker/CheckerCore/Actors/EventQueues/EventQueue.cs
+++ /dev/null
@@ -1,295 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using PChecker.Actors.Events;
-using PChecker.Actors.Managers;
-
-namespace PChecker.Actors.EventQueues
-{
- ///
- /// Implements a queue of events.
- ///
- internal sealed class EventQueue : IEventQueue
- {
- ///
- /// Manages the actor that owns this queue.
- ///
- private readonly IActorManager ActorManager;
-
- ///
- /// The internal queue.
- ///
- private readonly LinkedList<(Event e, Guid opGroupId)> Queue;
-
- ///
- /// The raised event and its metadata, or null if no event has been raised.
- ///
- private (Event e, Guid opGroupId) RaisedEvent;
-
- ///
- /// Map from the types of events that the owner of the queue is waiting to receive
- /// to an optional predicate. If an event of one of these types is enqueued, then
- /// if there is no predicate, or if there is a predicate and evaluates to true, then
- /// the event is received, else the event is deferred.
- ///
- private Dictionary> EventWaitTypes;
-
- ///
- /// Task completion source that contains the event obtained using an explicit receive.
- ///
- private TaskCompletionSource ReceiveCompletionSource;
-
- ///
- /// Checks if the queue is accepting new events.
- ///
- private bool IsClosed;
-
- ///
- public int Size => Queue.Count;
-
- ///
- public bool IsEventRaised => RaisedEvent != default;
-
- ///
- /// Initializes a new instance of the class.
- ///
- internal EventQueue(IActorManager actorManager)
- {
- ActorManager = actorManager;
- Queue = new LinkedList<(Event, Guid)>();
- EventWaitTypes = new Dictionary>();
- IsClosed = false;
- }
-
- ///
- public EnqueueStatus Enqueue(Event e, Guid opGroupId, EventInfo info)
- {
- var enqueueStatus = EnqueueStatus.EventHandlerRunning;
- lock (Queue)
- {
- if (IsClosed)
- {
- return EnqueueStatus.Dropped;
- }
-
- if (EventWaitTypes != null &&
- EventWaitTypes.TryGetValue(e.GetType(), out var predicate) &&
- (predicate is null || predicate(e)))
- {
- EventWaitTypes = null;
- enqueueStatus = EnqueueStatus.Received;
- }
- else
- {
- Queue.AddLast((e, opGroupId));
- if (!ActorManager.IsEventHandlerRunning)
- {
- ActorManager.IsEventHandlerRunning = true;
- enqueueStatus = EnqueueStatus.EventHandlerNotRunning;
- }
- }
- }
-
- if (enqueueStatus is EnqueueStatus.Received)
- {
- ActorManager.OnReceiveEvent(e, opGroupId, info);
- ReceiveCompletionSource.SetResult(e);
- return enqueueStatus;
- }
- else
- {
- ActorManager.OnEnqueueEvent(e, opGroupId, info);
- }
-
- return enqueueStatus;
- }
-
- ///
- public (DequeueStatus status, Event e, Guid opGroupId, EventInfo info) Dequeue()
- {
- // Try to get the raised event, if there is one. Raised events
- // have priority over the events in the inbox.
- if (RaisedEvent != default)
- {
- if (ActorManager.IsEventIgnored(RaisedEvent.e, RaisedEvent.opGroupId, null))
- {
- // TODO: should the user be able to raise an ignored event?
- // The raised event is ignored in the current state.
- RaisedEvent = default;
- }
- else
- {
- (var e, var opGroupId) = RaisedEvent;
- RaisedEvent = default;
- return (DequeueStatus.Raised, e, opGroupId, null);
- }
- }
-
- lock (Queue)
- {
- // Try to dequeue the next event, if there is one.
- var node = Queue.First;
- while (node != null)
- {
- // Iterates through the events in the inbox.
- if (ActorManager.IsEventIgnored(node.Value.e, node.Value.opGroupId, null))
- {
- // Removes an ignored event.
- var nextNode = node.Next;
- Queue.Remove(node);
- node = nextNode;
- continue;
- }
- else if (ActorManager.IsEventDeferred(node.Value.e, node.Value.opGroupId, null))
- {
- // Skips a deferred event.
- node = node.Next;
- continue;
- }
-
- // Found next event that can be dequeued.
- Queue.Remove(node);
- return (DequeueStatus.Success, node.Value.e, node.Value.opGroupId, null);
- }
-
- // No event can be dequeued, so check if there is a default event handler.
- if (!ActorManager.IsDefaultHandlerAvailable())
- {
- // There is no default event handler installed, so do not return an event.
- // Setting IsEventHandlerRunning must happen inside the lock as it needs
- // to be synchronized with the enqueue and starting a new event handler.
- ActorManager.IsEventHandlerRunning = false;
- return (DequeueStatus.NotAvailable, null, Guid.Empty, null);
- }
- }
-
- // TODO: check op-id of default event.
- // A default event handler exists.
- return (DequeueStatus.Default, DefaultEvent.Instance, Guid.Empty, null);
- }
-
- ///
- public void RaiseEvent(Event e, Guid opGroupId)
- {
- RaisedEvent = (e, opGroupId);
- ActorManager.OnRaiseEvent(e, opGroupId, null);
- }
-
- ////
- public Task ReceiveEventAsync(Type eventType, Func predicate = null)
- {
- var eventWaitTypes = new Dictionary>
- {
- { eventType, predicate }
- };
-
- return ReceiveEventAsync(eventWaitTypes);
- }
-
- ///
- public Task ReceiveEventAsync(params Type[] eventTypes)
- {
- var eventWaitTypes = new Dictionary>();
- foreach (var type in eventTypes)
- {
- eventWaitTypes.Add(type, null);
- }
-
- return ReceiveEventAsync(eventWaitTypes);
- }
-
- ///
- public Task ReceiveEventAsync(params Tuple>[] events)
- {
- var eventWaitTypes = new Dictionary>();
- foreach (var e in events)
- {
- eventWaitTypes.Add(e.Item1, e.Item2);
- }
-
- return ReceiveEventAsync(eventWaitTypes);
- }
-
- ///
- /// Waits for an event to be enqueued based on the conditions defined in the event wait types.
- ///
- private Task ReceiveEventAsync(Dictionary> eventWaitTypes)
- {
- (Event e, Guid opGroupId) receivedEvent = default;
- lock (Queue)
- {
- var node = Queue.First;
- while (node != null)
- {
- // Dequeue the first event that the caller waits to receive, if there is one in the queue.
- if (eventWaitTypes.TryGetValue(node.Value.e.GetType(), out var predicate) &&
- (predicate is null || predicate(node.Value.e)))
- {
- receivedEvent = node.Value;
- Queue.Remove(node);
- break;
- }
-
- node = node.Next;
- }
-
- if (receivedEvent == default)
- {
- ReceiveCompletionSource = new TaskCompletionSource();
- EventWaitTypes = eventWaitTypes;
- }
- }
-
- if (receivedEvent == default)
- {
- // Note that EventWaitTypes is racy, so should not be accessed outside
- // the lock, this is why we access eventWaitTypes instead.
- ActorManager.OnWaitEvent(eventWaitTypes.Keys);
- return ReceiveCompletionSource.Task;
- }
-
- ActorManager.OnReceiveEventWithoutWaiting(receivedEvent.e, receivedEvent.opGroupId, null);
- return Task.FromResult(receivedEvent.e);
- }
-
- ////
- public int GetCachedState() => 0;
-
- ///
- public void Close()
- {
- lock (Queue)
- {
- IsClosed = true;
- }
- }
-
- ///
- /// Disposes the queue resources.
- ///
- private void Dispose(bool disposing)
- {
- if (!disposing)
- {
- return;
- }
-
- foreach (var (e, opGroupId) in Queue)
- {
- ActorManager.OnDropEvent(e, opGroupId, null);
- }
-
- Queue.Clear();
- }
-
- ///
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- }
-}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/Actors/Events/Event.cs b/Src/PChecker/CheckerCore/Actors/Events/Event.cs
deleted file mode 100644
index a33f298172..0000000000
--- a/Src/PChecker/CheckerCore/Actors/Events/Event.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-using System.Runtime.Serialization;
-
-namespace PChecker.Actors.Events
-{
- ///
- /// Abstract class representing an event.
- ///
- [DataContract]
- public abstract class Event
- {
- }
-}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/Actors/Exceptions/OnEventDroppedHandler.cs b/Src/PChecker/CheckerCore/Actors/Exceptions/OnEventDroppedHandler.cs
deleted file mode 100644
index a96ad02dc0..0000000000
--- a/Src/PChecker/CheckerCore/Actors/Exceptions/OnEventDroppedHandler.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-using PChecker.Actors.Events;
-
-namespace PChecker.Actors.Exceptions
-{
- ///
- /// Handles the event.
- ///
- public delegate void OnEventDroppedHandler(Event e, ActorId target);
-}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/Actors/IActorRuntime.cs b/Src/PChecker/CheckerCore/Actors/IActorRuntime.cs
deleted file mode 100644
index c93bb2909c..0000000000
--- a/Src/PChecker/CheckerCore/Actors/IActorRuntime.cs
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-using System;
-using System.Threading.Tasks;
-using PChecker.Actors.Events;
-using PChecker.Actors.Exceptions;
-using PChecker.Actors.Logging;
-using PChecker.Runtime;
-
-namespace PChecker.Actors
-{
- ///
- /// Interface that exposes runtime methods for creating and executing actors.
- ///
- public interface IActorRuntime : ICoyoteRuntime
- {
- ///
- /// Callback that is fired when an event is dropped.
- ///
- event OnEventDroppedHandler OnEventDropped;
-
- ///
- /// Creates a fresh actor id that has not yet been bound to any actor.
- ///
- /// Type of the actor.
- /// Optional name used for logging.
- /// The result is the actor id.
- ActorId CreateActorId(Type type, string name = null);
-
- ///
- /// Creates a actor id that is uniquely tied to the specified unique name. The
- /// returned actor id can either be a fresh id (not yet bound to any actor), or
- /// it can be bound to a previously created actor. In the second case, this actor
- /// id can be directly used to communicate with the corresponding actor.
- ///
- /// Type of the actor.
- /// Unique name used to create or get the actor id.
- /// The result is the actor id.
- ActorId CreateActorIdFromName(Type type, string name);
-
- ///
- /// Creates a new actor of the specified and with the specified
- /// optional . This event can only be used to access its payload,
- /// and cannot be handled.
- ///
- /// Type of the actor.
- /// Optional event used during initialization.
- /// Optional id that can be used to identify this operation.
- /// The result is the actor id.
- ActorId CreateActor(Type type, Event initialEvent = null, Guid opGroupId = default);
-
- ///
- /// Creates a new actor of the specified and name, and with the
- /// specified optional . This event can only be used to access
- /// its payload, and cannot be handled.
- ///
- /// Type of the actor.
- /// Optional name used for logging.
- /// Optional event used during initialization.
- /// Optional id that can be used to identify this operation.
- /// The result is the actor id.
- ActorId CreateActor(Type type, string name, Event initialEvent = null, Guid opGroupId = default);
-
- ///
- /// Creates a new actor of the specified type, using the specified .
- /// This method optionally passes an to the new actor, which can only
- /// be used to access its payload, and cannot be handled.
- ///
- /// Unbound actor id.
- /// Type of the actor.
- /// Optional event used during initialization.
- /// Optional id that can be used to identify this operation.
- /// The result is the actor id.
- ActorId CreateActor(ActorId id, Type type, Event initialEvent = null, Guid opGroupId = default);
-
- ///
- /// Creates a new actor of the specified and with the specified
- /// optional . This event can only be used to access its payload,
- /// and cannot be handled. The method returns only when the actor is initialized and
- /// the (if any) is handled.
- ///
- /// Type of the actor.
- /// Optional event used during initialization.
- /// Optional id that can be used to identify this operation.
- /// Task that represents the asynchronous operation. The task result is the actor id.
- Task CreateActorAndExecuteAsync(Type type, Event initialEvent = null, Guid opGroupId = default);
-
- ///
- /// Creates a new actor of the specified and name, and with the
- /// specified optional . This event can only be used to access
- /// its payload, and cannot be handled. The method returns only when the actor is
- /// initialized and the (if any) is handled.
- ///
- /// Type of the actor.
- /// Optional name used for logging.
- /// Optional event used during initialization.
- /// Optional id that can be used to identify this operation.
- /// Task that represents the asynchronous operation. The task result is the actor id.
- Task CreateActorAndExecuteAsync(Type type, string name, Event initialEvent = null,
- Guid opGroupId = default);
-
- ///
- /// Creates a new actor of the specified , using the specified unbound
- /// actor id, and passes the specified optional . This event can only
- /// be used to access its payload, and cannot be handled. The method returns only when
- /// the actor is initialized and the (if any)
- /// is handled.
- ///
- /// Unbound actor id.
- /// Type of the actor.
- /// Optional event used during initialization.
- /// Optional id that can be used to identify this operation.
- /// Task that represents the asynchronous operation. The task result is the actor id.
- Task CreateActorAndExecuteAsync(ActorId id, Type type, Event initialEvent = null,
- Guid opGroupId = default);
-
- ///
- /// Sends an asynchronous to an actor.
- ///
- /// The id of the target.
- /// The event to send.
- /// Optional id that can be used to identify this operation.
- void SendEvent(ActorId targetId, Event e, Guid opGroupId = default);
-
- ///
- /// Sends an to an actor. Returns immediately if the target was already
- /// running. Otherwise blocks until the target handles the event and reaches quiescense.
- ///
- /// The id of the target.
- /// The event to send.
- /// Optional id that can be used to identify this operation.
- /// Task that represents the asynchronous operation. The task result is true if
- /// the event was handled, false if the event was only enqueued.
- Task SendEventAndExecuteAsync(ActorId targetId, Event e, Guid opGroupId = default);
-
- ///
- /// Returns the operation group id of the actor with the specified id. Returns
- /// if the id is not set, or if the is not associated with this runtime. During
- /// testing, the runtime asserts that the specified actor is currently executing.
- ///
- /// The id of the currently executing actor.
- /// The unique identifier.
- Guid GetCurrentOperationGroupId(ActorId currentActorId);
-
- ///
- /// Use this method to register an .
- ///
- /// The log writer to register.
- void RegisterLog(IActorRuntimeLog log);
-
- ///
- /// Use this method to unregister a previously registered .
- ///
- /// The previously registered log writer to unregister.
- void RemoveLog(IActorRuntimeLog log);
- }
-}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/Actors/Logging/ActorRuntimeLogJsonFormatter.cs b/Src/PChecker/CheckerCore/Actors/Logging/ActorRuntimeLogJsonFormatter.cs
deleted file mode 100644
index e1718377d3..0000000000
--- a/Src/PChecker/CheckerCore/Actors/Logging/ActorRuntimeLogJsonFormatter.cs
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-using System;
-using PChecker.Actors.Events;
-
-namespace PChecker.Actors.Logging
-{
- ///
- /// This class implements IActorRuntimeLog and generates log output in an XML format.
- ///
- public class ActorRuntimeLogJsonFormatter : IActorRuntimeLog
- {
- ///
- /// Get or set the JsonWriter to write to.
- ///
- public JsonWriter Writer { get; set; }
-
- ///
- /// Initializes a new instance of the class.
- ///
- protected ActorRuntimeLogJsonFormatter()
- {
- Writer = new JsonWriter();
- }
-
- ///
- public virtual void OnCompleted()
- {
- }
-
- ///
- public virtual void OnAssertionFailure(string error)
- {
- }
-
- ///
- public virtual void OnCreateActor(ActorId id, string creatorName, string creatorType)
- {
- }
-
- ///
- public virtual void OnCreateStateMachine(ActorId id, string creatorName, string creatorType)
- {
- }
-
- ///
- public virtual void OnDefaultEventHandler(ActorId id, string stateName)
- {
- }
-
- ///
- public virtual void OnDequeueEvent(ActorId id, string stateName, Event e)
- {
- }
-
- ///
- public virtual void OnEnqueueEvent(ActorId id, Event e)
- {
- }
-
- ///
- public virtual void OnExceptionHandled(ActorId id, string stateName, string actionName, Exception ex)
- {
- }
-
- ///
- public virtual void OnExceptionThrown(ActorId id, string stateName, string actionName, Exception ex)
- {
- }
-
- ///
- public virtual void OnExecuteAction(ActorId id, string handlingStateName, string currentStateName,
- string actionName)
- {
- }
-
- ///
- public virtual void OnGotoState(ActorId id, string currentStateName, string newStateName)
- {
- }
-
- ///
- public virtual void OnHalt(ActorId id, int inboxSize)
- {
- }
-
- ///
- public virtual void OnHandleRaisedEvent(ActorId id, string stateName, Event e)
- {
- }
-
- ///
- public virtual void OnPopState(ActorId id, string currentStateName, string restoredStateName)
- {
- }
-
- ///
- public virtual void OnPopStateUnhandledEvent(ActorId id, string stateName, Event e)
- {
- }
-
- ///
- public virtual void OnPushState(ActorId id, string currentStateName, string newStateName)
- {
- }
-
- ///
- public virtual void OnRaiseEvent(ActorId id, string stateName, Event e)
- {
- }
-
- ///
- public virtual void OnReceiveEvent(ActorId id, string stateName, Event e, bool wasBlocked)
- {
- }
-
- ///
- public virtual void OnSendEvent(ActorId targetActorId, string senderName, string senderType,
- string senderStateName,
- Event e, Guid opGroupId, bool isTargetHalted)
- {
- }
-
- ///
- public virtual void OnStateTransition(ActorId id, string stateName, bool isEntry)
- {
- }
-
- ///
- public virtual void OnWaitEvent(ActorId id, string stateName, Type eventType)
- {
- }
-
- ///
- public virtual void OnWaitEvent(ActorId id, string stateName, params Type[] eventTypes)
- {
- }
-
- ///
- public virtual void OnCreateMonitor(string monitorType)
- {
- }
-
- ///
- public virtual void OnMonitorExecuteAction(string monitorType, string stateName, string actionName)
- {
- }
-
- ///
- public virtual void OnMonitorProcessEvent(string monitorType, string stateName, string senderName,
- string senderType, string senderStateName, Event e)
- {
- }
-
- ///
- public virtual void OnMonitorRaiseEvent(string monitorType, string stateName, Event e)
- {
- }
-
- ///
- public virtual void OnMonitorStateTransition(string monitorType, string stateName, bool isEntry,
- bool? isInHotState)
- {
- }
-
- ///
- public virtual void OnMonitorError(string monitorType, string stateName, bool? isInHotState)
- {
- }
-
- ///
- public virtual void OnRandom(object result, string callerName, string callerType)
- {
- }
-
- ///
- public virtual void OnStrategyDescription(string strategyName, string description)
- {
- }
- }
-}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/Actors/Managers/ActorManager.cs b/Src/PChecker/CheckerCore/Actors/Managers/ActorManager.cs
deleted file mode 100644
index 3ec125adcd..0000000000
--- a/Src/PChecker/CheckerCore/Actors/Managers/ActorManager.cs
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-using System;
-using System.Collections.Generic;
-using System.Runtime.CompilerServices;
-using PChecker.Actors.Events;
-
-namespace PChecker.Actors.Managers
-{
- ///
- /// Manages an actor in production.
- ///
- internal class ActorManager : IActorManager
- {
- ///
- /// The runtime that executes the actor being managed.
- ///
- private readonly ActorRuntime Runtime;
-
- ///
- /// The actor being managed.
- ///
- private readonly Actor Instance;
-
- ///
- public bool IsEventHandlerRunning { get; set; }
-
- ///
- public Guid OperationGroupId { get; set; }
-
- ///
- /// Initializes a new instance of the class.
- ///
- internal ActorManager(ActorRuntime runtime, Actor instance, Guid operationGroupId)
- {
- Runtime = runtime;
- Instance = instance;
- IsEventHandlerRunning = true;
- OperationGroupId = operationGroupId;
- }
-
- ///
- public int GetCachedState() => 0;
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool IsEventIgnored(Event e, Guid opGroupId, EventInfo eventInfo) => Instance.IsEventIgnored(e);
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool IsEventDeferred(Event e, Guid opGroupId, EventInfo eventInfo) => false;
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool IsDefaultHandlerAvailable() => Instance.IsDefaultHandlerAvailable;
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void OnEnqueueEvent(Event e, Guid opGroupId, EventInfo eventInfo) =>
- Runtime.LogWriter.LogEnqueueEvent(Instance.Id, e);
-
- ////
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void OnRaiseEvent(Event e, Guid opGroupId, EventInfo eventInfo) =>
- Runtime.LogWriter.LogRaiseEvent(Instance.Id, default, e);
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void OnWaitEvent(IEnumerable eventTypes) =>
- Runtime.NotifyWaitEvent(Instance, eventTypes);
-
- ///
- public void OnReceiveEvent(Event e, Guid opGroupId, EventInfo eventInfo)
- {
- if (opGroupId != Guid.Empty)
- {
- // Inherit the operation group id of the receive operation, if it is non-empty.
- OperationGroupId = opGroupId;
- }
-
- Runtime.NotifyReceivedEvent(Instance, e, eventInfo);
- }
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void OnReceiveEventWithoutWaiting(Event e, Guid opGroupId, EventInfo eventInfo)
- {
- if (opGroupId != Guid.Empty)
- {
- // Inherit the operation group id of the receive operation, if it is non-empty.
- OperationGroupId = opGroupId;
- }
-
- Runtime.NotifyReceivedEventWithoutWaiting(Instance, e, eventInfo);
- }
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void OnDropEvent(Event e, Guid opGroupId, EventInfo eventInfo) =>
- Runtime.TryHandleDroppedEvent(e, Instance.Id);
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Assert(bool predicate, string s, object arg0) => Runtime.Assert(predicate, s, arg0);
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Assert(bool predicate, string s, object arg0, object arg1) => Runtime.Assert(predicate, s, arg0, arg1);
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Assert(bool predicate, string s, object arg0, object arg1, object arg2) =>
- Runtime.Assert(predicate, s, arg0, arg1, arg2);
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Assert(bool predicate, string s, params object[] args) => Runtime.Assert(predicate, s, args);
- }
-}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/Actors/Managers/Mocks/MockActorManager.cs b/Src/PChecker/CheckerCore/Actors/Managers/Mocks/MockActorManager.cs
deleted file mode 100644
index ad39164330..0000000000
--- a/Src/PChecker/CheckerCore/Actors/Managers/Mocks/MockActorManager.cs
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-using System;
-using System.Collections.Generic;
-using System.Runtime.CompilerServices;
-using PChecker.Actors.Events;
-using PChecker.SystematicTesting;
-
-namespace PChecker.Actors.Managers.Mocks
-{
- ///
- /// Implements an actor manager that is used during testing.
- ///
- internal sealed class MockActorManager : IActorManager
- {
- ///
- /// The runtime that executes the actor being managed.
- ///
- private readonly ControlledRuntime Runtime;
-
- ///
- /// The actor being managed.
- ///
- private readonly Actor Instance;
-
- ///
- public bool IsEventHandlerRunning { get; set; }
-
- ///
- public Guid OperationGroupId { get; set; }
-
- ///
- /// Program counter used for state-caching. Distinguishes
- /// scheduling from non-deterministic choices.
- ///
- internal int ProgramCounter;
-
- ///
- /// True if a transition statement was called in the current action, else false.
- ///
- internal bool IsTransitionStatementCalledInCurrentAction;
-
- ///
- /// True if the actor is executing an on exit action, else false.
- ///
- internal bool IsInsideOnExit;
-
- ///
- /// Initializes a new instance of the class.
- ///
- internal MockActorManager(ControlledRuntime runtime, Actor instance, Guid operationGroupId)
- {
- Runtime = runtime;
- Instance = instance;
- IsEventHandlerRunning = true;
- OperationGroupId = operationGroupId;
- ProgramCounter = 0;
- IsTransitionStatementCalledInCurrentAction = false;
- IsInsideOnExit = false;
- }
-
- ///
- public int GetCachedState()
- {
- unchecked
- {
- var hash = 19;
- hash = (hash * 31) + IsEventHandlerRunning.GetHashCode();
- hash = (hash * 31) + ProgramCounter;
- return hash;
- }
- }
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool IsEventIgnored(Event e, Guid opGroupId, EventInfo eventInfo) => Instance.IsEventIgnored(e);
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool IsEventDeferred(Event e, Guid opGroupId, EventInfo eventInfo) => false;
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool IsDefaultHandlerAvailable() => Instance.IsDefaultHandlerAvailable;
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void OnEnqueueEvent(Event e, Guid opGroupId, EventInfo eventInfo) =>
- Runtime.LogWriter.LogEnqueueEvent(Instance.Id, e);
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void OnRaiseEvent(Event e, Guid opGroupId, EventInfo eventInfo) =>
- Runtime.LogWriter.LogRaiseEvent(Instance.Id, default, e);
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void OnWaitEvent(IEnumerable eventTypes) =>
- Runtime.NotifyWaitEvent(Instance, eventTypes);
-
- ///
- public void OnReceiveEvent(Event e, Guid opGroupId, EventInfo eventInfo)
- {
- if (opGroupId != Guid.Empty)
- {
- // Inherit the operation group id of the receive operation, if it is non-empty.
- OperationGroupId = opGroupId;
- }
-
- Runtime.NotifyReceivedEvent(Instance, e, eventInfo);
- }
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void OnReceiveEventWithoutWaiting(Event e, Guid opGroupId, EventInfo eventInfo)
- {
- if (opGroupId != Guid.Empty)
- {
- // Inherit the operation group id of the receive operation, if it is non-empty.
- OperationGroupId = opGroupId;
- }
-
- Runtime.NotifyReceivedEventWithoutWaiting(Instance, e, eventInfo);
- }
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void OnDropEvent(Event e, Guid opGroupId, EventInfo eventInfo)
- {
- Runtime.TryHandleDroppedEvent(e, Instance.Id);
- }
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Assert(bool predicate, string s, object arg0) => Runtime.Assert(predicate, s, arg0);
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Assert(bool predicate, string s, object arg0, object arg1) => Runtime.Assert(predicate, s, arg0, arg1);
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Assert(bool predicate, string s, object arg0, object arg1, object arg2) =>
- Runtime.Assert(predicate, s, arg0, arg1, arg2);
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Assert(bool predicate, string s, params object[] args) => Runtime.Assert(predicate, s, args);
- }
-}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/Actors/Managers/StateMachineManager.cs b/Src/PChecker/CheckerCore/Actors/Managers/StateMachineManager.cs
deleted file mode 100644
index 91e28f0b71..0000000000
--- a/Src/PChecker/CheckerCore/Actors/Managers/StateMachineManager.cs
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-using System;
-using System.Collections.Generic;
-using System.Runtime.CompilerServices;
-using PChecker.Actors.Events;
-
-namespace PChecker.Actors.Managers
-{
- ///
- /// Manages a state machine in production.
- ///
- internal class StateMachineManager : IActorManager
- {
- ///
- /// The runtime that executes the state machine being managed.
- ///
- private readonly ActorRuntime Runtime;
-
- ///
- /// The state machine being managed.
- ///
- private readonly StateMachine Instance;
-
- ///
- public bool IsEventHandlerRunning { get; set; }
-
- ///
- public Guid OperationGroupId { get; set; }
-
- ///
- /// Initializes a new instance of the class.
- ///
- internal StateMachineManager(ActorRuntime runtime, StateMachine instance, Guid operationGroupId)
- {
- Runtime = runtime;
- Instance = instance;
- IsEventHandlerRunning = true;
- OperationGroupId = operationGroupId;
- }
-
- ///
- public int GetCachedState() => 0;
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool IsEventIgnored(Event e, Guid opGroupId, EventInfo eventInfo) =>
- Instance.IsEventIgnoredInCurrentState(e);
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool IsEventDeferred(Event e, Guid opGroupId, EventInfo eventInfo) =>
- Instance.IsEventDeferredInCurrentState(e);
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool IsDefaultHandlerAvailable() => Instance.IsDefaultHandlerInstalledInCurrentState();
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void OnEnqueueEvent(Event e, Guid opGroupId, EventInfo eventInfo) =>
- Runtime.LogWriter.LogEnqueueEvent(Instance.Id, e);
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void OnRaiseEvent(Event e, Guid opGroupId, EventInfo eventInfo) =>
- Runtime.NotifyRaisedEvent(Instance, e, eventInfo);
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void OnWaitEvent(IEnumerable eventTypes) =>
- Runtime.NotifyWaitEvent(Instance, eventTypes);
-
- ///
- public void OnReceiveEvent(Event e, Guid opGroupId, EventInfo eventInfo)
- {
- if (opGroupId != Guid.Empty)
- {
- // Inherit the operation group id of the receive operation, if it is non-empty.
- OperationGroupId = opGroupId;
- }
-
- Runtime.NotifyReceivedEvent(Instance, e, eventInfo);
- }
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void OnReceiveEventWithoutWaiting(Event e, Guid opGroupId, EventInfo eventInfo)
- {
- if (opGroupId != Guid.Empty)
- {
- // Inherit the operation group id of the receive operation, if it is non-empty.
- OperationGroupId = opGroupId;
- }
-
- Runtime.NotifyReceivedEventWithoutWaiting(Instance, e, eventInfo);
- }
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void OnDropEvent(Event e, Guid opGroupId, EventInfo eventInfo) =>
- Runtime.TryHandleDroppedEvent(e, Instance.Id);
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Assert(bool predicate, string s, object arg0) => Runtime.Assert(predicate, s, arg0);
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Assert(bool predicate, string s, object arg0, object arg1) => Runtime.Assert(predicate, s, arg0, arg1);
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Assert(bool predicate, string s, object arg0, object arg1, object arg2) =>
- Runtime.Assert(predicate, s, arg0, arg1, arg2);
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Assert(bool predicate, string s, params object[] args) => Runtime.Assert(predicate, s, args);
- }
-}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/Actors/NameResolver.cs b/Src/PChecker/CheckerCore/Actors/NameResolver.cs
deleted file mode 100644
index 501876bafd..0000000000
--- a/Src/PChecker/CheckerCore/Actors/NameResolver.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-using System;
-using System.Collections.Concurrent;
-using System.Globalization;
-
-namespace PChecker.Actors
-{
- ///
- /// Utility class for resolving names.
- ///
- internal static class NameResolver
- {
- ///
- /// Cache of state names.
- ///
- private static readonly ConcurrentDictionary StateNamesCache =
- new ConcurrentDictionary();
-
- ///
- /// Returns the qualified (i.e. ) name of the specified
- /// state machine or monitor state, or the empty string if there is no such name.
- ///
- internal static string GetQualifiedStateName(Type state)
- {
- if (state is null)
- {
- return string.Empty;
- }
-
- if (!StateNamesCache.TryGetValue(state, out var name))
- {
- name = state.Name;
-
- var nextState = state;
- while (nextState.DeclaringType != null)
- {
- if (!nextState.DeclaringType.IsSubclassOf(typeof(StateMachine.StateGroup)))
- {
- break;
- }
-
- name = string.Format(CultureInfo.InvariantCulture, "{0}.{1}", nextState.DeclaringType.Name, name);
- nextState = nextState.DeclaringType;
- }
-
- StateNamesCache.GetOrAdd(state, name);
- }
-
- return name;
- }
-
- ///
- /// Returns the state name to be used for logging purposes.
- ///
- internal static string GetStateNameForLogging(Type state) => state is null ? "None" : GetQualifiedStateName(state);
- }
-}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/Checker.cs b/Src/PChecker/CheckerCore/Checker.cs
index dbb9a173a3..e14dc5025b 100644
--- a/Src/PChecker/CheckerCore/Checker.cs
+++ b/Src/PChecker/CheckerCore/Checker.cs
@@ -1,9 +1,8 @@
using System;
-using PChecker.ExhaustiveSearch;
using PChecker.IO.Debugging;
using PChecker.IO.Logging;
-using PChecker.Scheduling;
using PChecker.SystematicTesting;
+using PChecker.Testing;
namespace PChecker;
@@ -53,7 +52,7 @@ public static void Run(CheckerConfiguration configuration)
switch (configuration.Mode)
{
case CheckerMode.BugFinding:
- TestingProcessScheduler.Create(configuration).Run();
+ TestingProcess.Create(configuration).Run();
break;
case CheckerMode.Verification:
case CheckerMode.Coverage:
diff --git a/Src/PChecker/CheckerCore/CheckerConfiguration.cs b/Src/PChecker/CheckerCore/CheckerConfiguration.cs
index 43e557cf92..b2c1d7d869 100644
--- a/Src/PChecker/CheckerCore/CheckerConfiguration.cs
+++ b/Src/PChecker/CheckerCore/CheckerConfiguration.cs
@@ -11,7 +11,7 @@ namespace PChecker
{
#pragma warning disable CA1724 // Type names should not match namespaces
///
- /// The Coyote project configurations.
+ /// The checker project configurations.
///
[DataContract]
[Serializable]
@@ -99,7 +99,7 @@ public class CheckerConfiguration
public bool IncrementalSchedulingSeed;
///
- /// If true, the Coyote tester performs a full exploration,
+ /// If true, the tester performs a full exploration,
/// and does not stop when it finds a bug.
///
[DataMember]
@@ -141,7 +141,7 @@ public int MaxSchedulingSteps
public bool UserExplicitlySetMaxFairSchedulingSteps;
///
- /// If true, then the Coyote tester will consider an execution
+ /// If true, then the tester will consider an execution
/// that hits the depth bound as buggy.
///
[DataMember]
@@ -188,13 +188,13 @@ public int MaxSchedulingSteps
public bool IsVerbose { get; set; }
///
- /// Enables code coverage reporting of a Coyote program.
+ /// Enables code coverage reporting of a program.
///
[DataMember]
public bool ReportCodeCoverage;
///
- /// Enables activity coverage reporting of a Coyote program.
+ /// Enables activity coverage reporting of a program.
///
[DataMember]
public bool ReportActivityCoverage { get; set; }
@@ -213,7 +213,7 @@ public int MaxSchedulingSteps
///
/// If specified, requests a DGML graph of the schedule that contains a bug, if a bug is found.
- /// This is different from a coverage activity graph, as it will also show actor instances.
+ /// This is different from a coverage activity graph, as it will also show state machine instances.
///
[DataMember]
public bool IsDgmlGraphEnabled { get; set; }
@@ -236,13 +236,7 @@ public int MaxSchedulingSteps
/// This is the AssemblyQualifiedName of the type to load.
///
[DataMember]
- public string CustomActorRuntimeLogType;
-
- ///
- /// Enables debugging.
- ///
- [DataMember]
- public bool EnableDebugging;
+ public string CustomStateMachineRuntimeLogType;
///
@@ -327,7 +321,6 @@ protected CheckerConfiguration()
DebugActivityCoverage = false;
IsVerbose = false;
- EnableDebugging = false;
EnableColoredConsoleOutput = false;
DisableEnvironmentExit = true;
diff --git a/Src/PChecker/CheckerCore/Coverage/ActivityCoverageReporter.cs b/Src/PChecker/CheckerCore/Coverage/ActivityCoverageReporter.cs
index e0b29a15c9..c17e3eb87d 100644
--- a/Src/PChecker/CheckerCore/Coverage/ActivityCoverageReporter.cs
+++ b/Src/PChecker/CheckerCore/Coverage/ActivityCoverageReporter.cs
@@ -5,12 +5,12 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
-using PChecker.Actors.Events;
+using PChecker.Runtime.Events;
namespace PChecker.Coverage
{
///
- /// The Coyote code coverage reporter.
+ /// The code coverage reporter.
///
public class ActivityCoverageReporter
{
@@ -35,17 +35,6 @@ public ActivityCoverageReporter(CoverageInfo coverageInfo)
BuiltInEvents.Add(typeof(DefaultEvent).FullName);
}
- ///
- /// Emits the visualization graph.
- ///
- public void EmitVisualizationGraph(string graphFile)
- {
- if (CoverageInfo.CoverageGraph != null)
- {
- CoverageInfo.CoverageGraph.SaveDgml(graphFile, true);
- }
- }
-
///
/// Emits the code coverage report.
///
diff --git a/Src/PChecker/CheckerCore/Coverage/ActorRuntimeLogEventCoverage.cs b/Src/PChecker/CheckerCore/Coverage/ControlledRuntimeLogEventCoverage.cs
similarity index 65%
rename from Src/PChecker/CheckerCore/Coverage/ActorRuntimeLogEventCoverage.cs
rename to Src/PChecker/CheckerCore/Coverage/ControlledRuntimeLogEventCoverage.cs
index 8d13857018..73df76499e 100644
--- a/Src/PChecker/CheckerCore/Coverage/ActorRuntimeLogEventCoverage.cs
+++ b/Src/PChecker/CheckerCore/Coverage/ControlledRuntimeLogEventCoverage.cs
@@ -4,28 +4,28 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
-using PChecker.Actors;
-using PChecker.Actors.Events;
-using PChecker.Actors.Logging;
+using PChecker.Runtime.Events;
+using PChecker.Runtime.Logging;
+using PChecker.Runtime.StateMachines;
namespace PChecker.Coverage
{
///
- /// This class maintains information about events received and sent from each state of each actor.
+ /// This class maintains information about events received and sent from each state of each state machine.
///
[DataContract]
public class EventCoverage
{
///
- /// Map from states to the list of events received by that state. The state id is fully qualified by
- /// the actor id it belongs to.
+ /// Map from states to the list of events received by that state. The state id is fully qualified by
+ /// the state machine id it belongs to.
///
[DataMember]
private readonly Dictionary> EventsReceived = new Dictionary>();
///
/// Map from states to the list of events sent by that state. The state id is fully qualified by
- /// the actor id it belongs to.
+ /// the state machine id it belongs to.
///
[DataMember]
private readonly Dictionary> EventsSent = new Dictionary>();
@@ -44,7 +44,7 @@ internal void AddEventReceived(string stateId, string eventId)
///
/// Get list of events received by the given fully qualified state.
///
- /// The actor qualified state name
+ /// The state machine qualified state name
public IEnumerable GetEventsReceived(string stateId)
{
if (EventsReceived.TryGetValue(stateId, out var set))
@@ -69,7 +69,7 @@ internal void AddEventSent(string stateId, string eventId)
///
/// Get list of events sent by the given state.
///
- /// The actor qualified state name
+ /// The state machine qualified state name
public IEnumerable GetEventsSent(string stateId)
{
if (EventsSent.TryGetValue(stateId, out var set))
@@ -102,12 +102,12 @@ private static void MergeHashSets(Dictionary> ours, Dict
}
}
- internal class ActorRuntimeLogEventCoverage : IActorRuntimeLog
+ internal class ControlledRuntimeLogEventCoverage : IControlledRuntimeLog
{
private readonly EventCoverage InternalEventCoverage = new EventCoverage();
private Event Dequeued;
- public ActorRuntimeLogEventCoverage()
+ public ControlledRuntimeLogEventCoverage()
{
}
@@ -121,11 +121,7 @@ public void OnCompleted()
{
}
- public void OnCreateActor(ActorId id, string creatorName, string creatorType)
- {
- }
-
- public void OnCreateStateMachine(ActorId id, string creatorName, string creatorType)
+ public void OnCreateStateMachine(StateMachineId id, string creatorName, string creatorType)
{
}
@@ -133,34 +129,34 @@ public void OnCreateMonitor(string monitorType)
{
}
- public void OnDefaultEventHandler(ActorId id, string stateName)
+ public void OnDefaultEventHandler(StateMachineId id, string stateName)
{
Dequeued = DefaultEvent.Instance;
}
- public void OnDequeueEvent(ActorId id, string stateName, Event e)
+ public void OnDequeueEvent(StateMachineId id, string stateName, Event e)
{
Dequeued = e;
}
- public void OnEnqueueEvent(ActorId id, Event e)
+ public void OnEnqueueEvent(StateMachineId id, Event e)
{
}
- public void OnExceptionHandled(ActorId id, string stateName, string actionName, Exception ex)
+ public void OnExceptionHandled(StateMachineId id, string stateName, string actionName, Exception ex)
{
}
- public void OnExceptionThrown(ActorId id, string stateName, string actionName, Exception ex)
+ public void OnExceptionThrown(StateMachineId id, string stateName, string actionName, Exception ex)
{
}
- public void OnExecuteAction(ActorId id, string handlingStateName, string currentStateName, string actionName)
+ public void OnExecuteAction(StateMachineId id, string handlingStateName, string currentStateName, string actionName)
{
OnEventHandled(id, handlingStateName);
}
- private void OnEventHandled(ActorId id, string stateName)
+ private void OnEventHandled(StateMachineId id, string stateName)
{
if (Dequeued != null)
{
@@ -169,16 +165,16 @@ private void OnEventHandled(ActorId id, string stateName)
}
}
- public void OnGotoState(ActorId id, string currentStateName, string newStateName)
+ public void OnGotoState(StateMachineId id, string currentStateName, string newStateName)
{
OnEventHandled(id, currentStateName);
}
- public void OnHalt(ActorId id, int inboxSize)
+ public void OnHalt(StateMachineId id, int inboxSize)
{
}
- public void OnHandleRaisedEvent(ActorId id, string stateName, Event e)
+ public void OnHandleRaisedEvent(StateMachineId id, string stateName, Event e)
{
Dequeued = e;
}
@@ -211,39 +207,39 @@ public void OnRandom(object result, string callerName, string callerType)
{
}
- public void OnPopState(ActorId id, string currentStateName, string restoredStateName)
+ public void OnPopState(StateMachineId id, string currentStateName, string restoredStateName)
{
}
- public void OnPopStateUnhandledEvent(ActorId id, string stateName, Event e)
+ public void OnPopStateUnhandledEvent(StateMachineId id, string stateName, Event e)
{
}
- public void OnPushState(ActorId id, string currentStateName, string newStateName)
+ public void OnPushState(StateMachineId id, string currentStateName, string newStateName)
{
OnEventHandled(id, currentStateName);
}
- public void OnRaiseEvent(ActorId id, string stateName, Event e)
+ public void OnRaiseEvent(StateMachineId id, string stateName, Event e)
{
var eventName = e.GetType().FullName;
EventCoverage.AddEventSent(GetStateId(id.Type, stateName), eventName);
}
- public void OnReceiveEvent(ActorId id, string stateName, Event e, bool wasBlocked)
+ public void OnReceiveEvent(StateMachineId id, string stateName, Event e, bool wasBlocked)
{
var eventName = e.GetType().FullName;
EventCoverage.AddEventReceived(GetStateId(id.Type, stateName), eventName);
}
- public void OnSendEvent(ActorId targetActorId, string senderName, string senderType, string senderStateName,
- Event e, Guid opGroupId, bool isTargetHalted)
+ public void OnSendEvent(StateMachineId targetStateMachineId, string senderName, string senderType, string senderStateName,
+ Event e, bool isTargetHalted)
{
var eventName = e.GetType().FullName;
EventCoverage.AddEventSent(GetStateId(senderType, senderStateName), eventName);
}
- public void OnStateTransition(ActorId id, string stateName, bool isEntry)
+ public void OnStateTransition(StateMachineId id, string stateName, bool isEntry)
{
}
@@ -251,20 +247,20 @@ public void OnStrategyDescription(string strategyName, string description)
{
}
- public void OnWaitEvent(ActorId id, string stateName, Type eventType)
+ public void OnWaitEvent(StateMachineId id, string stateName, Type eventType)
{
}
- public void OnWaitEvent(ActorId id, string stateName, params Type[] eventTypes)
+ public void OnWaitEvent(StateMachineId id, string stateName, params Type[] eventTypes)
{
}
- private static string GetStateId(string actorType, string stateName)
+ private static string GetStateId(string stateMachineType, string stateName)
{
- var id = ResolveActorTypeName(actorType);
+ var id = ResolvestateMachineTypeName(stateMachineType);
if (string.IsNullOrEmpty(stateName))
{
- if (actorType == null)
+ if (stateMachineType == null)
{
stateName = "ExternalState";
}
@@ -277,35 +273,22 @@ private static string GetStateId(string actorType, string stateName)
return id += "." + stateName;
}
- private static string ResolveActorTypeName(string actorType)
+ private static string ResolvestateMachineTypeName(string stateMachineType)
{
- if (actorType == null)
+ if (stateMachineType == null)
{
- // The sender id can be null if an event is fired from non-actor code.
+ // The sender id can be null if an event is fired from non-stateMachine code.
return "ExternalCode";
}
- return actorType;
+ return stateMachineType;
}
- private static string GetLabel(string actorId, string fullyQualifiedName)
+ private static string GetLabel(string stateMachineId, string fullyQualifiedName)
{
- if (fullyQualifiedName == null)
- {
- // then this is probably an Actor, not a StateMachine. For Actors we can invent a state
- // name equal to the short name of the class, this then looks like a Constructor which is fine.
- var pos = actorId.LastIndexOf(".");
- if (pos > 0)
- {
- return actorId.Substring(pos + 1);
- }
-
- return actorId;
- }
-
- if (fullyQualifiedName.StartsWith(actorId))
+ if (fullyQualifiedName.StartsWith(stateMachineId))
{
- fullyQualifiedName = fullyQualifiedName.Substring(actorId.Length + 1).Trim('+');
+ fullyQualifiedName = fullyQualifiedName.Substring(stateMachineId.Length + 1).Trim('+');
}
return fullyQualifiedName;
diff --git a/Src/PChecker/CheckerCore/Coverage/ActorRuntimeLogGraphBuilder.cs b/Src/PChecker/CheckerCore/Coverage/ControlledRuntimeLogGraphBuilder.cs
similarity index 72%
rename from Src/PChecker/CheckerCore/Coverage/ActorRuntimeLogGraphBuilder.cs
rename to Src/PChecker/CheckerCore/Coverage/ControlledRuntimeLogGraphBuilder.cs
index 752570a510..fab3dcfcd8 100644
--- a/Src/PChecker/CheckerCore/Coverage/ActorRuntimeLogGraphBuilder.cs
+++ b/Src/PChecker/CheckerCore/Coverage/ControlledRuntimeLogGraphBuilder.cs
@@ -7,26 +7,25 @@
using System.Runtime.Serialization;
using System.Text;
using System.Xml.Linq;
-using PChecker.Actors;
-using PChecker.Actors.Events;
-using PChecker.Actors.Logging;
+using PChecker.Runtime.Events;
+using PChecker.Runtime.Logging;
+using PChecker.Runtime.StateMachines;
namespace PChecker.Coverage
{
///
- /// Implements the and builds a directed graph
+ /// Implements the and builds a directed graph
/// from the recorded events and state transitions.
///
- public class ActorRuntimeLogGraphBuilder : IActorRuntimeLog
+ public class ControlledRuntimeLogGraphBuilder : IControlledRuntimeLog
{
private Graph CurrentGraph;
- private readonly Dictionary Dequeued = new Dictionary(); // current dequeued event.
- private readonly Dictionary HaltedStates = new Dictionary(); // halted state for given actor.
+ private readonly Dictionary Dequeued = new Dictionary(); // current dequeued event.
+ private readonly Dictionary HaltedStates = new Dictionary(); // halted state for given state machine.
private readonly bool MergeEventLinks; // merge events from node A to node B instead of making them separate links.
private const string ExternalCodeName = "ExternalCode";
private const string ExternalStateName = "ExternalState";
private const string StateMachineCategory = "StateMachine";
- private const string ActorCategory = "Actor";
private const string MonitorCategory = "Monitor";
private class EventInfo
@@ -51,7 +50,7 @@ private class PopStateEvent : Event
{
}
- static ActorRuntimeLogGraphBuilder()
+ static ControlledRuntimeLogGraphBuilder()
{
EventAliases[typeof(GotoStateEvent).FullName] = "goto";
EventAliases[typeof(HaltEvent).FullName] = "halt";
@@ -63,9 +62,9 @@ static ActorRuntimeLogGraphBuilder()
}
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
- public ActorRuntimeLogGraphBuilder(bool mergeEventLinks)
+ public ControlledRuntimeLogGraphBuilder(bool mergeEventLinks)
{
MergeEventLinks = mergeEventLinks;
CurrentGraph = new Graph();
@@ -80,9 +79,6 @@ public ActorRuntimeLogGraphBuilder(bool mergeEventLinks)
///
/// Get or set the underlying logging object.
///
- ///
- /// See Logging for more information.
- ///
public TextWriter Logger { get; set; }
///
@@ -102,37 +98,26 @@ public Graph Graph
}
///
- public void OnCreateActor(ActorId id, string creatorName, string creatorType)
+ public void OnCreateStateMachine(StateMachineId id, string creatorName, string creatorType)
{
lock (Inbox)
{
- var resolvedId = GetResolveActorId(id?.Name, id?.Type);
- var node = Graph.GetOrCreateNode(resolvedId);
- node.Category = ActorCategory;
- }
- }
-
- ///
- public void OnCreateStateMachine(ActorId id, string creatorName, string creatorType)
- {
- lock (Inbox)
- {
- var resolvedId = GetResolveActorId(id?.Name, id?.Type);
+ var resolvedId = GetResolveStateMachineId(id?.Name, id?.Type);
var node = Graph.GetOrCreateNode(resolvedId);
node.Category = StateMachineCategory;
}
}
///
- public void OnSendEvent(ActorId targetActorId, string senderName, string senderType, string senderStateName,
- Event e, Guid opGroupId, bool isTargetHalted)
+ public void OnSendEvent(StateMachineId targetStateMachineId, string senderName, string senderType, string senderStateName,
+ Event e, bool isTargetHalted)
{
var eventName = e.GetType().FullName;
- AddEvent(targetActorId.Name, targetActorId.Type, senderName, senderType, senderStateName, eventName);
+ AddEvent(targetStateMachineId.Name, targetStateMachineId.Type, senderName, senderType, senderStateName, eventName);
}
///
- public void OnRaiseEvent(ActorId id, string stateName, Event e)
+ public void OnRaiseEvent(StateMachineId id, string stateName, Event e)
{
var eventName = e.GetType().FullName;
// Raising event to self.
@@ -140,16 +125,16 @@ public void OnRaiseEvent(ActorId id, string stateName, Event e)
}
///
- public void OnEnqueueEvent(ActorId id, Event e)
+ public void OnEnqueueEvent(StateMachineId id, Event e)
{
}
///
- public void OnDequeueEvent(ActorId id, string stateName, Event e)
+ public void OnDequeueEvent(StateMachineId id, string stateName, Event e)
{
lock (Inbox)
{
- var resolvedId = GetResolveActorId(id?.Name, id?.Type);
+ var resolvedId = GetResolveStateMachineId(id?.Name, id?.Type);
var eventName = e.GetType().FullName;
var info = PopEvent(resolvedId, eventName);
if (info != null)
@@ -181,9 +166,9 @@ private EventInfo PopEvent(string resolvedId, string eventName)
}
///
- public void OnReceiveEvent(ActorId id, string stateName, Event e, bool wasBlocked)
+ public void OnReceiveEvent(StateMachineId id, string stateName, Event e, bool wasBlocked)
{
- var resolvedId = GetResolveActorId(id?.Name, id?.Type);
+ var resolvedId = GetResolveStateMachineId(id?.Name, id?.Type);
lock (Inbox)
{
if (Inbox.TryGetValue(resolvedId, out var inbox))
@@ -195,7 +180,7 @@ public void OnReceiveEvent(ActorId id, string stateName, Event e, bool wasBlocke
if (info.Event == eventName)
{
// Yay, found it so we can draw the complete link connecting the Sender state to this state!
- var category = string.IsNullOrEmpty(stateName) ? ActorCategory : StateMachineCategory;
+ var category = StateMachineCategory;
var source = GetOrCreateChild(info.Name, info.Type, info.State);
var target = GetOrCreateChild(id?.Name, id?.Type, category, stateName);
GetOrCreateEventLink(source, target, info);
@@ -208,17 +193,17 @@ public void OnReceiveEvent(ActorId id, string stateName, Event e, bool wasBlocke
}
///
- public void OnWaitEvent(ActorId id, string stateName, Type eventType)
+ public void OnWaitEvent(StateMachineId id, string stateName, Type eventType)
{
}
///
- public void OnWaitEvent(ActorId id, string stateName, params Type[] eventTypes)
+ public void OnWaitEvent(StateMachineId id, string stateName, params Type[] eventTypes)
{
}
///
- public void OnStateTransition(ActorId id, string stateName, bool isEntry)
+ public void OnStateTransition(StateMachineId id, string stateName, bool isEntry)
{
if (isEntry)
{
@@ -228,19 +213,19 @@ public void OnStateTransition(ActorId id, string stateName, bool isEntry)
}
///
- public void OnExecuteAction(ActorId id, string handlingStateName, string currentStateName, string actionName)
+ public void OnExecuteAction(StateMachineId id, string handlingStateName, string currentStateName, string actionName)
{
LinkTransition(typeof(DoActionEvent), id, handlingStateName, currentStateName, null);
}
///
- public void OnGotoState(ActorId id, string currentStateName, string newStateName)
+ public void OnGotoState(StateMachineId id, string currentStateName, string newStateName)
{
LinkTransition(typeof(GotoStateEvent), id, currentStateName, currentStateName, newStateName);
}
///
- public void OnHalt(ActorId id, int inboxSize)
+ public void OnHalt(StateMachineId id, int inboxSize)
{
lock (Inbox)
{
@@ -268,11 +253,11 @@ public void OnHalt(ActorId id, int inboxSize)
}
///
- public void OnDefaultEventHandler(ActorId id, string stateName)
+ public void OnDefaultEventHandler(StateMachineId id, string stateName)
{
lock (Inbox)
{
- var resolvedId = GetResolveActorId(id?.Name, id?.Type);
+ var resolvedId = GetResolveStateMachineId(id?.Name, id?.Type);
var eventName = typeof(DefaultEvent).FullName;
AddEvent(id.Name, id.Type, id.Name, id.Type, stateName, eventName);
Dequeued[id] = PopEvent(resolvedId, eventName);
@@ -280,13 +265,13 @@ public void OnDefaultEventHandler(ActorId id, string stateName)
}
///
- public void OnHandleRaisedEvent(ActorId id, string stateName, Event e)
+ public void OnHandleRaisedEvent(StateMachineId id, string stateName, Event e)
{
lock (Inbox)
{
// We used the inbox to store raised event, but it should be the first one handled since
// raised events are highest priority.
- var resolvedId = GetResolveActorId(id?.Name, id?.Type);
+ var resolvedId = GetResolveStateMachineId(id?.Name, id?.Type);
lock (Inbox)
{
if (Inbox.TryGetValue(resolvedId, out var inbox))
@@ -307,21 +292,21 @@ public void OnHandleRaisedEvent(ActorId id, string stateName, Event e)
}
///
- public void OnPopStateUnhandledEvent(ActorId actorId, string currentStateName, Event e)
+ public void OnPopStateUnhandledEvent(StateMachineId stateMachineId, string currentStateName, Event e)
{
if (e is HaltEvent)
{
- HaltedStates[actorId] = currentStateName;
+ HaltedStates[stateMachineId] = currentStateName;
}
}
///
- public void OnExceptionThrown(ActorId id, string stateName, string actionName, Exception ex)
+ public void OnExceptionThrown(StateMachineId id, string stateName, string actionName, Exception ex)
{
}
///
- public void OnExceptionHandled(ActorId id, string stateName, string actionName, Exception ex)
+ public void OnExceptionHandled(StateMachineId id, string stateName, string actionName, Exception ex)
{
}
@@ -460,11 +445,11 @@ public Graph SnapshotGraph(bool reset)
return result;
}
- private string GetResolveActorId(string name, string type)
+ private string GetResolveStateMachineId(string name, string type)
{
if (type == null)
{
- // The sender id can be null if an event is fired from non-actor code.
+ // The sender id can be null if an event is fired from non-stateMachine code.
return ExternalCodeName;
}
@@ -479,7 +464,7 @@ private string GetResolveActorId(string name, string type)
private EventInfo AddEvent(string targetName, string targetType, string senderName, string senderType,
string senderStateName, string eventName)
{
- var targetId = GetResolveActorId(targetName, targetType);
+ var targetId = GetResolveStateMachineId(targetName, targetType);
EventInfo info = null;
lock (Inbox)
{
@@ -503,7 +488,7 @@ private EventInfo AddEvent(string targetName, string targetType, string senderNa
return info;
}
- private void LinkTransition(Type transitionType, ActorId id, string handlingStateName,
+ private void LinkTransition(Type transitionType, StateMachineId id, string handlingStateName,
string currentStateName, string newStateName)
{
var name = id.Name;
@@ -548,10 +533,10 @@ private GraphNode GetOrCreateChild(string name, string type, string stateName, s
var initalStateName = stateName;
- // make label relative to fully qualified actor id (it's usually a nested class).
+ // make label relative to fully qualified state machine id (it's usually a nested class).
stateName = GetLabel(name, type, stateName);
- var id = GetResolveActorId(name, type);
+ var id = GetResolveStateMachineId(name, type);
var parent = Graph.GetOrCreateNode(id);
parent.AddAttribute("Group", "Expanded");
@@ -626,13 +611,7 @@ private string GetLabel(string name, string type, string fullyQualifiedName)
}
AddNamespace(type);
- if (string.IsNullOrEmpty(fullyQualifiedName))
- {
- // then this is probably an Actor, not a StateMachine. For Actors we can invent a state
- // name equal to the short name of the class, this then looks like a Constructor which is fine.
- fullyQualifiedName = CollapseMachineInstances ? type : name;
- }
-
+
var len = fullyQualifiedName.Length;
var index = fullyQualifiedName.LastIndexOfAny(TypeSeparators);
if (index > 0)
@@ -680,11 +659,8 @@ private static string GetEventCategory(string fullyQualifiedName)
[DataContract]
public class Graph
{
- internal const string DgmlNamespace = "http://schemas.microsoft.com/vs/2009/dgml";
-
// These [DataMember] fields are here so we can serialize the Graph across parallel or distributed
- // test processes without losing any information. There is more information here than in the serialized
- // DGML which is we we can't just use Save/LoadDgml to do the same.
+ // test processes without losing any information.
[DataMember]
private readonly Dictionary InternalNodes = new Dictionary();
@@ -815,175 +791,7 @@ internal int GetUniqueLinkIndex(GraphNode source, GraphNode target, string id)
return index;
}
-
- ///
- /// Serialize the graph to a DGML string.
- ///
- public override string ToString()
- {
- using (var writer = new StringWriter())
- {
- WriteDgml(writer, false);
- return writer.ToString();
- }
- }
-
- internal void SaveDgml(string graphFilePath, bool includeDefaultStyles)
- {
- using (var writer = new StreamWriter(graphFilePath, false, Encoding.UTF8))
- {
- WriteDgml(writer, includeDefaultStyles);
- }
- }
-
- ///
- /// Serialize the graph to DGML.
- ///
- public void WriteDgml(TextWriter writer, bool includeDefaultStyles)
- {
- writer.WriteLine("", DgmlNamespace);
- writer.WriteLine(" ");
-
- if (InternalNodes != null)
- {
- var nodes = new List(InternalNodes.Keys);
- nodes.Sort();
- foreach (var id in nodes)
- {
- var node = InternalNodes[id];
- writer.Write(" ");
- }
- }
-
- writer.WriteLine(" ");
- writer.WriteLine(" ");
-
- if (InternalLinks != null)
- {
- var links = new List(InternalLinks.Keys);
- links.Sort();
- foreach (var id in links)
- {
- var link = InternalLinks[id];
- writer.Write(" ");
- }
- }
-
- writer.WriteLine(" ");
- if (includeDefaultStyles)
- {
- writer.WriteLine(
- @"
-
-
-
-
-
-
- ");
- }
-
- writer.WriteLine("");
- }
-
- ///
- /// Load a DGML file into a new Graph object.
- ///
- /// Full path to the DGML file.
- /// The loaded Graph object.
- public static Graph LoadDgml(string graphFilePath)
- {
- var doc = XDocument.Load(graphFilePath);
- var result = new Graph();
- var ns = doc.Root.Name.Namespace;
- if (ns != DgmlNamespace)
- {
- throw new Exception(string.Format("File '{0}' does not contain the DGML namespace", graphFilePath));
- }
-
- foreach (var e in doc.Root.Element(ns + "Nodes").Elements(ns + "Node"))
- {
- var id = (string)e.Attribute("Id");
- var label = (string)e.Attribute("Label");
- var category = (string)e.Attribute("Category");
-
- var node = new GraphNode(id, label, category);
- node.AddDgmlProperties(e);
- result.GetOrCreateNode(node);
- }
-
- foreach (var e in doc.Root.Element(ns + "Links").Elements(ns + "Link"))
- {
- var srcId = (string)e.Attribute("Source");
- var targetId = (string)e.Attribute("Target");
- var label = (string)e.Attribute("Label");
- var category = (string)e.Attribute("Category");
- var srcNode = result.GetOrCreateNode(srcId);
- var targetNode = result.GetOrCreateNode(targetId);
- var indexAttr = e.Attribute("index");
- int? index = null;
- if (indexAttr != null)
- {
- index = (int)indexAttr;
- }
-
- var link = result.GetOrCreateLink(srcNode, targetNode, index, label, category);
- link.AddDgmlProperties(e);
- }
-
- return result;
- }
+
///
/// Merge the given graph so that this graph becomes a superset of both graphs.
@@ -1150,27 +958,6 @@ public GraphNode(string id, string label, string category)
Label = label;
Category = category;
}
-
- ///
- /// Add additional properties from XML element.
- ///
- /// An XML element representing the graph node in DGML format.
- public void AddDgmlProperties(XElement e)
- {
- foreach (var a in e.Attributes())
- {
- switch (a.Name.LocalName)
- {
- case "Id":
- case "Label":
- case "Category":
- break;
- default:
- AddAttribute(a.Name.LocalName, a.Value);
- break;
- }
- }
- }
}
///
@@ -1220,27 +1007,5 @@ public GraphLink(GraphNode source, GraphNode target, string label, string catego
Label = label;
Category = category;
}
-
- ///
- /// Add additional properties from XML element.
- ///
- /// An XML element representing the graph node in DGML format.
- public void AddDgmlProperties(XElement e)
- {
- foreach (var a in e.Attributes())
- {
- switch (a.Name.LocalName)
- {
- case "Source":
- case "Target":
- case "Label":
- case "Category":
- break;
- default:
- AddAttribute(a.Name.LocalName, a.Value);
- break;
- }
- }
- }
}
}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/Exceptions/AssertionFailureException.cs b/Src/PChecker/CheckerCore/Exceptions/AssertionFailureException.cs
index 779c439ab2..271eca30f8 100644
--- a/Src/PChecker/CheckerCore/Exceptions/AssertionFailureException.cs
+++ b/Src/PChecker/CheckerCore/Exceptions/AssertionFailureException.cs
@@ -6,7 +6,7 @@
namespace PChecker.Exceptions
{
///
- /// The exception that is thrown by the Coyote runtime upon assertion failure.
+ /// The exception that is thrown by the ControlledRuntime upon assertion failure.
///
internal sealed class AssertionFailureException : RuntimeException
{
diff --git a/Src/PChecker/CheckerCore/Exceptions/RuntimeException.cs b/Src/PChecker/CheckerCore/Exceptions/RuntimeException.cs
index 802bb68ea9..2b6b4d1011 100644
--- a/Src/PChecker/CheckerCore/Exceptions/RuntimeException.cs
+++ b/Src/PChecker/CheckerCore/Exceptions/RuntimeException.cs
@@ -8,7 +8,7 @@
namespace PChecker.Exceptions
{
///
- /// An exception that is thrown by the Coyote runtime.
+ /// An exception that is thrown by the ControlledRuntime.
///
[Serializable]
[DebuggerStepThrough]
diff --git a/Src/PChecker/CheckerCore/ExhaustiveSearch/ExhaustiveSearch.cs b/Src/PChecker/CheckerCore/ExhaustiveEngine.cs
similarity index 99%
rename from Src/PChecker/CheckerCore/ExhaustiveSearch/ExhaustiveSearch.cs
rename to Src/PChecker/CheckerCore/ExhaustiveEngine.cs
index 86fb55f544..445392c740 100644
--- a/Src/PChecker/CheckerCore/ExhaustiveSearch/ExhaustiveSearch.cs
+++ b/Src/PChecker/CheckerCore/ExhaustiveEngine.cs
@@ -7,7 +7,7 @@
using PChecker.IO.Debugging;
using PChecker.IO.Logging;
-namespace PChecker.ExhaustiveSearch
+namespace PChecker
{
///
/// Exhaustive engine that can run a controlled concurrency exhaustive search using
diff --git a/Src/PChecker/CheckerCore/IO/Logging/ConsoleLogger.cs b/Src/PChecker/CheckerCore/IO/Logging/ConsoleLogger.cs
index 027e89f7b7..b2cc0598b7 100644
--- a/Src/PChecker/CheckerCore/IO/Logging/ConsoleLogger.cs
+++ b/Src/PChecker/CheckerCore/IO/Logging/ConsoleLogger.cs
@@ -10,9 +10,6 @@ namespace PChecker.IO.Logging
///
/// Logger that writes text to the console.
///
- ///
- /// See Logging for more information.
- ///
public sealed class ConsoleLogger : TextWriter
{
///
diff --git a/Src/PChecker/CheckerCore/Monitoring/CodeCoverageMonitor.cs b/Src/PChecker/CheckerCore/Monitoring/CodeCoverageMonitor.cs
deleted file mode 100644
index 0f2a11d5e2..0000000000
--- a/Src/PChecker/CheckerCore/Monitoring/CodeCoverageMonitor.cs
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-#if NETFRAMEWORK
-using System;
-using System.Diagnostics;
-using System.IO;
-using System.Threading;
-
-using Microsoft.Coyote.IO;
-
-namespace Microsoft.Coyote.SystematicTesting
-{
- ///
- /// Monitors the program being tested for code coverage.
- ///
- internal static class CodeCoverageMonitor
- {
- ///
- /// CheckerConfiguration.
- ///
- private static CheckerConfiguration CheckerConfiguration;
-
- ///
- /// Monitoring process is running.
- ///
- internal static bool IsRunning;
-
- ///
- /// Starts the code coverage monitor.
- ///
- /// CheckerConfiguration
- internal static void Start(CheckerConfiguration checkerConfiguration)
- {
- if (IsRunning)
- {
- throw new InvalidOperationException("Process has already started.");
- }
-
- CheckerConfiguration = checkerConfiguration;
- RunMonitorProcess(true);
- IsRunning = true;
- }
-
- ///
- /// Stops the code coverage monitor.
- ///
- internal static void Stop()
- {
- if (CheckerConfiguration is null)
- {
- throw new InvalidOperationException("Process has not been configured.");
- }
-
- if (!IsRunning)
- {
- throw new InvalidOperationException("Process is not running.");
- }
-
- RunMonitorProcess(false);
- IsRunning = false;
- }
-
- private static void RunMonitorProcess(bool isStarting)
- {
- var error = string.Empty;
- var exitCode = 0;
- var outputFile = GetOutputName();
- var arguments = isStarting ? $"/start:coverage /output:{outputFile}" : "/shutdown";
- var timedOut = false;
- using (var monitorProc = new Process())
- {
- monitorProc.StartInfo.FileName = CodeCoverageInstrumentation.GetToolPath("VSPerfCmdToolPath", "VSPerfCmd");
- monitorProc.StartInfo.Arguments = arguments;
- monitorProc.StartInfo.UseShellExecute = false;
- monitorProc.StartInfo.RedirectStandardOutput = true;
- monitorProc.StartInfo.RedirectStandardError = true;
- monitorProc.Start();
-
- Console.WriteLine($"... {(isStarting ? "Starting" : "Shutting down")} code coverage monitor");
-
- // timedOut can only become true on shutdown (non-infinite timeout value)
- timedOut = !monitorProc.WaitForExit(isStarting ? Timeout.Infinite : 5000);
- if (!timedOut)
- {
- exitCode = monitorProc.ExitCode;
- if (exitCode != 0)
- {
- error = monitorProc.StandardError.ReadToEnd();
- }
- }
- }
-
- if (exitCode != 0 || error.Length > 0)
- {
- if (error.Length == 0)
- {
- error = "";
- }
-
- Console.WriteLine($"Warning: 'VSPerfCmd {arguments}' exit code {exitCode}: {error}");
- }
-
- if (!isStarting)
- {
- if (timedOut)
- {
- Console.WriteLine($"Warning: VsPerfCmd timed out on shutdown");
- }
-
- if (File.Exists(outputFile))
- {
- var fileInfo = new FileInfo(outputFile);
- Console.WriteLine($"..... Created {outputFile}");
- }
- else
- {
- Console.WriteLine($"Warning: Code coverage output file {outputFile} was not created");
- }
- }
- }
-
- ///
- /// Returns the output name.
- ///
- private static string GetOutputName()
- {
- string file = Path.GetFileNameWithoutExtension(CheckerConfiguration.AssemblyToBeAnalyzed);
- string directory = CodeCoverageInstrumentation.OutputDirectory;
- return $"{directory}{file}.coverage";
- }
- }
-}
-#endif
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/PRuntime/Exceptions/PrtInhabitsTypeException.cs b/Src/PChecker/CheckerCore/PRuntime/Exceptions/PrtInhabitsTypeException.cs
deleted file mode 100644
index b9c9d5037e..0000000000
--- a/Src/PChecker/CheckerCore/PRuntime/Exceptions/PrtInhabitsTypeException.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System;
-
-namespace PChecker.PRuntime.Exceptions
-{
- public class PrtInhabitsTypeException : Exception
- {
- public PrtInhabitsTypeException()
- {
- }
-
- public PrtInhabitsTypeException(string message) : base(message)
- {
- }
-
- public PrtInhabitsTypeException(string message, Exception innerException) : base(message, innerException)
- {
- }
- }
-}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/PRuntime/GodMachine.cs b/Src/PChecker/CheckerCore/PRuntime/GodMachine.cs
deleted file mode 100644
index a629d66cd4..0000000000
--- a/Src/PChecker/CheckerCore/PRuntime/GodMachine.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System;
-using PChecker.Actors;
-using PChecker.Actors.Events;
-
-namespace PChecker.PRuntime
-{
- public class _GodMachine : StateMachine
- {
- private void InitOnEntry(Event e)
- {
- var mainMachine = (e as Config).MainMachine;
- CreateActor(mainMachine, mainMachine.Name,
- new PMachine.InitializeParametersEvent(
- new PMachine.InitializeParameters("I_" + mainMachine.Name, null)));
- }
-
- public class Config : Event
- {
- public Type MainMachine;
-
- public Config(Type main)
- {
- MainMachine = main;
- }
- }
-
- [Start]
- [OnEntry(nameof(InitOnEntry))]
- private class Init : State
- {
- }
- }
-}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/PRuntime/PEvent.cs b/Src/PChecker/CheckerCore/PRuntime/PEvent.cs
deleted file mode 100644
index 33af7d6790..0000000000
--- a/Src/PChecker/CheckerCore/PRuntime/PEvent.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-using System;
-using PChecker.Actors.Events;
-using PChecker.PRuntime.Values;
-
-namespace PChecker.PRuntime
-{
- public class PEvent : Event, IPrtValue
- {
- public PEvent() : base()
- {
- }
-
- public PEvent(IPrtValue payload) : base()
- {
- Payload = payload;
- }
-
- public IPrtValue Payload { get; }
-
- public bool Equals(IPrtValue other)
- {
- return other != null && GetType().FullName.Equals(other.GetType().FullName);
- }
-
- public virtual IPrtValue Clone()
- {
- throw new NotImplementedException();
- }
-
- public object ToDict()
- {
- return this.GetType().Name;
- }
-
- public override bool Equals(object obj)
- {
- return obj is PEvent other && Equals(other);
- }
-
- public override int GetHashCode()
- {
- return GetType().FullName.GetHashCode();
- }
-
- public override string ToString()
- {
- return GetType().Name;
- }
- }
-
- public class PHalt : PEvent
- {
- public PHalt(IPrtValue payload) : base(payload)
- {
- }
- }
-}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/PRuntime/PLogFormatter.cs b/Src/PChecker/CheckerCore/PRuntime/PLogFormatter.cs
deleted file mode 100644
index 5e70ab79c7..0000000000
--- a/Src/PChecker/CheckerCore/PRuntime/PLogFormatter.cs
+++ /dev/null
@@ -1,220 +0,0 @@
-using System;
-using System.Linq;
-using PChecker.Actors;
-using PChecker.Actors.Events;
-using PChecker.Actors.Logging;
-using PChecker.PRuntime.Exceptions;
-
-namespace PChecker.PRuntime
-{
- ///
- /// Formatter for the runtime log.
- ///
- public class PLogFormatter : ActorRuntimeLogTextFormatter
- {
- public PLogFormatter() : base()
- {
- }
-
- private string GetShortName(string name)
- {
- return name.Split('.').Last();
- }
-
- private string GetEventNameWithPayload(Event e)
- {
- if (e.GetType().Name.Contains("GotoStateEvent"))
- {
- return e.GetType().Name;
- }
- var pe = (PEvent)(e);
- var payload = pe.Payload == null ? "null" : pe.Payload.ToEscapedString();
- var msg = pe.Payload == null ? "" : $" with payload ({payload})";
- return $"{GetShortName(e.GetType().Name)}{msg}";
- }
-
- public override void OnStateTransition(ActorId id, string stateName, bool isEntry)
- {
- if (stateName.Contains("__InitState__") || id.Name.Contains("GodMachine"))
- {
- return;
- }
-
- base.OnStateTransition(id, GetShortName(stateName), isEntry);
- }
-
- public override void OnDefaultEventHandler(ActorId id, string stateName)
- {
- base.OnDefaultEventHandler(id, GetShortName(stateName));
- }
-
- public override void OnWaitEvent(ActorId id, string stateName, params Type[] eventTypes)
- {
- base.OnWaitEvent(id, GetShortName(stateName), eventTypes);
- }
-
- public override void OnWaitEvent(ActorId id, string stateName, Type eventType)
- {
- base.OnWaitEvent(id, GetShortName(stateName), eventType);
- }
-
- public override void OnMonitorStateTransition(string monitorType, string stateName, bool isEntry, bool? isInHotState)
- {
- if (stateName.Contains("__InitState__"))
- {
- return;
- }
-
- base.OnMonitorStateTransition(monitorType: GetShortName(monitorType), stateName: GetShortName(stateName), isEntry: isEntry, isInHotState: isInHotState);
- }
-
- public override void OnCreateActor(ActorId id, string creatorName, string creatorType)
- {
- if (id.Name.Contains("GodMachine") || creatorName.Contains("GodMachine"))
- {
- return;
- }
-
- base.OnCreateActor(id, GetShortName(creatorName), creatorType);
- }
-
- public override void OnMonitorProcessEvent(string monitorType, string stateName, string senderName, string senderType,
- string senderStateName, Event e)
- {
- var text = $" {GetShortName(monitorType)} is processing event '{GetEventNameWithPayload(e)}' in state '{stateName}'.";
- Logger.WriteLine(text);
- }
-
- public override void OnDequeueEvent(ActorId id, string stateName, Event e)
- {
- if (stateName.Contains("__InitState__") || id.Name.Contains("GodMachine"))
- {
- return;
- }
-
- stateName = GetShortName(stateName);
- var eventName = GetEventNameWithPayload(e);
- string text = null;
- if (stateName is null)
- {
- text = $" '{id}' dequeued event '{eventName}'.";
- }
- else
- {
- text = $" '{id}' dequeued event '{eventName}' in state '{stateName}'.";
- }
-
- Logger.WriteLine(text);
- }
-
- public override void OnRaiseEvent(ActorId id, string stateName, Event e)
- {
- stateName = GetShortName(stateName);
- var eventName = GetEventNameWithPayload(e);
- if (stateName.Contains("__InitState__") || id.Name.Contains("GodMachine") || eventName.Contains("GotoStateEvent"))
- {
- return;
- }
-
- string text = null;
- if (stateName is null)
- {
- text = $" '{id}' raised event '{eventName}'.";
- }
- else
- {
- text = $" '{id}' raised event '{eventName}' in state '{stateName}'.";
- }
-
- Logger.WriteLine(text);
- }
-
- public override void OnEnqueueEvent(ActorId id, Event e) { }
-
- public override void OnReceiveEvent(ActorId id, string stateName, Event e, bool wasBlocked)
- {
- stateName = GetShortName(stateName);
- var eventName = GetEventNameWithPayload(e);
- string text = null;
- var unblocked = wasBlocked ? " and unblocked" : string.Empty;
- if (stateName is null)
- {
- text = $" '{id}' dequeued event '{eventName}'{unblocked}.";
- }
- else
- {
- text = $" '{id}' dequeued event '{eventName}'{unblocked} in state '{stateName}'.";
- }
-
- Logger.WriteLine(text);
- }
-
- public override void OnMonitorRaiseEvent(string monitorType, string stateName, Event e)
- {
- stateName = GetShortName(stateName);
- var eventName = GetEventNameWithPayload(e);
- var text = $" Monitor '{GetShortName(monitorType)}' raised event '{eventName}' in state '{stateName}'.";
- Logger.WriteLine(text);
- }
-
- public override void OnSendEvent(ActorId targetActorId, string senderName, string senderType, string senderStateName, Event e, Guid opGroupId, bool isTargetHalted)
- {
- senderStateName = GetShortName(senderStateName);
- var eventName = GetEventNameWithPayload(e);
- var opGroupIdMsg = opGroupId != Guid.Empty ? $" (operation group '{opGroupId}')" : string.Empty;
- var isHalted = isTargetHalted ? $" which has halted" : string.Empty;
- var sender = !string.IsNullOrEmpty(senderName) ? $"'{senderName}' in state '{senderStateName}'" : $"The runtime";
- var text = $" {sender} sent event '{eventName}' to '{targetActorId}'{isHalted}{opGroupIdMsg}.";
- Logger.WriteLine(text);
- }
-
- public override void OnGotoState(ActorId id, string currStateName, string newStateName)
- {
- if (currStateName.Contains("__InitState__") || id.Name.Contains("GodMachine"))
- {
- return;
- }
-
- base.OnGotoState(id, GetShortName(currStateName), GetShortName(newStateName));
- }
-
- public override void OnExecuteAction(ActorId id, string handlingStateName, string currentStateName, string actionName)
- {
- }
-
- public override void OnMonitorExecuteAction(string monitorType, string stateName, string actionName)
- {
- }
-
- public override void OnExceptionHandled(ActorId id, string stateName, string actionName, Exception ex)
- {
- if (ex is PNonStandardReturnException)
- {
- return;
- }
- base.OnExceptionHandled(id: id, stateName: GetShortName(stateName), actionName: actionName, ex: ex);
- }
-
- public override void OnExceptionThrown(ActorId id, string stateName, string actionName, Exception ex)
- {
- if (ex is PNonStandardReturnException)
- {
- return;
- }
- base.OnExceptionThrown(id: id, stateName: GetShortName(stateName), actionName: actionName, ex: ex);
- }
-
- public override void OnCreateMonitor(string monitorType)
- {
- base.OnCreateMonitor(GetShortName(monitorType));
- }
-
- public override void OnHandleRaisedEvent(ActorId id, string stateName, Event e)
- {
- }
-
- public override void OnRandom(object result, string callerName, string callerType)
- {
- }
- }
-}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/PRuntime/PMachine.cs b/Src/PChecker/CheckerCore/PRuntime/PMachine.cs
deleted file mode 100644
index 92014533ab..0000000000
--- a/Src/PChecker/CheckerCore/PRuntime/PMachine.cs
+++ /dev/null
@@ -1,261 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using PChecker.Actors;
-using PChecker.Actors.Events;
-using PChecker.Actors.Exceptions;
-using PChecker.Actors.Logging;
-using PChecker.PRuntime.Exceptions;
-using PChecker.PRuntime.Values;
-
-namespace PChecker.PRuntime
-{
- public class PMachine : StateMachine
- {
- public List creates = new List();
- protected IPrtValue gotoPayload;
- private string interfaceName;
- public List receives = new List();
- public PMachineValue self;
- public List sends = new List();
-
- public void TryAssert(bool predicate)
- {
- Assert(predicate);
- }
-
- public void TryAssert(bool predicate, string s, params object[] args)
- {
- Assert(predicate, s, args);
- }
-
- protected void InitializeParametersFunction(Event e)
- {
- if (!(e is InitializeParametersEvent @event))
- {
- throw new ArgumentException("Event type is incorrect: " + e.GetType().Name);
- }
-
- var initParam = @event.Payload as InitializeParameters;
- interfaceName = initParam.InterfaceName;
- self = new PMachineValue(Id, receives.ToList());
- TryRaiseEvent(GetConstructorEvent(initParam.Payload), initParam.Payload);
- }
-
- protected virtual Event GetConstructorEvent(IPrtValue value)
- {
- throw new NotImplementedException();
- }
-
- protected override OnExceptionOutcome OnException(Exception ex, string methodName, Event e)
- {
- var v = ex is UnhandledEventException;
- if (!v)
- {
- return ex is PNonStandardReturnException
- ? OnExceptionOutcome.HandledException
- : base.OnException(ex, methodName, e);
- }
-
- return (ex as UnhandledEventException).UnhandledEvent is PHalt
- ? OnExceptionOutcome.Halt
- : base.OnException(ex, methodName, e);
- }
-
- public PMachineValue CreateInterface(PMachine creator, IPrtValue payload = null)
- where T : PMachineValue
- {
- var createdInterface = PModule.linkMap[creator.interfaceName][typeof(T).Name];
- Assert(creates.Contains(createdInterface),
- $"Machine {GetType().Name} cannot create interface {createdInterface}, not in its creates set");
- var createMachine = PModule.interfaceDefinitionMap[createdInterface];
- var machineId = CreateActor(createMachine, createdInterface.Substring(2),
- new InitializeParametersEvent(new InitializeParameters(createdInterface, payload)));
- return new PMachineValue(machineId, PInterfaces.GetPermissions(createdInterface));
- }
-
- public void TrySendEvent(PMachineValue target, Event ev, object payload = null)
- {
- Assert(ev != null, "Machine cannot send a null event");
- Assert(target != null, "Machine in send cannot be null");
- Assert(sends.Contains(ev.GetType().Name),
- $"Event {ev.GetType().Name} is not in the sends set of the Machine {GetType().Name}");
- Assert(target.Permissions.Contains(ev.GetType().Name),
- $"Event {ev.GetType().Name} is not in the permissions set of the target machine");
- var oneArgConstructor = ev.GetType().GetConstructors().First(x => x.GetParameters().Length > 0);
- ev = (Event)oneArgConstructor.Invoke(new[] { payload });
-
- AnnounceInternal(ev);
- SendEvent(target.Id, ev);
- }
-
- public void TryRaiseEvent(Event ev, object payload = null)
- {
- Assert(ev != null, "Machine cannot raise a null event");
- var oneArgConstructor = ev.GetType().GetConstructors().First(x => x.GetParameters().Length > 0);
- ev = (Event)oneArgConstructor.Invoke(new[] { payload });
- RaiseEvent(ev);
- throw new PNonStandardReturnException { ReturnKind = NonStandardReturn.Raise };
- }
-
- public Task TryReceiveEvent(params Type[] events)
- {
- return ReceiveEventAsync(events);
- }
-
- public void TryGotoState(IPrtValue payload = null) where T : State
- {
- gotoPayload = payload;
- RaiseGotoStateEvent();
- throw new PNonStandardReturnException { ReturnKind = NonStandardReturn.Goto };
- }
-
- public int TryRandomInt(int maxValue)
- {
- return RandomInteger(maxValue);
- }
-
- public int TryRandomInt(int minValue, int maxValue)
- {
- return minValue + RandomInteger(maxValue - minValue);
- }
-
- public bool TryRandomBool(int maxValue)
- {
- return RandomBoolean(maxValue);
- }
-
- public bool TryRandomBool()
- {
- return RandomBoolean();
- }
-
- public IPrtValue TryRandom(IPrtValue param)
- {
- switch (param)
- {
- case PrtInt maxValue:
- {
- TryAssert(maxValue <= 10000, $"choose expects a parameter with at most 10000 choices, got {maxValue} choices instead.");
- return (PrtInt)TryRandomInt(maxValue);
- }
-
- case PrtSeq seq:
- {
- TryAssert(seq.Any(), "Trying to choose from an empty sequence!");
- TryAssert(seq.Count <= 10000, $"choose expects a parameter with at most 10000 choices, got {seq.Count} choices instead.");
- return seq[TryRandomInt(seq.Count)];
- }
- case PrtSet set:
- {
- TryAssert(set.Any(), "Trying to choose from an empty set!");
- TryAssert(set.Count <= 10000, $"choose expects a parameter with at most 10000 choices, got {set.Count} choices instead.");
- return set.ElementAt(TryRandomInt(set.Count));
- }
- case PrtMap map:
- {
- TryAssert(map.Any(), "Trying to choose from an empty map!");
- TryAssert(map.Keys.Count <= 10000, $"choose expects a parameter with at most 10000 choices, got {map.Keys.Count} choices instead.");
- return map.Keys.ElementAt(TryRandomInt(map.Keys.Count));
- }
- default:
- throw new PInternalException("This is an unexpected (internal) P exception. Please report to the P Developers");
- }
- }
-
- public void LogLine(string message)
- {
- Logger.WriteLine($" {message}");
-
- // Log message to JSON output
- JsonLogger.AddLogType(JsonWriter.LogType.Print);
- JsonLogger.AddLog(message);
- JsonLogger.AddToLogs(updateVcMap: false);
- }
-
- public void Log(string message)
- {
- Logger.Write($"{message}");
- }
-
- public void Announce(Event ev, object payload = null)
- {
- Assert(ev != null, "Machine cannot announce a null event");
- if (ev is PHalt)
- {
- ev = HaltEvent.Instance;
- }
-
- var oneArgConstructor = ev.GetType().GetConstructors().First(x => x.GetParameters().Length > 0);
- var @event = (Event)oneArgConstructor.Invoke(new[] { payload });
- var pText = payload == null ? "" : $" with payload {((IPrtValue)payload).ToEscapedString()}";
-
- Logger.WriteLine($" '{Id}' announced event '{ev.GetType().Name}'{pText}.");
-
- // Log message to JSON output
- JsonLogger.AddLogType(JsonWriter.LogType.Announce);
- JsonLogger.LogDetails.Id = $"{Id}";
- JsonLogger.LogDetails.Event = ev.GetType().Name;
- if (payload != null)
- {
- JsonLogger.LogDetails.Payload = ((IPrtValue)payload).ToDict();
- }
- JsonLogger.AddLog($"{Id} announced event {ev.GetType().Name}{pText}.");
- JsonLogger.AddToLogs(updateVcMap: true);
-
- AnnounceInternal(@event);
- }
-
- private void AnnounceInternal(Event ev)
- {
- Assert(ev != null, "cannot send a null event");
- if (!PModule.monitorMap.ContainsKey(interfaceName))
- {
- return;
- }
-
- foreach (var monitor in PModule.monitorMap[interfaceName])
- {
- if (PModule.monitorObserves[monitor.Name].Contains(ev.GetType().Name))
- {
- Monitor(monitor, ev);
- }
- }
- }
-
- public class InitializeParameters : IPrtValue
- {
- public InitializeParameters(string interfaceName, IPrtValue payload)
- {
- InterfaceName = interfaceName;
- Payload = payload;
- }
-
- public string InterfaceName { get; }
- public IPrtValue Payload { get; }
-
- public bool Equals(IPrtValue other)
- {
- throw new NotImplementedException();
- }
-
- public IPrtValue Clone()
- {
- throw new NotImplementedException();
- }
-
- public object ToDict()
- {
- throw new NotImplementedException();
- }
- }
-
- public class InitializeParametersEvent : PEvent
- {
- public InitializeParametersEvent(InitializeParameters payload) : base(payload)
- {
- }
- }
- }
-}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/PRuntime/PMonitor.cs b/Src/PChecker/CheckerCore/PRuntime/PMonitor.cs
deleted file mode 100644
index 08289f4cc3..0000000000
--- a/Src/PChecker/CheckerCore/PRuntime/PMonitor.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using PChecker.Actors.Events;
-using PChecker.Actors.Logging;
-using PChecker.Specifications.Monitors;
-
-namespace PChecker.PRuntime
-{
- public class PMonitor : Monitor
- {
- public static List observes = new List();
-
- public object gotoPayload;
-
- public void TryRaiseEvent(Event ev, object payload = null)
- {
- Assert(!(ev is DefaultEvent), "Monitor cannot raise a null event");
- var oneArgConstructor = ev.GetType().GetConstructors().First(x => x.GetParameters().Length > 0);
- var @event = (Event)oneArgConstructor.Invoke(new[] { payload });
- RaiseEvent(@event);
- }
-
- public void TryGotoState(object payload = null) where T : State
- {
- gotoPayload = payload;
- RaiseGotoStateEvent();
- }
-
- public void TryAssert(bool predicate)
- {
- Assert(predicate);
- }
-
- public void TryAssert(bool predicate, string s, params object[] args)
- {
- Assert(predicate, s, args);
- }
-
- public void LogLine(string message)
- {
- Logger.WriteLine($" {message}");
-
- // Log message to JSON output
- JsonLogger.AddLogType(JsonWriter.LogType.Print);
- JsonLogger.AddLog(message);
- JsonLogger.AddToLogs(updateVcMap: false);
- }
-
- public void Log(string message)
- {
- Logger.Write($"{message}");
- }
- }
-}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/PRuntime/PrtValues.cs b/Src/PChecker/CheckerCore/PRuntime/PrtValues.cs
deleted file mode 100644
index 6b56ffff04..0000000000
--- a/Src/PChecker/CheckerCore/PRuntime/PrtValues.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-using PChecker.PRuntime.Values;
-
-namespace PChecker.PRuntime
-{
- public static class PrtValues
- {
- public static PrtBool Box(bool value)
- {
- return value;
- }
-
- public static PrtInt Box(long value)
- {
- return new PrtInt(value);
- }
-
- public static PrtInt Box(int value)
- {
- return new PrtInt(value);
- }
-
- public static PrtInt Box(short value)
- {
- return new PrtInt(value);
- }
-
- public static PrtInt Box(byte value)
- {
- return new PrtInt(value);
- }
-
- public static PrtFloat Box(double value)
- {
- return new PrtFloat(value);
- }
-
- public static PrtFloat Box(float value)
- {
- return new PrtFloat(value);
- }
-
- public static PrtBool SafeEquals(IPrtValue val1, IPrtValue val2)
- {
- return ReferenceEquals(val1, val2) || val1 != null && val1.Equals(val2);
- }
-
- public static IPrtValue PrtCastValue(IPrtValue value, PrtType type)
- {
- //todo: Needs to be fixed for better error message
- /*if (!PrtInhabitsType(value, type))
- throw new PrtInhabitsTypeException(
- $"value {value.ToString()} is not a member of type {type.ToString()}");*/
- return value.Clone();
- }
- }
-}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/PRuntime/Values/IPrtMutableValue.cs b/Src/PChecker/CheckerCore/PRuntime/Values/IPrtMutableValue.cs
deleted file mode 100644
index b8b3d2c153..0000000000
--- a/Src/PChecker/CheckerCore/PRuntime/Values/IPrtMutableValue.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace PChecker.PRuntime.Values
-{
- public interface IPrtMutableValue : IPrtValue
- {
- void Freeze();
- }
-}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/PRuntime/Values/PrtFloat.cs b/Src/PChecker/CheckerCore/PRuntime/Values/PrtFloat.cs
deleted file mode 100644
index d46e38daa7..0000000000
--- a/Src/PChecker/CheckerCore/PRuntime/Values/PrtFloat.cs
+++ /dev/null
@@ -1,147 +0,0 @@
-using System;
-using System.Runtime.CompilerServices;
-
-namespace PChecker.PRuntime.Values
-{
- [Serializable]
- public readonly struct PrtFloat : IPrtValue
- {
- private readonly double value;
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public PrtFloat(double value)
- {
- this.value = value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public IPrtValue Clone()
- {
- return this;
- }
-
- public override string ToString()
- {
- return value.ToString();
- }
-
- public object ToDict()
- {
- return value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool Equals(IPrtValue other)
- {
- return other is PrtFloat f && value == f.value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public override bool Equals(object val)
- {
- return val is PrtFloat other && Equals(value, other.value);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public override int GetHashCode()
- {
- return value.GetHashCode();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator double(in PrtFloat val)
- {
- return val.value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator PrtFloat(float val)
- {
- return new PrtFloat(val);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator PrtFloat(double val)
- {
- return new PrtFloat(val);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator PrtFloat(PrtInt val)
- {
- return new PrtFloat(val);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtFloat operator +(in PrtFloat prtFloat1, in PrtFloat prtFloat2)
- {
- return new PrtFloat(prtFloat1.value + prtFloat2.value);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtFloat operator -(in PrtFloat prtFloat1, in PrtFloat prtFloat2)
- {
- return new PrtFloat(prtFloat1.value - prtFloat2.value);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtFloat operator *(in PrtFloat prtFloat1, in PrtFloat prtFloat2)
- {
- return new PrtFloat(prtFloat1.value * prtFloat2.value);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtFloat operator /(in PrtFloat prtFloat1, in PrtFloat prtFloat2)
- {
- return new PrtFloat(prtFloat1.value / prtFloat2.value);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator <(in PrtFloat prtFloat1, in PrtFloat prtFloat2)
- {
- return prtFloat1.value < prtFloat2.value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator >(in PrtFloat prtFloat1, in PrtFloat prtFloat2)
- {
- return prtFloat1.value > prtFloat2.value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator <=(in PrtFloat prtFloat1, in PrtFloat prtFloat2)
- {
- return prtFloat1.value <= prtFloat2.value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator >=(in PrtFloat prtFloat1, in PrtFloat prtFloat2)
- {
- return prtFloat1.value >= prtFloat2.value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator ==(in PrtFloat prtFloat1, in PrtFloat prtFloat2)
- {
- return Equals(prtFloat1.value, prtFloat2.value);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator !=(in PrtFloat prtFloat1, in PrtFloat prtFloat2)
- {
- return Equals(prtFloat1.value, prtFloat2.value) == false;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtFloat operator +(in PrtFloat prtFloat)
- {
- return new PrtFloat(+prtFloat.value);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtFloat operator -(in PrtFloat prtFloat)
- {
- return new PrtFloat(-prtFloat.value);
- }
- }
-}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/PRuntime/Values/PrtInt.cs b/Src/PChecker/CheckerCore/PRuntime/Values/PrtInt.cs
deleted file mode 100644
index f381ec8cd6..0000000000
--- a/Src/PChecker/CheckerCore/PRuntime/Values/PrtInt.cs
+++ /dev/null
@@ -1,185 +0,0 @@
-using System;
-using System.Runtime.CompilerServices;
-
-namespace PChecker.PRuntime.Values
-{
- [Serializable]
- public readonly struct PrtInt : IPrtValue
- {
- private readonly long value;
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public PrtInt(long value)
- {
- this.value = value;
- }
-
- public bool Equals(IPrtValue other)
- {
- return other is PrtInt i && value == i.value;
- }
-
- public IPrtValue Clone()
- {
- return this;
- }
-
- public override bool Equals(object val)
- {
- return val is PrtInt other && Equals(value, other.value);
- }
-
- public override int GetHashCode()
- {
- return value.GetHashCode();
- }
-
- public override string ToString()
- {
- return value.ToString();
- }
-
- public object ToDict()
- {
- return value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator PrtInt(byte val)
- {
- return new PrtInt(val);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator PrtInt(short val)
- {
- return new PrtInt(val);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator PrtInt(int val)
- {
- return new PrtInt(val);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator PrtInt(long val)
- {
- return new PrtInt(val);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator PrtInt(in PrtFloat val)
- {
- return new PrtInt((long)val);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator int(in PrtInt val)
- {
- return (int)val.value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator long(in PrtInt val)
- {
- return val.value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtInt operator +(in PrtInt prtInt1, in PrtInt prtInt2)
- {
- return new PrtInt(prtInt1.value + prtInt2.value);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtInt operator -(in PrtInt prtInt1, in PrtInt prtInt2)
- {
- return new PrtInt(prtInt1.value - prtInt2.value);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtInt operator *(in PrtInt prtInt1, in PrtInt prtInt2)
- {
- return new PrtInt(prtInt1.value * prtInt2.value);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtInt operator /(in PrtInt prtInt1, in PrtInt prtInt2)
- {
- return new PrtInt(prtInt1.value / prtInt2.value);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator <(in PrtInt prtInt1, in PrtInt prtInt2)
- {
- return prtInt1.value < prtInt2.value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator >(in PrtInt prtInt1, in PrtInt prtInt2)
- {
- return prtInt1.value > prtInt2.value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator <=(in PrtInt prtInt1, in PrtInt prtInt2)
- {
- return prtInt1.value <= prtInt2.value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator >=(in PrtInt prtInt1, in PrtInt prtInt2)
- {
- return prtInt1.value >= prtInt2.value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator ==(in PrtInt prtInt1, in PrtInt prtInt2)
- {
- return Equals(prtInt1.value, prtInt2.value);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator ==(in IPrtValue prtInt1, in PrtInt prtInt2)
- {
- return prtInt1 is PrtInt int1 && Equals(int1.value, prtInt2.value);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator !=(in IPrtValue prtInt1, in PrtInt prtInt2)
- {
- return prtInt1 is PrtInt int1 && !Equals(int1.value, prtInt2.value);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator ==(in PrtInt prtInt1, in IPrtValue prtInt2)
- {
- return prtInt2 is PrtInt int2 && Equals(prtInt1.value, int2.value);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator !=(in PrtInt prtInt1, in IPrtValue prtInt2)
- {
- return prtInt2 is PrtInt int2 && !Equals(prtInt1.value, int2.value);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator !=(in PrtInt prtInt1, in PrtInt prtInt2)
- {
- return Equals(prtInt1.value, prtInt2.value) == false;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtInt operator +(in PrtInt prtInt)
- {
- return new PrtInt(+prtInt.value);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtInt operator -(in PrtInt prtInt)
- {
- return new PrtInt(-prtInt.value);
- }
- }
-}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/PRuntime/Values/PrtString.cs b/Src/PChecker/CheckerCore/PRuntime/Values/PrtString.cs
deleted file mode 100644
index 92ef3fcaaf..0000000000
--- a/Src/PChecker/CheckerCore/PRuntime/Values/PrtString.cs
+++ /dev/null
@@ -1,197 +0,0 @@
-using System;
-using System.Runtime.CompilerServices;
-
-namespace PChecker.PRuntime.Values
-{
- [Serializable]
- public readonly struct PrtString : IPrtValue
- {
- public bool Equals(PrtString other)
- {
- return string.Equals(value, other.value);
- }
-
- public override bool Equals(object obj)
- {
- if (ReferenceEquals(null, obj))
- {
- return false;
- }
-
- return obj is PrtString other && Equals(other);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public IPrtValue Clone()
- {
- return this;
- }
-
- private readonly string value;
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator PrtString(string val)
- {
- return new PrtString(val);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator string(PrtString val)
- {
- return val.value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private PrtString(string value)
- {
- this.value = value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtString operator +(in PrtString prtString1, in PrtString prtString2)
- {
- return new PrtString(prtString1.value + prtString2.value);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator ==(in PrtString pValue1, in PrtString pValue2)
- {
- return Equals(pValue1, pValue2);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator !=(in PrtString pValue1, in PrtString pValue2)
- {
- return !Equals(pValue1, pValue2);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator ==(in PrtString pValue1, in IPrtValue pValue2)
- {
- return pValue2 is PrtString prtString && string.Equals(pValue1.value, prtString.value);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator !=(in PrtString pValue1, in IPrtValue pValue2)
- {
- return pValue2 is PrtString prtString && !string.Equals(pValue1.value, prtString.value);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator ==(in IPrtValue pValue1, in PrtString pValue2)
- {
- return pValue1 is PrtString prtString && string.Equals(pValue2.value, prtString.value);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator !=(in IPrtValue pValue1, in PrtString pValue2)
- {
- return pValue1 is PrtString prtString && !string.Equals(pValue2.value, prtString.value);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator <(in PrtString prtString1, in PrtString prtString2)
- {
- return string.Compare(prtString1.value, prtString2.value) == -1;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator <(in IPrtValue pValue1, in PrtString pValue2)
- {
- return pValue1 is PrtString prtString && string.Compare(prtString.value, pValue2.value) == -1;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator <(in PrtString pValue1, in IPrtValue pValue2)
- {
- return pValue2 is PrtString prtString && string.Compare(prtString.value, pValue1.value) == -1;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator >(in PrtString prtString1, in PrtString prtString2)
- {
- return string.Compare(prtString1.value, prtString2.value) == 1;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator >(in IPrtValue pValue1, in PrtString pValue2)
- {
- return pValue1 is PrtString prtString && string.Compare(prtString.value, pValue2.value) == 1;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator >(in PrtString pValue1, in IPrtValue pValue2)
- {
- return pValue2 is PrtString prtString && string.Compare(prtString.value, pValue1.value) == 1;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator <=(in PrtString prtString1, in PrtString prtString2)
- {
- return string.Compare(prtString1.value, prtString2.value) != 1;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator <=(in IPrtValue pValue1, in PrtString pValue2)
- {
- return pValue1 is PrtString prtString && string.Compare(prtString.value, pValue2.value) != 1;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator <=(in PrtString pValue1, in IPrtValue pValue2)
- {
- return pValue2 is PrtString prtString && string.Compare(prtString.value, pValue1.value) != 1;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator >=(in PrtString prtString1, in PrtString prtString2)
- {
- return string.Compare(prtString1.value, prtString2.value) != -1;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator >=(in IPrtValue pValue1, in PrtString pValue2)
- {
- return pValue1 is PrtString prtString && string.Compare(prtString.value, pValue2.value) != -1;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PrtBool operator >=(in PrtString pValue1, in IPrtValue pValue2)
- {
- return pValue2 is PrtString prtString && string.Compare(prtString.value, pValue1.value) != -1;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool Equals(IPrtValue obj)
- {
- return obj is PrtString other && string.Equals(value, other.value);
- }
-
- public override int GetHashCode()
- {
- return value.GetHashCode();
- }
-
- public override string ToString()
- {
- return value;
- }
-
- ///
- /// Like ToString, but emits a representation of a string literal, surrounded by double-quotes,
- /// and where all interior double-quotes are escaped.
- ///
- ///
- public string ToEscapedString()
- {
- var v = value ?? "";
- return $"\"{v.Replace("\"", "\\\"")}\"";
- }
-
-
- public object ToDict()
- {
- return ToString();
- }
- }
-}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/Random/Generator.cs b/Src/PChecker/CheckerCore/Random/Generator.cs
index 358c50bc7a..e7c4f474e6 100644
--- a/Src/PChecker/CheckerCore/Random/Generator.cs
+++ b/Src/PChecker/CheckerCore/Random/Generator.cs
@@ -2,7 +2,7 @@
// Licensed under the MIT License.
using System.Runtime.CompilerServices;
-using PChecker.Runtime;
+using PChecker.SystematicTesting;
namespace PChecker.Random
{
@@ -12,23 +12,19 @@ namespace PChecker.Random
/// During systematic testing, the generation of random values is controlled, which
/// allows the runtime to explore combinations of choices to find bugs.
///
- ///
- /// See Program non-determinism
- /// for more information.
- ///
public class Generator
{
///
/// The runtime associated with this random value generator.
///
- internal readonly CoyoteRuntime Runtime;
+ internal readonly ControlledRuntime Runtime;
///
/// Initializes a new instance of the class.
///
private Generator()
{
- Runtime = CoyoteRuntime.Current;
+ Runtime = ControlledRuntime.Current;
}
///
diff --git a/Src/PChecker/CheckerCore/Random/IRandomValueGenerator.cs b/Src/PChecker/CheckerCore/Random/IRandomValueGenerator.cs
index 8e3084ced9..60cd4b0847 100644
--- a/Src/PChecker/CheckerCore/Random/IRandomValueGenerator.cs
+++ b/Src/PChecker/CheckerCore/Random/IRandomValueGenerator.cs
@@ -6,7 +6,7 @@ namespace PChecker.Random
///
/// Interface for random value generators.
///
- internal interface IRandomValueGenerator
+ public interface IRandomValueGenerator
{
///
/// The seed currently used by the generator.
diff --git a/Src/PChecker/CheckerCore/Runtime/CoyoteRuntime.cs b/Src/PChecker/CheckerCore/Runtime/CoyoteRuntime.cs
deleted file mode 100644
index 058d314c32..0000000000
--- a/Src/PChecker/CheckerCore/Runtime/CoyoteRuntime.cs
+++ /dev/null
@@ -1,300 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Threading;
-using System.Threading.Tasks;
-using PChecker.Actors.Events;
-using PChecker.Exceptions;
-using PChecker.Random;
-using Monitor = PChecker.Specifications.Monitors.Monitor;
-
-namespace PChecker.Runtime
-{
- ///
- /// Runtime for executing asynchronous operations.
- ///
- internal abstract class CoyoteRuntime : ICoyoteRuntime
- {
- ///
- /// Provides access to the runtime associated with each asynchronous control flow.
- ///
- ///
- /// In testing mode, each testing schedule uses a unique runtime instance. To safely
- /// retrieve it from static methods, we store it in each asynchronous control flow.
- ///
- private static readonly AsyncLocal AsyncLocalInstance = new AsyncLocal();
-
- ///
- /// The currently executing runtime.
- ///
- internal static CoyoteRuntime Current => AsyncLocalInstance.Value ??
- (IsExecutionControlled ? throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture,
- "Uncontrolled task '{0}' invoked a runtime method. Please make sure to avoid using concurrency APIs " +
- "(e.g. 'Task.Run', 'Task.Delay' or 'Task.Yield' from the 'System.Threading.Tasks' namespace) inside " +
- "actor handlers or controlled tasks. If you are using external libraries that are executing concurrently, " +
- "you will need to mock them during testing.",
- Task.CurrentId.HasValue ? Task.CurrentId.Value.ToString() : "")) :
- RuntimeFactory.InstalledRuntime);
-
- ///
- /// If true, the program execution is controlled by the runtime to
- /// explore interleavings and sources of nondeterminism, else false.
- ///
- internal static bool IsExecutionControlled { get; private protected set; } = false;
-
- ///
- /// The checkerConfiguration used by the runtime.
- ///
- protected internal readonly CheckerConfiguration CheckerConfiguration;
-
- ///
- /// List of monitors in the program.
- ///
- protected readonly List Monitors;
-
- ///
- /// Responsible for generating random values.
- ///
- protected readonly IRandomValueGenerator ValueGenerator;
-
- ///
- /// Monotonically increasing operation id counter.
- ///
- private long OperationIdCounter;
-
- ///
- /// Records if the runtime is running.
- ///
- protected internal volatile bool IsRunning;
-
- ///
- /// Used to log text messages. Use
- /// to replace the logger with a custom one.
- ///
- public abstract TextWriter Logger { get; }
-
- ///
- /// Callback that is fired when the Coyote program throws an exception which includes failed assertions.
- ///
- public event OnFailureHandler OnFailure;
-
- ///
- /// Initializes a new instance of the class.
- ///
- protected CoyoteRuntime(CheckerConfiguration checkerConfiguration, IRandomValueGenerator valueGenerator)
- {
- CheckerConfiguration = checkerConfiguration;
- Monitors = new List();
- ValueGenerator = valueGenerator;
- OperationIdCounter = 0;
- IsRunning = true;
- }
-
- ///
- /// Registers a new specification monitor of the specified .
- ///
- public void RegisterMonitor()
- where T : Monitor =>
- TryCreateMonitor(typeof(T));
-
- ///
- /// Invokes the specified monitor with the specified .
- ///
- public void Monitor(Event e)
- where T : Monitor
- {
- // If the event is null then report an error and exit.
- Assert(e != null, "Cannot monitor a null event.");
- Monitor(typeof(T), e, null, null, null);
- }
-
- ///
- /// Returns a nondeterministic boolean choice, that can be controlled
- /// during analysis or testing.
- ///
- public bool RandomBoolean() => GetNondeterministicBooleanChoice(2, null, null);
-
- ///
- /// Returns a nondeterministic boolean choice, that can be controlled
- /// during analysis or testing. The value is used to generate a number
- /// in the range [0..maxValue), where 0 triggers true.
- ///
- public bool RandomBoolean(int maxValue) => GetNondeterministicBooleanChoice(maxValue, null, null);
-
- ///
- /// Returns a nondeterministic integer, that can be controlled during
- /// analysis or testing. The value is used to generate an integer in
- /// the range [0..maxValue).
- ///
- public int RandomInteger(int maxValue) => GetNondeterministicIntegerChoice(maxValue, null, null);
-
- ///
- /// Returns the next available unique operation id.
- ///
- /// Value representing the next available unique operation id.
- internal ulong GetNextOperationId() =>
- // Atomically increments and safely wraps the value into an unsigned long.
- (ulong)Interlocked.Increment(ref OperationIdCounter) - 1;
-
- ///
- /// Tries to create a new of the specified .
- ///
- internal abstract void TryCreateMonitor(Type type);
-
- ///
- /// Invokes the specified with the specified .
- ///
- internal virtual void Monitor(Type type, Event e, string senderName, string senderType, string senderState)
- {
- Monitor monitor = null;
-
- lock (Monitors)
- {
- foreach (var m in Monitors)
- {
- if (m.GetType() == type)
- {
- monitor = m;
- break;
- }
- }
- }
-
- if (monitor != null)
- {
- lock (monitor)
- {
- monitor.MonitorEvent(e, senderName, senderType, senderState);
- }
- }
- }
-
- ///
- /// Checks if the assertion holds, and if not, throws an exception.
- ///
- public virtual void Assert(bool predicate)
- {
- if (!predicate)
- {
- throw new AssertionFailureException("Detected an assertion failure.");
- }
- }
-
- ///
- /// Checks if the assertion holds, and if not, throws an exception.
- ///
- public virtual void Assert(bool predicate, string s, object arg0)
- {
- if (!predicate)
- {
- throw new AssertionFailureException(string.Format(CultureInfo.InvariantCulture, s, arg0?.ToString()));
- }
- }
-
- ///
- /// Checks if the assertion holds, and if not, throws an exception.
- ///
- public virtual void Assert(bool predicate, string s, object arg0, object arg1)
- {
- if (!predicate)
- {
- throw new AssertionFailureException(string.Format(CultureInfo.InvariantCulture, s, arg0?.ToString(), arg1?.ToString()));
- }
- }
-
- ///
- /// Checks if the assertion holds, and if not, throws an exception.
- ///
- public virtual void Assert(bool predicate, string s, object arg0, object arg1, object arg2)
- {
- if (!predicate)
- {
- throw new AssertionFailureException(string.Format(CultureInfo.InvariantCulture, s, arg0?.ToString(), arg1?.ToString(), arg2?.ToString()));
- }
- }
-
- ///
- /// Checks if the assertion holds, and if not, throws an exception.
- ///
- public virtual void Assert(bool predicate, string s, params object[] args)
- {
- if (!predicate)
- {
- throw new AssertionFailureException(string.Format(CultureInfo.InvariantCulture, s, args));
- }
- }
-
- ///
- /// Returns a controlled nondeterministic boolean choice.
- ///
- internal abstract bool GetNondeterministicBooleanChoice(int maxValue, string callerName, string callerType);
-
- ///
- /// Returns a controlled nondeterministic integer choice.
- ///
- internal abstract int GetNondeterministicIntegerChoice(int maxValue, string callerName, string callerType);
-
- ///
- /// Assigns the specified runtime as the default for the current asynchronous control flow.
- ///
- internal static void AssignAsyncControlFlowRuntime(CoyoteRuntime runtime) => AsyncLocalInstance.Value = runtime;
-
- ///
- /// Use this method to override the default for logging messages.
- ///
- public abstract TextWriter SetLogger(TextWriter logger);
-
- ///
- /// Raises the event with the specified .
- ///
- protected internal virtual void RaiseOnFailureEvent(Exception exception)
- {
- OnFailure?.Invoke(exception);
- }
-
- ///
- /// Throws an exception
- /// containing the specified exception.
- ///
- internal virtual void WrapAndThrowException(Exception exception, string s, params object[] args)
- {
- var msg = string.Format(CultureInfo.InvariantCulture, s, args);
- var message = string.Format(CultureInfo.InvariantCulture,
- "Exception '{0}' was thrown in {1}: {2}\n" +
- "from location '{3}':\n" +
- "The stack trace is:\n{4}",
- exception.GetType(), msg, exception.Message, exception.Source, exception.StackTrace);
-
- throw new AssertionFailureException(message, exception);
- }
-
- ///
- /// Terminates the runtime and notifies each active actor to halt execution.
- ///
- public void Stop() => IsRunning = false;
-
- ///
- /// Disposes runtime resources.
- ///
- protected virtual void Dispose(bool disposing)
- {
- if (disposing)
- {
- OperationIdCounter = 0;
- }
- }
-
- ///
- /// Disposes runtime resources.
- ///
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- }
-}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/Actors/Events/DefaultEvent.cs b/Src/PChecker/CheckerCore/Runtime/Events/DefaultEvent.cs
similarity index 95%
rename from Src/PChecker/CheckerCore/Actors/Events/DefaultEvent.cs
rename to Src/PChecker/CheckerCore/Runtime/Events/DefaultEvent.cs
index bf430e673a..ef1d57e413 100644
--- a/Src/PChecker/CheckerCore/Actors/Events/DefaultEvent.cs
+++ b/Src/PChecker/CheckerCore/Runtime/Events/DefaultEvent.cs
@@ -3,7 +3,7 @@
using System.Runtime.Serialization;
-namespace PChecker.Actors.Events
+namespace PChecker.Runtime.Events
{
///
/// A default event that is generated by the runtime when
diff --git a/Src/PChecker/CheckerCore/Runtime/Events/Event.cs b/Src/PChecker/CheckerCore/Runtime/Events/Event.cs
new file mode 100644
index 0000000000..b8bbf5b178
--- /dev/null
+++ b/Src/PChecker/CheckerCore/Runtime/Events/Event.cs
@@ -0,0 +1,64 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System;
+using System.Runtime.Serialization;
+using PChecker.Runtime.Values;
+
+namespace PChecker.Runtime.Events
+{
+ ///
+ /// Class representing an event.
+ ///
+ [DataContract]
+ public class Event: IPValue
+ {
+ public Event()
+ {
+ }
+
+ public Event(IPValue payload)
+ {
+ Payload = payload;
+ }
+
+ public IPValue Payload { get; set; }
+
+ public bool Equals(IPValue other)
+ {
+ return other != null && GetType().FullName.Equals(other.GetType().FullName);
+ }
+
+ public virtual IPValue Clone()
+ {
+ throw new NotImplementedException();
+ }
+
+ public object ToDict()
+ {
+ return this.GetType().Name;
+ }
+
+ public override bool Equals(object obj)
+ {
+ return obj is Event other && Equals(other);
+ }
+
+ public override int GetHashCode()
+ {
+ return GetType().FullName.GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return GetType().Name;
+ }
+ }
+
+ public class PHalt : Event
+ {
+ public PHalt(IPValue payload) : base(payload)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/Actors/Events/EventInfo.cs b/Src/PChecker/CheckerCore/Runtime/Events/EventInfo.cs
similarity index 78%
rename from Src/PChecker/CheckerCore/Actors/Events/EventInfo.cs
rename to Src/PChecker/CheckerCore/Runtime/Events/EventInfo.cs
index d11359d704..a4de780989 100644
--- a/Src/PChecker/CheckerCore/Actors/Events/EventInfo.cs
+++ b/Src/PChecker/CheckerCore/Runtime/Events/EventInfo.cs
@@ -3,7 +3,7 @@
using System.Runtime.Serialization;
-namespace PChecker.Actors.Events
+namespace PChecker.Runtime.Events
{
///
/// Contains an , and its associated metadata.
@@ -23,19 +23,12 @@ internal class EventInfo
[DataMember]
internal EventOriginInfo OriginInfo { get; private set; }
- ///
- /// User-defined hash of the event. The default value is 0. Override to
- /// improve the accuracy of stateful techniques during testing.
- ///
- internal int HashedState { get; set; }
-
///
/// Initializes a new instance of the class.
///
internal EventInfo(Event e)
{
EventName = e.GetType().FullName;
- HashedState = 0;
}
///
diff --git a/Src/PChecker/CheckerCore/Actors/Events/EventOriginInfo.cs b/Src/PChecker/CheckerCore/Runtime/Events/EventOriginInfo.cs
similarity index 59%
rename from Src/PChecker/CheckerCore/Actors/Events/EventOriginInfo.cs
rename to Src/PChecker/CheckerCore/Runtime/Events/EventOriginInfo.cs
index 8aea77ed51..e8747703fe 100644
--- a/Src/PChecker/CheckerCore/Actors/Events/EventOriginInfo.cs
+++ b/Src/PChecker/CheckerCore/Runtime/Events/EventOriginInfo.cs
@@ -2,8 +2,9 @@
// Licensed under the MIT License.
using System.Runtime.Serialization;
+using PChecker.Runtime.StateMachines;
-namespace PChecker.Actors.Events
+namespace PChecker.Runtime.Events
{
///
/// Contains the origin information of an .
@@ -12,16 +13,16 @@ namespace PChecker.Actors.Events
internal class EventOriginInfo
{
///
- /// The sender actor id.
+ /// The sender state machine id.
///
[DataMember]
- internal ActorId SenderActorId { get; private set; }
+ internal StateMachineId SenderStateMachineId { get; private set; }
///
- /// The sender actor name.
+ /// The sender state machine name.
///
[DataMember]
- internal string SenderActorName { get; private set; }
+ internal string SenderStateMachineName { get; private set; }
///
/// The sender state name, if there is one.
@@ -32,10 +33,10 @@ internal class EventOriginInfo
///
/// Initializes a new instance of the class.
///
- internal EventOriginInfo(ActorId senderActorId, string senderMachineName, string senderStateName)
+ internal EventOriginInfo(StateMachineId senderStateMachineId, string senderMachineName, string senderStateName)
{
- SenderActorId = senderActorId;
- SenderActorName = senderMachineName;
+ SenderStateMachineId = senderStateMachineId;
+ SenderStateMachineName = senderMachineName;
SenderStateName = senderStateName;
}
}
diff --git a/Src/PChecker/CheckerCore/Actors/Events/GotoStateEvent.cs b/Src/PChecker/CheckerCore/Runtime/Events/GotoStateEvent.cs
similarity index 95%
rename from Src/PChecker/CheckerCore/Actors/Events/GotoStateEvent.cs
rename to Src/PChecker/CheckerCore/Runtime/Events/GotoStateEvent.cs
index ef8eadf02b..2e20b61447 100644
--- a/Src/PChecker/CheckerCore/Actors/Events/GotoStateEvent.cs
+++ b/Src/PChecker/CheckerCore/Runtime/Events/GotoStateEvent.cs
@@ -4,7 +4,7 @@
using System;
using System.Runtime.Serialization;
-namespace PChecker.Actors.Events
+namespace PChecker.Runtime.Events
{
///
/// The goto state event.
diff --git a/Src/PChecker/CheckerCore/Actors/Events/HaltEvent.cs b/Src/PChecker/CheckerCore/Runtime/Events/HaltEvent.cs
similarity index 94%
rename from Src/PChecker/CheckerCore/Actors/Events/HaltEvent.cs
rename to Src/PChecker/CheckerCore/Runtime/Events/HaltEvent.cs
index e1dcc6e064..aaa47c281c 100644
--- a/Src/PChecker/CheckerCore/Actors/Events/HaltEvent.cs
+++ b/Src/PChecker/CheckerCore/Runtime/Events/HaltEvent.cs
@@ -3,7 +3,7 @@
using System.Runtime.Serialization;
-namespace PChecker.Actors.Events
+namespace PChecker.Runtime.Events
{
///
/// The halt event.
diff --git a/Src/PChecker/CheckerCore/Actors/Events/QuiescentEvent.cs b/Src/PChecker/CheckerCore/Runtime/Events/QuiescentEvent.cs
similarity index 50%
rename from Src/PChecker/CheckerCore/Actors/Events/QuiescentEvent.cs
rename to Src/PChecker/CheckerCore/Runtime/Events/QuiescentEvent.cs
index 9b0649273c..5b9722485f 100644
--- a/Src/PChecker/CheckerCore/Actors/Events/QuiescentEvent.cs
+++ b/Src/PChecker/CheckerCore/Runtime/Events/QuiescentEvent.cs
@@ -2,27 +2,28 @@
// Licensed under the MIT License.
using System.Runtime.Serialization;
+using PChecker.Runtime.StateMachines;
-namespace PChecker.Actors.Events
+namespace PChecker.Runtime.Events
{
///
- /// Signals that an actor has reached quiescence.
+ /// Signals that an state machine has reached quiescence.
///
[DataContract]
internal sealed class QuiescentEvent : Event
{
///
- /// The id of the actor that has reached quiescence.
+ /// The id of the state machine that has reached quiescence.
///
- public ActorId ActorId;
+ public StateMachineId StateMachineId;
///
/// Initializes a new instance of the class.
///
- /// The id of the actor that has reached quiescence.
- public QuiescentEvent(ActorId id)
+ /// The id of the state machine that has reached quiescence.
+ public QuiescentEvent(StateMachineId id)
{
- ActorId = id;
+ StateMachineId = id;
}
}
}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/Actors/Events/WildcardEvent.cs b/Src/PChecker/CheckerCore/Runtime/Events/WildcardEvent.cs
similarity index 93%
rename from Src/PChecker/CheckerCore/Actors/Events/WildcardEvent.cs
rename to Src/PChecker/CheckerCore/Runtime/Events/WildcardEvent.cs
index bba77fd07d..ab8e869ab6 100644
--- a/Src/PChecker/CheckerCore/Actors/Events/WildcardEvent.cs
+++ b/Src/PChecker/CheckerCore/Runtime/Events/WildcardEvent.cs
@@ -3,7 +3,7 @@
using System.Runtime.Serialization;
-namespace PChecker.Actors.Events
+namespace PChecker.Runtime.Events
{
///
/// The wild card event.
diff --git a/Src/PChecker/CheckerCore/PRuntime/Exceptions/PIllegalCoercionException.cs b/Src/PChecker/CheckerCore/Runtime/Exceptions/PIllegalCoercionException.cs
similarity index 90%
rename from Src/PChecker/CheckerCore/PRuntime/Exceptions/PIllegalCoercionException.cs
rename to Src/PChecker/CheckerCore/Runtime/Exceptions/PIllegalCoercionException.cs
index bea5bb9003..d57692888a 100644
--- a/Src/PChecker/CheckerCore/PRuntime/Exceptions/PIllegalCoercionException.cs
+++ b/Src/PChecker/CheckerCore/Runtime/Exceptions/PIllegalCoercionException.cs
@@ -1,6 +1,6 @@
using System;
-namespace PChecker.PRuntime.Exceptions
+namespace PChecker.Runtime.Exceptions
{
public class PIllegalCoercionException : Exception
{
diff --git a/Src/PChecker/CheckerCore/PRuntime/Exceptions/PInternalException.cs b/Src/PChecker/CheckerCore/Runtime/Exceptions/PInternalException.cs
similarity index 90%
rename from Src/PChecker/CheckerCore/PRuntime/Exceptions/PInternalException.cs
rename to Src/PChecker/CheckerCore/Runtime/Exceptions/PInternalException.cs
index eb52b9c48e..b137fb8191 100644
--- a/Src/PChecker/CheckerCore/PRuntime/Exceptions/PInternalException.cs
+++ b/Src/PChecker/CheckerCore/Runtime/Exceptions/PInternalException.cs
@@ -1,6 +1,6 @@
using System;
-namespace PChecker.PRuntime.Exceptions
+namespace PChecker.Runtime.Exceptions
{
public class PInternalException : Exception
{
diff --git a/Src/PChecker/CheckerCore/PRuntime/Exceptions/PNonStandardReturnException.cs b/Src/PChecker/CheckerCore/Runtime/Exceptions/PNonStandardReturnException.cs
similarity index 93%
rename from Src/PChecker/CheckerCore/PRuntime/Exceptions/PNonStandardReturnException.cs
rename to Src/PChecker/CheckerCore/Runtime/Exceptions/PNonStandardReturnException.cs
index 482d4cec51..4e99576472 100644
--- a/Src/PChecker/CheckerCore/PRuntime/Exceptions/PNonStandardReturnException.cs
+++ b/Src/PChecker/CheckerCore/Runtime/Exceptions/PNonStandardReturnException.cs
@@ -1,6 +1,6 @@
using System;
-namespace PChecker.PRuntime.Exceptions
+namespace PChecker.Runtime.Exceptions
{
public enum NonStandardReturn
{
diff --git a/Src/PChecker/CheckerCore/PRuntime/Exceptions/PUnReachableCodeException.cs b/Src/PChecker/CheckerCore/Runtime/Exceptions/PUnReachableCodeException.cs
similarity index 90%
rename from Src/PChecker/CheckerCore/PRuntime/Exceptions/PUnReachableCodeException.cs
rename to Src/PChecker/CheckerCore/Runtime/Exceptions/PUnReachableCodeException.cs
index 1d2316f77c..cbfc5873c9 100644
--- a/Src/PChecker/CheckerCore/PRuntime/Exceptions/PUnReachableCodeException.cs
+++ b/Src/PChecker/CheckerCore/Runtime/Exceptions/PUnReachableCodeException.cs
@@ -1,6 +1,6 @@
using System;
-namespace PChecker.PRuntime.Exceptions
+namespace PChecker.Runtime.Exceptions
{
public class PUnreachableCodeException : Exception
{
diff --git a/Src/PChecker/CheckerCore/Runtime/ICoyoteRuntime.cs b/Src/PChecker/CheckerCore/Runtime/ICoyoteRuntime.cs
deleted file mode 100644
index 72795194c8..0000000000
--- a/Src/PChecker/CheckerCore/Runtime/ICoyoteRuntime.cs
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-using System;
-using System.IO;
-using PChecker.Actors.Events;
-using PChecker.Exceptions;
-using PChecker.Specifications.Monitors;
-
-namespace PChecker.Runtime
-{
- ///
- /// Interface that exposes base runtime methods for Coyote.
- ///
- public interface ICoyoteRuntime : IDisposable
- {
- ///
- /// Used to log messages. Use
- /// to replace the logger with a custom one.
- ///
- ///
- /// See Logging for more information.
- ///
- TextWriter Logger { get; }
-
- ///
- /// Callback that is fired when the runtime throws an exception which includes failed assertions.
- ///
- event OnFailureHandler OnFailure;
-
- ///
- /// Registers a new specification monitor of the specified .
- ///
- /// Type of the monitor.
- void RegisterMonitor()
- where T : Monitor;
-
- ///
- /// Invokes the specified monitor with the specified .
- ///
- /// Type of the monitor.
- /// Event to send to the monitor.
- void Monitor(Event e)
- where T : Monitor;
-
- ///
- /// Returns a nondeterministic boolean choice, that can be controlled
- /// during analysis or testing.
- ///
- /// The nondeterministic boolean choice.
- ///
- /// See Program non-determinism
- /// for more information.
- ///
- bool RandomBoolean();
-
- ///
- /// Returns a nondeterministic boolean choice, that can be controlled
- /// during analysis or testing. The value is used to generate a number
- /// in the range [0..maxValue), where 0 triggers true.
- ///
- /// The max value.
- /// The nondeterministic boolean choice.
- ///
- /// See Program non-determinism
- /// for more information.
- ///
- bool RandomBoolean(int maxValue);
-
- ///
- /// Returns a nondeterministic integer choice, that can be
- /// controlled during analysis or testing. The value is used
- /// to generate an integer in the range [0..maxValue).
- ///
- /// The max value.
- /// The nondeterministic integer choice.
- ///
- /// See Program non-determinism
- /// for more information.
- ///
- int RandomInteger(int maxValue);
-
- ///
- /// Checks if the assertion holds, and if not, throws an exception.
- ///
- /// The predicate to check.
- void Assert(bool predicate);
-
- ///
- /// Checks if the assertion holds, and if not, throws an exception.
- ///
- /// The predicate to check.
- /// The message to print if the assertion fails.
- /// The first argument.
- void Assert(bool predicate, string s, object arg0);
-
- ///
- /// Checks if the assertion holds, and if not, throws an exception.
- ///
- /// The predicate to check.
- /// The message to print if the assertion fails.
- /// The first argument.
- /// The second argument.
- void Assert(bool predicate, string s, object arg0, object arg1);
-
- ///
- /// Checks if the assertion holds, and if not, throws an exception.
- ///
- /// The predicate to check.
- /// The message to print if the assertion fails.
- /// The first argument.
- /// The second argument.
- /// The third argument.
- void Assert(bool predicate, string s, object arg0, object arg1, object arg2);
-
- ///
- /// Checks if the assertion holds, and if not, throws an exception.
- ///
- /// The predicate to check.
- /// The message to print if the assertion fails.
- /// The message arguments.
- void Assert(bool predicate, string s, params object[] args);
-
- ///
- /// Use this method to override the default for logging messages.
- ///
- /// The logger to install.
- /// The previously installed logger.
- TextWriter SetLogger(TextWriter logger);
-
- ///
- /// Terminates the runtime and notifies each active actor to halt execution.
- ///
- void Stop();
- }
-}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/Actors/Logging/IActorRuntimeLog.cs b/Src/PChecker/CheckerCore/Runtime/Logging/IControlledRuntimeLog.cs
similarity index 61%
rename from Src/PChecker/CheckerCore/Actors/Logging/IActorRuntimeLog.cs
rename to Src/PChecker/CheckerCore/Runtime/Logging/IControlledRuntimeLog.cs
index ed4cb0b958..b765d62f5c 100644
--- a/Src/PChecker/CheckerCore/Actors/Logging/IActorRuntimeLog.cs
+++ b/Src/PChecker/CheckerCore/Runtime/Logging/IControlledRuntimeLog.cs
@@ -2,170 +2,163 @@
// Licensed under the MIT License.
using System;
-using PChecker.Actors.Events;
+using PChecker.Runtime.Events;
+using PChecker.Runtime.StateMachines;
-namespace PChecker.Actors.Logging
+namespace PChecker.Runtime.Logging
{
///
/// Interface that allows an external module to track what
- /// is happening in the .
+ /// is happening in the .
///
- public interface IActorRuntimeLog
+ public interface IControlledRuntimeLog
{
- ///
- /// Invoked when the specified actor has been created.
- ///
- /// The id of the actor that has been created.
- /// The name of the creator, or null.
- /// The type of the creator, or null.
- void OnCreateActor(ActorId id, string creatorName, string creatorType);
-
///
/// Invoked when the specified state machine has been created.
///
/// The id of the state machine that has been created.
/// The name of the creator, or null.
/// The type of the creator, or null.
- void OnCreateStateMachine(ActorId id, string creatorName, string creatorType);
+ void OnCreateStateMachine(StateMachineId id, string creatorName, string creatorType);
///
- /// Invoked when the specified actor executes an action.
+ /// Invoked when the specified state machine executes an action.
///
- /// The id of the actor executing the action.
+ /// The id of the state machine executing the action.
/// The state that declared this action (can be different from currentStateName in the case of pushed states.
- /// The state name, if the actor is a state machine and a state exists, else null.
+ /// The state name, if the state machine is a state machine and a state exists, else null.
/// The name of the action being executed.
- void OnExecuteAction(ActorId id, string handlingStateName, string currentStateName, string actionName);
+ void OnExecuteAction(StateMachineId id, string handlingStateName, string currentStateName, string actionName);
///
- /// Invoked when the specified event is sent to a target actor.
+ /// Invoked when the specified event is sent to a target state machine.
///
- /// The id of the target actor.
+ /// The id of the target state machine.
/// The name of the sender, if any.
/// The type of the sender, if any.
/// The state name, if the sender is a state machine, else null.
/// The event being sent.
/// The id used to identify the send operation.
- /// Is the target actor halted.
- void OnSendEvent(ActorId targetActorId, string senderName, string senderType, string senderStateName,
- Event e, Guid opGroupId, bool isTargetHalted);
+ /// Is the target state machine halted.
+ void OnSendEvent(StateMachineId targetStateMachineId, string senderName, string senderType, string senderStateName,
+ Event e, bool isTargetHalted);
///
/// Invoked when the specified state machine raises an event.
///
- /// The id of the actor raising the event.
+ /// The id of the state machine raising the event.
/// The name of the current state.
/// The event being raised.
- void OnRaiseEvent(ActorId id, string stateName, Event e);
+ void OnRaiseEvent(StateMachineId id, string stateName, Event e);
///
- /// Invoked when the specified event is about to be enqueued to an actor.
+ /// Invoked when the specified event is about to be enqueued to an state machine.
///
- /// The id of the actor that the event is being enqueued to.
+ /// The id of the state machine that the event is being enqueued to.
/// The event being enqueued.
- void OnEnqueueEvent(ActorId id, Event e);
+ void OnEnqueueEvent(StateMachineId id, Event e);
///
- /// Invoked when the specified event is dequeued by an actor.
+ /// Invoked when the specified event is dequeued by an state machine.
///
- /// The id of the actor that the event is being dequeued by.
- /// The state name, if the actor is a state machine and a state exists, else null.
+ /// The id of the state machine that the event is being dequeued by.
+ /// The state name, if the state machine is a state machine and a state exists, else null.
/// The event being dequeued.
- void OnDequeueEvent(ActorId id, string stateName, Event e);
+ void OnDequeueEvent(StateMachineId id, string stateName, Event e);
///
- /// Invoked when the specified event is received by an actor.
+ /// Invoked when the specified event is received by an state machine.
///
- /// The id of the actor that received the event.
- /// The state name, if the actor is a state machine and a state exists, else null.
+ /// The id of the state machine that received the event.
+ /// The state name, if the state machine is a state machine and a state exists, else null.
/// The the event being received.
- /// The actor was waiting for one or more specific events,
+ /// The state machine was waiting for one or more specific events,
/// and was one of them
- void OnReceiveEvent(ActorId id, string stateName, Event e, bool wasBlocked);
+ void OnReceiveEvent(StateMachineId id, string stateName, Event e, bool wasBlocked);
///
- /// Invoked when the specified actor waits to receive an event of a specified type.
+ /// Invoked when the specified state machine waits to receive an event of a specified type.
///
- /// The id of the actor that is entering the wait state.
- /// The state name, if the actor is a state machine and a state exists, else null.
+ /// The id of the state machine that is entering the wait state.
+ /// The state name, if the state machine is a state machine and a state exists, else null.
/// The type of the event being waited for.
- void OnWaitEvent(ActorId id, string stateName, Type eventType);
+ void OnWaitEvent(StateMachineId id, string stateName, Type eventType);
///
- /// Invoked when the specified actor waits to receive an event of one of the specified types.
+ /// Invoked when the specified state machine waits to receive an event of one of the specified types.
///
- /// The id of the actor that is entering the wait state.
- /// The state name, if the actor is a state machine and a state exists, else null.
+ /// The id of the state machine that is entering the wait state.
+ /// The state name, if the state machine is a state machine and a state exists, else null.
/// The types of the events being waited for, if any.
- void OnWaitEvent(ActorId id, string stateName, params Type[] eventTypes);
+ void OnWaitEvent(StateMachineId id, string stateName, params Type[] eventTypes);
///
/// Invoked when the specified state machine enters or exits a state.
///
- /// The id of the actor entering or exiting the state.
+ /// The id of the state machine entering or exiting the state.
/// The name of the state being entered or exited.
/// If true, this is called for a state entry; otherwise, exit.
- void OnStateTransition(ActorId id, string stateName, bool isEntry);
+ void OnStateTransition(StateMachineId id, string stateName, bool isEntry);
///
/// Invoked when the specified state machine performs a goto transition to the specified state.
///
- /// The id of the actor.
+ /// The id of the state machine.
/// The name of the current state.
/// The target state of the transition.
- void OnGotoState(ActorId id, string currentStateName, string newStateName);
+ void OnGotoState(StateMachineId id, string currentStateName, string newStateName);
///
- /// Invoked when the specified actor is idle (there is nothing to dequeue) and the default
+ /// Invoked when the specified state machine is idle (there is nothing to dequeue) and the default
/// event handler is about to be executed.
///
- /// The id of the actor that the state will execute in.
- /// The state name, if the actor is a state machine and a state exists, else null.
- void OnDefaultEventHandler(ActorId id, string stateName);
+ /// The id of the state machine that the state will execute in.
+ /// The state name, if the state machine is a state machine and a state exists, else null.
+ void OnDefaultEventHandler(StateMachineId id, string stateName);
///
- /// Invoked when the specified actor has been halted.
+ /// Invoked when the specified state machine has been halted.
///
- /// The id of the actor that has been halted.
+ /// The id of the state machine that has been halted.
/// Approximate size of the inbox.
- void OnHalt(ActorId id, int inboxSize);
+ void OnHalt(StateMachineId id, int inboxSize);
///
- /// Invoked when the specified actor handled a raised event.
+ /// Invoked when the specified state machine handled a raised event.
///
- /// The id of the actor handling the event.
- /// The state name, if the actor is a state machine and a state exists, else null.
+ /// The id of the state machine handling the event.
+ /// The state name, if the state machine is a state machine and a state exists, else null.
/// The event being handled.
- void OnHandleRaisedEvent(ActorId id, string stateName, Event e);
+ void OnHandleRaisedEvent(StateMachineId id, string stateName, Event e);
///
/// Invoked when the specified event cannot be handled in the current state, its exit
/// handler is executed and then the state is popped and any previous "current state"
/// is reentered. This handler is called when that pop has been done.
///
- /// The id of the actor that the pop executed in.
- /// The state name, if the actor is a state machine and a state exists, else null.
+ /// The id of the state machine that the pop executed in.
+ /// The state name, if the state machine is a state machine and a state exists, else null.
/// The event that cannot be handled.
- void OnPopStateUnhandledEvent(ActorId id, string stateName, Event e);
+ void OnPopStateUnhandledEvent(StateMachineId id, string stateName, Event e);
///
- /// Invoked when the specified actor throws an exception.
+ /// Invoked when the specified state machine throws an exception.
///
- /// The id of the actor that threw the exception.
- /// The state name, if the actor is a state machine and a state exists, else null.
+ /// The id of the state machine that threw the exception.
+ /// The state name, if the state machine is a state machine and a state exists, else null.
/// The name of the action being executed.
/// The exception.
- void OnExceptionThrown(ActorId id, string stateName, string actionName, Exception ex);
+ void OnExceptionThrown(StateMachineId id, string stateName, string actionName, Exception ex);
///
/// Invoked when the specified OnException method is used to handle a thrown exception.
///
- /// The id of the actor that threw the exception.
- /// The state name, if the actor is a state machine and a state exists, else null.
+ /// The id of the state machine that threw the exception.
+ /// The state name, if the state machine is a state machine and a state exists, else null.
/// The name of the action being executed.
/// The exception.
- void OnExceptionHandled(ActorId id, string stateName, string actionName, Exception ex);
+ void OnExceptionHandled(StateMachineId id, string stateName, string actionName, Exception ex);
///
diff --git a/Src/PChecker/CheckerCore/Actors/Logging/JsonWriter.cs b/Src/PChecker/CheckerCore/Runtime/Logging/JsonWriter.cs
similarity index 95%
rename from Src/PChecker/CheckerCore/Actors/Logging/JsonWriter.cs
rename to Src/PChecker/CheckerCore/Runtime/Logging/JsonWriter.cs
index 2802f9e715..a546bae0f2 100644
--- a/Src/PChecker/CheckerCore/Actors/Logging/JsonWriter.cs
+++ b/Src/PChecker/CheckerCore/Runtime/Logging/JsonWriter.cs
@@ -6,7 +6,7 @@
using System.Security.Cryptography;
using System.Text;
-namespace PChecker.Actors.Logging
+namespace PChecker.Runtime.Logging
{
///
/// Class for handling generating the vector clock for a log entry
@@ -15,7 +15,7 @@ internal class VectorClockGenerator
{
///
/// Nested class for handling FIFO send receive requests.
- /// NOTE: In the case of sending to a the same machine with the same event and same payload.
+ /// NOTE: In the case of sending to the same machine with the same event and same payload.
///
private class FifoSendReceiveMapping
{
@@ -349,23 +349,23 @@ public LogEntry()
/// Enum representing the possible attributes in the details dictionary,
/// which represents the data associated with a specific log type. All of
/// the following are available or expanded parameters associated with an
- /// IActorRuntime method. Naming for them is mostly the same except some
+ /// ControlledRuntime method. Naming for them is mostly the same except some
/// are changed for simplicity.
- /// I.e., for OnRaiseEvent(ActorId id, string, stateName, Event e), it
+ /// I.e., for OnRaiseEvent(StateMachineId id, string, stateName, Event e), it
/// will have attributes id, state (simplified from stateName, event
/// (simplified from eventName within Event e), and payload (in Event e).
///
public class LogDetails
{
///
- /// The text log from PLogFormatter. Removes the log tags.
+ /// The text log from PCheckerLogTextFormatter. Removes the log tags.
/// I.e., no <SomeLog> in the beginning.
/// Available for all log types.
///
public string? Log { get; set; }
///
- /// The actor id.
+ /// The state machine id.
///
public string? Id { get; set; }
@@ -437,7 +437,7 @@ public class LogDetails
public int? HaltInboxSize { get; set; }
///
- /// Boolean representing whether an actor was waiting for one or more events
+ /// Boolean representing whether an state machine was waiting for one or more events
/// Available for log type ReceiveEvent.
///
public bool? WasBlocked { get; set; }
@@ -449,7 +449,7 @@ public class LogDetails
public string? Sender { get; set; }
///
- /// Id of target actor.
+ /// Id of target state machine.
/// Available for log type SendEvent.
///
public string? Target { get; set; }
@@ -461,7 +461,7 @@ public class LogDetails
public string? OpGroupId { get; set; }
///
- /// Boolean representing whether the target actor was halted.
+ /// Boolean representing whether the target state machine was halted.
/// Available for log type SendEvent.
///
public bool? IsTargetHalted { get; set; }
@@ -557,8 +557,8 @@ public JsonWriter()
///
/// Enum representing the different log types the JSON error trace logs.
- /// Referenced from PLogFormatter.cs and ActorRuntimeLogTextFormatter.cs
- /// to see what those formatter logs. Check IActorRuntimeLog.cs to see
+ /// Referenced from PCheckerLogTextFormatter.cs and PCheckerLogTextFormatter.cs
+ /// to see what those formatter logs. Check IControlledRuntimeLog.cs to see
/// each log types' description and when they are invoked.
///
public enum LogType
@@ -568,11 +568,6 @@ public enum LogType
///
AssertionFailure,
- ///
- /// Invoked when the specified actor has been created.
- ///
- CreateActor,
-
///
/// Invoked when the specified state machine has been created.
///
@@ -584,13 +579,13 @@ public enum LogType
CreateMonitor,
///
- /// Invoked when the specified actor is idle (there is nothing to dequeue) and the default
+ /// Invoked when the specified state machine is idle (there is nothing to dequeue) and the default
/// event handler is about to be executed.
///
DefaultEventHandler,
///
- /// Invoked when the specified event is dequeued by an actor.
+ /// Invoked when the specified event is dequeued by an state machine.
///
DequeueEvent,
@@ -600,7 +595,7 @@ public enum LogType
ExceptionHandled,
///
- /// Invoked when the specified actor throws an exception.
+ /// Invoked when the specified state machine throws an exception.
///
ExceptionThrown,
@@ -610,7 +605,7 @@ public enum LogType
GotoState,
///
- /// Invoked when the specified actor has been halted.
+ /// Invoked when the specified state machine has been halted.
///
Halt,
@@ -652,12 +647,12 @@ public enum LogType
RaiseEvent,
///
- /// Invoked when the specified event is received by an actor.
+ /// Invoked when the specified event is received by an state machine.
///
ReceiveEvent,
///
- /// Invoked when the specified event is sent to a target actor.
+ /// Invoked when the specified event is sent to a target state machine.
///
SendEvent,
@@ -672,12 +667,12 @@ public enum LogType
StrategyDescription,
///
- /// Invoked when the specified actor waits to receive an event of a specified type.
+ /// Invoked when the specified state machine waits to receive an event of a specified type.
///
WaitEvent,
///
- /// Invoked when the specified actor waits to receive multiple events of a specified type.
+ /// Invoked when the specified state machine waits to receive multiple events of a specified type.
///
WaitMultipleEvents,
diff --git a/Src/PChecker/CheckerCore/Actors/Logging/LogWriter.cs b/Src/PChecker/CheckerCore/Runtime/Logging/LogWriter.cs
similarity index 72%
rename from Src/PChecker/CheckerCore/Actors/Logging/LogWriter.cs
rename to Src/PChecker/CheckerCore/Runtime/Logging/LogWriter.cs
index aad60d8aab..16a968e33f 100644
--- a/Src/PChecker/CheckerCore/Actors/Logging/LogWriter.cs
+++ b/Src/PChecker/CheckerCore/Runtime/Logging/LogWriter.cs
@@ -5,21 +5,22 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
-using PChecker.Actors.Events;
using PChecker.IO.Logging;
+using PChecker.Runtime.Events;
+using PChecker.Runtime.StateMachines;
-namespace PChecker.Actors.Logging
+namespace PChecker.Runtime.Logging
{
///
/// Manages the installed and all registered
- /// objects.
+ /// objects.
///
- internal sealed class LogWriter
+ public sealed class LogWriter
{
///
/// The set of registered log writers.
///
- private readonly HashSet Logs;
+ private readonly HashSet Logs;
///
/// Used to log messages.
@@ -36,7 +37,7 @@ internal sealed class LogWriter
///
internal LogWriter(CheckerConfiguration checkerConfiguration)
{
- Logs = new HashSet();
+ Logs = new HashSet();
if (checkerConfiguration.IsVerbose)
{
@@ -48,30 +49,13 @@ internal LogWriter(CheckerConfiguration checkerConfiguration)
}
}
- ///
- /// Logs that the specified actor has been created.
- ///
- /// The id of the actor that has been created.
- /// The name of the creator, or null.
- /// The type of the creator, or null.
- public void LogCreateActor(ActorId id, string creatorName, string creatorType)
- {
- if (Logs.Count > 0)
- {
- foreach (var log in Logs)
- {
- log.OnCreateActor(id, creatorName, creatorType);
- }
- }
- }
-
///
/// Logs that the specified state machine has been created.
///
/// The id of the state machine that has been created.
/// The name of the creator, or null.
/// The type of the creator, or null.
- public void LogCreateStateMachine(ActorId id, string creatorName, string creatorType)
+ public void LogCreateStateMachine(StateMachineId id, string creatorName, string creatorType)
{
if (Logs.Count > 0)
{
@@ -83,13 +67,13 @@ public void LogCreateStateMachine(ActorId id, string creatorName, string creator
}
///
- /// Logs that the specified actor executes an action.
+ /// Logs that the specified state machine executes an action.
///
- /// The id of the actor executing the action.
+ /// The id of the state machine executing the action.
/// The state that declared this action (can be different from currentStateName in the case of PushStates.
- /// The state name, if the actor is a state machine and a state exists, else null.
+ /// The state name, if the state machine is a state machine and a state exists, else null.
/// The name of the action being executed.
- public void LogExecuteAction(ActorId id, string handlingStateName, string currentStateName, string actionName)
+ public void LogExecuteAction(StateMachineId id, string handlingStateName, string currentStateName, string actionName)
{
if (Logs.Count > 0)
{
@@ -101,34 +85,34 @@ public void LogExecuteAction(ActorId id, string handlingStateName, string curren
}
///
- /// Logs that the specified event is sent to a target actor.
+ /// Logs that the specified event is sent to a target state machine.
///
- /// The id of the target actor.
+ /// The id of the target state machine.
/// The name of the sender, if any.
/// The type of the sender, if any.
/// The state name, if the sender is a state machine, else null.
/// The event being sent.
/// The id used to identify the send operation.
- /// Is the target actor halted.
- public void LogSendEvent(ActorId targetActorId, string senderName, string senderType, string senderState,
- Event e, Guid opGroupId, bool isTargetHalted)
+ /// Is the target state machine halted.
+ public void LogSendEvent(StateMachineId targetStateMachineId, string senderName, string senderType, string senderState,
+ Event e, bool isTargetHalted)
{
if (Logs.Count > 0)
{
foreach (var log in Logs)
{
- log.OnSendEvent(targetActorId, senderName, senderType, senderState, e, opGroupId, isTargetHalted);
+ log.OnSendEvent(targetStateMachineId, senderName, senderType, senderState, e, isTargetHalted);
}
}
}
///
- /// Logs that the specified actor raises an event.
+ /// Logs that the specified state machine raises an event.
///
- /// The id of the actor raising the event.
- /// The state name, if the actor is a state machine and a state exists, else null.
+ /// The id of the state machine raising the event.
+ /// The state name, if the state machine is a state machine and a state exists, else null.
/// The event being raised.
- public void LogRaiseEvent(ActorId id, string stateName, Event e)
+ public void LogRaiseEvent(StateMachineId id, string stateName, Event e)
{
if (Logs.Count > 0)
{
@@ -140,11 +124,11 @@ public void LogRaiseEvent(ActorId id, string stateName, Event e)
}
///
- /// Logs that the specified event is about to be enqueued to an actor.
+ /// Logs that the specified event is about to be enqueued to an state machine.
///
- /// The id of the actor that the event is being enqueued to.
+ /// The id of the state machine that the event is being enqueued to.
/// The event being enqueued.
- public void LogEnqueueEvent(ActorId id, Event e)
+ public void LogEnqueueEvent(StateMachineId id, Event e)
{
if (Logs.Count > 0)
{
@@ -156,12 +140,12 @@ public void LogEnqueueEvent(ActorId id, Event e)
}
///
- /// Logs that the specified event is dequeued by an actor.
+ /// Logs that the specified event is dequeued by an state machine.
///
- /// The id of the actor that the event is being dequeued by.
- /// The state name, if the actor is a state machine and a state exists, else null.
+ /// The id of the state machine that the event is being dequeued by.
+ /// The state name, if the state machine is a state machine and a state exists, else null.
/// The event being dequeued.
- public void LogDequeueEvent(ActorId id, string stateName, Event e)
+ public void LogDequeueEvent(StateMachineId id, string stateName, Event e)
{
if (Logs.Count > 0)
{
@@ -173,14 +157,14 @@ public void LogDequeueEvent(ActorId id, string stateName, Event e)
}
///
- /// Logs that the specified event is received by an actor.
+ /// Logs that the specified event is received by an state machine.
///
- /// The id of the actor that received the event.
- /// The state name, if the actor is a state machine and a state exists, else null.
+ /// The id of the state machine that received the event.
+ /// The state name, if the state machine is a state machine and a state exists, else null.
/// The event being received.
/// The state machine was waiting for one or more specific events,
/// and was one of them.
- public void LogReceiveEvent(ActorId id, string stateName, Event e, bool wasBlocked)
+ public void LogReceiveEvent(StateMachineId id, string stateName, Event e, bool wasBlocked)
{
if (Logs.Count > 0)
{
@@ -192,12 +176,12 @@ public void LogReceiveEvent(ActorId id, string stateName, Event e, bool wasBlock
}
///
- /// Logs that the specified actor waits to receive an event of a specified type.
+ /// Logs that the specified state machine waits to receive an event of a specified type.
///
- /// The id of the actor that is entering the wait state.
- /// The state name, if the actor is a state machine and a state exists, else null.
+ /// The id of the state machine that is entering the wait state.
+ /// The state name, if the state machine is a state machine and a state exists, else null.
/// The type of the event being waited for.
- public void LogWaitEvent(ActorId id, string stateName, Type eventType)
+ public void LogWaitEvent(StateMachineId id, string stateName, Type eventType)
{
if (Logs.Count > 0)
{
@@ -209,12 +193,12 @@ public void LogWaitEvent(ActorId id, string stateName, Type eventType)
}
///
- /// Logs that the specified actor waits to receive an event of one of the specified types.
+ /// Logs that the specified state machine waits to receive an event of one of the specified types.
///
- /// The id of the actor that is entering the wait state.
- /// The state name, if the actor is a state machine and a state exists, else null.
+ /// The id of the state machine that is entering the wait state.
+ /// The state name, if the state machine is a state machine and a state exists, else null.
/// The types of the events being waited for, if any.
- public void LogWaitEvent(ActorId id, string stateName, params Type[] eventTypes)
+ public void LogWaitEvent(StateMachineId id, string stateName, params Type[] eventTypes)
{
if (Logs.Count > 0)
{
@@ -245,10 +229,10 @@ public void LogRandom(object result, string callerName, string callerType)
///
/// Logs that the specified state machine enters or exits a state.
///
- /// The id of the actor entering or exiting the state.
+ /// The id of the state machine entering or exiting the state.
/// The name of the state being entered or exited.
/// If true, this is called for a state entry; otherwise, exit.
- public void LogStateTransition(ActorId id, string stateName, bool isEntry)
+ public void LogStateTransition(StateMachineId id, string stateName, bool isEntry)
{
if (Logs.Count > 0)
{
@@ -262,10 +246,10 @@ public void LogStateTransition(ActorId id, string stateName, bool isEntry)
///
/// Logs that the specified state machine performs a goto state transition.
///
- /// The id of the actor.
+ /// The id of the state machine.
/// The name of the current state.
/// The target state of the transition.
- public void LogGotoState(ActorId id, string currentStateName, string newStateName)
+ public void LogGotoState(StateMachineId id, string currentStateName, string newStateName)
{
if (Logs.Count > 0)
{
@@ -277,11 +261,11 @@ public void LogGotoState(ActorId id, string currentStateName, string newStateNam
}
///
- /// Logs that the specified actor has halted.
+ /// Logs that the specified state machine has halted.
///
- /// The id of the actor that has been halted.
+ /// The id of the state machine that has been halted.
/// Approximate size of the inbox.
- public void LogHalt(ActorId id, int inboxSize)
+ public void LogHalt(StateMachineId id, int inboxSize)
{
if (Logs.Count > 0)
{
@@ -293,12 +277,12 @@ public void LogHalt(ActorId id, int inboxSize)
}
///
- /// Logs that the specified actor is idle (there is nothing to dequeue) and the default
+ /// Logs that the specified state machine is idle (there is nothing to dequeue) and the default
/// event handler is about to be executed.
///
- /// The id of the actor that the state will execute in.
- /// The state name, if the actor is a state machine and a state exists, else null.
- public void LogDefaultEventHandler(ActorId id, string stateName)
+ /// The id of the state machine that the state will execute in.
+ /// The state name, if the state machine is a state machine and a state exists, else null.
+ public void LogDefaultEventHandler(StateMachineId id, string stateName)
{
if (Logs.Count > 0)
{
@@ -312,10 +296,10 @@ public void LogDefaultEventHandler(ActorId id, string stateName)
///
/// Logs that the specified state machine handled a raised event.
///
- /// The id of the actor handling the event.
+ /// The id of the state machine handling the event.
/// The name of the current state.
/// The event being handled.
- public void LogHandleRaisedEvent(ActorId id, string stateName, Event e)
+ public void LogHandleRaisedEvent(StateMachineId id, string stateName, Event e)
{
if (Logs.Count > 0)
{
@@ -331,10 +315,10 @@ public void LogHandleRaisedEvent(ActorId id, string stateName, Event e)
/// handler is executed and then the state is popped and any previous "current state"
/// is reentered. This handler is called when that pop has been done.
///
- /// The id of the actor that the pop executed in.
- /// The state name, if the actor is a state machine and a state exists, else null.
+ /// The id of the state machine that the pop executed in.
+ /// The state name, if the state machine is a state machine and a state exists, else null.
/// The event that cannot be handled.
- public void LogPopStateUnhandledEvent(ActorId id, string stateName, Event e)
+ public void LogPopStateUnhandledEvent(StateMachineId id, string stateName, Event e)
{
if (Logs.Count > 0)
{
@@ -346,13 +330,13 @@ public void LogPopStateUnhandledEvent(ActorId id, string stateName, Event e)
}
///
- /// Logs that the specified actor throws an exception.
+ /// Logs that the specified state machine throws an exception.
///
- /// The id of the actor that threw the exception.
- /// The state name, if the actor is a state machine and a state exists, else null.
+ /// The id of the state machine that threw the exception.
+ /// The state name, if the state machine is a state machine and a state exists, else null.
/// The name of the action being executed.
/// The exception.
- public void LogExceptionThrown(ActorId id, string stateName, string actionName, Exception ex)
+ public void LogExceptionThrown(StateMachineId id, string stateName, string actionName, Exception ex)
{
if (Logs.Count > 0)
{
@@ -366,11 +350,11 @@ public void LogExceptionThrown(ActorId id, string stateName, string actionName,
///
/// Logs that the specified OnException method is used to handle a thrown exception.
///
- /// The id of the actor that threw the exception.
- /// The state name, if the actor is a state machine and a state exists, else null.
+ /// The id of the state machine that threw the exception.
+ /// The state name, if the state machine is a state machine and a state exists, else null.
/// The name of the action being executed.
/// The exception.
- public void LogExceptionHandled(ActorId id, string stateName, string actionName, Exception ex)
+ public void LogExceptionHandled(StateMachineId id, string stateName, string actionName, Exception ex)
{
if (Logs.Count > 0)
{
@@ -532,12 +516,12 @@ internal void LogCompletion()
}
///
- /// Returns all registered logs of type ,
+ /// Returns all registered logs of type ,
/// if there are any.
///
- public IEnumerable GetLogsOfType()
- where TActorRuntimeLog : IActorRuntimeLog =>
- Logs.OfType();
+ public IEnumerable GetLogsOfType()
+ where TStateMachineRuntimeLog : IControlledRuntimeLog =>
+ Logs.OfType();
///
/// Use this method to override the default for logging messages.
@@ -549,7 +533,7 @@ internal TextWriter SetLogger(TextWriter logger)
{
Logger = TextWriter.Null;
- var textLog = GetLogsOfType().FirstOrDefault();
+ var textLog = GetLogsOfType().FirstOrDefault();
if (textLog != null)
{
textLog.Logger = Logger;
@@ -573,9 +557,9 @@ internal TextWriter SetLogger(TextWriter logger)
/// The jsonLogger instance created from runtime before running tests.
internal void SetJsonLogger(JsonWriter jsonLogger) => JsonLogger = jsonLogger;
- private ActorRuntimeLogTextFormatter GetOrCreateTextLog()
+ private PCheckerLogTextFormatter GetOrCreateTextLog()
{
- var textLog = GetLogsOfType().FirstOrDefault();
+ var textLog = GetLogsOfType().FirstOrDefault();
if (textLog == null)
{
if (Logger == null)
@@ -583,7 +567,7 @@ private ActorRuntimeLogTextFormatter GetOrCreateTextLog()
Logger = new ConsoleLogger();
}
- textLog = new ActorRuntimeLogTextFormatter
+ textLog = new PCheckerLogTextFormatter
{
Logger = Logger
};
@@ -595,9 +579,9 @@ private ActorRuntimeLogTextFormatter GetOrCreateTextLog()
}
///
- /// Use this method to register an .
+ /// Use this method to register an .
///
- internal void RegisterLog(IActorRuntimeLog log)
+ internal void RegisterLog(IControlledRuntimeLog log)
{
if (log == null)
{
@@ -605,9 +589,9 @@ internal void RegisterLog(IActorRuntimeLog log)
}
// Make sure we only have one text logger
- if (log is ActorRuntimeLogTextFormatter a)
+ if (log is PCheckerLogTextFormatter a)
{
- var textLog = GetLogsOfType().FirstOrDefault();
+ var textLog = GetLogsOfType().FirstOrDefault();
if (textLog != null)
{
Logs.Remove(textLog);
@@ -619,9 +603,9 @@ internal void RegisterLog(IActorRuntimeLog log)
}
}
- // If log is or of subclass ActorRuntimeLogJsonFormatter (i.e. when log is PJsonFormatter),
+ // If log is or of subclass PCheckerLogJsonFormatter (i.e. when log is PCheckerLogJsonFormatter),
// update the Writer reference to the JsonLogger instance defined within LogWriter.cs
- if (log is ActorRuntimeLogJsonFormatter tempJsonFormatter)
+ if (log is PCheckerLogJsonFormatter tempJsonFormatter)
{
tempJsonFormatter.Writer = JsonLogger;
}
@@ -630,9 +614,9 @@ internal void RegisterLog(IActorRuntimeLog log)
}
///
- /// Use this method to unregister a previously registered .
+ /// Use this method to unregister a previously registered .
///
- internal void RemoveLog(IActorRuntimeLog log)
+ internal void RemoveLog(IControlledRuntimeLog log)
{
if (log != null)
{
diff --git a/Src/PChecker/CheckerCore/PRuntime/PJsonFormatter.cs b/Src/PChecker/CheckerCore/Runtime/Logging/PCheckerLogJsonFormatter.cs
similarity index 76%
rename from Src/PChecker/CheckerCore/PRuntime/PJsonFormatter.cs
rename to Src/PChecker/CheckerCore/Runtime/Logging/PCheckerLogJsonFormatter.cs
index f654ff132b..c37b679a3c 100644
--- a/Src/PChecker/CheckerCore/PRuntime/PJsonFormatter.cs
+++ b/Src/PChecker/CheckerCore/Runtime/Logging/PCheckerLogJsonFormatter.cs
@@ -1,24 +1,35 @@
-// Copyright (c) Microsoft Corporation.
+// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
using System.Linq;
using System.Threading.Tasks;
-using PChecker.Actors;
-using PChecker.Actors.Events;
-using PChecker.Actors.Logging;
-using PChecker.PRuntime.Exceptions;
+using PChecker.Runtime.Events;
+using PChecker.Runtime.Exceptions;
+using PChecker.Runtime.StateMachines;
-namespace PChecker.PRuntime
+namespace PChecker.Runtime.Logging
{
///
- /// This class implements IActorRuntimeLog and generates log output in an XML format.
+ /// This class implements IControlledRuntimeLog and generates log output in an XML format.
///
- public class PJsonFormatter : ActorRuntimeLogJsonFormatter
+ public class PCheckerLogJsonFormatter : IControlledRuntimeLog
{
+ ///
+ /// Get or set the JsonWriter to write to.
+ ///
+ public JsonWriter Writer { get; set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ protected PCheckerLogJsonFormatter()
+ {
+ Writer = new JsonWriter();
+ }
///
- /// Removes the '<' and '>' tags for a log text.
+ /// Removes the "<" and ">" tags for a log text.
///
/// The text log
/// New string with the tag removed or just the string itself if there is no tag.
@@ -38,7 +49,7 @@ private static string RemoveLogTag(string log)
}
///
- /// Method taken from PLogFormatter.cs file. Takes in a string and only get the
+ /// Method taken from PCheckerLogTextFormatter.cs file. Takes in a string and only get the
/// last element of the string separated by a period.
/// I.e.
/// Input: PImplementation.TestWithSingleClient(2)
@@ -49,9 +60,9 @@ private static string RemoveLogTag(string log)
private static string GetShortName(string name) => name?.Split('.').Last();
///
- /// Method taken from PLogFormatter.cs file. Takes in Event e and returns string
+ /// Method taken from PCheckerLogTextFormatter.cs file. Takes in Event e and returns string
/// with details about the event such as event name and its payload. Slightly modified
- /// from the method in PLogFormatter.cs in that payload is parsed with the CleanPayloadString
+ /// from the method in PCheckerLogTextFormatter.cs in that payload is parsed with the CleanPayloadString
/// method right above.
///
/// Event input.
@@ -63,7 +74,7 @@ private static string GetEventNameWithPayload(Event e)
return e.GetType().Name;
}
- var pe = (PEvent)(e);
+ var pe = (Event)(e);
var payload = pe.Payload == null ? "null" : pe.Payload.ToEscapedString();
var msg = pe.Payload == null ? "" : $" with payload ({payload})";
return $"{GetShortName(e.GetType().Name)}{msg}";
@@ -81,15 +92,15 @@ private static object GetEventPayloadInJson(Event e)
return null;
}
- var pe = (PEvent)(e);
+ var pe = (Event)(e);
return pe.Payload?.ToDict();
}
- public override void OnCompleted()
+ public void OnCompleted()
{
}
- public override void OnAssertionFailure(string error)
+ public void OnAssertionFailure(string error)
{
error = RemoveLogTag(error);
@@ -98,33 +109,10 @@ public override void OnAssertionFailure(string error)
Writer.AddLog(error);
Writer.AddToLogs();
}
-
- public override void OnCreateActor(ActorId id, string creatorName, string creatorType)
- {
- if (id.Name.Contains("GodMachine") || creatorName.Contains("GodMachine"))
- {
- return;
- }
-
- var source = creatorName ?? $"task '{Task.CurrentId}'";
- var log = $"{id} was created by {source}.";
-
- Writer.AddLogType(JsonWriter.LogType.CreateActor);
- Writer.LogDetails.Id = id.ToString();
- Writer.LogDetails.CreatorName = source;
- Writer.LogDetails.CreatorType = creatorType;
- Writer.AddLog(log);
- Writer.AddToLogs(updateVcMap: true);
- }
-
+
///
- public override void OnCreateStateMachine(ActorId id, string creatorName, string creatorType)
+ public void OnCreateStateMachine(StateMachineId id, string creatorName, string creatorType)
{
- if (id.Name.Contains("GodMachine") || creatorName.Contains("GodMachine"))
- {
- return;
- }
-
var source = creatorName ?? $"task '{Task.CurrentId}'";
var log = $"{id} was created by {source}.";
@@ -136,7 +124,7 @@ public override void OnCreateStateMachine(ActorId id, string creatorName, string
Writer.AddToLogs(updateVcMap: true);
}
- public override void OnDefaultEventHandler(ActorId id, string stateName)
+ public void OnDefaultEventHandler(StateMachineId id, string stateName)
{
stateName = GetShortName(stateName);
@@ -151,13 +139,8 @@ public override void OnDefaultEventHandler(ActorId id, string stateName)
Writer.AddToLogs(updateVcMap: true);
}
- public override void OnDequeueEvent(ActorId id, string stateName, Event e)
+ public void OnDequeueEvent(StateMachineId id, string stateName, Event e)
{
- if (stateName.Contains("__InitState__") || id.Name.Contains("GodMachine"))
- {
- return;
- }
-
var eventName = GetEventNameWithPayload(e);
var log = stateName is null
? $"'{id}' dequeued event '{eventName}'."
@@ -172,11 +155,13 @@ public override void OnDequeueEvent(ActorId id, string stateName, Event e)
Writer.AddToLogs(updateVcMap: true);
}
- public override void OnEnqueueEvent(ActorId id, Event e)
+ ///
+ public void OnEnqueueEvent(StateMachineId id, Event e)
{
}
- public override void OnExceptionHandled(ActorId id, string stateName, string actionName, Exception ex)
+ ///
+ public void OnExceptionHandled(StateMachineId id, string stateName, string actionName, Exception ex)
{
if (ex is PNonStandardReturnException)
{
@@ -196,7 +181,8 @@ public override void OnExceptionHandled(ActorId id, string stateName, string act
Writer.AddToLogs(updateVcMap: true);
}
- public override void OnExceptionThrown(ActorId id, string stateName, string actionName, Exception ex)
+ ///
+ public void OnExceptionThrown(StateMachineId id, string stateName, string actionName, Exception ex)
{
if (ex is PNonStandardReturnException)
{
@@ -215,18 +201,15 @@ public override void OnExceptionThrown(ActorId id, string stateName, string acti
Writer.AddLog(log);
Writer.AddToLogs(updateVcMap: true);
}
-
- public override void OnExecuteAction(ActorId id, string handlingStateName, string currentStateName, string actionName)
+
+ ///
+ public void OnExecuteAction(StateMachineId id, string handlingStateName, string currentStateName, string actionName)
{
}
- public override void OnGotoState(ActorId id, string currentStateName, string newStateName)
+ ///
+ public void OnGotoState(StateMachineId id, string currentStateName, string newStateName)
{
- if (currentStateName.Contains("__InitState__") || id.Name.Contains("GodMachine"))
- {
- return;
- }
-
currentStateName = GetShortName(currentStateName);
newStateName = GetShortName(newStateName);
@@ -241,7 +224,8 @@ public override void OnGotoState(ActorId id, string currentStateName, string new
Writer.AddToLogs(updateVcMap: true);
}
- public override void OnHalt(ActorId id, int inboxSize)
+ ///
+ public void OnHalt(StateMachineId id, int inboxSize)
{
var log = $"{id} halted with {inboxSize} events in its inbox.";
@@ -251,12 +235,14 @@ public override void OnHalt(ActorId id, int inboxSize)
Writer.AddLog(log);
Writer.AddToLogs(updateVcMap: true);
}
-
- public override void OnHandleRaisedEvent(ActorId id, string stateName, Event e)
+
+ ///
+ public void OnHandleRaisedEvent(StateMachineId id, string stateName, Event e)
{
}
- public override void OnPopState(ActorId id, string currentStateName, string restoredStateName)
+ ///
+ public void OnPopState(StateMachineId id, string currentStateName, string restoredStateName)
{
currentStateName = string.IsNullOrEmpty(currentStateName) ? "[not recorded]" : currentStateName;
var reenteredStateName = restoredStateName ?? string.Empty;
@@ -270,7 +256,8 @@ public override void OnPopState(ActorId id, string currentStateName, string rest
Writer.AddToLogs(updateVcMap: true);
}
- public override void OnPopStateUnhandledEvent(ActorId id, string stateName, Event e)
+ ///
+ public void OnPopStateUnhandledEvent(StateMachineId id, string stateName, Event e)
{
var log = $"{id} popped state {stateName} due to unhandled event '{e.GetType().Name}'.";
@@ -282,7 +269,8 @@ public override void OnPopStateUnhandledEvent(ActorId id, string stateName, Even
Writer.AddToLogs(updateVcMap: true);
}
- public override void OnPushState(ActorId id, string currentStateName, string newStateName)
+ ///
+ public void OnPushState(StateMachineId id, string currentStateName, string newStateName)
{
var log = $"{id} pushed from state '{currentStateName}' to state '{newStateName}'.";
@@ -294,13 +282,13 @@ public override void OnPushState(ActorId id, string currentStateName, string new
Writer.AddToLogs(updateVcMap: true);
}
- public override void OnRaiseEvent(ActorId id, string stateName, Event e)
+ ///
+ public void OnRaiseEvent(StateMachineId id, string stateName, Event e)
{
stateName = GetShortName(stateName);
string eventName = GetEventNameWithPayload(e);
- if (stateName.Contains("__InitState__") || id.Name.Contains("GodMachine") ||
- eventName.Contains("GotoStateEvent"))
+ if (eventName.Contains("GotoStateEvent"))
{
return;
}
@@ -318,7 +306,8 @@ public override void OnRaiseEvent(ActorId id, string stateName, Event e)
Writer.AddToLogs(updateVcMap: true);
}
- public override void OnReceiveEvent(ActorId id, string stateName, Event e, bool wasBlocked)
+ ///
+ public void OnReceiveEvent(StateMachineId id, string stateName, Event e, bool wasBlocked)
{
stateName = GetShortName(stateName);
string eventName = GetEventNameWithPayload(e);
@@ -337,37 +326,32 @@ public override void OnReceiveEvent(ActorId id, string stateName, Event e, bool
Writer.AddToLogs(updateVcMap: true);
}
- public override void OnSendEvent(ActorId targetActorId, string senderName, string senderType, string senderStateName,
- Event e, Guid opGroupId, bool isTargetHalted)
+ ///
+ public void OnSendEvent(StateMachineId targetStateMachineId, string senderName, string senderType, string senderStateName,
+ Event e, bool isTargetHalted)
{
senderStateName = GetShortName(senderStateName);
string eventName = GetEventNameWithPayload(e);
- var opGroupIdMsg = opGroupId != Guid.Empty ? $" (operation group '{opGroupId}')" : string.Empty;
var isHalted = isTargetHalted ? $" which has halted" : string.Empty;
var sender = !string.IsNullOrEmpty(senderName)
? $"'{senderName}' in state '{senderStateName}'"
: $"The runtime";
- var log = $"{sender} sent event '{eventName}' to '{targetActorId}'{isHalted}{opGroupIdMsg}.";
+ var log = $"{sender} sent event '{eventName}' to '{targetStateMachineId}'{isHalted}.";
Writer.AddLogType(JsonWriter.LogType.SendEvent);
Writer.LogDetails.Sender = !string.IsNullOrEmpty(senderName) ? senderName : "Runtime";
Writer.LogDetails.State = senderStateName;
Writer.LogDetails.Event = GetShortName(e.GetType().Name);
- Writer.LogDetails.Target = targetActorId.ToString();
- Writer.LogDetails.OpGroupId = opGroupId.ToString();
+ Writer.LogDetails.Target = targetStateMachineId.ToString();
Writer.LogDetails.IsTargetHalted = isTargetHalted;
Writer.LogDetails.Payload = GetEventPayloadInJson(e);
Writer.AddLog(log);
Writer.AddToLogs(updateVcMap: true);
}
- public override void OnStateTransition(ActorId id, string stateName, bool isEntry)
+ ///
+ public void OnStateTransition(StateMachineId id, string stateName, bool isEntry)
{
- if (stateName.Contains("__InitState__") || id.Name.Contains("GodMachine"))
- {
- return;
- }
-
stateName = GetShortName(stateName);
var direction = isEntry ? "enters" : "exits";
var log = $"{id} {direction} state '{stateName}'.";
@@ -380,7 +364,8 @@ public override void OnStateTransition(ActorId id, string stateName, bool isEntr
Writer.AddToLogs(updateVcMap: true);
}
- public override void OnWaitEvent(ActorId id, string stateName, Type eventType)
+ ///
+ public void OnWaitEvent(StateMachineId id, string stateName, Type eventType)
{
stateName = GetShortName(stateName);
@@ -396,7 +381,8 @@ public override void OnWaitEvent(ActorId id, string stateName, Type eventType)
Writer.AddToLogs(updateVcMap: true);
}
- public override void OnWaitEvent(ActorId id, string stateName, params Type[] eventTypes)
+ ///
+ public void OnWaitEvent(StateMachineId id, string stateName, params Type[] eventTypes)
{
stateName = GetShortName(stateName);
string eventNames;
@@ -444,7 +430,8 @@ public override void OnWaitEvent(ActorId id, string stateName, params Type[] eve
Writer.AddToLogs(updateVcMap: true);
}
- public override void OnCreateMonitor(string monitorType)
+ ///
+ public void OnCreateMonitor(string monitorType)
{
monitorType = GetShortName(monitorType);
var log = $"{monitorType} was created.";
@@ -455,11 +442,13 @@ public override void OnCreateMonitor(string monitorType)
Writer.AddToLogs(updateVcMap: true);
}
- public override void OnMonitorExecuteAction(string monitorType, string stateName, string actionName)
+ ///
+ public void OnMonitorExecuteAction(string monitorType, string stateName, string actionName)
{
}
- public override void OnMonitorProcessEvent(string monitorType, string stateName, string senderName,
+ ///
+ public void OnMonitorProcessEvent(string monitorType, string stateName, string senderName,
string senderType, string senderStateName, Event e)
{
monitorType = GetShortName(monitorType);
@@ -475,7 +464,8 @@ public override void OnMonitorProcessEvent(string monitorType, string stateName,
Writer.AddToLogs(updateVcMap: true);
}
- public override void OnMonitorRaiseEvent(string monitorType, string stateName, Event e)
+ ///
+ public void OnMonitorRaiseEvent(string monitorType, string stateName, Event e)
{
stateName = GetShortName(stateName);
monitorType = GetShortName(monitorType);
@@ -491,7 +481,8 @@ public override void OnMonitorRaiseEvent(string monitorType, string stateName, E
Writer.AddToLogs(updateVcMap: true);
}
- public override void OnMonitorStateTransition(string monitorType, string stateName, bool isEntry, bool? isInHotState)
+ ///
+ public void OnMonitorStateTransition(string monitorType, string stateName, bool isEntry, bool? isInHotState)
{
monitorType = GetShortName(monitorType);
@@ -514,15 +505,18 @@ public override void OnMonitorStateTransition(string monitorType, string stateNa
Writer.AddToLogs(updateVcMap: true);
}
- public override void OnMonitorError(string monitorType, string stateName, bool? isInHotState)
+ ///
+ public void OnMonitorError(string monitorType, string stateName, bool? isInHotState)
{
}
-
- public override void OnRandom(object result, string callerName, string callerType)
+
+ ///
+ public void OnRandom(object result, string callerName, string callerType)
{
}
- public override void OnStrategyDescription(string strategyName, string description)
+ ///
+ public void OnStrategyDescription(string strategyName, string description)
{
var desc = string.IsNullOrEmpty(description) ? $" Description: {description}" : string.Empty;
var log = $"Found bug using '{strategyName}' strategy.{desc}";
diff --git a/Src/PChecker/CheckerCore/Actors/Logging/ActorRuntimeLogTextFormatter.cs b/Src/PChecker/CheckerCore/Runtime/Logging/PCheckerLogTextFormatter.cs
similarity index 53%
rename from Src/PChecker/CheckerCore/Actors/Logging/ActorRuntimeLogTextFormatter.cs
rename to Src/PChecker/CheckerCore/Runtime/Logging/PCheckerLogTextFormatter.cs
index 1fd02e2ac3..cee2413c94 100644
--- a/Src/PChecker/CheckerCore/Actors/Logging/ActorRuntimeLogTextFormatter.cs
+++ b/Src/PChecker/CheckerCore/Runtime/Logging/PCheckerLogTextFormatter.cs
@@ -3,16 +3,19 @@
using System;
using System.IO;
+using System.Linq;
using System.Threading.Tasks;
-using PChecker.Actors.Events;
using PChecker.IO.Logging;
+using PChecker.Runtime.Events;
+using PChecker.Runtime.Exceptions;
+using PChecker.Runtime.StateMachines;
-namespace PChecker.Actors.Logging
+namespace PChecker.Runtime.Logging
{
///
- /// This class implements IActorRuntimeLog and generates output in a a human readable text format.
+ /// Formatter for the runtime log.
///
- public class ActorRuntimeLogTextFormatter : IActorRuntimeLog
+ public class PCheckerLogTextFormatter : IControlledRuntimeLog
{
///
/// Get or set the TextWriter to write to.
@@ -20,52 +23,62 @@ public class ActorRuntimeLogTextFormatter : IActorRuntimeLog
public TextWriter Logger { get; set; }
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
- public ActorRuntimeLogTextFormatter()
+ public PCheckerLogTextFormatter()
{
Logger = new ConsoleLogger();
}
+ private string GetShortName(string name)
+ {
+ return name.Split('.').Last();
+ }
+
+ private string GetEventNameWithPayload(Event e)
+ {
+ if (e.GetType().Name.Contains("GotoStateEvent"))
+ {
+ return e.GetType().Name;
+ }
+ var pe = (Event)(e);
+ var payload = pe.Payload == null ? "null" : pe.Payload.ToEscapedString();
+ var msg = pe.Payload == null ? "" : $" with payload ({payload})";
+ return $"{GetShortName(e.GetType().Name)}{msg}";
+ }
+
///
- public virtual void OnAssertionFailure(string error)
+ public void OnAssertionFailure(string error)
{
Logger.WriteLine(error);
}
///
- public virtual void OnCreateActor(ActorId id, string creatorName, string creatorType)
+ public void OnCreateStateMachine(StateMachineId id, string creatorName, string creatorType)
{
- if (id.Name.Contains("GodMachine") || creatorName.Contains("GodMachine"))
- {
- return;
- }
var source = creatorName ?? $"task '{Task.CurrentId}'";
var text = $" {id} was created by {source}.";
Logger.WriteLine(text);
}
-
+
///
- public void OnCreateStateMachine(ActorId id, string creatorName, string creatorType)
+ public void OnStateTransition(StateMachineId id, string stateName, bool isEntry)
{
- if (id.Name.Contains("GodMachine") || creatorName.Contains("GodMachine"))
- {
- return;
- }
- var source = creatorName ?? $"task '{Task.CurrentId}'";
- var text = $" {id} was created by {source}.";
+ var direction = isEntry ? "enters" : "exits";
+ var text = $" {id} {direction} state '{stateName}'.";
Logger.WriteLine(text);
}
///
- public virtual void OnCreateMonitor(string monitorType)
+ public void OnPopStateUnhandledEvent(StateMachineId id, string stateName, Event e)
{
- var text = $" {monitorType} was created.";
+ var eventName = e.GetType().Name;
+ var text = $" {id} popped state {stateName} due to unhandled event '{eventName}'.";
Logger.WriteLine(text);
}
///
- public virtual void OnDefaultEventHandler(ActorId id, string stateName)
+ public void OnDefaultEventHandler(StateMachineId id, string stateName)
{
string text;
if (stateName is null)
@@ -81,296 +94,270 @@ public virtual void OnDefaultEventHandler(ActorId id, string stateName)
}
///
- public virtual void OnDequeueEvent(ActorId id, string stateName, Event e)
+ public void OnWaitEvent(StateMachineId id, string stateName, params Type[] eventTypes)
{
- var eventName = e.GetType().FullName;
string text;
- if (stateName is null)
+ string eventNames;
+ if (eventTypes.Length == 0)
{
- text = $" {id} dequeued event '{eventName}'.";
+ eventNames = "''";
}
- else
+ else if (eventTypes.Length == 1)
{
- text = $" {id} dequeued event '{eventName}' in state '{stateName}'.";
+ eventNames = "'" + eventTypes[0].Name + "'";
}
+ else if (eventTypes.Length == 2)
+ {
+ eventNames = "'" + eventTypes[0].Name + "' or '" + eventTypes[1].Name + "'";
+ }
+ else if (eventTypes.Length == 3)
+ {
+ eventNames = "'" + eventTypes[0].Name + "', '" + eventTypes[1].Name + "' or '" + eventTypes[2].Name + "'";
+ }
+ else
+ {
+ var eventNameArray = new string[eventTypes.Length - 1];
+ for (var i = 0; i < eventTypes.Length - 2; i++)
+ {
+ eventNameArray[i] = eventTypes[i].Name;
+ }
- Logger.WriteLine(text);
- }
-
- ///
- public virtual void OnEnqueueEvent(ActorId id, Event e)
- {
- var eventName = e.GetType().FullName;
- var text = $" {id} enqueued event '{eventName}'.";
- Logger.WriteLine(text);
- }
+ eventNames = "'" + string.Join("', '", eventNameArray) + "' or '" + eventTypes[eventTypes.Length - 1].Name + "'";
+ }
- ///
- public virtual void OnExceptionHandled(ActorId id, string stateName, string actionName, Exception ex)
- {
- string text;
if (stateName is null)
{
- text = $" {id} running action '{actionName}' chose to handle exception '{ex.GetType().Name}'.";
+ text = $" {id} is waiting to dequeue an event of type {eventNames}.";
}
else
{
- text = $" {id} running action '{actionName}' in state '{stateName}' chose to handle exception '{ex.GetType().Name}'.";
+ text = $" {id} is waiting to dequeue an event of type {eventNames} in state '{stateName}'.";
}
Logger.WriteLine(text);
}
///
- public virtual void OnExceptionThrown(ActorId id, string stateName, string actionName, Exception ex)
+ public void OnWaitEvent(StateMachineId id, string stateName, Type eventType)
{
string text;
if (stateName is null)
{
- text = $" {id} running action '{actionName}' threw exception '{ex.GetType().Name}'.";
+ text = $" {id} is waiting to dequeue an event of type '{eventType.FullName}'.";
}
else
{
- text = $" {id} running action '{actionName}' in state '{stateName}' threw exception '{ex.GetType().Name}'.";
+ text = $" {id} is waiting to dequeue an event of type '{eventType.FullName}' in state '{stateName}'.";
}
-
+
Logger.WriteLine(text);
}
///
- public virtual void OnExecuteAction(ActorId id, string handlingStateName, string currentStateName, string actionName)
+ public void OnMonitorStateTransition(string monitorType, string stateName, bool isEntry, bool? isInHotState)
{
- string text;
- if (currentStateName is null)
- {
- text = $" {id} invoked action '{actionName}'.";
- }
- else if (handlingStateName != currentStateName)
- {
- text = $" {id} invoked action '{actionName}' in state '{currentStateName}' where action was declared by state '{handlingStateName}'.";
- }
- else
+ if (stateName.Contains("__InitState__"))
{
- text = $" {id} invoked action '{actionName}' in state '{currentStateName}'.";
+ return;
}
+ var liveness = isInHotState.HasValue ? (isInHotState.Value ? "hot " : "cold ") : string.Empty;
+ var direction = isEntry ? "enters" : "exits";
+ var text = $" {monitorType} {direction} {liveness}state '{stateName}'.";
Logger.WriteLine(text);
}
-
+
///
- public virtual void OnGotoState(ActorId id, string currentStateName, string newStateName)
+ public void OnMonitorProcessEvent(string monitorType, string stateName, string senderName, string senderType,
+ string senderStateName, Event e)
{
- var text = $" {id} is transitioning from state '{currentStateName}' to state '{newStateName}'.";
+ var text = $" {GetShortName(monitorType)} is processing event '{GetEventNameWithPayload(e)}' in state '{stateName}'.";
Logger.WriteLine(text);
}
///
- public virtual void OnHalt(ActorId id, int inboxSize)
+ public void OnDequeueEvent(StateMachineId id, string stateName, Event e)
{
- var text = $" {id} halted with {inboxSize} events in its inbox.";
+ stateName = GetShortName(stateName);
+ var eventName = GetEventNameWithPayload(e);
+ string text = null;
+ if (stateName is null)
+ {
+ text = $" '{id}' dequeued event '{eventName}'.";
+ }
+ else
+ {
+ text = $" '{id}' dequeued event '{eventName}' in state '{stateName}'.";
+ }
+
Logger.WriteLine(text);
}
///
- public virtual void OnHandleRaisedEvent(ActorId id, string stateName, Event e)
+ public void OnRaiseEvent(StateMachineId id, string stateName, Event e)
{
- }
+ stateName = GetShortName(stateName);
+ var eventName = GetEventNameWithPayload(e);
+ if (eventName.Contains("GotoStateEvent"))
+ {
+ return;
+ }
+
+ string text = null;
+ if (stateName is null)
+ {
+ text = $" '{id}' raised event '{eventName}'.";
+ }
+ else
+ {
+ text = $" '{id}' raised event '{eventName}' in state '{stateName}'.";
+ }
- ///
- public virtual void OnMonitorExecuteAction(string monitorType, string stateName, string actionName)
- {
- var text = $" {monitorType} executed action '{actionName}' in state '{stateName}'.";
Logger.WriteLine(text);
}
///
- public virtual void OnMonitorProcessEvent(string monitorType, string stateName, string senderName,
- string senderType, string senderStateName, Event e)
- {
- var text = $" {monitorType} is processing event '{e.GetType().Name}' in state '{stateName}'.";
- Logger.WriteLine(text);
- }
+ public void OnEnqueueEvent(StateMachineId id, Event e) { }
///
- public virtual void OnMonitorRaiseEvent(string monitorType, string stateName, Event e)
+ public void OnReceiveEvent(StateMachineId id, string stateName, Event e, bool wasBlocked)
{
- var eventName = e.GetType().FullName;
- var text = $" {monitorType} raised event '{eventName}' in state '{stateName}'.";
+ stateName = GetShortName(stateName);
+ var eventName = GetEventNameWithPayload(e);
+ string text = null;
+ var unblocked = wasBlocked ? " and unblocked" : string.Empty;
+ if (stateName is null)
+ {
+ text = $" '{id}' dequeued event '{eventName}'{unblocked}.";
+ }
+ else
+ {
+ text = $" '{id}' dequeued event '{eventName}'{unblocked} in state '{stateName}'.";
+ }
+
Logger.WriteLine(text);
}
///
- public virtual void OnMonitorStateTransition(string monitorType, string stateName, bool isEntry, bool? isInHotState)
+ public void OnMonitorRaiseEvent(string monitorType, string stateName, Event e)
{
- var liveness = isInHotState.HasValue ? (isInHotState.Value ? "hot " : "cold ") : string.Empty;
- var direction = isEntry ? "enters" : "exits";
- var text = $" {monitorType} {direction} {liveness}state '{stateName}'.";
+ stateName = GetShortName(stateName);
+ var eventName = GetEventNameWithPayload(e);
+ var text = $" Monitor '{GetShortName(monitorType)}' raised event '{eventName}' in state '{stateName}'.";
Logger.WriteLine(text);
}
///
- public virtual void OnMonitorError(string monitorType, string stateName, bool? isInHotState)
+ public void OnSendEvent(StateMachineId targetStateMachineId, string senderName, string senderType, string senderStateName, Event e, bool isTargetHalted)
{
+ senderStateName = GetShortName(senderStateName);
+ var eventName = GetEventNameWithPayload(e);
+ var isHalted = isTargetHalted ? $" which has halted" : string.Empty;
+ var sender = !string.IsNullOrEmpty(senderName) ? $"'{senderName}' in state '{senderStateName}'" : $"The runtime";
+ var text = $" {sender} sent event '{eventName}' to '{targetStateMachineId}'{isHalted}.";
+ Logger.WriteLine(text);
}
///
- public virtual void OnPopState(ActorId id, string currentStateName, string restoredStateName)
+ public void OnGotoState(StateMachineId id, string currStateName, string newStateName)
{
- currentStateName = string.IsNullOrEmpty(currentStateName) ? "[not recorded]" : currentStateName;
- var reenteredStateName = restoredStateName ?? string.Empty;
- var text = $" {id} popped state '{currentStateName}' and reentered state '{reenteredStateName}'.";
+ var text = $" {id} is transitioning from state '{currStateName}' to state '{newStateName}'.";
Logger.WriteLine(text);
}
///
- public virtual void OnPopStateUnhandledEvent(ActorId id, string stateName, Event e)
+ public void OnExecuteAction(StateMachineId id, string handlingStateName, string currentStateName, string actionName)
{
- var eventName = e.GetType().FullName;
- var text = $" {id} popped state {stateName} due to unhandled event '{eventName}'.";
- Logger.WriteLine(text);
}
///
- public virtual void OnPushState(ActorId id, string currentStateName, string newStateName)
+ public void OnMonitorExecuteAction(string monitorType, string stateName, string actionName)
{
- var text = $" {id} pushed from state '{currentStateName}' to state '{newStateName}'.";
- Logger.WriteLine(text);
}
///
- public virtual void OnRaiseEvent(ActorId id, string stateName, Event e)
+ public void OnExceptionHandled(StateMachineId id, string stateName, string actionName, Exception ex)
{
- var eventName = e.GetType().FullName;
+ if (ex is PNonStandardReturnException)
+ {
+ return;
+ }
string text;
if (stateName is null)
{
- text = $" {id} raised event '{eventName}'.";
+ text = $" {id} running action '{actionName}' chose to handle exception '{ex.GetType().Name}'.";
}
else
{
- text = $" {id} raised event '{eventName}' in state '{stateName}'.";
+ text = $" {id} running action '{actionName}' in state '{stateName}' chose to handle exception '{ex.GetType().Name}'.";
}
Logger.WriteLine(text);
}
///
- public virtual void OnReceiveEvent(ActorId id, string stateName, Event e, bool wasBlocked)
+ public void OnExceptionThrown(StateMachineId id, string stateName, string actionName, Exception ex)
{
- var eventName = e.GetType().FullName;
+ if (ex is PNonStandardReturnException)
+ {
+ return;
+ }
string text;
- var unblocked = wasBlocked ? " and unblocked" : string.Empty;
if (stateName is null)
{
- text = $" {id} dequeued event '{eventName}'{unblocked}.";
+ text = $" {id} running action '{actionName}' threw exception '{ex.GetType().Name}'.";
}
else
{
- text = $" {id} dequeued event '{eventName}'{unblocked} in state '{stateName}'.";
+ text = $" {id} running action '{actionName}' in state '{stateName}' threw exception '{ex.GetType().Name}'.";
}
Logger.WriteLine(text);
}
///
- public virtual void OnSendEvent(ActorId targetActorId, string senderName, string senderType, string senderStateName,
- Event e, Guid opGroupId, bool isTargetHalted)
+ public void OnCreateMonitor(string monitorType)
{
- var opGroupIdMsg = opGroupId != Guid.Empty ? $" (operation group '{opGroupId}')" : string.Empty;
- var isHalted = isTargetHalted ? $" which has halted" : string.Empty;
- var sender = senderName != null ? $"{senderName} in state '{senderStateName}'" : $"task '{Task.CurrentId}'";
- var eventName = e.GetType().FullName;
- var text = $" {sender} sent event '{eventName}' to {targetActorId}{isHalted}{opGroupIdMsg}.";
+ var text = $" {monitorType} was created.";
Logger.WriteLine(text);
}
///
- public virtual void OnStateTransition(ActorId id, string stateName, bool isEntry)
+ public void OnHandleRaisedEvent(StateMachineId id, string stateName, Event e)
{
- var direction = isEntry ? "enters" : "exits";
- var text = $" {id} {direction} state '{stateName}'.";
- Logger.WriteLine(text);
}
///
- public virtual void OnStrategyDescription(string strategyName, string description)
+ public void OnRandom(object result, string callerName, string callerType)
{
- var desc = string.IsNullOrEmpty(description) ? $" Description: {description}" : string.Empty;
- var text = $" Found bug using '{strategyName}' strategy.{desc}";
+ var source = callerName ?? $"Task '{Task.CurrentId}'";
+ var text = $" {source} nondeterministically chose '{result}'.";
Logger.WriteLine(text);
}
-
+
///
- public virtual void OnWaitEvent(ActorId id, string stateName, Type eventType)
+ public void OnHalt(StateMachineId id, int inboxSize)
{
- string text;
- if (stateName is null)
- {
- text = $" {id} is waiting to dequeue an event of type '{eventType.FullName}'.";
- }
- else
- {
- text = $" {id} is waiting to dequeue an event of type '{eventType.FullName}' in state '{stateName}'.";
- }
-
+ var text = $" {id} halted with {inboxSize} events in its inbox.";
Logger.WriteLine(text);
}
-
+
///
- public virtual void OnWaitEvent(ActorId id, string stateName, params Type[] eventTypes)
+ public void OnMonitorError(string monitorType, string stateName, bool? isInHotState)
{
- string text;
- string eventNames;
- if (eventTypes.Length == 0)
- {
- eventNames = "''";
- }
- else if (eventTypes.Length == 1)
- {
- eventNames = "'" + eventTypes[0].Name + "'";
- }
- else if (eventTypes.Length == 2)
- {
- eventNames = "'" + eventTypes[0].Name + "' or '" + eventTypes[1].Name + "'";
- }
- else if (eventTypes.Length == 3)
- {
- eventNames = "'" + eventTypes[0].Name + "', '" + eventTypes[1].Name + "' or '" + eventTypes[2].Name + "'";
- }
- else
- {
- var eventNameArray = new string[eventTypes.Length - 1];
- for (var i = 0; i < eventTypes.Length - 2; i++)
- {
- eventNameArray[i] = eventTypes[i].Name;
- }
-
- eventNames = "'" + string.Join("', '", eventNameArray) + "' or '" + eventTypes[eventTypes.Length - 1].Name + "'";
- }
-
- if (stateName is null)
- {
- text = $" {id} is waiting to dequeue an event of type {eventNames}.";
- }
- else
- {
- text = $" {id} is waiting to dequeue an event of type {eventNames} in state '{stateName}'.";
- }
-
- Logger.WriteLine(text);
}
///
- public virtual void OnRandom(object result, string callerName, string callerType)
+ public void OnCompleted()
{
- var source = callerName ?? $"Task '{Task.CurrentId}'";
- var text = $" {source} nondeterministically chose '{result}'.";
- Logger.WriteLine(text);
}
-
+
///
- public virtual void OnCompleted()
+ public void OnStrategyDescription(string strategyName, string description)
{
+ var desc = string.IsNullOrEmpty(description) ? $" Description: {description}" : string.Empty;
+ var text = $" Found bug using '{strategyName}' strategy.{desc}";
+ Logger.WriteLine(text);
}
}
}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/Actors/Logging/ActorRuntimeLogXmlFormatter.cs b/Src/PChecker/CheckerCore/Runtime/Logging/PCheckerLogXmlFormatter.cs
similarity index 82%
rename from Src/PChecker/CheckerCore/Actors/Logging/ActorRuntimeLogXmlFormatter.cs
rename to Src/PChecker/CheckerCore/Runtime/Logging/PCheckerLogXmlFormatter.cs
index ebc7fb18d1..c8cc3dad2f 100644
--- a/Src/PChecker/CheckerCore/Actors/Logging/ActorRuntimeLogXmlFormatter.cs
+++ b/Src/PChecker/CheckerCore/Runtime/Logging/PCheckerLogXmlFormatter.cs
@@ -5,19 +5,20 @@
using System.Text;
using System.Threading.Tasks;
using System.Xml;
-using PChecker.Actors.Events;
+using PChecker.Runtime.Events;
+using PChecker.Runtime.StateMachines;
-namespace PChecker.Actors.Logging
+namespace PChecker.Runtime.Logging
{
///
- /// This class implements IActorRuntimeLog and generates log output in an XML format.
+ /// This class implements IControlledRuntimeLog and generates log output in an XML format.
///
- internal class ActorRuntimeLogXmlFormatter : IActorRuntimeLog
+ internal class PCheckerLogXmlFormatter : IControlledRuntimeLog
{
private readonly XmlWriter Writer;
private bool Closed;
- public ActorRuntimeLogXmlFormatter(XmlWriter writer)
+ public PCheckerLogXmlFormatter(XmlWriter writer)
{
Writer = writer;
Writer.WriteStartElement("Log");
@@ -44,33 +45,9 @@ public void OnAssertionFailure(string error)
Writer.WriteElementString("AssertionFailure", error);
}
-
- public void OnCreateActor(ActorId id, string creatorName, string creatorType)
- {
- if (Closed)
- {
- return;
- }
-
- Writer.WriteStartElement("CreateActor");
- Writer.WriteAttributeString("id", id.ToString());
-
- if (creatorName != null && creatorType != null)
- {
- Writer.WriteAttributeString("creatorName", creatorName);
- Writer.WriteAttributeString("creatorType", creatorType);
- }
- else
- {
- Writer.WriteAttributeString("creatorName", Task.CurrentId.ToString());
- Writer.WriteAttributeString("creatorType", "task");
- }
-
- Writer.WriteEndElement();
- }
-
+
///
- public void OnCreateStateMachine(ActorId id, string creatorName, string creatorType)
+ public void OnCreateStateMachine(StateMachineId id, string creatorName, string creatorType)
{
if (Closed)
{
@@ -94,7 +71,7 @@ public void OnCreateStateMachine(ActorId id, string creatorName, string creatorT
Writer.WriteEndElement();
}
- public void OnDefaultEventHandler(ActorId id, string stateName)
+ public void OnDefaultEventHandler(StateMachineId id, string stateName)
{
if (Closed)
{
@@ -111,7 +88,7 @@ public void OnDefaultEventHandler(ActorId id, string stateName)
Writer.WriteEndElement();
}
- public void OnDequeueEvent(ActorId id, string stateName, Event e)
+ public void OnDequeueEvent(StateMachineId id, string stateName, Event e)
{
if (Closed)
{
@@ -129,7 +106,7 @@ public void OnDequeueEvent(ActorId id, string stateName, Event e)
Writer.WriteEndElement();
}
- public void OnEnqueueEvent(ActorId id, Event e)
+ public void OnEnqueueEvent(StateMachineId id, Event e)
{
if (Closed)
{
@@ -142,7 +119,7 @@ public void OnEnqueueEvent(ActorId id, Event e)
Writer.WriteEndElement();
}
- public void OnExceptionHandled(ActorId id, string stateName, string actionName, Exception ex)
+ public void OnExceptionHandled(StateMachineId id, string stateName, string actionName, Exception ex)
{
if (Closed)
{
@@ -162,7 +139,7 @@ public void OnExceptionHandled(ActorId id, string stateName, string actionName,
Writer.WriteEndElement();
}
- public void OnExceptionThrown(ActorId id, string stateName, string actionName, Exception ex)
+ public void OnExceptionThrown(StateMachineId id, string stateName, string actionName, Exception ex)
{
if (Closed)
{
@@ -178,7 +155,7 @@ public void OnExceptionThrown(ActorId id, string stateName, string actionName, E
Writer.WriteEndElement();
}
- public void OnExecuteAction(ActorId id, string handlingStateName, string currentStateName, string actionName)
+ public void OnExecuteAction(StateMachineId id, string handlingStateName, string currentStateName, string actionName)
{
if (Closed)
{
@@ -200,7 +177,7 @@ public void OnExecuteAction(ActorId id, string handlingStateName, string current
Writer.WriteEndElement();
}
- public void OnGotoState(ActorId id, string currentStateName, string newStateName)
+ public void OnGotoState(StateMachineId id, string currentStateName, string newStateName)
{
if (Closed)
{
@@ -214,7 +191,7 @@ public void OnGotoState(ActorId id, string currentStateName, string newStateName
Writer.WriteEndElement();
}
- public void OnHalt(ActorId id, int inboxSize)
+ public void OnHalt(StateMachineId id, int inboxSize)
{
if (Closed)
{
@@ -227,7 +204,7 @@ public void OnHalt(ActorId id, int inboxSize)
Writer.WriteEndElement();
}
- public void OnHandleRaisedEvent(ActorId id, string stateName, Event e)
+ public void OnHandleRaisedEvent(StateMachineId id, string stateName, Event e)
{
if (Closed)
{
@@ -235,7 +212,7 @@ public void OnHandleRaisedEvent(ActorId id, string stateName, Event e)
}
}
- public void OnPopState(ActorId id, string currentStateName, string restoredStateName)
+ public void OnPopState(StateMachineId id, string currentStateName, string restoredStateName)
{
if (Closed)
{
@@ -249,7 +226,7 @@ public void OnPopState(ActorId id, string currentStateName, string restoredState
Writer.WriteEndElement();
}
- public void OnPopStateUnhandledEvent(ActorId id, string stateName, Event e)
+ public void OnPopStateUnhandledEvent(StateMachineId id, string stateName, Event e)
{
if (Closed)
{
@@ -263,7 +240,7 @@ public void OnPopStateUnhandledEvent(ActorId id, string stateName, Event e)
Writer.WriteEndElement();
}
- public void OnPushState(ActorId id, string currentStateName, string newStateName)
+ public void OnPushState(StateMachineId id, string currentStateName, string newStateName)
{
if (Closed)
{
@@ -277,7 +254,7 @@ public void OnPushState(ActorId id, string currentStateName, string newStateName
Writer.WriteEndElement();
}
- public void OnRaiseEvent(ActorId id, string stateName, Event e)
+ public void OnRaiseEvent(StateMachineId id, string stateName, Event e)
{
if (Closed)
{
@@ -295,7 +272,7 @@ public void OnRaiseEvent(ActorId id, string stateName, Event e)
Writer.WriteEndElement();
}
- public void OnReceiveEvent(ActorId id, string stateName, Event e, bool wasBlocked)
+ public void OnReceiveEvent(StateMachineId id, string stateName, Event e, bool wasBlocked)
{
if (Closed)
{
@@ -315,8 +292,8 @@ public void OnReceiveEvent(ActorId id, string stateName, Event e, bool wasBlocke
Writer.WriteEndElement();
}
- public void OnSendEvent(ActorId targetActorId, string senderName, string senderType, string senderStateName,
- Event e, Guid opGroupId, bool isTargetHalted)
+ public void OnSendEvent(StateMachineId targetStateMachineId, string senderName, string senderType, string senderStateName,
+ Event e, bool isTargetHalted)
{
if (Closed)
{
@@ -324,7 +301,7 @@ public void OnSendEvent(ActorId targetActorId, string senderName, string senderT
}
Writer.WriteStartElement("Send");
- Writer.WriteAttributeString("target", targetActorId.ToString());
+ Writer.WriteAttributeString("target", targetStateMachineId.ToString());
if (senderName != null && senderType != null)
{
@@ -336,16 +313,12 @@ public void OnSendEvent(ActorId targetActorId, string senderName, string senderT
Writer.WriteAttributeString("senderState", senderStateName);
Writer.WriteAttributeString("event", e.GetType().FullName);
- if (opGroupId != Guid.Empty)
- {
- Writer.WriteAttributeString("event", opGroupId.ToString());
- }
Writer.WriteAttributeString("isTargetHalted", isTargetHalted.ToString());
Writer.WriteEndElement();
}
- public void OnStateTransition(ActorId id, string stateName, bool isEntry)
+ public void OnStateTransition(StateMachineId id, string stateName, bool isEntry)
{
if (Closed)
{
@@ -359,7 +332,7 @@ public void OnStateTransition(ActorId id, string stateName, bool isEntry)
Writer.WriteEndElement();
}
- public void OnWaitEvent(ActorId id, string stateName, Type eventType)
+ public void OnWaitEvent(StateMachineId id, string stateName, Type eventType)
{
if (Closed)
{
@@ -377,7 +350,7 @@ public void OnWaitEvent(ActorId id, string stateName, Type eventType)
Writer.WriteEndElement();
}
- public void OnWaitEvent(ActorId id, string stateName, params Type[] eventTypes)
+ public void OnWaitEvent(StateMachineId id, string stateName, params Type[] eventTypes)
{
if (Closed)
{
diff --git a/Src/PChecker/CheckerCore/PRuntime/PInterfaces.cs b/Src/PChecker/CheckerCore/Runtime/PInterfaces.cs
similarity index 91%
rename from Src/PChecker/CheckerCore/PRuntime/PInterfaces.cs
rename to Src/PChecker/CheckerCore/Runtime/PInterfaces.cs
index de3c2d878c..67ff44f964 100644
--- a/Src/PChecker/CheckerCore/PRuntime/PInterfaces.cs
+++ b/Src/PChecker/CheckerCore/Runtime/PInterfaces.cs
@@ -1,9 +1,9 @@
using System.Collections.Generic;
using System.Linq;
-using PChecker.PRuntime.Exceptions;
-using PChecker.PRuntime.Values;
+using PChecker.Runtime.Exceptions;
+using PChecker.Runtime.Values;
-namespace PChecker.PRuntime
+namespace PChecker.Runtime
{
public class PInterfaces
{
diff --git a/Src/PChecker/CheckerCore/PRuntime/PModule.cs b/Src/PChecker/CheckerCore/Runtime/PModule.cs
similarity index 83%
rename from Src/PChecker/CheckerCore/PRuntime/PModule.cs
rename to Src/PChecker/CheckerCore/Runtime/PModule.cs
index 16cc35ceeb..623e96c661 100644
--- a/Src/PChecker/CheckerCore/PRuntime/PModule.cs
+++ b/Src/PChecker/CheckerCore/Runtime/PModule.cs
@@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
-using PChecker.Actors;
+using PChecker.SystematicTesting;
-namespace PChecker.PRuntime
+namespace PChecker.Runtime
{
public class PModule
{
@@ -13,6 +13,6 @@ public class PModule
public static IDictionary> linkMap =
new Dictionary>();
- public static IActorRuntime runtime;
+ public static ControlledRuntime runtime;
}
}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/PRuntime/PrtTypes.cs b/Src/PChecker/CheckerCore/Runtime/PTypes.cs
similarity index 72%
rename from Src/PChecker/CheckerCore/PRuntime/PrtTypes.cs
rename to Src/PChecker/CheckerCore/Runtime/PTypes.cs
index 681640a4fd..e8e103d17b 100644
--- a/Src/PChecker/CheckerCore/PRuntime/PrtTypes.cs
+++ b/Src/PChecker/CheckerCore/Runtime/PTypes.cs
@@ -3,9 +3,9 @@
using System.Diagnostics;
using System.Linq;
-namespace PChecker.PRuntime
+namespace PChecker.Runtime
{
- public abstract class PrtType
+ public abstract class PType
{
public override string ToString()
{
@@ -13,7 +13,7 @@ public override string ToString()
}
}
- public class PrtNullType : PrtType
+ public class PNullType : PType
{
public override string ToString()
{
@@ -21,7 +21,7 @@ public override string ToString()
}
}
- public class PrtAnyType : PrtType
+ public class PAnyType : PType
{
public override string ToString()
{
@@ -29,7 +29,7 @@ public override string ToString()
}
}
- public class PrtMachineType : PrtType
+ public class PMachineType : PType
{
public override string ToString()
{
@@ -37,7 +37,7 @@ public override string ToString()
}
}
- public class PrtIntType : PrtType
+ public class PIntType : PType
{
public override string ToString()
{
@@ -45,7 +45,7 @@ public override string ToString()
}
}
- public class PrtFloatType : PrtType
+ public class PFloatType : PType
{
public override string ToString()
{
@@ -53,12 +53,12 @@ public override string ToString()
}
}
- public class PrtEnumType : PrtType
+ public class PEnumType : PType
{
public Dictionary enumConstants;
public string name;
- public PrtEnumType(string typeName, params object[] args)
+ public PEnumType(string typeName, params object[] args)
{
name = typeName;
enumConstants = new Dictionary();
@@ -81,12 +81,12 @@ public override string ToString()
}
}
- public class PrtPermissionType : PrtType
+ public class PPermissionType : PType
{
public string name;
public List permissions;
- public PrtPermissionType(string name, IEnumerable perm)
+ public PPermissionType(string name, IEnumerable perm)
{
this.name = name;
permissions = perm.ToList();
@@ -98,7 +98,7 @@ public override string ToString()
}
}
- public class PrtBoolType : PrtType
+ public class PBoolType : PType
{
public override string ToString()
{
@@ -106,7 +106,7 @@ public override string ToString()
}
}
- public class PrtStringType : PrtType
+ public class PStringType : PType
{
public override string ToString()
{
@@ -114,7 +114,7 @@ public override string ToString()
}
}
- public class PrtEventType : PrtType
+ public class PEventType : PType
{
public override string ToString()
{
@@ -122,12 +122,12 @@ public override string ToString()
}
}
- public class PrtMapType : PrtType
+ public class PMapType : PType
{
- public PrtType keyType;
- public PrtType valType;
+ public PType keyType;
+ public PType valType;
- public PrtMapType(PrtType k, PrtType v)
+ public PMapType(PType k, PType v)
{
keyType = k;
valType = v;
@@ -139,11 +139,11 @@ public override string ToString()
}
}
- public class PrtSeqType : PrtType
+ public class PSeqType : PType
{
- public PrtType elemType;
+ public PType elemType;
- public PrtSeqType(PrtType s)
+ public PSeqType(PType s)
{
elemType = s;
}
@@ -154,11 +154,11 @@ public override string ToString()
}
}
- public class PrtSetType : PrtType
+ public class PSetType : PType
{
- public PrtType elemType;
+ public PType elemType;
- public PrtSetType(PrtType s)
+ public PSetType(PType s)
{
elemType = s;
}
@@ -169,22 +169,22 @@ public override string ToString()
}
}
- public class PrtTupleType : PrtType
+ public class PTupleType : PType
{
- public List fieldTypes;
+ public List fieldTypes;
- public PrtTupleType()
+ public PTupleType()
{
/*
This constructor is added only to prevent the other constructor from being called
- when an instance of PrtNamedTupleType is created.
+ when an instance of PNamedTupleType is created.
*/
}
- public PrtTupleType(params PrtType[] fields)
+ public PTupleType(params PType[] fields)
{
Debug.Assert(fields.Any());
- fieldTypes = new List();
+ fieldTypes = new List();
foreach (var f in fields)
{
fieldTypes.Add(f);
@@ -204,22 +204,22 @@ public override string ToString()
}
}
- public class PrtNamedTupleType : PrtTupleType
+ public class PNamedTupleType : PTupleType
{
public List fieldNames;
- public PrtNamedTupleType(params object[] args)
+ public PNamedTupleType(params object[] args)
{
Debug.Assert(args.Length > 0);
fieldNames = new List();
- fieldTypes = new List();
+ fieldTypes = new List();
var index = 0;
while (index < args.Length)
{
fieldNames.Add((string)args[index]);
index++;
- fieldTypes.Add((PrtType)args[index]);
+ fieldTypes.Add((PType)args[index]);
index++;
}
}
diff --git a/Src/PChecker/CheckerCore/Runtime/RuntimeFactory.cs b/Src/PChecker/CheckerCore/Runtime/RuntimeFactory.cs
deleted file mode 100644
index 55091af174..0000000000
--- a/Src/PChecker/CheckerCore/Runtime/RuntimeFactory.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-using PChecker.Actors;
-using PChecker.Random;
-
-namespace PChecker.Runtime
-{
- ///
- /// Provides methods for creating a runtime.
- ///
- public static class RuntimeFactory
- {
- ///
- /// The installed runtime instance.
- ///
- internal static CoyoteRuntime InstalledRuntime { get; private set; } = CreateWithConfiguration(default);
-
- ///
- /// Protects access to the installed runtime.
- ///
- private static readonly object SyncObject = new object();
-
- ///
- /// Creates a new Coyote runtime.
- ///
- /// The created task runtime.
- ///
- /// Only one task runtime can be created per process. If you create a new task
- /// runtime it replaces the previously installed one.
- ///
- public static ICoyoteRuntime Create() => CreateAndInstall(default);
-
- ///
- /// Creates a new Coyote runtime with the specified .
- ///
- /// The runtime checkerConfiguration to use.
- /// The created task runtime.
- ///
- /// Only one task runtime can be created per process. If you create a new task
- /// runtime it replaces the previously installed one.
- ///
- public static ICoyoteRuntime Create(CheckerConfiguration checkerConfiguration) => CreateAndInstall(checkerConfiguration);
-
- ///
- /// Creates a new Coyote runtime with the specified and sets
- /// it as the installed runtime, or returns the installed runtime if it already exists.
- ///
- private static CoyoteRuntime CreateAndInstall(CheckerConfiguration checkerConfiguration)
- {
- lock (SyncObject)
- {
- // Assign the newly created runtime as the installed runtime.
- return InstalledRuntime = CreateWithConfiguration(checkerConfiguration);
- }
- }
-
- ///
- /// Creates a new Coyote runtime with the specified .
- ///
- private static CoyoteRuntime CreateWithConfiguration(CheckerConfiguration checkerConfiguration)
- {
- if (checkerConfiguration is null)
- {
- checkerConfiguration = CheckerConfiguration.Create();
- }
-
- var valueGenerator = new RandomValueGenerator(checkerConfiguration);
- return new ActorRuntime(checkerConfiguration, valueGenerator);
- }
- }
-}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/Specifications/CachedDelegate.cs b/Src/PChecker/CheckerCore/Runtime/Specifications/CachedDelegate.cs
similarity index 95%
rename from Src/PChecker/CheckerCore/Specifications/CachedDelegate.cs
rename to Src/PChecker/CheckerCore/Runtime/Specifications/CachedDelegate.cs
index e6fae4cda5..f1fa273c44 100644
--- a/Src/PChecker/CheckerCore/Specifications/CachedDelegate.cs
+++ b/Src/PChecker/CheckerCore/Runtime/Specifications/CachedDelegate.cs
@@ -3,9 +3,9 @@
using System;
using System.Reflection;
-using PChecker.Actors.Events;
+using PChecker.Runtime.Events;
-namespace PChecker.Specifications.Monitors
+namespace PChecker.Runtime.Specifications
{
///
/// A monitor delegate that has been cached to optimize performance of invocations.
diff --git a/Src/PChecker/CheckerCore/Specifications/Monitor.cs b/Src/PChecker/CheckerCore/Runtime/Specifications/Monitor.cs
similarity index 95%
rename from Src/PChecker/CheckerCore/Specifications/Monitor.cs
rename to Src/PChecker/CheckerCore/Runtime/Specifications/Monitor.cs
index acf62c8dc9..79e3a79456 100644
--- a/Src/PChecker/CheckerCore/Specifications/Monitor.cs
+++ b/Src/PChecker/CheckerCore/Runtime/Specifications/Monitor.cs
@@ -10,23 +10,20 @@
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
-using PChecker.Actors;
-using PChecker.Actors.Events;
-using PChecker.Actors.Handlers;
-using PChecker.Actors.Logging;
-using PChecker.Actors.StateTransitions;
using PChecker.Exceptions;
-
-namespace PChecker.Specifications.Monitors
+using PChecker.Runtime.Events;
+using PChecker.Runtime.Exceptions;
+using PChecker.Runtime.Logging;
+using PChecker.Runtime.StateMachines.Handlers;
+using PChecker.Runtime.StateMachines.StateTransitions;
+using PChecker.SystematicTesting;
+
+namespace PChecker.Runtime.Specifications
{
///
/// Abstract class representing a specification monitor.
///
- ///
- /// See Specifications Overview
- /// for more information.
- ///
- public abstract class Monitor
+ public class Monitor
{
///
/// Map from monitor types to a set of all possible states types.
@@ -48,7 +45,7 @@ public abstract class Monitor
///
/// A set of lockable objects used to protect static initialization of the ActionCache while
- /// also enabling multithreaded initialization of different Actor types.
+ /// also enabling multithreaded initialization of different StateMachine types.
///
private static readonly ConcurrentDictionary ActionCacheLocks =
new ConcurrentDictionary();
@@ -61,7 +58,7 @@ public abstract class Monitor
///
/// The runtime that executes this monitor.
///
- private ActorRuntime Runtime;
+ private ControlledRuntime Runtime;
///
/// The active monitor state.
@@ -90,6 +87,16 @@ public abstract class Monitor
/// liveness bug has been found.
///
private int LivenessTemperature;
+
+ ///
+ /// List containing all the event types that are observed by this monitor.
+ ///
+ public static List observes = new List();
+
+ ///
+ /// Temporarily holds data that might be needed during a state transition.
+ ///
+ public object gotoPayload;
///
/// Gets the name of this monitor.
@@ -99,9 +106,6 @@ public abstract class Monitor
///
/// The logger installed to the runtime.
///
- ///
- /// See Logging for more information.
- ///
protected TextWriter Logger => Runtime.Logger;
///
@@ -130,7 +134,7 @@ protected internal Type CurrentState
///
internal string CurrentStateName
{
- get => NameResolver.GetQualifiedStateName(CurrentState);
+ get => CurrentState.Name;
}
///
@@ -172,7 +176,7 @@ protected Monitor()
/// Initializes this monitor.
///
/// The runtime that executes this monitor.
- internal void Initialize(ActorRuntime runtime)
+ internal void Initialize(ControlledRuntime runtime)
{
Runtime = runtime;
}
@@ -182,17 +186,39 @@ internal void Initialize(ActorRuntime runtime)
///
///
/// This event is not handled until the action that calls this method returns control back
- /// to the Coyote runtime. It is handled before any other events are dequeued from the inbox.
+ /// to the ControlledRuntime. It is handled before any other events are dequeued from the inbox.
/// Only one of the following can be called per action:
/// , .
/// An Assert is raised if you accidentally try and do two of these operations in a single action.
///
/// The event to raise.
- protected void RaiseEvent(Event e)
+ public void RaiseEvent(Event e)
{
Assert(e != null, "{0} is raising a null event.", GetType().FullName);
CheckDanglingTransition();
PendingTransition = new Transition(Transition.Type.Raise, default, e);
+ throw new PNonStandardReturnException { ReturnKind = NonStandardReturn.Raise };
+ }
+
+ ///
+ /// Writes PrintLog messages to logger.
+ ///
+ public void LogLine(string message)
+ {
+ Logger.WriteLine($" {message}");
+
+ // Log message to JSON output
+ JsonLogger.AddLogType(JsonWriter.LogType.Print);
+ JsonLogger.AddLog(message);
+ JsonLogger.AddToLogs(updateVcMap: false);
+ }
+
+ ///
+ /// Writes message to logger.
+ ///
+ public void Log(string message)
+ {
+ Logger.Write($"{message}");
}
///
@@ -208,15 +234,18 @@ protected void RaiseEvent(Event e)
/// this.RaiseEvent(new E());
///
/// This event is not handled until the action that calls this method returns control back
- /// to the Coyote runtime. It is handled before any other events are dequeued from the inbox.
+ /// to the ControlledRuntime. It is handled before any other events are dequeued from the inbox.
/// Only one of the following can be called per action:
/// , .
/// An Assert is raised if you accidentally try and do two of these operations in a single action.
///
/// Type of the state.
- protected void RaiseGotoStateEvent()
- where S : State =>
+ public void RaiseGotoStateEvent(object payload = null) where S : State
+ {
+ gotoPayload = payload;
RaiseGotoStateEvent(typeof(S));
+ throw new PNonStandardReturnException { ReturnKind = NonStandardReturn.Goto };
+ }
///
/// Raise a special event that performs a goto state operation at the end of the current action.
@@ -231,13 +260,13 @@ protected void RaiseGotoStateEvent()
/// this.RaiseEvent(new E());
///
/// This event is not handled until the action that calls this method returns control back
- /// to the Coyote runtime. It is handled before any other events are dequeued from the inbox.
+ /// to the ControlledRuntime. It is handled before any other events are dequeued from the inbox.
/// Only one of the following can be called per action:
/// , .
/// An Assert is raised if you accidentally try and do two of these operations in a single action.
///
/// Type of the state.
- protected void RaiseGotoStateEvent(Type state)
+ public void RaiseGotoStateEvent(Type state)
{
// If the state is not a state of the monitor, then report an error and exit.
Assert(StateTypeMap[GetType()].Any(val => val.DeclaringType.Equals(state.DeclaringType) && val.Name.Equals(state.Name)),
@@ -249,7 +278,7 @@ protected void RaiseGotoStateEvent(Type state)
///
/// Checks if the assertion holds, and if not, throws an exception.
///
- protected void Assert(bool predicate)
+ public void Assert(bool predicate)
{
if (!predicate)
{
@@ -261,7 +290,7 @@ protected void Assert(bool predicate)
///
/// Checks if the assertion holds, and if not, throws an exception.
///
- protected void Assert(bool predicate, string s, params object[] args)
+ public void Assert(bool predicate, string s, params object[] args)
{
if (!predicate)
{
@@ -459,6 +488,11 @@ private void ExecuteAction(CachedDelegate cachedAction, Event e)
innerException = innerException.InnerException;
}
+ if (innerException is PNonStandardReturnException)
+ {
+ return;
+ }
+
if (innerException is AggregateException)
{
innerException = innerException.InnerException;
@@ -702,7 +736,7 @@ internal void InitializeStateInformation()
var syncObject = ActionCacheLocks.GetOrAdd(monitorType, _ => new object());
// Locking this syncObject ensures only one thread enters the initialization code to update
- // the ActionCache for this specific Actor type.
+ // the ActionCache for this specific StateMachine type.
lock (syncObject)
{
if (MonitorActionMap.ContainsKey(monitorType))
@@ -950,7 +984,7 @@ internal HashSet GetAllStates()
var allStates = new HashSet();
foreach (var state in StateMap[GetType()])
{
- allStates.Add(NameResolver.GetQualifiedStateName(state.GetType()));
+ allStates.Add(state.GetType().Name);
}
return allStates;
@@ -968,7 +1002,7 @@ internal HashSet> GetAllStateEventPairs()
{
foreach (var binding in state.EventHandlers)
{
- pairs.Add(Tuple.Create(NameResolver.GetQualifiedStateName(state.GetType()), binding.Key.FullName));
+ pairs.Add(Tuple.Create(state.GetType().Name, binding.Key.FullName));
}
}
@@ -979,7 +1013,7 @@ internal HashSet> GetAllStateEventPairs()
/// Defines the transition that is the
/// result of executing an event handler. Transitions are created by using
/// , or .
- /// The Transition is processed by the Coyote runtime when
+ /// The Transition is processed by the ControlledRuntime when
/// an event handling method returns a Transition object.
/// This means such a method can only do one such Transition per method call.
/// If the method wants to do a conditional transition it can return
diff --git a/Src/PChecker/CheckerCore/Actors/EventQueues/DequeueStatus.cs b/Src/PChecker/CheckerCore/Runtime/StateMachines/EventQueues/DequeueStatus.cs
similarity index 92%
rename from Src/PChecker/CheckerCore/Actors/EventQueues/DequeueStatus.cs
rename to Src/PChecker/CheckerCore/Runtime/StateMachines/EventQueues/DequeueStatus.cs
index 6482634a40..4cce8d1b24 100644
--- a/Src/PChecker/CheckerCore/Actors/EventQueues/DequeueStatus.cs
+++ b/Src/PChecker/CheckerCore/Runtime/StateMachines/EventQueues/DequeueStatus.cs
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-namespace PChecker.Actors.EventQueues
+namespace PChecker.Runtime.StateMachines.EventQueues
{
///
/// The status returned as the result of a dequeue operation.
diff --git a/Src/PChecker/CheckerCore/Actors/EventQueues/EnqueueStatus.cs b/Src/PChecker/CheckerCore/Runtime/StateMachines/EventQueues/EnqueueStatus.cs
similarity index 94%
rename from Src/PChecker/CheckerCore/Actors/EventQueues/EnqueueStatus.cs
rename to Src/PChecker/CheckerCore/Runtime/StateMachines/EventQueues/EnqueueStatus.cs
index 57aab56ab6..33ea456768 100644
--- a/Src/PChecker/CheckerCore/Actors/EventQueues/EnqueueStatus.cs
+++ b/Src/PChecker/CheckerCore/Runtime/StateMachines/EventQueues/EnqueueStatus.cs
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-namespace PChecker.Actors.EventQueues
+namespace PChecker.Runtime.StateMachines.EventQueues
{
///
/// The status returned as the result of an enqueue operation.
diff --git a/Src/PChecker/CheckerCore/Actors/EventQueues/Mocks/MockEventQueue.cs b/Src/PChecker/CheckerCore/Runtime/StateMachines/EventQueues/EventQueue.cs
similarity index 69%
rename from Src/PChecker/CheckerCore/Actors/EventQueues/Mocks/MockEventQueue.cs
rename to Src/PChecker/CheckerCore/Runtime/StateMachines/EventQueues/EventQueue.cs
index 8142398e5a..7db5bb7440 100644
--- a/Src/PChecker/CheckerCore/Actors/EventQueues/Mocks/MockEventQueue.cs
+++ b/Src/PChecker/CheckerCore/Runtime/StateMachines/EventQueues/EventQueue.cs
@@ -3,37 +3,36 @@
using System;
using System.Collections.Generic;
-using System.Linq;
using System.Threading.Tasks;
-using PChecker.Actors.Events;
-using PChecker.Actors.Managers;
+using PChecker.Runtime.Events;
+using PChecker.Runtime.StateMachines.Managers;
-namespace PChecker.Actors.EventQueues.Mocks
+namespace PChecker.Runtime.StateMachines.EventQueues
{
///
/// Implements a queue of events that is used during testing.
///
- internal sealed class MockEventQueue : IEventQueue
+ internal sealed class EventQueue : IEventQueue
{
///
- /// Manages the actor that owns this queue.
+ /// Manages the state machine that owns this queue.
///
- private readonly IActorManager ActorManager;
+ private readonly IStateMachineManager StateMachineManager;
///
- /// The actor that owns this queue.
+ /// The state machine that owns this queue.
///
- private readonly Actor Actor;
+ private readonly StateMachine StateMachine;
///
/// The internal queue that contains events with their metadata.
///
- private readonly LinkedList<(Event e, Guid opGroupId, EventInfo info)> Queue;
+ private readonly LinkedList<(Event e, EventInfo info)> Queue;
///
/// The raised event and its metadata, or null if no event has been raised.
///
- private (Event e, Guid opGroupId, EventInfo info) RaisedEvent;
+ private (Event e, EventInfo info) RaisedEvent;
///
/// Map from the types of events that the owner of the queue is waiting to receive
@@ -64,19 +63,19 @@ internal sealed class MockEventQueue : IEventQueue
public bool IsEventRaised => RaisedEvent != default;
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
- internal MockEventQueue(IActorManager actorManager, Actor actor)
+ internal EventQueue(IStateMachineManager stateMachineManager, StateMachine stateMachine)
{
- ActorManager = actorManager;
- Actor = actor;
- Queue = new LinkedList<(Event, Guid, EventInfo)>();
+ StateMachineManager = stateMachineManager;
+ StateMachine = stateMachine;
+ Queue = new LinkedList<(Event, EventInfo)>();
EventWaitTypes = new Dictionary>();
IsClosed = false;
}
///
- public EnqueueStatus Enqueue(Event e, Guid opGroupId, EventInfo info)
+ public EnqueueStatus Enqueue(Event e, EventInfo info)
{
if (IsClosed)
{
@@ -87,15 +86,15 @@ public EnqueueStatus Enqueue(Event e, Guid opGroupId, EventInfo info)
(predicate is null || predicate(e)))
{
EventWaitTypes.Clear();
- ActorManager.OnReceiveEvent(e, opGroupId, info);
+ StateMachineManager.OnReceiveEvent(e, info);
ReceiveCompletionSource.SetResult(e);
return EnqueueStatus.EventHandlerRunning;
}
- ActorManager.OnEnqueueEvent(e, opGroupId, info);
- Queue.AddLast((e, opGroupId, info));
+ StateMachineManager.OnEnqueueEvent(e, info);
+ Queue.AddLast((e, info));
- if (!ActorManager.IsEventHandlerRunning)
+ if (!StateMachineManager.IsEventHandlerRunning)
{
if (TryDequeueEvent(true).e is null)
{
@@ -103,7 +102,7 @@ public EnqueueStatus Enqueue(Event e, Guid opGroupId, EventInfo info)
}
else
{
- ActorManager.IsEventHandlerRunning = true;
+ StateMachineManager.IsEventHandlerRunning = true;
return EnqueueStatus.EventHandlerNotRunning;
}
}
@@ -112,13 +111,13 @@ public EnqueueStatus Enqueue(Event e, Guid opGroupId, EventInfo info)
}
///
- public (DequeueStatus status, Event e, Guid opGroupId, EventInfo info) Dequeue()
+ public (DequeueStatus status, Event e, EventInfo info) Dequeue()
{
// Try to get the raised event, if there is one. Raised events
// have priority over the events in the inbox.
if (RaisedEvent != default)
{
- if (ActorManager.IsEventIgnored(RaisedEvent.e, RaisedEvent.opGroupId, RaisedEvent.info))
+ if (StateMachineManager.IsEventIgnored(RaisedEvent.e, RaisedEvent.info))
{
// TODO: should the user be able to raise an ignored event?
// The raised event is ignored in the current state.
@@ -128,46 +127,45 @@ public EnqueueStatus Enqueue(Event e, Guid opGroupId, EventInfo info)
{
var raisedEvent = RaisedEvent;
RaisedEvent = default;
- return (DequeueStatus.Raised, raisedEvent.e, raisedEvent.opGroupId, raisedEvent.info);
+ return (DequeueStatus.Raised, raisedEvent.e, raisedEvent.info);
}
}
- var hasDefaultHandler = ActorManager.IsDefaultHandlerAvailable();
+ var hasDefaultHandler = StateMachineManager.IsDefaultHandlerAvailable();
if (hasDefaultHandler)
{
- Actor.Runtime.NotifyDefaultEventHandlerCheck(Actor);
+ StateMachine.Runtime.NotifyDefaultEventHandlerCheck(StateMachine);
}
// Try to dequeue the next event, if there is one.
- var (e, opGroupId, info) = TryDequeueEvent();
+ var (e, info) = TryDequeueEvent();
if (e != null)
{
// Found next event that can be dequeued.
- return (DequeueStatus.Success, e, opGroupId, info);
+ return (DequeueStatus.Success, e, info);
}
// No event can be dequeued, so check if there is a default event handler.
if (!hasDefaultHandler)
{
// There is no default event handler installed, so do not return an event.
- ActorManager.IsEventHandlerRunning = false;
- return (DequeueStatus.NotAvailable, null, Guid.Empty, null);
+ StateMachineManager.IsEventHandlerRunning = false;
+ return (DequeueStatus.NotAvailable, null, null);
}
// TODO: check op-id of default event.
// A default event handler exists.
- var stateName = Actor is StateMachine stateMachine ?
- NameResolver.GetStateNameForLogging(stateMachine.CurrentState) : string.Empty;
- var eventOrigin = new EventOriginInfo(Actor.Id, Actor.GetType().FullName, stateName);
- return (DequeueStatus.Default, DefaultEvent.Instance, Guid.Empty, new EventInfo(DefaultEvent.Instance, eventOrigin));
+ var stateName = StateMachine.CurrentState.GetType().Name;
+ var eventOrigin = new EventOriginInfo(StateMachine.Id, StateMachine.GetType().FullName, stateName);
+ return (DequeueStatus.Default, DefaultEvent.Instance, new EventInfo(DefaultEvent.Instance, eventOrigin));
}
///
/// Dequeues the next event and its metadata, if there is one available, else returns null.
///
- private (Event e, Guid opGroupId, EventInfo info) TryDequeueEvent(bool checkOnly = false)
+ private (Event e, EventInfo info) TryDequeueEvent(bool checkOnly = false)
{
- (Event, Guid, EventInfo) nextAvailableEvent = default;
+ (Event, EventInfo) nextAvailableEvent = default;
// Iterates through the events and metadata in the inbox.
var node = Queue.First;
@@ -176,7 +174,7 @@ public EnqueueStatus Enqueue(Event e, Guid opGroupId, EventInfo info)
var nextNode = node.Next;
var currentEvent = node.Value;
- if (ActorManager.IsEventIgnored(currentEvent.e, currentEvent.opGroupId, currentEvent.info))
+ if (StateMachineManager.IsEventIgnored(currentEvent.e, currentEvent.info))
{
if (!checkOnly)
{
@@ -189,7 +187,7 @@ public EnqueueStatus Enqueue(Event e, Guid opGroupId, EventInfo info)
}
// Skips a deferred event.
- if (!ActorManager.IsEventDeferred(currentEvent.e, currentEvent.opGroupId, currentEvent.info))
+ if (!StateMachineManager.IsEventDeferred(currentEvent.e, currentEvent.info))
{
nextAvailableEvent = currentEvent;
if (!checkOnly)
@@ -207,14 +205,13 @@ public EnqueueStatus Enqueue(Event e, Guid opGroupId, EventInfo info)
}
///
- public void RaiseEvent(Event e, Guid opGroupId)
+ public void RaiseEvent(Event e)
{
- var stateName = Actor is StateMachine stateMachine ?
- NameResolver.GetStateNameForLogging(stateMachine.CurrentState) : string.Empty;
- var eventOrigin = new EventOriginInfo(Actor.Id, Actor.GetType().FullName, stateName);
+ var stateName = StateMachine.CurrentState.GetType().Name;
+ var eventOrigin = new EventOriginInfo(StateMachine.Id, StateMachine.GetType().FullName, stateName);
var info = new EventInfo(e, eventOrigin);
- RaisedEvent = (e, opGroupId, info);
- ActorManager.OnRaiseEvent(e, opGroupId, info);
+ RaisedEvent = (e, info);
+ StateMachineManager.OnRaiseEvent(e, info);
}
///
@@ -257,9 +254,9 @@ public Task ReceiveEventAsync(params Tuple>[] eve
///
private Task ReceiveEventAsync(Dictionary> eventWaitTypes)
{
- Actor.Runtime.NotifyReceiveCalled(Actor);
+ StateMachine.Runtime.NotifyReceiveCalled(StateMachine);
- (Event e, Guid opGroupId, EventInfo info) receivedEvent = default;
+ (Event e, EventInfo info) receivedEvent = default;
var node = Queue.First;
while (node != null)
{
@@ -279,11 +276,11 @@ private Task ReceiveEventAsync(Dictionary> eventW
{
ReceiveCompletionSource = new TaskCompletionSource();
EventWaitTypes = eventWaitTypes;
- ActorManager.OnWaitEvent(EventWaitTypes.Keys);
+ StateMachineManager.OnWaitEvent(EventWaitTypes.Keys);
return ReceiveCompletionSource.Task;
}
- ActorManager.OnReceiveEventWithoutWaiting(receivedEvent.e, receivedEvent.opGroupId, receivedEvent.info);
+ StateMachineManager.OnReceiveEventWithoutWaiting(receivedEvent.e, receivedEvent.info);
return Task.FromResult(receivedEvent.e);
}
@@ -293,14 +290,9 @@ public int GetCachedState()
unchecked
{
var hash = 19;
- foreach (var (_, _, info) in Queue)
+ foreach (var (_, info) in Queue)
{
hash = (hash * 31) + info.EventName.GetHashCode();
- if (info.HashedState != 0)
- {
- // Adds the user-defined hashed event state.
- hash = (hash * 31) + info.HashedState;
- }
}
return hash;
@@ -323,9 +315,9 @@ private void Dispose(bool disposing)
return;
}
- foreach (var (e, opGroupId, info) in Queue)
+ foreach (var (e, info) in Queue)
{
- ActorManager.OnDropEvent(e, opGroupId, info);
+ StateMachineManager.OnDropEvent(e, info);
}
Queue.Clear();
diff --git a/Src/PChecker/CheckerCore/Actors/EventQueues/IEventQueue.cs b/Src/PChecker/CheckerCore/Runtime/StateMachines/EventQueues/IEventQueue.cs
similarity index 86%
rename from Src/PChecker/CheckerCore/Actors/EventQueues/IEventQueue.cs
rename to Src/PChecker/CheckerCore/Runtime/StateMachines/EventQueues/IEventQueue.cs
index 20026e59c9..a74b05edf1 100644
--- a/Src/PChecker/CheckerCore/Actors/EventQueues/IEventQueue.cs
+++ b/Src/PChecker/CheckerCore/Runtime/StateMachines/EventQueues/IEventQueue.cs
@@ -3,9 +3,9 @@
using System;
using System.Threading.Tasks;
-using PChecker.Actors.Events;
+using PChecker.Runtime.Events;
-namespace PChecker.Actors.EventQueues
+namespace PChecker.Runtime.StateMachines.EventQueues
{
///
/// Interface of a queue of events.
@@ -25,17 +25,17 @@ internal interface IEventQueue : IDisposable
///
/// Enqueues the specified event and its optional metadata.
///
- EnqueueStatus Enqueue(Event e, Guid opGroupId, EventInfo info);
+ EnqueueStatus Enqueue(Event e, EventInfo info);
///
/// Dequeues the next event, if there is one available.
///
- (DequeueStatus status, Event e, Guid opGroupId, EventInfo info) Dequeue();
+ (DequeueStatus status, Event e, EventInfo info) Dequeue();
///
/// Enqueues the specified raised event.
///
- void RaiseEvent(Event e, Guid opGroupId);
+ void RaiseEvent(Event e);
///
/// Waits to receive an event of the specified type that satisfies an optional predicate.
diff --git a/Src/PChecker/CheckerCore/Actors/Exceptions/ActionExceptionFilterException.cs b/Src/PChecker/CheckerCore/Runtime/StateMachines/Exceptions/ActionExceptionFilterException.cs
similarity index 92%
rename from Src/PChecker/CheckerCore/Actors/Exceptions/ActionExceptionFilterException.cs
rename to Src/PChecker/CheckerCore/Runtime/StateMachines/Exceptions/ActionExceptionFilterException.cs
index dcb74df948..ae80a77ea0 100644
--- a/Src/PChecker/CheckerCore/Actors/Exceptions/ActionExceptionFilterException.cs
+++ b/Src/PChecker/CheckerCore/Runtime/StateMachines/Exceptions/ActionExceptionFilterException.cs
@@ -4,10 +4,10 @@
using System;
using PChecker.Exceptions;
-namespace PChecker.Actors.Exceptions
+namespace PChecker.Runtime.StateMachines.Exceptions
{
///
- /// Exception that is thrown by the runtime upon an action failure.
+ /// Exception that is thrown by the runtime upon an action failure.
///
internal sealed class ActionExceptionFilterException : RuntimeException
{
diff --git a/Src/PChecker/CheckerCore/Runtime/StateMachines/Exceptions/OnEventDroppedHandler.cs b/Src/PChecker/CheckerCore/Runtime/StateMachines/Exceptions/OnEventDroppedHandler.cs
new file mode 100644
index 0000000000..84f27b5bb2
--- /dev/null
+++ b/Src/PChecker/CheckerCore/Runtime/StateMachines/Exceptions/OnEventDroppedHandler.cs
@@ -0,0 +1,12 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using PChecker.Runtime.Events;
+
+namespace PChecker.Runtime.StateMachines.Exceptions
+{
+ ///
+ /// Handles the event.
+ ///
+ public delegate void OnEventDroppedHandler(Event e, StateMachineId target);
+}
\ No newline at end of file
diff --git a/Src/PChecker/CheckerCore/Actors/Exceptions/OnExceptionOutcome.cs b/Src/PChecker/CheckerCore/Runtime/StateMachines/Exceptions/OnExceptionOutcome.cs
similarity index 52%
rename from Src/PChecker/CheckerCore/Actors/Exceptions/OnExceptionOutcome.cs
rename to Src/PChecker/CheckerCore/Runtime/StateMachines/Exceptions/OnExceptionOutcome.cs
index dfa5bea2e3..bfa30b0396 100644
--- a/Src/PChecker/CheckerCore/Actors/Exceptions/OnExceptionOutcome.cs
+++ b/Src/PChecker/CheckerCore/Runtime/StateMachines/Exceptions/OnExceptionOutcome.cs
@@ -1,25 +1,25 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-namespace PChecker.Actors.Exceptions
+namespace PChecker.Runtime.StateMachines.Exceptions
{
///
- /// The outcome when an throws an exception.
+ /// The outcome when an throws an exception.
///
public enum OnExceptionOutcome
{
///
- /// The actor throws the exception causing the runtime to fail.
+ /// The state machine throws the exception causing the runtime to fail.
///
ThrowException = 0,
///
- /// The actor handles the exception and resumes execution.
+ /// The state machine handles the exception and resumes execution.
///
HandledException = 1,
///
- /// The actor handles the exception and halts.
+ /// The state machine handles the exception and halts.
///
Halt = 2
}
diff --git a/Src/PChecker/CheckerCore/Actors/Exceptions/UnhandledEventException.cs b/Src/PChecker/CheckerCore/Runtime/StateMachines/Exceptions/UnhandledEventException.cs
similarity index 79%
rename from Src/PChecker/CheckerCore/Actors/Exceptions/UnhandledEventException.cs
rename to Src/PChecker/CheckerCore/Runtime/StateMachines/Exceptions/UnhandledEventException.cs
index 97a1891bab..f4a43cf2ec 100644
--- a/Src/PChecker/CheckerCore/Actors/Exceptions/UnhandledEventException.cs
+++ b/Src/PChecker/CheckerCore/Runtime/StateMachines/Exceptions/UnhandledEventException.cs
@@ -1,13 +1,13 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using PChecker.Actors.Events;
using PChecker.Exceptions;
+using PChecker.Runtime.Events;
-namespace PChecker.Actors.Exceptions
+namespace PChecker.Runtime.StateMachines.Exceptions
{
///
- /// Signals that an received an unhandled event.
+ /// Signals that an received an unhandled event.
///
public sealed class UnhandledEventException : RuntimeException
{
@@ -17,7 +17,7 @@ public sealed class UnhandledEventException : RuntimeException
public Event UnhandledEvent;
///
- /// The name of the current state, if the actor that threw the exception
+ /// The name of the current state, if the state machine that threw the exception
/// is a and a state exists, else null.
///
public string CurrentStateName;
@@ -26,7 +26,7 @@ public sealed class UnhandledEventException : RuntimeException
/// Initializes a new instance of the class.
///
/// The event that was unhandled.
- /// The name of the current state, if the actor that threw the exception
+ /// The name of the current state, if the state machine that threw the exception
/// is a state machine and a state exists, else null.
/// The exception message.
internal UnhandledEventException(Event unhandledEvent, string currentStateName, string message)
diff --git a/Src/PChecker/CheckerCore/Actors/Handlers/ActionEventHandlerDeclaration.cs b/Src/PChecker/CheckerCore/Runtime/StateMachines/Handlers/ActionEventHandlerDeclaration.cs
similarity index 93%
rename from Src/PChecker/CheckerCore/Actors/Handlers/ActionEventHandlerDeclaration.cs
rename to Src/PChecker/CheckerCore/Runtime/StateMachines/Handlers/ActionEventHandlerDeclaration.cs
index eb8a3aa1dc..191317907e 100644
--- a/Src/PChecker/CheckerCore/Actors/Handlers/ActionEventHandlerDeclaration.cs
+++ b/Src/PChecker/CheckerCore/Runtime/StateMachines/Handlers/ActionEventHandlerDeclaration.cs
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-namespace PChecker.Actors.Handlers
+namespace PChecker.Runtime.StateMachines.Handlers
{
///
/// Defines an action event handler declaration.
diff --git a/Src/PChecker/CheckerCore/Actors/Handlers/CachedDelegate.cs b/Src/PChecker/CheckerCore/Runtime/StateMachines/Handlers/CachedDelegate.cs
similarity index 89%
rename from Src/PChecker/CheckerCore/Actors/Handlers/CachedDelegate.cs
rename to Src/PChecker/CheckerCore/Runtime/StateMachines/Handlers/CachedDelegate.cs
index 1d69e9511b..3fbd9b6c00 100644
--- a/Src/PChecker/CheckerCore/Actors/Handlers/CachedDelegate.cs
+++ b/Src/PChecker/CheckerCore/Runtime/StateMachines/Handlers/CachedDelegate.cs
@@ -4,12 +4,12 @@
using System;
using System.Reflection;
using System.Threading.Tasks;
-using PChecker.Actors.Events;
+using PChecker.Runtime.Events;
-namespace PChecker.Actors.Handlers
+namespace PChecker.Runtime.StateMachines.Handlers
{
///
- /// An actor delegate that has been cached to optimize performance of invocations.
+ /// An state machine delegate that has been cached to optimize performance of invocations.
///
internal class CachedDelegate
{
diff --git a/Src/PChecker/CheckerCore/Actors/Handlers/DeferEventHandlerDeclaration.cs b/Src/PChecker/CheckerCore/Runtime/StateMachines/Handlers/DeferEventHandlerDeclaration.cs
similarity index 86%
rename from Src/PChecker/CheckerCore/Actors/Handlers/DeferEventHandlerDeclaration.cs
rename to Src/PChecker/CheckerCore/Runtime/StateMachines/Handlers/DeferEventHandlerDeclaration.cs
index 428426ed4a..9e3bf9a065 100644
--- a/Src/PChecker/CheckerCore/Actors/Handlers/DeferEventHandlerDeclaration.cs
+++ b/Src/PChecker/CheckerCore/Runtime/StateMachines/Handlers/DeferEventHandlerDeclaration.cs
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-namespace PChecker.Actors.Handlers
+namespace PChecker.Runtime.StateMachines.Handlers
{
///
/// Defines a defer event handler declaration.
diff --git a/Src/PChecker/CheckerCore/Actors/Handlers/EventHandlerDeclaration.cs b/Src/PChecker/CheckerCore/Runtime/StateMachines/Handlers/EventHandlerDeclaration.cs
similarity index 84%
rename from Src/PChecker/CheckerCore/Actors/Handlers/EventHandlerDeclaration.cs
rename to Src/PChecker/CheckerCore/Runtime/StateMachines/Handlers/EventHandlerDeclaration.cs
index 870fae0ca7..6d9462251f 100644
--- a/Src/PChecker/CheckerCore/Actors/Handlers/EventHandlerDeclaration.cs
+++ b/Src/PChecker/CheckerCore/Runtime/StateMachines/Handlers/EventHandlerDeclaration.cs
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-namespace PChecker.Actors.Handlers
+namespace PChecker.Runtime.StateMachines.Handlers
{
///
/// An abstract event handler declaration.
diff --git a/Src/PChecker/CheckerCore/Actors/Handlers/IgnoreEventHandlerDeclaration.cs b/Src/PChecker/CheckerCore/Runtime/StateMachines/Handlers/IgnoreEventHandlerDeclaration.cs
similarity index 86%
rename from Src/PChecker/CheckerCore/Actors/Handlers/IgnoreEventHandlerDeclaration.cs
rename to Src/PChecker/CheckerCore/Runtime/StateMachines/Handlers/IgnoreEventHandlerDeclaration.cs
index 0486c36c04..454a9524e4 100644
--- a/Src/PChecker/CheckerCore/Actors/Handlers/IgnoreEventHandlerDeclaration.cs
+++ b/Src/PChecker/CheckerCore/Runtime/StateMachines/Handlers/IgnoreEventHandlerDeclaration.cs
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-namespace PChecker.Actors.Handlers
+namespace PChecker.Runtime.StateMachines.Handlers
{
///
/// Defines an ignore event handler declaration.
diff --git a/Src/PChecker/CheckerCore/Actors/Managers/IActorManager.cs b/Src/PChecker/CheckerCore/Runtime/StateMachines/Managers/IStateMachineManager.cs
similarity index 53%
rename from Src/PChecker/CheckerCore/Actors/Managers/IActorManager.cs
rename to Src/PChecker/CheckerCore/Runtime/StateMachines/Managers/IStateMachineManager.cs
index bc2ec7ab8e..52d6677292 100644
--- a/Src/PChecker/CheckerCore/Actors/Managers/IActorManager.cs
+++ b/Src/PChecker/CheckerCore/Runtime/StateMachines/Managers/IStateMachineManager.cs
@@ -3,39 +3,34 @@
using System;
using System.Collections.Generic;
-using PChecker.Actors.Events;
+using PChecker.Runtime.Events;
-namespace PChecker.Actors.Managers
+namespace PChecker.Runtime.StateMachines.Managers
{
///
- /// Interface for managing an actor.
+ /// Interface for managing a state machine.
///
- internal interface IActorManager
+ internal interface IStateMachineManager
{
///
- /// True if the event handler of the actor is running, else false.
+ /// True if the event handler of the state machine is running, else false.
///
bool IsEventHandlerRunning { get; set; }
-
- ///
- /// Id used to identify subsequent operations performed by the actor.
- ///
- Guid OperationGroupId { get; set; }
-
+
///
- /// Returns the cached state of the actor.
+ /// Returns the cached state of the state machine.
///
int GetCachedState();
///
/// Checks if the specified event is currently ignored.
///
- bool IsEventIgnored(Event e, Guid opGroupId, EventInfo eventInfo);
+ bool IsEventIgnored(Event e, EventInfo eventInfo);
///
/// Checks if the specified event is currently deferred.
///
- bool IsEventDeferred(Event e, Guid opGroupId, EventInfo eventInfo);
+ bool IsEventDeferred(Event e, EventInfo eventInfo);
///
/// Checks if a default handler is currently available.
@@ -43,35 +38,35 @@ internal interface IActorManager
bool IsDefaultHandlerAvailable();
///
- /// Notifies the actor that an event has been enqueued.
+ /// Notifies the state machine that an event has been enqueued.
///
- void OnEnqueueEvent(Event e, Guid opGroupId, EventInfo eventInfo);
+ void OnEnqueueEvent(Event e, EventInfo eventInfo);
///
- /// Notifies the actor that an event has been raised.
+ /// Notifies the state machine that an event has been raised.
///
- void OnRaiseEvent(Event e, Guid opGroupId, EventInfo eventInfo);
+ void OnRaiseEvent(Event e, EventInfo eventInfo);
///
- /// Notifies the actor that it is waiting to receive an event of one of the specified types.
+ /// Notifies the state machine that it is waiting to receive an event of one of the specified types.
///
void OnWaitEvent(IEnumerable eventTypes);
///
- /// Notifies the actor that an event it was waiting to receive has been enqueued.
+ /// Notifies the state machine that an event it was waiting to receive has been enqueued.
///
- void OnReceiveEvent(Event e, Guid opGroupId, EventInfo eventInfo);
+ void OnReceiveEvent(Event e, EventInfo eventInfo);
///
- /// Notifies the actor that an event it was waiting to receive was already in the
- /// event queue when the actor invoked the receive statement.
+ /// Notifies the state machine that an event it was waiting to receive was already in the
+ /// event queue when the state machine invoked the receiving statement.
///
- void OnReceiveEventWithoutWaiting(Event e, Guid opGroupId, EventInfo eventInfo);
+ void OnReceiveEventWithoutWaiting(Event e, EventInfo eventInfo);
///
- /// Notifies the actor that an event has been dropped.
+ /// Notifies the state machine that an event has been dropped.
///
- void OnDropEvent(Event e, Guid opGroupId, EventInfo eventInfo);
+ void OnDropEvent(Event e, EventInfo eventInfo);
///
/// Asserts if the specified condition holds.
diff --git a/Src/PChecker/CheckerCore/Actors/Managers/Mocks/MockStateMachineManager.cs b/Src/PChecker/CheckerCore/Runtime/StateMachines/Managers/StateMachineManager.cs
similarity index 71%
rename from Src/PChecker/CheckerCore/Actors/Managers/Mocks/MockStateMachineManager.cs
rename to Src/PChecker/CheckerCore/Runtime/StateMachines/Managers/StateMachineManager.cs
index 92bd38948b..549f37ed0b 100644
--- a/Src/PChecker/CheckerCore/Actors/Managers/Mocks/MockStateMachineManager.cs
+++ b/Src/PChecker/CheckerCore/Runtime/StateMachines/Managers/StateMachineManager.cs
@@ -4,15 +4,15 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
-using PChecker.Actors.Events;
+using PChecker.Runtime.Events;
using PChecker.SystematicTesting;
-namespace PChecker.Actors.Managers.Mocks
+namespace PChecker.Runtime.StateMachines.Managers
{
///
/// Implements a state machine manager that is used during testing.
///
- internal sealed class MockStateMachineManager : IActorManager
+ internal sealed class StateMachineManager : IStateMachineManager
{
///
/// The runtime that executes the state machine being managed.
@@ -27,9 +27,6 @@ internal sealed class MockStateMachineManager : IActorManager
///
public bool IsEventHandlerRunning { get; set; }
- ///
- public Guid OperationGroupId { get; set; }
-
///
/// Program counter used for state-caching. Distinguishes
/// scheduling from non-deterministic choices.
@@ -37,14 +34,13 @@ internal sealed class MockStateMachineManager : IActorManager
internal int ProgramCounter;
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
- internal MockStateMachineManager(ControlledRuntime runtime, StateMachine instance, Guid operationGroupId)
+ internal StateMachineManager(ControlledRuntime runtime, StateMachine instance)
{
Runtime = runtime;
Instance = instance;
IsEventHandlerRunning = true;
- OperationGroupId = operationGroupId;
ProgramCounter = 0;
}
@@ -62,12 +58,12 @@ public int GetCachedState()
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool IsEventIgnored(Event e, Guid opGroupId, EventInfo eventInfo) =>
+ public bool IsEventIgnored(Event e, EventInfo eventInfo) =>
Instance.IsEventIgnoredInCurrentState(e);
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool IsEventDeferred(Event e, Guid opGroupId, EventInfo eventInfo) =>
+ public bool IsEventDeferred(Event e, EventInfo eventInfo) =>
Instance.IsEventDeferredInCurrentState(e);
///
@@ -76,12 +72,12 @@ public bool IsEventDeferred(Event e, Guid opGroupId, EventInfo eventInfo) =>
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void OnEnqueueEvent(Event e, Guid opGroupId, EventInfo eventInfo) =>
+ public void OnEnqueueEvent(Event e, EventInfo eventInfo) =>
Runtime.LogWriter.LogEnqueueEvent(Instance.Id, e);
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void OnRaiseEvent(Event e, Guid opGroupId, EventInfo eventInfo) =>
+ public void OnRaiseEvent(Event e, EventInfo eventInfo) =>
Runtime.NotifyRaisedEvent(Instance, e, eventInfo);
///
@@ -90,33 +86,21 @@ public void OnWaitEvent(IEnumerable eventTypes) =>
Runtime.NotifyWaitEvent(Instance, eventTypes);
///
- public void OnReceiveEvent(Event e, Guid opGroupId, EventInfo eventInfo)
+ public void OnReceiveEvent(Event e, EventInfo eventInfo)
{
- if (opGroupId != Guid.Empty)
- {
- // Inherit the operation group id of the receive operation, if it is non-empty.
- OperationGroupId = opGroupId;
- }
-
Runtime.NotifyReceivedEvent(Instance, e, eventInfo);
}
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void OnReceiveEventWithoutWaiting(Event e, Guid opGroupId, EventInfo eventInfo)
+ public void OnReceiveEventWithoutWaiting(Event e, EventInfo eventInfo)
{
- if (opGroupId != Guid.Empty)
- {
- // Inherit the operation group id of the receive operation, if it is non-empty.
- OperationGroupId = opGroupId;
- }
-
Runtime.NotifyReceivedEventWithoutWaiting(Instance, e, eventInfo);
}
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void OnDropEvent(Event e, Guid opGroupId, EventInfo eventInfo)
+ public void OnDropEvent(Event e, EventInfo eventInfo)
{
Runtime.TryHandleDroppedEvent(e, Instance.Id);
}
diff --git a/Src/PChecker/CheckerCore/Actors/StateMachine.cs b/Src/PChecker/CheckerCore/Runtime/StateMachines/StateMachine.cs
similarity index 56%
rename from Src/PChecker/CheckerCore/Actors/StateMachine.cs
rename to Src/PChecker/CheckerCore/Runtime/StateMachines/StateMachine.cs
index 27e5d910da..0c2ae5701a 100644
--- a/Src/PChecker/CheckerCore/Actors/StateMachine.cs
+++ b/Src/PChecker/CheckerCore/Runtime/StateMachines/StateMachine.cs
@@ -4,25 +4,56 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
-using System.Globalization;
+using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
+using System.Runtime.CompilerServices;
using System.Threading.Tasks;
-using PChecker.Actors.Events;
-using PChecker.Actors.Exceptions;
-using PChecker.Actors.Handlers;
-using PChecker.Actors.StateTransitions;
using PChecker.Exceptions;
-
-namespace PChecker.Actors
+using PChecker.IO.Debugging;
+using PChecker.Runtime.Events;
+using PChecker.Runtime.Exceptions;
+using PChecker.Runtime.Logging;
+using PChecker.Runtime.StateMachines.EventQueues;
+using PChecker.Runtime.StateMachines.Exceptions;
+using PChecker.Runtime.StateMachines.Handlers;
+using PChecker.Runtime.StateMachines.Managers;
+using PChecker.Runtime.StateMachines.StateTransitions;
+using PChecker.Runtime.Values;
+using PChecker.SystematicTesting;
+using EventInfo = PChecker.Runtime.Events.EventInfo;
+
+
+namespace PChecker.Runtime.StateMachines
{
///
- /// Type that implements a state machine actor. Inherit from this class to declare
- /// a custom actor with states, state transitions and event handlers.
+ /// Type that implements a state machine with states, state transitions and event handlers.
///
- public abstract class StateMachine : Actor
+ public abstract class StateMachine
{
+
+ ///
+ /// The runtime that executes this state machine.
+ ///
+ internal ControlledRuntime Runtime { get; private set; }
+
+ ///
+ /// Unique id that identifies this state machine.
+ ///
+ protected internal StateMachineId Id { get; private set; }
+
+ ///
+ /// Manages the state machine.
+ ///
+ internal IStateMachineManager Manager { get; private set; }
+
+ ///
+ /// The inbox of the state machine. Incoming events are enqueued here.
+ /// Events are dequeued to be processed.
+ ///
+ private protected IEventQueue Inbox;
+
///
/// Cache of state machine types to a map of action names to action declarations.
///
@@ -35,7 +66,7 @@ public abstract class StateMachine : Actor
///
private static readonly ConcurrentDictionary ActionCacheLocks =
new ConcurrentDictionary();
-
+
///
/// Cache of state machine types to a set of all possible states types.
///
@@ -48,19 +79,6 @@ public abstract class StateMachine : Actor
private static readonly ConcurrentDictionary> StateInstanceCache =
new ConcurrentDictionary>();
- ///
- /// A stack of states. The state on the top of the stack represents the current state.
- ///
- private readonly Stack StateStack;
-
- ///
- /// A map from event type to a Stack of HandlerInfo where the stack contains the inheritable
- /// event handlers defined by each state that has been pushed onto the StateStack (if any).
- /// The HandlerInfo also remembers which state the handler was defined on so that when the
- /// handler is invoked the IActorRuntimeLog can be given that information.
- ///
- private readonly Dictionary> InheritableEventHandlerMap;
-
///
/// A map from event type to EventHandlerDeclaration for those EventHandlerDeclarations that
/// are not inheritable on the state stack.
@@ -76,6 +94,32 @@ public abstract class StateMachine : Actor
/// Map from action names to cached action delegates for all states in this state machine.
///
private readonly Dictionary StateMachineActionMap;
+
+ ///
+ /// A cached array that contains a single event type.
+ ///
+ private static readonly Type[] SingleEventTypeArray = new Type[] { typeof(Event) };
+
+ ///
+ /// The current status of the state machine. It is marked volatile as
+ /// the runtime can read it concurrently.
+ ///
+ private protected volatile Status CurrentStatus;
+
+ ///
+ /// Gets the name of the current state, if there is one.
+ ///
+ internal string CurrentStateName { get; private protected set; }
+
+ ///
+ /// Checks if the state machine is halted.
+ ///
+ internal bool IsHalted => CurrentStatus is Status.Halted;
+
+ ///
+ /// Checks if a default handler is available.
+ ///
+ internal bool IsDefaultHandlerAvailable { get; private set; }
///
/// Newly created Transition that hasn't been returned from InvokeActionAsync yet.
@@ -85,25 +129,327 @@ public abstract class StateMachine : Actor
///
/// Gets the of the current state.
///
- protected internal Type CurrentState { get; private set; }
+ protected internal State CurrentState { get; private set; }
+
+ ///
+ /// The installed runtime logger.
+ ///
+ protected TextWriter Logger => Runtime.Logger;
+
+ ///
+ /// The installed runtime json logger.
+ ///
+ protected JsonWriter JsonLogger => Runtime.JsonLogger;
+
+ protected IPValue gotoPayload;
+
+ public List creates = new List();
+ public string interfaceName;
+ public List receives = new List();
+ public PMachineValue self;
+ public List sends = new List();
+
+ protected virtual Event GetConstructorEvent(IPValue value)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public PMachineValue CreateInterface(StateMachine creator, IPValue payload = null)
+ where T : PMachineValue
+ {
+ var createdInterface = PModule.linkMap[creator.interfaceName][typeof(T).Name];
+ Assert(creates.Contains(createdInterface),
+ $"Machine {GetType().Name} cannot create interface {createdInterface}, not in its creates set");
+ var createMachine = PModule.interfaceDefinitionMap[createdInterface];
+ var machineId = CreateStateMachine(createMachine, createdInterface.Substring(2),
+ GetConstructorEvent(payload));
+ return new PMachineValue(machineId, PInterfaces.GetPermissions(createdInterface));
+ }
+
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public IPValue TryRandom(IPValue param)
+ {
+ switch (param)
+ {
+ case PInt maxValue:
+ {
+ Assert(maxValue <= 10000, $"choose expects a parameter with at most 10000 choices, got {maxValue} choices instead.");
+ return (PInt)RandomInteger(maxValue);
+ }
+
+ case PSeq seq:
+ {
+ Assert(seq.Any(), "Trying to choose from an empty sequence!");
+ Assert(seq.Count <= 10000, $"choose expects a parameter with at most 10000 choices, got {seq.Count} choices instead.");
+ return seq[RandomInteger(seq.Count)];
+ }
+ case PSet set:
+ {
+ Assert(set.Any(), "Trying to choose from an empty set!");
+ Assert(set.Count <= 10000, $"choose expects a parameter with at most 10000 choices, got {set.Count} choices instead.");
+ return set.ElementAt(RandomInteger(set.Count));
+ }
+ case PMap map:
+ {
+ Assert(map.Any(), "Trying to choose from an empty map!");
+ Assert(map.Keys.Count <= 10000, $"choose expects a parameter with at most 10000 choices, got {map.Keys.Count} choices instead.");
+ return map.Keys.ElementAt(RandomInteger(map.Keys.Count));
+ }
+ default:
+ throw new PInternalException("This is an unexpected (internal) P exception. Please report to the P Developers");
+ }
+ }
+
+ public void LogLine(string message)
+ {
+ Logger.WriteLine($" {message}");
+
+ // Log message to JSON output
+ JsonLogger.AddLogType(JsonWriter.LogType.Print);
+ JsonLogger.AddLog(message);
+ JsonLogger.AddToLogs(updateVcMap: false);
+ }
+
+ public void Log(string message)
+ {
+ Logger.Write($"{message}");
+ }
+
+ public void Announce(Event ev, object payload = null)
+ {
+ Assert(ev != null, "Machine cannot announce a null event");
+ if (ev is PHalt)
+ {
+ ev = HaltEvent.Instance;
+ }
+
+ var oneArgConstructor = ev.GetType().GetConstructors().First(x => x.GetParameters().Length > 0);
+ var @event = (Event)oneArgConstructor.Invoke(new[] { payload });
+ var pText = payload == null ? "" : $" with payload {((IPValue)payload).ToEscapedString()}";
+
+ Logger.WriteLine($" '{Id}' announced event '{ev.GetType().Name}'{pText}.");
+
+ // Log message to JSON output
+ JsonLogger.AddLogType(JsonWriter.LogType.Announce);
+ JsonLogger.LogDetails.Id = $"{Id}";
+ JsonLogger.LogDetails.Event = ev.GetType().Name;
+ if (payload != null)
+ {
+ JsonLogger.LogDetails.Payload = ((IPValue)payload).ToDict();
+ }
+ JsonLogger.AddLog($"{Id} announced event {ev.GetType().Name}{pText}.");
+ JsonLogger.AddToLogs(updateVcMap: true);
+
+ AnnounceInternal(@event);
+ }
+
+ private void AnnounceInternal(Event ev)
+ {
+ Assert(ev != null, "cannot send a null event");
+ if (!PModule.monitorMap.ContainsKey(interfaceName))
+ {
+ return;
+ }
+ foreach (var monitor in PModule.monitorMap[interfaceName])
+ {
+ if (PModule.monitorObserves[monitor.Name].Contains(ev.GetType().Name))
+ {
+ Monitor(monitor, ev);
+ }
+ }
+ }
+
///
/// Initializes a new instance of the class.
///
protected StateMachine()
: base()
{
- StateStack = new Stack();
- InheritableEventHandlerMap = new Dictionary>();
+ CurrentStatus = Status.Active;
+ CurrentStateName = default;
+ IsDefaultHandlerAvailable = false;
EventHandlerMap = EmptyEventHandlerMap;
StateMachineActionMap = new Dictionary();
}
+
+ ///
+ /// Configures the state machine.
+ ///
+ internal void Configure(ControlledRuntime runtime, StateMachineId id, IStateMachineManager manager, IEventQueue inbox)
+ {
+ Runtime = runtime;
+ Id = id;
+ Manager = manager;
+ Inbox = inbox;
+ }
+
+ ///
+ /// Returns a nondeterministic boolean choice, that can be
+ /// controlled during analysis or testing.
+ ///
+ /// The controlled nondeterministic choice.
+ public bool RandomBoolean() => Runtime.GetNondeterministicBooleanChoice(2, Id.Name, Id.Type);
+
+ ///
+ /// Returns a nondeterministic boolean choice, that can be
+ /// controlled during analysis or testing. The value is used
+ /// to generate a number in the range [0..maxValue), where 0
+ /// triggers true.
+ ///
+ /// The max value.
+ /// The controlled nondeterministic choice.
+ public bool RandomBoolean(int maxValue) =>
+ Runtime.GetNondeterministicBooleanChoice(maxValue, Id.Name, Id.Type);
+
+ ///
+ /// Returns a nondeterministic integer, that can be controlled during
+ /// analysis or testing. The value is used to generate an integer in
+ /// the range [0..maxValue).
+ ///
+ /// The max value.
+ /// The controlled nondeterministic integer.
+ public int RandomInteger(int maxValue) =>
+ Runtime.GetNondeterministicIntegerChoice(maxValue, Id.Name, Id.Type);
+
+ public int RandomInteger(int minValue, int maxValue)
+ {
+ return minValue + RandomInteger(maxValue - minValue);
+ }
+
+ ///
+ /// Invokes the specified monitor with the specified .
+ ///
+ /// Type of the monitor.
+ /// Event to send to the monitor.
+ protected void Monitor(Event e) => Monitor(typeof(T), e);
+
+ ///
+ /// Invokes the specified monitor with the specified event.
+ ///
+ /// Type of the monitor.
+ /// The event to send.
+ protected void Monitor(Type type, Event e)
+ {
+ Assert(e != null, "{0} is sending a null event.", Id);
+ Runtime.Monitor(type, e, Id.Name, Id.Type, CurrentStateName);
+ }
+
+ ///
+ /// Checks if the assertion holds, and if not, throws an exception.
+ ///
+ public void Assert(bool predicate) => Runtime.Assert(predicate);
+
+ ///
+ /// Checks if the assertion holds, and if not, throws an exception.
+ ///
+ public void Assert(bool predicate, string s, object arg0) =>
+ Runtime.Assert(predicate, s, arg0);
+
+ ///
+ /// Checks if the assertion holds, and if not, throws an exception.
+ ///
+ public void Assert(bool predicate, string s, object arg0, object arg1) =>
+ Runtime.Assert(predicate, s, arg0, arg1);
+
+ ///
+ /// Checks if the assertion holds, and if not, throws an exception.
+ ///
+ public void Assert(bool predicate, string s, object arg0, object arg1, object arg2) =>
+ Runtime.Assert(predicate, s, arg0, arg1, arg2);
+
+ ///
+ /// Checks if the assertion holds, and if not, throws an exception.
+ ///
+ public void Assert(bool predicate, string s, params object[] args) =>
+ Runtime.Assert(predicate, s, args);
+
+ ///
+ /// Asynchronous callback that is invoked when the state machine is initialized with an optional event.
+ ///
+ /// Optional event used for initialization.
+ /// Task that represents the asynchronous operation.
+ protected virtual Task OnInitializeAsync(Event initialEvent) => Task.CompletedTask;
+
+ ///
+ /// Asynchronous callback that is invoked when the state machine successfully dequeues
+ /// an event from its inbox. This method is not called when the dequeue happens
+ /// via a receive statement.
+ ///
+ /// The event that was dequeued.
+ protected virtual Task OnEventDequeuedAsync(Event e) => Task.CompletedTask;
+
+ ///
+ /// Asynchronous callback that is invoked when the state machine finishes handling a dequeued
+ /// event, unless the handler of the dequeued event caused the state machine to halt (either
+ /// normally or due to an exception). The state machine will either become idle or dequeue
+ /// the next event from its inbox.
+ ///
+ /// The event that was handled.
+ protected virtual Task OnEventHandledAsync(Event e) => Task.CompletedTask;
+
+ ///
+ /// Asynchronous callback that is invoked when the state machine receives an event that
+ /// it is not prepared to handle. The callback is invoked first, after which the
+ /// state machine will necessarily throw an
+ ///
+ /// The event that was unhandled.
+ /// The state when the event was dequeued.
+ protected Task OnEventUnhandledAsync(Event e, string state) => Task.CompletedTask;
+
+ ///
+ /// Asynchronous callback that is invoked when the state machine handles an exception.
+ ///
+ /// The exception thrown by the state machine.
+ /// The event being handled when the exception was thrown.
+ /// The action that the runtime should take.
+ protected Task OnExceptionHandledAsync(Exception ex, Event e) => Task.CompletedTask;
+
+ ///
+ /// Asynchronous callback that is invoked when the state machine halts.
+ ///
+ /// The event being handled when the state machine halted.
+ /// Task that represents the asynchronous operation.
+ protected Task OnHaltAsync(Event e) => Task.CompletedTask;
+
+ ///
+ /// Halts the state machine.
+ ///
+ /// The event being handled when the state machine halts.
+ private protected Task HaltAsync(Event e)
+ {
+ CurrentStatus = Status.Halted;
+
+ // Close the inbox, which will stop any subsequent enqueues.
+ Inbox.Close();
+
+ Runtime.LogWriter.LogHalt(Id, Inbox.Size);
+
+ // Dispose any held resources.
+ Inbox.Dispose();
+ // Invoke user callback.
+ return OnHaltAsync(e);
+ }
+
///
- /// Initializes the actor with the specified optional event.
+ /// Initializes the state machine with the specified optional event.
///
/// Optional event used for initialization.
- internal override async Task InitializeAsync(Event initialEvent)
+ internal async Task InitializeAsync(Event initialEvent)
{
// Invoke the custom initializer, if there is one.
await InvokeUserCallbackAsync(UserCallbackType.OnInitialize, initialEvent);
@@ -115,6 +461,480 @@ internal override async Task InitializeAsync(Event initialEvent)
await HaltAsync(initialEvent);
}
}
+
+ ///
+ /// An exception filter that calls,
+ /// which can choose to fast-fail the app to get a full dump.
+ ///
+ /// The action being executed when the failure occurred.
+ /// The exception being tested.
+ private protected bool InvokeOnFailureExceptionFilter(CachedDelegate action, Exception ex)
+ {
+ // This is called within the exception filter so the stack has not yet been unwound.
+ // If the call does not fail-fast, return false to process the exception normally.
+ Runtime.RaiseOnFailureEvent(new ActionExceptionFilterException(action.MethodInfo.Name, ex));
+ return false;
+ }
+
+ ///
+ /// Tries to handle an exception thrown during an action invocation.
+ ///
+ private protected Task TryHandleActionInvocationExceptionAsync(Exception ex, string actionName)
+ {
+ var innerException = ex;
+ while (innerException is TargetInvocationException)
+ {
+ innerException = innerException.InnerException;
+ }
+
+ if (innerException is AggregateException)
+ {
+ innerException = innerException.InnerException;
+ }
+
+ if (innerException is ExecutionCanceledException || innerException is TaskSchedulerException)
+ {
+ CurrentStatus = Status.Halted;
+ Debug.WriteLine($" {innerException.GetType().Name} was thrown from {Id}.");
+ }
+ else
+ {
+ // Reports the unhandled exception.
+ ReportUnhandledException(innerException, actionName);
+ }
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Creates a new state machine of the specified type and name, and with the specified
+ /// optional . This can only be used to
+ /// access its payload, and cannot be handled.
+ ///
+ /// Type of the state machine.
+ /// Optional name used for logging.
+ /// Optional initialization event.
+ /// Optional id that can be used to identify this operation.
+ /// The unique state machine id.
+ protected StateMachineId CreateStateMachine(Type type, string name, Event initialEvent = null) =>
+ Runtime.CreateStateMachine(null, type, name, initialEvent, this);
+
+
+ ///
+ /// Sends an asynchronous to a target.
+ ///
+ /// The target.
+ /// The event to send.
+ /// Optional id that can be used to identify this operation.
+ public void SendEvent(PMachineValue target, Event ev)
+ {
+ Assert(ev != null, "Machine cannot send a null event");
+ Assert(target != null, "Machine in send cannot be null");
+ Assert(sends.Contains(ev.GetType().Name),
+ $"Event {ev.GetType().Name} is not in the sends set of the Machine {GetType().Name}");
+ Assert(target.Permissions.Contains(ev.GetType().Name),
+ $"Event {ev.GetType().Name} is not in the permissions set of the target machine");
+ AnnounceInternal(ev);
+ Runtime.SendEvent(target.Id, ev, this);
+ }
+
+ ///
+ /// Waits to receive an of the specified type
+ /// that satisfies an optional predicate.
+ ///
+ /// The event type.
+ /// The optional predicate.
+ /// The received event.
+ public Task ReceiveEventAsync(Type eventType, Func predicate = null)
+ {
+ Assert(CurrentStatus is Status.Active, "{0} invoked ReceiveEventAsync while halting.", Id);
+ Runtime.NotifyReceiveCalled(this);
+ return Inbox.ReceiveEventAsync(eventType, predicate);
+ }
+
+ ///
+ /// Waits to receive an of the specified types.
+ ///
+ /// The event types to wait for.
+ /// The received event.
+ public Task ReceiveEventAsync(params Type[] eventTypes)
+ {
+ Assert(CurrentStatus is Status.Active, "{0} invoked ReceiveEventAsync while halting.", Id);
+ Runtime.NotifyReceiveCalled(this);
+ return Inbox.ReceiveEventAsync(eventTypes);
+ }
+
+ ///
+ /// Waits to receive an of the specified types
+ /// that satisfy the specified predicates.
+ ///
+ /// Event types and predicates.
+ /// The received event.
+ public Task ReceiveEventAsync(params Tuple>[] events)
+ {
+ Assert(CurrentStatus is Status.Active, "{0} invoked ReceiveEventAsync while halting.", Id);
+ Runtime.NotifyReceiveCalled(this);
+ return Inbox.ReceiveEventAsync(events);
+ }
+
+ ///
+ /// Runs the event handler. The handler terminates if there is no next
+ /// event to process or if the state machine has halted.
+ ///
+ internal async Task RunEventHandlerAsync()
+ {
+ Event lastDequeuedEvent = null;
+ while (CurrentStatus != Status.Halted && Runtime.IsRunning)
+ {
+ (var status, var e, var info) = Inbox.Dequeue();
+
+ if (status is DequeueStatus.Success)
+ {
+ // Notify the runtime for a new event to handle. This is only used
+ // during bug-finding and operation bounding, because the runtime
+ // has to schedule an state machine when a new operation is dequeued.
+ Runtime.NotifyDequeuedEvent(this, e, info);
+ await InvokeUserCallbackAsync(UserCallbackType.OnEventDequeued, e);
+ lastDequeuedEvent = e;
+ }
+ else if (status is DequeueStatus.Raised)
+ {
+ // Only supported by types (e.g. StateMachine) that allow
+ // the user to explicitly raise events.
+ Runtime.NotifyHandleRaisedEvent(this, e);
+ }
+ else if (status is DequeueStatus.Default)
+ {
+ Runtime.LogWriter.LogDefaultEventHandler(Id, CurrentStateName);
+
+ // If the default event was dequeued, then notify the runtime.
+ // This is only used during bug-finding, because the runtime must
+ // instrument a scheduling point between default event handlers.
+ Runtime.NotifyDefaultEventDequeued(this);
+ }
+ else if (status is DequeueStatus.NotAvailable)
+ {
+ // Terminate the handler as there is no event available.
+ break;
+ }
+
+ if (CurrentStatus is Status.Active)
+ {
+ // Handles the next event, if the state machine is not halted.
+ await HandleEventAsync(e);
+ }
+
+ if (!Inbox.IsEventRaised && lastDequeuedEvent != null && CurrentStatus != Status.Halted)
+ {
+ // Inform the user that the state machine handled the dequeued event.
+ await InvokeUserCallbackAsync(UserCallbackType.OnEventHandled, lastDequeuedEvent);
+ lastDequeuedEvent = null;
+ }
+
+ if (CurrentStatus is Status.Halting)
+ {
+ // If the current status is halting, then halt the state machine.
+ await HaltAsync(e);
+ }
+ }
+ }
+
+ ///
+ /// Invokes the specified event handler user callback.
+ ///
+ private protected async Task InvokeUserCallbackAsync(string callbackType, Event e, string currentState = default)
+ {
+ try
+ {
+ Task task = null;
+ if (callbackType is UserCallbackType.OnInitialize)
+ {
+ task = OnInitializeAsync(e);
+ }
+ else if (callbackType is UserCallbackType.OnEventDequeued)
+ {
+ task = OnEventDequeuedAsync(e);
+ }
+ else if (callbackType is UserCallbackType.OnEventHandled)
+ {
+ task = OnEventHandledAsync(e);
+ }
+ else if (callbackType is UserCallbackType.OnEventUnhandled)
+ {
+ task = OnEventUnhandledAsync(e, currentState);
+ }
+
+ Runtime.NotifyWaitTask(this, task);
+ await task;
+ }
+ catch (Exception ex) when (OnExceptionHandler(ex, callbackType, e))
+ {
+ // User handled the exception.
+ await OnExceptionHandledAsync(ex, e);
+ }
+ catch (Exception ex)
+ {
+ // Reports the unhandled exception.
+ await TryHandleActionInvocationExceptionAsync(ex, callbackType);
+ }
+ }
+
+ ///
+ /// Invokes the specified action delegate.
+ ///
+ private protected async Task InvokeActionAsync(CachedDelegate cachedAction, Event e)
+ {
+ try
+ {
+ if (cachedAction.IsAsync)
+ {
+ Task task = null;
+ if (cachedAction.Handler is Func taskFuncWithEvent)
+ {
+ task = taskFuncWithEvent(e);
+ }
+ else if (cachedAction.Handler is Func taskFunc)
+ {
+ task = taskFunc();
+ }
+
+ Runtime.NotifyWaitTask(this, task);
+
+ // We have no reliable stack for awaited operations.
+ await task;
+ }
+ else if (cachedAction.Handler is Action actionWithEvent)
+ {
+ actionWithEvent(e);
+ }
+ else if (cachedAction.Handler is Action action)
+ {
+ action();
+ }
+ }
+ catch (Exception ex) when (OnExceptionHandler(ex, cachedAction.MethodInfo.Name, e))
+ {
+ // User handled the exception.
+ await OnExceptionHandledAsync(ex, e);
+ }
+ catch (Exception ex) when (!cachedAction.IsAsync && InvokeOnFailureExceptionFilter(cachedAction, ex))
+ {
+ // Use an exception filter to call OnFailure before the stack
+ // has been unwound. If the exception filter does not fail-fast,
+ // it returns false to process the exception normally.
+ }
+ catch (Exception ex)
+ {
+ await TryHandleActionInvocationExceptionAsync(ex, cachedAction.MethodInfo.Name);
+ }
+ }
+
+ ///
+ /// Returns the action with the specified name.
+ ///
+ private protected MethodInfo GetActionWithName(string actionName)
+ {
+ MethodInfo action;
+ var stateMachineType = GetType();
+
+ do
+ {
+ var bindingFlags = BindingFlags.Public | BindingFlags.NonPublic |
+ BindingFlags.Instance | BindingFlags.FlattenHierarchy;
+ action = stateMachineType.GetMethod(actionName, bindingFlags, Type.DefaultBinder, SingleEventTypeArray, null);
+ if (action is null)
+ {
+ action = stateMachineType.GetMethod(actionName, bindingFlags, Type.DefaultBinder, Array.Empty(), null);
+ }
+
+ stateMachineType = stateMachineType.BaseType;
+ }
+ while (action is null && stateMachineType != typeof(StateMachine));
+
+ Assert(action != null, "Cannot detect action declaration '{0}' in '{1}'.", actionName, GetType().FullName);
+ AssertActionValidity(action);
+ return action;
+ }
+
+ ///