/*
 * Copyright 2008 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.dev.resource.impl;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.dev.resource.Resource;
import com.google.gwt.dev.util.Util;
import com.google.gwt.util.tools.Utility;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Tests {@link ResourceOracleImpl}.
 * 
 * <pre>
 * Important states to test:
 * - No class path entries
 * - A single class path entries
 *   - init/add/update/remove
 * - Multiple class path entries
 *   - init/add/update/remove
 *   - same as previous with shadowing
 *   - same as previous with superceding
 * </pre>
 */
public class ResourceOracleImplTest extends AbstractResourceOrientedTestBase {

  // Starts empty but can change during tests.
  private static class MOCK_CPE0 extends MockClassPathEntry {
    public MOCK_CPE0() {
      super("/cpe0/");
    }
  }

  private static class MOCK_CPE3 extends MockClassPathEntry {
    public MOCK_CPE3() {
      super("/cpe3/");
    }
  }

  private static class ResourceOracleSnapshot {
    private final Set<String> pathNames;
    private final Map<String, Resource> resourceMap;
    private final Set<Resource> resources;

    public ResourceOracleSnapshot(ResourceOracleImpl oracle) {
      resources = oracle.getResources();
      resourceMap = oracle.getResourceMap();
      pathNames = oracle.getPathNames();
    }

    public void assertCollectionsConsistent(int expectedSize) {
      assertEquals(expectedSize, resources.size());
      assertEquals(resources.size(), resourceMap.size());
      assertEquals(resources.size(), pathNames.size());

      // Ensure every resource is in the map correctly.
      for (Resource r : resources) {
        assertSame(r, resourceMap.get(r.getPath()));
      }

      // Ensure that every resource path is in the set.
      for (Resource r : resources) {
        assertTrue(pathNames.contains(r.getPath()));
      }
    }

    public void assertNotSameCollections(ResourceOracleSnapshot other) {
      assertNotSame(resourceMap, other.resourceMap);
      assertNotSame(resources, other.resources);
      assertNotSame(pathNames, other.pathNames);
    }

    public void assertPathIncluded(String path) {
      assertNotNull(findResourceWithPath(path));
    }

    /**
     * Asserts that a resource having the specified path is present and that it
     * was contributed by the specified classpath entry.
     */
    public void assertPathIncluded(String expectedPath,
        ClassPathEntry expectedCpe) {
      AbstractResource r = findResourceWithPath(expectedPath);
      assertNotNull(r);
      ClassPathEntry actualCpe = r.getClassPathEntry();
      assertEquals(expectedCpe.getLocation(), actualCpe.getLocation());
    }

    public void assertPathNotIncluded(String path) {
      assertNull(findResourceWithPath(path));
    }

    public void assertSameCollections(ResourceOracleSnapshot other) {
      assertResourcesEqual(resourceMap, other.resourceMap);
      assertResourcesEqual(resources, other.resources);
      assertEquals(pathNames, other.pathNames);
    }

    public AbstractResource findResourceWithPath(String path) {
      for (Resource r : resources) {
        if (r.getPath().equals(path)) {
          return (AbstractResource) r;
        }
      }
      return null;
    }

    @SuppressWarnings("deprecation")
    public void assertResourcesGetURL() {
      for (Resource resource : resources) {
        URL url = resource.getURL();
        assertNotNull("Resource " + resource + " had a null getURL()", url);

        InputStream is = resource.openContents();
        assertNotNull(is);

        String urlString = Util.readURLAsString(url);
        String inputString = Util.readStreamAsString(is);
        assertEquals(urlString, inputString);
        assertNotNull(urlString);
        assertNotNull(inputString);
      }
    }
  }

  public static void assertResourcesEqual(Collection<Resource> expected,
      Collection<Resource> actual) {
    Set<String> expectedLocs = new HashSet<String>();
    for (Resource resource : expected) {
      expectedLocs.add(resource.getLocation());
    }
    Set<String> actualLocs = new HashSet<String>();
    for (Resource resource : actual) {
      actualLocs.add(resource.getLocation());
    }
    assertEquals(expectedLocs, actualLocs);
  }

