public async Task TestGraphLoggerCollapsed() { CustomLogger logger = new CustomLogger(); Configuration config = Configuration.Create().WithVerbosityEnabled(); var graphBuilder = new ActorRuntimeLogGraphBuilder(false); graphBuilder.CollapseMachineInstances = true; var tcs = TaskCompletionSource.Create <bool>(); IActorRuntime runtime = CreateTestRuntime(config, tcs, logger); runtime.RegisterLog(graphBuilder); ActorId serverId = runtime.CreateActor(typeof(Server)); runtime.CreateActor(typeof(Client), new ClientSetupEvent(serverId)); runtime.CreateActor(typeof(Client), new ClientSetupEvent(serverId)); runtime.CreateActor(typeof(Client), new ClientSetupEvent(serverId)); await WaitAsync(tcs.Task, 5000000); await Task.Delay(1000); string actual = graphBuilder.Graph.ToString(); Assert.Contains("<Node Id='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+Client.Client' Label='Client'/>", actual); Assert.Contains("<Node Id='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+Server.Complete' Label='Complete'/>", actual); logger.Dispose(); }
public void TestQuiescentNetwork() { this.Test(async r => { var graphBuilder = new ActorRuntimeLogGraphBuilder(false); r.RegisterLog(graphBuilder); var op = new ActorHaltedEventGroup(); var id = r.CreateActor(typeof(NetworkActor), null, op); op.AddActor(id); // spawn 5 children, each child spawns 4 grand children and those spawn 3, etc. // so we should get 1 + 5 + (5*4) + (5*4*3) + (5*4*3*2) actors in this network = 206 // actors before they are all halted. r.SendEvent(id, new SpawnEvent() { Count = 5 }, op); var result = await this.GetResultAsync(op.Task); string dgml = graphBuilder.Graph.ToString(); Assert.Equal(206, op.Count); }, configuration: Configuration.Create().WithPCTStrategy(true)); }
public void TestGraphLoggerCollapsed() { this.Test(async runtime => { using (CustomLogger logger = new CustomLogger()) { runtime.Logger = logger; var graphBuilder = new ActorRuntimeLogGraphBuilder(false) { CollapseMachineInstances = true }; var tcs = new TaskCompletionSource <bool>(); runtime.RegisterMonitor <TestMonitor>(); runtime.Monitor <TestMonitor>(new SetupEvent(tcs)); runtime.RegisterLog(graphBuilder); ActorId serverId = runtime.CreateActor(typeof(Server)); runtime.CreateActor(typeof(Client), new ClientSetupEvent(serverId)); runtime.CreateActor(typeof(Client), new ClientSetupEvent(serverId)); runtime.CreateActor(typeof(Client), new ClientSetupEvent(serverId)); await this.WaitAsync(tcs.Task, 5000); await Task.Delay(1000); Assert.True(tcs.Task.IsCompleted, "The task await returned but the task is not completed???"); string actual = graphBuilder.Graph.ToString(); Assert.Contains("<Node Id='Microsoft.Coyote.Actors.Tests.CustomActorRuntimeLogTests+Client.Client' Label='Client'/>", actual); Assert.Contains("<Node Id='Microsoft.Coyote.Actors.Tests.CustomActorRuntimeLogTests+Server.Complete' Label='Complete'/>", actual); } }, this.GetConfiguration()); }
public void TestGraphLoggerInstances() { Configuration config = Configuration.Create().WithVerbosityEnabled(); this.Test(new Func <IActorRuntime, Task>(async(runtime) => { using (CustomLogger logger = new CustomLogger()) { runtime.SetLogger(logger); var graphBuilder = new ActorRuntimeLogGraphBuilder(false); var tcs = TaskCompletionSource.Create <bool>(); runtime.RegisterMonitor <TestMonitor>(); runtime.Monitor <TestMonitor>(new SetupEvent(tcs)); runtime.RegisterLog(graphBuilder); ActorId serverId = runtime.CreateActor(typeof(Server)); runtime.CreateActor(typeof(Client), new ClientSetupEvent(serverId)); runtime.CreateActor(typeof(Client), new ClientSetupEvent(serverId)); runtime.CreateActor(typeof(Client), new ClientSetupEvent(serverId)); await this.WaitAsync(tcs.Task); await Task.Delay(1000); Assert.True(tcs.Task.IsCompleted, "The task await returned but the task is not completed???"); string actual = graphBuilder.Graph.ToString(); actual = actual.RemoveInstanceIds(); Assert.Contains("<Node Id='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+Client().Client()' Label='Client()'/>", actual); Assert.Contains("<Node Id='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+Server().Complete' Label='Complete'/>", actual); Assert.Contains("<Node Id='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+TestMonitor.Init' Label='Init'/>", actual); } }), config); }
public void TestGraphLogger() { Configuration config = Configuration.Create().WithVerbosityEnabled(); this.Test(async runtime => { using (CustomLogger logger = new CustomLogger()) { runtime.SetLogger(logger); var tcs = TaskCompletionSource.Create <bool>(); runtime.RegisterMonitor <TestMonitor>(); runtime.Monitor <TestMonitor>(new SetupEvent(tcs)); var graphBuilder = new ActorRuntimeLogGraphBuilder(false); runtime.RegisterLog(graphBuilder); runtime.CreateActor(typeof(M)); await this.WaitAsync(tcs.Task); await Task.Delay(200); Assert.True(tcs.Task.IsCompleted, "The task await returned but the task is not completed???"); string expected = @"<DirectedGraph xmlns='http://schemas.microsoft.com/vs/2009/dgml'> <Nodes> <Node Id='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+M(0)' Category='Actor' Group='Expanded'/> <Node Id='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+M(0).M(0)' Label='M(0)'/> <Node Id='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+N(1)' Category='StateMachine' Group='Expanded'/> <Node Id='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+N(1).Act' Label='Act'/> <Node Id='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+N(1).Init' Label='Init'/> <Node Id='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+TestMonitor' Group='Expanded'/> <Node Id='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+TestMonitor.Init' Label='Init'/> </Nodes> <Links> <Link Source='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+M(0)' Target='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+M(0).M(0)' Category='Contains'/> <Link Source='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+M(0)' Target='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+N(1)' Label='CreateActor' Index='0' EventId='CreateActor'/> <Link Source='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+M(0).M(0)' Target='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+N(1).Init' Label='E' Index='0' EventId='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+E' HandledBy='Init'/> <Link Source='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+M(0).M(0)' Target='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+TestMonitor.Init' Label='CompletedEvent' Index='0' EventId='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+CompletedEvent'/> <Link Source='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+N(1)' Target='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+N(1).Act' Category='Contains'/> <Link Source='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+N(1)' Target='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+N(1).Init' Category='Contains'/> <Link Source='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+N(1).Act' Target='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+M(0).M(0)' Label='E' Index='0' EventId='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+E'/> <Link Source='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+N(1).Init' Target='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+N(1).Act' Label='E' Index='0' EventId='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+E' HandledBy='Init'/> <Link Source='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+TestMonitor' Target='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+TestMonitor.Init' Category='Contains'/> <Link Source='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+TestMonitor.Init' Target='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+TestMonitor.Init' Label='CompletedEvent' Index='0' EventId='Microsoft.Coyote.Production.Tests.Actors.CustomActorRuntimeLogTests+CompletedEvent'/> </Links> </DirectedGraph> "; string dgml = graphBuilder.Graph.ToString(); string actual = dgml.RemoveNonDeterministicValues(); expected = expected.RemoveNonDeterministicValues(); Assert.Equal(expected, actual); } }, config); }
public async Task TestGraphLogger() { CustomLogger logger = new CustomLogger(); Configuration config = Configuration.Create().WithVerbosityEnabled(); var graphBuilder = new ActorRuntimeLogGraphBuilder(false); var tcs = TaskCompletionSource.Create <bool>(); IActorRuntime runtime = CreateTestRuntime(config, tcs, logger); runtime.RegisterLog(graphBuilder); runtime.CreateActor(typeof(M)); await WaitAsync(tcs.Task); await Task.Delay(200); string expected = @"<DirectedGraph xmlns='http://schemas.microsoft.com/vs/2009/dgml'> <Nodes> <Node Id='M()' Category='Actor' Group='Expanded'/> <Node Id='M().M()' Label='M()'/> <Node Id='N()' Category='StateMachine' Group='Expanded'/> <Node Id='N().Act' Label='Act'/> <Node Id='N().Init' Label='Init'/> <Node Id='TestMonitor' Group='Expanded'/> <Node Id='TestMonitor.Init' Label='Init'/> <Node Id='TestMonitor.OnCompleted' Label='OnCompleted'/> </Nodes> <Links> <Link Source='M().M()' Target='N().Init' Label='E' Index='' EventId='E' HandledBy='Init'/> <Link Source='M().M()' Target='TestMonitor.Init' Label='CompletedEvent' Index='' EventId='CompletedEvent'/> <Link Source='M()' Target='M().M()' Category='Contains'/> <Link Source='N().Act' Target='M().M()' Label='E' Index='' EventId='E'/> <Link Source='N().Init' Target='N().Act' Label='E' Index='' EventId='E' HandledBy='Init'/> <Link Source='N()' Target='N().Act' Category='Contains'/> <Link Source='N()' Target='N().Init' Category='Contains'/> <Link Source='TestMonitor.Init' Target='TestMonitor.OnCompleted' Label='CompletedEvent' Index='' EventId='CompletedEvent'/> <Link Source='TestMonitor' Target='TestMonitor.Init' Category='Contains'/> <Link Source='TestMonitor' Target='TestMonitor.OnCompleted' Category='Contains'/> </Links> </DirectedGraph> "; string actual = RemoveNonDeterministicValuesFromReport(graphBuilder.Graph.ToString()); Assert.Equal(expected, actual); logger.Dispose(); }
private static async void PeriodicSaves(ActorRuntimeLogGraphBuilder log, string baseName) { while (true) { await Task.Delay(10000); Graph graph = log.SnapshotGraph(false); string filename = baseName + ".dgml"; using (var stream = new StreamWriter(filename, false, Encoding.UTF8)) { Console.WriteLine("############ saved " + filename + " ##########################################"); graph.WriteDgml(stream, true); } } }
public void TestQuiescentNetwork() { this.Test(async r => { var graphBuilder = new ActorRuntimeLogGraphBuilder(false, false); r.RegisterLog(graphBuilder); var op = new ActorHaltedEventGroup(); var id = r.CreateActor(typeof(NetworkActor), null, op); op.AddActor(id); // Spawn 4 children, each child spawns 3 children and those spawn 2, etc. // So we should get 41 (1 + 4 + (4*3) + (4*3*2)) actors in the network // before they are all halted. r.SendEvent(id, new SpawnEvent() { Count = 4 }, op); var result = await this.GetResultAsync(op.Task); Assert.Equal(41, op.Count); }); }
internal async Task RunAsync() { try { // We use the Topic/Subscription pattern which is a pub/sub model where each Server will send // messages to this Topic, and every other server has a Subscription to receive those messages. // If the Message has a "To" field then the server ignores the message as it was not meant for them. // Otherwise the Message is considered a "broadcast" to all servers and each server will handle it. // The client also has a subcription on the same topic and is how it broadcasts requests and receives // the final response from the elected Leader. var managementClient = new ManagementClient(this.ConnectionString); if (!await managementClient.TopicExistsAsync(this.TopicName)) { await managementClient.CreateTopicAsync(this.TopicName); } // then we need a subscription, whether we are client or server and the subscription name will be // the same as our local actorid. string subscriptionName = (this.ServerId < 0) ? "Client" : $"Server-{this.ServerId}"; if (!await managementClient.SubscriptionExistsAsync(this.TopicName, subscriptionName)) { await managementClient.CreateSubscriptionAsync( new SubscriptionDescription(this.TopicName, subscriptionName)); } Console.WriteLine("Running " + subscriptionName); IActorRuntime runtime = RuntimeFactory.Create(Configuration.Create().WithVerbosityEnabled()); if (this.GraphIt) { var graphBuilder = new ActorRuntimeLogGraphBuilder(false); runtime.RegisterLog(graphBuilder); _ = Task.Run(() => { PeriodicSaves(graphBuilder, subscriptionName); }); } // We create a new Coyote actor runtime instance, and pass an optional configuration // that increases the verbosity level to see the Coyote runtime log. runtime.OnFailure += RuntimeOnFailure; var topicClient = new TopicClient(this.ConnectionString, this.TopicName); // cluster manager needs the topic client in order to be able to broadcast messages using Azure Service Bus var clusterManager = runtime.CreateActor(typeof(AzureClusterManager), new AzureClusterManager.RegisterMessageBusEvent() { TopicClient = topicClient }); if (this.ServerId < 0) { await this.RunClient(runtime, clusterManager, subscriptionName); } else { await this.RunServer(runtime, clusterManager, subscriptionName); } } catch (Exception ex) { Console.WriteLine($"{DateTime.Now} :: ex: {ex.ToString()}"); } }