gt:         Path appCache = cache.resolve("apps").resolve("com.acme.Foo");
context: /*
   * Capsule
   * Copyright (c) 2014-2015, Parallel Universe Software Co. All rights reserved.
   * 
   * This program and the accompanying materials are licensed under the terms 
   * of the Eclipse Public License v1.0, available at
   * http://www.eclipse.org/legal/epl-v10.html
   */
  
  import co.paralleluniverse.capsule.Jar;
  import co.paralleluniverse.capsule.test.CapsuleTestUtils;
  import co.paralleluniverse.capsule.test.CapsuleTestUtils.StringPrintStream;
  import static co.paralleluniverse.capsule.test.CapsuleTestUtils.*;
  import co.paralleluniverse.common.ZipFS;
  import com.google.common.jimfs.Jimfs;
  import java.io.IOException;
  import java.io.InputStream;
  import static java.nio.charset.StandardCharsets.UTF_8;
  import java.nio.file.FileSystem;
  import java.nio.file.FileSystems;
  import java.nio.file.FileVisitResult;
  import java.nio.file.Files;
  import java.nio.file.Path;
  import java.nio.file.PathMatcher;
  import java.nio.file.SimpleFileVisitor;
  import java.nio.file.attribute.BasicFileAttributes;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.Collection;
  import java.util.Collections;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Map;
  import java.util.Properties;
  import java.util.Set;
  import java.util.jar.JarInputStream;
  import org.junit.After;
  import org.junit.Test;
  import static org.junit.Assert.*;
  import static org.junit.Assume.*;
  import org.junit.Before;
  import static com.google.common.truth.Truth.*;
  import org.joor.Reflect;
  //import static org.mockito.Mockito.*;
  
  public class CapsuleTest {
      /*
       * As a general rule, we prefer system tests, and only create unit tests for particular methods that,
       * while tested for integration, whose arguments don't get enough coverage in the system tests (like parsing methods and the like).
       *
       * All the tests in this test suite use an in-memory file system, and don't write to the disk at all.
       */
      private final FileSystem fs = Jimfs.newFileSystem();
      private final Path cache = fs.getPath("/cache");
      private final Path tmp = fs.getPath("/tmp");
      private static final ClassLoader MY_CLASSLOADER = Capsule.class.getClassLoader();
  
      private Properties props;
  
      @Before
      public void setUp() throws Exception {
          props = new Properties(System.getProperties());
          setProperties(props);
          setCacheDir(cache);
          resetOutputStreams();
  
          TestCapsule.reset();
      }
  
      @After
      public void tearDown() throws Exception {
          fs.close();
      }
  
      //<editor-fold desc="System Tests">
      /////////// System Tests ///////////////////////////////////
      @Test
      public void testSimpleExtract() throws Exception {
          Jar jar = newCapsuleJar()
                  .setAttribute("Application-Class", "com.acme.Foo")
                  .addEntry("foo.jar", emptyInputStream())
                  .addEntry("a.class", emptyInputStream())
                  .addEntry("b.txt", emptyInputStream())
                  .addEntry("lib/a.jar", emptyInputStream())
                  .addEntry("lib/b.class", emptyInputStream())
                  .addEntry("q/w/x.txt", emptyInputStream())
                  .addEntry("d\\f\\y.txt", emptyInputStream()) // test with Windows path
                  .addEntry("META-INF/x.txt", emptyInputStream());
  
          List<String> args = list("hi", "there");
          List<String> cmdLine = list();
  
          Capsule capsule = newCapsule(jar);
          ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
  
          // dumpFileSystem(fs);
          assertEquals(args, getAppArgs(pb));
  
          Path appCache = cache.resolve("apps").resolve("com.acme.Foo");
  
          assertEquals("com.acme.Foo", getProperty(pb, "capsule.app"));
          assertEquals("com.acme.Foo", getEnv(pb, "CAPSULE_APP"));
          assertEquals(appCache, path(getProperty(pb, "capsule.dir")));
          assertEquals(absolutePath("capsule.jar"), path(getProperty(pb, "capsule.jar")));
          assertEquals(appCache, path(getEnv(pb, "CAPSULE_DIR")));
          assertEquals(absolutePath("capsule.jar"), path(getEnv(pb, "CAPSULE_JAR")));
  
          assertEquals(list("com.acme.Foo", "hi", "there"), getMainAndArgs(pb));
  
          assertTrue(Files.isDirectory(cache));
          assertTrue(Files.isDirectory(cache.resolve("apps")));
          assertTrue(Files.isDirectory(appCache));
          assertTrue(Files.isRegularFile(appCache.resolve(".extracted")));
          assertTrue(Files.isRegularFile(appCache.resolve("foo.jar")));
          assertTrue(Files.isRegularFile(appCache.resolve("b.txt")));
          assertTrue(Files.isDirectory(appCache.resolve("lib")));
          assertTrue(Files.isRegularFile(appCache.resolve("lib").resolve("a.jar")));
          assertTrue(!Files.isRegularFile(appCache.resolve("a.class")));
          assertTrue(!Files.isRegularFile(appCache.resolve("lib").resolve("b.class")));
          assertTrue(!Files.isDirectory(appCache.resolve("META-INF")));
          assertTrue(!Files.isRegularFile(appCache.resolve("META-INF").resolve("x.txt")));
  
          assertTrue(Files.isDirectory(appCache.resolve("q").resolve("w")));
          assertTrue(Files.isDirectory(appCache.resolve("d").resolve("f")));
          assertTrue(Files.isRegularFile(appCache.resolve("q").resolve("w").resolve("x.txt")));
          assertTrue(Files.isRegularFile(appCache.resolve("d").resolve("f").resolve("y.txt")));
  
          assert_().that(getClassPath(pb)).has().item(absolutePath("capsule.jar"));
          assert_().that(getClassPath(pb)).has().item(appCache);
          assert_().that(getClassPath(pb)).has().item(appCache.resolve("foo.jar"));
          assert_().that(getClassPath(pb)).has().noneOf(appCache.resolve("lib").resolve("a.jar"));
      }
  
      @Test
      public void testNoExtract() throws Exception {
          Jar jar = newCapsuleJar()
                  .setAttribute("Application-Class", "com.acme.Foo")
                  .addEntry("foo.txt", emptyInputStream())
                  .addEntry("lib/a.jar", emptyInputStream());
  
          List<String> args = list("hi", "there");
          List<String> cmdLine = list();
  
          Capsule capsule = newCapsule(jar);
          ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
  
          assertEquals(args, getAppArgs(pb));
  
          Path appCache = cache.resolve("apps").resolve("com.acme.Foo");
          assertTrue(!Files.isDirectory(appCache));
      }
  
      @Test
      public void testJDKClassPath() throws Exception {
          assumeTrue(!isCI());
  
          Jar jar = newCapsuleJar()
                  .setAttribute("Application-Class", "com.acme.Foo")
                  //.setAttribute("Extract-Capsule", "false")
                  .setAttribute("JDK-Required", "true")
                  .setListAttribute("App-Class-Path", list("$JAVA_HOME/lib/tools.jar", "lib/*"))
                  .addEntry("foo.jar", emptyInputStream())
                  .addEntry("lib/a.jar", emptyInputStream())
                  .addEntry("lib/b.jar", emptyInputStream());
  
          List<String> args = list("hi", "there");
          List<String> cmdLine = list();
  
          Capsule capsule = newCapsule(jar);
          ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
          Path javaHome = path(capsule.getJavaHome().toString()); // different FS
  
          assertEquals(args, getAppArgs(pb));
  
          Path appCache = cache.resolve("apps").resolve("com.acme.Foo");
  
          assert_().that(javaHome.toString()).contains("jdk");
          assert_().that(javaHome.toString()).doesNotContain("jre");
          assert_().that(getClassPath(pb)).has().allOf(
                  javaHome.resolve("lib/tools.jar"),
                  appCache,
                  appCache.resolve("foo.jar"),
                  appCache.resolve("lib").resolve("a.jar"),
                  appCache.resolve("lib").resolve("b.jar"));
      }
  
      @Test
      public void testLogLevel() throws Exception {
          setSTDERR(DEVNULL);
  
          Jar jar = newCapsuleJar()
                  .setAttribute("Application-Class", "com.acme.Foo")
                  .setAttribute("Extract-Capsule", "false")
                  .setAttribute("Capsule-Log-Level", "verbose");
  
          newCapsule(jar);
          assertTrue(Capsule.isLogging(2));
          assertTrue(!Capsule.isLogging(3));
  
          props.setProperty("capsule.log", "none");
          newCapsule(jar);
          assertTrue(Capsule.isLogging(0));
          assertTrue(!Capsule.isLogging(1));
  
          props.setProperty("capsule.log", "quiet");
          newCapsule(jar);
          assertTrue(Capsule.isLogging(1));
          assertTrue(!Capsule.isLogging(2));
  
          props.setProperty("capsule.log", "");
          newCapsule(jar);
          assertTrue(Capsule.isLogging(1));
          assertTrue(!Capsule.isLogging(2));
  
          props.setProperty("capsule.log", "verbose");
          newCapsule(jar);
          assertTrue(Capsule.isLogging(2));
          assertTrue(!Capsule.isLogging(3));
  
          props.setProperty("capsule.log", "debug");
          newCapsule(jar);
          assertTrue(Capsule.isLogging(3));
      }
  
      @Test
      public void testCapsuleJavaHome() throws Exception {
          props.setProperty("capsule.java.home", "/my/1.7.0.jdk/home");
  
          Jar jar = newCapsuleJar()
                  .setAttribute("Application-Class", "com.acme.Foo")
                  .setAttribute("Extract-Capsule", "false")
                  .addEntry("foo.jar", emptyInputStream());
  
          List<String> args = list("hi", "there");
          List<String> cmdLine = list();
  
          Capsule capsule = newCapsule(jar);
          ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
  
          assertEquals("/my/1.7.0.jdk/home/bin/java" + (Capsule.isWindows() ? ".exe" : ""), pb.command().get(0));
      }
  
      @Test
      public void testCapsuleJavaCmd() throws Exception {
          props.setProperty("capsule.java.cmd", "/my/java/home/gogo");
  
          Jar jar = newCapsuleJar()
                  .setAttribute("Application-Class", "com.acme.Foo")
                  .setAttribute("Extract-Capsule", "false")
                  .addEntry("foo.jar", emptyInputStream());
  
          List<String> args = list("hi", "there");
          List<String> cmdLine = list();
  
          Capsule capsule = newCapsule(jar);
          ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
  
          assertEquals("/my/java/home/gogo", pb.command().get(0));
      }
  
      @Test
      public void testClassPath() throws Exception {
          Jar jar = newCapsuleJar()
                  .setAttribute("Application-Class", "com.acme.Foo")
                  .setListAttribute("App-Class-Path", list("lib/a.jar", "lib/b.jar", "lib2/*.jar"))
                  .addEntry("foo.jar", emptyInputStream())
                  .addEntry("lib/a.jar", emptyInputStream())
                  .addEntry("lib/b.jar", emptyInputStream())
                  .addEntry("lib2/c.jar", emptyInputStream())
                  .addEntry("lib2/d.jar", emptyInputStream())
                  .addEntry("lib2/e.txt", emptyInputStream());
  
          List<String> args = list("hi", "there");
          List<String> cmdLine = list();
  
          Capsule capsule = newCapsule(jar);
          ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
  
  