org.roda.core.plugins.ReplicationPluginTest.java Source code

Java tutorial

Introduction

Here is the source code for org.roda.core.plugins.ReplicationPluginTest.java

Source

/**
 * The contents of this file are subject to the license and copyright
 * detailed in the LICENSE file at the root of the source
 * tree and available online at
 *
 * https://github.com/keeps/roda
 */
package org.roda.core.plugins;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.solr.client.solrj.SolrServerException;
import org.roda.core.RodaCoreFactory;
import org.roda.core.TestsHelper;
import org.roda.core.common.iterables.CloseableIterable;
import org.roda.core.common.monitor.TransferredResourcesScanner;
import org.roda.core.data.common.RodaConstants;
import org.roda.core.data.common.RodaConstants.SolrType;
import org.roda.core.data.exceptions.AlreadyExistsException;
import org.roda.core.data.exceptions.AuthorizationDeniedException;
import org.roda.core.data.exceptions.GenericException;
import org.roda.core.data.exceptions.InvalidParameterException;
import org.roda.core.data.exceptions.JobAlreadyStartedException;
import org.roda.core.data.exceptions.NotFoundException;
import org.roda.core.data.exceptions.RequestNotValidException;
import org.roda.core.data.v2.common.OptionalWithCause;
import org.roda.core.data.v2.index.select.SelectedItemsAll;
import org.roda.core.data.v2.index.select.SelectedItemsList;
import org.roda.core.data.v2.ip.AIP;
import org.roda.core.data.v2.ip.File;
import org.roda.core.data.v2.ip.Representation;
import org.roda.core.data.v2.ip.TransferredResource;
import org.roda.core.data.v2.jobs.Job;
import org.roda.core.data.v2.jobs.PluginType;
import org.roda.core.index.IndexService;
import org.roda.core.model.ModelService;
import org.roda.core.model.utils.ModelUtils;
import org.roda.core.plugins.orchestrate.JobsHelper;
import org.roda.core.plugins.plugins.base.ReplicationPlugin;
import org.roda.core.plugins.plugins.ingest.TransferredResourceToAIPPlugin;
import org.roda.core.storage.Binary;
import org.roda.core.storage.StorageService;
import org.roda.core.storage.fs.FSUtils;
import org.roda.core.util.CommandException;
import org.roda.core.util.CommandUtility;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
import org.testng.AssertJUnit;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

@Test(groups = { RodaConstants.TEST_GROUP_ALL, RodaConstants.TEST_GROUP_TRAVIS })
public class ReplicationPluginTest {

    private static final Logger LOGGER = LoggerFactory.getLogger(ReplicationPluginTest.class);
    private static final int GENERATED_FILE_SIZE = 100;
    private static final int NUMBER_OF_AIPS = 1000;

    private static Path basePath;
    private static Path testPath;

    private static StorageService storage;
    private static ModelService model;
    private static IndexService index;

    private static String parentResourceUUID = null;
    private static int resourceCounter = 0;

    @BeforeClass
    public void setUp() throws Exception {
        basePath = TestsHelper.createBaseTempDir(getClass(), true,
                PosixFilePermissions.asFileAttribute(new HashSet<>(Arrays.asList(PosixFilePermission.OWNER_READ,
                        PosixFilePermission.OWNER_WRITE, PosixFilePermission.OWNER_EXECUTE,
                        PosixFilePermission.OTHERS_READ, PosixFilePermission.OTHERS_EXECUTE))));

        boolean deploySolr = true;
        boolean deployLdap = true;
        boolean deployFolderMonitor = true;
        boolean deployOrchestrator = true;
        boolean deployPluginManager = true;
        boolean deployDefaultResources = false;

        // embedded Apache Solr
        RodaCoreFactory.instantiateTest(deploySolr, deployLdap, deployFolderMonitor, deployOrchestrator,
                deployPluginManager, deployDefaultResources, SolrType.EMBEDDED);

        // // HTTP Apache Solr
        // RodaCoreFactory.instantiateTest(deploySolr, deployLdap,
        // deployFolderMonitor, deployOrchestrator,
        // deployPluginManager, deployDefaultResources, SolrType.HTTP);

        // // Cloud Apache Solr
        // RodaCoreFactory.instantiateTest(deploySolr, deployLdap,
        // deployFolderMonitor, deployOrchestrator,
        // deployPluginManager, deployDefaultResources, SolrType.HTTP_CLOUD);

        model = RodaCoreFactory.getModelService();
        index = RodaCoreFactory.getIndexService();
        storage = RodaCoreFactory.getStorageService();

        testPath = TestsHelper.createBaseTempDir(getClass(), true,
                PosixFilePermissions.asFileAttribute(new HashSet<>(Arrays.asList(PosixFilePermission.OWNER_READ,
                        PosixFilePermission.OWNER_WRITE, PosixFilePermission.OWNER_EXECUTE,
                        PosixFilePermission.OTHERS_READ, PosixFilePermission.OTHERS_EXECUTE))));

        Files.createDirectories(
                testPath.resolve(RodaConstants.CORE_STORAGE_FOLDER).resolve(RodaConstants.STORAGE_CONTAINER_AIP));
        Files.createDirectories(testPath.resolve(RodaConstants.CORE_STORAGE_FOLDER)
                .resolve(RodaConstants.STORAGE_CONTAINER_PRESERVATION)
                .resolve(RodaConstants.STORAGE_CONTAINER_PRESERVATION_AGENTS));

        LOGGER.info("Running {} tests under storage {}", getClass().getSimpleName(), basePath);
    }

