blob: 77ef146733c475f9471db9707c7830c504201dcd [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
Liz Kammer898e0762022-03-22 11:27:26 -0400566type StructInSlice struct {
567 G string
568 H bool
569 I []string
570}
571
Liz Kammer9525e712022-01-05 13:46:24 -0500572type propsTestModule struct {
573 ModuleBase
574 DefaultableModuleBase
575 props struct {
576 A string `android:"arch_variant"`
577 B *bool
578 C []string
579 }
580 otherProps struct {
581 PropsTestModuleEmbedded
582
583 D *int64
584 Nested struct {
585 E *string
586 }
587 F *string `blueprint:"mutated"`
Liz Kammer898e0762022-03-22 11:27:26 -0400588
589 Slice_of_struct []StructInSlice
Liz Kammer9525e712022-01-05 13:46:24 -0500590 }
591}
592
593func propsTestModuleFactory() Module {
594 module := &propsTestModule{}
595 module.AddProperties(&module.props, &module.otherProps)
596 InitAndroidArchModule(module, HostAndDeviceSupported, MultilibBoth)
597 InitDefaultableModule(module)
598 return module
599}
600
601type propsTestModuleDefaults struct {
602 ModuleBase
603 DefaultsModuleBase
604}
605
606func propsTestModuleDefaultsFactory() Module {
607 defaults := &propsTestModuleDefaults{}
608 module := propsTestModule{}
609 defaults.AddProperties(&module.props, &module.otherProps)
610 InitDefaultsModule(defaults)
611 return defaults
612}
613
614func (p *propsTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
615 str := "abc"
616 p.otherProps.F = &str
617}
618
619func TestUsedProperties(t *testing.T) {
620 testCases := []struct {
621 desc string
622 bp string
623 expectedProps []propInfo
624 }{
625 {
626 desc: "only name",
627 bp: `test {
628 name: "foo",
629 }
630 `,
631 expectedProps: []propInfo{
Liz Kammer898e0762022-03-22 11:27:26 -0400632 propInfo{Name: "Name", Type: "string", Value: "foo"},
Liz Kammer9525e712022-01-05 13:46:24 -0500633 },
634 },
635 {
636 desc: "some props",
637 bp: `test {
638 name: "foo",
639 a: "abc",
640 b: true,
641 d: 123,
642 }
643 `,
644 expectedProps: []propInfo{
Liz Kammer898e0762022-03-22 11:27:26 -0400645 propInfo{Name: "A", Type: "string", Value: "abc"},
646 propInfo{Name: "B", Type: "bool", Value: "true"},
647 propInfo{Name: "D", Type: "int64", Value: "123"},
648 propInfo{Name: "Name", Type: "string", Value: "foo"},
Liz Kammer9525e712022-01-05 13:46:24 -0500649 },
650 },
651 {
652 desc: "unused non-pointer prop",
653 bp: `test {
654 name: "foo",
655 b: true,
656 d: 123,
657 }
658 `,
659 expectedProps: []propInfo{
660 // for non-pointer cannot distinguish between unused and intentionally set to empty
Liz Kammer898e0762022-03-22 11:27:26 -0400661 propInfo{Name: "A", Type: "string", Value: ""},
662 propInfo{Name: "B", Type: "bool", Value: "true"},
663 propInfo{Name: "D", Type: "int64", Value: "123"},
664 propInfo{Name: "Name", Type: "string", Value: "foo"},
Liz Kammer9525e712022-01-05 13:46:24 -0500665 },
666 },
667 {
668 desc: "nested props",
669 bp: `test {
670 name: "foo",
671 nested: {
672 e: "abc",
673 }
674 }
675 `,
676 expectedProps: []propInfo{
Liz Kammer898e0762022-03-22 11:27:26 -0400677 propInfo{Name: "Name", Type: "string", Value: "foo"},
678 propInfo{Name: "Nested.E", Type: "string", Value: "abc"},
Liz Kammer9525e712022-01-05 13:46:24 -0500679 },
680 },
681 {
682 desc: "arch props",
683 bp: `test {
684 name: "foo",
685 arch: {
686 x86_64: {
687 a: "abc",
688 },
689 }
690 }
691 `,
692 expectedProps: []propInfo{
Liz Kammer898e0762022-03-22 11:27:26 -0400693 propInfo{Name: "Arch.X86_64.A", Type: "string", Value: "abc"},
694 propInfo{Name: "Name", Type: "string", Value: "foo"},
Liz Kammer9525e712022-01-05 13:46:24 -0500695 },
696 },
697 {
698 desc: "embedded props",
699 bp: `test {
700 name: "foo",
701 embedded_prop: "a",
702 }
703 `,
704 expectedProps: []propInfo{
Liz Kammer898e0762022-03-22 11:27:26 -0400705 propInfo{Name: "Embedded_prop", Type: "string", Value: "a"},
706 propInfo{Name: "Name", Type: "string", Value: "foo"},
707 },
708 },
709 {
710 desc: "struct slice",
711 bp: `test {
712 name: "foo",
713 slice_of_struct: [
714 {
715 g: "abc",
716 h: false,
717 i: ["baz"],
718 },
719 {
720 g: "def",
721 h: true,
722 i: [],
723 },
724 ]
725 }
726 `,
727 expectedProps: []propInfo{
728 propInfo{Name: "Name", Type: "string", Value: "foo"},
729 propInfo{Name: "Slice_of_struct", Type: "struct slice", Values: []string{
730 `android.StructInSlice{G: abc, H: false, I: [baz]}`,
731 `android.StructInSlice{G: def, H: true, I: []}`,
732 }},
Liz Kammer9525e712022-01-05 13:46:24 -0500733 },
734 },
735 {
736 desc: "defaults",
737 bp: `
738test_defaults {
739 name: "foo_defaults",
740 a: "a",
741 b: true,
Liz Kammer898e0762022-03-22 11:27:26 -0400742 c: ["default_c"],
Liz Kammer9525e712022-01-05 13:46:24 -0500743 embedded_prop:"a",
744 arch: {
745 x86_64: {
Liz Kammer898e0762022-03-22 11:27:26 -0400746 a: "x86_64 a",
Liz Kammer9525e712022-01-05 13:46:24 -0500747 },
748 },
749}
750test {
751 name: "foo",
752 defaults: ["foo_defaults"],
Liz Kammer898e0762022-03-22 11:27:26 -0400753 c: ["c"],
Liz Kammer9525e712022-01-05 13:46:24 -0500754 nested: {
Liz Kammer898e0762022-03-22 11:27:26 -0400755 e: "nested e",
Liz Kammer9525e712022-01-05 13:46:24 -0500756 },
757 target: {
758 linux: {
759 a: "a",
760 },
761 },
762}
763 `,
764 expectedProps: []propInfo{
Liz Kammer898e0762022-03-22 11:27:26 -0400765 propInfo{Name: "A", Type: "string", Value: "a"},
766 propInfo{Name: "Arch.X86_64.A", Type: "string", Value: "x86_64 a"},
767 propInfo{Name: "B", Type: "bool", Value: "true"},
768 propInfo{Name: "C", Type: "string slice", Values: []string{"default_c", "c"}},
769 propInfo{Name: "Defaults", Type: "string slice", Values: []string{"foo_defaults"}},
770 propInfo{Name: "Embedded_prop", Type: "string", Value: "a"},
771 propInfo{Name: "Name", Type: "string", Value: "foo"},
772 propInfo{Name: "Nested.E", Type: "string", Value: "nested e"},
773 propInfo{Name: "Target.Linux.A", Type: "string", Value: "a"},
Liz Kammer9525e712022-01-05 13:46:24 -0500774 },
775 },
776 }
777
778 for _, tc := range testCases {
779 t.Run(tc.desc, func(t *testing.T) {
780 result := GroupFixturePreparers(
781 PrepareForTestWithAllowMissingDependencies,
782 PrepareForTestWithDefaults,
783 FixtureRegisterWithContext(func(ctx RegistrationContext) {
784 ctx.RegisterModuleType("test", propsTestModuleFactory)
785 ctx.RegisterModuleType("test_defaults", propsTestModuleDefaultsFactory)
786 }),
787 FixtureWithRootAndroidBp(tc.bp),
788 ).RunTest(t)
789
790 foo := result.ModuleForTests("foo", "").Module().base()
791
792 AssertDeepEquals(t, "foo ", tc.expectedProps, foo.propertiesWithValues())
793
794 })
795 }
796}
Bob Badour4101c712022-02-09 11:54:35 -0800797
798func TestSortedUniqueNamedPaths(t *testing.T) {
799 type np struct {
800 path, name string
801 }
802 makePaths := func(l []np) NamedPaths {
803 result := make(NamedPaths, 0, len(l))
804 for _, p := range l {
805 result = append(result, NamedPath{PathForTesting(p.path), p.name})
806 }
807 return result
808 }
809
810 tests := []struct {
811 name string
812 in []np
813 expectedOut []np
814 }{
815 {
816 name: "empty",
817 in: []np{},
818 expectedOut: []np{},
819 },
820 {
821 name: "all_same",
822 in: []np{
823 {"a.txt", "A"},
824 {"a.txt", "A"},
825 {"a.txt", "A"},
826 {"a.txt", "A"},
827 {"a.txt", "A"},
828 },
829 expectedOut: []np{
830 {"a.txt", "A"},
831 },
832 },
833 {
834 name: "same_path_different_names",
835 in: []np{
836 {"a.txt", "C"},
837 {"a.txt", "A"},
838 {"a.txt", "D"},
839 {"a.txt", "B"},
840 {"a.txt", "E"},
841 },
842 expectedOut: []np{
843 {"a.txt", "A"},
844 {"a.txt", "B"},
845 {"a.txt", "C"},
846 {"a.txt", "D"},
847 {"a.txt", "E"},
848 },
849 },
850 {
851 name: "different_paths_same_name",
852 in: []np{
853 {"b/b.txt", "A"},
854 {"a/a.txt", "A"},
855 {"a/txt", "A"},
856 {"b", "A"},
857 {"a/b/d", "A"},
858 },
859 expectedOut: []np{
860 {"a/a.txt", "A"},
861 {"a/b/d", "A"},
862 {"a/txt", "A"},
863 {"b/b.txt", "A"},
864 {"b", "A"},
865 },
866 },
867 {
868 name: "all_different",
869 in: []np{
870 {"b/b.txt", "A"},
871 {"a/a.txt", "B"},
872 {"a/txt", "D"},
873 {"b", "C"},
874 {"a/b/d", "E"},
875 },
876 expectedOut: []np{
877 {"a/a.txt", "B"},
878 {"a/b/d", "E"},
879 {"a/txt", "D"},
880 {"b/b.txt", "A"},
881 {"b", "C"},
882 },
883 },
884 {
885 name: "some_different",
886 in: []np{
887 {"b/b.txt", "A"},
888 {"a/a.txt", "B"},
889 {"a/txt", "D"},
890 {"a/b/d", "E"},
891 {"b", "C"},
892 {"a/a.txt", "B"},
893 {"a/b/d", "E"},
894 },
895 expectedOut: []np{
896 {"a/a.txt", "B"},
897 {"a/b/d", "E"},
898 {"a/txt", "D"},
899 {"b/b.txt", "A"},
900 {"b", "C"},
901 },
902 },
903 }
904 for _, tt := range tests {
905 t.Run(tt.name, func(t *testing.T) {
906 actual := SortedUniqueNamedPaths(makePaths(tt.in))
907 expected := makePaths(tt.expectedOut)
908 t.Logf("actual: %v", actual)
909 t.Logf("expected: %v", expected)
910 AssertDeepEquals(t, "SortedUniqueNamedPaths ", expected, actual)
911 })
912 }
913}