Colin Cross | 7e0eaf1 | 2017-05-05 16:16:24 -0700 | [diff] [blame] | 1 | // Copyright 2015 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 | |
| 15 | package android |
| 16 | |
| 17 | import ( |
| 18 | "reflect" |
Colin Cross | 18c4680 | 2019-09-24 22:19:02 -0700 | [diff] [blame] | 19 | "strconv" |
Colin Cross | 7e0eaf1 | 2017-05-05 16:16:24 -0700 | [diff] [blame] | 20 | "testing" |
Colin Cross | 18c4680 | 2019-09-24 22:19:02 -0700 | [diff] [blame] | 21 | |
| 22 | "github.com/google/blueprint/proptools" |
Colin Cross | 7e0eaf1 | 2017-05-05 16:16:24 -0700 | [diff] [blame] | 23 | ) |
| 24 | |
| 25 | type printfIntoPropertyTestCase struct { |
| 26 | in string |
| 27 | val interface{} |
| 28 | out string |
| 29 | err bool |
| 30 | } |
| 31 | |
| 32 | var printfIntoPropertyTestCases = []printfIntoPropertyTestCase{ |
| 33 | { |
| 34 | in: "%d", |
| 35 | val: 0, |
| 36 | out: "0", |
| 37 | }, |
| 38 | { |
| 39 | in: "%d", |
| 40 | val: 1, |
| 41 | out: "1", |
| 42 | }, |
| 43 | { |
| 44 | in: "%d", |
| 45 | val: 2, |
| 46 | out: "2", |
| 47 | }, |
| 48 | { |
| 49 | in: "%d", |
| 50 | val: false, |
| 51 | out: "0", |
| 52 | }, |
| 53 | { |
| 54 | in: "%d", |
| 55 | val: true, |
| 56 | out: "1", |
| 57 | }, |
| 58 | { |
| 59 | in: "%d", |
| 60 | val: -1, |
| 61 | out: "-1", |
| 62 | }, |
| 63 | |
| 64 | { |
| 65 | in: "-DA=%d", |
| 66 | val: 1, |
| 67 | out: "-DA=1", |
| 68 | }, |
| 69 | { |
| 70 | in: "-DA=%du", |
| 71 | val: 1, |
| 72 | out: "-DA=1u", |
| 73 | }, |
| 74 | { |
| 75 | in: "-DA=%s", |
| 76 | val: "abc", |
| 77 | out: "-DA=abc", |
| 78 | }, |
| 79 | { |
| 80 | in: `-DA="%s"`, |
| 81 | val: "abc", |
| 82 | out: `-DA="abc"`, |
| 83 | }, |
| 84 | |
| 85 | { |
| 86 | in: "%%", |
| 87 | err: true, |
| 88 | }, |
| 89 | { |
| 90 | in: "%d%s", |
| 91 | err: true, |
| 92 | }, |
| 93 | { |
| 94 | in: "%d,%s", |
| 95 | err: true, |
| 96 | }, |
| 97 | { |
| 98 | in: "%d", |
| 99 | val: "", |
| 100 | err: true, |
| 101 | }, |
| 102 | { |
| 103 | in: "%d", |
| 104 | val: 1.5, |
| 105 | err: true, |
| 106 | }, |
| 107 | { |
| 108 | in: "%f", |
| 109 | val: 1.5, |
| 110 | err: true, |
| 111 | }, |
| 112 | } |
| 113 | |
| 114 | func TestPrintfIntoProperty(t *testing.T) { |
| 115 | for _, testCase := range printfIntoPropertyTestCases { |
| 116 | s := testCase.in |
| 117 | v := reflect.ValueOf(&s).Elem() |
| 118 | err := printfIntoProperty(v, testCase.val) |
| 119 | if err != nil && !testCase.err { |
| 120 | t.Errorf("unexpected error %s", err) |
| 121 | } else if err == nil && testCase.err { |
| 122 | t.Errorf("expected error") |
| 123 | } else if err == nil && v.String() != testCase.out { |
| 124 | t.Errorf("expected %q got %q", testCase.out, v.String()) |
| 125 | } |
| 126 | } |
| 127 | } |
Colin Cross | 18c4680 | 2019-09-24 22:19:02 -0700 | [diff] [blame] | 128 | |
| 129 | type testProductVariableModule struct { |
| 130 | ModuleBase |
| 131 | } |
| 132 | |
| 133 | func (m *testProductVariableModule) GenerateAndroidBuildActions(ctx ModuleContext) { |
| 134 | } |
| 135 | |
| 136 | var testProductVariableProperties = struct { |
| 137 | Product_variables struct { |
| 138 | Eng struct { |
| 139 | Srcs []string |
| 140 | Cflags []string |
| 141 | } |
| 142 | } |
| 143 | }{} |
| 144 | |
| 145 | func testProductVariableModuleFactoryFactory(props interface{}) func() Module { |
| 146 | return func() Module { |
| 147 | m := &testProductVariableModule{} |
| 148 | clonedProps := proptools.CloneProperties(reflect.ValueOf(props)).Interface() |
| 149 | m.AddProperties(clonedProps) |
| 150 | |
Colin Cross | 9d34f35 | 2019-11-22 16:03:51 -0800 | [diff] [blame^] | 151 | // Set a default soongConfigVariableProperties, this will be used as the input to the property struct filter |
Colin Cross | 18c4680 | 2019-09-24 22:19:02 -0700 | [diff] [blame] | 152 | // for this test module. |
| 153 | m.variableProperties = testProductVariableProperties |
| 154 | InitAndroidModule(m) |
| 155 | return m |
| 156 | } |
| 157 | } |
| 158 | |
| 159 | func TestProductVariables(t *testing.T) { |
| 160 | ctx := NewTestContext() |
| 161 | // A module type that has a srcs property but not a cflags property. |
Colin Cross | 4b49b76 | 2019-11-22 15:25:03 -0800 | [diff] [blame] | 162 | ctx.RegisterModuleType("module1", testProductVariableModuleFactoryFactory(struct { |
Colin Cross | 18c4680 | 2019-09-24 22:19:02 -0700 | [diff] [blame] | 163 | Srcs []string |
Colin Cross | 4b49b76 | 2019-11-22 15:25:03 -0800 | [diff] [blame] | 164 | }{})) |
Colin Cross | 18c4680 | 2019-09-24 22:19:02 -0700 | [diff] [blame] | 165 | // A module type that has a cflags property but not a srcs property. |
Colin Cross | 4b49b76 | 2019-11-22 15:25:03 -0800 | [diff] [blame] | 166 | ctx.RegisterModuleType("module2", testProductVariableModuleFactoryFactory(struct { |
Colin Cross | 18c4680 | 2019-09-24 22:19:02 -0700 | [diff] [blame] | 167 | Cflags []string |
Colin Cross | 4b49b76 | 2019-11-22 15:25:03 -0800 | [diff] [blame] | 168 | }{})) |
Colin Cross | 18c4680 | 2019-09-24 22:19:02 -0700 | [diff] [blame] | 169 | // A module type that does not have any properties that match product_variables. |
Colin Cross | 4b49b76 | 2019-11-22 15:25:03 -0800 | [diff] [blame] | 170 | ctx.RegisterModuleType("module3", testProductVariableModuleFactoryFactory(struct { |
Colin Cross | 18c4680 | 2019-09-24 22:19:02 -0700 | [diff] [blame] | 171 | Foo []string |
Colin Cross | 4b49b76 | 2019-11-22 15:25:03 -0800 | [diff] [blame] | 172 | }{})) |
Colin Cross | 18c4680 | 2019-09-24 22:19:02 -0700 | [diff] [blame] | 173 | ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) { |
| 174 | ctx.BottomUp("variable", variableMutator).Parallel() |
| 175 | }) |
| 176 | |
| 177 | // Test that a module can use one product variable even if it doesn't have all the properties |
| 178 | // supported by that product variable. |
| 179 | bp := ` |
| 180 | module1 { |
| 181 | name: "foo", |
| 182 | product_variables: { |
| 183 | eng: { |
| 184 | srcs: ["foo.c"], |
| 185 | }, |
| 186 | }, |
| 187 | } |
| 188 | module2 { |
| 189 | name: "bar", |
| 190 | product_variables: { |
| 191 | eng: { |
| 192 | cflags: ["-DBAR"], |
| 193 | }, |
| 194 | }, |
| 195 | } |
| 196 | |
| 197 | module3 { |
| 198 | name: "baz", |
| 199 | } |
| 200 | ` |
Colin Cross | 98be1bb | 2019-12-13 20:41:13 -0800 | [diff] [blame] | 201 | config := TestConfig(buildDir, nil, bp, nil) |
Colin Cross | 18c4680 | 2019-09-24 22:19:02 -0700 | [diff] [blame] | 202 | config.TestProductVariables.Eng = proptools.BoolPtr(true) |
| 203 | |
Colin Cross | 98be1bb | 2019-12-13 20:41:13 -0800 | [diff] [blame] | 204 | ctx.Register(config) |
| 205 | |
Colin Cross | 18c4680 | 2019-09-24 22:19:02 -0700 | [diff] [blame] | 206 | _, errs := ctx.ParseFileList(".", []string{"Android.bp"}) |
| 207 | FailIfErrored(t, errs) |
| 208 | _, errs = ctx.PrepareBuildActions(config) |
| 209 | FailIfErrored(t, errs) |
| 210 | } |
| 211 | |
| 212 | func BenchmarkSliceToTypeArray(b *testing.B) { |
| 213 | for _, n := range []int{1, 2, 4, 8, 100} { |
| 214 | var propStructs []interface{} |
| 215 | for i := 0; i < n; i++ { |
| 216 | propStructs = append(propStructs, &struct { |
| 217 | A *string |
| 218 | B string |
| 219 | }{}) |
| 220 | |
| 221 | } |
| 222 | b.Run(strconv.Itoa(n), func(b *testing.B) { |
| 223 | for i := 0; i < b.N; i++ { |
| 224 | _ = sliceToTypeArray(propStructs) |
| 225 | } |
| 226 | }) |
| 227 | } |
| 228 | } |