1#!/usr/bin/env python3 2# 3# Copyright (C) 2014 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 17import argparse 18import os 19 20from common.archs import archs_list 21from common.logger import Logger 22from file_format.c1visualizer.parser import parse_c1_visualizer_stream 23from file_format.checker.parser import parse_checker_stream 24from match.file import match_files 25 26 27def parse_arguments(): 28 parser = argparse.ArgumentParser() 29 parser.add_argument("tested_file", 30 help="text file the checks should be verified against") 31 parser.add_argument("source_path", nargs="?", 32 help="path to file/folder with checking annotations") 33 parser.add_argument("--check-prefix", dest="check_prefix", default="CHECK", metavar="PREFIX", 34 help="prefix of checks in the test files (default: CHECK)") 35 parser.add_argument("--list-passes", dest="list_passes", action="store_true", 36 help="print a list of all passes found in the tested file") 37 parser.add_argument("--dump-pass", dest="dump_pass", metavar="PASS", 38 help="print a compiler pass dump") 39 parser.add_argument("--arch", dest="arch", choices=archs_list, 40 help="Run tests for the specified target architecture.") 41 parser.add_argument("--debuggable", action="store_true", 42 help="Run tests for debuggable code.") 43 parser.add_argument("--print-cfg", action="store_true", default="True", dest="print_cfg", 44 help="Print the whole cfg file in case of test failure (default)") 45 parser.add_argument("--no-print-cfg", action="store_false", default="True", dest="print_cfg", 46 help="Don't print the whole cfg file in case of test failure") 47 parser.add_argument("-q", "--quiet", action="store_true", 48 help="print only errors") 49 return parser.parse_args() 50 51 52def list_passes(output_filename): 53 c1_file = parse_c1_visualizer_stream(output_filename, open(output_filename, "r")) 54 for compiler_pass in c1_file.passes: 55 Logger.log(compiler_pass.name) 56 57 58def dump_pass(output_filename, pass_name): 59 c1_file = parse_c1_visualizer_stream(output_filename, open(output_filename, "r")) 60 compiler_pass = c1_file.find_pass(pass_name) 61 if compiler_pass: 62 max_line_no = compiler_pass.start_line_no + len(compiler_pass.body) 63 len_line_no = len(str(max_line_no)) + 2 64 cur_line_no = compiler_pass.start_line_no 65 for line in compiler_pass.body: 66 Logger.log((str(cur_line_no) + ":").ljust(len_line_no) + line) 67 cur_line_no += 1 68 else: 69 Logger.fail('Pass "{}" not found in the output'.format(pass_name)) 70 71 72def find_checker_files(path): 73 """ Returns a list of files to scan for check annotations in the given path. 74 Path to a file is returned as a single-element list, directories are 75 recursively traversed and all '.java', '.j', and '.smali' files returned. 76 """ 77 if not path: 78 Logger.fail("No source path provided") 79 elif os.path.isfile(path): 80 return [path] 81 elif os.path.isdir(path): 82 found_files = [] 83 for root, dirs, files in os.walk(path): 84 for file in files: 85 extension = os.path.splitext(file)[1] 86 if extension in [".java", ".smali", ".j"]: 87 found_files.append(os.path.join(root, file)) 88 return found_files 89 else: 90 Logger.fail('Source path "{}" not found'.format(path)) 91 92 93def run_tests(check_prefix, check_path, output_filename, target_arch, debuggable_mode, print_cfg): 94 c1_file = parse_c1_visualizer_stream(output_filename, open(output_filename, "r")) 95 for check_filename in find_checker_files(check_path): 96 checker_file = parse_checker_stream(os.path.basename(check_filename), 97 check_prefix, 98 open(check_filename, "r"), 99 target_arch) 100 match_files(checker_file, c1_file, target_arch, debuggable_mode, print_cfg) 101 102 103if __name__ == "__main__": 104 args = parse_arguments() 105 106 if args.quiet: 107 Logger.Verbosity = Logger.Level.ERROR 108 109 if args.list_passes: 110 list_passes(args.tested_file) 111 elif args.dump_pass: 112 dump_pass(args.tested_file, args.dump_pass) 113 else: 114 run_tests(args.check_prefix, args.source_path, args.tested_file, args.arch, args.debuggable, 115 args.print_cfg) 116