1# Copyright 2017 The Bazel Authors. 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"""Unit tests for selects.bzl.""" 16 17load("//lib:selects.bzl", "selects") 18load("//lib:unittest.bzl", "analysistest", "asserts", "unittest") 19 20################################################### 21# with_or_test 22################################################### 23def _with_or_test(ctx): 24 """Unit tests for with_or.""" 25 env = unittest.begin(ctx) 26 27 # We actually test on with_or_dict because Starlark can't get the 28 # dictionary from a select(). 29 30 # Test select()-compatible input syntax. 31 input_dict = {":foo": ":d1", "//conditions:default": ":d1"} 32 asserts.equals(env, input_dict, selects.with_or_dict(input_dict)) 33 34 # Test OR syntax. 35 or_dict = {(":foo", ":bar"): ":d1"} 36 asserts.equals( 37 env, 38 {":bar": ":d1", ":foo": ":d1"}, 39 selects.with_or_dict(or_dict), 40 ) 41 42 # Test mixed syntax. 43 mixed_dict = { 44 ":foo": ":d1", 45 (":bar", ":baz"): ":d2", 46 "//conditions:default": ":d3", 47 } 48 asserts.equals( 49 env, 50 { 51 ":bar": ":d2", 52 ":baz": ":d2", 53 ":foo": ":d1", 54 "//conditions:default": ":d3", 55 }, 56 selects.with_or_dict(mixed_dict), 57 ) 58 59 return unittest.end(env) 60 61with_or_test = unittest.make(_with_or_test) 62 63################################################### 64# BUILD declarations for config_setting_group tests 65################################################### 66 67# TODO: redefine these config_settings with Starlark build flags when 68# they're available non-experimentally. 69def _create_config_settings(): 70 native.config_setting( 71 name = "condition1", 72 values = {"cpu": "ppc"}, 73 ) 74 native.config_setting( 75 name = "condition2", 76 values = {"compilation_mode": "opt"}, 77 ) 78 native.config_setting( 79 name = "condition3", 80 values = {"features": "myfeature"}, 81 ) 82 83def _create_config_setting_groups(): 84 selects.config_setting_group( 85 name = "1_and_2_and_3", 86 match_all = [":condition1", ":condition2", ":condition3"], 87 ) 88 selects.config_setting_group( 89 name = "1_and_nothing_else", 90 match_all = [":condition1"], 91 ) 92 selects.config_setting_group( 93 name = "1_or_2_or_3", 94 match_any = [":condition1", ":condition2", ":condition3"], 95 ) 96 selects.config_setting_group( 97 name = "1_or_nothing_else", 98 match_any = [":condition1"], 99 ) 100 101################################################### 102# Support code for config_setting_group tests 103################################################### 104 105def _set_conditions(condition_list): 106 """Returns an argument for config_settings that sets specific options. 107 108 Args: 109 condition_list: a list of three booleans 110 111 Returns: 112 a dictionary parameter for config_settings such that ":conditionN" is True 113 iff condition_list[N + 1] is True 114 """ 115 if len(condition_list) != 3: 116 fail("condition_list must be a list of 3 booleans") 117 ans = {} 118 if condition_list[0]: 119 ans["//command_line_option:cpu"] = "ppc" 120 else: 121 ans["//command_line_option:cpu"] = "k8" 122 if condition_list[1]: 123 ans["//command_line_option:compilation_mode"] = "opt" 124 else: 125 ans["//command_line_option:compilation_mode"] = "dbg" 126 if condition_list[2]: 127 ans["//command_line_option:features"] = ["myfeature"] 128 else: 129 ans["//command_line_option:features"] = ["notmyfeature"] 130 return ans 131 132_BooleanInfo = provider( 133 doc = "value for boolean tests", 134 fields = ["value"], 135) 136 137def _boolean_attr_impl(ctx): 138 return [_BooleanInfo(value = ctx.attr.myboolean)] 139 140boolean_attr_rule = rule( 141 implementation = _boolean_attr_impl, 142 attrs = {"myboolean": attr.bool()}, 143) 144 145def _expect_matches(ctx): 146 """Generic test implementation expecting myboolean == True.""" 147 env = analysistest.begin(ctx) 148 attrval = analysistest.target_under_test(env)[_BooleanInfo].value 149 asserts.equals(env, True, attrval) 150 return analysistest.end(env) 151 152def _expect_doesnt_match(ctx): 153 """Generic test implementation expecting myboolean == False.""" 154 env = analysistest.begin(ctx) 155 attrval = analysistest.target_under_test(env)[_BooleanInfo].value 156 asserts.equals(env, False, attrval) 157 return analysistest.end(env) 158 159################################################### 160# and_config_setting_group_matches_test 161################################################### 162and_config_setting_group_matches_test = analysistest.make( 163 _expect_matches, 164 config_settings = _set_conditions([True, True, True]), 165) 166 167def _and_config_setting_group_matches_test(): 168 """Test verifying match on an ANDing config_setting_group.""" 169 boolean_attr_rule( 170 name = "and_config_setting_group_matches_rule", 171 myboolean = select( 172 { 173 ":1_and_2_and_3": True, 174 "//conditions:default": False, 175 }, 176 ), 177 ) 178 and_config_setting_group_matches_test( 179 name = "and_config_setting_group_matches_test", 180 target_under_test = ":and_config_setting_group_matches_rule", 181 ) 182 183################################################### 184# and_config_setting_group_first_match_fails_test 185################################################### 186and_config_setting_group_first_match_fails_test = analysistest.make( 187 _expect_doesnt_match, 188 config_settings = _set_conditions([False, True, True]), 189) 190 191def _and_config_setting_group_first_match_fails_test(): 192 """Test verifying first condition mismatch on an ANDing config_setting_group.""" 193 boolean_attr_rule( 194 name = "and_config_setting_group_first_match_fails_rule", 195 myboolean = select( 196 { 197 ":1_and_2_and_3": True, 198 "//conditions:default": False, 199 }, 200 ), 201 ) 202 and_config_setting_group_first_match_fails_test( 203 name = "and_config_setting_group_first_match_fails_test", 204 target_under_test = ":and_config_setting_group_first_match_fails_rule", 205 ) 206 207################################################### 208# and_config_setting_group_middle_match_fails_test 209################################################### 210and_config_setting_group_middle_match_fails_test = analysistest.make( 211 _expect_doesnt_match, 212 config_settings = _set_conditions([True, False, True]), 213) 214 215def _and_config_setting_group_middle_match_fails_test(): 216 """Test verifying middle condition mismatch on an ANDing config_setting_group.""" 217 boolean_attr_rule( 218 name = "and_config_setting_group_middle_match_fails_rule", 219 myboolean = select( 220 { 221 ":1_and_2_and_3": True, 222 "//conditions:default": False, 223 }, 224 ), 225 ) 226 and_config_setting_group_middle_match_fails_test( 227 name = "and_config_setting_group_middle_match_fails_test", 228 target_under_test = ":and_config_setting_group_middle_match_fails_rule", 229 ) 230 231################################################### 232# and_config_setting_group_last_match_fails_test 233################################################### 234and_config_setting_group_last_match_fails_test = analysistest.make( 235 _expect_doesnt_match, 236 config_settings = _set_conditions([True, True, False]), 237) 238 239def _and_config_setting_group_last_match_fails_test(): 240 """Test verifying last condition mismatch on an ANDing config_setting_group.""" 241 boolean_attr_rule( 242 name = "and_config_setting_group_last_match_fails_rule", 243 myboolean = select( 244 { 245 ":1_and_2_and_3": True, 246 "//conditions:default": False, 247 }, 248 ), 249 ) 250 and_config_setting_group_last_match_fails_test( 251 name = "and_config_setting_group_last_match_fails_test", 252 target_under_test = ":and_config_setting_group_last_match_fails_rule", 253 ) 254 255################################################### 256# and_config_setting_group_multiple_matches_fail_test 257################################################### 258and_config_setting_group_multiple_matches_fail_test = analysistest.make( 259 _expect_doesnt_match, 260 config_settings = _set_conditions([True, False, False]), 261) 262 263def _and_config_setting_group_multiple_matches_fail_test(): 264 """Test verifying multiple conditions mismatch on an ANDing config_setting_group.""" 265 boolean_attr_rule( 266 name = "and_config_setting_group_multiple_matches_fail_rule", 267 myboolean = select( 268 { 269 ":1_and_2_and_3": True, 270 "//conditions:default": False, 271 }, 272 ), 273 ) 274 and_config_setting_group_multiple_matches_fail_test( 275 name = "and_config_setting_group_multiple_matches_fail_test", 276 target_under_test = ":and_config_setting_group_multiple_matches_fail_rule", 277 ) 278 279################################################### 280# and_config_setting_group_all_matches_fail_test 281################################################### 282and_config_setting_group_all_matches_fail_test = analysistest.make( 283 _expect_doesnt_match, 284 config_settings = _set_conditions([False, False, False]), 285) 286 287def _and_config_setting_group_all_matches_fail_test(): 288 """Test verifying all conditions mismatch on an ANDing config_setting_group.""" 289 boolean_attr_rule( 290 name = "and_config_setting_group_all_matches_fail_rule", 291 myboolean = select( 292 { 293 ":1_and_2_and_3": True, 294 "//conditions:default": False, 295 }, 296 ), 297 ) 298 and_config_setting_group_all_matches_fail_test( 299 name = "and_config_setting_group_all_matches_fail_test", 300 target_under_test = ":and_config_setting_group_all_matches_fail_rule", 301 ) 302 303################################################### 304# and_config_setting_group_single_setting_matches_test 305################################################### 306and_config_setting_group_single_setting_matches_test = analysistest.make( 307 _expect_matches, 308 config_settings = {"//command_line_option:cpu": "ppc"}, 309) 310 311def _and_config_setting_group_single_setting_matches_test(): 312 """Test verifying match on single-entry ANDing config_setting_group.""" 313 boolean_attr_rule( 314 name = "and_config_setting_group_single_setting_matches_rule", 315 myboolean = select( 316 { 317 ":1_and_nothing_else": True, 318 "//conditions:default": False, 319 }, 320 ), 321 ) 322 and_config_setting_group_single_setting_matches_test( 323 name = "and_config_setting_group_single_setting_matches_test", 324 target_under_test = ":and_config_setting_group_single_setting_matches_rule", 325 ) 326 327################################################### 328# and_config_setting_group_single_setting_fails_test 329################################################### 330and_config_setting_group_single_setting_fails_test = analysistest.make( 331 _expect_doesnt_match, 332 config_settings = {"//command_line_option:cpu": "x86"}, 333) 334 335def _and_config_setting_group_single_setting_fails_test(): 336 """Test verifying no match on single-entry ANDing config_setting_group.""" 337 boolean_attr_rule( 338 name = "and_config_setting_group_single_setting_fails_rule", 339 myboolean = select( 340 { 341 ":1_and_nothing_else": True, 342 "//conditions:default": False, 343 }, 344 ), 345 ) 346 and_config_setting_group_single_setting_fails_test( 347 name = "and_config_setting_group_single_setting_fails_test", 348 target_under_test = ":and_config_setting_group_single_setting_fails_rule", 349 ) 350 351################################################### 352# or_config_setting_group_no_match_test 353################################################### 354or_config_setting_group_no_matches_test = analysistest.make( 355 _expect_doesnt_match, 356 config_settings = _set_conditions([False, False, False]), 357) 358 359def _or_config_setting_group_no_matches_test(): 360 """Test verifying no matches on an ORing config_setting_group.""" 361 boolean_attr_rule( 362 name = "or_config_setting_group_no_matches_rule", 363 myboolean = select( 364 { 365 ":1_or_2_or_3": True, 366 "//conditions:default": False, 367 }, 368 ), 369 ) 370 or_config_setting_group_no_matches_test( 371 name = "or_config_setting_group_no_matches_test", 372 target_under_test = ":or_config_setting_group_no_matches_rule", 373 ) 374 375################################################### 376# or_config_setting_group_first_cond_matches_test 377################################################### 378or_config_setting_group_first_cond_matches_test = analysistest.make( 379 _expect_matches, 380 config_settings = _set_conditions([True, False, False]), 381) 382 383def _or_config_setting_group_first_cond_matches_test(): 384 """Test verifying first condition matching on an ORing config_setting_group.""" 385 boolean_attr_rule( 386 name = "or_config_setting_group_first_cond_matches_rule", 387 myboolean = select( 388 { 389 ":1_or_2_or_3": True, 390 "//conditions:default": False, 391 }, 392 ), 393 ) 394 or_config_setting_group_first_cond_matches_test( 395 name = "or_config_setting_group_first_cond_matches_test", 396 target_under_test = ":or_config_setting_group_first_cond_matches_rule", 397 ) 398 399################################################### 400# or_config_setting_group_middle_cond_matches_test 401################################################### 402or_config_setting_group_middle_cond_matches_test = analysistest.make( 403 _expect_matches, 404 config_settings = _set_conditions([False, True, False]), 405) 406 407def _or_config_setting_group_middle_cond_matches_test(): 408 """Test verifying middle condition matching on an ORing config_setting_group.""" 409 boolean_attr_rule( 410 name = "or_config_setting_group_middle_cond_matches_rule", 411 myboolean = select( 412 { 413 ":1_or_2_or_3": True, 414 "//conditions:default": False, 415 }, 416 ), 417 ) 418 or_config_setting_group_middle_cond_matches_test( 419 name = "or_config_setting_group_middle_cond_matches_test", 420 target_under_test = ":or_config_setting_group_middle_cond_matches_rule", 421 ) 422 423################################################### 424# or_config_setting_group_last_cond_matches_test 425################################################### 426or_config_setting_group_last_cond_matches_test = analysistest.make( 427 _expect_matches, 428 config_settings = _set_conditions([False, False, True]), 429) 430 431def _or_config_setting_group_last_cond_matches_test(): 432 """Test verifying last condition matching on an ORing config_setting_group.""" 433 boolean_attr_rule( 434 name = "or_config_setting_group_last_cond_matches_rule", 435 myboolean = select( 436 { 437 ":1_or_2_or_3": True, 438 "//conditions:default": False, 439 }, 440 ), 441 ) 442 or_config_setting_group_last_cond_matches_test( 443 name = "or_config_setting_group_last_cond_matches_test", 444 target_under_test = ":or_config_setting_group_last_cond_matches_rule", 445 ) 446 447################################################### 448# or_config_setting_group_multiple_conds_match_test 449################################################### 450or_config_setting_group_multiple_conds_match_test = analysistest.make( 451 _expect_matches, 452 config_settings = _set_conditions([False, True, True]), 453) 454 455def _or_config_setting_group_multiple_conds_match_test(): 456 """Test verifying multiple conditions matching on an ORing config_setting_group.""" 457 boolean_attr_rule( 458 name = "or_config_setting_group_multiple_conds_match_rule", 459 myboolean = select( 460 { 461 ":1_or_2_or_3": True, 462 "//conditions:default": False, 463 }, 464 ), 465 ) 466 or_config_setting_group_multiple_conds_match_test( 467 name = "or_config_setting_group_multiple_conds_match_test", 468 target_under_test = ":or_config_setting_group_multiple_conds_match_rule", 469 ) 470 471################################################### 472# or_config_setting_group_all_conds_match_test 473################################################### 474or_config_setting_group_all_conds_match_test = analysistest.make( 475 _expect_matches, 476 config_settings = _set_conditions([False, True, True]), 477) 478 479def _or_config_setting_group_all_conds_match_test(): 480 """Test verifying all conditions matching on an ORing config_setting_group.""" 481 boolean_attr_rule( 482 name = "or_config_setting_group_all_conds_match_rule", 483 myboolean = select( 484 { 485 ":1_or_2_or_3": True, 486 "//conditions:default": False, 487 }, 488 ), 489 ) 490 or_config_setting_group_all_conds_match_test( 491 name = "or_config_setting_group_all_conds_match_test", 492 target_under_test = ":or_config_setting_group_all_conds_match_rule", 493 ) 494 495################################################### 496# or_config_setting_group_single_setting_matches_test 497################################################### 498or_config_setting_group_single_setting_matches_test = analysistest.make( 499 _expect_matches, 500 config_settings = {"//command_line_option:cpu": "ppc"}, 501) 502 503def _or_config_setting_group_single_setting_matches_test(): 504 """Test verifying match on single-entry ORing config_setting_group.""" 505 boolean_attr_rule( 506 name = "or_config_setting_group_single_setting_matches_rule", 507 myboolean = select( 508 { 509 ":1_or_nothing_else": True, 510 "//conditions:default": False, 511 }, 512 ), 513 ) 514 or_config_setting_group_single_setting_matches_test( 515 name = "or_config_setting_group_single_setting_matches_test", 516 target_under_test = ":or_config_setting_group_single_setting_matches_rule", 517 ) 518 519################################################### 520# or_config_setting_group_single_setting_fails_test 521################################################### 522or_config_setting_group_single_setting_fails_test = analysistest.make( 523 _expect_doesnt_match, 524 config_settings = {"//command_line_option:cpu": "x86"}, 525) 526 527def _or_config_setting_group_single_setting_fails_test(): 528 """Test verifying no match on single-entry ORing config_setting_group.""" 529 boolean_attr_rule( 530 name = "or_config_setting_group_single_setting_fails_rule", 531 myboolean = select( 532 { 533 ":1_or_nothing_else": True, 534 "//conditions:default": False, 535 }, 536 ), 537 ) 538 or_config_setting_group_single_setting_fails_test( 539 name = "or_config_setting_group_single_setting_fails_test", 540 target_under_test = ":or_config_setting_group_single_setting_fails_rule", 541 ) 542 543################################################### 544# always_true_match_all_test 545################################################### 546always_true_match_all_test = analysistest.make(_expect_matches) 547 548def _always_true_match_all_test(): 549 """Tests that "match_all=['//conditions:default']" always matches.""" 550 selects.config_setting_group( 551 name = "all_always_match", 552 match_all = ["//conditions:default"], 553 ) 554 boolean_attr_rule( 555 name = "match_always_true_rule", 556 myboolean = select( 557 { 558 ":all_always_match": True, 559 }, 560 ), 561 ) 562 always_true_match_all_test( 563 name = "always_true_match_all_test", 564 target_under_test = ":match_always_true_rule", 565 ) 566 567################################################### 568# always_true_match_any_test 569################################################### 570always_true_match_any_test = analysistest.make(_expect_matches) 571 572def _always_true_match_any_test(): 573 """Tests that "match_any=['//conditions:default']" always matches.""" 574 selects.config_setting_group( 575 name = "any_always_match", 576 match_any = ["//conditions:default"], 577 ) 578 boolean_attr_rule( 579 name = "match_any_always_true_rule", 580 myboolean = select( 581 { 582 ":any_always_match": True, 583 }, 584 ), 585 ) 586 always_true_match_any_test( 587 name = "always_true_match_any_test", 588 target_under_test = ":match_any_always_true_rule", 589 ) 590 591################################################### 592# empty_config_setting_group_not_allowed_test 593################################################### 594 595# config_setting_group with no parameters triggers a failure. 596# TODO: how do we test this? This requires catching macro 597# evaluation failure. 598 599################################################### 600# and_and_or_not_allowed_together_test 601################################################### 602 603# config_setting_group: setting both match_any and match_or 604# triggers a failure. 605# TODO: how do we test this? This requires catching macro 606# evaluation failure. 607 608################################################### 609 610# buildifier: disable=unnamed-macro 611def selects_test_suite(): 612 """Creates the test targets and test suite for selects.bzl tests.""" 613 unittest.suite( 614 "selects_tests", 615 with_or_test, 616 ) 617 618 _create_config_settings() 619 _create_config_setting_groups() 620 621 _and_config_setting_group_matches_test() 622 _and_config_setting_group_first_match_fails_test() 623 _and_config_setting_group_middle_match_fails_test() 624 _and_config_setting_group_last_match_fails_test() 625 _and_config_setting_group_multiple_matches_fail_test() 626 _and_config_setting_group_all_matches_fail_test() 627 _and_config_setting_group_single_setting_matches_test() 628 _and_config_setting_group_single_setting_fails_test() 629 630 _or_config_setting_group_no_matches_test() 631 _or_config_setting_group_first_cond_matches_test() 632 _or_config_setting_group_middle_cond_matches_test() 633 _or_config_setting_group_last_cond_matches_test() 634 _or_config_setting_group_multiple_conds_match_test() 635 _or_config_setting_group_all_conds_match_test() 636 _or_config_setting_group_single_setting_matches_test() 637 _or_config_setting_group_single_setting_fails_test() 638 639 _always_true_match_all_test() 640 _always_true_match_any_test() 641 642 # _empty_config_setting_group_not_allowed_test() 643 # _and_and_or_not_allowed_together_test() 644