1#!/usr/bin/env python3
2#
3# Copyright (C) 2021 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#      http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17""" This script generates the Android.run-test.bp build file"""
18
19import glob
20import json
21import os
22import textwrap
23import sys
24
25def main():
26  os.chdir(os.path.dirname(__file__))
27  with open("Android.run-test.bp", mode="wt") as f:
28    f.write(textwrap.dedent(f"""
29      // This file was generated by {os.path.basename(__file__)}
30      // It is not necessary to regenerate it when tests are added/removed/modified.
31
32      TEST_BUILD_COMMON_ARGS = "$(location run_test_build.py) --out $(out) " +
33          "--bootclasspath $(location :art-run-test-bootclasspath) " +
34          "--d8 $(location d8) " +
35          "--jasmin $(location jasmin) " +
36          "--rewrapper $(location rewrapper) " +
37          "--smali $(location android-smali) " +
38          "--soong_zip $(location soong_zip) " +
39          "--zipalign $(location zipalign) "
40    """).lstrip())
41    for mode in ["host", "target", "jvm"]:
42      names = []
43      # Group the tests into shards based on the last two digits of the test number.
44      # This keeps the number of generated genrules low so we don't overwhelm soong,
45      # but it still allows iterating on single test without recompiling all tests.
46      for shard in ["{:02}".format(i) for i in range(100)]:
47        name = f"art-run-test-{mode}-data-shard{shard}"
48        names.append(name)
49        f.write(textwrap.dedent(f"""
50          java_genrule {{
51              name: "{name}-tmp",
52              out: ["{name}.zip"],
53              srcs: [
54                  "?{shard}-*/**/*",
55                  "??{shard}-*/**/*",
56              ],
57              cmd: TEST_BUILD_COMMON_ARGS + "--mode {mode} --test-dir-regex 'art/test/..?{shard}-' $(in)",
58              defaults: ["art-run-test-{mode}-data-defaults"],
59          }}
60
61          // Install in the output directory to make it accessible for tests.
62          prebuilt_etc_host {{
63              name: "{name}",
64              src: ":{name}-tmp",
65              sub_dir: "art",
66              filename: "{name}.zip",
67          }}
68          """))
69
70      # Build all hiddenapi tests in their own shard.
71      # This removes the dependency on hiddenapi from all other shards,
72      # which in turn removes dependency on ART C++ source code.
73      name = "art-run-test-{mode}-data-shardHiddenApi".format(mode=mode)
74      names.append(name)
75      f.write(textwrap.dedent(f"""
76        java_genrule {{
77            name: "{name}-tmp",
78            out: ["{name}.zip"],
79            srcs: [
80                "???-*hiddenapi*/**/*",
81                "????-*hiddenapi*/**/*",
82            ],
83            defaults: ["art-run-test-{mode}-data-defaults"],
84            tools: ["hiddenapi"],
85            cmd: TEST_BUILD_COMMON_ARGS + "--hiddenapi $(location hiddenapi) --mode {mode} --test-dir-regex 'art/test/....?-[^/]*hiddenapi' $(in)",
86        }}
87
88        // Install in the output directory to make it accessible for tests.
89        prebuilt_etc_host {{
90            name: "{name}",
91            src: ":{name}-tmp",
92            sub_dir: "art",
93            filename: "{name}.zip",
94        }}
95        """))
96
97      f.write(textwrap.dedent(f"""
98        genrule_defaults {{
99            name: "art-run-test-{mode}-data-defaults",
100            tool_files: [
101                "run_test_build.py",
102                ":art-run-test-bootclasspath",
103            ],
104            srcs: [
105                // Since genrules are sandboxed, all the sources they use must be listed in
106                // the Android.bp file. Some tests have symlinks to files from other tests, and
107                // those must also be listed to avoid a dangling symlink in the sandbox.
108                "jvmti-common/*.java",
109                "utils/python/**/*.py",
110                ":development_docs",
111                ":asm-9.6-filegroup",
112                ":ojluni-AbstractCollection",
113                "988-method-trace/expected-stdout.txt",
114                "988-method-trace/expected-stderr.txt",
115                "988-method-trace/src/art/Test988Intrinsics.java",
116                "988-method-trace/src/art/Test988.java",
117                "988-method-trace/trace_fib.cc",
118                "1953-pop-frame/src/art/Test1953.java",
119                "1953-pop-frame/src/art/SuspendEvents.java",
120            ],
121            tools: [
122                "android-smali",
123                "d8",
124                "jasmin",
125                "rewrapper",
126                "soong_zip",
127                "zipalign",
128            ],
129        }}
130        """))
131
132      name = "art-run-test-{mode}-data-merged".format(mode=mode)
133      srcs = ("\n"+" "*16).join('":{}-tmp",'.format(n) for n in names)
134      deps = ("\n"+" "*16).join('"{}",'.format(n) for n in names)
135      f.write(textwrap.dedent(f"""
136        java_genrule {{
137            name: "{name}-tmp",
138            out: ["{name}.zip"],
139            srcs: [
140                {srcs}
141            ],
142            tools: ["merge_zips"],
143            cmd: "$(location merge_zips) $(out) $(in)",
144        }}
145
146        // Install in the output directory to make it accessible for tests.
147        prebuilt_etc_host {{
148            name: "{name}",
149            src: ":{name}-tmp",
150            required: [
151                {deps}
152            ],
153            sub_dir: "art",
154            filename: "{name}.zip",
155        }}
156        """))
157
158      name = "art-run-test-{mode}-data".format(mode=mode)
159      srcs = ("\n"+" "*16).join('":{}-tmp",'.format(n) for n in names)
160      deps = ("\n"+" "*16).join('"{}",'.format(n) for n in names)
161      f.write(textwrap.dedent(f"""
162        // Phony target used to build all shards
163        java_genrule {{
164            name: "{name}-tmp",
165            out: ["{name}.txt"],
166            srcs: [
167                {srcs}
168            ],
169            cmd: "echo $(in) > $(out)",
170        }}
171
172        // Phony target used to install all shards
173        prebuilt_etc_host {{
174            name: "{name}",
175            src: ":{name}-tmp",
176            required: [
177                {deps}
178            ],
179            sub_dir: "art",
180            filename: "{name}.txt",
181        }}
182        """))
183
184if __name__ == "__main__":
185  main()
186