static string StartClients(string sctx, SynchronizedLogger logger, out DomainCommunicationProvider clientsNetworkProvider)
        {
            var configuration = Configuration.Create().WithMonitorsInProductionEnabled().WithVerbosityEnabled(2);
            var runtime       = PSharpRuntime.Create(configuration);
            var runtimeHost   = HostInfo.NewRuntimeHost(runtime);

            clientsNetworkProvider = new DomainCommunicationProvider(runtimeHost, "clients");
            runtimeHost.SetNetworkProvider(clientsNetworkProvider);
            runtimeHost.SetLogger(logger);

            var messages = new MessageCollection();

            messages.CollectionChanged += (sender, e) => logger.WriteLine(e.NewItems[0].ToString());
            var ctx = sctx.FromJson <DistributedStorageContext>();

            var synchronizable = Synchronizable.Empty();

            foreach (var storageNode in ctx.StorageNodes)
            {
                var waitIfHandledReplReq = logger.MachineActionHandledWait((machineId, _, actionName) => Equals(machineId, storageNode.Id) && actionName == "HandleReplReq");
                synchronizable = synchronizable.Then(waitIfHandledReplReq.Delay(10));
            }
            logger.ApplySynchronization(synchronizable);

            NewClients(runtimeHost, ctx, messages);
            logger.WaitForWriting(6000);
            return(ctx.ToJson());
        }
        static void StartTimers(string sctx, SynchronizedLogger logger)
        {
            var ctx             = sctx.FromJson <DistributedStorageContext>();
            var lastStorageNode = ctx.StorageNodes.Last();

            foreach (var storageNode in ctx.StorageNodes)
            {
                if (storageNode == lastStorageNode)
                {
                    var setIfHandledTimeout = logger.MachineActionHandledSet((_1, _2, actionName) => actionName == "HandleTimeout");
                    var setIfEnteredExit    = logger.MachineActionHandledSet((_1, _2, actionName) => actionName == "EnterExit");
                    logger.ApplySynchronization(setIfHandledTimeout.And(setIfEnteredExit));
                }
                else
                {
                    var setIfHandledTimeout = logger.MachineActionHandledSet((_1, _2, actionName) => actionName == "HandleTimeout");
                    logger.ApplySynchronization(setIfHandledTimeout);
                }

                storageNode.Timeout(new Timeout());

                logger.WaitForWriting(3000);
            }
        }
        public void Context_should_not_return_same_Machine_if_it_is_in_remote_and_multi_application()
        {
            // Arrange
            var expected        = default(int);
            var actual          = default(int);
            var expected_Assign = new MarshalByRefAction <int>(i => expected = i);
            var actual_Assign   = new MarshalByRefAction <int>(i => actual = i);

            // Act
            AppDomain.CurrentDomain.RunAtIsolatedDomain((expected_Assign_, actual_Assign_) =>
            {
                var configuration         = Configuration.Create().WithVerbosityEnabled(2);
                var runtime               = PSharpRuntime.Create(configuration);
                var runtimeHost           = HostInfo.NewRuntimeHost(runtime);
                var logger                = new SynchronizedLogger(new InMemoryLogger());
                var setIfHandledHandshake = logger.MachineActionHandledSet((_1, _2, actionName) => actionName == "HandleHandshake");
                logger.ApplySynchronization(setIfHandledHandshake);
                runtimeHost.SetLogger(logger);
                using (var networkProvider = new DomainCommunicationProvider(runtimeHost, "servers"))
                {
                    var parameter = default(string);
                    {
                        runtimeHost.SetNetworkProvider(networkProvider);

                        var ctx    = runtimeHost.New <DistributedStorageContext>();
                        ctx.Server = runtimeHost.New(MachineInterface.Sender <IServerSender>().Bundler <IServerBundler>().Receiver <ServerReceiverWithoutBug>());
                        ctx.Server.Configure(new ConfigureServer(new MessageCollection(), null, null));
                        expected_Assign_.Invoke(RuntimeHelpers.GetHashCode(ctx.Server));
                        parameter = ctx.ToJson();
                    }

                    AppDomain.CurrentDomain.RunAtIsolatedDomain((actual_Assign__, parameter_) =>
                    {
                        var ctx = parameter_.FromJson <DistributedStorageContext>();
                        actual_Assign__.Invoke(RuntimeHelpers.GetHashCode(ctx.Server));
                        ctx.Server.Handshake(new HandshakeServer(null, new IStorageNodeSender[0]));
                    }, actual_Assign_, parameter);

                    logger.WaitForWriting(1000);
                }
            }, expected_Assign, actual_Assign);


            // Assert
            Assert.AreNotEqual(expected, actual);
        }
        public void Machine_should_transit_its_state_according_to_passed_event()
        {
            // Arrange
            var configuration    = Configuration.Create().WithMonitorsInProductionEnabled().WithVerbosityEnabled(2);
            var runtime          = PSharpRuntime.Create(configuration);
            var runtimeHost      = HostInfo.NewRuntimeHost(runtime);
            var logger           = new SynchronizedLogger(new InMemoryLogger());
            var setIfHandledSync = logger.MachineActionHandledSet((_1, _2, actionName) => actionName == "HandleSync");

            logger.ApplySynchronization(setIfHandledSync);
            runtimeHost.SetLogger(logger);
            var server = runtimeHost.New(MachineInterface.Sender <IServerSender>().Bundler <IServerBundler>().Receiver <ServerReceiverWithoutBug>());


            // Act
            var messages            = new MessageCollection();
            var safetyMonitorMock   = new Mock <ISafetyMonitorSender>();
            var livenessMonitorMock = new Mock <ILivenessMonitorSender>();

            server.Configure(new ConfigureServer(messages, safetyMonitorMock.Object, livenessMonitorMock.Object));

            var clientMock = new Mock <IClientSender>();
            var clientId   = runtime.CreateMachine(typeof(Client));

            clientMock.SetupGet(_ => _.Id).Returns(clientId);
            var storageNodeMock = new Mock <IStorageNodeSender>();
            var storageNodeId   = runtime.CreateMachine(typeof(StorageNode));

            storageNodeMock.Setup(_ => _.Id).Returns(storageNodeId);
            server.Handshake(new HandshakeServer(clientMock.Object, new[] { storageNodeMock.Object }));

            var clientReq = new ClientReq(42);

            server.ClientReq(clientReq);

            server.Sync(new Sync(storageNodeMock.Object, 0));


            // Assert
            Assert.That(logger.WaitForWriting(3000), Does.Contain("handled action 'HandleSync'"));
            livenessMonitorMock.Verify(_ => _.ClientReq(clientReq));
            storageNodeMock.Verify(_ => _.ReplReq(It.Is <ReplReq>(x => x.Data == clientReq.DataToReplicate)));
        }
        public void Initializer_and_OnEnterInvoke_can_specify_to_the_same_place()
        {
            // Arrange
            var configuration = Configuration.Create().WithVerbosityEnabled(2);
            var runtime       = PSharpRuntime.Create(configuration);
            var runtimeHost   = HostInfo.NewRuntimeHost(runtime);

            var logger = new SynchronizedLogger(new InMemoryLogger());
            var waitIfEnteredInitialized1 = logger.MachineActionHandledWait((machineId, _, actionName) => machineId.Name.Contains("M1") && actionName == "EnterInitialized");
            var waitIfEnteredInitialized2 = logger.MachineActionHandledWait((machineId, _, actionName) => machineId.Name.Contains("M2") && actionName == "EnterInitialized");

            logger.ApplySynchronization(waitIfEnteredInitialized2.Then(waitIfEnteredInitialized1));
            runtimeHost.SetLogger(logger);


            // Act
            runtimeHost.New(MachineInterface.Sender <M1.ISender>().Bundler <M1.IBundler>().Receiver <M1.Receiver>());
            runtimeHost.New(MachineInterface.Sender <M2.ISender>().Bundler <M2.IBundler>().Receiver <M2.Receiver>());


            // Assert
            Assert.DoesNotThrow(() => logger.WaitForWriting(1000));
        }