/*
 * 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.thirdparty.guava.common.collect.Lists;
import com.google.gwt.thirdparty.guava.common.io.Files;

import java.io.File;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.net.URISyntaxException;
import java.util.Collection;
import java.util.Map;
import java.util.Set;

/**
 * Resource related tests.
 */
public class ClassPathEntryTest extends AbstractResourceOrientedTestBase {

  /**
   * This test will likely not work on Windows since directories that start with . are not
   * implicitly hidden there. But since Java 6 does not have a File.setHidden() function, fixing
   * this test for Windows is deferred till GWT officially depends on Java 7.
   */
  public void testIgnoresHiddenDirectories() throws IOException {
    // Setup a /tmp/.svn/ShouldNotBeFound.java folder structure.
    File tempDir = Files.createTempDir();
    File nestedHiddenDir = new File(tempDir, ".svn");
    nestedHiddenDir.mkdir();
    File javaFile = new File(nestedHiddenDir, "ShouldNotBeFound.java");
    javaFile.createNewFile();

    // Perform a class path directory inspection.
    DirectoryClassPathEntry cpe = new DirectoryClassPathEntry(tempDir);
    Map<AbstractResource, ResourceResolution> resources =
        cpe.findApplicableResources(TreeLogger.NULL, createInclusivePathPrefixSet());

    // Verify that even though we're using an ALL filter, we still didn't find any files inside the
    // .svn dir, because we never even enumerate its contents.
    assertTrue(resources.isEmpty());
  }

  public void testResourceCreated() throws IOException, InterruptedException {
    // With just 1 filter definition.
    testResourceCreated(Lists.newArrayList(createInclusivePathPrefixSet()));
    // With multiple filter definitions.
    testResourceCreated(Lists.newArrayList(createInclusivePathPrefixSet(),
        createInclusivePathPrefixSet(), createInclusivePathPrefixSet()));
  }

  public void testForResourceListenerLeaks_pathPrefixSetIsCollected() throws Exception {
    // Create a folder an initially empty folder.
    PathPrefixSet pathPrefixSet = createInclusivePathPrefixSet();
    DirectoryClassPathEntry classPathEntry = new DirectoryClassPathEntry(Files.createTempDir());

    // Show that we are not listening.
    awaitFullGc();
    assertEquals(0, ResourceAccumulatorManager.getActiveListenerCount());

    // Start listening for updates.
    ResourceAccumulatorManager.getResources(classPathEntry, pathPrefixSet);

    // Show that we are now listening for updates.
    awaitFullGc();
    assertEquals(1, ResourceAccumulatorManager.getActiveListenerCount());

    // Dereference the pathPrefixSet to give garbage collector an opportunity to clear any weak
    // references.
    pathPrefixSet = null;

    // Show that we are no longer listening for updates.
    awaitFullGc();
    assertEquals(0, ResourceAccumulatorManager.getActiveListenerCount());

    // Make sure classPathEntry is not GC'd until this point.
    assertNotNull(classPathEntry);
  }

  public void testForResourceListenerLeaks_classPathEntryIsCollected() throws Exception {
    // Create a folder an initially empty folder.
    PathPrefixSet pathPrefixSet = createInclusivePathPrefixSet();
    DirectoryClassPathEntry classPathEntry = new DirectoryClassPathEntry(Files.createTempDir());

    // Show that we are not listening.
    awaitFullGc();
    assertEquals(0, ResourceAccumulatorManager.getActiveListenerCount());

    // Start listening for updates.
    ResourceAccumulatorManager.getResources(classPathEntry, pathPrefixSet);

    // Show that we are now listening for updates.
    awaitFullGc();
    assertEquals(1, ResourceAccumulatorManager.getActiveListenerCount());

    // Dereference the classPathEntry to give the garbage collector an opportunity to clear any weak
    // references.
    classPathEntry = null;

    // Show that we are no longer listening for updates.
    awaitFullGc();
    assertEquals(0, ResourceAccumulatorManager.getActiveListenerCount());

    // Make sure pathPrefixSet is not GC'd until this point.
    assertNotNull(pathPrefixSet);
  }

