/**
* 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.configuration.migration;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.verifyStatic;
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.Collections;
import java.util.List;
import java.util.function.Supplier;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.validation.constraints.NotNull;
import org.codice.ddf.configuration.admin.ConfigurationAdminMigration;
import org.codice.ddf.migration.ConfigurationMigratable;
import org.codice.ddf.migration.DataMigratable;
import org.codice.ddf.migration.DescribableBean;
import org.codice.ddf.migration.MigrationException;
import org.codice.ddf.migration.MigrationMetadata;
import org.codice.ddf.migration.MigrationWarning;
import org.codice.ddf.platform.services.common.Describable;
import org.codice.ddf.platform.util.SortedServiceList;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.osgi.framework.InvalidSyntaxException;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.rule.PowerMockRule;
import com.google.common.collect.ImmutableList;
@PrepareForTest(ConfigurationMigrationManager.class)
public class ConfigurationMigrationManagerTest {
@Rule
public PowerMockRule powerMockRule = new PowerMockRule();
private static ObjectName configMigrationServiceObjectName;
@Mock
private ConfigurationAdminMigration configurationAdminMigration;
@Mock
private MBeanServer mBeanServer;
private List<ConfigurationMigratable> configurationMigratables;
private List<DataMigratable> dataMigratables;
@Mock
private ConfigurationMigratable configurationMigratable;
@Mock
private DataMigratable dataMigratable;
@Mock
Path exportDirectory;
private MigrationMetadata noWarnings = new MigrationMetadata(ImmutableList.of());
private Path exportPath = Paths.get("export", "dir");
@BeforeClass
public static void setupClass() throws MalformedObjectNameException {
configMigrationServiceObjectName = new ObjectName(
ConfigurationMigrationManager.class.getName() + ":service=configuration-migration");
}
@Before
public void setup() throws InvalidSyntaxException {
MockitoAnnotations.initMocks(this);
mockStatic(Files.class);
mockStatic(Paths.class);
configurationMigratables = Collections.singletonList(configurationMigratable);
dataMigratables = Collections.singletonList(dataMigratable);
when(configurationMigratable.export(any(Path.class))).thenReturn(noWarnings);
when(dataMigratable.export(any(Path.class))).thenReturn(noWarnings);
}
@Test
public void testGetOptionalMigratableInfo() {
DescribableBean bean1 = new DescribableBean("1.0",
"ddf.platform",
"Platform Migratable",
"Exports platform config",
"Codice");
DescribableBean bean2 = new DescribableBean("2.0",
"ddf.catalog",
"Catalog Migratable",
"Exports catalog metacards",
"Codice");
List<ConfigurationMigratable> mockConfigs = mock(List.class);
List<DataMigratable> migratables = new ArrayList<>();
migratables.add(new TestMigratable(bean1, 3));
migratables.add(new TestMigratable(bean2, 4));
ConfigurationMigrationManager manager = new ConfigurationMigrationManager(
configurationAdminMigration,
mBeanServer,
mockConfigs,
migratables);
Collection<Describable> describables = manager.getOptionalMigratableInfo();
verifyDescriptionEqual((Describable) describables.toArray()[0], bean1);
verifyDescriptionEqual((Describable) describables.toArray()[1], bean2);
}
@Test(expected = IllegalArgumentException.class)
public void constructorWithNullConfigurationAdminMigrator() {
new ConfigurationMigrationManager(null,
mBeanServer,
new SortedServiceList<>(),
new SortedServiceList<>());
}
@Test(expected = IllegalArgumentException.class)
public void constructorWithNullMBeanServer() {
new ConfigurationMigrationManager(configurationAdminMigration,
null,
new SortedServiceList<>(),
new SortedServiceList<>());
}
@Test(expected = IllegalArgumentException.class)
public void constructorWithNullConfigurationMigratablesList() {
new ConfigurationMigrationManager(configurationAdminMigration,
mBeanServer,
null,
new SortedServiceList<>());
}
@Test(expected = IllegalArgumentException.class)
public void constructorWithNullDataMigratablesList() {
new ConfigurationMigrationManager(configurationAdminMigration,
mBeanServer,
new SortedServiceList<>(),
null);
}
@Test
public void init() throws Exception {
ConfigurationMigrationManager configurationMigrationManager =
createConfigurationMigrationManager();
configurationMigrationManager.init();
verify(mBeanServer).registerMBean(configurationMigrationManager,
configMigrationServiceObjectName);
}
@Test
public void initWhenServiceAlreadyRegisteredAsMBean() throws Exception {
ConfigurationMigrationManager configurationMigrationManager =
createConfigurationMigrationManager();
when(mBeanServer.registerMBean(configurationMigrationManager,
configMigrationServiceObjectName)).thenThrow(new InstanceAlreadyExistsException())
.thenReturn(null);
configurationMigrationManager.init();
verify(mBeanServer, times(2)).registerMBean(configurationMigrationManager,
configMigrationServiceObjectName);
verify(mBeanServer).unregisterMBean(configMigrationServiceObjectName);
}
@Test(expected = MBeanRegistrationException.class)
public void initWhenMBeanUnregistrationFails() throws Exception {
ConfigurationMigrationManager configurationMigrationManager =
createConfigurationMigrationManager();
when(mBeanServer.registerMBean(configurationMigrationManager,
configMigrationServiceObjectName)).thenThrow(new InstanceAlreadyExistsException());
doThrow(new MBeanRegistrationException(new Exception())).when(mBeanServer)
.unregisterMBean(configMigrationServiceObjectName);
configurationMigrationManager.init();
}
@Test(expected = MBeanRegistrationException.class)
public void initWhenMBeanReRegistrationFails() throws Exception {
ConfigurationMigrationManager configurationMigrationManager =
createConfigurationMigrationManager();
when(mBeanServer.registerMBean(configurationMigrationManager,
configMigrationServiceObjectName)).thenThrow(new InstanceAlreadyExistsException(),
new MBeanRegistrationException(new Exception()));
configurationMigrationManager.init();
}
@Test
public void exportWithPath() throws Exception {
ConfigurationMigrationManager configurationMigrationManager =
createConfigurationMigrationManager();
when(exportDirectory.resolve(any(Path.class))).thenReturn(any(Path.class));
Collection<MigrationWarning> migrationWarnings =
export(() -> configurationMigrationManager.export(exportDirectory));
assertThat(migrationWarnings, is(empty()));
}
@Test
public void exportWithString() throws Exception {
ConfigurationMigrationManager configurationMigrationManager =
createConfigurationMigrationManager();
when(Paths.get("/export/dir")).thenReturn(exportDirectory);
Collection<MigrationWarning> migrationWarnings =
export(() -> configurationMigrationManager.export("/export/dir"));
assertThat(migrationWarnings, is(empty()));
}
@Test(expected = IllegalArgumentException.class)
public void exportWithNullPath() throws Exception {
ConfigurationMigrationManager configurationMigrationManager =
createConfigurationMigrationManager();
configurationMigrationManager.export((Path) null);
}
@Test(expected = IllegalArgumentException.class)
public void exportWithNullPathString() throws Exception {
ConfigurationMigrationManager configurationMigrationManager =
createConfigurationMigrationManager();
configurationMigrationManager.export((String) null);
}
@Test
public void exportWithWarnings() {
ConfigurationMigrationManager configurationMigrationManager =
createConfigurationMigrationManager();
MigrationWarning migrationWarning = new MigrationWarning("");
Collection<MigrationWarning> warningList = new ArrayList<>();
warningList.add(migrationWarning);
MigrationMetadata warning = new MigrationMetadata(warningList);
when(configurationMigratable.export(any(Path.class))).thenReturn(warning);
Collection<MigrationWarning> migrationWarnings = configurationMigrationManager.export(
exportDirectory);
assertThat(migrationWarnings, contains(migrationWarning));
}
@Test(expected = MigrationException.class)
public void exportFailsToCreateDirectory() throws Exception {
when(Files.createDirectories(exportPath)).thenThrow(new IOException());
ConfigurationMigrationManager configurationMigrationManager =
createConfigurationMigrationManager();
configurationMigrationManager.export(exportPath);
}
@Test(expected = MigrationException.class)
public void exportWhenConfigurationAdminMigratorThrowsIOException() throws Exception {
when(Files.createDirectories(exportPath)).thenReturn(exportPath);
doThrow(new IOException()).when(configurationAdminMigration)
.export(exportPath);
ConfigurationMigrationManager configurationMigrationManager =
createConfigurationMigrationManager();
configurationMigrationManager.export(exportPath);
}
@Test(expected = MigrationException.class)
public void exportWhenConfigurationAdminMigratorThrowsConfigurationFileException()
throws Exception {
when(Files.createDirectories(exportPath)).thenReturn(exportPath);
doThrow(new MigrationException("")).when(configurationAdminMigration)
.export(exportPath);
ConfigurationMigrationManager configurationMigrationManager =
createConfigurationMigrationManager();
configurationMigrationManager.export(exportPath);
}
@Test(expected = MigrationException.class)
public void exportWhenConfigurationAdminMigratorThrowsRuntimeException() throws Exception {
when(Files.createDirectories(exportPath)).thenReturn(exportPath);
doThrow(new RuntimeException("")).when(configurationAdminMigration)
.export(exportPath);
ConfigurationMigrationManager configurationMigrationManager =
createConfigurationMigrationManager();
configurationMigrationManager.export(exportPath);
}
@Test
public void exportCallsMigratables() throws Exception {
ConfigurationMigrationManager configurationMigrationManager =
createConfigurationMigrationManager();
Collection<MigrationWarning> migrationWarnings =
export(() -> configurationMigrationManager.export(exportDirectory));
assertThat(migrationWarnings, is(empty()));
verify(configurationMigratable).export(exportDirectory);
verify(dataMigratable).export(exportDirectory);
}
@Test
public void exportWhenMigratablesReturnWarnings() throws Exception {
ConfigurationMigrationManager configurationMigrationManager =
createConfigurationMigrationManager();
MigrationWarning[] expectedWarnings = new MigrationWarning[] {new MigrationWarning(
"Warning1"), new MigrationWarning("Warning2")};
when(configurationMigratable.export(any(Path.class))).thenReturn(new MigrationMetadata(
ImmutableList.of(expectedWarnings[0])));
when(dataMigratable.export(any(Path.class))).thenReturn(new MigrationMetadata(ImmutableList.of(
expectedWarnings[1])));
Collection<MigrationWarning> migrationWarnings =
export(() -> configurationMigrationManager.export(exportDirectory));
assertThat(migrationWarnings, containsInAnyOrder(expectedWarnings));
verify(configurationMigratable).export(exportDirectory);
verify(dataMigratable).export(exportDirectory);
}
@Test(expected = MigrationException.class)
public void exportFailsWhenMigratableThrowsMigrationException() throws Exception {
ConfigurationMigrationManager configurationMigrationManager =
createConfigurationMigrationManager();
when(configurationMigratable.export(any(Path.class))).thenThrow(new MigrationException(""));
when(dataMigratable.export(any(Path.class))).thenReturn(new MigrationMetadata(ImmutableList.of()));
try {
export(() -> configurationMigrationManager.export(exportPath));
} finally {
verify(configurationMigratable).export(exportPath);
verify(dataMigratable, never()).export(any(Path.class));
}
}
@Test(expected = MigrationException.class)
public void exportFailsWhenMigratableThrowsRuntimeException() throws Exception {
ConfigurationMigrationManager configurationMigrationManager =
createConfigurationMigrationManager();
when(configurationMigratable.export(any(Path.class))).thenThrow(new RuntimeException());
try {
export(() -> configurationMigrationManager.export(exportPath));
} finally {
verify(configurationMigratable).export(exportPath);
verify(dataMigratable, never()).export(any(Path.class));
}
}
private ConfigurationMigrationManager createConfigurationMigrationManager() {
return new ConfigurationMigrationManager(configurationAdminMigration,
mBeanServer,
configurationMigratables,
dataMigratables);
}
private Collection<MigrationWarning> export(Supplier<Collection<MigrationWarning>> exportCall)
throws Exception {
when(Files.createDirectories(exportDirectory)).thenReturn(exportDirectory);
Collection<MigrationWarning> migrationWarnings = exportCall.get();
verifyStatic();
Files.createDirectories(exportDirectory);
verify(configurationAdminMigration, times(1)).export(exportDirectory);
return migrationWarnings;
}
private void verifyDescriptionEqual(Describable describable, DescribableBean bean) {
assert (describable.getId()
.equals(bean.getId()));
assert (describable.getTitle()
.equals(bean.getTitle()));
assert (describable.getDescription()
.equals(bean.getDescription()));
assert (describable.getOrganization()
.equals(bean.getOrganization()));
assert (describable.getVersion()
.equals(bean.getVersion()));
}
}
class TestMigratable extends DescribableBean implements DataMigratable {
private int wrappedNumber;
public TestMigratable(DescribableBean info, int wrappedNumber) {
super(info);
this.wrappedNumber = wrappedNumber;
}
@Override
public MigrationMetadata export(@NotNull Path exportPath) throws MigrationException {
return null;
}
public int getWrappedNumber() {
return wrappedNumber;
}
}