  public static void assertResourcesEqual(Map<String, Resource> expected,
      Map<String, Resource> actual) {
    assertResourcesEqual(expected.values(), actual.values());
  }

  private static PathPrefix makeJavaLangPrefix() {
    return new PathPrefix("java/lang/", null, false);
  }

  private static PathPrefix makeBarPrefix() {
    return new PathPrefix("org/example/bar/client/", null, false);
  }

  private static PathPrefix makeRerootBarPrefix() {
    return new PathPrefix("org/example/bar/client/", null, true);
  }

  private static PathPrefix makeRerootFooPrefix() {
    return new PathPrefix("org/example/foo/client/", null, true);
  }

  private static PathPrefix makeTranslatablePrefix() {
    return new PathPrefix("translatable/", null, true);
  }

  public void testCachingOfJarResources() throws IOException,
      URISyntaxException {
    TreeLogger logger = createTestTreeLogger();
    File jarFile = findFile("com/google/gwt/dev/resource/impl/testdata/cpe1.jar");
    ClassPathEntry cpe1jar = ZipFileClassPathEntry.get(jarFile);

    // test basic caching
    PathPrefixSet pps1 = new PathPrefixSet();
    pps1.add(new PathPrefix("com/google/gwt/", null, false));
    Map<AbstractResource, PathPrefix> resourceMap1 = cpe1jar.findApplicableResources(
        logger, pps1);
    assertSame(resourceMap1, cpe1jar.findApplicableResources(logger, pps1));

    // test that cache is invalidated if PathPrefixSet is modified.
    pps1.add(new PathPrefix("com/google/gwt/user/", null, false));
    Map<AbstractResource, PathPrefix> resourceMap2 = cpe1jar.findApplicableResources(
        logger, pps1);
    assertNotSame(resourceMap1, resourceMap2);

    PathPrefixSet pps2 = new PathPrefixSet();
    pps2.add(new PathPrefix("org/example/bar/", null, false));
    Map<AbstractResource, PathPrefix> resourceMap3 = cpe1jar.findApplicableResources(
        logger, pps2);
    // check that the entry did go in the cache
    assertSame(resourceMap3, cpe1jar.findApplicableResources(logger, pps2));

    // check that the cache does not thrash
    assertSame(resourceMap2, cpe1jar.findApplicableResources(logger, pps1));
    assertSame(resourceMap3, cpe1jar.findApplicableResources(logger, pps2));
  }

  public void testGetUrlOnResources() throws URISyntaxException, IOException {
    ClassPathEntry cpe1jar = getClassPathEntry1AsJar();
    ClassPathEntry cpe1dir = getClassPathEntry1AsDirectory();
    ClassPathEntry cpe1zip = getClassPathEntry1AsZip();

    ClassPathEntry cpe2jar = getClassPathEntry2AsJar();
    ClassPathEntry cpe2dir = getClassPathEntry2AsDirectory();
    ClassPathEntry cpe2zip = getClassPathEntry2AsZip();

    testGetURLOnResourcesInCPE(cpe1jar);
    testGetURLOnResourcesInCPE(cpe1dir);
    testGetURLOnResourcesInCPE(cpe1zip);
    testGetURLOnResourcesInCPE(cpe2jar);
    testGetURLOnResourcesInCPE(cpe2dir);
    testGetURLOnResourcesInCPE(cpe2zip);
  }

  private void testGetURLOnResourcesInCPE(ClassPathEntry cpe) {
    TreeLogger logger = createTestTreeLogger();

    ResourceOracleImpl oracle = createResourceOracle(cpe);
    ResourceOracleSnapshot s = refreshAndSnapshot(logger, oracle);
    s.assertResourcesGetURL();
  }

