コード例 #1
0
        public void NodeDisposeTest()
        {
            // Memcache client config
            var config = new MemcacheClientConfiguration
            {
                TransportFactory = (_, __, r, s, ___, ____) =>
                {
                    var transport = new TransportMock(r)
                    {
                        IsAlive = true, Setup = s
                    };
                    if (s != null)
                    {
                        s(transport);
                    }
                    return(transport);
                },
                PoolSize = 1,
            };
            var node = new MemcacheNode(null, config);

            // TransportMock does not put back the transport in the pool after the TrySend
            Assert.IsTrue(node.TrySend(new NoOpRequest(), 5000), "Unable to send a request through the node");

            // Dispose the node after a certain delay
            ThreadPool.QueueUserWorkItem((o) => { Thread.Sleep(500); node.Dispose(); });

            // The following TrySend will block because the transport pool is empty
            Assert.DoesNotThrow(() => node.TrySend(new NoOpRequest(), 1000), "The TrySend should not throw an exception");
        }
コード例 #2
0
        public void SyncNodeDeadDetection()
        {
            bool aliveness      = true;
            var  transportMocks = new List <TransportMock>();
            var  config         = new MemcacheClientConfiguration
            {
                DeadTimeout      = TimeSpan.FromSeconds(1),
                TransportFactory = (_, __, r, s, ___, ____) =>
                {
                    var transport = new TransportMock(r)
                    {
                        IsAlive = aliveness, Setup = s
                    };
                    transportMocks.Add(transport);
                    if (s != null)
                    {
                        s(transport);
                    }
                    return(transport);
                },
                PoolSize = 2,
            };
            var node = new MemcacheNode(null, config);

            CollectionAssert.IsNotEmpty(transportMocks, "No transport has been created by the node");

            Assert.IsTrue(node.TrySend(new NoOpRequest(), 5000), "Unable to send a request through the node");

            // creation of new transport will set them as dead
            aliveness = false;
            foreach (var transport in transportMocks)
            {
                transport.IsAlive = false;
            }

            Assert.IsFalse(node.TrySend(new NoOpRequest(), 5000), "The node did not failed with all transport deads");

            foreach (var transport in transportMocks)
            {
                transport.IsAlive = true;
            }

            Assert.IsFalse(node.IsDead, "The node is still dead, should be alive now !");
            Assert.IsTrue(node.TrySend(new NoOpRequest(), 5000), "Unable to send a request throught the node after it's alive");
        }