    @AfterClass
    public void tearDown() throws Exception {
        RodaCoreFactory.shutdown();
        FSUtils.deletePath(basePath);
        FSUtils.deletePath(testPath);
    }

    private ByteArrayInputStream generateContentData() {
        return new ByteArrayInputStream(RandomStringUtils.randomAscii(GENERATED_FILE_SIZE).getBytes());
    }

    private String createCorpora() throws InterruptedException, IOException, NotFoundException, GenericException,
            RequestNotValidException, AlreadyExistsException {
        TransferredResourcesScanner f = RodaCoreFactory.getTransferredResourcesScanner();

        String parentUUID = f.createFolder(null, "test").getUUID();
        index.commit(TransferredResource.class);

        index.retrieve(TransferredResource.class, parentUUID, new ArrayList<>());
        return parentUUID;
    }

    private TransferredResource createCorpora(String parentUUID, int i) throws InterruptedException, IOException,
            NotFoundException, GenericException, RequestNotValidException, AlreadyExistsException {
        TransferredResourcesScanner f = RodaCoreFactory.getTransferredResourcesScanner();

        String test1UUID = f.createFolder(parentUUID, "test" + i).getUUID();
        f.createFile(test1UUID, "test" + i + ".txt", generateContentData());
        index.commit(TransferredResource.class);

        return index.retrieve(TransferredResource.class, test1UUID, new ArrayList<>());
    }

    private List<String> ingestCorpora() throws RequestNotValidException, NotFoundException, GenericException,
            AlreadyExistsException, AuthorizationDeniedException, InvalidParameterException, InterruptedException,
            IOException, SolrServerException {

        if (parentResourceUUID == null) {
            parentResourceUUID = createCorpora();
        }

        List<String> resourceUUIDs = new ArrayList<>();

        for (int i = 0; i < NUMBER_OF_AIPS / 2; i++) {
            TransferredResource transferredResource = createCorpora(parentResourceUUID, resourceCounter);
            AssertJUnit.assertNotNull(transferredResource);
            resourceUUIDs.add(transferredResource.getUUID());
            resourceCounter++;
        }

        Job job = TestsHelper.executeJob(TransferredResourceToAIPPlugin.class, new HashMap<>(),
                PluginType.SIP_TO_AIP, SelectedItemsList.create(TransferredResource.class, resourceUUIDs));

        index.commitAIPs();
        return TestsHelper.getJobReports(index, job).stream().map(r -> r.getOutcomeObjectId())
                .collect(Collectors.toList());
    }

    @Test
    private void testRsyncViaListOfIds() throws RequestNotValidException, NotFoundException, GenericException,
            AlreadyExistsException, AuthorizationDeniedException, InvalidParameterException, InterruptedException,
            IOException, SolrServerException, JobAlreadyStartedException, CommandException {
        // increase number of job workers
        int originalNumberOfJobWorkers = JobsHelper.getNumberOfJobsWorkers();
        JobsHelper.setNumberOfJobsWorkers(originalNumberOfJobWorkers * 2);
        // increase sync job execution timeout in seconds
        JobsHelper.setSyncTimeout(1200);

        LOGGER.info("Ingesting first pack of corpora...");
        List<String> aips = ingestCorpora();
        LOGGER.info("Rsyncing first pack of corpora...");
        executeJobWithReplicationPlugin(aips);

        LOGGER.info("Ingesting second pack of corpora...");
        List<String> newAips = ingestCorpora();
        LOGGER.info("Rsyncing second pack of corpora...");
        executeJobWithReplicationPlugin(newAips);

        LOGGER.info("Testing if destination has the number of AIPs that was supposed");
        Assert.assertEquals(FSUtils.countPath(
                testPath.resolve(RodaConstants.CORE_STORAGE_FOLDER).resolve(RodaConstants.STORAGE_CONTAINER_AIP))
                .intValue(), NUMBER_OF_AIPS);

        AIP aip1 = model.retrieveAIP(aips.get(0));
        AIP aip2 = model.retrieveAIP(aips.get(1));
        Binary binary = null;

        Representation rep1 = aip1.getRepresentations().get(0);
        CloseableIterable<OptionalWithCause<File>> listFilesUnder1 = model.listFilesUnder(aip1.getId(),
                rep1.getId(), false);
        Iterator<OptionalWithCause<File>> iterator1 = listFilesUnder1.iterator();
        while (iterator1.hasNext()) {
            OptionalWithCause<File> next = iterator1.next();
            File file = next.get();
            binary = storage.getBinary(ModelUtils.getFileStoragePath(file.getAipId(), file.getRepresentationId(),
                    file.getPath(), file.getId()));
        }

        Representation rep2 = aip2.getRepresentations().get(0);
        CloseableIterable<OptionalWithCause<File>> listFilesUnder2 = model.listFilesUnder(aip2.getId(),
                rep2.getId(), false);
        Iterator<OptionalWithCause<File>> iterator2 = listFilesUnder2.iterator();
        while (iterator2.hasNext()) {
            OptionalWithCause<File> next = iterator2.next();
            File file = next.get();
            if (binary != null) {
                model.updateFile(file.getAipId(), file.getRepresentationId(), file.getPath(), file.getId(),
                        binary.getContent(), true, true);
            }
        }

        executeJobWithReplicationPlugin(Arrays.asList(aip2.getId()));

        List<String> diffCommand = new ArrayList<>();
        diffCommand.add("diff");
        diffCommand.add("-rq");
        diffCommand.add(RodaCoreFactory.getDataPath().resolve(RodaConstants.CORE_STORAGE_FOLDER)
                .resolve(RodaConstants.STORAGE_CONTAINER_AIP).toString());
        diffCommand.add(testPath.resolve(RodaConstants.CORE_STORAGE_FOLDER)
                .resolve(RodaConstants.STORAGE_CONTAINER_AIP).toString());
        LOGGER.info("Executing diff to compare two folders: {}", diffCommand);
        CommandUtility.execute(diffCommand);
    }

