bisect.py revision 545b947888df1d07f4ad530e1c5eec930fc283c2
1#!/usr/bin/python2
2"""The unified package/object bisecting tool."""
3
4from __future__ import print_function
5
6import abc
7import argparse
8import os
9import sys
10
11if os.path.isabs(sys.argv[0]):
12  utils_pythonpath = os.path.abspath('{0}/..'.format(os.path.dirname(sys.argv[
13      0])))
14else:
15  wdir = os.getcwd()
16  utils_pythonpath = os.path.abspath('{0}/{1}/..'.format(wdir, os.path.dirname(
17      sys.argv[0])))
18sys.path.append(utils_pythonpath)
19from utils import command_executer
20from utils import logger
21
22import binary_search_state
23
24
25class Bisector(object):
26  """The abstract base class for Bisectors."""
27
28  # Make Bisector an abstract class
29  __metaclass__ = abc.ABCMeta
30
31  def __init__(self, options):
32    self.options = options
33    self.logger = logger.GetLogger()
34    self.ce = command_executer.GetCommandExecuter()
35
36  @abc.abstractmethod
37  def PreRun(self):
38    pass
39
40  @abc.abstractmethod
41  def Run(self):
42    pass
43
44  @abc.abstractmethod
45  def PostRun(self):
46    pass
47
48
49class BisectPackage(Bisector):
50  """The class for package bisection steps."""
51
52  cros_pkg_setup = 'cros_pkg/setup.sh'
53  cros_pkg_cleanup = 'cros_pkg/%s_cleanup.sh'
54  default_kwargs = {
55      'get_initial_items': 'cros_pkg/get_initial_items.sh',
56      'switch_to_good': 'cros_pkg/switch_to_good.sh',
57      'switch_to_bad': 'cros_pkg/switch_to_bad.sh',
58      'install_script': 'cros_pkg/install.sh',
59      'test_script': 'cros_pkg/interactive_test.sh',
60      'noincremental': False,
61      'prune': True,
62      'file_args': True
63  }
64
65  def __init__(self, options):
66    super(BisectPackage, self).__init__(options)
67
68  def PreRun(self):
69    cmd = ('%s %s %s' %
70           (self.cros_pkg_setup, self.options.board, self.options.remote))
71    ret, _, _ = self.ce.RunCommandWExceptionCleanup(cmd, print_to_console=True)
72    if ret:
73      self.logger.LogError('Package bisector setup failed w/ error %d' % ret)
74      return 1
75    return 0
76
77  def Run(self):
78    return binary_search_state.Run(**self.default_kwargs)
79
80  def PostRun(self):
81    cmd = self.cros_pkg_cleanup % self.options.board
82    ret, _, _ = self.ce.RunCommandWExceptionCleanup(cmd, print_to_console=True)
83    if ret:
84      self.logger.LogError('Package bisector cleanup failed w/ error %d' % ret)
85      return 1
86    return 0
87
88
89class BisectObject(Bisector):
90  """The class for object bisection steps."""
91
92  def __init__(self, options):
93    super(BisectObject, self).__init__(options)
94
95  def PreRun(self):
96    raise NotImplementedError('Object bisecting still WIP')
97
98  def Run(self):
99    return 1
100
101  def PostRun(self):
102    return 1
103
104
105def Run(bisector):
106  ret = bisector.PreRun()
107  if ret:
108    return ret
109
110  ret = bisector.Run()
111  if ret:
112    return ret
113
114  ret = bisector.PostRun()
115  if ret:
116    return ret
117
118  return 0
119
120
121def Main(argv):
122  parser = argparse.ArgumentParser(epilog=('Run ./bisect.py {command} --help '
123                                           'for individual subcommand '
124                                           'help/args.'))
125  subparsers = parser.add_subparsers(title='Bisect mode',
126                                     description=('Whether to package or object'
127                                                  'bisect'))
128
129  parser_package = subparsers.add_parser('package')
130  parser_package.add_argument('board', help='Board to target')
131  parser_package.add_argument('remote', help='Remote machine to test on')
132  parser_package.set_defaults(handler=BisectPackage)
133
134  parser_object = subparsers.add_parser('object')
135  parser_object.set_defaults(handler=BisectObject)
136
137  options = parser.parse_args(argv)
138
139  subcmd = options.handler
140  del options.handler
141
142  bisector = subcmd(options)
143  return Run(bisector)
144
145
146if __name__ == '__main__':
147  sys.exit(Main(sys.argv[1:]))
148