blob: 7373c2d3d50edbbff2c4ca07b02f6fc9f3cd3d07 [file] [log] [blame]
// Copyright 2015 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.skyframe;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
import com.google.devtools.build.lib.actions.ActionKeyContext;
import com.google.devtools.build.lib.actions.ActionLookupKey;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.FileValue;
import com.google.devtools.build.lib.actions.ThreadStateReceiver;
import com.google.devtools.build.lib.actions.util.InjectedActionLookupKey;
import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.analysis.ServerDirectories;
import com.google.devtools.build.lib.clock.BlazeClock;
import com.google.devtools.build.lib.packages.WorkspaceFileValue;
import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
import com.google.devtools.build.lib.skyframe.ExternalFilesHelper.ExternalFileAction;
import com.google.devtools.build.lib.skyframe.PackageFunction.GlobbingStrategy;
import com.google.devtools.build.lib.skyframe.PackageLookupFunction.CrossRepositoryLabelViolationStrategy;
import com.google.devtools.build.lib.testutil.TestConstants;
import com.google.devtools.build.lib.testutil.TestPackageFactoryBuilderFactory;
import com.google.devtools.build.lib.testutil.TestRuleClassProvider;
import com.google.devtools.build.lib.testutil.TestUtils;
import com.google.devtools.build.lib.util.io.TimestampGranularityMonitor;
import com.google.devtools.build.lib.vfs.DigestHashFunction;
import com.google.devtools.build.lib.vfs.FileStateKey;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.Root;
import com.google.devtools.build.lib.vfs.SyscallCache;
import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
import com.google.devtools.build.skyframe.InMemoryMemoizingEvaluator;
import com.google.devtools.build.skyframe.MemoizingEvaluator;
import com.google.devtools.build.skyframe.RecordingDifferencer;
import com.google.devtools.build.skyframe.SequencedRecordingDifferencer;
import com.google.devtools.build.skyframe.SkyFunction;
import com.google.devtools.build.skyframe.SkyFunctionException;
import com.google.devtools.build.skyframe.SkyFunctionName;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import java.io.IOException;
import java.util.LinkedHashSet;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.Before;
abstract class ArtifactFunctionTestCase {
static final ActionLookupKey ALL_OWNER = new InjectedActionLookupKey("all_owner");
protected LinkedHashSet<ActionAnalysisMetadata> actions;
protected boolean fastDigest = false;
protected RecordingDifferencer differencer = new SequencedRecordingDifferencer();
protected MemoizingEvaluator evaluator;
protected Path root;
protected Path middlemanPath;
protected final ActionKeyContext actionKeyContext = new ActionKeyContext();
/**
* The test action execution function. The Skyframe evaluator's action execution function
* delegates to this one.
*/
protected SkyFunction delegateActionExecutionFunction;
@Before
public void baseSetUp() throws Exception {
CustomInMemoryFs fs = new CustomInMemoryFs();
setupRoot(fs);
AtomicReference<PathPackageLocator> pkgLocator =
new AtomicReference<>(
new PathPackageLocator(
root.getFileSystem().getPath("/outputbase"),
ImmutableList.of(Root.fromPath(root)),
BazelSkyframeExecutorConstants.BUILD_FILES_BY_PRIORITY));
BlazeDirectories directories =
new BlazeDirectories(
new ServerDirectories(root, root, root),
root,
/* defaultSystemJavabase= */ null,
TestConstants.PRODUCT_NAME);
ExternalFilesHelper externalFilesHelper =
ExternalFilesHelper.createForTesting(
pkgLocator,
ExternalFileAction.DEPEND_ON_EXTERNAL_PKG_FOR_EXTERNAL_REPO_PATHS,
directories);
differencer = new SequencedRecordingDifferencer();
evaluator =
new InMemoryMemoizingEvaluator(
ImmutableMap.<SkyFunctionName, SkyFunction>builder()
.put(
FileStateKey.FILE_STATE,
new FileStateFunction(
Suppliers.ofInstance(
new TimestampGranularityMonitor(BlazeClock.instance())),
SyscallCache.NO_CACHE,
externalFilesHelper))
.put(FileValue.FILE, new FileFunction(pkgLocator, directories))
.put(
Artifact.ARTIFACT,
new ArtifactFunction(
() -> true, MetadataConsumerForMetrics.NO_OP, SyscallCache.NO_CACHE))
.put(SkyFunctions.ACTION_EXECUTION, new SimpleActionExecutionFunction())
.put(
SkyFunctions.PACKAGE,
new PackageFunction(
null,
null,
null,
null,
null,
/*packageProgress=*/ null,
PackageFunction.ActionOnIOExceptionReadingBuildFile.UseOriginalIOException
.INSTANCE,
GlobbingStrategy.SKYFRAME_HYBRID,
k -> ThreadStateReceiver.NULL_INSTANCE))
.put(
SkyFunctions.PACKAGE_LOOKUP,
new PackageLookupFunction(
null,
CrossRepositoryLabelViolationStrategy.ERROR,
BazelSkyframeExecutorConstants.BUILD_FILES_BY_PRIORITY,
BazelSkyframeExecutorConstants.EXTERNAL_PACKAGE_HELPER))
.put(
WorkspaceFileValue.WORKSPACE_FILE,
new WorkspaceFileFunction(
TestRuleClassProvider.getRuleClassProvider(),
TestPackageFactoryBuilderFactory.getInstance()
.builder(directories)
.build(TestRuleClassProvider.getRuleClassProvider(), fs),
directories,
/*bzlLoadFunctionForInlining=*/ null))
.put(
SkyFunctions.EXTERNAL_PACKAGE,
new ExternalPackageFunction(
BazelSkyframeExecutorConstants.EXTERNAL_PACKAGE_HELPER))
.put(
SkyFunctions.ACTION_TEMPLATE_EXPANSION,
new ActionTemplateExpansionFunction(actionKeyContext))
.build(),
differencer);
PrecomputedValue.BUILD_ID.set(differencer, UUID.randomUUID());
PrecomputedValue.PATH_PACKAGE_LOCATOR.set(differencer, pkgLocator.get());
actions = new LinkedHashSet<>();
}
protected void setupRoot(CustomInMemoryFs fs) throws IOException {
Path tmpDir = fs.getPath(TestUtils.tmpDir());
root = tmpDir.getChild("root");
root.createDirectoryAndParents();
FileSystemUtils.createEmptyFile(root.getRelative("WORKSPACE"));
middlemanPath = tmpDir.getChild("middlemanRoot");
middlemanPath.createDirectoryAndParents();
}
protected static void writeFile(Path path, String contents) throws IOException {
path.getParentDirectory().createDirectoryAndParents();
FileSystemUtils.writeContentAsLatin1(path, contents);
}
/** ActionExecutionFunction that delegates to our delegate. */
private class SimpleActionExecutionFunction implements SkyFunction {
@Override
public SkyValue compute(SkyKey skyKey, Environment env)
throws SkyFunctionException, InterruptedException {
return delegateActionExecutionFunction.compute(skyKey, env);
}
@Override
public String extractTag(SkyKey skyKey) {
return delegateActionExecutionFunction.extractTag(skyKey);
}
}
/** InMemoryFileSystem that can pretend to do a fast digest. */
protected class CustomInMemoryFs extends InMemoryFileSystem {
CustomInMemoryFs() {
super(DigestHashFunction.SHA256);
}
@Override
@SuppressWarnings("UnsynchronizedOverridesSynchronized")
protected byte[] getFastDigest(PathFragment path) throws IOException {
return fastDigest ? getDigest(path) : null;
}
}
}