blob: ca5e3a9cd57e8f65d1194931b798ccd4fa3b85ea [file] [log] [blame]
/*
* Copyright 2014 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.thirdparty.guava.common.collect.Lists;
import com.google.gwt.thirdparty.guava.common.collect.Sets;
import com.google.gwt.thirdparty.guava.common.io.Files;
import junit.framework.TestCase;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystemException;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
/**
* Tests for ResourceAccumulator.
*/
public class ResourceAccumulatorTest extends TestCase {
public void testAddFile() throws Exception {
File rootDirectory = Files.createTempDir();
File subDirectory = createDirectoryIn("subdir", rootDirectory);
ResourceAccumulator resourceAccumulator =
new ResourceAccumulator(rootDirectory.toPath(), createInclusivePathPrefixSet());
assertTrue(getResources(resourceAccumulator).isEmpty());
createFileIn("New.java", subDirectory);
waitForFileEvents();
List<AbstractResource> resources = getResources(resourceAccumulator);
assertEquals(1, resources.size());
assertTrue(resources.get(0).getPath().endsWith("New.java"));
resourceAccumulator.shutdown();
}
public void testDeleteFile() throws Exception {
File rootDirectory = Files.createTempDir();
File subDirectory = createDirectoryIn("subdir", rootDirectory);
File originalFile = createFileIn("SomeFile.java", subDirectory);
ResourceAccumulator resourceAccumulator =
new ResourceAccumulator(rootDirectory.toPath(), createInclusivePathPrefixSet());
List<AbstractResource> resources = getResources(resourceAccumulator);
assertEquals(1, resources.size());
assertTrue(resources.get(0).getPath().endsWith("SomeFile.java"));
originalFile.delete();
waitForFileEvents();
assertTrue(getResources(resourceAccumulator).isEmpty());
resourceAccumulator.shutdown();
}
public void testListensInNewDirectories() throws Exception {
File rootDirectory = Files.createTempDir();
ResourceAccumulator resourceAccumulator =
new ResourceAccumulator(rootDirectory.toPath(), createInclusivePathPrefixSet());
assertTrue(getResources(resourceAccumulator).isEmpty());
// Create a new directory and contained file AFTER the root directory has started being listened
// to.
File subDirectory = createDirectoryIn("subdir", rootDirectory);
createFileIn("New.java", subDirectory);
waitForFileEvents();
List<AbstractResource> resources = getResources(resourceAccumulator);
assertEquals(1, resources.size());
assertTrue(resources.get(0).getPath().endsWith("New.java"));
resourceAccumulator.shutdown();
}
public void testMultipleListeners() throws Exception {
File rootDirectory = Files.createTempDir();
File subDirectory = createDirectoryIn("subdir", rootDirectory);
ResourceAccumulator resourceAccumulator1 =
new ResourceAccumulator(rootDirectory.toPath(), createInclusivePathPrefixSet());
ResourceAccumulator resourceAccumulator2 =
new ResourceAccumulator(rootDirectory.toPath(), createInclusivePathPrefixSet());
assertTrue(getResources(resourceAccumulator1).isEmpty());
assertTrue(getResources(resourceAccumulator2).isEmpty());
createFileIn("New.java", subDirectory);
waitForFileEvents();
List<AbstractResource> resources1 = getResources(resourceAccumulator1);
assertEquals(1, resources1.size());
assertTrue(resources1.get(0).getPath().endsWith("New.java"));
List<AbstractResource> resources2 = getResources(resourceAccumulator2);
assertEquals(1, resources2.size());
assertTrue(resources2.get(0).getPath().endsWith("New.java"));
resourceAccumulator1.shutdown();
resourceAccumulator2.shutdown();
}
public void testRenameFile() throws Exception {
File rootDirectory = Files.createTempDir();
File subDirectory = createDirectoryIn("subdir", rootDirectory);
File originalFile = createFileIn("OriginalName.java", subDirectory);
File renamedFile = new File(subDirectory, "Renamed.java");
ResourceAccumulator resourceAccumulator =
new ResourceAccumulator(rootDirectory.toPath(), createInclusivePathPrefixSet());
List<AbstractResource> resources = getResources(resourceAccumulator);
assertEquals(1, resources.size());
assertTrue(resources.get(0).getPath().endsWith("OriginalName.java"));
originalFile.renameTo(renamedFile);
waitForFileEvents();
resources = getResources(resourceAccumulator);
assertEquals(1, resources.size());
assertTrue(resources.get(0).getPath().endsWith("Renamed.java"));
resourceAccumulator.shutdown();
}
public void testRenameDirectory() throws Exception {
File rootDirectory = Files.createTempDir();
File subDirectory = createDirectoryIn("original_dir", rootDirectory);
createFileIn("Name1.java", subDirectory);
createFileIn("Name2.java", subDirectory);
File renamedSubDirectory = new File(rootDirectory, "new_dir");
ResourceAccumulator resourceAccumulator =
new ResourceAccumulator(rootDirectory.toPath(), createInclusivePathPrefixSet());
List<AbstractResource> resources = getResources(resourceAccumulator);
assertEquals(2, resources.size());
assertTrue(resources.get(0).getPath().endsWith("original_dir/Name1.java"));
assertTrue(resources.get(1).getPath().endsWith("original_dir/Name2.java"));
subDirectory.renameTo(renamedSubDirectory);
waitForFileEvents();
resources = getResources(resourceAccumulator);
assertEquals(2, resources.size());
assertTrue(resources.get(0).getPath().endsWith("new_dir/Name1.java"));
assertTrue(resources.get(1).getPath().endsWith("new_dir/Name2.java"));
resourceAccumulator.shutdown();
}
public void testRenameParentDirectory() throws Exception {
File rootDirectory = Files.createTempDir();
File parentDirectory = createDirectoryIn("original_dir", rootDirectory);
File subDirectory = createDirectoryIn("subdir", parentDirectory);
createFileIn("Name1.java", subDirectory);
createFileIn("Name2.java", subDirectory);
File renamedParentDirectory = new File(rootDirectory, "new_dir");
ResourceAccumulator resourceAccumulator =
new ResourceAccumulator(rootDirectory.toPath(), createInclusivePathPrefixSet());
List<AbstractResource> resources = getResources(resourceAccumulator);
assertEquals(2, resources.size());
assertTrue(resources.get(0).getPath().endsWith("original_dir/subdir/Name1.java"));
assertTrue(resources.get(1).getPath().endsWith("original_dir/subdir/Name2.java"));
parentDirectory.renameTo(renamedParentDirectory);
waitForFileEvents();
resources = getResources(resourceAccumulator);
assertEquals(2, resources.size());
assertTrue(resources.get(0).getPath().endsWith("new_dir/subdir/Name1.java"));
assertTrue(resources.get(1).getPath().endsWith("new_dir/subdir/Name2.java"));
resourceAccumulator.shutdown();
}
public void testSymlinkInfiniteLoop() throws Exception {
File rootDirectory = Files.createTempDir();
File subDirectory = Files.createTempDir();
ResourceAccumulator resourceAccumulator =
new ResourceAccumulator(rootDirectory.toPath(), createInclusivePathPrefixSet());
assertTrue(getResources(resourceAccumulator).isEmpty());
// Symlink in a loop
java.nio.file.Files.createSymbolicLink(new File(rootDirectory, "sublink").toPath(),
subDirectory.toPath()).toFile();
java.nio.file.Files.createSymbolicLink(new File(subDirectory, "sublink").toPath(),
rootDirectory.toPath()).toFile();
createFileIn("New.java", subDirectory);
waitForFileEvents();
try {
// Should throw an error if resourceAccumulator got stuck in an infinite directory scan loop.
getResources(resourceAccumulator);
fail();
} catch (FileSystemException expected) {
// Expected
}
resourceAccumulator.shutdown();
}
public void testSymlinks() throws Exception {
File scratchDirectory = Files.createTempDir();
File newFile = createFileIn("New.java", scratchDirectory);
File rootDirectory = Files.createTempDir();
File subDirectory = Files.createTempDir();
ResourceAccumulator resourceAccumulator =
new ResourceAccumulator(rootDirectory.toPath(), createInclusivePathPrefixSet());
assertTrue(getResources(resourceAccumulator).isEmpty());
// Symlink in a subdirectory and then symlink in a contained file.
java.nio.file.Files.createSymbolicLink(new File(rootDirectory, "sublink").toPath(),
subDirectory.toPath()).toFile();
java.nio.file.Files.createSymbolicLink(new File(subDirectory, "New.java").toPath(),
newFile.toPath()).toFile();
waitForFileEvents();
List<AbstractResource> resources = getResources(resourceAccumulator);
assertEquals(1, resources.size());
assertTrue(resources.get(0).getPath().endsWith("sublink/New.java"));
resourceAccumulator.shutdown();
}
private static File createDirectoryIn(String fileName, File inDirectory) {
File newDirectory = new File(inDirectory, fileName);
newDirectory.mkdir();
return newDirectory;
}
private static File createFileIn(String fileName, File inDirectory) throws IOException {
File newFile = new File(inDirectory, fileName);
newFile.createNewFile();
return newFile;
}
private List<AbstractResource> getResources(ResourceAccumulator resourceAccumulator)
throws IOException {
resourceAccumulator.refreshResources();
List<AbstractResource> list = Lists.newArrayList(resourceAccumulator.getResources().keySet());
Collections.sort(list, new Comparator<AbstractResource>() {
@Override
public int compare(AbstractResource a, AbstractResource b) {
return a.getLocation().compareTo(b.getLocation());
}
});
return list;
}
private Set<PathPrefixSet> pathPrefixes = Sets.newHashSet();
@Override
public void tearDown() {
pathPrefixes.clear();
}
private PathPrefixSet createInclusivePathPrefixSet() {
PathPrefixSet pathPrefixSet = new PathPrefixSet();
pathPrefixSet.add(new PathPrefix("", null));
// Keep the the reference until the end of the test to create a strong reference, otherwise
// will get GCed as ResourceAccumulator refers to it weakly.
pathPrefixes.add(pathPrefixSet);
return pathPrefixSet;
}
private void waitForFileEvents() throws InterruptedException {
Thread.sleep(100);
}
}