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