Skip to content

Commit 42a3dbb

Browse files
authored
Move analysis_test into testing.analysis_test (bazelbuild#16702)
* Move analysis_test into testing.analysis_test Exporting it on a toplevel makes it impossible to override its name without a workaround. A temporary workaround is provided that should be in place until this is released in Bazel 3.6. RELNOTES[INC]: analysis_test moved into testing.analysis_test PiperOrigin-RevId: 471806624 Change-Id: I13bd1f5b38e5fb538d4c046952b9db7b82b3f31a * Passing useToolchainResolution to make it compatible with Bazel 5.x.x
1 parent bcaa566 commit 42a3dbb

File tree

9 files changed

+222
-168
lines changed

9 files changed

+222
-168
lines changed

src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleClassFunctions.java

+47-78
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@
100100
import com.google.errorprone.annotations.FormatMethod;
101101
import java.util.Collection;
102102
import java.util.Map;
103-
import java.util.regex.Pattern;
103+
import java.util.Objects;
104104
import javax.annotation.Nullable;
105105
import net.starlark.java.eval.Debug;
106106
import net.starlark.java.eval.Dict;
@@ -112,7 +112,6 @@
112112
import net.starlark.java.eval.StarlarkCallable;
113113
import net.starlark.java.eval.StarlarkFunction;
114114
import net.starlark.java.eval.StarlarkInt;
115-
import net.starlark.java.eval.StarlarkList;
116115
import net.starlark.java.eval.StarlarkThread;
117116
import net.starlark.java.eval.Tuple;
118117
import net.starlark.java.syntax.Identifier;
@@ -140,7 +139,6 @@ public Label load(String from) throws Exception {
140139
}
141140
}
142141
});
143-
private static final Pattern RULE_NAME_PATTERN = Pattern.compile("[A-Za-z_][A-Za-z0-9_]*");
144142

