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); }
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 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)); } }
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); }