blob: 51a0af225adf11d374b6b126b7b3a296bce23892 [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
94func TestDependingOnModuleInImportedNamespace(t *testing.T) {
95 ctx := setupTest(t,
96 map[string]string{
97 "dir1": `
98 soong_namespace {
99 }
100 test_module {
101 name: "a",
102 }
103 `,
104 "dir2": `
105 soong_namespace {
106 imports: ["dir1"],
107 }
108 test_module {
109 name: "b",
110 deps: ["a"],
111 }
112 `,
113 },
114 )
115
116 a := getModule(ctx, "a")
117 b := getModule(ctx, "b")
118 if !dependsOn(ctx, b, a) {
119 t.Errorf("module b does not depend on module a in the same namespace")
120 }
121}
122
123func TestDependingOnModuleInNonImportedNamespace(t *testing.T) {
124 _, errs := setupTestExpectErrs(
125 map[string]string{
126 "dir1": `
127 soong_namespace {
128 }
129 test_module {
130 name: "a",
131 }
132 `,
133 "dir2": `
134 soong_namespace {
135 }
136 test_module {
137 name: "a",
138 }
139 `,
140 "dir3": `
141 soong_namespace {
142 }
143 test_module {
144 name: "b",
145 deps: ["a"],
146 }
147 `,
148 },
149 )
150
151 expectedErrors := []error{
152 errors.New(
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800153 `dir3/Android.bp:4:4: "b" depends on undefined module "a"
Jeff Gaston088e29e2017-11-29 16:47:17 -0800154Module "b" is defined in namespace "dir3" which can read these 2 namespaces: ["dir3" "."]
155Module "a" can be found in these namespaces: ["dir1" "dir2"]`),
156 }
157
158 if len(errs) != 1 || errs[0].Error() != expectedErrors[0].Error() {
159 t.Errorf("Incorrect errors. Expected:\n%v\n, got:\n%v\n", expectedErrors, errs)
160 }
161}
162
163func TestDependingOnModuleByFullyQualifiedReference(t *testing.T) {
164 ctx := setupTest(t,
165 map[string]string{
166 "dir1": `
167 soong_namespace {
168 }
169 test_module {
170 name: "a",
171 }
172 `,
173 "dir2": `
174 soong_namespace {
175 }
176 test_module {
177 name: "b",
178 deps: ["//dir1:a"],
179 }
180 `,
181 },
182 )
183 a := getModule(ctx, "a")
184 b := getModule(ctx, "b")
185 if !dependsOn(ctx, b, a) {
186 t.Errorf("module b does not depend on module a")
187 }
188}
189
190func TestSameNameInTwoNamespaces(t *testing.T) {
191 ctx := setupTest(t,
192 map[string]string{
193 "dir1": `
194 soong_namespace {
195 }
196 test_module {
197 name: "a",
198 id: "1",
199 }
200 test_module {
201 name: "b",
202 deps: ["a"],
203 id: "2",
204 }
205 `,
206 "dir2": `
207 soong_namespace {
208 }
209 test_module {
210 name: "a",
211 id:"3",
212 }
213 test_module {
214 name: "b",
215 deps: ["a"],
216 id:"4",
217 }
218 `,
219 },
220 )
221
222 one := findModuleById(ctx, "1")
223 two := findModuleById(ctx, "2")
224 three := findModuleById(ctx, "3")
225 four := findModuleById(ctx, "4")
226 if !dependsOn(ctx, two, one) {
227 t.Fatalf("Module 2 does not depend on module 1 in its namespace")
228 }
229 if dependsOn(ctx, two, three) {
230 t.Fatalf("Module 2 depends on module 3 in another namespace")
231 }
232 if !dependsOn(ctx, four, three) {
233 t.Fatalf("Module 4 does not depend on module 3 in its namespace")
234 }
235 if dependsOn(ctx, four, one) {
236 t.Fatalf("Module 4 depends on module 1 in another namespace")
237 }
238}
239
240func TestSearchOrder(t *testing.T) {
241 ctx := setupTest(t,
242 map[string]string{
243 "dir1": `
244 soong_namespace {
245 }
246 test_module {
247 name: "a",
248 id: "1",
249 }
250 `,
251 "dir2": `
252 soong_namespace {
253 }
254 test_module {
255 name: "a",
256 id:"2",
257 }
258 test_module {
259 name: "b",
260 id:"3",
261 }
262 `,
263 "dir3": `
264 soong_namespace {
265 }
266 test_module {
267 name: "a",
268 id:"4",
269 }
270 test_module {
271 name: "b",
272 id:"5",
273 }
274 test_module {
275 name: "c",
276 id:"6",
277 }
278 `,
279 ".": `
280 test_module {
281 name: "a",
282 id: "7",
283 }
284 test_module {
285 name: "b",
286 id: "8",
287 }
288 test_module {
289 name: "c",
290 id: "9",
291 }
292 test_module {
293 name: "d",
294 id: "10",
295 }
296 `,
297 "dir4": `
298 soong_namespace {
299 imports: ["dir1", "dir2", "dir3"]
300 }
301 test_module {
302 name: "test_me",
303 id:"0",
304 deps: ["a", "b", "c", "d"],
305 }
306 `,
307 },
308 )
309
310 testMe := findModuleById(ctx, "0")
311 if !dependsOn(ctx, testMe, findModuleById(ctx, "1")) {
312 t.Errorf("test_me doesn't depend on id 1")
313 }
314 if !dependsOn(ctx, testMe, findModuleById(ctx, "3")) {
315 t.Errorf("test_me doesn't depend on id 3")
316 }
317 if !dependsOn(ctx, testMe, findModuleById(ctx, "6")) {
318 t.Errorf("test_me doesn't depend on id 6")
319 }
320 if !dependsOn(ctx, testMe, findModuleById(ctx, "10")) {
321 t.Errorf("test_me doesn't depend on id 10")
322 }
323 if numDeps(ctx, testMe) != 4 {
324 t.Errorf("num dependencies of test_me = %v, not 4\n", numDeps(ctx, testMe))
325 }
326}
327
328func TestTwoNamespacesCanImportEachOther(t *testing.T) {
329 _ = setupTest(t,
330 map[string]string{
331 "dir1": `
332 soong_namespace {
333 imports: ["dir2"]
334 }
335 test_module {
336 name: "a",
337 }
338 test_module {
339 name: "c",
340 deps: ["b"],
341 }
342 `,
343 "dir2": `
344 soong_namespace {
345 imports: ["dir1"],
346 }
347 test_module {
348 name: "b",
349 deps: ["a"],
350 }
351 `,
352 },
353 )
354
355 // setupTest will report any errors
356}
357
358func TestImportingNonexistentNamespace(t *testing.T) {
359 _, errs := setupTestExpectErrs(
360 map[string]string{
361 "dir1": `
362 soong_namespace {
363 imports: ["a_nonexistent_namespace"]
364 }
365 test_module {
366 name: "a",
367 deps: ["a_nonexistent_module"]
368 }
369 `,
370 },
371 )
372
373 // should complain about the missing namespace and not complain about the unresolvable dependency
374 expectedErrors := []error{
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800375 errors.New(`dir1/Android.bp:2:4: module "soong_namespace": namespace a_nonexistent_namespace does not exist`),
Jeff Gaston088e29e2017-11-29 16:47:17 -0800376 }
377 if len(errs) != 1 || errs[0].Error() != expectedErrors[0].Error() {
378 t.Errorf("Incorrect errors. Expected:\n%v\n, got:\n%v\n", expectedErrors, errs)
379 }
380}
381
382func TestNamespacesDontInheritParentNamespaces(t *testing.T) {
383 _, errs := setupTestExpectErrs(
384 map[string]string{
385 "dir1": `
386 soong_namespace {
387 }
388 test_module {
389 name: "a",
390 }
391 `,
392 "dir1/subdir1": `
393 soong_namespace {
394 }
395 test_module {
396 name: "b",
397 deps: ["a"],
398 }
399 `,
400 },
401 )
402
403 expectedErrors := []error{
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800404 errors.New(`dir1/subdir1/Android.bp:4:4: "b" depends on undefined module "a"
Jeff Gaston088e29e2017-11-29 16:47:17 -0800405Module "b" is defined in namespace "dir1/subdir1" which can read these 2 namespaces: ["dir1/subdir1" "."]
406Module "a" can be found in these namespaces: ["dir1"]`),
407 }
408 if len(errs) != 1 || errs[0].Error() != expectedErrors[0].Error() {
409 t.Errorf("Incorrect errors. Expected:\n%v\n, got:\n%v\n", expectedErrors, errs)
410 }
411}
412
413func TestModulesDoReceiveParentNamespace(t *testing.T) {
414 _ = setupTest(t,
415 map[string]string{
416 "dir1": `
417 soong_namespace {
418 }
419 test_module {
420 name: "a",
421 }
422 `,
423 "dir1/subdir": `
424 test_module {
425 name: "b",
426 deps: ["a"],
427 }
428 `,
429 },
430 )
431
432 // setupTest will report any errors
433}
434
435func TestNamespaceImportsNotTransitive(t *testing.T) {
436 _, errs := setupTestExpectErrs(
437 map[string]string{
438 "dir1": `
439 soong_namespace {
440 }
441 test_module {
442 name: "a",
443 }
444 `,
445 "dir2": `
446 soong_namespace {
447 imports: ["dir1"],
448 }
449 test_module {
450 name: "b",
451 deps: ["a"],
452 }
453 `,
454 "dir3": `
455 soong_namespace {
456 imports: ["dir2"],
457 }
458 test_module {
459 name: "c",
460 deps: ["a"],
461 }
462 `,
463 },
464 )
465
466 expectedErrors := []error{
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800467 errors.New(`dir3/Android.bp:5:4: "c" depends on undefined module "a"
Jeff Gaston088e29e2017-11-29 16:47:17 -0800468Module "c" is defined in namespace "dir3" which can read these 3 namespaces: ["dir3" "dir2" "."]
469Module "a" can be found in these namespaces: ["dir1"]`),
470 }
471 if len(errs) != 1 || errs[0].Error() != expectedErrors[0].Error() {
472 t.Errorf("Incorrect errors. Expected:\n%v\n, got:\n%v\n", expectedErrors, errs)
473 }
474}
475
476func TestTwoNamepacesInSameDir(t *testing.T) {
477 _, errs := setupTestExpectErrs(
478 map[string]string{
479 "dir1": `
480 soong_namespace {
481 }
482 soong_namespace {
483 }
484 `,
485 },
486 )
487
488 expectedErrors := []error{
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800489 errors.New(`dir1/Android.bp:4:4: namespace dir1 already exists`),
Jeff Gaston088e29e2017-11-29 16:47:17 -0800490 }
491 if len(errs) != 1 || errs[0].Error() != expectedErrors[0].Error() {
492 t.Errorf("Incorrect errors. Expected:\n%v\n, got:\n%v\n", expectedErrors, errs)
493 }
494}
495
496func TestNamespaceNotAtTopOfFile(t *testing.T) {
497 _, errs := setupTestExpectErrs(
498 map[string]string{
499 "dir1": `
500 test_module {
501 name: "a"
502 }
503 soong_namespace {
504 }
505 `,
506 },
507 )
508
509 expectedErrors := []error{
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800510 errors.New(`dir1/Android.bp:5:4: a namespace must be the first module in the file`),
Jeff Gaston088e29e2017-11-29 16:47:17 -0800511 }
512 if len(errs) != 1 || errs[0].Error() != expectedErrors[0].Error() {
513 t.Errorf("Incorrect errors. Expected:\n%v\n, got:\n%v\n", expectedErrors, errs)
514 }
515}
516
517func TestTwoModulesWithSameNameInSameNamespace(t *testing.T) {
518 _, errs := setupTestExpectErrs(
519 map[string]string{
520 "dir1": `
521 soong_namespace {
522 }
523 test_module {
524 name: "a"
525 }
526 test_module {
527 name: "a"
528 }
529 `,
530 },
531 )
532
533 expectedErrors := []error{
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800534 errors.New(`dir1/Android.bp:7:4: module "a" already defined
535 dir1/Android.bp:4:4 <-- previous definition here`),
Jeff Gaston088e29e2017-11-29 16:47:17 -0800536 }
537 if len(errs) != 1 || errs[0].Error() != expectedErrors[0].Error() {
538 t.Errorf("Incorrect errors. Expected:\n%v\n, got:\n%v\n", expectedErrors, errs)
539 }
540}
541
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800542func TestDeclaringNamespaceInNonAndroidBpFile(t *testing.T) {
543 _, errs := setupTestFromFiles(
544 map[string][]byte{
545 "Android.bp": []byte(`
546 build = ["include.bp"]
547 `),
548 "include.bp": []byte(`
549 soong_namespace {
550 }
551 `),
552 },
553 )
554
555 expectedErrors := []error{
556 errors.New(`include.bp:2:5: A namespace may only be declared in a file named Android.bp`),
557 }
558
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 Gastonb274ed32017-12-01 17:10:33 -0800564// so that the generated .ninja file will have consistent names
565func TestConsistentNamespaceNames(t *testing.T) {
566 ctx := setupTest(t,
567 map[string]string{
568 "dir1": "soong_namespace{}",
569 "dir2": "soong_namespace{}",
570 "dir3": "soong_namespace{}",
571 })
572
573 ns1, _ := ctx.NameResolver.namespaceAt("dir1")
574 ns2, _ := ctx.NameResolver.namespaceAt("dir2")
575 ns3, _ := ctx.NameResolver.namespaceAt("dir3")
576 actualIds := []string{ns1.id, ns2.id, ns3.id}
577 expectedIds := []string{"1", "2", "3"}
578 if !reflect.DeepEqual(actualIds, expectedIds) {
579 t.Errorf("Incorrect namespace ids.\nactual: %s\nexpected: %s\n", actualIds, expectedIds)
580 }
581}
582
Colin Crosseafb10c2018-04-16 13:58:10 -0700583// so that the generated .ninja file will have consistent names
584func TestRename(t *testing.T) {
585 _ = setupTest(t,
586 map[string]string{
587 "dir1": `
588 soong_namespace {
589 }
590 test_module {
591 name: "a",
592 deps: ["c"],
593 }
594 test_module {
595 name: "b",
596 rename: "c",
597 }
598 `})
599 // setupTest will report any errors
600}
601
Jeff Gaston088e29e2017-11-29 16:47:17 -0800602// some utils to support the tests
603
604func mockFiles(bps map[string]string) (files map[string][]byte) {
605 files = make(map[string][]byte, len(bps))
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800606 files["Android.bp"] = []byte("")
Jeff Gaston088e29e2017-11-29 16:47:17 -0800607 for dir, text := range bps {
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800608 files[filepath.Join(dir, "Android.bp")] = []byte(text)
Jeff Gaston088e29e2017-11-29 16:47:17 -0800609 }
610 return files
611}
612
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800613func setupTestFromFiles(bps map[string][]byte) (ctx *TestContext, errs []error) {
Jeff Gaston088e29e2017-11-29 16:47:17 -0800614 config := TestConfig(buildDir, nil)
615
616 ctx = NewTestContext()
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800617 ctx.MockFileSystem(bps)
Jeff Gaston088e29e2017-11-29 16:47:17 -0800618 ctx.RegisterModuleType("test_module", ModuleFactoryAdaptor(newTestModule))
619 ctx.RegisterModuleType("soong_namespace", ModuleFactoryAdaptor(NamespaceFactory))
Dan Willemsen6e72ef72018-01-26 18:27:02 -0800620 ctx.PreArchMutators(RegisterNamespaceMutator)
Colin Crosseafb10c2018-04-16 13:58:10 -0700621 ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
622 ctx.BottomUp("rename", renameMutator)
623 })
Jeff Gaston088e29e2017-11-29 16:47:17 -0800624 ctx.Register()
625
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800626 _, errs = ctx.ParseBlueprintsFiles("Android.bp")
Jeff Gaston088e29e2017-11-29 16:47:17 -0800627 if len(errs) > 0 {
628 return ctx, errs
629 }
630 _, errs = ctx.PrepareBuildActions(config)
631 return ctx, errs
632}
633
Jeff Gaston5c3886d2017-11-30 16:46:47 -0800634func setupTestExpectErrs(bps map[string]string) (ctx *TestContext, errs []error) {
635 files := make(map[string][]byte, len(bps))
636 files["Android.bp"] = []byte("")
637 for dir, text := range bps {
638 files[filepath.Join(dir, "Android.bp")] = []byte(text)
639 }
640 return setupTestFromFiles(files)
641}
642
Jeff Gaston088e29e2017-11-29 16:47:17 -0800643func setupTest(t *testing.T, bps map[string]string) (ctx *TestContext) {
644 ctx, errs := setupTestExpectErrs(bps)
Logan Chien42039712018-03-12 16:29:17 +0800645 FailIfErrored(t, errs)
Jeff Gaston088e29e2017-11-29 16:47:17 -0800646 return ctx
647}
648
649func dependsOn(ctx *TestContext, module TestingModule, possibleDependency TestingModule) bool {
650 depends := false
651 visit := func(dependency blueprint.Module) {
652 if dependency == possibleDependency.module {
653 depends = true
654 }
655 }
656 ctx.VisitDirectDeps(module.module, visit)
657 return depends
658}
659
660func numDeps(ctx *TestContext, module TestingModule) int {
661 count := 0
662 visit := func(dependency blueprint.Module) {
663 count++
664 }
665 ctx.VisitDirectDeps(module.module, visit)
666 return count
667}
668
669func getModule(ctx *TestContext, moduleName string) TestingModule {
670 return ctx.ModuleForTests(moduleName, "")
671}
672
673func findModuleById(ctx *TestContext, id string) (module TestingModule) {
674 visit := func(candidate blueprint.Module) {
675 testModule, ok := candidate.(*testModule)
676 if ok {
677 if testModule.properties.Id == id {
678 module = TestingModule{testModule}
679 }
680 }
681 }
682 ctx.VisitAllModules(visit)
683 return module
684}
685
686type testModule struct {
687 ModuleBase
688 properties struct {
Colin Crosseafb10c2018-04-16 13:58:10 -0700689 Rename string
690 Deps []string
691 Id string
Jeff Gaston088e29e2017-11-29 16:47:17 -0800692 }
693}
694
695func (m *testModule) DepsMutator(ctx BottomUpMutatorContext) {
Colin Crosseafb10c2018-04-16 13:58:10 -0700696 if m.properties.Rename != "" {
697 ctx.Rename(m.properties.Rename)
698 }
Jeff Gaston088e29e2017-11-29 16:47:17 -0800699 for _, d := range m.properties.Deps {
700 ctx.AddDependency(ctx.Module(), nil, d)
701 }
702}
703
704func (m *testModule) GenerateAndroidBuildActions(ModuleContext) {
705}
706
Colin Crosseafb10c2018-04-16 13:58:10 -0700707func renameMutator(ctx BottomUpMutatorContext) {
708 if m, ok := ctx.Module().(*testModule); ok {
709 if m.properties.Rename != "" {
710 ctx.Rename(m.properties.Rename)
711 }
712 }
713}
714
Jeff Gaston088e29e2017-11-29 16:47:17 -0800715func newTestModule() Module {
716 m := &testModule{}
717 m.AddProperties(&m.properties)
718 InitAndroidModule(m)
719 return m
720}