Java tutorial
/* * Copyright 2010 Talis Information Ltd * * 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 com.talis.storage.s3; import static org.easymock.EasyMock.expectLastCall; import static org.easymock.classextension.EasyMock.createStrictMock; import static org.easymock.classextension.EasyMock.replay; import static org.easymock.classextension.EasyMock.verify; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import java.util.UUID; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.io.IOUtils; import org.jets3t.service.S3Service; import org.jets3t.service.S3ServiceException; import org.jets3t.service.model.S3Bucket; import org.jets3t.service.model.S3Object; import org.junit.Before; import org.junit.Test; public class DirectChunkHandlerTest { private String key; private String bucketName; private S3Bucket bucket; @Before public void setup() { key = UUID.randomUUID().toString(); bucketName = UUID.randomUUID().toString(); bucket = new S3Bucket(bucketName); } @Test public void writeChunkUsesSuppliedServiceToStoreObject() throws Exception { S3Object chunk = new S3Object(key); chunk.setMd5Hash(DigestUtils.md5("Mickey Mouse is dead")); S3Service mockService = createStrictMock(S3Service.class); mockService.putObject(bucket, chunk); expectLastCall().andReturn(chunk); replay(mockService); new DirectChunkHandler(bucket, mockService).writeChunk(chunk); verify(mockService); } @Test(expected = IOException.class) public void exceptionThrownByServiceAreCaughtAndRethrown() throws Exception { S3Object chunk = new S3Object(key); chunk.setMd5Hash(DigestUtils.md5("Mickey Mouse is dead")); S3Service mockService = createStrictMock(S3Service.class); mockService.putObject(bucket, chunk); expectLastCall().andThrow(new S3ServiceException("TEST")); replay(mockService); try { new DirectChunkHandler(bucket, mockService).writeChunk(chunk); } finally { verify(mockService); } } @Test public void writeChunkReturnsObjectReturnedByService() throws Exception { S3Object chunk = new S3Object(key); S3Object written = new S3Object(key); written.setMd5Hash(DigestUtils.md5("Mickey Mouse is dead")); S3Service mockService = createStrictMock(S3Service.class); mockService.putObject(bucket, chunk); expectLastCall().andReturn(written); replay(mockService); assertSame(written, new DirectChunkHandler(bucket, mockService).writeChunk(chunk)); verify(mockService); } @Test public void listChunksForResourceWithSinglePart() throws Exception { S3Object chunk = new S3Object(key); S3Object[] chunks = new S3Object[] { chunk }; S3Service mockService = createStrictMock(S3Service.class); mockService.listObjects(bucket, key, null); expectLastCall().andReturn(chunks); replay(mockService); assertSame(chunks, new DirectChunkHandler(bucket, mockService).listChunks(key)); verify(mockService); } @Test public void listChunksForResourceWithMultipleParts() throws Exception { S3Object chunk0 = new S3Object(key + "/0"); S3Object chunk1 = new S3Object(key + "/1"); S3Object[] chunks = new S3Object[] { chunk0, chunk1 }; S3Service mockService = createStrictMock(S3Service.class); mockService.listObjects(bucket, key, null); expectLastCall().andReturn(chunks); replay(mockService); assertSame(chunks, new DirectChunkHandler(bucket, mockService).listChunks(key)); verify(mockService); } @Test public void listChunksForResourceWithNoParts() throws Exception { S3Object[] chunks = new S3Object[] {}; S3Service mockService = createStrictMock(S3Service.class); mockService.listObjects(bucket, key, null); expectLastCall().andReturn(chunks); replay(mockService); assertSame(chunks, new DirectChunkHandler(bucket, mockService).listChunks(key)); verify(mockService); } @Test(expected = IOException.class) public void remoteServiceThrowsErrorWhenListingChunks() throws Exception { S3Service mockService = createStrictMock(S3Service.class); mockService.listObjects(bucket, key, null); expectLastCall().andThrow(new S3ServiceException("TEST")); replay(mockService); try { new DirectChunkHandler(bucket, mockService).listChunks(key); } finally { verify(mockService); } } @Test public void deleteChunkDeletesUsingRemoteService() throws Exception { S3Object chunk0 = new S3Object(key + "/0"); S3Service mockService = createStrictMock(S3Service.class); mockService.deleteObject(bucket, chunk0.getKey()); replay(mockService); new DirectChunkHandler(bucket, mockService).deleteChunk(chunk0.getKey()); verify(mockService); } @Test(expected = IOException.class) public void remoteServiceThrowsErrorWhenDeletingChunk() throws Exception { S3Object chunk0 = new S3Object(key + "/0"); S3Service mockService = createStrictMock(S3Service.class); mockService.deleteObject(bucket, chunk0.getKey()); expectLastCall().andThrow(new S3ServiceException("TEST")); replay(mockService); new DirectChunkHandler(bucket, mockService).deleteChunk(chunk0.getKey()); verify(mockService); } @Test public void getChunkReturnsObjectFromRemoteService() throws Exception { S3Object chunk0 = new S3Object(key + "/0"); S3Service mockService = createStrictMock(S3Service.class); mockService.getObject(bucket, chunk0.getKey()); expectLastCall().andReturn(chunk0); replay(mockService); assertSame(chunk0, new DirectChunkHandler(bucket, mockService).getChunk(chunk0.getKey())); verify(mockService); } @Test public void reconstructItemFromMultipleChunks() throws Exception { S3Object chunk0 = new S3Object(key + "/0"); byte[] bytes0 = "There's a band on stage\n".getBytes(); chunk0.setDataInputStream(new ByteArrayInputStream(bytes0)); S3Object chunk1 = new S3Object(key + "/1"); byte[] bytes1 = "That used to be huge\n".getBytes(); chunk1.setDataInputStream(new ByteArrayInputStream(bytes1)); S3Object chunk2 = new S3Object(key + "/2"); byte[] bytes2 = "They're on but noone's listening".getBytes(); chunk2.setDataInputStream(new ByteArrayInputStream(bytes2)); S3Service mockService = createStrictMock(S3Service.class); replay(mockService); S3Object[] chunks = new S3Object[] { chunk0, chunk1, chunk2 }; InputStream in = new DirectChunkHandler(bucket, mockService).reconstructChunks(chunks); ByteArrayOutputStream out = new ByteArrayOutputStream(); IOUtils.copy(in, out); byte[] expected = new byte[bytes0.length + bytes1.length + bytes2.length]; System.arraycopy(bytes0, 0, expected, 0, bytes0.length); System.arraycopy(bytes1, 0, expected, bytes0.length, bytes1.length); System.arraycopy(bytes2, 0, expected, (bytes0.length + bytes1.length), bytes2.length); assertTrue(Arrays.equals(expected, out.toByteArray())); verify(mockService); } @Test public void reconstructItemFromSingleChunk() throws Exception { S3Object chunk0 = new S3Object(key + "/0"); byte[] bytes0 = "There's a band on stage\n".getBytes(); chunk0.setDataInputStream(new ByteArrayInputStream(bytes0)); S3Service mockService = createStrictMock(S3Service.class); replay(mockService); S3Object[] chunks = new S3Object[] { chunk0 }; InputStream in = new DirectChunkHandler(bucket, mockService).reconstructChunks(chunks); ByteArrayOutputStream out = new ByteArrayOutputStream(); IOUtils.copy(in, out); assertTrue(Arrays.equals(bytes0, out.toByteArray())); verify(mockService); } @Test public void checkDataInputStreamInitialisedForChunkBeforeReading() throws Exception { S3Object unreadChunk = new S3Object(key + "/0"); S3Object readChunk = new S3Object(key + "/0"); byte[] bytes = "There's a band on stage\n".getBytes(); readChunk.setDataInputStream(new ByteArrayInputStream(bytes)); S3Service mockService = createStrictMock(S3Service.class); mockService.getObject(bucket, unreadChunk.getKey()); expectLastCall().andReturn(readChunk); replay(mockService); S3Object[] chunks = new S3Object[] { unreadChunk }; InputStream in = new DirectChunkHandler(bucket, mockService).reconstructChunks(chunks); ByteArrayOutputStream out = new ByteArrayOutputStream(); IOUtils.copy(in, out); verify(mockService); } @Test public void ensureChunksSortedByKeyBeforeStreaming() throws Exception { // TODO : check s3 docs and/or implement comparator to sort array by key } @Test(expected = IOException.class) public void ensureContinuousSequenceOfKeysBeforeRead() throws Exception { S3Object chunk0 = new S3Object(key + "/0"); S3Object chunk1 = new S3Object(key + "/1"); S3Object chunk3 = new S3Object(key + "/3"); S3Object[] incorrectlyOrderedChunks = new S3Object[] { chunk0, chunk1, chunk3 }; S3Service mockService = createStrictMock(S3Service.class); replay(mockService); try { new DirectChunkHandler(bucket, mockService).reconstructChunks(incorrectlyOrderedChunks); } finally { verify(mockService); } } }