public void SerializationThrows()
        {
            var serializerMoq = new Mock<ISerializer<TestType>>();
            serializerMoq.Setup(s => s.FromBytes(It.IsAny<byte[]>())).Throws(new SerializationException());
            serializerMoq.Setup(s => s.ToBytes(It.IsAny<TestType>())).Throws(new SerializationException());
            serializerMoq.Setup(s => s.TypeFlag).Returns(314);

            Exception raised = null;

            var config = new MemcacheClientConfiguration
            {
                ClusterFactory = c => _clusterMock,
            };
            var serialiserMoqObj = serializerMoq.Object;
            config.SetSerializer(serialiserMoqObj);
            var client = new MemcacheClient(config);
            client.CallbackError += e => raised = e;

            // test that the throws of the serializer is synchronously propagated
            Assert.Throws(typeof(SerializationException), () => client.Set("Hello", new TestType(), TimeSpan.Zero));

            // test that the failing serializer does not synchronously throws but sends a CallbackError event
            _responseHeader = new MemcacheResponseHeader
            {
                ExtraLength = 4,
                TotalBodyLength = 4,
                Opcode = Opcode.Get,
            };
            _extra = new byte[] { 0, 0, 0, 0};
            Assert.True(client.Get("Hello", (Status s, TestType v) => { }));
            Assert.IsNotNull(raised);
            Assert.IsInstanceOf<SerializationException>(raised);
        }
        public void MemcacheClientReplicasTest()
        {
            var client = new MemcacheClient(_configuration);

            for (int replicas = 0; replicas < _configuration.NodesEndPoints.Count; replicas++)
            {
                _configuration.Replicas = replicas;

                // SET
                NodeMock.trySendCounter = 0;
                Assert.IsTrue(client.Set("toto", new byte[0], TimeSpan.MaxValue, null));
                Assert.AreEqual(replicas + 1, NodeMock.trySendCounter);

                // GET
                NodeMock.trySendCounter = 0;
                Assert.IsTrue(client.Get("toto", null));
                Assert.AreEqual(replicas + 1, NodeMock.trySendCounter);

                // DELETE
                NodeMock.trySendCounter = 0;
                Assert.IsTrue(client.Delete("toto", null));
                Assert.AreEqual(replicas + 1, NodeMock.trySendCounter);
            }

            // Set number of replicas to a number strictly greater than the number of nodes, minus one.
            NodeMock.trySendCounter = 0;
            _configuration.Replicas = _configuration.NodesEndPoints.Count;
            Assert.IsTrue(client.Set("toto", new byte[0], TimeSpan.MaxValue, null));
            Assert.AreEqual(_configuration.NodesEndPoints.Count, NodeMock.trySendCounter);
        }
Exemple #3
0
        public void UnsupportedSerializationThrows()
        {
            var config = new MemcacheClientConfiguration
            {
                ClusterFactory = c => _clusterMock,
            };
            var client = new MemcacheClient(config);

            // assert that both set and get throws NotSupportedException for an unknown type
            Assert.Throws(typeof(NotSupportedException), () => client.Set("Hello", new TestType(), TimeSpan.Zero));
            Assert.Throws(typeof(NotSupportedException), () => client.Get("Hello", (Status s, TestType v) => { }));
        }
