Example #1
0
        public void TestRemoveChangeListener()
        {
            var statuses         = new List <ReplicatorActivityLevel>();
            var listener         = new MessageEndpointListener(new MessageEndpointListenerConfiguration(_otherDB, ProtocolType.ByteStream));
            var awaiter          = new ListenerAwaiter(listener);
            var serverConnection = new MockServerConnection(listener, ProtocolType.ByteStream);
            var config           = new ReplicatorConfiguration(Db,
                                                               new MessageEndpoint("p2ptest1", serverConnection, ProtocolType.ByteStream,
                                                                                   new MockConnectionFactory(null)))
            {
                Continuous = true
            };
            var token = listener.AddChangeListener((sender, args) =>
            {
                statuses.Add(args.Status.Activity);
            });
            var connection = listener.Connections;

            listener.RemoveChangeListener(token);
            RunReplication(config, 0, 0);
            awaiter.WaitHandle.WaitOne(TimeSpan.FromSeconds(10)).Should().BeTrue();
            awaiter.Validate();

            statuses.Count.Should().Be(0);
        }
 public void TearDown()
 {
     user    = null;
     manager = null;
     server  = null;
     server  = null;
 }
Example #3
0
        private ReplicatorConfiguration CreateFailureP2PConfiguration(ProtocolType protocolType, MockConnectionLifecycleLocation location, bool recoverable)
        {
            var errorLocation = TestErrorLogic.FailWhen(location);

            if (recoverable)
            {
                errorLocation.WithRecoverableException();
            }
            else
            {
                errorLocation.WithPermanentException();
            }

            var listener = new MessageEndpointListener(new MessageEndpointListenerConfiguration(_otherDB, protocolType));
            var server   = new MockServerConnection(listener, protocolType)
            {
                ErrorLogic = errorLocation
            };
            var config = new ReplicatorConfiguration(Db,
                                                     new MessageEndpoint("p2ptest1", server, protocolType, new MockConnectionFactory(errorLocation)))
            {
                ReplicatorType = ReplicatorType.Push,
                Continuous     = false
            };

            return(config);
        }
Example #4
0
        public void Setup()
        {
            manager     = new ServerUserManager();
            permissions = new MockPermissionsProvider();
            channels    = new LobbyChannelProvider();

            MockServerContext mcontext;

            context = mcontext = new MockServerContext
            {
                ChannelsProvider    = channels,
                PermissionsProvider = permissions,
                UserManager         = new ServerUserManager(),
                Settings            = new ServerSettings {
                    Name = "Test Server"
                }
            };

            mcontext.Users    = new ServerUserHandler(context, manager);
            mcontext.Channels = handler = new ServerChannelHandler(context);

            user = UserInfoTests.GetTestUser(1, 1, false);

            provider = new MockConnectionProvider(GablarskiProtocol.Instance);
            mcontext.AddConnectionProvider(provider);
            mcontext.Start();

            var connections = provider.GetConnections(GablarskiProtocol.Instance);

            client = new ConnectionBuffer(connections.Item1);
            server = connections.Item2;

            manager.Connect(server);
            manager.Join(server, user);
        }
 public void Teardown()
 {
     handler     = null;
     manager     = null;
     context     = null;
     server      = null;
     permissions = null;
 }
        public void Setup()
        {
            user    = new UserInfo("Nickname", "Phonetic", "Username", 1, 2, true);
            manager = new ServerUserManager();

            provider = new MockConnectionProvider(GablarskiProtocol.Instance);
            provider.Start(MessageTypes.All);

            var cs = provider.GetConnections(GablarskiProtocol.Instance);

            server = cs.Item2;
            client = cs.Item1;
        }
