ddf.test.itests.platform.TestSolrCommands.java Source code

Java tutorial

Introduction

Here is the source code for ddf.test.itests.platform.TestSolrCommands.java

Source

/**
 * Copyright (c) Codice Foundation
 *
 * <p>This is free software: you can redistribute it and/or modify it under the terms of the GNU
 * Lesser General Public License as published by the Free Software Foundation, either version 3 of
 * the License, or any later version.
 *
 * <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details. A copy of the GNU Lesser General Public
 * License is distributed along with this program and can be found at
 * <http://www.gnu.org/licenses/lgpl.html>.
 */
package ddf.test.itests.platform;

import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.hasSize;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import com.google.common.base.Predicate;
import com.google.common.collect.Sets;
import java.io.File;
import java.io.FilenameFilter;
import java.nio.file.Paths;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.FileUtils;
import org.codice.ddf.itests.common.AbstractIntegrationTest;
import org.codice.ddf.test.common.LoggingUtils;
import org.codice.ddf.test.common.annotations.BeforeExam;
import org.junit.After;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
import org.ops4j.pax.exam.spi.reactors.PerSuite;

@RunWith(PaxExam.class)
@ExamReactorStrategy(PerSuite.class)
public class TestSolrCommands extends AbstractIntegrationTest {

    private static final String BACKUP_COMMAND = "solr:backup";

    private static final String DDF_HOME_PROPERTY = "ddf.home";

    private static final String BACKUP_SUCCESS_MESSAGE = "Backup of [catalog] complete";

    private static final String BACKUP_ERROR_MESSAGE_FORMAT = "Error backing up Solr core: [%s]";

    private static final String CATALOG_CORE_NAME = "catalog";

    @BeforeExam
    public void beforeExam() throws Exception {
        try {
            waitForSystemReady();
            basePort = getBasePort();
            getServiceManager().startFeature(true, getDefaultRequiredApps());
            getServiceManager().waitForAllBundles();
            getCatalogBundle().waitForCatalogProvider();
            getServiceManager().waitForHttpEndpoint(SERVICE_ROOT + "/catalog/query");

            configureRestForGuest();
            getSecurityPolicy().waitForGuestAuthReady(REST_PATH.getUrl() + "?_wadl");
        } catch (Exception e) {
            LoggingUtils.failWithThrowableStacktrace(e, "Failed in @BeforeExam: ");
        }
    }

    @After
    public void tearDown() {
        cleanUpBackups(CATALOG_CORE_NAME);
    }

    // TODO: Turn on this test once DDF-3340 is complete
    @Ignore
    @Test
    public void testSolrBackupCommand() {
        String output = console.runCommand(BACKUP_COMMAND);
        assertThat(output, containsString(BACKUP_SUCCESS_MESSAGE));
    }

    // TODO: Turn on this test once DDF-3340 is complete
    @Ignore
    @Test
    public void testSolrBackupBadCoreName() {
        String coreName = "blah";
        String command = BACKUP_COMMAND + " -c " + coreName;
        String output = console.runCommand(command);

        assertThat(output, containsString(String.format(BACKUP_ERROR_MESSAGE_FORMAT, coreName)));
    }

    // TODO: Turn on this test once DDF-3340 is complete
    @Ignore
    @Test
    public void testSolrBackupNumToKeep() throws InterruptedException {
        int numToKeep = 2;

        String command = BACKUP_COMMAND + " --numToKeep " + numToKeep;

        // Run this 3 times to make sure 2 backups are kept
        // On run 1, backup A is created.
        console.runCommand(command);
        Set<File> firstBackupDirSet = waitForBackupDirsToBeCreated(CATALOG_CORE_NAME, 1, 1);

        // On run 2, backup B is created (2 backups now: A and B).
        console.runCommand(command);
        Set<File> secondBackupDirSet = waitForBackupDirsToBeCreated(CATALOG_CORE_NAME, 2, 2);
        assertTrue("Unexpected backup directories found on pass 2.",
                secondBackupDirSet.containsAll(firstBackupDirSet));

        // On run 3, backup C is created (backup A is deleted and backups B and C remain).
        console.runCommand(command);
        // Wait for the 3rd backup to replace the 1st backup
        Set<File> thirdBackupDirSet = waitForFirstBackupDirToBeDeleted(CATALOG_CORE_NAME, firstBackupDirSet);

        assertThat("Wrong number of backup directories kept. Number of backups found in "
                + getSolrDataPath(CATALOG_CORE_NAME).getAbsolutePath() + " is : [" + thirdBackupDirSet.size()
                + "]; Expected: [2].", thirdBackupDirSet, hasSize(2));

        secondBackupDirSet.removeAll(firstBackupDirSet);
        assertTrue("Unexpected backup directories found on pass 3.",
                thirdBackupDirSet.containsAll(secondBackupDirSet));
    }

    private Set<File> waitFor(String coreName, Predicate<Set<File>> predicate) throws InterruptedException {
        final long timeout = TimeUnit.SECONDS.toMillis(10);
        int currentWaitTime = 0;

        Set<File> backupDirs = getBackupDirectories(coreName);

        while (predicate.apply(backupDirs) && (currentWaitTime < timeout)) {
            TimeUnit.MILLISECONDS.sleep(250);
            currentWaitTime += 250;
            backupDirs = getBackupDirectories(coreName);
        }

        if (currentWaitTime >= timeout) {
            fail("Timed out after " + timeout + " seconds waiting for correct number of backups in "
                    + getSolrDataPath(CATALOG_CORE_NAME).getAbsolutePath());
        }

        return backupDirs;
    }

    private Set<File> waitForFirstBackupDirToBeDeleted(String coreName, final Set<File> firstBackupDirSet)
            throws InterruptedException {
        return waitFor(coreName, new Predicate<Set<File>>() {
            @Override
            public boolean apply(Set<File> backupDirs) {
                return backupDirs.containsAll(firstBackupDirSet) && (backupDirs.size() != 2);
            }
        });
    }

    private Set<File> waitForBackupDirsToBeCreated(String coreName, final int numberOfDirs, int pass)
            throws InterruptedException {
        Set<File> backupDirs = waitFor(coreName, new Predicate<Set<File>>() {
            @Override
            public boolean apply(Set<File> backupDirs) {
                return backupDirs.size() < numberOfDirs;
            }
        });

        assertThat("Wrong number of backup directories created on pass: [" + pass + "].  Found: " + backupDirs
                + ". Expected: [" + numberOfDirs + "].", backupDirs, hasSize(numberOfDirs));
        return backupDirs;
    }

    private Set<File> getBackupDirectories(String coreName) {
        File solrDir = getSolrDataPath(coreName);

        File[] backupDirs;

        backupDirs = solrDir.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                // Only match on snapshot.<timestamp> directories, filter out snapshot_metadata
                return name.startsWith("snapshot.");
            }
        });

        return Sets.newHashSet(backupDirs);
    }

    private File getSolrDataPath(String coreName) {
        String home = System.getProperty(DDF_HOME_PROPERTY);
        File dir = Paths.get(home + "/data/solr/" + coreName + "/data").toFile();
        return dir;
    }

    private void cleanUpBackups(String coreName) {
        Set<File> backupDirs = getBackupDirectories(coreName);
        for (File backupDir : backupDirs) {
            FileUtils.deleteQuietly(backupDir);
        }
    }
}