Exemple #4
0
        public void ExecutionContextShouldFlow()
        {
            var config = new MemcacheClientConfiguration
            {
                ClusterFactory = c => _clusterMock,
            };
            var client = new MemcacheClient(config);

            object value = null;

            _extra = new byte[] { 0, 0, 0, 0 };

            CallContext.LogicalSetData(CallContextKey, "OK");

            client.Get("test", (Status s, byte[] v) =>
            {
                value = CallContext.LogicalGetData("MemcacheClientTest");
            });

            Assert.AreEqual("OK", value, "The execution context didn't flow");
        }
        public void MemcacheClientReplicasTest()
        {
            var callbackMutex = new ManualResetEventSlim(false);

            var client = new MemcacheClient(_configuration);

            // The number of requests sent is capped by the number of nodes in the cluster.
            // The last iteration of the loop below actually tests the case where the total
            // number of copies (Replicas+1) is strictly greater than the number of nodes.
            int nodeCount = _configuration.NodesEndPoints.Count;

            for (int replicas = 0; replicas <= nodeCount; replicas++)
            {
                _configuration.Replicas = replicas;

                // SET
                callbackMutex.Reset();
                NodeMock.TrySendCounter = 0;
                Assert.IsTrue(client.Set("toto", new byte[0], TimeSpan.MaxValue, s => callbackMutex.Set()));
                Assert.AreEqual(Math.Min(replicas + 1, nodeCount), NodeMock.TrySendCounter);
                Assert.IsTrue(callbackMutex.Wait(1000),
                              string.Format("The SET callback has not been received after 1 second (Replicas = {0})", replicas));

                // GET
                callbackMutex.Reset();
                NodeMock.TrySendCounter = 0;
                Assert.IsTrue(client.Get("toto", (s, data) => callbackMutex.Set()));
                Assert.AreEqual(Math.Min(replicas + 1, nodeCount), NodeMock.TrySendCounter);
                Assert.IsTrue(callbackMutex.Wait(1000),
                              string.Format("The GET callback has not been received after 1 second (Replicas = {0})", replicas));

                // DELETE
                callbackMutex.Reset();
                NodeMock.TrySendCounter = 0;
                Assert.IsTrue(client.Delete("toto", s => callbackMutex.Set()));
                Assert.AreEqual(Math.Min(replicas + 1, nodeCount), NodeMock.TrySendCounter);
                Assert.IsTrue(callbackMutex.Wait(1000),
                              string.Format("The DELETE callback has not been received after 1 second (Replicas = {0})", replicas));
            }
        }
        public void MemcacheClientReplicasTest()
        {
            var callbackMutex = new ManualResetEventSlim(false);

            var client = new MemcacheClient(_configuration);

            // The number of requests sent is capped by the number of nodes in the cluster.
            // The last iteration of the loop below actually tests the case where the total
            // number of copies (Replicas+1) is strictly greater than the number of nodes.
            int nodeCount = _configuration.NodesEndPoints.Count;
            for (int replicas = 0; replicas <= nodeCount; replicas++)
            {
                _configuration.Replicas = replicas;

                // SET
                callbackMutex.Reset();
                NodeMock.TrySendCounter = 0;
                Assert.IsTrue(client.Set("toto", new byte[0], TimeSpan.MaxValue, s => callbackMutex.Set()));
                Assert.AreEqual(Math.Min(replicas + 1, nodeCount), NodeMock.TrySendCounter);
                Assert.IsTrue(callbackMutex.Wait(1000),
                    string.Format("The SET callback has not been received after 1 second (Replicas = {0})", replicas));

                // GET
                callbackMutex.Reset();
                NodeMock.TrySendCounter = 0;
                Assert.IsTrue(client.Get("toto", (Status s, byte[] data) => callbackMutex.Set()));
                Assert.AreEqual(Math.Min(replicas + 1, nodeCount), NodeMock.TrySendCounter);
                Assert.IsTrue(callbackMutex.Wait(1000),
                    string.Format("The GET callback has not been received after 1 second (Replicas = {0})", replicas));

                // DELETE
                callbackMutex.Reset();
                NodeMock.TrySendCounter = 0;
                Assert.IsTrue(client.Delete("toto", s => callbackMutex.Set()));
                Assert.AreEqual(Math.Min(replicas + 1, nodeCount), NodeMock.TrySendCounter);
                Assert.IsTrue(callbackMutex.Wait(1000),
                    string.Format("The DELETE callback has not been received after 1 second (Replicas = {0})", replicas));

            }
        }