Example #7
0
        public void TestP2PPassiveCloseAll()
        {
            var listener          = new MessageEndpointListener(new MessageEndpointListenerConfiguration(_otherDB, ProtocolType.MessageStream));
            var serverConnection1 = new MockServerConnection(listener, ProtocolType.MessageStream);
            var serverConnection2 = new MockServerConnection(listener, ProtocolType.MessageStream);
            var errorLogic        = new ReconnectErrorLogic();
            var config            = new ReplicatorConfiguration(Db,
                                                                new MessageEndpoint("p2ptest1", serverConnection1, ProtocolType.MessageStream,
                                                                                    new MockConnectionFactory(errorLogic)))
            {
                Continuous = true
            };

            var config2 = new ReplicatorConfiguration(Db,
                                                      new MessageEndpoint("p2ptest2", serverConnection2, ProtocolType.MessageStream,
                                                                          new MockConnectionFactory(errorLogic)))
            {
                Continuous = true
            };

            var replicator = new Replicator(config);

            replicator.Start();
            var replicator2 = new Replicator(config2);

            replicator2.Start();

            var count = 0;

            while (count++ < 10 && replicator.Status.Activity != ReplicatorActivityLevel.Idle && replicator2.Status.Activity != ReplicatorActivityLevel.Idle)
            {
                Thread.Sleep(500);
                count.Should().BeLessThan(10, "because otherwise the replicator(s) never went idle");
            }

            errorLogic.ErrorActive = true;
            listener.CloseAll();
            count = 0;
            while (count++ < 10 && replicator.Status.Activity != ReplicatorActivityLevel.Stopped && replicator2.Status.Activity != ReplicatorActivityLevel.Stopped)
            {
                Thread.Sleep(500);
                count.Should().BeLessThan(10, "because otherwise the replicator(s) never stopped");
            }

            replicator.Status.Error.Should()
            .NotBeNull("because closing the passive side creates an error on the active one");
            replicator2.Status.Error.Should()
            .NotBeNull("because closing the passive side creates an error on the active one");
            replicator.Dispose();
            replicator2.Dispose();
        }
        public void Setup()
        {
            permissions = new MockPermissionsProvider();

            LobbyChannelProvider channels = new LobbyChannelProvider();

            channels.SaveChannel(new ChannelInfo
            {
                Name = "Channel 2"
            });

            this.provider = new MockConnectionProvider(GablarskiProtocol.Instance);
            this.provider.Start(MessageTypes.All);

            userManager = new ServerUserManager();
            MockServerContext c;

            context = c = new MockServerContext(provider)
            {
                Settings = new ServerSettings
                {
                    Name = "Server",
                    DefaultAudioBitrate = defaultBitrate,
                    MaximumAudioBitrate = maxBitrate,
                    MinimumAudioBitrate = minBitrate
                },

                UserManager         = userManager,
                PermissionsProvider = permissions,
                ChannelsProvider    = channels
            };
            c.Users = new ServerUserHandler(context, userManager);

            manager = new ServerSourceManager(context);
            handler = new ServerSourceHandler(context, manager);

            user = UserInfoTests.GetTestUser(1, 1, false);

            var cs = provider.GetConnections(GablarskiProtocol.Instance);

            client = new ConnectionBuffer(cs.Item1);
            server = cs.Item2;

            userManager.Connect(server);
            userManager.Join(server, user);
        }
