package com.constellio.app.services.migrations;
import static com.constellio.sdk.tests.TestUtils.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InOrder;
import org.mockito.Mock;
import com.constellio.app.entities.modules.InstallableModule;
import com.constellio.app.entities.modules.MigrationResourcesProvider;
import com.constellio.app.entities.modules.MigrationScript;
import com.constellio.app.services.collections.CollectionsManager;
import com.constellio.app.services.extensions.ConstellioModulesManagerImpl;
import com.constellio.app.services.extensions.plugins.ConstellioPluginManager;
import com.constellio.app.services.factories.AppLayerFactory;
import com.constellio.app.services.systemSetup.SystemGlobalConfigsManager;
import com.constellio.data.dao.managers.config.ConfigManager;
import com.constellio.data.dao.managers.config.ConfigManagerException.OptimisticLockingConfiguration;
import com.constellio.data.dao.managers.config.values.PropertiesConfiguration;
import com.constellio.data.dao.services.factories.DataLayerFactory;
import com.constellio.data.utils.Delayed;
import com.constellio.model.services.collections.CollectionsListManager;
import com.constellio.model.services.factories.ModelLayerFactory;
import com.constellio.sdk.tests.ConstellioTest;
public class MigrationServicesAcceptanceTest extends ConstellioTest {
ConstellioPluginManager pluginManager;
ModelLayerFactory modelLayerFactory;
AppLayerFactory appLayerFactory;
DataLayerFactory dataLayerFactory;
ConfigManager configManager;
PropertiesConfiguration propertiesConfig;
com.constellio.app.services.migrations.MigrationServices migrationServices;
@Mock SystemGlobalConfigsManager systemGlobalConfigsManager;
@Mock ConstellioEIM constellioEIM;
@Mock MigrationScript coreMigrationTo100;
@Mock MigrationScript coreMigrationTo103;
@Mock MigrationScript coreMigrationTo110;
@Mock ConstellioModulesManagerImpl moduleManager;
String aModuleId = "aModuleId";
String aModuleWithDependencyId = "aModuleWithDependencyId";
InstallableModule aModule, aModuleWithDependency;
@Mock MigrationScript aModuleMigrationTo100;
@Mock MigrationScript aModuleMigrationTo102;
@Mock MigrationScript aModuleMigrationTo110;
@Mock MigrationScript aModuleWithDependencyMigrationTo100;
@Mock MigrationScript aModuleWithDependencyMigrationTo101;
@Mock MigrationScript aModuleWithDependencyMigrationTo106;
InOrder inOrder;
@Mock MigrationScript moduleAMigrationTo100, moduleBMigrationTo100, moduleCMigrationTo100, moduleDMigrationTo100, moduleEMigrationTo100, moduleFMigrationTo100;
@Before
public void setUp() {
pluginManager = getAppLayerFactory().getPluginManager();
configManager = getDataLayerFactory().getConfigManager();
dataLayerFactory = getDataLayerFactory();
modelLayerFactory = getModelLayerFactory();
appLayerFactory = getAppLayerFactory();
aModule = givenModuleWithId(aModuleId);
aModuleWithDependency = givenModuleWithId(aModuleWithDependencyId);
migrationServices = new com.constellio.app.services.migrations.MigrationServices(constellioEIM, appLayerFactory,
moduleManager, pluginManager);
when(coreMigrationTo100.getVersion()).thenReturn("1.0.0");
when(coreMigrationTo103.getVersion()).thenReturn("1.0.3");
when(coreMigrationTo110.getVersion()).thenReturn("1.1.0");
when(constellioEIM.getMigrationScripts()).thenReturn(
Arrays.asList(coreMigrationTo100, coreMigrationTo103, coreMigrationTo110));
when(aModuleMigrationTo100.getVersion()).thenReturn("1.0.0");
when(aModuleMigrationTo102.getVersion()).thenReturn("1.0.2");
when(aModuleMigrationTo110.getVersion()).thenReturn("1.1.0");
when(aModule.getMigrationScripts()).thenReturn(
Arrays.asList(aModuleMigrationTo100, aModuleMigrationTo102, aModuleMigrationTo110));
when(aModuleWithDependencyMigrationTo100.getVersion()).thenReturn("1.0.0");
when(aModuleWithDependencyMigrationTo101.getVersion()).thenReturn("1.0.1");
when(aModuleWithDependencyMigrationTo106.getVersion()).thenReturn("1.0.6");
when(aModuleWithDependency.getMigrationScripts()).thenReturn(
Arrays.asList(aModuleWithDependencyMigrationTo100, aModuleWithDependencyMigrationTo101,
aModuleWithDependencyMigrationTo106));
when(aModuleWithDependency.getDependencies()).thenReturn(Arrays.asList(aModuleId));
when(moduleAMigrationTo100.getVersion()).thenReturn("1.0.0");
when(moduleBMigrationTo100.getVersion()).thenReturn("1.0.0");
when(moduleCMigrationTo100.getVersion()).thenReturn("1.0.0");
when(moduleDMigrationTo100.getVersion()).thenReturn("1.0.0");
when(moduleEMigrationTo100.getVersion()).thenReturn("1.0.0");
when(moduleFMigrationTo100.getVersion()).thenReturn("1.0.0");
inOrder = inOrder(coreMigrationTo100, coreMigrationTo103, coreMigrationTo110, aModuleMigrationTo100,
aModuleMigrationTo102, aModuleMigrationTo110, aModuleWithDependencyMigrationTo100,
aModuleWithDependencyMigrationTo101, aModuleWithDependencyMigrationTo106, moduleAMigrationTo100,
moduleBMigrationTo100, moduleCMigrationTo100, moduleDMigrationTo100, moduleEMigrationTo100,
moduleFMigrationTo100);
}
//@Test
// This behaviour is no longer required anywhere
public void givenMultipleCollectionsThenMigratedIndependently()
throws Exception {
when(moduleManager.getEnabledModules(zeCollection)).thenReturn(Arrays.asList(aModule));
CollectionsListManager collectionsListManager = getModelLayerFactory().getCollectionsListManager();
CollectionsManager collectionsManager = spy(
new CollectionsManager(getModelLayerFactory(), moduleManager, new Delayed<>(migrationServices),
systemGlobalConfigsManager));
collectionsManager.createCollectionConfigs("collection1");
collectionsListManager.addCollection("collection1", Arrays.asList("fr"));
try {
migrationServices.migrate("collection1", null, false);
} catch (OptimisticLockingConfiguration optimisticLockingConfiguration) {
throw new RuntimeException(optimisticLockingConfiguration);
}
collectionsManager.createCollectionConfigs("collection2");
collectionsListManager.addCollection("collection2", Arrays.asList("fr"));
try {
migrationServices.migrate("collection2", null, false);
} catch (OptimisticLockingConfiguration optimisticLockingConfiguration) {
throw new RuntimeException(optimisticLockingConfiguration);
}
inOrder.verify(coreMigrationTo100)
.migrate(eq("collection1"), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(aModuleMigrationTo100)
.migrate(eq("collection1"), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(aModuleMigrationTo102)
.migrate(eq("collection1"), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(coreMigrationTo103)
.migrate(eq("collection1"), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(coreMigrationTo110)
.migrate(eq("collection1"), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(aModuleMigrationTo110)
.migrate(eq("collection1"), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(coreMigrationTo100)
.migrate(eq("collection2"), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(aModuleMigrationTo100).migrate(eq("collection2"), any(MigrationResourcesProvider.class), eq(
appLayerFactory));
inOrder.verify(aModuleMigrationTo102).migrate(eq("collection2"), any(MigrationResourcesProvider.class), eq(
appLayerFactory));
inOrder.verify(coreMigrationTo103)
.migrate(eq("collection2"), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(coreMigrationTo110)
.migrate(eq("collection2"), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(aModuleMigrationTo110).migrate(eq("collection2"), any(MigrationResourcesProvider.class), eq(
appLayerFactory));
assertThat(migrationServices.getCurrentVersion("collection1")).isEqualTo("1.1.0");
assertThat(migrationServices.getCurrentVersion("collection2")).isEqualTo("1.1.0");
}
@Test
public void whenMigrateToVersionThenMigrationDone()
throws Exception {
givenCollection(zeCollection);
when(moduleManager.getEnabledModules(zeCollection)).thenReturn(Arrays.asList(aModule));
migrationServices.setCurrentDataVersion(zeCollection, "0.9.9");
migrationServices.migrate(zeCollection, "1.1.0", false);
inOrder.verify(coreMigrationTo100)
.migrate(eq(zeCollection), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(aModuleMigrationTo100)
.migrate(eq(zeCollection), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(aModuleMigrationTo102)
.migrate(eq(zeCollection), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(coreMigrationTo103)
.migrate(eq(zeCollection), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(coreMigrationTo110)
.migrate(eq(zeCollection), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(aModuleMigrationTo110)
.migrate(eq(zeCollection), any(MigrationResourcesProvider.class), eq(appLayerFactory));
assertThat(migrationServices.getCurrentVersion(zeCollection)).isEqualTo("1.1.0");
}
@Test
public void givenModuleWithDependencyThenDepencyAlwaysMigratedBefore()
throws Exception {
givenCollection(zeCollection);
when(moduleManager.getEnabledModules(zeCollection)).thenReturn(Arrays.asList(aModuleWithDependency, aModule));
migrationServices.setCurrentDataVersion(zeCollection, "0.9.9");
migrationServices.migrate(zeCollection, "1.1.0", false);
inOrder.verify(coreMigrationTo100)
.migrate(eq(zeCollection), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(aModuleMigrationTo100)
.migrate(eq(zeCollection), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(aModuleWithDependencyMigrationTo100)
.migrate(eq(zeCollection), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(aModuleWithDependencyMigrationTo101)
.migrate(eq(zeCollection), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(aModuleMigrationTo102)
.migrate(eq(zeCollection), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(coreMigrationTo103)
.migrate(eq(zeCollection), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(aModuleWithDependencyMigrationTo106)
.migrate(eq(zeCollection), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(coreMigrationTo110)
.migrate(eq(zeCollection), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(aModuleMigrationTo110)
.migrate(eq(zeCollection), any(MigrationResourcesProvider.class), eq(appLayerFactory));
assertThat(migrationServices.getCurrentVersion(zeCollection)).isEqualTo("1.1.0");
}
@Test
public void givenModuleWithADependencyToAnotherModuleWithADependencyThenDepencyAlwaysMigratedBefore()
throws Exception {
givenCollection(zeCollection);
when(constellioEIM.getMigrationScripts()).thenReturn(Arrays.asList(coreMigrationTo100, coreMigrationTo103));
InstallableModule moduleA = givenModuleWithIdAndMigrationScripts("a", moduleAMigrationTo100);
InstallableModule moduleB = givenModuleWithIdAndMigrationScripts("b", moduleBMigrationTo100);
InstallableModule moduleC = givenModuleWithIdAndMigrationScripts("c", moduleCMigrationTo100);
InstallableModule moduleD = givenModuleWithIdAndMigrationScripts("d", moduleDMigrationTo100);
InstallableModule moduleE = givenModuleWithIdAndMigrationScripts("e", moduleEMigrationTo100);
InstallableModule moduleF = givenModuleWithIdAndMigrationScripts("f", moduleFMigrationTo100);
//b -> a,c
//a -> d,e
//e -> f
//f -> d
//d -> c
when(moduleB.getDependencies()).thenReturn(asList("a", "c"));
when(moduleA.getDependencies()).thenReturn(asList("d", "e"));
when(moduleE.getDependencies()).thenReturn(asList("f"));
when(moduleF.getDependencies()).thenReturn(asList("d"));
when(moduleD.getDependencies()).thenReturn(asList("c"));
when(moduleManager.getEnabledModules(zeCollection))
.thenReturn(Arrays.asList(moduleA, moduleB, moduleC, moduleD, moduleE, moduleF));
migrationServices.setCurrentDataVersion(zeCollection, "0.9.9");
migrationServices.migrate(zeCollection, "1.1.0", false);
inOrder.verify(coreMigrationTo100)
.migrate(eq(zeCollection), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(moduleCMigrationTo100)
.migrate(eq(zeCollection), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(moduleDMigrationTo100)
.migrate(eq(zeCollection), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(moduleFMigrationTo100)
.migrate(eq(zeCollection), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(moduleEMigrationTo100)
.migrate(eq(zeCollection), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(moduleAMigrationTo100)
.migrate(eq(zeCollection), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(moduleBMigrationTo100)
.migrate(eq(zeCollection), any(MigrationResourcesProvider.class), eq(appLayerFactory));
inOrder.verify(coreMigrationTo103)
.migrate(eq(zeCollection), any(MigrationResourcesProvider.class), eq(appLayerFactory));
assertThat(migrationServices.getCurrentVersion(zeCollection)).isEqualTo("1.0.3");
}
//TODO Validate module has migration scripts of different versions
//TODO Validate no multiple modules with same id
private InstallableModule givenModuleWithIdAndMigrationScripts(String id, MigrationScript... scripts) {
InstallableModule constellioModule = givenModuleWithId(id);
when(constellioModule.getMigrationScripts()).thenReturn(Arrays.asList(scripts));
return constellioModule;
}
private InstallableModule givenModuleWithId(String id) {
InstallableModule constellioModule = mock(InstallableModule.class, id);
when(constellioModule.getId()).thenReturn(id);
when(moduleManager.getInstalledModule(id)).thenReturn(constellioModule);
return constellioModule;
}
}