public async Task TestRemotelyCloseConsumer() { Mock <INmsConnectionListener> mockConnectionListener = new Mock <INmsConnectionListener>(); string errorMessage = "buba"; using (TestAmqpPeer testPeer = new TestAmqpPeer()) { ManualResetEvent consumerClosed = new ManualResetEvent(false); ManualResetEvent exceptionFired = new ManualResetEvent(false); mockConnectionListener .Setup(listener => listener.OnConsumerClosed(It.IsAny <IMessageConsumer>(), It.IsAny <Exception>())) .Callback(() => consumerClosed.Set()); NmsConnection connection = (NmsConnection) await EstablishConnectionAsync(testPeer); connection.AddConnectionListener(mockConnectionListener.Object); connection.ExceptionListener += exception => { exceptionFired.Set(); }; testPeer.ExpectBegin(); ISession session = await connection.CreateSessionAsync(AcknowledgementMode.AutoAcknowledge); // Create a consumer, then remotely end it afterwards. testPeer.ExpectReceiverAttach(); testPeer.ExpectLinkFlow(); testPeer.RemotelyDetachLastOpenedLinkOnLastOpenedSession(expectDetachResponse: true, closed: true, errorType: AmqpError.RESOURCE_DELETED, errorMessage: errorMessage, delayBeforeSend: 400); IQueue queue = await session.GetQueueAsync("myQueue"); IMessageConsumer consumer = await session.CreateConsumerAsync(queue); // Verify the consumer gets marked closed testPeer.WaitForAllMatchersToComplete(1000); Assert.True(consumerClosed.WaitOne(2000), "Consumer closed callback didn't trigger"); Assert.False(exceptionFired.WaitOne(20), "Exception listener shouldn't fire with no MessageListener"); // Try closing it explicitly, should effectively no-op in client. // The test peer will throw during close if it sends anything. await consumer.CloseAsync(); } }
public async Task TestRemotelyEndConnectionWithSessionWithConsumer() { string errorMessage = "buba"; using (TestAmqpPeer testPeer = new TestAmqpPeer()) { IConnection connection = await EstablishConnectionAsync(testPeer); testPeer.ExpectBegin(); ISession session = await connection.CreateSessionAsync(AcknowledgementMode.AutoAcknowledge); // Create a consumer, then remotely end the connection afterwards. testPeer.ExpectReceiverAttach(); testPeer.ExpectLinkFlow(); testPeer.RemotelyCloseConnection(expectCloseResponse: true, errorCondition: AmqpError.RESOURCE_LIMIT_EXCEEDED, errorMessage: errorMessage); IQueue queue = await session.GetQueueAsync("myQueue"); IMessageConsumer consumer = await session.CreateConsumerAsync(queue); Assert.That(() => ((NmsConnection)connection).IsConnected, Is.False.After(10_000, 100), "Connection never closes."); try { await connection.CreateSessionAsync(AcknowledgementMode.AutoAcknowledge); Assert.Fail("Expected ISE to be thrown due to being closed"); } catch (NMSConnectionException e) { Assert.True(e.ToString().Contains(AmqpError.RESOURCE_LIMIT_EXCEEDED)); Assert.True(e.ToString().Contains(errorMessage)); } // Verify the session is now marked closed try { var _ = session.AcknowledgementMode; Assert.Fail("Expected ISE to be thrown due to being closed"); } catch (IllegalStateException e) { Assert.True(e.ToString().Contains(AmqpError.RESOURCE_LIMIT_EXCEEDED)); Assert.True(e.ToString().Contains(errorMessage)); } // Verify the consumer is now marked closed try { consumer.Listener += message => { }; } catch (IllegalStateException e) { Assert.True(e.ToString().Contains(AmqpError.RESOURCE_LIMIT_EXCEEDED)); Assert.True(e.ToString().Contains(errorMessage)); } // Try closing them explicitly, should effectively no-op in client. // The test peer will throw during close if it sends anything. await consumer.CloseAsync(); await session.CloseAsync(); await connection.CloseAsync(); } }
public async Task TestReceiveIgnoreExpirationMessage( [Values(AcknowledgementMode.AutoAcknowledge, AcknowledgementMode.ClientAcknowledge, AcknowledgementMode.DupsOkAcknowledge, AcknowledgementMode.Transactional)] AcknowledgementMode ackMode, [Values(MsgDeliveryMode.NonPersistent, MsgDeliveryMode.Persistent)] MsgDeliveryMode deliveryMode, [Values(ExpirationOptions.DEFAULT, ExpirationOptions.IGNORE, ExpirationOptions.DO_NOT_IGNORE)] ExpirationOptions expirationOption) { using (IConnection connection = CreateConnection(TEST_CLIENT_ID)) { await connection.StartAsync(); using (Session session = await connection.CreateSessionAsync(ackMode) as Session) { string destinationName = DESTINATION_NAME; if (ExpirationOptions.IGNORE == expirationOption) { destinationName += "?consumer.nms.ignoreExpiration=true"; } else if (ExpirationOptions.DO_NOT_IGNORE == expirationOption) { destinationName += "?consumer.nms.ignoreExpiration=false"; } try { IDestination destination = SessionUtil.GetDestination(session, destinationName); using (IMessageConsumer consumer = await session.CreateConsumerAsync(destination)) using (IMessageProducer producer = await session.CreateProducerAsync(destination)) { producer.DeliveryMode = deliveryMode; string msgText = string.Format("ExpiredMessage: {0}", Guid.NewGuid().ToString()); ActiveMQTextMessage msg = await session.CreateTextMessageAsync(msgText) as ActiveMQTextMessage; // Give it two seconds to live. msg.NMSTimeToLive = TimeSpan.FromMilliseconds(2000); await producer.SendAsync(msg); if (AcknowledgementMode.Transactional == ackMode) { await session.CommitAsync(); } // Wait for four seconds before processing it. The broker will have sent it to our local // client dispatch queue, but we won't attempt to process the message until it has had // a chance to expire within our internal queue system. Thread.Sleep(4000); ActiveMQTextMessage rcvMsg = consumer.ReceiveNoWait() as ActiveMQTextMessage; if (ExpirationOptions.IGNORE == expirationOption) { Assert.IsNotNull(rcvMsg, "Did not receive expired message."); await rcvMsg.AcknowledgeAsync(); Assert.AreEqual(msgText, rcvMsg.Text, "Message text does not match."); Assert.IsTrue(rcvMsg.IsExpired()); if (AcknowledgementMode.Transactional == ackMode) { await session.CommitAsync(); } } else { // Should not receive a message. Assert.IsNull(rcvMsg, "Received an expired message!"); } await consumer.CloseAsync(); await producer.CloseAsync(); } } finally { try { // Ensure that Session resources on the Broker release transacted Consumers. await session.CloseAsync(); // Give the Broker some time to remove the subscriptions. Thread.Sleep(2000); SessionUtil.DeleteDestination(session, destinationName); } catch { } } } } }