1# Copyright 2022 Google LLC. All rights reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the License); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15"""kt_testing_rules""" 16 17load("//:visibility.bzl", "RULES_KOTLIN") 18load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") 19load(":analysis.bzl", "kt_analysis") 20 21visibility(RULES_KOTLIN) 22 23# Mark targets that's aren't expected to build, but are needed for analysis test assertions. 24_ONLY_FOR_ANALYSIS_TAGS = ["manual", "nobuilder", "notap"] 25 26def _wrap_for_analysis(inner_rule): 27 """Wrap an existing rule to make it easier to use in analysis tests. 28 29 Args: 30 inner_rule: [rule|macro] 31 32 Returns: 33 [macro] Calls inner_rule with appropate tags, returning the target name 34 """ 35 36 def wrapper(name, tags = [], **kwargs): 37 inner_rule( 38 name = name, 39 tags = tags + _ONLY_FOR_ANALYSIS_TAGS, 40 **kwargs 41 ) 42 return name 43 44 return wrapper 45 46_assert_failure_test = analysistest.make( 47 impl = lambda ctx: _assert_failure_test_impl(ctx), 48 expect_failure = True, 49 attrs = dict( 50 msg_contains = attr.string(mandatory = True), 51 ), 52) 53 54def _assert_failure_test_impl(ctx): 55 kt_analysis.check_endswith_test(ctx) 56 57 env = analysistest.begin(ctx) 58 asserts.expect_failure(env, ctx.attr.msg_contains) 59 return analysistest.end(env) 60 61_coverage_instrumentation_test = analysistest.make( 62 impl = lambda ctx: _coverage_instrumentation_test_impl(ctx), 63 attrs = dict( 64 expected_instrumented_file_names = attr.string_list(), 65 ), 66 config_settings = { 67 "//command_line_option:collect_code_coverage": "1", 68 "//command_line_option:instrument_test_targets": "1", 69 "//command_line_option:instrumentation_filter": "+", 70 }, 71) 72 73def _coverage_instrumentation_test_impl(ctx): 74 env = analysistest.begin(ctx) 75 target_under_test = analysistest.target_under_test(env) 76 instrumented_files_info = target_under_test[InstrumentedFilesInfo] 77 instrumented_files = instrumented_files_info.instrumented_files.to_list() 78 asserts.equals( 79 env, 80 ctx.attr.expected_instrumented_file_names, 81 [file.basename for file in instrumented_files], 82 ) 83 return analysistest.end(env) 84 85def _create_file(name, content = ""): 86 """Declare a generated file with optional content. 87 88 Args: 89 name: [string] The relative file path 90 content: [string] 91 92 Returns: 93 [File] The label of the file 94 """ 95 96 if content.startswith("\n"): 97 content = content[1:-1] 98 99 native.genrule( 100 name = "gen_" + name, 101 outs = [name], 102 cmd = """ 103cat > $@ <<EOF 104%s 105EOF 106""" % content, 107 ) 108 109 return name 110 111_create_dir = rule( 112 implementation = lambda ctx: _create_dir_impl(ctx), 113 attrs = dict( 114 subdir = attr.string(), 115 srcs = attr.label_list(allow_files = True), 116 ), 117) 118 119def _create_dir_impl(ctx): 120 dir = ctx.actions.declare_directory(ctx.attr.name) 121 122 command = "mkdir -p {0} " + ("&& cp {1} {0}" if ctx.files.srcs else "# {1}") 123 ctx.actions.run_shell( 124 command = command.format( 125 dir.path + "/" + ctx.attr.subdir, 126 " ".join([s.path for s in ctx.files.srcs]), 127 ), 128 inputs = ctx.files.srcs, 129 outputs = [dir], 130 ) 131 132 return [DefaultInfo(files = depset([dir]))] 133 134kt_testing_rules = struct( 135 # go/keep-sorted start 136 ONLY_FOR_ANALYSIS_TAGS = _ONLY_FOR_ANALYSIS_TAGS, 137 assert_failure_test = _assert_failure_test, 138 coverage_instrumentation_test = _coverage_instrumentation_test, 139 create_dir = _wrap_for_analysis(_create_dir), 140 create_file = _create_file, 141 wrap_for_analysis = _wrap_for_analysis, 142 # go/keep-sorted end 143) 144