1*d6050574SRomain Jobredeaux# Copyright 2022 The Bazel Authors. All rights reserved. 2*d6050574SRomain Jobredeaux# 3*d6050574SRomain Jobredeaux# Licensed under the Apache License, Version 2.0 (the "License"); 4*d6050574SRomain Jobredeaux# you may not use this file except in compliance with the License. 5*d6050574SRomain Jobredeaux# You may obtain a copy of the License at 6*d6050574SRomain Jobredeaux# 7*d6050574SRomain Jobredeaux# http://www.apache.org/licenses/LICENSE-2.0 8*d6050574SRomain Jobredeaux# 9*d6050574SRomain Jobredeaux# Unless required by applicable law or agreed to in writing, software 10*d6050574SRomain Jobredeaux# distributed under the License is distributed on an "AS IS" BASIS, 11*d6050574SRomain Jobredeaux# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*d6050574SRomain Jobredeaux# See the License for the specific language governing permissions and 13*d6050574SRomain Jobredeaux# limitations under the License. 14*d6050574SRomain Jobredeaux 15*d6050574SRomain Jobredeaux"""Unit tests for analysis_test.bzl.""" 16*d6050574SRomain Jobredeaux 17*d6050574SRomain Jobredeauxload("//lib:analysis_test.bzl", "analysis_test", "test_suite") 18*d6050574SRomain Jobredeauxload("//lib:truth.bzl", "matching") 19*d6050574SRomain Jobredeauxload("//lib:util.bzl", "TestingAspectInfo") 20*d6050574SRomain Jobredeaux 21*d6050574SRomain Jobredeaux################################### 22*d6050574SRomain Jobredeaux####### change_setting_test ####### 23*d6050574SRomain Jobredeaux################################### 24*d6050574SRomain Jobredeaux 25*d6050574SRomain Jobredeaux_ChangeSettingInfo = provider( 26*d6050574SRomain Jobredeaux doc = "min_os_version for change_setting_test", 27*d6050574SRomain Jobredeaux fields = ["min_os_version"], 28*d6050574SRomain Jobredeaux) 29*d6050574SRomain Jobredeaux 30*d6050574SRomain Jobredeauxdef _change_setting_fake_rule(ctx): 31*d6050574SRomain Jobredeaux return [_ChangeSettingInfo(min_os_version = ctx.fragments.cpp.minimum_os_version())] 32*d6050574SRomain Jobredeaux 33*d6050574SRomain Jobredeauxchange_setting_fake_rule = rule( 34*d6050574SRomain Jobredeaux implementation = _change_setting_fake_rule, 35*d6050574SRomain Jobredeaux fragments = ["cpp"], 36*d6050574SRomain Jobredeaux) 37*d6050574SRomain Jobredeaux 38*d6050574SRomain Jobredeauxdef test_change_setting(name): 39*d6050574SRomain Jobredeaux """Test to verify that an analysis test may change configuration.""" 40*d6050574SRomain Jobredeaux change_setting_fake_rule(name = name + "_fake_target", tags = ["manual"]) 41*d6050574SRomain Jobredeaux 42*d6050574SRomain Jobredeaux analysis_test( 43*d6050574SRomain Jobredeaux name = name, 44*d6050574SRomain Jobredeaux target = name + "_fake_target", 45*d6050574SRomain Jobredeaux impl = _test_change_setting, 46*d6050574SRomain Jobredeaux config_settings = { 47*d6050574SRomain Jobredeaux "//command_line_option:minimum_os_version": "1234.5678", 48*d6050574SRomain Jobredeaux }, 49*d6050574SRomain Jobredeaux ) 50*d6050574SRomain Jobredeaux 51*d6050574SRomain Jobredeauxdef _test_change_setting(env, target): 52*d6050574SRomain Jobredeaux dep_min_os_version = target[_ChangeSettingInfo].min_os_version 53*d6050574SRomain Jobredeaux env.expect.that_str(dep_min_os_version).equals("1234.5678") 54*d6050574SRomain Jobredeaux 55*d6050574SRomain Jobredeaux#################################### 56*d6050574SRomain Jobredeaux####### failure_testing_test ####### 57*d6050574SRomain Jobredeaux#################################### 58*d6050574SRomain Jobredeaux 59*d6050574SRomain Jobredeauxdef _failure_testing_fake_rule(_ctx): 60*d6050574SRomain Jobredeaux fail("This rule should never work") 61*d6050574SRomain Jobredeaux 62*d6050574SRomain Jobredeauxfailure_testing_fake_rule = rule( 63*d6050574SRomain Jobredeaux implementation = _failure_testing_fake_rule, 64*d6050574SRomain Jobredeaux) 65*d6050574SRomain Jobredeaux 66*d6050574SRomain Jobredeauxdef test_failure_testing(name): 67*d6050574SRomain Jobredeaux """Test to verify that an analysis test may verify a rule fails with fail().""" 68*d6050574SRomain Jobredeaux failure_testing_fake_rule(name = name + "_fake_target", tags = ["manual"]) 69*d6050574SRomain Jobredeaux 70*d6050574SRomain Jobredeaux analysis_test( 71*d6050574SRomain Jobredeaux name = name, 72*d6050574SRomain Jobredeaux target = name + "_fake_target", 73*d6050574SRomain Jobredeaux impl = _test_failure_testing, 74*d6050574SRomain Jobredeaux expect_failure = True, 75*d6050574SRomain Jobredeaux ) 76*d6050574SRomain Jobredeaux 77*d6050574SRomain Jobredeauxdef _test_failure_testing(env, target): 78*d6050574SRomain Jobredeaux env.expect.that_target(target).failures().contains_predicate(matching.contains("This rule should never work")) 79*d6050574SRomain Jobredeaux 80*d6050574SRomain Jobredeaux############################################ 81*d6050574SRomain Jobredeaux####### fail_unexpected_passing_test ####### 82*d6050574SRomain Jobredeaux############################################ 83*d6050574SRomain Jobredeaux 84*d6050574SRomain Jobredeauxdef _fail_unexpected_passing_fake_rule(_ctx): 85*d6050574SRomain Jobredeaux return [] 86*d6050574SRomain Jobredeaux 87*d6050574SRomain Jobredeauxfail_unexpected_passing_fake_rule = rule( 88*d6050574SRomain Jobredeaux implementation = _fail_unexpected_passing_fake_rule, 89*d6050574SRomain Jobredeaux) 90*d6050574SRomain Jobredeaux 91*d6050574SRomain Jobredeaux# @unused # TODO(ilist): add a shell test checking it fails 92*d6050574SRomain Jobredeauxdef test_fail_unexpected_passing(name): 93*d6050574SRomain Jobredeaux """Test that fails by expecting an error that never occurs.""" 94*d6050574SRomain Jobredeaux fail_unexpected_passing_fake_rule(name = name + "_fake_target", tags = ["manual"]) 95*d6050574SRomain Jobredeaux 96*d6050574SRomain Jobredeaux analysis_test( 97*d6050574SRomain Jobredeaux name = name, 98*d6050574SRomain Jobredeaux target = name + "_fake_target", 99*d6050574SRomain Jobredeaux impl = _test_fail_unexpected_passing, 100*d6050574SRomain Jobredeaux expect_failure = True, 101*d6050574SRomain Jobredeaux ) 102*d6050574SRomain Jobredeaux 103*d6050574SRomain Jobredeauxdef _test_fail_unexpected_passing(env, target): 104*d6050574SRomain Jobredeaux env.expect.that_target(target).failures().contains_predicate(matching.contains("Oh no, going to fail")) 105*d6050574SRomain Jobredeaux 106*d6050574SRomain Jobredeaux################################################ 107*d6050574SRomain Jobredeaux####### change_setting_with_failure_test ####### 108*d6050574SRomain Jobredeaux################################################ 109*d6050574SRomain Jobredeauxdef _change_setting_with_failure_fake_rule(ctx): 110*d6050574SRomain Jobredeaux if ctx.fragments.cpp.minimum_os_version() == "error_error": 111*d6050574SRomain Jobredeaux fail("unexpected minimum_os_version!!!") 112*d6050574SRomain Jobredeaux return [] 113*d6050574SRomain Jobredeaux 114*d6050574SRomain Jobredeauxchange_setting_with_failure_fake_rule = rule( 115*d6050574SRomain Jobredeaux implementation = _change_setting_with_failure_fake_rule, 116*d6050574SRomain Jobredeaux fragments = ["cpp"], 117*d6050574SRomain Jobredeaux) 118*d6050574SRomain Jobredeaux 119*d6050574SRomain Jobredeauxdef test_change_setting_with_failure(name): 120*d6050574SRomain Jobredeaux change_setting_with_failure_fake_rule(name = name + "_fake_target", tags = ["manual"]) 121*d6050574SRomain Jobredeaux 122*d6050574SRomain Jobredeaux analysis_test( 123*d6050574SRomain Jobredeaux name = name, 124*d6050574SRomain Jobredeaux target = name + "_fake_target", 125*d6050574SRomain Jobredeaux impl = _test_change_setting_with_failure, 126*d6050574SRomain Jobredeaux expect_failure = True, 127*d6050574SRomain Jobredeaux config_settings = { 128*d6050574SRomain Jobredeaux "//command_line_option:minimum_os_version": "error_error", 129*d6050574SRomain Jobredeaux }, 130*d6050574SRomain Jobredeaux ) 131*d6050574SRomain Jobredeaux 132*d6050574SRomain Jobredeauxdef _test_change_setting_with_failure(env, target): 133*d6050574SRomain Jobredeaux """Test verifying failure while changing configuration.""" 134*d6050574SRomain Jobredeaux env.expect.that_target(target).failures().contains_predicate( 135*d6050574SRomain Jobredeaux matching.contains("unexpected minimum_os_version!!!"), 136*d6050574SRomain Jobredeaux ) 137*d6050574SRomain Jobredeaux 138*d6050574SRomain Jobredeaux#################################### 139*d6050574SRomain Jobredeaux####### inspect_actions_test ####### 140*d6050574SRomain Jobredeaux#################################### 141*d6050574SRomain Jobredeauxdef _inspect_actions_fake_rule(ctx): 142*d6050574SRomain Jobredeaux out_file = ctx.actions.declare_file("out.txt") 143*d6050574SRomain Jobredeaux ctx.actions.run_shell( 144*d6050574SRomain Jobredeaux command = "echo 'hello' > %s" % out_file.basename, 145*d6050574SRomain Jobredeaux outputs = [out_file], 146*d6050574SRomain Jobredeaux ) 147*d6050574SRomain Jobredeaux return [DefaultInfo(files = depset([out_file]))] 148*d6050574SRomain Jobredeaux 149*d6050574SRomain Jobredeauxinspect_actions_fake_rule = rule(implementation = _inspect_actions_fake_rule) 150*d6050574SRomain Jobredeaux 151*d6050574SRomain Jobredeauxdef test_inspect_actions(name): 152*d6050574SRomain Jobredeaux """Test verifying actions registered by a target.""" 153*d6050574SRomain Jobredeaux inspect_actions_fake_rule(name = name + "_fake_target", tags = ["manual"]) 154*d6050574SRomain Jobredeaux 155*d6050574SRomain Jobredeaux analysis_test(name = name, target = name + "_fake_target", impl = _test_inspect_actions) 156*d6050574SRomain Jobredeaux 157*d6050574SRomain Jobredeauxdef _test_inspect_actions(env, target): 158*d6050574SRomain Jobredeaux env.expect.that_int(len(target[TestingAspectInfo].actions)).equals(1) 159*d6050574SRomain Jobredeaux action_output = target[TestingAspectInfo].actions[0].outputs.to_list()[0] 160*d6050574SRomain Jobredeaux env.expect.that_str(action_output.basename).equals("out.txt") 161*d6050574SRomain Jobredeaux 162*d6050574SRomain Jobredeaux#################################### 163*d6050574SRomain Jobredeaux####### inspect_aspect_test ####### 164*d6050574SRomain Jobredeaux#################################### 165*d6050574SRomain Jobredeaux_AddedByAspectInfo = provider( 166*d6050574SRomain Jobredeaux doc = "Example provider added by example aspect", 167*d6050574SRomain Jobredeaux fields = {"value": "(str)"}, 168*d6050574SRomain Jobredeaux) 169*d6050574SRomain Jobredeaux 170*d6050574SRomain Jobredeauxdef _example_aspect_impl(_target, _ctx): 171*d6050574SRomain Jobredeaux return [_AddedByAspectInfo(value = "attached by aspect")] 172*d6050574SRomain Jobredeaux 173*d6050574SRomain Jobredeauxexample_aspect = aspect(implementation = _example_aspect_impl) 174*d6050574SRomain Jobredeaux 175*d6050574SRomain Jobredeauxdef _inspect_aspect_fake_rule(ctx): 176*d6050574SRomain Jobredeaux out_file = ctx.actions.declare_file("out.txt") 177*d6050574SRomain Jobredeaux ctx.actions.run_shell( 178*d6050574SRomain Jobredeaux command = "echo 'hello' > %s" % out_file.basename, 179*d6050574SRomain Jobredeaux outputs = [out_file], 180*d6050574SRomain Jobredeaux ) 181*d6050574SRomain Jobredeaux return [DefaultInfo(files = depset([out_file]))] 182*d6050574SRomain Jobredeaux 183*d6050574SRomain Jobredeauxinspect_aspect_fake_rule = rule(implementation = _inspect_aspect_fake_rule) 184*d6050574SRomain Jobredeaux 185*d6050574SRomain Jobredeauxdef test_inspect_aspect(name): 186*d6050574SRomain Jobredeaux """Test verifying aspect run on a target.""" 187*d6050574SRomain Jobredeaux inspect_aspect_fake_rule(name = name + "_fake_target", tags = ["manual"]) 188*d6050574SRomain Jobredeaux 189*d6050574SRomain Jobredeaux analysis_test( 190*d6050574SRomain Jobredeaux name = name, 191*d6050574SRomain Jobredeaux target = name + "_fake_target", 192*d6050574SRomain Jobredeaux impl = _test_inspect_aspect, 193*d6050574SRomain Jobredeaux extra_target_under_test_aspects = [example_aspect], 194*d6050574SRomain Jobredeaux ) 195*d6050574SRomain Jobredeaux 196*d6050574SRomain Jobredeauxdef _test_inspect_aspect(env, target): 197*d6050574SRomain Jobredeaux env.expect.that_str(target[_AddedByAspectInfo].value).equals("attached by aspect") 198*d6050574SRomain Jobredeaux 199*d6050574SRomain Jobredeaux######################################## 200*d6050574SRomain Jobredeaux####### inspect_output_dirs_test ####### 201*d6050574SRomain Jobredeaux######################################## 202*d6050574SRomain Jobredeaux_OutputDirInfo = provider( 203*d6050574SRomain Jobredeaux doc = "bin_path for inspect_output_dirs_test", 204*d6050574SRomain Jobredeaux fields = ["bin_path"], 205*d6050574SRomain Jobredeaux) 206*d6050574SRomain Jobredeaux 207*d6050574SRomain Jobredeauxdef _inspect_output_dirs_fake_rule(ctx): 208*d6050574SRomain Jobredeaux return [_OutputDirInfo(bin_path = ctx.bin_dir.path)] 209*d6050574SRomain Jobredeaux 210*d6050574SRomain Jobredeauxinspect_output_dirs_fake_rule = rule(implementation = _inspect_output_dirs_fake_rule) 211*d6050574SRomain Jobredeaux 212*d6050574SRomain Jobredeaux######################################## 213*d6050574SRomain Jobredeaux####### common_attributes_test ####### 214*d6050574SRomain Jobredeaux######################################## 215*d6050574SRomain Jobredeaux 216*d6050574SRomain Jobredeauxdef _test_common_attributes(name): 217*d6050574SRomain Jobredeaux native.filegroup(name = name + "_subject") 218*d6050574SRomain Jobredeaux _toolchain_template_vars(name = name + "_toolchain_template_vars") 219*d6050574SRomain Jobredeaux analysis_test( 220*d6050574SRomain Jobredeaux name = name, 221*d6050574SRomain Jobredeaux impl = _test_common_attributes_impl, 222*d6050574SRomain Jobredeaux target = name + "_subject", 223*d6050574SRomain Jobredeaux attr_values = dict( 224*d6050574SRomain Jobredeaux features = ["some-feature"], 225*d6050574SRomain Jobredeaux tags = ["taga", "tagb"], 226*d6050574SRomain Jobredeaux visibility = ["//visibility:private"], 227*d6050574SRomain Jobredeaux toolchains = [name + "_toolchain_template_vars"], 228*d6050574SRomain Jobredeaux # An empty list means "compatible with everything" 229*d6050574SRomain Jobredeaux target_compatible_with = [], 230*d6050574SRomain Jobredeaux ), 231*d6050574SRomain Jobredeaux ) 232*d6050574SRomain Jobredeaux 233*d6050574SRomain Jobredeauxdef _test_common_attributes_impl(env, target): 234*d6050574SRomain Jobredeaux _ = target # @unused 235*d6050574SRomain Jobredeaux ctx = env.ctx 236*d6050574SRomain Jobredeaux expect = env.expect 237*d6050574SRomain Jobredeaux 238*d6050574SRomain Jobredeaux expect.that_collection(ctx.attr.tags).contains_at_least(["taga", "tagb"]) 239*d6050574SRomain Jobredeaux 240*d6050574SRomain Jobredeaux expect.that_collection(ctx.attr.features).contains_exactly(["some-feature"]) 241*d6050574SRomain Jobredeaux 242*d6050574SRomain Jobredeaux expect.that_collection(ctx.attr.visibility).contains_exactly([ 243*d6050574SRomain Jobredeaux Label("//visibility:private"), 244*d6050574SRomain Jobredeaux ]) 245*d6050574SRomain Jobredeaux 246*d6050574SRomain Jobredeaux expect.that_collection(ctx.attr.target_compatible_with).contains_exactly([]) 247*d6050574SRomain Jobredeaux 248*d6050574SRomain Jobredeaux expanded = ctx.expand_make_variables("cmd", "$(key)", {}) 249*d6050574SRomain Jobredeaux expect.that_str(expanded).equals("value") 250*d6050574SRomain Jobredeaux 251*d6050574SRomain Jobredeauxdef _toolchain_template_vars_impl(ctx): 252*d6050574SRomain Jobredeaux _ = ctx # @unused 253*d6050574SRomain Jobredeaux return [platform_common.TemplateVariableInfo({"key": "value"})] 254*d6050574SRomain Jobredeaux 255*d6050574SRomain Jobredeaux_toolchain_template_vars = rule(implementation = _toolchain_template_vars_impl) 256*d6050574SRomain Jobredeaux 257*d6050574SRomain Jobredeauxdef analysis_test_test_suite(name): 258*d6050574SRomain Jobredeaux test_suite( 259*d6050574SRomain Jobredeaux name = name, 260*d6050574SRomain Jobredeaux tests = [ 261*d6050574SRomain Jobredeaux test_change_setting, 262*d6050574SRomain Jobredeaux _test_common_attributes, 263*d6050574SRomain Jobredeaux test_failure_testing, 264*d6050574SRomain Jobredeaux test_change_setting_with_failure, 265*d6050574SRomain Jobredeaux test_inspect_actions, 266*d6050574SRomain Jobredeaux test_inspect_aspect, 267*d6050574SRomain Jobredeaux ], 268*d6050574SRomain Jobredeaux ) 269