How to use GetCurrentEventGroup method of Microsoft.Coyote.Actors.ActorExecutionContext class

Best Coyote code snippet using Microsoft.Coyote.Actors.ActorExecutionContext.GetCurrentEventGroup

ActorExecutionContext.cs

Source:ActorExecutionContext.cs Github

copy

Full Screen

...345 /// Creates a new timer that sends a <see cref="TimerElapsedEvent"/> to its owner actor.346 /// </summary>347 internal virtual IActorTimer CreateActorTimer(TimerInfo info, Actor owner) => new ActorTimer(info, owner);348 /// <inheritdoc/>349 public virtual EventGroup GetCurrentEventGroup(ActorId currentActorId)350 {351 Actor actor = this.GetActorWithId<Actor>(currentActorId);352 return actor?.CurrentEventGroup;353 }354 /// <summary>355 /// Gets the actor of type <typeparamref name="TActor"/> with the specified id,356 /// or null if no such actor exists.357 /// </summary>358 internal TActor GetActorWithId<TActor>(ActorId id)359 where TActor : Actor =>360 id != null && this.ActorMap.TryGetValue(id, out Actor value) &&361 value is TActor actor ? actor : null;362 /// <summary>363 /// Returns the next available unique operation id.364 /// </summary>365 /// <returns>Value representing the next available unique operation id.</returns>366 internal ulong GetNextOperationId() => this.Runtime.GetNextOperationId();367 /// <inheritdoc/>368 public bool RandomBoolean() => this.GetNondeterministicBooleanChoice(2, null, null);369 /// <inheritdoc/>370 public bool RandomBoolean(int maxValue) => this.GetNondeterministicBooleanChoice(maxValue, null, null);371 /// <summary>372 /// Returns a controlled nondeterministic boolean choice.373 /// </summary>374 internal virtual bool GetNondeterministicBooleanChoice(int maxValue, string callerName, string callerType)375 {376 bool result = false;377 if (this.ValueGenerator.Next(maxValue) is 0)378 {379 result = true;380 }381 this.LogWriter.LogRandom(result, callerName, callerType);382 return result;383 }384 /// <inheritdoc/>385 public int RandomInteger(int maxValue) => this.GetNondeterministicIntegerChoice(maxValue, null, null);386 /// <summary>387 /// Returns a controlled nondeterministic integer choice.388 /// </summary>389 internal virtual int GetNondeterministicIntegerChoice(int maxValue, string callerName, string callerType)390 {391 var result = this.ValueGenerator.Next(maxValue);392 this.LogWriter.LogRandom(result, callerName, callerType);393 return result;394 }395 /// <summary>396 /// Logs that the specified actor invoked an action.397 /// </summary>398 internal virtual void LogInvokedAction(Actor actor, MethodInfo action, string handlingStateName, string currentStateName)399 {400 if (this.Configuration.IsVerbose)401 {402 this.LogWriter.LogExecuteAction(actor.Id, handlingStateName, currentStateName, action.Name);403 }404 }405 /// <summary>406 /// Logs that the specified actor enqueued an <see cref="Event"/>.407 /// </summary>408 internal virtual void LogEnqueuedEvent(Actor actor, Event e, EventGroup eventGroup, EventInfo eventInfo)409 {410 if (this.Configuration.IsVerbose)411 {412 this.LogWriter.LogEnqueueEvent(actor.Id, e);413 }414 }415 /// <summary>416 /// Logs that the specified actor dequeued an <see cref="Event"/>.417 /// </summary>418 internal virtual void LogDequeuedEvent(Actor actor, Event e, EventInfo eventInfo, bool isFreshDequeue)419 {420 if (this.Configuration.IsVerbose)421 {422 string stateName = actor is StateMachine stateMachine ? stateMachine.CurrentStateName : default;423 this.LogWriter.LogDequeueEvent(actor.Id, stateName, e);424 }425 }426 /// <summary>427 /// Logs that the specified actor dequeued the default <see cref="Event"/>.428 /// </summary>429 [MethodImpl(MethodImplOptions.AggressiveInlining)]430 internal virtual void LogDefaultEventDequeued(Actor actor)431 {432 }433 /// <summary>434 /// Notifies that the inbox of the specified actor is about to be435 /// checked to see if the default event handler should fire.436 /// </summary>437 [MethodImpl(MethodImplOptions.AggressiveInlining)]438 internal virtual void LogDefaultEventHandlerCheck(Actor actor)439 {440 }441 /// <summary>442 /// Logs that the specified actor raised an <see cref="Event"/>.443 /// </summary>444 internal virtual void LogRaisedEvent(Actor actor, Event e, EventGroup eventGroup, EventInfo eventInfo)445 {446 if (this.Configuration.IsVerbose)447 {448 string stateName = actor is StateMachine stateMachine ? stateMachine.CurrentStateName : default;449 this.LogWriter.LogRaiseEvent(actor.Id, stateName, e);450 }451 }452 /// <summary>453 /// Logs that the specified actor is handling a raised <see cref="Event"/>.454 /// </summary>455 [MethodImpl(MethodImplOptions.AggressiveInlining)]456 internal virtual void LogHandleRaisedEvent(Actor actor, Event e)457 {458 }459 /// <summary>460 /// Logs that the specified actor called <see cref="Actor.ReceiveEventAsync(Type[])"/>461 /// or one of its overloaded methods.462 /// </summary>463 [MethodImpl(MethodImplOptions.AggressiveInlining)]464 internal virtual void LogReceiveCalled(Actor actor)465 {466 }467 /// <summary>468 /// Logs that the specified actor enqueued an event that it was waiting to receive.469 /// </summary>470 internal virtual void LogReceivedEvent(Actor actor, Event e, EventInfo eventInfo)471 {472 if (this.Configuration.IsVerbose)473 {474 string stateName = actor is StateMachine stateMachine ? stateMachine.CurrentStateName : default;475 this.LogWriter.LogReceiveEvent(actor.Id, stateName, e, wasBlocked: true);476 }477 }478 /// <summary>479 /// Logs that the specified actor received an event without waiting because the event480 /// was already in the inbox when the actor invoked the receive statement.481 /// </summary>482 internal virtual void LogReceivedEventWithoutWaiting(Actor actor, Event e, EventInfo eventInfo)483 {484 if (this.Configuration.IsVerbose)485 {486 string stateName = actor is StateMachine stateMachine ? stateMachine.CurrentStateName : default;487 this.LogWriter.LogReceiveEvent(actor.Id, stateName, e, wasBlocked: false);488 }489 }490 /// <summary>491 /// Logs that the specified actor is waiting to receive an event of one of the specified types.492 /// </summary>493 internal virtual void LogWaitEvent(Actor actor, IEnumerable<Type> eventTypes)494 {495 if (this.Configuration.IsVerbose)496 {497 string stateName = actor is StateMachine stateMachine ? stateMachine.CurrentStateName : default;498 var eventWaitTypesArray = eventTypes.ToArray();499 if (eventWaitTypesArray.Length is 1)500 {501 this.LogWriter.LogWaitEvent(actor.Id, stateName, eventWaitTypesArray[0]);502 }503 else504 {505 this.LogWriter.LogWaitEvent(actor.Id, stateName, eventWaitTypesArray);506 }507 }508 }509 /// <summary>510 /// Logs that the specified state machine entered a state.511 /// </summary>512 internal virtual void LogEnteredState(StateMachine stateMachine)513 {514 if (this.Configuration.IsVerbose)515 {516 this.LogWriter.LogStateTransition(stateMachine.Id, stateMachine.CurrentStateName, isEntry: true);517 }518 }519 /// <summary>520 /// Logs that the specified state machine exited a state.521 /// </summary>522 internal virtual void LogExitedState(StateMachine stateMachine)523 {524 if (this.Configuration.IsVerbose)525 {526 this.LogWriter.LogStateTransition(stateMachine.Id, stateMachine.CurrentStateName, isEntry: false);527 }528 }529 /// <summary>530 /// Logs that the specified state machine invoked pop.531 /// </summary>532 [MethodImpl(MethodImplOptions.AggressiveInlining)]533 internal virtual void LogPopState(StateMachine stateMachine)534 {535 }536 /// <summary>537 /// Logs that the specified state machine invoked an action.538 /// </summary>539 internal virtual void LogInvokedOnEntryAction(StateMachine stateMachine, MethodInfo action)540 {541 if (this.Configuration.IsVerbose)542 {543 this.LogWriter.LogExecuteAction(stateMachine.Id, stateMachine.CurrentStateName,544 stateMachine.CurrentStateName, action.Name);545 }546 }547 /// <summary>548 /// Logs that the specified state machine invoked an action.549 /// </summary>550 internal virtual void LogInvokedOnExitAction(StateMachine stateMachine, MethodInfo action)551 {552 if (this.Configuration.IsVerbose)553 {554 this.LogWriter.LogExecuteAction(stateMachine.Id, stateMachine.CurrentStateName,555 stateMachine.CurrentStateName, action.Name);556 }557 }558 /// <summary>559 /// Builds the coverage graph information, if any. This information is only available560 /// when <see cref="Configuration.ReportActivityCoverage"/> is enabled.561 /// </summary>562 internal CoverageInfo BuildCoverageInfo()563 {564 var result = this.CoverageInfo;565 if (result != null)566 {567 var builder = this.LogWriter.GetLogsOfType<ActorRuntimeLogGraphBuilder>().FirstOrDefault();568 if (builder != null)569 {570 result.CoverageGraph = builder.SnapshotGraph(this.Configuration.IsDgmlBugGraph);571 }572 var eventCoverage = this.LogWriter.GetLogsOfType<ActorRuntimeLogEventCoverage>().FirstOrDefault();573 if (eventCoverage != null)574 {575 result.EventInfo = eventCoverage.EventCoverage;576 }577 }578 return result;579 }580 /// <summary>581 /// Returns the current hashed state of the actors.582 /// </summary>583 /// <remarks>584 /// The hash is updated in each execution step.585 /// </remarks>586 internal virtual int GetHashedActorState() => 0;587 /// <summary>588 /// Returns the program counter of the specified actor.589 /// </summary>590 [MethodImpl(MethodImplOptions.AggressiveInlining)]591 internal virtual int GetActorProgramCounter(ActorId actorId) => 0;592 /// <inheritdoc/>593 public void RegisterMonitor<T>()594 where T : Monitor =>595 this.TryCreateMonitor(typeof(T));596 /// <inheritdoc/>597 public void Monitor<T>(Event e)598 where T : Monitor599 {600 // If the event is null then report an error and exit.601 this.Assert(e != null, "Cannot monitor a null event.");602 this.InvokeMonitor(typeof(T), e, null, null, null);603 }604 /// <summary>605 /// Tries to create a new <see cref="Specifications.Monitor"/> of the specified <see cref="Type"/>.606 /// </summary>607 protected bool TryCreateMonitor(Type type) => this.SpecificationEngine.TryCreateMonitor(608 type, this.CoverageInfo, this.LogWriter);609 /// <summary>610 /// Invokes the specified <see cref="Specifications.Monitor"/> with the specified <see cref="Event"/>.611 /// </summary>612 internal void InvokeMonitor(Type type, Event e, string senderName, string senderType, string senderStateName) =>613 this.SpecificationEngine.InvokeMonitor(type, e, senderName, senderType, senderStateName);614 /// <inheritdoc/>615 [MethodImpl(MethodImplOptions.AggressiveInlining)]616 public void Assert(bool predicate) => this.SpecificationEngine.Assert(predicate);617 /// <inheritdoc/>618 [MethodImpl(MethodImplOptions.AggressiveInlining)]619 public void Assert(bool predicate, string s, object arg0) => this.SpecificationEngine.Assert(predicate, s, arg0);620 /// <inheritdoc/>621 [MethodImpl(MethodImplOptions.AggressiveInlining)]622 public void Assert(bool predicate, string s, object arg0, object arg1) => this.SpecificationEngine.Assert(predicate, s, arg0, arg1);623 /// <inheritdoc/>624 [MethodImpl(MethodImplOptions.AggressiveInlining)]625 public void Assert(bool predicate, string s, object arg0, object arg1, object arg2) =>626 this.SpecificationEngine.Assert(predicate, s, arg0, arg1, arg2);627 /// <inheritdoc/>628 [MethodImpl(MethodImplOptions.AggressiveInlining)]629 public void Assert(bool predicate, string s, params object[] args) => this.SpecificationEngine.Assert(predicate, s, args);630 /// <summary>631 /// Asserts that the actor calling an actor method is also the actor that is currently executing.632 /// </summary>633 [MethodImpl(MethodImplOptions.AggressiveInlining)]634 internal virtual void AssertExpectedCallerActor(Actor caller, string calledAPI)635 {636 }637 /// <summary>638 /// Raises the <see cref="OnFailure"/> event with the specified <see cref="Exception"/>.639 /// </summary>640 internal void RaiseOnFailureEvent(Exception exception) => this.Runtime.RaiseOnFailureEvent(exception);641 /// <summary>642 /// Handle the specified dropped <see cref="Event"/>.643 /// </summary>644 internal void HandleDroppedEvent(Event e, ActorId id) => this.OnEventDropped?.Invoke(e, id);645 /// <summary>646 /// Throws an <see cref="AssertionFailureException"/> exception containing the specified exception.647 /// </summary>648#if !DEBUG649 [DebuggerHidden]650#endif651 internal void WrapAndThrowException(Exception exception, string s, params object[] args) =>652 this.SpecificationEngine.WrapAndThrowException(exception, s, args);653 /// <inheritdoc/>654 [Obsolete("Please set the Logger property directory instead of calling this method.")]655 public TextWriter SetLogger(TextWriter logger)656 {657 var result = this.LogWriter.SetLogger(new TextWriterLogger(logger));658 if (result != null)659 {660 return result.TextWriter;661 }662 return null;663 }664 /// <inheritdoc/>665 public void RegisterLog(IActorRuntimeLog log) => this.LogWriter.RegisterLog(log);666 /// <inheritdoc/>667 public void RemoveLog(IActorRuntimeLog log) => this.LogWriter.RemoveLog(log);668 /// <inheritdoc/>669 public void Stop() => this.Scheduler.ForceStop();670 /// <summary>671 /// Disposes runtime resources.672 /// </summary>673 protected virtual void Dispose(bool disposing)674 {675 if (disposing)676 {677 this.ActorMap.Clear();678 }679 }680 /// <inheritdoc/>681 public void Dispose()682 {683 this.Dispose(true);684 GC.SuppressFinalize(this);685 }686 /// <summary>687 /// The mocked execution context of an actor program.688 /// </summary>689 internal sealed class Mock : ActorExecutionContext690 {691 /// <summary>692 /// Map that stores all unique names and their corresponding actor ids.693 /// </summary>694 private readonly ConcurrentDictionary<string, ActorId> NameValueToActorId;695 /// <summary>696 /// Map of program counters used for state-caching to distinguish697 /// scheduling from non-deterministic choices.698 /// </summary>699 private readonly ConcurrentDictionary<ActorId, int> ProgramCounterMap;700 /// <summary>701 /// If true, the actor execution is controlled, else false.702 /// </summary>703 internal override bool IsExecutionControlled => true;704 /// <summary>705 /// Initializes a new instance of the <see cref="Mock"/> class.706 /// </summary>707 internal Mock(Configuration configuration, CoyoteRuntime runtime, OperationScheduler scheduler,708 SpecificationEngine specificationEngine, IRandomValueGenerator valueGenerator, LogWriter logWriter)709 : base(configuration, runtime, scheduler, specificationEngine, valueGenerator, logWriter)710 {711 this.NameValueToActorId = new ConcurrentDictionary<string, ActorId>();712 this.ProgramCounterMap = new ConcurrentDictionary<ActorId, int>();713 }714 /// <inheritdoc/>715 public override ActorId CreateActorIdFromName(Type type, string name)716 {717 // It is important that all actor ids use the monotonically incrementing718 // value as the id during testing, and not the unique name.719 return this.NameValueToActorId.GetOrAdd(name, key => this.CreateActorId(type, key));720 }721 /// <inheritdoc/>722 public override ActorId CreateActor(Type type, Event initialEvent = null, EventGroup eventGroup = null) =>723 this.CreateActor(null, type, null, initialEvent, eventGroup);724 /// <inheritdoc/>725 public override ActorId CreateActor(Type type, string name, Event initialEvent = null, EventGroup eventGroup = null) =>726 this.CreateActor(null, type, name, initialEvent, eventGroup);727 /// <inheritdoc/>728 public override ActorId CreateActor(ActorId id, Type type, Event initialEvent = null, EventGroup eventGroup = null)729 {730 this.Assert(id != null, "Cannot create an actor using a null actor id.");731 return this.CreateActor(id, type, null, initialEvent, eventGroup);732 }733 /// <inheritdoc/>734 public override Task<ActorId> CreateActorAndExecuteAsync(Type type, Event initialEvent = null, EventGroup eventGroup = null) =>735 this.CreateActorAndExecuteAsync(null, type, null, initialEvent, eventGroup);736 /// <inheritdoc/>737 public override Task<ActorId> CreateActorAndExecuteAsync(Type type, string name, Event initialEvent = null, EventGroup eventGroup = null) =>738 this.CreateActorAndExecuteAsync(null, type, name, initialEvent, eventGroup);739 /// <inheritdoc/>740 public override Task<ActorId> CreateActorAndExecuteAsync(ActorId id, Type type, Event initialEvent = null, EventGroup eventGroup = null)741 {742 this.Assert(id != null, "Cannot create an actor using a null actor id.");743 return this.CreateActorAndExecuteAsync(id, type, null, initialEvent, eventGroup);744 }745 /// <summary>746 /// Creates a new actor of the specified <see cref="Type"/> and name, using the specified747 /// unbound actor id, and passes the specified optional <see cref="Event"/>. This event748 /// can only be used to access its payload, and cannot be handled.749 /// </summary>750 internal ActorId CreateActor(ActorId id, Type type, string name, Event initialEvent = null, EventGroup eventGroup = null)751 {752 var creatorOp = this.Scheduler.GetExecutingOperation<ActorOperation>();753 return this.CreateActor(id, type, name, initialEvent, creatorOp?.Actor, eventGroup);754 }755 /// <summary>756 /// Creates a new <see cref="Actor"/> of the specified <see cref="Type"/>.757 /// </summary>758 internal override ActorId CreateActor(ActorId id, Type type, string name, Event initialEvent, Actor creator, EventGroup eventGroup)759 {760 this.AssertExpectedCallerActor(creator, "CreateActor");761 Actor actor = this.CreateActor(id, type, name, creator, eventGroup);762 this.RunActorEventHandler(actor, initialEvent, true, null);763 return actor.Id;764 }765 /// <summary>766 /// Creates a new actor of the specified <see cref="Type"/> and name, using the specified767 /// unbound actor id, and passes the specified optional <see cref="Event"/>. This event768 /// can only be used to access its payload, and cannot be handled. The method returns only769 /// when the actor is initialized and the <see cref="Event"/> (if any) is handled.770 /// </summary>771 internal Task<ActorId> CreateActorAndExecuteAsync(ActorId id, Type type, string name, Event initialEvent = null,772 EventGroup eventGroup = null)773 {774 var creatorOp = this.Scheduler.GetExecutingOperation<ActorOperation>();775 return this.CreateActorAndExecuteAsync(id, type, name, initialEvent, creatorOp?.Actor, eventGroup);776 }777 /// <summary>778 /// Creates a new <see cref="Actor"/> of the specified <see cref="Type"/>. The method779 /// returns only when the actor is initialized and the <see cref="Event"/> (if any)780 /// is handled.781 /// </summary>782 internal override async Task<ActorId> CreateActorAndExecuteAsync(ActorId id, Type type, string name, Event initialEvent,783 Actor creator, EventGroup eventGroup)784 {785 this.AssertExpectedCallerActor(creator, "CreateActorAndExecuteAsync");786 this.Assert(creator != null, "Only an actor can call 'CreateActorAndExecuteAsync': avoid calling " +787 "it directly from the test method; instead call it through a test driver actor.");788 Actor actor = this.CreateActor(id, type, name, creator, eventGroup);789 this.RunActorEventHandler(actor, initialEvent, true, creator);790 // Wait until the actor reaches quiescence.791 await creator.ReceiveEventAsync(typeof(QuiescentEvent), rev => (rev as QuiescentEvent).ActorId == actor.Id);792 return await Task.FromResult(actor.Id);793 }794 /// <summary>795 /// Creates a new <see cref="Actor"/> of the specified <see cref="Type"/>.796 /// </summary>797 internal override Actor CreateActor(ActorId id, Type type, string name, Actor creator, EventGroup eventGroup)798 {799 this.Assert(type.IsSubclassOf(typeof(Actor)), "Type '{0}' is not an actor.", type.FullName);800 // Using ulong.MaxValue because a Create operation cannot specify801 // the id of its target, because the id does not exist yet.802 this.Scheduler.ScheduleNextOperation(AsyncOperationType.Create);803 this.ResetProgramCounter(creator);804 if (id is null)805 {806 id = this.CreateActorId(type, name);807 }808 else809 {810 this.Assert(id.Runtime is null || id.Runtime == this, "Unbound actor id '{0}' was created by another runtime.", id.Value);811 this.Assert(id.Type == type.FullName, "Cannot bind actor id '{0}' of type '{1}' to an actor of type '{2}'.",812 id.Value, id.Type, type.FullName);813 id.Bind(this);814 }815 // If a group was not provided, inherit the current event group from the creator (if any).816 if (eventGroup is null && creator != null)817 {818 eventGroup = creator.EventGroup;819 }820 Actor actor = ActorFactory.Create(type);821 ActorOperation op = new ActorOperation(id.Value, id.Name, actor, this.Scheduler);822 IEventQueue eventQueue = new MockEventQueue(actor);823 actor.Configure(this, id, op, eventQueue, eventGroup);824 actor.SetupEventHandlers();825 if (this.Configuration.ReportActivityCoverage)826 {827 actor.ReportActivityCoverage(this.CoverageInfo);828 }829 bool result = this.Scheduler.RegisterOperation(op);830 this.Assert(result, "Actor id '{0}' is used by an existing or previously halted actor.", id.Value);831 if (actor is StateMachine)832 {833 this.LogWriter.LogCreateStateMachine(id, creator?.Id.Name, creator?.Id.Type);834 }835 else836 {837 this.LogWriter.LogCreateActor(id, creator?.Id.Name, creator?.Id.Type);838 }839 return actor;840 }841 /// <inheritdoc/>842 public override void SendEvent(ActorId targetId, Event initialEvent, EventGroup eventGroup = default, SendOptions options = null)843 {844 var senderOp = this.Scheduler.GetExecutingOperation<ActorOperation>();845 this.SendEvent(targetId, initialEvent, senderOp?.Actor, eventGroup, options);846 }847 /// <inheritdoc/>848 public override Task<bool> SendEventAndExecuteAsync(ActorId targetId, Event initialEvent,849 EventGroup eventGroup = null, SendOptions options = null)850 {851 var senderOp = this.Scheduler.GetExecutingOperation<ActorOperation>();852 return this.SendEventAndExecuteAsync(targetId, initialEvent, senderOp?.Actor, eventGroup, options);853 }854 /// <summary>855 /// Sends an asynchronous <see cref="Event"/> to an actor.856 /// </summary>857 internal override void SendEvent(ActorId targetId, Event e, Actor sender, EventGroup eventGroup, SendOptions options)858 {859 if (e is null)860 {861 string message = sender != null ?862 string.Format("{0} is sending a null event.", sender.Id.ToString()) :863 "Cannot send a null event.";864 this.Assert(false, message);865 }866 if (sender != null)867 {868 this.Assert(targetId != null, "{0} is sending event {1} to a null actor.", sender.Id, e);869 }870 else871 {872 this.Assert(targetId != null, "Cannot send event {1} to a null actor.", e);873 }874 this.AssertExpectedCallerActor(sender, "SendEvent");875 EnqueueStatus enqueueStatus = this.EnqueueEvent(targetId, e, sender, eventGroup, options, out Actor target);876 if (enqueueStatus is EnqueueStatus.EventHandlerNotRunning)877 {878 this.RunActorEventHandler(target, null, false, null);879 }880 }881 /// <summary>882 /// Sends an asynchronous <see cref="Event"/> to an actor. Returns immediately if the target was883 /// already running. Otherwise blocks until the target handles the event and reaches quiescense.884 /// </summary>885 internal override async Task<bool> SendEventAndExecuteAsync(ActorId targetId, Event e, Actor sender,886 EventGroup eventGroup, SendOptions options)887 {888 this.Assert(sender is StateMachine, "Only an actor can call 'SendEventAndExecuteAsync': avoid " +889 "calling it directly from the test method; instead call it through a test driver actor.");890 this.Assert(e != null, "{0} is sending a null event.", sender.Id);891 this.Assert(targetId != null, "{0} is sending event {1} to a null actor.", sender.Id, e);892 this.AssertExpectedCallerActor(sender, "SendEventAndExecuteAsync");893 EnqueueStatus enqueueStatus = this.EnqueueEvent(targetId, e, sender, eventGroup, options, out Actor target);894 if (enqueueStatus is EnqueueStatus.EventHandlerNotRunning)895 {896 this.RunActorEventHandler(target, null, false, sender as StateMachine);897 // Wait until the actor reaches quiescence.898 await (sender as StateMachine).ReceiveEventAsync(typeof(QuiescentEvent), rev => (rev as QuiescentEvent).ActorId == targetId);899 return true;900 }901 // EnqueueStatus.EventHandlerNotRunning is not returned by EnqueueEvent902 // (even when the actor was previously inactive) when the event e requires903 // no action by the actor (i.e., it implicitly handles the event).904 return enqueueStatus is EnqueueStatus.Dropped || enqueueStatus is EnqueueStatus.NextEventUnavailable;905 }906 /// <summary>907 /// Enqueues an event to the actor with the specified id.908 /// </summary>909 private EnqueueStatus EnqueueEvent(ActorId targetId, Event e, Actor sender, EventGroup eventGroup,910 SendOptions options, out Actor target)911 {912 target = this.Scheduler.GetOperationWithId<ActorOperation>(targetId.Value)?.Actor;913 this.Assert(target != null,914 "Cannot send event '{0}' to actor id '{1}' that is not bound to an actor instance.",915 e.GetType().FullName, targetId.Value);916 this.Scheduler.ScheduleNextOperation(AsyncOperationType.Send);917 this.ResetProgramCounter(sender as StateMachine);918 // If no group is provided we default to passing along the group from the sender.919 if (eventGroup is null && sender != null)920 {921 eventGroup = sender.EventGroup;922 }923 if (target.IsHalted)924 {925 Guid groupId = eventGroup is null ? Guid.Empty : eventGroup.Id;926 this.LogWriter.LogSendEvent(targetId, sender?.Id.Name, sender?.Id.Type,927 (sender as StateMachine)?.CurrentStateName ?? default, e, groupId, isTargetHalted: true);928 this.Assert(options is null || !options.MustHandle,929 "A must-handle event '{0}' was sent to {1} which has halted.", e.GetType().FullName, targetId);930 this.HandleDroppedEvent(e, targetId);931 return EnqueueStatus.Dropped;932 }933 EnqueueStatus enqueueStatus = this.EnqueueEvent(target, e, sender, eventGroup, options);934 if (enqueueStatus == EnqueueStatus.Dropped)935 {936 this.HandleDroppedEvent(e, targetId);937 }938 return enqueueStatus;939 }940 /// <summary>941 /// Enqueues an event to the actor with the specified id.942 /// </summary>943 private EnqueueStatus EnqueueEvent(Actor actor, Event e, Actor sender, EventGroup eventGroup, SendOptions options)944 {945 EventOriginInfo originInfo;946 string stateName = null;947 if (sender is StateMachine senderStateMachine)948 {949 originInfo = new EventOriginInfo(sender.Id, senderStateMachine.GetType().FullName,950 NameResolver.GetStateNameForLogging(senderStateMachine.CurrentState));951 stateName = senderStateMachine.CurrentStateName;952 }953 else if (sender is Actor senderActor)954 {955 originInfo = new EventOriginInfo(sender.Id, senderActor.GetType().FullName, string.Empty);956 }957 else958 {959 // Message comes from the environment.960 originInfo = new EventOriginInfo(null, "Env", "Env");961 }962 EventInfo eventInfo = new EventInfo(e, originInfo)963 {964 MustHandle = options?.MustHandle ?? false,965 Assert = options?.Assert ?? -1966 };967 Guid opId = eventGroup is null ? Guid.Empty : eventGroup.Id;968 this.LogWriter.LogSendEvent(actor.Id, sender?.Id.Name, sender?.Id.Type, stateName,969 e, opId, isTargetHalted: false);970 return actor.Enqueue(e, eventGroup, eventInfo);971 }972 /// <summary>973 /// Runs a new asynchronous event handler for the specified actor.974 /// This is a fire and forget invocation.975 /// </summary>976 /// <param name="actor">The actor that executes this event handler.</param>977 /// <param name="initialEvent">Optional event for initializing the actor.</param>978 /// <param name="isFresh">If true, then this is a new actor.</param>979 /// <param name="syncCaller">Caller actor that is blocked for quiscence.</param>980 private void RunActorEventHandler(Actor actor, Event initialEvent, bool isFresh, Actor syncCaller)981 {982 var op = actor.Operation;983 Task task = new Task(async () =>984 {985 try986 {987 // Update the current asynchronous control flow with this runtime instance,988 // allowing future retrieval in the same asynchronous call stack.989 CoyoteRuntime.AssignAsyncControlFlowRuntime(this.Runtime);990 this.Scheduler.StartOperation(op);991 if (isFresh)992 {993 await actor.InitializeAsync(initialEvent);994 }995 await actor.RunEventHandlerAsync();996 if (syncCaller != null)997 {998 this.EnqueueEvent(syncCaller, new QuiescentEvent(actor.Id), actor, actor.CurrentEventGroup, null);999 }1000 if (!actor.IsHalted)1001 {1002 this.ResetProgramCounter(actor);1003 }1004 IODebug.WriteLine("<ScheduleDebug> Completed operation {0} on task '{1}'.", actor.Id, Task.CurrentId);1005 op.OnCompleted();1006 // The actor is inactive or halted, schedule the next enabled operation.1007 this.Scheduler.ScheduleNextOperation(AsyncOperationType.Stop);1008 }1009 catch (Exception ex)1010 {1011 this.ProcessUnhandledExceptionInOperation(op, ex);1012 }1013 });1014 task.Start();1015 this.Scheduler.WaitOperationStart(op);1016 }1017 /// <summary>1018 /// Creates a new timer that sends a <see cref="TimerElapsedEvent"/> to its owner actor.1019 /// </summary>1020 internal override IActorTimer CreateActorTimer(TimerInfo info, Actor owner)1021 {1022 var id = this.CreateActorId(typeof(MockStateMachineTimer));1023 this.CreateActor(id, typeof(MockStateMachineTimer), new TimerSetupEvent(info, owner, this.Configuration.TimeoutDelay));1024 return this.Scheduler.GetOperationWithId<ActorOperation>(id.Value).Actor as MockStateMachineTimer;1025 }1026 /// <inheritdoc/>1027 public override EventGroup GetCurrentEventGroup(ActorId currentActorId)1028 {1029 var callerOp = this.Scheduler.GetExecutingOperation<ActorOperation>();1030 this.Assert(callerOp != null && currentActorId == callerOp.Actor.Id,1031 "Trying to access the event group id of {0}, which is not the currently executing actor.",1032 currentActorId);1033 return callerOp.Actor.CurrentEventGroup;1034 }1035 /// <summary>1036 /// Returns a controlled nondeterministic boolean choice.1037 /// </summary>1038 internal override bool GetNondeterministicBooleanChoice(int maxValue, string callerName, string callerType)1039 {1040 var caller = this.Scheduler.GetExecutingOperation<ActorOperation>()?.Actor;1041 if (caller is Actor callerActor)...

