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