public void TestWithConnectionFactoryDefaults()
        {
            var mockConnectionFactory = new Mock<ConnectionFactory>();
            var mockConnection = new Mock<IConnection>();
            var mockChannel = new Mock<IModel>();

            mockConnectionFactory.Setup(factory => factory.CreateConnection()).Returns(mockConnection.Object);
            mockConnection.Setup(connection => connection.CreateModel()).Returns(mockChannel.Object);
            mockChannel.Setup(chan => chan.IsOpen).Returns(true);
            mockConnection.Setup(conn => conn.IsOpen).Returns(true);

            var ccf = new CachingConnectionFactory(mockConnectionFactory.Object);
            var con = ccf.CreateConnection();

            var channel = con.CreateChannel(false);
            channel.Close(); // should be ignored, and placed into channel cache.
            con.Close(); // should be ignored

            var con2 = ccf.CreateConnection();

            /*
             * will retrieve same channel object that was just put into channel cache
             */
            var channel2 = con2.CreateChannel(false);
            channel2.Close(); // should be ignored
            con2.Close(); // should be ignored

            Assert.AreSame(con, con2);
            Assert.AreSame(channel, channel2);
            mockConnection.Verify(conn => conn.Close(), Times.Never());
            mockChannel.Verify(chan => chan.Close(), Times.Never());
        }
        public void CachedChannel()
        {
            TestConnectionFactory testConnectionFactory = new TestConnectionFactory();

            CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory(testConnectionFactory, "localhost:" + RabbitUtils.DEFAULT_PORT);

            IConnection con1 = cachingConnectionFactory.CreateConnection();
            Assert.AreEqual(1, testConnectionFactory.CreateConnectionCount);

            IModel model1 = con1.CreateModel();
            TestModel testModel = GetTestModel(model1);
            Assert.AreEqual(1, testModel.CreatedCount);
            Assert.AreEqual(0, testModel.CloseCount);
            Assert.AreEqual(1, testConnectionFactory.CreateConnectionCount);

            model1.Close();  // won't close, will put in channel cache.
            Assert.AreEqual(0, testModel.CloseCount);

            IModel model2 = con1.CreateModel();
            TestModel testModel2 = GetTestModel(model2);

            Assert.AreSame(testModel, testModel2);

            Assert.AreEqual(1, testModel.CreatedCount);
            Assert.AreEqual(0, testModel.CloseCount);
            Assert.AreEqual(1, testConnectionFactory.CreateConnectionCount);
        }
        public void TestCacheSizeExceeded()
        {
            var mocker = new AutoMoqer();

            var mockConnectionFactory = mocker.GetMock<RabbitMQ.Client.ConnectionFactory>();
            var mockConnection = mocker.GetMock<RabbitMQ.Client.IConnection>();
            var mockChannel1 = new Mock<IModel>();
            var mockChannel2 = new Mock<IModel>();
            var mockChannel3 = new Mock<IModel>();

            mockConnectionFactory.Setup(c => c.CreateConnection()).Returns(mockConnection.Object);
            mockConnection.Setup(c => c.CreateModel()).ReturnsInOrder(mockChannel1.Object, mockChannel2.Object, mockChannel3.Object);
            mockConnection.Setup(c => c.IsOpen).Returns(true);

            // Called during physical close
            mockChannel1.Setup(c => c.IsOpen).Returns(true);
            mockChannel2.Setup(c => c.IsOpen).Returns(true);
            mockChannel3.Setup(c => c.IsOpen).Returns(true);

            var ccf = new CachingConnectionFactory(mockConnectionFactory.Object);
            ccf.ChannelCacheSize = 1;

            var con = ccf.CreateConnection();

            var channel1 = con.CreateChannel(false);

            // cache size is 1, but the other connection is not released yet so this creates a new one
            var channel2 = con.CreateChannel(false);
            Assert.AreNotSame(channel1, channel2);

            // should be ignored, and added last into channel cache.
            channel1.Close();

            // should be physically closed
            channel2.Close();

            // remove first entry in cache (channel1)
            var ch1 = con.CreateChannel(false);

            // create a new channel
            var ch2 = con.CreateChannel(false);

            Assert.AreNotSame(ch1, ch2);
            Assert.AreSame(ch1, channel1);
            Assert.AreNotSame(ch2, channel2);

            ch1.Close();
            ch2.Close();

            mockConnection.Verify(c => c.CreateModel(), Times.Exactly(3));

            con.Close(); // should be ignored

            mockConnection.Verify(c => c.Close(), Times.Never());
            mockChannel1.Verify(c => c.Close(), Times.Never());
            mockChannel2.Verify(c => c.Close(), Times.AtLeastOnce());
            mockChannel3.Verify(c => c.Close(), Times.AtLeastOnce());
        }
        public void CachedModelTwoRequests()
        {
            TestConnectionFactory testConnectionFactory = new TestConnectionFactory();

            CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory(testConnectionFactory, "localhost:" + RabbitUtils.DEFAULT_PORT);

            //Create a session
            IConnection con1 = cachingConnectionFactory.CreateConnection();
            Assert.AreEqual(1, testConnectionFactory.CreateConnectionCount);

            //Create a model
            IModel model1 = con1.CreateModel();
            TestModel testModel1 = GetTestModel(model1);
            Assert.AreEqual(1, testModel1.CreatedCount);
            Assert.AreEqual(0, testModel1.CloseCount);

            //will create a new model, not taken from the cache since cache size is 1.
            IModel model2 = con1.CreateModel();
            TestModel testModel2 = GetTestModel(model2);
            Assert.AreEqual(1, testModel2.CreatedCount);
            Assert.AreEqual(0, testModel2.CloseCount);

            Assert.AreNotSame(testModel1, testModel2);
            Assert.AreNotSame(model1, model2);

            model1.Close(); // will put the model in the cache

            // now get a new model, will be taken from the cache
            IModel model3 = con1.CreateModel();
            TestModel testModel3 = GetTestModel(model3);
            Assert.AreSame(testModel1, testModel3);
            Assert.AreSame(model1, model3);
            Assert.AreEqual(1, testModel1.CreatedCount);
            Assert.AreEqual(0, testModel1.CloseCount);

            Assert.AreEqual(1, testConnectionFactory.CreateConnectionCount);
        }
        public void TestWithListener()
        {
            var mocker = new AutoMoqer();

            var mockConnectionFactory = mocker.GetMock<RabbitMQ.Client.ConnectionFactory>();
            var mockConnection = mocker.GetMock<RabbitMQ.Client.IConnection>();

            mockConnectionFactory.Setup(c => c.CreateConnection()).Returns(mockConnection.Object);

            var called = new AtomicInteger(0);
            var connectionFactory = new CachingConnectionFactory(mockConnectionFactory.Object);

            var mockConnectionListener = new Mock<IConnectionListener>();
            mockConnectionListener.Setup(m => m.OnCreate(It.IsAny<IConnection>())).Callback((IConnection conn) => called.IncrementValueAndReturn());
            mockConnectionListener.Setup(m => m.OnClose(It.IsAny<IConnection>())).Callback((IConnection conn) => called.DecrementValueAndReturn());

            connectionFactory.ConnectionListeners = new List<IConnectionListener>() { mockConnectionListener.Object };

            var con = connectionFactory.CreateConnection();
            Assert.AreEqual(1, called.Value);

            con.Close();
            Assert.AreEqual(1, called.Value);
            mockConnection.Verify(c => c.Close(), Times.Never());

            connectionFactory.CreateConnection();
            Assert.AreEqual(1, called.Value);

            connectionFactory.Dispose();
            Assert.AreEqual(0, called.Value);
            mockConnection.Verify(c => c.Close(), Times.AtLeastOnce());

            mockConnectionFactory.Verify(c => c.CreateConnection(), Times.Exactly(1));
        }
        public void TestWithConnectionFactoryDestroy()
        {
            var mocker = new AutoMoqer();

            var mockConnectionFactory = mocker.GetMock<RabbitMQ.Client.ConnectionFactory>();
            var mockConnection = mocker.GetMock<RabbitMQ.Client.IConnection>();
            var mockChannel1 = new Mock<IModel>();
            var mockChannel2 = new Mock<IModel>();

            Assert.AreNotSame(mockChannel1, mockChannel2);

            mockConnectionFactory.Setup(c => c.CreateConnection()).Returns(mockConnection.Object);
            mockConnection.Setup(c => c.CreateModel()).ReturnsInOrder(mockChannel1.Object, mockChannel2.Object);
            mockConnection.Setup(c => c.IsOpen).Returns(true);

            // Called during physical close
            mockChannel1.Setup(c => c.IsOpen).Returns(true);
            mockChannel2.Setup(c => c.IsOpen).Returns(true);

            var ccf = new CachingConnectionFactory(mockConnectionFactory.Object);
            ccf.ChannelCacheSize = 2;

            var con = ccf.CreateConnection();

            // This will return a proxy that surpresses calls to close
            var channel1 = con.CreateChannel(false);
            var channel2 = con.CreateChannel(false);

            // Should be ignored, and add last into channel cache.
            channel1.Close();
            channel2.Close();

            // remove first entry in cache (channel1)
            var ch1 = con.CreateChannel(false);

            // remove first entry in cache (channel2)
            var ch2 = con.CreateChannel(false);

            Assert.AreSame(ch1, channel1);
            Assert.AreSame(ch2, channel2);

            var target1 = ((IChannelProxy)ch1).GetTargetChannel();
            var target2 = ((IChannelProxy)ch2).GetTargetChannel();

            // make sure mokito returned different mocks for the channel
            Assert.AreNotSame(target1, target2);

            ch1.Close();
            ch2.Close();
            con.Close(); // should be ignored

            ccf.Dispose(); // should call close on connection and channels in cache

            mockConnection.Verify(c => c.CreateModel(), Times.Exactly(2));

            mockConnection.Verify(c => c.Close(), Times.Exactly(1));

            // verify(mockChannel1).close();
            mockChannel2.Verify(c => c.Close(), Times.Exactly(1));

            // After destroy we can get a new connection
            var con1 = ccf.CreateConnection();
            Assert.AreNotSame(con, con1);

            // This will return a proxy that surpresses calls to close
            var channel3 = con.CreateChannel(false);
            Assert.AreNotSame(channel3, channel1);
            Assert.AreNotSame(channel3, channel2);
        }
        public void TestWithConnectionFactoryCacheSize()
        {
            var mocker = new AutoMoqer();

            var mockConnectionFactory = mocker.GetMock<ConnectionFactory>();
            var mockConnection = mocker.GetMock<RabbitMQ.Client.IConnection>();
            var mockChannel1 = new Mock<IModel>();
            var mockChannel2 = new Mock<IModel>();

            mockConnectionFactory.Setup(a => a.CreateConnection()).Returns(mockConnection.Object);
            mockConnection.Setup(a => a.IsOpen).Returns(true);
            mockConnection.Setup(a => a.CreateModel()).ReturnsInOrder(mockChannel1.Object, mockChannel2.Object);
            mockChannel1.Setup(a => a.BasicGet("foo", false)).Returns(new BasicGetResult(0, false, null, null, 1, null, null));
            mockChannel2.Setup(a => a.BasicGet("bar", false)).Returns(new BasicGetResult(0, false, null, null, 1, null, null));
            mockChannel1.Setup(a => a.IsOpen).Returns(true);
            mockChannel2.Setup(a => a.IsOpen).Returns(true);

            var ccf = new CachingConnectionFactory(mockConnectionFactory.Object);
            ccf.ChannelCacheSize = 2;

            var con = ccf.CreateConnection();

            var channel1 = con.CreateChannel(false);
            var channel2 = con.CreateChannel(false);

            channel1.BasicGet("foo", true);
            channel2.BasicGet("bar", true);

            channel1.Close(); // should be ignored, and add last into channel cache.
            channel2.Close(); // should be ignored, and add last into channel cache.

            // (channel1)
            var ch1 = con.CreateChannel(false); // remove first entry in cache

            // (channel2)
            var ch2 = con.CreateChannel(false); // remove first entry in cache

            Assert.AreNotSame(ch1, ch2);
            Assert.AreSame(ch1, channel1);
            Assert.AreSame(ch2, channel2);

            ch1.Close();
            ch2.Close();

            mockConnection.Verify(conn => conn.CreateModel(), Times.Exactly(2));

            con.Close(); // should be ignored

            mockConnection.Verify(c => c.Close(), Times.Never());
            mockChannel1.Verify(c => c.Close(), Times.Never());
            mockChannel2.Verify(c => c.Close(), Times.Never());
        }
        public void TestTransactionalAndNonTransactionalChannelsSegregated()
        {
            var mocker = new AutoMoqer();

            var mockConnectionFactory = mocker.GetMock<RabbitMQ.Client.ConnectionFactory>();
            var mockConnection = mocker.GetMock<RabbitMQ.Client.IConnection>();
            var mockChannel1 = new Mock<IModel>();
            var mockChannel2 = new Mock<IModel>();

            mockConnectionFactory.Setup(c => c.CreateConnection()).Returns(mockConnection.Object);
            mockConnection.Setup(c => c.CreateModel()).ReturnsInOrder(mockChannel1.Object, mockChannel2.Object);
            mockConnection.Setup(c => c.IsOpen).Returns(true);

            // Called during physical close
            mockChannel1.Setup(c => c.IsOpen).Returns(true);
            mockChannel2.Setup(c => c.IsOpen).Returns(true);

            var ccf = new CachingConnectionFactory(mockConnectionFactory.Object);
            ccf.ChannelCacheSize = 1;

            var con = ccf.CreateConnection();

            var channel1 = con.CreateChannel(true);
            channel1.TxSelect();
            channel1.Close(); // should be ignored, and add last into channel cache.

            /*
             * When a channel is created as non-transactional we should create a new one.
             */
            var channel2 = con.CreateChannel(false);
            channel2.Close(); // should be ignored, and add last into channel cache.
            Assert.AreNotSame(channel1, channel2);

            var ch1 = con.CreateChannel(true); // remove first entry in cache (channel1)
            var ch2 = con.CreateChannel(false); // create new channel

            Assert.AreNotSame(ch1, ch2);
            Assert.AreSame(ch1, channel1); // The non-transactional one
            Assert.AreSame(ch2, channel2);

            ch1.Close();
            ch2.Close();

            mockConnection.Verify(c => c.CreateModel(), Times.Exactly(2));

            con.Close(); // should be ignored

            mockConnection.Verify(c => c.Close(), Times.Never());
            mockChannel1.Verify(c => c.Close(), Times.Never());
            mockChannel2.Verify(c => c.Close(), Times.Never());

            var notxlist = (LinkedList<IChannelProxy>)ReflectionUtils.GetInstanceFieldValue(ccf, "cachedChannelsNonTransactional");
            Assert.AreEqual(1, notxlist.Count);

            var txlist = (LinkedList<IChannelProxy>)ReflectionUtils.GetInstanceFieldValue(ccf, "cachedChannelsTransactional");
            Assert.AreEqual(1, txlist.Count);
        }
        public void CachedModelTwoRequestsWithCacheSize()
        {
            TestConnectionFactory testConnectionFactory = new TestConnectionFactory();

            CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory(testConnectionFactory, "localhost:" + RabbitUtils.DEFAULT_PORT);
            cachingConnectionFactory.ChannelCacheSize = 2;
            cachingConnectionFactory.AfterPropertiesSet();

            //Create a session
            IConnection con1 = cachingConnectionFactory.CreateConnection();
            Assert.AreEqual(1, testConnectionFactory.CreateConnectionCount);

            IModel model1 = con1.CreateModel();
            IModel model2 = con1.CreateModel();

            model1.Close(); // should be ignored, and add last into model cache.
            model2.Close(); // should be ignored, and add last into model cache.

            IModel m1 = con1.CreateModel();
            IModel m2 = con1.CreateModel();

            Assert.AreNotSame(m1, m2);
            Assert.AreSame(m1, model1);
            Assert.AreSame(m2, model2);

            m1.Close();
            m2.Close();

            Assert.AreEqual(2, GetTestConnection(con1).CreateModelCount);

            con1.Close();  // should be ignored.

            Assert.AreEqual(0, GetTestConnection(con1).CloseCount);
            Assert.AreEqual(0, GetTestModel(model1).CloseCount);
            Assert.AreEqual(0, GetTestModel(model2).CloseCount);

            Assert.AreEqual(1, testConnectionFactory.CreateConnectionCount);
        }
        public void TestCacheSizeExceededAfterClose()
        {
            var mockConnectionFactory = new Mock<ConnectionFactory>();
            var mockConnection = new Mock<IConnection>();
            var mockChannel1 = new Mock<IModel>();
            var mockChannel2 = new Mock<IModel>();

            mockConnectionFactory.Setup(c => c.CreateConnection()).Returns(mockConnection.Object);
            mockConnection.Setup(c => c.CreateModel()).ReturnsInOrder(mockChannel1.Object, mockChannel2.Object);
            mockConnection.Setup(c => c.IsOpen).Returns(true);

            // Called during physical close
            mockChannel1.Setup(c => c.IsOpen).Returns(true);
            mockChannel2.Setup(c => c.IsOpen).Returns(true);

            var ccf = new CachingConnectionFactory(mockConnectionFactory.Object);
            ccf.ChannelCacheSize = 1;

            var con = ccf.CreateConnection();

            var channel1 = con.CreateChannel(false);
            channel1.Close(); // should be ignored, and add last into channel cache.
            var channel2 = con.CreateChannel(false);
            channel2.Close(); // should be ignored, and add last into channel cache.
            Assert.AreSame(channel1, channel2);

            var ch1 = con.CreateChannel(false); // remove first entry in cache (channel1)
            var ch2 = con.CreateChannel(false); // create new channel

            Assert.AreNotSame(ch1, ch2);
            Assert.AreSame(ch1, channel1);
            Assert.AreNotSame(ch2, channel2);

            ch1.Close();
            ch2.Close();

            mockConnection.Verify(c => c.CreateModel(), Times.Exactly(2));

            con.Close(); // should be ignored

            mockConnection.Verify(c => c.Close(), Times.Never());
            mockChannel1.Verify(c => c.Close(), Times.Never());
            mockChannel2.Verify(c => c.Close(), Times.AtLeastOnce());
        }