145143
// TODO(bazel-team): Remove the code duplication (BaseRuleClasses and this class).
146144
/** Parent rule class for non-executable non-test Starlark rules. */
@@ -308,6 +306,51 @@ public StarlarkRuleFunction rule(
308306
Object name,
309307
StarlarkThread thread)
310308
throws EvalException {
309+
return createRule(
310+
implementation,
311+
test,
312+
attrs,
313+
implicitOutputs,
314+
executable,
315+
outputToGenfiles,
316+
fragments,
317+
hostFragments,
318+
starlarkTestable,
319+
toolchains,
320+
useToolchainTransition,
321+
providesArg,
322+
execCompatibleWith,
323+
analysisTest,
324+
buildSetting,
325+
cfg,
326+
execGroups,
327+
compileOneFiletype,
328+
name,
329+
thread);
330+
}
331+
332+
public static StarlarkRuleFunction createRule(
333+
StarlarkFunction implementation,
334+
boolean test,
335+
Object attrs,
336+
Object implicitOutputs,
337+
boolean executable,
338+
boolean outputToGenfiles,
339+
Sequence<?> fragments,
340+
Sequence<?> hostFragments,
341+
boolean starlarkTestable,
342+
Sequence<?> toolchains,
343+
boolean useToolchainTransition,
344+
Sequence<?> providesArg,
345+
Sequence<?> execCompatibleWith,
346+
Object analysisTest,
347+
Object buildSetting,
348+
Object cfg,
349+
Object execGroups,
350+
Object compileOneFiletype,
351+
Object name,
352+
StarlarkThread thread)
353+
throws EvalException {
311354
BazelStarlarkContext bazelContext = BazelStarlarkContext.from(thread);
312355
bazelContext.checkLoadingOrWorkspacePhase("rule");
313356
// analysis_test=true implies test=true.
@@ -510,81 +553,6 @@ public StarlarkRuleFunction rule(
510553
return starlarkRuleFunction;
511554
}
512555

513-
@Override
514-
public void analysisTest(
515-
String name,
516-
StarlarkFunction implementation,
517-
Object attrs,
518-
Sequence<?> fragments,
519-
Sequence<?> toolchains,
520-
Object attrValuesApi,
521-
StarlarkThread thread)
522-
throws EvalException, InterruptedException {
523-
if (!RULE_NAME_PATTERN.matcher(name).matches()) {
524-
throw Starlark.errorf("'name' is limited to Starlark identifiers, got %s", name);
525-
}
526-
Dict<String, Object> attrValues =
527-
Dict.cast(attrValuesApi, String.class, Object.class, "attr_values");
528-
if (attrValues.containsKey("name")) {
529-
throw Starlark.errorf("'name' cannot be set or overridden in 'attr_values'");
530-
}
531-
532-
StarlarkRuleFunction starlarkRuleFunction =
533-
rule(
534-
implementation,
535-
/*test=*/ true,
536-
attrs,
537-
/*implicitOutputs=*/ Starlark.NONE,
538-
/*executable=*/ false,
539-
/*outputToGenfiles=*/ false,
540-
/*fragments=*/ fragments,
541-
/*hostFragments=*/ StarlarkList.empty(),
542-
/*starlarkTestable=*/ false,
543-
/*toolchains=*/ toolchains,
544-
/*useToolchainTransition=*/ false,
545-
/*doc=*/ "",
546-
/*providesArg=*/ StarlarkList.empty(),
547-
/*execCompatibleWith=*/ StarlarkList.empty(),
548-
/*analysisTest=*/ Boolean.TRUE,
549-
/*buildSetting=*/ Starlark.NONE,
550-
/*cfg=*/ Starlark.NONE,
551-
/*execGroups=*/ Starlark.NONE,
552-
/*compileOneFiletype=*/ Starlark.NONE,
553-
/*name=*/ Starlark.NONE,
554-
thread);
555-
556-
// Export the rule
557-
// Because exporting can raise multiple errors, we need to accumulate them here into a single
558-
// EvalException. This is a code smell because any non-ERROR events will be lost, and any
559-
// location information in the events will be overwritten by the location of this rule's
560-
// definition.
561-
// However, this is currently fine because StarlarkRuleFunction#export only creates events that
562-
// are ERRORs and that have the rule definition as their location.
563-
// TODO(brandjon): Instead of accumulating events here, consider registering the rule in the
564-
// BazelStarlarkContext, and exporting such rules after module evaluation in
565-
// BzlLoadFunction#execAndExport.
566-
PackageContext pkgContext = thread.getThreadLocal(PackageContext.class);
567-
StoredEventHandler handler = new StoredEventHandler();
568-
starlarkRuleFunction.export(
569-
handler, pkgContext.getLabel(), name + "_test"); // export in BUILD thread
570-
if (handler.hasErrors()) {
571-
StringBuilder errors =
572-
handler.getEvents().stream()
573-
.filter(e -> e.getKind() == EventKind.ERROR)
574-
.reduce(
575-
new StringBuilder(),
576-
(sb, ev) -> sb.append("\n").append(ev.getMessage()),
577-
StringBuilder::append);
578-
throw Starlark.errorf("Errors in exporting %s: %s", name, errors.toString());
579-
}
580-
581-
// Instantiate the target
582-
Dict.Builder<String, Object> args = Dict.builder();
583-
args.put("name", name);
584-
args.putAll(attrValues);
585-
starlarkRuleFunction.call(thread, Tuple.of(), args.buildImmutable());
586-
}
587-
588556
/**
589557
* Returns the module (file) of the outermost enclosing Starlark function on the call stack or
590558
* null if none of the active calls are functions defined in Starlark.
@@ -1002,6 +970,7 @@ private void errorf(EventHandler handler, String format, Object... args) {
1002970
handler.handle(Event.error(definitionLocation, String.format(format, args)));
1003971
}
1004972

973+
@Override
1005974
public RuleClass getRuleClass() {
1006975
Preconditions.checkState(ruleClass != null && builder == null);
1007976
return ruleClass;

src/main/java/com/google/devtools/build/lib/rules/BUILD

+1
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ java_library(
131131
"//src/main/java/com/google/devtools/build/lib/analysis:transitive_info_collection",
132132
"//src/main/java/com/google/devtools/build/lib/analysis:transitive_info_provider",
133133
"//src/main/java/com/google/devtools/build/lib/concurrent",
134+
"//src/main/java/com/google/devtools/build/lib/events",
134135
"//src/main/java/com/google/devtools/build/lib/packages",
135136
"//src/main/java/com/google/devtools/build/lib/starlarkbuildapi/test",
136137
"//src/main/java/com/google/devtools/build/lib/util",

src/main/java/com/google/devtools/build/lib/rules/config/ConfigGlobalLibrary.java

+1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ public ConfigurationTransitionApi transition(
6868
moduleContext.repoMapping());
6969
}
7070

71+
// TODO(b/237422931): move into testing module
7172
@Override
7273
public ConfigurationTransitionApi analysisTestTransition(
7374
Dict<?, ?> changedSettings, // <String, String> expected

src/main/java/com/google/devtools/build/lib/rules/test/StarlarkTestingModule.java

+85
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,26 @@
1414
package com.google.devtools.build.lib.rules.test;
1515

1616
import com.google.devtools.build.lib.analysis.RunEnvironmentInfo;
17+
import com.google.devtools.build.lib.analysis.starlark.StarlarkRuleClassFunctions;
18+
import com.google.devtools.build.lib.analysis.starlark.StarlarkRuleClassFunctions.StarlarkRuleFunction;
1719
import com.google.devtools.build.lib.analysis.test.ExecutionInfo;
20+
import com.google.devtools.build.lib.events.EventKind;
21+
import com.google.devtools.build.lib.events.StoredEventHandler;
22+
import com.google.devtools.build.lib.packages.PackageFactory.PackageContext;
1823
import com.google.devtools.build.lib.starlarkbuildapi.test.TestingModuleApi;
24+
import java.util.regex.Pattern;
1925
import net.starlark.java.eval.Dict;
2026
import net.starlark.java.eval.EvalException;
2127
import net.starlark.java.eval.Sequence;
28+
import net.starlark.java.eval.Starlark;
29+
import net.starlark.java.eval.StarlarkFunction;
2230
import net.starlark.java.eval.StarlarkList;
31+
import net.starlark.java.eval.StarlarkThread;
32+
import net.starlark.java.eval.Tuple;
2333

2434
/** A class that exposes testing infrastructure to Starlark. */
2535
public class StarlarkTestingModule implements TestingModuleApi {
36+
private static final Pattern RULE_NAME_PATTERN = Pattern.compile("[A-Za-z_][A-Za-z0-9_]*");
2637

2738
@Override
2839
public ExecutionInfo executionInfo(Dict<?, ?> requirements /* <String, String> */)
@@ -41,4 +52,78 @@ public RunEnvironmentInfo testEnvironment(
4152
Sequence.cast(inheritedEnvironment, String.class, "inherited_environment")),
4253
/* shouldErrorOnNonExecutableRule */ false);
4354
}
55+
56+
@Override
57+
public void analysisTest(
58+
String name,
59+
StarlarkFunction implementation,
60+
Object attrs,
61+
Sequence<?> fragments,
62+
Sequence<?> toolchains,
63+
Object attrValuesApi,
64+
StarlarkThread thread)
65+
throws EvalException, InterruptedException {
66+
if (!RULE_NAME_PATTERN.matcher(name).matches()) {
67+
throw Starlark.errorf("'name' is limited to Starlark identifiers, got %s", name);
68+
}
69+
Dict<String, Object> attrValues =
70+
Dict.cast(attrValuesApi, String.class, Object.class, "attr_values");
71+
if (attrValues.containsKey("name")) {
72+
throw Starlark.errorf("'name' cannot be set or overridden in 'attr_values'");
73+
}
74+
75+
StarlarkRuleFunction starlarkRuleFunction =
76+
StarlarkRuleClassFunctions.createRule(
77+
implementation,
78+
/*test=*/ true,
79+
attrs,
80+
/*implicitOutputs=*/ Starlark.NONE,
81+
/*executable=*/ false,
82+
/*outputToGenfiles=*/ false,
83+
/*fragments=*/ fragments,
84+
/*hostFragments=*/ StarlarkList.empty(),
85+
/*starlarkTestable=*/ false,
86+
/*toolchains=*/ toolchains,
87+
/*useToolchainTransition=*/ false,
88+
/*providesArg=*/ StarlarkList.empty(),
89+
/*execCompatibleWith=*/ StarlarkList.empty(),
90+
/*analysisTest=*/ Boolean.TRUE,
91+
/*buildSetting=*/ Starlark.NONE,
92+
/*cfg=*/ Starlark.NONE,
93+
/*execGroups=*/ Starlark.NONE,
94+
/*compileOneFiletype=*/ Starlark.NONE,
95+
/*name=*/ Starlark.NONE,
96+
thread);
97+
98+
// Export the rule
99+
// Because exporting can raise multiple errors, we need to accumulate them here into a single
100+
// EvalException. This is a code smell because any non-ERROR events will be lost, and any
101+
// location information in the events will be overwritten by the location of this rule's
102+
// definition.
103+
// However, this is currently fine because StarlarkRuleFunction#export only creates events that
104+
// are ERRORs and that have the rule definition as their location.
105+
// TODO(brandjon): Instead of accumulating events here, consider registering the rule in the
106+
// BazelStarlarkContext, and exporting such rules after module evaluation in
107+
// BzlLoadFunction#execAndExport.
108+
PackageContext pkgContext = thread.getThreadLocal(PackageContext.class);
109+
StoredEventHandler handler = new StoredEventHandler();
110+
starlarkRuleFunction.export(
111+
handler, pkgContext.getLabel(), name + "_test"); // export in BUILD thread
112+
if (handler.hasErrors()) {
113+
StringBuilder errors =
114+
handler.getEvents().stream()
115+
.filter(e -> e.getKind() == EventKind.ERROR)
116+
.reduce(
117+
new StringBuilder(),
118+
(sb, ev) -> sb.append("\n").append(ev.getMessage()),
119+
StringBuilder::append);
120+
throw Starlark.errorf("Errors in exporting %s: %s", name, errors.toString());
121+
}
122+
123+
// Instantiate the target
124+
Dict.Builder<String, Object> args = Dict.builder();
125+
args.put("name", name);
126+
args.putAll(attrValues);
127+
starlarkRuleFunction.call(thread, Tuple.of(), args.buildImmutable());
128+
}
44129
}

