예제 #1
0
		public void Publish_Where_Channel_Publication_Fails_Results_In_A_Non_Completed_Publication_Task_Which_Is_Placed_Back_On_The_Publication_Queue()
		{
			var _connection = Substitute.For<IConnection>();
			var _channel = Substitute.For<IModel>();
			var _publicationQueue = new BlockingCollection<Publication>();

			_connection.CreateModel().Returns(_channel);
			_channel
				.When(channel => channel.BasicPublish(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<IBasicProperties>(), Arg.Any<byte[]>()))
				.Do(callInfo => { throw new ApplicationException("Bang !"); });

			var _messageDelivery = new MessageDelivery("EXCHANGE", typeof(MyEvent).Name, MessageDeliveryMode.Persistent, message => "ARoutingKey");
			var _myEvent = new MyEvent(Guid.NewGuid(), "CorrlationId_1", "Detail", 1);
			var _taskCompletionSource = new TaskCompletionSource<PublicationResult>();
			var _publication = new Publication(_messageDelivery, _myEvent, _taskCompletionSource);

			var _SUT = new Publisher(_connection, _publicationQueue, CancellationToken.None);
			var _publisherTask = _SUT.Start();

			_publicationQueue.Add(_publication);
			try { _publisherTask.Wait(); } catch { }

			Assert.IsFalse(_publication.ResultTask.IsCompleted);
			Assert.AreSame(_publication, _publicationQueue.First());
		}
예제 #2
0
		public void TestMockingingABus()
		{
			var _bus = Substitute.For<IBus>();

			var _event = new MyEvent(Guid.NewGuid(), "", "", 1);
			var _result = new TaskCompletionSource<PMCG.Messaging.PublicationResult>();
			_result.SetResult(new PMCG.Messaging.PublicationResult(PMCG.Messaging.PublicationResultStatus.Published, _event));
			
			_bus.PublishAsync(_event).Returns(_result.Task);
			_bus.PublishAsync(Arg.Any<MyEvent>()).Returns(_result.Task);
		}
예제 #3
0
		public void Publish_Where_Channel_Is_Closed_Results_In_Faulted_Publisher_Task()
		{
			var _connection = Substitute.For<IConnection>();
			var _channel = Substitute.For<IModel>();
			var _publicationQueue = new BlockingCollection<Publication>();

			_connection.CreateModel().Returns(_channel);
			_channel.CreateBasicProperties().Returns(callInfo => { throw new Exception("Channel not open !"); });

			var _messageDelivery = new MessageDelivery("test_publisher_confirms", typeof(MyEvent).Name, MessageDeliveryMode.Persistent, message => "ARoutingKey");
			var _myEvent = new MyEvent(Guid.NewGuid(), "CorrlationId_1", "Detail", 1);
			var _taskCompletionSource = new TaskCompletionSource<PublicationResult>();
			var _publication = new Publication(_messageDelivery, _myEvent, _taskCompletionSource);

			var _SUT = new Publisher(_connection, _publicationQueue, CancellationToken.None);
			var _publisherTask = _SUT.Start();

			_publicationQueue.Add(_publication);

			bool _isFaultedPublisherTask = false;
			try { _publisherTask.Wait(); } catch { _isFaultedPublisherTask = true; }

			Assert.IsTrue(_isFaultedPublisherTask);
		}
