Java tutorial
/* * Copyright 2008 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hydracache.client.partition; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.io.StringWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import org.hydracache.client.EmptySpaceException; import org.hydracache.client.transport.NullTransport; import org.hydracache.client.transport.RequestMessage; import org.hydracache.client.transport.ResponseMessage; import org.hydracache.client.transport.Transport; import org.hydracache.data.partitioning.NodePartition; import org.hydracache.data.partitioning.SubstancePartition; import org.hydracache.protocol.data.message.DataMessage; import org.hydracache.server.Identity; import org.hydracache.server.data.versioning.IncrementVersionFactory; import org.json.JSONObject; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; /** * @author Tan Quach * @since 1.0 */ public class PartitionAwareClientTest { private PartitionAwareClient client; private NullTransport nullTransport = new NullTransport(); private Transport mockTransport; private Messenger messenger; private PartitionUpdatesPoller poller; @Before public void beforeTestMethods() throws Exception { mockTransport = mock(Transport.class); messenger = mock(Messenger.class); poller = mock(PartitionUpdatesPoller.class); } @After public void afterTestMethods() throws Exception { mockTransport = null; messenger = null; poller = null; } @Test public void ensureVersionIsContextSensitive() { client = new PartitionAwareClient(Arrays.asList(new Identity(8080)), mockTransport, poller); String context = "ctx"; String key = "key"; DataMessage dataMessage = new DataMessage(); dataMessage.setVersion(new IncrementVersionFactory().create(new Identity(1234))); client.updateVersion(context, key, dataMessage); DataMessage newMessage = new DataMessage(); client.attachVersion(context, key, newMessage); assertTrue("Version should be the same", dataMessage.getVersion().equals(newMessage.getVersion())); client.attachVersion("diffCtx", key, newMessage); assertFalse("Version should not be the same", dataMessage.getVersion().equals(newMessage.getVersion())); } @Test public void testSuccessfulDeletionWithoutContext() throws Exception { client = new PartitionAwareClient(Arrays.asList(new Identity(8080)), mockTransport, poller); mockSuccessfulMessaging(); client.setMessager(messenger); String context = null; String key = "testKey"; boolean result = client.delete(key); assertTrue("Should be successful", result); ArgumentCaptor<RequestMessage> reqMsgCaptor = verifySendMessageAndCaptureRequest(); assertRequestMsg("delete", context, key, reqMsgCaptor); } @Test public void testSuccessfulDeletionWithContext() throws Exception { client = new PartitionAwareClient(Arrays.asList(new Identity(8080)), mockTransport, poller); mockSuccessfulMessaging(); client.setMessager(messenger); String context = "testContext"; String key = "testKey"; boolean result = client.delete(context, key); assertTrue("Should be successful", result); ArgumentCaptor<RequestMessage> reqMsgCaptor = verifySendMessageAndCaptureRequest(); assertRequestMsg("delete", context, key, reqMsgCaptor); } private void mockSuccessfulMessaging() throws Exception { when(messenger.sendMessage(any(Identity.class), any(SubstancePartition.class), any(RequestMessage.class))) .thenReturn(new ResponseMessage(true)); } private ArgumentCaptor<RequestMessage> verifySendMessageAndCaptureRequest() throws Exception { ArgumentCaptor<RequestMessage> reqMsgCaptor = ArgumentCaptor.forClass(RequestMessage.class); verify(messenger, atLeastOnce()).sendMessage(any(Identity.class), any(SubstancePartition.class), reqMsgCaptor.capture()); return reqMsgCaptor; } private void assertRequestMsg(String method, String context, String key, ArgumentCaptor<RequestMessage> reqMsgCaptor) { assertEquals("Method is incorrect", method, reqMsgCaptor.getValue().getMethod()); assertEquals("Context is incorrect", context, reqMsgCaptor.getValue().getContext()); assertEquals("Path is incorrect", key, reqMsgCaptor.getValue().getPath()); } @Test(expected = EmptySpaceException.class) public void listNodesShouldThrowExceptionIfPartitionIsEmpty() throws Exception { client = new PartitionAwareClient(new ArrayList<Identity>(), nullTransport, poller); client.listNodes(); } @Test(expected = EmptySpaceException.class) public void getStorageInfoShouldThrowExceptionIfPartitionIsEmpty() throws Exception { client = new PartitionAwareClient(new ArrayList<Identity>(), nullTransport, poller); client.getStorageInfo(); } @Test(expected = EmptySpaceException.class) public void getShouldThrowExceptionIfPartitionIsEmpty() throws Exception { client = new PartitionAwareClient(new ArrayList<Identity>(), nullTransport, poller); client.get("testKey"); } @Test(expected = EmptySpaceException.class) public void deleteShouldThrowExceptionIfPartitionIsEmpty() throws Exception { client = new PartitionAwareClient(new ArrayList<Identity>(), nullTransport, poller); client.delete("testKey"); } @Test(expected = EmptySpaceException.class) public void putShouldThrowExceptionIfPartitionIsEmpty() throws Exception { client = new PartitionAwareClient(new ArrayList<Identity>(), nullTransport, poller); client.put("testKey", ""); } @Test public void shouldReturnEmptyListWhenCurrentPartitionIsNull() throws Exception { client = new PartitionAwareClient(Arrays.asList(new Identity(8080)), nullTransport, poller); ResponseMessage responseMessage = new ResponseMessage(true); responseMessage.setResponseBody("[{\"port\":8080,\"ip\":\"127.0.0.1\"}]".getBytes()); nullTransport.setResponseMessage(responseMessage); List<Identity> nodes = this.client.listNodes(); assertNotNull(nodes); assertFalse(nodes.isEmpty()); nullTransport.setResponseMessage(null); } @Test public void ensureNodeIsRemovedIfFailToSendMessage() throws Exception { Identity node = new Identity(8080); when(mockTransport.sendRequest(any(RequestMessage.class))).thenThrow(new RuntimeException()); PartitionAwareClient client = new PartitionAwareClient(Arrays.asList(node), mockTransport, poller); NodePartition<Identity> partition = client.getNodePartition(); assertTrue("Partition should contain the ID", partition.contains(node)); try { client.put("key", "value"); fail("Should have thrown exception"); } catch (Exception e) { assertFalse("Partition should not contain the ID any more", partition.contains(node)); } } @Test public void ensureShutdownReleasesResources() throws Exception { client = new PartitionAwareClient(Arrays.asList(new Identity(8080)), nullTransport, poller); assertTrue("Client should be running", client.isRunning()); client.shutdown(); assertFalse("Client should be stopped", client.isRunning()); } @Test public void ensureStorageInfoCanBeRetrieved() throws Exception { client = new PartitionAwareClient(Arrays.asList(new Identity(8080)), mockTransport, poller); ResponseMessage responseMsg = new ResponseMessage(true); JSONObject output = new JSONObject(); output.put("testField", "100"); StringWriter writer = new StringWriter(); output.write(writer); responseMsg.setResponseBody(writer.toString().getBytes()); when(messenger.sendMessage(any(Identity.class), any(SubstancePartition.class), any(RequestMessage.class))) .thenReturn(responseMsg); client.setMessager(messenger); Map<String, String> info = client.getStorageInfo(); assertEquals("Test field value is incorrect", "100", info.get("testField")); } @Test public void ensureNodeIsRemovedIfGetQueryFails() throws Exception { Identity node = new Identity(8080); when(mockTransport.sendRequest(any(RequestMessage.class))).thenThrow(new RuntimeException()); PartitionAwareClient client = new PartitionAwareClient(Arrays.asList(node), mockTransport, poller); NodePartition<Identity> partition = client.getNodePartition(); assertTrue("Partition should contain the ID", partition.contains(node)); try { client.put("key", "value"); fail("Should have thrown exception"); } catch (Exception e) { assertFalse("Partition should not contain the ID any more", partition.contains(node)); } } @Test public void ensureGetRandomNodeUsesSeedsWhenSpaceIsEmpty() throws Exception { Identity expectedNode = new Identity(8080); client = new PartitionAwareClient(Arrays.asList(expectedNode), nullTransport, poller); client.getNodePartition().remove(expectedNode); Identity node = client.pickRandomServerFromRegistry(); assertEquals("Random node is incorrect", expectedNode, node); } @Test public void ensureFindNodeByHashUsesSeedsWhenSpaceIsEmpty() throws Exception { Identity expectedNode = new Identity(8080); client = new PartitionAwareClient(Arrays.asList(expectedNode), nullTransport, poller); client.getNodePartition().remove(expectedNode); Identity node = client.findNodeByKey("key"); assertEquals("Target node is incorrect", expectedNode, node); } }