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