blob: b987d56974fc0bf4d0fdd30b0a70642d275d9722 [file] [log] [blame]
Colin Crosscb988072019-01-24 14:58:11 -08001// Copyright 2019 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 "reflect"
Colin Cross158eeb72019-10-16 13:06:07 -070019 "runtime"
Colin Crosscb988072019-01-24 14:58:11 -080020 "testing"
Colin Cross74449102019-09-25 11:26:40 -070021
22 "github.com/google/blueprint/proptools"
Colin Crosscb988072019-01-24 14:58:11 -080023)
24
25type Named struct {
26 A *string `android:"arch_variant"`
27 B *string
28}
29
30type NamedAllFiltered struct {
31 A *string
32}
33
34type NamedNoneFiltered struct {
35 A *string `android:"arch_variant"`
36}
37
38func TestFilterArchStruct(t *testing.T) {
39 tests := []struct {
40 name string
41 in interface{}
42 out interface{}
43 filtered bool
44 }{
45 // Property tests
46 {
47 name: "basic",
48 in: &struct {
49 A *string `android:"arch_variant"`
50 B *string
51 }{},
52 out: &struct {
53 A *string
54 }{},
55 filtered: true,
56 },
57 {
Colin Crossb4fecbf2020-01-21 11:38:47 -080058 name: "tags",
59 in: &struct {
60 A *string `android:"arch_variant"`
61 B *string `android:"arch_variant,path"`
62 C *string `android:"arch_variant,path,variant_prepend"`
63 D *string `android:"path,variant_prepend,arch_variant"`
64 E *string `android:"path"`
65 F *string
66 }{},
67 out: &struct {
68 A *string
69 B *string
70 C *string
71 D *string
72 }{},
73 filtered: true,
74 },
75 {
Colin Crosscb988072019-01-24 14:58:11 -080076 name: "all filtered",
77 in: &struct {
78 A *string
79 }{},
80 out: nil,
81 filtered: true,
82 },
83 {
84 name: "none filtered",
85 in: &struct {
86 A *string `android:"arch_variant"`
87 }{},
88 out: &struct {
89 A *string `android:"arch_variant"`
90 }{},
91 filtered: false,
92 },
93
94 // Sub-struct tests
95 {
96 name: "substruct",
97 in: &struct {
98 A struct {
99 A *string `android:"arch_variant"`
100 B *string
101 } `android:"arch_variant"`
102 }{},
103 out: &struct {
104 A struct {
105 A *string
106 }
107 }{},
108 filtered: true,
109 },
110 {
111 name: "substruct all filtered",
112 in: &struct {
113 A struct {
114 A *string
115 } `android:"arch_variant"`
116 }{},
117 out: nil,
118 filtered: true,
119 },
120 {
121 name: "substruct none filtered",
122 in: &struct {
123 A struct {
124 A *string `android:"arch_variant"`
125 } `android:"arch_variant"`
126 }{},
127 out: &struct {
128 A struct {
129 A *string `android:"arch_variant"`
130 } `android:"arch_variant"`
131 }{},
132 filtered: false,
133 },
134
135 // Named sub-struct tests
136 {
137 name: "named substruct",
138 in: &struct {
139 A Named `android:"arch_variant"`
140 }{},
141 out: &struct {
142 A struct {
143 A *string
144 }
145 }{},
146 filtered: true,
147 },
148 {
149 name: "substruct all filtered",
150 in: &struct {
151 A NamedAllFiltered `android:"arch_variant"`
152 }{},
153 out: nil,
154 filtered: true,
155 },
156 {
157 name: "substruct none filtered",
158 in: &struct {
159 A NamedNoneFiltered `android:"arch_variant"`
160 }{},
161 out: &struct {
162 A NamedNoneFiltered `android:"arch_variant"`
163 }{},
164 filtered: false,
165 },
166
167 // Pointer to sub-struct tests
168 {
169 name: "pointer substruct",
170 in: &struct {
171 A *struct {
172 A *string `android:"arch_variant"`
173 B *string
174 } `android:"arch_variant"`
175 }{},
176 out: &struct {
177 A *struct {
178 A *string
179 }
180 }{},
181 filtered: true,
182 },
183 {
184 name: "pointer substruct all filtered",
185 in: &struct {
186 A *struct {
187 A *string
188 } `android:"arch_variant"`
189 }{},
190 out: nil,
191 filtered: true,
192 },
193 {
194 name: "pointer substruct none filtered",
195 in: &struct {
196 A *struct {
197 A *string `android:"arch_variant"`
198 } `android:"arch_variant"`
199 }{},
200 out: &struct {
201 A *struct {
202 A *string `android:"arch_variant"`
203 } `android:"arch_variant"`
204 }{},
205 filtered: false,
206 },
207
208 // Pointer to named sub-struct tests
209 {
210 name: "pointer named substruct",
211 in: &struct {
212 A *Named `android:"arch_variant"`
213 }{},
214 out: &struct {
215 A *struct {
216 A *string
217 }
218 }{},
219 filtered: true,
220 },
221 {
222 name: "pointer substruct all filtered",
223 in: &struct {
224 A *NamedAllFiltered `android:"arch_variant"`
225 }{},
226 out: nil,
227 filtered: true,
228 },
229 {
230 name: "pointer substruct none filtered",
231 in: &struct {
232 A *NamedNoneFiltered `android:"arch_variant"`
233 }{},
234 out: &struct {
235 A *NamedNoneFiltered `android:"arch_variant"`
236 }{},
237 filtered: false,
238 },
239 }
240
241 for _, test := range tests {
242 t.Run(test.name, func(t *testing.T) {
Colin Cross74449102019-09-25 11:26:40 -0700243 out, filtered := proptools.FilterPropertyStruct(reflect.TypeOf(test.in), filterArchStruct)
Colin Crosscb988072019-01-24 14:58:11 -0800244 if filtered != test.filtered {
245 t.Errorf("expected filtered %v, got %v", test.filtered, filtered)
246 }
247 expected := reflect.TypeOf(test.out)
248 if out != expected {
249 t.Errorf("expected type %v, got %v", expected, out)
250 }
251 })
252 }
253}
Colin Cross158eeb72019-10-16 13:06:07 -0700254
255type archTestModule struct {
256 ModuleBase
257 props struct {
258 Deps []string
259 }
260}
261
262func (m *archTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
263}
264
265func (m *archTestModule) DepsMutator(ctx BottomUpMutatorContext) {
266 ctx.AddDependency(ctx.Module(), nil, m.props.Deps...)
267}
268
269func archTestModuleFactory() Module {
270 m := &archTestModule{}
271 m.AddProperties(&m.props)
272 InitAndroidArchModule(m, HostAndDeviceSupported, MultilibBoth)
273 return m
274}
275
276func TestArchMutator(t *testing.T) {
277 var buildOSVariants []string
278 var buildOS32Variants []string
279 switch runtime.GOOS {
280 case "linux":
281 buildOSVariants = []string{"linux_glibc_x86_64", "linux_glibc_x86"}
282 buildOS32Variants = []string{"linux_glibc_x86"}
283 case "darwin":
284 buildOSVariants = []string{"darwin_x86_64"}
285 buildOS32Variants = nil
286 }
287
288 bp := `
289 module {
290 name: "foo",
291 }
292
293 module {
294 name: "bar",
295 host_supported: true,
296 }
297
298 module {
299 name: "baz",
300 device_supported: false,
301 }
302
303 module {
304 name: "qux",
305 host_supported: true,
306 compile_multilib: "32",
307 }
308 `
309
Colin Cross158eeb72019-10-16 13:06:07 -0700310 testCases := []struct {
311 name string
312 config func(Config)
313 fooVariants []string
314 barVariants []string
315 bazVariants []string
316 quxVariants []string
317 }{
318 {
319 name: "normal",
320 config: nil,
321 fooVariants: []string{"android_arm64_armv8-a", "android_arm_armv7-a-neon"},
322 barVariants: append(buildOSVariants, "android_arm64_armv8-a", "android_arm_armv7-a-neon"),
323 bazVariants: nil,
324 quxVariants: append(buildOS32Variants, "android_arm_armv7-a-neon"),
325 },
326 {
327 name: "host-only",
328 config: func(config Config) {
329 config.BuildOSTarget = Target{}
330 config.BuildOSCommonTarget = Target{}
331 config.Targets[Android] = nil
332 },
333 fooVariants: nil,
334 barVariants: buildOSVariants,
335 bazVariants: nil,
336 quxVariants: buildOS32Variants,
337 },
338 }
339
340 enabledVariants := func(ctx *TestContext, name string) []string {
341 var ret []string
342 variants := ctx.ModuleVariantsForTests(name)
343 for _, variant := range variants {
344 m := ctx.ModuleForTests(name, variant)
345 if m.Module().Enabled() {
346 ret = append(ret, variant)
347 }
348 }
349 return ret
350 }
351
352 for _, tt := range testCases {
353 t.Run(tt.name, func(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -0800354 config := TestArchConfig(buildDir, nil, bp, nil)
355
Colin Cross158eeb72019-10-16 13:06:07 -0700356 ctx := NewTestArchContext()
Colin Cross4b49b762019-11-22 15:25:03 -0800357 ctx.RegisterModuleType("module", archTestModuleFactory)
Colin Cross98be1bb2019-12-13 20:41:13 -0800358 ctx.Register(config)
Colin Cross158eeb72019-10-16 13:06:07 -0700359 if tt.config != nil {
360 tt.config(config)
361 }
362
363 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
364 FailIfErrored(t, errs)
365 _, errs = ctx.PrepareBuildActions(config)
366 FailIfErrored(t, errs)
367
368 if g, w := enabledVariants(ctx, "foo"), tt.fooVariants; !reflect.DeepEqual(w, g) {
369 t.Errorf("want foo variants:\n%q\ngot:\n%q\n", w, g)
370 }
371
372 if g, w := enabledVariants(ctx, "bar"), tt.barVariants; !reflect.DeepEqual(w, g) {
373 t.Errorf("want bar variants:\n%q\ngot:\n%q\n", w, g)
374 }
375
376 if g, w := enabledVariants(ctx, "baz"), tt.bazVariants; !reflect.DeepEqual(w, g) {
377 t.Errorf("want baz variants:\n%q\ngot:\n%q\n", w, g)
378 }
379
380 if g, w := enabledVariants(ctx, "qux"), tt.quxVariants; !reflect.DeepEqual(w, g) {
381 t.Errorf("want qux variants:\n%q\ngot:\n%q\n", w, g)
382 }
383 })
384 }
385}