Full Screen

Full Screen

GetCurrentEventGroup

Using AI Code Generation

copy

Full Screen

1using System;2using System.Threading.Tasks;3using Microsoft.Coyote;4using Microsoft.Coyote.Actors;5using Microsoft.Coyote.Specifications;6using Microsoft.Coyote.Tasks;7using Microsoft.Coyote.Testing;8using Microsoft.Coyote.TestingServices;9using Microsoft.Coyote.TestingServices.Runtime;10using Microsoft.Coyote.TestingServices.SchedulingStrategies;11using Microsoft.Coyote.TestingServices.StateCaching;12using Microsoft.Coyote.TestingServices.Tracing.Schedule;13using Microsoft.Coyote.TestingServices.Tracing.Schedule.Default;14using Microsoft.Coyote.TestingServices.Tracing.Schedule.Default.Cached;15using Microsoft.Coyote.TestingServices.Tracing.Schedule.Default.Strategies;16using Microsoft.Coyote.TestingServices.Tracing.Schedule.Default.Strategies.Bounded;17using Microsoft.Coyote.TestingServices.Tracing.Schedule.Default.Strategies.Unbounded;18using Microsoft.Coyote.TestingServices.Tracing.Schedule.Default.Strategies.Unbounded.DPOR;19using Microsoft.Coyote.TestingServices.Tracing.Schedule.Default.Strategies.Unbounded.DPOR.StateCaching;20using Microsoft.Coyote.TestingServices.Tracing.Schedule.Default.Strategies.Unbounded.DPOR.StateCaching.Directed;21using Microsoft.Coyote.TestingServices.Tracing.Schedule.Default.Strategies.Unbounded.DPOR.StateCaching.Directed.FullExploration;22using Microsoft.Coyote.TestingServices.Tracing.Schedule.Default.Strategies.Unbounded.DPOR.StateCaching.Directed.FullExploration.DPOR;23using Microsoft.Coyote.TestingServices.Tracing.Schedule.Default.Strategies.Unbounded.DPOR.StateCaching.Directed.FullExploration.DPOR.StateCaching;24using Microsoft.Coyote.TestingServices.Tracing.Schedule.Default.Strategies.Unbounded.DPOR.StateCaching.Directed.FullExploration.DPOR.StateCaching.DPOR;25using Microsoft.Coyote.TestingServices.Tracing.Schedule.Default.Strategies.Unbounded.DPOR.StateCaching.Directed.FullExploration.DPOR.StateCaching.DPOR.StateCaching;26using Microsoft.Coyote.TestingServices.Tracing.Schedule.Default.Strategies.Unbounded.DPOR.StateCaching.Directed.FullExploration.DPOR.StateCaching.DPOR.StateCaching.DPOR;27using Microsoft.Coyote.TestingServices.Tracing.Schedule.Default.Strategies.Unbounded.DPOR.StateCaching.Directed.FullExploration.DPOR.StateCaching.DPOR.StateCaching.DPOR.StateCaching;