    @Test(enabled = false)
    private void testRsyncViaFilter() throws RequestNotValidException, NotFoundException, GenericException,
            AlreadyExistsException, AuthorizationDeniedException, InvalidParameterException, InterruptedException,
            IOException, SolrServerException, JobAlreadyStartedException, CommandException {
        // increase sync job execution timeout in seconds
        JobsHelper.setSyncTimeout(1200);
        JobsHelper.setBlockSize(100);

        LOGGER.info("Ingesting first pack of corpora...");
        ingestCorpora();
        LOGGER.info("Ingesting second pack of corpora...");
        ingestCorpora();
        LOGGER.info("Rsyncing corpora via filter...");
        executeJobWithReplicationPlugin();

        LOGGER.info("Testing if destination has the number of AIPs that was supposed");
        Assert.assertEquals(FSUtils.countPath(
                testPath.resolve(RodaConstants.CORE_STORAGE_FOLDER).resolve(RodaConstants.STORAGE_CONTAINER_AIP))
                .intValue(), NUMBER_OF_AIPS);

        List<String> diffCommand = new ArrayList<>();
        diffCommand.add("diff");
        diffCommand.add("-rq");
        diffCommand.add(RodaCoreFactory.getDataPath().resolve(RodaConstants.CORE_STORAGE_FOLDER)
                .resolve(RodaConstants.STORAGE_CONTAINER_AIP).toString());
        diffCommand.add(testPath.resolve(RodaConstants.CORE_STORAGE_FOLDER)
                .resolve(RodaConstants.STORAGE_CONTAINER_AIP).toString());
        LOGGER.info("Executing diff to compare two folders: {}", diffCommand);
        CommandUtility.execute(diffCommand);
    }

    private void executeJobWithReplicationPlugin(List<String> aipIds)
            throws CommandException, IOException, JobAlreadyStartedException, GenericException,
            RequestNotValidException, NotFoundException, AuthorizationDeniedException {

        String targetUser = RodaCoreFactory.getRodaConfigurationAsString("core", "aip_rsync", "target");
        RodaCoreFactory.getRodaConfiguration().setProperty("core.aip_rsync.target", testPath.toString() + "/");

        Job job = TestsHelper.executeJob(ReplicationPlugin.class, new HashMap<>(), PluginType.MISC,
                SelectedItemsList.create(AIP.class, aipIds));

        TestsHelper.getJobReports(index, job, true);

        RodaCoreFactory.getRodaConfiguration().setProperty("core.aip_rsync.target", targetUser);
    }

    private void executeJobWithReplicationPlugin() throws CommandException, IOException, JobAlreadyStartedException,
            GenericException, RequestNotValidException, NotFoundException, AuthorizationDeniedException {

        String targetUser = RodaCoreFactory.getRodaConfigurationAsString("core", "aip_rsync", "target");
        RodaCoreFactory.getRodaConfiguration().setProperty("core.aip_rsync.target", testPath.toString());

        TestsHelper.executeJob(ReplicationPlugin.class, PluginType.MISC, SelectedItemsAll.create(AIP.class));
        RodaCoreFactory.getRodaConfiguration().setProperty("core.aip_rsync.target", targetUser);
    }

}