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