  /**
   * Test that ResourceOracleImpl preserves the order in which the same logical
   * resource is occurs in multiple ClassPathEntries.
   * 
   * @throws URISyntaxException
   * @throws IOException
   */
  public void testClassPathOrderIsHonored() throws IOException,
      URISyntaxException {
    TreeLogger logger = createTestTreeLogger();
    ClassPathEntry cpe1jar = getClassPathEntry1AsJar();
    ClassPathEntry cpe2jar = getClassPathEntry2AsJar();

    ClassPathEntry[] cp12 = new ClassPathEntry[]{cpe1jar, cpe2jar};
    ClassPathEntry[] cp21 = new ClassPathEntry[]{cpe2jar, cpe1jar};
    String resKeyNormal = "org/example/bar/client/BarClient2.txt";
    String resKeyReroot = "BarClient2.txt";
    testResourceInCPE(logger, resKeyNormal, cpe1jar, cp12, makeBarPrefix());
    testResourceInCPE(logger, resKeyReroot, cpe1jar, cp12,
        makeRerootBarPrefix());
    testResourceInCPE(logger, resKeyNormal, cpe2jar, cp21, makeBarPrefix());
    testResourceInCPE(logger, resKeyReroot, cpe2jar, cp21,
        makeRerootBarPrefix());
  }

  public void testNoClassPathEntries() {
    TreeLogger logger = createTestTreeLogger();
    ResourceOracleImpl oracle = createResourceOracle(new MOCK_CPE0());
    ResourceOracleSnapshot s = refreshAndSnapshot(logger, oracle);
    s.assertCollectionsConsistent(0);
  }

  /**
   * Test that ResourceOracleImpl prefers the order of path prefixes over
   * ClassPathEntries.
   * <p>
   * cpe1 contains org/example/bar/client/BarClient1.txt and cpe2 contains
   * org/example/foo/client/BarClient1.txt
   * 
   * @throws URISyntaxException
   * @throws IOException
   */
  public void testPathPrefixOrderPreferredOverClasspath() throws IOException,
      URISyntaxException {
    TreeLogger logger = createTestTreeLogger();
    ClassPathEntry cpe1jar = getClassPathEntry1AsJar();
    ClassPathEntry cpe2jar = getClassPathEntry2AsJar();

    ClassPathEntry[] cp12 = new ClassPathEntry[]{cpe1jar, cpe2jar};
    ClassPathEntry[] cp21 = new ClassPathEntry[]{cpe2jar, cpe1jar};

    String keyReroot = "BarClient1.txt";

    // Resource in cpe2 wins because pp2 comes later.
    testResourceInCPE(logger, keyReroot, cpe2jar, cp12, makeRerootBarPrefix(),
        makeRerootFooPrefix());
    // Order of specifying classpath is reversed, it still matches cpe2.
    testResourceInCPE(logger, keyReroot, cpe2jar, cp21, makeRerootBarPrefix(),
        makeRerootFooPrefix());

    // Resource in cpe1 wins because pp1 comes later.
    testResourceInCPE(logger, keyReroot, cpe1jar, cp12, makeRerootFooPrefix(),
        makeRerootBarPrefix());
    // Order of specifying classpath is reversed, it still matches cpe1.
    testResourceInCPE(logger, keyReroot, cpe1jar, cp21, makeRerootFooPrefix(),
        makeRerootBarPrefix());
  }

  /**
   * Tests the actual reading of resources.
   * 
   * @throws URISyntaxException
   * @throws IOException
   */
  public void testReadingResource() throws IOException, URISyntaxException {
    ClassPathEntry cpe1jar = getClassPathEntry1AsJar();
    ClassPathEntry cpe1dir = getClassPathEntry1AsDirectory();
    ClassPathEntry cpe1zip = getClassPathEntry1AsZip();

    ClassPathEntry cpe2jar = getClassPathEntry2AsJar();
    ClassPathEntry cpe2dir = getClassPathEntry2AsDirectory();
    ClassPathEntry cpe2zip = getClassPathEntry2AsZip();

    testReadingResource(cpe1jar, cpe2jar);
    testReadingResource(cpe1dir, cpe2jar);
    testReadingResource(cpe1zip, cpe2jar);

    testReadingResource(cpe1jar, cpe2dir);
    testReadingResource(cpe1dir, cpe2dir);
    testReadingResource(cpe1zip, cpe2dir);

    testReadingResource(cpe1jar, cpe2zip);
    testReadingResource(cpe1dir, cpe2zip);
    testReadingResource(cpe1zip, cpe2zip);
  }

