blob: 3d0fe4da30e085391e46332c1a93e66dc378e0f8 [file] [log] [blame]
// Copyright 2016 The Bazel Authors. All rights reserved.
//
// 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.devtools.build.lib.bazel.repository.cache;
import static com.google.common.truth.Truth.assertThat;
import com.google.common.base.Strings;
import com.google.devtools.build.lib.bazel.repository.cache.RepositoryCache.KeyType;
import com.google.devtools.build.lib.testutil.Scratch;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
import java.io.IOException;
import java.nio.charset.Charset;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/**
* Tests for {@link RepositoryCache}.
*/
@RunWith(JUnit4.class)
public class RepositoryCacheTest {
@Rule public ExpectedException thrown = ExpectedException.none();
private Scratch scratch;
private RepositoryCache repositoryCache;
private Path repositoryCachePath;
private Path contentAddressableCachePath;
private Path downloadedFile;
private String downloadedFileSha256;
@Before
public void setUp() throws Exception {
scratch = new Scratch("/");
repositoryCachePath = scratch.dir("/repository_cache");
repositoryCache = new RepositoryCache();
repositoryCache.setRepositoryCachePath(repositoryCachePath);
contentAddressableCachePath = repositoryCache.getContentAddressableCachePath();
downloadedFile = scratch.file("file.tmp", Charset.defaultCharset(), "contents");
downloadedFileSha256 = "bfe5ed57e6e323555b379c660aa8d35b70c2f8f07cf03ad6747266495ac13be0";
}
@After
public void tearDown() throws IOException {
repositoryCachePath.deleteTree();
}
@Test
public void testNonExistentCacheValue() {
String fakeSha256 = Strings.repeat("a", 64);
assertThat(repositoryCache.exists(fakeSha256, KeyType.SHA256)).isFalse();
}
/** Test that the put method correctly stores the downloaded file into the cache. */
@Test
public void testPutCacheValue() throws Exception {
repositoryCache.put(downloadedFileSha256, downloadedFile, KeyType.SHA256);
Path cacheEntry = KeyType.SHA256.getCachePath(contentAddressableCachePath).getChild(downloadedFileSha256);
Path cacheValue = cacheEntry.getChild(RepositoryCache.DEFAULT_CACHE_FILENAME);
assertThat(FileSystemUtils.readContent(downloadedFile, Charset.defaultCharset()))
.isEqualTo(FileSystemUtils.readContent(cacheValue, Charset.defaultCharset()));
}
/**
* Test that the put mehtod without cache key correctly stores the downloaded file into the cache.
*/
@Test
public void testPutCacheValueWithoutHash() throws Exception {
String cacheKey = repositoryCache.put(downloadedFile, KeyType.SHA256);
assertThat(cacheKey).isEqualTo(downloadedFileSha256);
Path cacheEntry =
KeyType.SHA256.getCachePath(contentAddressableCachePath).getChild(downloadedFileSha256);
Path cacheValue = cacheEntry.getChild(RepositoryCache.DEFAULT_CACHE_FILENAME);
assertThat(FileSystemUtils.readContent(downloadedFile, Charset.defaultCharset()))
.isEqualTo(FileSystemUtils.readContent(cacheValue, Charset.defaultCharset()));
}
/**
* Test that the put method is idempotent, i.e. two successive put calls should not affect the
* final state in the cache.
*/
@Test
public void testPutCacheValueIdempotent() throws Exception {
repositoryCache.put(downloadedFileSha256, downloadedFile, KeyType.SHA256);
repositoryCache.put(downloadedFileSha256, downloadedFile, KeyType.SHA256);
Path cacheEntry = KeyType.SHA256.getCachePath(contentAddressableCachePath).getChild(downloadedFileSha256);
Path cacheValue = cacheEntry.getChild(RepositoryCache.DEFAULT_CACHE_FILENAME);
assertThat(FileSystemUtils.readContent(downloadedFile, Charset.defaultCharset()))
.isEqualTo(FileSystemUtils.readContent(cacheValue, Charset.defaultCharset()));
}
/** Test that the get method correctly retrieves the cached file from the cache. */
@Test
public void testGetCacheValue() throws Exception {
// Inject file into cache
repositoryCache.put(downloadedFileSha256, downloadedFile, KeyType.SHA256);
Path targetDirectory = scratch.dir("/external");
Path targetPath = targetDirectory.getChild(downloadedFile.getBaseName());
Path actualTargetPath = repositoryCache.get(downloadedFileSha256, targetPath, KeyType.SHA256);
// Check that the contents are the same.
assertThat(FileSystemUtils.readContent(downloadedFile, Charset.defaultCharset()))
.isEqualTo(FileSystemUtils.readContent(actualTargetPath, Charset.defaultCharset()));
// Check that the returned value is stored under outputBaseExternal.
assertThat((Object) actualTargetPath).isEqualTo(targetPath);
}
/** Test that the get method retrieves a null if the value is not cached. */
@Test
public void testGetNullCacheValue() throws Exception {
Path targetDirectory = scratch.dir("/external");
Path targetPath = targetDirectory.getChild(downloadedFile.getBaseName());
Path actualTargetPath = repositoryCache.get(downloadedFileSha256, targetPath, KeyType.SHA256);
assertThat(actualTargetPath).isNull();
}
@Test
public void testInvalidSha256Throws() throws Exception {
String invalidSha = "foo";
thrown.expect(IOException.class);
thrown.expectMessage("Invalid key \"foo\" of type SHA-256");
repositoryCache.put(invalidSha, downloadedFile, KeyType.SHA256);
}
@Test
public void testPoisonedCache() throws Exception {
Path poisonedEntry = KeyType.SHA256
.getCachePath(contentAddressableCachePath).getChild(downloadedFileSha256);
Path poisonedValue = poisonedEntry.getChild(RepositoryCache.DEFAULT_CACHE_FILENAME);
scratch.file(poisonedValue.getPathString(), Charset.defaultCharset(), "poisoned");
Path targetDirectory = scratch.dir("/external");
Path targetPath = targetDirectory.getChild(downloadedFile.getBaseName());
thrown.expect(IOException.class);
thrown.expectMessage("does not match expected");
thrown.expectMessage("Please delete the directory");
repositoryCache.get(downloadedFileSha256, targetPath, KeyType.SHA256);
}
@Test
public void testGetChecksum() throws Exception {
String actualChecksum = RepositoryCache.getChecksum(KeyType.SHA256, downloadedFile);
assertThat(actualChecksum).isEqualTo(downloadedFileSha256);
}
@Test
public void testAssertFileChecksumPass() throws Exception {
RepositoryCache.assertFileChecksum(downloadedFileSha256, downloadedFile, KeyType.SHA256);
}
@Test
public void testAssertFileChecksumFail() throws Exception {
thrown.expect(IOException.class);
thrown.expectMessage("does not match expected");
RepositoryCache.assertFileChecksum(
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
downloadedFile,
KeyType.SHA256);
}
@Test
public void testCanonicalId() throws Exception {
repositoryCache.put(downloadedFileSha256, downloadedFile, KeyType.SHA256, "fooid");
Path targetDirectory = scratch.dir("/external");
Path targetPath = targetDirectory.getChild(downloadedFile.getBaseName());
Path lookupWithSameId =
repositoryCache.get(downloadedFileSha256, targetPath, KeyType.SHA256, "fooid");
assertThat(lookupWithSameId).isEqualTo(targetPath);
Path lookupOtherId =
repositoryCache.get(downloadedFileSha256, targetPath, KeyType.SHA256, "barid");
assertThat(lookupOtherId).isNull();
Path lookupNoId = repositoryCache.get(downloadedFileSha256, targetPath, KeyType.SHA256);
assertThat(lookupNoId).isEqualTo(targetPath);
}
}