예제 #4
0
        public void Consume_Where_We_Mock_All_Without_A_Real_Connection_Knows_Too_Much_About_RabbitMQ_Internals()
        {
            var _waitHandle        = new AutoResetEvent(false);
            var _capturedMessageId = Guid.Empty;

            var _configurationBuilder = new BusConfigurationBuilder();

            _configurationBuilder.ConnectionUris.Add(TestingConfiguration.LocalConnectionUri);
            _configurationBuilder.RegisterConsumer <MyEvent>(
                TestingConfiguration.QueueName,
                typeof(MyEvent).Name,
                message =>
            {
                _capturedMessageId = message.Id;
                _waitHandle.Set();
                return(ConsumerHandlerResult.Completed);
            });
            var _configuration = _configurationBuilder.Build();

            var _connection = Substitute.For <IConnection>();
            var _channel    = Substitute.For <IModel>();

            _connection.CreateModel().Returns(_channel);

            var _myEvent           = new MyEvent(Guid.NewGuid(), "CorrlationId_1", "Detail", 1);
            var _messageProperties = Substitute.For <IBasicProperties>();

            _messageProperties.ContentType   = "application/json";
            _messageProperties.DeliveryMode  = (byte)MessageDeliveryMode.Persistent;
            _messageProperties.Type          = typeof(MyEvent).Name;
            _messageProperties.MessageId     = _myEvent.Id.ToString();
            _messageProperties.CorrelationId = _myEvent.CorrelationId;
            _channel.CreateBasicProperties().Returns(_messageProperties);

            QueueingBasicConsumer _capturedConsumer = null;

            _channel
            .When(channel => channel.BasicConsume(TestingConfiguration.QueueName, false, Arg.Any <IBasicConsumer>()))
            .Do(callInfo => { _capturedConsumer = callInfo[2] as QueueingBasicConsumer; _waitHandle.Set(); });

            var _SUT = new Consumer(_connection, _configuration, CancellationToken.None);

            _SUT.Start();                                       // Can't capture result due to compiler treating warnings as errors
            _waitHandle.WaitOne();                              // Wait till consumer task has called the BasicConsume method which captures the consumer
            _waitHandle.Reset();                                // Reset so we can block on the consumer message func

            var _messageJson = JsonConvert.SerializeObject(_myEvent);
            var _messageBody = Encoding.UTF8.GetBytes(_messageJson);

            _capturedConsumer.Queue.Enqueue(
                new BasicDeliverEventArgs
            {
                ConsumerTag     = "consumerTag",
                DeliveryTag     = 1UL,
                Redelivered     = false,
                Exchange        = "TheExchange",
                RoutingKey      = "ARoutingKey",
                BasicProperties = _messageProperties,
                Body            = _messageBody
            });
            _waitHandle.WaitOne();                      // Wait for message to be consumed

            Assert.AreEqual(_myEvent.Id, _capturedMessageId);
        }
예제 #5
0
		public void Publish_Where_Single_Publication_Published_And_Acked_Results_In_Task_Completion()
		{
			var _connection = Substitute.For<IConnection>();
			var _channel = Substitute.For<IModel>();
			var _publicationQueue = new BlockingCollection<Publication>();
			var _messageProperties = Substitute.For<IBasicProperties>();
			var _waitHandle = new AutoResetEvent(false);

			_connection.CreateModel().Returns(_channel);
			_channel.CreateBasicProperties().Returns(_messageProperties);
			_channel.NextPublishSeqNo.Returns(1UL);
			_channel
				.When(channel => channel.BasicPublish(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<IBasicProperties>(), Arg.Any<byte[]>()))
				.Do(callInfo => _waitHandle.Set());

			var _SUT = new Publisher(_connection, _publicationQueue, CancellationToken.None);
			_SUT.Start(); 	// Can't capture result due to compiler treating warnings as errors - var is not used

			var _messageDelivery = new MessageDelivery("test_publisher_confirms", typeof(MyEvent).Name, MessageDeliveryMode.Persistent, message => "ARoutingKey");
			var _myEvent = new MyEvent(Guid.NewGuid(), "CorrlationId_1", "Detail", 1);
			var _taskCompletionSource = new TaskCompletionSource<PublicationResult>();
			var _publication = new Publication(_messageDelivery, _myEvent, _taskCompletionSource);
			_publicationQueue.Add(_publication);

			_waitHandle.WaitOne();	// Allow publication to complete
			_channel.BasicAcks += Raise.Event<BasicAckEventHandler>(_channel, new BasicAckEventArgs { Multiple = false, DeliveryTag = 1 });
			
			Assert.IsTrue(_publication.ResultTask.IsCompleted);
			_messageProperties.Received().ContentType = "application/json";
			_messageProperties.Received().DeliveryMode = (byte)_messageDelivery.DeliveryMode;
			_messageProperties.Received().Type = _messageDelivery.TypeHeader;
			_messageProperties.Received().MessageId = _myEvent.Id.ToString();
			_messageProperties.Received().CorrelationId = _myEvent.CorrelationId;
			_channel.Received().BasicPublish(_messageDelivery.ExchangeName, _messageDelivery.RoutingKeyFunc(_myEvent), _messageProperties, Arg.Any<byte[]>());
		}
