blob: ca09345578d429ec49be4896c771adc14cd2c781 [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 {
Paul Duffin51084ff2020-05-05 19:19:22 +0100639 name: "//visibility:private override //visibility:public",
640 fs: map[string][]byte{
641 "top/Blueprints": []byte(`
642 mock_defaults {
643 name: "libexample_defaults",
644 visibility: ["//visibility:public"],
645 }
646 mock_library {
647 name: "libexample",
648 visibility: ["//visibility:private"],
649 defaults: ["libexample_defaults"],
650 }`),
651 },
652 expectedErrors: []string{
653 `module "libexample": visibility: cannot mix "//visibility:private" with any other visibility rules`,
654 },
655 },
656 {
657 name: "//visibility:public override //visibility:private",
658 fs: map[string][]byte{
659 "top/Blueprints": []byte(`
660 mock_defaults {
661 name: "libexample_defaults",
662 visibility: ["//visibility:private"],
663 }
664 mock_library {
665 name: "libexample",
666 visibility: ["//visibility:public"],
667 defaults: ["libexample_defaults"],
668 }`),
669 },
670 expectedErrors: []string{
671 `module "libexample": visibility: cannot mix "//visibility:private" with any other visibility rules`,
672 },
673 },
674 {
675 name: "//visibility:override must be first in the list",
676 fs: map[string][]byte{
677 "top/Blueprints": []byte(`
678 mock_library {
679 name: "libexample",
680 visibility: ["//other", "//visibility:override", "//namespace"],
681 }`),
682 },
683 expectedErrors: []string{
684 `module "libexample": visibility: "//visibility:override" may only be used at the start of the visibility rules`,
685 },
686 },
687 {
688 name: "//visibility:override discards //visibility:private",
689 fs: map[string][]byte{
690 "top/Blueprints": []byte(`
691 mock_defaults {
692 name: "libexample_defaults",
693 visibility: ["//visibility:private"],
694 }
695 mock_library {
696 name: "libexample",
697 // Make this visibility to //other but not //visibility:private
698 visibility: ["//visibility:override", "//other"],
699 defaults: ["libexample_defaults"],
700 }`),
701 "other/Blueprints": []byte(`
702 mock_library {
703 name: "libother",
704 deps: ["libexample"],
705 }`),
706 },
707 },
708 {
709 name: "//visibility:override discards //visibility:public",
710 fs: map[string][]byte{
711 "top/Blueprints": []byte(`
712 mock_defaults {
713 name: "libexample_defaults",
714 visibility: ["//visibility:public"],
715 }
716 mock_library {
717 name: "libexample",
718 // Make this visibility to //other but not //visibility:public
719 visibility: ["//visibility:override", "//other"],
720 defaults: ["libexample_defaults"],
721 }`),
722 "other/Blueprints": []byte(`
723 mock_library {
724 name: "libother",
725 deps: ["libexample"],
726 }`),
727 "namespace/Blueprints": []byte(`
728 mock_library {
729 name: "libnamespace",
730 deps: ["libexample"],
731 }`),
732 },
733 expectedErrors: []string{
734 `module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module`,
735 },
736 },
737 {
738 name: "//visibility:override discards defaults supplied rules",
739 fs: map[string][]byte{
740 "top/Blueprints": []byte(`
741 mock_defaults {
742 name: "libexample_defaults",
743 visibility: ["//namespace"],
744 }
745 mock_library {
746 name: "libexample",
747 // Make this visibility to //other but not //namespace
748 visibility: ["//visibility:override", "//other"],
749 defaults: ["libexample_defaults"],
750 }`),
751 "other/Blueprints": []byte(`
752 mock_library {
753 name: "libother",
754 deps: ["libexample"],
755 }`),
756 "namespace/Blueprints": []byte(`
757 mock_library {
758 name: "libnamespace",
759 deps: ["libexample"],
760 }`),
761 },
762 expectedErrors: []string{
763 `module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module`,
764 },
765 },
766 {
767 name: "//visibility:override can override //visibility:public with //visibility:private",
768 fs: map[string][]byte{
769 "top/Blueprints": []byte(`
770 mock_defaults {
771 name: "libexample_defaults",
772 visibility: ["//visibility:public"],
773 }
774 mock_library {
775 name: "libexample",
776 visibility: ["//visibility:override", "//visibility:private"],
777 defaults: ["libexample_defaults"],
778 }`),
779 "namespace/Blueprints": []byte(`
780 mock_library {
781 name: "libnamespace",
782 deps: ["libexample"],
783 }`),
784 },
785 expectedErrors: []string{
786 `module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module`,
787 },
788 },
789 {
790 name: "//visibility:override can override //visibility:private with //visibility:public",
791 fs: map[string][]byte{
792 "top/Blueprints": []byte(`
793 mock_defaults {
794 name: "libexample_defaults",
795 visibility: ["//visibility:private"],
796 }
797 mock_library {
798 name: "libexample",
799 visibility: ["//visibility:override", "//visibility:public"],
800 defaults: ["libexample_defaults"],
801 }`),
802 "namespace/Blueprints": []byte(`
803 mock_library {
804 name: "libnamespace",
805 deps: ["libexample"],
806 }`),
807 },
808 },
809 {
Martin Stjernholm226b20d2019-05-17 22:42:02 +0100810 name: "//visibility:private mixed with itself",
811 fs: map[string][]byte{
812 "top/Blueprints": []byte(`
813 mock_defaults {
814 name: "libexample_defaults_1",
815 visibility: ["//visibility:private"],
816 }
817 mock_defaults {
818 name: "libexample_defaults_2",
819 visibility: ["//visibility:private"],
820 }
821 mock_library {
822 name: "libexample",
823 visibility: ["//visibility:private"],
824 defaults: ["libexample_defaults_1", "libexample_defaults_2"],
825 }`),
826 "outsider/Blueprints": []byte(`
827 mock_library {
828 name: "liboutsider",
829 deps: ["libexample"],
830 }`),
831 },
832 expectedErrors: []string{
833 `module "liboutsider" variant "android_common": depends on //top:libexample which is not` +
834 ` visible to this module`,
835 },
836 },
Paul Duffin95d53b52019-07-24 13:45:05 +0100837
838 // Defaults module's defaults_visibility tests
839 {
840 name: "defaults_visibility invalid",
841 fs: map[string][]byte{
842 "top/Blueprints": []byte(`
843 mock_defaults {
844 name: "top_defaults",
845 defaults_visibility: ["//visibility:invalid"],
846 }`),
847 },
848 expectedErrors: []string{
849 `defaults_visibility: unrecognized visibility rule "//visibility:invalid"`,
850 },
851 },
852 {
853 name: "defaults_visibility overrides package default",
854 fs: map[string][]byte{
855 "top/Blueprints": []byte(`
856 package {
857 default_visibility: ["//visibility:private"],
858 }
859 mock_defaults {
860 name: "top_defaults",
861 defaults_visibility: ["//visibility:public"],
862 }`),
863 "outsider/Blueprints": []byte(`
864 mock_library {
865 name: "liboutsider",
866 defaults: ["top_defaults"],
867 }`),
868 },
869 },
870
Paul Duffine2453c72019-05-31 14:00:04 +0100871 // Package default_visibility tests
872 {
873 name: "package default_visibility property is checked",
874 fs: map[string][]byte{
875 "top/Blueprints": []byte(`
876 package {
877 default_visibility: ["//visibility:invalid"],
878 }`),
879 },
880 expectedErrors: []string{`default_visibility: unrecognized visibility rule "//visibility:invalid"`},
881 },
882 {
883 // This test relies on the default visibility being legacy_public.
884 name: "package default_visibility property used when no visibility specified",
885 fs: map[string][]byte{
886 "top/Blueprints": []byte(`
887 package {
888 default_visibility: ["//visibility:private"],
889 }
890
891 mock_library {
892 name: "libexample",
893 }`),
894 "outsider/Blueprints": []byte(`
895 mock_library {
896 name: "liboutsider",
897 deps: ["libexample"],
898 }`),
899 },
900 expectedErrors: []string{
901 `module "liboutsider" variant "android_common": depends on //top:libexample which is not` +
902 ` visible to this module`,
903 },
904 },
905 {
906 name: "package default_visibility public does not override visibility private",
907 fs: map[string][]byte{
908 "top/Blueprints": []byte(`
909 package {
910 default_visibility: ["//visibility:public"],
911 }
912
913 mock_library {
914 name: "libexample",
915 visibility: ["//visibility:private"],
916 }`),
917 "outsider/Blueprints": []byte(`
918 mock_library {
919 name: "liboutsider",
920 deps: ["libexample"],
921 }`),
922 },
923 expectedErrors: []string{
924 `module "liboutsider" variant "android_common": depends on //top:libexample which is not` +
925 ` visible to this module`,
926 },
927 },
928 {
929 name: "package default_visibility private does not override visibility public",
930 fs: map[string][]byte{
931 "top/Blueprints": []byte(`
932 package {
933 default_visibility: ["//visibility:private"],
934 }
935
936 mock_library {
937 name: "libexample",
938 visibility: ["//visibility:public"],
939 }`),
940 "outsider/Blueprints": []byte(`
941 mock_library {
942 name: "liboutsider",
943 deps: ["libexample"],
944 }`),
945 },
946 },
947 {
948 name: "package default_visibility :__subpackages__",
949 fs: map[string][]byte{
950 "top/Blueprints": []byte(`
951 package {
952 default_visibility: [":__subpackages__"],
953 }
954
955 mock_library {
956 name: "libexample",
957 }`),
958 "top/nested/Blueprints": []byte(`
959 mock_library {
960 name: "libnested",
961 deps: ["libexample"],
962 }`),
963 "outsider/Blueprints": []byte(`
964 mock_library {
965 name: "liboutsider",
966 deps: ["libexample"],
967 }`),
968 },
969 expectedErrors: []string{
970 `module "liboutsider" variant "android_common": depends on //top:libexample which is not` +
971 ` visible to this module`,
972 },
973 },
Paul Duffine484f472019-06-20 16:38:08 +0100974 {
975 name: "package default_visibility inherited to subpackages",
976 fs: map[string][]byte{
977 "top/Blueprints": []byte(`
978 package {
979 default_visibility: ["//outsider"],
980 }
981
982 mock_library {
983 name: "libexample",
984 visibility: [":__subpackages__"],
985 }`),
986 "top/nested/Blueprints": []byte(`
987 mock_library {
988 name: "libnested",
989 deps: ["libexample"],
990 }`),
991 "outsider/Blueprints": []byte(`
992 mock_library {
993 name: "liboutsider",
994 deps: ["libexample", "libnested"],
995 }`),
996 },
997 expectedErrors: []string{
998 `module "liboutsider" variant "android_common": depends on //top:libexample which is not` +
999 ` visible to this module`,
1000 },
1001 },
1002 {
1003 name: "package default_visibility inherited to subpackages",
1004 fs: map[string][]byte{
1005 "top/Blueprints": []byte(`
1006 package {
1007 default_visibility: ["//visibility:private"],
1008 }`),
1009 "top/nested/Blueprints": []byte(`
1010 package {
1011 default_visibility: ["//outsider"],
1012 }
1013
1014 mock_library {
1015 name: "libnested",
1016 }`),
1017 "top/other/Blueprints": []byte(`
1018 mock_library {
1019 name: "libother",
1020 }`),
1021 "outsider/Blueprints": []byte(`
1022 mock_library {
1023 name: "liboutsider",
1024 deps: ["libother", "libnested"],
1025 }`),
1026 },
1027 expectedErrors: []string{
1028 `module "liboutsider" variant "android_common": depends on //top/other:libother which is` +
1029 ` not visible to this module`,
1030 },
1031 },
Paul Duffin78ac5b92020-01-14 12:42:08 +00001032 {
1033 name: "verify that prebuilt dependencies are ignored for visibility reasons (not preferred)",
1034 fs: map[string][]byte{
1035 "prebuilts/Blueprints": []byte(`
1036 prebuilt {
1037 name: "module",
1038 visibility: ["//top/other"],
1039 }`),
1040 "top/sources/source_file": nil,
1041 "top/sources/Blueprints": []byte(`
1042 source {
1043 name: "module",
1044 visibility: ["//top/other"],
1045 }`),
1046 "top/other/source_file": nil,
1047 "top/other/Blueprints": []byte(`
1048 source {
1049 name: "other",
1050 deps: [":module"],
1051 }`),
1052 },
1053 },
1054 {
1055 name: "verify that prebuilt dependencies are ignored for visibility reasons (preferred)",
1056 fs: map[string][]byte{
1057 "prebuilts/Blueprints": []byte(`
1058 prebuilt {
1059 name: "module",
1060 visibility: ["//top/other"],
1061 prefer: true,
1062 }`),
1063 "top/sources/source_file": nil,
1064 "top/sources/Blueprints": []byte(`
1065 source {
1066 name: "module",
1067 visibility: ["//top/other"],
1068 }`),
1069 "top/other/source_file": nil,
1070 "top/other/Blueprints": []byte(`
1071 source {
1072 name: "other",
1073 deps: [":module"],
1074 }`),
1075 },
1076 },
Paul Duffinafa9fa12020-04-29 16:47:28 +01001077 {
1078 name: "ensure visibility properties are checked for correctness",
1079 fs: map[string][]byte{
1080 "top/Blueprints": []byte(`
1081 mock_parent {
1082 name: "parent",
1083 visibility: ["//top/nested"],
1084 child: {
1085 name: "libchild",
1086 visibility: ["top/other"],
1087 },
1088 }`),
1089 },
1090 expectedErrors: []string{
1091 `module "parent": child.visibility: invalid visibility pattern "top/other"`,
1092 },
1093 },
1094 {
1095 name: "invalid visibility added to child detected during gather phase",
1096 fs: map[string][]byte{
1097 "top/Blueprints": []byte(`
1098 mock_parent {
1099 name: "parent",
1100 visibility: ["//top/nested"],
1101 child: {
1102 name: "libchild",
1103 invalid_visibility: ["top/other"],
1104 },
1105 }`),
1106 },
1107 expectedErrors: []string{
1108 // That this error is reported against the child not the parent shows it was
1109 // not being detected in the parent which is correct as invalid_visibility is
1110 // purposely not added to the list of visibility properties to check, and was
1111 // in fact detected in the child in the gather phase. Contrast this error message
1112 // with the preceding one.
1113 `module "libchild" \(created by module "parent"\): visibility: invalid visibility pattern "top/other"`,
1114 },
1115 },
1116 {
1117 name: "automatic visibility inheritance enabled",
1118 fs: map[string][]byte{
1119 "top/Blueprints": []byte(`
1120 mock_parent {
1121 name: "parent",
1122 visibility: ["//top/nested"],
1123 child: {
1124 name: "libchild",
1125 visibility: ["//top/other"],
1126 },
1127 }`),
1128 "top/nested/Blueprints": []byte(`
1129 mock_library {
1130 name: "libnested",
1131 deps: ["libchild"],
1132 }`),
1133 "top/other/Blueprints": []byte(`
1134 mock_library {
1135 name: "libother",
1136 deps: ["libchild"],
1137 }`),
1138 },
1139 },
Paul Duffin2e61fa62019-03-28 14:10:57 +00001140}
1141
1142func TestVisibility(t *testing.T) {
Paul Duffin2e61fa62019-03-28 14:10:57 +00001143 for _, test := range visibilityTests {
1144 t.Run(test.name, func(t *testing.T) {
Paul Duffin44885e22020-02-19 16:10:09 +00001145 ctx, errs := testVisibility(buildDir, test.fs)
Paul Duffin2e61fa62019-03-28 14:10:57 +00001146
Paul Duffin91e38192019-08-05 15:07:57 +01001147 CheckErrorsAgainstExpectations(t, errs, test.expectedErrors)
Paul Duffin44885e22020-02-19 16:10:09 +00001148
1149 if test.effectiveVisibility != nil {
1150 checkEffectiveVisibility(t, ctx, test.effectiveVisibility)
1151 }
Paul Duffin2e61fa62019-03-28 14:10:57 +00001152 })
1153 }
1154}
1155
Paul Duffin44885e22020-02-19 16:10:09 +00001156func checkEffectiveVisibility(t *testing.T, ctx *TestContext, effectiveVisibility map[qualifiedModuleName][]string) {
1157 for moduleName, expectedRules := range effectiveVisibility {
1158 rule := effectiveVisibilityRules(ctx.config, moduleName)
1159 stringRules := rule.Strings()
1160 if !reflect.DeepEqual(expectedRules, stringRules) {
1161 t.Errorf("effective rules mismatch: expected %q, found %q", expectedRules, stringRules)
1162 }
1163 }
1164}
1165
Paul Duffin2e61fa62019-03-28 14:10:57 +00001166func testVisibility(buildDir string, fs map[string][]byte) (*TestContext, []error) {
1167
1168 // Create a new config per test as visibility information is stored in the config.
Colin Cross98be1bb2019-12-13 20:41:13 -08001169 config := TestArchConfig(buildDir, nil, "", fs)
Paul Duffin2e61fa62019-03-28 14:10:57 +00001170
1171 ctx := NewTestArchContext()
Colin Cross4b49b762019-11-22 15:25:03 -08001172 ctx.RegisterModuleType("mock_library", newMockLibraryModule)
Paul Duffinafa9fa12020-04-29 16:47:28 +01001173 ctx.RegisterModuleType("mock_parent", newMockParentFactory)
Colin Cross4b49b762019-11-22 15:25:03 -08001174 ctx.RegisterModuleType("mock_defaults", defaultsFactory)
Paul Duffin78ac5b92020-01-14 12:42:08 +00001175
1176 // Order of the following method calls is significant.
Paul Duffinc1327422020-01-14 12:15:29 +00001177 RegisterPackageBuildComponents(ctx)
Paul Duffin78ac5b92020-01-14 12:42:08 +00001178 registerTestPrebuiltBuildComponents(ctx)
Paul Duffin593b3c92019-12-05 14:31:48 +00001179 ctx.PreArchMutators(RegisterVisibilityRuleChecker)
Martin Stjernholm226b20d2019-05-17 22:42:02 +01001180 ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
Paul Duffin593b3c92019-12-05 14:31:48 +00001181 ctx.PreArchMutators(RegisterVisibilityRuleGatherer)
1182 ctx.PostDepsMutators(RegisterVisibilityRuleEnforcer)
Colin Cross98be1bb2019-12-13 20:41:13 -08001183 ctx.Register(config)
Paul Duffin2e61fa62019-03-28 14:10:57 +00001184
1185 _, errs := ctx.ParseBlueprintsFiles(".")
1186 if len(errs) > 0 {
1187 return ctx, errs
1188 }
1189
1190 _, errs = ctx.PrepareBuildActions(config)
1191 return ctx, errs
1192}
1193
1194type mockLibraryProperties struct {
1195 Deps []string
1196}
1197
1198type mockLibraryModule struct {
1199 ModuleBase
Martin Stjernholm226b20d2019-05-17 22:42:02 +01001200 DefaultableModuleBase
Paul Duffin2e61fa62019-03-28 14:10:57 +00001201 properties mockLibraryProperties
1202}
1203
1204func newMockLibraryModule() Module {
1205 m := &mockLibraryModule{}
1206 m.AddProperties(&m.properties)
1207 InitAndroidArchModule(m, HostAndDeviceSupported, MultilibCommon)
Martin Stjernholm226b20d2019-05-17 22:42:02 +01001208 InitDefaultableModule(m)
Paul Duffin2e61fa62019-03-28 14:10:57 +00001209 return m
1210}
1211
1212type dependencyTag struct {
1213 blueprint.BaseDependencyTag
1214 name string
1215}
1216
1217func (j *mockLibraryModule) DepsMutator(ctx BottomUpMutatorContext) {
1218 ctx.AddVariationDependencies(nil, dependencyTag{name: "mockdeps"}, j.properties.Deps...)
1219}
1220
1221func (p *mockLibraryModule) GenerateAndroidBuildActions(ModuleContext) {
1222}
Martin Stjernholm226b20d2019-05-17 22:42:02 +01001223
1224type mockDefaults struct {
1225 ModuleBase
1226 DefaultsModuleBase
1227}
1228
1229func defaultsFactory() Module {
1230 m := &mockDefaults{}
1231 InitDefaultsModule(m)
1232 return m
1233}
Paul Duffinafa9fa12020-04-29 16:47:28 +01001234
1235type mockParentProperties struct {
1236 Child struct {
1237 Name *string
1238
1239 // Visibility to pass to the child module.
1240 Visibility []string
1241
1242 // Purposely not validated visibility to pass to the child.
1243 Invalid_visibility []string
1244 }
1245}
1246
1247type mockParent struct {
1248 ModuleBase
1249 DefaultableModuleBase
1250 properties mockParentProperties
1251}
1252
1253func (p *mockParent) GenerateAndroidBuildActions(ModuleContext) {
1254}
1255
1256func newMockParentFactory() Module {
1257 m := &mockParent{}
1258 m.AddProperties(&m.properties)
1259 InitAndroidArchModule(m, HostAndDeviceSupported, MultilibCommon)
1260 InitDefaultableModule(m)
1261 AddVisibilityProperty(m, "child.visibility", &m.properties.Child.Visibility)
1262
1263 m.SetDefaultableHook(func(ctx DefaultableHookContext) {
1264 visibility := m.properties.Child.Visibility
1265 visibility = append(visibility, m.properties.Child.Invalid_visibility...)
1266 ctx.CreateModule(newMockLibraryModule, &struct {
1267 Name *string
1268 Visibility []string
1269 }{m.properties.Child.Name, visibility})
1270 })
1271 return m
1272}