Alex Light | 9139e00 | 2015-10-09 15:59:48 -0700 | [diff] [blame] | 1 | #!/usr/bin/python3 |
| 2 | # |
| 3 | # Copyright (C) 2015 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 | """ |
| 18 | Generate java test files for test 966. |
| 19 | """ |
| 20 | |
| 21 | import generate_smali as base |
| 22 | import os |
| 23 | import sys |
| 24 | from pathlib import Path |
| 25 | |
| 26 | BUILD_TOP = os.getenv("ANDROID_BUILD_TOP") |
| 27 | if BUILD_TOP is None: |
| 28 | print("ANDROID_BUILD_TOP not set. Please run build/envsetup.sh", file=sys.stderr) |
| 29 | sys.exit(1) |
| 30 | |
| 31 | # Allow us to import mixins. |
| 32 | sys.path.append(str(Path(BUILD_TOP)/"art"/"test"/"utils"/"python")) |
| 33 | |
| 34 | import testgen.mixins as mixins |
| 35 | import functools |
| 36 | import operator |
| 37 | import subprocess |
| 38 | |
| 39 | class JavaConverter(mixins.DumpMixin, mixins.Named, mixins.JavaFileMixin): |
| 40 | """ |
| 41 | A class that can convert a SmaliFile to a JavaFile. |
| 42 | """ |
| 43 | def __init__(self, inner): |
| 44 | self.inner = inner |
| 45 | |
| 46 | def get_name(self): |
| 47 | """Gets the name of this file.""" |
| 48 | return self.inner.get_name() |
| 49 | |
| 50 | def __str__(self): |
| 51 | out = "" |
| 52 | for line in str(self.inner).splitlines(keepends = True): |
| 53 | if line.startswith("#"): |
| 54 | out += line[1:] |
| 55 | return out |
| 56 | |
| 57 | class Compiler: |
| 58 | def __init__(self, sources, javac, temp_dir, classes_dir): |
| 59 | self.javac = javac |
| 60 | self.temp_dir = temp_dir |
| 61 | self.classes_dir = classes_dir |
| 62 | self.sources = sources |
| 63 | |
| 64 | def compile_files(self, args, files): |
| 65 | """ |
| 66 | Compile the files given with the arguments given. |
| 67 | """ |
| 68 | args = args.split() |
| 69 | files = list(map(str, files)) |
| 70 | cmd = ['sh', '-a', '-e', '--', str(self.javac)] + args + files |
| 71 | print("Running compile command: {}".format(cmd)) |
| 72 | subprocess.check_call(cmd) |
| 73 | print("Compiled {} files".format(len(files))) |
| 74 | |
| 75 | def execute(self): |
| 76 | """ |
| 77 | Compiles this test, doing partial compilation as necessary. |
| 78 | """ |
| 79 | # Compile Main and all classes first. Force all interfaces to be default so that there will be |
| 80 | # no compiler problems (works since classes only implement 1 interface). |
| 81 | for f in self.sources: |
| 82 | if isinstance(f, base.TestInterface): |
| 83 | JavaConverter(f.get_specific_version(base.InterfaceType.default)).dump(self.temp_dir) |
| 84 | else: |
| 85 | JavaConverter(f).dump(self.temp_dir) |
| 86 | self.compile_files("-d {}".format(self.classes_dir), self.temp_dir.glob("*.java")) |
| 87 | |
| 88 | # Now we compile the interfaces |
| 89 | ifaces = set(i for i in self.sources if isinstance(i, base.TestInterface)) |
| 90 | while len(ifaces) != 0: |
| 91 | # Find those ifaces where there are no (uncompiled) interfaces that are subtypes. |
| 92 | tops = set(filter(lambda a: not any(map(lambda i: a in i.get_super_types(), ifaces)), ifaces)) |
| 93 | files = [] |
| 94 | # Dump these ones, they are getting compiled. |
| 95 | for f in tops: |
| 96 | out = JavaConverter(f) |
| 97 | out.dump(self.temp_dir) |
| 98 | files.append(self.temp_dir / out.get_file_name()) |
| 99 | # Force all superinterfaces of these to be empty so there will be no conflicts |
| 100 | overrides = functools.reduce(operator.or_, map(lambda i: i.get_super_types(), tops), set()) |
| 101 | for overridden in overrides: |
| 102 | out = JavaConverter(overridden.get_specific_version(base.InterfaceType.empty)) |
| 103 | out.dump(self.temp_dir) |
| 104 | files.append(self.temp_dir / out.get_file_name()) |
| 105 | self.compile_files("-d {outdir} -cp {outdir}".format(outdir = self.classes_dir), files) |
| 106 | # Remove these from the set of interfaces to be compiled. |
| 107 | ifaces -= tops |
| 108 | print("Finished compiling all files.") |
| 109 | return |
| 110 | |
| 111 | def main(argv): |
| 112 | javac_exec = Path(argv[1]) |
| 113 | if not javac_exec.exists() or not javac_exec.is_file(): |
| 114 | print("{} is not a shell script".format(javac_exec), file=sys.stderr) |
| 115 | sys.exit(1) |
| 116 | temp_dir = Path(argv[2]) |
| 117 | if not temp_dir.exists() or not temp_dir.is_dir(): |
| 118 | print("{} is not a valid source dir".format(temp_dir), file=sys.stderr) |
| 119 | sys.exit(1) |
| 120 | classes_dir = Path(argv[3]) |
| 121 | if not classes_dir.exists() or not classes_dir.is_dir(): |
| 122 | print("{} is not a valid classes directory".format(classes_dir), file=sys.stderr) |
| 123 | sys.exit(1) |
| 124 | expected_txt = Path(argv[4]) |
| 125 | mainclass, all_files = base.create_all_test_files() |
| 126 | |
| 127 | with expected_txt.open('w') as out: |
| 128 | print(mainclass.get_expected(), file=out) |
| 129 | print("Wrote expected output") |
| 130 | |
| 131 | Compiler(all_files, javac_exec, temp_dir, classes_dir).execute() |
| 132 | |
| 133 | if __name__ == '__main__': |
| 134 | main(sys.argv) |