/* * 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.runner.TestUtils.randomString; import static org.jboss.as.patching.runner.TestUtils.tree; import java.io.File; import org.jboss.as.patching.HashUtils; import org.jboss.as.patching.IoUtils; import org.jboss.as.patching.PatchingException; import org.jboss.as.patching.installation.InstalledIdentity; import org.jboss.as.patching.installation.PatchableTarget; import org.jboss.as.patching.metadata.ContentModification; import org.jboss.as.patching.metadata.MiscContentItem; import org.jboss.as.patching.metadata.ModificationType; import org.jboss.as.patching.metadata.ModuleItem; import org.jboss.as.patching.runner.ContentModificationUtils; import org.junit.Assert; import org.junit.Test; /** * Test that undo actions properly handle failures. * * @author Emanuel Muckenhuber */ public class PatchUndoTestCase extends AbstractPatchingTest { private static final String[] MODULES_BASE = new String[]{ "modules", "system", "layers", "base", ".overlays" }; private static final byte[] WRONG_HASH = HashUtils.hexStringToByteArray("ffaf3edf942c0f6fb8754f75d60722bfb6a6a503"); @Test public void testWrongModuleContent() throws Exception { final PatchingTestBuilder builder = createDefaultBuilder(); // Add some random content ContentModificationUtils.addModule(builder.getRoot(), "base-patch-001", "test.module", randomString()); // Override the hash with a wrong one final ModuleItem item = new ModuleItem("test.module", "main", WRONG_HASH); final ContentModification wrongModification = new ContentModification(item, IoUtils.NO_CONTENT, ModificationType.ADD); final PatchingTestStepBuilder step1 = builder.createStepBuilder(); step1.oneOffPatchIdentity(PRODUCT_VERSION) .setPatchId("oo1") .oneOffPatchElement("base-patch-001", "base", false) .addContentModification(wrongModification) .getParent() .addFileWithRandomContent(null, "test", "content"); // try { apply(step1); Assert.fail("should have failed"); } catch (PatchingException e) { Assert.assertFalse(builder.hasFile("test", "content")); final InstalledIdentity identity = loadInstallationManager().getDefaultIdentity(); final PatchableTarget base = identity.getLayer("base"); Assert.assertFalse(base.getDirectoryStructure().getModulePatchDirectory("base-patch-001").exists()); Assert.assertFalse(identity.getInstalledImage().getPatchHistoryDir("oo1").exists()); } } @Test public void testWrongMiscContent() throws Exception { final PatchingTestBuilder builder = createDefaultBuilder(); ContentModificationUtils.addMisc(builder.getRoot(), "oo2", "test-content", "wrong-content"); final MiscContentItem item = new MiscContentItem("wrong-content", new String[0], WRONG_HASH); final ContentModification wrongModification = new ContentModification(item, IoUtils.NO_CONTENT, ModificationType.ADD); final PatchingTestStepBuilder step1 = builder.createStepBuilder(); step1.oneOffPatchIdentity(PRODUCT_VERSION) .setPatchId("oo2") .oneOffPatchElement("base-patch-002", "base", false) .addModuleWithRandomContent("other.test", null) .getParent() .addFileWithRandomContent(null, "test", "content") .addContentModification(wrongModification) ; // try { apply(step1); Assert.fail("should have failed"); } catch (PatchingException e) { Assert.assertFalse(builder.hasFile("test", "content")); Assert.assertFalse(builder.hasFile("wrong-content")); final InstalledIdentity identity = loadInstallationManager().getDefaultIdentity(); final PatchableTarget base = identity.getLayer("base"); Assert.assertFalse(base.getDirectoryStructure().getModulePatchDirectory("base-patch-002").exists()); Assert.assertFalse(identity.getInstalledImage().getPatchHistoryDir("oo2").exists()); } } @Test public void testInvalidPatch() throws Exception { final PatchingTestBuilder builder = createDefaultBuilder(); ContentModificationUtils.addMisc(builder.getRoot(), "oo2", "test-content", "wrong-content"); final MiscContentItem item = new MiscContentItem("wrong-content", new String[0], WRONG_HASH); final ContentModification wrongModification = new ContentModification(item, IoUtils.NO_CONTENT, ModificationType.ADD); final PatchingTestStepBuilder step1 = builder.createStepBuilder(); step1.oneOffPatchIdentity(PRODUCT_VERSION) .setPatchId("oo2") .oneOffPatchElement("base-patch-002", "base", false) .addModuleWithRandomContent("other.test", null) .getParent() .addFileWithRandomContent(null, "test", "content") ; apply(step1); Assert.assertTrue(builder.hasFile("test", "content")); // final PatchingTestStepBuilder step2 = builder.createStepBuilder(); step2.upgradeIdentity(PRODUCT_VERSION, PRODUCT_VERSION) .setPatchId("cp2") .upgradeElement("base-patch-cp2", "base", false) .getParent() .addContentModification(wrongModification) ; try { apply(step2); Assert.fail("should have failed"); } catch (PatchingException e) { Assert.assertTrue(builder.hasFile("test", "content")); } } @Test public void testModificationCompletion() throws Exception { final PatchingTestBuilder builder = createDefaultBuilder(); final PatchingTestStepBuilder step1 = builder.createStepBuilder(); step1.oneOffPatchIdentity(PRODUCT_VERSION) .setPatchId("patch1") .oneOffPatchElement("base-patch-001", "base", false) .addModuleWithRandomContent("test.module", null) .getParent() .addFileWithRandomContent(null, "test", "file") ; final File overlays = builder.getFile(MODULES_BASE); // Make the modification.complete() fail final File file = new File(overlays, ".overlays"); Assert.assertTrue(file.mkdirs()); try { apply(step1); tree(builder.getRoot()); Assert.fail(); } catch (Exception e) { // Ok Assert.assertFalse(builder.hasFile("test", "file")); Assert.assertFalse(new File(overlays, "base-patch-001").exists()); } } }