Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@

### Added

* Nothing yet
* Added support for testing actions created in an aspect, via
`util.make_testing_aspect` and `analysis_test`'s `testing_aspect` parameter.

### Removed

Expand Down
2 changes: 2 additions & 0 deletions lib/private/analysis_test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ def analysis_test(
attr_values = {},
fragments = [],
config_settings = {},
testing_aspect = testing_aspect,
extra_target_under_test_aspects = [],
provider_subject_factories = []):
"""Creates an analysis test from its implementation function.
Expand Down Expand Up @@ -213,6 +214,7 @@ def analysis_test(
--platforms flag), it's suggested to always explicitly call `Label()`
on the value before passing it in. This ensures the label is resolved
in your repository's context, not rule_testing's.
testing_aspect: An optional override of testing_aspect. See `util.make_testing_aspect`.
extra_target_under_test_aspects: An optional list of aspects to apply to the target_under_test
in addition to those set up by default for the test harness itself.
provider_subject_factories: Optional list of ProviderSubjectFactory structs,
Expand Down
26 changes: 20 additions & 6 deletions lib/private/expect.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -244,13 +244,27 @@ def _expect_that_target(self, target):
Returns:
[`TargetSubject`] object.
"""
format_str_kwargs = {
"name": target.label.name,
"package": target.label.package,
}
expr = "target({})".format(target.label)
details = ["target: {}".format(target.label)]
if TestingAspectInfo in target:
format_str_kwargs["bindir"] = target[TestingAspectInfo].bin_path
if target[TestingAspectInfo].required_aspects:
expr = "aspect({aspects} over {target})".format(
aspects = ", ".join(target[TestingAspectInfo].required_aspects),
target = target.label,
)
details.extend([
"aspect: {}".format(aspect)
for aspect in target[TestingAspectInfo].required_aspects
])
return TargetSubject.new(target, self.meta.derive(
expr = "target({})".format(target.label),
details = ["target: {}".format(target.label)],
format_str_kwargs = {
"name": target.label.name,
"package": target.label.package,
} | {"bindir": target[TestingAspectInfo].bin_path} if TestingAspectInfo in target else {},
expr = expr,
details = details,
format_str_kwargs = format_str_kwargs,
))

def _expect_that_value(self, value, *, factory, expr = "value"):
Expand Down
20 changes: 20 additions & 0 deletions lib/util.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ TestingAspectInfo = provider(
"actions": "The actions registered for the target under test.",
"vars": "The var dict (ctx.var) for the target under text.",
"bin_path": "str; the ctx.bin_dir.path value (aka execroot).",
"required_aspects": "list[str]: aspects applied over this target",
},
)

Expand All @@ -170,13 +171,31 @@ def _testing_aspect_impl(target, ctx):
actions = target.actions,
vars = ctx.var,
bin_path = ctx.bin_dir.path,
required_aspects = ctx.aspect_ids[:-1],
)]

# TODO(ilist): make private, after switching python tests to new testing framework
testing_aspect = aspect(
implementation = _testing_aspect_impl,
)

def _make_testing_aspect(aspects = []):
"""Makes a testing_aspect

Use when you need to test actions created by aspect. Pass
the returned aspect to analysis_test as `testing_aspect`.

Args:
aspects: a list of aspects to apply testing aspect over.

Returns:
custom testing aspect
"""
return aspect(
implementation = _testing_aspect_impl,
requires = aspects,
)

def get_target_attrs(env):
return analysistest.target_under_test(env)[TestingAspectInfo].attrs

Expand Down Expand Up @@ -253,6 +272,7 @@ util = struct(
empty_file = empty_file,
force_exec_config = force_exec_config,
helper_target = helper_target,
make_testing_aspect = _make_testing_aspect,
merge_kwargs = merge_kwargs,
runfiles_map = runfiles_map,
runfiles_paths = runfiles_paths,
Expand Down
39 changes: 38 additions & 1 deletion tests/analysis_test_tests.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
load("//lib:analysis_test.bzl", "analysis_test", "test_suite")
load("//lib:truth.bzl", "matching")
load("//lib:util.bzl", "TestingAspectInfo")
load("//lib:util.bzl", "TestingAspectInfo", "util")

_TestingFlagsInfo = provider(
doc = "Flags used for testing",
Expand Down Expand Up @@ -223,6 +223,42 @@ def test_inspect_aspect(name):
def _test_inspect_aspect(env, target):
env.expect.that_str(target[_AddedByAspectInfo].value).equals("attached by aspect")

####################################
####### inspect_aspect_actions_test #######
####################################
def _inspect_actions_fake_aspect_impl(_target, ctx):
out_file = ctx.actions.declare_file("aspect_out.txt")
ctx.actions.run_shell(
command = "echo 'hello' > %s" % out_file.basename,
outputs = [out_file],
mnemonic = "RunningHello",
)
return []

_inspect_actions_fake_aspect = aspect(
implementation = _inspect_actions_fake_aspect_impl,
)

_inspect_actions_fake_aspect_testing_aspect = util.make_testing_aspect(
aspects = [_inspect_actions_fake_aspect],
)

def test_inspect_aspect_actions(name):
"""Test verifying actions registered by an aspect."""
native.filegroup(name = name + "_subject")

analysis_test(
name = name,
target = name + "_subject",
impl = _test_inspect_aspect_actions,
testing_aspect = _inspect_actions_fake_aspect_testing_aspect,
)

def _test_inspect_aspect_actions(env, target):
env.expect.that_int(len(target[TestingAspectInfo].actions)).equals(1)
action_output = target[TestingAspectInfo].actions[0].outputs.to_list()[0]
env.expect.that_str(action_output.basename).equals("aspect_out.txt")

########################################
####### inspect_output_dirs_test #######
########################################
Expand Down Expand Up @@ -449,5 +485,6 @@ def analysis_test_test_suite(name):
test_change_setting_with_failure,
test_inspect_actions,
test_inspect_aspect,
test_inspect_aspect_actions,
],
)
2 changes: 1 addition & 1 deletion tests/truth_tests.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -1240,7 +1240,7 @@ def _runfiles_subject_test(env, target):
"expected to contain: does-not-exist",
"actual default runfiles:",
"default_runfile1.txt",
"target: ".format(target.label),
"target: {}".format(target.label),
],
env = env,
msg = "check contains",
Expand Down