  /**
   * Verify that duplicate entries are removed from the classpath, and that
   * multiple ResourceOracleImpls created from the same classloader return the
   * same list of ClassPathEntries.
   * 
   * @throws MalformedURLException
   */
  public void testRemoveDuplicates() {
    TreeLogger logger = createTestTreeLogger();
    URL cpe1 = findUrl("com/google/gwt/dev/resource/impl/testdata/cpe1.jar");
    URL cpe2 = findUrl("com/google/gwt/dev/resource/impl/testdata/cpe2.zip");
    URLClassLoader classLoader = new URLClassLoader(new URL[]{
        cpe1, cpe2, cpe2, cpe1, cpe2,}, null);
    ResourceOracleImpl oracle = new ResourceOracleImpl(logger, classLoader);
    List<ClassPathEntry> classPath = oracle.getClassPath();
    assertEquals(2, classPath.size());
    assertJarEntry(classPath.get(0), "cpe1.jar");
    assertJarEntry(classPath.get(1), "cpe2.zip");
    oracle = new ResourceOracleImpl(logger, classLoader);
    List<ClassPathEntry> classPath2 = oracle.getClassPath();
    assertEquals(2, classPath2.size());
    for (int i = 0; i < 2; ++i) {
      assertSame(classPath.get(i), classPath2.get(i));
    }
  }

  public void testResourceAddition() throws IOException, URISyntaxException {
    ClassPathEntry cpe1mock = getClassPathEntry1AsMock();
    ClassPathEntry cpe1jar = getClassPathEntry1AsJar();
    ClassPathEntry cpe1dir = getClassPathEntry1AsDirectory();
    ClassPathEntry cpe1zip = getClassPathEntry1AsZip();

    ClassPathEntry cpe2mock = getClassPathEntry2AsMock();
    ClassPathEntry cpe2jar = getClassPathEntry2AsJar();
    ClassPathEntry cpe2dir = getClassPathEntry2AsDirectory();
    ClassPathEntry cpe2zip = getClassPathEntry2AsZip();

    testResourceAddition(cpe1jar, cpe2jar);
    testResourceAddition(cpe1dir, cpe2jar);
    testResourceAddition(cpe1mock, cpe2jar);
    testResourceAddition(cpe1zip, cpe2jar);

    testResourceAddition(cpe1jar, cpe2dir);
    testResourceAddition(cpe1dir, cpe2dir);
    testResourceAddition(cpe1mock, cpe2dir);
    testResourceAddition(cpe1zip, cpe2dir);

    testResourceAddition(cpe1jar, cpe2mock);
    testResourceAddition(cpe1dir, cpe2mock);
    testResourceAddition(cpe1mock, cpe2mock);
    testResourceAddition(cpe1zip, cpe2mock);

    testResourceAddition(cpe1jar, cpe2zip);
    testResourceAddition(cpe1dir, cpe2zip);
    testResourceAddition(cpe1mock, cpe2zip);
    testResourceAddition(cpe1zip, cpe2zip);
  }

  public void testResourceDeletion() throws IOException, URISyntaxException {
    ClassPathEntry cpe1mock = getClassPathEntry1AsMock();
    ClassPathEntry cpe1jar = getClassPathEntry1AsJar();
    ClassPathEntry cpe1dir = getClassPathEntry1AsDirectory();
    ClassPathEntry cpe1zip = getClassPathEntry1AsZip();

    ClassPathEntry cpe2mock = getClassPathEntry2AsMock();
    ClassPathEntry cpe2jar = getClassPathEntry2AsJar();
    ClassPathEntry cpe2dir = getClassPathEntry2AsDirectory();
    ClassPathEntry cpe2zip = getClassPathEntry2AsZip();

    testResourceDeletion(cpe1jar, cpe2jar);
    testResourceDeletion(cpe1dir, cpe2jar);
    testResourceDeletion(cpe1mock, cpe2jar);
    testResourceDeletion(cpe1zip, cpe2jar);

    testResourceDeletion(cpe1jar, cpe2dir);
    testResourceDeletion(cpe1dir, cpe2dir);
    testResourceDeletion(cpe1mock, cpe2dir);
    testResourceDeletion(cpe1zip, cpe2dir);

    testResourceDeletion(cpe1jar, cpe2mock);
    testResourceDeletion(cpe1dir, cpe2mock);
    testResourceDeletion(cpe1mock, cpe2mock);
    testResourceDeletion(cpe1zip, cpe2mock);

    testResourceDeletion(cpe1jar, cpe2zip);
    testResourceDeletion(cpe1dir, cpe2zip);
    testResourceDeletion(cpe1mock, cpe2zip);
    testResourceDeletion(cpe1zip, cpe2zip);
  }