Exemple #7
0
        public void SerializationThrows()
        {
            var serializerMoq = new Mock <ISerializer <TestType> >();

            serializerMoq.Setup(s => s.FromBytes(It.IsAny <byte[]>())).Throws(new SerializationException());
            serializerMoq.Setup(s => s.ToBytes(It.IsAny <TestType>())).Throws(new SerializationException());
            serializerMoq.Setup(s => s.TypeFlag).Returns(314);

            Exception raised = null;

            var config = new MemcacheClientConfiguration
            {
                ClusterFactory = c => _clusterMock,
            };
            var serialiserMoqObj = serializerMoq.Object;

            config.SetSerializer(serialiserMoqObj);
            var client = new MemcacheClient(config);

            client.CallbackError += e => raised = e;

            // test that the throws of the serializer is synchronously propagated
            Assert.Throws(typeof(SerializationException), () => client.Set("Hello", new TestType(), TimeSpan.Zero));

            // test that the failing serializer does not synchronously throws but sends a CallbackError event
            _responseHeader = new MemcacheResponseHeader
            {
                ExtraLength     = 4,
                TotalBodyLength = 4,
                Opcode          = Opcode.Get,
            };
            _extra = new byte[] { 0, 0, 0, 0 };
            Assert.True(client.Get("Hello", (Status s, TestType v) => { }));
            Assert.IsNotNull(raised);
            Assert.IsInstanceOf <SerializationException>(raised);
        }
        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();
            }
        }
        public void MemcacheTransportDisposeTransportNotInPoolTest()
        {
            int createdTransports = 0;
            int disposedTransports = 0;
            var mutex1 = new ManualResetEventSlim(false);
            var mutex2 = new ManualResetEventSlim(false);
            Status returnStatus = Status.NoError;

            // Memcache client config
            var config = new MemcacheClientConfiguration
            {
                DeadTimeout = TimeSpan.FromSeconds(1),
                TransportConnectTimerPeriod = TimeSpan.FromMilliseconds(100),
                TransportFactory = (_, __, ___, ____, _____, ______) =>
                    new MemcacheTransportForTest(_, __, ___, ____, _____, ______, () => { createdTransports++; }, () => { disposedTransports++; mutex1.Set(); }),
                PoolSize = 1,
            };

            MemcacheClient memcacheClient;
            using (var serverMock = new ServerMock())
            {
                config.NodesEndPoints.Add(serverMock.ListenEndPoint);
                serverMock.ResponseBody = new byte[24];

                // Create Memcache client
                memcacheClient = new MemcacheClient(config);

                // Test the number of transports that have been created
                Assert.AreEqual(1, createdTransports);

                // Do a get to initialize the transport
                Assert.IsTrue(memcacheClient.Get("whatever", (Status s, byte[] o) => { returnStatus = s; mutex2.Set(); }));
                Assert.IsTrue(mutex2.Wait(1000), "Timeout on the get request");
                Assert.AreEqual(Status.InternalError, returnStatus);
                mutex2.Reset();
            }

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

            // Attempt to send a request to take the transport out of the pool
            Assert.IsTrue(memcacheClient.Get("whatever", (Status s, byte[] o) => { returnStatus = s; mutex2.Set(); }));
            Assert.IsTrue(mutex2.Wait(1000), "Timeout on the get request");
            Assert.AreEqual(Status.InternalError, returnStatus);
            mutex2.Reset();

            // The initial transport should now be disposed, a new transport has been allocated and
            // is periodically trying to reconnect
            Assert.IsTrue(mutex1.Wait(1000), "Timeout on initial transport disposal");
            Assert.AreEqual(1, disposedTransports, "Expected the initial transport to be disposed");
            Assert.AreEqual(2, createdTransports, "Expected a new transport to be created to replace the disposed one");

            mutex1.Reset();

            // Dispose the client
            memcacheClient.Dispose();

            // Wait enough time for the reconnect timer to fire at least once
            Assert.IsTrue(mutex1.Wait(4000), "MemcacheTransport was not disposed before the timeout");

            // Check that all transports have been disposed
            Assert.AreEqual(2, disposedTransports);
            Assert.AreEqual(createdTransports, disposedTransports);
        }
        public void MemcacheTransportDisposeTransportNotInPoolTest()
        {
            int    createdTransports  = 0;
            int    disposedTransports = 0;
            var    mutex1             = new ManualResetEventSlim(false);
            var    mutex2             = new ManualResetEventSlim(false);
            Status returnStatus       = Status.NoError;

            // Memcache client config
            var config = new MemcacheClientConfiguration
            {
                DeadTimeout = TimeSpan.FromSeconds(1),
                TransportConnectTimerPeriod = TimeSpan.FromMilliseconds(100),
                TransportFactory            = (_, __, ___, ____, _____, ______) =>
                                              new MemcacheTransportForTest(_, __, ___, ____, _____, ______, () => { createdTransports++; }, () => { disposedTransports++; mutex1.Set(); }),
                PoolSize = 1,
            };

            MemcacheClient memcacheClient;

            using (var serverMock = new ServerMock())
            {
                config.NodesEndPoints.Add(serverMock.ListenEndPoint);
                serverMock.ResponseBody = new byte[24];

                // Create Memcache client
                memcacheClient = new MemcacheClient(config);

                // Test the number of transports that have been created
                Assert.AreEqual(1, createdTransports);

                // Do a get to initialize the transport
                Assert.IsTrue(memcacheClient.Get("whatever", (Status s, byte[] o) => { returnStatus = s; mutex2.Set(); }));
                Assert.IsTrue(mutex2.Wait(1000), "Timeout on the get request");
                Assert.AreEqual(Status.InternalError, returnStatus);
                mutex2.Reset();
            }

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

            // Attempt to send a request to take the transport out of the pool
            Assert.IsTrue(memcacheClient.Get("whatever", (Status s, byte[] o) => { returnStatus = s; mutex2.Set(); }));
            Assert.IsTrue(mutex2.Wait(1000), "Timeout on the get request");
            Assert.AreEqual(Status.InternalError, returnStatus);
            mutex2.Reset();

            // The initial transport should now be disposed, a new transport has been allocated and
            // is periodically trying to reconnect
            Assert.IsTrue(mutex1.Wait(1000), "Timeout on initial transport disposal");
            Assert.AreEqual(1, disposedTransports, "Expected the initial transport to be disposed");
            Assert.AreEqual(2, createdTransports, "Expected a new transport to be created to replace the disposed one");

            mutex1.Reset();

            // Dispose the client
            memcacheClient.Dispose();

            // Wait enough time for the reconnect timer to fire at least once
            Assert.IsTrue(mutex1.Wait(4000), "MemcacheTransport was not disposed before the timeout");

            // Check that all transports have been disposed
            Assert.AreEqual(2, disposedTransports);
            Assert.AreEqual(createdTransports, disposedTransports);
        }
Exemple #11
0
        public void UnsupportedSerializationThrows()
        {
            var config = new MemcacheClientConfiguration
            {
                ClusterFactory = c => _clusterMock,
            };
            var client = new MemcacheClient(config);

            // assert that both set and get throws NotSupportedException for an unknown type
            Assert.Throws(typeof(NotSupportedException), () => client.Set("Hello", new TestType(), TimeSpan.Zero));
            Assert.Throws(typeof(NotSupportedException), () => client.Get("Hello", (Status s, TestType v) => { }));
        }
        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();
            }
        }