예제 #6
0
		public void Publish_Where_Exchange_Does_Not_Exist_Results_In_Channel_Shutdown_And_A_Channel_Shutdown_Task_Result()
		{
			var _connection = Substitute.For<IConnection>();
			var _channel = Substitute.For<IModel>();
			var _publicationQueue = new BlockingCollection<Publication>();
			var _waitHandle = new AutoResetEvent(false);

			_connection.CreateModel().Returns(_channel);
			_channel.NextPublishSeqNo.Returns(1Ul);
			_channel
				.When(channel => channel.BasicPublish(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<IBasicProperties>(), Arg.Any<byte[]>()))
				.Do(callInfo => _waitHandle.Set());

			var _SUT = new Publisher(_connection, _publicationQueue, CancellationToken.None);
			_SUT.Start();

			var _messageDelivery = new MessageDelivery("NON_EXISTENT_EXCHANGE", typeof(MyEvent).Name, MessageDeliveryMode.Persistent, message => "ARoutingKey");
			var _myEvent = new MyEvent(Guid.NewGuid(), "CorrlationId_1", "Detail", 100);
			var _taskCompletionSource = new TaskCompletionSource<PublicationResult>();
			var _publication = new Publication(_messageDelivery, _myEvent, _taskCompletionSource);
			_publicationQueue.Add(_publication);

			_waitHandle.WaitOne();		// Allow channel publication to complete
			_channel.ModelShutdown += Raise.Event<ModelShutdownEventHandler>(_channel, new ShutdownEventArgs(ShutdownInitiator.Peer, 1, "404 Exchange does not exist !"));

			// Since all running on the same thread we do not need to wait - this is also not relaistic as we know the channel shutdown event will happen on a different thread
			Assert.IsTrue(_publication.ResultTask.IsCompleted);
			Assert.AreEqual(PublicationResultStatus.ChannelShutdown, _publication.ResultTask.Result.Status);
			Assert.IsTrue(_publication.ResultTask.Result.StatusContext.Contains("404 Exchange does not exist !"));
		}
예제 #7
0
		public void Publish_Where_Two_Messages_Being_Published_But_Channel_Is_Closed_Before_Acks_Received_Results_In_Two_Channel_Shutdown_Tasks()
		{
			var _connection = Substitute.For<IConnection>();
			var _channel = Substitute.For<IModel>();
			var _publicationQueue = new BlockingCollection<Publication>();
			var _waitHandle = new CountdownEvent(2);

			_connection.CreateModel().Returns(_channel);
			_channel.NextPublishSeqNo.Returns(1Ul, 2UL);
			_channel
				.When(channel => channel.BasicPublish(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<IBasicProperties>(), Arg.Any<byte[]>()))
				.Do(callInfo => _waitHandle.Signal());

			var _SUT = new Publisher(_connection, _publicationQueue, CancellationToken.None);
			_SUT.Start();

			var _messageDelivery = new MessageDelivery("test_publisher_confirms", typeof(MyEvent).Name, MessageDeliveryMode.Persistent, message => "ARoutingKey");
			var _myEvent = new MyEvent(Guid.NewGuid(), "CorrlationId_1", "Detail", 100);

			var _taskCompletionSource1 = new TaskCompletionSource<PublicationResult>();
			var _publication1 = new Publication(_messageDelivery, _myEvent, _taskCompletionSource1);
			var _taskCompletionSource2 = new TaskCompletionSource<PublicationResult>();
			var _publication2 = new Publication(_messageDelivery, _myEvent, _taskCompletionSource2);
			_publicationQueue.Add(_publication1);
			_publicationQueue.Add(_publication2);
			
			_waitHandle.Wait();		// Allow channel publications to complete
			_channel.ModelShutdown += Raise.Event<ModelShutdownEventHandler>(_channel, new ShutdownEventArgs(ShutdownInitiator.Peer, 1, "Bang!"));

			// Since all running on the same thread we do not need to wait - this is also not relaistic as we know the channel shutdown event will happen on a different thread
			Assert.IsTrue(_publication1.ResultTask.IsCompleted);
			Assert.AreEqual(PublicationResultStatus.ChannelShutdown, _publication1.ResultTask.Result.Status);
			Assert.IsTrue(_publication1.ResultTask.Result.StatusContext.Contains("Bang!"));
			Assert.IsTrue(_publication2.ResultTask.IsCompleted);
			Assert.AreEqual(PublicationResultStatus.ChannelShutdown, _publication2.ResultTask.Result.Status);
			Assert.IsTrue(_publication2.ResultTask.Result.StatusContext.Contains("Bang!"));
		}
