/* * RHQ Management Platform * Copyright (C) 2005-2014 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as * published by the Free Software Foundation, and/or the GNU Lesser * General Public License, version 2.1, also as published by the Free * Software Foundation. * * 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 General Public License and the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU General Public License * and the GNU Lesser General Public License along with this program; * if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package org.rhq.bundle.ant; import static org.rhq.core.util.stream.StreamUtil.slurp; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Properties; import java.util.Set; import java.util.Vector; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; import io.undertow.Undertow; import io.undertow.server.HttpHandler; import io.undertow.server.HttpServerExchange; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.tools.ant.BuildListener; import org.apache.tools.ant.DefaultLogger; import org.apache.tools.ant.Project; import org.apache.tools.ant.Target; import org.apache.tools.ant.Task; import org.apache.tools.ant.UnknownElement; import org.apache.tools.ant.helper.AntXMLContext; import org.testng.SkipException; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import org.rhq.bundle.ant.task.BundleTask; import org.rhq.bundle.ant.type.DeploymentUnitType; import org.rhq.bundle.ant.type.HandoverInfo; import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.configuration.definition.ConfigurationDefinition; import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple; import org.rhq.core.domain.configuration.definition.PropertySimpleType; import org.rhq.core.util.ZipUtil; import org.rhq.core.util.file.FileUtil; import org.rhq.core.util.stream.StreamUtil; import org.rhq.core.util.updater.DeploymentsMetadata; import org.rhq.core.util.updater.DestinationComplianceMode; import org.rhq.core.util.updater.FileHashcodeMap; import org.rhq.test.PortScout; /** * @author John Mazzitelli * @author Ian Springer */ @Test public class AntLauncherTest { private static final Log LOG = LogFactory.getLog(AntLauncherTest.class); private static final File DEPLOY_DIR = new File("target/test-ant-bundle").getAbsoluteFile(); private static final File WORKING_DIR = new File("target/test-ant-working-dir").getAbsoluteFile(); private static final String ANT_BASEDIR = "target/test-classes"; private static final File REDHAT_RELEASE_FILE = new File("/etc/redhat-release"); private int deploymentId; @BeforeClass public void beforeClass() { deploymentId = 0; } @BeforeMethod public void beforeTest() { FileUtil.purge(DEPLOY_DIR, true); } @AfterClass public void afterClass() { FileUtil.purge(new File(DEPLOY_DIR.getParentFile(), "test-ant-bundle-sibling"), true); FileUtil.purge(DEPLOY_DIR, true); FileUtil.purge(WORKING_DIR, true); } public void testParse_legacy() throws Exception { testParse(false, "legacy-test-bundle-v1.xml"); } public void testParse() throws Exception { testParse(true, "test-bundle-v1.xml"); } private void testParse(boolean validate, String recipeFile) throws Exception { AntLauncher ant = new AntLauncher(validate); BundleAntProject project = ant.parseBundleDeployFile(getFileFromTestClasses(recipeFile), null); assertNotNull(project); Set<String> bundleFiles = project.getBundleFileNames(); assertNotNull(bundleFiles); assertEquals(bundleFiles.size(), 5, String.valueOf(bundleFiles)); assertTrue(bundleFiles.contains("prepareDatasource.cli"), String.valueOf(bundleFiles)); // handed over file assertTrue(bundleFiles.contains("test-v1.properties"), String.valueOf(bundleFiles)); assertTrue(bundleFiles.contains("file.zip"), String.valueOf(bundleFiles)); assertTrue(bundleFiles.contains("foo-script"), String.valueOf(bundleFiles)); // from install-system-service assertTrue(bundleFiles.contains("foo-config"), String.valueOf(bundleFiles)); // from install-system-service assertEquals(project.getBundleName(), "example.com (JBoss EAP 4.3)"); assertEquals(project.getBundleVersion(), "1.0"); assertEquals(project.getBundleDescription(), "example.com corporate website hosted on JBoss EAP 4.3"); ConfigurationDefinition configDef = project.getConfigurationDefinition(); assertEquals(configDef.getPropertyDefinitions().size(), 1, String.valueOf(configDef.getPropertyDefinitions())); PropertyDefinitionSimple propDef = configDef.getPropertyDefinitionSimple("listener.port"); assertNotNull(propDef); assertEquals(propDef.getType(), PropertySimpleType.INTEGER); assertEquals(propDef.getDefaultValue(), "8080"); assertEquals(propDef.getDescription(), "This is where the product will listen for incoming messages"); assertTrue(propDef.isRequired()); // all we did was parse, nothing should really have been extracted or installed assertFalse(DEPLOY_DIR.exists(), "Nothing should have been installed to the deploy dir"); } public void testParseWithNoDestinationComplianceCheck() throws Exception { //instantiate the launcher in the new validating mode (new as of RHQ 4.9.0) AntLauncher ant = new AntLauncher(true); try { ant.parseBundleDeployFile(getFileFromTestClasses("test-bundle-no-manage-root-dir-nor-compliance.xml"), null); fail("Parsing a bundle with no explicit manageRootDir should have failed."); } catch (InvalidBuildFileException e) { assertEquals(e.getMessage(), "The deployment unit must specifically declare compliance mode of the destination directory."); } BundleAntProject project = ant.parseBundleDeployFile( getFileFromTestClasses("test-bundle-with-manage-root-dir.xml"), null); assertNotNull(project); BundleTask bundleTask = findBundleTask(project); assertNotNull(bundleTask); assertNotNull(bundleTask.getDeploymentUnits()); assertEquals(bundleTask.getDeploymentUnits().size(), 1); DeploymentUnitType deploymentUnit = bundleTask.getDeploymentUnits().values().iterator().next(); assertNotNull(deploymentUnit); //assert the compatibility with the legacy attribute //noinspection deprecation assertEquals(deploymentUnit.getManageRootDir(), "false"); assertEquals(DestinationComplianceMode.filesAndDirectories, deploymentUnit.getCompliance()); // all we did was parse, nothing should really have been extracted or installed assertFalse(DEPLOY_DIR.exists(), "Nothing should have been installed to the deploy dir"); } public void testInstall_legacy() throws Exception { testInstall(false, "legacy-test-bundle-v1.xml"); } @Test(dependsOnMethods = "testUpgrade_legacy") public void testInstall() throws Exception { testInstall(true, "test-bundle-v1.xml"); } private void testInstall(boolean validate, String recipeFile) throws Exception { skipNonRHLinux(); // but we do want to add an unrelated file to see that it goes away - since we have manageRootDir=true File unrelatedFile = writeFile("unrelated content", DEPLOY_DIR, "unrelated-file.txt"); AntLauncher ant = new AntLauncher(validate); Properties inputProps = createInputProperties("/test-bundle-v1-input.properties"); List<BuildListener> buildListeners = createBuildListeners(); BundleAntProject project = ant.executeBundleDeployFile(getFileFromTestClasses(recipeFile), inputProps, buildListeners); assertNotNull(project); Set<String> bundleFiles = project.getBundleFileNames(); assertNotNull(bundleFiles); assertEquals(bundleFiles.size(), 5, String.valueOf(bundleFiles)); assertTrue(bundleFiles.contains("prepareDatasource.cli"), String.valueOf(bundleFiles)); // handed over file assertTrue(bundleFiles.contains("test-v1.properties"), String.valueOf(bundleFiles)); assertTrue(bundleFiles.contains("file.zip"), String.valueOf(bundleFiles)); assertTrue(bundleFiles.contains("foo-script"), String.valueOf(bundleFiles)); // from install-system-service assertTrue(bundleFiles.contains("foo-config"), String.valueOf(bundleFiles)); // from install-system-service assertEquals(project.getBundleName(), "example.com (JBoss EAP 4.3)"); assertEquals(project.getBundleVersion(), "1.0"); assertEquals(project.getBundleDescription(), "example.com corporate website hosted on JBoss EAP 4.3"); ConfigurationDefinition configDef = project.getConfigurationDefinition(); assertEquals(configDef.getPropertyDefinitions().size(), 1, String.valueOf(configDef.getPropertyDefinitions())); PropertyDefinitionSimple propDef = configDef.getPropertyDefinitionSimple("listener.port"); assertNotNull(propDef); assertEquals(propDef.getType(), PropertySimpleType.INTEGER); assertEquals(propDef.getDefaultValue(), "8080"); assertEquals(propDef.getDescription(), "This is where the product will listen for incoming messages"); assertTrue(propDef.isRequired()); // make sure our test infrastruction setup the input properties correctly Configuration config = project.getConfiguration(); assertEquals(config.getProperties().size(), 1, String.valueOf(config.getProperties())); assertEquals(config.getSimpleValue("listener.port", null), "10000", String.valueOf(config.getProperties())); String preinstallTargetExecuted = (String) project.getProperties().get("preinstallTargetExecuted"); assertEquals(preinstallTargetExecuted, "1a"); String postinstallTargetExecuted = (String) project.getProperties().get("postinstallTargetExecuted"); assertEquals(postinstallTargetExecuted, "1b"); assertTrue(new File(DEPLOY_DIR, "subdir/test.properties").exists(), "missing file"); assertTrue(new File(DEPLOY_DIR, "archived-bundle-file.txt").exists(), "missing archived bundle file"); assertTrue(new File(DEPLOY_DIR, "archived-subdir/archived-file-in-subdir.properties").exists(), "missing subdir archive file"); assertFalse(unrelatedFile.exists(), "unrelated file was not removed during the install"); assertEquals(readPropsFile(new File(DEPLOY_DIR, "subdir/test.properties")).getProperty("junk.listener.port"), "10000"); assertEquals(readPropsFile(new File(DEPLOY_DIR, "archived-subdir/archived-file-in-subdir.properties")) .getProperty("templatized.variable"), "10000"); } private void skipNonRHLinux() { if (!System.getProperty("os.name").equals("Linux") || !REDHAT_RELEASE_FILE.exists()) { throw new SkipException("This test only works on Red Hat Linux flavors"); } } @Test(dependsOnMethods = "testInstall_legacy") public void testUpgrade_legacy() throws Exception { testUpgrade(false, "legacy-test-bundle-v2.xml"); } @Test(dependsOnMethods = "testInstall") public void testUpgrade() throws Exception { testUpgrade(true, "test-bundle-v2.xml"); } private void testUpgrade(boolean validate, String recipeFile) throws Exception { skipNonRHLinux(); // add an unrelated file to see that it gets deleted as part of the upgrade File unrelatedFile = writeFile("unrelated content", DEPLOY_DIR, "unrelated-file.txt"); AntLauncher ant = new AntLauncher(validate); Properties inputProps = createInputProperties("/test-bundle-v2-input.properties"); List<BuildListener> buildListeners = createBuildListeners(); BundleAntProject project = ant.executeBundleDeployFile(getFileFromTestClasses(recipeFile), inputProps, buildListeners); assertNotNull(project); Set<String> bundleFiles = project.getBundleFileNames(); assertNotNull(bundleFiles); assertEquals(bundleFiles.size(), 5, String.valueOf(bundleFiles)); assertTrue(bundleFiles.contains("fileToHandover.zip"), String.valueOf(bundleFiles)); // handed over file assertTrue(bundleFiles.contains("test-v2.properties"), String.valueOf(bundleFiles)); assertTrue(bundleFiles.contains("file.zip"), String.valueOf(bundleFiles)); assertTrue(bundleFiles.contains("foo-script"), String.valueOf(bundleFiles)); // from install-system-service assertTrue(bundleFiles.contains("foo-config"), String.valueOf(bundleFiles)); // from install-system-service assertEquals(project.getBundleName(), "example.com (JBoss EAP 4.3)"); assertEquals(project.getBundleVersion(), "2.5"); assertEquals(project.getBundleDescription(), "updated bundle"); ConfigurationDefinition configDef = project.getConfigurationDefinition(); assertEquals(configDef.getPropertyDefinitions().size(), 1, String.valueOf(configDef.getPropertyDefinitions())); PropertyDefinitionSimple propDef = configDef.getPropertyDefinitionSimple("listener.port"); assertNotNull(propDef); assertEquals(propDef.getType(), PropertySimpleType.INTEGER); assertEquals(propDef.getDefaultValue(), "9090"); assertEquals(propDef.getDescription(), "This is where the product will listen for incoming messages"); assertTrue(propDef.isRequired()); // make sure our test infrastruction setup the input properties correctly Configuration config = project.getConfiguration(); assertEquals(config.getProperties().size(), 1); assertEquals(config.getSimpleValue("listener.port", null), "20000", String.valueOf(config.getProperties())); String preinstallTargetExecuted = (String) project.getProperties().get("preinstallTargetExecuted"); assertEquals(preinstallTargetExecuted, "2a"); String postinstallTargetExecuted = (String) project.getProperties().get("postinstallTargetExecuted"); assertEquals(postinstallTargetExecuted, "2b"); assertTrue(new File(DEPLOY_DIR, "subdir/test.properties").exists(), "missing file"); assertTrue(new File(DEPLOY_DIR, "archived-bundle-file.txt").exists(), "missing archived bundle file"); assertTrue(new File(DEPLOY_DIR, "archived-subdir/archived-file-in-subdir.properties").exists(), "missing subdir archive file"); assertFalse(unrelatedFile.exists(), "we are managing root dir so unrelated file should be removed during upgrade"); assertEquals(readPropsFile(new File(DEPLOY_DIR, "subdir/test.properties")).getProperty("junk.listener.port"), "20000"); assertEquals(readPropsFile(new File(DEPLOY_DIR, "archived-subdir/archived-file-in-subdir.properties")) .getProperty("templatized.variable"), "20000"); } public void testUpgradeNoManageRootDir_legacy() throws Exception { testUpgradeNoManageRootDir(false, "legacy-test-bundle-v2-noManageRootDir.xml"); } public void testUpgradeNoManageRootDir() throws Exception { testUpgradeNoManageRootDir(true, "test-bundle-v2-filesAndDirectories.xml"); } private void testUpgradeNoManageRootDir(boolean validate, String recipeFile) throws Exception { skipNonRHLinux(); // We want to test an upgrade, so do *not* wipe out the deploy dir - let's re-invoke testInstall // to get us to an initial state of the v1 bundle installed testInstall(); // we still want the unrelated file - we want to see that manageRootDir=false works (unrelated files should not be deleted) File unrelatedFile = writeFile("unrelated content", DEPLOY_DIR, "unrelated-file.txt"); assertTrue(unrelatedFile.exists(), "our initial install test method should have prepared an unmanaged file"); AntLauncher ant = new AntLauncher(validate); Properties inputProps = createInputProperties("/test-bundle-v2-input.properties"); List<BuildListener> buildListeners = createBuildListeners(); BundleAntProject project = ant.executeBundleDeployFile(getFileFromTestClasses(recipeFile), inputProps, buildListeners); assertNotNull(project); Set<String> bundleFiles = project.getBundleFileNames(); assertNotNull(bundleFiles); assertEquals(bundleFiles.size(), 4, String.valueOf(bundleFiles)); assertTrue(bundleFiles.contains("test-v2.properties"), String.valueOf(bundleFiles)); assertTrue(bundleFiles.contains("file.zip"), String.valueOf(bundleFiles)); assertTrue(bundleFiles.contains("foo-script"), String.valueOf(bundleFiles)); // from install-system-service assertTrue(bundleFiles.contains("foo-config"), String.valueOf(bundleFiles)); // from install-system-service assertEquals(project.getBundleName(), "example.com (JBoss EAP 4.3)"); assertEquals(project.getBundleVersion(), "2.5"); assertEquals(project.getBundleDescription(), "updated bundle"); ConfigurationDefinition configDef = project.getConfigurationDefinition(); assertEquals(configDef.getPropertyDefinitions().size(), 1, String.valueOf(configDef.getPropertyDefinitions())); PropertyDefinitionSimple propDef = configDef.getPropertyDefinitionSimple("listener.port"); assertNotNull(propDef); assertEquals(propDef.getType(), PropertySimpleType.INTEGER); assertEquals(propDef.getDefaultValue(), "9090"); assertEquals(propDef.getDescription(), "This is where the product will listen for incoming messages"); assertTrue(propDef.isRequired()); // make sure our test infrastruction setup the input properties correctly Configuration config = project.getConfiguration(); assertEquals(config.getProperties().size(), 1); assertEquals(config.getSimpleValue("listener.port", null), "20000", String.valueOf(config.getProperties())); String preinstallTargetExecuted = (String) project.getProperties().get("preinstallTargetExecuted"); assertEquals(preinstallTargetExecuted, "2a"); String postinstallTargetExecuted = (String) project.getProperties().get("postinstallTargetExecuted"); assertEquals(postinstallTargetExecuted, "2b"); assertTrue(new File(DEPLOY_DIR, "subdir/test.properties").exists(), "missing file"); assertTrue(new File(DEPLOY_DIR, "archived-bundle-file.txt").exists(), "missing archived bundle file"); assertTrue(new File(DEPLOY_DIR, "archived-subdir/archived-file-in-subdir.properties").exists(), "missing subdir archive file"); assertTrue(unrelatedFile.exists(), "we are NOT managing root dir so unrelated file should NOT be removed during upgrade"); assertEquals(readPropsFile(new File(DEPLOY_DIR, "subdir/test.properties")).getProperty("junk.listener.port"), "20000"); assertEquals(readPropsFile(new File(DEPLOY_DIR, "archived-subdir/archived-file-in-subdir.properties")) .getProperty("templatized.variable"), "20000"); } public void testInstallCompressedZipNoDryRun_legacy() throws Exception { testInstallCompressedZip(false, false, "legacy-test-bundle-compressed-archives.xml"); } public void testInstallCompressedZipNoDryRun() throws Exception { testInstallCompressedZip(false, true, "test-bundle-compressed-archives.xml"); } public void testInstallCompressedZipDryRun_legacy() throws Exception { testInstallCompressedZip(true, false, "legacy-test-bundle-compressed-archives.xml"); } public void testInstallCompressedZipDryRun() throws Exception { testInstallCompressedZip(true, true, "test-bundle-compressed-archives.xml"); } private void testInstallCompressedZip(boolean dryRun, boolean validate, String recipeFile) throws Exception { AntLauncher ant = new AntLauncher(validate); Properties inputProps = createInputProperties("/test-bundle-compressed-archives-input.properties", dryRun); List<BuildListener> buildListeners = createBuildListeners(); BundleAntProject project = ant.executeBundleDeployFile(getFileFromTestClasses(recipeFile), inputProps, buildListeners); assertNotNull(project); Set<String> bundleFiles = project.getBundleFileNames(); assertNotNull(bundleFiles); assertEquals(bundleFiles.size(), 1, String.valueOf(bundleFiles)); assertTrue(bundleFiles.contains("file.zip"), String.valueOf(bundleFiles)); assertEquals(project.getBundleName(), "test compressed archive files"); assertEquals(project.getBundleVersion(), "1.0"); assertNull(project.getBundleDescription()); // while we are here, let's see that we have 0 config props ConfigurationDefinition configDef = project.getConfigurationDefinition(); assertEquals(configDef.getPropertyDefinitions().size(), 0, String.valueOf(configDef.getPropertyDefinitions())); Configuration config = project.getConfiguration(); assertEquals(config.getProperties().size(), 0, String.valueOf(config.getProperties())); if (!dryRun) { assertTrue(new File(DEPLOY_DIR, "file.zip").exists(), "should be here, we told it to stay compressed"); } else { assertFalse(new File(DEPLOY_DIR, "file.zip").exists(), "dry run - should not be here"); } assertFalse(new File(DEPLOY_DIR, "archived-bundle-file.txt").exists(), "should not have exploded this"); assertFalse(new File(DEPLOY_DIR, "archived-subdir/archived-file-in-subdir.properties").exists(), "should not have exploded this"); assertFalse(new File(DEPLOY_DIR, "archived-subdir").isDirectory(), "should not still have the exploded dir"); DeploymentsMetadata dm = new DeploymentsMetadata(DEPLOY_DIR); if (!dryRun) { FileHashcodeMap fhm = dm.getCurrentDeploymentFileHashcodes(); assertFalse(fhm.containsKey("archived-bundle-file.txt"), "should not have metadata - this is inside the compressed zip"); assertFalse(fhm.containsKey("archived-subdir/archived-file-in-subdir.properties"), "should not have metadata - this is inside the compressed zip"); assertTrue(fhm.containsKey("file.zip"), String .valueOf("should have metadata for this - we didn't explode it, we just have this compressed file")); // test that we created the zip OK. Note that our test did not do any file replacing/realization of templates final String[] templateVarValue = new String[1]; final int[] entries = new int[1]; ZipUtil.walkZipFile(new File(DEPLOY_DIR, "file.zip"), new ZipUtil.ZipEntryVisitor() { @Override public boolean visit(ZipEntry entry, ZipInputStream stream) throws Exception { if (entry.getName().equals("archived-subdir/archived-file-in-subdir.properties")) { Properties props = new Properties(); props.load(stream); templateVarValue[0] = props.getProperty("templatized.variable"); } if (!entry.isDirectory()) { entries[0] = entries[0] + 1; } return true; } }); assertNotNull(templateVarValue[0]); assertEquals(templateVarValue[0], "@@listener.port@@"); assertEquals(entries[0], 2, String.valueOf(entries[0])); // we only counted the file entries } else { try { dm.getCurrentDeploymentFileHashcodes(); fail("this was a dry run, we should not have written our metadata to the filesystem"); } catch (Exception e) { // expected } } } public void testInstallCompressedZipWithTemplatizedFilesNoDryRun_legacy() throws Exception { testInstallCompressedZipWithTemplatizedFiles(false, false, "legacy-test-bundle-compressed-archives-with-replace.xml"); } public void testInstallCompressedZipWithTemplatizedFilesNoDryRun() throws Exception { testInstallCompressedZipWithTemplatizedFiles(false, true, "test-bundle-compressed-archives-with-replace.xml"); } public void testInstallCompressedZipWithTemplatizedFilesDryRun_legacy() throws Exception { testInstallCompressedZipWithTemplatizedFiles(true, false, "legacy-test-bundle-compressed-archives-with-replace.xml"); } public void testInstallCompressedZipWithTemplatizedFilesDryRun() throws Exception { testInstallCompressedZipWithTemplatizedFiles(true, true, "test-bundle-compressed-archives-with-replace.xml"); } private void testInstallCompressedZipWithTemplatizedFiles(boolean dryRun, boolean validate, String recipeFile) throws Exception { AntLauncher ant = new AntLauncher(validate); Properties inputProps = createInputProperties("/test-bundle-compressed-archives-input.properties", dryRun); List<BuildListener> buildListeners = createBuildListeners(); BundleAntProject project = ant.executeBundleDeployFile(getFileFromTestClasses(recipeFile), inputProps, buildListeners); assertNotNull(project); Set<String> bundleFiles = project.getBundleFileNames(); assertNotNull(bundleFiles); assertEquals(bundleFiles.size(), 1, String.valueOf(bundleFiles)); assertTrue(bundleFiles.contains("file.zip"), String.valueOf(bundleFiles)); assertEquals(project.getBundleName(), "test compressed archive files"); assertEquals(project.getBundleVersion(), "1.0"); assertNull(project.getBundleDescription()); // we have one property that we use to realize our content ConfigurationDefinition configDef = project.getConfigurationDefinition(); assertEquals(configDef.getPropertyDefinitions().size(), 1, String.valueOf(configDef.getPropertyDefinitions())); PropertyDefinitionSimple propDef = configDef.getPropertyDefinitionSimple("listener.port"); assertNotNull(propDef); assertEquals(propDef.getType(), PropertySimpleType.INTEGER); assertNull(propDef.getDefaultValue(), "recipe didn't define a default for our property"); assertNull(propDef.getDescription(), "recipe didn't define a description for our property"); assertTrue(propDef.isRequired(), "recipe didn't make the property required, but the default should be required"); if (!dryRun) { assertTrue(new File(DEPLOY_DIR, "file.zip").exists(), "should be here, we told it to stay compressed"); } else { assertFalse(new File(DEPLOY_DIR, "file.zip").exists(), "this was a dry run, should not be here"); } assertFalse(new File(DEPLOY_DIR, "archived-bundle-file.txt").exists(), "should not have exploded this"); assertFalse(new File(DEPLOY_DIR, "archived-subdir/archived-file-in-subdir.properties").exists(), "should not have exploded this"); assertFalse(new File(DEPLOY_DIR, "archived-subdir").isDirectory(), "should not still have the exploded dir"); DeploymentsMetadata dm = new DeploymentsMetadata(DEPLOY_DIR); if (!dryRun) { FileHashcodeMap fhm = dm.getCurrentDeploymentFileHashcodes(); assertFalse(fhm.containsKey("archived-bundle-file.txt"), "should not have metadata - this is inside the compressed zip"); assertFalse(fhm.containsKey("archived-subdir/archived-file-in-subdir.properties"), "should not have metadata - this is inside the compressed zip"); assertTrue(fhm.containsKey("file.zip"), String .valueOf("should have metadata for this - we didn't explode it, we just have this compressed file")); // test that the file in the zip is realized final String[] templateVarValue = new String[1]; final int[] entries = new int[1]; ZipUtil.walkZipFile(new File(DEPLOY_DIR, "file.zip"), new ZipUtil.ZipEntryVisitor() { @Override public boolean visit(ZipEntry entry, ZipInputStream stream) throws Exception { if (entry.getName().equals("archived-subdir/archived-file-in-subdir.properties")) { Properties props = new Properties(); props.load(stream); templateVarValue[0] = props.getProperty("templatized.variable"); } if (!entry.isDirectory()) { entries[0] = entries[0] + 1; } return true; } }); assertNotNull(templateVarValue[0]); assertEquals(templateVarValue[0], "12345"); assertEquals(entries[0], 2, String.valueOf(entries[0])); // we only counted the file entries } else { try { dm.getCurrentDeploymentFileHashcodes(); fail("this was a dry run, we should not have written our metadata to the filesystem"); } catch (Exception e) { // expected } } } public void testAuditMessages_legacy() throws Exception { testAuditMessages(false, "legacy-test-bundle-audit.xml"); } public void testAuditMessages() throws Exception { testAuditMessages(true, "test-bundle-audit.xml"); } // this doesn't verify the audit messages getting emitted are correct // but it does verify the audit tag getting processed correctly. // you have to look at the test logs to see the audit messages // TODO: write a ant build listener to listen for this messages, parse them and verify they are correct // this test should then ask the listener at the end if everything was OK and assertTrue(false if not private void testAuditMessages(boolean validate, String recipeFile) throws Exception { AntLauncher ant = new AntLauncher(validate); Properties inputProps = createInputProperties("/test-audit-input.properties"); List<BuildListener> buildListeners = createBuildListeners(); BundleAntProject project = ant.executeBundleDeployFile(getFileFromTestClasses(recipeFile), inputProps, buildListeners); assertNotNull(project); Set<String> bundleFiles = project.getBundleFileNames(); assertNotNull(bundleFiles); assertEquals(bundleFiles.size(), 1, String.valueOf(bundleFiles)); assertTrue(bundleFiles.contains("test-audit.properties"), String.valueOf(bundleFiles)); // sanity check - make sure our recipe defined this property ConfigurationDefinition configDef = project.getConfigurationDefinition(); assertEquals(configDef.getPropertyDefinitions().size(), 1, String.valueOf(configDef.getPropertyDefinitions())); PropertyDefinitionSimple propDef = configDef.getPropertyDefinitionSimple("listener.port"); assertNotNull(propDef); // make sure our test infrastruction setup the input properties correctly Configuration config = project.getConfiguration(); assertEquals(config.getProperties().size(), 1, String.valueOf(config.getProperties())); assertEquals(config.getSimpleValue("listener.port", null), "777", String.valueOf(config.getProperties())); String preinstallTargetExecuted = (String) project.getProperties().get("preinstallTargetExecuted"); assertEquals(preinstallTargetExecuted, "1a"); String postinstallTargetExecuted = (String) project.getProperties().get("postinstallTargetExecuted"); assertEquals(postinstallTargetExecuted, "1b"); assertTrue(new File(DEPLOY_DIR, "test-audit.properties").exists(), "missing file"); assertEquals(readPropsFile(new File(DEPLOY_DIR, "test-audit.properties")).getProperty("my.listener.port"), "777"); } public void testSubdirectoriesInRecipe_legacy() throws Exception { testSubdirectoriesInRecipe(false, "legacy-test-bundle-subdir.xml"); } public void testSubdirectoriesInRecipe() throws Exception { testSubdirectoriesInRecipe(true, "test-bundle-subdir.xml"); } private void testSubdirectoriesInRecipe(boolean validate, String origRecipeFile) throws Exception { // we need to create our own directory structure - let's build a temporary ant basedir // and put our recipe in there as well as a subdirectory with a test raw file and test zip file File antBasedir = FileUtil.createTempDirectory("anttest", ".test", null); try { File subdir = new File(antBasedir, "subdir"); // must match the name in the recipe subdir.mkdirs(); writeFile("file0", subdir, "test0.txt"); // filename must match recipe writeFile("file1", subdir, "test1.txt"); // filename must match recipe writeFile("file2", subdir, "test2.txt"); // filename must match recipe createZip(new String[] { "one", "two" }, subdir, "test.zip", new String[] { "one.txt", "two.txt" }); createZip(new String[] { "3", "4" }, subdir, "test-explode.zip", new String[] { "three.txt", "four.txt" }); createZip(new String[] { "X=@@X@@\n" }, subdir, "test-replace.zip", new String[] { "template.txt" }); // will be exploded then recompressed createZip(new String[] { "X=@@X@@\n" }, subdir, "test-replace2.zip", new String[] { "template.txt" }); // will be exploded then recompressed File recipeFile = new File(antBasedir, "deploy.xml"); FileUtil.copyFile(new File(ANT_BASEDIR, origRecipeFile), recipeFile); AntLauncher ant = new AntLauncher(validate); Properties inputProps = new Properties(); inputProps.setProperty(DeployPropertyNames.DEPLOY_DIR, DEPLOY_DIR.getPath()); inputProps.setProperty(DeployPropertyNames.DEPLOY_ID, String.valueOf(++this.deploymentId)); inputProps.setProperty(DeployPropertyNames.DEPLOY_PHASE, DeploymentPhase.INSTALL.name()); inputProps.setProperty("X", "alpha-omega"); List<BuildListener> buildListeners = createBuildListeners(); BundleAntProject project = ant.executeBundleDeployFile(recipeFile, inputProps, buildListeners); assertNotNull(project); Set<String> bundleFiles = project.getBundleFileNames(); assertNotNull(bundleFiles); assertEquals(bundleFiles.size(), 7, String.valueOf(bundleFiles)); assertTrue(bundleFiles.contains("subdir/test0.txt"), String.valueOf(bundleFiles)); assertTrue(bundleFiles.contains("subdir/test1.txt"), String.valueOf(bundleFiles)); assertTrue(bundleFiles.contains("subdir/test2.txt"), String.valueOf(bundleFiles)); assertTrue(bundleFiles.contains("subdir/test.zip"), String.valueOf(bundleFiles)); assertTrue(bundleFiles.contains("subdir/test-explode.zip"), String.valueOf(bundleFiles)); assertTrue(bundleFiles.contains("subdir/test-replace.zip"), String.valueOf(bundleFiles)); assertTrue(bundleFiles.contains("subdir/test-replace2.zip"), String.valueOf(bundleFiles)); assertTrue(new File(DEPLOY_DIR, "subdir/test0.txt").exists(), "missing raw file from default destination location"); assertTrue(new File(DEPLOY_DIR, "another/foo.txt").exists(), "missing raw file from the destinationFile"); assertTrue(new File(DEPLOY_DIR, "second.dir/test2.txt").exists(), "missing raw file from the destinationDir"); assertFalse(new File(DEPLOY_DIR, "subdir/test1.txt").exists(), "should not be here because destinationFile was specified"); assertFalse(new File(DEPLOY_DIR, "subdir/test2.txt").exists(), "should not be here because destinationFile was specified"); assertTrue(new File(DEPLOY_DIR, "subdir/test.zip").exists(), "missing unexploded zip file"); assertTrue(new File(DEPLOY_DIR, "subdir/test-replace.zip").exists(), "missing unexploded zip file"); assertTrue(new File(DEPLOY_DIR, "second.dir/test-replace2.zip").exists(), "missing unexploded second zip file"); assertFalse(new File(DEPLOY_DIR, "subdir/test-explode.zip").exists(), "should have been exploded"); // test that the file in the zip is realized final String[] templateVarValue = new String[] { null }; ZipUtil.walkZipFile(new File(DEPLOY_DIR, "subdir/test-replace.zip"), new ZipUtil.ZipEntryVisitor() { @Override public boolean visit(ZipEntry entry, ZipInputStream stream) throws Exception { if (entry.getName().equals("template.txt")) { Properties props = new Properties(); props.load(stream); templateVarValue[0] = props.getProperty("X"); } return true; } }); assertNotNull(templateVarValue[0]); assertEquals(templateVarValue[0], "alpha-omega"); // test that the file in the second zip is realized final String[] templateVarValue2 = new String[] { null }; ZipUtil.walkZipFile(new File(DEPLOY_DIR, "second.dir/test-replace2.zip"), new ZipUtil.ZipEntryVisitor() { @Override public boolean visit(ZipEntry entry, ZipInputStream stream) throws Exception { if (entry.getName().equals("template.txt")) { Properties props = new Properties(); props.load(stream); templateVarValue2[0] = props.getProperty("X"); } return true; } }); assertNotNull(templateVarValue2[0]); assertEquals(templateVarValue2[0], "alpha-omega"); } finally { FileUtil.purge(antBasedir, true); } } public void testUrlFilesAndArchives_legacy() throws Exception { testUrlFilesAndArchives(false, "legacy-test-bundle-url.xml"); } public void testUrlFilesAndArchives() throws Exception { testUrlFilesAndArchives(true, "test-bundle-url.xml"); } public void testNotDeployedPropertyFile() throws Exception { testNotDeployedFiles(getFileFromTestClasses("ant-properties/deploy.xml.properties-in-bundle"), true, false); } public void testNotDeployedRhqPropertyFile() throws Exception { testNotDeployedFiles(getFileFromTestClasses("ant-properties/deploy.xml.rhq-property-tag-in-bundle"), true, false); } public void testDeployedPropertyFile() throws Exception { testNotDeployedFiles(getFileFromTestClasses("ant-properties/deploy.xml.properties-in-bundle-props-deployed"), true, true); } public void testAntPropertiesUsedForTokenReplacement() throws Exception { testNotDeployedPropertyFile(); checkPropertiesFromExternalFileReplaced(); } public void testAntPropertiesLoadFromAbsolutePath() throws Exception { File tempDir = FileUtil.createTempDirectory("ant-launcher-test", null, null); try { //prepare the test bundle.. update the recipe with an absolute path to a properties file. File deployXml = new File(tempDir, "deploy.xml"); FileUtil.copyFile(getFileFromTestClasses("ant-properties/deploy.xml.properties-out-of-bundle"), deployXml); //copy the other file from the bundle, too, into the correct location FileUtil.copyFile(getFileFromTestClasses("ant-properties/deployed.file"), new File(tempDir, "deployed.file")); File absoluteLocation = new File(tempDir, "absolute-location"); assert absoluteLocation.mkdir() : "Failed to create dir under temp"; String deployXmlContents = StreamUtil.slurp(new InputStreamReader(new FileInputStream(deployXml))); File absolutePropertiesLocation = new File(absoluteLocation, "in-bundle.properties"); FileUtil .copyFile(getFileFromTestClasses("ant-properties/in-bundle.properties"), absolutePropertiesLocation); deployXmlContents = deployXmlContents.replace("%%REPLACE_ME%%", "file=\"" + absolutePropertiesLocation.getAbsolutePath() + "\""); FileUtil.writeFile(new ByteArrayInputStream(deployXmlContents.getBytes()), deployXml); //k, now the test itself... testNotDeployedFiles(deployXml, false, false); checkPropertiesFromExternalFileReplaced(); } finally { FileUtil.purge(tempDir, true); } } public void testAntPropertiesLoadFromURL() throws Exception { File tempDir = FileUtil.createTempDirectory("ant-launcher-test", null, null); Undertow undertow = null; try { //prepare the test bundle.. update the recipe with an absolute path to a properties file. File deployXml = new File(tempDir, "deploy.xml"); FileUtil.copyFile(getFileFromTestClasses("ant-properties/deploy.xml.properties-out-of-bundle"), deployXml); //copy the other file from the bundle, too, into the correct location FileUtil.copyFile(getFileFromTestClasses("ant-properties/deployed.file"), new File(tempDir, "deployed.file")); //fire up minimal server PortScout portScout = new PortScout(); int port = 0; try { port = portScout.getNextFreePort(); } finally { portScout.close(); } undertow = Undertow.builder().addHttpListener(port, "localhost").setHandler(new HttpHandler() { @Override public void handleRequest(HttpServerExchange httpServerExchange) throws Exception { httpServerExchange.startBlocking(); FileInputStream in = new FileInputStream( getFileFromTestClasses("ant-properties/in-bundle.properties")); try { StreamUtil.copy(in, httpServerExchange.getOutputStream(), false); } catch (Exception e) { LOG.error("Failed to handle the HTTP request for loading properties.", e); throw e; } finally { StreamUtil.safeClose(in); } } }).build(); undertow.start(); String deployXmlContents = StreamUtil.slurp(new InputStreamReader(new FileInputStream(deployXml))); deployXmlContents = deployXmlContents.replace("%%REPLACE_ME%%", "url=\"http://localhost:" + port + "\""); FileUtil.writeFile(new ByteArrayInputStream(deployXmlContents.getBytes()), deployXml); //k, now the test itself... testNotDeployedFiles(deployXml, false, false); checkPropertiesFromExternalFileReplaced(); } finally { FileUtil.purge(tempDir, true); if (undertow != null) { undertow.stop(); } } } public void testRhqPropertiesLoadFromDestination() throws Exception { File sideDir = new File(DEPLOY_DIR.getParentFile(), "test-ant-bundle-sibling"); assert sideDir.mkdir() : "Failed to create a side directory"; FileUtil.copyFile(getFileFromTestClasses("ant-properties/in-bundle.properties"), new File(sideDir, "in-bundle.properties")); testNotDeployedFiles(getFileFromTestClasses("ant-properties/deploy.xml.rhq-property-tag-in-destination"), false, false); } private void testNotDeployedFiles(File deployXml, boolean expectPropertiesFileInBundle, boolean expectPropertiesFileInDestination) throws Exception { FileUtil.purge(DEPLOY_DIR, true); FileUtil.purge(WORKING_DIR, true); FileUtil.copyDirectory(deployXml.getParentFile(), WORKING_DIR); deployXml = new File(WORKING_DIR, deployXml.getName()); AntLauncher ant = new AntLauncher(true); Properties inputProps = createInputProperties(null); List<BuildListener> buildListeners = createBuildListeners(); BundleAntProject project = ant.executeBundleDeployFile(deployXml, inputProps, buildListeners); assert project != null; Set<String> bundleFiles = project.getBundleFileNames(); assert bundleFiles != null; assert bundleFiles.size() == (expectPropertiesFileInBundle ? 2 : 1) : bundleFiles; assert bundleFiles.contains("deployed.file") : bundleFiles; assert !expectPropertiesFileInBundle || bundleFiles.contains("in-bundle.properties") : bundleFiles; assert new File(DEPLOY_DIR, "deployed.file").exists() : "deployed.file missing"; assert expectPropertiesFileInDestination == new File(DEPLOY_DIR, "in-bundle.properties").exists() : "in-bundle.properties " + (expectPropertiesFileInDestination ? "not deployed but should have" : "deployed but shouldn't have"); } private void checkPropertiesFromExternalFileReplaced() throws Exception { Properties props = readPropsFile(new File(DEPLOY_DIR, "deployed.file")); assert "user provided value".equals(props.getProperty("user.provided")) : "user.provided"; assert "bundle provided value".equals(props.getProperty("bundle.provided")) : "bundle.provided"; assert "a".equals(props.get("a.from.properties.file")) : "a.from.properties.file"; assert "b".equals(props.get("b.from.properties.file")) : "b.from.properties.file"; } private void testUrlFilesAndArchives(boolean validate, String recipeFile) throws Exception { // we need to create our own directory structure so we can use file: URLs File tmpUrlLocation = FileUtil.createTempDirectory("anttest", ".url", null); Set<File> downloadedFiles = null; try { File subdir = new File(tmpUrlLocation, "subdir"); // must match the name in the recipe subdir.mkdirs(); writeFile("file0", subdir, "test0.txt"); // filename must match recipe writeFile("file1", subdir, "test1.txt"); // filename must match recipe writeFile("X=@@X@@\n", subdir, "test2.txt"); // filename must match recipe writeFile("pipo", subdir, "prepareDatasource.cli"); // filename must match recipe createZip(new String[] { "one", "two" }, subdir, "test.zip", new String[] { "one.txt", "two.txt" }); createZip(new String[] { "3", "4" }, subdir, "test-explode.zip", new String[] { "three.txt", "four.txt" }); createZip(new String[] { "X=@@X@@\n" }, subdir, "test-replace.zip", new String[] { "template.txt" }); // will be exploded then recompressed createZip(new String[] { "one", "two" }, subdir, "fileToHandover.zip", new String[] { "one.txt", "two.txt" }); AntLauncher ant = new AntLauncher(validate); Properties inputProps = createInputProperties("/test-bundle-url-input.properties"); inputProps.setProperty("rhq.test.url.dir", tmpUrlLocation.toURI().toURL().toString()); // we use this so our recipe can use URLs List<BuildListener> buildListeners = createBuildListeners(); BundleAntProject project = ant.executeBundleDeployFile(getFileFromTestClasses(recipeFile), inputProps, buildListeners); assertNotNull(project); Set<String> bundleFiles = project.getBundleFileNames(); assertNotNull(bundleFiles); assertEquals(bundleFiles.size(), 0, "we don't have any bundle files - only downloaded files from URLs: " + bundleFiles); downloadedFiles = project.getDownloadedFiles(); assertNotNull(downloadedFiles); assertEquals(downloadedFiles.size(), 8, String.valueOf(downloadedFiles)); ArrayList<String> expectedDownloadedFileNames = new ArrayList<String>(); // remember, we store url downloaded files under the names of their destination file/dir, not source location expectedDownloadedFileNames.add("test0.txt"); expectedDownloadedFileNames.add("foo.txt"); expectedDownloadedFileNames.add("test2.txt"); expectedDownloadedFileNames.add("prepareDatasource.cli"); expectedDownloadedFileNames.add("test.zip"); expectedDownloadedFileNames.add("test-explode.zip"); expectedDownloadedFileNames.add("test-replace.zip"); expectedDownloadedFileNames.add("fileToHandover.zip"); for (File downloadedFile : downloadedFiles) { assertTrue(expectedDownloadedFileNames.contains(downloadedFile.getName()), "We downloaded a file but its not in the project's list: " + downloadedFile); } assertTrue(new File(DEPLOY_DIR, "test0.txt").exists(), "missing raw file from default destination location"); assertTrue(new File(DEPLOY_DIR, "another/foo.txt").exists(), "missing raw file from the destinationFile"); assertTrue(new File(DEPLOY_DIR, "second.dir/test2.txt").exists(), "missing raw file from the destinationDir"); assertFalse(new File(DEPLOY_DIR, "test1.txt").exists(), "should not be here because destinationFile was specified"); assertFalse(new File(DEPLOY_DIR, "test2.txt").exists(), "should not be here because destinationFile was specified"); assertTrue(new File(DEPLOY_DIR, "test.zip").exists(), "missing unexploded zip file"); assertTrue(new File(DEPLOY_DIR, "test-replace.zip").exists(), "missing unexploded zip file"); assertFalse(new File(DEPLOY_DIR, "test-explode.zip").exists(), "should have been exploded"); // test that the file in the zip is realized final String[] templateVarValue = new String[] { null }; ZipUtil.walkZipFile(new File(DEPLOY_DIR, "test-replace.zip"), new ZipUtil.ZipEntryVisitor() { @Override public boolean visit(ZipEntry entry, ZipInputStream stream) throws Exception { if (entry.getName().equals("template.txt")) { Properties props = new Properties(); props.load(stream); templateVarValue[0] = props.getProperty("X"); } return true; } }); assertNotNull(templateVarValue[0]); assertEquals(templateVarValue[0], "9876"); // test that our raw file was realized File realizedFile = new File(DEPLOY_DIR, "second.dir/test2.txt"); Properties props = new Properties(); FileInputStream inStream = new FileInputStream(realizedFile); try { props.load(inStream); assertEquals(props.getProperty("X", "<unset>"), "9876"); } finally { inStream.close(); } } finally { FileUtil.purge(tmpUrlLocation, true); if (downloadedFiles != null) { for (File doomed : downloadedFiles) { doomed.delete(); } } } } public void testHandover() throws Exception { AntLauncher ant = new AntLauncher(true); final List<HandoverInfoArgument> handoverInfoArguments = new ArrayList<HandoverInfoArgument>(); HandoverTarget handoverTarget = new HandoverTarget() { @Override public boolean handoverContent(HandoverInfo handoverInfo) { HandoverInfoArgument handoverInfoArgument; try { handoverInfoArgument = new HandoverInfoArgument(handoverInfo); } catch (IOException e) { return false; } handoverInfoArguments.add(handoverInfoArgument); try { FileUtil.writeFile(handoverInfo.getContent(), handoverInfoArgument.handoverInfoTestContentFile); } catch (IOException e) { e.printStackTrace(); } return true; } }; ant.setHandoverTarget(handoverTarget); List<BuildListener> buildListeners = createBuildListeners(); Properties inputProps = createInputProperties("/handover-test-bundle-input.properties"); BundleAntProject project = ant.executeBundleDeployFile(getFileFromTestClasses("handover-test-bundle.xml"), inputProps, buildListeners); assertNotNull(project); assertEquals(project.getBundleName(), "example.com (EAP 6)"); assertEquals(project.getBundleVersion(), "1.0"); assertEquals(project.getBundleDescription(), "example.com corporate website hosted on EAP 6"); Set<String> bundleFiles = project.getBundleFileNames(); assertNotNull(bundleFiles); assertEquals(bundleFiles.size(), 2, String.valueOf(bundleFiles)); assertTrue(bundleFiles.contains("prepareDatasource.cli"), String.valueOf(bundleFiles)); // handed over file assertTrue(bundleFiles.contains("fileToHandover.zip"), String.valueOf(bundleFiles)); // handed over archive ConfigurationDefinition projectConfigDef = project.getConfigurationDefinition(); assertEquals(projectConfigDef.getPropertyDefinitions().size(), 3, String.valueOf(projectConfigDef.getPropertyDefinitions())); PropertyDefinitionSimple propDef = projectConfigDef.getPropertyDefinitionSimple("myapp.datasource.property"); assertNotNull(propDef); assertEquals(propDef.getType(), PropertySimpleType.INTEGER); assertTrue(propDef.isRequired()); propDef = projectConfigDef.getPropertyDefinitionSimple("myapp.listener.port"); assertNotNull(propDef); assertEquals(propDef.getType(), PropertySimpleType.INTEGER); assertTrue(propDef.isRequired()); propDef = projectConfigDef.getPropertyDefinitionSimple("myapp.runtime.name"); assertNotNull(propDef); assertEquals(propDef.getType(), PropertySimpleType.STRING); assertTrue(propDef.isRequired()); Configuration projectConfig = project.getConfiguration(); assertNotNull(projectConfig); assertEquals(projectConfig.getProperties().size(), 3, String.valueOf(projectConfig.getProperties())); assertEquals(projectConfig.getSimpleValue("myapp.datasource.property"), "10", String.valueOf(projectConfig.getProperties())); assertEquals(projectConfig.getSimpleValue("myapp.listener.port"), "9777", String.valueOf(projectConfig.getProperties())); assertEquals(projectConfig.getSimpleValue("myapp.runtime.name"), "site.war", String.valueOf(projectConfig.getProperties())); assertEquals(handoverInfoArguments.size(), 2, String.valueOf(handoverInfoArguments)); Iterator<HandoverInfoArgument> handoverInfoIterator = handoverInfoArguments.iterator(); HandoverInfoArgument handoverInfoArgument = handoverInfoIterator.next(); HandoverInfo handoverInfo = handoverInfoArgument.handoverInfo; InputStream cliScriptContent = getClass().getClassLoader().getResourceAsStream("prepareDatasource.cli"); assertNotNull(cliScriptContent); FileInputStream actualContent = new FileInputStream(handoverInfoArgument.handoverInfoTestContentFile); assertEquals(slurp(actualContent), slurp(cliScriptContent)); assertEquals(handoverInfo.getFilename(), "prepareDatasource.cli"); assertEquals(handoverInfo.getAction(), "execute-script"); assertEquals(handoverInfo.getParams(), Collections.emptyMap()); assertEquals(handoverInfo.isRevert(), false); handoverInfoArgument = handoverInfoIterator.next(); handoverInfo = handoverInfoArgument.handoverInfo; final Properties[] propertiesHolder = new Properties[1]; ZipUtil.walkZipFile(handoverInfoArgument.handoverInfoTestContentFile, new ZipUtil.ZipEntryVisitor() { @Override public boolean visit(ZipEntry entry, ZipInputStream stream) throws Exception { String entryName = entry.getName(); if (entryName.equals("archived-subdir/archived-file-in-subdir.properties")) { Properties properties = new Properties(); properties.load(stream); propertiesHolder[0] = properties; } return true; } }); Properties properties = propertiesHolder[0]; assertNotNull(properties); assertEquals(properties.size(), 3, String.valueOf(properties)); assertEquals(properties.getProperty("templatized.variable"), "9777", String.valueOf(properties)); assertEquals(handoverInfo.getFilename(), "fileToHandover.zip"); assertEquals(handoverInfo.getAction(), "deployment"); assertEquals(handoverInfo.getParams(), new HashMap<String, String>() { { put("runtimeName", "site.war"); } }); assertEquals(handoverInfo.isRevert(), false); } public void testHandoverFailure() throws Exception { AntLauncher ant = new AntLauncher(true); final List<HandoverInfoArgument> handoverInfoArguments = new ArrayList<HandoverInfoArgument>(); HandoverTarget handoverTarget = new HandoverTarget() { @Override public boolean handoverContent(HandoverInfo handoverInfo) { HandoverInfoArgument handoverInfoArgument; try { handoverInfoArgument = new HandoverInfoArgument(handoverInfo); } catch (IOException e) { return false; } handoverInfoArguments.add(handoverInfoArgument); return false; } }; ant.setHandoverTarget(handoverTarget); List<BuildListener> buildListeners = createBuildListeners(); Properties inputProps = createInputProperties("/handover-test-bundle-input.properties"); try { ant.executeBundleDeployFile(getFileFromTestClasses("handover-test-bundle.xml"), inputProps, buildListeners); fail("Expected RuntimeException because of failed handover"); } catch (RuntimeException expected) { } // We still expect the callback to be called twice, as the first handover has a failonerror="false" attribute assertEquals(handoverInfoArguments.size(), 2, String.valueOf(handoverInfoArguments)); } public void testHandoverFailonerrorAttribute() throws Exception { AntLauncher ant = new AntLauncher(true); final List<HandoverInfoArgument> handoverInfoArguments = new ArrayList<HandoverInfoArgument>(); HandoverTarget handoverTarget = new HandoverTarget() { @Override public boolean handoverContent(HandoverInfo handoverInfo) { HandoverInfoArgument handoverInfoArgument; try { handoverInfoArgument = new HandoverInfoArgument(handoverInfo); } catch (IOException e) { return false; } handoverInfoArguments.add(handoverInfoArgument); return !handoverInfo.getFilename().equals("prepareDatasource.cli"); } }; ant.setHandoverTarget(handoverTarget); List<BuildListener> buildListeners = createBuildListeners(); Properties inputProps = createInputProperties("/handover-test-bundle-input.properties"); ant.executeBundleDeployFile(getFileFromTestClasses("handover-test-bundle.xml"), inputProps, buildListeners); assertEquals(handoverInfoArguments.size(), 2, String.valueOf(handoverInfoArguments)); } private List<BuildListener> createBuildListeners() { List<BuildListener> buildListeners = new ArrayList<BuildListener>(); DefaultLogger logger = new DefaultLogger(); logger.setMessageOutputLevel(Project.MSG_DEBUG); logger.setOutputPrintStream(System.out); logger.setErrorPrintStream(System.err); buildListeners.add(logger); return buildListeners; } private Properties createInputProperties(String resourcePath) throws IOException { return createInputProperties(resourcePath, false); } private Properties createInputProperties(String resourcePath, boolean dryRun) throws IOException { Properties inputProps = new Properties(); inputProps.setProperty(DeployPropertyNames.DEPLOY_DIR, DEPLOY_DIR.getPath()); inputProps.setProperty(DeployPropertyNames.DEPLOY_ID, String.valueOf(++this.deploymentId)); inputProps.setProperty(DeployPropertyNames.DEPLOY_PHASE, DeploymentPhase.INSTALL.name()); if (dryRun) { inputProps.setProperty(DeployPropertyNames.DEPLOY_DRY_RUN, Boolean.TRUE.toString()); } if (resourcePath != null) { InputStream inputStream = this.getClass().getResourceAsStream(resourcePath); try { inputProps.load(inputStream); } finally { inputStream.close(); } } return inputProps; } private Properties readPropsFile(File propFile) throws Exception { Properties props = new Properties(); InputStream inputStream = new FileInputStream(propFile); try { props.load(inputStream); } finally { inputStream.close(); } return props; } private File getFileFromTestClasses(String name) throws Exception { File file = new File(ANT_BASEDIR, name); assertTrue(file.exists(), "The file doesn't exist: " + file.getAbsolutePath()); return file; } private File writeFile(String content, File fileToOverwrite) throws Exception { FileOutputStream out = null; try { fileToOverwrite.getParentFile().mkdirs(); out = new FileOutputStream(fileToOverwrite); out.write(content.getBytes()); return fileToOverwrite; } finally { if (out != null) { out.close(); } } } private File writeFile(String content, File destDir, String fileName) throws Exception { File destFile = new File(destDir, fileName); return writeFile(content, destFile); } private File createZip(String[] content, File destDir, String zipName, String[] entryName) throws Exception { FileOutputStream stream = null; ZipOutputStream out = null; try { destDir.mkdirs(); File zipFile = new File(destDir, zipName); stream = new FileOutputStream(zipFile); out = new ZipOutputStream(stream); assertEquals(content.length, entryName.length); for (int i = 0; i < content.length; i++) { ZipEntry zipAdd = new ZipEntry(entryName[i]); zipAdd.setTime(System.currentTimeMillis()); out.putNextEntry(zipAdd); out.write(content[i].getBytes()); } return zipFile; } finally { if (out != null) { out.close(); } if (stream != null) { stream.close(); } } } private BundleTask findBundleTask(BundleAntProject project) { AntXMLContext antParsingContext = (AntXMLContext) project.getReference("ant.parsing.context"); Vector targets = antParsingContext.getTargets(); for (Object targetObj : targets) { Target target = (Target) targetObj; Task[] tasks = target.getTasks(); for (Task task : tasks) { if ("rhq:bundle".equals(task.getTaskName())) { return (BundleTask) preconfigureTask(task); } } } return null; } private static Task preconfigureTask(Task task) { if (task instanceof UnknownElement) { task.maybeConfigure(); Task resolvedTask = ((UnknownElement) task).getTask(); return (resolvedTask != null) ? resolvedTask : task; } else { return task; } } private static class HandoverInfoArgument { final HandoverInfo handoverInfo; final File handoverInfoTestContentFile; private HandoverInfoArgument(HandoverInfo handoverInfo) throws IOException { this.handoverInfo = handoverInfo; handoverInfoTestContentFile = File.createTempFile(HandoverInfoArgument.class.getSimpleName() + "-", ".tmp"); handoverInfoTestContentFile.deleteOnExit(); } @Override public String toString() { return "HandoverInfoArgument[" + "handoverInfo=" + handoverInfo + ", handoverInfoTestContentFile=" + handoverInfoTestContentFile + ']'; } } }