blob: 6d8dae4c1ad2e172a783895fa7446d0579944e00 [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"
Cole Faust9a346f62024-01-18 20:12:02 +000021
22 "github.com/google/blueprint"
Jooyung Hand48f3c32019-08-23 11:18:57 +090023)
Colin Cross41955e82019-05-29 14:40:35 -070024
25func TestSrcIsModule(t *testing.T) {
26 type args struct {
27 s string
28 }
29 tests := []struct {
30 name string
31 args args
32 wantModule string
33 }{
34 {
35 name: "file",
36 args: args{
37 s: "foo",
38 },
39 wantModule: "",
40 },
41 {
42 name: "module",
43 args: args{
44 s: ":foo",
45 },
46 wantModule: "foo",
47 },
48 {
49 name: "tag",
50 args: args{
51 s: ":foo{.bar}",
52 },
53 wantModule: "foo{.bar}",
54 },
55 {
56 name: "extra colon",
57 args: args{
58 s: ":foo:bar",
59 },
60 wantModule: "foo:bar",
61 },
Paul Duffine6ba0722021-07-12 20:12:12 +010062 {
63 name: "fully qualified",
64 args: args{
65 s: "//foo:bar",
66 },
67 wantModule: "//foo:bar",
68 },
69 {
70 name: "fully qualified with tag",
71 args: args{
72 s: "//foo:bar{.tag}",
73 },
74 wantModule: "//foo:bar{.tag}",
75 },
76 {
77 name: "invalid unqualified name",
78 args: args{
79 s: ":foo/bar",
80 },
81 wantModule: "",
82 },
Colin Cross41955e82019-05-29 14:40:35 -070083 }
84 for _, tt := range tests {
85 t.Run(tt.name, func(t *testing.T) {
86 if gotModule := SrcIsModule(tt.args.s); gotModule != tt.wantModule {
87 t.Errorf("SrcIsModule() = %v, want %v", gotModule, tt.wantModule)
88 }
89 })
90 }
91}
92
93func TestSrcIsModuleWithTag(t *testing.T) {
94 type args struct {
95 s string
96 }
97 tests := []struct {
98 name string
99 args args
100 wantModule string
101 wantTag string
102 }{
103 {
104 name: "file",
105 args: args{
106 s: "foo",
107 },
108 wantModule: "",
109 wantTag: "",
110 },
111 {
112 name: "module",
113 args: args{
114 s: ":foo",
115 },
116 wantModule: "foo",
117 wantTag: "",
118 },
119 {
120 name: "tag",
121 args: args{
122 s: ":foo{.bar}",
123 },
124 wantModule: "foo",
125 wantTag: ".bar",
126 },
127 {
128 name: "empty tag",
129 args: args{
130 s: ":foo{}",
131 },
132 wantModule: "foo",
133 wantTag: "",
134 },
135 {
136 name: "extra colon",
137 args: args{
138 s: ":foo:bar",
139 },
140 wantModule: "foo:bar",
141 },
142 {
143 name: "invalid tag",
144 args: args{
145 s: ":foo{.bar",
146 },
147 wantModule: "foo{.bar",
148 },
149 {
150 name: "invalid tag 2",
151 args: args{
152 s: ":foo.bar}",
153 },
154 wantModule: "foo.bar}",
155 },
Paul Duffine6ba0722021-07-12 20:12:12 +0100156 {
157 name: "fully qualified",
158 args: args{
159 s: "//foo:bar",
160 },
161 wantModule: "//foo:bar",
162 },
163 {
164 name: "fully qualified with tag",
165 args: args{
166 s: "//foo:bar{.tag}",
167 },
168 wantModule: "//foo:bar",
169 wantTag: ".tag",
170 },
171 {
172 name: "invalid unqualified name",
173 args: args{
174 s: ":foo/bar",
175 },
176 wantModule: "",
177 },
178 {
179 name: "invalid unqualified name with tag",
180 args: args{
181 s: ":foo/bar{.tag}",
182 },
183 wantModule: "",
184 },
Colin Cross41955e82019-05-29 14:40:35 -0700185 }
186 for _, tt := range tests {
187 t.Run(tt.name, func(t *testing.T) {
188 gotModule, gotTag := SrcIsModuleWithTag(tt.args.s)
189 if gotModule != tt.wantModule {
190 t.Errorf("SrcIsModuleWithTag() gotModule = %v, want %v", gotModule, tt.wantModule)
191 }
192 if gotTag != tt.wantTag {
193 t.Errorf("SrcIsModuleWithTag() gotTag = %v, want %v", gotTag, tt.wantTag)
194 }
195 })
196 }
197}
Jooyung Hand48f3c32019-08-23 11:18:57 +0900198
199type depsModule struct {
200 ModuleBase
201 props struct {
202 Deps []string
203 }
204}
205
206func (m *depsModule) GenerateAndroidBuildActions(ctx ModuleContext) {
Colin Cross6ac95762021-11-09 13:17:44 -0800207 outputFile := PathForModuleOut(ctx, ctx.ModuleName())
208 ctx.Build(pctx, BuildParams{
209 Rule: Touch,
210 Output: outputFile,
211 })
212 installFile := ctx.InstallFile(PathForModuleInstall(ctx), ctx.ModuleName(), outputFile)
213 ctx.InstallSymlink(PathForModuleInstall(ctx, "symlinks"), ctx.ModuleName(), installFile)
Jooyung Hand48f3c32019-08-23 11:18:57 +0900214}
215
216func (m *depsModule) DepsMutator(ctx BottomUpMutatorContext) {
Colin Cross6ac95762021-11-09 13:17:44 -0800217 ctx.AddDependency(ctx.Module(), installDepTag{}, m.props.Deps...)
Jooyung Hand48f3c32019-08-23 11:18:57 +0900218}
219
220func depsModuleFactory() Module {
221 m := &depsModule{}
222 m.AddProperties(&m.props)
Colin Cross6ac95762021-11-09 13:17:44 -0800223 InitAndroidArchModule(m, HostAndDeviceDefault, MultilibCommon)
Jooyung Hand48f3c32019-08-23 11:18:57 +0900224 return m
225}
226
Paul Duffinf62dc9b2021-03-16 19:44:51 +0000227var prepareForModuleTests = FixtureRegisterWithContext(func(ctx RegistrationContext) {
228 ctx.RegisterModuleType("deps", depsModuleFactory)
229})
230
Jooyung Hand48f3c32019-08-23 11:18:57 +0900231func TestErrorDependsOnDisabledModule(t *testing.T) {
Jooyung Hand48f3c32019-08-23 11:18:57 +0900232 bp := `
233 deps {
234 name: "foo",
235 deps: ["bar"],
236 }
237 deps {
238 name: "bar",
239 enabled: false,
240 }
241 `
242
Paul Duffin30ac3e72021-03-20 00:36:14 +0000243 prepareForModuleTests.
Paul Duffinf62dc9b2021-03-16 19:44:51 +0000244 ExtendWithErrorHandler(FixtureExpectsAtLeastOneErrorMatchingPattern(`module "foo": depends on disabled module "bar"`)).
Paul Duffin30ac3e72021-03-20 00:36:14 +0000245 RunTestWithBp(t, bp)
Jooyung Hand48f3c32019-08-23 11:18:57 +0900246}
Jingwen Chence679d22020-09-23 04:30:02 +0000247
Paul Duffin89968e32020-11-23 18:17:03 +0000248func TestDistErrorChecking(t *testing.T) {
249 bp := `
250 deps {
251 name: "foo",
252 dist: {
253 dest: "../invalid-dest",
254 dir: "../invalid-dir",
255 suffix: "invalid/suffix",
256 },
257 dists: [
258 {
259 dest: "../invalid-dest0",
260 dir: "../invalid-dir0",
261 suffix: "invalid/suffix0",
262 },
263 {
264 dest: "../invalid-dest1",
265 dir: "../invalid-dir1",
266 suffix: "invalid/suffix1",
267 },
268 ],
269 }
270 `
271
Paul Duffin89968e32020-11-23 18:17:03 +0000272 expectedErrs := []string{
273 "\\QAndroid.bp:5:13: module \"foo\": dist.dest: Path is outside directory: ../invalid-dest\\E",
274 "\\QAndroid.bp:6:12: module \"foo\": dist.dir: Path is outside directory: ../invalid-dir\\E",
275 "\\QAndroid.bp:7:15: module \"foo\": dist.suffix: Suffix may not contain a '/' character.\\E",
276 "\\QAndroid.bp:11:15: module \"foo\": dists[0].dest: Path is outside directory: ../invalid-dest0\\E",
277 "\\QAndroid.bp:12:14: module \"foo\": dists[0].dir: Path is outside directory: ../invalid-dir0\\E",
278 "\\QAndroid.bp:13:17: module \"foo\": dists[0].suffix: Suffix may not contain a '/' character.\\E",
279 "\\QAndroid.bp:16:15: module \"foo\": dists[1].dest: Path is outside directory: ../invalid-dest1\\E",
280 "\\QAndroid.bp:17:14: module \"foo\": dists[1].dir: Path is outside directory: ../invalid-dir1\\E",
281 "\\QAndroid.bp:18:17: module \"foo\": dists[1].suffix: Suffix may not contain a '/' character.\\E",
282 }
Paul Duffinf62dc9b2021-03-16 19:44:51 +0000283
Paul Duffin30ac3e72021-03-20 00:36:14 +0000284 prepareForModuleTests.
Paul Duffinf62dc9b2021-03-16 19:44:51 +0000285 ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(expectedErrs)).
Paul Duffin30ac3e72021-03-20 00:36:14 +0000286 RunTestWithBp(t, bp)
Paul Duffin89968e32020-11-23 18:17:03 +0000287}
Colin Cross6ac95762021-11-09 13:17:44 -0800288
289func TestInstall(t *testing.T) {
290 if runtime.GOOS != "linux" {
291 t.Skip("requires linux")
292 }
293 bp := `
294 deps {
295 name: "foo",
296 deps: ["bar"],
297 }
298
299 deps {
300 name: "bar",
301 deps: ["baz", "qux"],
302 }
303
304 deps {
305 name: "baz",
306 deps: ["qux"],
307 }
308
309 deps {
310 name: "qux",
311 }
312 `
313
314 result := GroupFixturePreparers(
315 prepareForModuleTests,
316 PrepareForTestWithArchMutator,
317 ).RunTestWithBp(t, bp)
318
319 module := func(name string, host bool) TestingModule {
320 variant := "android_common"
321 if host {
322 variant = result.Config.BuildOSCommonTarget.String()
323 }
324 return result.ModuleForTests(name, variant)
325 }
326
327 outputRule := func(name string) TestingBuildParams { return module(name, false).Output(name) }
328
329 installRule := func(name string) TestingBuildParams {
330 return module(name, false).Output(filepath.Join("out/soong/target/product/test_device/system", name))
331 }
332
333 symlinkRule := func(name string) TestingBuildParams {
334 return module(name, false).Output(filepath.Join("out/soong/target/product/test_device/system/symlinks", name))
335 }
336
337 hostOutputRule := func(name string) TestingBuildParams { return module(name, true).Output(name) }
338
339 hostInstallRule := func(name string) TestingBuildParams {
340 return module(name, true).Output(filepath.Join("out/soong/host/linux-x86", name))
341 }
342
343 hostSymlinkRule := func(name string) TestingBuildParams {
344 return module(name, true).Output(filepath.Join("out/soong/host/linux-x86/symlinks", name))
345 }
346
347 assertInputs := func(params TestingBuildParams, inputs ...Path) {
348 t.Helper()
349 AssertArrayString(t, "expected inputs", Paths(inputs).Strings(),
350 append(PathsIfNonNil(params.Input), params.Inputs...).Strings())
351 }
352
353 assertImplicits := func(params TestingBuildParams, implicits ...Path) {
354 t.Helper()
355 AssertArrayString(t, "expected implicit dependencies", Paths(implicits).Strings(),
356 append(PathsIfNonNil(params.Implicit), params.Implicits...).Strings())
357 }
358
359 assertOrderOnlys := func(params TestingBuildParams, orderonlys ...Path) {
360 t.Helper()
361 AssertArrayString(t, "expected orderonly dependencies", Paths(orderonlys).Strings(),
362 params.OrderOnly.Strings())
363 }
364
365 // Check host install rule dependencies
366 assertInputs(hostInstallRule("foo"), hostOutputRule("foo").Output)
367 assertImplicits(hostInstallRule("foo"),
368 hostInstallRule("bar").Output,
369 hostSymlinkRule("bar").Output,
370 hostInstallRule("baz").Output,
371 hostSymlinkRule("baz").Output,
372 hostInstallRule("qux").Output,
373 hostSymlinkRule("qux").Output,
374 )
375 assertOrderOnlys(hostInstallRule("foo"))
376
Colin Cross64002af2021-11-09 16:37:52 -0800377 // Check host symlink rule dependencies. Host symlinks must use a normal dependency, not an
378 // order-only dependency, so that the tool gets updated when the symlink is depended on.
Colin Cross6ac95762021-11-09 13:17:44 -0800379 assertInputs(hostSymlinkRule("foo"), hostInstallRule("foo").Output)
380 assertImplicits(hostSymlinkRule("foo"))
381 assertOrderOnlys(hostSymlinkRule("foo"))
382
383 // Check device install rule dependencies
384 assertInputs(installRule("foo"), outputRule("foo").Output)
385 assertImplicits(installRule("foo"))
386 assertOrderOnlys(installRule("foo"),
387 installRule("bar").Output,
388 symlinkRule("bar").Output,
389 installRule("baz").Output,
390 symlinkRule("baz").Output,
391 installRule("qux").Output,
392 symlinkRule("qux").Output,
393 )
394
Colin Cross64002af2021-11-09 16:37:52 -0800395 // Check device symlink rule dependencies. Device symlinks could use an order-only dependency,
396 // but the current implementation uses a normal dependency.
Colin Cross6ac95762021-11-09 13:17:44 -0800397 assertInputs(symlinkRule("foo"), installRule("foo").Output)
398 assertImplicits(symlinkRule("foo"))
399 assertOrderOnlys(symlinkRule("foo"))
400}
401
Colin Crossc68db4b2021-11-11 18:59:15 -0800402func TestInstallKatiEnabled(t *testing.T) {
Colin Cross6ac95762021-11-09 13:17:44 -0800403 if runtime.GOOS != "linux" {
404 t.Skip("requires linux")
405 }
406 bp := `
407 deps {
408 name: "foo",
409 deps: ["bar"],
410 }
411
412 deps {
413 name: "bar",
414 deps: ["baz", "qux"],
415 }
416
417 deps {
418 name: "baz",
419 deps: ["qux"],
420 }
421
422 deps {
423 name: "qux",
424 }
425 `
426
427 result := GroupFixturePreparers(
428 prepareForModuleTests,
429 PrepareForTestWithArchMutator,
430 FixtureModifyConfig(SetKatiEnabledForTests),
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000431 PrepareForTestWithMakevars,
Colin Cross6ac95762021-11-09 13:17:44 -0800432 ).RunTestWithBp(t, bp)
433
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000434 rules := result.InstallMakeRulesForTesting(t)
Colin Cross6ac95762021-11-09 13:17:44 -0800435
436 module := func(name string, host bool) TestingModule {
437 variant := "android_common"
438 if host {
439 variant = result.Config.BuildOSCommonTarget.String()
440 }
441 return result.ModuleForTests(name, variant)
442 }
443
444 outputRule := func(name string) TestingBuildParams { return module(name, false).Output(name) }
445
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000446 ruleForOutput := func(output string) InstallMakeRule {
Colin Cross6ac95762021-11-09 13:17:44 -0800447 for _, rule := range rules {
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000448 if rule.Target == output {
Colin Cross6ac95762021-11-09 13:17:44 -0800449 return rule
450 }
451 }
452 t.Fatalf("no make install rule for %s", output)
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000453 return InstallMakeRule{}
Colin Cross6ac95762021-11-09 13:17:44 -0800454 }
455
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000456 installRule := func(name string) InstallMakeRule {
Colin Cross6ac95762021-11-09 13:17:44 -0800457 return ruleForOutput(filepath.Join("out/target/product/test_device/system", name))
458 }
459
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000460 symlinkRule := func(name string) InstallMakeRule {
Colin Cross6ac95762021-11-09 13:17:44 -0800461 return ruleForOutput(filepath.Join("out/target/product/test_device/system/symlinks", name))
462 }
463
464 hostOutputRule := func(name string) TestingBuildParams { return module(name, true).Output(name) }
465
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000466 hostInstallRule := func(name string) InstallMakeRule {
Colin Cross6ac95762021-11-09 13:17:44 -0800467 return ruleForOutput(filepath.Join("out/host/linux-x86", name))
468 }
469
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000470 hostSymlinkRule := func(name string) InstallMakeRule {
Colin Cross6ac95762021-11-09 13:17:44 -0800471 return ruleForOutput(filepath.Join("out/host/linux-x86/symlinks", name))
472 }
473
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000474 assertDeps := func(rule InstallMakeRule, deps ...string) {
Colin Cross6ac95762021-11-09 13:17:44 -0800475 t.Helper()
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000476 AssertArrayString(t, "expected inputs", deps, rule.Deps)
Colin Cross6ac95762021-11-09 13:17:44 -0800477 }
478
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000479 assertOrderOnlys := func(rule InstallMakeRule, orderonlys ...string) {
Colin Cross6ac95762021-11-09 13:17:44 -0800480 t.Helper()
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000481 AssertArrayString(t, "expected orderonly dependencies", orderonlys, rule.OrderOnlyDeps)
Colin Cross6ac95762021-11-09 13:17:44 -0800482 }
483
484 // Check host install rule dependencies
485 assertDeps(hostInstallRule("foo"),
486 hostOutputRule("foo").Output.String(),
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000487 hostInstallRule("bar").Target,
488 hostSymlinkRule("bar").Target,
489 hostInstallRule("baz").Target,
490 hostSymlinkRule("baz").Target,
491 hostInstallRule("qux").Target,
492 hostSymlinkRule("qux").Target,
Colin Cross6ac95762021-11-09 13:17:44 -0800493 )
494 assertOrderOnlys(hostInstallRule("foo"))
495
Colin Cross64002af2021-11-09 16:37:52 -0800496 // Check host symlink rule dependencies. Host symlinks must use a normal dependency, not an
497 // order-only dependency, so that the tool gets updated when the symlink is depended on.
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000498 assertDeps(hostSymlinkRule("foo"), hostInstallRule("foo").Target)
Colin Cross64002af2021-11-09 16:37:52 -0800499 assertOrderOnlys(hostSymlinkRule("foo"))
Colin Cross6ac95762021-11-09 13:17:44 -0800500
501 // Check device install rule dependencies
502 assertDeps(installRule("foo"), outputRule("foo").Output.String())
503 assertOrderOnlys(installRule("foo"),
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000504 installRule("bar").Target,
505 symlinkRule("bar").Target,
506 installRule("baz").Target,
507 symlinkRule("baz").Target,
508 installRule("qux").Target,
509 symlinkRule("qux").Target,
Colin Cross6ac95762021-11-09 13:17:44 -0800510 )
511
Colin Cross64002af2021-11-09 16:37:52 -0800512 // Check device symlink rule dependencies. Device symlinks could use an order-only dependency,
513 // but the current implementation uses a normal dependency.
Martin Stjernholm1ebef5b2022-02-10 23:34:28 +0000514 assertDeps(symlinkRule("foo"), installRule("foo").Target)
Colin Cross64002af2021-11-09 16:37:52 -0800515 assertOrderOnlys(symlinkRule("foo"))
Colin Cross6ac95762021-11-09 13:17:44 -0800516}
517
Liz Kammer9525e712022-01-05 13:46:24 -0500518type PropsTestModuleEmbedded struct {
519 Embedded_prop *string
520}
521
Liz Kammer898e0762022-03-22 11:27:26 -0400522type StructInSlice struct {
523 G string
524 H bool
525 I []string
526}
527
Liz Kammer9525e712022-01-05 13:46:24 -0500528type propsTestModule struct {
529 ModuleBase
530 DefaultableModuleBase
531 props struct {
532 A string `android:"arch_variant"`
533 B *bool
534 C []string
535 }
536 otherProps struct {
537 PropsTestModuleEmbedded
538
539 D *int64
540 Nested struct {
541 E *string
542 }
543 F *string `blueprint:"mutated"`
Liz Kammer898e0762022-03-22 11:27:26 -0400544
545 Slice_of_struct []StructInSlice
Liz Kammer9525e712022-01-05 13:46:24 -0500546 }
547}
548
549func propsTestModuleFactory() Module {
550 module := &propsTestModule{}
551 module.AddProperties(&module.props, &module.otherProps)
552 InitAndroidArchModule(module, HostAndDeviceSupported, MultilibBoth)
553 InitDefaultableModule(module)
554 return module
555}
556
557type propsTestModuleDefaults struct {
558 ModuleBase
559 DefaultsModuleBase
560}
561
562func propsTestModuleDefaultsFactory() Module {
563 defaults := &propsTestModuleDefaults{}
564 module := propsTestModule{}
565 defaults.AddProperties(&module.props, &module.otherProps)
566 InitDefaultsModule(defaults)
567 return defaults
568}
569
570func (p *propsTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
571 str := "abc"
572 p.otherProps.F = &str
573}
574
575func TestUsedProperties(t *testing.T) {
576 testCases := []struct {
577 desc string
578 bp string
579 expectedProps []propInfo
580 }{
581 {
582 desc: "only name",
583 bp: `test {
584 name: "foo",
585 }
586 `,
587 expectedProps: []propInfo{
Liz Kammer898e0762022-03-22 11:27:26 -0400588 propInfo{Name: "Name", Type: "string", Value: "foo"},
Liz Kammer9525e712022-01-05 13:46:24 -0500589 },
590 },
591 {
592 desc: "some props",
593 bp: `test {
594 name: "foo",
595 a: "abc",
596 b: true,
597 d: 123,
598 }
599 `,
600 expectedProps: []propInfo{
Liz Kammer898e0762022-03-22 11:27:26 -0400601 propInfo{Name: "A", Type: "string", Value: "abc"},
602 propInfo{Name: "B", Type: "bool", Value: "true"},
603 propInfo{Name: "D", Type: "int64", Value: "123"},
604 propInfo{Name: "Name", Type: "string", Value: "foo"},
Liz Kammer9525e712022-01-05 13:46:24 -0500605 },
606 },
607 {
608 desc: "unused non-pointer prop",
609 bp: `test {
610 name: "foo",
611 b: true,
612 d: 123,
613 }
614 `,
615 expectedProps: []propInfo{
616 // for non-pointer cannot distinguish between unused and intentionally set to empty
Liz Kammer898e0762022-03-22 11:27:26 -0400617 propInfo{Name: "A", Type: "string", Value: ""},
618 propInfo{Name: "B", Type: "bool", Value: "true"},
619 propInfo{Name: "D", Type: "int64", Value: "123"},
620 propInfo{Name: "Name", Type: "string", Value: "foo"},
Liz Kammer9525e712022-01-05 13:46:24 -0500621 },
622 },
623 {
624 desc: "nested props",
625 bp: `test {
626 name: "foo",
627 nested: {
628 e: "abc",
629 }
630 }
631 `,
632 expectedProps: []propInfo{
Liz Kammer898e0762022-03-22 11:27:26 -0400633 propInfo{Name: "Name", Type: "string", Value: "foo"},
634 propInfo{Name: "Nested.E", Type: "string", Value: "abc"},
Liz Kammer9525e712022-01-05 13:46:24 -0500635 },
636 },
637 {
638 desc: "arch props",
639 bp: `test {
640 name: "foo",
641 arch: {
642 x86_64: {
643 a: "abc",
644 },
645 }
646 }
647 `,
648 expectedProps: []propInfo{
Liz Kammer898e0762022-03-22 11:27:26 -0400649 propInfo{Name: "Arch.X86_64.A", Type: "string", Value: "abc"},
650 propInfo{Name: "Name", Type: "string", Value: "foo"},
Liz Kammer9525e712022-01-05 13:46:24 -0500651 },
652 },
653 {
654 desc: "embedded props",
655 bp: `test {
656 name: "foo",
657 embedded_prop: "a",
658 }
659 `,
660 expectedProps: []propInfo{
Liz Kammer898e0762022-03-22 11:27:26 -0400661 propInfo{Name: "Embedded_prop", Type: "string", Value: "a"},
662 propInfo{Name: "Name", Type: "string", Value: "foo"},
663 },
664 },
665 {
666 desc: "struct slice",
667 bp: `test {
668 name: "foo",
669 slice_of_struct: [
670 {
671 g: "abc",
672 h: false,
673 i: ["baz"],
674 },
675 {
676 g: "def",
677 h: true,
678 i: [],
679 },
680 ]
681 }
682 `,
683 expectedProps: []propInfo{
684 propInfo{Name: "Name", Type: "string", Value: "foo"},
685 propInfo{Name: "Slice_of_struct", Type: "struct slice", Values: []string{
686 `android.StructInSlice{G: abc, H: false, I: [baz]}`,
687 `android.StructInSlice{G: def, H: true, I: []}`,
688 }},
Liz Kammer9525e712022-01-05 13:46:24 -0500689 },
690 },
691 {
692 desc: "defaults",
693 bp: `
694test_defaults {
695 name: "foo_defaults",
696 a: "a",
697 b: true,
Liz Kammer898e0762022-03-22 11:27:26 -0400698 c: ["default_c"],
Liz Kammer9525e712022-01-05 13:46:24 -0500699 embedded_prop:"a",
700 arch: {
701 x86_64: {
Liz Kammer898e0762022-03-22 11:27:26 -0400702 a: "x86_64 a",
Liz Kammer9525e712022-01-05 13:46:24 -0500703 },
704 },
705}
706test {
707 name: "foo",
708 defaults: ["foo_defaults"],
Liz Kammer898e0762022-03-22 11:27:26 -0400709 c: ["c"],
Liz Kammer9525e712022-01-05 13:46:24 -0500710 nested: {
Liz Kammer898e0762022-03-22 11:27:26 -0400711 e: "nested e",
Liz Kammer9525e712022-01-05 13:46:24 -0500712 },
713 target: {
714 linux: {
715 a: "a",
716 },
717 },
718}
719 `,
720 expectedProps: []propInfo{
Liz Kammer898e0762022-03-22 11:27:26 -0400721 propInfo{Name: "A", Type: "string", Value: "a"},
722 propInfo{Name: "Arch.X86_64.A", Type: "string", Value: "x86_64 a"},
723 propInfo{Name: "B", Type: "bool", Value: "true"},
724 propInfo{Name: "C", Type: "string slice", Values: []string{"default_c", "c"}},
Liz Kammer898e0762022-03-22 11:27:26 -0400725 propInfo{Name: "Embedded_prop", Type: "string", Value: "a"},
726 propInfo{Name: "Name", Type: "string", Value: "foo"},
727 propInfo{Name: "Nested.E", Type: "string", Value: "nested e"},
728 propInfo{Name: "Target.Linux.A", Type: "string", Value: "a"},
Liz Kammer9525e712022-01-05 13:46:24 -0500729 },
730 },
731 }
732
733 for _, tc := range testCases {
734 t.Run(tc.desc, func(t *testing.T) {
735 result := GroupFixturePreparers(
736 PrepareForTestWithAllowMissingDependencies,
737 PrepareForTestWithDefaults,
738 FixtureRegisterWithContext(func(ctx RegistrationContext) {
739 ctx.RegisterModuleType("test", propsTestModuleFactory)
740 ctx.RegisterModuleType("test_defaults", propsTestModuleDefaultsFactory)
741 }),
742 FixtureWithRootAndroidBp(tc.bp),
743 ).RunTest(t)
744
745 foo := result.ModuleForTests("foo", "").Module().base()
746
747 AssertDeepEquals(t, "foo ", tc.expectedProps, foo.propertiesWithValues())
Liz Kammer9525e712022-01-05 13:46:24 -0500748 })
749 }
750}
Bob Badour4101c712022-02-09 11:54:35 -0800751
752func TestSortedUniqueNamedPaths(t *testing.T) {
753 type np struct {
754 path, name string
755 }
756 makePaths := func(l []np) NamedPaths {
757 result := make(NamedPaths, 0, len(l))
758 for _, p := range l {
759 result = append(result, NamedPath{PathForTesting(p.path), p.name})
760 }
761 return result
762 }
763
764 tests := []struct {
765 name string
766 in []np
767 expectedOut []np
768 }{
769 {
770 name: "empty",
771 in: []np{},
772 expectedOut: []np{},
773 },
774 {
775 name: "all_same",
776 in: []np{
777 {"a.txt", "A"},
778 {"a.txt", "A"},
779 {"a.txt", "A"},
780 {"a.txt", "A"},
781 {"a.txt", "A"},
782 },
783 expectedOut: []np{
784 {"a.txt", "A"},
785 },
786 },
787 {
788 name: "same_path_different_names",
789 in: []np{
790 {"a.txt", "C"},
791 {"a.txt", "A"},
792 {"a.txt", "D"},
793 {"a.txt", "B"},
794 {"a.txt", "E"},
795 },
796 expectedOut: []np{
797 {"a.txt", "A"},
798 {"a.txt", "B"},
799 {"a.txt", "C"},
800 {"a.txt", "D"},
801 {"a.txt", "E"},
802 },
803 },
804 {
805 name: "different_paths_same_name",
806 in: []np{
807 {"b/b.txt", "A"},
808 {"a/a.txt", "A"},
809 {"a/txt", "A"},
810 {"b", "A"},
811 {"a/b/d", "A"},
812 },
813 expectedOut: []np{
814 {"a/a.txt", "A"},
815 {"a/b/d", "A"},
816 {"a/txt", "A"},
817 {"b/b.txt", "A"},
818 {"b", "A"},
819 },
820 },
821 {
822 name: "all_different",
823 in: []np{
824 {"b/b.txt", "A"},
825 {"a/a.txt", "B"},
826 {"a/txt", "D"},
827 {"b", "C"},
828 {"a/b/d", "E"},
829 },
830 expectedOut: []np{
831 {"a/a.txt", "B"},
832 {"a/b/d", "E"},
833 {"a/txt", "D"},
834 {"b/b.txt", "A"},
835 {"b", "C"},
836 },
837 },
838 {
839 name: "some_different",
840 in: []np{
841 {"b/b.txt", "A"},
842 {"a/a.txt", "B"},
843 {"a/txt", "D"},
844 {"a/b/d", "E"},
845 {"b", "C"},
846 {"a/a.txt", "B"},
847 {"a/b/d", "E"},
848 },
849 expectedOut: []np{
850 {"a/a.txt", "B"},
851 {"a/b/d", "E"},
852 {"a/txt", "D"},
853 {"b/b.txt", "A"},
854 {"b", "C"},
855 },
856 },
857 }
858 for _, tt := range tests {
859 t.Run(tt.name, func(t *testing.T) {
860 actual := SortedUniqueNamedPaths(makePaths(tt.in))
861 expected := makePaths(tt.expectedOut)
862 t.Logf("actual: %v", actual)
863 t.Logf("expected: %v", expected)
864 AssertDeepEquals(t, "SortedUniqueNamedPaths ", expected, actual)
865 })
866 }
867}
Zhenhuang Wang0ac5a432022-08-12 18:49:20 +0800868
Zhenhuang Wang409d2772022-08-22 16:00:05 +0800869func TestSetAndroidMkEntriesWithTestOptions(t *testing.T) {
Zhenhuang Wang0ac5a432022-08-12 18:49:20 +0800870 tests := []struct {
871 name string
872 testOptions CommonTestOptions
873 expected map[string][]string
874 }{
875 {
876 name: "empty",
877 testOptions: CommonTestOptions{},
878 expected: map[string][]string{},
879 },
880 {
881 name: "is unit test",
882 testOptions: CommonTestOptions{
883 Unit_test: boolPtr(true),
884 },
885 expected: map[string][]string{
886 "LOCAL_IS_UNIT_TEST": []string{"true"},
887 },
888 },
889 {
890 name: "is not unit test",
891 testOptions: CommonTestOptions{
892 Unit_test: boolPtr(false),
893 },
894 expected: map[string][]string{},
895 },
Zhenhuang Wang409d2772022-08-22 16:00:05 +0800896 {
897 name: "empty tag",
898 testOptions: CommonTestOptions{
899 Tags: []string{},
900 },
901 expected: map[string][]string{},
902 },
903 {
904 name: "single tag",
905 testOptions: CommonTestOptions{
906 Tags: []string{"tag1"},
907 },
908 expected: map[string][]string{
909 "LOCAL_TEST_OPTIONS_TAGS": []string{"tag1"},
910 },
911 },
912 {
913 name: "multiple tag",
914 testOptions: CommonTestOptions{
915 Tags: []string{"tag1", "tag2", "tag3"},
916 },
917 expected: map[string][]string{
918 "LOCAL_TEST_OPTIONS_TAGS": []string{"tag1", "tag2", "tag3"},
919 },
920 },
Zhenhuang Wang0ac5a432022-08-12 18:49:20 +0800921 }
922 for _, tt := range tests {
923 t.Run(tt.name, func(t *testing.T) {
924 actualEntries := AndroidMkEntries{
925 EntryMap: map[string][]string{},
926 }
927 tt.testOptions.SetAndroidMkEntries(&actualEntries)
928 actual := actualEntries.EntryMap
929 t.Logf("actual: %v", actual)
930 t.Logf("expected: %v", tt.expected)
931 AssertDeepEquals(t, "TestProcessCommonTestOptions ", tt.expected, actual)
932 })
933 }
934}
Colin Cross14ec66c2022-10-03 21:02:27 -0700935
936type fakeBlueprintModule struct{}
937
938func (fakeBlueprintModule) Name() string { return "foo" }
939
940func (fakeBlueprintModule) GenerateBuildActions(blueprint.ModuleContext) {}
941
942type sourceProducerTestModule struct {
943 fakeBlueprintModule
944 source Path
945}
946
947func (s sourceProducerTestModule) Srcs() Paths { return Paths{s.source} }
948
949type outputFileProducerTestModule struct {
950 fakeBlueprintModule
951 output map[string]Path
952 error map[string]error
953}
954
955func (o outputFileProducerTestModule) OutputFiles(tag string) (Paths, error) {
956 return PathsIfNonNil(o.output[tag]), o.error[tag]
957}
958
959type pathContextAddMissingDependenciesWrapper struct {
960 PathContext
961 missingDeps []string
962}
963
964func (p *pathContextAddMissingDependenciesWrapper) AddMissingDependencies(deps []string) {
965 p.missingDeps = append(p.missingDeps, deps...)
966}
967func (p *pathContextAddMissingDependenciesWrapper) OtherModuleName(module blueprint.Module) string {
968 return module.Name()
969}
970
971func TestOutputFileForModule(t *testing.T) {
972 testcases := []struct {
973 name string
974 module blueprint.Module
975 tag string
976 env map[string]string
977 config func(*config)
978 expected string
979 missingDeps []string
980 }{
981 {
982 name: "SourceFileProducer",
983 module: &sourceProducerTestModule{source: PathForTesting("foo.txt")},
984 expected: "foo.txt",
985 },
986 {
987 name: "OutputFileProducer",
988 module: &outputFileProducerTestModule{output: map[string]Path{"": PathForTesting("foo.txt")}},
989 expected: "foo.txt",
990 },
991 {
992 name: "OutputFileProducer_tag",
993 module: &outputFileProducerTestModule{output: map[string]Path{"foo": PathForTesting("foo.txt")}},
994 tag: "foo",
995 expected: "foo.txt",
996 },
997 {
998 name: "OutputFileProducer_AllowMissingDependencies",
999 config: func(config *config) {
1000 config.TestProductVariables.Allow_missing_dependencies = boolPtr(true)
1001 },
1002 module: &outputFileProducerTestModule{},
1003 missingDeps: []string{"foo"},
1004 expected: "missing_output_file/foo",
1005 },
1006 }
1007 for _, tt := range testcases {
1008 config := TestConfig(buildDir, tt.env, "", nil)
1009 if tt.config != nil {
1010 tt.config(config.config)
1011 }
1012 ctx := &pathContextAddMissingDependenciesWrapper{
1013 PathContext: PathContextForTesting(config),
1014 }
1015 got := OutputFileForModule(ctx, tt.module, tt.tag)
1016 AssertPathRelativeToTopEquals(t, "expected source path", tt.expected, got)
1017 AssertArrayString(t, "expected missing deps", tt.missingDeps, ctx.missingDeps)
1018 }
1019}