/* * JBoss, Home of Professional Open Source. * Copyright 2015, Red Hat, Inc., and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * 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 2.1 of * the License, or (at your option) any later version. * * This software 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. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.as.patching.tests; import static org.jboss.as.patching.Constants.BASE; import static org.jboss.as.patching.HashUtils.hashFile; import static org.jboss.as.patching.IoUtils.mkdir; import static org.jboss.as.patching.runner.PatchingAssert.assertDefinedAbsentModule; import static org.jboss.as.patching.runner.PatchingAssert.assertDefinedModule; import static org.jboss.as.patching.runner.PatchingAssert.assertDirExists; import static org.jboss.as.patching.runner.PatchingAssert.assertFileContent; import static org.jboss.as.patching.runner.PatchingAssert.assertFileDoesNotExist; import static org.jboss.as.patching.runner.PatchingAssert.assertFileExists; import static org.jboss.as.patching.runner.PatchingAssert.assertPatchHasBeenApplied; import static org.jboss.as.patching.runner.TestUtils.createPatchXMLFile; import static org.jboss.as.patching.runner.TestUtils.createZippedPatchFile; import static org.jboss.as.patching.runner.TestUtils.dump; import static org.jboss.as.patching.runner.TestUtils.randomString; import static org.jboss.as.patching.runner.TestUtils.touch; import java.io.File; import java.io.IOException; import org.jboss.as.patching.HashUtils; import org.jboss.as.patching.IoUtils; import org.jboss.as.patching.installation.InstalledIdentity; import org.jboss.as.patching.metadata.ContentModification; import org.jboss.as.patching.metadata.Patch; import org.jboss.as.patching.metadata.PatchBuilder; import org.jboss.as.patching.metadata.PatchMerger; import org.jboss.as.patching.runner.AbstractTaskTestCase; import org.jboss.as.patching.runner.ContentModificationUtils; import org.jboss.as.patching.tool.PatchTool; import org.jboss.as.patching.tool.PatchingResult; import org.junit.Assert; import org.junit.Before; import org.junit.Test; /** * * @author Alexey Loubyansky */ public class MergingPatchContentTestCase extends AbstractTaskTestCase { final String moduleName = "org.jboss.test"; private File standaloneSh; private byte[] originalStandaloneHash; private File addedByCP1; private File addedByCP1RemovedByCP3; private File addedByCP2; private Patch cp1; private String baseCP1ID = "base-CP1"; private String layer1CP1ID = "layer1-CP1"; private String layer2CP1ID = "layer2-CP1"; private ContentModification cp1BaseModuleAdded; private ContentModification cp1BaseModule2Added; private ContentModification cp1Layer1ModuleAdded; private ContentModification cp1Layer2ModuleAdded; private ContentModification cp1Layer2Module2Added; private ContentModification cp1StandaloneModified; private ContentModification cp1AddedByCP1Added; private Patch cp2; private String baseCP2ID = "base-CP2"; private String layer2CP2ID = "layer2-CP2"; private ContentModification cp2BaseModuleModified; private ContentModification cp2BaseModule2Removed; private ContentModification cp2StandaloneModified; private ContentModification cp2AddedByCp2Added; private ContentModification cp2Layer2ModuleRemoved; private ContentModification cp2Layer2Module3Added; private Patch cp3; private String baseCP3ID = "base-CP3"; private ContentModification cp3BaseModuleModified; private ContentModification cp3BaseModule2Added; private ContentModification cp3StandaloneModified; private File cp1Zip; private File cp2Zip; private File cp3Zip; private File mergedZip; private PatchTool tool; @Before public void init() throws Exception { installLayers("layer1", "layer2"); final File binDir = mkdir(env.getInstalledImage().getJbossHome(), "bin"); standaloneSh = touch(binDir, "standalone.sh"); dump(standaloneSh, "original script to run standalone server"); originalStandaloneHash = hashFile(standaloneSh); addedByCP1 = new File(binDir, "added-by-cp1.txt"); addedByCP1RemovedByCP3 = new File(binDir, "added-by-cp1-removed-by-cp3.txt"); addedByCP2 = new File(binDir, "added-by-cp2.txt"); tool = newPatchTool(); } /** * This test creates three consequent CPs and applies them one by one first. * Then creates a merged CP. * Then rollsback one by one applying the merged CP and verifying the latest CP * has been applied. * This also tests the "undo", i.e. a rollback as one step, of the merged CP. */ @Test public void testMain() throws Exception { final InstalledIdentity installedIdentity = loadInstalledIdentity(); PatchingResult result; assertNotPatched(); prepareCP1(installedIdentity); result = executePatch(tool, cp1Zip); assertCP1State(result); prepareCP2(installedIdentity); result = executePatch(tool, cp2Zip); assertCP2State(result); prepareCP3(installedIdentity); result = executePatch(tool, cp3Zip); assertCP3State(result); // ls(installedIdentity.getInstalledImage().getJbossHome()); mergedZip = new File(tempDir, "merged-patch.zip"); PatchMerger.merge(cp1Zip, cp2Zip, mergedZip); PatchMerger.merge(mergedZip, cp3Zip, mergedZip); // File mergedDir = mkdir(tempDir, "merged2"); // ZipUtils.unzip(mergedZip, mergedDir); // ls(mergedDir); // less(new File(mergedDir, "patch.xml")); result = rollback(tool, cp3.getPatchId()); assertCP2State(result); result = executePatch(tool, mergedZip); assertCP3State(result); result = rollback(tool, cp3.getPatchId()); assertCP2State(result); result = rollback(tool, cp2.getPatchId()); assertCP1State(result); result = executePatch(tool, mergedZip); assertCP3State(result); result = rollback(tool, cp3.getPatchId()); assertCP1State(result); result = rollback(tool, cp1.getPatchId()); assertNotPatched(); result = executePatch(tool, mergedZip); assertCP3State(result); result = rollback(tool, cp3.getPatchId()); assertNotPatched(); } private void assertCP3State(PatchingResult result) throws Exception { assertPatchHasBeenApplied(result, cp3); assertFileExists(standaloneSh); assertFileContent(cp3StandaloneModified.getItem().getContentHash(), standaloneSh); assertFileExists(addedByCP1); assertFileContent(cp1AddedByCP1Added.getItem().getContentHash(), addedByCP1); assertFileDoesNotExist(addedByCP1RemovedByCP3); assertFileExists(addedByCP2); assertFileContent(cp2AddedByCp2Added.getItem().getContentHash(), addedByCP2); final InstalledIdentity installedIdentity = loadInstalledIdentity(); File modulePatchDir = installedIdentity.getLayer(BASE).loadTargetInfo().getDirectoryStructure().getModulePatchDirectory(baseCP3ID); assertDirExists(modulePatchDir); assertDefinedModule(modulePatchDir, moduleName, cp3BaseModuleModified.getItem().getContentHash()); assertDefinedModule(modulePatchDir, moduleName + 2, cp3BaseModule2Added.getItem().getContentHash()); modulePatchDir = installedIdentity.getLayer("layer1").loadTargetInfo().getDirectoryStructure().getModulePatchDirectory(layer1CP1ID); assertDirExists(modulePatchDir); assertDefinedModule(modulePatchDir, moduleName, cp1Layer1ModuleAdded.getItem().getContentHash()); modulePatchDir = installedIdentity.getLayer("layer2").loadTargetInfo().getDirectoryStructure().getModulePatchDirectory(layer2CP2ID); assertDirExists(modulePatchDir); assertDefinedModule(modulePatchDir, moduleName + "2", cp1Layer2Module2Added.getItem().getContentHash()); assertDefinedModule(modulePatchDir, moduleName + "3", cp2Layer2Module3Added.getItem().getContentHash()); if(IoUtils.newFile(modulePatchDir, "org", "jboss", "test").exists()) { assertDefinedAbsentModule(modulePatchDir, moduleName); } } private void assertCP2State(PatchingResult result) throws Exception { assertPatchHasBeenApplied(result, cp2); assertFileExists(standaloneSh); assertFileContent(cp2StandaloneModified.getItem().getContentHash(), standaloneSh); assertFileExists(addedByCP1); assertFileContent(cp1AddedByCP1Added.getItem().getContentHash(), addedByCP1); assertFileExists(addedByCP1RemovedByCP3); assertFileExists(addedByCP2); assertFileContent(cp2AddedByCp2Added.getItem().getContentHash(), addedByCP2); final InstalledIdentity installedIdentity = loadInstalledIdentity(); File modulePatchDiry = installedIdentity.getLayer(BASE).loadTargetInfo().getDirectoryStructure().getModulePatchDirectory(baseCP2ID); assertDirExists(modulePatchDiry); assertDefinedModule(modulePatchDiry, moduleName, cp2BaseModuleModified.getItem().getContentHash()); assertDefinedAbsentModule(modulePatchDiry, moduleName + "2"); modulePatchDiry = installedIdentity.getLayer("layer1").loadTargetInfo().getDirectoryStructure().getModulePatchDirectory(layer1CP1ID); assertDirExists(modulePatchDiry); assertDefinedModule(modulePatchDiry, moduleName, cp1Layer1ModuleAdded.getItem().getContentHash()); modulePatchDiry = installedIdentity.getLayer("layer2").loadTargetInfo().getDirectoryStructure().getModulePatchDirectory(layer2CP2ID); assertDirExists(modulePatchDiry); assertDefinedAbsentModule(modulePatchDiry, moduleName); assertDefinedModule(modulePatchDiry, moduleName + "2", cp1Layer2Module2Added.getItem().getContentHash()); assertDefinedModule(modulePatchDiry, moduleName + "3", cp2Layer2Module3Added.getItem().getContentHash()); } private void assertCP1State(PatchingResult result) throws Exception { assertPatchHasBeenApplied(result, cp1); assertFileExists(standaloneSh); assertFileContent(cp1StandaloneModified.getItem().getContentHash(), standaloneSh); assertFileExists(addedByCP1); assertFileContent(cp1AddedByCP1Added.getItem().getContentHash(), addedByCP1); assertFileExists(addedByCP1RemovedByCP3); assertFileDoesNotExist(addedByCP2); final InstalledIdentity installedIdentity = loadInstalledIdentity(); File modulePatchDir = installedIdentity.getLayer(BASE).loadTargetInfo().getDirectoryStructure().getModulePatchDirectory(baseCP1ID); assertDirExists(modulePatchDir); assertDefinedModule(modulePatchDir, moduleName, cp1BaseModuleAdded.getItem().getContentHash()); assertDefinedModule(modulePatchDir, moduleName + "2", cp1BaseModule2Added.getItem().getContentHash()); modulePatchDir = installedIdentity.getLayer("layer1").loadTargetInfo().getDirectoryStructure().getModulePatchDirectory(layer1CP1ID); assertDirExists(modulePatchDir); assertDefinedModule(modulePatchDir, moduleName, cp1Layer1ModuleAdded.getItem().getContentHash()); modulePatchDir = installedIdentity.getLayer("layer2").loadTargetInfo().getDirectoryStructure().getModulePatchDirectory(layer2CP1ID); assertDirExists(modulePatchDir); assertDefinedModule(modulePatchDir, moduleName, cp1Layer2ModuleAdded.getItem().getContentHash()); assertDefinedModule(modulePatchDir, moduleName + "2", cp1Layer2Module2Added.getItem().getContentHash()); } private void assertNotPatched() throws Exception { assertFileExists(standaloneSh); assertFileContent(originalStandaloneHash, standaloneSh); assertFileDoesNotExist(addedByCP1); assertFileDoesNotExist(addedByCP1RemovedByCP3); assertFileDoesNotExist(addedByCP2); final InstalledIdentity installedIdentity = loadInstalledIdentity(); Assert.assertTrue(installedIdentity.getAllInstalledPatches().isEmpty()); } private void prepareCP3(final InstalledIdentity installedIdentity) throws IOException, Exception { final String cp3ID = "CP3"; final File cp3Dir = mkdir(tempDir, cp3ID); cp3StandaloneModified = ContentModificationUtils.modifyMisc(cp3Dir, cp3ID, "updated by cp3", standaloneSh, "bin", standaloneSh.getName()); cp3BaseModuleModified = ContentModificationUtils.modifyModule(cp3Dir, baseCP3ID, moduleName, cp2BaseModuleModified.getItem().getContentHash(), "cp3 content"); // cp3BaseModule2Added = ContentModificationUtils.addModule(cp3Dir, baseCP3ID, moduleName + "2"); the patchgen tool // would generate an update instead final File absentModuleXml = IoUtils.newFile(installedIdentity.getLayer("base").loadTargetInfo() .getDirectoryStructure().getModulePatchDirectory(baseCP2ID), "org", "jboss", "test2", "main", "module.xml"); cp3BaseModule2Added = ContentModificationUtils.modifyModule(cp3Dir, baseCP3ID, moduleName + "2", HashUtils.hashFile(absentModuleXml), "cp3 content"); final ContentModification cp3AddedByCP1RemovedByCP3Removed = ContentModificationUtils.removeMisc(addedByCP1RemovedByCP3, "bin", addedByCP1RemovedByCP3.getName()); cp3 = PatchBuilder.create() .setPatchId(cp3ID) .setDescription(randomString()) .upgradeIdentity(installedIdentity.getIdentity().getName(), productConfig.getProductVersion() + "_CP2", productConfig.getProductVersion() + "_CP3") .getParent() .upgradeElement(baseCP3ID, BASE, false) .addContentModification(cp3BaseModuleModified) .addContentModification(cp3BaseModule2Added) .getParent() .addContentModification(cp3StandaloneModified) .addContentModification(cp3AddedByCP1RemovedByCP3Removed) .build(); createPatchXMLFile(cp3Dir, cp3); cp3Zip = createZippedPatchFile(cp3Dir, cp3ID); } private void prepareCP2(final InstalledIdentity installedIdentity) throws Exception { final String cp2ID = "CP2"; final File cp2Dir = mkdir(tempDir, cp2ID); cp2BaseModuleModified = ContentModificationUtils.modifyModule(cp2Dir, baseCP2ID, moduleName, cp1BaseModuleAdded.getItem().getContentHash(), "cp2 content"); final File baseModule2Dir = IoUtils.newFile( installedIdentity.getLayer("base").loadTargetInfo().getDirectoryStructure().getModulePatchDirectory(baseCP1ID), "org", "jboss", "test2"); cp2BaseModule2Removed = ContentModificationUtils.removeModule(baseModule2Dir, moduleName + 2); final File layer2ModuleDir = IoUtils.newFile( installedIdentity.getLayer("layer2").loadTargetInfo().getDirectoryStructure().getModulePatchDirectory(layer2CP1ID), "org", "jboss", "test"); cp2Layer2ModuleRemoved = ContentModificationUtils.removeModule(layer2ModuleDir, moduleName); cp2Layer2Module3Added = ContentModificationUtils.addModule(cp2Dir, layer2CP2ID, moduleName + "3"); cp2StandaloneModified = ContentModificationUtils.modifyMisc(cp2Dir, cp2ID, "updated by cp2", cp1StandaloneModified.getItem().getContentHash(), "bin", standaloneSh.getName()); cp2AddedByCp2Added = ContentModificationUtils.addMisc(cp2Dir, cp2ID, "added by cp2", "bin", addedByCP2.getName()); cp2 = PatchBuilder.create() .setPatchId(cp2ID) .setDescription(randomString()) .upgradeIdentity(installedIdentity.getIdentity().getName(), productConfig.getProductVersion() + "_CP1", productConfig.getProductVersion() + "_CP2") .getParent() .upgradeElement(baseCP2ID, BASE, false) .addContentModification(cp2BaseModuleModified) .addContentModification(cp2BaseModule2Removed) .getParent() .upgradeElement(layer2CP2ID, "layer2", false) .addContentModification(cp2Layer2ModuleRemoved) .addContentModification(cp2Layer2Module3Added) .getParent() .addContentModification(cp2StandaloneModified) .addContentModification(cp2AddedByCp2Added) .build(); createPatchXMLFile(cp2Dir, cp2); cp2Zip = createZippedPatchFile(cp2Dir, cp2ID); } private void prepareCP1(final InstalledIdentity installedIdentity) throws Exception { final String cp1ID = "CP1"; final File cp1Dir = mkdir(tempDir, cp1ID); cp1BaseModuleAdded = ContentModificationUtils.addModule(cp1Dir, baseCP1ID, moduleName); cp1BaseModule2Added = ContentModificationUtils.addModule(cp1Dir, baseCP1ID, moduleName + 2); cp1Layer1ModuleAdded = ContentModificationUtils.addModule(cp1Dir, layer1CP1ID, moduleName); cp1Layer2ModuleAdded = ContentModificationUtils.addModule(cp1Dir, layer2CP1ID, moduleName); cp1Layer2Module2Added = ContentModificationUtils.addModule(cp1Dir, layer2CP1ID, moduleName + "2"); cp1StandaloneModified = ContentModificationUtils.modifyMisc(cp1Dir, cp1ID, "updated by cp1", standaloneSh, "bin", standaloneSh.getName()); cp1AddedByCP1Added = ContentModificationUtils.addMisc(cp1Dir, cp1ID, "added by cp1", "bin", addedByCP1.getName()); final ContentModification cp1AddedByCP1RemovedByCP3Added = ContentModificationUtils.addMisc(cp1Dir, cp1ID, "added by cp1", "bin", addedByCP1RemovedByCP3.getName()); cp1 = PatchBuilder.create() .setPatchId(cp1ID) .setDescription(randomString()) .upgradeIdentity(installedIdentity.getIdentity().getName(), installedIdentity.getIdentity().getVersion(), productConfig.getProductVersion() + "_CP1") .getParent() .upgradeElement(baseCP1ID, BASE, false) .addContentModification(cp1BaseModuleAdded) .addContentModification(cp1BaseModule2Added) .getParent() .upgradeElement(layer1CP1ID, "layer1", false) .addContentModification(cp1Layer1ModuleAdded) .getParent() .upgradeElement(layer2CP1ID, "layer2", false) .addContentModification(cp1Layer2ModuleAdded) .addContentModification(cp1Layer2Module2Added) .getParent() .addContentModification(cp1StandaloneModified) .addContentModification(cp1AddedByCP1Added) .addContentModification(cp1AddedByCP1RemovedByCP3Added) .build(); createPatchXMLFile(cp1Dir, cp1); cp1Zip = createZippedPatchFile(cp1Dir, cp1ID); } }