Best Coyote code snippet using Microsoft.Coyote.Actors.Coverage.GraphNode
ActorRuntimeLogGraphBuilder.cs
Source:ActorRuntimeLogGraphBuilder.cs  
...107        {108            lock (this.Inbox)109            {110                var resolvedId = this.GetResolveActorId(id?.Name, id?.Type);111                GraphNode node = this.Graph.GetOrCreateNode(resolvedId);112                node.Category = ActorCategory;113                if (!string.IsNullOrEmpty(creatorName))114                {115                    var creatorId = this.GetResolveActorId(creatorName, creatorType);116                    GraphNode creator = this.Graph.GetOrCreateNode(creatorId);117                    this.GetOrCreateEventLink(creator, node, new EventInfo() { Event = "CreateActor" });118                }119            }120        }121        /// <inheritdoc/>122        public void OnCreateStateMachine(ActorId id, string creatorName, string creatorType)123        {124            lock (this.Inbox)125            {126                var resolvedId = this.GetResolveActorId(id?.Name, id?.Type);127                GraphNode node = this.Graph.GetOrCreateNode(resolvedId);128                node.Category = StateMachineCategory;129                if (!string.IsNullOrEmpty(creatorName))130                {131                    var creatorId = this.GetResolveActorId(creatorName, creatorType);132                    GraphNode creator = this.Graph.GetOrCreateNode(creatorId);133                    this.GetOrCreateEventLink(creator, node, new EventInfo() { Event = "CreateActor" });134                }135            }136        }137        /// <inheritdoc/>138        public void OnSendEvent(ActorId targetActorId, string senderName, string senderType, string senderStateName,139            Event e, Guid eventGroupId, bool isTargetHalted)140        {141            string eventName = e.GetType().FullName;142            this.AddEvent(targetActorId.Name, targetActorId.Type, senderName, senderType, senderStateName, eventName);143        }144        /// <inheritdoc/>145        public void OnRaiseEvent(ActorId id, string stateName, Event e)146        {147            string eventName = e.GetType().FullName;148            // Raising event to self.149            this.AddEvent(id.Name, id.Type, id.Name, id.Type, stateName, eventName);150        }151        /// <inheritdoc/>152        public void OnHandleRaisedEvent(ActorId id, string stateName, Event e)153        {154            lock (this.Inbox)155            {156                // We used the inbox to store raised event, but it should be the first one handled since157                // raised events are highest priority.158                string resolvedId = this.GetResolveActorId(id?.Name, id?.Type);159                lock (this.Inbox)160                {161                    if (this.Inbox.TryGetValue(resolvedId, out List<EventInfo> inbox))162                    {163                        string eventName = e.GetType().FullName;164                        for (int i = inbox.Count - 1; i >= 0; i--)165                        {166                            EventInfo info = inbox[i];167                            if (info.Event == eventName)168                            {169                                this.Dequeued[id] = info;170                                break;171                            }172                        }173                    }174                }175            }176        }177        /// <inheritdoc/>178        public void OnEnqueueEvent(ActorId id, Event e)179        {180        }181        /// <inheritdoc/>182        public void OnDequeueEvent(ActorId id, string stateName, Event e)183        {184            lock (this.Inbox)185            {186                var resolvedId = this.GetResolveActorId(id?.Name, id?.Type);187                string eventName = e.GetType().FullName;188                EventInfo info = this.PopEvent(resolvedId, eventName);189                if (info != null)190                {191                    this.Dequeued[id] = info;192                }193            }194        }195        private EventInfo PopEvent(string resolvedId, string eventName)196        {197            EventInfo result = null;198            lock (this.Inbox)199            {200                if (this.Inbox.TryGetValue(resolvedId, out List<EventInfo> inbox))201                {202                    for (int i = inbox.Count - 1; i >= 0; i--)203                    {204                        if (inbox[i].Event == eventName)205                        {206                            result = inbox[i];207                            inbox.RemoveAt(i);208                        }209                    }210                }211            }212            return result;213        }214        /// <inheritdoc/>215        public void OnReceiveEvent(ActorId id, string stateName, Event e, bool wasBlocked)216        {217            string resolvedId = this.GetResolveActorId(id?.Name, id?.Type);218            lock (this.Inbox)219            {220                if (this.Inbox.TryGetValue(resolvedId, out List<EventInfo> inbox))221                {222                    string eventName = e.GetType().FullName;223                    for (int i = inbox.Count - 1; i >= 0; i--)224                    {225                        EventInfo info = inbox[i];226                        if (info.Event == eventName)227                        {228                            // Yay, found it so we can draw the complete link connecting the Sender state to this state!229                            string category = string.IsNullOrEmpty(stateName) ? ActorCategory : StateMachineCategory;230                            var source = this.GetOrCreateChild(info.Name, info.Type, info.State);231                            var target = this.GetOrCreateChild(id?.Name, id?.Type, category, stateName);232                            this.GetOrCreateEventLink(source, target, info);233                            inbox.RemoveAt(i);234                            break;235                        }236                    }237                }238            }239        }240        /// <inheritdoc/>241        public void OnWaitEvent(ActorId id, string stateName, Type eventType)242        {243        }244        /// <inheritdoc/>245        public void OnWaitEvent(ActorId id, string stateName, params Type[] eventTypes)246        {247        }248        /// <inheritdoc/>249        public void OnStateTransition(ActorId id, string stateName, bool isEntry)250        {251            if (isEntry)252            {253                // record the fact we have entered this state254                this.GetOrCreateChild(id?.Name, id?.Type, stateName);255            }256        }257        /// <inheritdoc/>258        public void OnExecuteAction(ActorId id, string handlingStateName, string currentStateName, string actionName)259        {260            this.LinkTransition(typeof(DoActionEvent), id, handlingStateName, currentStateName, null);261        }262        /// <inheritdoc/>263        public void OnGotoState(ActorId id, string currentStateName, string newStateName)264        {265            this.LinkTransition(typeof(GotoStateEvent), id, currentStateName, currentStateName, newStateName);266        }267        /// <inheritdoc/>268        public void OnPushState(ActorId id, string currentStateName, string newStateName)269        {270            this.LinkTransition(typeof(PushStateEvent), id, currentStateName, currentStateName, newStateName);271        }272        /// <inheritdoc/>273        public void OnPopState(ActorId id, string currentStateName, string restoredStateName)274        {275            if (!string.IsNullOrEmpty(currentStateName))276            {277                this.LinkTransition(typeof(PopStateEvent), id, currentStateName,278                    currentStateName, restoredStateName);279            }280        }281        /// <inheritdoc/>282        public void OnHalt(ActorId id, int inboxSize)283        {284            lock (this.Inbox)285            {286                this.HaltedStates.TryGetValue(id, out string stateName);287                var target = this.GetOrCreateChild(id?.Name, id?.Type, "Halt", "Halt");288                // Transition to the Halt state.289                if (!string.IsNullOrEmpty(stateName))290                {291                    var source = this.GetOrCreateChild(id?.Name, id?.Type, stateName);292                    this.GetOrCreateEventLink(source, target, new EventInfo() { Event = typeof(HaltEvent).FullName });293                }294            }295        }296        private int? GetLinkIndex(GraphNode source, GraphNode target, string id)297        {298            if (this.MergeEventLinks)299            {300                return null;301            }302            return this.Graph.GetUniqueLinkIndex(source, target, id);303        }304        /// <inheritdoc/>305        public void OnDefaultEventHandler(ActorId id, string stateName)306        {307            lock (this.Inbox)308            {309                string resolvedId = this.GetResolveActorId(id?.Name, id?.Type);310                string eventName = typeof(DefaultEvent).FullName;311                this.AddEvent(id.Name, id.Type, id.Name, id.Type, stateName, eventName);312                this.Dequeued[id] = this.PopEvent(resolvedId, eventName);313            }314        }315        /// <inheritdoc/>316        public void OnEventHandlerTerminated(ActorId id, string stateName, DequeueStatus dequeueStatus)317        {318        }319        /// <inheritdoc/>320        public void OnPopStateUnhandledEvent(ActorId actorId, string currentStateName, Event e)321        {322            lock (this.Inbox)323            {324                if (e is HaltEvent)325                {326                    this.HaltedStates[actorId] = currentStateName;327                }328            }329        }330        /// <inheritdoc/>331        public void OnExceptionThrown(ActorId id, string stateName, string actionName, Exception ex)332        {333        }334        /// <inheritdoc/>335        public void OnExceptionHandled(ActorId id, string stateName, string actionName, Exception ex)336        {337        }338        /// <inheritdoc/>339        public void OnCreateTimer(TimerInfo info)340        {341            // TODO: figure out how to graph timers when we have no "timer id" at this point...342        }343        /// <inheritdoc/>344        public void OnStopTimer(TimerInfo info)345        {346        }347        /// <inheritdoc/>348        public void OnCreateMonitor(string monitorType)349        {350            lock (this.Inbox)351            {352                GraphNode node = this.Graph.GetOrCreateNode(monitorType, monitorType);353                node.Category = MonitorCategory;354            }355        }356        /// <inheritdoc/>357        public void OnMonitorExecuteAction(string monitorType, string stateName, string actionName)358        {359            // Monitors process actions immediately, so this state transition is a result of the only event in the inbox.360            lock (this.Inbox)361            {362                if (this.Inbox.TryGetValue(monitorType, out List<EventInfo> inbox) && inbox.Count > 0)363                {364                    var e = inbox[inbox.Count - 1];365                    inbox.RemoveAt(inbox.Count - 1);366                    // Draw the link connecting the Sender state to this state!367                    var source = this.GetOrCreateChild(e.Name, e.Type, e.State);368                    var target = this.GetOrCreateChild(monitorType, monitorType, stateName);369                    this.GetOrCreateEventLink(source, target, e);370                }371            }372        }373        /// <inheritdoc/>374        public void OnMonitorProcessEvent(string monitorType, string stateName, string senderName, string senderType,375            string senderStateName, Event e)376        {377            lock (this.Inbox)378            {379                string eventName = e.GetType().FullName;380                // Now add a fake event for internal monitor state transition that might now happen as a result of this event,381                // storing the monitor's current state in this event.382                var info = this.AddEvent(monitorType, monitorType, monitorType, monitorType, stateName, eventName);383                // Draw the link connecting the Sender state to this state!384                var source = this.GetOrCreateChild(senderName, senderType, senderStateName);385                var target = this.GetOrCreateChild(monitorType, monitorType, stateName);386                this.GetOrCreateEventLink(source, target, info);387            }388        }389        /// <inheritdoc/>390        public void OnMonitorRaiseEvent(string monitorType, string stateName, Event e)391        {392            // Raising event to self.393            string eventName = e.GetType().FullName;394            this.AddEvent(monitorType, monitorType, monitorType, monitorType, stateName, eventName);395        }396        /// <inheritdoc/>397        public void OnMonitorStateTransition(string monitorType, string stateName, bool isEntry, bool? isInHotState)398        {399            if (isEntry)400            {401                lock (this.Inbox)402                {403                    // Monitors process events immediately (and does not call OnDequeue), so this state transition is a result of404                    // the fake event we created in OnMonitorProcessEvent.405                    if (this.Inbox.TryGetValue(monitorType, out List<EventInfo> inbox) && inbox.Count > 0)406                    {407                        var info = inbox[inbox.Count - 1];408                        inbox.RemoveAt(inbox.Count - 1);409                        // draw the link connecting the current state to this new state!410                        var source = this.GetOrCreateChild(monitorType, monitorType, info.State);411                        var shortStateName = this.GetLabel(monitorType, monitorType, stateName);412                        if (isInHotState.HasValue)413                        {414                            string suffix = (isInHotState is true) ? "[hot]" : "[cold]";415                            shortStateName += suffix;416                        }417                        string label = shortStateName;418                        var target = this.GetOrCreateChild(monitorType, monitorType, shortStateName, label);419                        // In case this node was already created, we may need to override the label here now that420                        // we know this is a hot state. This is because, unfortunately, other OnMonitor* methods421                        // do not provide the isInHotState parameter.422                        target.Label = label;423                        this.GetOrCreateEventLink(source, target, info);424                    }425                }426            }427        }428        /// <inheritdoc/>429        public void OnMonitorError(string monitorType, string stateName, bool? isInHotState)430        {431            var source = this.GetOrCreateChild(monitorType, monitorType, stateName);432            source.Category = "Error";433        }434        /// <inheritdoc/>435        public void OnRandom(bool result, string callerName, string callerType)436        {437        }438        /// <inheritdoc/>439        public void OnRandom(int result, string callerName, string callerType)440        {441        }442        /// <inheritdoc/>443        public void OnAssertionFailure(string error)444        {445        }446        /// <inheritdoc/>447        public void OnCompleted()448        {449        }450        /// <summary>451        /// Return current graph and reset for next iteration.452        /// </summary>453        /// <param name="reset">Set to true will reset the graph for the next iteration.</param>454        /// <returns>The graph.</returns>455        internal Graph SnapshotGraph(bool reset)456        {457            Graph result = this.CurrentGraph;458            if (reset)459            {460                // Reset the graph to start fresh.461                this.CurrentGraph = null;462            }463            return result;464        }465        private string GetResolveActorId(string name, string type)466        {467            if (type is null)468            {469                // The sender id can be null if an event is fired from non-actor code.470                return ExternalCodeName;471            }472            if (this.CollapseInstances)473            {474                return type;475            }476            return name;477        }478        private EventInfo AddEvent(string targetName, string targetType, string senderName, string senderType,479            string senderStateName, string eventName)480        {481            string targetId = this.GetResolveActorId(targetName, targetType);482            EventInfo info = null;483            lock (this.Inbox)484            {485                if (!this.Inbox.TryGetValue(targetId, out List<EventInfo> inbox))486                {487                    inbox = new List<EventInfo>();488                    this.Inbox[targetId] = inbox;489                }490                info = new EventInfo()491                {492                    Name = senderName ?? ExternalCodeName,493                    Type = senderType ?? ExternalCodeName,494                    State = senderStateName,495                    Event = eventName496                };497                inbox.Add(info);498            }499            return info;500        }501        private void LinkTransition(Type transitionType, ActorId id, string handlingStateName,502            string currentStateName, string newStateName)503        {504            string name = id.Name;505            string type = id.Type;506            lock (this.Inbox)507            {508                if (this.Dequeued.TryGetValue(id, out EventInfo info))509                {510                    // Event was dequeued, but now we know what state is handling this event, so connect the dots...511                    if (info.Type != type || info.Name != name || info.State != currentStateName)512                    {513                        var source = this.GetOrCreateChild(info.Name, info.Type, info.State);514                        var target = this.GetOrCreateChild(name, type, currentStateName);515                        info.HandlingState = handlingStateName;516                        this.GetOrCreateEventLink(source, target, info);517                    }518                }519                if (newStateName != null)520                {521                    // Then this is a goto or push and we can draw that link also.522                    var source = this.GetOrCreateChild(name, type, currentStateName);523                    var target = this.GetOrCreateChild(name, type, newStateName);524                    if (info is null)525                    {526                        info = new EventInfo { Event = transitionType.FullName };527                    }528                    this.GetOrCreateEventLink(source, target, info);529                }530                this.Dequeued.Remove(id);531            }532        }533        private GraphNode GetOrCreateChild(string name, string type, string stateName, string label = null)534        {535            GraphNode child = null;536            lock (this.Inbox)537            {538                this.AddNamespace(type);539                var initalStateName = stateName;540                // make label relative to fully qualified actor id (it's usually a nested class).541                stateName = this.GetLabel(name, type, stateName);542                string id = this.GetResolveActorId(name, type);543                GraphNode parent = this.Graph.GetOrCreateNode(id);544                parent.AddAttribute("Group", "Expanded");545                if (string.IsNullOrEmpty(label))546                {547                    label = stateName ?? ExternalStateName;548                }549                if (!string.IsNullOrEmpty(stateName))550                {551                    id += "." + stateName;552                }553                child = this.Graph.GetOrCreateNode(id, label);554                this.Graph.GetOrCreateLink(parent, child, null, null, "Contains");555            }556            return child;557        }558        private GraphLink GetOrCreateEventLink(GraphNode source, GraphNode target, EventInfo e)559        {560            GraphLink link = null;561            lock (this.Inbox)562            {563                string label = this.GetEventLabel(e.Event);564                var index = this.GetLinkIndex(source, target, label);565                var category = GetEventCategory(e.Event);566                link = this.Graph.GetOrCreateLink(source, target, index, label, category);567                if (this.MergeEventLinks)568                {569                    if (link.AddListAttribute("EventIds", e.Event) > 1)570                    {571                        link.Label = "*";572                    }573                }574                else575                {576                    if (e.Event != null)577                    {578                        link.AddAttribute("EventId", e.Event);579                    }580                    if (e.HandlingState != null)581                    {582                        link.AddAttribute("HandledBy", e.HandlingState);583                    }584                }585            }586            return link;587        }588        private void AddNamespace(string type)589        {590            if (type != null && !this.Namespaces.Contains(type))591            {592                string typeName = type;593                int index = typeName.Length;594                do595                {596                    typeName = typeName.Substring(0, index);597                    this.Namespaces.Add(typeName);598                    index = typeName.LastIndexOfAny(TypeSeparators);599                }600                while (index > 0);601            }602        }603        private string GetLabel(string name, string type, string fullyQualifiedName)604        {605            if (type is null)606            {607                // external code608                return fullyQualifiedName;609            }610            this.AddNamespace(type);611            if (string.IsNullOrEmpty(fullyQualifiedName))612            {613                // then this is probably an Actor, not a StateMachine.  For Actors we can invent a state614                // name equal to the short name of the class, this then looks like a Constructor which is fine.615                fullyQualifiedName = this.CollapseInstances ? type : name;616            }617            var index = fullyQualifiedName.LastIndexOfAny(TypeSeparators);618            if (index > 0)619            {620                fullyQualifiedName = fullyQualifiedName.Substring(index).Trim('+').Trim('.');621            }622            return fullyQualifiedName;623        }624        private string GetEventLabel(string fullyQualifiedName)625        {626            if (EventAliases.TryGetValue(fullyQualifiedName, out string label))627            {628                return label;629            }630            int i = fullyQualifiedName.LastIndexOfAny(TypeSeparators);631            if (i > 0)632            {633                string ns = fullyQualifiedName.Substring(0, i);634                if (this.Namespaces.Contains(ns))635                {636                    return fullyQualifiedName.Substring(i + 1);637                }638            }639            return fullyQualifiedName;640        }641        private static string GetEventCategory(string fullyQualifiedName)642        {643            if (EventAliases.TryGetValue(fullyQualifiedName, out string label))644            {645                return label;646            }647            return null;648        }649    }650    /// <summary>651    /// A directed graph made up of Nodes and Links.652    /// </summary>653    [DataContract]654    public class Graph655    {656        internal const string DgmlNamespace = "http://schemas.microsoft.com/vs/2009/dgml";657        // These [DataMember] fields are here so we can serialize the Graph across parallel or distributed658        // test processes without losing any information.  There is more information here than in the serialized659        // DGML which is we we can't just use Save/LoadDgml to do the same.660        [DataMember]661        private readonly Dictionary<string, GraphNode> InternalNodes = new Dictionary<string, GraphNode>();662        [DataMember]663        private readonly Dictionary<string, GraphLink> InternalLinks = new Dictionary<string, GraphLink>();664        // last used index for simple link key "a->b".665        [DataMember]666        private readonly Dictionary<string, int> InternalNextLinkIndex = new Dictionary<string, int>();667        // maps augmented link key to the index that has been allocated for that link id "a->b(goto)" => 0668        [DataMember]669        private readonly Dictionary<string, int> InternalAllocatedLinkIndexes = new Dictionary<string, int>();670        [DataMember]671        private readonly Dictionary<string, string> InternalAllocatedLinkIds = new Dictionary<string, string>();672        /// <summary>673        /// Return the current list of nodes (in no particular order).674        /// </summary>675        public IEnumerable<GraphNode> Nodes676        {677            get { return this.InternalNodes.Values; }678        }679        /// <summary>680        /// Return the current list of links (in no particular order).681        /// </summary>682        public IEnumerable<GraphLink> Links683        {684            get685            {686                if (this.InternalLinks is null)687                {688                    return Array.Empty<GraphLink>();689                }690                return this.InternalLinks.Values;691            }692        }693        /// <summary>694        /// Get existing node or null.695        /// </summary>696        /// <param name="id">The id of the node.</param>697        public GraphNode GetNode(string id)698        {699            this.InternalNodes.TryGetValue(id, out GraphNode node);700            return node;701        }702        /// <summary>703        /// Get existing node or create a new one with the given id and label.704        /// </summary>705        /// <returns>Returns the new node or the existing node if it was already defined.</returns>706        public GraphNode GetOrCreateNode(string id, string label = null, string category = null)707        {708            if (!this.InternalNodes.TryGetValue(id, out GraphNode node))709            {710                node = new GraphNode(id, label, category);711                this.InternalNodes.Add(id, node);712            }713            return node;714        }715        /// <summary>716        /// Get existing node or create a new one with the given id and label.717        /// </summary>718        /// <returns>Returns the new node or the existing node if it was already defined.</returns>719        private GraphNode GetOrCreateNode(GraphNode newNode)720        {721            if (!this.InternalNodes.ContainsKey(newNode.Id))722            {723                this.InternalNodes.Add(newNode.Id, newNode);724            }725            return newNode;726        }727        /// <summary>728        /// Get existing link or create a new one connecting the given source and target nodes.729        /// </summary>730        /// <returns>The new link or the existing link if it was already defined.</returns>731        public GraphLink GetOrCreateLink(GraphNode source, GraphNode target, int? index = null, string linkLabel = null, string category = null)732        {733            string key = source.Id + "->" + target.Id;734            if (index.HasValue)735            {736                key += string.Format("({0})", index.Value);737            }738            if (!this.InternalLinks.TryGetValue(key, out GraphLink link))739            {740                link = new GraphLink(source, target, linkLabel, category);741                if (index.HasValue)742                {743                    link.Index = index.Value;744                }745                this.InternalLinks.Add(key, link);746            }747            return link;748        }749        internal int GetUniqueLinkIndex(GraphNode source, GraphNode target, string id)750        {751            // augmented key752            string key = string.Format("{0}->{1}({2})", source.Id, target.Id, id);753            if (this.InternalAllocatedLinkIndexes.TryGetValue(key, out int index))754            {755                return index;756            }757            // allocate a new index for the simple key758            var simpleKey = string.Format("{0}->{1}", source.Id, target.Id);759            if (this.InternalNextLinkIndex.TryGetValue(simpleKey, out index))760            {761                index++;762            }763            this.InternalNextLinkIndex[simpleKey] = index;764            // remember this index has been allocated for this link id.765            this.InternalAllocatedLinkIndexes[key] = index;766            // remember the original id associated with this link index.767            key = string.Format("{0}->{1}({2})", source.Id, target.Id, index);768            this.InternalAllocatedLinkIds[key] = id;769            return index;770        }771        /// <summary>772        /// Serialize the graph to a DGML string.773        /// </summary>774        public override string ToString()775        {776            using var writer = new StringWriter();777            this.WriteDgml(writer, false);778            return writer.ToString();779        }780        internal void SaveDgml(string graphFilePath, bool includeDefaultStyles)781        {782            using StreamWriter writer = new StreamWriter(graphFilePath, false, Encoding.UTF8);783            this.WriteDgml(writer, includeDefaultStyles);784        }785        /// <summary>786        /// Serialize the graph to DGML.787        /// </summary>788        public void WriteDgml(TextWriter writer, bool includeDefaultStyles)789        {790            writer.WriteLine("<DirectedGraph xmlns='{0}'>", DgmlNamespace);791            writer.WriteLine("  <Nodes>");792            if (this.InternalNodes != null)793            {794                List<string> nodes = new List<string>(this.InternalNodes.Keys);795                nodes.Sort(StringComparer.Ordinal);796                foreach (var id in nodes)797                {798                    GraphNode node = this.InternalNodes[id];799                    writer.Write("    <Node Id='{0}'", node.Id);800                    if (!string.IsNullOrEmpty(node.Label))801                    {802                        writer.Write(" Label='{0}'", node.Label);803                    }804                    if (!string.IsNullOrEmpty(node.Category))805                    {806                        writer.Write(" Category='{0}'", node.Category);807                    }808                    node.WriteAttributes(writer);809                    writer.WriteLine("/>");810                }811            }812            writer.WriteLine("  </Nodes>");813            writer.WriteLine("  <Links>");814            if (this.InternalLinks != null)815            {816                List<string> links = new List<string>(this.InternalLinks.Keys);817                links.Sort(StringComparer.Ordinal);818                foreach (var id in links)819                {820                    GraphLink link = this.InternalLinks[id];821                    writer.Write("    <Link Source='{0}' Target='{1}'", link.Source.Id, link.Target.Id);822                    if (!string.IsNullOrEmpty(link.Label))823                    {824                        writer.Write(" Label='{0}'", link.Label);825                    }826                    if (!string.IsNullOrEmpty(link.Category))827                    {828                        writer.Write(" Category='{0}'", link.Category);829                    }830                    if (link.Index.HasValue)831                    {832                        writer.Write(" Index='{0}'", link.Index.Value);833                    }834                    link.WriteAttributes(writer);835                    writer.WriteLine("/>");836                }837            }838            writer.WriteLine("  </Links>");839            if (includeDefaultStyles)840            {841                writer.WriteLine(842@"  <Styles>843    <Style TargetType=""Node"" GroupLabel=""Error"" ValueLabel=""True"">844      <Condition Expression=""HasCategory('Error')"" />845      <Setter Property=""Background"" Value=""#FFC15656"" />846    </Style>847    <Style TargetType=""Node"" GroupLabel=""Actor"" ValueLabel=""True"">848      <Condition Expression=""HasCategory('Actor')"" />849      <Setter Property=""Background"" Value=""#FF57AC56"" />850    </Style>851    <Style TargetType=""Node"" GroupLabel=""Monitor"" ValueLabel=""True"">852      <Condition Expression=""HasCategory('Monitor')"" />853      <Setter Property=""Background"" Value=""#FF558FDA"" />854    </Style>855    <Style TargetType=""Link"" GroupLabel=""halt"" ValueLabel=""True"">856      <Condition Expression=""HasCategory('halt')"" />857      <Setter Property=""Stroke"" Value=""#FFFF6C6C"" />858      <Setter Property=""StrokeDashArray"" Value=""4 2"" />859    </Style>860    <Style TargetType=""Link"" GroupLabel=""push"" ValueLabel=""True"">861      <Condition Expression=""HasCategory('push')"" />862      <Setter Property=""Stroke"" Value=""#FF7380F5"" />863      <Setter Property=""StrokeDashArray"" Value=""4 2"" />864    </Style>865    <Style TargetType=""Link"" GroupLabel=""pop"" ValueLabel=""True"">866      <Condition Expression=""HasCategory('pop')"" />867      <Setter Property=""Stroke"" Value=""#FF7380F5"" />868      <Setter Property=""StrokeDashArray"" Value=""4 2"" />869    </Style>870  </Styles>");871            }872            writer.WriteLine("</DirectedGraph>");873        }874        /// <summary>875        /// Load a DGML file into a new Graph object.876        /// </summary>877        /// <param name="graphFilePath">Full path to the DGML file.</param>878        /// <returns>The loaded Graph object.</returns>879        public static Graph LoadDgml(string graphFilePath)880        {881            XDocument doc = XDocument.Load(graphFilePath);882            Graph result = new Graph();883            var ns = doc.Root.Name.Namespace;884            if (ns != DgmlNamespace)885            {886                throw new InvalidOperationException(string.Format(887                    "File '{0}' does not contain the DGML namespace", graphFilePath));888            }889            foreach (var e in doc.Root.Element(ns + "Nodes").Elements(ns + "Node"))890            {891                var id = (string)e.Attribute("Id");892                var label = (string)e.Attribute("Label");893                var category = (string)e.Attribute("Category");894                GraphNode node = new GraphNode(id, label, category);895                node.AddDgmlProperties(e);896                result.GetOrCreateNode(node);897            }898            foreach (var e in doc.Root.Element(ns + "Links").Elements(ns + "Link"))899            {900                var srcId = (string)e.Attribute("Source");901                var targetId = (string)e.Attribute("Target");902                var label = (string)e.Attribute("Label");903                var category = (string)e.Attribute("Category");904                var srcNode = result.GetOrCreateNode(srcId);905                var targetNode = result.GetOrCreateNode(targetId);906                XAttribute indexAttr = e.Attribute("index");907                int? index = null;908                if (indexAttr != null)909                {910                    index = (int)indexAttr;911                }912                var link = result.GetOrCreateLink(srcNode, targetNode, index, label, category);913                link.AddDgmlProperties(e);914            }915            return result;916        }917        /// <summary>918        /// Merge the given graph so that this graph becomes a superset of both graphs.919        /// </summary>920        /// <param name="other">The new graph to merge into this graph.</param>921        public void Merge(Graph other)922        {923            foreach (var node in other.InternalNodes.Values)924            {925                var newNode = this.GetOrCreateNode(node.Id, node.Label, node.Category);926                newNode.Merge(node);927            }928            foreach (var link in other.InternalLinks.Values)929            {930                var source = this.GetOrCreateNode(link.Source.Id, link.Source.Label, link.Source.Category);931                var target = this.GetOrCreateNode(link.Target.Id, link.Target.Label, link.Target.Category);932                int? index = null;933                if (link.Index.HasValue)934                {935                    // ouch, link indexes cannot be compared across Graph instances, we need to assign a new index here.936                    string key = string.Format("{0}->{1}({2})", source.Id, target.Id, link.Index.Value);937                    string linkId = other.InternalAllocatedLinkIds[key];938                    index = this.GetUniqueLinkIndex(source, target, linkId);939                }940                var newLink = this.GetOrCreateLink(source, target, index, link.Label, link.Category);941                newLink.Merge(link);942            }943        }944    }945    /// <summary>946    /// A Node of a Graph.947    /// </summary>948    [DataContract]949    public class GraphObject950    {951        /// <summary>952        /// Optional list of attributes for the node.953        /// </summary>954        [DataMember]955        public Dictionary<string, string> Attributes { get; internal set; }956        /// <summary>957        /// Optional list of attributes that have a multi-part value.958        /// </summary>959        [DataMember]960        public Dictionary<string, HashSet<string>> AttributeLists { get; internal set; }961        /// <summary>962        /// Add an attribute to the node.963        /// </summary>964        public void AddAttribute(string name, string value)965        {966            if (this.Attributes is null)967            {968                this.Attributes = new Dictionary<string, string>();969            }970            this.Attributes[name] = value;971        }972        /// <summary>973        /// Creates a compound attribute value containing a merged list of unique values.974        /// </summary>975        /// <param name="key">The attribute name.</param>976        /// <param name="value">The new value to add to the unique list.</param>977        public int AddListAttribute(string key, string value)978        {979            if (this.AttributeLists is null)980            {981                this.AttributeLists = new Dictionary<string, HashSet<string>>();982            }983            if (!this.AttributeLists.TryGetValue(key, out HashSet<string> list))984            {985                list = new HashSet<string>();986                this.AttributeLists[key] = list;987            }988            list.Add(value);989            return list.Count;990        }991        internal void WriteAttributes(TextWriter writer)992        {993            if (this.Attributes != null)994            {995                List<string> names = new List<string>(this.Attributes.Keys);996                names.Sort(StringComparer.Ordinal);  // creates a more stable output file (can be handy for expected output during testing).997                foreach (string name in names)998                {999                    var value = this.Attributes[name];1000                    writer.Write(" {0}='{1}'", name, value);1001                }1002            }1003            if (this.AttributeLists != null)1004            {1005                List<string> names = new List<string>(this.AttributeLists.Keys);1006                names.Sort(StringComparer.Ordinal);  // creates a more stable output file (can be handy for expected output during testing).1007                foreach (string name in names)1008                {1009                    var value = this.AttributeLists[name];1010                    writer.Write(" {0}='{1}'", name, string.Join(",", value));1011                }1012            }1013        }1014        internal void Merge(GraphObject other)1015        {1016            if (other.Attributes != null)1017            {1018                foreach (var key in other.Attributes.Keys)1019                {1020                    this.AddAttribute(key, other.Attributes[key]);1021                }1022            }1023            if (other.AttributeLists != null)1024            {1025                foreach (var key in other.AttributeLists.Keys)1026                {1027                    foreach (var value in other.AttributeLists[key])1028                    {1029                        this.AddListAttribute(key, value);1030                    }1031                }1032            }1033        }1034    }1035    /// <summary>1036    /// A Node of a Graph.1037    /// </summary>1038    [DataContract]1039    public class GraphNode : GraphObject1040    {1041        /// <summary>1042        /// The unique Id of the Node within the Graph.1043        /// </summary>1044        [DataMember]1045        public string Id { get; internal set; }1046        /// <summary>1047        /// An optional display label for the node (does not need to be unique).1048        /// </summary>1049        [DataMember]1050        public string Label { get; internal set; }1051        /// <summary>1052        /// An optional category for the node.1053        /// </summary>1054        [DataMember]1055        public string Category { get; internal set; }1056        /// <summary>1057        /// Initializes a new instance of the <see cref="GraphNode"/> class.1058        /// </summary>1059        public GraphNode(string id, string label, string category)1060        {1061            this.Id = id;1062            this.Label = label;1063            this.Category = category;1064        }1065        /// <summary>1066        /// Add additional properties from XML element.1067        /// </summary>1068        /// <param name="e">An XML element representing the graph node in DGML format.</param>1069        public void AddDgmlProperties(XElement e)1070        {1071            foreach (XAttribute a in e.Attributes())1072            {1073                switch (a.Name.LocalName)1074                {1075                    case "Id":1076                    case "Label":1077                    case "Category":1078                        break;1079                    default:1080                        this.AddAttribute(a.Name.LocalName, a.Value);1081                        break;1082                }1083            }1084        }1085    }1086    /// <summary>1087    /// A Link represents a directed graph connection between two Nodes.1088    /// </summary>1089    [DataContract]1090    public class GraphLink : GraphObject1091    {1092        /// <summary>1093        /// An optional display label for the link.1094        /// </summary>1095        [DataMember]1096        public string Label { get; internal set; }1097        /// <summary>1098        /// An optional category for the link.1099        /// The special category "Contains" is reserved for building groups.1100        /// </summary>1101        [DataMember]1102        public string Category { get; internal set; }1103        /// <summary>1104        /// The source end of the link.1105        /// </summary>1106        [DataMember]1107        public GraphNode Source { get; internal set; }1108        /// <summary>1109        /// The target end of the link.1110        /// </summary>1111        [DataMember]1112        public GraphNode Target { get; internal set; }1113        /// <summary>1114        /// The optional link index.1115        /// </summary>1116        [DataMember]1117        public int? Index { get; internal set; }1118        /// <summary>1119        /// Initializes a new instance of the <see cref="GraphLink"/> class.1120        /// </summary>1121        public GraphLink(GraphNode source, GraphNode target, string label, string category)1122        {1123            this.Source = source;1124            this.Target = target;1125            this.Label = label;1126            this.Category = category;1127        }1128        /// <summary>1129        /// Add additional properties from XML element.1130        /// </summary>1131        /// <param name="e">An XML element representing the graph node in DGML format.</param>1132        public void AddDgmlProperties(XElement e)1133        {1134            foreach (XAttribute a in e.Attributes())1135            {...GraphNode
Using AI Code Generation
1using Microsoft.Coyote.Actors.Coverage;2using System;3using System.Collections.Generic;4using System.Linq;5using System.Text;6using System.Threading.Tasks;7{8    {9        public string Name { get; set; }10        public List<GraphNode> Children { get; set; }11        public GraphNode(string name)12        {13            Name = name;14            Children = new List<GraphNode>();15        }16        public void AddChild(GraphNode node)17        {18            Children.Add(node);19        }20    }21}22using Microsoft.Coyote.Actors.Coverage;23using System;24using System.Collections.Generic;25using System.Linq;26using System.Text;27using System.Threading.Tasks;28{29    {30        public GraphNode Root { get; set; }31        public Graph(GraphNode root)32        {33            Root = root;34        }35    }36}37using Microsoft.Coyote.Actors.Coverage;38using System;39using System.Collections.Generic;40using System.Linq;41using System.Text;42using System.Threading.Tasks;43{44    {45        public Graph BuildGraph(ActorRuntime runtime)46        {47            var root = new GraphNode("root");48            var rootChildren = new List<GraphNode>();49            foreach (var actor in runtime.GetActors())50            {51                var actorNode = new GraphNode(actor.Id.ToString());52                var actorChildren = new List<GraphNode>();53                foreach (var state in actor.GetStateNames())54                {55                    var stateNode = new GraphNode(state);56                    actorChildren.Add(stateNode);57                }58                actorNode.Children = actorChildren;59                rootChildren.Add(actorNode);60            }61            root.Children = rootChildren;62            return new Graph(root);63        }64    }65}66using Microsoft.Coyote.Actors.Coverage;67using Microsoft.Coyote.Runtime;68using System;69using System.Collections.Generic;70using System.Linq;GraphNode
Using AI Code Generation
1using Microsoft.Coyote.Actors.Coverage;2using System;3using System.Collections.Generic;4using System.Linq;5using System.Text;6using System.Threading.Tasks;7{8    {9        static void Main(string[] args)10        {11            GraphNode node1 = new GraphNode("Node1");12            GraphNode node2 = new GraphNode("Node2");13            GraphNode node3 = new GraphNode("Node3");14            GraphNode node4 = new GraphNode("Node4");15            GraphNode node5 = new GraphNode("Node5");16            GraphNode node6 = new GraphNode("Node6");17            GraphNode node7 = new GraphNode("Node7");18            GraphNode node8 = new GraphNode("Node8");19            GraphNode node9 = new GraphNode("Node9");20            GraphNode node10 = new GraphNode("Node10");21            GraphNode node11 = new GraphNode("Node11");22            GraphNode node12 = new GraphNode("Node12");23            GraphNode node13 = new GraphNode("Node13");24            GraphNode node14 = new GraphNode("Node14");25            GraphNode node15 = new GraphNode("Node15");26            GraphNode node16 = new GraphNode("Node16");27            GraphNode node17 = new GraphNode("Node17");28            GraphNode node18 = new GraphNode("Node18");29            GraphNode node19 = new GraphNode("Node19");30            GraphNode node20 = new GraphNode("Node20");31            GraphNode node21 = new GraphNode("Node21");32            GraphNode node22 = new GraphNode("Node22");33            GraphNode node23 = new GraphNode("Node23");34            GraphNode node24 = new GraphNode("Node24");35            GraphNode node25 = new GraphNode("Node25");36            GraphNode node26 = new GraphNode("Node26");37            GraphNode node27 = new GraphNode("Node27");38            GraphNode node28 = new GraphNode("Node28");39            GraphNode node29 = new GraphNode("Node29");40            GraphNode node30 = new GraphNode("Node30");41            GraphNode node31 = new GraphNode("Node31");42            GraphNode node32 = new GraphNode("Node32");43            GraphNode node33 = new GraphNode("Node33");44            GraphNode node34 = new GraphNode("Node34");GraphNode
Using AI Code Generation
1using Microsoft.Coyote.Actors.Coverage;2using System;3using System.Collections.Generic;4using System.Linq;5using System.Text;6using System.Threading.Tasks;7{8    {9        static void Main(string[] args)10        {11            GraphNode node1 = new GraphNode("1");12            GraphNode node2 = new GraphNode("2");13            GraphNode node3 = new GraphNode("3");14            GraphNode node4 = new GraphNode("4");15            GraphNode node5 = new GraphNode("5");16            GraphNode node6 = new GraphNode("6");17            GraphNode node7 = new GraphNode("7");18            GraphNode node8 = new GraphNode("8");19            GraphNode node9 = new GraphNode("9");20            GraphNode node10 = new GraphNode("10");21            GraphNode node11 = new GraphNode("11");22            GraphNode node12 = new GraphNode("12");23            GraphNode node13 = new GraphNode("13");24            GraphNode node14 = new GraphNode("14");25            GraphNode node15 = new GraphNode("15");26            GraphNode node16 = new GraphNode("16");27            GraphNode node17 = new GraphNode("17");28            GraphNode node18 = new GraphNode("18");29            GraphNode node19 = new GraphNode("19");30            GraphNode node20 = new GraphNode("20");31            GraphNode node21 = new GraphNode("21");32            GraphNode node22 = new GraphNode("22");33            GraphNode node23 = new GraphNode("23");34            GraphNode node24 = new GraphNode("24");35            GraphNode node25 = new GraphNode("25");36            GraphNode node26 = new GraphNode("26");37            GraphNode node27 = new GraphNode("27");38            GraphNode node28 = new GraphNode("28");39            GraphNode node29 = new GraphNode("29");40            GraphNode node30 = new GraphNode("30");41            GraphNode node31 = new GraphNode("31");42            GraphNode node32 = new GraphNode("32");43            GraphNode node33 = new GraphNode("33");44            GraphNode node34 = new GraphNode("34");45            GraphNode node35 = new GraphNode("35");46            GraphNode node36 = new GraphNode("36");47            GraphNode node37 = new GraphNode("37GraphNode
Using AI Code Generation
1using Microsoft.Coyote.Actors.Coverage;2using System;3using System.Collections.Generic;4using System.Linq;5using System.Text;6using System.Threading.Tasks;7{8    {9        static void Main(string[] args)10        {11            GraphNode node1 = new GraphNode("node1");12            GraphNode node2 = new GraphNode("node2");13            GraphNode node3 = new GraphNode("node3");14            GraphNode node4 = new GraphNode("node4");15            GraphNode node5 = new GraphNode("node5");16            GraphNode node6 = new GraphNode("node6");17            GraphNode node7 = new GraphNode("node7");18            GraphNode node8 = new GraphNode("node8");19            GraphNode node9 = new GraphNode("node9");20            GraphNode node10 = new GraphNode("node10");21            GraphNode node11 = new GraphNode("node11");22            GraphNode node12 = new GraphNode("node12");23            GraphNode node13 = new GraphNode("node13");24            GraphNode node14 = new GraphNode("node14");25            GraphNode node15 = new GraphNode("node15");26            GraphNode node16 = new GraphNode("node16");27            GraphNode node17 = new GraphNode("node17");28            GraphNode node18 = new GraphNode("node18");29            GraphNode node19 = new GraphNode("node19");30            GraphNode node20 = new GraphNode("node20");31            GraphNode node21 = new GraphNode("node21");GraphNode
Using AI Code Generation
1using Microsoft.Coyote.Actors.Coverage;2using System;3using System.Collections.Generic;4using System.Linq;5using System.Text;6using System.Threading.Tasks;7{8    {9        static void Main(string[] args)10        {11            var graphNode = new GraphNode();12            graphNode.Id = 1;13            graphNode.Name = "node1";14            Console.WriteLine(graphNode.Id);15            Console.WriteLine(graphNode.Name);16            Console.Read();17        }18    }19}GraphNode
Using AI Code Generation
1using Microsoft.Coyote.Actors.Coverage;2using Microsoft.Coyote.Actors.Coverage;3using Microsoft.Coyote.Actors.Coverage;4using Microsoft.Coyote.Actors.Coverage;5using Microsoft.Coyote.Actors.Coverage;6using Microsoft.Coyote.Actors.Coverage;7using Microsoft.Coyote.Actors.Coverage;8using Microsoft.Coyote.Actors.Coverage;9using Microsoft.Coyote.Actors.Coverage;10using Microsoft.Coyote.Actors.Coverage;11using Microsoft.Coyote.Actors.Coverage;12using Microsoft.Coyote.Actors.Coverage;13using Microsoft.Coyote.Actors.Coverage;14using Microsoft.Coyote.Actors.Coverage;15using Microsoft.Coyote.Actors.Coverage;16using Microsoft.Coyote.Actors.Coverage;GraphNode
Using AI Code Generation
1using Microsoft.Coyote.Actors.Coverage;2{3    {4        public static void Main(string[] args)5        {6            GraphNode node = new GraphNode();7            node.Name = "TestNode";8            node.Label = "TestLabel";9            node.IsEntry = true;10            node.IsExit = true;11            node.IsError = true;12            node.IsAccept = true;13            node.IsReject = true;14            node.IsSkip = true;15            node.IsReplay = true;16            node.IsReplayAsync = true;17            node.IsReplayNext = true;18            node.IsReplayNextAsync = true;19            node.IsReplayChoice = true;20            node.IsReplayChoiceAsync = true;21            node.IsReplayChoiceNext = true;22            node.IsReplayChoiceNextAsync = true;23            node.IsReplayChoiceNondet = true;24            node.IsReplayChoiceNondetAsync = true;25            node.IsReplayChoiceNondetNext = true;26            node.IsReplayChoiceNondetNextAsync = true;27            node.IsReplayNondet = true;28            node.IsReplayNondetAsync = true;29            node.IsReplayNondetNext = true;30            node.IsReplayNondetNextAsync = true;31            node.IsReplayTask = true;32            node.IsReplayTaskAsync = true;33            node.IsReplayTaskNext = true;34            node.IsReplayTaskNextAsync = true;35            node.IsReplayTaskNondet = true;36            node.IsReplayTaskNondetAsync = true;37            node.IsReplayTaskNondetNext = true;38            node.IsReplayTaskNondetNextAsync = true;39            node.IsReplayTaskChoice = true;40            node.IsReplayTaskChoiceAsync = true;41            node.IsReplayTaskChoiceNext = true;42            node.IsReplayTaskChoiceNextAsync = true;43            node.IsReplayTaskChoiceNondet = true;44            node.IsReplayTaskChoiceNondetAsync = true;45            node.IsReplayTaskChoiceNondetNext = true;46            node.IsReplayTaskChoiceNondetNextAsync = true;47            node.IsReplayTaskWait = true;48            node.IsReplayTaskWaitAsync = true;GraphNode
Using AI Code Generation
1using System;2using System.Collections.Generic;3using System.Linq;4using System.Text;5using System.Threading.Tasks;6using Microsoft.Coyote.Actors.Coverage;7using Microsoft.Coyote.Actors;8using Microsoft.Coyote.Runtime;9using Microsoft.Coyote;10using System.Threading;11using System.IO;12{13    {14        static void Main(string[] args)15        {16            var g = new GraphNode("main");17            var g1 = g.AddChild("g1");18            var g2 = g1.AddChild("g2");19            var g3 = g2.AddChild("g3");20            var g4 = g3.AddChild("g4");21            var g5 = g4.AddChild("g5");22            var g6 = g5.AddChild("g6");23            var g7 = g6.AddChild("g7");24            var g8 = g7.AddChild("g8");25            var g9 = g8.AddChild("g9");26            var g10 = g9.AddChild("g10");27            var g11 = g10.AddChild("g11");28            var g12 = g11.AddChild("g12");29            var g13 = g12.AddChild("g13");30            var g14 = g13.AddChild("g14");31            var g15 = g14.AddChild("g15");32            var g16 = g15.AddChild("g16");33            var g17 = g16.AddChild("g17");34            var g18 = g17.AddChild("g18");35            var g19 = g18.AddChild("g19");36            var g20 = g19.AddChild("g20");37            var g21 = g20.AddChild("g21");38            var g22 = g21.AddChild("g22");39            var g23 = g22.AddChild("g23");40            var g24 = g23.AddChild("g24");41            var g25 = g24.AddChild("g25");42            var g26 = g25.AddChild("g26");43            var g27 = g26.AddChild("g27");44            var g28 = g27.AddChild("g28");45            var g29 = g28.AddChild("g29");46            var g30 = g29.AddChild("g30");GraphNode
Using AI Code Generation
1using Microsoft.Coyote.Actors.Coverage;2{3    {4        static void Main(string[] args)5        {6            var graphNode = new GraphNode();7            graphNode.AddEdge(new GraphNode());8            graphNode.AddEdge(new GraphNode());9        }10    }11}12using Microsoft.Coyote.Actors.Coverage;13{14    {15        static void Main(string[] args)16        {17            var graphNode = new GraphNode();18            graphNode.AddEdge(new GraphNode());19            graphNode.AddEdge(new GraphNode());20        }21    }22}23using Microsoft.Coyote.Actors.Coverage;24{25    {26        static void Main(string[] args)27        {28            var graphNode = new GraphNode();29            graphNode.AddEdge(new GraphNode());30            graphNode.AddEdge(new GraphNode());31        }32    }33}34using Microsoft.Coyote.Actors.Coverage;35{36    {37        static void Main(string[] args)38        {39            var graphNode = new GraphNode();40            graphNode.AddEdge(new GraphNode());41            graphNode.AddEdge(new GraphNode());42        }43    }44}45using Microsoft.Coyote.Actors.Coverage;46{47    {48        static void Main(string[] args)49        {50            var graphNode = new GraphNode();51            graphNode.AddEdge(new GraphNode());52            graphNode.AddEdge(new GraphNode());53        }54    }55}56using Microsoft.Coyote.Actors.Coverage;57{58    {59        static void Main(string[] args)60        {61            var graphNode = new GraphNode();62            graphNode.AddEdge(new GraphLearn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
