/*
* 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.artifact_cache;
import static org.junit.Assert.assertThat;
import com.facebook.buck.cli.BuckConfigTestUtils;
import com.facebook.buck.io.MorePaths;
import com.facebook.buck.io.ProjectFilesystem;
import com.facebook.buck.testutil.FakeProjectFilesystem;
import com.facebook.buck.testutil.integration.TemporaryPaths;
import com.facebook.buck.util.HumanReadableException;
import com.facebook.buck.util.environment.Architecture;
import com.facebook.buck.util.environment.Platform;
import com.google.common.base.Joiner;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import java.io.StringReader;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
import org.hamcrest.Matchers;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
public class ArtifactCacheBuckConfigTest {
@Rule public TemporaryPaths tmpDir = new TemporaryPaths();
@Rule public ExpectedException expectedException = ExpectedException.none();
@Test
public void testWifiBlacklist() throws IOException {
ArtifactCacheBuckConfig config =
createFromText("[cache]", "mode = http", "blacklisted_wifi_ssids = yolocoaster");
ImmutableSet<HttpCacheEntry> httpCaches = config.getCacheEntries().getHttpCacheEntries();
assertThat(httpCaches, Matchers.hasSize(1));
HttpCacheEntry cacheEntry = FluentIterable.from(httpCaches).get(0);
assertThat(
cacheEntry.isWifiUsableForDistributedCache(Optional.of("yolocoaster")), Matchers.is(false));
assertThat(
cacheEntry.isWifiUsableForDistributedCache(Optional.of("swagtastic")), Matchers.is(true));
config = createFromText("[cache]", "mode = http");
httpCaches = config.getCacheEntries().getHttpCacheEntries();
assertThat(httpCaches, Matchers.hasSize(1));
cacheEntry = FluentIterable.from(httpCaches).get(0);
assertThat(
cacheEntry.isWifiUsableForDistributedCache(Optional.of("yolocoaster")), Matchers.is(true));
}
@Test
public void testMode() throws IOException {
ArtifactCacheBuckConfig config = createFromText("[cache]", "mode = http");
assertThat(config.hasAtLeastOneWriteableCache(), Matchers.is(true));
assertThat(
config.getArtifactCacheModes(),
Matchers.contains(ArtifactCacheBuckConfig.ArtifactCacheMode.http));
config = createFromText("[cache]", "mode = dir");
assertThat(config.hasAtLeastOneWriteableCache(), Matchers.is(false));
assertThat(
config.getArtifactCacheModes(),
Matchers.contains(ArtifactCacheBuckConfig.ArtifactCacheMode.dir));
config = createFromText("[cache]", "mode = dir, http");
assertThat(config.hasAtLeastOneWriteableCache(), Matchers.is(true));
assertThat(
config.getArtifactCacheModes(),
Matchers.containsInAnyOrder(
ArtifactCacheBuckConfig.ArtifactCacheMode.dir,
ArtifactCacheBuckConfig.ArtifactCacheMode.http));
}
@Test
public void testHttpCacheSettings() throws Exception {
ArtifactCacheBuckConfig config =
createFromText(
"[cache]",
"http_max_concurrent_writes = 5",
"http_writer_shutdown_timeout_seconds = 6",
"http_timeout_seconds = 42",
"http_url = http://test.host:1234",
"http_read_headers = Foo: bar; Baz: meh",
"http_write_headers = Authorization: none",
"http_mode = readwrite");
ImmutableSet<HttpCacheEntry> httpCaches = config.getCacheEntries().getHttpCacheEntries();
assertThat(httpCaches, Matchers.hasSize(1));
HttpCacheEntry cacheEntry = FluentIterable.from(httpCaches).get(0);
ImmutableMap.Builder<String, String> readBuilder = ImmutableMap.builder();
ImmutableMap<String, String> expectedReadHeaders =
readBuilder.put("Foo", "bar").put("Baz", "meh").build();
ImmutableMap.Builder<String, String> writeBuilder = ImmutableMap.builder();
ImmutableMap<String, String> expectedWriteHeaders =
writeBuilder.put("Authorization", "none").build();
assertThat(config.getHttpMaxConcurrentWrites(), Matchers.is(5));
assertThat(config.getHttpWriterShutdownTimeout(), Matchers.is(6));
assertThat(cacheEntry.getTimeoutSeconds(), Matchers.is(42));
assertThat(cacheEntry.getUrl(), Matchers.equalTo(new URI("http://test.host:1234")));
assertThat(cacheEntry.getReadHeaders(), Matchers.equalTo(expectedReadHeaders));
assertThat(cacheEntry.getWriteHeaders(), Matchers.equalTo(expectedWriteHeaders));
assertThat(cacheEntry.getCacheReadMode(), Matchers.is(CacheReadMode.READWRITE));
}
@Test
public void testHttpCacheHeaderDefaultSettings() throws Exception {
ArtifactCacheBuckConfig config = createFromText("[cache]", "http_timeout_seconds = 42");
ImmutableSet<HttpCacheEntry> httpCaches = config.getCacheEntries().getHttpCacheEntries();
assertThat(httpCaches, Matchers.hasSize(1));
HttpCacheEntry cacheEntry = FluentIterable.from(httpCaches).get(0);
// If the headers are not set we shouldn't get any by default.
ImmutableMap.Builder<String, String> readBuilder = ImmutableMap.builder();
ImmutableMap<String, String> expectedReadHeaders = readBuilder.build();
ImmutableMap.Builder<String, String> writeBuilder = ImmutableMap.builder();
ImmutableMap<String, String> expectedWriteHeaders = writeBuilder.build();
assertThat(cacheEntry.getReadHeaders(), Matchers.equalTo(expectedReadHeaders));
assertThat(cacheEntry.getWriteHeaders(), Matchers.equalTo(expectedWriteHeaders));
}
@Test
public void testDirCacheSettings() throws IOException {
ArtifactCacheBuckConfig config =
createFromText("[cache]", "dir = cache_dir", "dir_mode = readonly", "dir_max_size = 1022B");
DirCacheEntry dirCacheConfig = config.getCacheEntries().getDirCacheEntries().asList().get(0);
assertThat(
dirCacheConfig.getCacheDir(), Matchers.equalTo(Paths.get("cache_dir").toAbsolutePath()));
assertThat(dirCacheConfig.getCacheReadMode(), Matchers.is(CacheReadMode.READONLY));
assertThat(dirCacheConfig.getMaxSizeBytes(), Matchers.equalTo(Optional.of(1022L)));
}
@Test
public void testMultipleDirCacheSettings() throws IOException {
ArtifactCacheBuckConfig config =
createFromText(
"[cache]",
"dir_cache_names = name1, othername",
"[cache#name1]",
"dir = cache_dir_name1",
"dir_mode = readwrite",
"dir_max_size = 1022B",
"[cache#othername]",
"dir = othername_dir_cache",
"dir_mode = readonly",
"dir_max_size = 800B");
ImmutableList<DirCacheEntry> entries =
ImmutableList.copyOf(config.getCacheEntries().getDirCacheEntries());
DirCacheEntry name1Entry = entries.get(0);
assertThat(
name1Entry.getCacheDir(), Matchers.equalTo(Paths.get("cache_dir_name1").toAbsolutePath()));
assertThat(name1Entry.getCacheReadMode(), Matchers.equalTo(CacheReadMode.READWRITE));
assertThat(name1Entry.getMaxSizeBytes(), Matchers.equalTo(Optional.of(1022L)));
DirCacheEntry othernameDirCche = entries.get(1);
assertThat(
othernameDirCche.getCacheDir(),
Matchers.equalTo(Paths.get("othername_dir_cache").toAbsolutePath()));
assertThat(othernameDirCche.getCacheReadMode(), Matchers.equalTo(CacheReadMode.READONLY));
assertThat(othernameDirCche.getMaxSizeBytes(), Matchers.equalTo(Optional.of(800L)));
}
@Test(expected = HumanReadableException.class)
public void testMalformedHttpUrl() throws IOException {
ArtifactCacheBuckConfig config = createFromText("[cache]", "http_url = notaurl");
config.getCacheEntries().getHttpCacheEntries();
}
@Test(expected = HumanReadableException.class)
public void testMalformedMode() throws IOException {
ArtifactCacheBuckConfig config = createFromText("[cache]", "dir_mode = notamode");
config.getCacheEntries().getDirCacheEntries();
}
@Test
public void testServedCacheAbsentByDefault() throws IOException {
ArtifactCacheBuckConfig config = createFromText("[cache]", "dir = ~/cache_dir");
assertThat(config.getServedLocalCache(), Matchers.equalTo(Optional.empty()));
}
@Test
public void testServedCacheInheritsDirAndSizeFromDirCache() throws IOException {
Path cacheDir = tmpDir.getRoot();
ArtifactCacheBuckConfig config =
createFromText("[cache]", "serve_local_cache = true", "dir = " + cacheDir);
assertThat(
config.getServedLocalCache(),
Matchers.equalTo(
Optional.of(
DirCacheEntry.builder()
.setMaxSizeBytes(Optional.empty())
.setCacheDir(cacheDir)
.setCacheReadMode(CacheReadMode.READONLY)
.build())));
config =
createFromText(
"[cache]",
"serve_local_cache = true",
"dir = " + cacheDir,
"dir_mode = readwrite",
"dir_max_size = 42b");
assertThat(
config.getServedLocalCache(),
Matchers.equalTo(
Optional.of(
DirCacheEntry.builder()
.setMaxSizeBytes(Optional.of(42L))
.setCacheDir(cacheDir)
.setCacheReadMode(CacheReadMode.READONLY)
.build())));
}
@Test
public void testServedCacheMode() throws IOException {
Path cacheDir = tmpDir.getRoot();
ArtifactCacheBuckConfig config =
createFromText(
"[cache]",
"serve_local_cache = true",
"dir = " + cacheDir,
"served_local_cache_mode = readwrite");
assertThat(
config.getServedLocalCache(),
Matchers.equalTo(
Optional.of(
DirCacheEntry.builder()
.setMaxSizeBytes(Optional.empty())
.setCacheDir(cacheDir)
.setCacheReadMode(CacheReadMode.READWRITE)
.build())));
}
@Test
public void testExpandUserHomeCacheDir() throws IOException {
ArtifactCacheBuckConfig config = createFromText("[cache]", "dir = ~/cache_dir");
assertThat(
"User home cache directory must be expanded.",
config.getCacheEntries().getDirCacheEntries().stream().findFirst().get().getCacheDir(),
Matchers.equalTo(MorePaths.expandHomeDir(Paths.get("~/cache_dir"))));
}
@Test
public void testRepository() throws IOException {
ArtifactCacheBuckConfig config = createFromText("[cache]", "repository = some_repo");
assertThat(config.getRepository(), Matchers.equalTo("some_repo"));
ArtifactCacheBuckConfig defaultConfig = createFromText("[cache]");
assertThat(defaultConfig.getRepository(), Matchers.equalTo(""));
}
@Test
public void testScheduleType() throws IOException {
ArtifactCacheBuckConfig config = createFromText("[cache]", "schedule_type = master");
assertThat(config.getScheduleType(), Matchers.equalTo("master"));
ArtifactCacheBuckConfig defaultConfig = createFromText("[cache]");
assertThat(defaultConfig.getScheduleType(), Matchers.equalTo("none"));
}
@Test
public void errorMessageFormatter() throws IOException {
final String testText = "this is a test";
ArtifactCacheBuckConfig config =
createFromText("[cache]", "http_error_message_format = " + testText);
ImmutableSet<HttpCacheEntry> httpCacheEntries = config.getCacheEntries().getHttpCacheEntries();
HttpCacheEntry cache = FluentIterable.from(httpCacheEntries).get(0);
assertThat(cache.getErrorMessageFormat(), Matchers.equalTo(testText));
}
public static ArtifactCacheBuckConfig createFromText(String... lines) throws IOException {
ProjectFilesystem projectFilesystem = new FakeProjectFilesystem();
StringReader reader = new StringReader(Joiner.on('\n').join(lines));
return new ArtifactCacheBuckConfig(
BuckConfigTestUtils.createFromReader(
reader,
projectFilesystem,
Architecture.detect(),
Platform.detect(),
ImmutableMap.copyOf(System.getenv())));
}
}