Example #9
0
        public void TestP2PPassiveClose()
        {
            var listener         = new MessageEndpointListener(new MessageEndpointListenerConfiguration(_otherDB, ProtocolType.MessageStream));
            var awaiter          = new ListenerAwaiter(listener);
            var serverConnection = new MockServerConnection(listener, ProtocolType.MessageStream);
            var errorLogic       = new ReconnectErrorLogic();
            var config           = new ReplicatorConfiguration(Db,
                                                               new MessageEndpoint("p2ptest1", serverConnection, ProtocolType.MessageStream,
                                                                                   new MockConnectionFactory(errorLogic)))
            {
                Continuous = true
            };

            var replicator = new Replicator(config);

            replicator.Start();

            var count = 0;

            while (count++ < 10 && replicator.Status.Activity != ReplicatorActivityLevel.Idle)
            {
                Thread.Sleep(500);
                count.Should().BeLessThan(10, "because otherwise the replicator never went idle");
            }

            errorLogic.ErrorActive = true;
            listener.Close(serverConnection);
            count = 0;
            while (count++ < 10 && replicator.Status.Activity != ReplicatorActivityLevel.Stopped)
            {
                Thread.Sleep(500);
                count.Should().BeLessThan(10, "because otherwise the replicator never stopped");
            }


            awaiter.WaitHandle.WaitOne(TimeSpan.FromSeconds(10)).Should().BeTrue();
            awaiter.Validate();

            replicator.Status.Error.Should()
            .NotBeNull("because closing the passive side creates an error on the active one");
        }
        public AudioSource GetSourceFromRequest(MockServerConnection serverConnection, ConnectionBuffer clientConnection)
        {
            permissions.EnablePermissions(userManager.GetUser(serverConnection).UserId, PermissionName.RequestSource);

            var audioArgs = new AudioCodecArgs(AudioFormat.Mono16bitLPCM, 64000, AudioSourceTests.FrameSize, 10);

            handler.RequestSourceMessage(new MessageEventArgs <RequestSourceMessage> (serverConnection,
                                                                                      new RequestSourceMessage("Name", audioArgs)));

            var result = clientConnection.DequeueAndAssertMessage <SourceResultMessage>();

            Assert.AreEqual(SourceResult.Succeeded, result.SourceResult);
            Assert.AreEqual("Name", result.SourceName);
            Assert.AreEqual("Name", result.Source.Name);

            AudioCodecArgsTests.AssertAreEqual(audioArgs, result.Source.CodecSettings);

            clientConnection.AssertNoMessage();

            return(result.Source);
        }
Example #11
0
        public void TestP2PChangeListener()
        {
            var statuses         = new List <ReplicatorActivityLevel>();
            var listener         = new MessageEndpointListener(new MessageEndpointListenerConfiguration(_otherDB, ProtocolType.ByteStream));
            var serverConnection = new MockServerConnection(listener, ProtocolType.ByteStream);
            var config           = new ReplicatorConfiguration(Db,
                                                               new MessageEndpoint("p2ptest1", serverConnection, ProtocolType.ByteStream,
                                                                                   new MockConnectionFactory(null)))
            {
                Continuous = true
            };

            listener.AddChangeListener((sender, args) =>
            {
                statuses.Add(args.Status.Activity);
            });

            RunReplication(config, 0, 0);
            statuses.Count(x => x == ReplicatorActivityLevel.Connecting).Should().Be(1);
            statuses.Count(x => x == ReplicatorActivityLevel.Busy).Should().BeGreaterOrEqualTo(1);
            statuses.Any(x => x == ReplicatorActivityLevel.Offline).Should().Be(false);
            statuses.Count(x => x == ReplicatorActivityLevel.Stopped).Should().Be(1);
        }
Example #12
0
        //[Fact] uwp
        public void TestP2PChangeListener()
        {
            var statuses         = new List <ReplicatorActivityLevel>();
            var listener         = new MessageEndpointListener(new MessageEndpointListenerConfiguration(OtherDb, ProtocolType.ByteStream));
            var awaiter          = new ListenerAwaiter(listener);
            var serverConnection = new MockServerConnection(listener, ProtocolType.ByteStream);
            var config           = new ReplicatorConfiguration(Db,
                                                               new MessageEndpoint("p2ptest1", serverConnection, ProtocolType.ByteStream,
                                                                                   new MockConnectionFactory(null)))
            {
                Continuous = true
            };

            listener.AddChangeListener((sender, args) => {
                statuses.Add(args.Status.Activity);
            });
            var connection = listener.Connections;

            RunReplication(config, 0, 0);
            awaiter.WaitHandle.WaitOne(TimeSpan.FromSeconds(10)).Should().BeTrue();
            awaiter.Validate();
            statuses.Count.Should()
            .BeGreaterThan(1, "because otherwise there were no callbacks to the change listener");
        }
