blob: 4cf41a6cc7e2b352ed79af6f196864c61108b380 [file] [log] [blame]
Paul Duffin2e61fa62019-03-28 14:10:57 +00001package android
2
3import (
Paul Duffin44885e22020-02-19 16:10:09 +00004 "reflect"
Paul Duffin2e61fa62019-03-28 14:10:57 +00005 "testing"
Martin Stjernholm8edeb632019-05-21 12:18:38 +01006
7 "github.com/google/blueprint"
Paul Duffin2e61fa62019-03-28 14:10:57 +00008)
9
10var visibilityTests = []struct {
Paul Duffin44885e22020-02-19 16:10:09 +000011 name string
12 fs map[string][]byte
13 expectedErrors []string
14 effectiveVisibility map[qualifiedModuleName][]string
Paul Duffin2e61fa62019-03-28 14:10:57 +000015}{
16 {
17 name: "invalid visibility: empty list",
18 fs: map[string][]byte{
19 "top/Blueprints": []byte(`
20 mock_library {
21 name: "libexample",
22 visibility: [],
23 }`),
24 },
25 expectedErrors: []string{`visibility: must contain at least one visibility rule`},
26 },
27 {
28 name: "invalid visibility: empty rule",
29 fs: map[string][]byte{
30 "top/Blueprints": []byte(`
31 mock_library {
32 name: "libexample",
33 visibility: [""],
34 }`),
35 },
36 expectedErrors: []string{`visibility: invalid visibility pattern ""`},
37 },
38 {
39 name: "invalid visibility: unqualified",
40 fs: map[string][]byte{
41 "top/Blueprints": []byte(`
42 mock_library {
43 name: "libexample",
44 visibility: ["target"],
45 }`),
46 },
47 expectedErrors: []string{`visibility: invalid visibility pattern "target"`},
48 },
49 {
50 name: "invalid visibility: empty namespace",
51 fs: map[string][]byte{
52 "top/Blueprints": []byte(`
53 mock_library {
54 name: "libexample",
55 visibility: ["//"],
56 }`),
57 },
58 expectedErrors: []string{`visibility: invalid visibility pattern "//"`},
59 },
60 {
61 name: "invalid visibility: empty module",
62 fs: map[string][]byte{
63 "top/Blueprints": []byte(`
64 mock_library {
65 name: "libexample",
66 visibility: [":"],
67 }`),
68 },
69 expectedErrors: []string{`visibility: invalid visibility pattern ":"`},
70 },
71 {
72 name: "invalid visibility: empty namespace and module",
73 fs: map[string][]byte{
74 "top/Blueprints": []byte(`
75 mock_library {
76 name: "libexample",
77 visibility: ["//:"],
78 }`),
79 },
80 expectedErrors: []string{`visibility: invalid visibility pattern "//:"`},
81 },
82 {
83 name: "//visibility:unknown",
84 fs: map[string][]byte{
85 "top/Blueprints": []byte(`
86 mock_library {
87 name: "libexample",
88 visibility: ["//visibility:unknown"],
89 }`),
90 },
91 expectedErrors: []string{`unrecognized visibility rule "//visibility:unknown"`},
92 },
93 {
Martin Stjernholm226b20d2019-05-17 22:42:02 +010094 name: "//visibility:xxx mixed",
Paul Duffin2e61fa62019-03-28 14:10:57 +000095 fs: map[string][]byte{
96 "top/Blueprints": []byte(`
97 mock_library {
98 name: "libexample",
99 visibility: ["//visibility:public", "//namespace"],
100 }
101
102 mock_library {
103 name: "libother",
104 visibility: ["//visibility:private", "//namespace"],
105 }`),
106 },
107 expectedErrors: []string{
Martin Stjernholm226b20d2019-05-17 22:42:02 +0100108 `module "libother": visibility: cannot mix "//visibility:private"` +
Paul Duffin2e61fa62019-03-28 14:10:57 +0000109 ` with any other visibility rules`,
Martin Stjernholm226b20d2019-05-17 22:42:02 +0100110 `module "libexample": visibility: cannot mix "//visibility:public"` +
111 ` with any other visibility rules`,
Paul Duffin2e61fa62019-03-28 14:10:57 +0000112 },
113 },
114 {
115 name: "//visibility:legacy_public",
116 fs: map[string][]byte{
117 "top/Blueprints": []byte(`
118 mock_library {
119 name: "libexample",
120 visibility: ["//visibility:legacy_public"],
121 }`),
122 },
123 expectedErrors: []string{
Martin Stjernholm226b20d2019-05-17 22:42:02 +0100124 `module "libexample": visibility: //visibility:legacy_public must` +
Paul Duffin2e61fa62019-03-28 14:10:57 +0000125 ` not be used`,
126 },
127 },
128 {
129 // Verify that //visibility:public will allow the module to be referenced from anywhere, e.g.
130 // the current directory, a nested directory and a directory in a separate tree.
131 name: "//visibility:public",
132 fs: map[string][]byte{
133 "top/Blueprints": []byte(`
134 mock_library {
135 name: "libexample",
136 visibility: ["//visibility:public"],
137 }
138
139 mock_library {
140 name: "libsamepackage",
141 deps: ["libexample"],
142 }`),
143 "top/nested/Blueprints": []byte(`
144 mock_library {
145 name: "libnested",
146 deps: ["libexample"],
147 }`),
148 "other/Blueprints": []byte(`
149 mock_library {
150 name: "libother",
151 deps: ["libexample"],
152 }`),
153 },
154 },
155 {
Paul Duffin2e61fa62019-03-28 14:10:57 +0000156 // Verify that //visibility:private allows the module to be referenced from the current
157 // directory only.
158 name: "//visibility:private",
159 fs: map[string][]byte{
160 "top/Blueprints": []byte(`
161 mock_library {
162 name: "libexample",
163 visibility: ["//visibility:private"],
164 }
165
166 mock_library {
167 name: "libsamepackage",
168 deps: ["libexample"],
169 }`),
170 "top/nested/Blueprints": []byte(`
171 mock_library {
172 name: "libnested",
173 deps: ["libexample"],
174 }`),
Martin Stjernholm8edeb632019-05-21 12:18:38 +0100175 "other/Blueprints": []byte(`
176 mock_library {
177 name: "libother",
178 deps: ["libexample"],
179 }`),
Paul Duffin2e61fa62019-03-28 14:10:57 +0000180 },
181 expectedErrors: []string{
182 `module "libnested" variant "android_common": depends on //top:libexample which is not` +
Martin Stjernholm226b20d2019-05-17 22:42:02 +0100183 ` visible to this module`,
Martin Stjernholm8edeb632019-05-21 12:18:38 +0100184 `module "libother" variant "android_common": depends on //top:libexample which is not` +
Martin Stjernholm226b20d2019-05-17 22:42:02 +0100185 ` visible to this module`,
Paul Duffin2e61fa62019-03-28 14:10:57 +0000186 },
187 },
188 {
189 // Verify that :__pkg__ allows the module to be referenced from the current directory only.
190 name: ":__pkg__",
191 fs: map[string][]byte{
192 "top/Blueprints": []byte(`
193 mock_library {
194 name: "libexample",
195 visibility: [":__pkg__"],
196 }
197
198 mock_library {
199 name: "libsamepackage",
200 deps: ["libexample"],
201 }`),
202 "top/nested/Blueprints": []byte(`
203 mock_library {
204 name: "libnested",
205 deps: ["libexample"],
206 }`),
Martin Stjernholm8edeb632019-05-21 12:18:38 +0100207 "other/Blueprints": []byte(`
208 mock_library {
209 name: "libother",
210 deps: ["libexample"],
211 }`),
Paul Duffin2e61fa62019-03-28 14:10:57 +0000212 },
213 expectedErrors: []string{
214 `module "libnested" variant "android_common": depends on //top:libexample which is not` +
Martin Stjernholm226b20d2019-05-17 22:42:02 +0100215 ` visible to this module`,
Martin Stjernholm8edeb632019-05-21 12:18:38 +0100216 `module "libother" variant "android_common": depends on //top:libexample which is not` +
Martin Stjernholm226b20d2019-05-17 22:42:02 +0100217 ` visible to this module`,
Paul Duffin2e61fa62019-03-28 14:10:57 +0000218 },
219 },
220 {
221 // Verify that //top/nested allows the module to be referenced from the current directory and
222 // the top/nested directory only, not a subdirectory of top/nested and not peak directory.
223 name: "//top/nested",
224 fs: map[string][]byte{
225 "top/Blueprints": []byte(`
226 mock_library {
227 name: "libexample",
228 visibility: ["//top/nested"],
229 }
230
231 mock_library {
232 name: "libsamepackage",
233 deps: ["libexample"],
234 }`),
235 "top/nested/Blueprints": []byte(`
236 mock_library {
237 name: "libnested",
238 deps: ["libexample"],
239 }`),
240 "top/nested/again/Blueprints": []byte(`
241 mock_library {
242 name: "libnestedagain",
243 deps: ["libexample"],
244 }`),
245 "peak/Blueprints": []byte(`
246 mock_library {
247 name: "libother",
248 deps: ["libexample"],
249 }`),
250 },
251 expectedErrors: []string{
252 `module "libother" variant "android_common": depends on //top:libexample which is not` +
Martin Stjernholm226b20d2019-05-17 22:42:02 +0100253 ` visible to this module`,
Paul Duffin2e61fa62019-03-28 14:10:57 +0000254 `module "libnestedagain" variant "android_common": depends on //top:libexample which is not` +
Martin Stjernholm226b20d2019-05-17 22:42:02 +0100255 ` visible to this module`,
Paul Duffin2e61fa62019-03-28 14:10:57 +0000256 },
257 },
258 {
259 // Verify that :__subpackages__ allows the module to be referenced from the current directory
260 // and sub directories but nowhere else.
261 name: ":__subpackages__",
262 fs: map[string][]byte{
263 "top/Blueprints": []byte(`
264 mock_library {
265 name: "libexample",
266 visibility: [":__subpackages__"],
267 }
268
269 mock_library {
270 name: "libsamepackage",
271 deps: ["libexample"],
272 }`),
273 "top/nested/Blueprints": []byte(`
274 mock_library {
275 name: "libnested",
276 deps: ["libexample"],
277 }`),
278 "peak/other/Blueprints": []byte(`
279 mock_library {
280 name: "libother",
281 deps: ["libexample"],
282 }`),
283 },
284 expectedErrors: []string{
285 `module "libother" variant "android_common": depends on //top:libexample which is not` +
Martin Stjernholm226b20d2019-05-17 22:42:02 +0100286 ` visible to this module`,
Paul Duffin2e61fa62019-03-28 14:10:57 +0000287 },
288 },
289 {
290 // Verify that //top/nested:__subpackages__ allows the module to be referenced from the current
291 // directory and sub directories but nowhere else.
292 name: "//top/nested:__subpackages__",
293 fs: map[string][]byte{
294 "top/Blueprints": []byte(`
295 mock_library {
296 name: "libexample",
297 visibility: ["//top/nested:__subpackages__", "//other"],
298 }
299
300 mock_library {
301 name: "libsamepackage",
302 deps: ["libexample"],
303 }`),
304 "top/nested/Blueprints": []byte(`
305 mock_library {
306 name: "libnested",
307 deps: ["libexample"],
308 }`),
309 "top/other/Blueprints": []byte(`
310 mock_library {
311 name: "libother",
312 deps: ["libexample"],
313 }`),
314 },
315 expectedErrors: []string{
316 `module "libother" variant "android_common": depends on //top:libexample which is not` +
Martin Stjernholm226b20d2019-05-17 22:42:02 +0100317 ` visible to this module`,
Paul Duffin2e61fa62019-03-28 14:10:57 +0000318 },
319 },
320 {
321 // Verify that ["//top/nested", "//peak:__subpackages"] allows the module to be referenced from
322 // the current directory, top/nested and peak and all its subpackages.
323 name: `["//top/nested", "//peak:__subpackages__"]`,
324 fs: map[string][]byte{
325 "top/Blueprints": []byte(`
326 mock_library {
327 name: "libexample",
328 visibility: ["//top/nested", "//peak:__subpackages__"],
329 }
330
331 mock_library {
332 name: "libsamepackage",
333 deps: ["libexample"],
334 }`),
335 "top/nested/Blueprints": []byte(`
336 mock_library {
337 name: "libnested",
338 deps: ["libexample"],
339 }`),
340 "peak/other/Blueprints": []byte(`
341 mock_library {
342 name: "libother",
343 deps: ["libexample"],
344 }`),
345 },
346 },
347 {
348 // Verify that //vendor... cannot be used outside vendor apart from //vendor:__subpackages__
349 name: `//vendor`,
350 fs: map[string][]byte{
351 "top/Blueprints": []byte(`
352 mock_library {
353 name: "libexample",
354 visibility: ["//vendor:__subpackages__"],
355 }
356
357 mock_library {
358 name: "libsamepackage",
359 visibility: ["//vendor/apps/AcmeSettings"],
360 }`),
361 "vendor/Blueprints": []byte(`
362 mock_library {
363 name: "libvendorexample",
364 deps: ["libexample"],
365 visibility: ["//vendor/nested"],
366 }`),
367 "vendor/nested/Blueprints": []byte(`
368 mock_library {
369 name: "libvendornested",
370 deps: ["libexample", "libvendorexample"],
371 }`),
372 },
373 expectedErrors: []string{
Martin Stjernholm226b20d2019-05-17 22:42:02 +0100374 `module "libsamepackage": visibility: "//vendor/apps/AcmeSettings"` +
Paul Duffin2e61fa62019-03-28 14:10:57 +0000375 ` is not allowed. Packages outside //vendor cannot make themselves visible to specific` +
376 ` targets within //vendor, they can only use //vendor:__subpackages__.`,
377 },
378 },
Martin Stjernholm226b20d2019-05-17 22:42:02 +0100379
380 // Defaults propagation tests
381 {
382 // Check that visibility is the union of the defaults modules.
383 name: "defaults union, basic",
384 fs: map[string][]byte{
385 "top/Blueprints": []byte(`
386 mock_defaults {
387 name: "libexample_defaults",
388 visibility: ["//other"],
389 }
390 mock_library {
391 name: "libexample",
392 visibility: ["//top/nested"],
393 defaults: ["libexample_defaults"],
394 }
395 mock_library {
396 name: "libsamepackage",
397 deps: ["libexample"],
398 }`),
399 "top/nested/Blueprints": []byte(`
400 mock_library {
401 name: "libnested",
402 deps: ["libexample"],
403 }`),
404 "other/Blueprints": []byte(`
405 mock_library {
406 name: "libother",
407 deps: ["libexample"],
408 }`),
409 "outsider/Blueprints": []byte(`
410 mock_library {
411 name: "liboutsider",
412 deps: ["libexample"],
413 }`),
414 },
415 expectedErrors: []string{
416 `module "liboutsider" variant "android_common": depends on //top:libexample which is not` +
417 ` visible to this module`,
418 },
419 },
420 {
421 name: "defaults union, multiple defaults",
422 fs: map[string][]byte{
423 "top/Blueprints": []byte(`
424 mock_defaults {
425 name: "libexample_defaults_1",
426 visibility: ["//other"],
427 }
428 mock_defaults {
429 name: "libexample_defaults_2",
430 visibility: ["//top/nested"],
431 }
432 mock_library {
433 name: "libexample",
434 defaults: ["libexample_defaults_1", "libexample_defaults_2"],
435 }
436 mock_library {
437 name: "libsamepackage",
438 deps: ["libexample"],
439 }`),
440 "top/nested/Blueprints": []byte(`
441 mock_library {
442 name: "libnested",
443 deps: ["libexample"],
444 }`),
445 "other/Blueprints": []byte(`
446 mock_library {
447 name: "libother",
448 deps: ["libexample"],
449 }`),
450 "outsider/Blueprints": []byte(`
451 mock_library {
452 name: "liboutsider",
453 deps: ["libexample"],
454 }`),
455 },
456 expectedErrors: []string{
457 `module "liboutsider" variant "android_common": depends on //top:libexample which is not` +
458 ` visible to this module`,
459 },
460 },
461 {
462 name: "//visibility:public mixed with other in defaults",
463 fs: map[string][]byte{
464 "top/Blueprints": []byte(`
465 mock_defaults {
466 name: "libexample_defaults",
467 visibility: ["//visibility:public", "//namespace"],
468 }
469 mock_library {
470 name: "libexample",
471 defaults: ["libexample_defaults"],
472 }`),
473 },
474 expectedErrors: []string{
475 `module "libexample_defaults": visibility: cannot mix "//visibility:public"` +
476 ` with any other visibility rules`,
477 },
478 },
479 {
480 name: "//visibility:public overriding defaults",
481 fs: map[string][]byte{
482 "top/Blueprints": []byte(`
483 mock_defaults {
484 name: "libexample_defaults",
485 visibility: ["//namespace"],
486 }
487 mock_library {
488 name: "libexample",
489 visibility: ["//visibility:public"],
490 defaults: ["libexample_defaults"],
491 }`),
492 "outsider/Blueprints": []byte(`
493 mock_library {
494 name: "liboutsider",
495 deps: ["libexample"],
496 }`),
497 },
Paul Duffin44885e22020-02-19 16:10:09 +0000498 effectiveVisibility: map[qualifiedModuleName][]string{
499 qualifiedModuleName{pkg: "top", name: "libexample"}: {"//visibility:public"},
500 },
Martin Stjernholm226b20d2019-05-17 22:42:02 +0100501 },
502 {
503 name: "//visibility:public mixed with other from different defaults 1",
504 fs: map[string][]byte{
505 "top/Blueprints": []byte(`
506 mock_defaults {
507 name: "libexample_defaults_1",
508 visibility: ["//namespace"],
509 }
510 mock_defaults {
511 name: "libexample_defaults_2",
512 visibility: ["//visibility:public"],
513 }
514 mock_library {
515 name: "libexample",
516 defaults: ["libexample_defaults_1", "libexample_defaults_2"],
517 }`),
518 "outsider/Blueprints": []byte(`
519 mock_library {
520 name: "liboutsider",
521 deps: ["libexample"],
522 }`),
523 },
524 },
525 {
526 name: "//visibility:public mixed with other from different defaults 2",
527 fs: map[string][]byte{
528 "top/Blueprints": []byte(`
529 mock_defaults {
530 name: "libexample_defaults_1",
531 visibility: ["//visibility:public"],
532 }
533 mock_defaults {
534 name: "libexample_defaults_2",
535 visibility: ["//namespace"],
536 }
537 mock_library {
538 name: "libexample",
539 defaults: ["libexample_defaults_1", "libexample_defaults_2"],
540 }`),
541 "outsider/Blueprints": []byte(`
542 mock_library {
543 name: "liboutsider",
544 deps: ["libexample"],
545 }`),
546 },
547 },
548 {
549 name: "//visibility:private in defaults",
550 fs: map[string][]byte{
551 "top/Blueprints": []byte(`
552 mock_defaults {
553 name: "libexample_defaults",
554 visibility: ["//visibility:private"],
555 }
556 mock_library {
557 name: "libexample",
558 defaults: ["libexample_defaults"],
559 }
560 mock_library {
561 name: "libsamepackage",
562 deps: ["libexample"],
563 }`),
564 "top/nested/Blueprints": []byte(`
565 mock_library {
566 name: "libnested",
567 deps: ["libexample"],
568 }`),
569 "other/Blueprints": []byte(`
570 mock_library {
571 name: "libother",
572 deps: ["libexample"],
573 }`),
574 },
575 expectedErrors: []string{
576 `module "libnested" variant "android_common": depends on //top:libexample which is not` +
577 ` visible to this module`,
578 `module "libother" variant "android_common": depends on //top:libexample which is not` +
579 ` visible to this module`,
580 },
581 },
582 {
583 name: "//visibility:private mixed with other in defaults",
584 fs: map[string][]byte{
585 "top/Blueprints": []byte(`
586 mock_defaults {
587 name: "libexample_defaults",
588 visibility: ["//visibility:private", "//namespace"],
589 }
590 mock_library {
591 name: "libexample",
592 defaults: ["libexample_defaults"],
593 }`),
594 },
595 expectedErrors: []string{
596 `module "libexample_defaults": visibility: cannot mix "//visibility:private"` +
597 ` with any other visibility rules`,
598 },
599 },
600 {
601 name: "//visibility:private overriding defaults",
602 fs: map[string][]byte{
603 "top/Blueprints": []byte(`
604 mock_defaults {
605 name: "libexample_defaults",
606 visibility: ["//namespace"],
607 }
608 mock_library {
609 name: "libexample",
610 visibility: ["//visibility:private"],
611 defaults: ["libexample_defaults"],
612 }`),
613 },
614 expectedErrors: []string{
615 `module "libexample": visibility: cannot mix "//visibility:private"` +
616 ` with any other visibility rules`,
617 },
618 },
619 {
620 name: "//visibility:private in defaults overridden",
621 fs: map[string][]byte{
622 "top/Blueprints": []byte(`
623 mock_defaults {
624 name: "libexample_defaults",
625 visibility: ["//visibility:private"],
626 }
627 mock_library {
628 name: "libexample",
629 visibility: ["//namespace"],
630 defaults: ["libexample_defaults"],
631 }`),
632 },
633 expectedErrors: []string{
634 `module "libexample": visibility: cannot mix "//visibility:private"` +
635 ` with any other visibility rules`,
636 },
637 },
638 {
639 name: "//visibility:private mixed with itself",
640 fs: map[string][]byte{
641 "top/Blueprints": []byte(`
642 mock_defaults {
643 name: "libexample_defaults_1",
644 visibility: ["//visibility:private"],
645 }
646 mock_defaults {
647 name: "libexample_defaults_2",
648 visibility: ["//visibility:private"],
649 }
650 mock_library {
651 name: "libexample",
652 visibility: ["//visibility:private"],
653 defaults: ["libexample_defaults_1", "libexample_defaults_2"],
654 }`),
655 "outsider/Blueprints": []byte(`
656 mock_library {
657 name: "liboutsider",
658 deps: ["libexample"],
659 }`),
660 },
661 expectedErrors: []string{
662 `module "liboutsider" variant "android_common": depends on //top:libexample which is not` +
663 ` visible to this module`,
664 },
665 },
Paul Duffin95d53b52019-07-24 13:45:05 +0100666
667 // Defaults module's defaults_visibility tests
668 {
669 name: "defaults_visibility invalid",
670 fs: map[string][]byte{
671 "top/Blueprints": []byte(`
672 mock_defaults {
673 name: "top_defaults",
674 defaults_visibility: ["//visibility:invalid"],
675 }`),
676 },
677 expectedErrors: []string{
678 `defaults_visibility: unrecognized visibility rule "//visibility:invalid"`,
679 },
680 },
681 {
682 name: "defaults_visibility overrides package default",
683 fs: map[string][]byte{
684 "top/Blueprints": []byte(`
685 package {
686 default_visibility: ["//visibility:private"],
687 }
688 mock_defaults {
689 name: "top_defaults",
690 defaults_visibility: ["//visibility:public"],
691 }`),
692 "outsider/Blueprints": []byte(`
693 mock_library {
694 name: "liboutsider",
695 defaults: ["top_defaults"],
696 }`),
697 },
698 },
699
Paul Duffine2453c72019-05-31 14:00:04 +0100700 // Package default_visibility tests
701 {
702 name: "package default_visibility property is checked",
703 fs: map[string][]byte{
704 "top/Blueprints": []byte(`
705 package {
706 default_visibility: ["//visibility:invalid"],
707 }`),
708 },
709 expectedErrors: []string{`default_visibility: unrecognized visibility rule "//visibility:invalid"`},
710 },
711 {
712 // This test relies on the default visibility being legacy_public.
713 name: "package default_visibility property used when no visibility specified",
714 fs: map[string][]byte{
715 "top/Blueprints": []byte(`
716 package {
717 default_visibility: ["//visibility:private"],
718 }
719
720 mock_library {
721 name: "libexample",
722 }`),
723 "outsider/Blueprints": []byte(`
724 mock_library {
725 name: "liboutsider",
726 deps: ["libexample"],
727 }`),
728 },
729 expectedErrors: []string{
730 `module "liboutsider" variant "android_common": depends on //top:libexample which is not` +
731 ` visible to this module`,
732 },
733 },
734 {
735 name: "package default_visibility public does not override visibility private",
736 fs: map[string][]byte{
737 "top/Blueprints": []byte(`
738 package {
739 default_visibility: ["//visibility:public"],
740 }
741
742 mock_library {
743 name: "libexample",
744 visibility: ["//visibility:private"],
745 }`),
746 "outsider/Blueprints": []byte(`
747 mock_library {
748 name: "liboutsider",
749 deps: ["libexample"],
750 }`),
751 },
752 expectedErrors: []string{
753 `module "liboutsider" variant "android_common": depends on //top:libexample which is not` +
754 ` visible to this module`,
755 },
756 },
757 {
758 name: "package default_visibility private does not override visibility public",
759 fs: map[string][]byte{
760 "top/Blueprints": []byte(`
761 package {
762 default_visibility: ["//visibility:private"],
763 }
764
765 mock_library {
766 name: "libexample",
767 visibility: ["//visibility:public"],
768 }`),
769 "outsider/Blueprints": []byte(`
770 mock_library {
771 name: "liboutsider",
772 deps: ["libexample"],
773 }`),
774 },
775 },
776 {
777 name: "package default_visibility :__subpackages__",
778 fs: map[string][]byte{
779 "top/Blueprints": []byte(`
780 package {
781 default_visibility: [":__subpackages__"],
782 }
783
784 mock_library {
785 name: "libexample",
786 }`),
787 "top/nested/Blueprints": []byte(`
788 mock_library {
789 name: "libnested",
790 deps: ["libexample"],
791 }`),
792 "outsider/Blueprints": []byte(`
793 mock_library {
794 name: "liboutsider",
795 deps: ["libexample"],
796 }`),
797 },
798 expectedErrors: []string{
799 `module "liboutsider" variant "android_common": depends on //top:libexample which is not` +
800 ` visible to this module`,
801 },
802 },
Paul Duffine484f472019-06-20 16:38:08 +0100803 {
804 name: "package default_visibility inherited to subpackages",
805 fs: map[string][]byte{
806 "top/Blueprints": []byte(`
807 package {
808 default_visibility: ["//outsider"],
809 }
810
811 mock_library {
812 name: "libexample",
813 visibility: [":__subpackages__"],
814 }`),
815 "top/nested/Blueprints": []byte(`
816 mock_library {
817 name: "libnested",
818 deps: ["libexample"],
819 }`),
820 "outsider/Blueprints": []byte(`
821 mock_library {
822 name: "liboutsider",
823 deps: ["libexample", "libnested"],
824 }`),
825 },
826 expectedErrors: []string{
827 `module "liboutsider" variant "android_common": depends on //top:libexample which is not` +
828 ` visible to this module`,
829 },
830 },
831 {
832 name: "package default_visibility inherited to subpackages",
833 fs: map[string][]byte{
834 "top/Blueprints": []byte(`
835 package {
836 default_visibility: ["//visibility:private"],
837 }`),
838 "top/nested/Blueprints": []byte(`
839 package {
840 default_visibility: ["//outsider"],
841 }
842
843 mock_library {
844 name: "libnested",
845 }`),
846 "top/other/Blueprints": []byte(`
847 mock_library {
848 name: "libother",
849 }`),
850 "outsider/Blueprints": []byte(`
851 mock_library {
852 name: "liboutsider",
853 deps: ["libother", "libnested"],
854 }`),
855 },
856 expectedErrors: []string{
857 `module "liboutsider" variant "android_common": depends on //top/other:libother which is` +
858 ` not visible to this module`,
859 },
860 },
Paul Duffin78ac5b92020-01-14 12:42:08 +0000861 {
862 name: "verify that prebuilt dependencies are ignored for visibility reasons (not preferred)",
863 fs: map[string][]byte{
864 "prebuilts/Blueprints": []byte(`
865 prebuilt {
866 name: "module",
867 visibility: ["//top/other"],
868 }`),
869 "top/sources/source_file": nil,
870 "top/sources/Blueprints": []byte(`
871 source {
872 name: "module",
873 visibility: ["//top/other"],
874 }`),
875 "top/other/source_file": nil,
876 "top/other/Blueprints": []byte(`
877 source {
878 name: "other",
879 deps: [":module"],
880 }`),
881 },
882 },
883 {
884 name: "verify that prebuilt dependencies are ignored for visibility reasons (preferred)",
885 fs: map[string][]byte{
886 "prebuilts/Blueprints": []byte(`
887 prebuilt {
888 name: "module",
889 visibility: ["//top/other"],
890 prefer: true,
891 }`),
892 "top/sources/source_file": nil,
893 "top/sources/Blueprints": []byte(`
894 source {
895 name: "module",
896 visibility: ["//top/other"],
897 }`),
898 "top/other/source_file": nil,
899 "top/other/Blueprints": []byte(`
900 source {
901 name: "other",
902 deps: [":module"],
903 }`),
904 },
905 },
Paul Duffinafa9fa12020-04-29 16:47:28 +0100906 {
907 name: "ensure visibility properties are checked for correctness",
908 fs: map[string][]byte{
909 "top/Blueprints": []byte(`
910 mock_parent {
911 name: "parent",
912 visibility: ["//top/nested"],
913 child: {
914 name: "libchild",
915 visibility: ["top/other"],
916 },
917 }`),
918 },
919 expectedErrors: []string{
920 `module "parent": child.visibility: invalid visibility pattern "top/other"`,
921 },
922 },
923 {
924 name: "invalid visibility added to child detected during gather phase",
925 fs: map[string][]byte{
926 "top/Blueprints": []byte(`
927 mock_parent {
928 name: "parent",
929 visibility: ["//top/nested"],
930 child: {
931 name: "libchild",
932 invalid_visibility: ["top/other"],
933 },
934 }`),
935 },
936 expectedErrors: []string{
937 // That this error is reported against the child not the parent shows it was
938 // not being detected in the parent which is correct as invalid_visibility is
939 // purposely not added to the list of visibility properties to check, and was
940 // in fact detected in the child in the gather phase. Contrast this error message
941 // with the preceding one.
942 `module "libchild" \(created by module "parent"\): visibility: invalid visibility pattern "top/other"`,
943 },
944 },
945 {
946 name: "automatic visibility inheritance enabled",
947 fs: map[string][]byte{
948 "top/Blueprints": []byte(`
949 mock_parent {
950 name: "parent",
951 visibility: ["//top/nested"],
952 child: {
953 name: "libchild",
954 visibility: ["//top/other"],
955 },
956 }`),
957 "top/nested/Blueprints": []byte(`
958 mock_library {
959 name: "libnested",
960 deps: ["libchild"],
961 }`),
962 "top/other/Blueprints": []byte(`
963 mock_library {
964 name: "libother",
965 deps: ["libchild"],
966 }`),
967 },
968 },
Paul Duffin2e61fa62019-03-28 14:10:57 +0000969}
970
971func TestVisibility(t *testing.T) {
Paul Duffin2e61fa62019-03-28 14:10:57 +0000972 for _, test := range visibilityTests {
973 t.Run(test.name, func(t *testing.T) {
Paul Duffin44885e22020-02-19 16:10:09 +0000974 ctx, errs := testVisibility(buildDir, test.fs)
Paul Duffin2e61fa62019-03-28 14:10:57 +0000975
Paul Duffin91e38192019-08-05 15:07:57 +0100976 CheckErrorsAgainstExpectations(t, errs, test.expectedErrors)
Paul Duffin44885e22020-02-19 16:10:09 +0000977
978 if test.effectiveVisibility != nil {
979 checkEffectiveVisibility(t, ctx, test.effectiveVisibility)
980 }
Paul Duffin2e61fa62019-03-28 14:10:57 +0000981 })
982 }
983}
984
Paul Duffin44885e22020-02-19 16:10:09 +0000985func checkEffectiveVisibility(t *testing.T, ctx *TestContext, effectiveVisibility map[qualifiedModuleName][]string) {
986 for moduleName, expectedRules := range effectiveVisibility {
987 rule := effectiveVisibilityRules(ctx.config, moduleName)
988 stringRules := rule.Strings()
989 if !reflect.DeepEqual(expectedRules, stringRules) {
990 t.Errorf("effective rules mismatch: expected %q, found %q", expectedRules, stringRules)
991 }
992 }
993}
994
Paul Duffin2e61fa62019-03-28 14:10:57 +0000995func testVisibility(buildDir string, fs map[string][]byte) (*TestContext, []error) {
996
997 // Create a new config per test as visibility information is stored in the config.
Colin Cross98be1bb2019-12-13 20:41:13 -0800998 config := TestArchConfig(buildDir, nil, "", fs)
Paul Duffin2e61fa62019-03-28 14:10:57 +0000999
1000 ctx := NewTestArchContext()
Colin Cross4b49b762019-11-22 15:25:03 -08001001 ctx.RegisterModuleType("mock_library", newMockLibraryModule)
Paul Duffinafa9fa12020-04-29 16:47:28 +01001002 ctx.RegisterModuleType("mock_parent", newMockParentFactory)
Colin Cross4b49b762019-11-22 15:25:03 -08001003 ctx.RegisterModuleType("mock_defaults", defaultsFactory)
Paul Duffin78ac5b92020-01-14 12:42:08 +00001004
1005 // Order of the following method calls is significant.
Paul Duffinc1327422020-01-14 12:15:29 +00001006 RegisterPackageBuildComponents(ctx)
Paul Duffin78ac5b92020-01-14 12:42:08 +00001007 registerTestPrebuiltBuildComponents(ctx)
Paul Duffin593b3c92019-12-05 14:31:48 +00001008 ctx.PreArchMutators(RegisterVisibilityRuleChecker)
Martin Stjernholm226b20d2019-05-17 22:42:02 +01001009 ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
Paul Duffin593b3c92019-12-05 14:31:48 +00001010 ctx.PreArchMutators(RegisterVisibilityRuleGatherer)
1011 ctx.PostDepsMutators(RegisterVisibilityRuleEnforcer)
Colin Cross98be1bb2019-12-13 20:41:13 -08001012 ctx.Register(config)
Paul Duffin2e61fa62019-03-28 14:10:57 +00001013
1014 _, errs := ctx.ParseBlueprintsFiles(".")
1015 if len(errs) > 0 {
1016 return ctx, errs
1017 }
1018
1019 _, errs = ctx.PrepareBuildActions(config)
1020 return ctx, errs
1021}
1022
1023type mockLibraryProperties struct {
1024 Deps []string
1025}
1026
1027type mockLibraryModule struct {
1028 ModuleBase
Martin Stjernholm226b20d2019-05-17 22:42:02 +01001029 DefaultableModuleBase
Paul Duffin2e61fa62019-03-28 14:10:57 +00001030 properties mockLibraryProperties
1031}
1032
1033func newMockLibraryModule() Module {
1034 m := &mockLibraryModule{}
1035 m.AddProperties(&m.properties)
1036 InitAndroidArchModule(m, HostAndDeviceSupported, MultilibCommon)
Martin Stjernholm226b20d2019-05-17 22:42:02 +01001037 InitDefaultableModule(m)
Paul Duffin2e61fa62019-03-28 14:10:57 +00001038 return m
1039}
1040
1041type dependencyTag struct {
1042 blueprint.BaseDependencyTag
1043 name string
1044}
1045
1046func (j *mockLibraryModule) DepsMutator(ctx BottomUpMutatorContext) {
1047 ctx.AddVariationDependencies(nil, dependencyTag{name: "mockdeps"}, j.properties.Deps...)
1048}
1049
1050func (p *mockLibraryModule) GenerateAndroidBuildActions(ModuleContext) {
1051}
Martin Stjernholm226b20d2019-05-17 22:42:02 +01001052
1053type mockDefaults struct {
1054 ModuleBase
1055 DefaultsModuleBase
1056}
1057
1058func defaultsFactory() Module {
1059 m := &mockDefaults{}
1060 InitDefaultsModule(m)
1061 return m
1062}
Paul Duffinafa9fa12020-04-29 16:47:28 +01001063
1064type mockParentProperties struct {
1065 Child struct {
1066 Name *string
1067
1068 // Visibility to pass to the child module.
1069 Visibility []string
1070
1071 // Purposely not validated visibility to pass to the child.
1072 Invalid_visibility []string
1073 }
1074}
1075
1076type mockParent struct {
1077 ModuleBase
1078 DefaultableModuleBase
1079 properties mockParentProperties
1080}
1081
1082func (p *mockParent) GenerateAndroidBuildActions(ModuleContext) {
1083}
1084
1085func newMockParentFactory() Module {
1086 m := &mockParent{}
1087 m.AddProperties(&m.properties)
1088 InitAndroidArchModule(m, HostAndDeviceSupported, MultilibCommon)
1089 InitDefaultableModule(m)
1090 AddVisibilityProperty(m, "child.visibility", &m.properties.Child.Visibility)
1091
1092 m.SetDefaultableHook(func(ctx DefaultableHookContext) {
1093 visibility := m.properties.Child.Visibility
1094 visibility = append(visibility, m.properties.Child.Invalid_visibility...)
1095 ctx.CreateModule(newMockLibraryModule, &struct {
1096 Name *string
1097 Visibility []string
1098 }{m.properties.Child.Name, visibility})
1099 })
1100 return m
1101}