1# Copyright 2017 - The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14"""Provides command 'check_compat'.""" 15 16from __future__ import print_function 17 18import argparse 19import logging 20 21from gsi_util.checkers import checker 22from gsi_util.commands.common import image_sources 23 24 25class CheckReporter(object): 26 """Outputs the checker result with formatting.""" 27 28 # The output will look like: 29 # 30 # check result 1 : pass 31 # check result 2 : pass 32 # 33 # ------------------------------------ 34 # Pass/Total : 2/2 35 _OUTPUT_FORMAT = '{:30}: {}' 36 _ERR_MSE_FORMAT = ' {}' 37 _OUTPUT_MAX_LEN = 36 38 _SUMMARY_NAME = 'Pass/Total' 39 40 def __init__(self): 41 """Whether to only output a summary result of all checks.""" 42 self._only_summary = False 43 44 def set_only_summary(self): 45 """Only outputs summary result. 46 47 When _only_summary is set, only shows the number of pass items over 48 the number of total check items. 49 """ 50 self._only_summary = True 51 52 @staticmethod 53 def _get_result_str(result_ok): 54 """Gets the result string 'pass' or 'fail' based on the check result.""" 55 return 'pass' if result_ok else 'fail' 56 57 def _output_result_item(self, result_item): 58 """Outputs the result of a CheckResultItem(). 59 60 Args: 61 result_item: a namedtuple of check_result.CheckResultItem(). 62 63 Returns: 64 True if the test result passed. False otherwise. 65 """ 66 title, result_ok, stderr = result_item 67 68 if not self._only_summary: 69 result_str = self._get_result_str(result_ok) 70 print(self._OUTPUT_FORMAT.format(title, result_str)) 71 if stderr: 72 print(self._ERR_MSE_FORMAT.format(stderr)) 73 74 return result_ok 75 76 def _output_summary(self, num_pass_items, num_all_items): 77 """Outputs a summary of all checker tests. 78 79 Args: 80 num_pass_items: The number of passing tests. 81 num_all_items: Total number of finished tests. 82 """ 83 print('-' * self._OUTPUT_MAX_LEN) 84 summary_result_str = '{}/{}'.format(num_pass_items, num_all_items) 85 print(self._OUTPUT_FORMAT.format(self._SUMMARY_NAME, summary_result_str)) 86 87 def output(self, check_result_items): 88 """The main public method to output a sequence of CheckResultItem()s.""" 89 num_pass_items = 0 90 num_all_items = 0 91 for result_item in check_result_items: 92 result_ok = self._output_result_item(result_item) 93 if result_ok: 94 num_pass_items += 1 95 num_all_items += 1 96 self._output_summary(num_pass_items, num_all_items) 97 98 99def _format_check_list(check_list): 100 """Returns a string of check list item names.""" 101 # The string is like: "'check_item1', 'check_item2', 'check_item3'". 102 return ', '.join('{!r}'.format(x.check_item) for x in check_list) 103 104 105def do_list_checks(_): 106 """Prints the all supported check items.""" 107 print(_format_check_list(checker.Checker.get_all_check_list())) 108 109 110def do_check_compat(args): 111 """The actual function to do 'gsi_util check_compat' command.""" 112 logging.info('==== CHECK_COMPAT ====') 113 logging.info(' system=%s vendor=%s', args.system, args.vendor) 114 115 check_list = (checker.Checker.make_check_list(args.CHECK_ITEM) 116 if args.CHECK_ITEM else checker.Checker.get_all_check_list()) 117 logging.debug('Starting check list: %s', _format_check_list(check_list)) 118 mounter = image_sources.create_composite_mounter_by_args(args) 119 with mounter as file_accessor: 120 the_checker = checker.Checker(file_accessor) 121 check_result = the_checker.check(check_list) 122 123 reporter = CheckReporter() 124 if args.only_summary: 125 reporter.set_only_summary() 126 reporter.output(check_result) 127 128 logging.info('==== DONE ====') 129 130 131_CHECK_COMPAT_DESC = """ 132'check_compat' command checks compatibility between images. 133 134You must assign both image sources by SYSTEM and VENDOR. 135 136You could use command 'list_checks' to query all check items: 137 138 $ ./gsi_util.py list_checks 139 140Here is an examples to check a system.img and a device are compatible: 141 142 $ ./gsi_util.py check_compat --system system.img --vendor adb""" 143 144 145def setup_command_args(parser): 146 """Sets up command 'list_checks' and 'check_compat'.""" 147 148 # Command 'list_checks'. 149 list_check_parser = parser.add_parser( 150 'list_checks', help='lists all possible check items. Run') 151 list_check_parser.set_defaults(func=do_list_checks) 152 153 # command 'check_compat' 154 check_compat_parser = parser.add_parser( 155 'check_compat', 156 help='checks compatibility between a system and a vendor', 157 description=_CHECK_COMPAT_DESC, 158 formatter_class=argparse.RawTextHelpFormatter) 159 check_compat_parser.add_argument( 160 '-s', 161 '--only-summary', 162 action='store_true', 163 help='only output the summary result') 164 image_sources.add_argument_group( 165 check_compat_parser, 166 required_images=['system', 'vendor']) 167 check_compat_parser.add_argument( 168 'CHECK_ITEM', 169 type=str, 170 nargs='*', 171 help=('the check item to be performed\n' 172 'select one from: {}\n'.format(_format_check_list( 173 checker.Checker.get_all_check_list())) + 174 'if not given, it will check all')) 175 check_compat_parser.set_defaults(func=do_check_compat) 176