Example #13
0
        private void RunTwoStepContinuous(ReplicatorType type, string uid)
        {
            var listener = new MessageEndpointListener(new MessageEndpointListenerConfiguration(_otherDB, ProtocolType.ByteStream));
            var server   = new MockServerConnection(listener, ProtocolType.ByteStream);
            var config   = new ReplicatorConfiguration(Db,
                                                       new MessageEndpoint(uid, server, ProtocolType.ByteStream, new MockConnectionFactory(null)))
            {
                ReplicatorType = type,
                Continuous     = true
            };
            var replicator = new Replicator(config);

            replicator.Start();

            Database firstSource  = null;
            Database secondSource = null;
            Database firstTarget  = null;
            Database secondTarget = null;

            if (type == ReplicatorType.Push)
            {
                firstSource  = Db;
                secondSource = Db;
                firstTarget  = _otherDB;
                secondTarget = _otherDB;
            }
            else if (type == ReplicatorType.Pull)
            {
                firstSource  = _otherDB;
                secondSource = _otherDB;
                firstTarget  = Db;
                secondTarget = Db;
            }
            else
            {
                firstSource  = Db;
                secondSource = _otherDB;
                firstTarget  = _otherDB;
                secondTarget = Db;
            }

            using (var mdoc = new MutableDocument("livesindb")) {
                mdoc.SetString("name", "db");
                mdoc.SetInt("version", 1);
                firstSource.Save(mdoc);
            }

            var count = 0;

            while (replicator.Status.Progress.Completed == 0 ||
                   replicator.Status.Activity != ReplicatorActivityLevel.Idle)
            {
                Thread.Sleep(500);
                count++;
                count.Should().BeLessThan(10, "because otherwise the replicator did not advance");
            }

            var previousCompleted = replicator.Status.Progress.Completed;

            firstTarget.Count.Should().Be(1);

            using (var savedDoc = secondSource.GetDocument("livesindb"))
                using (var mdoc = savedDoc.ToMutable()) {
                    mdoc.SetInt("version", 2);
                    secondSource.Save(mdoc);
                }

            count = 0;
            while (replicator.Status.Progress.Completed == previousCompleted ||
                   replicator.Status.Activity != ReplicatorActivityLevel.Idle)
            {
                Thread.Sleep(500);
                count++;
                count.Should().BeLessThan(10, "because otherwise the replicator did not advance");
            }

            using (var savedDoc = secondTarget.GetDocument("livesindb")) {
                savedDoc.GetInt("version").Should().Be(2);
            }

            replicator.Stop();
            while (replicator.Status.Activity != ReplicatorActivityLevel.Stopped)
            {
                Thread.Sleep(100);
            }

            replicator.Dispose();
        }
