/**
* 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 org.codice.ddf.migration.util;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.doThrow;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.verifyStatic;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Properties;
import org.apache.commons.io.FileUtils;
import org.codice.ddf.migration.MigrationException;
import org.codice.ddf.migration.MigrationWarning;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.rule.PowerMockRule;
@PrepareForTest({MigratableUtil.class, FileUtils.class})
public class MigratableUtilTest {
private static final Path DDF_BASE_DIR = Paths.get("ddf");
public static final String CONFIG_FILE_NAME = "file.config";
private static final Path VALID_SOURCE_PATH = Paths.get("etc");
private static final Path VALID_SOURCE_FILE = Paths.get(VALID_SOURCE_PATH.toString(),
CONFIG_FILE_NAME);
private static final Path ABSOLUTE_SOURCE_PATH = Paths.get(System.getProperty("java.io.tmpdir"));
private static final Path ABSOLUTE_SOURCE_FILE = Paths.get(ABSOLUTE_SOURCE_PATH.toString(),
CONFIG_FILE_NAME);
private static final Path OUTSIDE_DDF_HOME_SOURCE_PATH = Paths.get("..", "outside");
private static final Path OUTSIDE_DDF_HOME_SOURCE_FILE =
Paths.get(OUTSIDE_DDF_HOME_SOURCE_PATH.toString(), CONFIG_FILE_NAME);
private static final Path EXPORT_DIR = Paths.get("etc", "exported");
private static final Path VALID_DESTINATION_PATH = EXPORT_DIR;
private static final String DDF_HOME_PROPERTY_NAME = "ddf.home";
private static final String SOURCE_PATH_PROPERTY_NAME = "source";
private static final Path JAVA_PROPERTIES_FILE = Paths.get("etc", "java.properties");
@Rule
public PowerMockRule rule = new PowerMockRule();
@Rule
public TemporaryFolder tempDir = new TemporaryFolder();
private Path ddfHome;
private Collection<MigrationWarning> warnings;
@Before
public void setup() throws Exception {
mockStatic(FileUtils.class);
mockStatic(Files.class);
tempDir.newFolder(DDF_BASE_DIR.toString());
ddfHome = Paths.get(tempDir.getRoot()
.getAbsolutePath(), DDF_BASE_DIR.toString())
.toRealPath();
warnings = new ArrayList<>();
System.setProperty(DDF_HOME_PROPERTY_NAME, ddfHome.toString());
System.setProperty(SOURCE_PATH_PROPERTY_NAME, VALID_SOURCE_FILE.toString());
createTempPropertiesFiles();
}
@Test(expected = MigrationException.class)
public void constructorWithDdfHomeNotSet() {
System.clearProperty(DDF_HOME_PROPERTY_NAME);
new MigratableUtil();
}
@Test(expected = MigrationException.class)
public void constructorWithDdfHomeEmpty() {
System.setProperty(DDF_HOME_PROPERTY_NAME, "");
new MigratableUtil();
}
@Test
public void copyFile() throws IOException {
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFile(VALID_SOURCE_FILE, VALID_DESTINATION_PATH, warnings);
assertThat(warnings, is(empty()));
verifyStatic();
FileUtils.copyFile(VALID_SOURCE_FILE.toFile(),
VALID_DESTINATION_PATH.resolve(VALID_SOURCE_FILE)
.toFile());
}
@Test(expected = IllegalArgumentException.class)
public void copyFileNullSource() {
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFile(null, VALID_DESTINATION_PATH, warnings);
}
@Test(expected = IllegalArgumentException.class)
public void copyFileNullExportDirectory() {
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFile(VALID_SOURCE_FILE, null, warnings);
}
@Test(expected = IllegalArgumentException.class)
public void copyFileNullWarningsCollection() {
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFile(VALID_SOURCE_FILE, VALID_DESTINATION_PATH, null);
}
@Test
public void copyFileSourceIsAbsolutePath() throws IOException {
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFile(ABSOLUTE_SOURCE_FILE, VALID_DESTINATION_PATH, warnings);
assertWarnings("is absolute");
}
@Test
public void copyFileSourceHasSymbolicLink() throws IOException {
when(Files.isSymbolicLink(VALID_SOURCE_FILE)).thenReturn(true);
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFile(VALID_SOURCE_FILE, VALID_DESTINATION_PATH, warnings);
assertWarnings("contains a symbolic link");
}
@Test
public void copyFileSourceNotUnderDdfHome() throws IOException {
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFile(OUTSIDE_DDF_HOME_SOURCE_FILE, VALID_DESTINATION_PATH, warnings);
assertWarnings(String.format("is outside [%s]", ddfHome));
}
@Test(expected = MigrationException.class)
public void copyFileFails() throws IOException {
doThrow(new IOException()).when(FileUtils.class);
FileUtils.copyFile(any(File.class), any(File.class));
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFile(VALID_SOURCE_FILE, VALID_DESTINATION_PATH, warnings);
}
@Test
public void copyFileSourceOutsideDdfHomeDoesNotExist() throws IOException {
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFile(OUTSIDE_DDF_HOME_SOURCE_PATH.resolve("invalid.properties"),
VALID_DESTINATION_PATH,
warnings);
assertWarnings(String.format("does not exist or cannot be read", ddfHome));
}
@Test
public void copyDirectory() throws IOException {
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyDirectory(VALID_SOURCE_PATH, VALID_DESTINATION_PATH, warnings);
assertThat(warnings, is(empty()));
verifyStatic();
FileUtils.copyDirectory(VALID_SOURCE_PATH.toFile(),
VALID_DESTINATION_PATH.resolve(VALID_SOURCE_PATH)
.toFile());
}
@Test(expected = IllegalArgumentException.class)
public void copyDirectoryNullSource() {
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyDirectory(null, VALID_DESTINATION_PATH, warnings);
}
@Test(expected = IllegalArgumentException.class)
public void copyDirectoryNullExportDirectory() {
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyDirectory(VALID_SOURCE_PATH, null, warnings);
}
@Test(expected = IllegalArgumentException.class)
public void copyDirectoryNullWarningsCollection() {
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyDirectory(VALID_SOURCE_PATH, VALID_DESTINATION_PATH, null);
}
@Test
public void copyDirectorySourceIsAbsolutePath() throws IOException {
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyDirectory(ABSOLUTE_SOURCE_PATH, VALID_DESTINATION_PATH, warnings);
assertWarnings("is absolute");
}
@Test
public void copyDirectorySourceHasSymbolicLink() throws IOException {
when(Files.isSymbolicLink(VALID_SOURCE_PATH)).thenReturn(true);
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyDirectory(VALID_SOURCE_PATH, VALID_DESTINATION_PATH, warnings);
assertWarnings("contains a symbolic link");
}
@Test
public void copyDirectorySourceNotUnderDdfHome() throws IOException {
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyDirectory(OUTSIDE_DDF_HOME_SOURCE_PATH,
VALID_DESTINATION_PATH,
warnings);
assertWarnings(String.format("is outside [%s]", ddfHome));
}
@Test(expected = MigrationException.class)
public void copyDirectoryFails() throws IOException {
doThrow(new IOException()).when(FileUtils.class);
FileUtils.copyDirectory(any(File.class), any(File.class));
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyDirectory(VALID_SOURCE_PATH, VALID_DESTINATION_PATH, warnings);
}
@Test
public void copyDirectorySourceOutsideDdfHomeDoesNotExist() throws IOException {
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyDirectory(OUTSIDE_DDF_HOME_SOURCE_PATH.resolve("invalid"),
VALID_DESTINATION_PATH,
warnings);
assertWarnings("does not exist or cannot be read");
}
@Test
public void copyFileFromSystemPropertyValue() throws IOException {
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFileFromSystemPropertyValue(SOURCE_PATH_PROPERTY_NAME,
VALID_DESTINATION_PATH,
warnings);
assertThat(warnings, is(empty()));
verifyStatic();
FileUtils.copyFile(VALID_SOURCE_FILE.toFile(),
VALID_DESTINATION_PATH.resolve(VALID_SOURCE_FILE)
.toFile());
}
@Test(expected = IllegalArgumentException.class)
public void copyFileFromSystemPropertyWithNullValue() {
System.clearProperty(SOURCE_PATH_PROPERTY_NAME);
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFileFromSystemPropertyValue(SOURCE_PATH_PROPERTY_NAME,
VALID_DESTINATION_PATH,
warnings);
}
@Test(expected = IllegalArgumentException.class)
public void copyFileFromSystemPropertyWithEmptyValue() {
System.setProperty(SOURCE_PATH_PROPERTY_NAME, "");
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFileFromSystemPropertyValue(SOURCE_PATH_PROPERTY_NAME,
VALID_DESTINATION_PATH,
warnings);
}
@Test(expected = IllegalArgumentException.class)
public void copyFileFromSystemPropertyValueNullExportDirectory() {
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFileFromSystemPropertyValue(SOURCE_PATH_PROPERTY_NAME, null, warnings);
}
@Test(expected = IllegalArgumentException.class)
public void copyFileFromSystemPropertyValueNullWarningsCollection() {
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFileFromSystemPropertyValue(SOURCE_PATH_PROPERTY_NAME,
VALID_DESTINATION_PATH,
null);
}
@Test
public void copyFileFromSystemPropertyValueSourceIsAbsolutePath() throws IOException {
System.setProperty(SOURCE_PATH_PROPERTY_NAME, ABSOLUTE_SOURCE_FILE.toString());
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFileFromSystemPropertyValue(SOURCE_PATH_PROPERTY_NAME,
VALID_DESTINATION_PATH,
warnings);
assertWarnings("is absolute");
}
@Test
public void copyFileFromSystemPropertyValueSourceHasSymbolicLink() throws IOException {
when(Files.isSymbolicLink(VALID_SOURCE_FILE)).thenReturn(true);
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFileFromSystemPropertyValue(SOURCE_PATH_PROPERTY_NAME,
VALID_DESTINATION_PATH,
warnings);
assertWarnings("contains a symbolic link");
}
@Test
public void copyFileFromSystemPropertyValueSourceNotUnderDdfHome() throws IOException {
System.setProperty(SOURCE_PATH_PROPERTY_NAME, OUTSIDE_DDF_HOME_SOURCE_FILE.toString());
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFileFromSystemPropertyValue(SOURCE_PATH_PROPERTY_NAME,
VALID_DESTINATION_PATH,
warnings);
assertWarnings(String.format("is outside [%s]", ddfHome));
}
@Test(expected = MigrationException.class)
public void copyFileFromSystemPropertyValueFails() throws IOException {
doThrow(new IOException()).when(FileUtils.class);
FileUtils.copyFile(any(File.class), any(File.class));
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFileFromSystemPropertyValue(SOURCE_PATH_PROPERTY_NAME,
VALID_DESTINATION_PATH,
warnings);
}
@Test
public void copyFileFromSystemPropertyValueSourceOutsideDdfHomeDoesNotExist() {
System.setProperty(SOURCE_PATH_PROPERTY_NAME,
OUTSIDE_DDF_HOME_SOURCE_PATH.resolve("invalid.properties")
.toString());
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFileFromSystemPropertyValue(SOURCE_PATH_PROPERTY_NAME,
VALID_DESTINATION_PATH,
warnings);
}
@Test
public void copyFileFromJavaProperty() throws IOException {
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFileFromJavaPropertyValue(JAVA_PROPERTIES_FILE,
SOURCE_PATH_PROPERTY_NAME,
VALID_DESTINATION_PATH,
warnings);
assertThat(warnings, is(empty()));
verifyStatic();
FileUtils.copyFile(VALID_SOURCE_FILE.toFile(),
VALID_DESTINATION_PATH.resolve(VALID_SOURCE_FILE)
.toFile());
}
@Test(expected = MigrationException.class)
public void copyFileFromJavaPropertyThatCannotBeRead() throws IOException {
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFileFromJavaPropertyValue(Paths.get("nowhere",
JAVA_PROPERTIES_FILE.toString()),
SOURCE_PATH_PROPERTY_NAME,
VALID_DESTINATION_PATH,
warnings);
}
@Test
public void copyFileFromJavaPropertyWithAnAbsolutePath() {
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFileFromJavaPropertyValue(ddfHome.resolve(JAVA_PROPERTIES_FILE),
SOURCE_PATH_PROPERTY_NAME,
VALID_DESTINATION_PATH,
warnings);
}
@Test(expected = IllegalArgumentException.class)
public void copyFileFromJavaPropertyWithNullJavaPropertiesFile() throws IOException {
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFileFromJavaPropertyValue(null,
SOURCE_PATH_PROPERTY_NAME,
VALID_DESTINATION_PATH,
warnings);
}
@Test(expected = IllegalArgumentException.class)
public void copyFileFromJavaPropertyWithNullValue() throws Exception {
Properties properties = new Properties();
properties.store(new FileOutputStream(ddfHome.resolve(JAVA_PROPERTIES_FILE)
.toFile()), "Test");
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFileFromJavaPropertyValue(JAVA_PROPERTIES_FILE,
SOURCE_PATH_PROPERTY_NAME,
VALID_DESTINATION_PATH,
warnings);
}
@Test(expected = IllegalArgumentException.class)
public void copyFileFromJavaPropertyWithEmptyValue() throws Exception {
createJavaPropertiesFile("");
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFileFromJavaPropertyValue(JAVA_PROPERTIES_FILE,
SOURCE_PATH_PROPERTY_NAME,
VALID_DESTINATION_PATH,
warnings);
}
@Test(expected = IllegalArgumentException.class)
public void copyFileFromJavaPropertyValueNullExportDirectory() {
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFileFromJavaPropertyValue(JAVA_PROPERTIES_FILE,
SOURCE_PATH_PROPERTY_NAME,
null,
warnings);
}
@Test(expected = IllegalArgumentException.class)
public void copyFileFromJavaPropertyValueNullWarningsCollection() {
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFileFromJavaPropertyValue(JAVA_PROPERTIES_FILE,
SOURCE_PATH_PROPERTY_NAME,
VALID_DESTINATION_PATH,
null);
}
@Test
public void copyFileFromJavaPropertyValueSourceIsAbsolutePath() throws IOException {
createJavaPropertiesFile(ABSOLUTE_SOURCE_FILE.toString());
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFileFromJavaPropertyValue(JAVA_PROPERTIES_FILE,
SOURCE_PATH_PROPERTY_NAME,
VALID_DESTINATION_PATH,
warnings);
assertWarnings("is absolute");
}
@Test
public void copyFileFromJavaPropertyValueSourceHasSymbolicLink() throws IOException {
when(Files.isSymbolicLink(VALID_SOURCE_FILE)).thenReturn(true);
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFileFromJavaPropertyValue(JAVA_PROPERTIES_FILE,
SOURCE_PATH_PROPERTY_NAME,
VALID_DESTINATION_PATH,
warnings);
assertWarnings("contains a symbolic link");
}
@Test
public void copyFileFromJavaPropertyValueSourceNotUnderDdfHome() throws IOException {
createJavaPropertiesFile(OUTSIDE_DDF_HOME_SOURCE_FILE.toString());
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFileFromJavaPropertyValue(JAVA_PROPERTIES_FILE,
SOURCE_PATH_PROPERTY_NAME,
VALID_DESTINATION_PATH,
warnings);
assertWarnings(String.format("is outside [%s]", ddfHome));
}
@Test(expected = MigrationException.class)
public void copyFileFromJavaPropertyValueFails() throws IOException {
doThrow(new IOException()).when(FileUtils.class);
FileUtils.copyFile(any(File.class), any(File.class));
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFileFromJavaPropertyValue(JAVA_PROPERTIES_FILE,
SOURCE_PATH_PROPERTY_NAME,
VALID_DESTINATION_PATH,
warnings);
}
@Test
public void copyFileFromJavaPropertyValueSourceOutsideDdfHomeDoesNotExist() throws IOException {
createJavaPropertiesFile(OUTSIDE_DDF_HOME_SOURCE_PATH.resolve("invalid.properties")
.toString());
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.copyFileFromJavaPropertyValue(JAVA_PROPERTIES_FILE,
SOURCE_PATH_PROPERTY_NAME,
VALID_DESTINATION_PATH,
warnings);
assertWarnings("does not exist or cannot be read");
}
@Test(expected = IllegalArgumentException.class)
public void testGetJavaPropertyValueNullPropertyFilePath() throws Exception {
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.getJavaPropertyValue(null, SOURCE_PATH_PROPERTY_NAME);
}
@Test(expected = IllegalArgumentException.class)
public void testGetJavaPropertyValueNullPropertyPropertyName() throws Exception {
MigratableUtil migratableUtil = new MigratableUtil();
migratableUtil.getJavaPropertyValue(JAVA_PROPERTIES_FILE, null);
}
@Test
public void testGetJavaPropertyValuePropetyExists() throws Exception {
MigratableUtil migratableUtil = new MigratableUtil();
String value = migratableUtil.getJavaPropertyValue(JAVA_PROPERTIES_FILE,
SOURCE_PATH_PROPERTY_NAME);
assertThat(value, is(VALID_SOURCE_FILE.toString()));
}
@Test
public void testGetJavaPropertyValuePropetyDoesNotExist() throws Exception {
MigratableUtil migratableUtil = new MigratableUtil();
String value = migratableUtil.getJavaPropertyValue(JAVA_PROPERTIES_FILE, "nonexistent");
assertThat(value, is(nullValue()));
}
private void createTempPropertiesFiles() throws IOException {
File etcPath = tempDir.newFolder(DDF_BASE_DIR.toString(), "etc");
File propertiesFile = new File(etcPath + File.separator + CONFIG_FILE_NAME);
propertiesFile.createNewFile();
File outsidePath = tempDir.newFolder("outside");
File outsidePropertiesFile = new File(outsidePath + File.separator + CONFIG_FILE_NAME);
outsidePropertiesFile.createNewFile();
createJavaPropertiesFile(VALID_SOURCE_FILE.toString());
}
private void createJavaPropertiesFile(String sourceDirectoryValue) throws IOException {
Properties properties = new Properties();
properties.setProperty(SOURCE_PATH_PROPERTY_NAME, sourceDirectoryValue);
properties.store(new FileOutputStream(ddfHome.resolve(JAVA_PROPERTIES_FILE)
.toFile()), "Test");
}
private void assertWarnings(String expectedReason) throws IOException {
assertThat(warnings, hasSize(1));
assertThat(warnings.iterator()
.next()
.getMessage(), containsString(expectedReason));
verifyStatic(never());
FileUtils.copyFile(any(File.class), any(File.class));
}
}