  public void testResourceModification() throws IOException, URISyntaxException {
    ClassPathEntry cpe1mock = getClassPathEntry1AsMock();
    ClassPathEntry cpe1jar = getClassPathEntry1AsJar();
    ClassPathEntry cpe1dir = getClassPathEntry1AsDirectory();
    ClassPathEntry cpe1zip = getClassPathEntry1AsZip();

    ClassPathEntry cpe2mock = getClassPathEntry2AsMock();
    ClassPathEntry cpe2jar = getClassPathEntry2AsJar();
    ClassPathEntry cpe2dir = getClassPathEntry2AsDirectory();
    ClassPathEntry cpe2zip = getClassPathEntry2AsZip();

    testResourceModification(cpe1jar, cpe2jar);
    testResourceModification(cpe1dir, cpe2jar);
    testResourceModification(cpe1mock, cpe2jar);
    testResourceModification(cpe1zip, cpe2jar);

    testResourceModification(cpe1jar, cpe2dir);
    testResourceModification(cpe1dir, cpe2dir);
    testResourceModification(cpe1mock, cpe2dir);
    testResourceModification(cpe1zip, cpe2dir);

    testResourceModification(cpe1jar, cpe2mock);
    testResourceModification(cpe1dir, cpe2mock);
    testResourceModification(cpe1mock, cpe2mock);
    testResourceModification(cpe1zip, cpe2mock);

    testResourceModification(cpe1jar, cpe2zip);
    testResourceModification(cpe1dir, cpe2zip);
    testResourceModification(cpe1mock, cpe2zip);
    testResourceModification(cpe1zip, cpe2zip);

    /*
     * TODO(bruce): figure out a good way to test real resource modifications of
     * jar files and directories
     */
  }

  /**
   * Ensure refresh is stable when multiple classpaths + multiple path prefixes
   * all include the same resource.
   */
  public void testStableRefreshOnBlot() {
    TreeLogger logger = createTestTreeLogger();
    ClassPathEntry cpe1 = getClassPathEntry1AsMock();
    ClassPathEntry cpe2 = getClassPathEntry2AsMock();
    testResourceInCPE(logger, "org/example/bar/client/BarClient2.txt", cpe1,
        new ClassPathEntry[]{cpe1, cpe2}, makeBarPrefix(), new PathPrefix(
            "org/example/bar/", null, false));
  }

  /**
   * Ensure refresh is stable when multiple classpaths + multiple path prefixes
   * all include the same resource.
   */
  public void testSuperSourceSupercedesSource() {
    TreeLogger logger = createTestTreeLogger();

    MockClassPathEntry cpe1 = new MockClassPathEntry("/cpe1/");
    cpe1.addResource("java/lang/Object.java");

    MockClassPathEntry cpe2 = new MockClassPathEntry("/cpe2/");
    cpe2.addResource("translatable/java/lang/Object.java");

    // Ensure the translatable overrides the basic despite swapping CPE order.
    testResourceInCPE(logger, "java/lang/Object.java", cpe2,
        new ClassPathEntry[]{cpe1, cpe2}, makeJavaLangPrefix(),
        makeTranslatablePrefix());
    testResourceInCPE(logger, "java/lang/Object.java", cpe2,
        new ClassPathEntry[]{cpe2, cpe1}, makeJavaLangPrefix(),
        makeTranslatablePrefix());

    // Ensure the translatable overrides the basic despite swapping PPS order.
    testResourceInCPE(logger, "java/lang/Object.java", cpe2,
        new ClassPathEntry[]{cpe1, cpe2}, makeTranslatablePrefix(),
        makeJavaLangPrefix());
    testResourceInCPE(logger, "java/lang/Object.java", cpe2,
        new ClassPathEntry[]{cpe2, cpe1}, makeTranslatablePrefix(),
        makeJavaLangPrefix());
  }