예제 #8
0
		public void Publish_Where_Single_Message_Published_And_Nacked_Results_In_Nacked_Task_Result()
		{
			var _connection = Substitute.For<IConnection>();
			var _channel = Substitute.For<IModel>();
			var _publicationQueue = new BlockingCollection<Publication>();
			var _waitHandle = new AutoResetEvent(false);

			_connection.CreateModel().Returns(_channel);
			_channel.NextPublishSeqNo.Returns(1Ul);
			_channel
				.When(channel => channel.BasicPublish(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<IBasicProperties>(), Arg.Any<byte[]>()))
				.Do(callInfo => _waitHandle.Set());

			var _SUT = new Publisher(_connection, _publicationQueue, CancellationToken.None);
			_SUT.Start();

			var _messageDelivery = new MessageDelivery("test_publisher_confirms", typeof(MyEvent).Name, MessageDeliveryMode.Persistent, message => "ARoutingKey");
			var _myEvent = new MyEvent(Guid.NewGuid(), "CorrlationId_1", "Detail", 100);
			var _taskCompletionSource = new TaskCompletionSource<PublicationResult>();
			var _publication = new Publication(_messageDelivery, _myEvent, _taskCompletionSource);
			_publicationQueue.Add(_publication);

			_waitHandle.WaitOne();		// Allow channel publication to complete
			_channel.BasicNacks += Raise.Event<BasicNackEventHandler>(_channel, new BasicNackEventArgs { Multiple = true, DeliveryTag = 1UL });

			Assert.IsTrue(_publication.ResultTask.IsCompleted);
			Assert.AreEqual(PublicationResultStatus.Nacked, _publication.ResultTask.Result.Status);
			Assert.IsNull(_publication.ResultTask.Result.StatusContext);
		}
예제 #9
0
		public void Publish_Where_100_Messages_Published_And_A_Single_Multi_Ack_For_Some_Messages_Results_In_Some_Completed_Tasks_And_Some_Still_Pending()
		{
			var _connection = Substitute.For<IConnection>();
			var _channel = Substitute.For<IModel>();
			var _publicationQueue = new BlockingCollection<Publication>();
			var _waitHandle = new CountdownEvent(100);

			_connection.CreateModel().Returns(_channel);
			var _nextPublishSeqNo = 1UL;
			_channel.NextPublishSeqNo.Returns(callInfo => _nextPublishSeqNo++);		// Would not work when I used .Returns(1Ul, 2UL, 3UL); Not sure why this works !
			_channel
				.When(channel => channel.BasicPublish(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<IBasicProperties>(), Arg.Any<byte[]>()))
				.Do(callInfo => _waitHandle.Signal());

			var _SUT = new Publisher(_connection, _publicationQueue, CancellationToken.None);
			_SUT.Start();

			var _publications = new List<Publication>();
			for (var _index = 1; _index <= 100; _index++)
			{
				var _messageDelivery = new MessageDelivery("test_publisher_confirms", typeof(MyEvent).Name, MessageDeliveryMode.Persistent, message => "ARoutingKey");
				var _myEvent = new MyEvent(Guid.NewGuid(), "CorrlationId_1", "Detail", _index);
				var _taskCompletionSource = new TaskCompletionSource<PublicationResult>();
				var _publication = new Publication(_messageDelivery, _myEvent, _taskCompletionSource);

				_publicationQueue.Add(_publication);
				_publications.Add(_publication);
			}

			_waitHandle.Wait();		// Allow channel publications to complete
			foreach(var _publication in _publications) { Assert.IsFalse(_publication.ResultTask.IsCompleted); }
			var _deliveryTagToAcknowledge = 73;
			_channel.BasicAcks += Raise.Event<BasicAckEventHandler>(_channel, new BasicAckEventArgs { Multiple = true, DeliveryTag = (ulong)_deliveryTagToAcknowledge });

			Assert.AreEqual(_deliveryTagToAcknowledge, _publications.Count(publication => publication.ResultTask.IsCompleted), "A1");
			Assert.AreEqual(_deliveryTagToAcknowledge, _publications.Count(publication => publication.ResultTask.IsCompleted && publication.ResultTask.Result.Status == PublicationResultStatus.Acked), "A2");
			Assert.AreEqual(100 - _deliveryTagToAcknowledge, _publications.Count(publication => !publication.ResultTask.IsCompleted), "A3");
		}
