|  | // Copyright 2024 Google Inc. All rights reserved. | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | // you may not use this file except in compliance with the License. | 
|  | // You may obtain a copy of the License at | 
|  | // | 
|  | //     http://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, software | 
|  | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | // See the License for the specific language governing permissions and | 
|  | // limitations under the License. | 
|  |  | 
|  | package android | 
|  |  | 
|  | import ( | 
|  | "fmt" | 
|  | "reflect" | 
|  | "testing" | 
|  |  | 
|  | "github.com/google/blueprint" | 
|  | "github.com/google/blueprint/proptools" | 
|  | ) | 
|  |  | 
|  | func TestSelects(t *testing.T) { | 
|  | testCases := []struct { | 
|  | name          string | 
|  | bp            string | 
|  | provider      selectsTestProvider | 
|  | vendorVars    map[string]map[string]string | 
|  | expectedError string | 
|  | }{ | 
|  | { | 
|  | name: "basic string list", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_string_list: select(soong_config_variable("my_namespace", "my_variable"), { | 
|  | "a": ["a.cpp"], | 
|  | "b": ["b.cpp"], | 
|  | default: ["c.cpp"], | 
|  | }), | 
|  | } | 
|  | `, | 
|  | provider: selectsTestProvider{ | 
|  | my_string_list: &[]string{"c.cpp"}, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "basic string", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_string: select(soong_config_variable("my_namespace", "my_variable"), { | 
|  | "a": "a.cpp", | 
|  | "b": "b.cpp", | 
|  | default: "c.cpp", | 
|  | }), | 
|  | } | 
|  | `, | 
|  | provider: selectsTestProvider{ | 
|  | my_string: proptools.StringPtr("c.cpp"), | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "basic bool", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_bool: select(soong_config_variable("my_namespace", "my_variable"), { | 
|  | "a": true, | 
|  | "b": false, | 
|  | default: true, | 
|  | }), | 
|  | } | 
|  | `, | 
|  | provider: selectsTestProvider{ | 
|  | my_bool: proptools.BoolPtr(true), | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "basic paths", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_paths: select(soong_config_variable("my_namespace", "my_variable"), { | 
|  | "a": ["foo.txt"], | 
|  | "b": ["bar.txt"], | 
|  | default: ["baz.txt"], | 
|  | }), | 
|  | } | 
|  | `, | 
|  | provider: selectsTestProvider{ | 
|  | my_paths: &[]string{"baz.txt"}, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "paths with module references", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_paths: select(soong_config_variable("my_namespace", "my_variable"), { | 
|  | "a": [":a"], | 
|  | "b": [":b"], | 
|  | default: [":c"], | 
|  | }), | 
|  | } | 
|  | `, | 
|  | expectedError: `"foo" depends on undefined module "c"`, | 
|  | }, | 
|  | { | 
|  | name: "Differing types", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_string: select(soong_config_variable("my_namespace", "my_variable"), { | 
|  | "a": "a.cpp", | 
|  | "b": true, | 
|  | default: "c.cpp", | 
|  | }), | 
|  | } | 
|  | `, | 
|  | expectedError: `Android.bp:8:5: Found select statement with differing types "string" and "bool" in its cases`, | 
|  | }, | 
|  | { | 
|  | name: "Select type doesn't match property type", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_string: select(soong_config_variable("my_namespace", "my_variable"), { | 
|  | "a": false, | 
|  | "b": true, | 
|  | default: true, | 
|  | }), | 
|  | } | 
|  | `, | 
|  | expectedError: `can't assign bool value to string property "my_string\[0\]"`, | 
|  | }, | 
|  | { | 
|  | name: "String list non-default", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_string_list: select(soong_config_variable("my_namespace", "my_variable"), { | 
|  | "a": ["a.cpp"], | 
|  | "b": ["b.cpp"], | 
|  | default: ["c.cpp"], | 
|  | }), | 
|  | } | 
|  | `, | 
|  | provider: selectsTestProvider{ | 
|  | my_string_list: &[]string{"a.cpp"}, | 
|  | }, | 
|  | vendorVars: map[string]map[string]string{ | 
|  | "my_namespace": { | 
|  | "my_variable": "a", | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "String list append", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_string_list: select(soong_config_variable("my_namespace", "my_variable"), { | 
|  | "a": ["a.cpp"], | 
|  | "b": ["b.cpp"], | 
|  | default: ["c.cpp"], | 
|  | }) + select(soong_config_variable("my_namespace", "my_variable_2"), { | 
|  | "a2": ["a2.cpp"], | 
|  | "b2": ["b2.cpp"], | 
|  | default: ["c2.cpp"], | 
|  | }), | 
|  | } | 
|  | `, | 
|  | provider: selectsTestProvider{ | 
|  | my_string_list: &[]string{"a.cpp", "c2.cpp"}, | 
|  | }, | 
|  | vendorVars: map[string]map[string]string{ | 
|  | "my_namespace": { | 
|  | "my_variable": "a", | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "String list prepend literal", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_string_list: ["literal.cpp"] + select(soong_config_variable("my_namespace", "my_variable"), { | 
|  | "a2": ["a2.cpp"], | 
|  | "b2": ["b2.cpp"], | 
|  | default: ["c2.cpp"], | 
|  | }), | 
|  | } | 
|  | `, | 
|  | provider: selectsTestProvider{ | 
|  | my_string_list: &[]string{"literal.cpp", "c2.cpp"}, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "String list append literal", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_string_list: select(soong_config_variable("my_namespace", "my_variable"), { | 
|  | "a2": ["a2.cpp"], | 
|  | "b2": ["b2.cpp"], | 
|  | default: ["c2.cpp"], | 
|  | }) + ["literal.cpp"], | 
|  | } | 
|  | `, | 
|  | provider: selectsTestProvider{ | 
|  | my_string_list: &[]string{"c2.cpp", "literal.cpp"}, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "true + false = true", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_bool: select(soong_config_variable("my_namespace", "my_variable"), { | 
|  | "a": true, | 
|  | "b": false, | 
|  | default: true, | 
|  | }) + false, | 
|  | } | 
|  | `, | 
|  | provider: selectsTestProvider{ | 
|  | my_bool: proptools.BoolPtr(true), | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "false + false = false", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_bool: select(soong_config_variable("my_namespace", "my_variable"), { | 
|  | "a": true, | 
|  | "b": false, | 
|  | default: true, | 
|  | }) + false, | 
|  | } | 
|  | `, | 
|  | vendorVars: map[string]map[string]string{ | 
|  | "my_namespace": { | 
|  | "my_variable": "b", | 
|  | }, | 
|  | }, | 
|  | provider: selectsTestProvider{ | 
|  | my_bool: proptools.BoolPtr(false), | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "Append string", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_string: select(soong_config_variable("my_namespace", "my_variable"), { | 
|  | "a": "a", | 
|  | "b": "b", | 
|  | default: "c", | 
|  | }) + ".cpp", | 
|  | } | 
|  | `, | 
|  | provider: selectsTestProvider{ | 
|  | my_string: proptools.StringPtr("c.cpp"), | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "Select on arch", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_string: select(arch(), { | 
|  | "x86": "my_x86", | 
|  | "x86_64": "my_x86_64", | 
|  | "arm": "my_arm", | 
|  | "arm64": "my_arm64", | 
|  | default: "my_default", | 
|  | }), | 
|  | } | 
|  | `, | 
|  | provider: selectsTestProvider{ | 
|  | my_string: proptools.StringPtr("my_arm64"), | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "Select on os", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_string: select(os(), { | 
|  | "android": "my_android", | 
|  | "linux": "my_linux", | 
|  | default: "my_default", | 
|  | }), | 
|  | } | 
|  | `, | 
|  | provider: selectsTestProvider{ | 
|  | my_string: proptools.StringPtr("my_android"), | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "Unset value", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_string: select(soong_config_variable("my_namespace", "my_variable"), { | 
|  | "a": unset, | 
|  | "b": "b", | 
|  | default: "c", | 
|  | }) | 
|  | } | 
|  | `, | 
|  | vendorVars: map[string]map[string]string{ | 
|  | "my_namespace": { | 
|  | "my_variable": "a", | 
|  | }, | 
|  | }, | 
|  | provider: selectsTestProvider{}, | 
|  | }, | 
|  | { | 
|  | name: "Unset value on different branch", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_string: select(soong_config_variable("my_namespace", "my_variable"), { | 
|  | "a": unset, | 
|  | "b": "b", | 
|  | default: "c", | 
|  | }) | 
|  | } | 
|  | `, | 
|  | provider: selectsTestProvider{ | 
|  | my_string: proptools.StringPtr("c"), | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "unset + unset = unset", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_string: select(soong_config_variable("my_namespace", "my_variable"), { | 
|  | "foo": "bar", | 
|  | default: unset, | 
|  | }) + select(soong_config_variable("my_namespace", "my_variable2"), { | 
|  | "baz": "qux", | 
|  | default: unset, | 
|  | }) | 
|  | } | 
|  | `, | 
|  | provider: selectsTestProvider{}, | 
|  | }, | 
|  | { | 
|  | name: "unset + string = string", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_string: select(soong_config_variable("my_namespace", "my_variable"), { | 
|  | "foo": "bar", | 
|  | default: unset, | 
|  | }) + select(soong_config_variable("my_namespace", "my_variable2"), { | 
|  | default: "a", | 
|  | }) | 
|  | } | 
|  | `, | 
|  | provider: selectsTestProvider{ | 
|  | my_string: proptools.StringPtr("a"), | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "unset + bool = bool", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_bool: select(soong_config_variable("my_namespace", "my_variable"), { | 
|  | "a": true, | 
|  | default: unset, | 
|  | }) + select(soong_config_variable("my_namespace", "my_variable2"), { | 
|  | default: true, | 
|  | }) | 
|  | } | 
|  | `, | 
|  | provider: selectsTestProvider{ | 
|  | my_bool: proptools.BoolPtr(true), | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "defaults with lists are appended", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | defaults: ["bar"], | 
|  | my_string_list: select(soong_config_variable("my_namespace", "my_variable"), { | 
|  | "a": ["a1"], | 
|  | default: ["b1"], | 
|  | }), | 
|  | } | 
|  | my_defaults { | 
|  | name: "bar", | 
|  | my_string_list: select(soong_config_variable("my_namespace", "my_variable2"), { | 
|  | "a": ["a2"], | 
|  | default: ["b2"], | 
|  | }), | 
|  | } | 
|  | `, | 
|  | provider: selectsTestProvider{ | 
|  | my_string_list: &[]string{"b2", "b1"}, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "Replacing string list", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | defaults: ["bar"], | 
|  | replacing_string_list: select(soong_config_variable("my_namespace", "my_variable"), { | 
|  | "a": ["a1"], | 
|  | default: ["b1"], | 
|  | }), | 
|  | } | 
|  | my_defaults { | 
|  | name: "bar", | 
|  | replacing_string_list: select(soong_config_variable("my_namespace", "my_variable2"), { | 
|  | "a": ["a2"], | 
|  | default: ["b2"], | 
|  | }), | 
|  | } | 
|  | `, | 
|  | provider: selectsTestProvider{ | 
|  | replacing_string_list: &[]string{"b1"}, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "Multi-condition string 1", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_string: select(( | 
|  | soong_config_variable("my_namespace", "my_variable"), | 
|  | soong_config_variable("my_namespace", "my_variable2"), | 
|  | ), { | 
|  | ("a", "b"): "a+b", | 
|  | ("a", default): "a+default", | 
|  | (default, default): "default", | 
|  | }), | 
|  | } | 
|  | `, | 
|  | vendorVars: map[string]map[string]string{ | 
|  | "my_namespace": { | 
|  | "my_variable":  "a", | 
|  | "my_variable2": "b", | 
|  | }, | 
|  | }, | 
|  | provider: selectsTestProvider{ | 
|  | my_string: proptools.StringPtr("a+b"), | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "Multi-condition string 2", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_string: select(( | 
|  | soong_config_variable("my_namespace", "my_variable"), | 
|  | soong_config_variable("my_namespace", "my_variable2"), | 
|  | ), { | 
|  | ("a", "b"): "a+b", | 
|  | ("a", default): "a+default", | 
|  | (default, default): "default", | 
|  | }), | 
|  | } | 
|  | `, | 
|  | vendorVars: map[string]map[string]string{ | 
|  | "my_namespace": { | 
|  | "my_variable":  "a", | 
|  | "my_variable2": "c", | 
|  | }, | 
|  | }, | 
|  | provider: selectsTestProvider{ | 
|  | my_string: proptools.StringPtr("a+default"), | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "Multi-condition string 3", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_string: select(( | 
|  | soong_config_variable("my_namespace", "my_variable"), | 
|  | soong_config_variable("my_namespace", "my_variable2"), | 
|  | ), { | 
|  | ("a", "b"): "a+b", | 
|  | ("a", default): "a+default", | 
|  | (default, default): "default", | 
|  | }), | 
|  | } | 
|  | `, | 
|  | vendorVars: map[string]map[string]string{ | 
|  | "my_namespace": { | 
|  | "my_variable":  "c", | 
|  | "my_variable2": "b", | 
|  | }, | 
|  | }, | 
|  | provider: selectsTestProvider{ | 
|  | my_string: proptools.StringPtr("default"), | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "Select on boolean", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_string: select(boolean_var_for_testing(), { | 
|  | true: "t", | 
|  | false: "f", | 
|  | }), | 
|  | } | 
|  | `, | 
|  | vendorVars: map[string]map[string]string{ | 
|  | "boolean_var": { | 
|  | "for_testing": "true", | 
|  | }, | 
|  | }, | 
|  | provider: selectsTestProvider{ | 
|  | my_string: proptools.StringPtr("t"), | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "Select on boolean false", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_string: select(boolean_var_for_testing(), { | 
|  | true: "t", | 
|  | false: "f", | 
|  | }), | 
|  | } | 
|  | `, | 
|  | vendorVars: map[string]map[string]string{ | 
|  | "boolean_var": { | 
|  | "for_testing": "false", | 
|  | }, | 
|  | }, | 
|  | provider: selectsTestProvider{ | 
|  | my_string: proptools.StringPtr("f"), | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "Select on boolean undefined", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_string: select(boolean_var_for_testing(), { | 
|  | true: "t", | 
|  | false: "f", | 
|  | }), | 
|  | } | 
|  | `, | 
|  | expectedError: "foo", | 
|  | }, | 
|  | { | 
|  | name: "Select on boolean undefined with default", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_string: select(boolean_var_for_testing(), { | 
|  | true: "t", | 
|  | false: "f", | 
|  | default: "default", | 
|  | }), | 
|  | } | 
|  | `, | 
|  | provider: selectsTestProvider{ | 
|  | my_string: proptools.StringPtr("default"), | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "Mismatched condition types", | 
|  | bp: ` | 
|  | my_module_type { | 
|  | name: "foo", | 
|  | my_string: select(boolean_var_for_testing(), { | 
|  | "true": "t", | 
|  | "false": "f", | 
|  | default: "default", | 
|  | }), | 
|  | } | 
|  | `, | 
|  | vendorVars: map[string]map[string]string{ | 
|  | "boolean_var": { | 
|  | "for_testing": "false", | 
|  | }, | 
|  | }, | 
|  | expectedError: "Expected all branches of a select on condition boolean_var_for_testing\\(\\) to have type bool, found string", | 
|  | }, | 
|  | } | 
|  |  | 
|  | for _, tc := range testCases { | 
|  | t.Run(tc.name, func(t *testing.T) { | 
|  | fixtures := GroupFixturePreparers( | 
|  | PrepareForTestWithDefaults, | 
|  | PrepareForTestWithArchMutator, | 
|  | FixtureRegisterWithContext(func(ctx RegistrationContext) { | 
|  | ctx.RegisterModuleType("my_module_type", newSelectsMockModule) | 
|  | ctx.RegisterModuleType("my_defaults", newSelectsMockModuleDefaults) | 
|  | }), | 
|  | FixtureModifyProductVariables(func(variables FixtureProductVariables) { | 
|  | variables.VendorVars = tc.vendorVars | 
|  | }), | 
|  | ) | 
|  | if tc.expectedError != "" { | 
|  | fixtures = fixtures.ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(tc.expectedError)) | 
|  | } | 
|  | result := fixtures.RunTestWithBp(t, tc.bp) | 
|  |  | 
|  | if tc.expectedError == "" { | 
|  | m := result.ModuleForTests("foo", "android_arm64_armv8-a") | 
|  | p, _ := OtherModuleProvider(result.testContext.OtherModuleProviderAdaptor(), m.Module(), selectsTestProviderKey) | 
|  | if !reflect.DeepEqual(p, tc.provider) { | 
|  | t.Errorf("Expected:\n  %q\ngot:\n  %q", tc.provider.String(), p.String()) | 
|  | } | 
|  | } | 
|  | }) | 
|  | } | 
|  | } | 
|  |  | 
|  | type selectsTestProvider struct { | 
|  | my_bool               *bool | 
|  | my_string             *string | 
|  | my_string_list        *[]string | 
|  | my_paths              *[]string | 
|  | replacing_string_list *[]string | 
|  | } | 
|  |  | 
|  | func (p *selectsTestProvider) String() string { | 
|  | myBoolStr := "nil" | 
|  | if p.my_bool != nil { | 
|  | myBoolStr = fmt.Sprintf("%t", *p.my_bool) | 
|  | } | 
|  | myStringStr := "nil" | 
|  | if p.my_string != nil { | 
|  | myStringStr = *p.my_string | 
|  | } | 
|  | return fmt.Sprintf(`selectsTestProvider { | 
|  | my_bool: %v, | 
|  | my_string: %s, | 
|  | my_string_list: %s, | 
|  | my_paths: %s, | 
|  | replacing_string_list %s, | 
|  | }`, myBoolStr, myStringStr, p.my_string_list, p.my_paths, p.replacing_string_list) | 
|  | } | 
|  |  | 
|  | var selectsTestProviderKey = blueprint.NewProvider[selectsTestProvider]() | 
|  |  | 
|  | type selectsMockModuleProperties struct { | 
|  | My_bool               proptools.Configurable[bool] | 
|  | My_string             proptools.Configurable[string] | 
|  | My_string_list        proptools.Configurable[[]string] | 
|  | My_paths              proptools.Configurable[[]string] `android:"path"` | 
|  | Replacing_string_list proptools.Configurable[[]string] `android:"replace_instead_of_append,arch_variant"` | 
|  | } | 
|  |  | 
|  | type selectsMockModule struct { | 
|  | ModuleBase | 
|  | DefaultableModuleBase | 
|  | properties selectsMockModuleProperties | 
|  | } | 
|  |  | 
|  | func (p *selectsMockModule) GenerateAndroidBuildActions(ctx ModuleContext) { | 
|  | SetProvider(ctx, selectsTestProviderKey, selectsTestProvider{ | 
|  | my_bool:               p.properties.My_bool.Get(ctx), | 
|  | my_string:             p.properties.My_string.Get(ctx), | 
|  | my_string_list:        p.properties.My_string_list.Get(ctx), | 
|  | my_paths:              p.properties.My_paths.Get(ctx), | 
|  | replacing_string_list: p.properties.Replacing_string_list.Get(ctx), | 
|  | }) | 
|  | } | 
|  |  | 
|  | func newSelectsMockModule() Module { | 
|  | m := &selectsMockModule{} | 
|  | m.AddProperties(&m.properties) | 
|  | InitAndroidArchModule(m, HostAndDeviceSupported, MultilibFirst) | 
|  | InitDefaultableModule(m) | 
|  | return m | 
|  | } | 
|  |  | 
|  | type selectsMockModuleDefaults struct { | 
|  | ModuleBase | 
|  | DefaultsModuleBase | 
|  | } | 
|  |  | 
|  | func (d *selectsMockModuleDefaults) GenerateAndroidBuildActions(ctx ModuleContext) { | 
|  | } | 
|  |  | 
|  | func newSelectsMockModuleDefaults() Module { | 
|  | module := &selectsMockModuleDefaults{} | 
|  |  | 
|  | module.AddProperties( | 
|  | &selectsMockModuleProperties{}, | 
|  | ) | 
|  |  | 
|  | InitDefaultsModule(module) | 
|  |  | 
|  | return module | 
|  | } |