/*
* Copyright 2017-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.distributed;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import com.facebook.buck.cli.BuckConfig;
import com.facebook.buck.cli.FakeBuckConfig;
import com.facebook.buck.distributed.thrift.BuildJobState;
import com.facebook.buck.distributed.thrift.BuildJobStateFileHashEntry;
import com.facebook.buck.distributed.thrift.BuildJobStateFileHashes;
import com.facebook.buck.event.BuckEventBusFactory;
import com.facebook.buck.event.listener.BroadcastEventListener;
import com.facebook.buck.io.MorePaths;
import com.facebook.buck.io.ProjectFilesystem;
import com.facebook.buck.model.BuildTargetFactory;
import com.facebook.buck.parser.Parser;
import com.facebook.buck.parser.ParserConfig;
import com.facebook.buck.rules.ActionGraphAndResolver;
import com.facebook.buck.rules.ActionGraphCache;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.Cell;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.rules.SourcePathRuleFinder;
import com.facebook.buck.rules.TargetGraph;
import com.facebook.buck.rules.TestCellBuilder;
import com.facebook.buck.rules.coercer.ConstructorArgMarshaller;
import com.facebook.buck.rules.coercer.DefaultTypeCoercerFactory;
import com.facebook.buck.rules.coercer.TypeCoercerFactory;
import com.facebook.buck.testutil.integration.ProjectWorkspace;
import com.facebook.buck.testutil.integration.TemporaryPaths;
import com.facebook.buck.testutil.integration.TestDataHelper;
import com.facebook.buck.util.cache.DefaultFileHashCache;
import com.facebook.buck.util.cache.ProjectFileHashCache;
import com.facebook.buck.util.cache.StackedFileHashCache;
import com.facebook.buck.util.environment.Platform;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.MoreExecutors;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import org.junit.Assume;
import org.junit.Rule;
import org.junit.Test;
public class DistBuildFileHashesIntegrationTest {
private static final String SYMLINK_FILE_NAME = "SymlinkSourceFile.java";
private static final int KEY_SEED = 0;
@Rule public TemporaryPaths temporaryFolder = new TemporaryPaths();
@Test
public void symlinkPathsRecordedInRootCell() throws Exception {
Assume.assumeTrue(Platform.detect() != Platform.WINDOWS);
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "symlink", temporaryFolder);
workspace.setUp();
ProjectFilesystem rootFs =
new ProjectFilesystem(temporaryFolder.getRoot().toAbsolutePath().resolve("root_cell"));
Path absSymlinkFilePath = rootFs.resolve("../" + SYMLINK_FILE_NAME);
Path symLinkPath = rootFs.resolve(SYMLINK_FILE_NAME);
rootFs.createSymLink(symLinkPath, absSymlinkFilePath, false);
BuckConfig rootCellConfig = FakeBuckConfig.builder().setFilesystem(rootFs).build();
Cell rootCell =
new TestCellBuilder().setBuckConfig(rootCellConfig).setFilesystem(rootFs).build();
TypeCoercerFactory typeCoercerFactory = new DefaultTypeCoercerFactory();
ConstructorArgMarshaller constructorArgMarshaller =
new ConstructorArgMarshaller(typeCoercerFactory);
Parser parser =
new Parser(
new BroadcastEventListener(),
rootCellConfig.getView(ParserConfig.class),
typeCoercerFactory,
constructorArgMarshaller);
TargetGraph targetGraph =
parser.buildTargetGraph(
BuckEventBusFactory.newInstance(),
rootCell,
/* enableProfiling */ false,
MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()),
ImmutableSet.of(BuildTargetFactory.newInstance(rootFs.getRootPath(), "//:libA")));
DistBuildTargetGraphCodec targetGraphCodec =
DistBuildStateTest.createDefaultCodec(rootCell, Optional.of(parser));
BuildJobState dump =
DistBuildState.dump(
new DistBuildCellIndexer(rootCell),
createDistBuildFileHashes(targetGraph, rootCell),
targetGraphCodec,
targetGraph,
ImmutableSet.of(BuildTargetFactory.newInstance(rootFs.getRootPath(), "//:libA")));
assertNotNull(dump);
assertEquals(1, dump.getFileHashesSize());
BuildJobStateFileHashes rootCellHashes = dump.getFileHashes().get(0);
assertEquals(2, rootCellHashes.getEntriesSize());
BuildJobStateFileHashEntry symLinkEntry =
rootCellHashes.getEntries().stream().filter(x -> x.isSetRootSymLink()).findFirst().get();
String expectedPath =
temporaryFolder.getRoot().resolve(SYMLINK_FILE_NAME).toAbsolutePath().toString();
assertEquals(
MorePaths.pathWithUnixSeparators(expectedPath),
symLinkEntry.getRootSymLinkTarget().getPath());
assertEquals(SYMLINK_FILE_NAME, symLinkEntry.getRootSymLink().getPath());
BuildJobStateFileHashEntry relPathEntry =
rootCellHashes.getEntries().stream().filter(x -> !x.isPathIsAbsolute()).findFirst().get();
assertEquals("A.java", relPathEntry.getPath().getPath());
}
@Test
public void crossCellDoesNotCauseAbsolutePathSrcs() throws Exception {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "cross_cell", temporaryFolder);
workspace.setUp();
ProjectFilesystem rootFs =
new ProjectFilesystem(temporaryFolder.getRoot().toAbsolutePath().resolve("root_cell"));
ProjectFilesystem secondaryFs =
new ProjectFilesystem(temporaryFolder.getRoot().toAbsolutePath().resolve("secondary_cell"));
BuckConfig rootCellConfig =
FakeBuckConfig.builder()
.setFilesystem(rootFs)
.setSections(
"[repositories]",
"cross_cell_secondary = " + secondaryFs.getRootPath().toAbsolutePath())
.build();
Cell rootCell =
new TestCellBuilder().setBuckConfig(rootCellConfig).setFilesystem(rootFs).build();
TypeCoercerFactory typeCoercerFactory = new DefaultTypeCoercerFactory();
ConstructorArgMarshaller constructorArgMarshaller =
new ConstructorArgMarshaller(typeCoercerFactory);
Parser parser =
new Parser(
new BroadcastEventListener(),
rootCellConfig.getView(ParserConfig.class),
typeCoercerFactory,
constructorArgMarshaller);
TargetGraph targetGraph =
parser.buildTargetGraph(
BuckEventBusFactory.newInstance(),
rootCell,
/* enableProfiling */ false,
MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()),
ImmutableSet.of(BuildTargetFactory.newInstance(rootFs.getRootPath(), "//:libA")));
DistBuildTargetGraphCodec targetGraphCodec =
DistBuildStateTest.createDefaultCodec(rootCell, Optional.of(parser));
BuildJobState dump =
DistBuildState.dump(
new DistBuildCellIndexer(rootCell),
createDistBuildFileHashes(targetGraph, rootCell),
targetGraphCodec,
targetGraph,
ImmutableSet.of(BuildTargetFactory.newInstance(rootFs.getRootPath(), "//:libA")));
assertNotNull(dump);
assertEquals(2, dump.getFileHashesSize());
List<BuildJobStateFileHashes> sortedHashes =
dump.getFileHashes()
.stream()
.sorted(Comparator.comparingInt(BuildJobStateFileHashes::getCellIndex))
.collect(Collectors.toList());
BuildJobStateFileHashes rootCellHashes = sortedHashes.get(0);
assertEquals(1, rootCellHashes.getEntriesSize());
assertEquals("A.java", rootCellHashes.getEntries().get(0).getPath().getPath());
BuildJobStateFileHashes secondaryCellHashes = sortedHashes.get(1);
assertEquals(1, secondaryCellHashes.getEntriesSize());
assertEquals("B.java", secondaryCellHashes.getEntries().get(0).getPath().getPath());
}
private DistBuildFileHashes createDistBuildFileHashes(TargetGraph targetGraph, Cell rootCell)
throws InterruptedException, IOException {
ActionGraphCache cache = new ActionGraphCache(new BroadcastEventListener());
ActionGraphAndResolver actionGraphAndResolver =
cache.getActionGraph(BuckEventBusFactory.newInstance(), true, false, targetGraph, KEY_SEED);
BuildRuleResolver ruleResolver = actionGraphAndResolver.getResolver();
SourcePathRuleFinder ruleFinder = new SourcePathRuleFinder(ruleResolver);
SourcePathResolver sourcePathResolver = new SourcePathResolver(ruleFinder);
DistBuildCellIndexer cellIndexer = new DistBuildCellIndexer(rootCell);
ImmutableList.Builder<ProjectFileHashCache> allCaches = ImmutableList.builder();
allCaches.add(DefaultFileHashCache.createDefaultFileHashCache(rootCell.getFilesystem()));
for (Path cellPath : rootCell.getKnownRoots()) {
Cell cell = rootCell.getCell(cellPath);
allCaches.add(DefaultFileHashCache.createDefaultFileHashCache(cell.getFilesystem()));
}
allCaches.addAll(DefaultFileHashCache.createOsRootDirectoriesCaches());
StackedFileHashCache stackedCache = new StackedFileHashCache(allCaches.build());
return new DistBuildFileHashes(
actionGraphAndResolver.getActionGraph(),
sourcePathResolver,
ruleFinder,
stackedCache,
cellIndexer,
MoreExecutors.newDirectExecutorService(),
/* keySeed */ KEY_SEED,
rootCell);
}
}