package com.constellio.app.services.appManagement;
import static java.util.Arrays.asList;
import static org.apache.commons.io.FileUtils.readFileToString;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.io.FileUtils;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import com.constellio.app.entities.modules.ProgressInfo;
import com.constellio.app.services.appManagement.AppManagementService.LicenseInfo;
import com.constellio.app.services.appManagement.AppManagementServiceRuntimeException.WarFileNotFound;
import com.constellio.app.services.extensions.plugins.ConstellioPluginManager;
import com.constellio.app.services.extensions.plugins.InvalidJarsTest;
import com.constellio.app.services.factories.AppLayerFactory;
import com.constellio.app.services.systemSetup.SystemGlobalConfigsManager;
import com.constellio.model.conf.FoldersLocator;
import com.constellio.model.services.migrations.ConstellioEIMConfigs;
import com.constellio.sdk.tests.ConstellioTest;
import com.constellio.sdk.tests.annotations.SlowTest;
//TODO Maxime : Vérifier pourquoi ce test est extrêmement lent
@SlowTest
public class AppManagementServicesAcceptanceTest extends ConstellioTest {
@Mock ConstellioPluginManager pluginManager;
File plugin1, plugin2, notAPlugin;
File webappsFolder;
File wrapperConf;
File commandFile;
File uploadWarFile;
File pluginsFolder;
AppManagementService appManagementService;
FoldersLocator foldersLocator;
@Before
public void setup()
throws IOException {
webappsFolder = newTempFolder();
final File currentConstellioFolder = new File(webappsFolder, "webapp-5.0.5");
currentConstellioFolder.mkdirs();
commandFile = new File(newTempFolder(), "cmd");
uploadWarFile = new File(newTempFolder(), "upload.war");
wrapperConf = new File(newTempFolder(), "wrapper.conf");
pluginsFolder = newTempFolder();
FileUtils.copyFile(getTestResourceFile("initial-wrapper.conf"), wrapperConf);
SystemGlobalConfigsManager systemGlobalConfigsManager = getAppLayerFactory().getSystemGlobalConfigsManager();
getAppLayerFactory().getModelLayerFactory().getSystemConfigurationsManager()
.setValue(ConstellioEIMConfigs.CLEAN_DURING_INSTALL, true);
foldersLocator = new FoldersLocator() {
@Override
public File getConstellioWebappFolder() {
return currentConstellioFolder;
}
@Override
public File getWrapperCommandFile() {
return commandFile;
}
@Override
public File getWrapperConf() {
return wrapperConf;
}
@Override
public File getUploadConstellioWarFile() {
return uploadWarFile;
}
@Override
public File getPluginsJarsFolder() {
return pluginsFolder;
}
};
AppLayerFactory appLayerFactory = spy(getAppLayerFactory());
when(appLayerFactory.getPluginManager()).thenReturn(pluginManager);
appManagementService = spy(new AppManagementService(appLayerFactory, foldersLocator));
doReturn("5.0.4").when(appManagementService).getWarVersion();
}
@Test
public void givenAValidWarFileHasBeenUpdatedWhenUpdateTriggeredThenUnzipInCorrectFolder()
throws Exception {
uploadADummyUpdateJarWithVersion("5.1.2");
appManagementService.update(new ProgressInfo());
String wrapperConfContent = readFileToString(wrapperConf)
.replace(webappsFolder.getAbsolutePath() + File.separator, "/path/to/webapps/");
assertThat(wrapperConfContent).isEqualTo(getTestResourceContent("expected-modified-wrapper.conf"));
File newWebappVersion = new File(webappsFolder, "webapp-5.1.2");
File newWebappVersionWEB_INF = new File(newWebappVersion, "WEB-INF");
File newWebappVersionLib = new File(newWebappVersionWEB_INF, "lib");
assertThat(uploadWarFile).doesNotExist();
assertThat(readFileToString(new File(newWebappVersionLib, "core-app-5.1.2.jar"))).isEqualTo("The content of core app!");
assertThat(readFileToString(new File(newWebappVersionLib, "core-model-5.1.2.jar")))
.isEqualTo("The content of core model!");
assertThat(readFileToString(new File(newWebappVersionLib, "core-data-5.1.2.jar"))).isEqualTo("The content of core data!");
}
@Test
public void givenAValidWarFileWithUpdatedPluginsThenInstallThem()
throws Exception {
uploadADummyUpdateJarWithDummyPluginsAndVersion("5.1.2");
appManagementService.update(new ProgressInfo());
String wrapperConfContent = readFileToString(wrapperConf)
.replace(webappsFolder.getAbsolutePath() + File.separator, "/path/to/webapps/");
assertThat(wrapperConfContent).isEqualTo(getTestResourceContent("expected-modified-wrapper.conf"));
File newWebappVersion = new File(webappsFolder, "webapp-5.1.2");
File newWebappVersionWEB_INF = new File(newWebappVersion, "WEB-INF");
File newWebappVersionLib = new File(newWebappVersionWEB_INF, "lib");
File newWebappUpdatedPlugins = new File(webappsFolder, "plugins-to-install");
ArgumentCaptor<File> installedPluginsCaptor = ArgumentCaptor.forClass(File.class);
verify(pluginManager, times(2))
.prepareInstallablePluginInNextWebapp(installedPluginsCaptor.capture(), any(File.class));
assertThat(installedPluginsCaptor.getAllValues()).extracting("name")
.containsOnly("plugin1.jar", "PLUGIN2.JAR");
assertThat(newWebappUpdatedPlugins).doesNotExist();
assertThat(uploadWarFile).doesNotExist();
assertThat(readFileToString(new File(newWebappVersionLib, "core-app-5.1.2.jar"))).isEqualTo("The content of core app!");
assertThat(readFileToString(new File(newWebappVersionLib, "core-model-5.1.2.jar")))
.isEqualTo("The content of core model!");
assertThat(readFileToString(new File(newWebappVersionLib, "core-data-5.1.2.jar"))).isEqualTo("The content of core data!");
}
//FIXME
@Test
public void givenInstalledPluginsWhenUpdateTriggeredThenPluginsInCorrectFolder()
throws Exception {
InvalidJarsTest.loadJarsToPluginsFolder(pluginsFolder);
uploadADummyUpdateJarWithVersion("5.1.2");
appManagementService.update(new ProgressInfo());
File newWebappVersion = new File(webappsFolder, "webapp-5.1.2");
InvalidJarsTest.assertThatJarsLoadedCorrectly(new File(newWebappVersion, "WEB-INF/plugins"));
}
@Test
public void givenWebAppFolderWithVersionsMoreRecentThanCurrentVersionWhenUpdateTriggeredThenCurrentVersionNotRemoved()
throws Exception {
InvalidJarsTest.loadJarsToPluginsFolder(pluginsFolder);
addVersion("5.0");
addVersion("5.0.7");
addVersion("5.1.1");
addVersion("5.1.1-1");
addVersion("5.0.5-1");
File versionToKeep1 = addVersion("5.1.1-3");
File versionToKeep2 = addVersion("5.2.1");
File versionToKeep3 = addVersion("5.2.1-4");
File versionToKeep4 = addVersion("5.4.1");
uploadADummyUpdateJarWithVersion("5.0.5");
String[] expectedFilesNames = { versionToKeep1.getName(), versionToKeep2.getName(), versionToKeep3.getName(),
versionToKeep4.getName(), "webapp-5.0.5-2" };
appManagementService.update(new ProgressInfo());
File[] keptFolders = webappsFolder.listFiles();
List<String> keptFilesNames = new ArrayList<>();
for (File keptFile : keptFolders) {
keptFilesNames.add(keptFile.getName());
}
assertThat(keptFilesNames).containsOnly(expectedFilesNames);
}
@Test
public void givenWebAppFolderWithInvalidVersionsWhenUpdateTriggeredThenOk()
throws Exception {
InvalidJarsTest.loadJarsToPluginsFolder(pluginsFolder);
File invalidVersionToKeep1 = addVersion("5.1.1-3lol");
File versionToKeep1 = addVersion("5.0.5");
uploadADummyUpdateJarWithVersion("5.0.5");
String[] expectedFilesNames = { invalidVersionToKeep1.getName(), versionToKeep1.getName(), "webapp-5.0.5-1" };
appManagementService.update(new ProgressInfo());
File[] keptFolders = webappsFolder.listFiles();
List<String> keptFilesNames = new ArrayList<>();
for (File keptFile : keptFolders) {
keptFilesNames.add(keptFile.getName());
}
assertThat(keptFilesNames).containsOnly(expectedFilesNames);
}
@Test
public void givenSeveralVersionsWhenUpdateTriggeredThenOnly5VersionsSaved()
throws Exception {
InvalidJarsTest.loadJarsToPluginsFolder(pluginsFolder);
File fileBeforeLastWeek = getTestResourceFile("initial-wrapper.conf");
givenTimeIs(new LocalDateTime(pluginsFolder.lastModified()).plusDays(6));
assertThat(appManagementService.isModifiedBeforeLastWeek(fileBeforeLastWeek)).isTrue();
addVersion("5.0");
addVersion("5.0.7");
addVersion("5.1.1");
addVersion("5.1.1-1");
File versionToKeep1 = addVersion("5.1.1-3");
File versionToKeep2 = addVersion("5.2.1");
File versionToKeep3 = addVersion("5.2.1-4");
File versionToKeep4 = addVersion("5.4.1");
uploadADummyUpdateJarWithVersion("5.4.1");
String[] expectedFilesNames = { versionToKeep1.getName(), versionToKeep2.getName(), versionToKeep3.getName(),
versionToKeep4.getName(), "webapp-5.4.1-1" };
appManagementService.update(new ProgressInfo());
File[] keptFolders = webappsFolder.listFiles();
List<String> keptFilesNames = new ArrayList<>();
for (File keptFile : keptFolders) {
keptFilesNames.add(keptFile.getName());
}
assertThat(keptFilesNames).containsOnly(expectedFilesNames);
}
@Test(expected = AppManagementServiceRuntimeException.CannotConnectToServer.class)
public void givenNoConnectionChangelogCannotBeRetrieve()
throws Exception {
doReturn(new LicenseInfo("", new LocalDate(), "")).when(appManagementService).getLicenseInfo();
doReturn("").when(appManagementService).sendPost(any(String.class), any(String.class));
doReturn(null).when(appManagementService).getInputForPost(any(String.class), any(String.class));
appManagementService.getChangelogFromServer();
}
@Test
public void givenConnectionChangelogCanBeRetrieve()
throws Exception {
InputStream tmp = getDummyInputStream();
doReturn(new LicenseInfo("", new LocalDate(), "")).when(appManagementService).getLicenseInfo();
doReturn("").when(appManagementService).sendPost(any(String.class), any(String.class));
doReturn(tmp).when(appManagementService).getInputForPost(any(String.class), any(String.class));
doReturn(false).when(appManagementService).isProxyPage(anyString());
appManagementService.getChangelogFromServer();
tmp.close();
}
//TODO Maxime
//@Test(expected = AppManagementServiceRuntimeException.CannotConnectToServer.class)
public void givenProxyConnectionWarCannotBeRetrieve()
throws Exception {
doReturn(new LicenseInfo("", new LocalDate(), "")).when(appManagementService).getLicenseInfo();
doReturn("").when(appManagementService).sendPost(any(String.class), any(String.class));
doReturn(null).when(appManagementService).getInputForPost(any(String.class), any(String.class));
doReturn(true).when(appManagementService).isProxyPage(anyString());
appManagementService.getWarFromServer(new ProgressInfo());
}
//TODO Maxime
//@Test(expected = AppManagementServiceRuntimeException.CannotConnectToServer.class)
public void givenNoConnectionWarCannotBeRetrieve()
throws Exception {
doReturn(new LicenseInfo("", new LocalDate(), "")).when(appManagementService).getLicenseInfo();
doReturn("").when(appManagementService).sendPost(any(String.class), any(String.class));
doReturn(null).when(appManagementService).getInputForPost(any(String.class), any(String.class));
appManagementService.getWarFromServer(new ProgressInfo());
}
@Test
public void givenConnectionWarCanBeRetrieve()
throws Exception {
InputStream tmp = getDummyInputStream();
doReturn(new LicenseInfo("", new LocalDate(), "")).when(appManagementService).getLicenseInfo();
doReturn("").when(appManagementService).sendPost(any(String.class), any(String.class));
doReturn(tmp).when(appManagementService).getInputForPost(any(String.class), any(String.class));
appManagementService.getWarFromServer(new ProgressInfo());
tmp.close();
}
@Test
public void givenUploadedWarIsSameVersionThenCanUpload()
throws Exception {
uploadADummyUpdateJarWithVersion("5.0.5");
appManagementService.update(new ProgressInfo());
}
@Test(expected = AppManagementServiceRuntimeException.WarFileVersionMustBeHigher.class)
public void givenUploadedWarIsPreviousVersionThenCannotUpload()
throws Exception {
uploadADummyUpdateJarWithVersion("5.0.3");
appManagementService.update(new ProgressInfo());
}
@Test(expected = WarFileNotFound.class)
public void givenWarIsNotUploadedThenCannotUpload()
throws Exception {
appManagementService.update(new ProgressInfo());
}
@Test
public void givenVersionAndSubVersionWhenFindDeployFolderThenBehavesAsExpected()
throws Exception {
String version = "1.2";
String versionWithSubVersion = version + "-3";
File tempFolder = newTempFolder();
addFile(tempFolder, "webapp-" + versionWithSubVersion + "lol");
addFile(tempFolder, "webapp-" + version + "2");
addFile(tempFolder, "webapp-" + version);
addFile(tempFolder, "webapp-" + version + "-2");
File folder = appManagementService.findDeployFolder(tempFolder, version);
assertThat(folder.getName()).isEqualTo("webapp-" + versionWithSubVersion);
}
@Test
public void givenSubVersionWhenFindDeployFolderThenBehavesAsExpected()
throws Exception {
String version = "1.2";
String expectedVersion = version + "-3";
File tempFolder = newTempFolder();
addFile(tempFolder, "webapp-" + version + "lol");
addFile(tempFolder, "webapp-" + version + "2");
addFile(tempFolder, "webapp-" + version + "-2");
File folder = appManagementService.findDeployFolder(tempFolder, version);
assertThat(folder.getName()).isEqualTo("webapp-" + expectedVersion);
}
@Test
public void givenVersionWhenFindDeployFolderThenBehavesAsExpected()
throws Exception {
String version = "1.2";
File tempFolder = newTempFolder();
addFile(tempFolder, "webapp-" + version + "lol");
addFile(tempFolder, "webapp-" + version + "2");
addFile(tempFolder, "webapp-" + version);
File folder = appManagementService.findDeployFolder(tempFolder, version);
assertThat(folder.getName()).isEqualTo("webapp-" + version + "-1");
}
@Test
public void givenNeitherVersionNorSubVersionWhenFindDeployFolderThenBehavesAsExpected()
throws Exception {
String version = "1.2";
File tempFolder = newTempFolder();
addFile(tempFolder, "webapp-" + version + "lol");
addFile(tempFolder, "webapp-" + version + "2");
File folder = appManagementService.findDeployFolder(tempFolder, version);
assertThat(folder.getName()).isEqualTo("webapp-" + version);
}
private InputStream getDummyInputStream() {
try {
File tmpContentFolder = newTempFolder();
File warTmp = new File(tmpContentFolder, "tmpUpload.war");
warTmp.createNewFile();
return new FileInputStream(warTmp);
} catch (IOException ioe) {
ioe.printStackTrace();
}
return null;
}
private File uploadADummyUpdateJarWithVersion(String version)
throws Exception {
File warContentFolder = new File(newTempFolder(), "webapp-" + version);
File webInf = new File(warContentFolder, "WEB-INF");
File lib = new File(webInf, "lib");
lib.mkdirs();
File coreApp = new File(lib, "core-app-" + version + ".jar");
File coreModel = new File(lib, "core-model-" + version + ".jar");
File coreData = new File(lib, "core-data-" + version + ".jar");
FileUtils.write(coreApp, "The content of core app!");
FileUtils.write(coreModel, "The content of core model!");
FileUtils.write(coreData, "The content of core data!");
getIOLayerFactory().newZipService().zip(uploadWarFile, asList(webInf));
return warContentFolder;
}
private File uploadADummyUpdateJarWithDummyPluginsAndVersion(String version)
throws Exception {
File warContentFolder = new File(newTempFolder(), "webapp-" + version);
File webInf = new File(warContentFolder, "WEB-INF");
File lib = new File(webInf, "lib");
lib.mkdirs();
File coreApp = new File(lib, "core-app-" + version + ".jar");
File coreModel = new File(lib, "core-model-" + version + ".jar");
File coreData = new File(lib, "core-data-" + version + ".jar");
FileUtils.write(coreApp, "The content of core app!");
FileUtils.write(coreModel, "The content of core model!");
FileUtils.write(coreData, "The content of core data!");
File updatedPlugins = new File(warContentFolder, "plugins-to-install");
updatedPlugins.mkdirs();
plugin1 = new File(updatedPlugins, "plugin1.jar");
plugin2 = new File(updatedPlugins, "PLUGIN2.JAR");
notAPlugin = new File(updatedPlugins, "plugin3.zip");
FileUtils.write(plugin1, "A plugin");
FileUtils.write(plugin2, "Another plugin");
FileUtils.write(notAPlugin, "I am not a plugin - Mouhahahaha");
getIOLayerFactory().newZipService().zip(uploadWarFile, asList(webInf, updatedPlugins));
return warContentFolder;
}
private File addVersion(String version)
throws Exception {
File warContentFolder = new File(webappsFolder, "webapp-" + version);
File webInf = new File(warContentFolder, "WEB-INF");
File lib = new File(webInf, "lib");
lib.mkdirs();
File coreApp = new File(lib, "core-app-" + version + ".jar");
File coreModel = new File(lib, "core-model-" + version + ".jar");
File coreData = new File(lib, "core-data-" + version + ".jar");
FileUtils.write(coreApp, "The content of core app!");
FileUtils.write(coreModel, "The content of core model!");
FileUtils.write(coreData, "The content of core data!");
return warContentFolder;
}
private void addFile(File tempFolder, String fileName)
throws IOException {
FileUtils.writeStringToFile(new File(tempFolder, fileName), "a");
}
//TODO add test for recovery
}