  public void testResourceCreated(Collection<PathPrefixSet> pathPrefixSets) throws IOException,
      InterruptedException {
    // Create a folder an initially empty folder.
    File tempDir = Files.createTempDir();
    DirectoryClassPathEntry cpe = new DirectoryClassPathEntry(tempDir);

    // Perform a class path directory inspection.
    for (PathPrefixSet pathPrefixSet : pathPrefixSets) {
      Map<AbstractResource, ResourceResolution> foundResources =
          cpe.findApplicableResources(TreeLogger.NULL, pathPrefixSet);

      // Verify the directory is initially empty.
      assertTrue(foundResources.isEmpty());
    }

    // Create a file and give file events time to fire.
    File createdFile = new File(tempDir, "Created.java");
    createdFile.createNewFile();
    Thread.sleep(10);

    // Perform a class path directory inspection.
    for (PathPrefixSet pathPrefixSet : pathPrefixSets) {
      Map<AbstractResource, ResourceResolution> foundResources =
          cpe.findApplicableResources(TreeLogger.NULL, pathPrefixSet);

      // Verify the directory is no longer empty.
      assertEquals(1, foundResources.size());
      assertEquals("Created.java", foundResources.keySet().iterator().next().getPath());
    }
  }

  public void testResourceDeleted() throws IOException, InterruptedException {
    // With just 1 filter definition.
    testResourceDeleted(Lists.newArrayList(createInclusivePathPrefixSet()));
    // With multiple filter definitions.
    testResourceDeleted(Lists.newArrayList(createInclusivePathPrefixSet(),
        createInclusivePathPrefixSet(), createInclusivePathPrefixSet()));
  }

  private void testResourceDeleted(Collection<PathPrefixSet> pathPrefixSets) throws IOException,
      InterruptedException {
    // Create a folder with one initial file, that can be deleted.
    File tempDir = Files.createTempDir();
    File fileToDelete = new File(tempDir, "ToDelete.java");
    fileToDelete.createNewFile();
    DirectoryClassPathEntry cpe = new DirectoryClassPathEntry(tempDir);

    // Perform a class path directory inspection.
    for (PathPrefixSet pathPrefixSet : pathPrefixSets) {
      Map<AbstractResource, ResourceResolution> foundResources =
          cpe.findApplicableResources(TreeLogger.NULL, pathPrefixSet);

      // Verify the directory is not initially empty.
      assertEquals(1, foundResources.size());
      assertEquals("ToDelete.java", foundResources.keySet().iterator().next().getPath());
    }

    // Delete the file and give file events time to fire.
    fileToDelete.delete();
    Thread.sleep(10);

    // Perform a class path directory inspection.
    for (PathPrefixSet pathPrefixSet : pathPrefixSets) {
      Map<AbstractResource, ResourceResolution> foundResources =
          cpe.findApplicableResources(TreeLogger.NULL, pathPrefixSet);

      // Verify the directory is now empty.
      assertTrue(foundResources.isEmpty());
    }
  }

  public void testResourceRenamed() throws IOException, InterruptedException {
    // With just 1 filter definition.
    testResourceRenamed(Lists.newArrayList(createInclusivePathPrefixSet()));
    // With multiple filter definitions.
    testResourceRenamed(Lists.newArrayList(createInclusivePathPrefixSet(),
        createInclusivePathPrefixSet(), createInclusivePathPrefixSet()));
  }

