blob: 20241fe1b42c4b740fd44ffae60acc58fca4614a [file] [log] [blame]
Jeff Gaston088e29e2017-11-29 16:47:17 -08001// Copyright 2017 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 "errors"
Jeff Gaston088e29e2017-11-29 16:47:17 -080019 "path/filepath"
Jeff Gastonb274ed32017-12-01 17:10:33 -080020 "reflect"
Jeff Gaston088e29e2017-11-29 16:47:17 -080021 "testing"
22
23 "github.com/google/blueprint"
24)
25
26func TestDependingOnModuleInSameNamespace(t *testing.T) {
27 ctx := setupTest(t,
28 map[string]string{
29 "dir1": `
30 soong_namespace {
31 }
32 test_module {
33 name: "a",
34 }
35 test_module {
36 name: "b",
37 deps: ["a"],
38 }
39 `,
40 },
41 )
42
43 a := getModule(ctx, "a")
44 b := getModule(ctx, "b")
45 if !dependsOn(ctx, b, a) {
46 t.Errorf("module b does not depend on module a in the same namespace")
47 }
48}
49
50func TestDependingOnModuleInRootNamespace(t *testing.T) {
51 ctx := setupTest(t,
52 map[string]string{
53 ".": `
54 test_module {
55 name: "b",
56 deps: ["a"],
57 }
58 test_module {
59 name: "a",
60 }
61 `,
62 },
63 )
64
65 a := getModule(ctx, "a")
66 b := getModule(ctx, "b")
67 if !dependsOn(ctx, b, a) {
68 t.Errorf("module b in root namespace does not depend on module a in the root namespace")
69 }
70}
71
72func TestImplicitlyImportRootNamespace(t *testing.T) {
73 _ = setupTest(t,
74 map[string]string{
75 ".": `
76 test_module {
77 name: "a",
78 }
79 `,
80 "dir1": `
81 soong_namespace {
82 }
83 test_module {
84 name: "b",
85 deps: ["a"],
86 }
87 `,
88 },
89 )
90
91 // setupTest will report any errors
92}
93
Colin Crosscd84b4e2019-06-14 11:26:09 -070094func TestDependingOnBlueprintModuleInRootNamespace(t *testing.T) {
95 _ = setupTest(t,
96 map[string]string{
97 ".": `
98 blueprint_test_module {
99 name: "a",
100 }
101 `,
102 "dir1": `
103 soong_namespace {
104 }
105 blueprint_test_module {
106 name: "b",
107 deps: ["a"],
108 }
109 `,
110 },
111 )
112
113 // setupTest will report any errors
114}
115
Jeff Gaston088e29e2017-11-29 16:47:17 -0800116func TestDependingOnModuleInImportedNamespace(t *testing.T) {
117 ctx := setupTest(t,
118 map[string]string{
119 "dir1": `
120 soong_namespace {
121 }
122 test_module {
123 name: "a",
124 }
125 `,
126 "dir2": `
127 soong_namespace {
128 imports: ["dir1"],
129 }
130 test_module {
131 name: "b",
132 deps: ["a"],
133 }
134 `,
135 },
136 )
137
138 a := getModule(ctx, "a")
139 b := getModule(ctx, "b")
140 if !dependsOn(ctx, b, a) {
141 t.Errorf("module b does not depend on module a in the same namespace")
142 }
143}
144
145func TestDependingOnModuleInNonImportedNamespace(t *testing.T) {
146 _, errs := setupTestExpectErrs(
147 map[string]string{
148 "dir1": `
149 soong_namespace {
150 }
151 test_module {
152 name: "a",
153 }
154 `,
155 "dir2": `
156 soong_namespace {
157 }
158 test_module {
159 name: "a",
160 }
161 `,
162 "dir3": `
163 soong_namespace {
164 }
165 test_module {
166 name: "b",
167 deps: ["a"],
168 }
169 `,
170 },
171 )
172
173 expectedErrors := []error{
174 errors.New(
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800175 `dir3/Android.bp:4:4: "b" depends on undefined module "a"
Jeff Gaston088e29e2017-11-29 16:47:17 -0800176Module "b" is defined in namespace "dir3" which can read these 2 namespaces: ["dir3" "."]
177Module "a" can be found in these namespaces: ["dir1" "dir2"]`),
178 }
179
180 if len(errs) != 1 || errs[0].Error() != expectedErrors[0].Error() {
181 t.Errorf("Incorrect errors. Expected:\n%v\n, got:\n%v\n", expectedErrors, errs)
182 }
183}
184
185func TestDependingOnModuleByFullyQualifiedReference(t *testing.T) {
186 ctx := setupTest(t,
187 map[string]string{
188 "dir1": `
189 soong_namespace {
190 }
191 test_module {
192 name: "a",
193 }
194 `,
195 "dir2": `
196 soong_namespace {
197 }
198 test_module {
199 name: "b",
200 deps: ["//dir1:a"],
201 }
202 `,
203 },
204 )
205 a := getModule(ctx, "a")
206 b := getModule(ctx, "b")
207 if !dependsOn(ctx, b, a) {
208 t.Errorf("module b does not depend on module a")
209 }
210}
211
212func TestSameNameInTwoNamespaces(t *testing.T) {
213 ctx := setupTest(t,
214 map[string]string{
215 "dir1": `
216 soong_namespace {
217 }
218 test_module {
219 name: "a",
220 id: "1",
221 }
222 test_module {
223 name: "b",
224 deps: ["a"],
225 id: "2",
226 }
227 `,
228 "dir2": `
229 soong_namespace {
230 }
231 test_module {
232 name: "a",
233 id:"3",
234 }
235 test_module {
236 name: "b",
237 deps: ["a"],
238 id:"4",
239 }
240 `,
241 },
242 )
243
244 one := findModuleById(ctx, "1")
245 two := findModuleById(ctx, "2")
246 three := findModuleById(ctx, "3")
247 four := findModuleById(ctx, "4")
248 if !dependsOn(ctx, two, one) {
249 t.Fatalf("Module 2 does not depend on module 1 in its namespace")
250 }
251 if dependsOn(ctx, two, three) {
252 t.Fatalf("Module 2 depends on module 3 in another namespace")
253 }
254 if !dependsOn(ctx, four, three) {
255 t.Fatalf("Module 4 does not depend on module 3 in its namespace")
256 }
257 if dependsOn(ctx, four, one) {
258 t.Fatalf("Module 4 depends on module 1 in another namespace")
259 }
260}
261
262func TestSearchOrder(t *testing.T) {
263 ctx := setupTest(t,
264 map[string]string{
265 "dir1": `
266 soong_namespace {
267 }
268 test_module {
269 name: "a",
270 id: "1",
271 }
272 `,
273 "dir2": `
274 soong_namespace {
275 }
276 test_module {
277 name: "a",
278 id:"2",
279 }
280 test_module {
281 name: "b",
282 id:"3",
283 }
284 `,
285 "dir3": `
286 soong_namespace {
287 }
288 test_module {
289 name: "a",
290 id:"4",
291 }
292 test_module {
293 name: "b",
294 id:"5",
295 }
296 test_module {
297 name: "c",
298 id:"6",
299 }
300 `,
301 ".": `
302 test_module {
303 name: "a",
304 id: "7",
305 }
306 test_module {
307 name: "b",
308 id: "8",
309 }
310 test_module {
311 name: "c",
312 id: "9",
313 }
314 test_module {
315 name: "d",
316 id: "10",
317 }
318 `,
319 "dir4": `
320 soong_namespace {
321 imports: ["dir1", "dir2", "dir3"]
322 }
323 test_module {
324 name: "test_me",
325 id:"0",
326 deps: ["a", "b", "c", "d"],
327 }
328 `,
329 },
330 )
331
332 testMe := findModuleById(ctx, "0")
333 if !dependsOn(ctx, testMe, findModuleById(ctx, "1")) {
334 t.Errorf("test_me doesn't depend on id 1")
335 }
336 if !dependsOn(ctx, testMe, findModuleById(ctx, "3")) {
337 t.Errorf("test_me doesn't depend on id 3")
338 }
339 if !dependsOn(ctx, testMe, findModuleById(ctx, "6")) {
340 t.Errorf("test_me doesn't depend on id 6")
341 }
342 if !dependsOn(ctx, testMe, findModuleById(ctx, "10")) {
343 t.Errorf("test_me doesn't depend on id 10")
344 }
345 if numDeps(ctx, testMe) != 4 {
346 t.Errorf("num dependencies of test_me = %v, not 4\n", numDeps(ctx, testMe))
347 }
348}
349
350func TestTwoNamespacesCanImportEachOther(t *testing.T) {
351 _ = setupTest(t,
352 map[string]string{
353 "dir1": `
354 soong_namespace {
355 imports: ["dir2"]
356 }
357 test_module {
358 name: "a",
359 }
360 test_module {
361 name: "c",
362 deps: ["b"],
363 }
364 `,
365 "dir2": `
366 soong_namespace {
367 imports: ["dir1"],
368 }
369 test_module {
370 name: "b",
371 deps: ["a"],
372 }
373 `,
374 },
375 )
376
377 // setupTest will report any errors
378}
379
380func TestImportingNonexistentNamespace(t *testing.T) {
381 _, errs := setupTestExpectErrs(
382 map[string]string{
383 "dir1": `
384 soong_namespace {
385 imports: ["a_nonexistent_namespace"]
386 }
387 test_module {
388 name: "a",
389 deps: ["a_nonexistent_module"]
390 }
391 `,
392 },
393 )
394
395 // should complain about the missing namespace and not complain about the unresolvable dependency
396 expectedErrors := []error{
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800397 errors.New(`dir1/Android.bp:2:4: module "soong_namespace": namespace a_nonexistent_namespace does not exist`),
Jeff Gaston088e29e2017-11-29 16:47:17 -0800398 }
399 if len(errs) != 1 || errs[0].Error() != expectedErrors[0].Error() {
400 t.Errorf("Incorrect errors. Expected:\n%v\n, got:\n%v\n", expectedErrors, errs)
401 }
402}
403
404func TestNamespacesDontInheritParentNamespaces(t *testing.T) {
405 _, errs := setupTestExpectErrs(
406 map[string]string{
407 "dir1": `
408 soong_namespace {
409 }
410 test_module {
411 name: "a",
412 }
413 `,
414 "dir1/subdir1": `
415 soong_namespace {
416 }
417 test_module {
418 name: "b",
419 deps: ["a"],
420 }
421 `,
422 },
423 )
424
425 expectedErrors := []error{
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800426 errors.New(`dir1/subdir1/Android.bp:4:4: "b" depends on undefined module "a"
Jeff Gaston088e29e2017-11-29 16:47:17 -0800427Module "b" is defined in namespace "dir1/subdir1" which can read these 2 namespaces: ["dir1/subdir1" "."]
428Module "a" can be found in these namespaces: ["dir1"]`),
429 }
430 if len(errs) != 1 || errs[0].Error() != expectedErrors[0].Error() {
431 t.Errorf("Incorrect errors. Expected:\n%v\n, got:\n%v\n", expectedErrors, errs)
432 }
433}
434
435func TestModulesDoReceiveParentNamespace(t *testing.T) {
436 _ = setupTest(t,
437 map[string]string{
438 "dir1": `
439 soong_namespace {
440 }
441 test_module {
442 name: "a",
443 }
444 `,
445 "dir1/subdir": `
446 test_module {
447 name: "b",
448 deps: ["a"],
449 }
450 `,
451 },
452 )
453
454 // setupTest will report any errors
455}
456
457func TestNamespaceImportsNotTransitive(t *testing.T) {
458 _, errs := setupTestExpectErrs(
459 map[string]string{
460 "dir1": `
461 soong_namespace {
462 }
463 test_module {
464 name: "a",
465 }
466 `,
467 "dir2": `
468 soong_namespace {
469 imports: ["dir1"],
470 }
471 test_module {
472 name: "b",
473 deps: ["a"],
474 }
475 `,
476 "dir3": `
477 soong_namespace {
478 imports: ["dir2"],
479 }
480 test_module {
481 name: "c",
482 deps: ["a"],
483 }
484 `,
485 },
486 )
487
488 expectedErrors := []error{
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800489 errors.New(`dir3/Android.bp:5:4: "c" depends on undefined module "a"
Jeff Gaston088e29e2017-11-29 16:47:17 -0800490Module "c" is defined in namespace "dir3" which can read these 3 namespaces: ["dir3" "dir2" "."]
491Module "a" can be found in these namespaces: ["dir1"]`),
492 }
493 if len(errs) != 1 || errs[0].Error() != expectedErrors[0].Error() {
494 t.Errorf("Incorrect errors. Expected:\n%v\n, got:\n%v\n", expectedErrors, errs)
495 }
496}
497
498func TestTwoNamepacesInSameDir(t *testing.T) {
499 _, errs := setupTestExpectErrs(
500 map[string]string{
501 "dir1": `
502 soong_namespace {
503 }
504 soong_namespace {
505 }
506 `,
507 },
508 )
509
510 expectedErrors := []error{
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800511 errors.New(`dir1/Android.bp:4:4: namespace dir1 already exists`),
Jeff Gaston088e29e2017-11-29 16:47:17 -0800512 }
513 if len(errs) != 1 || errs[0].Error() != expectedErrors[0].Error() {
514 t.Errorf("Incorrect errors. Expected:\n%v\n, got:\n%v\n", expectedErrors, errs)
515 }
516}
517
518func TestNamespaceNotAtTopOfFile(t *testing.T) {
519 _, errs := setupTestExpectErrs(
520 map[string]string{
521 "dir1": `
522 test_module {
523 name: "a"
524 }
525 soong_namespace {
526 }
527 `,
528 },
529 )
530
531 expectedErrors := []error{
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800532 errors.New(`dir1/Android.bp:5:4: a namespace must be the first module in the file`),
Jeff Gaston088e29e2017-11-29 16:47:17 -0800533 }
534 if len(errs) != 1 || errs[0].Error() != expectedErrors[0].Error() {
535 t.Errorf("Incorrect errors. Expected:\n%v\n, got:\n%v\n", expectedErrors, errs)
536 }
537}
538
539func TestTwoModulesWithSameNameInSameNamespace(t *testing.T) {
540 _, errs := setupTestExpectErrs(
541 map[string]string{
542 "dir1": `
543 soong_namespace {
544 }
545 test_module {
546 name: "a"
547 }
548 test_module {
549 name: "a"
550 }
551 `,
552 },
553 )
554
555 expectedErrors := []error{
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800556 errors.New(`dir1/Android.bp:7:4: module "a" already defined
557 dir1/Android.bp:4:4 <-- previous definition here`),
Jeff Gaston088e29e2017-11-29 16:47:17 -0800558 }
559 if len(errs) != 1 || errs[0].Error() != expectedErrors[0].Error() {
560 t.Errorf("Incorrect errors. Expected:\n%v\n, got:\n%v\n", expectedErrors, errs)
561 }
562}
563
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800564func TestDeclaringNamespaceInNonAndroidBpFile(t *testing.T) {
565 _, errs := setupTestFromFiles(
566 map[string][]byte{
567 "Android.bp": []byte(`
568 build = ["include.bp"]
569 `),
570 "include.bp": []byte(`
571 soong_namespace {
572 }
573 `),
574 },
575 )
576
577 expectedErrors := []error{
578 errors.New(`include.bp:2:5: A namespace may only be declared in a file named Android.bp`),
579 }
580
581 if len(errs) != 1 || errs[0].Error() != expectedErrors[0].Error() {
582 t.Errorf("Incorrect errors. Expected:\n%v\n, got:\n%v\n", expectedErrors, errs)
583 }
584}
585
Jeff Gastonb274ed32017-12-01 17:10:33 -0800586// so that the generated .ninja file will have consistent names
587func TestConsistentNamespaceNames(t *testing.T) {
588 ctx := setupTest(t,
589 map[string]string{
590 "dir1": "soong_namespace{}",
591 "dir2": "soong_namespace{}",
592 "dir3": "soong_namespace{}",
593 })
594
595 ns1, _ := ctx.NameResolver.namespaceAt("dir1")
596 ns2, _ := ctx.NameResolver.namespaceAt("dir2")
597 ns3, _ := ctx.NameResolver.namespaceAt("dir3")
598 actualIds := []string{ns1.id, ns2.id, ns3.id}
599 expectedIds := []string{"1", "2", "3"}
600 if !reflect.DeepEqual(actualIds, expectedIds) {
601 t.Errorf("Incorrect namespace ids.\nactual: %s\nexpected: %s\n", actualIds, expectedIds)
602 }
603}
604
Colin Crosseafb10c2018-04-16 13:58:10 -0700605// so that the generated .ninja file will have consistent names
606func TestRename(t *testing.T) {
607 _ = setupTest(t,
608 map[string]string{
609 "dir1": `
610 soong_namespace {
611 }
612 test_module {
613 name: "a",
614 deps: ["c"],
615 }
616 test_module {
617 name: "b",
618 rename: "c",
619 }
620 `})
621 // setupTest will report any errors
622}
623
Jeff Gaston088e29e2017-11-29 16:47:17 -0800624// some utils to support the tests
625
626func mockFiles(bps map[string]string) (files map[string][]byte) {
627 files = make(map[string][]byte, len(bps))
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800628 files["Android.bp"] = []byte("")
Jeff Gaston088e29e2017-11-29 16:47:17 -0800629 for dir, text := range bps {
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800630 files[filepath.Join(dir, "Android.bp")] = []byte(text)
Jeff Gaston088e29e2017-11-29 16:47:17 -0800631 }
632 return files
633}
634
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800635func setupTestFromFiles(bps map[string][]byte) (ctx *TestContext, errs []error) {
Jeff Gaston088e29e2017-11-29 16:47:17 -0800636 config := TestConfig(buildDir, nil)
637
638 ctx = NewTestContext()
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800639 ctx.MockFileSystem(bps)
Jeff Gaston088e29e2017-11-29 16:47:17 -0800640 ctx.RegisterModuleType("test_module", ModuleFactoryAdaptor(newTestModule))
641 ctx.RegisterModuleType("soong_namespace", ModuleFactoryAdaptor(NamespaceFactory))
Colin Crosscd84b4e2019-06-14 11:26:09 -0700642 ctx.RegisterModuleType("blueprint_test_module", newBlueprintTestModule)
Dan Willemsen6e72ef72018-01-26 18:27:02 -0800643 ctx.PreArchMutators(RegisterNamespaceMutator)
Colin Crosseafb10c2018-04-16 13:58:10 -0700644 ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
645 ctx.BottomUp("rename", renameMutator)
646 })
Jeff Gaston088e29e2017-11-29 16:47:17 -0800647 ctx.Register()
648
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800649 _, errs = ctx.ParseBlueprintsFiles("Android.bp")
Jeff Gaston088e29e2017-11-29 16:47:17 -0800650 if len(errs) > 0 {
651 return ctx, errs
652 }
653 _, errs = ctx.PrepareBuildActions(config)
654 return ctx, errs
655}
656
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800657func setupTestExpectErrs(bps map[string]string) (ctx *TestContext, errs []error) {
658 files := make(map[string][]byte, len(bps))
659 files["Android.bp"] = []byte("")
660 for dir, text := range bps {
661 files[filepath.Join(dir, "Android.bp")] = []byte(text)
662 }
663 return setupTestFromFiles(files)
664}
665
Jeff Gaston088e29e2017-11-29 16:47:17 -0800666func setupTest(t *testing.T, bps map[string]string) (ctx *TestContext) {
Colin Crosscd84b4e2019-06-14 11:26:09 -0700667 t.Helper()
Jeff Gaston088e29e2017-11-29 16:47:17 -0800668 ctx, errs := setupTestExpectErrs(bps)
Logan Chien42039712018-03-12 16:29:17 +0800669 FailIfErrored(t, errs)
Jeff Gaston088e29e2017-11-29 16:47:17 -0800670 return ctx
671}
672
673func dependsOn(ctx *TestContext, module TestingModule, possibleDependency TestingModule) bool {
674 depends := false
675 visit := func(dependency blueprint.Module) {
676 if dependency == possibleDependency.module {
677 depends = true
678 }
679 }
680 ctx.VisitDirectDeps(module.module, visit)
681 return depends
682}
683
684func numDeps(ctx *TestContext, module TestingModule) int {
685 count := 0
686 visit := func(dependency blueprint.Module) {
687 count++
688 }
689 ctx.VisitDirectDeps(module.module, visit)
690 return count
691}
692
693func getModule(ctx *TestContext, moduleName string) TestingModule {
694 return ctx.ModuleForTests(moduleName, "")
695}
696
697func findModuleById(ctx *TestContext, id string) (module TestingModule) {
698 visit := func(candidate blueprint.Module) {
699 testModule, ok := candidate.(*testModule)
700 if ok {
701 if testModule.properties.Id == id {
702 module = TestingModule{testModule}
703 }
704 }
705 }
706 ctx.VisitAllModules(visit)
707 return module
708}
709
710type testModule struct {
711 ModuleBase
712 properties struct {
Colin Crosseafb10c2018-04-16 13:58:10 -0700713 Rename string
714 Deps []string
715 Id string
Jeff Gaston088e29e2017-11-29 16:47:17 -0800716 }
717}
718
719func (m *testModule) DepsMutator(ctx BottomUpMutatorContext) {
Colin Crosseafb10c2018-04-16 13:58:10 -0700720 if m.properties.Rename != "" {
721 ctx.Rename(m.properties.Rename)
722 }
Jeff Gaston088e29e2017-11-29 16:47:17 -0800723 for _, d := range m.properties.Deps {
724 ctx.AddDependency(ctx.Module(), nil, d)
725 }
726}
727
728func (m *testModule) GenerateAndroidBuildActions(ModuleContext) {
729}
730
Colin Crosseafb10c2018-04-16 13:58:10 -0700731func renameMutator(ctx BottomUpMutatorContext) {
732 if m, ok := ctx.Module().(*testModule); ok {
733 if m.properties.Rename != "" {
734 ctx.Rename(m.properties.Rename)
735 }
736 }
737}
738
Jeff Gaston088e29e2017-11-29 16:47:17 -0800739func newTestModule() Module {
740 m := &testModule{}
741 m.AddProperties(&m.properties)
742 InitAndroidModule(m)
743 return m
744}
Colin Crosscd84b4e2019-06-14 11:26:09 -0700745
746type blueprintTestModule struct {
747 blueprint.SimpleName
748 properties struct {
749 Deps []string
750 }
751}
752
753func (b *blueprintTestModule) DynamicDependencies(ctx blueprint.DynamicDependerModuleContext) []string {
754 return b.properties.Deps
755}
756
757func (b *blueprintTestModule) GenerateBuildActions(blueprint.ModuleContext) {
758}
759
760func newBlueprintTestModule() (blueprint.Module, []interface{}) {
761 m := &blueprintTestModule{}
762 return m, []interface{}{&m.properties, &m.SimpleName.Properties}
763}