コード例 #3
0
        public void NodeWorkingTransportsTest(int nbOfTransportsPerNode)
        {
            int          createdTransports = 0;
            int          rememberPort;
            var          mutex        = new ManualResetEventSlim(false);
            Status       returnStatus = Status.NoError;
            MemcacheNode theNode      = null;

            // Memcache client config
            var config = new MemcacheClientConfiguration
            {
                DeadTimeout      = TimeSpan.FromSeconds(1),
                TransportFactory = (_, __, ___, ____, _____, ______) =>
                                   new MemcacheTransportForTest(_, __, ___, ____, _____, ______, () => { createdTransports++; }, () => { }),
                NodeFactory                     = (_, __) =>
                                        theNode = MemcacheClientConfiguration.DefaultNodeFactory(_, __) as MemcacheNode,
                PoolSize = nbOfTransportsPerNode,
            };

            MemcacheClient memcacheClient;

            using (var serverMock1 = new ServerMock())
            {
                config.NodesEndPoints.Add(serverMock1.ListenEndPoint);
                rememberPort = serverMock1.ListenEndPoint.Port;

                serverMock1.ResponseBody = new byte[24];

                // Create a Memcache client with one node
                memcacheClient = new MemcacheClient(config);

                // Check that we hooked to the MemcacheNode
                Assert.IsNotNull(theNode, "Did not hook to the MemcacheNode while creating the client");

                // Check the number of transports that have been created
                Assert.AreEqual(nbOfTransportsPerNode, createdTransports, "The number of created should be the number of configured transport");

                // Check the number of working transports (meaning, connected to the server) and the node state
                // By default, the transport are marked as being available upon creation of the client
                Assert.AreEqual(nbOfTransportsPerNode, theNode.WorkingTransports, "The number of working transport should be the number of created transport (1)");
                Assert.IsFalse(theNode.IsDead, "The node should be alive (1)");
                Assert.AreEqual(1, memcacheClient.AliveNodes, "Number of alive nodes is incorrect (1)");

                // Do a get to initialize one of the transports
                Assert.IsTrue(memcacheClient.Get("whatever", (Status s, byte[] o) => { returnStatus = s; mutex.Set(); }), "The request should be sent correctly (1)");
                Assert.IsTrue(mutex.Wait(1000), "Timeout on the get request");
                Assert.AreEqual(Status.InternalError, returnStatus, "The status of the request should be InternalError (1)");
                mutex.Reset();

                // Check the number of working transports and the node state
                Assert.AreEqual(nbOfTransportsPerNode, theNode.WorkingTransports, "The number of working transport should be the number of created transport (2)");
                Assert.IsFalse(theNode.IsDead, "The node should be alive (2)");
                Assert.AreEqual(1, memcacheClient.AliveNodes, "Number of alive nodes is incorrect (2)");
            }

            // Wait for the ServerMock to be fully disposed
            Thread.Sleep(100);

            // Attempt to send a request to take one of the transports out of the pool
            // After that the transport should be dead
            Assert.IsTrue(memcacheClient.Get("whatever", (Status s, byte[] o) => { returnStatus = s; mutex.Set(); }), "The request should be sent correctly (2)");
            Assert.IsTrue(mutex.Wait(1000), "Timeout on the get request");
            Assert.AreEqual(Status.InternalError, returnStatus, "The status of the request should be InternalError (2)");
            mutex.Reset();

            // Check the number of working transports and the node state
            Assert.AreEqual(nbOfTransportsPerNode - 1, theNode.WorkingTransports, "The number of working transport should be the number of created transport minus 1");
            if (nbOfTransportsPerNode == 1)
            {
                Assert.IsTrue(theNode.IsDead, "The node should be dead (3)");
                Assert.AreEqual(0, memcacheClient.AliveNodes, "Number of alive nodes is incorrect (3)");
            }
            else
            {
                Assert.IsFalse(theNode.IsDead, "The node should be alive (3)");
                Assert.AreEqual(1, memcacheClient.AliveNodes, "Number of alive nodes is incorrect (3)");
            }

            // A new transport has been allocated and is periodically trying to reconnect
            Assert.AreEqual(nbOfTransportsPerNode + 1, createdTransports, "Expected a new transport to be created to replace the disposed one");

            using (var serverMock2 = new ServerMock(rememberPort))
            {
                serverMock2.ResponseBody = new byte[24];

                // After some delay, the transport should connect
                Assert.That(() => theNode.WorkingTransports, new DelayedConstraint(new EqualConstraint(nbOfTransportsPerNode), 4000, 100), "After a while, the transport should manage to connect");
                Assert.IsFalse(theNode.IsDead, "The node should be alive (4)");
                Assert.AreEqual(1, memcacheClient.AliveNodes, "Number of alive nodes is incorrect (4)");

                // Attempt a get
                Assert.IsTrue(memcacheClient.Get("whatever", (Status s, byte[] o) => { returnStatus = s; mutex.Set(); }), "The request should be sent correctly (4)");
                Assert.IsTrue(mutex.Wait(1000), "Timeout on the get request");
                Assert.AreEqual(Status.InternalError, returnStatus, "The status of the request should be InternalError (4)");
                mutex.Reset();

                // Check the number of working transports and the node state
                Assert.AreEqual(nbOfTransportsPerNode, theNode.WorkingTransports, "The number of working transport should be the number of created transport (5)");
                Assert.IsFalse(theNode.IsDead, "The node should be alive (5)");
                Assert.AreEqual(1, memcacheClient.AliveNodes, "Number of alive nodes is incorrect (5)");

                // Dispose the client
                memcacheClient.Dispose();
            }
        }