/*
* Copyright 2013-2014 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.
*/
// CHECKSTYLE:OFF
// Checkstyle is disabled because in test 'testUploadBigFileAndCompareChecksum'
// there is a needed while loop without a statement inside.
package org.springframework.cloud.aws.context.support.io;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.ObjectMetadata;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.aws.core.env.stack.StackResourceRegistry;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.WritableResource;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.DigestUtils;
import org.springframework.util.FileCopyUtils;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* @author Agim Emruli
*/
@RunWith(SpringJUnit4ClassRunner.class)
public abstract class ResourceLoaderAwsTest {
private static final String S3_PREFIX = "s3://";
private final List<String> createdObjects = new ArrayList<>();
@Autowired
private ResourceLoader resourceLoader;
@SuppressWarnings("SpringJavaAutowiringInspection")
@Autowired
private AmazonS3 amazonS3;
@SuppressWarnings("SpringJavaAutowiringInspection")
@Autowired
private StackResourceRegistry stackResourceRegistry;
@Test
public void testUploadAndDownloadOfSmallFileWithInjectedResourceLoader() throws Exception {
String bucketName = this.stackResourceRegistry.lookupPhysicalResourceId("EmptyBucket");
uploadFileTestFile(bucketName, "testUploadAndDownloadOfSmallFileWithInjectedResourceLoader", "hello world");
Resource resource = this.resourceLoader.getResource(S3_PREFIX + bucketName + "/testUploadAndDownloadOfSmallFileWithInjectedResourceLoader");
assertTrue(resource.exists());
InputStream inputStream = resource.getInputStream();
assertNotNull(inputStream);
assertEquals("hello world", FileCopyUtils.copyToString(new InputStreamReader(inputStream, "UTF-8")));
assertEquals("hello world".length(), resource.contentLength());
}
@Test
public void testUploadFileWithRelativePath() throws Exception {
String bucketName = this.stackResourceRegistry.lookupPhysicalResourceId("EmptyBucket");
uploadFileTestFile(bucketName, "testUploadFileWithRelativePathParent", "hello world");
Resource resource = this.resourceLoader.getResource(S3_PREFIX + bucketName + "/testUploadFileWithRelativePathParent");
assertTrue(resource.exists());
WritableResource childFileResource = (WritableResource) resource.createRelative("child");
try (OutputStream outputStream = childFileResource.getOutputStream(); OutputStreamWriter writer = new OutputStreamWriter(outputStream)) {
writer.write("hello world");
}
this.createdObjects.add(childFileResource.getFilename());
InputStream inputStream = childFileResource.getInputStream();
assertNotNull(inputStream);
assertEquals("hello world", FileCopyUtils.copyToString(new InputStreamReader(inputStream, "UTF-8")));
assertEquals("hello world".length(), childFileResource.contentLength());
}
private void uploadFileTestFile(String bucketName, String objectKey, String content) throws UnsupportedEncodingException {
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(content.length());
this.amazonS3.putObject(bucketName, objectKey, new ByteArrayInputStream(content.getBytes("UTF-8")), objectMetadata);
this.createdObjects.add(objectKey);
}
@Test
public void testUploadFileWithMoreThenFiveMegabytes() throws Exception {
String bucketName = this.stackResourceRegistry.lookupPhysicalResourceId("EmptyBucket");
Resource resource = this.resourceLoader.getResource(S3_PREFIX + bucketName + "/testUploadFileWithMoreThenFiveMegabytes");
assertTrue(WritableResource.class.isInstance(resource));
WritableResource writableResource = (WritableResource) resource;
OutputStream outputStream = writableResource.getOutputStream();
for (int i = 0; i < (1024 * 1024 * 6); i++) {
outputStream.write("c".getBytes("UTF-8"));
}
outputStream.close();
this.createdObjects.add("testUploadFileWithMoreThenFiveMegabytes");
}
@Test
public void testUploadBigFileAndCompareChecksum() throws IOException, NoSuchAlgorithmException {
String bucketName = this.stackResourceRegistry.lookupPhysicalResourceId("EmptyBucket");
Resource resource = this.resourceLoader.getResource(S3_PREFIX + bucketName + "/test-file.jpg");
assertTrue(WritableResource.class.isInstance(resource));
WritableResource writableResource = (WritableResource) resource;
OutputStream outputStream = writableResource.getOutputStream();
ClassPathResource testFileResource = new ClassPathResource("test-file.jpg", getClass());
InputStream inputStream = new FileInputStream(testFileResource.getFile());
MessageDigest md = MessageDigest.getInstance("MD5");
inputStream = new DigestInputStream(inputStream, md);
FileCopyUtils.copy(inputStream, outputStream);
byte[] originalMd5Checksum = md.digest();
Resource downloadedResource = this.resourceLoader.getResource(S3_PREFIX + bucketName + "/test-file.jpg");
InputStream downloadedInputStream = downloadedResource.getInputStream();
md.reset();
try {
downloadedInputStream = new DigestInputStream(downloadedInputStream, md);
//noinspection StatementWithEmptyBody
while (downloadedInputStream.read() != -1) {
// go through the input stream until EOF to compute MD5 checksum.
}
} finally {
downloadedInputStream.close();
}
byte[] downloadedMd5Checksum = md.digest();
assertEquals(DigestUtils.md5DigestAsHex(originalMd5Checksum), DigestUtils.md5DigestAsHex(downloadedMd5Checksum));
this.createdObjects.add("test-file.jpg");
}
@Test
public void exists_withNonExistingObject_shouldReturnFalse() throws Exception {
// Arrange
String bucketName = this.stackResourceRegistry.lookupPhysicalResourceId("EmptyBucket");
// Act & Assert
assertFalse(this.resourceLoader.getResource(S3_PREFIX + bucketName + "/dummy-file.txt").exists());
}
@Test
public void exists_withNonExistingBucket_shouldReturnFalse() throws Exception {
assertFalse(this.resourceLoader.getResource(S3_PREFIX + "dummy-bucket-does-not-really-exist/dummy-file.txt").exists());
}
//Cleans up the bucket. Because if the bucket is not cleaned up, then the bucket will not be deleted after the test run.
@After
public void tearDown() {
String bucketName = this.stackResourceRegistry.lookupPhysicalResourceId("EmptyBucket");
for (String createdObject : this.createdObjects) {
this.amazonS3.deleteObject(bucketName, createdObject);
}
}
}