1"""Unittest to verify workspace status stamping is applied to environment files""" 2 3load("@bazel_skylib//lib:unittest.bzl", "analysistest") 4load("//rust:defs.bzl", "rust_binary", "rust_common", "rust_library", "rust_test") 5load( 6 "//test/unit:common.bzl", 7 "assert_action_mnemonic", 8 "assert_argv_contains", 9 "assert_argv_contains_not", 10) 11 12_STAMP_ATTR_VALUES = (0, 1, -1) 13_BUILD_FLAG_VALUES = ("true", "false") 14 15def _assert_stamped(env, action): 16 assert_argv_contains(env, action, "--volatile-status-file") 17 assert_argv_contains(env, action, "bazel-out/volatile-status.txt") 18 19 assert_argv_contains(env, action, "--stable-status-file") 20 assert_argv_contains(env, action, "bazel-out/stable-status.txt") 21 22def _assert_not_stamped(env, action): 23 assert_argv_contains_not(env, action, "--volatile-status-file") 24 assert_argv_contains_not(env, action, "bazel-out/volatile-status.txt") 25 26 assert_argv_contains_not(env, action, "--stable-status-file") 27 assert_argv_contains_not(env, action, "bazel-out/stable-status.txt") 28 29def _stamp_build_flag_test_impl(ctx, flag_value): 30 env = analysistest.begin(ctx) 31 target = analysistest.target_under_test(env) 32 33 action = target.actions[0] 34 assert_action_mnemonic(env, action, "Rustc") 35 36 is_test = target[rust_common.crate_info].is_test 37 is_bin = target[rust_common.crate_info].type == "bin" 38 39 # bazel build --stamp should lead to stamped rust binaries, but not 40 # libraries and tests. 41 if flag_value: 42 if is_bin and not is_test: 43 _assert_stamped(env, action) 44 else: 45 _assert_not_stamped(env, action) 46 else: 47 _assert_not_stamped(env, action) 48 49 return analysistest.end(env) 50 51def _stamp_build_flag_is_true_impl(ctx): 52 return _stamp_build_flag_test_impl(ctx, True) 53 54def _stamp_build_flag_is_false_impl(ctx): 55 return _stamp_build_flag_test_impl(ctx, False) 56 57stamp_build_flag_is_true_test = analysistest.make( 58 _stamp_build_flag_is_true_impl, 59 config_settings = { 60 "//command_line_option:stamp": True, 61 }, 62) 63 64stamp_build_flag_is_false_test = analysistest.make( 65 _stamp_build_flag_is_false_impl, 66 config_settings = { 67 "//command_line_option:stamp": False, 68 }, 69) 70 71def _build_flag_tests(): 72 tests = [] 73 for stamp_value in _BUILD_FLAG_VALUES: 74 if stamp_value == "true": 75 name = "default_with_build_flag_on" 76 features = ["always_stamp"] 77 build_flag_stamp_test = stamp_build_flag_is_true_test 78 else: 79 name = "default_with_build_flag_off" 80 features = ["never_stamp"] 81 build_flag_stamp_test = stamp_build_flag_is_false_test 82 83 rust_library( 84 name = "{}_lib".format(name), 85 srcs = ["stamp.rs"], 86 rustc_env_files = ["stamp.env"], 87 edition = "2018", 88 # Building with --stamp should not affect rust libraries 89 crate_features = ["never_stamp"], 90 ) 91 92 rust_binary( 93 name = "{}_bin".format(name), 94 srcs = ["stamp_main.rs"], 95 edition = "2018", 96 deps = ["{}_lib".format(name)], 97 rustc_env_files = ["stamp.env"], 98 crate_features = features, 99 ) 100 101 rust_test( 102 name = "{}_test".format(name), 103 crate = "{}_lib".format(name), 104 edition = "2018", 105 rustc_env_files = ["stamp.env"], 106 # Building with --stamp should not affect tests 107 crate_features = ["never_stamp"], 108 ) 109 110 build_flag_stamp_test( 111 name = "lib_{}_test".format(name), 112 target_under_test = "{}_lib".format(name), 113 ) 114 build_flag_stamp_test( 115 name = "bin_{}_test".format(name), 116 target_under_test = "{}_bin".format(name), 117 ) 118 119 build_flag_stamp_test( 120 name = "test_{}_test".format(name), 121 target_under_test = "{}_test".format(name), 122 ) 123 124 tests.extend([ 125 "lib_{}_test".format(name), 126 "bin_{}_test".format(name), 127 "test_{}_test".format(name), 128 ]) 129 return tests 130 131def _attribute_stamp_test_impl(ctx, attribute_value, build_flag_value): 132 env = analysistest.begin(ctx) 133 target = analysistest.target_under_test(env) 134 135 action = target.actions[0] 136 assert_action_mnemonic(env, action, "Rustc") 137 138 if attribute_value == 1: 139 _assert_stamped(env, action) 140 elif attribute_value == 0: 141 _assert_not_stamped(env, action) 142 elif build_flag_value: 143 _assert_stamped(env, action) 144 else: 145 _assert_not_stamped(env, action) 146 147 return analysistest.end(env) 148 149def _always_stamp_build_flag_is_true_test_impl(ctx): 150 return _attribute_stamp_test_impl(ctx, attribute_value = 1, build_flag_value = True) 151 152def _always_stamp_build_flag_is_false_test_impl(ctx): 153 return _attribute_stamp_test_impl(ctx, attribute_value = 1, build_flag_value = False) 154 155def _never_stamp_build_flag_is_true_test_impl(ctx): 156 return _attribute_stamp_test_impl(ctx, attribute_value = 0, build_flag_value = True) 157 158def _never_stamp_build_flag_is_false_test_impl(ctx): 159 return _attribute_stamp_test_impl(ctx, attribute_value = 0, build_flag_value = False) 160 161def _consult_build_flag_value_is_true_test_impl(ctx): 162 return _attribute_stamp_test_impl(ctx, attribute_value = -1, build_flag_value = True) 163 164def _consult_build_flag_value_is_false_test_impl(ctx): 165 return _attribute_stamp_test_impl(ctx, attribute_value = -1, build_flag_value = False) 166 167always_stamp_test_build_flag_is_true_test = analysistest.make( 168 _always_stamp_build_flag_is_true_test_impl, 169 config_settings = { 170 "//command_line_option:stamp": True, 171 }, 172) 173 174always_stamp_test_build_flag_is_false_test = analysistest.make( 175 _always_stamp_build_flag_is_false_test_impl, 176 config_settings = { 177 "//command_line_option:stamp": False, 178 }, 179) 180 181never_stamp_test_build_flag_is_true_test = analysistest.make( 182 _never_stamp_build_flag_is_true_test_impl, 183 config_settings = { 184 "//command_line_option:stamp": True, 185 }, 186) 187 188never_stamp_test_build_flag_is_false_test = analysistest.make( 189 _never_stamp_build_flag_is_false_test_impl, 190 config_settings = { 191 "//command_line_option:stamp": False, 192 }, 193) 194 195consult_build_flag_value_is_true_test = analysistest.make( 196 _consult_build_flag_value_is_true_test_impl, 197 config_settings = { 198 "//command_line_option:stamp": True, 199 }, 200) 201 202consult_build_flag_value_is_false_test = analysistest.make( 203 _consult_build_flag_value_is_false_test_impl, 204 config_settings = { 205 "//command_line_option:stamp": False, 206 }, 207) 208 209def _stamp_attribute_tests(): 210 tests = [] 211 212 for stamp_value in _STAMP_ATTR_VALUES: 213 for flag_value in _BUILD_FLAG_VALUES: 214 if stamp_value == 1: 215 name = "always_stamp_build_flag_{}".format(flag_value) 216 features = ["always_stamp_build_flag_{}".format(flag_value)] 217 stamp_attr_test = always_stamp_test_build_flag_is_true_test if flag_value == "true" else always_stamp_test_build_flag_is_false_test 218 elif stamp_value == 0: 219 name = "never_stamp_build_flag_{}".format(flag_value) 220 features = ["never_stamp_build_flag_{}".format(flag_value)] 221 stamp_attr_test = never_stamp_test_build_flag_is_true_test if flag_value == "true" else never_stamp_test_build_flag_is_false_test 222 else: 223 name = "consult_cmdline_value_is_{}".format(flag_value) 224 features = ["consult_cmdline_value_is_{}".format(flag_value)] 225 stamp_attr_test = consult_build_flag_value_is_true_test if flag_value == "true" else consult_build_flag_value_is_false_test 226 227 rust_library( 228 name = "{}_lib".format(name), 229 srcs = ["stamp.rs"], 230 edition = "2018", 231 rustc_env_files = [":stamp.env"], 232 stamp = stamp_value, 233 crate_features = features, 234 ) 235 236 rust_test( 237 name = "{}_unit_test".format(name), 238 crate = ":{}_lib".format(name), 239 edition = "2018", 240 rustc_env_files = [":stamp.env"], 241 stamp = stamp_value, 242 crate_features = features, 243 # We disable this test so that it doesn't try to run with bazel test //test/... 244 # The reason for this is because then it is sensitive to the --stamp value which 245 # we override in the unit test implementation. 246 tags = ["manual"], 247 ) 248 249 rust_binary( 250 name = "{}_bin".format(name), 251 srcs = ["stamp_main.rs"], 252 edition = "2018", 253 deps = [":{}_lib".format(name)], 254 rustc_env_files = [":stamp.env"], 255 stamp = stamp_value, 256 crate_features = features, 257 ) 258 259 stamp_attr_test( 260 name = "lib_{}_test".format(name), 261 target_under_test = "{}_lib".format(name), 262 ) 263 stamp_attr_test( 264 name = "bin_{}_test".format(name), 265 target_under_test = "{}_bin".format(name), 266 ) 267 268 stamp_attr_test( 269 name = "test_{}_test".format(name), 270 target_under_test = "{}_unit_test".format(name), 271 ) 272 273 tests.extend([ 274 "lib_{}_test".format(name), 275 "bin_{}_test".format(name), 276 "test_{}_test".format(name), 277 ]) 278 return tests 279 280def _process_wrapper_with_stamp_test_impl(ctx): 281 env = analysistest.begin(ctx) 282 target = analysistest.target_under_test(env) 283 284 action = target.actions[0] 285 assert_action_mnemonic(env, action, "Rustc") 286 287 _assert_not_stamped(env, action) 288 289 return analysistest.end(env) 290 291process_wrapper_with_stamp_test = analysistest.make( 292 _process_wrapper_with_stamp_test_impl, 293 config_settings = { 294 "//command_line_option:stamp": True, 295 }, 296) 297 298def _process_wrapper_tests(): 299 process_wrapper_with_stamp_test( 300 name = "test_process_wrapper_with_stamp_test", 301 target_under_test = "//util/process_wrapper:process_wrapper", 302 ) 303 304 return ["test_process_wrapper_with_stamp_test"] 305 306def stamp_test_suite(name): 307 """Entry-point macro called from the BUILD file. 308 309 Args: 310 name (str): Name of the macro. 311 """ 312 tests = _build_flag_tests() + _stamp_attribute_tests() + _process_wrapper_tests() 313 314 native.test_suite( 315 name = name, 316 tests = tests, 317 ) 318