From addf41bce1f26e8bc4bd0b09cb2fbffbb0446f25 Mon Sep 17 00:00:00 2001 From: Googler Date: Fri, 19 Jan 2024 14:14:53 -0800 Subject: [PATCH] Add a way to test StateMachine producers. PiperOrigin-RevId: 599934800 Change-Id: Ie03488c30a7e60e067e9345c839758ef030d510b --- .../google/devtools/build/lib/analysis/BUILD | 1 + .../build/lib/analysis/producers/BUILD | 36 ++++++ .../producers/PlatformInfoProducerTest.java | 110 ++++++++++++++++++ .../analysis/producers/ProducerTestCase.java | 53 +++++++++ 4 files changed, 200 insertions(+) create mode 100644 src/test/java/com/google/devtools/build/lib/analysis/producers/BUILD create mode 100644 src/test/java/com/google/devtools/build/lib/analysis/producers/PlatformInfoProducerTest.java create mode 100644 src/test/java/com/google/devtools/build/lib/analysis/producers/ProducerTestCase.java diff --git a/src/test/java/com/google/devtools/build/lib/analysis/BUILD b/src/test/java/com/google/devtools/build/lib/analysis/BUILD index 7da3a251cebbe7..b1aae6b4036051 100644 --- a/src/test/java/com/google/devtools/build/lib/analysis/BUILD +++ b/src/test/java/com/google/devtools/build/lib/analysis/BUILD @@ -14,6 +14,7 @@ filegroup( "//src/test/java/com/google/devtools/build/lib/analysis/extra:srcs", "//src/test/java/com/google/devtools/build/lib/analysis/mock:srcs", "//src/test/java/com/google/devtools/build/lib/analysis/platform:srcs", + "//src/test/java/com/google/devtools/build/lib/analysis/producers:srcs", "//src/test/java/com/google/devtools/build/lib/analysis/starlark/annotations/processor:srcs", "//src/test/java/com/google/devtools/build/lib/analysis/testing:srcs", "//src/test/java/com/google/devtools/build/lib/analysis/util:srcs", diff --git a/src/test/java/com/google/devtools/build/lib/analysis/producers/BUILD b/src/test/java/com/google/devtools/build/lib/analysis/producers/BUILD new file mode 100644 index 00000000000000..eac53e8c7bae76 --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/analysis/producers/BUILD @@ -0,0 +1,36 @@ +load("@rules_java//java:defs.bzl", "java_test") + +package( + default_applicable_licenses = ["//:license"], + default_testonly = 1, + default_visibility = ["//src:__subpackages__"], +) + +filegroup( + name = "srcs", + testonly = 0, + srcs = glob(["*"]), + visibility = ["//src:__subpackages__"], +) + +java_test( + name = "ProducersTests", + srcs = glob(["*.java"]), + test_class = "com.google.devtools.build.lib.AllTests", + runtime_deps = [ + "//src/test/java/com/google/devtools/build/lib:test_runner", + ], + deps = [ + "//src/main/java/com/google/devtools/build/lib/analysis/platform", + "//src/main/java/com/google/devtools/build/lib/analysis/producers", + "//src/main/java/com/google/devtools/build/lib/cmdline", + "//src/main/java/com/google/devtools/build/lib/skyframe:skyframe_cluster", + "//src/main/java/com/google/devtools/build/lib/skyframe/toolchains:platform_lookup_util", + "//src/main/java/com/google/devtools/build/skyframe", + "//src/main/java/com/google/devtools/build/skyframe:skyframe-objects", + "//src/test/java/com/google/devtools/build/lib/analysis/util", + "//third_party:jsr305", + "//third_party:junit4", + "//third_party:truth", + ], +) diff --git a/src/test/java/com/google/devtools/build/lib/analysis/producers/PlatformInfoProducerTest.java b/src/test/java/com/google/devtools/build/lib/analysis/producers/PlatformInfoProducerTest.java new file mode 100644 index 00000000000000..b2228d8a76703b --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/analysis/producers/PlatformInfoProducerTest.java @@ -0,0 +1,110 @@ +// Copyright 2024 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.analysis.producers; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertThrows; + +import com.google.devtools.build.lib.analysis.platform.PlatformInfo; +import com.google.devtools.build.lib.cmdline.Label; +import com.google.devtools.build.lib.skyframe.toolchains.PlatformLookupUtil.InvalidPlatformException; +import com.google.devtools.build.skyframe.state.StateMachine; +import javax.annotation.Nullable; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests of {@link PlatformInfoProducer}. */ +@RunWith(JUnit4.class) +public class PlatformInfoProducerTest extends ProducerTestCase { + @Test + public void infoLookup() throws Exception { + scratch.overwriteFile( + "lookup/BUILD", + "constraint_setting(name = 'setting1')", + "constraint_value(name = 'value1', constraint_setting = ':setting1')", + "platform(", + " name = 'basic',", + " constraint_values = [':value1'],", + ")"); + + Label platformLabel = Label.parseCanonicalUnchecked("//lookup:basic"); + PlatformInfo result = fetch(platformLabel); + + assertThat(result).isNotNull(); + assertThat(result.label()).isEqualTo(platformLabel); + } + + @Test + public void infoLookup_alias() throws Exception { + scratch.overwriteFile( + "lookup/BUILD", + "constraint_setting(name = 'setting1')", + "constraint_value(name = 'value1', constraint_setting = ':setting1')", + "platform(", + " name = 'basic',", + " constraint_values = [':value1'],", + ")", + "alias(name = 'alias', actual = ':basic')"); + + Label platformLabel = Label.parseCanonicalUnchecked("//lookup:alias"); + PlatformInfo result = fetch(platformLabel); + + assertThat(result).isNotNull(); + assertThat(result.label()).isEqualTo(Label.parseCanonicalUnchecked("//lookup:basic")); + } + + @Test + public void infoLookup_error() throws Exception { + scratch.overwriteFile("lookup/BUILD", "filegroup(", " name = 'basic',", ")"); + + Label platformLabel = Label.parseCanonicalUnchecked("//lookup:basic"); + assertThrows(InvalidPlatformException.class, () -> fetch(platformLabel)); + } + + private PlatformInfo fetch(Label platformLabel) + throws InvalidPlatformException, InterruptedException { + PlatformInfoSink sink = new PlatformInfoSink(); + PlatformInfoProducer producer = + new PlatformInfoProducer(platformLabel, sink, StateMachine.DONE); + assertThat(executeProducer(producer)).isTrue(); + return sink.platformInfo(); + } + + /** Receiver for platform info from {@link PlatformInfoProducer}. */ + private static class PlatformInfoSink implements PlatformInfoProducer.ResultSink { + @Nullable private PlatformInfo platformInfo = null; + @Nullable private InvalidPlatformException platformInfoError = null; + + @Override + public void acceptPlatformInfo(PlatformInfo info) { + this.platformInfo = info; + } + + @Override + public void acceptPlatformInfoError(InvalidPlatformException error) { + this.platformInfoError = error; + } + + PlatformInfo platformInfo() throws InvalidPlatformException { + if (this.platformInfoError != null) { + throw this.platformInfoError; + } + if (this.platformInfo != null) { + return platformInfo; + } + throw new IllegalStateException("Value and exception not set"); + } + } +} diff --git a/src/test/java/com/google/devtools/build/lib/analysis/producers/ProducerTestCase.java b/src/test/java/com/google/devtools/build/lib/analysis/producers/ProducerTestCase.java new file mode 100644 index 00000000000000..2748f3ecdccfa2 --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/analysis/producers/ProducerTestCase.java @@ -0,0 +1,53 @@ +// Copyright 2024 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.analysis.producers; + +import com.google.devtools.build.lib.analysis.util.BuildViewTestCase; +import com.google.devtools.build.lib.skyframe.SkyframeExecutor; +import com.google.devtools.build.skyframe.EvaluationContext; +import com.google.devtools.build.skyframe.EvaluationResult; +import com.google.devtools.build.skyframe.SkyValue; +import com.google.devtools.build.skyframe.state.StateMachine; +import com.google.devtools.build.skyframe.state.StateMachineEvaluatorForTesting; + +/** Base class for tests of producers. */ +public abstract class ProducerTestCase extends BuildViewTestCase { + /** + * Use a {@link StateMachineEvaluatorForTesting} to drive the given {@link StateMachine} until it + * finishes (with a result or an error). Results should be retrieved from whatever result sink the + * {@link StateMachine} is designed for. + * + * @return {@code true} on success + */ + public boolean executeProducer(StateMachine producer) throws InterruptedException { + EvaluationContext context = + EvaluationContext.newBuilder() + .setKeepGoing(true) + .setParallelism(SkyframeExecutor.DEFAULT_THREAD_COUNT) + .setEventHandler(reporter) + .build(); + try { + getSkyframeExecutor().getSkyframeBuildView().enableAnalysis(true); + EvaluationResult result = + StateMachineEvaluatorForTesting.run( + producer, getSkyframeExecutor().getEvaluator(), context); + if (result != null) { + return !result.hasError(); + } + } finally { + getSkyframeExecutor().getSkyframeBuildView().enableAnalysis(false); + } + return true; + } +}