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_asserts""" 16 17load("//:visibility.bzl", "RULES_KOTLIN") 18load("@bazel_skylib//lib:unittest.bzl", "asserts") 19 20visibility(RULES_KOTLIN) 21 22def _equals(a, b): 23 return a == b 24 25def _list_matching(left, right, matcher = None): 26 """Find the overlap between two lists. 27 28 Args: 29 left: [list[A]] 30 right: [list[B]] 31 matcher: [function(A,B):bool] A matcher on the two list types 32 33 Returns: 34 [(list[A], list[(A, B)], list[B])] The left-only, matching-pair, and right-only lists 35 """ 36 37 matcher = matcher or _equals 38 39 left_only = [] 40 matches = [] 41 right_only = list(right) 42 43 def _process_left_ele(left_ele): 44 for index, right_ele in enumerate(right_only): 45 if matcher(left_ele, right_ele): 46 right_only.pop(index) 47 matches.append((left_ele, right_ele)) 48 return 49 50 left_only.append(left_ele) 51 52 for left_ele in left: 53 _process_left_ele(left_ele) 54 55 return (left_only, matches, right_only) 56 57def _assert_list_matches(env, expected, actual, matcher = None, items_name = "items"): 58 """Assert two lists have an exact matching. 59 60 Args: 61 env: [unittest.env] 62 expected: [list[A]] 63 actual: [list[B]] 64 matcher: [function(A,B):bool] 65 items_name: [string] The plural noun describing the list items in an error message 66 67 Returns: 68 [None] Fails if assertion violated 69 """ 70 71 extra_expected, _, extra_actual = _list_matching(expected, actual, matcher = matcher) 72 asserts.true( 73 env, 74 len(extra_actual) == 0 and len(extra_expected) == 0, 75 "Unmatched expected {name} {expected}\nUnmatched actual {name} {actual}".format( 76 name = items_name, 77 expected = extra_expected, 78 actual = extra_actual, 79 ), 80 ) 81 82def _assert_required_mnemonic_counts(env, required_mnemonic_counts, actual_actions): 83 """Assert that some set of menemonics is present/absent within a set of Actions. 84 85 Args: 86 env: [unittest.env] 87 required_mnemonic_counts: [dict[string,string]] The menemonics to check -> expected count 88 actual_actions: [list[Action]] 89 90 Returns: 91 [None] Fails if assertion violated 92 """ 93 94 considered_actual_mnemonics = [ 95 x.mnemonic 96 for x in actual_actions 97 # Ignore any mnemonics not mentioned by the user 98 if (x.mnemonic in required_mnemonic_counts) 99 ] 100 101 required_mnemonics = [] 102 for m, c in required_mnemonic_counts.items(): 103 for _ in range(0, int(c)): 104 required_mnemonics.append(m) 105 106 _assert_list_matches( 107 env, 108 required_mnemonics, 109 considered_actual_mnemonics, 110 items_name = "mnemonics", 111 ) 112 113kt_asserts = struct( 114 list_matches = _assert_list_matches, 115 required_mnemonic_counts = _assert_required_mnemonic_counts, 116) 117