Example #14
0
        private void RunTwoStepContinuous(ReplicatorType type, string uid)
        {
            using (var OtherDb1 = OpenDB(OtherDb.Name))
                using (var Db1 = OpenDB(Db.Name)) {
                    var listener = new MessageEndpointListener(new MessageEndpointListenerConfiguration(OtherDb1, ProtocolType.ByteStream));
                    var server   = new MockServerConnection(listener, ProtocolType.ByteStream);
                    var config   = new ReplicatorConfiguration(Db1,
                                                               new MessageEndpoint(uid, server, ProtocolType.ByteStream, new MockConnectionFactory(null)))
                    {
                        ReplicatorType = type,
                        Continuous     = true
                    };

                    using (var replicator = new Replicator(config)) {
                        Database firstSource  = null;
                        Database secondSource = null;
                        Database firstTarget  = null;
                        Database secondTarget = null;
                        if (type == ReplicatorType.Push)
                        {
                            firstSource  = Db1;
                            secondSource = Db1;
                            firstTarget  = OtherDb1;
                            secondTarget = OtherDb1;
                        }
                        else if (type == ReplicatorType.Pull)
                        {
                            firstSource  = OtherDb1;
                            secondSource = OtherDb1;
                            firstTarget  = Db1;
                            secondTarget = Db1;
                        }
                        else
                        {
                            firstSource  = Db1;
                            secondSource = OtherDb1;
                            firstTarget  = OtherDb1;
                            secondTarget = Db1;
                        }

                        replicator.Start();

                        using (var mdoc = new MutableDocument("livesindb")) {
                            mdoc.SetString("name", "db");
                            mdoc.SetInt("version", 1);
                            firstSource.Save(mdoc);
                        }

                        var count = 0;
                        if (type != ReplicatorType.Push)
                        {
                            while (true)
                            {
                                count++;
                                Thread.Sleep(1000);
                                if (replicator.Status.Progress.Completed > 0 &&
                                    replicator.Status.Activity == ReplicatorActivityLevel.Idle)
                                {
                                    break;
                                }
                            }

                            count.Should().BeLessThan(10, "because otherwise the replicator did not advance");
                        }
                        else //when both doc updates happens on local side with push only, replicator.Status.Progress value wipe out too fast, so skip while loop
                        {
                            Thread.Sleep(1000);
                        }

                        var previousCompleted = replicator.Status.Progress.Completed;
                        firstTarget.Count.Should().Be(1);

                        using (var savedDoc = secondSource.GetDocument("livesindb"))
                            using (var mdoc = savedDoc.ToMutable()) {
                                mdoc.SetInt("version", 2);
                                secondSource.Save(mdoc);
                            }

                        count = 0;
                        if (type != ReplicatorType.Push)
                        {
                            while (true)
                            {
                                count++;
                                Thread.Sleep(1000);
                                if (replicator.Status.Progress.Completed > previousCompleted &&
                                    replicator.Status.Activity == ReplicatorActivityLevel.Idle)
                                {
                                    break;
                                }
                            }

                            count.Should().BeLessThan(10, "because otherwise the replicator did not advance");
                        }
                        else //when both doc updates happens on local side with push only, replicator.Status.Progress value wipe out too fast, so skip while loop
                        {
                            Thread.Sleep(1000);
                        }

                        using (var savedDoc = secondTarget.GetDocument("livesindb")) {
                            savedDoc.GetInt("version").Should().Be(2);
                        }

                        replicator.Stop();
                        Thread.Sleep(100);
                        while (true)
                        {
                            if (replicator.Status.Activity == ReplicatorActivityLevel.Stopped)
                            {
                                break;
                            }
                        }
                    }
                }
        }
