#!/usr/bin/python3 # # Copyright (C) 2015 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Generate java test files for test 966. """ import generate_smali as base import os import sys from pathlib import Path BUILD_TOP = os.getenv("ANDROID_BUILD_TOP") if BUILD_TOP is None: print("ANDROID_BUILD_TOP not set. Please run build/envsetup.sh", file=sys.stderr) sys.exit(1) # Allow us to import mixins. sys.path.append(str(Path(BUILD_TOP)/"art"/"test"/"utils"/"python")) import testgen.mixins as mixins import functools import operator import subprocess class JavaConverter(mixins.DumpMixin, mixins.Named, mixins.JavaFileMixin): """ A class that can convert a SmaliFile to a JavaFile. """ def __init__(self, inner): self.inner = inner def get_name(self): """Gets the name of this file.""" return self.inner.get_name() def __str__(self): out = "" for line in str(self.inner).splitlines(keepends = True): if line.startswith("#"): out += line[1:] return out class Compiler: def __init__(self, sources, javac, temp_dir, classes_dir): self.javac = javac self.temp_dir = temp_dir self.classes_dir = classes_dir self.sources = sources def compile_files(self, args, files): """ Compile the files given with the arguments given. """ args = args.split() files = list(map(str, files)) cmd = ['sh', '-a', '-e', '--', str(self.javac)] + args + sorted(files) subprocess.check_call(cmd) def execute(self): """ Compiles this test, doing partial compilation as necessary. """ # Compile Main and all classes first. Force all interfaces to be default so that there will be # no compiler problems (works since classes only implement 1 interface). for f in self.sources: if isinstance(f, base.TestInterface): JavaConverter(f.get_specific_version(base.InterfaceType.default)).dump(self.temp_dir) else: JavaConverter(f).dump(self.temp_dir) self.compile_files("-d {}".format(self.classes_dir), self.temp_dir.glob("*.java")) # Now we compile the interfaces ifaces = set(i for i in self.sources if isinstance(i, base.TestInterface)) filters = (lambda a: a.is_default(), lambda a: not a.is_default()) converters = (lambda a: JavaConverter(a.get_specific_version(base.InterfaceType.default)), lambda a: JavaConverter(a.get_specific_version(base.InterfaceType.empty))) while len(ifaces) != 0: for iface_filter, iface_converter in zip(filters, converters): # Find those ifaces where there are no (uncompiled) interfaces that are subtypes. tops = set(filter(lambda a: iface_filter(a) and not any(map(lambda i: a in i.get_super_types(), ifaces)), ifaces)) files = [] # Dump these ones, they are getting compiled. for f in tops: out = JavaConverter(f) out.dump(self.temp_dir) files.append(self.temp_dir / out.get_file_name()) # Force all superinterfaces of these to be empty so there will be no conflicts overrides = functools.reduce(operator.or_, map(lambda i: i.get_super_types(), tops), set()) for overridden in overrides: out = iface_converter(overridden) out.dump(self.temp_dir) files.append(self.temp_dir / out.get_file_name()) self.compile_files("-d {outdir} -cp {outdir}".format(outdir = self.classes_dir), files) # Remove these from the set of interfaces to be compiled. ifaces -= tops return def main(argv): javac_exec = Path(argv[1]) if not javac_exec.exists() or not javac_exec.is_file(): print("{} is not a shell script".format(javac_exec), file=sys.stderr) sys.exit(1) temp_dir = Path(argv[2]) if not temp_dir.exists() or not temp_dir.is_dir(): print("{} is not a valid source dir".format(temp_dir), file=sys.stderr) sys.exit(1) classes_dir = Path(argv[3]) if not classes_dir.exists() or not classes_dir.is_dir(): print("{} is not a valid classes directory".format(classes_dir), file=sys.stderr) sys.exit(1) expected_txt = Path(argv[4]) mainclass, all_files = base.create_all_test_files() with expected_txt.open('w') as out: print(mainclass.get_expected(), file=out) Compiler(all_files, javac_exec, temp_dir, classes_dir).execute() if __name__ == '__main__': main(sys.argv)