| # 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) |