  private void testResourceRenamed(Collection<PathPrefixSet> pathPrefixSets) throws IOException,
      InterruptedException {
    // Create a folder with one initial file, that can be renamed.
    File tempDir = Files.createTempDir();
    File fileToRename = new File(tempDir, "ToRename.java");
    fileToRename.createNewFile();
    DirectoryClassPathEntry cpe = new DirectoryClassPathEntry(tempDir);

    // Perform class path directory inspections.
    for (PathPrefixSet pathPrefixSet : pathPrefixSets) {
      Map<AbstractResource, ResourceResolution> foundResources =
          cpe.findApplicableResources(TreeLogger.NULL, pathPrefixSet);

      // Verify the directory is not initially empty.
      assertEquals(1, foundResources.size());
      assertEquals("ToRename.java", foundResources.keySet().iterator().next().getPath());
    }

    // Rename the file and give file events time to fire.
    fileToRename.renameTo(new File(tempDir, "Renamed.java"));
    Thread.sleep(10);

    for (PathPrefixSet pathPrefixSet : pathPrefixSets) {
      // Perform a class path directory inspection.
      Map<AbstractResource, ResourceResolution> foundResources =
          cpe.findApplicableResources(TreeLogger.NULL, pathPrefixSet);

      // Verify the file is seen as renamed.
      assertEquals(1, foundResources.size());
      assertEquals("Renamed.java", foundResources.keySet().iterator().next().getPath());
    }
  }

  public void testAllCpe1FilesFound() throws URISyntaxException, IOException {
    testAllCpe1FilesFound(getClassPathEntry1AsJar());
    testAllCpe1FilesFound(getClassPathEntry1AsDirectory());
    testAllCpe1FilesFound(getClassPathEntry1AsZip());
  }

  public void testAllCpe2FilesFound() throws URISyntaxException, IOException {
    testAllCpe2FilesFound(getClassPathEntry2AsJar());
    testAllCpe2FilesFound(getClassPathEntry2AsDirectory());
    testAllCpe2FilesFound(getClassPathEntry2AsZip());
  }