예제 #10
0
		public void Consume_Where_We_Mock_All_Without_A_Real_Connection_Knows_Too_Much_About_RabbitMQ_Internals()
		{
			var _waitHandle = new AutoResetEvent(false);
			var _capturedMessageId = Guid.Empty;

			var _configurationBuilder = new BusConfigurationBuilder();
			_configurationBuilder.ConnectionUris.Add(TestingConfiguration.LocalConnectionUri);
			_configurationBuilder.RegisterConsumer<MyEvent>(
				TestingConfiguration.QueueName,
				typeof(MyEvent).Name,
				message =>
					{
						_capturedMessageId = message.Id;
						_waitHandle.Set();
						return ConsumerHandlerResult.Completed;
					});
			var _configuration = _configurationBuilder.Build();

			var _connection = Substitute.For<IConnection>();
			var _channel = Substitute.For<IModel>();
			
			_connection.CreateModel().Returns(_channel);
	
			var _myEvent = new MyEvent(Guid.NewGuid(), "CorrlationId_1", "Detail", 1);
			var _messageProperties = Substitute.For<IBasicProperties>();
			_messageProperties.ContentType = "application/json";
			_messageProperties.DeliveryMode = (byte)MessageDeliveryMode.Persistent;
			_messageProperties.Type = typeof(MyEvent).Name;
			_messageProperties.MessageId = _myEvent.Id.ToString();
			_messageProperties.CorrelationId = _myEvent.CorrelationId;
			_channel.CreateBasicProperties().Returns(_messageProperties);

			QueueingBasicConsumer _capturedConsumer = null;
			_channel
				.When(channel => channel.BasicConsume(TestingConfiguration.QueueName, false, Arg.Any<IBasicConsumer>()))
				.Do(callInfo => { _capturedConsumer = callInfo[2] as QueueingBasicConsumer; _waitHandle.Set(); });

			var _SUT = new Consumer(_connection, _configuration, CancellationToken.None);
			_SUT.Start();				// Can't capture result due to compiler treating warnings as errors 
			_waitHandle.WaitOne();			// Wait till consumer task has called the BasicConsume method which captures the consumer
			_waitHandle.Reset();			// Reset so we can block on the consumer message func

			var _messageJson = JsonConvert.SerializeObject(_myEvent);
			var _messageBody = Encoding.UTF8.GetBytes(_messageJson);
			_capturedConsumer.Queue.Enqueue(
				new BasicDeliverEventArgs
					{
						ConsumerTag = "consumerTag",
						DeliveryTag = 1UL,
						Redelivered = false,
						Exchange = "TheExchange",
						RoutingKey = "ARoutingKey",
						BasicProperties = _messageProperties,
						Body = _messageBody
					});
			_waitHandle.WaitOne();		// Wait for message to be consumed

			Assert.AreEqual(_myEvent.Id, _capturedMessageId);
		}