public void BlockOnSendBlockedIfReachedBoundedCapacity()
            {
                var send1     = new ManualResetEvent(false);
                var send2     = new ManualResetEvent(false);
                var processor = new FakeMessageProcessor <Object>();
                var bus       = new OptimisticMessageSender <Object>(processor, 1);

                Assert.Equal(1, bus.BoundedCapacity);

                Task.Run(() =>
                {
                    //NOTE: Once message is received for processing, the message is dequeued and thus we actually need
                    //      one more message to confirm blocking behavior (i.e., one in queue and one being processed).
                    bus.Send(new Message <Object>(Guid.NewGuid(), HeaderCollection.Empty, new Object()));
                    bus.Send(new Message <Object>(Guid.NewGuid(), HeaderCollection.Empty, new Object()));
                    send1.Set();
                });

                Task.Run(() =>
                {
                    send1.WaitOne();
                    bus.Send(new Message <Object>(Guid.NewGuid(), HeaderCollection.Empty, new Object()));
                    send2.Set();
                });

                processor.WaitForMessage();

                Assert.True(send1.WaitOne(TimeSpan.FromMilliseconds(100)));
                Assert.False(send2.WaitOne(TimeSpan.FromMilliseconds(100)));

                processor.ProcessNextMessage();
                processor.WaitForMessage();

                Assert.True(send2.WaitOne(TimeSpan.FromMilliseconds(100)));
            }
            public void BlockOnSendBlockedIfReachedBoundedCapacity()
            {
                var send1 = new ManualResetEvent(false);
                var send2 = new ManualResetEvent(false);
                var processor = new FakeMessageProcessor<Object>();
                var bus = new OptimisticMessageSender<Object>(processor, 1);

                Assert.Equal(1, bus.BoundedCapacity);

                Task.Run(() =>
                {
                    //NOTE: Once message is received for processing, the message is dequeued and thus we actually need
                    //      one more message to confirm blocking behavior (i.e., one in queue and one being processed).
                    bus.Send(new Message<Object>(Guid.NewGuid(), HeaderCollection.Empty, new Object()));
                    bus.Send(new Message<Object>(Guid.NewGuid(), HeaderCollection.Empty, new Object()));
                    send1.Set();
                });

                Task.Run(() =>
                {
                    send1.WaitOne();
                    bus.Send(new Message<Object>(Guid.NewGuid(), HeaderCollection.Empty, new Object()));
                    send2.Set();
                });

                processor.WaitForMessage();

                Assert.True(send1.WaitOne(TimeSpan.FromMilliseconds(100)));
                Assert.False(send2.WaitOne(TimeSpan.FromMilliseconds(100)));

                processor.ProcessNextMessage();
                processor.WaitForMessage();

                Assert.True(send2.WaitOne(TimeSpan.FromMilliseconds(100)));
            }
            public void MessageCannotBeNull()
            {
                var bus = new OptimisticMessageSender<Object>(messageProcessor.Object);
                var ex = Assert.Throws<ArgumentNullException>(() => bus.Send(null));

                Assert.Equal("message", ex.ParamName);
            }
            public void MessageCannotBeNull()
            {
                var bus = new OptimisticMessageSender <Object>(messageProcessor.Object);
                var ex  = Assert.Throws <ArgumentNullException>(() => bus.Send(null));

                Assert.Equal("message", ex.ParamName);
            }
            public void WillWaitForMessageDrain()
            {
                var processor = new FakeMessageProcessor <Object>();
                var bus       = new OptimisticMessageSender <Object>(processor);
                var messages  = new[]
                {
                    new Message <Object>(Guid.NewGuid(), HeaderCollection.Empty, new Object()),
                    new Message <Object>(Guid.NewGuid(), HeaderCollection.Empty, new Object()),
                    new Message <Object>(Guid.NewGuid(), HeaderCollection.Empty, new Object())
                };

                foreach (var message in messages)
                {
                    bus.Send(message);
                }

                Task.Run(() =>
                {
                    foreach (var message in messages)
                    {
                        processor.WaitForMessage();
                        processor.ProcessNextMessage();
                    }
                });

                bus.Dispose();

                Assert.Equal(0, bus.Count);
            }
            public void CannotSendIfDisposed()
            {
                var bus = new OptimisticMessageSender<Object>(messageProcessor.Object);

                bus.Dispose();

                Assert.Throws<ObjectDisposedException>(() => bus.Send(new Message<Object>(Guid.NewGuid(), HeaderCollection.Empty, new Object())));
            }
            public void CannotSendIfDisposed()
            {
                var bus = new OptimisticMessageSender <Object>(messageProcessor.Object);

                bus.Dispose();

                Assert.Throws <ObjectDisposedException>(() => bus.Send(new Message <Object>(Guid.NewGuid(), HeaderCollection.Empty, new Object())));
            }
            public void CanCallDisposeMultipleTimes()
            {
                var processor = new FakeMessageProcessor <Object>();

                using (var bus = new OptimisticMessageSender <Object>(processor))
                {
                    bus.Dispose();
                    bus.Dispose();
                }
            }
            public void WillIgnorePosionMessageExceptions()
            {
                var processor = new FakeMessageProcessor <Object>();
                var bus       = new OptimisticMessageSender <Object>(processor);
                var ex        = new InvalidOperationException();

                bus.Send(new Message <Object>(Guid.NewGuid(), HeaderCollection.Empty, new Object()));
                processor.WaitForMessage();
                processor.ThrowException(ex);
                processor.ProcessNextMessage();
                bus.Dispose();
            }
            public void WillRemoveFromQueueOnceMessageProcessed()
            {
                var processor = new FakeMessageProcessor <Object>();
                var bus       = new OptimisticMessageSender <Object>(processor, 1);
                var attempt   = 0;

                bus.Send(new Message <Object>(Guid.NewGuid(), HeaderCollection.Empty, new Object()));
                processor.WaitForMessage();
                processor.ProcessNextMessage();

                while (bus.Count > 0 && attempt < 10)
                {
                    Thread.Sleep(100);
                }

                Assert.Equal(0, bus.Count);
            }
            public void WillRemoveFromQueueOnceMessageProcessed()
            {
                var processor = new FakeMessageProcessor<Object>();
                var bus = new OptimisticMessageSender<Object>(processor, 1);
                var attempt = 0;

                bus.Send(new Message<Object>(Guid.NewGuid(), HeaderCollection.Empty, new Object()));
                processor.WaitForMessage();
                processor.ProcessNextMessage();

                while (bus.Count > 0 && attempt < 10) Thread.Sleep(100);

                Assert.Equal(0, bus.Count);
            }
            public void WillIgnorePosionMessageExceptions()
            {
                var processor = new FakeMessageProcessor<Object>();
                var bus = new OptimisticMessageSender<Object>(processor);
                var ex = new InvalidOperationException();

                bus.Send(new Message<Object>(Guid.NewGuid(), HeaderCollection.Empty, new Object()));
                processor.WaitForMessage();
                processor.ThrowException(ex);
                processor.ProcessNextMessage();
                bus.Dispose();
            }
            public void WillWaitForMessageDrain()
            {
                var processor = new FakeMessageProcessor<Object>();
                var bus = new OptimisticMessageSender<Object>(processor);
                var messages = new[]
                {
                    new Message<Object>(Guid.NewGuid(), HeaderCollection.Empty, new Object()),
                    new Message<Object>(Guid.NewGuid(), HeaderCollection.Empty, new Object()),
                    new Message<Object>(Guid.NewGuid(), HeaderCollection.Empty, new Object())
                };

                foreach (var message in messages)
                    bus.Send(message);

                Task.Run(() =>
                {
                    foreach (var message in messages)
                    {
                        processor.WaitForMessage();
                        processor.ProcessNextMessage();
                    }
                });

                bus.Dispose();

                Assert.Equal(0, bus.Count);
            }
 public void CanCallDisposeMultipleTimes()
 {
     var processor = new FakeMessageProcessor<Object>();
     using (var bus = new OptimisticMessageSender<Object>(processor))
     {
         bus.Dispose();
         bus.Dispose();
     }
 }