public async Task TestMonitorCancelsAfterTargetChannelChanges() { var connectionFactory = new Mock <Connection.IConnectionFactory>(); var connection = new Mock <Connection.IConnection>(); var channel = new Mock <IChannelProxy>(); var rabbitChannel1 = new Mock <R.IModel>(); var rabbitChannel2 = new Mock <R.IModel>(); var target = new AtomicReference <R.IModel>(rabbitChannel1.Object); channel.Setup(c => c.TargetChannel).Returns(() => target.Value); connectionFactory.Setup((f) => f.CreateConnection()).Returns(connection.Object); connection.Setup((c) => c.CreateChannel(It.IsAny <bool>())).Returns(channel.Object); connection.Setup((c) => c.IsOpen).Returns(true); channel.Setup(c => c.IsOpen).Returns(true); rabbitChannel1.Setup(c => c.CreateBasicProperties()).Returns(new MockRabbitBasicProperties()); rabbitChannel2.Setup(c => c.CreateBasicProperties()).Returns(new MockRabbitBasicProperties()); channel.Setup(c => c.QueueDeclarePassive(It.IsAny <string>())).Returns(new R.QueueDeclareOk("test", 0, 0)); var consumer = new AtomicReference <R.IBasicConsumer>(); var latch1 = new CountdownEvent(1); var latch2 = new CountdownEvent(1); channel.Setup(c => c.BasicConsume(It.IsAny <string>(), It.IsAny <bool>(), It.IsAny <string>(), It.IsAny <bool>(), It.IsAny <bool>(), It.IsAny <IDictionary <string, object> >(), It.IsAny <R.IBasicConsumer>())) .Callback <string, bool, string, bool, bool, IDictionary <string, object>, R.IBasicConsumer>( (queue, autoAck, consumerTag, noLocal, exclusive, args, cons) => { consumer.Value = cons; latch1.Signal(); }) .Returns("consumerTag"); channel.Setup(c => c.BasicCancel("consumerTag")) .Callback(() => { consumer.Value.HandleBasicCancelOk("consumerTag"); latch2.Signal(); }); var container = new DirectMessageListenerContainer(null, connectionFactory.Object); container.SetQueueNames("test"); container.PrefetchCount = 2; container.MonitorInterval = 100; container.MessageListener = new TestListener2(target, rabbitChannel2.Object); container.AcknowledgeMode = AcknowledgeMode.MANUAL; container.Initialize(); await container.Start(); Assert.True(container._startedLatch.Wait(TimeSpan.FromSeconds(10))); Assert.True(latch1.Wait(TimeSpan.FromSeconds(10))); var props = new MockRabbitBasicProperties(); consumer.Value.HandleBasicDeliver("consumerTag", 1ul, false, string.Empty, string.Empty, props, new byte[1]); Assert.True(latch2.Wait(TimeSpan.FromSeconds(10))); await container.Stop(); }
public void TestBatch() { var bs = new SimpleBatchingStrategy(2, 10_000, 10_000L); var headers = new RabbitHeaderAccessor(); headers.ContentType = "test/plain"; var message = Message.Create(Encoding.UTF8.GetBytes("test1"), headers.MessageHeaders); bs.AddToBatch("foo", "bar", message); message = Message.Create(Encoding.UTF8.GetBytes("test2"), headers.MessageHeaders); var batched = bs.AddToBatch("foo", "bar", message); Assert.True(batched.HasValue); var batchMessage = batched.Value.Message; var batchHeaders = batchMessage.Headers; var headerConverter = new DefaultMessageHeadersConverter(); var props = new MockRabbitBasicProperties(); headerConverter.FromMessageHeaders(batchHeaders, props, Encoding.UTF8); props.ContentType = "text/plain"; var config = new ConfigurationBuilder().Build(); var services = new ServiceCollection().BuildServiceProvider(); var context = new GenericApplicationContext(services, config); var channel = new Mock <R.IModel>(); channel.Setup(c => c.IsOpen).Returns(true); var getResponse = new R.BasicGetResult(123Ul, false, "ex", "rk", 0, props, (byte[])batchMessage.Payload); channel.Setup(c => c.BasicGet("foo", false)).Returns(getResponse); var connection = new Mock <R.IConnection>(); connection.Setup(c => c.IsOpen).Returns(true); connection.Setup(c => c.CreateModel()).Returns(channel.Object); var connectionFactory = new Mock <R.IConnectionFactory>(); connectionFactory.Setup(f => f.CreateConnection(It.IsAny <string>())).Returns(connection.Object); var ccf = new CachingConnectionFactory(connectionFactory.Object); var source = new RabbitMessageSource(context, ccf, "foo"); var received = source.Receive(); Assert.NotNull(received); var asList = received.Payload as List <object>; Assert.NotNull(asList); Assert.Contains("test1", asList); Assert.Contains("test2", asList); }
public void TestAck() { var config = new ConfigurationBuilder().Build(); var services = new ServiceCollection().BuildServiceProvider(); var context = new GenericApplicationContext(services, config); var channel = new Mock <R.IModel>(); channel.Setup(c => c.IsOpen).Returns(true); var props = new MockRabbitBasicProperties(); var getResponse = new R.BasicGetResult(123Ul, false, "ex", "rk", 0, props, Encoding.UTF8.GetBytes("foo")); channel.Setup(c => c.BasicGet("foo", false)).Returns(getResponse); var connection = new Mock <R.IConnection>(); connection.Setup(c => c.IsOpen).Returns(true); connection.Setup(c => c.CreateModel()).Returns(channel.Object); var connectionFactory = new Mock <R.IConnectionFactory>(); connectionFactory.Setup(f => f.CreateConnection(It.IsAny <string>())).Returns(connection.Object); var ccf = new CachingConnectionFactory(connectionFactory.Object); var source = new RabbitMessageSource(context, ccf, "foo"); source.RawMessageHeader = true; var received = source.Receive(); var rawMessage = received.Headers.Get <IMessage>(RabbitMessageHeaderErrorMessageStrategy.AMQP_RAW_MESSAGE); var sourceData = received.Headers.Get <IMessage>(IntegrationMessageHeaderAccessor.SOURCE_DATA); Assert.NotNull(rawMessage); Assert.Same(rawMessage, sourceData); Assert.Equal("foo", received.Headers.Get <string>(RabbitMessageHeaders.CONSUMER_QUEUE)); // make sure channel is not cached var conn = ccf.CreateConnection(); var notCached = conn.CreateChannel(false); connection.Verify(c => c.CreateModel(), Times.Exactly(2)); var callback = received.Headers.Get <IAcknowledgmentCallback>(IntegrationMessageHeaderAccessor.ACKNOWLEDGMENT_CALLBACK); callback.Acknowledge(Status.ACCEPT); channel.Verify(c => c.BasicAck(123ul, false)); var cached = conn.CreateChannel(false); // should have been "closed" connection.Verify(c => c.CreateModel(), Times.Exactly(2)); notCached.Close(); cached.Close(); ccf.Destroy(); channel.Verify(c => c.Close(), Times.Exactly(2)); connection.Verify(c => c.Close(30000)); }
private void TestNackOrRequeue(bool requeue) { var config = new ConfigurationBuilder().Build(); var services = new ServiceCollection().BuildServiceProvider(); var context = new GenericApplicationContext(services, config); var channel = new Mock <R.IModel>(); channel.Setup(c => c.IsOpen).Returns(true); var props = new MockRabbitBasicProperties(); var getResponse = new R.BasicGetResult(123Ul, false, "ex", "rk", 0, props, Encoding.UTF8.GetBytes("bar")); channel.Setup(c => c.BasicGet("foo", false)).Returns(getResponse); var connection = new Mock <R.IConnection>(); connection.Setup(c => c.IsOpen).Returns(true); connection.Setup(c => c.CreateModel()).Returns(channel.Object); var connectionFactory = new Mock <R.IConnectionFactory>(); connectionFactory.Setup(f => f.CreateConnection(It.IsAny <string>())).Returns(connection.Object); var ccf = new CachingConnectionFactory(connectionFactory.Object); var source = new RabbitMessageSource(context, ccf, "foo"); var received = source.Receive(); connection.Verify(c => c.CreateModel()); var callback = received.Headers.Get <IAcknowledgmentCallback>(IntegrationMessageHeaderAccessor.ACKNOWLEDGMENT_CALLBACK); if (requeue) { callback.Acknowledge(Status.REQUEUE); } else { callback.Acknowledge(Status.REJECT); } channel.Verify(c => c.BasicReject(123ul, requeue)); connection.Verify(c => c.CreateModel()); ccf.Destroy(); channel.Verify(c => c.Close()); connection.Verify(c => c.Close(30000)); }
public async Task TestDeferredAcks() { var connectionFactory = new Mock <Connection.IConnectionFactory>(); var connection = new Mock <Connection.IConnection>(); var channel = new Mock <IChannelProxy>(); var rabbitChannel = new Mock <R.IModel>(); channel.Setup(c => c.TargetChannel).Returns(rabbitChannel.Object); connectionFactory.Setup((f) => f.CreateConnection()).Returns(connection.Object); connection.Setup((c) => c.CreateChannel(It.IsAny <bool>())).Returns(channel.Object); connection.Setup((c) => c.IsOpen).Returns(true); channel.Setup((c) => c.IsOpen).Returns(true); rabbitChannel.Setup(c => c.CreateBasicProperties()).Returns(new MockRabbitBasicProperties()); channel.Setup(c => c.QueueDeclarePassive(It.IsAny <string>())).Returns(new R.QueueDeclareOk("test", 0, 0)); var consumer = new AtomicReference <R.IBasicConsumer>(); var latch1 = new CountdownEvent(1); channel.Setup(c => c.BasicConsume(It.IsAny <string>(), It.IsAny <bool>(), It.IsAny <string>(), It.IsAny <bool>(), It.IsAny <bool>(), It.IsAny <IDictionary <string, object> >(), It.IsAny <R.IBasicConsumer>())) .Callback <string, bool, string, bool, bool, IDictionary <string, object>, R.IBasicConsumer>( (queue, autoAck, consumerTag, noLocal, exclusive, args, cons) => { consumer.Value = cons; cons.HandleBasicConsumeOk("consumerTag"); latch1.Signal(); }) .Returns("consumerTag"); var qos = new AtomicInteger(); channel.Setup(c => c.BasicQos(It.IsAny <uint>(), It.IsAny <ushort>(), It.IsAny <bool>())) .Callback <uint, ushort, bool>((size, count, global) => { qos.Value = count; }); var latch2 = new CountdownEvent(1); var latch3 = new CountdownEvent(1); channel.Setup(c => c.BasicAck(It.IsAny <ulong>(), It.IsAny <bool>())) .Callback <ulong, bool>((tag, multi) => { if (tag == 10ul || tag == 16ul) { latch2.Signal(); } else if (tag == 17ul) { latch3.Signal(); } }); var latch4 = new CountdownEvent(1); channel.Setup(c => c.BasicNack(It.IsAny <ulong>(), It.IsAny <bool>(), It.IsAny <bool>())) .Callback <ulong, bool, bool>((tag, multi, re) => { latch4.Signal(); }); var container = new DirectMessageListenerContainer(null, connectionFactory.Object); container.SetQueueNames("test"); container.PrefetchCount = 2; container.MonitorInterval = 100; container.MessagesPerAck = 10; container.AckTimeout = 100; container.MessageListener = new TestListener(); container.Initialize(); await container.Start(); Assert.True(container._startedLatch.Wait(TimeSpan.FromSeconds(10))); Assert.True(latch1.Wait(TimeSpan.FromSeconds(10))); Assert.Equal(10, qos.Value); var props = new MockRabbitBasicProperties(); var body = new byte[1]; for (long i = 1; i < 16; i++) { consumer.Value.HandleBasicDeliver("consumerTag", (ulong)i, false, string.Empty, string.Empty, props, body); } Thread.Sleep(200); consumer.Value.HandleBasicDeliver("consumerTag", 16ul, false, string.Empty, string.Empty, props, body); // should get 2 acks #10 and #16 (timeout) Assert.True(latch2.Wait(TimeSpan.FromSeconds(10))); consumer.Value.HandleBasicDeliver("consumerTag", 17ul, false, string.Empty, string.Empty, props, body); channel.Verify(c => c.BasicAck(10ul, true)); channel.Verify(c => c.BasicAck(15ul, true)); Assert.True(latch3.Wait(TimeSpan.FromSeconds(10))); // monitor task timeout channel.Verify(c => c.BasicAck(17ul, true)); consumer.Value.HandleBasicDeliver("consumerTag", 18ul, false, string.Empty, string.Empty, props, body); consumer.Value.HandleBasicDeliver("consumerTag", 19ul, false, string.Empty, string.Empty, props, body); Assert.True(latch4.Wait(TimeSpan.FromSeconds(10))); // pending acks before nack channel.Verify(c => c.BasicAck(18ul, true)); channel.Verify(c => c.BasicNack(19ul, true, true)); consumer.Value.HandleBasicDeliver("consumerTag", 20ul, false, string.Empty, string.Empty, props, body); var latch5 = new CountdownEvent(1); channel.Setup(c => c.BasicCancel("consumerTag")) .Callback(() => { consumer.Value.HandleBasicCancelOk("consumerTag"); latch5.Signal(); }); await container.Stop(); Assert.True(latch5.Wait(TimeSpan.FromSeconds(10))); channel.Verify((c) => c.BasicAck(20ul, true)); }