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 @@ -6,7 +6,8 @@

### Changed

* Nothing yet
* `TargetSubject.provider()` and `TargetSubject.has_provider()` accept a
`provider_name` for better error messaging.

### Added

Expand Down
21 changes: 12 additions & 9 deletions lib/private/target_subject.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -175,19 +175,20 @@ def _target_subject_failures(self):
failure_messages = []
return CollectionSubject.new(failure_messages, meta, container_name = "failure messages")

def _target_subject_has_provider(self, provider):
def _target_subject_has_provider(self, provider, provider_name = "<Unknown provider>"):
"""Asserts that the target as provider `provider`.

Method: TargetSubject.has_provider

Args:
self: implicitly added.
provider: The provider object to check for.
provider_name: The display name of the provider
"""
if self.meta.has_provider(self.target, provider):
return
self.meta.add_failure(
"expected to have provider: {}".format(_provider_subject_factory(self, provider).name),
"expected to have provider: {}".format(_provider_subject_factory(self, provider, provider_name).name),
"but provider was not found",
)

Expand Down Expand Up @@ -221,7 +222,7 @@ def _target_subject_output_group(self, name):
meta = self.meta.derive("output_group({})".format(name)),
)

def _target_subject_provider(self, provider_key, factory = None):
def _target_subject_provider(self, provider_key, factory = None, provider_name = "<Unknown provider>"):
"""Returns a subject for a provider in the target.

Method: TargetSubject.provider
Expand All @@ -235,20 +236,22 @@ def _target_subject_provider(self, provider_key, factory = None):
signature: `def factory(value, /, *, meta)`.
Additional types of providers can be pre-registered by using the
`provider_subject_factories` arg of `analysis_test`.
provider_name: The display name of the provider. This must be supplied
separately because str(provider_key) just returns "<provider>",
which isn't helpful. For lack of a better option, this defaults to
<Unknown provider>.

Returns:
A subject wrapper of the provider value.
"""
if factory:
provider_subject_factory = struct(
type = provider_key,
# str(provider_key) just returns "<provider>", which isn't helpful.
# For lack of a better option, just call it unknown
name = "<Unknown provider>",
name = provider_name,
factory = factory,
)
else:
provider_subject_factory = _provider_subject_factory(self, provider_key)
provider_subject_factory = _provider_subject_factory(self, provider_key, provider_name)

if not provider_subject_factory.factory:
fail("Unsupported provider: {}".format(provider_subject_factory.name))
Expand Down Expand Up @@ -392,14 +395,14 @@ def _target_subject_attr(self, name, *, factory = None):
meta = self.meta.derive("attr({})".format(name)),
)

def _provider_subject_factory(self, provider):
def _provider_subject_factory(self, provider, provider_name = "<Unknown provider>"):
for provider_subject_factory in self.meta.env.provider_subject_factories:
if provider_subject_factory.type == provider:
return provider_subject_factory

return struct(
type = provider,
name = "<Unknown provider>",
name = provider_name,
factory = None,
)

Expand Down
59 changes: 59 additions & 0 deletions tests/truth_tests.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,62 @@ def _action_subject_test(env, target):

_suite.append(action_subject_test)

def provider_subject_test(name):
analysis_test(name = name, impl = _provider_subject_test, target = "truth_tests_helper")

_UnusedInfo = provider("unused testing provider", fields = [])

def _provider_subject_test(env, target):
fake_env = _fake_env(env)
fake_env.expect.that_target(target).has_provider(_UnusedInfo)
_assert_failure(
fake_env,
["expected to have provider: <Unknown provider>"],
env = env,
msg = "check has_provider() failure uses Unknown provider name",
)

fake_env.expect.that_target(target).has_provider(_UnusedInfo, provider_name = "MyInfo")
_assert_failure(
fake_env,
["expected to have provider: MyInfo"],
env = env,
msg = "check has_provider() failure uses supplied provider name",
)

def _factory(_unused, meta):
return struct(
always_fails = lambda: meta.add_failure("Expected error msg", "Actual error msg"),
)

fake_env.expect.that_target(target).provider(_TestHelperInfo, _factory).always_fails()
_assert_failure(
fake_env,
[
".provider(<Unknown provider>)",
"Expected error msg",
"Actual error msg",
],
env = env,
msg = "check has_provider() failure uses Unknown provider name",
)

fake_env.expect.that_target(target).provider(_TestHelperInfo, _factory, provider_name = "MyInfo").always_fails()
_assert_failure(
fake_env,
[
".provider(MyInfo)",
"Expected error msg",
"Actual error msg",
],
env = env,
msg = "check provider() failure uses supplied provider name",
)

_end(env, fake_env)

_suite.append(provider_subject_test)

def bool_subject_test(name):
analysis_test(name = name, impl = _bool_subject_test, target = "truth_tests_helper")

Expand Down Expand Up @@ -1589,6 +1645,8 @@ def _assert_failure(fake_env, expected_strs, *, env, msg = ""):

fake_env.reset()

_TestHelperInfo = provider("empty provider for testing", fields = [])

def _test_helper_impl(ctx):
action_output = ctx.actions.declare_file("action.txt")
generated_input = _empty_file(ctx, "input.gen.txt")
Expand Down Expand Up @@ -1627,6 +1685,7 @@ def _test_helper_impl(ctx):
OutputGroupInfo(
some_group = depset([_empty_file(ctx, "output_group_file.txt")]),
),
_TestHelperInfo(),
]

test_helper = rule(
Expand Down