package de.is24.infrastructure.gridfs.http.gridfs; import com.mongodb.BasicDBObject; import com.mongodb.DBObject; import com.mongodb.gridfs.GridFSDBFile; import com.mongodb.gridfs.GridFSFile; import de.is24.infrastructure.gridfs.http.category.LocalExecutionOnly; import de.is24.infrastructure.gridfs.http.mongo.IntegrationTestContext; import de.is24.infrastructure.gridfs.http.storage.FileDescriptor; import de.is24.infrastructure.gridfs.http.storage.FileStorageItem; import org.apache.commons.lang.time.DateUtils; import org.junit.ClassRule; import org.junit.Test; import org.junit.experimental.categories.Category; import java.io.IOException; import java.util.Date; import java.util.List; import static com.mongodb.gridfs.GridFSUtil.mergeMetaData; import static de.is24.infrastructure.gridfs.http.gridfs.StorageServiceIT.TESTING_ARCH; import static de.is24.infrastructure.gridfs.http.mongo.DatabaseStructure.GRIDFS_FILES_COLLECTION; import static de.is24.infrastructure.gridfs.http.mongo.DatabaseStructure.MARKED_AS_DELETED_KEY; import static de.is24.infrastructure.gridfs.http.mongo.DatabaseStructure.REPO_KEY; import static de.is24.infrastructure.gridfs.http.utils.RepositoryUtils.simpleInputStream; import static de.is24.infrastructure.gridfs.http.utils.RepositoryUtils.uniqueRepoName; import static org.apache.commons.lang.time.DateUtils.addDays; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; import static org.springframework.data.mongodb.core.query.Criteria.where; import static org.springframework.data.mongodb.core.query.Query.query; import static org.springframework.data.mongodb.core.query.Update.update; import static org.springframework.data.mongodb.gridfs.GridFsCriteria.whereMetaData; @Category(LocalExecutionOnly.class) public class GridFsFileStorageServiceIT { @ClassRule public static IntegrationTestContext context = new IntegrationTestContext(); @Test public void deleteFilesMarkedAsDeleted() throws Exception { final Date now = new Date(); final String nothingToDeleteRepo = context.storageTestUtils().givenFullRepository(); givenTowOfThreeFilesToBeDeleted(now); context.fileStorageService().removeFilesMarkedAsDeletedBefore(now); final List<GridFSDBFile> fileList = context.gridFsTemplate() .find(query(whereMetaData(MARKED_AS_DELETED_KEY).ne(null))); assertThat(fileList.size(), is(1)); final List<GridFSDBFile> filesInNothingToDeleteRepo = context.gridFsTemplate() .find(query(whereMetaData(REPO_KEY).is(nothingToDeleteRepo))); assertThat(filesInNothingToDeleteRepo.size(), is(4)); } @Test public void metaDataForDeletionIsSetOnlyOnce() throws Exception { final String repoName = context.storageTestUtils().givenFullRepository(); final Date yesterday = DateUtils.addDays(new Date(), -1); final String file = "a_file_to_be_deleted"; FileDescriptor descriptor = new FileDescriptor(repoName, TESTING_ARCH, file); givenFileToBeDeleted(descriptor, yesterday); context.fileStorageService().markForDeletionByPath(descriptor.getPath()); final FileStorageItem storageItem = context.fileStorageService().findBy(descriptor); assertThat(storageItem.getDateOfMarkAsDeleted(), is(equalTo(yesterday))); } @Test public void getCorruptFiles() throws Exception { setFilenameToNull(context.storageTestUtils().givenFullRepository()); setMetadataToNull(context.storageTestUtils().givenFullRepository()); List<FileStorageItem> corruptFiles = context.fileStorageService().getCorruptFiles(); assertThat(corruptFiles.size(), greaterThanOrEqualTo(2)); assertAllFilesAreCorrupt(corruptFiles); } @Test public void deleteCorruptFiles() throws Exception { setFilenameToNull(context.storageTestUtils().givenFullRepository()); setMetadataToNull(context.storageTestUtils().givenFullRepository()); context.fileStorageService().deleteCorruptFiles(); assertThat(context.fileStorageService().getCorruptFiles().size(), is(0)); } @Test public void ensureIndex() throws Exception { new GridFsFileStorageService(context.gridFs(), context.gridFsTemplate(), context.mongoTemplate()); new GridFsFileStorageService(context.gridFs(), context.gridFsTemplate(), context.mongoTemplate()); List<DBObject> indexInfos = context.mongoTemplate().getCollection(GRIDFS_FILES_COLLECTION).getIndexInfo(); assertThat(indexInfos.size(), is(6)); } @Test public void overwriteEvenMultipleFiles() throws Exception { String filename = uniqueRepoName() + "/repodata/repomd.xml"; context.gridFs().createFile(simpleInputStream(), filename).save(); context.gridFs().createFile(simpleInputStream(), filename).save(); context.gridFs().createFile(simpleInputStream(), filename).save(); context.fileStorageService().storeFile(simpleInputStream(), new FileDescriptor(filename), true); assertThat(context.fileStorageService().findByPrefix(filename).size(), is(1)); } private void assertAllFilesAreCorrupt(List<FileStorageItem> corruptFiles) { for (FileStorageItem file : corruptFiles) { if (file.getFilename() != null && file.getRepo() != null) throw new AssertionError("Found item that is not corrupt."); } } private void setMetadataToNull(String reponame) { GridFsFileStorageItem fileStorageItem = (GridFsFileStorageItem) context.fileStorageService().getAllRpms(reponame).get(0); context.mongoTemplate().updateFirst(query(where("_id").is(fileStorageItem.getId())), update("metadata", null), GRIDFS_FILES_COLLECTION); assertThat(context.fileStorageService().findById(fileStorageItem.getId()).getRepo(), nullValue()); } private void setFilenameToNull(String reponame) { GridFsFileStorageItem fileStorageItem = (GridFsFileStorageItem) context.fileStorageService().getAllRpms(reponame).get(0); context.mongoTemplate().updateFirst(query(where("_id").is(fileStorageItem.getId())), update("filename", null), GRIDFS_FILES_COLLECTION); assertThat(context.fileStorageService().findById(fileStorageItem.getId()).getFilename(), nullValue()); } private void givenTowOfThreeFilesToBeDeleted(final Date now) throws IOException { final String repoToDeleteIn = uniqueRepoName(); final Date past = addDays(now, -1); givenFileToBeDeleted(new FileDescriptor(repoToDeleteIn, TESTING_ARCH, "toBeDeletedPast1"), past); givenFileToBeDeleted(new FileDescriptor(repoToDeleteIn, TESTING_ARCH, "toBeDeletedPast2"), past); givenFileToBeDeleted(new FileDescriptor(repoToDeleteIn, TESTING_ARCH, "toBeDeletedFuture"), addDays(now, 1)); } private GridFSFile givenFileToBeDeleted(FileDescriptor descriptor, final Date time) throws IOException { final GridFSDBFile toBeDeleted = ((GridFsFileStorageItem) context.storageTestUtils().givenFileWithDescriptor(descriptor)).getDbFile(); mergeMetaData(toBeDeleted, new BasicDBObject(MARKED_AS_DELETED_KEY, time)); toBeDeleted.save(); return toBeDeleted; } }