/*
 * 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.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 Set<Resource> resources;

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

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

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

    public void assertNotSameCollections(ResourceOracleSnapshot other) {
      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 resource = findResourceWithPath(expectedPath);
      assertNotNull(resource);
      String cpeLocation = expectedCpe.getLocation();
      if (cpeLocation.endsWith(".jar") || cpeLocation.endsWith(".zip")) {
        assertTrue(resource.getLocation().startsWith("jar:" + cpeLocation));
      } else {
        assertTrue(resource.getLocation().startsWith(cpeLocation));
      }
    }

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

    public void assertSameCollections(ResourceOracleSnapshot other) {
      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() throws IOException {
      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, ResourceResolution> 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, ResourceResolution> resourceMap2 =
        cpe1jar.findApplicableResources(logger, pps1);
    assertNotSame(resourceMap1, resourceMap2);

    PathPrefixSet pps2 = new PathPrefixSet();
    pps2.add(new PathPrefix("org/example/bar/", null, false));
    Map<AbstractResource, ResourceResolution> 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) throws IOException {
    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 ResourceOracleImpls created from the same state return the same list of
   * ClassPathEntries.
   */
  public void testSameClassPathEntries() {
    TreeLogger logger = createTestTreeLogger();
    ResourceOracleImpl oracle = new ResourceOracleImpl(logger);
    List<ClassPathEntry> classPathEntries = oracle.getClassPathEntries();

    oracle = new ResourceOracleImpl(logger);
    List<ClassPathEntry> classPathEntries2 = oracle.getClassPathEntries();
    assertEquals(classPathEntries.size(), classPathEntries2.size());
    for (int i = 0; i < classPathEntries2.size(); ++i) {
      assertSame(classPathEntries.get(i), classPathEntries2.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) {
    oracle.scanResources(logger);
    ResourceOracleSnapshot snapshot1 = new ResourceOracleSnapshot(oracle);
    oracle.scanResources(logger);
    ResourceOracleSnapshot snapshot2 = new ResourceOracleSnapshot(oracle);
    snapshot1.assertSameCollections(snapshot2);
    return snapshot1;
  }

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

    String commandPath = "com/google/gwt/user/client/Command.java";
    String messagesPath = "com/google/gwt/i18n/client/Messages.java";

    String userPackage = "cpe1.com.google.gwt.user.client";
    String i18nPackage = "cpe2.com.google.gwt.i18n.client";

    ResourceOracleImpl oracle = createResourceOracle(cpe1, cpe2);
    ResourceOracleSnapshot s = refreshAndSnapshot(logger, oracle);
    s.assertCollectionsConsistent(10);

    // Read a resource in cpe1.
    readAndAssertResource(oracle, commandPath, userPackage);

    // Read a resource in cpe2.
    readAndAssertResource(oracle, messagesPath, i18nPackage);

    // Read relative path.
    readAndAssertResource(oracle, "com/google/gwt/i18n/../i18n/client/Messages.java", i18nPackage);

    // Read path that doesn't exist.
    assertNull(oracle.getResource("com/google/gwt/i18n/client/DoesntExist.java"));
  }

  private void readAndAssertResource(ResourceOracleImpl oracle, String path, String expectedPackage)
      throws IOException {
    Resource res = oracle.getResource(path);
    assertNotNull(res);
    BufferedReader rdr = null;
    try {
      InputStream is = res.openContents();
      assertNotNull(is);
      rdr = new BufferedReader(new InputStreamReader(is));
      // Skip lines until package line is found.
      String line = rdr.readLine();
      while (line != null && !line.startsWith("package")) {
        line = rdr.readLine();
      }
      assertTrue(line != null
          && line.indexOf("package com.google.gwt.dev.resource.impl.testdata." + expectedPackage
              + ";") >= 0);
    } finally {
      Utility.close(rdr);
    }
  }

  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);
    }
  }
}
