/*
* 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.util.cache;
import static org.junit.Assert.assertTrue;
import com.facebook.buck.config.Config;
import com.facebook.buck.config.ConfigBuilder;
import com.facebook.buck.io.ArchiveMemberPath;
import com.facebook.buck.io.ProjectFilesystem;
import com.facebook.buck.testutil.FakeProjectFilesystem;
import com.facebook.buck.testutil.integration.TemporaryPaths;
import com.facebook.buck.zip.CustomJarOutputStream;
import com.facebook.buck.zip.ZipOutputStreams;
import com.google.common.collect.ImmutableList;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
public class StackedFileHashCacheTest {
private static final String SOME_FILE_INSIDE_JAR = "SomeClass.class";
@Rule public TemporaryPaths tmp = new TemporaryPaths();
@Rule public TemporaryPaths tmp2 = new TemporaryPaths();
@Rule public ExpectedException expectedException = ExpectedException.none();
@Test
public void usesFirstCacheAbsolutePath() throws InterruptedException, IOException {
ProjectFilesystem filesystem = FakeProjectFilesystem.createJavaOnlyFilesystem();
Path path = Paths.get("world.txt");
filesystem.touch(path);
Path fullPath = filesystem.resolve(path);
ProjectFileHashCache innerCache = DefaultFileHashCache.createDefaultFileHashCache(filesystem);
StackedFileHashCache cache = new StackedFileHashCache(ImmutableList.of(innerCache));
cache.get(fullPath);
assertTrue(innerCache.willGet(path));
}
@Test
public void usesFirstCache() throws InterruptedException, IOException {
ProjectFilesystem filesystem = FakeProjectFilesystem.createJavaOnlyFilesystem();
Path path = Paths.get("world.txt");
filesystem.touch(path);
ProjectFileHashCache innerCache = DefaultFileHashCache.createDefaultFileHashCache(filesystem);
StackedFileHashCache cache = new StackedFileHashCache(ImmutableList.of(innerCache));
cache.get(filesystem, path);
assertTrue(innerCache.willGet(path));
}
@Test
public void usesFirstCacheForArchivePathAbsolutePath() throws IOException {
ProjectFilesystem filesystem = new FakeProjectFilesystem();
Path path = Paths.get("world.jar");
writeJarWithHashes(filesystem, path);
ArchiveMemberPath archiveMemberPath =
ArchiveMemberPath.of(path, Paths.get(SOME_FILE_INSIDE_JAR));
ArchiveMemberPath fullArchiveMemberPath =
archiveMemberPath.withArchivePath(filesystem.resolve(archiveMemberPath.getArchivePath()));
ProjectFileHashCache innerCache = DefaultFileHashCache.createDefaultFileHashCache(filesystem);
StackedFileHashCache cache = new StackedFileHashCache(ImmutableList.of(innerCache));
cache.get(fullArchiveMemberPath);
assertTrue(innerCache.willGet(archiveMemberPath));
}
@Test
public void usesFirstCacheForArchivePath() throws IOException {
ProjectFilesystem filesystem = new FakeProjectFilesystem();
Path path = filesystem.getPath("world.jar");
writeJarWithHashes(filesystem, path);
ArchiveMemberPath archiveMemberPath =
ArchiveMemberPath.of(path, Paths.get(SOME_FILE_INSIDE_JAR));
ProjectFileHashCache innerCache = DefaultFileHashCache.createDefaultFileHashCache(filesystem);
StackedFileHashCache cache = new StackedFileHashCache(ImmutableList.of(innerCache));
cache.get(filesystem, archiveMemberPath);
assertTrue(innerCache.willGet(archiveMemberPath));
}
@Test
public void usesSecondCacheAbsolutePath() throws InterruptedException, IOException {
Path path = Paths.get("world.txt");
Path fullPath = tmp2.getRoot().resolve(path);
ProjectFileHashCache innerCache =
DefaultFileHashCache.createDefaultFileHashCache(new ProjectFilesystem(tmp.getRoot()));
// The second project filesystem has the file.
ProjectFilesystem filesystem2 = new ProjectFilesystem(tmp2.getRoot());
ProjectFileHashCache innerCache2 = DefaultFileHashCache.createDefaultFileHashCache(filesystem2);
filesystem2.touch(path);
StackedFileHashCache cache =
new StackedFileHashCache(ImmutableList.of(innerCache, innerCache2));
cache.get(fullPath);
assertTrue(innerCache2.willGet(path));
}
@Test
public void usesSecondCache() throws InterruptedException, IOException {
ProjectFileHashCache innerCache =
DefaultFileHashCache.createDefaultFileHashCache(new ProjectFilesystem(tmp.getRoot()));
// The second project filesystem has the file.
ProjectFilesystem filesystem2 = new ProjectFilesystem(tmp2.getRoot());
Path path = filesystem2.getPath("world.txt");
ProjectFileHashCache innerCache2 = DefaultFileHashCache.createDefaultFileHashCache(filesystem2);
filesystem2.touch(path);
StackedFileHashCache cache =
new StackedFileHashCache(ImmutableList.of(innerCache, innerCache2));
cache.get(filesystem2, path);
assertTrue(innerCache2.willGet(path));
}
@Test
public void usesSecondCacheForArchivePathAbsolutePath() throws InterruptedException, IOException {
Path path = Paths.get("world.jar");
Path fullPath = tmp2.getRoot().resolve(path);
ProjectFileHashCache innerCache =
DefaultFileHashCache.createDefaultFileHashCache(new ProjectFilesystem(tmp.getRoot()));
// The second project filesystem has the file.
ProjectFilesystem filesystem2 = new ProjectFilesystem(tmp2.getRoot());
ProjectFileHashCache innerCache2 = DefaultFileHashCache.createDefaultFileHashCache(filesystem2);
writeJarWithHashes(filesystem2, fullPath);
ArchiveMemberPath archiveMemberPath =
ArchiveMemberPath.of(path, Paths.get(SOME_FILE_INSIDE_JAR));
ArchiveMemberPath fullArchiveMemberPath =
archiveMemberPath.withArchivePath(filesystem2.resolve(archiveMemberPath.getArchivePath()));
StackedFileHashCache cache =
new StackedFileHashCache(ImmutableList.of(innerCache, innerCache2));
cache.get(fullArchiveMemberPath);
assertTrue(innerCache2.willGet(archiveMemberPath));
}
@Test
public void usesSecondCacheForArchivePath() throws InterruptedException, IOException {
ProjectFileHashCache innerCache =
DefaultFileHashCache.createDefaultFileHashCache(new ProjectFilesystem(tmp.getRoot()));
// The second project filesystem has the file.
ProjectFilesystem filesystem2 = new ProjectFilesystem(tmp2.getRoot());
Path path = filesystem2.getPath("world.jar");
ProjectFileHashCache innerCache2 = DefaultFileHashCache.createDefaultFileHashCache(filesystem2);
writeJarWithHashes(filesystem2, path);
ArchiveMemberPath archiveMemberPath =
ArchiveMemberPath.of(path, Paths.get(SOME_FILE_INSIDE_JAR));
StackedFileHashCache cache =
new StackedFileHashCache(ImmutableList.of(innerCache, innerCache2));
cache.get(filesystem2, archiveMemberPath);
assertTrue(innerCache2.willGet(archiveMemberPath));
}
@Test
public void skipsFirstCacheAbsolutePath() throws IOException {
Path fullPath = Paths.get("some/path");
ProjectFilesystem filesystem = new FakeProjectFilesystem(tmp.getRoot());
ProjectFileHashCache innerCache = DefaultFileHashCache.createDefaultFileHashCache(filesystem);
StackedFileHashCache cache = new StackedFileHashCache(ImmutableList.of(innerCache));
expectedException.expect(NoSuchFileException.class);
cache.get(filesystem.resolve(fullPath));
}
@Test
public void skipsFirstCache() throws IOException {
ProjectFilesystem filesystem = new FakeProjectFilesystem(tmp.getRoot());
Path path = filesystem.getPath("some/path");
ProjectFileHashCache innerCache = DefaultFileHashCache.createDefaultFileHashCache(filesystem);
StackedFileHashCache cache = new StackedFileHashCache(ImmutableList.of(innerCache));
expectedException.expect(NoSuchFileException.class);
cache.get(filesystem, path);
}
@Test
public void skipsFirstCacheForArchiveMemberPathAbsolutePath()
throws InterruptedException, IOException {
Path fullPath = Paths.get("world.jar");
ProjectFilesystem filesystem = new ProjectFilesystem(tmp.getRoot());
writeJarWithHashes(filesystem, filesystem.resolve(fullPath));
ArchiveMemberPath archiveMemberPath =
ArchiveMemberPath.of(filesystem.resolve(fullPath), Paths.get("Nonexistent.class"));
ProjectFileHashCache innerCache = DefaultFileHashCache.createDefaultFileHashCache(filesystem);
StackedFileHashCache cache = new StackedFileHashCache(ImmutableList.of(innerCache));
expectedException.expect(NoSuchFileException.class);
cache.get(archiveMemberPath);
}
@Test
public void skipsFirstCacheForArchiveMemberPath() throws InterruptedException, IOException {
ProjectFilesystem filesystem = new ProjectFilesystem(tmp.getRoot());
Path path = filesystem.getPath("world.jar");
writeJarWithHashes(filesystem, path);
ArchiveMemberPath archiveMemberPath =
ArchiveMemberPath.of(path, filesystem.getPath("Nonexistent.class"));
ProjectFileHashCache innerCache = DefaultFileHashCache.createDefaultFileHashCache(filesystem);
StackedFileHashCache cache = new StackedFileHashCache(ImmutableList.of(innerCache));
expectedException.expect(NoSuchFileException.class);
cache.get(filesystem, archiveMemberPath);
}
@Test
public void skipsFirstCacheBecauseIgnoredAbsolutePath() throws InterruptedException, IOException {
Config config = ConfigBuilder.createFromText("[project]", "ignore = world.txt");
Path path = Paths.get("world.txt");
Path fullPath = tmp.getRoot().resolve(path);
ProjectFilesystem filesystem = new ProjectFilesystem(tmp.getRoot(), config);
filesystem.touch(path);
ProjectFileHashCache innerCache = DefaultFileHashCache.createDefaultFileHashCache(filesystem);
StackedFileHashCache cache = new StackedFileHashCache(ImmutableList.of(innerCache));
expectedException.expect(NoSuchFileException.class);
cache.get(filesystem.resolve(fullPath));
}
@Test
public void skipsFirstCacheBecauseIgnored() throws InterruptedException, IOException {
Config config = ConfigBuilder.createFromText("[project]", "ignore = world.txt");
ProjectFilesystem filesystem = new ProjectFilesystem(tmp.getRoot(), config);
Path path = filesystem.getPath("world.txt");
filesystem.touch(path);
ProjectFileHashCache innerCache = DefaultFileHashCache.createDefaultFileHashCache(filesystem);
StackedFileHashCache cache = new StackedFileHashCache(ImmutableList.of(innerCache));
expectedException.expect(NoSuchFileException.class);
cache.get(filesystem, path);
}
@Test
public void skipsFirstCacheBecauseIgnoredForArchiveMemberPathAbsolutePath()
throws InterruptedException, IOException {
Config config = ConfigBuilder.createFromText("[project]", "ignore = world.jar");
Path fullPath = Paths.get("world.jar");
ProjectFilesystem filesystem = new ProjectFilesystem(tmp.getRoot(), config);
writeJarWithHashes(filesystem, filesystem.resolve(fullPath));
ArchiveMemberPath archiveMemberPath =
ArchiveMemberPath.of(filesystem.resolve(fullPath), Paths.get("Nonexistent.class"));
ProjectFileHashCache innerCache = DefaultFileHashCache.createDefaultFileHashCache(filesystem);
StackedFileHashCache cache = new StackedFileHashCache(ImmutableList.of(innerCache));
expectedException.expect(NoSuchFileException.class);
cache.get(archiveMemberPath);
}
@Test
public void skipsFirstCacheBecauseIgnoredForArchiveMemberPath()
throws InterruptedException, IOException {
Config config = ConfigBuilder.createFromText("[project]", "ignore = world.jar");
ProjectFilesystem filesystem = new ProjectFilesystem(tmp.getRoot(), config);
Path path = filesystem.getPath("world.jar");
writeJarWithHashes(filesystem, path);
ArchiveMemberPath archiveMemberPath =
ArchiveMemberPath.of(path, filesystem.getPath("Nonexistent.class"));
ProjectFileHashCache innerCache = DefaultFileHashCache.createDefaultFileHashCache(filesystem);
StackedFileHashCache cache = new StackedFileHashCache(ImmutableList.of(innerCache));
expectedException.expect(NoSuchFileException.class);
cache.get(filesystem, archiveMemberPath);
}
private void writeJarWithHashes(ProjectFilesystem filesystem, Path path) throws IOException {
try (CustomJarOutputStream jar =
ZipOutputStreams.newJarOutputStream(filesystem.newFileOutputStream(path))) {
jar.setEntryHashingEnabled(true);
jar.writeEntry(
SOME_FILE_INSIDE_JAR,
new ByteArrayInputStream("fake contents".getBytes(StandardCharsets.UTF_8)));
}
}
}