xref: /aosp_15_r20/external/bazelbuild-kotlin-rules/kotlin/common/testing/asserts.bzl (revision 3a22c0a33dd99bcca39a024d43e6fbcc55c2806e)
1*3a22c0a3SAlix# Copyright 2022 Google LLC. All rights reserved.
2*3a22c0a3SAlix#
3*3a22c0a3SAlix# Licensed under the Apache License, Version 2.0 (the License);
4*3a22c0a3SAlix# you may not use this file except in compliance with the License.
5*3a22c0a3SAlix# You may obtain a copy of the License at
6*3a22c0a3SAlix#
7*3a22c0a3SAlix#     http://www.apache.org/licenses/LICENSE-2.0
8*3a22c0a3SAlix#
9*3a22c0a3SAlix# Unless required by applicable law or agreed to in writing, software
10*3a22c0a3SAlix# distributed under the License is distributed on an "AS IS" BASIS,
11*3a22c0a3SAlix# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*3a22c0a3SAlix# See the License for the specific language governing permissions and
13*3a22c0a3SAlix# limitations under the License.
14*3a22c0a3SAlix
15*3a22c0a3SAlix"""kt_asserts"""
16*3a22c0a3SAlix
17*3a22c0a3SAlixload("//:visibility.bzl", "RULES_KOTLIN")
18*3a22c0a3SAlixload("@bazel_skylib//lib:unittest.bzl", "asserts")
19*3a22c0a3SAlix
20*3a22c0a3SAlixvisibility(RULES_KOTLIN)
21*3a22c0a3SAlix
22*3a22c0a3SAlixdef _equals(a, b):
23*3a22c0a3SAlix    return a == b
24*3a22c0a3SAlix
25*3a22c0a3SAlixdef _list_matching(left, right, matcher = None):
26*3a22c0a3SAlix    """Find the overlap between two lists.
27*3a22c0a3SAlix
28*3a22c0a3SAlix    Args:
29*3a22c0a3SAlix        left: [list[A]]
30*3a22c0a3SAlix        right: [list[B]]
31*3a22c0a3SAlix        matcher: [function(A,B):bool] A matcher on the two list types
32*3a22c0a3SAlix
33*3a22c0a3SAlix    Returns:
34*3a22c0a3SAlix        [(list[A], list[(A, B)], list[B])] The left-only, matching-pair, and right-only lists
35*3a22c0a3SAlix    """
36*3a22c0a3SAlix
37*3a22c0a3SAlix    matcher = matcher or _equals
38*3a22c0a3SAlix
39*3a22c0a3SAlix    left_only = []
40*3a22c0a3SAlix    matches = []
41*3a22c0a3SAlix    right_only = list(right)
42*3a22c0a3SAlix
43*3a22c0a3SAlix    def _process_left_ele(left_ele):
44*3a22c0a3SAlix        for index, right_ele in enumerate(right_only):
45*3a22c0a3SAlix            if matcher(left_ele, right_ele):
46*3a22c0a3SAlix                right_only.pop(index)
47*3a22c0a3SAlix                matches.append((left_ele, right_ele))
48*3a22c0a3SAlix                return
49*3a22c0a3SAlix
50*3a22c0a3SAlix        left_only.append(left_ele)
51*3a22c0a3SAlix
52*3a22c0a3SAlix    for left_ele in left:
53*3a22c0a3SAlix        _process_left_ele(left_ele)
54*3a22c0a3SAlix
55*3a22c0a3SAlix    return (left_only, matches, right_only)
56*3a22c0a3SAlix
57*3a22c0a3SAlixdef _assert_list_matches(env, expected, actual, matcher = None, items_name = "items"):
58*3a22c0a3SAlix    """Assert two lists have an exact matching.
59*3a22c0a3SAlix
60*3a22c0a3SAlix    Args:
61*3a22c0a3SAlix        env: [unittest.env]
62*3a22c0a3SAlix        expected: [list[A]]
63*3a22c0a3SAlix        actual: [list[B]]
64*3a22c0a3SAlix        matcher: [function(A,B):bool]
65*3a22c0a3SAlix        items_name: [string] The plural noun describing the list items in an error message
66*3a22c0a3SAlix
67*3a22c0a3SAlix    Returns:
68*3a22c0a3SAlix        [None] Fails if assertion violated
69*3a22c0a3SAlix    """
70*3a22c0a3SAlix
71*3a22c0a3SAlix    extra_expected, _, extra_actual = _list_matching(expected, actual, matcher = matcher)
72*3a22c0a3SAlix    asserts.true(
73*3a22c0a3SAlix        env,
74*3a22c0a3SAlix        len(extra_actual) == 0 and len(extra_expected) == 0,
75*3a22c0a3SAlix        "Unmatched expected {name} {expected}\nUnmatched actual {name} {actual}".format(
76*3a22c0a3SAlix            name = items_name,
77*3a22c0a3SAlix            expected = extra_expected,
78*3a22c0a3SAlix            actual = extra_actual,
79*3a22c0a3SAlix        ),
80*3a22c0a3SAlix    )
81*3a22c0a3SAlix
82*3a22c0a3SAlixdef _assert_required_mnemonic_counts(env, required_mnemonic_counts, actual_actions):
83*3a22c0a3SAlix    """Assert that some set of menemonics is present/absent within a set of Actions.
84*3a22c0a3SAlix
85*3a22c0a3SAlix    Args:
86*3a22c0a3SAlix        env: [unittest.env]
87*3a22c0a3SAlix        required_mnemonic_counts: [dict[string,string]] The menemonics to check -> expected count
88*3a22c0a3SAlix        actual_actions: [list[Action]]
89*3a22c0a3SAlix
90*3a22c0a3SAlix    Returns:
91*3a22c0a3SAlix        [None] Fails if assertion violated
92*3a22c0a3SAlix    """
93*3a22c0a3SAlix
94*3a22c0a3SAlix    considered_actual_mnemonics = [
95*3a22c0a3SAlix        x.mnemonic
96*3a22c0a3SAlix        for x in actual_actions
97*3a22c0a3SAlix        # Ignore any mnemonics not mentioned by the user
98*3a22c0a3SAlix        if (x.mnemonic in required_mnemonic_counts)
99*3a22c0a3SAlix    ]
100*3a22c0a3SAlix
101*3a22c0a3SAlix    required_mnemonics = []
102*3a22c0a3SAlix    for m, c in required_mnemonic_counts.items():
103*3a22c0a3SAlix        for _ in range(0, int(c)):
104*3a22c0a3SAlix            required_mnemonics.append(m)
105*3a22c0a3SAlix
106*3a22c0a3SAlix    _assert_list_matches(
107*3a22c0a3SAlix        env,
108*3a22c0a3SAlix        required_mnemonics,
109*3a22c0a3SAlix        considered_actual_mnemonics,
110*3a22c0a3SAlix        items_name = "mnemonics",
111*3a22c0a3SAlix    )
112*3a22c0a3SAlix
113*3a22c0a3SAlixkt_asserts = struct(
114*3a22c0a3SAlix    list_matches = _assert_list_matches,
115*3a22c0a3SAlix    required_mnemonic_counts = _assert_required_mnemonic_counts,
116*3a22c0a3SAlix)
117