gt:         final JavaArchive archive = ShrinkWrap.create(JavaArchive.class)
context: /*
   * 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 java.io.File;
  import java.io.IOException;
  import java.lang.reflect.Constructor;
  import java.net.URL;
  import java.net.URLClassLoader;
  import java.util.Arrays;
  import java.util.zip.ZipException;
  import java.util.zip.ZipFile;
  
  import org.jboss.as.patching.HashUtils;
  import org.jboss.as.patching.IoUtils;
  import org.jboss.as.patching.installation.PatchableTarget;
  import org.jboss.as.patching.runner.TestUtils;
  import org.jboss.shrinkwrap.api.ShrinkWrap;
  import org.jboss.shrinkwrap.api.asset.StringAsset;
  import org.jboss.shrinkwrap.api.exporter.ZipExporter;
  import org.jboss.shrinkwrap.api.spec.JavaArchive;
  import org.junit.Assert;
  import org.junit.Assume;
  import org.junit.BeforeClass;
  import org.junit.Test;
  
  import static org.jboss.as.patching.runner.PatchUtils.BACKUP_EXT;
  import static org.jboss.as.patching.runner.PatchUtils.JAR_EXT;
  import static org.jboss.as.patching.runner.TestUtils.createModule0;
  import static org.jboss.as.patching.runner.TestUtils.randomString;
  import static org.junit.Assert.assertThat;
  import static org.hamcrest.CoreMatchers.is;
  
  /**
   * @author Emanuel Muckenhuber
   */
  public class PatchModuleInvalidationTestCase extends AbstractPatchingTest {
  
      private static final Boolean INVALIDATION_ENABLED = Boolean.getBoolean("org.wildfly.patching.jar.invalidation");
      private static final String MODULE_NAME = "org.jboss.test.module";
      private static final String RESOURCE = "resource0.jar";
  
      private static final TestUtils.ContentTask CONTENT_TASK = new TestUtils.ContentTask() {
          @Override
          public String[] writeContent(File target) throws IOException {
              writeJar(new File(target, RESOURCE));
              return new String[] { RESOURCE };
          }
      };
  
      @BeforeClass
      public static void checkValidationEnabled() {
          Assume.assumeTrue(INVALIDATION_ENABLED);
      }
  
      @Test
      public void test() throws Exception {
  
          final PatchingTestBuilder test = createDefaultBuilder();
  
          final File root = test.getRoot();
          final File installation = new File(root, JBOSS_INSTALLATION);
          final File moduleRoot = new File(installation, "modules/system/layers/base".replace('/', File.separatorChar));
          final File module0 = createModule0(moduleRoot, MODULE_NAME, CONTENT_TASK);
          final File resource = new File(module0, "main/resource0.jar".replace('/', File.separatorChar));
          final File resourceBackup = new File(module0, "main/resource0.jar.patched".replace('/', File.separatorChar));
          assertLoadable(resource);
  
          final byte[] existingHash = HashUtils.hashFile(module0);
          final byte[] resultingHash = Arrays.copyOf(existingHash, existingHash.length);
  
          final PatchingTestStepBuilder oop1 = test.createStepBuilder();
          oop1.setPatchId("oop1")
                  .oneOffPatchIdentity(PRODUCT_VERSION)
                  .oneOffPatchElement("base-oop1", "base", false)
                  .updateModule(MODULE_NAME, existingHash, resultingHash, CONTENT_TASK)
                  ;
  
          apply(oop1);
          assertThat(resourceBackup.exists(), is(true));
          assertThat(resource.exists(), is(false));
          assertNotLoadable(resourceBackup);
  
          // Module in patch oop1
          final File resource1 = getModuleResource("base-oop1", MODULE_NAME);
          assertLoadable(resource1);
          final File resource1Backup = getBackupFile(resource1);
          assertThat(resource1Backup.exists(), is(false));
          assertThat(resource1.exists(), is(true));
  
          final PatchingTestStepBuilder oop2 = test.createStepBuilder();
          oop2.setPatchId("oop2")
                  .oneOffPatchIdentity(PRODUCT_VERSION)
                  .oneOffPatchElement("base-oop2", "base", false)
                  .updateModule(MODULE_NAME, resultingHash, null, CONTENT_TASK)
                  ;
  
          apply(oop2);
  
          // Module in patch oop2
          final File resource2 = getModuleResource("base-oop2", MODULE_NAME);
          final File resource2Backup = getBackupFile(resource2);
          assertThat(resource2Backup.exists(), is(false));
          assertThat(resource2.exists(), is(true));
  
          assertNotLoadable(resourceBackup);
          assertThat(resource1Backup.exists(), is(true));
          assertThat(resource1.exists(), is(false));
          assertNotLoadable(resource1Backup);
          assertLoadable(resource2);
  
          final PatchingTestStepBuilder cp1 = test.createStepBuilder();
          cp1.setPatchId("cp1")
                  .upgradeIdentity(PRODUCT_VERSION, PRODUCT_VERSION)
                  .upgradeElement("base-cp1", "base", false)
                  .updateModule(MODULE_NAME, existingHash, resultingHash, CONTENT_TASK)
                  ;
  
          apply(cp1);
  
          // Module in patch cp1
          final File resource3 = getModuleResource("base-cp1", MODULE_NAME);
          final File resource3Backup = getBackupFile(resource3);
          assertThat(resource3Backup.exists(), is(false));
          assertThat(resource3.exists(), is(true));
  
          assertNotLoadable(resourceBackup);
          assertNotLoadable(resource1Backup);
          assertThat(resource2Backup.exists(), is(true));
          assertThat(resource2.exists(), is(false));
          assertNotLoadable(resource2Backup);
          assertLoadable(resource3);
  
          final PatchingTestStepBuilder cp2 = test.createStepBuilder();
          cp2.setPatchId("cp2")
                  .upgradeIdentity(PRODUCT_VERSION, PRODUCT_VERSION)
                  .upgradeElement("base-cp2", "base", false)
                  .updateModule(MODULE_NAME, resultingHash, null, CONTENT_TASK)
                  ;
  
          apply(cp2);
  
          // Module in patch cp2
          final File resource4 = getModuleResource("base-cp2", MODULE_NAME);
  
          assertNotLoadable(resourceBackup);
          assertNotLoadable(resource1Backup);
          assertNotLoadable(resource2Backup);
          assertThat(resource3Backup.exists(), is(true));
          assertThat(resource3.exists(), is(false));
          assertNotLoadable(resource3Backup);
          assertLoadable(resource4);
  
          rollback(cp2);
  
          assertNotLoadable(resourceBackup);
          assertNotLoadable(resource1Backup);
          assertNotLoadable(resource2Backup);
          assertThat(resource3Backup.exists(), is(false));
          assertThat(resource3.exists(), is(true));
          assertLoadable(resource3);
  
          rollback(cp1);
  
          assertNotLoadable(resourceBackup);
          assertNotLoadable(resource1Backup);
          assertThat(resource2Backup.exists(), is(false));
          assertThat(resource2.exists(), is(true));
          assertLoadable(resource2);
  
          rollback(oop2);
          assertNotLoadable(resourceBackup);
          assertThat(resource1Backup.exists(), is(false));
          assertThat(resource1.exists(), is(true));
          assertLoadable(resource1);
  
          rollback(oop1);
          assertThat(resourceBackup.exists(), is(false));
          assertThat(resource.exists(), is(true));
          assertLoadable(resource);
      }
  
      File getModuleResource(final String patchID, final String moduleName) throws IOException {
          return getModuleResource("base", patchID, moduleName);
      }
  
      File getModuleResource(final String layer, final String patchID, final String moduleName) throws IOException {
          final PatchableTarget.TargetInfo info = getLayer(layer).loadTargetInfo();
          final File root = info.getDirectoryStructure().getModulePatchDirectory(patchID);
          final File moduleRoot = TestUtils.getModuleRoot(root, moduleName);
          return new File(moduleRoot, RESOURCE);
      }
  
      static File writeJar(final File target) {
  