/*
* JBoss, Home of Professional Open Source.
* Copyright 2013, 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.IoUtils.safeClose;
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.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.jboss.as.patching.PatchingException;
import org.jboss.as.patching.ZipUtils;
import org.jboss.as.patching.installation.InstallationManager;
import org.jboss.as.patching.installation.InstalledIdentity;
import org.jboss.as.patching.metadata.BundledPatch;
import org.jboss.as.patching.metadata.Patch;
import org.jboss.as.patching.metadata.PatchBundleXml;
import org.jboss.as.patching.tool.ContentVerificationPolicy;
import org.jboss.as.patching.tool.PatchTool;
import org.jboss.as.patching.tool.PatchingResult;
import org.junit.Assert;
import org.junit.Test;
/**
* @author Emanuel Muckenhuber
*/
public class PatchBundleUnitTestCase extends AbstractPatchingTest {
static final String[] FILE_ONE = {"bin", "standalone.sh"};
static final String[] FILE_TWO = {"bin", "standalone.conf"};
static final String[] FILE_EXISTING = {"bin", "test"};
@Test
public void testMultiInstall() throws Exception {
final PatchingTestBuilder builder = createDefaultBuilder("layer-2", "layer-1", "base");
final byte[] moduleHashOne = new byte[20];
final byte[] moduleHashTwo = new byte[20];
final byte[] moduleHashThree = new byte[20];
final byte[] moduleHashFour = new byte[20];
final byte[] moduleHashFive = new byte[20];
final byte[] moduleHashSix = new byte[20];
final PatchingTestStepBuilder cp1 = builder.createStepBuilder();
cp1.setPatchId("CP1")
.upgradeIdentity(PRODUCT_VERSION, PRODUCT_VERSION)
.upgradeElement("base-CP1", "base", false)
.addModuleWithRandomContent("org.jboss.test", moduleHashOne)
;
final PatchingTestStepBuilder cp2 = builder.createStepBuilder();
cp2.setPatchId("CP2")
.upgradeIdentity(PRODUCT_VERSION, PRODUCT_VERSION)
.upgradeElement("layer-1-CP1", "layer-1", false)
.addModuleWithRandomContent("org.jboss.test.two", moduleHashTwo)
;
final PatchingTestStepBuilder cp3 = builder.createStepBuilder();
cp3.setPatchId("CP3")
.upgradeIdentity(PRODUCT_VERSION, PRODUCT_VERSION)
.upgradeElement("layer-2-CP1", "layer-2", false)
.removeModule("org.jboss.test.three", "main", moduleHashThree)
;
final PatchingTestStepBuilder cp4 = builder.createStepBuilder();
cp4.setPatchId("CP4")
.upgradeIdentity(PRODUCT_VERSION, PRODUCT_VERSION)
.upgradeElement("base-CP2", "base", false)
.addModuleWithRandomContent("org.jboss.test.four", moduleHashFour)
;
final PatchingTestStepBuilder cp5 = builder.createStepBuilder();
cp5.setPatchId("CP5")
.upgradeIdentity(PRODUCT_VERSION, PRODUCT_VERSION)
.upgradeElement("base-CP3", "base", false)
.updateModuleWithRandomContent("org.jboss.test.four", moduleHashFour, null)
.getParent()
.upgradeElement("layer-1-CP2", "layer-1", false)
.addModuleWithRandomContent("org.jboss.test.five", moduleHashFive)
.getParent()
.upgradeElement("layer-2-CP2", "layer-2", false)
.addModuleWithRandomContent("org.jboss.test.six", moduleHashSix)
;
final File multiPatch = prepare(builder.getRoot(), cp1, cp2, cp3, cp4, cp5);
// Create the patch tool and apply the patch
InstallationManager mgr = updateInstallationManager(); // Get installation manager instance for the unit test
final PatchTool patchTool = PatchTool.Factory.create(mgr);
final PatchingResult result = patchTool.applyPatch(multiPatch, ContentVerificationPolicy.STRICT);
result.commit();
try {
PatchStepAssertions.APPLY.after(builder.getFile(JBOSS_INSTALLATION), cp5.build(), mgr);
} catch (IOException e) {
throw new PatchingException(e);
}
mgr = loadInstallationManager();
final InstalledIdentity installedIdentity = mgr.getDefaultIdentity();
Assert.assertEquals(Arrays.asList(new String[] {"CP1", "CP2", "CP3", "CP4", "CP5"}), installedIdentity.getAllInstalledPatches());
PatchStepAssertions.assertModule("base-CP3", installedIdentity.getLayer("base"), "org.jboss.test", "main");
PatchStepAssertions.assertModule("base-CP3", installedIdentity.getLayer("base"), "org.jboss.test.four", "main");
PatchStepAssertions.assertModule("layer-1-CP2", installedIdentity.getLayer("layer-1"), "org.jboss.test.two", "main");
PatchStepAssertions.assertModule("layer-1-CP2", installedIdentity.getLayer("layer-1"), "org.jboss.test.five", "main");
PatchStepAssertions.assertModule("layer-2-CP2", installedIdentity.getLayer("layer-2"), "org.jboss.test.three", "main");
PatchStepAssertions.assertModule("layer-2-CP2", installedIdentity.getLayer("layer-2"), "org.jboss.test.six", "main");
rollback(cp5);
mgr = loadInstallationManager();
PatchStepAssertions.assertModule("base-CP2", installedIdentity.getLayer("base"), "org.jboss.test", "main");
PatchStepAssertions.assertModule("base-CP2", installedIdentity.getLayer("base"), "org.jboss.test.four", "main");
rollback(cp4);
rollback(cp3);
rollback(cp2);
rollback(cp1);
}
@Test
public void testRevert() throws Exception {
final PatchingTestBuilder builder = createDefaultBuilder("layer-2", "layer-1", "base");
final byte[] moduleHashOne = new byte[20];
final byte[] moduleHashTwo = new byte[20];
final byte[] moduleHashThree = new byte[20];
final byte[] moduleHashFour = new byte[20];
final byte[] moduleHashFive = new byte[20];
final byte[] moduleHashSix = new byte[20];
final PatchingTestStepBuilder cp1 = builder.createStepBuilder();
cp1.setPatchId("CP1")
.upgradeIdentity(PRODUCT_VERSION, PRODUCT_VERSION)
.upgradeElement("base-CP1", "base", false)
.addModuleWithRandomContent("org.jboss.test", moduleHashOne)
;
final PatchingTestStepBuilder cp2 = builder.createStepBuilder();
cp2.setPatchId("CP2")
.upgradeIdentity(PRODUCT_VERSION, PRODUCT_VERSION)
.upgradeElement("layer-1-CP1", "layer-1", false)
.addModuleWithRandomContent("org.jboss.test.two", moduleHashTwo)
;
final PatchingTestStepBuilder cp3 = builder.createStepBuilder();
cp3.setPatchId("CP3")
.upgradeIdentity(PRODUCT_VERSION, PRODUCT_VERSION)
.upgradeElement("layer-2-CP1", "layer-2", false)
.removeModule("org.jboss.test.three", "main", moduleHashThree)
;
final PatchingTestStepBuilder cp4 = builder.createStepBuilder();
cp4.setPatchId("CP4")
.upgradeIdentity(PRODUCT_VERSION, PRODUCT_VERSION)
.upgradeElement("base-CP2", "base", false)
.addModuleWithRandomContent("org.jboss.test.four", moduleHashFour)
;
final PatchingTestStepBuilder cp5 = builder.createStepBuilder();
cp5.setPatchId("CP5")
.upgradeIdentity(PRODUCT_VERSION, PRODUCT_VERSION)
.upgradeElement("base-CP3", "base", false)
.updateModuleWithRandomContent("org.jboss.test.four", moduleHashFour, null)
.getParent()
.upgradeElement("layer-1-CP2", "layer-1", false)
.addModuleWithRandomContent("org.jboss.test.five", moduleHashFive)
.getParent()
.upgradeElement("layer-2-CP2", "layer-2", false)
.addModuleWithRandomContent("org.jboss.test.six", moduleHashSix)
;
final File multiPatch = prepare(builder.getRoot(), cp1, cp2, cp3, cp4, cp5);
// Create the patch tool and apply the patch
InstallationManager mgr = loadInstallationManager();
final PatchTool patchTool = PatchTool.Factory.create(mgr);
final PatchingResult result = patchTool.applyPatch(multiPatch, ContentVerificationPolicy.STRICT);
result.rollback();
mgr = loadInstallationManager();
checkNotApplied(builder.getRoot(), mgr, cp1, cp2, cp3, cp4, cp5);
}
@Test
public void testConflicts() throws Exception {
final PatchingTestBuilder builder = createDefaultBuilder();
final byte[] standaloneHash = new byte[20];
final byte[] configHash = new byte[20];
final byte[] existingHash = new byte[20];
// Create a file
final File existing = builder.getFile(FILE_EXISTING);
touch(existing);
dump(existing, randomString());
final PatchingTestStepBuilder cp1 = builder.createStepBuilder();
cp1.setPatchId("cp1")
.upgradeIdentity(PRODUCT_VERSION, PRODUCT_VERSION)
.addFileWithRandomContent(standaloneHash, FILE_ONE);
final PatchingTestStepBuilder cp2 = builder.createStepBuilder();
cp2.setPatchId("cp2")
.upgradeIdentity(PRODUCT_VERSION, PRODUCT_VERSION)
.addFileWithRandomContent(configHash, FILE_TWO);
final PatchingTestStepBuilder cp3 = builder.createStepBuilder();
cp3.setPatchId("cp3")
.upgradeIdentity(PRODUCT_VERSION, PRODUCT_VERSION)
.addFileWithRandomContent(existingHash, FILE_EXISTING);
final File multiPatch = prepare(builder.getRoot(), cp1, cp2, cp3);
// Create the patch tool and apply the patch
InstallationManager mgr = loadInstallationManager();
final PatchTool patchTool = PatchTool.Factory.create(mgr);
try {
patchTool.applyPatch(multiPatch, ContentVerificationPolicy.STRICT);
Assert.fail();
} catch (PatchingException e) {
//ok
}
Assert.assertFalse(builder.hasFile(FILE_ONE));
Assert.assertFalse(builder.hasFile(FILE_TWO));
}
@Test
public void testSkipInstalled() throws Exception {
final PatchingTestBuilder builder = createDefaultBuilder("layer-2", "layer-1", "base");
final byte[] moduleHashOne = new byte[20];
final byte[] moduleHashTwo = new byte[20];
final byte[] moduleHashThree = new byte[20];
final PatchingTestStepBuilder cp1 = builder.createStepBuilder();
cp1.setPatchId("CP1")
.upgradeIdentity(PRODUCT_VERSION, PRODUCT_VERSION)
.upgradeElement("base-CP1", "base", false)
.addModuleWithRandomContent("org.jboss.test", moduleHashOne)
;
final PatchingTestStepBuilder cp2 = builder.createStepBuilder();
cp2.setPatchId("CP2")
.upgradeIdentity(PRODUCT_VERSION, PRODUCT_VERSION)
.upgradeElement("layer-1-CP1", "layer-1", false)
.addModuleWithRandomContent("org.jboss.test.two", moduleHashTwo)
;
final PatchingTestStepBuilder cp3 = builder.createStepBuilder();
cp3.setPatchId("CP3")
.upgradeIdentity(PRODUCT_VERSION, PRODUCT_VERSION)
.upgradeElement("layer-2-CP1", "layer-2", false)
.removeModule("org.jboss.test.three", "main", moduleHashThree)
;
apply(cp1);
apply(cp2);
// Prepare multi patch
final File multiPatch = prepare(builder.getRoot(), cp1, cp2, cp3);
// Create the patch tool and apply the patch
InstallationManager mgr = updateInstallationManager(); // Get installation manager instance for the unit test
final PatchTool patchTool = PatchTool.Factory.create(mgr);
final PatchingResult result = patchTool.applyPatch(multiPatch, ContentVerificationPolicy.STRICT);
result.commit();
try {
PatchStepAssertions.APPLY.after(builder.getFile(JBOSS_INSTALLATION), cp3.build(), mgr);
} catch (IOException e) {
throw new PatchingException(e);
}
}
protected void checkNotApplied(final File root, final InstallationManager mgr, final PatchingTestStepBuilder... steps) throws Exception {
for (final PatchingTestStepBuilder step : steps) {
PatchStepAssertions.APPLY.before(root, step.build(), mgr);
}
}
/**
* Prepare the multi patch bundle.
*
* @param root the temp dir root
* @param steps the individual steps
* @return the prepared content
* @throws PatchingException
*/
protected File prepare(File root, PatchingTestStepBuilder... steps) throws PatchingException {
final File tempDir = new File(root, randomString());
tempDir.mkdir();
final List<BundledPatch.BundledPatchEntry> entries = new ArrayList<BundledPatch.BundledPatchEntry>();
for (final PatchingTestStepBuilder step : steps) {
// Prepare the patches.
final Patch patch = step.build();
writePatch(step.getPatchDir(), patch);
final String patchId = patch.getPatchId();
final String path = patchId + ".zip";
final File patchOutput = new File(tempDir, path);
ZipUtils.zip(step.getPatchDir(), patchOutput);
entries.add(new BundledPatch.BundledPatchEntry(patchId, path));
}
final File multiPatchXml = new File(tempDir, PatchBundleXml.MULTI_PATCH_XML);
try {
final OutputStream os = new FileOutputStream(multiPatchXml);
try {
PatchBundleXml.marshal(os, new BundledPatch() {
@Override
public List<BundledPatchEntry> getPatches() {
return entries;
}
});
} finally {
safeClose(os);
}
} catch (Exception e) {
throw new PatchingException(e);
}
final File result = new File(root, "multi-step-contents.zip");
ZipUtils.zip(tempDir, result);
return result;
}
}