  private void assertJarEntry(ClassPathEntry classPathEntry, String expected) {
    assertTrue("Should be instance of ZipFileClassPathEntry",
        classPathEntry instanceof ZipFileClassPathEntry);
    ZipFileClassPathEntry zipCPE = (ZipFileClassPathEntry) classPathEntry;
    String jar = zipCPE.getLocation();
    assertTrue("URL should contain " + expected, jar.contains(expected));
  }

  /**
   * Creates an array of class path entries, setting up each one with a
   * well-known set of client prefixes.
   */
  private ResourceOracleImpl createResourceOracle(ClassPathEntry... entries) {
    PathPrefixSet pps = new PathPrefixSet();
    pps.add(new PathPrefix("com/google/gwt/user/client/", null));
    pps.add(new PathPrefix("org/example/bar/client/", null));
    pps.add(new PathPrefix("org/example/foo/client/", null));
    pps.add(new PathPrefix("com/google/gwt/i18n/client/", null));

    List<ClassPathEntry> classPath = new ArrayList<ClassPathEntry>();
    for (ClassPathEntry entry : entries) {
      classPath.add(entry);
    }
    ResourceOracleImpl oracle = new ResourceOracleImpl(classPath);
    oracle.setPathPrefixes(pps);
    return oracle;
  }

  private ResourceOracleSnapshot refreshAndSnapshot(TreeLogger logger,
      ResourceOracleImpl oracle) {
    ResourceOracleImpl.refresh(logger, oracle);
    ResourceOracleSnapshot snapshot1 = new ResourceOracleSnapshot(oracle);
    ResourceOracleImpl.refresh(logger, oracle);
    ResourceOracleSnapshot snapshot2 = new ResourceOracleSnapshot(oracle);
    snapshot1.assertSameCollections(snapshot2);
    return snapshot1;
  }

  private void testReadingResource(ClassPathEntry cpe1, ClassPathEntry cpe2)
      throws IOException {
    TreeLogger logger = createTestTreeLogger();

    ResourceOracleImpl oracle = createResourceOracle(cpe1, cpe2);
    ResourceOracleSnapshot s = refreshAndSnapshot(logger, oracle);
    s.assertCollectionsConsistent(10);
    s.assertPathIncluded("com/google/gwt/user/client/Command.java", cpe1);
    s.assertPathIncluded("com/google/gwt/i18n/client/Messages.java", cpe2);

    {
      /*
       * Read a resource in cpe1.
       */
      AbstractResource res = s.findResourceWithPath("com/google/gwt/user/client/Command.java");
      BufferedReader rdr = null;
      try {
        InputStream is = res.openContents();
        assertNotNull(is);
        rdr = new BufferedReader(new InputStreamReader(is));
        assertTrue(rdr.readLine().indexOf(
            "package com.google.gwt.dev.resource.impl.testdata.cpe1.com.google.gwt.user.client;") >= 0);
      } finally {
        Utility.close(rdr);
      }
    }

    {
      /*
       * Read a resource in cpe2.
       */
      AbstractResource res = s.findResourceWithPath("com/google/gwt/i18n/client/Messages.java");
      BufferedReader rdr = null;
      try {
        InputStream is = res.openContents();
        assertNotNull(is);
        rdr = new BufferedReader(new InputStreamReader(is));
        assertTrue(rdr.readLine().indexOf(
            "package com.google.gwt.dev.resource.impl.testdata.cpe2.com.google.gwt.i18n.client;") >= 0);
      } finally {
        Utility.close(rdr);
      }
    }

    {
      /*
       * TODO: Try to read an invalid resource and watch it fail as intended.
       */
    }
  }

