1*d4726bddSHONG Yifan"""End to end tests for rust toolchains.""" 2*d4726bddSHONG Yifan 3*d4726bddSHONG Yifanload("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") 4*d4726bddSHONG Yifanload("@bazel_skylib//rules:write_file.bzl", "write_file") 5*d4726bddSHONG Yifanload("//rust:defs.bzl", "rust_library", "rust_shared_library") 6*d4726bddSHONG Yifanload("//rust:toolchain.bzl", "rust_stdlib_filegroup", "rust_toolchain") 7*d4726bddSHONG Yifan 8*d4726bddSHONG YifanEXEC_TOOLCHAIN_FLAG = "missing" 9*d4726bddSHONG YifanTOOLCHAIN_FLAG = "before" 10*d4726bddSHONG YifanCONFIG_FLAG = "after" 11*d4726bddSHONG YifanCRATE_FLAGS = {"cdylib": ["cdylib_flag"], "rlib": ["rlib_flag"]} 12*d4726bddSHONG Yifan 13*d4726bddSHONG Yifandef _toolchain_adds_rustc_flags_impl(ctx, crate_type): 14*d4726bddSHONG Yifan """ Tests adding extra_rustc_flags on the toolchain, asserts that: 15*d4726bddSHONG Yifan 16*d4726bddSHONG Yifan - extra_rustc_flags added by the toolchain are applied BEFORE flags added by a config on the commandline 17*d4726bddSHONG Yifan - The exec flags from the toolchain don't go on the commandline for a non-exec target 18*d4726bddSHONG Yifan - crate type rustc flags are added 19*d4726bddSHONG Yifan """ 20*d4726bddSHONG Yifan env = analysistest.begin(ctx) 21*d4726bddSHONG Yifan target = analysistest.target_under_test(env) 22*d4726bddSHONG Yifan action = target[DepActionsInfo].actions[0] 23*d4726bddSHONG Yifan 24*d4726bddSHONG Yifan asserts.equals(env, "Rustc", action.mnemonic) 25*d4726bddSHONG Yifan 26*d4726bddSHONG Yifan asserts.true( 27*d4726bddSHONG Yifan env, 28*d4726bddSHONG Yifan action.argv[-2:] == [TOOLCHAIN_FLAG, CONFIG_FLAG], 29*d4726bddSHONG Yifan "Unexpected rustc flags: {}\nShould have ended with: {}".format( 30*d4726bddSHONG Yifan action.argv, 31*d4726bddSHONG Yifan [TOOLCHAIN_FLAG, CONFIG_FLAG], 32*d4726bddSHONG Yifan ), 33*d4726bddSHONG Yifan ) 34*d4726bddSHONG Yifan 35*d4726bddSHONG Yifan asserts.true( 36*d4726bddSHONG Yifan env, 37*d4726bddSHONG Yifan action.argv[-3] == CRATE_FLAGS[crate_type][0], 38*d4726bddSHONG Yifan "Unexpected rustc flags: {}\nShould have contained: {}".format( 39*d4726bddSHONG Yifan action.argv, 40*d4726bddSHONG Yifan CRATE_FLAGS["rlib"], 41*d4726bddSHONG Yifan ), 42*d4726bddSHONG Yifan ) 43*d4726bddSHONG Yifan 44*d4726bddSHONG Yifan for type in CRATE_FLAGS.keys(): 45*d4726bddSHONG Yifan if type == crate_type: 46*d4726bddSHONG Yifan continue 47*d4726bddSHONG Yifan asserts.false( 48*d4726bddSHONG Yifan env, 49*d4726bddSHONG Yifan CRATE_FLAGS[type][0] in action.argv, 50*d4726bddSHONG Yifan "Unexpected rustc flags: {}\nShould not contain: {}".format( 51*d4726bddSHONG Yifan action.argv, 52*d4726bddSHONG Yifan CRATE_FLAGS[type], 53*d4726bddSHONG Yifan ), 54*d4726bddSHONG Yifan ) 55*d4726bddSHONG Yifan 56*d4726bddSHONG Yifan asserts.true( 57*d4726bddSHONG Yifan env, 58*d4726bddSHONG Yifan EXEC_TOOLCHAIN_FLAG not in action.argv, 59*d4726bddSHONG Yifan "Found exec toolchain flag ({}) in rustc flags: {}".format(EXEC_TOOLCHAIN_FLAG, action.argv), 60*d4726bddSHONG Yifan ) 61*d4726bddSHONG Yifan 62*d4726bddSHONG Yifan found_sysroot = False 63*d4726bddSHONG Yifan for arg in action.argv: 64*d4726bddSHONG Yifan if arg.startswith("--sysroot") and arg.endswith("test/toolchain/rust_extra_flags_toolchain"): 65*d4726bddSHONG Yifan found_sysroot = True 66*d4726bddSHONG Yifan asserts.true( 67*d4726bddSHONG Yifan env, 68*d4726bddSHONG Yifan found_sysroot, 69*d4726bddSHONG Yifan "Missing --sysroot flag or --sysroot does not point to correct sysroot directory", 70*d4726bddSHONG Yifan ) 71*d4726bddSHONG Yifan 72*d4726bddSHONG Yifan return analysistest.end(env) 73*d4726bddSHONG Yifan 74*d4726bddSHONG Yifandef _toolchain_adds_rustc_flags_lib_impl(ctx): 75*d4726bddSHONG Yifan return _toolchain_adds_rustc_flags_impl(ctx, "rlib") 76*d4726bddSHONG Yifan 77*d4726bddSHONG Yifandef _toolchain_adds_rustc_flags_shared_lib_impl(ctx): 78*d4726bddSHONG Yifan return _toolchain_adds_rustc_flags_impl(ctx, "cdylib") 79*d4726bddSHONG Yifan 80*d4726bddSHONG Yifantoolchain_adds_rustc_flags_lib_test = analysistest.make( 81*d4726bddSHONG Yifan _toolchain_adds_rustc_flags_lib_impl, 82*d4726bddSHONG Yifan config_settings = { 83*d4726bddSHONG Yifan str(Label("//:extra_rustc_flags")): [CONFIG_FLAG], 84*d4726bddSHONG Yifan str(Label("//rust/settings:experimental_toolchain_generated_sysroot")): True, 85*d4726bddSHONG Yifan }, 86*d4726bddSHONG Yifan) 87*d4726bddSHONG Yifan 88*d4726bddSHONG Yifantoolchain_adds_rustc_flags_shared_lib_test = analysistest.make( 89*d4726bddSHONG Yifan _toolchain_adds_rustc_flags_shared_lib_impl, 90*d4726bddSHONG Yifan config_settings = { 91*d4726bddSHONG Yifan str(Label("//:extra_rustc_flags")): [CONFIG_FLAG], 92*d4726bddSHONG Yifan str(Label("//rust/settings:experimental_toolchain_generated_sysroot")): True, 93*d4726bddSHONG Yifan }, 94*d4726bddSHONG Yifan) 95*d4726bddSHONG Yifan 96*d4726bddSHONG Yifandef _extra_toolchain_transition_impl(settings, _attr): 97*d4726bddSHONG Yifan return {"//command_line_option:extra_toolchains": [ 98*d4726bddSHONG Yifan "@rules_rust//test/toolchain:extra_flags_toolchain", 99*d4726bddSHONG Yifan ] + settings["//command_line_option:extra_toolchains"]} 100*d4726bddSHONG Yifan 101*d4726bddSHONG Yifan_extra_toolchain_transition = transition( 102*d4726bddSHONG Yifan implementation = _extra_toolchain_transition_impl, 103*d4726bddSHONG Yifan inputs = ["//command_line_option:extra_toolchains"], 104*d4726bddSHONG Yifan outputs = ["//command_line_option:extra_toolchains"], 105*d4726bddSHONG Yifan) 106*d4726bddSHONG Yifan 107*d4726bddSHONG YifanDepActionsInfo = provider( 108*d4726bddSHONG Yifan "Contains information about dependencies actions.", 109*d4726bddSHONG Yifan fields = {"actions": "List[Action]"}, 110*d4726bddSHONG Yifan) 111*d4726bddSHONG Yifan 112*d4726bddSHONG Yifandef _collect_dep_actions_aspect_impl(target, ctx): 113*d4726bddSHONG Yifan actions = [] 114*d4726bddSHONG Yifan actions.extend(target.actions) 115*d4726bddSHONG Yifan for dep in ctx.rule.attr.deps: 116*d4726bddSHONG Yifan actions.extend(dep[DepActionsInfo].actions) 117*d4726bddSHONG Yifan return [DepActionsInfo(actions = actions)] 118*d4726bddSHONG Yifan 119*d4726bddSHONG Yifancollect_dep_actions_aspect = aspect( 120*d4726bddSHONG Yifan implementation = _collect_dep_actions_aspect_impl, 121*d4726bddSHONG Yifan attr_aspects = ["deps"], 122*d4726bddSHONG Yifan) 123*d4726bddSHONG Yifan 124*d4726bddSHONG Yifandef _extra_toolchain_wrapper_impl(ctx): 125*d4726bddSHONG Yifan return [ctx.attr.dep[DepActionsInfo]] 126*d4726bddSHONG Yifan 127*d4726bddSHONG Yifanextra_toolchain_wrapper = rule( 128*d4726bddSHONG Yifan implementation = _extra_toolchain_wrapper_impl, 129*d4726bddSHONG Yifan attrs = { 130*d4726bddSHONG Yifan "dep": attr.label(aspects = [collect_dep_actions_aspect]), 131*d4726bddSHONG Yifan "_allowlist_function_transition": attr.label( 132*d4726bddSHONG Yifan default = "@bazel_tools//tools/allowlists/function_transition_allowlist", 133*d4726bddSHONG Yifan ), 134*d4726bddSHONG Yifan }, 135*d4726bddSHONG Yifan cfg = _extra_toolchain_transition, 136*d4726bddSHONG Yifan) 137*d4726bddSHONG Yifan 138*d4726bddSHONG Yifandef _define_targets(): 139*d4726bddSHONG Yifan rust_library( 140*d4726bddSHONG Yifan name = "lib", 141*d4726bddSHONG Yifan srcs = ["lib.rs"], 142*d4726bddSHONG Yifan edition = "2021", 143*d4726bddSHONG Yifan ) 144*d4726bddSHONG Yifan 145*d4726bddSHONG Yifan rust_shared_library( 146*d4726bddSHONG Yifan name = "shared_lib", 147*d4726bddSHONG Yifan srcs = ["lib.rs"], 148*d4726bddSHONG Yifan edition = "2021", 149*d4726bddSHONG Yifan ) 150*d4726bddSHONG Yifan 151*d4726bddSHONG Yifan native.filegroup( 152*d4726bddSHONG Yifan name = "stdlib_srcs", 153*d4726bddSHONG Yifan srcs = ["config.txt"], 154*d4726bddSHONG Yifan ) 155*d4726bddSHONG Yifan rust_stdlib_filegroup( 156*d4726bddSHONG Yifan name = "std_libs", 157*d4726bddSHONG Yifan srcs = [":stdlib_srcs"], 158*d4726bddSHONG Yifan ) 159*d4726bddSHONG Yifan write_file( 160*d4726bddSHONG Yifan name = "mock_rustc", 161*d4726bddSHONG Yifan out = "mock_rustc.exe", 162*d4726bddSHONG Yifan content = [], 163*d4726bddSHONG Yifan is_executable = True, 164*d4726bddSHONG Yifan ) 165*d4726bddSHONG Yifan write_file( 166*d4726bddSHONG Yifan name = "mock_rustdoc", 167*d4726bddSHONG Yifan out = "mock_rustdoc.exe", 168*d4726bddSHONG Yifan content = [], 169*d4726bddSHONG Yifan is_executable = True, 170*d4726bddSHONG Yifan ) 171*d4726bddSHONG Yifan 172*d4726bddSHONG Yifan rust_toolchain( 173*d4726bddSHONG Yifan name = "rust_extra_flags_toolchain", 174*d4726bddSHONG Yifan binary_ext = "", 175*d4726bddSHONG Yifan dylib_ext = ".so", 176*d4726bddSHONG Yifan exec_triple = "x86_64-unknown-none", 177*d4726bddSHONG Yifan target_triple = "x86_64-unknown-none", 178*d4726bddSHONG Yifan rust_doc = ":mock_rustdoc", 179*d4726bddSHONG Yifan rust_std = ":std_libs", 180*d4726bddSHONG Yifan rustc = ":mock_rustc", 181*d4726bddSHONG Yifan staticlib_ext = ".a", 182*d4726bddSHONG Yifan stdlib_linkflags = [], 183*d4726bddSHONG Yifan extra_rustc_flags = [TOOLCHAIN_FLAG], 184*d4726bddSHONG Yifan extra_exec_rustc_flags = [EXEC_TOOLCHAIN_FLAG], 185*d4726bddSHONG Yifan extra_rustc_flags_for_crate_types = CRATE_FLAGS, 186*d4726bddSHONG Yifan visibility = ["//visibility:public"], 187*d4726bddSHONG Yifan ) 188*d4726bddSHONG Yifan 189*d4726bddSHONG Yifan native.toolchain( 190*d4726bddSHONG Yifan name = "extra_flags_toolchain", 191*d4726bddSHONG Yifan toolchain = ":rust_extra_flags_toolchain", 192*d4726bddSHONG Yifan toolchain_type = "@rules_rust//rust:toolchain", 193*d4726bddSHONG Yifan ) 194*d4726bddSHONG Yifan 195*d4726bddSHONG Yifan extra_toolchain_wrapper( 196*d4726bddSHONG Yifan name = "lib_with_extra_toolchain", 197*d4726bddSHONG Yifan dep = ":lib", 198*d4726bddSHONG Yifan ) 199*d4726bddSHONG Yifan 200*d4726bddSHONG Yifan extra_toolchain_wrapper( 201*d4726bddSHONG Yifan name = "shared_lib_with_extra_toolchain", 202*d4726bddSHONG Yifan dep = ":shared_lib", 203*d4726bddSHONG Yifan ) 204*d4726bddSHONG Yifan 205*d4726bddSHONG Yifandef _rust_stdlib_filegroup_provides_runfiles_test_impl(ctx): 206*d4726bddSHONG Yifan env = analysistest.begin(ctx) 207*d4726bddSHONG Yifan target = analysistest.target_under_test(env) 208*d4726bddSHONG Yifan runfiles = target[DefaultInfo].default_runfiles 209*d4726bddSHONG Yifan asserts.true(env, len(runfiles.files.to_list()) > 0) 210*d4726bddSHONG Yifan 211*d4726bddSHONG Yifan return analysistest.end(env) 212*d4726bddSHONG Yifan 213*d4726bddSHONG Yifanrust_stdlib_filegroup_provides_runfiles_test = analysistest.make( 214*d4726bddSHONG Yifan _rust_stdlib_filegroup_provides_runfiles_test_impl, 215*d4726bddSHONG Yifan) 216*d4726bddSHONG Yifan 217*d4726bddSHONG Yifandef toolchain_test_suite(name): 218*d4726bddSHONG Yifan """ Instantiates tests for rust toolchains. 219*d4726bddSHONG Yifan 220*d4726bddSHONG Yifan Args: 221*d4726bddSHONG Yifan name: a name for the test suite 222*d4726bddSHONG Yifan """ 223*d4726bddSHONG Yifan _define_targets() 224*d4726bddSHONG Yifan 225*d4726bddSHONG Yifan toolchain_adds_rustc_flags_lib_test( 226*d4726bddSHONG Yifan name = "toolchain_adds_rustc_flags_lib_test", 227*d4726bddSHONG Yifan target_under_test = ":lib_with_extra_toolchain", 228*d4726bddSHONG Yifan ) 229*d4726bddSHONG Yifan 230*d4726bddSHONG Yifan toolchain_adds_rustc_flags_shared_lib_test( 231*d4726bddSHONG Yifan name = "toolchain_adds_rustc_flags_shared_lib_test", 232*d4726bddSHONG Yifan target_under_test = ":shared_lib_with_extra_toolchain", 233*d4726bddSHONG Yifan ) 234*d4726bddSHONG Yifan 235*d4726bddSHONG Yifan rust_stdlib_filegroup_provides_runfiles_test( 236*d4726bddSHONG Yifan name = "rust_stdlib_filegroup_provides_runfiles_test", 237*d4726bddSHONG Yifan target_under_test = ":std_libs", 238*d4726bddSHONG Yifan ) 239*d4726bddSHONG Yifan 240*d4726bddSHONG Yifan native.test_suite( 241*d4726bddSHONG Yifan name = name, 242*d4726bddSHONG Yifan tests = [ 243*d4726bddSHONG Yifan ":toolchain_adds_rustc_flags_lib_test", 244*d4726bddSHONG Yifan ":toolchain_adds_rustc_flags_shared_lib_test", 245*d4726bddSHONG Yifan ":rust_stdlib_filegroup_provides_runfiles_test", 246*d4726bddSHONG Yifan ], 247*d4726bddSHONG Yifan ) 248