/**
   * Test to make sue an archive can be exported and nested archives are also in exported.
   *
   * @throws Exception
   */
  @Test
  public void testExportNested() throws Exception {
    log.info("testExportNested");

    // Get a temp directory for the test
    final File tempDirectory = createTempDirectory("testExportNested");

    // Get an archive instance
    final Archive<?> archive = createArchiveWithNestedArchives();

    // Export as InputStream
    final InputStream exportStream = this.exportAsInputStream(archive);

    // Write out and retrieve as exported file
    final File exported = new File(tempDirectory, NAME_ARCHIVE + this.getArchiveExtension());
    final OutputStream exportedOut = new FileOutputStream(exported);
    IOUtil.copyWithClose(exportStream, exportedOut);

    // Validate entries were written out
    this.ensureAssetInExportedFile(exported, PATH_ONE, ASSET_ONE);
    this.ensureAssetInExportedFile(exported, PATH_TWO, ASSET_TWO);

    // Validate nested archive entries were written out
    final ArchivePath nestedArchivePath =
        ArchivePaths.create(NAME_NESTED_ARCHIVE + this.getArchiveExtension());

    // Get inputstream for entry
    final InputStream nestedArchiveStream =
        this.getContentsFromExportedFile(exported, nestedArchivePath);

    // Write out and retrieve nested contents
    final File nestedFile =
        new File(tempDirectory, NAME_NESTED_ARCHIVE + this.getArchiveExtension());
    final OutputStream nestedOut = new FileOutputStream(nestedFile);
    IOUtil.copyWithClose(nestedArchiveStream, nestedOut);

    // Ensure contents are in the nested
    this.ensureAssetInExportedFile(nestedFile, PATH_ONE, ASSET_ONE);
    this.ensureAssetInExportedFile(nestedFile, PATH_TWO, ASSET_TWO);

    // Validate nested archive entries were written out
    final ArchivePath nestedArchiveTwoPath =
        ArchivePaths.create(NESTED_PATH, NAME_NESTED_ARCHIVE_2 + this.getArchiveExtension());
    this.getContentsFromExportedFile(exported, nestedArchiveTwoPath);
    final InputStream nestedArchiveTwoStream =
        this.getContentsFromExportedFile(exported, nestedArchiveTwoPath);

    // Write out and retrieve secondnested contents
    final File nestedTwoFile =
        new File(tempDirectory, NAME_NESTED_ARCHIVE_2 + this.getArchiveExtension());
    final OutputStream nestedTwoOut = new FileOutputStream(nestedTwoFile);
    IOUtil.copyWithClose(nestedArchiveTwoStream, nestedTwoOut);

    // Ensure contents are in the second nested
    this.ensureAssetInExportedFile(nestedTwoFile, PATH_ONE, ASSET_ONE);
    this.ensureAssetInExportedFile(nestedTwoFile, PATH_TWO, ASSET_TWO);
  }
  /**
   * {@inheritDoc}
   *
   * @see
   *     org.jboss.shrinkwrap.impl.base.exporter.StreamExporterTestBase#ensureAssetInExportedFile(java.io.File,
   *     org.jboss.shrinkwrap.api.ArchivePath, org.jboss.shrinkwrap.api.asset.Asset)
   */
  protected final void ensureAssetInExportedFile(
      final File file, final ArchivePath path, final Asset asset) throws IOException {
    // Precondition checks
    assert file != null : "file must be specified";
    assert path != null : "path must be specified";
    assert asset != null : "asset must be specified";

    // Get as Exported File
    final InputStream actualStream = this.getContentsFromExportedFile(file, path);
    assert actualStream != null
        : "No contents found at path " + path + " in " + file.getAbsolutePath();
    byte[] actualContents = IOUtil.asByteArray(actualStream);
    byte[] expectedContents = IOUtil.asByteArray(asset.openStream());
    Assert.assertArrayEquals(expectedContents, actualContents);
  }
  @Test(expected = ArchiveExportException.class)
  public void testExportThrowsArchiveExceptionOnAssetWriteFailure() throws IOException {
    log.info("testExportThrowsArchiveExceptionOnAssetWriteFailure");
    Archive<?> archive = createArchiveWithAssets();

    // Check if a the path already contains a node so we remove it from the parent's children
    if (archive.contains(PATH_ONE)) {
      archive.delete(PATH_ONE);
    }

    archive.add(
        new Asset() {
          @Override
          public InputStream openStream() {
            throw new RuntimeException("Mock Exception from an Asset write");
          }
        },
        PATH_ONE);

    // Export
    final InputStream in = this.exportAsInputStream(archive);

    // Read in the full content (to in turn empty the underlying buffer and ensure we complete)
    final OutputStream sink =
        new OutputStream() {
          @Override
          public void write(int b) throws IOException {}
        };
    IOUtil.copyWithClose(in, sink);
  }
  /**
   * Test to make sue an archive can be exported and all contents are correctly located.
   *
   * @throws Exception
   */
  @Test
  public void testExport() throws Exception {
    log.info("testExport");

    // Get an archive instance
    Archive<?> archive = createArchiveWithAssets();

    // Export as InputStream
    final InputStream exportStream = this.exportAsInputStream(archive);

    // Validate
    final File tempDirectory = createTempDirectory("testExport");
    final File serialized = new File(tempDirectory, archive.getName());
    final FileOutputStream out = new FileOutputStream(serialized);
    IOUtil.copyWithClose(exportStream, out);
    ensureInExpectedForm(serialized);
  }
  /**
   * Test to ensure that the export process accepts an archive with only directories, no assets.
   *
   * @throws Exception
   */
  @Test
  public void testExportArchiveWithOnlyDirectories() throws IOException {
    // Create an archive with directories
    final ArchivePath path = ArchivePaths.create("/test/game");
    final Archive<?> archive =
        ShrinkWrap.create(JavaArchive.class, NAME_ARCHIVE).addAsDirectories(path);

    // Fully export by reading all content (export is on-demand)
    final InputStream content = this.exportAsInputStream(archive);
    final ByteArrayOutputStream exportedContents = new ByteArrayOutputStream();
    IOUtil.copyWithClose(content, exportedContents);

    final GenericArchive roundtrip =
        ShrinkWrap.create(this.getImporterClass(), "roundtrip.zip")
            .importFrom(new ByteArrayInputStream(exportedContents.toByteArray()))
            .as(GenericArchive.class);
    log.info(roundtrip.toString(true));
    Assert.assertTrue(roundtrip.contains(path));
  }
  /**
   * Ensures that the export write task uses the {@link ExecutorService} that we've configured, and
   * leaves it running (does not shut it down)
   *
   * @throws Exception
   */
  @Test
  public void exportUsesOurExecutorService() throws Exception {
    // Make a custom ES
    final CountingExecutorService service = new CountingExecutorService();

    // Create a custom configuration
    final Domain domain =
        ShrinkWrap.createDomain(new ConfigurationBuilder().executorService(service).build());

    // Make an archive using the new configuration
    final Archive<?> archive =
        domain
            .getArchiveFactory()
            .create(JavaArchive.class, "test.jar")
            .addClass(StreamExporterTestBase.class);

    // Fully export by reading all content (export is on-demand)
    final InputStream content = this.exportAsInputStream(archive);
    final OutputStream sink =
        new OutputStream() {

          @Override
          public void write(int b) throws IOException {
            // NOOP
          }
        };
    IOUtil.copyWithClose(content, sink);

    // Ensure the ES was used (one job was submitted to it)
    Assert.assertEquals(
        "Custom " + ExecutorService.class.getSimpleName() + " was not used by export process",
        1,
        service.counter);

    // Ensure the ES was not shut down by the export process
    Assert.assertFalse(
        "Export should not shut down a user-supplied " + ExecutorService.class.getName(),
        service.isShutdown());

    // Shut down the ES (clean up)
    service.shutdown();
  }