Full Screen

Full Screen

GetCurrentEventGroup

Using AI Code Generation

copy

Full Screen

1using System;2using System.Threading.Tasks;3using Microsoft.Coyote;4using Microsoft.Coyote.Actors;5using Microsoft.Coyote.Tasks;6{7 {8 static void Main(string[] args)9 {10 var runtime = RuntimeFactory.Create();11 Task.Run(async () =>12 {13 var id = new ActorId("HelloWorldActor");14 await runtime.CreateActorAndExecuteAsync<HelloWorldActor>(id, null);15 }).Wait();16 }17 }18 {19 protected override Task OnInitializeAsync(Event initialEvent)20 {21 var currentEventGroup = this.Context.GetCurrentEventGroup();22 Console.WriteLine("Current event group is: " + currentEventGroup);23 return Task.CompletedTask;24 }25 }26}27public int GetNextEventGroup()28using System;29using System.Threading.Tasks;30using Microsoft.Coyote;31using Microsoft.Coyote.Actors;32using Microsoft.Coyote.Tasks;33{34 {35 static void Main(string[] args)36 {37 var runtime = RuntimeFactory.Create();38 Task.Run(async () =>39 {40 var id = new ActorId("HelloWorldActor");41 await runtime.CreateActorAndExecuteAsync<HelloWorldActor>(id, null);42 }).Wait();43 }44 }45 {46 protected override Task OnInitializeAsync(Event initialEvent)47 {48 var nextEventGroup = this.Context.GetNextEventGroup();49 Console.WriteLine("Next event group is: " + nextEventGroup);50 return Task.CompletedTask;

Full Screen

Full Screen

GetCurrentEventGroup

Using AI Code Generation

copy

Full Screen

1using System;2using System.Threading.Tasks;3using Microsoft.Coyote;4using Microsoft.Coyote.Actors;5using Microsoft.Coyote.Runtime;6{7 {8 public static async Task Main()9 {10 var runtime = RuntimeFactory.Create();11 var config = Configuration.Create();12 runtime.RegisterMonitor<M>();13 runtime.CreateActor(typeof(A), config);14 await Task.Delay(1000);15 runtime.Dispose();16 }17 }18 {19 protected override Task OnInitializeAsync(Event initialEvent)20 {21 this.SendEvent(this.Id, new E1());22 return Task.CompletedTask;23 }24 protected override async Task OnEventAsync(Event e)25 {26 switch (e)27 {28 this.SendEvent(this.Id, new E2());29 break;30 this.SendEvent(this.Id, new E3());31 break;32 this.SendEvent(this.Id, new E4());33 break;34 this.SendEvent(this.Id, new E5());35 break;36 this.SendEvent(this.Id, new E6());37 break;38 this.SendEvent(this.Id, new E7());39 break;40 this.SendEvent(this.Id, new E8());41 break;42 this.SendEvent(this.Id, new E9());43 break;44 this.SendEvent(this.Id, new E10());45 break;46 this.SendEvent(this.Id, new E11());47 break;48 this.SendEvent(this.Id, new E12());49 break;50 this.SendEvent(this.Id, new E13());51 break;52 this.SendEvent(this.Id, new E14());53 break;54 this.SendEvent(this.Id, new E15());55 break;56 this.SendEvent(this.Id, new E16());57 break;58 this.SendEvent(this.Id, new E17());59 break;60 this.SendEvent(this.Id, new E18());61 break;

Full Screen

Full Screen

GetCurrentEventGroup

Using AI Code Generation

copy

Full Screen

1using System;2using System.Threading.Tasks;3using Microsoft.Coyote;4using Microsoft.Coyote.Actors;5using Microsoft.Coyote.Actors.Timers;6using Microsoft.Coyote.Specifications;7{8 {9 private static void Main(string[] args)10 {11 var runtime = RuntimeFactory.Create();12 runtime.CreateActor(typeof(Actor1));13 runtime.Run();14 }15 }16 {17 protected override async Task OnInitializeAsync(Event initialEvent)18 {19 var actor2 = this.CreateActor(typeof(Actor2));20 var actor3 = this.CreateActor(typeof(Actor3));21 var actor4 = this.CreateActor(typeof(Actor4));22 var actor5 = this.CreateActor(typeof(Actor5));23 var actor6 = this.CreateActor(typeof(Actor6));24 var actor7 = this.CreateActor(typeof(Actor7));25 var actor8 = this.CreateActor(typeof(Actor8));26 var actor9 = this.CreateActor(typeof(Actor9));27 var actor10 = this.CreateActor(typeof(Actor10));28 var actor11 = this.CreateActor(typeof(Actor11));29 var actor12 = this.CreateActor(typeof(Actor12));30 var actor13 = this.CreateActor(typeof(Actor13));31 var actor14 = this.CreateActor(typeof(Actor14));32 var actor15 = this.CreateActor(typeof(Actor15));33 var actor16 = this.CreateActor(typeof(Actor16));34 var actor17 = this.CreateActor(typeof(Actor17));35 var actor18 = this.CreateActor(typeof(Actor18));36 var actor19 = this.CreateActor(typeof(Actor19));37 var actor20 = this.CreateActor(typeof(Actor20));38 var actor21 = this.CreateActor(typeof(Actor21));39 var actor22 = this.CreateActor(typeof(Actor22));40 var actor23 = this.CreateActor(typeof(Actor23));41 var actor24 = this.CreateActor(typeof(Actor24));42 var actor25 = this.CreateActor(typeof(Actor25));43 var actor26 = this.CreateActor(typeof(Actor26));44 var actor27 = this.CreateActor(typeof(Actor27));45 var actor28 = this.CreateActor(typeof(Actor28));46 var actor29 = this.CreateActor(typeof(Actor29));47 var actor30 = this.CreateActor(typeof(Actor30));

Full Screen

Full Screen

GetCurrentEventGroup

Using AI Code Generation

copy

Full Screen

1using System;2using System.Threading.Tasks;3using Microsoft.Coyote;4using Microsoft.Coyote.Actors;5using Microsoft.Coyote.Tasks;6{7 {8 public static void Main()9 {10 Runtime.RegisterMonitor(typeof(MyMonitor));11 Runtime.Run(new Configuration(), () => {12 var actor = Actor.Create(typeof(MyActor));13 actor.SendEvent(new UnitEvent());14 });15 }16 }17 {18 protected override Task OnInitializeAsync(Event initialEvent)19 {20 this.SendEvent(this.Id, new UnitEvent());21 return Task.CompletedTask;22 }23 protected override Task OnEventAsync(Event e)24 {25 return Task.CompletedTask;26 }27 }28 {29 [OnEventDoAction(typeof(UnitEvent), nameof(HandleUnitEvent))]30 private class Init : MonitorState { }31 private void HandleUnitEvent()32 {33 var group = this.Runtime.GetCurrentEventGroup();34 this.Assert(group == 0, "Expected event group 0, but found {0}", group);35 }36 }37}38using System;39using System.Threading.Tasks;40using Microsoft.Coyote;41using Microsoft.Coyote.Actors;42using Microsoft.Coyote.Tasks;43{44 {45 public static void Main()46 {47 Runtime.RegisterMonitor(typeof(MyMonitor));48 Runtime.Run(new Configuration(), () => {49 var actor = Actor.Create(typeof(MyActor));50 actor.SendEvent(new UnitEvent());51 });52 }53 }54 {55 protected override Task OnInitializeAsync(Event initialEvent)56 {57 this.SendEvent(this.Id, new UnitEvent());58 return Task.CompletedTask;59 }60 protected override Task OnEventAsync(Event e)61 {62 return Task.CompletedTask;63 }64 }65 {66 [OnEventDoAction(typeof(UnitEvent), nameof(HandleUnitEvent))]67 private class Init : MonitorState { }68 private void HandleUnitEvent()69 {70 var group = this.Runtime.GetNextEventGroup();71 this.Assert(group == 1, "Expected event group

Full Screen

Full Screen

GetCurrentEventGroup

Using AI Code Generation

copy

Full Screen

1{2 using System;3 using System.Threading.Tasks;4 using Microsoft.Coyote;5 using Microsoft.Coyote.Actors;6 using Microsoft.Coyote.Testing;7 using Microsoft.Coyote.Tasks;8 {9 public static void Main(string[] args)10 {11 Console.WriteLine("CoyoteTest");12 var config = Configuration.Create();13 config.SchedulingIterations = 100;14 config.SchedulingStrategy = SchedulingStrategy.FairPCT;15 config.SchedulingRandomizationSeed = 1;16 config.SchedulingVerbosity = 2;17 config.TestingIterations = 10;18 config.TestReporters.Add(new HtmlReporter());19 config.TestReporters.Add(new XunitTestReporter());20 config.TestReporters.Add(new TracingLogger());21 config.MaxFairSchedulingSteps = 100;22 config.MaxUnfairSchedulingSteps = 100;23 config.MaxStepsFromEntryToExit = 100;24 config.MaxSchedulingSteps = 100;25 config.MaxStepsFromAnyStateToExit = 100;26 config.MaxStepsFromAnyStateToAnyState = 100;27 config.MaxStepsFromAnyStateToAnyStateInEntry = 100;28 config.MaxStepsFromAnyStateToAnyStateInExit = 100;29 config.MaxStepsFromAnyStateToAnyStateInError = 100;30 config.MaxStepsFromAnyStateToAnyStateInHalt = 100;31 config.MaxStepsFromAnyStateToAnyStateInIgnore = 100;32 config.MaxStepsFromAnyStateToAnyStateInWait = 100;33 config.MaxStepsFromAnyStateToAnyStateInYield = 100;34 config.MaxStepsFromAnyStateToAnyStateInChoice = 100;35 config.MaxStepsFromAnyStateToAnyStateInDefer = 100;36 config.MaxStepsFromAnyStateToAnyStateInPushState = 100;37 config.MaxStepsFromAnyStateToAnyStateInPopState = 100;38 config.MaxStepsFromAnyStateToAnyStateInPushChoice = 100;39 config.MaxStepsFromAnyStateToAnyStateInPopChoice = 100;40 config.MaxStepsFromAnyStateToAnyStateInPushEntry = 100;41 config.MaxStepsFromAnyStateToAnyStateInPopEntry = 100;

Full Screen

Full Screen

GetCurrentEventGroup

Using AI Code Generation

copy

Full Screen

1using Microsoft.Coyote.Actors;2using System;3using System.Threading.Tasks;4{5 {6 protected override Task OnInitializeAsync(Event initialEvent)7 {8 Console.WriteLine("Actor1 OnInitializeAsync");9 return Task.CompletedTask;10 }11 protected override Task OnEventAsync(Event e)12 {13 Console.WriteLine("Actor1 OnEventAsync");14 return Task.CompletedTask;15 }16 }17 {18 protected override Task OnInitializeAsync(Event initialEvent)19 {20 Console.WriteLine("Actor2 OnInitializeAsync");21 return Task.CompletedTask;22 }23 protected override Task OnEventAsync(Event e)24 {25 Console.WriteLine("Actor2 OnEventAsync");26 return Task.CompletedTask;27 }28 }29 {30 protected override Task OnInitializeAsync(Event initialEvent)31 {32 Console.WriteLine("Actor3 OnInitializeAsync");33 return Task.CompletedTask;34 }35 protected override Task OnEventAsync(Event e)36 {37 Console.WriteLine("Actor3 OnEventAsync");38 return Task.CompletedTask;39 }40 }41 {42 protected override Task OnInitializeAsync(Event initialEvent)43 {44 Console.WriteLine("Actor4 OnInitializeAsync");45 return Task.CompletedTask;46 }47 protected override Task OnEventAsync(Event e)48 {49 Console.WriteLine("Actor4 OnEventAsync");50 return Task.CompletedTask;51 }52 }53 {54 protected override Task OnInitializeAsync(Event initialEvent)55 {56 Console.WriteLine("Actor5 OnInitializeAsync");57 return Task.CompletedTask;58 }59 protected override Task OnEventAsync(Event e)60 {61 Console.WriteLine("Actor5 OnEventAsync");62 return Task.CompletedTask;63 }64 }65 {66 static void Main(string[] args)67 {68 var runtime = RuntimeFactory.Create();69 runtime.CreateActor(typeof(Actor1));70 runtime.CreateActor(typeof(Actor2));71 runtime.CreateActor(typeof(Actor3));72 runtime.CreateActor(typeof(Actor4));73 runtime.CreateActor(typeof(Actor5));74 Console.ReadLine();75 }76 }77}

Full Screen

Full Screen

GetCurrentEventGroup

Using AI Code Generation

copy

Full Screen

1using Microsoft.Coyote;2using System;3using System.Threading.Tasks;4{5 {6 static void Main(string[] args)7 {8 Console.WriteLine("Hello World!");9 Console.ReadLine();10 }11 }12 {13 protected override Task OnInitializeAsync(Event initialEvent)14 {15 var eventGroup = this.Runtime.GetCurrentEventGroup();16 return Task.CompletedTask;17 }18 }19}20Severity Code Description Project File Line Suppression State Error CS1061 'ActorExecutionContext' does not contain a definition for 'GetCurrentEventGroup' and no accessible extension method 'GetCurrentEventGroup' accepting a first argument of type 'ActorExecutionContext' could be found (are you missing a using directive or an assembly reference?) CoyoteApp C:\Users\user\source\repos\CoyoteApp\CoyoteApp\Program.cs 19 Active

Full Screen

Full Screen

GetCurrentEventGroup

Using AI Code Generation

copy

Full Screen

1using System;2using System.Threading.Tasks;3using Microsoft.Coyote.Actors;4{5 {6 private static async Task Main(string[] args)7 {8 var runtime = RuntimeFactory.Create();9 await runtime.CreateActorAndExecuteAsync(typeof(CoyoteActor));10 }11 }12 {13 protected override async Task OnInitializeAsync(Event initialEvent)14 {15 var group = this.CreateEventGroup();16 var e = new Event();17 this.SendEvent(this.Id, e, group);18 var eventGroup = this.GetCurrentEventGroup(e);19 if (eventGroup != null)20 {21 Console.WriteLine("The event group of the event e is not null.");22 }23 {24 Console.WriteLine("The event group of the event e is null.");25 }26 eventGroup = this.GetCurrentEventGroup(initialEvent);27 if (eventGroup != null)28 {29 Console.WriteLine("The event group of the event initialEvent is not null.");30 }31 {32 Console.WriteLine("The event group of the event initialEvent is null.");33 }34 eventGroup = this.GetCurrentEventGroup(group);35 if (eventGroup != null)36 {37 Console.WriteLine("The event group of the event group is not null.");38 }39 {40 Console.WriteLine("The event group of the event group is null.");41 }42 }43 }44}

Full Screen

Full Screen

Automation Testing Tutorials

Learn 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.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful