1*9e965d6fSRomain Jobredeaux# Copyright 2020 The Bazel Authors. All rights reserved. 2*9e965d6fSRomain Jobredeaux# 3*9e965d6fSRomain Jobredeaux# Licensed under the Apache License, Version 2.0 (the "License"); 4*9e965d6fSRomain Jobredeaux# you may not use this file except in compliance with the License. 5*9e965d6fSRomain Jobredeaux# You may obtain a copy of the License at 6*9e965d6fSRomain Jobredeaux# 7*9e965d6fSRomain Jobredeaux# http://www.apache.org/licenses/LICENSE-2.0 8*9e965d6fSRomain Jobredeaux# 9*9e965d6fSRomain Jobredeaux# Unless required by applicable law or agreed to in writing, software 10*9e965d6fSRomain Jobredeaux# distributed under the License is distributed on an "AS IS" BASIS, 11*9e965d6fSRomain Jobredeaux# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*9e965d6fSRomain Jobredeaux# See the License for the specific language governing permissions and 13*9e965d6fSRomain Jobredeaux# limitations under the License. 14*9e965d6fSRomain Jobredeaux 15*9e965d6fSRomain Jobredeaux"""Bazel testing library asserts.""" 16*9e965d6fSRomain Jobredeaux 17*9e965d6fSRomain Jobredeauxload( 18*9e965d6fSRomain Jobredeaux "//rules:providers.bzl", 19*9e965d6fSRomain Jobredeaux "ResourcesNodeInfo", 20*9e965d6fSRomain Jobredeaux "StarlarkAndroidResourcesInfo", 21*9e965d6fSRomain Jobredeaux) 22*9e965d6fSRomain Jobredeaux 23*9e965d6fSRomain Jobredeaux_ATTRS = dict( 24*9e965d6fSRomain Jobredeaux expected_default_info = attr.string_list_dict(), 25*9e965d6fSRomain Jobredeaux expected_java_info = attr.string_list_dict(), 26*9e965d6fSRomain Jobredeaux expected_proguard_spec_provider = attr.string_list_dict(), 27*9e965d6fSRomain Jobredeaux expected_starlark_android_resources_info = attr.label(), 28*9e965d6fSRomain Jobredeaux expected_output_group_info = attr.string_list_dict(), 29*9e965d6fSRomain Jobredeaux expected_native_libs_info = attr.label(), 30*9e965d6fSRomain Jobredeaux expected_generated_extension_registry_provider = attr.string_list_dict(), 31*9e965d6fSRomain Jobredeaux) 32*9e965d6fSRomain Jobredeaux 33*9e965d6fSRomain Jobredeauxdef _expected_resources_node_info_impl(ctx): 34*9e965d6fSRomain Jobredeaux return [ 35*9e965d6fSRomain Jobredeaux ResourcesNodeInfo( 36*9e965d6fSRomain Jobredeaux label = ctx.attr.label.label, 37*9e965d6fSRomain Jobredeaux assets = ctx.files.assets, 38*9e965d6fSRomain Jobredeaux assets_dir = ctx.attr.assets_dir, 39*9e965d6fSRomain Jobredeaux assets_symbols = ctx.attr.assets_symbols if ctx.attr.assets_symbols else None, 40*9e965d6fSRomain Jobredeaux compiled_assets = ctx.attr.compiled_assets if ctx.attr.compiled_assets else None, 41*9e965d6fSRomain Jobredeaux compiled_resources = ctx.attr.compiled_resources if ctx.attr.compiled_resources else None, 42*9e965d6fSRomain Jobredeaux r_txt = ctx.attr.r_txt if ctx.attr.r_txt else None, 43*9e965d6fSRomain Jobredeaux manifest = ctx.attr.manifest if ctx.attr.manifest else None, 44*9e965d6fSRomain Jobredeaux exports_manifest = ctx.attr.exports_manifest, 45*9e965d6fSRomain Jobredeaux ), 46*9e965d6fSRomain Jobredeaux ] 47*9e965d6fSRomain Jobredeaux 48*9e965d6fSRomain Jobredeaux_expected_resources_node_info = rule( 49*9e965d6fSRomain Jobredeaux implementation = _expected_resources_node_info_impl, 50*9e965d6fSRomain Jobredeaux attrs = dict( 51*9e965d6fSRomain Jobredeaux label = attr.label(), 52*9e965d6fSRomain Jobredeaux assets = attr.label_list(allow_files = True), 53*9e965d6fSRomain Jobredeaux assets_dir = attr.string(), 54*9e965d6fSRomain Jobredeaux assets_symbols = attr.string(), 55*9e965d6fSRomain Jobredeaux compiled_assets = attr.string(), 56*9e965d6fSRomain Jobredeaux compiled_resources = attr.string(), 57*9e965d6fSRomain Jobredeaux r_txt = attr.string(), 58*9e965d6fSRomain Jobredeaux manifest = attr.string(), 59*9e965d6fSRomain Jobredeaux exports_manifest = attr.bool(default = False), 60*9e965d6fSRomain Jobredeaux ), 61*9e965d6fSRomain Jobredeaux) 62*9e965d6fSRomain Jobredeaux 63*9e965d6fSRomain Jobredeauxdef ExpectedResourcesNodeInfo( 64*9e965d6fSRomain Jobredeaux label, 65*9e965d6fSRomain Jobredeaux assets = [], 66*9e965d6fSRomain Jobredeaux assets_dir = "", 67*9e965d6fSRomain Jobredeaux assets_symbols = None, 68*9e965d6fSRomain Jobredeaux compiled_assets = None, 69*9e965d6fSRomain Jobredeaux compiled_resources = None, 70*9e965d6fSRomain Jobredeaux r_txt = None, 71*9e965d6fSRomain Jobredeaux manifest = None, 72*9e965d6fSRomain Jobredeaux exports_manifest = False, 73*9e965d6fSRomain Jobredeaux name = "unused"): # appease linter 74*9e965d6fSRomain Jobredeaux name = label + str(assets) + assets_dir + str(assets_symbols) + str(compiled_resources) + str(exports_manifest) 75*9e965d6fSRomain Jobredeaux name = ":" + "".join([c for c in name.elems() if c != ":"]) 76*9e965d6fSRomain Jobredeaux 77*9e965d6fSRomain Jobredeaux _expected_resources_node_info( 78*9e965d6fSRomain Jobredeaux name = name[1:], 79*9e965d6fSRomain Jobredeaux label = label, 80*9e965d6fSRomain Jobredeaux assets = assets, 81*9e965d6fSRomain Jobredeaux assets_dir = assets_dir, 82*9e965d6fSRomain Jobredeaux assets_symbols = assets_symbols, 83*9e965d6fSRomain Jobredeaux compiled_assets = compiled_assets, 84*9e965d6fSRomain Jobredeaux compiled_resources = compiled_resources, 85*9e965d6fSRomain Jobredeaux r_txt = r_txt, 86*9e965d6fSRomain Jobredeaux manifest = manifest, 87*9e965d6fSRomain Jobredeaux exports_manifest = exports_manifest, 88*9e965d6fSRomain Jobredeaux ) 89*9e965d6fSRomain Jobredeaux return name 90*9e965d6fSRomain Jobredeaux 91*9e965d6fSRomain Jobredeauxdef _expected_starlark_android_resources_info_impl(ctx): 92*9e965d6fSRomain Jobredeaux return [ 93*9e965d6fSRomain Jobredeaux StarlarkAndroidResourcesInfo( 94*9e965d6fSRomain Jobredeaux direct_resources_nodes = [node[ResourcesNodeInfo] for node in ctx.attr.direct_resources_nodes], 95*9e965d6fSRomain Jobredeaux transitive_resources_nodes = [node[ResourcesNodeInfo] for node in ctx.attr.transitive_resources_nodes], 96*9e965d6fSRomain Jobredeaux transitive_assets = ctx.attr.transitive_assets, 97*9e965d6fSRomain Jobredeaux transitive_assets_symbols = ctx.attr.transitive_assets_symbols, 98*9e965d6fSRomain Jobredeaux transitive_compiled_resources = ctx.attr.transitive_compiled_resources, 99*9e965d6fSRomain Jobredeaux packages_to_r_txts = ctx.attr.packages_to_r_txts, 100*9e965d6fSRomain Jobredeaux ), 101*9e965d6fSRomain Jobredeaux ] 102*9e965d6fSRomain Jobredeaux 103*9e965d6fSRomain Jobredeaux_expected_starlark_android_resources_info = rule( 104*9e965d6fSRomain Jobredeaux implementation = _expected_starlark_android_resources_info_impl, 105*9e965d6fSRomain Jobredeaux attrs = dict( 106*9e965d6fSRomain Jobredeaux direct_resources_nodes = attr.label_list( 107*9e965d6fSRomain Jobredeaux providers = [ResourcesNodeInfo], 108*9e965d6fSRomain Jobredeaux ), 109*9e965d6fSRomain Jobredeaux transitive_resources_nodes = attr.label_list( 110*9e965d6fSRomain Jobredeaux providers = [ResourcesNodeInfo], 111*9e965d6fSRomain Jobredeaux ), 112*9e965d6fSRomain Jobredeaux transitive_assets = attr.string_list(), 113*9e965d6fSRomain Jobredeaux transitive_assets_symbols = attr.string_list(), 114*9e965d6fSRomain Jobredeaux transitive_compiled_resources = attr.string_list(), 115*9e965d6fSRomain Jobredeaux packages_to_r_txts = attr.string_list_dict(), 116*9e965d6fSRomain Jobredeaux ), 117*9e965d6fSRomain Jobredeaux) 118*9e965d6fSRomain Jobredeaux 119*9e965d6fSRomain Jobredeauxdef ExpectedStarlarkAndroidResourcesInfo( 120*9e965d6fSRomain Jobredeaux direct_resources_nodes = None, 121*9e965d6fSRomain Jobredeaux transitive_resources_nodes = [], 122*9e965d6fSRomain Jobredeaux transitive_assets = [], 123*9e965d6fSRomain Jobredeaux transitive_assets_symbols = [], 124*9e965d6fSRomain Jobredeaux transitive_compiled_resources = [], 125*9e965d6fSRomain Jobredeaux packages_to_r_txts = {}, 126*9e965d6fSRomain Jobredeaux name = "unused"): # appease linter 127*9e965d6fSRomain Jobredeaux name = (str(direct_resources_nodes) + str(transitive_resources_nodes) + str(transitive_assets) + 128*9e965d6fSRomain Jobredeaux str(transitive_assets_symbols) + str(transitive_compiled_resources)) 129*9e965d6fSRomain Jobredeaux name = ":" + "".join([c for c in name.elems() if c not in [":", "\\"]]) 130*9e965d6fSRomain Jobredeaux _expected_starlark_android_resources_info( 131*9e965d6fSRomain Jobredeaux name = name[1:], 132*9e965d6fSRomain Jobredeaux direct_resources_nodes = direct_resources_nodes, 133*9e965d6fSRomain Jobredeaux transitive_resources_nodes = transitive_resources_nodes, 134*9e965d6fSRomain Jobredeaux transitive_assets = transitive_assets, 135*9e965d6fSRomain Jobredeaux transitive_assets_symbols = transitive_assets_symbols, 136*9e965d6fSRomain Jobredeaux transitive_compiled_resources = transitive_compiled_resources, 137*9e965d6fSRomain Jobredeaux packages_to_r_txts = packages_to_r_txts, 138*9e965d6fSRomain Jobredeaux ) 139*9e965d6fSRomain Jobredeaux return name 140*9e965d6fSRomain Jobredeaux 141*9e965d6fSRomain Jobredeauxdef _build_expected_resources_node_info(string): 142*9e965d6fSRomain Jobredeaux parts = string.split(":") 143*9e965d6fSRomain Jobredeaux if len(parts) != 5: 144*9e965d6fSRomain Jobredeaux fail("Error: malformed resources_node_info string: %s" % string) 145*9e965d6fSRomain Jobredeaux return dict( 146*9e965d6fSRomain Jobredeaux label = parts[0], 147*9e965d6fSRomain Jobredeaux assets = parts[1].split(",") if parts[1] else [], 148*9e965d6fSRomain Jobredeaux assets_dir = parts[2], 149*9e965d6fSRomain Jobredeaux assets_symbols = parts[3], 150*9e965d6fSRomain Jobredeaux compiled_resources = parts[4], 151*9e965d6fSRomain Jobredeaux ) 152*9e965d6fSRomain Jobredeaux 153*9e965d6fSRomain Jobredeauxdef _expected_android_binary_native_libs_info_impl(ctx): 154*9e965d6fSRomain Jobredeaux return _ExpectedAndroidBinaryNativeInfo( 155*9e965d6fSRomain Jobredeaux transitive_native_libs = ctx.attr.transitive_native_libs, 156*9e965d6fSRomain Jobredeaux native_libs_name = ctx.attr.native_libs_name, 157*9e965d6fSRomain Jobredeaux native_libs = ctx.attr.native_libs, 158*9e965d6fSRomain Jobredeaux ) 159*9e965d6fSRomain Jobredeaux 160*9e965d6fSRomain Jobredeaux_expected_android_binary_native_libs_info = rule( 161*9e965d6fSRomain Jobredeaux implementation = _expected_android_binary_native_libs_info_impl, 162*9e965d6fSRomain Jobredeaux attrs = { 163*9e965d6fSRomain Jobredeaux "transitive_native_libs": attr.string_list(), 164*9e965d6fSRomain Jobredeaux "native_libs_name": attr.string(), 165*9e965d6fSRomain Jobredeaux "native_libs": attr.string_list_dict(), 166*9e965d6fSRomain Jobredeaux }, 167*9e965d6fSRomain Jobredeaux) 168*9e965d6fSRomain Jobredeaux 169*9e965d6fSRomain Jobredeauxdef ExpectedAndroidBinaryNativeLibsInfo(**kwargs): 170*9e965d6fSRomain Jobredeaux name = "".join([str(kwargs[param]) for param in kwargs]) 171*9e965d6fSRomain Jobredeaux name = ":" + "".join([c for c in name.elems() if c not in [" ", "[", "]", ":", "\\", "{", "\""]]) 172*9e965d6fSRomain Jobredeaux _expected_android_binary_native_libs_info(name = name[1:], **kwargs) 173*9e965d6fSRomain Jobredeaux return name 174*9e965d6fSRomain Jobredeaux 175*9e965d6fSRomain Jobredeaux_ExpectedAndroidBinaryNativeInfo = provider( 176*9e965d6fSRomain Jobredeaux "Test provider to compare native deps info", 177*9e965d6fSRomain Jobredeaux fields = ["native_libs", "native_libs_name", "transitive_native_libs"], 178*9e965d6fSRomain Jobredeaux) 179*9e965d6fSRomain Jobredeaux 180*9e965d6fSRomain Jobredeauxdef _assert_native_libs_info(expected, actual): 181*9e965d6fSRomain Jobredeaux expected = expected[_ExpectedAndroidBinaryNativeInfo] 182*9e965d6fSRomain Jobredeaux if expected.native_libs_name: 183*9e965d6fSRomain Jobredeaux _assert_file( 184*9e965d6fSRomain Jobredeaux expected.native_libs_name, 185*9e965d6fSRomain Jobredeaux actual.native_libs_name, 186*9e965d6fSRomain Jobredeaux "AndroidBinaryNativeInfo.native_libs_name", 187*9e965d6fSRomain Jobredeaux ) 188*9e965d6fSRomain Jobredeaux for config in expected.native_libs: 189*9e965d6fSRomain Jobredeaux if config not in actual.native_libs: 190*9e965d6fSRomain Jobredeaux fail("Error for AndroidBinaryNativeInfo.native_libs: expected key %s was not found" % config) 191*9e965d6fSRomain Jobredeaux _assert_files( 192*9e965d6fSRomain Jobredeaux expected.native_libs[config], 193*9e965d6fSRomain Jobredeaux actual.native_libs[config].to_list(), 194*9e965d6fSRomain Jobredeaux "AndroidBinaryNativeInfo.native_libs." + config, 195*9e965d6fSRomain Jobredeaux ) 196*9e965d6fSRomain Jobredeaux _assert_files( 197*9e965d6fSRomain Jobredeaux expected.transitive_native_libs, 198*9e965d6fSRomain Jobredeaux actual.transitive_native_libs.to_list(), 199*9e965d6fSRomain Jobredeaux "AndroidBinaryNativeInfo.transitive_native_libs", 200*9e965d6fSRomain Jobredeaux ) 201*9e965d6fSRomain Jobredeaux 202*9e965d6fSRomain Jobredeauxdef _assert_files(expected_file_names, actual_files, error_msg_field_name): 203*9e965d6fSRomain Jobredeaux """Asserts that expected file names and actual list of files is equal. 204*9e965d6fSRomain Jobredeaux 205*9e965d6fSRomain Jobredeaux Args: 206*9e965d6fSRomain Jobredeaux expected_file_names: The expected names of file basenames (no path), 207*9e965d6fSRomain Jobredeaux actual_files: The actual list of files produced. 208*9e965d6fSRomain Jobredeaux error_msg_field_name: The field the actual list of files is from. 209*9e965d6fSRomain Jobredeaux """ 210*9e965d6fSRomain Jobredeaux actual_file_names = [f.basename for f in actual_files] 211*9e965d6fSRomain Jobredeaux if sorted(actual_file_names) == sorted(expected_file_names): 212*9e965d6fSRomain Jobredeaux return 213*9e965d6fSRomain Jobredeaux fail("""Error for %s, expected and actual file names are not the same: 214*9e965d6fSRomain Jobredeauxexpected file names: %s 215*9e965d6fSRomain Jobredeauxactual files: %s 216*9e965d6fSRomain Jobredeaux""" % (error_msg_field_name, expected_file_names, actual_files)) 217*9e965d6fSRomain Jobredeaux 218*9e965d6fSRomain Jobredeauxdef _assert_file_objects(expected_files, actual_files, error_msg_field_name): 219*9e965d6fSRomain Jobredeaux if sorted([f.basename for f in expected_files]) == sorted([f.basename for f in actual_files]): 220*9e965d6fSRomain Jobredeaux return 221*9e965d6fSRomain Jobredeaux fail("""Error for %s, expected and actual file names are not the same: 222*9e965d6fSRomain Jobredeauxexpected file names: %s 223*9e965d6fSRomain Jobredeauxactual files: %s 224*9e965d6fSRomain Jobredeaux""" % (error_msg_field_name, expected_files, actual_files)) 225*9e965d6fSRomain Jobredeaux 226*9e965d6fSRomain Jobredeauxdef _assert_file_depset(expected_file_paths, actual_depset, error_msg_field_name, ignore_label_prefix = ""): 227*9e965d6fSRomain Jobredeaux """Asserts that expected file short_paths and actual depset of files is equal. 228*9e965d6fSRomain Jobredeaux 229*9e965d6fSRomain Jobredeaux Args: 230*9e965d6fSRomain Jobredeaux expected_file_paths: The expected file short_paths in depset order. 231*9e965d6fSRomain Jobredeaux actual_depset: The actual depset produced. 232*9e965d6fSRomain Jobredeaux error_msg_field_name: The field the actual depset is from. 233*9e965d6fSRomain Jobredeaux ignore_label_prefix: Path prefix to ignore on actual file short_paths. 234*9e965d6fSRomain Jobredeaux """ 235*9e965d6fSRomain Jobredeaux actual_paths = [] # = [f.short_path for f in actual_depset.to_list()] 236*9e965d6fSRomain Jobredeaux for f in actual_depset.to_list(): 237*9e965d6fSRomain Jobredeaux path = f.short_path 238*9e965d6fSRomain Jobredeaux if path.startswith(ignore_label_prefix): 239*9e965d6fSRomain Jobredeaux path = path[len(ignore_label_prefix):] 240*9e965d6fSRomain Jobredeaux actual_paths.append(path) 241*9e965d6fSRomain Jobredeaux 242*9e965d6fSRomain Jobredeaux if len(expected_file_paths) != len(actual_paths): 243*9e965d6fSRomain Jobredeaux fail("""Error for %s, expected %d items, got %d items 244*9e965d6fSRomain Jobredeauxexpected: %s 245*9e965d6fSRomain Jobredeauxactual: %s""" % ( 246*9e965d6fSRomain Jobredeaux error_msg_field_name, 247*9e965d6fSRomain Jobredeaux len(expected_file_paths), 248*9e965d6fSRomain Jobredeaux len(actual_paths), 249*9e965d6fSRomain Jobredeaux expected_file_paths, 250*9e965d6fSRomain Jobredeaux actual_paths, 251*9e965d6fSRomain Jobredeaux )) 252*9e965d6fSRomain Jobredeaux for i in range(len(expected_file_paths)): 253*9e965d6fSRomain Jobredeaux if expected_file_paths[i] != actual_paths[i]: 254*9e965d6fSRomain Jobredeaux fail("""Error for %s, actual file depset ordering does not match expected ordering: 255*9e965d6fSRomain Jobredeauxexpected ordering: %s 256*9e965d6fSRomain Jobredeauxactual ordering: %s 257*9e965d6fSRomain Jobredeaux""" % (error_msg_field_name, expected_file_paths, actual_paths)) 258*9e965d6fSRomain Jobredeaux 259*9e965d6fSRomain Jobredeauxdef _assert_empty(contents, error_msg_field_name): 260*9e965d6fSRomain Jobredeaux """Asserts that the given is empty.""" 261*9e965d6fSRomain Jobredeaux if len(contents) == 0: 262*9e965d6fSRomain Jobredeaux return 263*9e965d6fSRomain Jobredeaux fail("Error %s is not empty: %s" % (error_msg_field_name, contents)) 264*9e965d6fSRomain Jobredeaux 265*9e965d6fSRomain Jobredeauxdef _assert_none(content, error_msg_field_name): 266*9e965d6fSRomain Jobredeaux """Asserts that the given is None.""" 267*9e965d6fSRomain Jobredeaux if content == None: 268*9e965d6fSRomain Jobredeaux return 269*9e965d6fSRomain Jobredeaux fail("Error %s is not None: %s" % (error_msg_field_name, content)) 270*9e965d6fSRomain Jobredeaux 271*9e965d6fSRomain Jobredeauxdef _assert_java_info(expected, actual): 272*9e965d6fSRomain Jobredeaux """Asserts that expected matches actual JavaInfo. 273*9e965d6fSRomain Jobredeaux 274*9e965d6fSRomain Jobredeaux Args: 275*9e965d6fSRomain Jobredeaux expected: A dict containing fields of a JavaInfo that are compared against 276*9e965d6fSRomain Jobredeaux the actual given JavaInfo. 277*9e965d6fSRomain Jobredeaux actual: A JavaInfo. 278*9e965d6fSRomain Jobredeaux """ 279*9e965d6fSRomain Jobredeaux for key in expected.keys(): 280*9e965d6fSRomain Jobredeaux if not hasattr(actual, key): 281*9e965d6fSRomain Jobredeaux fail("Actual JavaInfo does not have attribute %s:\n%s" % (key, actual)) 282*9e965d6fSRomain Jobredeaux actual_attr = getattr(actual, key) 283*9e965d6fSRomain Jobredeaux expected_attr = expected[key] 284*9e965d6fSRomain Jobredeaux 285*9e965d6fSRomain Jobredeaux # files based asserts. 286*9e965d6fSRomain Jobredeaux if key in [ 287*9e965d6fSRomain Jobredeaux "compile_jars", 288*9e965d6fSRomain Jobredeaux "runtime_output_jars", 289*9e965d6fSRomain Jobredeaux "source_jars", 290*9e965d6fSRomain Jobredeaux "transitive_compile_time_jars", 291*9e965d6fSRomain Jobredeaux "transitive_runtime_jars", 292*9e965d6fSRomain Jobredeaux "transitive_source_jars", 293*9e965d6fSRomain Jobredeaux ]: 294*9e965d6fSRomain Jobredeaux files = \ 295*9e965d6fSRomain Jobredeaux actual_attr if type(actual_attr) == "list" else actual_attr.to_list() 296*9e965d6fSRomain Jobredeaux _assert_files(expected_attr, files, "JavaInfo.%s" % key) 297*9e965d6fSRomain Jobredeaux else: 298*9e965d6fSRomain Jobredeaux fail("Error validation of JavaInfo.%s not implemented." % key) 299*9e965d6fSRomain Jobredeaux 300*9e965d6fSRomain Jobredeauxdef _assert_default_info( 301*9e965d6fSRomain Jobredeaux expected, 302*9e965d6fSRomain Jobredeaux actual): 303*9e965d6fSRomain Jobredeaux """Asserts that the DefaultInfo contains the expected values.""" 304*9e965d6fSRomain Jobredeaux if not expected: 305*9e965d6fSRomain Jobredeaux return 306*9e965d6fSRomain Jobredeaux 307*9e965d6fSRomain Jobredeaux # DefaultInfo.data_runfiles Assertions 308*9e965d6fSRomain Jobredeaux _assert_empty( 309*9e965d6fSRomain Jobredeaux actual.data_runfiles.empty_filenames.to_list(), 310*9e965d6fSRomain Jobredeaux "DefaultInfo.data_runfiles.empty_filenames", 311*9e965d6fSRomain Jobredeaux ) 312*9e965d6fSRomain Jobredeaux _assert_files( 313*9e965d6fSRomain Jobredeaux expected["runfiles"], 314*9e965d6fSRomain Jobredeaux actual.data_runfiles.files.to_list(), 315*9e965d6fSRomain Jobredeaux "DefaultInfo.data_runfiles.files", 316*9e965d6fSRomain Jobredeaux ) 317*9e965d6fSRomain Jobredeaux _assert_empty( 318*9e965d6fSRomain Jobredeaux actual.data_runfiles.symlinks.to_list(), 319*9e965d6fSRomain Jobredeaux "DefaultInfo.data_runfiles.symlinks", 320*9e965d6fSRomain Jobredeaux ) 321*9e965d6fSRomain Jobredeaux 322*9e965d6fSRomain Jobredeaux # DefaultInfo.default_runfile Assertions 323*9e965d6fSRomain Jobredeaux _assert_empty( 324*9e965d6fSRomain Jobredeaux actual.default_runfiles.empty_filenames.to_list(), 325*9e965d6fSRomain Jobredeaux "DefaultInfo.default_runfiles.empty_filenames", 326*9e965d6fSRomain Jobredeaux ) 327*9e965d6fSRomain Jobredeaux _assert_files( 328*9e965d6fSRomain Jobredeaux expected["runfiles"], 329*9e965d6fSRomain Jobredeaux actual.default_runfiles.files.to_list(), 330*9e965d6fSRomain Jobredeaux "DefaultInfo.default_runfiles.files", 331*9e965d6fSRomain Jobredeaux ) 332*9e965d6fSRomain Jobredeaux _assert_empty( 333*9e965d6fSRomain Jobredeaux actual.default_runfiles.symlinks.to_list(), 334*9e965d6fSRomain Jobredeaux "DefaultInfo.default_runfiles.symlinks", 335*9e965d6fSRomain Jobredeaux ) 336*9e965d6fSRomain Jobredeaux 337*9e965d6fSRomain Jobredeaux # DefaultInfo.files Assertion 338*9e965d6fSRomain Jobredeaux _assert_files( 339*9e965d6fSRomain Jobredeaux expected["files"], 340*9e965d6fSRomain Jobredeaux actual.files.to_list(), 341*9e965d6fSRomain Jobredeaux "DefaultInfo.files", 342*9e965d6fSRomain Jobredeaux ) 343*9e965d6fSRomain Jobredeaux 344*9e965d6fSRomain Jobredeaux # DefaultInfo.files_to_run Assertions 345*9e965d6fSRomain Jobredeaux _assert_none( 346*9e965d6fSRomain Jobredeaux actual.files_to_run.executable, 347*9e965d6fSRomain Jobredeaux "DefaultInfo.files_to_run.executable", 348*9e965d6fSRomain Jobredeaux ) 349*9e965d6fSRomain Jobredeaux _assert_none( 350*9e965d6fSRomain Jobredeaux actual.files_to_run.runfiles_manifest, 351*9e965d6fSRomain Jobredeaux "DefaultInfo.files_to_run.runfiles_manifest", 352*9e965d6fSRomain Jobredeaux ) 353*9e965d6fSRomain Jobredeaux 354*9e965d6fSRomain Jobredeauxdef _assert_proguard_spec_provider(expected, actual): 355*9e965d6fSRomain Jobredeaux """Asserts that expected matches actual ProguardSpecProvider. 356*9e965d6fSRomain Jobredeaux 357*9e965d6fSRomain Jobredeaux Args: 358*9e965d6fSRomain Jobredeaux expected: A dict containing fields of a ProguardSpecProvider that are 359*9e965d6fSRomain Jobredeaux compared against the actual given ProguardSpecProvider. 360*9e965d6fSRomain Jobredeaux actual: A ProguardSpecProvider. 361*9e965d6fSRomain Jobredeaux """ 362*9e965d6fSRomain Jobredeaux for key in expected.keys(): 363*9e965d6fSRomain Jobredeaux if not hasattr(actual, key): 364*9e965d6fSRomain Jobredeaux fail("Actual ProguardSpecProvider does not have attribute %s:\n%s" % (key, actual)) 365*9e965d6fSRomain Jobredeaux actual_attr = getattr(actual, key) 366*9e965d6fSRomain Jobredeaux expected_attr = expected[key] 367*9e965d6fSRomain Jobredeaux if key in ["specs"]: 368*9e965d6fSRomain Jobredeaux _assert_files( 369*9e965d6fSRomain Jobredeaux expected_attr, 370*9e965d6fSRomain Jobredeaux actual_attr.to_list(), 371*9e965d6fSRomain Jobredeaux "ProguardSpecProvider.%s" % key, 372*9e965d6fSRomain Jobredeaux ) 373*9e965d6fSRomain Jobredeaux else: 374*9e965d6fSRomain Jobredeaux fail("Error validation of ProguardSpecProvider.%s not implemented." % key) 375*9e965d6fSRomain Jobredeaux 376*9e965d6fSRomain Jobredeauxdef _assert_string(expected, actual, error_msg): 377*9e965d6fSRomain Jobredeaux if type(actual) != "string": 378*9e965d6fSRomain Jobredeaux fail("Error for %s, actual value not of type string, got %s" % (error_msg, type(actual))) 379*9e965d6fSRomain Jobredeaux if actual != expected: 380*9e965d6fSRomain Jobredeaux fail("""Error for %s, expected and actual values are not the same: 381*9e965d6fSRomain Jobredeauxexpected value: %s 382*9e965d6fSRomain Jobredeauxactual value: %s 383*9e965d6fSRomain Jobredeaux""" % (error_msg, expected, actual)) 384*9e965d6fSRomain Jobredeaux 385*9e965d6fSRomain Jobredeauxdef _assert_file(expected, actual, error_msg_field_name): 386*9e965d6fSRomain Jobredeaux if actual == None and expected == None: 387*9e965d6fSRomain Jobredeaux return 388*9e965d6fSRomain Jobredeaux 389*9e965d6fSRomain Jobredeaux if actual == None and expected != None: 390*9e965d6fSRomain Jobredeaux fail("Error at %s, expected %s but got None" % (error_msg_field_name, expected)) 391*9e965d6fSRomain Jobredeaux 392*9e965d6fSRomain Jobredeaux if type(actual) != "File": 393*9e965d6fSRomain Jobredeaux fail("Error at %s, expected a File but got %s" % (error_msg_field_name, type(actual))) 394*9e965d6fSRomain Jobredeaux 395*9e965d6fSRomain Jobredeaux if actual != None and expected == None: 396*9e965d6fSRomain Jobredeaux fail("Error at %s, expected None but got %s" % (error_msg_field_name, actual.short_path)) 397*9e965d6fSRomain Jobredeaux 398*9e965d6fSRomain Jobredeaux ignore_label_prefix = actual.owner.package + "/" 399*9e965d6fSRomain Jobredeaux actual_path = actual.short_path 400*9e965d6fSRomain Jobredeaux if actual_path.startswith(ignore_label_prefix): 401*9e965d6fSRomain Jobredeaux actual_path = actual_path[len(ignore_label_prefix):] 402*9e965d6fSRomain Jobredeaux _assert_string(expected, actual_path, error_msg_field_name) 403*9e965d6fSRomain Jobredeaux 404*9e965d6fSRomain Jobredeauxdef _assert_resources_node_info(expected, actual): 405*9e965d6fSRomain Jobredeaux if type(actual.label) != "Label": 406*9e965d6fSRomain Jobredeaux fail("Error for ResourcesNodeInfo.label, expected type Label, actual type is %s" % type(actual.label)) 407*9e965d6fSRomain Jobredeaux _assert_string(expected.label.name, actual.label.name, "ResourcesNodeInfo.label.name") 408*9e965d6fSRomain Jobredeaux 409*9e965d6fSRomain Jobredeaux if type(actual.assets) != "depset": 410*9e965d6fSRomain Jobredeaux fail("Error for ResourcesNodeInfo.assets, expected type depset, actual type is %s" % type(actual.assets)) 411*9e965d6fSRomain Jobredeaux 412*9e965d6fSRomain Jobredeaux # TODO(djwhang): Align _assert_file_objects and _assert_file_depset to work 413*9e965d6fSRomain Jobredeaux # in a similar manner. For now, we will just call to_list() as this field 414*9e965d6fSRomain Jobredeaux # was list prior to this change. 415*9e965d6fSRomain Jobredeaux _assert_file_objects(expected.assets, actual.assets.to_list(), "ResourcesNodeInfo.assets") 416*9e965d6fSRomain Jobredeaux 417*9e965d6fSRomain Jobredeaux _assert_string(expected.assets_dir, actual.assets_dir, "ResourcesNodeInfo.assets_dir") 418*9e965d6fSRomain Jobredeaux 419*9e965d6fSRomain Jobredeaux _assert_file( 420*9e965d6fSRomain Jobredeaux expected.assets_symbols, 421*9e965d6fSRomain Jobredeaux actual.assets_symbols, 422*9e965d6fSRomain Jobredeaux "ResourcesNodeInfo.assets_symbols", 423*9e965d6fSRomain Jobredeaux ) 424*9e965d6fSRomain Jobredeaux 425*9e965d6fSRomain Jobredeaux _assert_file( 426*9e965d6fSRomain Jobredeaux expected.compiled_assets, 427*9e965d6fSRomain Jobredeaux actual.compiled_assets, 428*9e965d6fSRomain Jobredeaux "ResourcesNodeInfo.compiled_assets", 429*9e965d6fSRomain Jobredeaux ) 430*9e965d6fSRomain Jobredeaux 431*9e965d6fSRomain Jobredeaux _assert_file( 432*9e965d6fSRomain Jobredeaux expected.compiled_resources, 433*9e965d6fSRomain Jobredeaux actual.compiled_resources, 434*9e965d6fSRomain Jobredeaux "ResourcesNodeInfo.compiled_resources", 435*9e965d6fSRomain Jobredeaux ) 436*9e965d6fSRomain Jobredeaux 437*9e965d6fSRomain Jobredeaux _assert_file( 438*9e965d6fSRomain Jobredeaux expected.r_txt, 439*9e965d6fSRomain Jobredeaux actual.r_txt, 440*9e965d6fSRomain Jobredeaux "ResourcesNodeInfo.r_txt", 441*9e965d6fSRomain Jobredeaux ) 442*9e965d6fSRomain Jobredeaux 443*9e965d6fSRomain Jobredeaux _assert_file( 444*9e965d6fSRomain Jobredeaux expected.manifest, 445*9e965d6fSRomain Jobredeaux actual.manifest, 446*9e965d6fSRomain Jobredeaux "ResourcesNodeInfo.manifest", 447*9e965d6fSRomain Jobredeaux ) 448*9e965d6fSRomain Jobredeaux 449*9e965d6fSRomain Jobredeaux if type(actual.exports_manifest) != "bool": 450*9e965d6fSRomain Jobredeaux fail("Error for ResourcesNodeInfo.exports_manifest, expected type bool, actual type is %s" % type(actual.exports_manifest)) 451*9e965d6fSRomain Jobredeaux if expected.exports_manifest != actual.exports_manifest: 452*9e965d6fSRomain Jobredeaux fail("""Error for ResourcesNodeInfo.exports_manifest, expected and actual values are not the same: 453*9e965d6fSRomain Jobredeauxexpected value: %s 454*9e965d6fSRomain Jobredeauxactual value: %s 455*9e965d6fSRomain Jobredeaux""" % (expected.exports_manifest, actual.exports_manifest)) 456*9e965d6fSRomain Jobredeaux 457*9e965d6fSRomain Jobredeauxdef _assert_resources_node_info_depset(expected_resources_node_infos, actual_depset, error_msg): 458*9e965d6fSRomain Jobredeaux actual_resources_node_infos = actual_depset.to_list() 459*9e965d6fSRomain Jobredeaux if len(expected_resources_node_infos) != len(actual_resources_node_infos): 460*9e965d6fSRomain Jobredeaux fail( 461*9e965d6fSRomain Jobredeaux "Error for StarlarkAndroidResourcesInfo.%s, expected size of list to be %d, got %d:\nExpected: %s\nActual: %s" % 462*9e965d6fSRomain Jobredeaux ( 463*9e965d6fSRomain Jobredeaux error_msg, 464*9e965d6fSRomain Jobredeaux len(expected_resources_node_infos), 465*9e965d6fSRomain Jobredeaux len(actual_resources_node_infos), 466*9e965d6fSRomain Jobredeaux [node.label for node in expected_resources_node_infos], 467*9e965d6fSRomain Jobredeaux [node.label for node in actual_resources_node_infos], 468*9e965d6fSRomain Jobredeaux ), 469*9e965d6fSRomain Jobredeaux ) 470*9e965d6fSRomain Jobredeaux for i in range(len(actual_resources_node_infos)): 471*9e965d6fSRomain Jobredeaux _assert_resources_node_info(expected_resources_node_infos[i], actual_resources_node_infos[i]) 472*9e965d6fSRomain Jobredeaux 473*9e965d6fSRomain Jobredeauxdef _assert_starlark_android_resources_info(expected, actual, label_under_test): 474*9e965d6fSRomain Jobredeaux _assert_resources_node_info_depset( 475*9e965d6fSRomain Jobredeaux expected.direct_resources_nodes, 476*9e965d6fSRomain Jobredeaux actual.direct_resources_nodes, 477*9e965d6fSRomain Jobredeaux "direct_resources_nodes", 478*9e965d6fSRomain Jobredeaux ) 479*9e965d6fSRomain Jobredeaux 480*9e965d6fSRomain Jobredeaux _assert_resources_node_info_depset( 481*9e965d6fSRomain Jobredeaux expected.transitive_resources_nodes, 482*9e965d6fSRomain Jobredeaux actual.transitive_resources_nodes, 483*9e965d6fSRomain Jobredeaux "transitive_resources_nodes", 484*9e965d6fSRomain Jobredeaux ) 485*9e965d6fSRomain Jobredeaux 486*9e965d6fSRomain Jobredeaux # Use the package from the target under test to shrink actual paths being compared down to the 487*9e965d6fSRomain Jobredeaux # name of the target. 488*9e965d6fSRomain Jobredeaux ignore_label_prefix = label_under_test.package + "/" 489*9e965d6fSRomain Jobredeaux 490*9e965d6fSRomain Jobredeaux _assert_file_depset( 491*9e965d6fSRomain Jobredeaux expected.transitive_assets, 492*9e965d6fSRomain Jobredeaux actual.transitive_assets, 493*9e965d6fSRomain Jobredeaux "StarlarkAndroidResourcesInfo.transitive_assets", 494*9e965d6fSRomain Jobredeaux ignore_label_prefix, 495*9e965d6fSRomain Jobredeaux ) 496*9e965d6fSRomain Jobredeaux _assert_file_depset( 497*9e965d6fSRomain Jobredeaux expected.transitive_assets_symbols, 498*9e965d6fSRomain Jobredeaux actual.transitive_assets_symbols, 499*9e965d6fSRomain Jobredeaux "StarlarkAndroidResourcesInfo.transitive_assets_symbols", 500*9e965d6fSRomain Jobredeaux ignore_label_prefix, 501*9e965d6fSRomain Jobredeaux ) 502*9e965d6fSRomain Jobredeaux _assert_file_depset( 503*9e965d6fSRomain Jobredeaux expected.transitive_compiled_resources, 504*9e965d6fSRomain Jobredeaux actual.transitive_compiled_resources, 505*9e965d6fSRomain Jobredeaux "StarlarkAndroidResourcesInfo.transitive_compiled_resources", 506*9e965d6fSRomain Jobredeaux ignore_label_prefix, 507*9e965d6fSRomain Jobredeaux ) 508*9e965d6fSRomain Jobredeaux for pkg, value in expected.packages_to_r_txts.items(): 509*9e965d6fSRomain Jobredeaux if pkg in actual.packages_to_r_txts: 510*9e965d6fSRomain Jobredeaux _assert_file_depset( 511*9e965d6fSRomain Jobredeaux value, 512*9e965d6fSRomain Jobredeaux actual.packages_to_r_txts[pkg], 513*9e965d6fSRomain Jobredeaux "StarlarkAndroidResourcesInfo.packages_to_r_txts[%s]" % pkg, 514*9e965d6fSRomain Jobredeaux ignore_label_prefix, 515*9e965d6fSRomain Jobredeaux ) 516*9e965d6fSRomain Jobredeaux else: 517*9e965d6fSRomain Jobredeaux fail("Error for StarlarkAndroidResourceInfo.packages_to_r_txts, expected key %s was not found" % pkg) 518*9e965d6fSRomain Jobredeaux 519*9e965d6fSRomain Jobredeaux_R_CLASS_ATTRS = dict( 520*9e965d6fSRomain Jobredeaux _r_class_check = attr.label( 521*9e965d6fSRomain Jobredeaux default = "//test/utils/java/com/google:RClassChecker_deploy.jar", 522*9e965d6fSRomain Jobredeaux executable = True, 523*9e965d6fSRomain Jobredeaux allow_files = True, 524*9e965d6fSRomain Jobredeaux cfg = "exec", 525*9e965d6fSRomain Jobredeaux ), 526*9e965d6fSRomain Jobredeaux expected_r_class_fields = attr.string_list(), 527*9e965d6fSRomain Jobredeaux) 528*9e965d6fSRomain Jobredeaux 529*9e965d6fSRomain Jobredeauxdef _assert_output_group_info(expected, actual): 530*9e965d6fSRomain Jobredeaux for key in expected: 531*9e965d6fSRomain Jobredeaux actual_attr = getattr(actual, key, None) 532*9e965d6fSRomain Jobredeaux if actual_attr == None: # both empty depset and list will fail. 533*9e965d6fSRomain Jobredeaux fail("%s is not defined in OutputGroupInfo: %s" % (key, actual)) 534*9e965d6fSRomain Jobredeaux _assert_files( 535*9e965d6fSRomain Jobredeaux expected[key], 536*9e965d6fSRomain Jobredeaux actual_attr.to_list(), 537*9e965d6fSRomain Jobredeaux "OutputGroupInfo." + key, 538*9e965d6fSRomain Jobredeaux ) 539*9e965d6fSRomain Jobredeaux 540*9e965d6fSRomain Jobredeauxdef _assert_generated_extension_registry_provider(expected, actual): 541*9e965d6fSRomain Jobredeaux if expected and not actual: 542*9e965d6fSRomain Jobredeaux fail("GeneratedExtensionRegistryProvider was expected but not found!") 543*9e965d6fSRomain Jobredeaux for key in expected: 544*9e965d6fSRomain Jobredeaux actual_attr = getattr(actual, key, None) 545*9e965d6fSRomain Jobredeaux if actual_attr == None: # both empty depset and list will fail. 546*9e965d6fSRomain Jobredeaux fail("%s is not defined in OutputGroupInfo: %s" % (key, actual)) 547*9e965d6fSRomain Jobredeaux 548*9e965d6fSRomain Jobredeaux _assert_files( 549*9e965d6fSRomain Jobredeaux expected[key], 550*9e965d6fSRomain Jobredeaux [actual_attr] if type(actual_attr) != "depset" else actual_attr.to_list(), 551*9e965d6fSRomain Jobredeaux "GeneratedExtensionRegistryProvider." + key, 552*9e965d6fSRomain Jobredeaux ) 553*9e965d6fSRomain Jobredeaux 554*9e965d6fSRomain Jobredeauxdef _is_suffix_sublist(full, suffixes): 555*9e965d6fSRomain Jobredeaux """Returns whether suffixes is a sublist of suffixes of full.""" 556*9e965d6fSRomain Jobredeaux for (fi, _) in enumerate(full): 557*9e965d6fSRomain Jobredeaux sublist_match = True 558*9e965d6fSRomain Jobredeaux for (si, sv) in enumerate(suffixes): 559*9e965d6fSRomain Jobredeaux if (fi + si >= len(full)) or not full[fi + si].endswith(sv): 560*9e965d6fSRomain Jobredeaux sublist_match = False 561*9e965d6fSRomain Jobredeaux break 562*9e965d6fSRomain Jobredeaux if sublist_match: 563*9e965d6fSRomain Jobredeaux return True 564*9e965d6fSRomain Jobredeaux return False 565*9e965d6fSRomain Jobredeaux 566*9e965d6fSRomain Jobredeauxdef _check_actions(inspect, actions): 567*9e965d6fSRomain Jobredeaux for mnemonic, expected_argvs in inspect.items(): 568*9e965d6fSRomain Jobredeaux # Action mnemonic is not unique, even in the context of a target, hence 569*9e965d6fSRomain Jobredeaux # it is necessary to find all actions and compare argv. If there are no 570*9e965d6fSRomain Jobredeaux # matches among the actions that match the mnemonic, fail and present 571*9e965d6fSRomain Jobredeaux # all the possible actions that could have matched. 572*9e965d6fSRomain Jobredeaux mnemonic_matching_actions = [] 573*9e965d6fSRomain Jobredeaux mnemonic_match = False 574*9e965d6fSRomain Jobredeaux for _, value in actions.by_file.items(): 575*9e965d6fSRomain Jobredeaux # TODO(b/130571505): Remove this after SpawnActionTemplate is supported in Starlark 576*9e965d6fSRomain Jobredeaux if not (hasattr(value, "mnemonic") and hasattr(value, "argv")): 577*9e965d6fSRomain Jobredeaux continue 578*9e965d6fSRomain Jobredeaux 579*9e965d6fSRomain Jobredeaux if mnemonic != value.mnemonic: 580*9e965d6fSRomain Jobredeaux continue 581*9e965d6fSRomain Jobredeaux mnemonic_match = True 582*9e965d6fSRomain Jobredeaux 583*9e965d6fSRomain Jobredeaux if _is_suffix_sublist(value.argv, expected_argvs): 584*9e965d6fSRomain Jobredeaux # When there is a match, clear the actions stored for displaying 585*9e965d6fSRomain Jobredeaux # an error messaage. 586*9e965d6fSRomain Jobredeaux mnemonic_matching_actions = [] 587*9e965d6fSRomain Jobredeaux break 588*9e965d6fSRomain Jobredeaux else: 589*9e965d6fSRomain Jobredeaux mnemonic_matching_actions.append(value) 590*9e965d6fSRomain Jobredeaux 591*9e965d6fSRomain Jobredeaux if not mnemonic_match: 592*9e965d6fSRomain Jobredeaux fail("%s action not found." % mnemonic) 593*9e965d6fSRomain Jobredeaux if mnemonic_matching_actions: 594*9e965d6fSRomain Jobredeaux # If there are mnemonic_matching_actions, then the argvs did not 595*9e965d6fSRomain Jobredeaux # align. Fail but show the other actions that were created. 596*9e965d6fSRomain Jobredeaux error_message = ( 597*9e965d6fSRomain Jobredeaux "%s with the following argv not found: %s\nSimilar actions:\n" % 598*9e965d6fSRomain Jobredeaux (mnemonic, expected_argvs) 599*9e965d6fSRomain Jobredeaux ) 600*9e965d6fSRomain Jobredeaux for i, action in enumerate(mnemonic_matching_actions): 601*9e965d6fSRomain Jobredeaux error_message += ( 602*9e965d6fSRomain Jobredeaux "%d. Progress Message: %s\n Argv: %s\n\n" % 603*9e965d6fSRomain Jobredeaux (i + 1, action, action.argv) 604*9e965d6fSRomain Jobredeaux ) 605*9e965d6fSRomain Jobredeaux fail(error_message) 606*9e965d6fSRomain Jobredeaux 607*9e965d6fSRomain Jobredeaux_ACTIONS_ATTRS = dict( 608*9e965d6fSRomain Jobredeaux inspect_actions = attr.string_list_dict(), 609*9e965d6fSRomain Jobredeaux) 610*9e965d6fSRomain Jobredeaux 611*9e965d6fSRomain Jobredeauxasserts = struct( 612*9e965d6fSRomain Jobredeaux provider = struct( 613*9e965d6fSRomain Jobredeaux attrs = _ATTRS, 614*9e965d6fSRomain Jobredeaux default_info = _assert_default_info, 615*9e965d6fSRomain Jobredeaux java_info = _assert_java_info, 616*9e965d6fSRomain Jobredeaux proguard_spec_provider = _assert_proguard_spec_provider, 617*9e965d6fSRomain Jobredeaux starlark_android_resources_info = _assert_starlark_android_resources_info, 618*9e965d6fSRomain Jobredeaux output_group_info = _assert_output_group_info, 619*9e965d6fSRomain Jobredeaux native_libs_info = _assert_native_libs_info, 620*9e965d6fSRomain Jobredeaux generated_extension_registry_provider = _assert_generated_extension_registry_provider, 621*9e965d6fSRomain Jobredeaux ), 622*9e965d6fSRomain Jobredeaux files = _assert_files, 623*9e965d6fSRomain Jobredeaux r_class = struct( 624*9e965d6fSRomain Jobredeaux attrs = _R_CLASS_ATTRS, 625*9e965d6fSRomain Jobredeaux ), 626*9e965d6fSRomain Jobredeaux actions = struct( 627*9e965d6fSRomain Jobredeaux attrs = _ACTIONS_ATTRS, 628*9e965d6fSRomain Jobredeaux check_actions = _check_actions, 629*9e965d6fSRomain Jobredeaux ), 630*9e965d6fSRomain Jobredeaux) 631