diff options
author | nickreid <nickreid@google.com> | 2023-10-09 12:09:21 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2023-10-09 12:10:03 -0700 |
commit | b3b689f3fb5d2428a37574e3e8f34398765b02a6 (patch) | |
tree | 167bb24fd900166214f75583107e9c3081bd813b | |
parent | 53879a257620503971d5474b61581aa8749fd9c3 (diff) | |
download | bazelbuild-kotlin-rules-b3b689f3fb5d2428a37574e3e8f34398765b02a6.tar.gz |
Add kt_asserts for common testing assertions.
PiperOrigin-RevId: 572005221
-rw-r--r-- | kotlin/common/testing/BUILD | 35 | ||||
-rw-r--r-- | kotlin/common/testing/asserts.bzl | 114 | ||||
-rw-r--r-- | tests/analysis/jvm_library_test.bzl | 29 |
3 files changed, 160 insertions, 18 deletions
diff --git a/kotlin/common/testing/BUILD b/kotlin/common/testing/BUILD new file mode 100644 index 0000000..b7755de --- /dev/null +++ b/kotlin/common/testing/BUILD @@ -0,0 +1,35 @@ +# Copyright 2022 Google LLC. 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. + +load("@bazel_skylib//:bzl_library.bzl", "bzl_library") + +package( + default_applicable_licenses = ["//:license"], + default_testonly = True, + default_visibility = ["//:internal"], +) + +licenses(["notice"]) + +bzl_library( + name = "testing_bzl", + srcs = glob(["*.bzl"]), + visibility = [ + "//:internal", + ], + deps = [ + "//:visibility_bzl", + "@bazel_skylib//lib:unittest", + ], +) diff --git a/kotlin/common/testing/asserts.bzl b/kotlin/common/testing/asserts.bzl new file mode 100644 index 0000000..b064eb7 --- /dev/null +++ b/kotlin/common/testing/asserts.bzl @@ -0,0 +1,114 @@ +# Copyright 2022 Google LLC. 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. + +"""kt_asserts""" + +load("//:visibility.bzl", "RULES_KOTLIN") +load("@bazel_skylib//lib:unittest.bzl", "asserts") + +def _equals(a, b): + return a == b + +def _list_matching(left, right, matcher = None): + """Find the overlap between two lists. + + Args: + left: [list[A]] + right: [list[B]] + matcher: [function(A,B):bool] A matcher on the two list types + + Returns: + [(list[A], list[(A, B)], list[B])] The left-only, matching-pair, and right-only lists + """ + + matcher = matcher or _equals + + left_only = [] + matches = [] + right_only = list(right) + + def _process_left_ele(left_ele): + for index, right_ele in enumerate(right_only): + if matcher(left_ele, right_ele): + right_only.pop(index) + matches.append((left_ele, right_ele)) + return + + left_only.append(left_ele) + + for left_ele in left: + _process_left_ele(left_ele) + + return (left_only, matches, right_only) + +def _assert_list_matches(env, expected, actual, matcher = None, items_name = "items"): + """Assert two lists have an exact matching. + + Args: + env: [unittest.env] + expected: [list[A]] + actual: [list[B]] + matcher: [function(A,B):bool] + items_name: [string] The plural noun describing the list items in an error message + + Returns: + [None] Fails if assertion violated + """ + + extra_expected, _, extra_actual = _list_matching(expected, actual, matcher = matcher) + asserts.true( + env, + len(extra_actual) == 0 and len(extra_expected) == 0, + "Unmatched expected {name} {expected}\nUnmatched actual {name} {actual}".format( + name = items_name, + expected = extra_expected, + actual = extra_actual, + ), + ) + +def _assert_required_mnemonic_counts(env, required_mnemonic_counts, actual_actions): + """Assert that some set of menemonics is present/absent within a set of Actions. + + Args: + env: [unittest.env] + required_mnemonic_counts: [dict[string,string]] The menemonics to check -> expected count + actual_actions: [list[Action]] + + Returns: + [None] Fails if assertion violated + """ + + considered_actual_mnemonics = [ + x.mnemonic + for x in actual_actions + # Ignore any mnemonics not mentioned by the user + if (x.mnemonic in required_mnemonic_counts) + ] + + required_mnemonics = [] + for m, c in required_mnemonic_counts.items(): + for _ in range(0, int(c)): + required_mnemonics.append(m) + + _assert_list_matches( + env, + required_mnemonics, + considered_actual_mnemonics, + items_name = "mnemonics", + ) + +kt_asserts = struct( + list_matches = _assert_list_matches, + required_mnemonic_counts = _assert_required_mnemonic_counts, +) diff --git a/tests/analysis/jvm_library_test.bzl b/tests/analysis/jvm_library_test.bzl index c72aff0..e9d9330 100644 --- a/tests/analysis/jvm_library_test.bzl +++ b/tests/analysis/jvm_library_test.bzl @@ -16,6 +16,7 @@ load("//:visibility.bzl", "RULES_KOTLIN") load("//kotlin:jvm_library.bzl", "kt_jvm_library") +load("//kotlin/common/testing:asserts.bzl", "kt_asserts") load("//tests/analysis:util.bzl", "ONLY_FOR_ANALYSIS_TEST_TAGS", "create_file", "get_action", "get_arg") load("@bazel_skylib//lib:sets.bzl", "sets") load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") @@ -83,8 +84,13 @@ def _test_impl(ctx): if ctx.attr.expected_friend_jar_names != _DEFAULT_LIST: friend_paths_arg = get_arg(kt_2_java_compile, "-Xfriend-paths=") - friend_jar_names = [p.rsplit("/", 1)[1] for p in friend_paths_arg.split(",")] if friend_paths_arg else [] - asserts.set_equals(env, sets.make(ctx.attr.expected_friend_jar_names), sets.make(friend_jar_names)) + kt_asserts.list_matches( + env, + expected = ctx.attr.expected_friend_jar_names, + actual = ["/" + x for x in (friend_paths_arg.split(",") if friend_paths_arg else [])], + matcher = lambda expected, actual: actual.endswith(expected), + items_name = "friend JARs", + ) asserts.equals( env, @@ -93,20 +99,7 @@ def _test_impl(ctx): "Mismatch: Expected transitive_runtime_jars iff (neverlink == False)", ) - for mnemonic in ctx.attr.required_mnemonics: - if mnemonic.startswith("-"): - mnemonic = mnemonic.removeprefix("-") - asserts.false( - env, - mnemonic in [a.mnemonic for a in actions], - "Found action with forbidden mnemonic " + mnemonic, - ) - else: - asserts.true( - env, - mnemonic in [a.mnemonic for a in actions], - "Missing action with required mnemonic " + mnemonic, - ) + kt_asserts.required_mnemonic_counts(env, ctx.attr.required_mnemonic_counts, actions) return analysistest.end(env) @@ -142,7 +135,7 @@ _test = analysistest.make( expect_jdeps = attr.bool(default = True), expect_processor_classpath = attr.bool(), expect_neverlink = attr.bool(), - required_mnemonics = attr.string_list( + required_mnemonic_counts = attr.string_dict( doc = """ Mnemonics that must be registered (or must not be, if starting with '-'). @@ -628,7 +621,7 @@ def _test_kt_jvm_library_with_no_sources_with_exports(): name = test_name, target_under_test = test_name + "_tut", expect_jdeps = False, - required_mnemonics = ["-KtAndroidLint"], + required_mnemonic_counts = {"KtAndroidLint": "0"}, ) return test_name |