  public void testPathPrefixSetChanges() throws IOException, URISyntaxException {
    ClassPathEntry cpe1jar = getClassPathEntry1AsJar();
    ClassPathEntry cpe1dir = getClassPathEntry1AsDirectory();
    ClassPathEntry cpe1zip = getClassPathEntry1AsZip();
    ClassPathEntry cpe2jar = getClassPathEntry2AsJar();
    ClassPathEntry cpe2dir = getClassPathEntry2AsDirectory();
    ClassPathEntry cpe2zip = getClassPathEntry2AsZip();

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

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

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

  public void testUseOfPrefixesWithFiltering() throws IOException,
      URISyntaxException {
    ClassPathEntry cpe1jar = getClassPathEntry1AsJar();
    ClassPathEntry cpe1dir = getClassPathEntry1AsDirectory();
    ClassPathEntry cpe1zip = getClassPathEntry1AsZip();
    ClassPathEntry cpe2jar = getClassPathEntry2AsJar();
    ClassPathEntry cpe2dir = getClassPathEntry2AsDirectory();
    ClassPathEntry cpe2zip = getClassPathEntry2AsZip();

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

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

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

  public void testUseOfPrefixesWithoutFiltering() throws URISyntaxException,
      IOException {
    ClassPathEntry cpe1jar = getClassPathEntry1AsJar();
    ClassPathEntry cpe1dir = getClassPathEntry1AsDirectory();
    ClassPathEntry cpe1zip = getClassPathEntry1AsZip();
    ClassPathEntry cpe2jar = getClassPathEntry2AsJar();
    ClassPathEntry cpe2dir = getClassPathEntry2AsDirectory();
    ClassPathEntry cpe2zip = getClassPathEntry2AsZip();

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

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

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

  public void testUseOfPrefixesWithoutFiltering(ClassPathEntry cpe1,
      ClassPathEntry cpe2) {
    TreeLogger logger = createTestTreeLogger();

    PathPrefixSet pps = new PathPrefixSet();
    pps.add(new PathPrefix("com/google/gwt/user/client/", null));
    pps.add(new PathPrefix("com/google/gwt/i18n/client/", null));

    {
      // Examine cpe1.
      Set<AbstractResource> r = cpe1.findApplicableResources(logger, pps).keySet();

      assertEquals(3, r.size());
      assertPathIncluded(r, "com/google/gwt/user/client/Command.java");
      assertPathIncluded(r, "com/google/gwt/user/client/Timer.java");
      assertPathIncluded(r, "com/google/gwt/user/client/ui/Widget.java");
    }

    {
      // Examine cpe2.
      Set<AbstractResource> r = cpe2.findApplicableResources(logger, pps).keySet();

      assertEquals(1, r.size());
      assertPathIncluded(r, "com/google/gwt/i18n/client/Messages.java");
    }
  }

  private static void awaitFullGc() throws InterruptedException {
    Object object = new Object();
    WeakReference<Object> objectReference = new WeakReference<Object>(object);
    object = null;
    System.gc();

    while (objectReference.get() != null) {
      Thread.sleep(10);
      System.gc();
    }
  }

  // NOTE: if this test fails, ensure that the source root containing this very
  // source file is *FIRST* on the classpath
  private void testAllCpe1FilesFound(ClassPathEntry cpe1) {
    TreeLogger logger = createTestTreeLogger();

    PathPrefixSet pps = new PathPrefixSet();
    pps.add(new PathPrefix("", null));

    Set<AbstractResource> r = cpe1.findApplicableResources(logger, pps).keySet();

    assertEquals(9, r.size());
    assertPathIncluded(r, "com/google/gwt/user/User.gwt.xml");
    assertPathIncluded(r, "com/google/gwt/user/client/Command.java");
    assertPathIncluded(r, "com/google/gwt/user/client/Timer.java");
    assertPathIncluded(r, "com/google/gwt/user/client/ui/Widget.java");
    assertPathIncluded(r, "org/example/bar/client/BarClient1.txt");
    assertPathIncluded(r, "org/example/bar/client/BarClient2.txt");
    assertPathIncluded(r, "org/example/bar/client/etc/BarEtc.txt");
    assertPathIncluded(r, "org/example/foo/client/FooClient.java");
    assertPathIncluded(r, "org/example/foo/server/FooServer.java");
  }

  // NOTE: if this test fails, ensure that the source root containing this very
  // source file is on the classpath
  private void testAllCpe2FilesFound(ClassPathEntry cpe2) {
    TreeLogger logger = createTestTreeLogger();

    PathPrefixSet pps = createInclusivePathPrefixSet();
    Set<AbstractResource> r = cpe2.findApplicableResources(logger, pps).keySet();

    assertEquals(6, r.size());
    assertPathIncluded(r, "com/google/gwt/i18n/I18N.gwt.xml");
    assertPathIncluded(r, "com/google/gwt/i18n/client/Messages.java");
    assertPathIncluded(r,
        "com/google/gwt/i18n/rebind/LocalizableGenerator.java");
    assertPathIncluded(r, "org/example/bar/client/BarClient2.txt");
    assertPathIncluded(r, "org/example/bar/client/BarClient3.txt");
    assertPathIncluded(r, "org/example/foo/client/BarClient1.txt");
  }

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

    {
      // Filter is not set yet.
      PathPrefixSet pps = new PathPrefixSet();
      pps.add(new PathPrefix("com/google/gwt/user/", null));
      pps.add(new PathPrefix("com/google/gwt/i18n/", null));

      // Examine cpe1 in the absence of the filter.
      Set<AbstractResource> r1 = cpe1.findApplicableResources(logger, pps).keySet();

      assertEquals(4, r1.size());
      assertPathIncluded(r1, "com/google/gwt/user/User.gwt.xml");
      assertPathIncluded(r1, "com/google/gwt/user/client/Command.java");
      assertPathIncluded(r1, "com/google/gwt/user/client/Timer.java");
      assertPathIncluded(r1, "com/google/gwt/user/client/ui/Widget.java");

      // Examine cpe2 in the absence of the filter.
      Set<AbstractResource> r2 = cpe2.findApplicableResources(logger, pps).keySet();

      assertEquals(3, r2.size());
      assertPathIncluded(r2, "com/google/gwt/i18n/I18N.gwt.xml");
      assertPathIncluded(r2, "com/google/gwt/i18n/client/Messages.java");
      assertPathIncluded(r2,
          "com/google/gwt/i18n/rebind/LocalizableGenerator.java");
    }

    {
      // Create a pps with a filter.
      ResourceFilter excludeXmlFiles = new ResourceFilter() {
        @Override
        public boolean allows(String path) {
          return !path.endsWith(".xml");
        }
      };

      PathPrefixSet pps = new PathPrefixSet();
      pps.add(new PathPrefix("com/google/gwt/user/", excludeXmlFiles));
      pps.add(new PathPrefix("com/google/gwt/i18n/", excludeXmlFiles));

      // Examine cpe1 in the presence of the filter.
      Set<AbstractResource> r1 = cpe1.findApplicableResources(logger, pps).keySet();

      assertEquals(3, r1.size());
      assertPathNotIncluded(r1, "com/google/gwt/user/User.gwt.xml");
      assertPathIncluded(r1, "com/google/gwt/user/client/Command.java");
      assertPathIncluded(r1, "com/google/gwt/user/client/Timer.java");
      assertPathIncluded(r1, "com/google/gwt/user/client/ui/Widget.java");

      // Examine cpe2 in the presence of the filter.
      Set<AbstractResource> r2 = cpe2.findApplicableResources(logger, pps).keySet();

      assertEquals(2, r2.size());
      assertPathNotIncluded(r1, "com/google/gwt/user/User.gwt.xml");
      assertPathIncluded(r2, "com/google/gwt/i18n/client/Messages.java");
      assertPathIncluded(r2,
          "com/google/gwt/i18n/rebind/LocalizableGenerator.java");
    }

    {
      /*
       * Change the prefix path set to the zero-lenth prefix (which allows
       * everything), but specify a filter that disallows everything.
       */
      PathPrefixSet pps = new PathPrefixSet();
      pps.add(new PathPrefix("", new ResourceFilter() {
        @Override
        public boolean allows(String path) {
          // Exclude everything.
          return false;
        }
      }));

      // Examine cpe1 in the presence of the filter.
      Set<AbstractResource> r1 = cpe1.findApplicableResources(logger, pps).keySet();

      assertEquals(0, r1.size());

      // Examine cpe2 in the presence of the filter.
      Set<AbstractResource> r2 = cpe2.findApplicableResources(logger, pps).keySet();

      assertEquals(0, r2.size());
    }
  }

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

    PathPrefixSet pps = new PathPrefixSet();
    ResourceFilter excludeXmlFiles = new ResourceFilter() {
      @Override
      public boolean allows(String path) {
        return !path.endsWith(".xml");
      }
    };
    // The prefix is intentionally starting at the module-level, not 'client'.
    pps.add(new PathPrefix("com/google/gwt/user/", excludeXmlFiles));
    pps.add(new PathPrefix("com/google/gwt/i18n/", excludeXmlFiles));

    {
      // Examine cpe1.
      Set<AbstractResource> r = cpe1.findApplicableResources(logger, pps).keySet();

      assertEquals(3, r.size());
      // User.gwt.xml would be included but for the filter.
      assertPathIncluded(r, "com/google/gwt/user/client/Command.java");
      assertPathIncluded(r, "com/google/gwt/user/client/Timer.java");
      assertPathIncluded(r, "com/google/gwt/user/client/ui/Widget.java");
    }

    {
      // Examine cpe2.
      Set<AbstractResource> r = cpe2.findApplicableResources(logger, pps).keySet();

      assertEquals(2, r.size());
      // I18N.gwt.xml would be included but for the filter.
      assertPathIncluded(r, "com/google/gwt/i18n/client/Messages.java");
      assertPathIncluded(r,
          "com/google/gwt/i18n/rebind/LocalizableGenerator.java");
    }
  }

  private static PathPrefixSet createInclusivePathPrefixSet() {
    PathPrefixSet pathPrefixes = new PathPrefixSet();
    pathPrefixes.add(new PathPrefix("", null));
    return pathPrefixes;
  }
}