src/main/java/com/google/devtools/build/lib/starlarkbuildapi/StarlarkRuleFunctionsApi.java

-71
Original file line numberDiff line numberDiff line change
@@ -397,77 +397,6 @@ StarlarkCallable rule(
397397
StarlarkThread thread)
398398
throws EvalException;
399399

400-
@StarlarkMethod(
401-
name = "analysis_test",
402-
doc =
403-
"Creates a new analysis test target. <p>The number of transitive dependencies of the test"
404-
+ " are limited. The limit is controlled by"
405-
+ " <code>--analysis_testing_deps_limit</code> flag.",
406-
parameters = {
407-
@Param(
408-
name = "name",
409-
named = true,
410-
doc =
411-
"Name of the target. It should be a Starlark identifier, matching pattern"
412-
+ " '[A-Za-z_][A-Za-z0-9_]*'."),
413-
@Param(
414-
name = "implementation",
415-
named = true,
416-
doc =
417-
"The Starlark function implementing this analysis test. It must have exactly one"
418-
+ " parameter: <a href=\"ctx.html\">ctx</a>. The function is called during the"
419-
+ " analysis phase. It can access the attributes declared by <code>attrs</code>"
420-
+ " and populated via <code>attr_values</code>. The implementation function may"
421-
+ " not register actions. Instead, it must register a pass/fail result"
422-
+ " via providing <a"
423-
+ " href='AnalysisTestResultInfo.html'>AnalysisTestResultInfo</a>."),
424-
@Param(
425-
name = "attrs",
426-
allowedTypes = {
427-
@ParamType(type = Dict.class),
428-
@ParamType(type = NoneType.class),
429-
},
430-
named = true,
431-
defaultValue = "None",
432-
doc =
433-
"Dictionary declaring the attributes. See the <a href=\"rule.html\">rule</a> call."
434-
+ "Attributes are allowed to use configuration transitions defined using <a "
435-
+ " href=\"#analysis_test_transition\">analysis_test_transition</a>."),
436-
@Param(
437-
name = "fragments",
438-
allowedTypes = {@ParamType(type = Sequence.class, generic1 = String.class)},
439-
named = true,
440-
defaultValue = "[]",
441-
doc =
442-
"List of configuration fragments that are available to the implementation of the"
443-
+ " analysis test."),
444-
@Param(
445-
name = TOOLCHAINS_PARAM,
446-
allowedTypes = {@ParamType(type = Sequence.class, generic1 = Object.class)},
447-
named = true,
448-
defaultValue = "[]",
449-
doc =
450-
"The set of toolchains the test requires. See the <a href=\"#rule\">rule</a>"
451-
+ " call."),
452-
@Param(
453-
name = "attr_values",
454-
allowedTypes = {@ParamType(type = Dict.class, generic1 = String.class)},
455-
named = true,
456-
defaultValue = "{}",
457-
doc = "Dictionary of attribute values to pass to the implementation."),
458-
},
459-
useStarlarkThread = true,
460-
enableOnlyWithFlag = BuildLanguageOptions.EXPERIMENTAL_ANALYSIS_TEST_CALL)
461-
void analysisTest(
462-
String name,
463-
StarlarkFunction implementation,
464-
Object attrs,
465-
Sequence<?> fragments,
466-
Sequence<?> toolchains,
467-
Object argsValue,
468-
StarlarkThread thread)
469-
throws EvalException, InterruptedException;
470-
471400
@StarlarkMethod(
472401
name = "aspect",
473402
doc =

src/main/java/com/google/devtools/build/lib/starlarkbuildapi/test/BUILD

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ java_library(
2525
# TODO(b/80307387): Remove dependency on Label implementation.
2626
"//src/main/java/com/google/devtools/build/lib/cmdline",
2727
"//src/main/java/com/google/devtools/build/lib/collect/nestedset",
28+
"//src/main/java/com/google/devtools/build/lib/packages/semantics",
2829
"//src/main/java/com/google/devtools/build/lib/starlarkbuildapi/core",
2930
"//src/main/java/com/google/devtools/build/lib/starlarkbuildapi/platform",
3031
"//src/main/java/net/starlark/java/annot",

0 commit comments

Comments
 (0)