1*795d594fSAndroid Build Coastguard Worker#!/usr/bin/env python3 2*795d594fSAndroid Build Coastguard Worker# 3*795d594fSAndroid Build Coastguard Worker# Copyright (C) 2014 The Android Open Source Project 4*795d594fSAndroid Build Coastguard Worker# 5*795d594fSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*795d594fSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*795d594fSAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*795d594fSAndroid Build Coastguard Worker# 9*795d594fSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*795d594fSAndroid Build Coastguard Worker# 11*795d594fSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*795d594fSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*795d594fSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*795d594fSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*795d594fSAndroid Build Coastguard Worker# limitations under the License. 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Workerimport argparse 18*795d594fSAndroid Build Coastguard Workerimport os 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Workerfrom common.archs import archs_list 21*795d594fSAndroid Build Coastguard Workerfrom common.logger import Logger 22*795d594fSAndroid Build Coastguard Workerfrom file_format.c1visualizer.parser import parse_c1_visualizer_stream 23*795d594fSAndroid Build Coastguard Workerfrom file_format.checker.parser import parse_checker_stream 24*795d594fSAndroid Build Coastguard Workerfrom match.file import match_files 25*795d594fSAndroid Build Coastguard Worker 26*795d594fSAndroid Build Coastguard Worker 27*795d594fSAndroid Build Coastguard Workerdef parse_arguments(): 28*795d594fSAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 29*795d594fSAndroid Build Coastguard Worker parser.add_argument("tested_file", 30*795d594fSAndroid Build Coastguard Worker help="text file the checks should be verified against") 31*795d594fSAndroid Build Coastguard Worker parser.add_argument("source_path", nargs="?", 32*795d594fSAndroid Build Coastguard Worker help="path to file/folder with checking annotations") 33*795d594fSAndroid Build Coastguard Worker parser.add_argument("--check-prefix", dest="check_prefix", default="CHECK", metavar="PREFIX", 34*795d594fSAndroid Build Coastguard Worker help="prefix of checks in the test files (default: CHECK)") 35*795d594fSAndroid Build Coastguard Worker parser.add_argument("--list-passes", dest="list_passes", action="store_true", 36*795d594fSAndroid Build Coastguard Worker help="print a list of all passes found in the tested file") 37*795d594fSAndroid Build Coastguard Worker parser.add_argument("--dump-pass", dest="dump_pass", metavar="PASS", 38*795d594fSAndroid Build Coastguard Worker help="print a compiler pass dump") 39*795d594fSAndroid Build Coastguard Worker parser.add_argument("--arch", dest="arch", choices=archs_list, 40*795d594fSAndroid Build Coastguard Worker help="Run tests for the specified target architecture.") 41*795d594fSAndroid Build Coastguard Worker parser.add_argument("--debuggable", action="store_true", 42*795d594fSAndroid Build Coastguard Worker help="Run tests for debuggable code.") 43*795d594fSAndroid Build Coastguard Worker parser.add_argument("--print-cfg", action="store_true", default="True", dest="print_cfg", 44*795d594fSAndroid Build Coastguard Worker help="Print the whole cfg file in case of test failure (default)") 45*795d594fSAndroid Build Coastguard Worker parser.add_argument("--no-print-cfg", action="store_false", default="True", dest="print_cfg", 46*795d594fSAndroid Build Coastguard Worker help="Don't print the whole cfg file in case of test failure") 47*795d594fSAndroid Build Coastguard Worker parser.add_argument("-q", "--quiet", action="store_true", 48*795d594fSAndroid Build Coastguard Worker help="print only errors") 49*795d594fSAndroid Build Coastguard Worker return parser.parse_args() 50*795d594fSAndroid Build Coastguard Worker 51*795d594fSAndroid Build Coastguard Worker 52*795d594fSAndroid Build Coastguard Workerdef list_passes(output_filename): 53*795d594fSAndroid Build Coastguard Worker c1_file = parse_c1_visualizer_stream(output_filename, open(output_filename, "r")) 54*795d594fSAndroid Build Coastguard Worker for compiler_pass in c1_file.passes: 55*795d594fSAndroid Build Coastguard Worker Logger.log(compiler_pass.name) 56*795d594fSAndroid Build Coastguard Worker 57*795d594fSAndroid Build Coastguard Worker 58*795d594fSAndroid Build Coastguard Workerdef dump_pass(output_filename, pass_name): 59*795d594fSAndroid Build Coastguard Worker c1_file = parse_c1_visualizer_stream(output_filename, open(output_filename, "r")) 60*795d594fSAndroid Build Coastguard Worker compiler_pass = c1_file.find_pass(pass_name) 61*795d594fSAndroid Build Coastguard Worker if compiler_pass: 62*795d594fSAndroid Build Coastguard Worker max_line_no = compiler_pass.start_line_no + len(compiler_pass.body) 63*795d594fSAndroid Build Coastguard Worker len_line_no = len(str(max_line_no)) + 2 64*795d594fSAndroid Build Coastguard Worker cur_line_no = compiler_pass.start_line_no 65*795d594fSAndroid Build Coastguard Worker for line in compiler_pass.body: 66*795d594fSAndroid Build Coastguard Worker Logger.log((str(cur_line_no) + ":").ljust(len_line_no) + line) 67*795d594fSAndroid Build Coastguard Worker cur_line_no += 1 68*795d594fSAndroid Build Coastguard Worker else: 69*795d594fSAndroid Build Coastguard Worker Logger.fail('Pass "{}" not found in the output'.format(pass_name)) 70*795d594fSAndroid Build Coastguard Worker 71*795d594fSAndroid Build Coastguard Worker 72*795d594fSAndroid Build Coastguard Workerdef find_checker_files(path): 73*795d594fSAndroid Build Coastguard Worker """ Returns a list of files to scan for check annotations in the given path. 74*795d594fSAndroid Build Coastguard Worker Path to a file is returned as a single-element list, directories are 75*795d594fSAndroid Build Coastguard Worker recursively traversed and all '.java', '.j', and '.smali' files returned. 76*795d594fSAndroid Build Coastguard Worker """ 77*795d594fSAndroid Build Coastguard Worker if not path: 78*795d594fSAndroid Build Coastguard Worker Logger.fail("No source path provided") 79*795d594fSAndroid Build Coastguard Worker elif os.path.isfile(path): 80*795d594fSAndroid Build Coastguard Worker return [path] 81*795d594fSAndroid Build Coastguard Worker elif os.path.isdir(path): 82*795d594fSAndroid Build Coastguard Worker found_files = [] 83*795d594fSAndroid Build Coastguard Worker for root, dirs, files in os.walk(path): 84*795d594fSAndroid Build Coastguard Worker for file in files: 85*795d594fSAndroid Build Coastguard Worker extension = os.path.splitext(file)[1] 86*795d594fSAndroid Build Coastguard Worker if extension in [".java", ".smali", ".j"]: 87*795d594fSAndroid Build Coastguard Worker found_files.append(os.path.join(root, file)) 88*795d594fSAndroid Build Coastguard Worker return found_files 89*795d594fSAndroid Build Coastguard Worker else: 90*795d594fSAndroid Build Coastguard Worker Logger.fail('Source path "{}" not found'.format(path)) 91*795d594fSAndroid Build Coastguard Worker 92*795d594fSAndroid Build Coastguard Worker 93*795d594fSAndroid Build Coastguard Workerdef run_tests(check_prefix, check_path, output_filename, target_arch, debuggable_mode, print_cfg): 94*795d594fSAndroid Build Coastguard Worker c1_file = parse_c1_visualizer_stream(output_filename, open(output_filename, "r")) 95*795d594fSAndroid Build Coastguard Worker for check_filename in find_checker_files(check_path): 96*795d594fSAndroid Build Coastguard Worker checker_file = parse_checker_stream(os.path.basename(check_filename), 97*795d594fSAndroid Build Coastguard Worker check_prefix, 98*795d594fSAndroid Build Coastguard Worker open(check_filename, "r"), 99*795d594fSAndroid Build Coastguard Worker target_arch) 100*795d594fSAndroid Build Coastguard Worker match_files(checker_file, c1_file, target_arch, debuggable_mode, print_cfg) 101*795d594fSAndroid Build Coastguard Worker 102*795d594fSAndroid Build Coastguard Worker 103*795d594fSAndroid Build Coastguard Workerif __name__ == "__main__": 104*795d594fSAndroid Build Coastguard Worker args = parse_arguments() 105*795d594fSAndroid Build Coastguard Worker 106*795d594fSAndroid Build Coastguard Worker if args.quiet: 107*795d594fSAndroid Build Coastguard Worker Logger.Verbosity = Logger.Level.ERROR 108*795d594fSAndroid Build Coastguard Worker 109*795d594fSAndroid Build Coastguard Worker if args.list_passes: 110*795d594fSAndroid Build Coastguard Worker list_passes(args.tested_file) 111*795d594fSAndroid Build Coastguard Worker elif args.dump_pass: 112*795d594fSAndroid Build Coastguard Worker dump_pass(args.tested_file, args.dump_pass) 113*795d594fSAndroid Build Coastguard Worker else: 114*795d594fSAndroid Build Coastguard Worker run_tests(args.check_prefix, args.source_path, args.tested_file, args.arch, args.debuggable, 115*795d594fSAndroid Build Coastguard Worker args.print_cfg) 116