/*
* Copyright 2015-present Facebook, 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.facebook.buck.hashing;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;
import com.google.common.collect.ImmutableSet;
import com.google.common.hash.HashCode;
import com.google.common.jimfs.Configuration;
import com.google.common.jimfs.Jimfs;
import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
import org.junit.Before;
import org.junit.Test;
public class FilePathHashLoaderTest {
private final FileSystem vfs = Jimfs.newFileSystem(Configuration.unix());
private Path cellRoot;
private Path file;
private Path directory;
private Path fileInDirectory;
@Before
public void setUpFileSystem() throws IOException {
cellRoot = vfs.getPath("/path/to/the/cell/root");
file = cellRoot.resolve("a.txt");
directory = cellRoot.resolve("dir");
fileInDirectory = directory.resolve("a.txt");
Files.createDirectories(cellRoot);
Files.createDirectory(directory);
Files.write(file, "Hello!".getBytes());
Files.write(fileInDirectory, "Hello!".getBytes());
}
@Test
public void returnsDifferentHashesForDifferentPaths() throws IOException {
FilePathHashLoader loader = new FilePathHashLoader(cellRoot, ImmutableSet.of());
assertThat(loader.get(file), not(equalTo(loader.get(fileInDirectory))));
}
@Test
public void doesNotCareAboutFileContents() throws IOException {
FilePathHashLoader loader = new FilePathHashLoader(cellRoot, ImmutableSet.of());
HashCode hashBefore = loader.get(file);
Files.write(file, "Goodbye!".getBytes());
HashCode hashAfter = loader.get(file);
assertThat(hashBefore, equalTo(hashAfter));
}
@Test
public void returnsDifferentHashesIfFileIsAssumedToBeModified() throws IOException {
assertThatChangeIsDetected(file, file);
}
@Test
public void detectsChangesWithinADirectory() throws IOException {
assertThatChangeIsDetected(fileInDirectory, directory);
}
@Test
public void changesInOtherFilesDoNotAffectDirectoryHash() throws IOException {
FilePathHashLoader baseLoader = new FilePathHashLoader(cellRoot, ImmutableSet.of());
FilePathHashLoader modifiedLoader = new FilePathHashLoader(cellRoot, ImmutableSet.of(file));
assertThat(baseLoader.get(directory), equalTo(modifiedLoader.get(directory)));
}
@Test
public void detectsChangesBehindASymlink() throws IOException {
Path virtualFile = cellRoot.resolve("symlink");
Files.createSymbolicLink(virtualFile, vfs.getPath("a.txt"));
assertThatChangeIsDetected(file, virtualFile);
assertThatChangeIsDetected(virtualFile, file);
}
@Test
public void detectsChangesBehindADirectorySymlink() throws IOException {
Path symlink = cellRoot.resolve("symlink");
Files.createSymbolicLink(symlink, vfs.getPath("dir"));
assertThatChangeIsDetected(fileInDirectory, symlink);
}
@Test
public void detectsChangesBehindASymlinkInADirectory() throws IOException {
Path symlink = directory.resolve("symlink");
Files.createSymbolicLink(symlink, vfs.getPath("../a.txt"));
assertThatChangeIsDetected(file, directory);
}
@Test
public void relativePathsAreResolvedToCellRoot() throws IOException {
assertThatChangeIsDetected(vfs.getPath("a.txt"), file);
assertThatChangeIsDetected(file, vfs.getPath("a.txt"));
}
@Test
public void denormalizedPathsAlsoWork() throws IOException {
assertThatChangeIsDetected(directory.resolve("../dir/a.txt"), fileInDirectory);
assertThatChangeIsDetected(fileInDirectory, directory.resolve("../dir/a.txt"));
}
@Test
public void cellRootPathDoesNotInfluenceTheHashes() throws IOException {
FilePathHashLoader baseLoader =
new FilePathHashLoader(cellRoot, ImmutableSet.of(fileInDirectory));
HashCode fileHashCode = baseLoader.get(file);
HashCode fileInDirectoryHashCode = baseLoader.get(fileInDirectory);
HashCode directoryHashCode = baseLoader.get(directory);
Path newCellRoot = vfs.getPath("/different");
Files.move(cellRoot, newCellRoot);
file = newCellRoot.resolve("a.txt");
directory = newCellRoot.resolve("dir");
fileInDirectory = directory.resolve("a.txt");
FilePathHashLoader newLoader =
new FilePathHashLoader(newCellRoot, ImmutableSet.of(fileInDirectory));
assertThat(newLoader.get(file), equalTo(fileHashCode));
assertThat(newLoader.get(fileInDirectory), equalTo(fileInDirectoryHashCode));
assertThat(newLoader.get(directory), equalTo(directoryHashCode));
}
private void assertThatChangeIsDetected(Path changedPath, Path checkedPath) throws IOException {
FilePathHashLoader baseLoader = new FilePathHashLoader(cellRoot, ImmutableSet.of());
FilePathHashLoader modifiedLoader =
new FilePathHashLoader(cellRoot, ImmutableSet.of(changedPath));
assertThat(baseLoader.get(checkedPath), not(equalTo(modifiedLoader.get(checkedPath))));
}
}