/* * Copyright 2016 Red Hat, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.as.test.patching; import static org.jboss.as.patching.IoUtils.mkdir; import static org.jboss.as.test.patching.PatchingTestUtil.AS_VERSION; import static org.jboss.as.test.patching.PatchingTestUtil.FILE_SEPARATOR; import static org.jboss.as.test.patching.PatchingTestUtil.MODULES_PATH; import static org.jboss.as.test.patching.PatchingTestUtil.PRODUCT; import static org.jboss.as.test.patching.PatchingTestUtil.createPatchXMLFile; import static org.jboss.as.test.patching.PatchingTestUtil.createZippedPatchFile; import static org.jboss.as.test.patching.PatchingTestUtil.randomString; import java.io.File; import org.jboss.as.patching.Constants; import org.jboss.as.patching.HashUtils; import org.jboss.as.patching.IoUtils; 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.test.patching.util.module.Module; import org.jboss.as.version.ProductConfig; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.wildfly.core.testrunner.ServerControl; import org.wildfly.core.testrunner.WildflyTestRunner; /** * @author Alexey Loubyansky */ @RunWith(WildflyTestRunner.class) @ServerControl(manual = true) public class MergedCpWithSubmoduleTestCase extends AbstractPatchingTestCase { private final String topModuleName = "org.wildfly.test.topmodule"; private final String subModuleName = "org.wildfly.test.topmodule.impl"; private ResourceItem cp1ResourceItem1; private ResourceItem cp1ResourceItem2; private String cp1Slot; @Test public void testSubmoduleUpdated() throws Exception { File patchTmpDir = mkdir(tempDir, randomString("patchdir")); final String cp1Id = "cp1"; final String cp2Id = "cp2"; final String cp1AsVersion = AS_VERSION + cp1Id; final String cp2AsVersion = AS_VERSION + cp2Id; final File cp1Zip = createCp1(cp1Id, AS_VERSION, cp1AsVersion, patchTmpDir); final File cp2Zip = createSubmoduleUpdateCp2(cp2Id, cp1AsVersion, cp1Id, cp2AsVersion, patchTmpDir); final File mergedCp1Cp2Zip = PatchMerger.merge(cp1Zip, cp2Zip, new File("merged-cp1-cp2.zip")); mergedCp1Cp2Zip.deleteOnExit(); // apply bundle controller.start(); Assert.assertTrue("Patch should be accepted", CliUtilsForPatching.applyPatch(mergedCp1Cp2Zip.getAbsolutePath())); Assert.assertTrue("server should be in restart-required mode", CliUtilsForPatching.doesServerRequireRestart()); controller.stop(); } @Test public void testTopModuleSlotUpdated() throws Exception { File patchTmpDir = mkdir(tempDir, randomString("patchdir")); final String cp1Id = "cp1"; final String cp2Id = "cp2"; final String cp1AsVersion = AS_VERSION + cp1Id; final String cp2AsVersion = AS_VERSION + cp2Id; final File cp1Zip = createCp1(cp1Id, AS_VERSION, cp1AsVersion, patchTmpDir); final File cp2Zip = createTopModuleSlotAndSubmoduleUpdateCp2(cp2Id, cp1AsVersion, cp1Id, cp2AsVersion, patchTmpDir); final File mergedCp1Cp2Zip = PatchMerger.merge(cp1Zip, cp2Zip, new File("merged-cp1-cp2.zip")); mergedCp1Cp2Zip.deleteOnExit(); // apply bundle controller.start(); Assert.assertTrue("Patch should be accepted", CliUtilsForPatching.applyPatch(mergedCp1Cp2Zip.getAbsolutePath())); Assert.assertTrue("server should be in restart-required mode", CliUtilsForPatching.doesServerRequireRestart()); controller.stop(); } @Test public void testTopModuleMainSlotUpdated() throws Exception { File patchTmpDir = mkdir(tempDir, randomString("patchdir")); final String cp1Id = "cp1"; final String cp2Id = "cp2"; final String cp1AsVersion = AS_VERSION + cp1Id; final String cp2AsVersion = AS_VERSION + cp2Id; final File cp1Zip = createCp1(cp1Id, AS_VERSION, cp1AsVersion, patchTmpDir); final File cp2Zip = createTopModuleMainSlotUpdateCp2(cp2Id, cp1AsVersion, cp1Id, cp2AsVersion, patchTmpDir); final File mergedCp1Cp2Zip = PatchMerger.merge(cp1Zip, cp2Zip, new File("merged-cp1-cp2.zip")); mergedCp1Cp2Zip.deleteOnExit(); // apply bundle controller.start(); Assert.assertTrue("Patch should be accepted", CliUtilsForPatching.applyPatch(mergedCp1Cp2Zip.getAbsolutePath())); Assert.assertTrue("server should be in restart-required mode", CliUtilsForPatching.doesServerRequireRestart()); controller.stop(); } @Test public void testAllUpdated() throws Exception { File patchTmpDir = mkdir(tempDir, randomString("patchdir")); final String cp1Id = "cp1"; final String cp2Id = "cp2"; final String cp1AsVersion = AS_VERSION + cp1Id; final String cp2AsVersion = AS_VERSION + cp2Id; final File cp1Zip = createCp1(cp1Id, AS_VERSION, cp1AsVersion, patchTmpDir); final File cp2Zip = createAllUpdatedCp2(cp2Id, cp1AsVersion, cp1Id, cp2AsVersion, patchTmpDir); final File mergedCp1Cp2Zip = PatchMerger.merge(cp1Zip, cp2Zip, new File("merged-cp1-cp2.zip")); mergedCp1Cp2Zip.deleteOnExit(); // apply bundle controller.start(); Assert.assertTrue("Patch should be accepted", CliUtilsForPatching.applyPatch(mergedCp1Cp2Zip.getAbsolutePath())); Assert.assertTrue("server should be in restart-required mode", CliUtilsForPatching.doesServerRequireRestart()); controller.stop(); } private File createCp1(String cpId, String asVersion, final String targetAsVersion, File targetDir) throws Exception { final String cp1LayerPatchId = "layer" + cpId; File cpPatchDir = mkdir(tempDir, cpId); cp1ResourceItem1 = new ResourceItem("testFile1", "content1".getBytes()); cp1ResourceItem2 = new ResourceItem("testFile2", "content2".getBytes()); final Module topModuleMain = new Module.Builder(topModuleName) .resourceRoot(cp1ResourceItem1) .resourceRoot(cp1ResourceItem2) .build(); final Module topModule41 = new Module.Builder(topModuleName) .slot("slot41") .resourceRoot(cp1ResourceItem1) .resourceRoot(cp1ResourceItem2) .build(); final Module subModule = new Module.Builder(subModuleName) .resourceRoot(cp1ResourceItem1) .resourceRoot(cp1ResourceItem2) .build(); // Create the version module final String versionModuleName = ProductInfo.getVersionModule(); cp1Slot = ProductInfo.getVersionModuleSlot(); final String originalVersionModulePath = MODULES_PATH + FILE_SEPARATOR + versionModuleName .replace(".", FILE_SEPARATOR) + FILE_SEPARATOR + cp1Slot; final Module modifiedModule = PatchingTestUtil.createVersionModule(targetAsVersion); final ContentModification topModuleMainAdded = ContentModificationUtils.addModule(cpPatchDir, cp1LayerPatchId, topModuleMain); final ContentModification topModule41Added = ContentModificationUtils.addModule(cpPatchDir, cp1LayerPatchId, topModule41); final ContentModification subModuleAdded = ContentModificationUtils.addModule(cpPatchDir, cp1LayerPatchId, subModule); ContentModification versionModuleModified = ContentModificationUtils .modifyModule(cpPatchDir, cp1LayerPatchId, HashUtils.hashFile(new File(originalVersionModulePath)), modifiedModule); Patch cpPatch = PatchBuilder.create() .setPatchId(cpId) .setDescription("A cp patch.") .upgradeIdentity(PRODUCT, asVersion, targetAsVersion) .getParent() .upgradeElement(cp1LayerPatchId, "base", false) // the order of the submodule and topmodule modifications is important in this case .addContentModification(subModuleAdded) .addContentModification(topModuleMainAdded) .addContentModification(topModule41Added) .addContentModification(versionModuleModified) .getParent() .build(); createPatchXMLFile(cpPatchDir, cpPatch); return createZippedPatchFile(cpPatchDir, cpId, targetDir); } private File createSubmoduleUpdateCp2(String cpId, String asVersion, final String currentCpId, final String targetAsVersion, File targetDir) throws Exception { final String layerPatchId = "layer" + cpId; File cpPatchDir = mkdir(tempDir, cpId); // Create the version module final String versionModuleName = ProductInfo.getVersionModule(); final Module modifiedModule = PatchingTestUtil.createVersionModule(targetAsVersion); // Calculate the target hash of the currently active module final String currentLayerPatchId = "layer" + currentCpId; final File originalVersionModulePath = IoUtils.newFile(tempDir, currentCpId, currentLayerPatchId, Constants.MODULES, versionModuleName.replace('.', File.separatorChar), ProductInfo.getVersionModuleSlot()); byte[] patchedAsVersionHash = HashUtils.hashFile(originalVersionModulePath); assert patchedAsVersionHash != null; ContentModification versionModuleModified = ContentModificationUtils .modifyModule(cpPatchDir, layerPatchId, patchedAsVersionHash, modifiedModule); final File subModulePath = IoUtils.newFile(tempDir, currentCpId, currentLayerPatchId, Constants.MODULES, subModuleName.replace('.', File.separatorChar), "main"); final ResourceItem cp2ResourceItem1 = new ResourceItem("testFile3", "content1".getBytes()); final Module subModule = new Module.Builder(subModuleName) .resourceRoot(cp1ResourceItem1) .resourceRoot(cp1ResourceItem2) .resourceRoot(cp2ResourceItem1) .build(); final byte[] currentSubmoduleHash = HashUtils.hashFile(subModulePath); assert currentSubmoduleHash != null; final ContentModification subModuleModified = ContentModificationUtils .modifyModule(cpPatchDir, layerPatchId, currentSubmoduleHash, subModule); ProductConfig productConfig = new ProductConfig(PRODUCT, asVersion, "main"); Patch cpPatch = PatchBuilder.create() .setPatchId(cpId) .setDescription("A cp patch.") .upgradeIdentity(productConfig.getProductName(), productConfig.getProductVersion(), targetAsVersion) .getParent() .upgradeElement(layerPatchId, "base", false) .addContentModification(subModuleModified) .addContentModification(versionModuleModified) .getParent() .build(); createPatchXMLFile(cpPatchDir, cpPatch); return createZippedPatchFile(cpPatchDir, cpId, targetDir); } private File createTopModuleSlotAndSubmoduleUpdateCp2(String cpId, String asVersion, final String currentCpId, final String targetAsVersion, File targetDir) throws Exception { final String layerPatchId = "layer" + cpId; File cpPatchDir = mkdir(tempDir, cpId); // Create the version module final String versionModuleName = ProductInfo.getVersionModule(); final Module modifiedModule = PatchingTestUtil.createVersionModule(targetAsVersion); // Calculate the target hash of the currently active module final String currentLayerPatchId = "layer" + currentCpId; final File originalVersionModulePath = IoUtils.newFile(tempDir, currentCpId, currentLayerPatchId, Constants.MODULES, versionModuleName.replace('.', File.separatorChar), ProductInfo.getVersionModuleSlot()); byte[] patchedAsVersionHash = HashUtils.hashFile(originalVersionModulePath); assert patchedAsVersionHash != null; ContentModification versionModuleModified = ContentModificationUtils.modifyModule(cpPatchDir, layerPatchId, patchedAsVersionHash, modifiedModule); final ResourceItem cp2ResourceItem1 = new ResourceItem("testFile3", "content1".getBytes()); final ContentModification subModuleModified; { final File subModulePath = IoUtils.newFile(tempDir, currentCpId, currentLayerPatchId, Constants.MODULES, subModuleName.replace('.', File.separatorChar), "main"); final Module subModule = new Module.Builder(subModuleName) .resourceRoot(cp1ResourceItem1) .resourceRoot(cp1ResourceItem2) .resourceRoot(cp2ResourceItem1) .build(); final byte[] currentSubmoduleHash = HashUtils.hashFile(subModulePath); assert currentSubmoduleHash != null; subModuleModified = ContentModificationUtils.modifyModule(cpPatchDir, layerPatchId, currentSubmoduleHash, subModule); } final ContentModification topModule41Modified; { final File topModulePath = IoUtils.newFile(tempDir, currentCpId, currentLayerPatchId, Constants.MODULES, topModuleName.replace('.', File.separatorChar), "slot41"); final Module topModule41 = new Module.Builder(topModuleName) .slot("slot41") .resourceRoot(cp1ResourceItem1) .resourceRoot(cp1ResourceItem2) .resourceRoot(cp2ResourceItem1) .build(); final byte[] currentTopModuleHash = HashUtils.hashFile(topModulePath); assert currentTopModuleHash != null; topModule41Modified = ContentModificationUtils .modifyModule(cpPatchDir, layerPatchId, currentTopModuleHash, topModule41); } ProductConfig productConfig = new ProductConfig(PRODUCT, asVersion, "main"); Patch cpPatch = PatchBuilder.create().setPatchId(cpId).setDescription("A cp patch.") .upgradeIdentity(productConfig.getProductName(), productConfig.getProductVersion(), targetAsVersion) .getParent() .upgradeElement(layerPatchId, "base", false) .addContentModification(topModule41Modified) .addContentModification(subModuleModified) .addContentModification(versionModuleModified) .getParent() .build(); createPatchXMLFile(cpPatchDir, cpPatch); return createZippedPatchFile(cpPatchDir, cpId, targetDir); } private File createTopModuleMainSlotUpdateCp2(String cpId, String asVersion, final String currentCpId, final String targetAsVersion, File targetDir) throws Exception { final String layerPatchId = "layer" + cpId; File cpPatchDir = mkdir(tempDir, cpId); // Create the version module final String versionModuleName = ProductInfo.getVersionModule(); final Module modifiedModule = PatchingTestUtil.createVersionModule(targetAsVersion); // Calculate the target hash of the currently active module final String currentLayerPatchId = "layer" + currentCpId; final File originalVersionModulePath = IoUtils.newFile(tempDir, currentCpId, currentLayerPatchId, Constants.MODULES, versionModuleName.replace('.', File.separatorChar), ProductInfo.getVersionModuleSlot()); byte[] patchedAsVersionHash = HashUtils.hashFile(originalVersionModulePath); assert patchedAsVersionHash != null; ContentModification versionModuleModified = ContentModificationUtils.modifyModule(cpPatchDir, layerPatchId, patchedAsVersionHash, modifiedModule); final ResourceItem cp2ResourceItem1 = new ResourceItem("testFile3", "content1".getBytes()); final ContentModification topModuleModified; { final File topModulePath = IoUtils.newFile(tempDir, currentCpId, currentLayerPatchId, Constants.MODULES, topModuleName.replace('.', File.separatorChar), "main"); final Module topModule = new Module.Builder(topModuleName) .resourceRoot(cp1ResourceItem1) .resourceRoot(cp1ResourceItem2) .resourceRoot(cp2ResourceItem1) .build(); final byte[] currentTopModuleHash = HashUtils.hashFile(topModulePath); assert currentTopModuleHash != null; topModuleModified = ContentModificationUtils .modifyModule(cpPatchDir, layerPatchId, currentTopModuleHash, topModule); } ProductConfig productConfig = new ProductConfig(PRODUCT, asVersion, "main"); Patch cpPatch = PatchBuilder.create().setPatchId(cpId).setDescription("A cp patch.") .upgradeIdentity(productConfig.getProductName(), productConfig.getProductVersion(), targetAsVersion) .getParent() .upgradeElement(layerPatchId, "base", false) .addContentModification(topModuleModified) .addContentModification(versionModuleModified) .getParent() .build(); createPatchXMLFile(cpPatchDir, cpPatch); return createZippedPatchFile(cpPatchDir, cpId, targetDir); } private File createAllUpdatedCp2(String cpId, String asVersion, final String currentCpId, final String targetAsVersion, File targetDir) throws Exception { final String layerPatchId = "layer" + cpId; File cpPatchDir = mkdir(tempDir, cpId); // Create the version module final String versionModuleName = ProductInfo.getVersionModule(); final Module modifiedModule = PatchingTestUtil.createVersionModule(targetAsVersion); // Calculate the target hash of the currently active module final String currentLayerPatchId = "layer" + currentCpId; final File originalVersionModulePath = IoUtils.newFile(tempDir, currentCpId, currentLayerPatchId, Constants.MODULES, versionModuleName.replace('.', File.separatorChar), ProductInfo.getVersionModuleSlot()); byte[] patchedAsVersionHash = HashUtils.hashFile(originalVersionModulePath); assert patchedAsVersionHash != null; ContentModification versionModuleModified = ContentModificationUtils.modifyModule(cpPatchDir, layerPatchId, patchedAsVersionHash, modifiedModule); final ResourceItem cp2ResourceItem1 = new ResourceItem("testFile3", "content1".getBytes()); final ContentModification subModuleModified; { final File subModulePath = IoUtils.newFile(tempDir, currentCpId, currentLayerPatchId, Constants.MODULES, subModuleName.replace('.', File.separatorChar), "main"); final Module subModule = new Module.Builder(subModuleName) .resourceRoot(cp1ResourceItem1) .resourceRoot(cp1ResourceItem2) .resourceRoot(cp2ResourceItem1) .build(); final byte[] currentSubmoduleHash = HashUtils.hashFile(subModulePath); assert currentSubmoduleHash != null; subModuleModified = ContentModificationUtils.modifyModule(cpPatchDir, layerPatchId, currentSubmoduleHash, subModule); } final ContentModification topModule41Modified; { final File topModulePath = IoUtils.newFile(tempDir, currentCpId, currentLayerPatchId, Constants.MODULES, topModuleName.replace('.', File.separatorChar), "slot41"); final Module topModule41 = new Module.Builder(topModuleName) .slot("slot41") .resourceRoot(cp1ResourceItem1) .resourceRoot(cp1ResourceItem2) .resourceRoot(cp2ResourceItem1) .build(); final byte[] currentTopModuleHash = HashUtils.hashFile(topModulePath); assert currentTopModuleHash != null; topModule41Modified = ContentModificationUtils .modifyModule(cpPatchDir, layerPatchId, currentTopModuleHash, topModule41); } final ContentModification topModuleMainModified; { final File topModulePath = IoUtils.newFile(tempDir, currentCpId, currentLayerPatchId, Constants.MODULES, topModuleName.replace('.', File.separatorChar), "main"); final Module topModuleMain = new Module.Builder(topModuleName) .slot("main") .resourceRoot(cp1ResourceItem1) .resourceRoot(cp1ResourceItem2) .resourceRoot(cp2ResourceItem1) .build(); final byte[] currentTopModuleHash = HashUtils.hashFile(topModulePath); assert currentTopModuleHash != null; topModuleMainModified = ContentModificationUtils .modifyModule(cpPatchDir, layerPatchId, currentTopModuleHash, topModuleMain); } ProductConfig productConfig = new ProductConfig(PRODUCT, asVersion, "main"); Patch cpPatch = PatchBuilder.create().setPatchId(cpId).setDescription("A cp patch.") .upgradeIdentity(productConfig.getProductName(), productConfig.getProductVersion(), targetAsVersion) .getParent() .upgradeElement(layerPatchId, "base", false) .addContentModification(topModuleMainModified) .addContentModification(topModule41Modified) .addContentModification(subModuleModified) .addContentModification(versionModuleModified) .getParent() .build(); createPatchXMLFile(cpPatchDir, cpPatch); return createZippedPatchFile(cpPatchDir, cpId, targetDir); } }