blob: 2f326a012a783cbba655cee7990904eaf1dd1e46 [file] [log] [blame]
# Copyright 2019 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.
"""Unit tests for unittest.bzl."""
load("//lib:partial.bzl", "partial")
load("//lib:unittest.bzl", "analysistest", "asserts", "loadingtest", "unittest")
###################################
####### basic_failing_test ########
###################################
def _basic_failing_test(ctx):
"""Unit tests for a basic library verification test that fails."""
env = unittest.begin(ctx)
asserts.equals(env, 1, 2)
return unittest.end(env)
basic_failing_test = unittest.make(_basic_failing_test)
###################################
####### failure_message_test ######
###################################
def _failure_message_test(ctx):
"""Failing unit test with arbitrary content in the message."""
env = unittest.begin(ctx)
if not ctx.attr.message:
unittest.fail(env, "Message must be non-empty.")
asserts.equals(env, "", ctx.attr.message)
return unittest.end(env)
failure_message_test = unittest.make(
_failure_message_test,
attrs = {
"message": attr.string(),
},
)
###################################
####### basic_passing_test ########
###################################
def _basic_passing_test(ctx):
"""Unit tests for a basic library verification test."""
env = unittest.begin(ctx)
asserts.equals(env, 1, 1)
return unittest.end(env)
basic_passing_test = unittest.make(_basic_passing_test)
#################################################
####### basic_passing_short_timeout_test ########
#################################################
def _basic_passing_short_timeout_test(ctx):
"""Unit tests for a basic library verification test."""
env = unittest.begin(ctx)
asserts.equals(env, ctx.attr.timeout, "short")
return unittest.end(env)
basic_passing_short_timeout_test = unittest.make(_basic_passing_short_timeout_test)
###################################
####### change_setting_test #######
###################################
def _change_setting_test(ctx):
"""Test to verify that an analysis test may change configuration."""
env = analysistest.begin(ctx)
dep_min_os_version = analysistest.target_under_test(env)[_ChangeSettingInfo].min_os_version
asserts.equals(env, "1234.5678", dep_min_os_version)
return analysistest.end(env)
_ChangeSettingInfo = provider(
doc = "min_os_version for change_setting_test",
fields = ["min_os_version"],
)
def _change_setting_fake_rule(ctx):
return [_ChangeSettingInfo(min_os_version = ctx.fragments.cpp.minimum_os_version())]
change_setting_fake_rule = rule(
implementation = _change_setting_fake_rule,
fragments = ["cpp"],
)
change_setting_test = analysistest.make(
_change_setting_test,
config_settings = {
"//command_line_option:minimum_os_version": "1234.5678",
},
)
####################################
####### failure_testing_test #######
####################################
def _failure_testing_test(ctx):
"""Test to verify that an analysis test may verify a rule fails with fail()."""
env = analysistest.begin(ctx)
asserts.expect_failure(env, "This rule should never work")
return analysistest.end(env)
def _failure_testing_fake_rule(ctx):
_ignore = [ctx] # @unused
fail("This rule should never work")
failure_testing_fake_rule = rule(
implementation = _failure_testing_fake_rule,
)
failure_testing_test = analysistest.make(
_failure_testing_test,
expect_failure = True,
)
############################################
####### fail_unexpected_passing_test #######
############################################
def _fail_unexpected_passing_test(ctx):
"""Test that fails by expecting an error that never occurs."""
env = analysistest.begin(ctx)
asserts.expect_failure(env, "Oh no, going to fail")
return analysistest.end(env)
def _fail_unexpected_passing_fake_rule(ctx):
_ignore = [ctx] # @unused
return []
fail_unexpected_passing_fake_rule = rule(
implementation = _fail_unexpected_passing_fake_rule,
)
fail_unexpected_passing_test = analysistest.make(
_fail_unexpected_passing_test,
expect_failure = True,
)
################################################
####### change_setting_with_failure_test #######
################################################
def _change_setting_with_failure_test(ctx):
"""Test verifying failure while changing configuration."""
env = analysistest.begin(ctx)
asserts.expect_failure(env, "unexpected minimum_os_version!!!")
return analysistest.end(env)
def _change_setting_with_failure_fake_rule(ctx):
if ctx.fragments.cpp.minimum_os_version() == "error_error":
fail("unexpected minimum_os_version!!!")
return []
change_setting_with_failure_fake_rule = rule(
implementation = _change_setting_with_failure_fake_rule,
fragments = ["cpp"],
)
change_setting_with_failure_test = analysistest.make(
_change_setting_with_failure_test,
expect_failure = True,
config_settings = {
"//command_line_option:minimum_os_version": "error_error",
},
)
####################################
####### inspect_actions_test #######
####################################
def _inspect_actions_test(ctx):
"""Test verifying actions registered by a target."""
env = analysistest.begin(ctx)
actions = analysistest.target_actions(env)
asserts.equals(env, 1, len(actions))
action_output = actions[0].outputs.to_list()[0]
asserts.equals(env, "out.txt", action_output.basename)
return analysistest.end(env)
def _inspect_actions_fake_rule(ctx):
out_file = ctx.actions.declare_file("out.txt")
ctx.actions.run_shell(
command = "echo 'hello' > %s" % out_file.basename,
outputs = [out_file],
)
return [DefaultInfo(files = depset([out_file]))]
inspect_actions_fake_rule = rule(
implementation = _inspect_actions_fake_rule,
)
inspect_actions_test = analysistest.make(
_inspect_actions_test,
)
####################################
####### inspect_aspect_test #######
####################################
_AddedByAspectInfo = provider(
doc = "Example provider added by example aspect",
fields = {
"value": "(str)",
},
)
def _example_aspect_impl(target, ctx):
_ignore = [target, ctx] # @unused
return [
_AddedByAspectInfo(value = "attached by aspect"),
]
example_aspect = aspect(
implementation = _example_aspect_impl,
)
def _inspect_aspect_test(ctx):
"""Test verifying aspect run on a target."""
env = analysistest.begin(ctx)
tut = env.ctx.attr.target_under_test
asserts.equals(env, "attached by aspect", tut[_AddedByAspectInfo].value)
return analysistest.end(env)
def _inspect_aspect_fake_rule(ctx):
out_file = ctx.actions.declare_file("out.txt")
ctx.actions.run_shell(
command = "echo 'hello' > %s" % out_file.basename,
outputs = [out_file],
)
return [DefaultInfo(files = depset([out_file]))]
inspect_aspect_fake_rule = rule(
implementation = _inspect_aspect_fake_rule,
)
inspect_aspect_test = analysistest.make(
_inspect_aspect_test,
extra_target_under_test_aspects = [example_aspect],
)
########################################
####### inspect_output_dirs_test #######
########################################
_OutputDirInfo = provider(
doc = "bin_path for inspect_output_dirs_test",
fields = ["bin_path"],
)
def _inspect_output_dirs_test(ctx):
"""Test verifying output directories used by a test."""
env = analysistest.begin(ctx)
# Assert that the output bin dir observed by the aspect added by analysistest
# is the same as those observed by the rule directly, even when that's
# under a config transition and therefore not the same as the bin dir
# used by the test rule.
bin_path = analysistest.target_bin_dir_path(env)
target_under_test = analysistest.target_under_test(env)
asserts.false(env, not bin_path, "bin dir path not found.")
asserts.false(
env,
bin_path == ctx.bin_dir.path,
"test bin dir (%s) expected to differ with target_under_test bin dir (%s)." % (bin_path, ctx.bin_dir.path),
)
asserts.equals(env, bin_path, target_under_test[_OutputDirInfo].bin_path)
return analysistest.end(env)
def _inspect_output_dirs_fake_rule(ctx):
return [
_OutputDirInfo(
bin_path = ctx.bin_dir.path,
),
]
inspect_output_dirs_fake_rule = rule(
implementation = _inspect_output_dirs_fake_rule,
)
inspect_output_dirs_test = analysistest.make(
_inspect_output_dirs_test,
# The output directories differ between the test and target under test when
# the target under test is under a config transition.
config_settings = {
"//command_line_option:minimum_os_version": "1234.5678",
},
)
def _loading_phase_test(env):
loadingtest.equals(env, "self_glob", ["unittest_tests.bzl"], native.glob(["unittest_tests.bzl"]))
# now use our own calls to assert we created a test case rule and test_suite for it.
loadingtest.equals(env, "test_exists", True, native.existing_rule(env.name + "_self_glob") != None)
loadingtest.equals(env, "suite_exists", True, native.existing_rule(env.name + "_tests") != None)
#########################################
# buildifier: disable=unnamed-macro
def unittest_passing_tests_suite():
"""Creates the test targets and test suite for passing unittest.bzl tests.
Not all tests are included. Some unittest.bzl tests verify a test fails
when assertions are not met. Such tests must be run in an e2e shell test.
This suite only includes tests which verify success tests.
"""
unittest.suite(
"unittest_tests",
basic_passing_test,
partial.make(basic_passing_short_timeout_test, timeout = "short"),
)
change_setting_test(
name = "change_setting_test",
target_under_test = ":change_setting_fake_target",
)
change_setting_fake_rule(
name = "change_setting_fake_target",
tags = ["manual"],
)
failure_testing_test(
name = "failure_testing_test",
target_under_test = ":failure_testing_fake_target",
)
failure_testing_fake_rule(
name = "failure_testing_fake_target",
tags = ["manual"],
)
change_setting_with_failure_test(
name = "change_setting_with_failure_test",
target_under_test = ":change_setting_with_failure_fake_target",
)
change_setting_with_failure_fake_rule(
name = "change_setting_with_failure_fake_target",
tags = ["manual"],
)
inspect_actions_test(
name = "inspect_actions_test",
target_under_test = ":inspect_actions_fake_target",
)
inspect_actions_fake_rule(
name = "inspect_actions_fake_target",
tags = ["manual"],
)
inspect_aspect_test(
name = "inspect_aspect_test",
target_under_test = ":inspect_aspect_fake_target",
)
inspect_aspect_fake_rule(
name = "inspect_aspect_fake_target",
tags = ["manual"],
)
inspect_output_dirs_test(
name = "inspect_output_dirs_test",
target_under_test = ":inspect_output_dirs_fake_target",
)
inspect_output_dirs_fake_rule(
name = "inspect_output_dirs_fake_target",
tags = ["manual"],
)
loading_env = loadingtest.make("selftest")
_loading_phase_test(loading_env)