blob: 52a66847ecf5a96f97cb47c46495857f7e92e71e [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
292 mockFS := map[string][]byte{
293 "Android.bp": []byte(bp),
294 }
295
296 testCases := []struct {
297 name string
298 config func(Config)
299 fooVariants []string
300 barVariants []string
301 bazVariants []string
302 quxVariants []string
303 }{
304 {
305 name: "normal",
306 config: nil,
307 fooVariants: []string{"android_arm64_armv8-a", "android_arm_armv7-a-neon"},
308 barVariants: append(buildOSVariants, "android_arm64_armv8-a", "android_arm_armv7-a-neon"),
309 bazVariants: nil,
310 quxVariants: append(buildOS32Variants, "android_arm_armv7-a-neon"),
311 },
312 {
313 name: "host-only",
314 config: func(config Config) {
315 config.BuildOSTarget = Target{}
316 config.BuildOSCommonTarget = Target{}
317 config.Targets[Android] = nil
318 },
319 fooVariants: nil,
320 barVariants: buildOSVariants,
321 bazVariants: nil,
322 quxVariants: buildOS32Variants,
323 },
324 }
325
326 enabledVariants := func(ctx *TestContext, name string) []string {
327 var ret []string
328 variants := ctx.ModuleVariantsForTests(name)
329 for _, variant := range variants {
330 m := ctx.ModuleForTests(name, variant)
331 if m.Module().Enabled() {
332 ret = append(ret, variant)
333 }
334 }
335 return ret
336 }
337
338 for _, tt := range testCases {
339 t.Run(tt.name, func(t *testing.T) {
340 ctx := NewTestArchContext()
341 ctx.RegisterModuleType("module", ModuleFactoryAdaptor(archTestModuleFactory))
342 ctx.MockFileSystem(mockFS)
343 ctx.Register()
344 config := TestArchConfig(buildDir, nil)
345 if tt.config != nil {
346 tt.config(config)
347 }
348
349 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
350 FailIfErrored(t, errs)
351 _, errs = ctx.PrepareBuildActions(config)
352 FailIfErrored(t, errs)
353
354 if g, w := enabledVariants(ctx, "foo"), tt.fooVariants; !reflect.DeepEqual(w, g) {
355 t.Errorf("want foo variants:\n%q\ngot:\n%q\n", w, g)
356 }
357
358 if g, w := enabledVariants(ctx, "bar"), tt.barVariants; !reflect.DeepEqual(w, g) {
359 t.Errorf("want bar variants:\n%q\ngot:\n%q\n", w, g)
360 }
361
362 if g, w := enabledVariants(ctx, "baz"), tt.bazVariants; !reflect.DeepEqual(w, g) {
363 t.Errorf("want baz variants:\n%q\ngot:\n%q\n", w, g)
364 }
365
366 if g, w := enabledVariants(ctx, "qux"), tt.quxVariants; !reflect.DeepEqual(w, g) {
367 t.Errorf("want qux variants:\n%q\ngot:\n%q\n", w, g)
368 }
369 })
370 }
371}