• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (C) 2022 The Android Open Source Project
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
15load("@bazel_skylib//lib:new_sets.bzl", "sets")
16load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
17load("@soong_injection//apex_toolchain:constants.bzl", "default_manifest_version")
18load("//build/bazel/platforms:platform_utils.bzl", "platforms")
19load("//build/bazel/rules:common.bzl", "get_dep_targets")
20load("//build/bazel/rules:prebuilt_file.bzl", "prebuilt_file")
21load("//build/bazel/rules:sh_binary.bzl", "sh_binary")
22load("//build/bazel/rules/aidl:aidl_interface.bzl", "aidl_interface")
23load("//build/bazel/rules/android:android_app_certificate.bzl", "android_app_certificate")
24load("//build/bazel/rules/cc:cc_binary.bzl", "cc_binary")
25load("//build/bazel/rules/cc:cc_library_headers.bzl", "cc_library_headers")
26load("//build/bazel/rules/cc:cc_library_shared.bzl", "cc_library_shared")
27load("//build/bazel/rules/cc:cc_library_static.bzl", "cc_library_static")
28load("//build/bazel/rules/cc:cc_stub_library.bzl", "cc_stub_suite")
29load("//build/bazel/rules/test_common:rules.bzl", "expect_failure_test", "target_under_test_exist_test")
30load(":apex_deps_validation.bzl", "ApexDepsInfo", "apex_dep_infos_to_allowlist_strings")
31load(":apex_info.bzl", "ApexInfo", "ApexMkInfo")
32load(":apex_test_helpers.bzl", "test_apex")
33
34ActionArgsInfo = provider(
35    fields = {
36        "argv": "The link action arguments.",
37    },
38)
39
40def _canned_fs_config_test(ctx):
41    env = analysistest.begin(ctx)
42    actions = analysistest.target_actions(env)
43
44    found_canned_fs_config_action = False
45
46    def pretty_print_list(the_list):
47        if not the_list:
48            return "[]"
49        result = "[\n"
50        for item in the_list:
51            result += "  \"%s\",\n" % item
52        return result + "]"
53
54    if ctx.attr.expected_extra_cat:
55        append_custom_fs_config = [a for a in actions if a.mnemonic == "AppendCustomFsConfig"]
56        asserts.true(env, len(append_custom_fs_config) == 1, "could not find the AppendCustomFsConfig action")
57        a = append_custom_fs_config[0]
58        args = a.argv[2].split(" ")  # first 2 are "/bin/bash" and "-c"
59        asserts.equals(env, args[0], "cat")
60        asserts.true(env, args[1].endswith("_canned_fs_config.txt"))
61        asserts.true(env, args[2].endswith(ctx.attr.expected_extra_cat), "expected %s, but got %s" % (ctx.attr.expected_extra_cat, args[2]))
62        asserts.equals(env, args[3], ">")
63        asserts.true(env, args[4].endswith("_combined_canned_fs_config.txt"))
64
65    for a in actions:
66        if a.mnemonic != "FileWrite":
67            # The canned_fs_config uses ctx.actions.write.
68            continue
69
70        outputs = a.outputs.to_list()
71        if len(outputs) != 1:
72            continue
73        if not outputs[0].basename.endswith("_canned_fs_config.txt"):
74            continue
75
76        found_canned_fs_config_action = True
77
78        # Don't sort -- the order is significant.
79        actual_entries = a.content.split("\n")
80        replacement = "64" if platforms.get_target_bitness(ctx.attr._platform_utils) == 64 else ""
81        expected_entries = [x.replace("{64_OR_BLANK}", replacement) for x in ctx.attr.expected_entries]
82        asserts.equals(env, pretty_print_list(expected_entries), pretty_print_list(actual_entries))
83
84        break
85
86    # Ensures that we actually found the canned_fs_config.txt generation action.
87    asserts.true(env, found_canned_fs_config_action, "did not find the canned fs config generating action")
88
89    return analysistest.end(env)
90
91canned_fs_config_test = analysistest.make(
92    _canned_fs_config_test,
93    attrs = {
94        "expected_entries": attr.string_list(
95            doc = "Expected lines in the canned_fs_config.txt",
96        ),
97        "expected_extra_cat": attr.string(
98            doc = "Filename of the custom canned fs config to be found in the AppendCustomFsConfig action",
99        ),
100        "_platform_utils": attr.label(
101            default = Label("//build/bazel/platforms:platform_utils"),
102        ),
103    },
104)
105
106def _test_canned_fs_config_basic():
107    name = "apex_canned_fs_config_basic"
108    test_name = name + "_test"
109
110    test_apex(name = name)
111
112    canned_fs_config_test(
113        name = test_name,
114        target_under_test = name,
115        expected_entries = [
116            "/ 1000 1000 0755",
117            "/apex_manifest.json 1000 1000 0644",
118            "/apex_manifest.pb 1000 1000 0644",
119            "",  # ends with a newline
120        ],
121    )
122
123    return test_name
124
125def _test_canned_fs_config_custom():
126    name = "apex_canned_fs_config_custom"
127    test_name = name + "_test"
128
129    native.genrule(
130        name = name + ".custom_config",
131        outs = [name + ".custom.config"],
132        cmd = "echo -e \"/2.bin 0 1000 0750\n/1.bin 0 1000 0777\n\" > $@",
133    )
134
135    test_apex(
136        name = name,
137        canned_fs_config = name + "_custom.config",
138    )
139
140    canned_fs_config_test(
141        name = test_name,
142        target_under_test = name,
143        expected_entries = [
144            "/ 1000 1000 0755",
145            "/apex_manifest.json 1000 1000 0644",
146            "/apex_manifest.pb 1000 1000 0644",
147            "",  # ends with a newline
148            # unfortunately, due to bazel analysis not being able to read the
149            # contents of inputs (i.e. dynamic dependencies), we cannot test for
150            # the contents of the custom config here. but, we can test that the
151            # custom config is concatenated in the action command with
152            # 'expected_extra_cat' below.
153        ],
154        expected_extra_cat = name + "_custom.config",
155    )
156
157    return test_name
158
159def _test_canned_fs_config_binaries():
160    name = "apex_canned_fs_config_binaries"
161    test_name = name + "_test"
162
163    sh_binary(
164        name = "bin_sh",
165        srcs = ["bin.sh"],
166        tags = ["manual"],
167    )
168
169    cc_binary(
170        name = "bin_cc",
171        srcs = ["bin.cc"],
172        tags = ["manual"],
173    )
174
175    test_apex(
176        name = name,
177        binaries = ["bin_sh", "bin_cc"],
178    )
179
180    canned_fs_config_test(
181        name = test_name,
182        target_under_test = name,
183        expected_entries = [
184            "/ 1000 1000 0755",
185            "/apex_manifest.json 1000 1000 0644",
186            "/apex_manifest.pb 1000 1000 0644",
187            "/lib{64_OR_BLANK}/libc++.so 1000 1000 0644",
188            "/bin/bin_cc 0 2000 0755",
189            "/bin/bin_sh 0 2000 0755",
190            "/bin 0 2000 0755",
191            "/lib{64_OR_BLANK} 0 2000 0755",
192            "",  # ends with a newline
193        ],
194        target_compatible_with = ["//build/bazel/platforms/os:android"],
195    )
196
197    return test_name
198
199def _test_canned_fs_config_native_shared_libs_arm():
200    name = "apex_canned_fs_config_native_shared_libs_arm"
201    test_name = name + "_test"
202
203    cc_library_shared(
204        name = name + "_lib_cc",
205        srcs = [name + "_lib.cc"],
206        tags = ["manual"],
207    )
208
209    cc_library_shared(
210        name = name + "_lib2_cc",
211        srcs = [name + "_lib2.cc"],
212        tags = ["manual"],
213    )
214
215    test_apex(
216        name = name,
217        native_shared_libs_32 = [name + "_lib_cc"],
218        native_shared_libs_64 = [name + "_lib2_cc"],
219    )
220
221    canned_fs_config_test(
222        name = test_name,
223        target_under_test = name,
224        expected_entries = [
225            "/ 1000 1000 0755",
226            "/apex_manifest.json 1000 1000 0644",
227            "/apex_manifest.pb 1000 1000 0644",
228            "/lib/apex_canned_fs_config_native_shared_libs_arm_lib_cc.so 1000 1000 0644",
229            "/lib/libc++.so 1000 1000 0644",
230            "/lib 0 2000 0755",
231            "",  # ends with a newline
232        ],
233        target_compatible_with = ["//build/bazel/platforms/arch:arm"],
234    )
235
236    return test_name
237
238def _test_canned_fs_config_native_shared_libs_arm64():
239    name = "apex_canned_fs_config_native_shared_libs_arm64"
240    test_name = name + "_test"
241
242    cc_library_shared(
243        name = name + "_lib_cc",
244        srcs = [name + "_lib.cc"],
245        tags = ["manual"],
246    )
247
248    cc_library_shared(
249        name = name + "_lib2_cc",
250        srcs = [name + "_lib2.cc"],
251        tags = ["manual"],
252    )
253
254    test_apex(
255        name = name,
256        native_shared_libs_32 = [name + "_lib_cc"],
257        native_shared_libs_64 = [name + "_lib2_cc"],
258    )
259
260    canned_fs_config_test(
261        name = test_name,
262        target_under_test = name,
263        expected_entries = [
264            "/ 1000 1000 0755",
265            "/apex_manifest.json 1000 1000 0644",
266            "/apex_manifest.pb 1000 1000 0644",
267            "/lib/apex_canned_fs_config_native_shared_libs_arm64_lib_cc.so 1000 1000 0644",
268            "/lib/libc++.so 1000 1000 0644",
269            "/lib64/apex_canned_fs_config_native_shared_libs_arm64_lib2_cc.so 1000 1000 0644",
270            "/lib64/libc++.so 1000 1000 0644",
271            "/lib 0 2000 0755",
272            "/lib64 0 2000 0755",
273            "",  # ends with a newline
274        ],
275        target_compatible_with = ["//build/bazel/platforms/arch:arm64"],
276    )
277
278    return test_name
279
280def _test_canned_fs_config_prebuilts():
281    name = "apex_canned_fs_config_prebuilts"
282    test_name = name + "_test"
283
284    prebuilt_file(
285        name = "file",
286        src = "file.txt",
287        dir = "etc",
288        tags = ["manual"],
289    )
290
291    prebuilt_file(
292        name = "nested_file_in_dir",
293        src = "file2.txt",
294        dir = "etc/nested",
295        tags = ["manual"],
296    )
297
298    prebuilt_file(
299        name = "renamed_file_in_dir",
300        src = "file3.txt",
301        dir = "etc",
302        filename = "renamed_file3.txt",
303        tags = ["manual"],
304    )
305
306    test_apex(
307        name = name,
308        prebuilts = [
309            ":file",
310            ":nested_file_in_dir",
311            ":renamed_file_in_dir",
312        ],
313    )
314
315    canned_fs_config_test(
316        name = test_name,
317        target_under_test = name,
318        expected_entries = [
319            "/ 1000 1000 0755",
320            "/apex_manifest.json 1000 1000 0644",
321            "/apex_manifest.pb 1000 1000 0644",
322            "/etc/file 1000 1000 0644",
323            "/etc/nested/nested_file_in_dir 1000 1000 0644",
324            "/etc/renamed_file3.txt 1000 1000 0644",
325            "/etc 0 2000 0755",
326            "/etc/nested 0 2000 0755",
327            "",  # ends with a newline
328        ],
329    )
330
331    return test_name
332
333def _test_canned_fs_config_prebuilts_sort_order():
334    name = "apex_canned_fs_config_prebuilts_sort_order"
335    test_name = name + "_test"
336
337    prebuilt_file(
338        name = "file_a",
339        src = "file_a.txt",
340        dir = "etc/a",
341        tags = ["manual"],
342    )
343
344    prebuilt_file(
345        name = "file_b",
346        src = "file_b.txt",
347        dir = "etc/b",
348        tags = ["manual"],
349    )
350
351    prebuilt_file(
352        name = "file_a_c",
353        src = "file_a_c.txt",
354        dir = "etc/a/c",
355        tags = ["manual"],
356    )
357
358    test_apex(
359        name = name,
360        prebuilts = [
361            ":file_a",
362            ":file_b",
363            ":file_a_c",
364        ],
365    )
366
367    canned_fs_config_test(
368        name = test_name,
369        target_under_test = name,
370        expected_entries = [
371            "/ 1000 1000 0755",
372            "/apex_manifest.json 1000 1000 0644",
373            "/apex_manifest.pb 1000 1000 0644",
374            "/etc/a/c/file_a_c 1000 1000 0644",
375            "/etc/a/file_a 1000 1000 0644",
376            "/etc/b/file_b 1000 1000 0644",
377            "/etc 0 2000 0755",
378            "/etc/a 0 2000 0755",
379            "/etc/a/c 0 2000 0755",
380            "/etc/b 0 2000 0755",
381            "",  # ends with a newline
382        ],
383    )
384
385    return test_name
386
387def _test_canned_fs_config_runtime_deps():
388    name = "apex_canned_fs_config_runtime_deps"
389    test_name = name + "_test"
390
391    cc_library_shared(
392        name = name + "_runtime_dep_3",
393        srcs = ["lib2.cc"],
394        tags = ["manual"],
395    )
396
397    cc_library_static(
398        name = name + "_static_lib",
399        srcs = ["lib3.cc"],
400        runtime_deps = [name + "_runtime_dep_3"],
401        tags = ["manual"],
402    )
403
404    cc_library_shared(
405        name = name + "_runtime_dep_2",
406        srcs = ["lib2.cc"],
407        tags = ["manual"],
408    )
409
410    cc_library_shared(
411        name = name + "_runtime_dep_1",
412        srcs = ["lib.cc"],
413        runtime_deps = [name + "_runtime_dep_2"],
414        tags = ["manual"],
415    )
416
417    cc_binary(
418        name = name + "_bin_cc",
419        srcs = ["bin.cc"],
420        runtime_deps = [name + "_runtime_dep_1"],
421        deps = [name + "_static_lib"],
422        tags = ["manual"],
423    )
424
425    test_apex(
426        name = name,
427        binaries = [name + "_bin_cc"],
428    )
429
430    canned_fs_config_test(
431        name = test_name,
432        target_under_test = name,
433        expected_entries = [
434            "/ 1000 1000 0755",
435            "/apex_manifest.json 1000 1000 0644",
436            "/apex_manifest.pb 1000 1000 0644",
437            "/lib{64_OR_BLANK}/%s_runtime_dep_1.so 1000 1000 0644" % name,
438            "/lib{64_OR_BLANK}/%s_runtime_dep_2.so 1000 1000 0644" % name,
439            "/lib{64_OR_BLANK}/%s_runtime_dep_3.so 1000 1000 0644" % name,
440            "/lib{64_OR_BLANK}/libc++.so 1000 1000 0644",
441            "/bin/%s_bin_cc 0 2000 0755" % name,
442            "/bin 0 2000 0755",
443            "/lib{64_OR_BLANK} 0 2000 0755",
444            "",  # ends with a newline
445        ],
446        target_compatible_with = ["//build/bazel/platforms/os:android"],
447    )
448
449    return test_name
450
451def _apex_manifest_test(ctx):
452    env = analysistest.begin(ctx)
453    actions = analysistest.target_actions(env)
454
455    conv_apex_manifest_action = [a for a in actions if a.mnemonic == "ConvApexManifest"][0]
456
457    apexer_action = [a for a in actions if a.mnemonic == "Apexer"][0]
458    argv = apexer_action.argv[:-1] + apexer_action.argv[-1].split(" ")
459    manifest_index = argv.index("--manifest")
460    manifest_path = argv[manifest_index + 1]
461
462    asserts.equals(
463        env,
464        conv_apex_manifest_action.outputs.to_list()[0].path,
465        manifest_path,
466        "the generated apex manifest protobuf is used as input to apexer",
467    )
468    asserts.true(
469        env,
470        manifest_path.endswith(".pb"),
471        "the generated apex manifest should be a .pb file",
472    )
473
474    if ctx.attr.expected_min_sdk_version != "":
475        flag_index = argv.index("--min_sdk_version")
476        min_sdk_version_argv = argv[flag_index + 1]
477        asserts.equals(
478            env,
479            ctx.attr.expected_min_sdk_version,
480            min_sdk_version_argv,
481        )
482
483    return analysistest.end(env)
484
485apex_manifest_test_attr = dict(
486    impl = _apex_manifest_test,
487    attrs = {
488        "expected_min_sdk_version": attr.string(),
489    },
490)
491
492apex_manifest_test = analysistest.make(
493    **apex_manifest_test_attr
494)
495
496apex_manifest_global_min_sdk_current_test = analysistest.make(
497    config_settings = {
498        "@//build/bazel/rules/apex:unbundled_build_target_sdk_with_api_fingerprint": False,
499    },
500    **apex_manifest_test_attr
501)
502
503apex_manifest_global_min_sdk_override_tiramisu_test = analysistest.make(
504    config_settings = {
505        "@//build/bazel/rules/apex:apex_global_min_sdk_version_override": "Tiramisu",
506        "@//build/bazel/rules/apex:unbundled_build_target_sdk_with_api_fingerprint": False,
507    },
508    **apex_manifest_test_attr
509)
510
511def _test_apex_manifest():
512    name = "apex_manifest"
513    test_name = name + "_test"
514
515    test_apex(name = name)
516
517    apex_manifest_test(
518        name = test_name,
519        target_under_test = name,
520    )
521
522    return test_name
523
524def _test_apex_manifest_min_sdk_version():
525    name = "apex_manifest_min_sdk_version"
526    test_name = name + "_test"
527
528    test_apex(
529        name = name,
530        min_sdk_version = "30",
531    )
532
533    apex_manifest_test(
534        name = test_name,
535        target_under_test = name,
536        expected_min_sdk_version = "30",
537    )
538
539    return test_name
540
541def _test_apex_manifest_min_sdk_version_current():
542    name = "apex_manifest_min_sdk_version_current"
543    test_name = name + "_test"
544
545    test_apex(
546        name = name,
547        min_sdk_version = "current",
548    )
549
550    # this test verifies min_sdk_version without use_api_fingerprint
551    apex_manifest_global_min_sdk_current_test(
552        name = test_name,
553        target_under_test = name,
554        expected_min_sdk_version = "10000",
555    )
556
557    return test_name
558
559def _test_apex_manifest_min_sdk_version_override():
560    name = "apex_manifest_min_sdk_version_override"
561    test_name = name + "_test"
562
563    test_apex(
564        name = name,
565        min_sdk_version = "30",
566    )
567
568    # this test verifies min_sdk_version without use_api_fingerprint
569    apex_manifest_global_min_sdk_override_tiramisu_test(
570        name = test_name,
571        target_under_test = name,
572        expected_min_sdk_version = "33",  # overriden to 33
573    )
574
575    return test_name
576
577def _apex_native_libs_requires_provides_test(ctx):
578    env = analysistest.begin(ctx)
579    target_under_test = analysistest.target_under_test(env)
580    asserts.equals(
581        env,
582        [t.label for t in ctx.attr.requires_native_libs],  # expected
583        target_under_test[ApexInfo].requires_native_libs,  # actual
584        "did not get expected requires_native_libs",
585    )
586    asserts.equals(
587        env,
588        [t.label for t in ctx.attr.provides_native_libs],
589        target_under_test[ApexInfo].provides_native_libs,
590        "did not get expected provides_native_libs",
591    )
592    asserts.equals(
593        env,
594        ctx.attr.make_modules_to_install,
595        target_under_test[ApexMkInfo].make_modules_to_install,
596        "did not get expected make_modules_to_install",
597    )
598
599    # Compare the argv of the jsonmodify action that updates the apex
600    # manifest with information about provided and required libs.
601    actions = analysistest.target_actions(env)
602    action = [a for a in actions if a.mnemonic == "ApexManifestModify"][0]
603    requires_argv_index = action.argv.index("requireNativeLibs") + 1
604    provides_argv_index = action.argv.index("provideNativeLibs") + 1
605
606    for idx, requires in enumerate(ctx.attr.requires_native_libs):
607        asserts.equals(
608            env,
609            requires.label.name + ".so",  # expected
610            action.argv[requires_argv_index + idx],  # actual
611        )
612
613    for idx, provides in enumerate(ctx.attr.provides_native_libs):
614        asserts.equals(
615            env,
616            provides.label.name + ".so",
617            action.argv[provides_argv_index + idx],
618        )
619
620    return analysistest.end(env)
621
622apex_native_libs_requires_provides_test = analysistest.make(
623    _apex_native_libs_requires_provides_test,
624    attrs = {
625        "make_modules_to_install": attr.string_list(doc = "make module names that should be installed to system"),
626        "provides_argv": attr.string_list(),
627        "provides_native_libs": attr.label_list(doc = "bazel target names of libs provided for dynamic linking"),
628        "requires_argv": attr.string_list(),
629        "requires_native_libs": attr.label_list(doc = "bazel target names of libs required for dynamic linking"),
630    },
631)
632
633def _test_apex_manifest_dependencies_nodep():
634    name = "apex_manifest_dependencies_nodep"
635    test_name = name + "_test"
636
637    cc_library_shared(
638        name = name + "_lib_nodep",
639        stl = "none",
640        system_dynamic_deps = [],
641        tags = ["manual"],
642    )
643
644    test_apex(
645        name = name,
646        native_shared_libs_32 = [name + "_lib_nodep"],
647        native_shared_libs_64 = [name + "_lib_nodep"],
648    )
649
650    apex_native_libs_requires_provides_test(
651        name = test_name,
652        target_under_test = name,
653        requires_native_libs = [],
654        provides_native_libs = [],
655        make_modules_to_install = [],
656    )
657
658    return test_name
659
660def _test_apex_manifest_dependencies_cc_library_shared_bionic_deps():
661    name = "apex_manifest_dependencies_cc_library_shared_bionic_deps"
662    test_name = name + "_test"
663
664    cc_library_shared(
665        name = name + "_lib",
666        # implicit bionic system_dynamic_deps
667        tags = ["manual"],
668    )
669
670    test_apex(
671        name = name,
672        native_shared_libs_32 = [name + "_lib"],
673        native_shared_libs_64 = [name + "_lib"],
674    )
675
676    apex_native_libs_requires_provides_test(
677        name = test_name,
678        target_under_test = name,
679        requires_native_libs = [
680            "//bionic/libc",
681            "//bionic/libdl",
682            "//bionic/libm",
683        ],
684        provides_native_libs = [],
685        make_modules_to_install = [],
686    )
687
688    return test_name
689
690def _test_apex_manifest_dependencies_cc_binary_bionic_deps():
691    name = "apex_manifest_dependencies_cc_binary_bionic_deps"
692    test_name = name + "_test"
693
694    cc_binary(
695        name = name + "_bin",
696        # implicit bionic system_deps
697        tags = ["manual"],
698    )
699
700    test_apex(
701        name = name,
702        binaries = [name + "_bin"],
703    )
704
705    apex_native_libs_requires_provides_test(
706        name = test_name,
707        target_under_test = name,
708        requires_native_libs = [
709            "//bionic/libc",
710            "//bionic/libdl",
711            "//bionic/libm",
712        ],
713        provides_native_libs = [],
714        make_modules_to_install = [],
715    )
716
717    return test_name
718
719def _test_apex_manifest_dependencies_requires():
720    name = "apex_manifest_dependencies_requires"
721    test_name = name + "_test"
722
723    cc_library_shared(
724        name = name + "_lib_with_dep",
725        system_dynamic_deps = [],
726        stl = "none",
727        implementation_dynamic_deps = select({
728            "//build/bazel/rules/apex:android-in_apex": [name + "_libfoo_stub_libs_current"],
729            "//build/bazel/rules/apex:android-non_apex": [name + "_libfoo"],
730        }),
731        tags = ["manual"],
732        stubs_symbol_file = name + "_lib_with_dep" + ".map.txt",
733    )
734
735    native.genrule(
736        name = name + "_genrule_lib_with_dep_map_txt",
737        outs = [name + "_lib_with_dep.map.txt"],
738        cmd = "touch $@",
739        tags = ["manual"],
740    )
741
742    cc_stub_suite(
743        name = name + "_lib_with_dep_stub_libs",
744        soname = name + "_lib_with_dep.so",
745        source_library_label = ":" + name + "_lib_with_dep",
746        symbol_file = name + "_lib_with_dep.map.txt",
747        versions = ["30"],
748    )
749
750    cc_library_shared(
751        name = name + "_libfoo",
752        system_dynamic_deps = [],
753        stl = "none",
754        tags = ["manual"],
755        stubs_symbol_file = name + "_libfoo" + ".map.txt",
756    )
757
758    native.genrule(
759        name = name + "_genrule_libfoo_map_txt",
760        outs = [name + "_libfoo.map.txt"],
761        cmd = "touch $@",
762        tags = ["manual"],
763    )
764
765    cc_stub_suite(
766        name = name + "_libfoo_stub_libs",
767        soname = name + "_libfoo.so",
768        source_library_label = ":" + name + "_libfoo",
769        symbol_file = name + "_libfoo.map.txt",
770        versions = ["30"],
771    )
772
773    test_apex(
774        name = name,
775        native_shared_libs_32 = [name + "_lib_with_dep"],
776        native_shared_libs_64 = [name + "_lib_with_dep"],
777    )
778
779    apex_native_libs_requires_provides_test(
780        name = test_name,
781        target_under_test = name,
782        requires_native_libs = [name + "_libfoo"],
783        provides_native_libs = [name + "_lib_with_dep"],
784        make_modules_to_install = [name + "_libfoo"],
785        target_compatible_with = ["//build/bazel/platforms/os:android"],
786    )
787
788    return test_name
789
790def _test_apex_manifest_dependencies_provides():
791    name = "apex_manifest_dependencies_provides"
792    test_name = name + "_test"
793
794    cc_library_shared(
795        name = name + "_libfoo",
796        system_dynamic_deps = [],
797        stl = "none",
798        tags = ["manual"],
799        stubs_symbol_file = name + "_libfoo" + ".map.txt",
800    )
801
802    native.genrule(
803        name = name + "_genrule_libfoo_map_txt",
804        outs = [name + "_libfoo.map.txt"],
805        cmd = "touch $@",
806        tags = ["manual"],
807    )
808
809    cc_stub_suite(
810        name = name + "_libfoo_stub_libs",
811        soname = name + "_libfoo.so",
812        source_library_label = ":" + name + "_libfoo",
813        symbol_file = name + "_libfoo.map.txt",
814        versions = ["30"],
815    )
816
817    test_apex(
818        name = name,
819        native_shared_libs_32 = [name + "_libfoo"],
820        native_shared_libs_64 = [name + "_libfoo"],
821    )
822
823    apex_native_libs_requires_provides_test(
824        name = test_name,
825        target_under_test = name,
826        requires_native_libs = [],
827        provides_native_libs = [name + "_libfoo"],
828        make_modules_to_install = [],
829    )
830
831    return test_name
832
833def _test_apex_manifest_dependencies_selfcontained():
834    name = "apex_manifest_dependencies_selfcontained"
835    test_name = name + "_test"
836
837    cc_library_shared(
838        name = name + "_lib_with_dep",
839        system_dynamic_deps = [],
840        stl = "none",
841        implementation_dynamic_deps = select({
842            "//build/bazel/rules/apex:android-in_apex": [name + "_libfoo_stub_libs_current"],
843            "//build/bazel/rules/apex:android-non_apex": [name + "_libfoo"],
844        }),
845        tags = ["manual"],
846        stubs_symbol_file = name + "_lib_with_dep" + ".map.txt",
847    )
848
849    native.genrule(
850        name = name + "_genrule_lib-with_dep_map_txt",
851        outs = [name + "_lib_with_dep.map.txt"],
852        cmd = "touch $@",
853        tags = ["manual"],
854    )
855
856    cc_stub_suite(
857        name = name + "_lib_with_dep_stub_libs",
858        soname = name + "_lib_with_dep.so",
859        source_library_label = ":" + name + "_lib_with_dep",
860        symbol_file = name + "_lib_with_dep.map.txt",
861        versions = ["30"],
862    )
863
864    cc_library_shared(
865        name = name + "_libfoo",
866        system_dynamic_deps = [],
867        stl = "none",
868        tags = ["manual"],
869        stubs_symbol_file = name + "_libfoo" + ".map.txt",
870    )
871
872    native.genrule(
873        name = name + "_genrule_libfoo_map_txt",
874        outs = [name + "_libfoo.map.txt"],
875        cmd = "touch $@",
876        tags = ["manual"],
877    )
878
879    cc_stub_suite(
880        name = name + "_libfoo_stub_libs",
881        soname = name + "_libfoo.so",
882        source_library_label = ":" + name + "_libfoo",
883        symbol_file = name + "_libfoo.map.txt",
884        versions = ["30"],
885    )
886
887    test_apex(
888        name = name,
889        native_shared_libs_32 = [
890            name + "_lib_with_dep",
891            name + "_libfoo",
892        ],
893        native_shared_libs_64 = [
894            name + "_lib_with_dep",
895            name + "_libfoo",
896        ],
897    )
898
899    apex_native_libs_requires_provides_test(
900        name = test_name,
901        target_under_test = name,
902        requires_native_libs = [],
903        provides_native_libs = [
904            name + "_lib_with_dep",
905            name + "_libfoo",
906        ],
907        make_modules_to_install = [],
908        target_compatible_with = ["//build/bazel/platforms/os:android"],
909    )
910
911    return test_name
912
913def _test_apex_manifest_dependencies_cc_binary():
914    name = "apex_manifest_dependencies_cc_binary"
915    test_name = name + "_test"
916
917    cc_binary(
918        name = name + "_bin",
919        stl = "none",
920        system_deps = [],
921        dynamic_deps = [
922            name + "_lib_with_dep",
923        ] + select({
924            "//build/bazel/rules/apex:android-in_apex": [name + "_librequires2_stub_libs_current"],
925            "//build/bazel/rules/apex:android-non_apex": [name + "_librequires2"],
926        }),
927        tags = ["manual"],
928    )
929
930    cc_library_shared(
931        name = name + "_lib_with_dep",
932        system_dynamic_deps = [],
933        stl = "none",
934        implementation_dynamic_deps = select({
935            "//build/bazel/rules/apex:android-in_apex": [name + "_librequires_stub_libs_current"],
936            "//build/bazel/rules/apex:android-non_apex": [name + "_librequires"],
937        }),
938        tags = ["manual"],
939    )
940
941    cc_library_shared(
942        name = name + "_librequires",
943        system_dynamic_deps = [],
944        stl = "none",
945        tags = ["manual"],
946        stubs_symbol_file = name + "_librequires" + ".map.txt",
947    )
948
949    native.genrule(
950        name = name + "_genrule_librequires_map_txt",
951        outs = [name + "_librequires.map.txt"],
952        cmd = "touch $@",
953        tags = ["manual"],
954    )
955
956    cc_stub_suite(
957        name = name + "_librequires_stub_libs",
958        soname = name + "_librequires.so",
959        source_library_label = ":" + name + "_librequires",
960        symbol_file = name + "_librequires.map.txt",
961        versions = ["30"],
962    )
963
964    cc_library_shared(
965        name = name + "_librequires2",
966        system_dynamic_deps = [],
967        stl = "none",
968        tags = ["manual"],
969        stubs_symbol_file = name + "_librequires2.map.txt",
970    )
971
972    native.genrule(
973        name = name + "_genrule_librequires2_map_txt",
974        outs = [name + "_librequires2.map.txt"],
975        cmd = "touch $@",
976        tags = ["manual"],
977    )
978
979    cc_stub_suite(
980        name = name + "_librequires2_stub_libs",
981        soname = name + "_librequires2.so",
982        source_library_label = ":" + name + "_librequires2",
983        symbol_file = name + "_librequires2.map.txt",
984        versions = ["30"],
985    )
986
987    test_apex(
988        name = name,
989        binaries = [name + "_bin"],
990    )
991
992    apex_native_libs_requires_provides_test(
993        name = test_name,
994        target_under_test = name,
995        requires_native_libs = [
996            name + "_librequires",
997            name + "_librequires2",
998        ],
999        make_modules_to_install = [
1000            name + "_librequires",
1001            name + "_librequires2",
1002        ],
1003        target_compatible_with = ["//build/bazel/platforms/os:android"],
1004    )
1005
1006    return test_name
1007
1008def _action_args_test(ctx):
1009    env = analysistest.begin(ctx)
1010    actions = analysistest.target_actions(env)
1011
1012    action = [a for a in actions if a.mnemonic == ctx.attr.action_mnemonic][0]
1013    argv = action.argv[:-1] + action.argv[-1].split(" ")
1014    flag_idx = argv.index(ctx.attr.expected_args[0])
1015
1016    for i, expected_arg in enumerate(ctx.attr.expected_args):
1017        asserts.equals(
1018            env,
1019            expected_arg,
1020            argv[flag_idx + i],
1021        )
1022
1023    return analysistest.end(env)
1024
1025_action_args_test_attrs = {
1026    "action_mnemonic": attr.string(mandatory = True),
1027    "expected_args": attr.string_list(mandatory = True),
1028}
1029
1030action_args_test = analysistest.make(
1031    _action_args_test,
1032    attrs = _action_args_test_attrs,
1033)
1034
1035def _test_logging_parent_flag():
1036    name = "logging_parent"
1037    test_name = name + "_test"
1038
1039    test_apex(
1040        name = name,
1041        logging_parent = "logging.parent",
1042    )
1043
1044    action_args_test(
1045        name = test_name,
1046        target_under_test = name,
1047        action_mnemonic = "Apexer",
1048        expected_args = [
1049            "--logging_parent",
1050            "logging.parent",
1051        ],
1052    )
1053
1054    return test_name
1055
1056def _test_default_apex_manifest_version():
1057    name = "default_apex_manifest_version"
1058    test_name = name + "_test"
1059
1060    test_apex(
1061        name = name,
1062    )
1063
1064    action_args_test(
1065        name = test_name,
1066        target_under_test = name,
1067        action_mnemonic = "ApexManifestModify",
1068        expected_args = [
1069            "-se",
1070            "version",
1071            "0",
1072            str(default_manifest_version),
1073        ],
1074    )
1075
1076    return test_name
1077
1078action_args_with_overrides_test = analysistest.make(
1079    _action_args_test,
1080    attrs = _action_args_test_attrs,
1081    config_settings = {
1082        "//command_line_option:platforms": "@//build/bazel/tests/products:aosp_arm64_for_testing_with_overrides_and_app_cert",
1083    },
1084)
1085
1086def _test_package_name():
1087    name = "package_name"
1088    test_name = name + "_test"
1089
1090    test_apex(
1091        name = name,
1092        package_name = "my.package.name",
1093    )
1094
1095    action_args_test(
1096        name = test_name,
1097        target_under_test = name,
1098        action_mnemonic = "Apexer",
1099        expected_args = [
1100            "--override_apk_package_name",
1101            "my.package.name",
1102        ],
1103    )
1104
1105    return test_name
1106
1107def _test_package_name_override_from_config():
1108    name = "package_name_override_from_config"
1109    test_name = name + "_test"
1110
1111    test_apex(name = name)
1112
1113    action_args_with_overrides_test(
1114        name = test_name,
1115        target_under_test = name,
1116        action_mnemonic = "Apexer",
1117        expected_args = [
1118            "--override_apk_package_name",
1119            "another.package",
1120        ],
1121    )
1122
1123    return test_name
1124
1125action_args_with_override_apex_manifest_default_version_test = analysistest.make(
1126    _action_args_test,
1127    attrs = _action_args_test_attrs,
1128    # Wouldn't it be nice if it's possible to set the config_setting from the test callsite..
1129    config_settings = {
1130        "@//build/bazel/rules/apex:override_apex_manifest_default_version": "1234567890",
1131    },
1132)
1133
1134def _test_override_apex_manifest_version():
1135    name = "override_apex_manifest_version"
1136    test_name = name + "_test"
1137
1138    test_apex(
1139        name = name,
1140    )
1141
1142    action_args_with_override_apex_manifest_default_version_test(
1143        name = test_name,
1144        target_under_test = name,
1145        action_mnemonic = "ApexManifestModify",
1146        expected_args = [
1147            "-se",
1148            "version",
1149            "0",
1150            "1234567890",
1151        ],
1152    )
1153
1154    return test_name
1155
1156def _file_contexts_args_test(ctx):
1157    env = analysistest.begin(ctx)
1158    actions = analysistest.target_actions(env)
1159
1160    file_contexts_action = [a for a in actions if a.mnemonic == "GenerateApexFileContexts"][0]
1161
1162    # GenerateApexFileContexts is a run_shell action.
1163    # ["/bin/bash", "c", "<args>"]
1164    cmd = file_contexts_action.argv[2]
1165
1166    for expected_arg in ctx.attr.expected_args:
1167        asserts.true(
1168            env,
1169            expected_arg in cmd,
1170            "failed to find '%s' in '%s'" % (expected_arg, cmd),
1171        )
1172
1173    return analysistest.end(env)
1174
1175file_contexts_args_test = analysistest.make(
1176    _file_contexts_args_test,
1177    attrs = {
1178        "expected_args": attr.string_list(mandatory = True),
1179    },
1180)
1181
1182def _test_generate_file_contexts():
1183    name = "apex_manifest_pb_file_contexts"
1184    test_name = name + "_test"
1185
1186    test_apex(
1187        name = name,
1188    )
1189
1190    file_contexts_args_test(
1191        name = test_name,
1192        target_under_test = name,
1193        expected_args = [
1194            "/apex_manifest\\\\.pb u:object_r:system_file:s0",
1195            "/ u:object_r:system_file:s0",
1196        ],
1197    )
1198
1199    return test_name
1200
1201def _min_sdk_version_failure_test_impl(ctx):
1202    env = analysistest.begin(ctx)
1203
1204    asserts.expect_failure(
1205        env,
1206        "min_sdk_version %s cannot be lower than the dep's min_sdk_version %s" %
1207        (ctx.attr.apex_min, ctx.attr.dep_min),
1208    )
1209
1210    return analysistest.end(env)
1211
1212min_sdk_version_failure_test = analysistest.make(
1213    _min_sdk_version_failure_test_impl,
1214    expect_failure = True,
1215    attrs = {
1216        "apex_min": attr.string(),
1217        "dep_min": attr.string(),
1218    },
1219)
1220
1221def _test_min_sdk_version_failure():
1222    name = "min_sdk_version_failure"
1223    test_name = name + "_test"
1224
1225    cc_library_shared(
1226        name = name + "_lib_cc",
1227        srcs = [name + "_lib.cc"],
1228        tags = ["manual"],
1229        min_sdk_version = "32",
1230    )
1231
1232    test_apex(
1233        name = name,
1234        native_shared_libs_32 = [name + "_lib_cc"],
1235        min_sdk_version = "30",
1236    )
1237
1238    min_sdk_version_failure_test(
1239        name = test_name,
1240        target_under_test = name,
1241        apex_min = "30",
1242        dep_min = "32",
1243    )
1244
1245    return test_name
1246
1247def _test_min_sdk_version_failure_transitive():
1248    name = "min_sdk_version_failure_transitive"
1249    test_name = name + "_test"
1250
1251    cc_library_shared(
1252        name = name + "_lib_cc",
1253        dynamic_deps = [name + "_lib2_cc"],
1254        tags = ["manual"],
1255    )
1256
1257    cc_library_shared(
1258        name = name + "_lib2_cc",
1259        srcs = [name + "_lib2.cc"],
1260        tags = ["manual"],
1261        min_sdk_version = "32",
1262    )
1263
1264    test_apex(
1265        name = name,
1266        native_shared_libs_32 = [name + "_lib_cc"],
1267        min_sdk_version = "30",
1268    )
1269
1270    min_sdk_version_failure_test(
1271        name = test_name,
1272        target_under_test = name,
1273        apex_min = "30",
1274        dep_min = "32",
1275    )
1276
1277    return test_name
1278
1279def _apex_certificate_test(ctx):
1280    env = analysistest.begin(ctx)
1281    target_under_test = analysistest.target_under_test(env)
1282    container_key_info = target_under_test[ApexInfo].container_key_info
1283
1284    asserts.equals(env, ctx.attr.expected_pem_path, container_key_info.pem.path)
1285    asserts.equals(env, ctx.attr.expected_pk8_path, container_key_info.pk8.path)
1286
1287    return analysistest.end(env)
1288
1289apex_certificate_test = analysistest.make(
1290    _apex_certificate_test,
1291    attrs = {
1292        "expected_pem_path": attr.string(),
1293        "expected_pk8_path": attr.string(),
1294    },
1295)
1296
1297apex_certificate_with_overrides_test = analysistest.make(
1298    _apex_certificate_test,
1299    attrs = {
1300        "expected_pem_path": attr.string(),
1301        "expected_pk8_path": attr.string(),
1302    },
1303    config_settings = {
1304        "//command_line_option:platforms": "@//build/bazel/tests/products:aosp_arm64_for_testing_with_overrides_and_app_cert",
1305    },
1306)
1307
1308def _test_apex_certificate_none():
1309    name = "apex_certificate_none"
1310    test_name = name + "_test"
1311
1312    test_apex(
1313        name = name,
1314        certificate = None,
1315    )
1316
1317    apex_certificate_test(
1318        name = test_name,
1319        target_under_test = name,
1320        expected_pem_path = "build/make/target/product/security/testkey.x509.pem",
1321        expected_pk8_path = "build/make/target/product/security/testkey.pk8",
1322    )
1323
1324    return test_name
1325
1326def _test_apex_certificate_name():
1327    name = "apex_certificate_name"
1328    test_name = name + "_test"
1329
1330    test_apex(
1331        name = name,
1332        certificate = None,
1333        certificate_name = "shared",  # use something other than testkey
1334    )
1335
1336    apex_certificate_test(
1337        name = test_name,
1338        target_under_test = name,
1339        expected_pem_path = "build/make/target/product/security/shared.x509.pem",
1340        expected_pk8_path = "build/make/target/product/security/shared.pk8",
1341    )
1342
1343    return test_name
1344
1345def _test_apex_certificate_label():
1346    name = "apex_certificate_label"
1347    test_name = name + "_test"
1348
1349    android_app_certificate(
1350        name = name + "_cert",
1351        certificate = name,
1352        tags = ["manual"],
1353    )
1354
1355    test_apex(
1356        name = name,
1357        certificate = name + "_cert",
1358    )
1359
1360    apex_certificate_test(
1361        name = test_name,
1362        target_under_test = name,
1363        expected_pem_path = "build/bazel/rules/apex/apex_certificate_label.x509.pem",
1364        expected_pk8_path = "build/bazel/rules/apex/apex_certificate_label.pk8",
1365    )
1366
1367    return test_name
1368
1369def _test_apex_certificate_label_with_overrides():
1370    name = "apex_certificate_label_with_overrides"
1371    test_name = name + "_test"
1372
1373    android_app_certificate(
1374        name = name + "_cert",
1375        certificate = name,
1376        tags = ["manual"],
1377    )
1378
1379    test_apex(
1380        name = name,
1381        certificate = name + "_cert",
1382    )
1383
1384    apex_certificate_with_overrides_test(
1385        name = test_name,
1386        target_under_test = name,
1387        expected_pem_path = "build/bazel/rules/apex/testdata/another.x509.pem",
1388        expected_pk8_path = "build/bazel/rules/apex/testdata/another.pk8",
1389    )
1390
1391    return test_name
1392
1393def _min_sdk_version_apex_inherit_test_impl(ctx):
1394    env = analysistest.begin(ctx)
1395    target_under_test = analysistest.target_under_test(env)
1396    argv = target_under_test[ActionArgsInfo].argv
1397
1398    found = False
1399    for arg in argv:
1400        if arg.startswith("--target="):
1401            found = True
1402            asserts.true(
1403                env,
1404                arg.endswith(ctx.attr.apex_min),
1405                "Incorrect --target flag: %s %s" % (arg, ctx.attr.apex_min),
1406            )
1407
1408    asserts.true(
1409        env,
1410        found,
1411        "No --target flag found: %s" % argv,
1412    )
1413
1414    return analysistest.end(env)
1415
1416def _feature_check_aspect_impl(target, ctx):
1417    rules_propagate_src = [
1418        "_bssl_hash_injection",
1419        "stripped_shared_library",
1420        "versioned_shared_library",
1421    ]
1422
1423    argv = []
1424    if ctx.rule.kind == "cc_shared_library" and target.label.name == ctx.attr.cc_target:
1425        link_actions = [a for a in target.actions if a.mnemonic == "CppLink"]
1426        argv = link_actions[0].argv
1427    elif ctx.rule.kind in rules_propagate_src and hasattr(ctx.rule.attr, "src"):
1428        argv = ctx.rule.attr.src[ActionArgsInfo].argv
1429    elif ctx.rule.kind == "_cc_library_shared_proxy" and hasattr(ctx.rule.attr, "shared"):
1430        argv = ctx.rule.attr.shared[0][ActionArgsInfo].argv
1431    elif ctx.rule.kind == "_apex" and hasattr(ctx.rule.attr, "native_shared_libs_32"):
1432        argv = ctx.rule.attr.native_shared_libs_32[0][ActionArgsInfo].argv
1433
1434    return [
1435        ActionArgsInfo(
1436            argv = argv,
1437        ),
1438    ]
1439
1440feature_check_aspect = aspect(
1441    implementation = _feature_check_aspect_impl,
1442    attrs = {
1443        "cc_target": attr.string(values = [
1444            # This has to mirror the test impl library names
1445            "min_sdk_version_apex_inherit_lib_cc_unstripped",
1446            "min_sdk_version_apex_inherit_override_min_sdk_tiramisu_lib_cc_unstripped",
1447        ]),
1448    },
1449    attr_aspects = ["native_shared_libs_32", "shared", "src"],
1450)
1451
1452min_sdk_version_apex_inherit_test_attrs = dict(
1453    impl = _min_sdk_version_apex_inherit_test_impl,
1454    attrs = {
1455        "apex_min": attr.string(),
1456        "cc_target": attr.string(),
1457    },
1458    # We need to use aspect to examine the dependencies' actions of the apex
1459    # target as the result of the transition, checking the dependencies directly
1460    # using names will give you the info before the transition takes effect.
1461    extra_target_under_test_aspects = [feature_check_aspect],
1462)
1463
1464min_sdk_version_apex_inherit_test = analysistest.make(
1465    **min_sdk_version_apex_inherit_test_attrs
1466)
1467
1468min_sdk_version_apex_inherit_override_min_sdk_tiramisu_test = analysistest.make(
1469    config_settings = {
1470        "@//build/bazel/rules/apex:apex_global_min_sdk_version_override": "Tiramisu",
1471    },
1472    **min_sdk_version_apex_inherit_test_attrs
1473)
1474
1475def _test_min_sdk_version_apex_inherit():
1476    name = "min_sdk_version_apex_inherit"
1477    test_name = name + "_test"
1478    cc_name = name + "_lib_cc"
1479    apex_min = "29"
1480
1481    cc_library_shared(
1482        name = cc_name,
1483        srcs = [name + "_lib.cc"],
1484        tags = ["manual"],
1485        min_sdk_version = "apex_inherit",
1486    )
1487
1488    test_apex(
1489        name = name,
1490        native_shared_libs_32 = [cc_name],
1491        min_sdk_version = apex_min,
1492    )
1493
1494    min_sdk_version_apex_inherit_test(
1495        name = test_name,
1496        target_under_test = name,
1497        apex_min = apex_min,
1498        cc_target = cc_name + "_unstripped",
1499    )
1500
1501    return test_name
1502
1503def _test_min_sdk_version_apex_inherit_override_min_sdk_tiramisu():
1504    name = "min_sdk_version_apex_inherit_override_min_sdk_tiramisu"
1505    test_name = name + "_test"
1506    cc_name = name + "_lib_cc"
1507
1508    cc_library_shared(
1509        name = cc_name,
1510        srcs = [name + "_lib.cc"],
1511        tags = ["manual"],
1512        min_sdk_version = "apex_inherit",
1513    )
1514
1515    test_apex(
1516        name = name,
1517        native_shared_libs_32 = [cc_name],
1518        min_sdk_version = "29",
1519    )
1520
1521    min_sdk_version_apex_inherit_override_min_sdk_tiramisu_test(
1522        name = test_name,
1523        target_under_test = name,
1524        apex_min = "33",  # the apex transition forced the apex min_sdk_version to be 33
1525        cc_target = cc_name + "_unstripped",
1526    )
1527
1528    return test_name
1529
1530def _apex_provides_base_zip_files_test_impl(ctx):
1531    env = analysistest.begin(ctx)
1532    target_under_test = analysistest.target_under_test(env)
1533
1534    # The particular name of the file isn't important as it just gets zipped with the other apex files for other architectures
1535    asserts.true(
1536        env,
1537        target_under_test[ApexInfo].base_file != None,
1538        "Expected base_file to exist, but found None %s" % target_under_test[ApexInfo].base_file,
1539    )
1540
1541    asserts.equals(
1542        env,
1543        target_under_test[ApexInfo].base_with_config_zip.basename,
1544        # name is important here because the file gets disted and then referenced by name
1545        ctx.attr.apex_name + ".apex-base.zip",
1546        "Expected base file with config zip to have name ending with , but found %s" % target_under_test[ApexInfo].base_with_config_zip.basename,
1547    )
1548
1549    return analysistest.end(env)
1550
1551apex_provides_base_zip_files_test = analysistest.make(
1552    _apex_provides_base_zip_files_test_impl,
1553    attrs = {
1554        "apex_name": attr.string(),
1555    },
1556)
1557
1558def _test_apex_provides_base_zip_files():
1559    name = "apex_provides_base_zip_files"
1560    test_name = name + "_test"
1561
1562    test_apex(name = name)
1563
1564    apex_provides_base_zip_files_test(
1565        name = test_name,
1566        target_under_test = name,
1567        apex_name = name,
1568    )
1569
1570    return test_name
1571
1572def _apex_testonly_with_manifest_test_impl(ctx):
1573    env = analysistest.begin(ctx)
1574    actions = [a for a in analysistest.target_actions(env) if a.mnemonic == "Apexer"]
1575    asserts.true(
1576        env,
1577        len(actions) == 1,
1578        "No apexer action found: %s" % actions,
1579    )
1580    argv = actions[0].argv
1581
1582    asserts.false(
1583        env,
1584        "--test_only" in argv,
1585        "Calling apexer with --test_only when manifest file is specified: %s" % argv,
1586    )
1587
1588    actions = [a for a in analysistest.target_actions(env) if a.mnemonic == "MarkAndroidManifestTestOnly"]
1589    asserts.true(
1590        env,
1591        len(actions) == 1,
1592        "No MarkAndroidManifestTestOnly action found: %s" % actions,
1593    )
1594    argv = actions[0].argv
1595
1596    asserts.true(
1597        env,
1598        "--test-only" in argv,
1599        "Calling manifest_fixer without --test-only: %s" % argv,
1600    )
1601
1602    return analysistest.end(env)
1603
1604apex_testonly_with_manifest_test = analysistest.make(
1605    _apex_testonly_with_manifest_test_impl,
1606)
1607
1608def _test_apex_testonly_with_manifest():
1609    name = "apex_testonly_with_manifest"
1610    test_name = name + "_test"
1611
1612    cc_library_shared(
1613        name = name + "_lib_cc",
1614        srcs = [name + "_lib.cc"],
1615        tags = ["manual"],
1616        min_sdk_version = "32",
1617    )
1618
1619    test_apex(
1620        name = name,
1621        native_shared_libs_32 = [name + "_lib_cc"],
1622        # This will not cause the validation failure because it is testonly.
1623        min_sdk_version = "30",
1624        testonly = True,
1625        tests = [name + "_cc_test"],
1626        android_manifest = "AndroidManifest.xml",
1627    )
1628
1629    # It shouldn't complain about the min_sdk_version of the dep is too low.
1630    apex_testonly_with_manifest_test(
1631        name = test_name,
1632        target_under_test = name,
1633    )
1634
1635    return test_name
1636
1637def _apex_testonly_without_manifest_test_impl(ctx):
1638    env = analysistest.begin(ctx)
1639    actions = [a for a in analysistest.target_actions(env) if a.mnemonic == "Apexer"]
1640    asserts.true(
1641        env,
1642        len(actions) == 1,
1643        "No apexer action found: %s" % actions,
1644    )
1645    argv = actions[0].argv[:-1] + actions[0].argv[-1].split(" ")
1646
1647    asserts.true(
1648        env,
1649        "--test_only" in argv,
1650        "Calling apexer without --test_only when manifest file is not specified: %s" % argv,
1651    )
1652
1653    actions = [a for a in analysistest.target_actions(env) if a.mnemonic == "MarkAndroidManifestTestOnly"]
1654    asserts.true(
1655        env,
1656        len(actions) == 0,
1657        "MarkAndroidManifestTestOnly shouldn't be called when manifest file is not specified: %s" % actions,
1658    )
1659
1660    return analysistest.end(env)
1661
1662apex_testonly_without_manifest_test = analysistest.make(
1663    _apex_testonly_without_manifest_test_impl,
1664)
1665
1666def _test_apex_testonly_without_manifest():
1667    name = "apex_testonly_without_manifest"
1668    test_name = name + "_test"
1669
1670    test_apex(
1671        name = name,
1672        testonly = True,
1673    )
1674
1675    apex_testonly_without_manifest_test(
1676        name = test_name,
1677        target_under_test = name,
1678    )
1679
1680    return test_name
1681
1682def _apex_backing_file_test(ctx):
1683    env = analysistest.begin(ctx)
1684    actions = [a for a in analysistest.target_actions(env) if a.mnemonic == "FileWrite" and a.outputs.to_list()[0].basename.endswith("_backing.txt")]
1685    asserts.true(
1686        env,
1687        len(actions) == 1,
1688        "No FileWrite action found for creating <apex>_backing.txt file: %s" % actions,
1689    )
1690
1691    asserts.equals(env, ctx.attr.expected_content, actions[0].content)
1692    return analysistest.end(env)
1693
1694apex_backing_file_test = analysistest.make(
1695    _apex_backing_file_test,
1696    attrs = {
1697        "expected_content": attr.string(),
1698    },
1699)
1700
1701def _test_apex_backing_file():
1702    name = "apex_backing_file"
1703    test_name = name + "_test"
1704
1705    cc_library_shared(
1706        name = name + "_lib_cc",
1707        srcs = [name + "_lib.cc"],
1708        tags = ["manual"],
1709    )
1710
1711    test_apex(
1712        name = name,
1713        native_shared_libs_32 = [name + "_lib_cc"],
1714        android_manifest = "AndroidManifest.xml",
1715    )
1716
1717    apex_backing_file_test(
1718        name = test_name,
1719        target_under_test = name,
1720        expected_content = "apex_backing_file_lib_cc.so libc++.so\n",
1721    )
1722
1723    return test_name
1724
1725def _apex_installed_files_test(ctx):
1726    env = analysistest.begin(ctx)
1727    actions = [a for a in analysistest.target_actions(env) if a.mnemonic == "GenerateApexInstalledFileList"]
1728    asserts.true(
1729        env,
1730        len(actions) == 1,
1731        "No GenerateApexInstalledFileList action found for creating <apex>-installed-files.txt file: %s" % actions,
1732    )
1733
1734    asserts.equals(
1735        env,
1736        len(ctx.attr.expected_inputs),
1737        len(actions[0].inputs.to_list()),
1738        "Expected inputs length: %d, actual inputs length: %d" % (len(ctx.attr.expected_inputs), len(actions[0].inputs.to_list())),
1739    )
1740    for file in actions[0].inputs.to_list():
1741        asserts.true(
1742            env,
1743            file.basename in ctx.attr.expected_inputs,
1744            "Unexpected input: %s" % file.basename,
1745        )
1746    asserts.equals(env, ctx.attr.expected_output, actions[0].outputs.to_list()[0].basename)
1747    return analysistest.end(env)
1748
1749apex_installed_files_test = analysistest.make(
1750    _apex_installed_files_test,
1751    attrs = {
1752        "expected_inputs": attr.string_list(),
1753        "expected_output": attr.string(),
1754    },
1755)
1756
1757def _test_apex_installed_files():
1758    name = "apex_installed_files"
1759    test_name = name + "_test"
1760
1761    cc_library_shared(
1762        name = name + "_lib_cc",
1763        srcs = [name + "_lib.cc"],
1764        tags = ["manual"],
1765    )
1766
1767    test_apex(
1768        name = name,
1769        native_shared_libs_32 = [name + "_lib_cc"],
1770        android_manifest = "AndroidManifest.xml",
1771    )
1772
1773    apex_installed_files_test(
1774        name = test_name,
1775        target_under_test = name,
1776        expected_inputs = ["libc++.so", "apex_installed_files_lib_cc.so"],
1777        expected_output = "apex_installed_files-installed-files.txt",
1778    )
1779
1780    return test_name
1781
1782def _apex_symbols_used_by_apex_test(ctx):
1783    env = analysistest.begin(ctx)
1784    target_under_test = analysistest.target_under_test(env)
1785    actual = target_under_test[ApexInfo].symbols_used_by_apex
1786
1787    asserts.equals(env, ctx.attr.expected_path, actual.short_path)
1788
1789    return analysistest.end(env)
1790
1791apex_symbols_used_by_apex_test = analysistest.make(
1792    _apex_symbols_used_by_apex_test,
1793    attrs = {
1794        "expected_path": attr.string(),
1795    },
1796)
1797
1798def _test_apex_symbols_used_by_apex():
1799    name = "apex_with_symbols_used_by_apex"
1800    test_name = name + "_test"
1801
1802    test_apex(
1803        name = name,
1804    )
1805
1806    apex_symbols_used_by_apex_test(
1807        name = test_name,
1808        target_under_test = name,
1809        expected_path = "build/bazel/rules/apex/apex_with_symbols_used_by_apex_using.txt",
1810    )
1811
1812    return test_name
1813
1814def _apex_java_symbols_used_by_apex_test(ctx):
1815    env = analysistest.begin(ctx)
1816    target_under_test = analysistest.target_under_test(env)
1817    actual = target_under_test[ApexInfo].java_symbols_used_by_apex
1818
1819    asserts.equals(env, ctx.attr.expected_path, actual.short_path)
1820
1821    return analysistest.end(env)
1822
1823apex_java_symbols_used_by_apex_test = analysistest.make(
1824    _apex_java_symbols_used_by_apex_test,
1825    attrs = {
1826        "expected_path": attr.string(),
1827    },
1828)
1829
1830def _test_apex_java_symbols_used_by_apex():
1831    name = "apex_with_java_symbols_used_by_apex"
1832    test_name = name + "_test"
1833
1834    test_apex(
1835        name = name,
1836    )
1837
1838    apex_java_symbols_used_by_apex_test(
1839        name = test_name,
1840        target_under_test = name,
1841        expected_path = "build/bazel/rules/apex/apex_with_java_symbols_used_by_apex_using.xml",
1842    )
1843
1844    return test_name
1845
1846def _generate_notice_file_test(ctx):
1847    env = analysistest.begin(ctx)
1848    actions = [a for a in analysistest.target_actions(env) if a.mnemonic == "GenerateNoticeFile"]
1849    asserts.true(
1850        env,
1851        len(actions) == 1,
1852        "apex target should have a single GenerateNoticeFile action, found %s" % actions,
1853    )
1854    input_json = [f for f in actions[0].inputs.to_list() if f.basename.endswith("_licenses.json")]
1855    asserts.true(
1856        env,
1857        len(input_json) == 1,
1858        "apex GenerateNoticeFile should have a single input *_license.json file, got %s" % input_json,
1859    )
1860    outs = actions[0].outputs.to_list()
1861    asserts.true(
1862        env,
1863        len(outs) == 1 and outs[0].basename == "NOTICE.html.gz",
1864        "apex GenerateNoticeFile should generate a single NOTICE.html.gz file, got %s" % [o.short_path for o in outs],
1865    )
1866    return analysistest.end(env)
1867
1868apex_generate_notice_file_test = analysistest.make(_generate_notice_file_test)
1869
1870def _test_apex_generate_notice_file():
1871    name = "apex_notice_file"
1872    test_name = name + "_test"
1873    test_apex(name = name)
1874    apex_generate_notice_file_test(name = test_name, target_under_test = name)
1875    return test_name
1876
1877def _analysis_success_test(ctx):
1878    env = analysistest.begin(ctx)
1879
1880    # An empty analysis test that just ensures the target_under_test can be analyzed.
1881    return analysistest.end(env)
1882
1883analysis_success_test = analysistest.make(_analysis_success_test)
1884
1885def _test_apex_available():
1886    name = "apex_available"
1887    test_name = name + "_test"
1888    static_lib_name = name + "_lib_cc_static"
1889    lib_headers_name = name + "_lib_cc_headers"
1890
1891    cc_library_static(
1892        name = static_lib_name,
1893        srcs = ["src.cc"],
1894        tags = [
1895            "manual",
1896            "apex_available_checked_manual_for_testing",
1897            # anyapex.
1898            "apex_available=//apex_available:anyapex",
1899        ],
1900    )
1901    cc_library_headers(
1902        name = lib_headers_name,
1903        absolute_includes = ["include_dir"],
1904        tags = [
1905            "manual",
1906            "apex_available_checked_manual_for_testing",
1907            "apex_available=//apex_available:anyapex",
1908        ],
1909    )
1910    cc_library_shared(
1911        name = name + "_lib_cc",
1912        srcs = [name + "_lib.cc"],
1913        deps = [
1914            static_lib_name,
1915            lib_headers_name,
1916        ],
1917        tags = [
1918            "manual",
1919            "apex_available_checked_manual_for_testing",
1920            # Explicit name.
1921            "apex_available=" + name,
1922        ],
1923    )
1924    cc_library_shared(
1925        name = name + "_lib2_cc",
1926        srcs = [name + "_lib2.cc"],
1927        tags = [
1928            "manual",
1929            "apex_available_checked_manual_for_testing",
1930            # anyapex.
1931            "apex_available=//apex_available:anyapex",
1932        ],
1933    )
1934    test_apex(
1935        name = name,
1936        native_shared_libs_32 = [
1937            name + "_lib_cc",
1938            name + "_lib2_cc",
1939        ],
1940        android_manifest = "AndroidManifest.xml",
1941    )
1942
1943    analysis_success_test(
1944        name = test_name,
1945        target_under_test = name,
1946    )
1947
1948    return test_name
1949
1950def _test_apex_available_failure():
1951    name = "apex_available_failure"
1952    test_name = name + "_test"
1953    static_lib_name = name + "_lib_cc_static"
1954    lib_headers_name = name + "_lib_cc_headers"
1955
1956    cc_library_static(
1957        name = static_lib_name,
1958        srcs = ["src.cc"],
1959        tags = [
1960            "manual",
1961            "apex_available_checked_manual_for_testing",
1962        ],
1963    )
1964    cc_library_headers(
1965        name = lib_headers_name,
1966        absolute_includes = ["include_dir"],
1967        tags = [
1968            "manual",
1969            "apex_available_checked_manual_for_testing",
1970        ],
1971    )
1972    cc_library_shared(
1973        name = name + "_lib_cc",
1974        srcs = [name + "_lib.cc"],
1975        deps = [
1976            static_lib_name,
1977            lib_headers_name,
1978        ],
1979        tags = [
1980            "manual",
1981            "apex_available_checked_manual_for_testing",
1982        ],
1983    )
1984    cc_library_shared(
1985        name = name + "_lib2_cc",
1986        srcs = [name + "_lib2.cc"],
1987        tags = [
1988            "manual",
1989            "apex_available_checked_manual_for_testing",
1990            # anyapex.
1991            "apex_available=//apex_available:anyapex",
1992        ],
1993    )
1994    test_apex(
1995        name = name,
1996        native_shared_libs_32 = [
1997            name + "_lib_cc",
1998            name + "_lib2_cc",
1999        ],
2000        android_manifest = "AndroidManifest.xml",
2001    )
2002
2003    expect_failure_test(
2004        name = test_name,
2005        target_under_test = name,
2006        failure_message = """
2007Error in fail: `@//build/bazel/rules/apex:apex_available_failure` apex has transitive dependencies that do not include the apex in their apex_available tags:
2008    @//build/bazel/rules/apex:apex_available_failure_lib_cc_static; apex_available tags: []
2009    @//build/bazel/rules/apex:apex_available_failure_lib_cc_headers; apex_available tags: []
2010    @//build/bazel/rules/apex:apex_available_failure_lib_cc; apex_available tags: []""",
2011    )
2012    return test_name
2013
2014def _test_apex_available_with_base_apex():
2015    name = "apex_available_with_base_apex"
2016    test_name = name + "_test"
2017
2018    cc_library_shared(
2019        name = name + "_lib_cc",
2020        srcs = [name + "_lib.cc"],
2021        tags = [
2022            "manual",
2023            "apex_available_checked_manual_for_testing",
2024            # Explicit name.
2025            "apex_available=" + name + "_base",
2026        ],
2027    )
2028
2029    cc_library_shared(
2030        name = name + "_lib2_cc",
2031        srcs = [name + "_lib2.cc"],
2032        tags = [
2033            "manual",
2034            "apex_available_checked_manual_for_testing",
2035            # anyapex.
2036            "apex_available=//apex_available:anyapex",
2037        ],
2038    )
2039
2040    test_apex(
2041        name = name,
2042        native_shared_libs_32 = [
2043            name + "_lib_cc",
2044            name + "_lib2_cc",
2045        ],
2046        base_apex_name = name + "_base",
2047        android_manifest = "AndroidManifest.xml",
2048    )
2049
2050    analysis_success_test(
2051        name = test_name,
2052        target_under_test = name,
2053    )
2054
2055    return test_name
2056
2057def _apex_deps_validation_test_impl(ctx):
2058    env = analysistest.begin(ctx)
2059
2060    target_under_test = analysistest.target_under_test(env)
2061    asserts.new_set_equals(
2062        env,
2063        sets.make(ctx.attr.allowed_deps_manifest + ctx.attr._default_apex_deps),
2064        sets.make(apex_dep_infos_to_allowlist_strings(
2065            target_under_test[ApexDepsInfo].transitive_deps.to_list(),
2066        )),
2067    )
2068
2069    return analysistest.end(env)
2070
2071_apex_deps_validation_test = analysistest.make(
2072    _apex_deps_validation_test_impl,
2073    attrs = {
2074        "allowed_deps_manifest": attr.string_list(),
2075        "_default_apex_deps": attr.string_list(
2076            default = [
2077                "libc_llndk_headers(minSdkVersion:apex_inherit)",
2078                "libc_headers(minSdkVersion:apex_inherit)",
2079                "libc++abi(minSdkVersion:apex_inherit)",
2080                "libc++_static(minSdkVersion:apex_inherit)",
2081                "libc++(minSdkVersion:apex_inherit)",
2082                "libc++demangle(minSdkVersion:apex_inherit)",
2083            ],
2084        ),
2085    },
2086    config_settings = {
2087        "@//build/bazel/rules/apex:unsafe_disable_apex_allowed_deps_check": True,
2088    },
2089)
2090
2091def _test_apex_deps_validation():
2092    name = "apex_deps_validation"
2093    test_name = name + "_test"
2094
2095    aidl_interface_name = name + "_aidl_interface"
2096    aidl_interface(
2097        name = aidl_interface_name,
2098        ndk_config = {
2099            "enabled": True,
2100            "min_sdk_version": "28",
2101        },
2102        srcs = ["Foo.aidl"],
2103        tags = [
2104            "manual",
2105            "apex_available_checked_manual_for_testing",
2106            "apex_available=" + name,
2107            "apex_available=//apex_available:platform",
2108        ],
2109    )
2110
2111    specific_apex_available_name = name + "_specific_apex_available"
2112    cc_library_shared(
2113        name = specific_apex_available_name,
2114        srcs = [name + "_lib.cc"],
2115        tags = [
2116            "manual",
2117            "apex_available_checked_manual_for_testing",
2118            "apex_available=" + name,
2119            "apex_available=//apex_available:platform",
2120        ],
2121        min_sdk_version = "30",
2122    )
2123
2124    any_apex_available_name = name + "_any_apex_available"
2125    cc_library_shared(
2126        name = any_apex_available_name,
2127        srcs = [name + "_lib.cc"],
2128        implementation_dynamic_deps = [aidl_interface_name + "-V1-ndk"],
2129        tags = [
2130            "manual",
2131            "apex_available_checked_manual_for_testing",
2132            "apex_available=//apex_available:anyapex",
2133            "apex_available=//apex_available:platform",
2134        ],
2135        min_sdk_version = "30",
2136    )
2137
2138    no_platform_available_name = name + "_no_platform_available"
2139    cc_library_shared(
2140        name = no_platform_available_name,
2141        srcs = [name + "_lib.cc"],
2142        tags = [
2143            "manual",
2144            "apex_available_checked_manual_for_testing",
2145            "apex_available=//apex_available:anyapex",
2146        ],
2147        min_sdk_version = "30",
2148    )
2149
2150    no_platform_available_transitive_dep_name = name + "_no_platform_available_transitive_dep"
2151    cc_library_shared(
2152        name = no_platform_available_transitive_dep_name,
2153        srcs = [name + "_lib.cc"],
2154        tags = [
2155            "manual",
2156            "apex_available_checked_manual_for_testing",
2157            "apex_available=//apex_available:anyapex",
2158        ],
2159        min_sdk_version = "30",
2160    )
2161
2162    platform_available_but_dep_with_no_platform_available_name = name + "_shared_platform_available_but_dep_with_no_platform_available"
2163    cc_library_shared(
2164        name = platform_available_but_dep_with_no_platform_available_name,
2165        srcs = [name + "_lib.cc"],
2166        deps = [no_platform_available_transitive_dep_name],
2167        tags = [
2168            "manual",
2169            "apex_available_checked_manual_for_testing",
2170            "apex_available=//apex_available:anyapex",
2171            "apex_available=//apex_available:platform",
2172        ],
2173        min_sdk_version = "30",
2174    )
2175
2176    test_apex(
2177        name = name,
2178        native_shared_libs_32 = [
2179            specific_apex_available_name,
2180            any_apex_available_name,
2181            no_platform_available_name,
2182            platform_available_but_dep_with_no_platform_available_name,
2183        ],
2184        android_manifest = "AndroidManifest.xml",
2185        min_sdk_version = "30",
2186    )
2187
2188    _apex_deps_validation_test(
2189        name = test_name,
2190        target_under_test = name,
2191        allowed_deps_manifest = [
2192            specific_apex_available_name + "(minSdkVersion:30)",
2193            any_apex_available_name + "(minSdkVersion:30)",
2194            platform_available_but_dep_with_no_platform_available_name + "(minSdkVersion:30)",
2195            aidl_interface_name + "-V1-ndk(minSdkVersion:28)",
2196            "jni_headers(minSdkVersion:29)",
2197        ],
2198        tags = ["manual"],
2199    )
2200
2201    return test_name
2202
2203_MarchInfo = provider(fields = {"march": "list of march values found in the cc deps of this apex"})
2204
2205def _apex_transition_test(ctx):
2206    env = analysistest.begin(ctx)
2207    target_under_test = analysistest.target_under_test(env)
2208    march_values = target_under_test[_MarchInfo].march
2209
2210    asserts.equals(env, ctx.attr.expected, march_values.to_list())
2211
2212    return analysistest.end(env)
2213
2214def _cc_compile_test_aspect_impl(target, ctx):
2215    transitive_march = []
2216    for attr_deps in get_dep_targets(ctx.rule.attr, predicate = lambda target: _MarchInfo in target).values():
2217        for dep in attr_deps:
2218            transitive_march.append(dep[_MarchInfo].march)
2219    march_values = []
2220    if (target.label.name).startswith("apex_transition_lib"):
2221        for a in target.actions:
2222            if a.mnemonic == "CppCompile":
2223                march_values += [arg for arg in a.argv if "march" in arg]
2224    return [
2225        _MarchInfo(
2226            march = depset(
2227                direct = march_values,
2228                transitive = transitive_march,
2229            ),
2230        ),
2231    ]
2232
2233_cc_compile_test_aspect = aspect(
2234    implementation = _cc_compile_test_aspect_impl,
2235    attr_aspects = ["*"],
2236)
2237
2238apex_transition_test = analysistest.make(
2239    _apex_transition_test,
2240    attrs = {
2241        "expected": attr.string_list(),
2242    },
2243    extra_target_under_test_aspects = [_cc_compile_test_aspect],
2244)
2245
2246def _test_apex_transition():
2247    name = "apex_transition"
2248    test_name = name + "_test"
2249
2250    cc_library_shared(
2251        name = name + "_lib_cc",
2252        srcs = [name + "_lib.cc"],
2253        tags = ["manual"],
2254    )
2255
2256    cc_library_shared(
2257        name = name + "_lib2_cc",
2258        srcs = [name + "_lib2.cc"],
2259        tags = ["manual"],
2260    )
2261
2262    test_apex(
2263        name = name,
2264        native_shared_libs_32 = [name + "_lib_cc"],
2265        native_shared_libs_64 = [name + "_lib2_cc"],
2266        android_manifest = "AndroidManifest.xml",
2267    )
2268
2269    apex_transition_test(
2270        name = test_name + "_32",
2271        target_under_test = name,
2272        target_compatible_with = ["//build/bazel/platforms/os:android", "//build/bazel/platforms/arch:arm"],
2273        expected = ["-march=armv7-a"],
2274    )
2275
2276    apex_transition_test(
2277        name = test_name + "_64",
2278        target_under_test = name,
2279        target_compatible_with = ["//build/bazel/platforms/os:android", "//build/bazel/platforms/arch:arm64"],
2280        expected = ["-march=armv8-a"],
2281    )
2282
2283    return [test_name + "_32", test_name + "_64"]
2284
2285def _test_no_static_linking_for_stubs_lib():
2286    name = "no_static_linking_for_stubs_lib"
2287    test_name = name + "_test"
2288
2289    cc_library_static(
2290        name = name + "_static_unavailable_to_apex",
2291        tags = [
2292            "apex_available_checked_manual_for_testing",
2293            "manual",
2294        ],
2295    )
2296
2297    cc_library_shared(
2298        name = name + "_shared",
2299        deps = [name + "_static_unavailable_to_apex"],
2300        tags = [
2301            "apex_available=" + name,
2302            "apex_available_checked_manual_for_testing",
2303            "manual",
2304        ],
2305    )
2306
2307    test_apex(
2308        name = name,
2309        native_shared_libs_32 = [name + "_shared"],
2310    )
2311
2312    expect_failure_test(
2313        name = test_name,
2314        target_under_test = name,
2315        failure_message = """
2316Error in fail: `@//build/bazel/rules/apex:no_static_linking_for_stubs_lib` apex has transitive dependencies that do not include the apex in their apex_available tags:
2317    @//build/bazel/rules/apex:no_static_linking_for_stubs_lib_static_unavailable_to_apex; apex_available tags: []""",
2318    )
2319
2320    return test_name
2321
2322def _test_directly_included_stubs_lib_with_indirectly_static_variant():
2323    name = "directly_included_stubs_lib_with_indirectly_static_variant"
2324    test_name = name + "_test"
2325
2326    cc_binary(
2327        name = name + "bar",
2328        deps = [name + "_shared_bp2build_cc_library_static"],
2329        tags = [
2330            "apex_available=" + name,
2331            "apex_available_checked_manual_for_testing",
2332            "manual",
2333        ],
2334    )
2335
2336    cc_library_shared(
2337        name = name + "foo",
2338        deps = [name + "_shared_bp2build_cc_library_static"],
2339        tags = [
2340            "apex_available=" + name,
2341            "apex_available_checked_manual_for_testing",
2342            "manual",
2343        ],
2344    )
2345
2346    # This target is unavailable to apex but is allowed to be required by
2347    # cc_binary bar and cc_library_shared foo because its shared variant
2348    # is directly in the apex
2349    cc_library_static(
2350        name = name + "_shared_bp2build_cc_library_static",
2351        tags = [
2352            "apex_available_checked_manual_for_testing",
2353            "manual",
2354        ],
2355    )
2356
2357    cc_library_shared(
2358        name = name + "_shared",
2359        tags = [
2360            "apex_available=" + name,
2361            "apex_available_checked_manual_for_testing",
2362            "manual",
2363        ],
2364    )
2365
2366    test_apex(
2367        name = name,
2368        native_shared_libs_32 = [name + "_shared", name + "foo"],
2369        binaries = [name + "bar"],
2370    )
2371
2372    target_under_test_exist_test(
2373        name = test_name,
2374        target_under_test = name,
2375    )
2376
2377    return test_name
2378
2379def cc_library_shared_with_stubs(name):
2380    cc_library_shared(
2381        name = name,
2382        system_dynamic_deps = [],
2383        stl = "none",
2384        tags = ["manual"],
2385        stubs_symbol_file = name + ".map.txt",
2386    )
2387
2388    native.genrule(
2389        name = name + "_genrule_map_txt",
2390        outs = [name + ".map.txt"],
2391        cmd = "touch $@",
2392        tags = ["manual"],
2393    )
2394
2395    cc_stub_suite(
2396        name = name + "_stub_libs",
2397        soname = name + ".so",
2398        source_library_label = ":" + name,
2399        symbol_file = name + ".map.txt",
2400        versions = ["30"],
2401        tags = ["manual"],
2402    )
2403
2404    return [
2405        name,
2406        name + "_stub_libs",
2407    ]
2408
2409def _apex_in_unbundled_build_test(ctx):
2410    env = analysistest.begin(ctx)
2411    target_under_test = analysistest.target_under_test(env)
2412    mk_modules_to_install = target_under_test[ApexMkInfo].make_modules_to_install
2413    asserts.true(
2414        env,
2415        "apex_in_unbundled_build_libfoo" not in mk_modules_to_install,
2416        "stub libs apex_in_unbundled_build_libfoo should not be propagated " +
2417        "to make for installation in unbundled mode",
2418    )
2419    return analysistest.end(env)
2420
2421apex_in_unbundled_build_test = analysistest.make(
2422    _apex_in_unbundled_build_test,
2423    config_settings = {
2424        "//command_line_option:platforms": "@//build/bazel/tests/products:aosp_arm64_for_testing_unbundled_build",
2425    },
2426)
2427
2428def _test_apex_in_unbundled_build():
2429    name = "apex_in_unbundled_build"
2430    test_name = name + "_test"
2431
2432    [cc_library_shared_name, cc_stub_suite_name] = cc_library_shared_with_stubs(name + "_libfoo")
2433
2434    cc_binary(
2435        name = name + "_bar",
2436        tags = [
2437            "apex_available=" + name,
2438            "apex_available_checked_manual_for_testing",
2439            "manual",
2440        ],
2441        dynamic_deps = select({
2442            "//build/bazel/rules/apex:android-in_apex": [cc_stub_suite_name + "_current"],
2443            "//build/bazel/rules/apex:android-non_apex": [cc_library_shared_name],
2444        }),
2445    )
2446
2447    test_apex(
2448        name = name,
2449        binaries = [name + "_bar"],
2450    )
2451
2452    apex_in_unbundled_build_test(
2453        name = test_name,
2454        target_under_test = name,
2455    )
2456
2457    return test_name
2458
2459def _apex_in_bundled_build_test(ctx):
2460    env = analysistest.begin(ctx)
2461    target_under_test = analysistest.target_under_test(env)
2462    mk_modules_to_install = target_under_test[ApexMkInfo].make_modules_to_install
2463    asserts.true(
2464        env,
2465        "apex_in_bundled_build_libfoo" in mk_modules_to_install,
2466        "stub libs apex_in_unbundled_build_libfoo should be propagated " +
2467        "to make for installation in unbundled mode",
2468    )
2469
2470    return analysistest.end(env)
2471
2472apex_in_bundled_build_test = analysistest.make(
2473    _apex_in_bundled_build_test,
2474    config_settings = {
2475        "//command_line_option:platforms": "@//build/bazel/tests/products:aosp_arm64_for_testing",
2476    },
2477)
2478
2479def _test_apex_in_bundled_build():
2480    name = "apex_in_bundled_build"
2481    test_name = name + "_test"
2482
2483    [cc_library_shared_name, cc_stub_suite_name] = cc_library_shared_with_stubs(name + "_libfoo")
2484
2485    cc_binary(
2486        name = name + "_bar",
2487        tags = [
2488            "apex_available=" + name,
2489            "apex_available_checked_manual_for_testing",
2490            "manual",
2491        ],
2492        dynamic_deps = select({
2493            "//build/bazel/rules/apex:android-in_apex": [cc_stub_suite_name + "_current"],
2494            "//build/bazel/rules/apex:android-non_apex": [cc_library_shared_name],
2495        }),
2496    )
2497
2498    test_apex(
2499        name = name,
2500        binaries = [name + "_bar"],
2501    )
2502
2503    apex_in_bundled_build_test(
2504        name = test_name,
2505        target_under_test = name,
2506    )
2507
2508    return test_name
2509
2510def _apex_compression_test(ctx):
2511    env = analysistest.begin(ctx)
2512
2513    target = analysistest.target_under_test(env)
2514    asserts.true(
2515        env,
2516        target[ApexInfo].signed_compressed_output != None,
2517        "ApexInfo.signed_compressed_output should exist from compressible apex",
2518    )
2519
2520    return analysistest.end(env)
2521
2522apex_compression_test = analysistest.make(
2523    _apex_compression_test,
2524    config_settings = {
2525        "//command_line_option:platforms": "@//build/bazel/tests/products:aosp_arm64_for_testing",
2526    },
2527)
2528
2529def _test_apex_compression():
2530    name = "apex_compression"
2531    test_name = name + "_test"
2532
2533    test_apex(
2534        name = name,
2535        compressible = True,
2536    )
2537
2538    apex_compression_test(
2539        name = test_name,
2540        target_under_test = name,
2541    )
2542
2543    return test_name
2544
2545def _apex_no_compression_test(ctx):
2546    env = analysistest.begin(ctx)
2547
2548    target = analysistest.target_under_test(env)
2549    asserts.true(
2550        env,
2551        target[ApexInfo].signed_compressed_output == None,
2552        "ApexInfo.signed_compressed_output should not exist when compression_enabled is not specified",
2553    )
2554
2555    return analysistest.end(env)
2556
2557apex_no_compression_test = analysistest.make(
2558    _apex_no_compression_test,
2559    config_settings = {
2560        "//command_line_option:platforms": "@//build/bazel/tests/products:aosp_arm64_for_testing_no_compression",
2561    },
2562)
2563
2564def _test_apex_no_compression():
2565    name = "apex_no_compression"
2566    test_name = name + "_test"
2567
2568    test_apex(
2569        name = name,
2570    )
2571
2572    apex_no_compression_test(
2573        name = test_name,
2574        target_under_test = name,
2575    )
2576
2577    return test_name
2578
2579def _min_target_sdk_version_api_fingerprint_test(ctx):
2580    env = analysistest.begin(ctx)
2581    actions = analysistest.target_actions(env)
2582
2583    apexer_action = None
2584    for action in actions:
2585        if action.argv == None:
2586            continue
2587        for a in action.argv:
2588            if "--min_sdk_version" in a:
2589                apexer_action = action
2590                break
2591        if apexer_action != None:
2592            break
2593
2594    asserts.true(
2595        env,
2596        apexer_action != None,
2597        "There is no apexer action in all the actions",
2598    )
2599
2600    argv = apexer_action.argv[:-1] + apexer_action.argv[-1].split(" ")
2601    api_fingerprint_in_input = False
2602    api_fingerprint_path = None
2603    for f in apexer_action.inputs.to_list():
2604        if f.basename == "api_fingerprint.txt":
2605            api_fingerprint_in_input = True
2606            api_fingerprint_path = f.path
2607            break
2608
2609    asserts.true(
2610        env,
2611        api_fingerprint_in_input,
2612        "api_fingerprint.txt is not in the input files",
2613    )
2614
2615    expected_target_sdk_version = "123" + ".$(cat {})".format(api_fingerprint_path)
2616    target_sdk_version_index = argv.index("--target_sdk_version")
2617    asserts.equals(
2618        env,
2619        expected = expected_target_sdk_version,
2620        actual = argv[target_sdk_version_index + 1] + " " + argv[target_sdk_version_index + 2],
2621    )
2622
2623    min_sdk_version_index = argv.index("--min_sdk_version")
2624    if ctx.attr.min_sdk_version in ["current", "10000"]:
2625        expected_min_sdk_version = "123" + ".$(cat {})".format(api_fingerprint_path)
2626        actual_min_sdk_version = argv[min_sdk_version_index + 1] + " " + argv[min_sdk_version_index + 2]
2627    else:
2628        expected_min_sdk_version = ctx.attr.min_sdk_version
2629        actual_min_sdk_version = argv[min_sdk_version_index + 1]
2630    asserts.equals(
2631        env,
2632        expected = expected_min_sdk_version,
2633        actual = actual_min_sdk_version,
2634    )
2635
2636    return analysistest.end(env)
2637
2638min_target_sdk_version_api_fingerprint_test = analysistest.make(
2639    _min_target_sdk_version_api_fingerprint_test,
2640    attrs = {
2641        "min_sdk_version": attr.string(
2642            default = "current",
2643        ),
2644    },
2645    config_settings = {
2646        "//command_line_option:platforms": "@//build/bazel/tests/products:aosp_arm64_for_testing_unbundled_build",
2647        "@//build/bazel/rules/apex:unbundled_build_target_sdk_with_api_fingerprint": True,
2648        "@//build/bazel/rules/apex:platform_sdk_codename": "123",
2649    },
2650)
2651
2652def _test_min_target_sdk_version_api_fingerprint_min_sdk_version_specified():
2653    name = "min_target_sdk_version_api_fingerprint_min_sdk_version_specified"
2654    test_name = name + "_test"
2655    min_sdk_version = "30"
2656
2657    test_apex(
2658        name = name,
2659        min_sdk_version = min_sdk_version,
2660    )
2661
2662    min_target_sdk_version_api_fingerprint_test(
2663        name = test_name,
2664        target_under_test = name,
2665        min_sdk_version = min_sdk_version,
2666    )
2667
2668    return test_name
2669
2670def _test_min_target_sdk_version_api_fingerprint_min_sdk_version_not_specified():
2671    name = "min_target_sdk_version_api_fingerprint_min_sdk_version_not_specified"
2672    test_name = name + "_test"
2673
2674    test_apex(
2675        name = name,
2676    )
2677
2678    min_target_sdk_version_api_fingerprint_test(
2679        name = test_name,
2680        target_under_test = name,
2681    )
2682
2683    return test_name
2684
2685def _apex_sbom_test(ctx):
2686    env = analysistest.begin(ctx)
2687
2688    # Action GenerateSBOMMetadata
2689    actions = [a for a in analysistest.target_actions(env) if a.mnemonic == "GenerateSBOMMetadata"]
2690    asserts.true(
2691        env,
2692        len(actions) == 1,
2693        "No GenerateSBOMMetadata action found for creating <apex>-sbom-metadata.csv file: %s" % actions,
2694    )
2695
2696    input_files = [input.basename for input in actions[0].inputs.to_list()]
2697    asserts.true(
2698        env,
2699        "apex_sbom_lib_cc.so" in input_files,
2700        "No expected file in inputs of GenerateSBOMMetadata action",
2701    )
2702
2703    output_files = [output.basename for output in actions[0].outputs.to_list()]
2704    asserts.true(
2705        env,
2706        "apex_sbom.apex-sbom-metadata.csv" in output_files,
2707        "No expected file in outputs of GenerateSBOMMetadata action",
2708    )
2709
2710    # Action GenerateSBOM
2711    actions = [a for a in analysistest.target_actions(env) if a.mnemonic == "GenerateSBOM"]
2712    asserts.true(
2713        env,
2714        len(actions) == 1,
2715        "No GenerateSBOM action found for creating sbom.spdx.json file: %s" % actions,
2716    )
2717    input_files = [input.short_path for input in actions[0].inputs.to_list()]
2718    expected_input_files = [
2719        "build/bazel/rules/apex/apex_sbom.apex",
2720        "build/bazel/rules/apex/apex_sbom.apex-sbom-metadata.csv",
2721        "build/make/tools/sbom/generate-sbom",
2722        "build/bazel/rules/apex/apex_sbom_lib_cc.so",
2723        "build/bazel/rules/apex/METADATA",
2724    ]
2725    asserts.true(
2726        env,
2727        all([f in input_files for f in expected_input_files]),
2728        "Missing input files: %s" % input_files,
2729    )
2730
2731    output_files = [output.basename for output in actions[0].outputs.to_list()]
2732    expected_output_files = [
2733        "apex_sbom.apex.spdx.json",
2734        "apex_sbom.apex-fragment.spdx",
2735    ]
2736    asserts.true(
2737        env,
2738        all([f in output_files for f in expected_output_files]),
2739        "Missing output files: %s" % input_files,
2740    )
2741
2742    return analysistest.end(env)
2743
2744apex_sbom_test = analysistest.make(
2745    _apex_sbom_test,
2746)
2747
2748def _test_apex_sbom():
2749    name = "apex_sbom"
2750    test_name = name + "_test"
2751
2752    cc_library_shared(
2753        name = name + "_lib_cc",
2754        srcs = [name + "_lib.cc"],
2755        tags = ["manual"],
2756    )
2757
2758    test_apex(
2759        name = name,
2760        native_shared_libs_32 = [name + "_lib_cc"],
2761        android_manifest = "AndroidManifest.xml",
2762    )
2763
2764    apex_sbom_test(
2765        name = test_name,
2766        target_under_test = name,
2767    )
2768
2769    return test_name
2770
2771def apex_test_suite(name):
2772    native.test_suite(
2773        name = name,
2774        tests = [
2775            _test_canned_fs_config_basic(),
2776            _test_canned_fs_config_custom(),
2777            _test_canned_fs_config_binaries(),
2778            _test_canned_fs_config_native_shared_libs_arm(),
2779            _test_canned_fs_config_native_shared_libs_arm64(),
2780            _test_canned_fs_config_prebuilts(),
2781            _test_canned_fs_config_prebuilts_sort_order(),
2782            _test_canned_fs_config_runtime_deps(),
2783            _test_apex_manifest(),
2784            _test_apex_manifest_min_sdk_version(),
2785            _test_apex_manifest_min_sdk_version_current(),
2786            _test_apex_manifest_min_sdk_version_override(),
2787            _test_apex_manifest_dependencies_nodep(),
2788            _test_apex_manifest_dependencies_cc_binary_bionic_deps(),
2789            _test_apex_manifest_dependencies_cc_library_shared_bionic_deps(),
2790            _test_apex_manifest_dependencies_requires(),
2791            _test_apex_manifest_dependencies_provides(),
2792            _test_apex_manifest_dependencies_selfcontained(),
2793            _test_apex_manifest_dependencies_cc_binary(),
2794            _test_logging_parent_flag(),
2795            _test_package_name(),
2796            _test_package_name_override_from_config(),
2797            _test_generate_file_contexts(),
2798            _test_default_apex_manifest_version(),
2799            _test_override_apex_manifest_version(),
2800            _test_min_sdk_version_failure(),
2801            _test_min_sdk_version_failure_transitive(),
2802            _test_apex_certificate_none(),
2803            _test_apex_certificate_name(),
2804            _test_apex_certificate_label(),
2805            _test_apex_certificate_label_with_overrides(),
2806            _test_min_sdk_version_apex_inherit(),
2807            _test_min_sdk_version_apex_inherit_override_min_sdk_tiramisu(),
2808            _test_apex_testonly_with_manifest(),
2809            _test_apex_provides_base_zip_files(),
2810            _test_apex_testonly_without_manifest(),
2811            _test_apex_backing_file(),
2812            _test_apex_symbols_used_by_apex(),
2813            _test_apex_installed_files(),
2814            _test_apex_java_symbols_used_by_apex(),
2815            _test_apex_generate_notice_file(),
2816            _test_apex_available(),
2817            _test_apex_available_failure(),
2818            _test_apex_available_with_base_apex(),
2819            _test_apex_deps_validation(),
2820            _test_no_static_linking_for_stubs_lib(),
2821            _test_directly_included_stubs_lib_with_indirectly_static_variant(),
2822            _test_apex_in_unbundled_build(),
2823            _test_apex_in_bundled_build(),
2824            _test_apex_compression(),
2825            _test_apex_no_compression(),
2826            _test_min_target_sdk_version_api_fingerprint_min_sdk_version_specified(),
2827            _test_min_target_sdk_version_api_fingerprint_min_sdk_version_not_specified(),
2828            _test_apex_sbom(),
2829        ] + _test_apex_transition(),
2830    )
2831