Example #15
0
        public void TestShortP2P()
        {
            var testNo = 1;

            foreach (var protocolType in new[] { ProtocolType.ByteStream, ProtocolType.MessageStream })
            {
                using (var mdoc = new MutableDocument("livesindb")) {
                    mdoc.SetString("name", "db");
                    Db.Save(mdoc);
                }

                using (var mdoc = new MutableDocument("livesinotherdb")) {
                    mdoc.SetString("name", "otherdb");
                    _otherDB.Save(mdoc);
                }


                // PUSH
                var listener = new MessageEndpointListener(new MessageEndpointListenerConfiguration(_otherDB, protocolType));
                var server   = new MockServerConnection(listener, protocolType);
                var config   = new ReplicatorConfiguration(Db,
                                                           new MessageEndpoint($"p2ptest{testNo++}", server, protocolType,
                                                                               new MockConnectionFactory(null)))
                {
                    ReplicatorType = ReplicatorType.Push,
                    Continuous     = false
                };
                RunReplication(config, 0, 0);
                _otherDB.Count.Should().Be(2UL, "because it contains the original and new");
                Db.Count.Should().Be(1UL, "because there is no pull, so the first db should only have the original");

                // PULL
                server = new MockServerConnection(listener, protocolType);
                config = new ReplicatorConfiguration(Db,
                                                     new MessageEndpoint($"p2ptest{testNo++}", server, protocolType,
                                                                         new MockConnectionFactory(null)))
                {
                    ReplicatorType = ReplicatorType.Pull,
                    Continuous     = false
                };

                RunReplication(config, 0, 0);
                Db.Count.Should().Be(2UL, "because the pull should add the document from otherDB");

                using (var savedDoc = Db.GetDocument("livesinotherdb"))
                    using (var mdoc = savedDoc.ToMutable()) {
                        mdoc.SetBoolean("modified", true);
                        Db.Save(mdoc);
                    }

                using (var savedDoc = _otherDB.GetDocument("livesindb"))
                    using (var mdoc = savedDoc.ToMutable()) {
                        mdoc.SetBoolean("modified", true);
                        _otherDB.Save(mdoc);
                    }

                // PUSH & PULL
                server = new MockServerConnection(listener, protocolType);
                config = new ReplicatorConfiguration(Db,
                                                     new MessageEndpoint($"p2ptest{testNo++}", server, protocolType,
                                                                         new MockConnectionFactory(null)))
                {
                    Continuous = false
                };

                RunReplication(config, 0, 0);
                Db.Count.Should().Be(2UL, "because no new documents were added");

                using (var savedDoc = Db.GetDocument("livesindb")) {
                    savedDoc.GetBoolean("modified").Should()
                    .BeTrue("because the property change should have come from the other DB");
                }

                using (var savedDoc = _otherDB.GetDocument("livesinotherdb")) {
                    savedDoc.GetBoolean("modified").Should()
                    .BeTrue("because the proeprty change should come from the original DB");
                }

                Db.Delete();
                ReopenDB();
                _otherDB.Delete();
                _otherDB.Dispose();
                _otherDB = OpenDB(_otherDB.Name);
            }
        }
Example #16
0
//        Exception thrown at 0x00007FFE3090A799 in dotnet.exe: Microsoft C++ exception: EEFileLoadException at memory location 0x000000C288E79D88.
//Exception thrown at 0x00007FFE3090A799 in dotnet.exe: Microsoft C++ exception: [rethrow] at memory location 0x0000000000000000.
        //[Fact] uwp
        public void TestP2PPassiveCloseAll()
        {
            using (var doc = new MutableDocument("test")) {
                doc.SetString("name", "Smokey");
                Db.Save(doc);
            }

            var listener          = new MessageEndpointListener(new MessageEndpointListenerConfiguration(OtherDb, ProtocolType.MessageStream));
            var serverConnection1 = new MockServerConnection(listener, ProtocolType.MessageStream);
            var serverConnection2 = new MockServerConnection(listener, ProtocolType.MessageStream);
            var closeWait1        = new ManualResetEventSlim();
            var closeWait2        = new ManualResetEventSlim();
            var errorLogic        = new ReconnectErrorLogic();
            var config            = new ReplicatorConfiguration(Db,
                                                                new MessageEndpoint("p2ptest1", serverConnection1, ProtocolType.MessageStream,
                                                                                    new MockConnectionFactory(errorLogic)))
            {
                Continuous = true
            };

            var config2 = new ReplicatorConfiguration(Db,
                                                      new MessageEndpoint("p2ptest2", serverConnection2, ProtocolType.MessageStream,
                                                                          new MockConnectionFactory(errorLogic)))
            {
                Continuous = true
            };

            using (var replicator = new Replicator(config))
                using (var replicator2 = new Replicator(config2)) {
                    replicator.Start();
                    replicator2.Start();

                    var count = 0;
                    while (count++ < 15 && replicator.Status.Activity != ReplicatorActivityLevel.Idle &&
                           replicator2.Status.Activity != ReplicatorActivityLevel.Idle)
                    {
                        Thread.Sleep(500);
                        count.Should().BeLessThan(15, "because otherwise the replicator(s) never went idle");
                    }

                    errorLogic.ErrorActive = true;
                    listener.AddChangeListener((sender, args) => {
                        if (args.Status.Activity == ReplicatorActivityLevel.Stopped)
                        {
                            if (args.Connection == serverConnection1)
                            {
                                closeWait1.Set();
                            }
                            else
                            {
                                closeWait2.Set();
                            }
                        }
                    });
                    var connection = listener.Connections;
                    listener.CloseAll();
                    count = 0;
                    while (count++ < 10 && replicator.Status.Activity != ReplicatorActivityLevel.Stopped &&
                           replicator2.Status.Activity != ReplicatorActivityLevel.Stopped)
                    {
                        Thread.Sleep(500);
                        count.Should().BeLessThan(10, "because otherwise the replicator(s) never stopped");
                    }

                    closeWait1.Wait(TimeSpan.FromSeconds(5)).Should()
                    .BeTrue("because otherwise the first listener did not stop");
                    closeWait2.Wait(TimeSpan.FromSeconds(5)).Should()
                    .BeTrue("because otherwise the second listener did not stop");

                    replicator.Status.Error.Should()
                    .NotBeNull("because closing the passive side creates an error on the active one");
                    replicator2.Status.Error.Should()
                    .NotBeNull("because closing the passive side creates an error on the active one");
                }
        }
