blob: aa8ad694586665b06dcf4273abe00d4df2f9facf [file] [log] [blame]
Colin Cross41955e82019-05-29 14:40:35 -07001// 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
15package android
16
Jooyung Hand48f3c32019-08-23 11:18:57 +090017import (
Colin Cross6ac95762021-11-09 13:17:44 -080018 "path/filepath"
19 "runtime"
Jooyung Hand48f3c32019-08-23 11:18:57 +090020 "testing"
21)
Colin Cross41955e82019-05-29 14:40:35 -070022
23func TestSrcIsModule(t *testing.T) {
24 type args struct {
25 s string
26 }
27 tests := []struct {
28 name string
29 args args
30 wantModule string
31 }{
32 {
33 name: "file",
34 args: args{
35 s: "foo",
36 },
37 wantModule: "",
38 },
39 {
40 name: "module",
41 args: args{
42 s: ":foo",
43 },
44 wantModule: "foo",
45 },
46 {
47 name: "tag",
48 args: args{
49 s: ":foo{.bar}",
50 },
51 wantModule: "foo{.bar}",
52 },
53 {
54 name: "extra colon",
55 args: args{
56 s: ":foo:bar",
57 },
58 wantModule: "foo:bar",
59 },
Paul Duffine6ba0722021-07-12 20:12:12 +010060 {
61 name: "fully qualified",
62 args: args{
63 s: "//foo:bar",
64 },
65 wantModule: "//foo:bar",
66 },
67 {
68 name: "fully qualified with tag",
69 args: args{
70 s: "//foo:bar{.tag}",
71 },
72 wantModule: "//foo:bar{.tag}",
73 },
74 {
75 name: "invalid unqualified name",
76 args: args{
77 s: ":foo/bar",
78 },
79 wantModule: "",
80 },
Colin Cross41955e82019-05-29 14:40:35 -070081 }
82 for _, tt := range tests {
83 t.Run(tt.name, func(t *testing.T) {
84 if gotModule := SrcIsModule(tt.args.s); gotModule != tt.wantModule {
85 t.Errorf("SrcIsModule() = %v, want %v", gotModule, tt.wantModule)
86 }
87 })
88 }
89}
90
91func TestSrcIsModuleWithTag(t *testing.T) {
92 type args struct {
93 s string
94 }
95 tests := []struct {
96 name string
97 args args
98 wantModule string
99 wantTag string
100 }{
101 {
102 name: "file",
103 args: args{
104 s: "foo",
105 },
106 wantModule: "",
107 wantTag: "",
108 },
109 {
110 name: "module",
111 args: args{
112 s: ":foo",
113 },
114 wantModule: "foo",
115 wantTag: "",
116 },
117 {
118 name: "tag",
119 args: args{
120 s: ":foo{.bar}",
121 },
122 wantModule: "foo",
123 wantTag: ".bar",
124 },
125 {
126 name: "empty tag",
127 args: args{
128 s: ":foo{}",
129 },
130 wantModule: "foo",
131 wantTag: "",
132 },
133 {
134 name: "extra colon",
135 args: args{
136 s: ":foo:bar",
137 },
138 wantModule: "foo:bar",
139 },
140 {
141 name: "invalid tag",
142 args: args{
143 s: ":foo{.bar",
144 },
145 wantModule: "foo{.bar",
146 },
147 {
148 name: "invalid tag 2",
149 args: args{
150 s: ":foo.bar}",
151 },
152 wantModule: "foo.bar}",
153 },
Paul Duffine6ba0722021-07-12 20:12:12 +0100154 {
155 name: "fully qualified",
156 args: args{
157 s: "//foo:bar",
158 },
159 wantModule: "//foo:bar",
160 },
161 {
162 name: "fully qualified with tag",
163 args: args{
164 s: "//foo:bar{.tag}",
165 },
166 wantModule: "//foo:bar",
167 wantTag: ".tag",
168 },
169 {
170 name: "invalid unqualified name",
171 args: args{
172 s: ":foo/bar",
173 },
174 wantModule: "",
175 },
176 {
177 name: "invalid unqualified name with tag",
178 args: args{
179 s: ":foo/bar{.tag}",
180 },
181 wantModule: "",
182 },
Colin Cross41955e82019-05-29 14:40:35 -0700183 }
184 for _, tt := range tests {
185 t.Run(tt.name, func(t *testing.T) {
186 gotModule, gotTag := SrcIsModuleWithTag(tt.args.s)
187 if gotModule != tt.wantModule {
188 t.Errorf("SrcIsModuleWithTag() gotModule = %v, want %v", gotModule, tt.wantModule)
189 }
190 if gotTag != tt.wantTag {
191 t.Errorf("SrcIsModuleWithTag() gotTag = %v, want %v", gotTag, tt.wantTag)
192 }
193 })
194 }
195}
Jooyung Hand48f3c32019-08-23 11:18:57 +0900196
197type depsModule struct {
198 ModuleBase
199 props struct {
200 Deps []string
201 }
202}
203
204func (m *depsModule) GenerateAndroidBuildActions(ctx ModuleContext) {
Colin Cross6ac95762021-11-09 13:17:44 -0800205 outputFile := PathForModuleOut(ctx, ctx.ModuleName())
206 ctx.Build(pctx, BuildParams{
207 Rule: Touch,
208 Output: outputFile,
209 })
210 installFile := ctx.InstallFile(PathForModuleInstall(ctx), ctx.ModuleName(), outputFile)
211 ctx.InstallSymlink(PathForModuleInstall(ctx, "symlinks"), ctx.ModuleName(), installFile)
Jooyung Hand48f3c32019-08-23 11:18:57 +0900212}
213
214func (m *depsModule) DepsMutator(ctx BottomUpMutatorContext) {
Colin Cross6ac95762021-11-09 13:17:44 -0800215 ctx.AddDependency(ctx.Module(), installDepTag{}, m.props.Deps...)
Jooyung Hand48f3c32019-08-23 11:18:57 +0900216}
217
218func depsModuleFactory() Module {
219 m := &depsModule{}
220 m.AddProperties(&m.props)
Colin Cross6ac95762021-11-09 13:17:44 -0800221 InitAndroidArchModule(m, HostAndDeviceDefault, MultilibCommon)
Jooyung Hand48f3c32019-08-23 11:18:57 +0900222 return m
223}
224
Paul Duffinf62dc9b2021-03-16 19:44:51 +0000225var prepareForModuleTests = FixtureRegisterWithContext(func(ctx RegistrationContext) {
226 ctx.RegisterModuleType("deps", depsModuleFactory)
227})
228
Jooyung Hand48f3c32019-08-23 11:18:57 +0900229func TestErrorDependsOnDisabledModule(t *testing.T) {
Jooyung Hand48f3c32019-08-23 11:18:57 +0900230 bp := `
231 deps {
232 name: "foo",
233 deps: ["bar"],
234 }
235 deps {
236 name: "bar",
237 enabled: false,
238 }
239 `
240
Paul Duffin30ac3e72021-03-20 00:36:14 +0000241 prepareForModuleTests.
Paul Duffinf62dc9b2021-03-16 19:44:51 +0000242 ExtendWithErrorHandler(FixtureExpectsAtLeastOneErrorMatchingPattern(`module "foo": depends on disabled module "bar"`)).
Paul Duffin30ac3e72021-03-20 00:36:14 +0000243 RunTestWithBp(t, bp)
Jooyung Hand48f3c32019-08-23 11:18:57 +0900244}
Jingwen Chence679d22020-09-23 04:30:02 +0000245
246func TestValidateCorrectBuildParams(t *testing.T) {
Paul Duffinf62dc9b2021-03-16 19:44:51 +0000247 config := TestConfig(t.TempDir(), nil, "", nil)
Jingwen Chence679d22020-09-23 04:30:02 +0000248 pathContext := PathContextForTesting(config)
249 bparams := convertBuildParams(BuildParams{
250 // Test with Output
251 Output: PathForOutput(pathContext, "undeclared_symlink"),
252 SymlinkOutput: PathForOutput(pathContext, "undeclared_symlink"),
253 })
254
255 err := validateBuildParams(bparams)
256 if err != nil {
257 t.Error(err)
258 }
259
260 bparams = convertBuildParams(BuildParams{
261 // Test with ImplicitOutput
262 ImplicitOutput: PathForOutput(pathContext, "undeclared_symlink"),
263 SymlinkOutput: PathForOutput(pathContext, "undeclared_symlink"),
264 })
265
266 err = validateBuildParams(bparams)
267 if err != nil {
268 t.Error(err)
269 }
270}
271
272func TestValidateIncorrectBuildParams(t *testing.T) {
Paul Duffinf62dc9b2021-03-16 19:44:51 +0000273 config := TestConfig(t.TempDir(), nil, "", nil)
Jingwen Chence679d22020-09-23 04:30:02 +0000274 pathContext := PathContextForTesting(config)
275 params := BuildParams{
276 Output: PathForOutput(pathContext, "regular_output"),
277 Outputs: PathsForOutput(pathContext, []string{"out1", "out2"}),
278 ImplicitOutput: PathForOutput(pathContext, "implicit_output"),
279 ImplicitOutputs: PathsForOutput(pathContext, []string{"i_out1", "_out2"}),
280 SymlinkOutput: PathForOutput(pathContext, "undeclared_symlink"),
281 }
282
283 bparams := convertBuildParams(params)
284 err := validateBuildParams(bparams)
285 if err != nil {
286 FailIfNoMatchingErrors(t, "undeclared_symlink is not a declared output or implicit output", []error{err})
287 } else {
288 t.Errorf("Expected build params to fail validation: %+v", bparams)
289 }
290}
Paul Duffin89968e32020-11-23 18:17:03 +0000291
292func TestDistErrorChecking(t *testing.T) {
293 bp := `
294 deps {
295 name: "foo",
296 dist: {
297 dest: "../invalid-dest",
298 dir: "../invalid-dir",
299 suffix: "invalid/suffix",
300 },
301 dists: [
302 {
303 dest: "../invalid-dest0",
304 dir: "../invalid-dir0",
305 suffix: "invalid/suffix0",
306 },
307 {
308 dest: "../invalid-dest1",
309 dir: "../invalid-dir1",
310 suffix: "invalid/suffix1",
311 },
312 ],
313 }
314 `
315
Paul Duffin89968e32020-11-23 18:17:03 +0000316 expectedErrs := []string{
317 "\\QAndroid.bp:5:13: module \"foo\": dist.dest: Path is outside directory: ../invalid-dest\\E",
318 "\\QAndroid.bp:6:12: module \"foo\": dist.dir: Path is outside directory: ../invalid-dir\\E",
319 "\\QAndroid.bp:7:15: module \"foo\": dist.suffix: Suffix may not contain a '/' character.\\E",
320 "\\QAndroid.bp:11:15: module \"foo\": dists[0].dest: Path is outside directory: ../invalid-dest0\\E",
321 "\\QAndroid.bp:12:14: module \"foo\": dists[0].dir: Path is outside directory: ../invalid-dir0\\E",
322 "\\QAndroid.bp:13:17: module \"foo\": dists[0].suffix: Suffix may not contain a '/' character.\\E",
323 "\\QAndroid.bp:16:15: module \"foo\": dists[1].dest: Path is outside directory: ../invalid-dest1\\E",
324 "\\QAndroid.bp:17:14: module \"foo\": dists[1].dir: Path is outside directory: ../invalid-dir1\\E",
325 "\\QAndroid.bp:18:17: module \"foo\": dists[1].suffix: Suffix may not contain a '/' character.\\E",
326 }
Paul Duffinf62dc9b2021-03-16 19:44:51 +0000327
Paul Duffin30ac3e72021-03-20 00:36:14 +0000328 prepareForModuleTests.
Paul Duffinf62dc9b2021-03-16 19:44:51 +0000329 ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(expectedErrs)).
Paul Duffin30ac3e72021-03-20 00:36:14 +0000330 RunTestWithBp(t, bp)
Paul Duffin89968e32020-11-23 18:17:03 +0000331}
Colin Cross6ac95762021-11-09 13:17:44 -0800332
333func TestInstall(t *testing.T) {
334 if runtime.GOOS != "linux" {
335 t.Skip("requires linux")
336 }
337 bp := `
338 deps {
339 name: "foo",
340 deps: ["bar"],
341 }
342
343 deps {
344 name: "bar",
345 deps: ["baz", "qux"],
346 }
347
348 deps {
349 name: "baz",
350 deps: ["qux"],
351 }
352
353 deps {
354 name: "qux",
355 }
356 `
357
358 result := GroupFixturePreparers(
359 prepareForModuleTests,
360 PrepareForTestWithArchMutator,
361 ).RunTestWithBp(t, bp)
362
363 module := func(name string, host bool) TestingModule {
364 variant := "android_common"
365 if host {
366 variant = result.Config.BuildOSCommonTarget.String()
367 }
368 return result.ModuleForTests(name, variant)
369 }
370
371 outputRule := func(name string) TestingBuildParams { return module(name, false).Output(name) }
372
373 installRule := func(name string) TestingBuildParams {
374 return module(name, false).Output(filepath.Join("out/soong/target/product/test_device/system", name))
375 }
376
377 symlinkRule := func(name string) TestingBuildParams {
378 return module(name, false).Output(filepath.Join("out/soong/target/product/test_device/system/symlinks", name))
379 }
380
381 hostOutputRule := func(name string) TestingBuildParams { return module(name, true).Output(name) }
382
383 hostInstallRule := func(name string) TestingBuildParams {
384 return module(name, true).Output(filepath.Join("out/soong/host/linux-x86", name))
385 }
386
387 hostSymlinkRule := func(name string) TestingBuildParams {
388 return module(name, true).Output(filepath.Join("out/soong/host/linux-x86/symlinks", name))
389 }
390
391 assertInputs := func(params TestingBuildParams, inputs ...Path) {
392 t.Helper()
393 AssertArrayString(t, "expected inputs", Paths(inputs).Strings(),
394 append(PathsIfNonNil(params.Input), params.Inputs...).Strings())
395 }
396
397 assertImplicits := func(params TestingBuildParams, implicits ...Path) {
398 t.Helper()
399 AssertArrayString(t, "expected implicit dependencies", Paths(implicits).Strings(),
400 append(PathsIfNonNil(params.Implicit), params.Implicits...).Strings())
401 }
402
403 assertOrderOnlys := func(params TestingBuildParams, orderonlys ...Path) {
404 t.Helper()
405 AssertArrayString(t, "expected orderonly dependencies", Paths(orderonlys).Strings(),
406 params.OrderOnly.Strings())
407 }
408
409 // Check host install rule dependencies
410 assertInputs(hostInstallRule("foo"), hostOutputRule("foo").Output)
411 assertImplicits(hostInstallRule("foo"),
412 hostInstallRule("bar").Output,
413 hostSymlinkRule("bar").Output,
414 hostInstallRule("baz").Output,
415 hostSymlinkRule("baz").Output,
416 hostInstallRule("qux").Output,
417 hostSymlinkRule("qux").Output,
418 )
419 assertOrderOnlys(hostInstallRule("foo"))
420
Colin Cross64002af2021-11-09 16:37:52 -0800421 // Check host symlink rule dependencies. Host symlinks must use a normal dependency, not an
422 // order-only dependency, so that the tool gets updated when the symlink is depended on.
Colin Cross6ac95762021-11-09 13:17:44 -0800423 assertInputs(hostSymlinkRule("foo"), hostInstallRule("foo").Output)
424 assertImplicits(hostSymlinkRule("foo"))
425 assertOrderOnlys(hostSymlinkRule("foo"))
426
427 // Check device install rule dependencies
428 assertInputs(installRule("foo"), outputRule("foo").Output)
429 assertImplicits(installRule("foo"))
430 assertOrderOnlys(installRule("foo"),
431 installRule("bar").Output,
432 symlinkRule("bar").Output,
433 installRule("baz").Output,
434 symlinkRule("baz").Output,
435 installRule("qux").Output,
436 symlinkRule("qux").Output,
437 )
438
Colin Cross64002af2021-11-09 16:37:52 -0800439 // Check device symlink rule dependencies. Device symlinks could use an order-only dependency,
440 // but the current implementation uses a normal dependency.
Colin Cross6ac95762021-11-09 13:17:44 -0800441 assertInputs(symlinkRule("foo"), installRule("foo").Output)
442 assertImplicits(symlinkRule("foo"))
443 assertOrderOnlys(symlinkRule("foo"))
444}
445
Colin Crossc68db4b2021-11-11 18:59:15 -0800446func TestInstallKatiEnabled(t *testing.T) {
Colin Cross6ac95762021-11-09 13:17:44 -0800447 if runtime.GOOS != "linux" {
448 t.Skip("requires linux")
449 }
450 bp := `
451 deps {
452 name: "foo",
453 deps: ["bar"],
454 }
455
456 deps {
457 name: "bar",
458 deps: ["baz", "qux"],
459 }
460
461 deps {
462 name: "baz",
463 deps: ["qux"],
464 }
465
466 deps {
467 name: "qux",
468 }
469 `
470
471 result := GroupFixturePreparers(
472 prepareForModuleTests,
473 PrepareForTestWithArchMutator,
474 FixtureModifyConfig(SetKatiEnabledForTests),
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000475 PrepareForTestWithMakevars,
Colin Cross6ac95762021-11-09 13:17:44 -0800476 ).RunTestWithBp(t, bp)
477
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000478 rules := result.InstallMakeRulesForTesting(t)
Colin Cross6ac95762021-11-09 13:17:44 -0800479
480 module := func(name string, host bool) TestingModule {
481 variant := "android_common"
482 if host {
483 variant = result.Config.BuildOSCommonTarget.String()
484 }
485 return result.ModuleForTests(name, variant)
486 }
487
488 outputRule := func(name string) TestingBuildParams { return module(name, false).Output(name) }
489
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000490 ruleForOutput := func(output string) InstallMakeRule {
Colin Cross6ac95762021-11-09 13:17:44 -0800491 for _, rule := range rules {
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000492 if rule.Target == output {
Colin Cross6ac95762021-11-09 13:17:44 -0800493 return rule
494 }
495 }
496 t.Fatalf("no make install rule for %s", output)
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000497 return InstallMakeRule{}
Colin Cross6ac95762021-11-09 13:17:44 -0800498 }
499
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000500 installRule := func(name string) InstallMakeRule {
Colin Cross6ac95762021-11-09 13:17:44 -0800501 return ruleForOutput(filepath.Join("out/target/product/test_device/system", name))
502 }
503
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000504 symlinkRule := func(name string) InstallMakeRule {
Colin Cross6ac95762021-11-09 13:17:44 -0800505 return ruleForOutput(filepath.Join("out/target/product/test_device/system/symlinks", name))
506 }
507
508 hostOutputRule := func(name string) TestingBuildParams { return module(name, true).Output(name) }
509
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000510 hostInstallRule := func(name string) InstallMakeRule {
Colin Cross6ac95762021-11-09 13:17:44 -0800511 return ruleForOutput(filepath.Join("out/host/linux-x86", name))
512 }
513
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000514 hostSymlinkRule := func(name string) InstallMakeRule {
Colin Cross6ac95762021-11-09 13:17:44 -0800515 return ruleForOutput(filepath.Join("out/host/linux-x86/symlinks", name))
516 }
517
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000518 assertDeps := func(rule InstallMakeRule, deps ...string) {
Colin Cross6ac95762021-11-09 13:17:44 -0800519 t.Helper()
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000520 AssertArrayString(t, "expected inputs", deps, rule.Deps)
Colin Cross6ac95762021-11-09 13:17:44 -0800521 }
522
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000523 assertOrderOnlys := func(rule InstallMakeRule, orderonlys ...string) {
Colin Cross6ac95762021-11-09 13:17:44 -0800524 t.Helper()
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000525 AssertArrayString(t, "expected orderonly dependencies", orderonlys, rule.OrderOnlyDeps)
Colin Cross6ac95762021-11-09 13:17:44 -0800526 }
527
528 // Check host install rule dependencies
529 assertDeps(hostInstallRule("foo"),
530 hostOutputRule("foo").Output.String(),
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000531 hostInstallRule("bar").Target,
532 hostSymlinkRule("bar").Target,
533 hostInstallRule("baz").Target,
534 hostSymlinkRule("baz").Target,
535 hostInstallRule("qux").Target,
536 hostSymlinkRule("qux").Target,
Colin Cross6ac95762021-11-09 13:17:44 -0800537 )
538 assertOrderOnlys(hostInstallRule("foo"))
539
Colin Cross64002af2021-11-09 16:37:52 -0800540 // Check host symlink rule dependencies. Host symlinks must use a normal dependency, not an
541 // order-only dependency, so that the tool gets updated when the symlink is depended on.
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000542 assertDeps(hostSymlinkRule("foo"), hostInstallRule("foo").Target)
Colin Cross64002af2021-11-09 16:37:52 -0800543 assertOrderOnlys(hostSymlinkRule("foo"))
Colin Cross6ac95762021-11-09 13:17:44 -0800544
545 // Check device install rule dependencies
546 assertDeps(installRule("foo"), outputRule("foo").Output.String())
547 assertOrderOnlys(installRule("foo"),
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000548 installRule("bar").Target,
549 symlinkRule("bar").Target,
550 installRule("baz").Target,
551 symlinkRule("baz").Target,
552 installRule("qux").Target,
553 symlinkRule("qux").Target,
Colin Cross6ac95762021-11-09 13:17:44 -0800554 )
555
Colin Cross64002af2021-11-09 16:37:52 -0800556 // Check device symlink rule dependencies. Device symlinks could use an order-only dependency,
557 // but the current implementation uses a normal dependency.
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000558 assertDeps(symlinkRule("foo"), installRule("foo").Target)
Colin Cross64002af2021-11-09 16:37:52 -0800559 assertOrderOnlys(symlinkRule("foo"))
Colin Cross6ac95762021-11-09 13:17:44 -0800560}
561
Liz Kammer9525e712022-01-05 13:46:24 -0500562type PropsTestModuleEmbedded struct {
563 Embedded_prop *string
564}
565
566type propsTestModule struct {
567 ModuleBase
568 DefaultableModuleBase
569 props struct {
570 A string `android:"arch_variant"`
571 B *bool
572 C []string
573 }
574 otherProps struct {
575 PropsTestModuleEmbedded
576
577 D *int64
578 Nested struct {
579 E *string
580 }
581 F *string `blueprint:"mutated"`
582 }
583}
584
585func propsTestModuleFactory() Module {
586 module := &propsTestModule{}
587 module.AddProperties(&module.props, &module.otherProps)
588 InitAndroidArchModule(module, HostAndDeviceSupported, MultilibBoth)
589 InitDefaultableModule(module)
590 return module
591}
592
593type propsTestModuleDefaults struct {
594 ModuleBase
595 DefaultsModuleBase
596}
597
598func propsTestModuleDefaultsFactory() Module {
599 defaults := &propsTestModuleDefaults{}
600 module := propsTestModule{}
601 defaults.AddProperties(&module.props, &module.otherProps)
602 InitDefaultsModule(defaults)
603 return defaults
604}
605
606func (p *propsTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
607 str := "abc"
608 p.otherProps.F = &str
609}
610
611func TestUsedProperties(t *testing.T) {
612 testCases := []struct {
613 desc string
614 bp string
615 expectedProps []propInfo
616 }{
617 {
618 desc: "only name",
619 bp: `test {
620 name: "foo",
621 }
622 `,
623 expectedProps: []propInfo{
624 propInfo{"Name", "string"},
625 },
626 },
627 {
628 desc: "some props",
629 bp: `test {
630 name: "foo",
631 a: "abc",
632 b: true,
633 d: 123,
634 }
635 `,
636 expectedProps: []propInfo{
637 propInfo{"A", "string"},
638 propInfo{"B", "bool"},
639 propInfo{"D", "int64"},
640 propInfo{"Name", "string"},
641 },
642 },
643 {
644 desc: "unused non-pointer prop",
645 bp: `test {
646 name: "foo",
647 b: true,
648 d: 123,
649 }
650 `,
651 expectedProps: []propInfo{
652 // for non-pointer cannot distinguish between unused and intentionally set to empty
653 propInfo{"A", "string"},
654 propInfo{"B", "bool"},
655 propInfo{"D", "int64"},
656 propInfo{"Name", "string"},
657 },
658 },
659 {
660 desc: "nested props",
661 bp: `test {
662 name: "foo",
663 nested: {
664 e: "abc",
665 }
666 }
667 `,
668 expectedProps: []propInfo{
669 propInfo{"Nested.E", "string"},
670 propInfo{"Name", "string"},
671 },
672 },
673 {
674 desc: "arch props",
675 bp: `test {
676 name: "foo",
677 arch: {
678 x86_64: {
679 a: "abc",
680 },
681 }
682 }
683 `,
684 expectedProps: []propInfo{
685 propInfo{"Name", "string"},
686 propInfo{"Arch.X86_64.A", "string"},
687 },
688 },
689 {
690 desc: "embedded props",
691 bp: `test {
692 name: "foo",
693 embedded_prop: "a",
694 }
695 `,
696 expectedProps: []propInfo{
697 propInfo{"Embedded_prop", "string"},
698 propInfo{"Name", "string"},
699 },
700 },
701 {
702 desc: "defaults",
703 bp: `
704test_defaults {
705 name: "foo_defaults",
706 a: "a",
707 b: true,
708 embedded_prop:"a",
709 arch: {
710 x86_64: {
711 a: "a",
712 },
713 },
714}
715test {
716 name: "foo",
717 defaults: ["foo_defaults"],
718 c: ["a"],
719 nested: {
720 e: "d",
721 },
722 target: {
723 linux: {
724 a: "a",
725 },
726 },
727}
728 `,
729 expectedProps: []propInfo{
730 propInfo{"A", "string"},
731 propInfo{"B", "bool"},
732 propInfo{"C", "string slice"},
733 propInfo{"Embedded_prop", "string"},
734 propInfo{"Nested.E", "string"},
735 propInfo{"Name", "string"},
736 propInfo{"Arch.X86_64.A", "string"},
737 propInfo{"Target.Linux.A", "string"},
738 propInfo{"Defaults", "string slice"},
739 },
740 },
741 }
742
743 for _, tc := range testCases {
744 t.Run(tc.desc, func(t *testing.T) {
745 result := GroupFixturePreparers(
746 PrepareForTestWithAllowMissingDependencies,
747 PrepareForTestWithDefaults,
748 FixtureRegisterWithContext(func(ctx RegistrationContext) {
749 ctx.RegisterModuleType("test", propsTestModuleFactory)
750 ctx.RegisterModuleType("test_defaults", propsTestModuleDefaultsFactory)
751 }),
752 FixtureWithRootAndroidBp(tc.bp),
753 ).RunTest(t)
754
755 foo := result.ModuleForTests("foo", "").Module().base()
756
757 AssertDeepEquals(t, "foo ", tc.expectedProps, foo.propertiesWithValues())
758
759 })
760 }
761}