  private void testResourceAddition(ClassPathEntry cpe1, ClassPathEntry cpe2) {
    TreeLogger logger = createTestTreeLogger();

    MOCK_CPE0 cpe0 = new MOCK_CPE0();
    MOCK_CPE3 cpe3 = new MOCK_CPE3();
    ResourceOracleImpl oracle = createResourceOracle(cpe0, cpe1, cpe2, cpe3);

    {
      /*
       * Ensure it's correct as a baseline. These tests have hard-coded
       * assumptions about the contents of each classpath entry.
       */
      ResourceOracleSnapshot s = refreshAndSnapshot(logger, oracle);
      s.assertCollectionsConsistent(10);
      s.assertPathIncluded("com/google/gwt/user/client/Command.java");
      s.assertPathIncluded("com/google/gwt/user/client/Timer.java");
      s.assertPathIncluded("com/google/gwt/user/client/ui/Widget.java");
      s.assertPathIncluded("org/example/bar/client/BarClient1.txt");
      s.assertPathIncluded("org/example/bar/client/BarClient2.txt");
      s.assertPathIncluded("org/example/bar/client/BarClient3.txt");
      s.assertPathIncluded("org/example/bar/client/etc/BarEtc.txt");
      s.assertPathIncluded("org/example/foo/client/FooClient.java");
      s.assertPathIncluded("com/google/gwt/i18n/client/Messages.java");
    }

    {
      /*
       * Add duplicate resources later in the classpath, which won't be found.
       * Consequently, the collections' identities should not change.
       */
      cpe3.addResource("com/google/gwt/user/client/Command.java");
      cpe3.addResource("com/google/gwt/user/client/Timer.java");
      cpe3.addResource("com/google/gwt/bar/client/etc/BarEtc.txt");

      ResourceOracleSnapshot before = new ResourceOracleSnapshot(oracle);
      ResourceOracleSnapshot after = refreshAndSnapshot(logger, oracle);
      after.assertCollectionsConsistent(10);
      after.assertSameCollections(before);
    }

    {
      /*
       * Add a unique resource later in the classpath, which will be found.
       * Consequently, the collections' identities should change.
       */
      cpe3.addResource("com/google/gwt/i18n/client/Constants.java");

      ResourceOracleSnapshot before = new ResourceOracleSnapshot(oracle);
      ResourceOracleSnapshot after = refreshAndSnapshot(logger, oracle);
      after.assertCollectionsConsistent(11);
      after.assertNotSameCollections(before);
      after.assertPathIncluded("com/google/gwt/i18n/client/Constants.java");
    }
  }

  private void testResourceDeletion(ClassPathEntry cpe1, ClassPathEntry cpe2) {
    TreeLogger logger = createTestTreeLogger();

    MOCK_CPE0 cpe0 = new MOCK_CPE0();
    MOCK_CPE3 cpe3 = new MOCK_CPE3();
    ResourceOracleImpl oracle = createResourceOracle(cpe0, cpe1, cpe2, cpe3);

    /*
     * Intentionally add some duplicate resources.
     */
    cpe0.addResource("com/google/gwt/user/client/Command.java");
    cpe0.addResource("com/google/gwt/i18n/client/Constants.java");
    cpe3.addResource("com/google/gwt/user/client/Command.java");
    cpe3.addResource("com/google/gwt/i18n/client/Constants.java");

    {
      /*
       * Ensure it's correct as a baseline. These tests have hard-coded
       * assumptions about the contents of each classpath entry.
       */
      ResourceOracleSnapshot s = refreshAndSnapshot(logger, oracle);
      s.assertCollectionsConsistent(11);
      s.assertPathIncluded("com/google/gwt/user/client/Command.java");
      s.assertPathIncluded("com/google/gwt/user/client/Timer.java");
      s.assertPathIncluded("com/google/gwt/user/client/ui/Widget.java");
      s.assertPathIncluded("org/example/bar/client/BarClient1.txt");
      s.assertPathIncluded("org/example/bar/client/BarClient2.txt");
      s.assertPathIncluded("org/example/bar/client/BarClient3.txt");
      s.assertPathIncluded("org/example/bar/client/etc/BarEtc.txt");
      s.assertPathIncluded("org/example/foo/client/FooClient.java");
      s.assertPathIncluded("com/google/gwt/i18n/client/Messages.java");
      s.assertPathIncluded("com/google/gwt/i18n/client/Constants.java");
    }

    {
      /*
       * Remove a shadowed resource, which shouldn't have been found anyway.
       * Consequently, the collections' identities should not change.
       */
      cpe3.removeResource("com/google/gwt/user/client/Command.java");
      cpe3.removeResource("com/google/gwt/i18n/client/Constants.java");

      ResourceOracleSnapshot before = new ResourceOracleSnapshot(oracle);
      ResourceOracleSnapshot after = refreshAndSnapshot(logger, oracle);
      after.assertCollectionsConsistent(11);
      after.assertSameCollections(before);
    }

    {
      /*
       * Remove a unique resource, which will no longer be found. We also add a
       * new one to ensure that lack of size change doesn't confuse anything.
       * Consequently, the collections' identities should change.
       */
      cpe0.removeResource("com/google/gwt/i18n/client/Constants.java");
      cpe3.addResource("com/google/gwt/user/client/Window.java");

      ResourceOracleSnapshot before = new ResourceOracleSnapshot(oracle);
      ResourceOracleSnapshot after = refreshAndSnapshot(logger, oracle);
      after.assertCollectionsConsistent(11);
      after.assertNotSameCollections(before);
      after.assertPathIncluded("com/google/gwt/user/client/Window.java");
      after.assertPathNotIncluded("com/google/gwt/i18n/client/Constants.java");
    }
  }

