/*
* 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.parser;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import com.facebook.buck.cli.BuckConfig;
import com.facebook.buck.cli.BuckConfigTestUtils;
import com.facebook.buck.cli.FakeBuckConfig;
import com.facebook.buck.io.ExecutableFinder;
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.WatchmanWatcher.CursorType;
import com.google.common.base.Joiner;
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.Reader;
import java.io.StringReader;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.hamcrest.Matchers;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
public class ParserConfigTest {
@Rule public TemporaryPaths temporaryFolder = new TemporaryPaths();
@Rule public ExpectedException thrown = ExpectedException.none();
@Test
public void testGetAllowEmptyGlobs() throws InterruptedException, IOException {
assertTrue(FakeBuckConfig.builder().build().getView(ParserConfig.class).getAllowEmptyGlobs());
Reader reader = new StringReader(Joiner.on('\n').join("[build]", "allow_empty_globs = false"));
ParserConfig config =
BuckConfigTestUtils.createWithDefaultFilesystem(temporaryFolder, reader)
.getView(ParserConfig.class);
assertFalse(config.getAllowEmptyGlobs());
}
@Test
public void testGetGlobHandler() throws InterruptedException, IOException {
assertThat(
FakeBuckConfig.builder().build().getView(ParserConfig.class).getGlobHandler(),
Matchers.equalTo(ParserConfig.GlobHandler.PYTHON));
for (ParserConfig.GlobHandler handler : ParserConfig.GlobHandler.values()) {
Reader reader =
new StringReader(
Joiner.on('\n').join("[project]", "glob_handler = " + handler.toString()));
ParserConfig config =
BuckConfigTestUtils.createWithDefaultFilesystem(temporaryFolder, reader)
.getView(ParserConfig.class);
assertThat(config.getGlobHandler(), Matchers.equalTo(handler));
}
}
@Test
public void testGetWatchCells() throws InterruptedException, IOException {
assertTrue(
"watch_cells defaults to true",
FakeBuckConfig.builder().build().getView(ParserConfig.class).getWatchCells());
Reader reader = new StringReader(Joiner.on('\n').join("[project]", "watch_cells = false"));
ParserConfig config =
BuckConfigTestUtils.createWithDefaultFilesystem(temporaryFolder, reader)
.getView(ParserConfig.class);
assertFalse(config.getWatchCells());
reader = new StringReader(Joiner.on('\n').join("[project]", "watch_cells = true"));
config =
BuckConfigTestUtils.createWithDefaultFilesystem(temporaryFolder, reader)
.getView(ParserConfig.class);
assertTrue(config.getWatchCells());
}
@Test
public void testGetWatchmanCursor() throws InterruptedException, IOException {
assertEquals(
"watchman_cursor defaults to clock_id",
CursorType.CLOCK_ID,
FakeBuckConfig.builder().build().getView(ParserConfig.class).getWatchmanCursor());
Reader reader = new StringReader(Joiner.on('\n').join("[project]", "watchman_cursor = named"));
ParserConfig config =
BuckConfigTestUtils.createWithDefaultFilesystem(temporaryFolder, reader)
.getView(ParserConfig.class);
assertEquals(CursorType.NAMED, config.getWatchmanCursor());
reader = new StringReader(Joiner.on('\n').join("[project]", "watchman_cursor = clock_id"));
config =
BuckConfigTestUtils.createWithDefaultFilesystem(temporaryFolder, reader)
.getView(ParserConfig.class);
assertEquals(CursorType.CLOCK_ID, config.getWatchmanCursor());
reader =
new StringReader(Joiner.on('\n').join("[project]", "watchman_cursor = some_trash_value"));
config =
BuckConfigTestUtils.createWithDefaultFilesystem(temporaryFolder, reader)
.getView(ParserConfig.class);
thrown.expect(HumanReadableException.class);
config.getWatchmanCursor();
}
@Test
public void shouldReturnThreadCountIfParallelParsingIsEnabled() {
BuckConfig config =
FakeBuckConfig.builder()
.setSections("[project]", "parsing_threads = 2", "parallel_parsing = true")
.build();
ParserConfig parserConfig = config.getView(ParserConfig.class);
assertTrue(parserConfig.getEnableParallelParsing());
assertEquals(2, parserConfig.getNumParsingThreads());
}
@Test
public void shouldReturnOneThreadCountIfParallelParsingIsNotEnabled() {
BuckConfig config =
FakeBuckConfig.builder()
.setSections("[project]", "parsing_threads = 3", "parallel_parsing = false")
.build();
ParserConfig parserConfig = config.getView(ParserConfig.class);
assertFalse(parserConfig.getEnableParallelParsing());
assertEquals(1, parserConfig.getNumParsingThreads());
}
@Test
public void shouldGetReadOnlyDirs() throws IOException {
String existingPath1 = "tmp/tmp-file";
String existingPath2 = "tmp2/tmp2-file";
ImmutableSet<Path> readOnlyPaths =
ImmutableSet.of(Paths.get(existingPath1), Paths.get(existingPath2));
ProjectFilesystem filesystem = new FakeProjectFilesystem(readOnlyPaths);
ParserConfig parserConfig =
FakeBuckConfig.builder()
.setSections("[project]", "read_only_paths = " + existingPath1 + "," + existingPath2)
.setFilesystem(filesystem)
.build()
.getView(ParserConfig.class);
assertTrue(parserConfig.getReadOnlyPaths().isPresent());
assertEquals(
parserConfig.getReadOnlyPaths().get(),
ImmutableList.of(
filesystem.resolve(Paths.get(existingPath1)),
filesystem.resolve(Paths.get(existingPath2))));
String notExistingDir = "not/existing/path";
parserConfig =
FakeBuckConfig.builder()
.setSections("[project]", "read_only_paths = " + notExistingDir)
.setFilesystem(filesystem)
.build()
.getView(ParserConfig.class);
thrown.expect(HumanReadableException.class);
parserConfig.getReadOnlyPaths();
}
@Test
public void testGetBuildFileImportWhitelist() throws InterruptedException, IOException {
assertTrue(
FakeBuckConfig.builder()
.build()
.getView(ParserConfig.class)
.getBuildFileImportWhitelist()
.isEmpty());
Reader reader =
new StringReader(
Joiner.on('\n').join("[project]", "build_file_import_whitelist = os, foo"));
ParserConfig config =
BuckConfigTestUtils.createWithDefaultFilesystem(temporaryFolder, reader)
.getView(ParserConfig.class);
assertEquals(ImmutableList.of("os", "foo"), config.getBuildFileImportWhitelist());
}
@Test
public void whenParserPythonIsExecutableFileThenItIsUsed() throws IOException {
Path configPythonFile = temporaryFolder.newExecutableFile("python");
ParserConfig parserConfig =
FakeBuckConfig.builder()
.setSections(
ImmutableMap.of(
"parser",
ImmutableMap.of(
"python_interpreter", configPythonFile.toAbsolutePath().toString())))
.build()
.getView(ParserConfig.class);
assertEquals(
"Should return path to temp file.",
configPythonFile.toAbsolutePath().toString(),
parserConfig.getPythonInterpreter(new ExecutableFinder()));
}
@Test(expected = HumanReadableException.class)
public void whenParserPythonDoesNotExistThenItIsNotUsed() throws IOException {
String invalidPath = temporaryFolder.getRoot().toAbsolutePath() + "DoesNotExist";
ParserConfig parserConfig =
FakeBuckConfig.builder()
.setSections(
ImmutableMap.of("parser", ImmutableMap.of("python_interpreter", invalidPath)))
.build()
.getView(ParserConfig.class);
parserConfig.getPythonInterpreter(new ExecutableFinder());
fail("Should throw exception as python config is invalid.");
}
@Test
public void whenParserPythonIsNotSetFallbackIsUsed() throws IOException {
Path configPythonFile = temporaryFolder.newExecutableFile("python");
// This sets the python.interpreter section, not parser.python_interpreter
ParserConfig parserConfig =
FakeBuckConfig.builder()
.setSections(
ImmutableMap.of(
"python",
ImmutableMap.of("interpreter", configPythonFile.toAbsolutePath().toString())))
.build()
.getView(ParserConfig.class);
assertEquals(
"Should return path to temp file.",
configPythonFile.toAbsolutePath().toString(),
parserConfig.getPythonInterpreter(new ExecutableFinder()));
}
@Test
public void whenParserPythonPathIsNotSetDefaultIsUsed() {
ParserConfig parserConfig = FakeBuckConfig.builder().build().getView(ParserConfig.class);
assertEquals(
"Should return an empty optional",
"<not set>",
parserConfig.getPythonModuleSearchPath().orElse("<not set>"));
}
@Test
public void whenParserPythonPathIsSet() {
ParserConfig parserConfig =
FakeBuckConfig.builder()
.setSections(
ImmutableMap.of("parser", ImmutableMap.of("python_path", "foobar:spamham")))
.build()
.getView(ParserConfig.class);
assertEquals(
"Should return the configured string",
"foobar:spamham",
parserConfig.getPythonModuleSearchPath().orElse("<not set>"));
}
}