1// Copyright 2024 Google Inc. 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 15package android 16 17import ( 18 "fmt" 19 "reflect" 20 "testing" 21 22 "github.com/google/blueprint" 23 "github.com/google/blueprint/proptools" 24) 25 26func TestSelects(t *testing.T) { 27 testCases := []struct { 28 name string 29 bp string 30 provider selectsTestProvider 31 providers map[string]selectsTestProvider 32 vendorVars map[string]map[string]string 33 expectedError string 34 }{ 35 { 36 name: "basic string list", 37 bp: ` 38 my_module_type { 39 name: "foo", 40 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), { 41 "a": ["a.cpp"], 42 "b": ["b.cpp"], 43 default: ["c.cpp"], 44 }), 45 } 46 `, 47 provider: selectsTestProvider{ 48 my_string_list: &[]string{"c.cpp"}, 49 }, 50 }, 51 { 52 name: "basic string", 53 bp: ` 54 my_module_type { 55 name: "foo", 56 my_string: select(soong_config_variable("my_namespace", "my_variable"), { 57 "a": "a.cpp", 58 "b": "b.cpp", 59 default: "c.cpp", 60 }), 61 } 62 `, 63 provider: selectsTestProvider{ 64 my_string: proptools.StringPtr("c.cpp"), 65 }, 66 }, 67 { 68 name: "basic bool", 69 bp: ` 70 my_module_type { 71 name: "foo", 72 my_bool: select(soong_config_variable("my_namespace", "my_variable"), { 73 "a": true, 74 "b": false, 75 default: true, 76 }), 77 } 78 `, 79 provider: selectsTestProvider{ 80 my_bool: proptools.BoolPtr(true), 81 }, 82 }, 83 { 84 name: "basic paths", 85 bp: ` 86 my_module_type { 87 name: "foo", 88 my_paths: select(soong_config_variable("my_namespace", "my_variable"), { 89 "a": ["foo.txt"], 90 "b": ["bar.txt"], 91 default: ["baz.txt"], 92 }), 93 } 94 `, 95 provider: selectsTestProvider{ 96 my_paths: &[]string{"baz.txt"}, 97 }, 98 }, 99 { 100 name: "paths with module references", 101 bp: ` 102 my_module_type { 103 name: "foo", 104 my_paths: select(soong_config_variable("my_namespace", "my_variable"), { 105 "a": [":a"], 106 "b": [":b"], 107 default: [":c"], 108 }), 109 } 110 `, 111 expectedError: `"foo" depends on undefined module "c"`, 112 }, 113 { 114 name: "Differing types", 115 bp: ` 116 my_module_type { 117 name: "foo", 118 my_string: select(soong_config_variable("my_namespace", "my_variable"), { 119 "a": "a.cpp", 120 "b": true, 121 default: "c.cpp", 122 }), 123 } 124 `, 125 expectedError: `Android.bp:8:5: Found select statement with differing types "string" and "bool" in its cases`, 126 }, 127 { 128 name: "Select type doesn't match property type", 129 bp: ` 130 my_module_type { 131 name: "foo", 132 my_string: select(soong_config_variable("my_namespace", "my_variable"), { 133 "a": false, 134 "b": true, 135 default: true, 136 }), 137 } 138 `, 139 expectedError: `can't assign bool value to string property "my_string\[0\]"`, 140 }, 141 { 142 name: "String list non-default", 143 bp: ` 144 my_module_type { 145 name: "foo", 146 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), { 147 "a": ["a.cpp"], 148 "b": ["b.cpp"], 149 default: ["c.cpp"], 150 }), 151 } 152 `, 153 provider: selectsTestProvider{ 154 my_string_list: &[]string{"a.cpp"}, 155 }, 156 vendorVars: map[string]map[string]string{ 157 "my_namespace": { 158 "my_variable": "a", 159 }, 160 }, 161 }, 162 { 163 name: "String list append", 164 bp: ` 165 my_module_type { 166 name: "foo", 167 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), { 168 "a": ["a.cpp"], 169 "b": ["b.cpp"], 170 default: ["c.cpp"], 171 }) + select(soong_config_variable("my_namespace", "my_variable_2"), { 172 "a2": ["a2.cpp"], 173 "b2": ["b2.cpp"], 174 default: ["c2.cpp"], 175 }), 176 } 177 `, 178 provider: selectsTestProvider{ 179 my_string_list: &[]string{"a.cpp", "c2.cpp"}, 180 }, 181 vendorVars: map[string]map[string]string{ 182 "my_namespace": { 183 "my_variable": "a", 184 }, 185 }, 186 }, 187 { 188 name: "String list prepend literal", 189 bp: ` 190 my_module_type { 191 name: "foo", 192 my_string_list: ["literal.cpp"] + select(soong_config_variable("my_namespace", "my_variable"), { 193 "a2": ["a2.cpp"], 194 "b2": ["b2.cpp"], 195 default: ["c2.cpp"], 196 }), 197 } 198 `, 199 provider: selectsTestProvider{ 200 my_string_list: &[]string{"literal.cpp", "c2.cpp"}, 201 }, 202 }, 203 { 204 name: "String list append literal", 205 bp: ` 206 my_module_type { 207 name: "foo", 208 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), { 209 "a2": ["a2.cpp"], 210 "b2": ["b2.cpp"], 211 default: ["c2.cpp"], 212 }) + ["literal.cpp"], 213 } 214 `, 215 provider: selectsTestProvider{ 216 my_string_list: &[]string{"c2.cpp", "literal.cpp"}, 217 }, 218 }, 219 { 220 name: "true + false = true", 221 bp: ` 222 my_module_type { 223 name: "foo", 224 my_bool: select(soong_config_variable("my_namespace", "my_variable"), { 225 "a": true, 226 "b": false, 227 default: true, 228 }) + false, 229 } 230 `, 231 provider: selectsTestProvider{ 232 my_bool: proptools.BoolPtr(true), 233 }, 234 }, 235 { 236 name: "false + false = false", 237 bp: ` 238 my_module_type { 239 name: "foo", 240 my_bool: select(soong_config_variable("my_namespace", "my_variable"), { 241 "a": true, 242 "b": false, 243 default: true, 244 }) + false, 245 } 246 `, 247 vendorVars: map[string]map[string]string{ 248 "my_namespace": { 249 "my_variable": "b", 250 }, 251 }, 252 provider: selectsTestProvider{ 253 my_bool: proptools.BoolPtr(false), 254 }, 255 }, 256 { 257 name: "Append string", 258 bp: ` 259 my_module_type { 260 name: "foo", 261 my_string: select(soong_config_variable("my_namespace", "my_variable"), { 262 "a": "a", 263 "b": "b", 264 default: "c", 265 }) + ".cpp", 266 } 267 `, 268 provider: selectsTestProvider{ 269 my_string: proptools.StringPtr("c.cpp"), 270 }, 271 }, 272 { 273 name: "Select on arch", 274 bp: ` 275 my_module_type { 276 name: "foo", 277 my_string: select(arch(), { 278 "x86": "my_x86", 279 "x86_64": "my_x86_64", 280 "arm": "my_arm", 281 "arm64": "my_arm64", 282 default: "my_default", 283 }), 284 } 285 `, 286 provider: selectsTestProvider{ 287 my_string: proptools.StringPtr("my_arm64"), 288 }, 289 }, 290 { 291 name: "Select on os", 292 bp: ` 293 my_module_type { 294 name: "foo", 295 my_string: select(os(), { 296 "android": "my_android", 297 "linux": "my_linux", 298 default: "my_default", 299 }), 300 } 301 `, 302 provider: selectsTestProvider{ 303 my_string: proptools.StringPtr("my_android"), 304 }, 305 }, 306 { 307 name: "Unset value", 308 bp: ` 309 my_module_type { 310 name: "foo", 311 my_string: select(soong_config_variable("my_namespace", "my_variable"), { 312 "a": unset, 313 "b": "b", 314 default: "c", 315 }) 316 } 317 `, 318 vendorVars: map[string]map[string]string{ 319 "my_namespace": { 320 "my_variable": "a", 321 }, 322 }, 323 provider: selectsTestProvider{}, 324 }, 325 { 326 name: "Unset value on different branch", 327 bp: ` 328 my_module_type { 329 name: "foo", 330 my_string: select(soong_config_variable("my_namespace", "my_variable"), { 331 "a": unset, 332 "b": "b", 333 default: "c", 334 }) 335 } 336 `, 337 provider: selectsTestProvider{ 338 my_string: proptools.StringPtr("c"), 339 }, 340 }, 341 { 342 name: "unset + unset = unset", 343 bp: ` 344 my_module_type { 345 name: "foo", 346 my_string: select(soong_config_variable("my_namespace", "my_variable"), { 347 "foo": "bar", 348 default: unset, 349 }) + select(soong_config_variable("my_namespace", "my_variable2"), { 350 "baz": "qux", 351 default: unset, 352 }) 353 } 354 `, 355 provider: selectsTestProvider{}, 356 }, 357 { 358 name: "unset + string = string", 359 bp: ` 360 my_module_type { 361 name: "foo", 362 my_string: select(soong_config_variable("my_namespace", "my_variable"), { 363 "foo": "bar", 364 default: unset, 365 }) + select(soong_config_variable("my_namespace", "my_variable2"), { 366 default: "a", 367 }) 368 } 369 `, 370 provider: selectsTestProvider{ 371 my_string: proptools.StringPtr("a"), 372 }, 373 }, 374 { 375 name: "unset + bool = bool", 376 bp: ` 377 my_module_type { 378 name: "foo", 379 my_bool: select(soong_config_variable("my_namespace", "my_variable"), { 380 "a": true, 381 default: unset, 382 }) + select(soong_config_variable("my_namespace", "my_variable2"), { 383 default: true, 384 }) 385 } 386 `, 387 provider: selectsTestProvider{ 388 my_bool: proptools.BoolPtr(true), 389 }, 390 }, 391 { 392 name: "defaults with lists are appended", 393 bp: ` 394 my_module_type { 395 name: "foo", 396 defaults: ["bar"], 397 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), { 398 "a": ["a1"], 399 default: ["b1"], 400 }), 401 } 402 my_defaults { 403 name: "bar", 404 my_string_list: select(soong_config_variable("my_namespace", "my_variable2"), { 405 "a": ["a2"], 406 default: ["b2"], 407 }), 408 } 409 `, 410 provider: selectsTestProvider{ 411 my_string_list: &[]string{"b2", "b1"}, 412 }, 413 }, 414 { 415 name: "defaults applied to multiple modules", 416 bp: ` 417 my_module_type { 418 name: "foo2", 419 defaults: ["bar"], 420 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), { 421 "a": ["a1"], 422 default: ["b1"], 423 }), 424 } 425 my_module_type { 426 name: "foo", 427 defaults: ["bar"], 428 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), { 429 "a": ["a1"], 430 default: ["b1"], 431 }), 432 } 433 my_defaults { 434 name: "bar", 435 my_string_list: select(soong_config_variable("my_namespace", "my_variable2"), { 436 "a": ["a2"], 437 default: ["b2"], 438 }), 439 } 440 `, 441 providers: map[string]selectsTestProvider{ 442 "foo": { 443 my_string_list: &[]string{"b2", "b1"}, 444 }, 445 "foo2": { 446 my_string_list: &[]string{"b2", "b1"}, 447 }, 448 }, 449 }, 450 { 451 name: "Replacing string list", 452 bp: ` 453 my_module_type { 454 name: "foo", 455 defaults: ["bar"], 456 replacing_string_list: select(soong_config_variable("my_namespace", "my_variable"), { 457 "a": ["a1"], 458 default: ["b1"], 459 }), 460 } 461 my_defaults { 462 name: "bar", 463 replacing_string_list: select(soong_config_variable("my_namespace", "my_variable2"), { 464 "a": ["a2"], 465 default: ["b2"], 466 }), 467 } 468 `, 469 provider: selectsTestProvider{ 470 replacing_string_list: &[]string{"b1"}, 471 }, 472 }, 473 { 474 name: "Multi-condition string 1", 475 bp: ` 476 my_module_type { 477 name: "foo", 478 my_string: select(( 479 soong_config_variable("my_namespace", "my_variable"), 480 soong_config_variable("my_namespace", "my_variable2"), 481 ), { 482 ("a", "b"): "a+b", 483 ("a", default): "a+default", 484 (default, default): "default", 485 }), 486 } 487 `, 488 vendorVars: map[string]map[string]string{ 489 "my_namespace": { 490 "my_variable": "a", 491 "my_variable2": "b", 492 }, 493 }, 494 provider: selectsTestProvider{ 495 my_string: proptools.StringPtr("a+b"), 496 }, 497 }, 498 { 499 name: "Multi-condition string 2", 500 bp: ` 501 my_module_type { 502 name: "foo", 503 my_string: select(( 504 soong_config_variable("my_namespace", "my_variable"), 505 soong_config_variable("my_namespace", "my_variable2"), 506 ), { 507 ("a", "b"): "a+b", 508 ("a", default): "a+default", 509 (default, default): "default", 510 }), 511 } 512 `, 513 vendorVars: map[string]map[string]string{ 514 "my_namespace": { 515 "my_variable": "a", 516 "my_variable2": "c", 517 }, 518 }, 519 provider: selectsTestProvider{ 520 my_string: proptools.StringPtr("a+default"), 521 }, 522 }, 523 { 524 name: "Multi-condition string 3", 525 bp: ` 526 my_module_type { 527 name: "foo", 528 my_string: select(( 529 soong_config_variable("my_namespace", "my_variable"), 530 soong_config_variable("my_namespace", "my_variable2"), 531 ), { 532 ("a", "b"): "a+b", 533 ("a", default): "a+default", 534 (default, default): "default", 535 }), 536 } 537 `, 538 vendorVars: map[string]map[string]string{ 539 "my_namespace": { 540 "my_variable": "c", 541 "my_variable2": "b", 542 }, 543 }, 544 provider: selectsTestProvider{ 545 my_string: proptools.StringPtr("default"), 546 }, 547 }, 548 { 549 name: "Unhandled string value", 550 bp: ` 551 my_module_type { 552 name: "foo", 553 my_string: select(soong_config_variable("my_namespace", "my_variable"), { 554 "foo": "a", 555 "bar": "b", 556 }), 557 } 558 `, 559 vendorVars: map[string]map[string]string{ 560 "my_namespace": { 561 "my_variable": "baz", 562 }, 563 }, 564 expectedError: `my_string: soong_config_variable\("my_namespace", "my_variable"\) had value "baz", which was not handled by the select statement`, 565 }, 566 { 567 name: "Select on boolean", 568 bp: ` 569 my_module_type { 570 name: "foo", 571 my_string: select(boolean_var_for_testing(), { 572 true: "t", 573 false: "f", 574 }), 575 } 576 `, 577 vendorVars: map[string]map[string]string{ 578 "boolean_var": { 579 "for_testing": "true", 580 }, 581 }, 582 provider: selectsTestProvider{ 583 my_string: proptools.StringPtr("t"), 584 }, 585 }, 586 { 587 name: "Select on boolean false", 588 bp: ` 589 my_module_type { 590 name: "foo", 591 my_string: select(boolean_var_for_testing(), { 592 true: "t", 593 false: "f", 594 }), 595 } 596 `, 597 vendorVars: map[string]map[string]string{ 598 "boolean_var": { 599 "for_testing": "false", 600 }, 601 }, 602 provider: selectsTestProvider{ 603 my_string: proptools.StringPtr("f"), 604 }, 605 }, 606 { 607 name: "Select on boolean undefined", 608 bp: ` 609 my_module_type { 610 name: "foo", 611 my_string: select(boolean_var_for_testing(), { 612 true: "t", 613 false: "f", 614 }), 615 } 616 `, 617 expectedError: `my_string: boolean_var_for_testing\(\) had value undefined, which was not handled by the select statement`, 618 }, 619 { 620 name: "Select on boolean undefined with default", 621 bp: ` 622 my_module_type { 623 name: "foo", 624 my_string: select(boolean_var_for_testing(), { 625 true: "t", 626 false: "f", 627 default: "default", 628 }), 629 } 630 `, 631 provider: selectsTestProvider{ 632 my_string: proptools.StringPtr("default"), 633 }, 634 }, 635 { 636 name: "Mismatched condition types", 637 bp: ` 638 my_module_type { 639 name: "foo", 640 my_string: select(boolean_var_for_testing(), { 641 "true": "t", 642 "false": "f", 643 default: "default", 644 }), 645 } 646 `, 647 vendorVars: map[string]map[string]string{ 648 "boolean_var": { 649 "for_testing": "false", 650 }, 651 }, 652 expectedError: "Expected all branches of a select on condition boolean_var_for_testing\\(\\) to have type bool, found string", 653 }, 654 { 655 name: "Assigning select to nonconfigurable bool", 656 bp: ` 657 my_module_type { 658 name: "foo", 659 my_nonconfigurable_bool: select(arch(), { 660 "x86_64": true, 661 default: false, 662 }), 663 } 664 `, 665 expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_bool"`, 666 }, 667 { 668 name: "Assigning select to nonconfigurable string", 669 bp: ` 670 my_module_type { 671 name: "foo", 672 my_nonconfigurable_string: select(arch(), { 673 "x86_64": "x86!", 674 default: "unknown!", 675 }), 676 } 677 `, 678 expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_string"`, 679 }, 680 { 681 name: "Assigning appended selects to nonconfigurable string", 682 bp: ` 683 my_module_type { 684 name: "foo", 685 my_nonconfigurable_string: select(arch(), { 686 "x86_64": "x86!", 687 default: "unknown!", 688 }) + select(os(), { 689 "darwin": "_darwin!", 690 default: "unknown!", 691 }), 692 } 693 `, 694 expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_string"`, 695 }, 696 { 697 name: "Assigning select to nonconfigurable string list", 698 bp: ` 699 my_module_type { 700 name: "foo", 701 my_nonconfigurable_string_list: select(arch(), { 702 "x86_64": ["foo", "bar"], 703 default: ["baz", "qux"], 704 }), 705 } 706 `, 707 expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_string_list"`, 708 }, 709 { 710 name: "Select in variable", 711 bp: ` 712 my_second_variable = ["after.cpp"] 713 my_variable = select(soong_config_variable("my_namespace", "my_variable"), { 714 "a": ["a.cpp"], 715 "b": ["b.cpp"], 716 default: ["c.cpp"], 717 }) + my_second_variable 718 my_module_type { 719 name: "foo", 720 my_string_list: ["before.cpp"] + my_variable, 721 } 722 `, 723 provider: selectsTestProvider{ 724 my_string_list: &[]string{"before.cpp", "a.cpp", "after.cpp"}, 725 }, 726 vendorVars: map[string]map[string]string{ 727 "my_namespace": { 728 "my_variable": "a", 729 }, 730 }, 731 }, 732 { 733 name: "Soong config value variable on configurable property", 734 bp: ` 735 soong_config_module_type { 736 name: "soong_config_my_module_type", 737 module_type: "my_module_type", 738 config_namespace: "my_namespace", 739 value_variables: ["my_variable"], 740 properties: ["my_string", "my_string_list"], 741 } 742 743 soong_config_my_module_type { 744 name: "foo", 745 my_string_list: ["before.cpp"], 746 soong_config_variables: { 747 my_variable: { 748 my_string_list: ["after_%s.cpp"], 749 my_string: "%s.cpp", 750 }, 751 }, 752 } 753 `, 754 provider: selectsTestProvider{ 755 my_string: proptools.StringPtr("foo.cpp"), 756 my_string_list: &[]string{"before.cpp", "after_foo.cpp"}, 757 }, 758 vendorVars: map[string]map[string]string{ 759 "my_namespace": { 760 "my_variable": "foo", 761 }, 762 }, 763 }, 764 { 765 name: "Property appending with variable", 766 bp: ` 767 my_variable = ["b.cpp"] 768 my_module_type { 769 name: "foo", 770 my_string_list: ["a.cpp"] + my_variable + select(soong_config_variable("my_namespace", "my_variable"), { 771 "a": ["a.cpp"], 772 "b": ["b.cpp"], 773 default: ["c.cpp"], 774 }), 775 } 776 `, 777 provider: selectsTestProvider{ 778 my_string_list: &[]string{"a.cpp", "b.cpp", "c.cpp"}, 779 }, 780 }, 781 { 782 name: "Test AppendSimpleValue", 783 bp: ` 784 my_module_type { 785 name: "foo", 786 my_string_list: ["a.cpp"] + select(soong_config_variable("my_namespace", "my_variable"), { 787 "a": ["a.cpp"], 788 "b": ["b.cpp"], 789 default: ["c.cpp"], 790 }), 791 } 792 `, 793 vendorVars: map[string]map[string]string{ 794 "selects_test": { 795 "append_to_string_list": "foo.cpp", 796 }, 797 }, 798 provider: selectsTestProvider{ 799 my_string_list: &[]string{"a.cpp", "c.cpp", "foo.cpp"}, 800 }, 801 }, 802 } 803 804 for _, tc := range testCases { 805 t.Run(tc.name, func(t *testing.T) { 806 fixtures := GroupFixturePreparers( 807 PrepareForTestWithDefaults, 808 PrepareForTestWithArchMutator, 809 PrepareForTestWithSoongConfigModuleBuildComponents, 810 FixtureRegisterWithContext(func(ctx RegistrationContext) { 811 ctx.RegisterModuleType("my_module_type", newSelectsMockModule) 812 ctx.RegisterModuleType("my_defaults", newSelectsMockModuleDefaults) 813 }), 814 FixtureModifyProductVariables(func(variables FixtureProductVariables) { 815 variables.VendorVars = tc.vendorVars 816 }), 817 ) 818 if tc.expectedError != "" { 819 fixtures = fixtures.ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(tc.expectedError)) 820 } 821 result := fixtures.RunTestWithBp(t, tc.bp) 822 823 if tc.expectedError == "" { 824 if len(tc.providers) == 0 { 825 tc.providers = map[string]selectsTestProvider{ 826 "foo": tc.provider, 827 } 828 } 829 830 for moduleName := range tc.providers { 831 expected := tc.providers[moduleName] 832 m := result.ModuleForTests(moduleName, "android_arm64_armv8-a") 833 p, _ := OtherModuleProvider(result.testContext.OtherModuleProviderAdaptor(), m.Module(), selectsTestProviderKey) 834 if !reflect.DeepEqual(p, expected) { 835 t.Errorf("Expected:\n %q\ngot:\n %q", expected.String(), p.String()) 836 } 837 } 838 } 839 }) 840 } 841} 842 843type selectsTestProvider struct { 844 my_bool *bool 845 my_string *string 846 my_string_list *[]string 847 my_paths *[]string 848 replacing_string_list *[]string 849 my_nonconfigurable_bool *bool 850 my_nonconfigurable_string *string 851 my_nonconfigurable_string_list []string 852} 853 854func (p *selectsTestProvider) String() string { 855 myBoolStr := "nil" 856 if p.my_bool != nil { 857 myBoolStr = fmt.Sprintf("%t", *p.my_bool) 858 } 859 myStringStr := "nil" 860 if p.my_string != nil { 861 myStringStr = *p.my_string 862 } 863 myNonconfigurableStringStr := "nil" 864 if p.my_nonconfigurable_string != nil { 865 myNonconfigurableStringStr = *p.my_nonconfigurable_string 866 } 867 return fmt.Sprintf(`selectsTestProvider { 868 my_bool: %v, 869 my_string: %s, 870 my_string_list: %s, 871 my_paths: %s, 872 replacing_string_list %s, 873 my_nonconfigurable_bool: %v, 874 my_nonconfigurable_string: %s, 875 my_nonconfigurable_string_list: %s, 876}`, 877 myBoolStr, 878 myStringStr, 879 p.my_string_list, 880 p.my_paths, 881 p.replacing_string_list, 882 p.my_nonconfigurable_bool, 883 myNonconfigurableStringStr, 884 p.my_nonconfigurable_string_list, 885 ) 886} 887 888var selectsTestProviderKey = blueprint.NewProvider[selectsTestProvider]() 889 890type selectsMockModuleProperties struct { 891 My_bool proptools.Configurable[bool] 892 My_string proptools.Configurable[string] 893 My_string_list proptools.Configurable[[]string] 894 My_paths proptools.Configurable[[]string] `android:"path"` 895 Replacing_string_list proptools.Configurable[[]string] `android:"replace_instead_of_append,arch_variant"` 896 My_nonconfigurable_bool *bool 897 My_nonconfigurable_string *string 898 My_nonconfigurable_string_list []string 899} 900 901type selectsMockModule struct { 902 ModuleBase 903 DefaultableModuleBase 904 properties selectsMockModuleProperties 905} 906 907func optionalToPtr[T any](o proptools.ConfigurableOptional[T]) *T { 908 if o.IsEmpty() { 909 return nil 910 } 911 x := o.Get() 912 return &x 913} 914 915func (p *selectsMockModule) GenerateAndroidBuildActions(ctx ModuleContext) { 916 toAppend := ctx.Config().VendorConfig("selects_test").String("append_to_string_list") 917 if toAppend != "" { 918 p.properties.My_string_list.AppendSimpleValue([]string{toAppend}) 919 } 920 SetProvider(ctx, selectsTestProviderKey, selectsTestProvider{ 921 my_bool: optionalToPtr(p.properties.My_bool.Get(ctx)), 922 my_string: optionalToPtr(p.properties.My_string.Get(ctx)), 923 my_string_list: optionalToPtr(p.properties.My_string_list.Get(ctx)), 924 my_paths: optionalToPtr(p.properties.My_paths.Get(ctx)), 925 replacing_string_list: optionalToPtr(p.properties.Replacing_string_list.Get(ctx)), 926 my_nonconfigurable_bool: p.properties.My_nonconfigurable_bool, 927 my_nonconfigurable_string: p.properties.My_nonconfigurable_string, 928 my_nonconfigurable_string_list: p.properties.My_nonconfigurable_string_list, 929 }) 930} 931 932func newSelectsMockModule() Module { 933 m := &selectsMockModule{} 934 m.AddProperties(&m.properties) 935 InitAndroidArchModule(m, HostAndDeviceSupported, MultilibFirst) 936 InitDefaultableModule(m) 937 return m 938} 939 940type selectsMockModuleDefaults struct { 941 ModuleBase 942 DefaultsModuleBase 943} 944 945func (d *selectsMockModuleDefaults) GenerateAndroidBuildActions(ctx ModuleContext) { 946} 947 948func newSelectsMockModuleDefaults() Module { 949 module := &selectsMockModuleDefaults{} 950 951 module.AddProperties( 952 &selectsMockModuleProperties{}, 953 ) 954 955 InitDefaultsModule(module) 956 957 return module 958} 959