  private void testResourceInCPE(TreeLogger logger, String resourceKey,
      ClassPathEntry expectedCPE, ClassPathEntry[] classPath,
      PathPrefix... pathPrefixes) {
    ResourceOracleImpl oracle = new ResourceOracleImpl(Arrays.asList(classPath));
    PathPrefixSet pps = new PathPrefixSet();
    for (PathPrefix pathPrefix : pathPrefixes) {
      pps.add(pathPrefix);
    }
    oracle.setPathPrefixes(pps);
    ResourceOracleSnapshot s = refreshAndSnapshot(logger, oracle);
    s.assertPathIncluded(resourceKey, expectedCPE);
  }

  private void testResourceModification(ClassPathEntry cpe1, ClassPathEntry cpe2) {
    TreeLogger logger = createTestTreeLogger();

    MOCK_CPE0 cpe0 = new MOCK_CPE0();
    MOCK_CPE3 cpe3 = new MOCK_CPE3();
    ResourceOracleImpl oracle = createResourceOracle(cpe0, cpe1, cpe2, cpe3);

    {
      /*
       * Baseline assumptions about the set of resources present by default.
       */
      ResourceOracleSnapshot s = refreshAndSnapshot(logger, oracle);
      s.assertPathIncluded("com/google/gwt/user/client/Command.java", cpe1);
      s.assertPathIncluded("com/google/gwt/user/client/Timer.java", cpe1);
    }

    // Add intentionally duplicate resources.
    cpe0.addResource("com/google/gwt/user/client/Command.java");
    cpe3.addResource("com/google/gwt/user/client/Timer.java");

    {
      /*
       * Ensure that the dups have the effect we expect.
       */
      ResourceOracleSnapshot s = refreshAndSnapshot(logger, oracle);
      s.assertPathIncluded("com/google/gwt/user/client/Command.java", cpe0);
      s.assertPathIncluded("com/google/gwt/user/client/Timer.java", cpe1);
    }

    {
      /*
       * Change a mock resource that was shadowed to ensure that the change
       * isn't observed.
       */
      ResourceOracleSnapshot before = new ResourceOracleSnapshot(oracle);
      before.assertCollectionsConsistent(10);

      cpe3.updateResource("com/google/gwt/user/client/Timer.java");

      ResourceOracleSnapshot after = refreshAndSnapshot(logger, oracle);
      after.assertSameCollections(before);
    }

    {
      /*
       * Change a mock resource that was not shadowed to ensure that the change
       * is observed.
       */
      ResourceOracleSnapshot before = new ResourceOracleSnapshot(oracle);
      before.assertCollectionsConsistent(10);

      cpe0.updateResource("com/google/gwt/user/client/Command.java");

      ResourceOracleSnapshot after = refreshAndSnapshot(logger, oracle);
      after.assertNotSameCollections(before);
    }
  }
}