Example #17
0
        public void TestP2PPassiveCloseAll()
        {
            using (var doc = new MutableDocument("test"))
            {
                doc.SetString("name", "Smokey");
                Db.Save(doc);
            }

            var listener          = new MessageEndpointListener(new MessageEndpointListenerConfiguration(OtherDb, ProtocolType.MessageStream));
            var serverConnection1 = new MockServerConnection(listener, ProtocolType.MessageStream);
            var serverConnection2 = new MockServerConnection(listener, ProtocolType.MessageStream);
            var closeWait1        = new ManualResetEventSlim();
            var closeWait2        = new ManualResetEventSlim();
            var errorLogic        = new ReconnectErrorLogic();
            var config            = new ReplicatorConfiguration(Db,
                                                                new MessageEndpoint("p2ptest1", serverConnection1, ProtocolType.MessageStream,
                                                                                    new MockConnectionFactory(errorLogic)))
            {
                Continuous = true
            };

            var config2 = new ReplicatorConfiguration(Db,
                                                      new MessageEndpoint("p2ptest2", serverConnection2, ProtocolType.MessageStream,
                                                                          new MockConnectionFactory(errorLogic)))
            {
                Continuous = true
            };

            using (var replicator = new Replicator(config))
                using (var replicator2 = new Replicator(config2))
                {
                    EventHandler <ReplicatorStatusChangedEventArgs> changeListener = (sender, args) =>
                    {
                        if (args.Status.Activity == ReplicatorActivityLevel.Stopped)
                        {
                            if (sender == replicator)
                            {
                                closeWait1.Set();
                            }
                            else
                            {
                                closeWait2.Set();
                            }
                        }
                    };

                    replicator.AddChangeListener(changeListener);
                    replicator2.AddChangeListener(changeListener);
                    replicator.Start();
                    replicator2.Start();

                    errorLogic.ErrorActive = true;
                    listener.CloseAll();

                    WaitHandle.WaitAll(new[] { closeWait1.WaitHandle, closeWait2.WaitHandle }, TimeSpan.FromSeconds(20)).Should().BeTrue();

                    replicator.Status.Error.Should()
                    .NotBeNull("because closing the passive side creates an error on the active one");
                    replicator2.Status.Error.Should()
                    .NotBeNull("because closing the passive side creates an error on the active one");
                }

            closeWait1.Dispose();
            closeWait2.Dispose();
        }