Commit 0dfe3ad4 authored by Matija Obreza's avatar Matija Obreza
Browse files

Merge branch '37-test-coverage' into 'main'

Resolve "Test coverage 70%"

Closes #37

See merge request !49
parents 3b8dddb9 170302b9
/*
* Copyright 2020 Global Crop Diversity Trust
*
* 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.genesys.filerepository.migration;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import org.genesys.filerepository.model.ImageGallery;
import org.genesys.filerepository.model.QRepositoryFile;
import org.genesys.filerepository.model.RepositoryFile;
import org.genesys.filerepository.model.RepositoryFolder;
import org.genesys.filerepository.persistence.ImageGalleryPersistence;
import org.genesys.filerepository.persistence.RepositoryFilePersistence;
import org.genesys.filerepository.service.RepositoryService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import com.querydsl.jpa.impl.JPAQueryFactory;
/**
* Creates {@link RepositoryFolder} entries and their parents - Links all
* {@link RepositoryFile} to their parent folders.
*
* @author Matija Obreza
*/
@Component
public class RepositoryUpgrade20180920 {
private static final Logger LOG = LoggerFactory.getLogger(RepositoryUpgrade20180920.class);
/** The tx manager. */
@Autowired
@Qualifier("transactionManager")
protected PlatformTransactionManager txManager;
@Autowired
private RepositoryFilePersistence fileRepository;
@Autowired
private RepositoryService repositoryService;
@Autowired
private ImageGalleryPersistence imagegalleryRepository;
@Autowired
private JPAQueryFactory jpaQueryFactory;
/**
* Do upgrade.
*
* @throws Exception the exception
*/
public void doUpgrade() throws Exception {
TransactionTemplate tmpl = new TransactionTemplate(txManager);
tmpl.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
try {
makeFolders();
} catch (Throwable e) {
LOG.error("Could not migrate 1.0 to 1.1 model: {}", e.getMessage(), e);
}
}
});
tmpl.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
try {
moveFilesToFolders();
} catch (Throwable e) {
LOG.error("Could not migrate 1.0 to 1.1 model: {}", e.getMessage(), e);
}
}
});
tmpl.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
try {
migrateImageGalleries();
} catch (Throwable e) {
LOG.error("Could not migrate 1.0 to 1.1 model: {}", e.getMessage(), e);
}
}
});
}
/**
* Do the migration.
*
* @throws Exception the exception
*/
void makeFolders() throws Exception {
long count = 0;
// get distinct paths
List<String> paths = jpaQueryFactory.selectFrom(QRepositoryFile.repositoryFile).select(QRepositoryFile.repositoryFile.path).distinct().orderBy(
QRepositoryFile.repositoryFile.path.asc()).fetch();
for (String folderName : paths) {
if (folderName == null) {
continue;
}
final Path folderPath = Paths.get(folderName);
RepositoryFolder folder = repositoryService.getFolder(folderPath);
if (folder == null) {
LOG.warn("Creating repository path={}", folderPath);
folder = repositoryService.ensureFolder(folderPath);
LOG.warn("Created folder={}", folder.getFolderPath());
count++;
}
}
if (count == 0) {
LOG.warn("\n\n\t** All repository folders have been created **\n\t You can remove the {} bean.\n\n", this.getClass().getName());
}
}
/**
* Do the migration.
*
* @throws Exception the exception
*/
void moveFilesToFolders() throws Exception {
long count = 0;
for (RepositoryFile repoFile : fileRepository.findAll()) {
if (repoFile.getFolder() == null) {
RepositoryFolder repoFolder = repositoryService.getFolder(Paths.get(repoFile.getPath()));
if (repoFile.getFolder() == null || repoFile.getFolder().getId().equals(repoFolder.getId())) {
LOG.warn("Upgrading {} to folder={}", repoFile.getPath(), repoFolder.getPath());
repoFile.setFolder(repoFolder);
fileRepository.save(repoFile);
count++;
}
}
}
if (count == 0) {
LOG.warn("\n\n\t** All repository files have been moved to proper folders **\n\t You can remove the {} bean.\n\n", this.getClass().getName());
}
}
/**
* Do the migration.
*
* @throws Exception the exception
*/
void migrateImageGalleries() throws Exception {
long count = 0;
for (ImageGallery imageGallery : imagegalleryRepository.findAll()) {
if (imageGallery.getFolder() == null) {
RepositoryFolder repoFolder = repositoryService.getFolder(Paths.get(imageGallery.getPath()));
if (imageGallery.getFolder() == null || imageGallery.getFolder().getId().equals(repoFolder.getId())) {
LOG.warn("Upgrading image gallery {} to folder={}", imageGallery.getPath(), repoFolder.getPath());
imageGallery.setFolder(repoFolder);
imagegalleryRepository.save(imageGallery);
count++;
}
}
}
if (count == 0) {
LOG.warn("\n\n\t** All image galleries have been moved to proper folders **\n\t You can remove the {} bean.\n\n", this.getClass().getName());
}
}
}
......@@ -20,7 +20,7 @@ package org.genesys.filerepository.service.impl;
/**
* Make sure filenames are okay.
*/
public class FilenameValidator {
public abstract class FilenameValidator {
/**
* Checks if the filename is acceptable.
......
......@@ -81,14 +81,8 @@ import com.querydsl.core.types.dsl.BooleanExpression;
/**
* The RepositoryServiceImpl implementation.
*/
/**
* @author Matija Obreza
*
*/
/**
* @author Matija Obreza
*
*/
@Service
@Transactional(readOnly = true)
......@@ -237,8 +231,8 @@ public class RepositoryServiceImpl implements RepositoryService, InitializingBea
repositoryFile.setOriginalFilename(originalFilename);
repositoryFile.setContentType(contentType);
if ((contentType == null) || (contentType.length() == 0)) {
throw new InvalidRepositoryFileDataException("Content type not privided and could not be detected");
if (contentType.length() == 0) {
throw new InvalidRepositoryFileDataException("Content type not provided and could not be detected");
}
repositoryFile = repositoryFilePersistence.save(repositoryFile);
......@@ -605,7 +599,7 @@ public class RepositoryServiceImpl implements RepositoryService, InitializingBea
@Override
public Page<RepositoryFolder> listFolders(Path root, Pageable page) throws InvalidRepositoryPathException {
PathValidator.checkValidPath(root);
if (root == null || "/".equals(root.normalize().toAbsolutePath().toString())) {
if ("/".equals(root.normalize().toAbsolutePath().toString())) {
return folderRepository.findAll(QRepositoryFolder.repositoryFolder.parent.isNull(), page);
} else {
RepositoryFolder parent = getFolder(root);
......@@ -905,7 +899,7 @@ public class RepositoryServiceImpl implements RepositoryService, InitializingBea
repositoryFile = (RepositoryFile) Hibernate.unproxy(repositoryFile);
}
LOG.info("Moving path={} name={} to {}", repositoryFile.getFolder(), repositoryFile.getFilename(), fullPath);
LOG.info("Moving name={} to {}", repositoryFile.getFilename(), fullPath);
final Path path = fullPath.normalize().toAbsolutePath();
PathValidator.checkValidPath(path.getParent().toString());
......
......@@ -22,6 +22,7 @@ import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.InvalidKeyException;
......@@ -69,7 +70,7 @@ import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
@Service("S3Storage")
public class S3StorageServiceImpl implements BytesStorageService, InitializingBean {
private static final Charset CHARSET_UTF8 = Charset.forName("UTF8");
private static final Charset CHARSET_UTF8 = StandardCharsets.UTF_8;
private static final String HTTP_AUTHORIZATION = "Authorization";
......
......@@ -69,8 +69,10 @@ public class ThumbnailGenerator1 implements ThumbnailGenerator {
th.size(width, height);
} else if (width != null) {
th.width(width);
th.height(width);
} else if (height != null) {
th.height(height);
th.width(height);
}
final ByteArrayOutputStream os = new ByteArrayOutputStream(imageBytes.length);
......
......@@ -18,12 +18,14 @@ package org.genesys.filerepository.service;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertThrows;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.UUID;
import java.util.stream.Stream;
import org.genesys.filerepository.InvalidRepositoryFileDataException;
import org.genesys.filerepository.InvalidRepositoryPathException;
......@@ -31,6 +33,8 @@ import org.genesys.filerepository.NoSuchRepositoryFileException;
import org.genesys.filerepository.model.RepositoryFile;
import org.junit.Before;
import org.junit.Test;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.transaction.annotation.Transactional;
......@@ -110,6 +114,34 @@ public class FileRepositoryUpdateTest extends RepositoryServiceTest {
FileRepositoryTestUtil.assertMetadataIsBlank(repoFile);
}
/**
* Load list of files by folder path.
* @throws InvalidRepositoryPathException
*/
@Test
public void listFilesByFolderPath() throws InvalidRepositoryPathException {
PageRequest page = PageRequest.of(0, 10);
Page<RepositoryFile> repoFiles = repositoryService.listFiles(Paths.get("/initial2/"), page);
assertThat(repoFiles.getTotalElements(), is(0L));
repoFiles = repositoryService.listFiles(initialPath, page);
assertThat("List should have one element", repoFiles.getTotalElements(), is(1L));
final RepositoryFile repoFile = repoFiles.getContent().get(0);
FileRepositoryTestUtil.checkFile(repoFile, initialPath, initialOriginalFilename, initialExtension, initialContentType);
FileRepositoryTestUtil.assertMetadataIsBlank(repoFile);
}
/**
* Streaming files test.
* @throws Exception
*/
@Test
public void streamFiles() throws Exception {
final Stream<RepositoryFile> repoFilesStream = repositoryService.streamFiles(initialPath, RepositoryFile.DEFAULT_SORT);
assertThat(repoFilesStream.anyMatch(f -> f.getUuid().equals(fileUuid)), is(true));
}
/**
* Change of originalFilename must update extension.
*
......@@ -124,6 +156,25 @@ public class FileRepositoryUpdateTest extends RepositoryServiceTest {
repositoryFile.setOriginalFilename(originalFilename);
repositoryFile = repositoryService.updateMetadata(repositoryFile);
assertThat("Extension was not updated", repositoryFile.getExtension(), equalTo(extension));
RepositoryFile notExistingFile = new RepositoryFile();
notExistingFile.setUuid(UUID.randomUUID());
notExistingFile.setVersion(1);
assertThrows(NoSuchRepositoryFileException.class, () -> repositoryService.updateMetadata(notExistingFile));
}
/**
* Move file to another folder and rename.
* @throws Exception
*/
@Test
public void moveAndRenameFile() throws Exception {
assertThrows(NullPointerException.class, () -> repositoryService.moveAndRenameFile(repositoryService.getFile(fileUuid), null));
RepositoryFile repositoryFile = repositoryService.getFile(fileUuid);
repositoryFile = repositoryService.moveAndRenameFile(repositoryFile, Paths.get("/moved/changed"));
assertThat( repositoryFile.getOriginalFilename(), equalTo("changed"));
assertThat(repositoryFile.getFolder().getName(), equalTo("moved"));
}
/**
......
......@@ -27,6 +27,8 @@ import java.util.List;
import java.util.Random;
import javax.persistence.EntityNotFoundException;
import org.genesys.filerepository.model.RepositoryFolder;
import org.springframework.transaction.annotation.Transactional;
import org.genesys.filerepository.InvalidRepositoryFileDataException;
......@@ -148,6 +150,44 @@ public class ImageGalleryTest extends RepositoryServiceTest {
assertThat("Must be null", loadedGallery, nullValue());
}
/**
* Load all galleries for paths.
* @throws InvalidRepositoryPathException
*/
@Test
public void loadImageGalleries() throws InvalidRepositoryPathException {
final ImageGallery imageGallery = imageGalleryService.createImageGallery(initialPath, DEFAULT_GALLERY_TITLE, DEFAULT_GALLERY_DESCRIPTION);
List<ImageGallery> imageGalleries = imageGalleryService.loadImageGalleries(List.of(initialPath));
assertThat(imageGalleries.size(), is(1));
ImageGallery loadedGallery = imageGalleries.get(0);
assertThat("Must not be null", loadedGallery, notNullValue());
imageGalleryService.removeGallery(imageGallery);
loadedGallery = imageGalleryService.loadImageGallery(initialPath);
assertThat("Must be null", loadedGallery, nullValue());
}
/**
* Get gallery by folder.
* @throws InvalidRepositoryPathException
*/
@Test
public void getImageGallery() throws InvalidRepositoryPathException {
imageGalleryService.createImageGallery(initialPath, DEFAULT_GALLERY_TITLE, DEFAULT_GALLERY_DESCRIPTION);
RepositoryFolder folder = fileRepoService.getFolder(initialPath);
assertThat("Must not be null", folder, notNullValue());
ImageGallery loadedImageGallery = imageGalleryService.getImageGallery(folder);
assertThat("Must not be null", loadedImageGallery, notNullValue());
imageGalleryService.removeGallery(loadedImageGallery);
loadedImageGallery = imageGalleryService.loadImageGallery(initialPath);
assertThat("Must be null", loadedImageGallery, nullValue());
}
/**
* Update gallery blah null.
*/
......
......@@ -51,10 +51,6 @@ public class MetadataTest extends RepositoryServiceTest {
private final ObjectMapper objectMapper;
/** The repository service. */
@Autowired
private RepositoryService repositoryService;
@Autowired
private BytesStorageService bytesStorageService;
......
......@@ -18,6 +18,7 @@ package org.genesys.filerepository.service;
import static org.hamcrest.Matchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertThrows;
import java.nio.file.Path;
import java.nio.file.Paths;
......@@ -28,6 +29,8 @@ import org.genesys.filerepository.InvalidRepositoryPathException;
import org.genesys.filerepository.NoSuchRepositoryFolderException;
import org.genesys.filerepository.model.RepositoryFolder;
import org.junit.Test;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.security.test.context.support.WithMockUser;
// TODO: Auto-generated Javadoc
......@@ -88,6 +91,37 @@ public class RepositoryFolderTest extends RepositoryServiceTest {
assertThat(folders, hasSize(4));
}
@Test
public void listFolders2() throws InvalidRepositoryPathException {
RepositoryFolder folder1 = repositoryService.ensureFolder(Paths.get("/bbbb/cccc"));
assertThat(folder1, notNullValue());
RepositoryFolder folder2 = repositoryService.ensureFolder(Paths.get("/bbbb/cccc2"));
assertThat(folder2, notNullValue());
Page<RepositoryFolder> folders = repositoryService.listFolders(Paths.get("/bbbb"), PageRequest.of(0, 5));
assertThat(folders.getTotalElements(), is(2L));
folders = repositoryService.listFolders(Paths.get("/"), PageRequest.of(0, 5));
assertThat(folders.getTotalElements(), is(1L));
assertThat(folders.getContent().get(0).getPath(), equalTo("/bbbb"));
}
@Test
public void ensureFolder() throws Exception {
RepositoryFolder folder1 = repositoryService.ensureFolder(Paths.get("/bbbb"));
assertThat(folder1, notNullValue());
RepositoryFolder folder2 = repositoryService.ensureFolder(Paths.get("/cccc"));
assertThat(folder2, notNullValue());
RepositoryFolder updatedFolder = repositoryService.ensureFolder(Paths.get("/bbbb"), folder2);
assertThat(updatedFolder.getId(), equalTo(folder1.getId()));
assertThat(updatedFolder.getPath(), equalTo(folder1.getPath()));
assertThat(updatedFolder.getParentOid(), nullValue());
assertThrows(RuntimeException.class, () -> repositoryService.ensureFolder(Paths.get("/bbbb/cccc"), folder1));
}
@Test
public void renamePath() throws InvalidRepositoryPathException {
Path path = Paths.get("/bbbb/cccc/dddd/eeee");
......@@ -183,6 +217,8 @@ public class RepositoryFolderTest extends RepositoryServiceTest {
assertThat(folderUpdated.getVersion(), equalTo(folder.getVersion() + 1));
assertThat(folderUpdated.getTitle(), equalTo(folder.getTitle()));
assertThat(folderUpdated.getDescription(), equalTo(folder.getDescription()));
assertThrows(NoSuchRepositoryFolderException.class, () -> repositoryService.updateFolder(folder));
}
@Test
......
......@@ -18,6 +18,7 @@ package org.genesys.filerepository.service;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertThrows;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
......@@ -58,6 +59,9 @@ public class RepositoryImageThumbnailsTest extends RepositoryServiceTest {
@Autowired
private BytesStorageService bytesStorageService;
@Autowired
private ThumbnailGenerator thumbnailGenerator;
/**
* Test names.
*/
......@@ -99,4 +103,33 @@ public class RepositoryImageThumbnailsTest extends RepositoryServiceTest {
fileRepoService.removeImage(repoImage1);
}
/**
* Test thumbnail generator.
* @throws IOException
*/
@Test
public void testCreateThumbnail() throws IOException {
final TestImage image1 = new TestImage("maize.jpg", "image/jpg");
try (InputStream is = new ByteArrayInputStream(image1.getImageBytes())) {
final BufferedImage imageData = ImageIO.read(is);
assertThat("Thumbnail width mismatch", imageData.getWidth(), equalTo(640));
assertThat("Thumbnail height mismatch", imageData.getHeight(), equalTo(427));
}
// create new thumbnail
assertThrows(NullPointerException.class, () -> thumbnailGenerator.createThumbnail(150, 150, null));
try (InputStream is = new ByteArrayInputStream(thumbnailGenerator.createThumbnail(150, null, image1.getImageBytes()))) {
final BufferedImage imageData = ImageIO.read(is);
assertThat("Thumbnail width mismatch", imageData.getWidth(), equalTo(150));
assertThat("Thumbnail height mismatch", imageData.getHeight(), equalTo(150));
}
try (InputStream is = new ByteArrayInputStream(thumbnailGenerator.createThumbnail(null, 100, image1.getImageBytes()))) {
final BufferedImage imageData = ImageIO.read(is);
assertThat("Thumbnail width mismatch", imageData.getWidth(), equalTo(100));
assertThat("Thumbnail height mismatch", imageData.getHeight(), equalTo(100));
}
}
}
/*
* Copyright 2021 Global Crop Diversity Trust
*
* 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.genesys.filerepository.util;