def _HandleMake(self, commit, brd, stage, cwd, *args, **kwargs): """Handle execution of 'make' Args: commit: Commit object that is being built brd: Board object that is being built stage: Stage that we are at (mrproper, config, build) cwd: Directory where make should be run args: Arguments to pass to make kwargs: Arguments to pass to command.run_pipe() """ self._make_calls += 1 if stage == 'mrproper': return command.CommandResult(return_code=0) elif stage == 'config': return command.CommandResult(return_code=0, combined='Test configuration complete') elif stage == 'build': stderr = '' out_dir = '' for arg in args: if arg.startswith('O='): out_dir = arg[2:] fname = os.path.join(cwd or '', out_dir, 'u-boot') tools.write_file(fname, b'U-Boot') if type(commit) is not str: stderr = self._error.get((brd.target, commit.sequence)) if stderr: return command.CommandResult(return_code=1, stderr=stderr) return command.CommandResult(return_code=0) # Not handled, so abort print('make', stage) sys.exit(1)
def _HandleCommandGit(self, in_args): """Handle execution of a git command This uses a hacked-up parser. Args: in_args: Arguments after 'git' from the command line """ git_args = [] # Top-level arguments to git itself sub_cmd = None # Git sub-command selected args = [] # Arguments to the git sub-command for arg in in_args: if sub_cmd: args.append(arg) elif arg[0] == '-': git_args.append(arg) else: if git_args and git_args[-1] in ['--git-dir', '--work-tree']: git_args.append(arg) else: sub_cmd = arg if sub_cmd == 'config': return self._HandleCommandGitConfig(args) elif sub_cmd == 'log': return self._HandleCommandGitLog(args) elif sub_cmd == 'clone': return command.CommandResult(return_code=0) elif sub_cmd == 'checkout': return command.CommandResult(return_code=0) elif sub_cmd == 'worktree': return command.CommandResult(return_code=0) # Not handled, so abort print('git', git_args, sub_cmd, args) sys.exit(1)
def testGitSetup(self): """Test gitutils.Setup(), from outside the module itself""" command.test_result = command.CommandResult(return_code=1) gitutil.setup() self.assertEqual(gitutil.use_no_decorate, False) command.test_result = command.CommandResult(return_code=0) gitutil.setup() self.assertEqual(gitutil.use_no_decorate, True)
def _HandleCommandGitConfig(self, args): config = args[0] if config == 'sendemail.aliasesfile': return command.CommandResult(return_code=0) elif config.startswith('branch.badbranch'): return command.CommandResult(return_code=1) elif config == 'branch.%s.remote' % self._test_branch: return command.CommandResult(return_code=0, stdout='upstream\n') elif config == 'branch.%s.merge' % self._test_branch: return command.CommandResult(return_code=0, stdout='refs/heads/master\n') # Not handled, so abort print('git config', args) sys.exit(1)
def _HandleCommandGitLog(self, args): if args[-1] == '--': args = args[:-1] if '-n0' in args: return command.CommandResult(return_code=0) elif args[-1] == 'upstream/master..%s' % self._test_branch: return command.CommandResult(return_code=0, stdout=commit_shortlog) elif args[:3] == ['--no-color', '--no-decorate', '--reverse']: if args[-1] == self._test_branch: count = int(args[3][2:]) return command.CommandResult(return_code=0, stdout=''.join(commit_log[:count])) # Not handled, so abort print('git log', args) sys.exit(1)
def test_all_bintool_versions(self): """Test handling of bintool version when it cannot be run""" all_tools = Bintool.get_tool_list() for name in all_tools: btool = Bintool.create(name) with unittest.mock.patch.object( btool, 'run_cmd_result', return_value=command.CommandResult()): self.assertEqual('unknown', btool.version())
def Make(self, commit, brd, stage, *args, **kwargs): result = command.CommandResult() boardnum = int(brd.target[-1]) result.return_code = 0 result.stderr = '' result.stdout = ('This is the test output for board %s, commit %s' % (brd.target, commit.hash)) if ((boardnum >= 1 and boardnum >= commit.sequence) or boardnum == 4 and commit.sequence == 6): result.return_code = commit.return_code result.stderr = (''.join(commit.error_list) % {'basedir' : self.base_dir + '/.bm-work/00/'}) elif commit.sequence < 6: result.stderr = migration result.combined = result.stdout + result.stderr return result
def _HandleCommand(self, **kwargs): """Handle a command execution. The command is in kwargs['pipe-list'], as a list of pipes, each a list of commands. The command should be emulated as required for testing purposes. Returns: A CommandResult object """ pipe_list = kwargs['pipe_list'] wc = False if len(pipe_list) != 1: if pipe_list[1] == ['wc', '-l']: wc = True else: print('invalid pipe', kwargs) sys.exit(1) cmd = pipe_list[0][0] args = pipe_list[0][1:] result = None if cmd == 'git': result = self._HandleCommandGit(args) elif cmd == './scripts/show-gnu-make': return command.CommandResult(return_code=0, stdout='make') elif cmd.endswith('nm'): return self._HandleCommandNm(args) elif cmd.endswith('objdump'): return self._HandleCommandObjdump(args) elif cmd.endswith('objcopy'): return self._HandleCommandObjcopy(args) elif cmd.endswith( 'size'): return self._HandleCommandSize(args) if not result: # Not handled, so abort print('unknown command', kwargs) sys.exit(1) if wc: result.stdout = len(result.stdout.splitlines()) return result
def RunCommit(self, commit_upto, brd, work_dir, do_config, config_only, force_build, force_build_failures, work_in_output): """Build a particular commit. If the build is already done, and we are not forcing a build, we skip the build and just return the previously-saved results. Args: commit_upto: Commit number to build (0...n-1) brd: Board object to build work_dir: Directory to which the source will be checked out do_config: True to run a make <board>_defconfig on the source config_only: Only configure the source, do not build it force_build: Force a build even if one was previously done force_build_failures: Force a bulid if the previous result showed failure work_in_output: Use the output directory as the work directory and don't write to a separate output directory. Returns: tuple containing: - CommandResult object containing the results of the build - boolean indicating whether 'make config' is still needed """ # Create a default result - it will be overwritte by the call to # self.Make() below, in the event that we do a build. result = command.CommandResult() result.return_code = 0 if work_in_output or self.builder.in_tree: out_dir = work_dir else: if self.per_board_out_dir: out_rel_dir = os.path.join('..', brd.target) else: out_rel_dir = 'build' out_dir = os.path.join(work_dir, out_rel_dir) # Check if the job was already completed last time done_file = self.builder.GetDoneFile(commit_upto, brd.target) result.already_done = os.path.exists(done_file) will_build = (force_build or force_build_failures or not result.already_done) if result.already_done: # Get the return code from that build and use it with open(done_file, 'r') as fd: try: result.return_code = int(fd.readline()) except ValueError: # The file may be empty due to running out of disk space. # Try a rebuild result.return_code = RETURN_CODE_RETRY # Check the signal that the build needs to be retried if result.return_code == RETURN_CODE_RETRY: will_build = True elif will_build: err_file = self.builder.GetErrFile(commit_upto, brd.target) if os.path.exists(err_file) and os.stat(err_file).st_size: result.stderr = 'bad' elif not force_build: # The build passed, so no need to build it again will_build = False if will_build: # We are going to have to build it. First, get a toolchain if not self.toolchain: try: self.toolchain = self.builder.toolchains.Select(brd.arch) except ValueError as err: result.return_code = 10 result.stdout = '' result.stderr = str(err) # TODO([email protected]): This gets swallowed, but needs # to be reported. if self.toolchain: # Checkout the right commit if self.builder.commits: commit = self.builder.commits[commit_upto] if self.builder.checkout: git_dir = os.path.join(work_dir, '.git') gitutil.Checkout(commit.hash, git_dir, work_dir, force=True) else: commit = 'current' # Set up the environment and command line env = self.toolchain.MakeEnvironment(self.builder.full_path) Mkdir(out_dir) args = [] cwd = work_dir src_dir = os.path.realpath(work_dir) if not self.builder.in_tree: if commit_upto is None: # In this case we are building in the original source # directory (i.e. the current directory where buildman # is invoked. The output directory is set to this # thread's selected work directory. # # Symlinks can confuse U-Boot's Makefile since # we may use '..' in our path, so remove them. out_dir = os.path.realpath(out_dir) args.append('O=%s' % out_dir) cwd = None src_dir = os.getcwd() else: args.append('O=%s' % out_rel_dir) if self.builder.verbose_build: args.append('V=1') else: args.append('-s') if self.builder.num_jobs is not None: args.extend(['-j', str(self.builder.num_jobs)]) if self.builder.warnings_as_errors: args.append('KCFLAGS=-Werror') config_args = ['%s_defconfig' % brd.target] config_out = '' args.extend(self.builder.toolchains.GetMakeArguments(brd)) args.extend(self.toolchain.MakeArgs()) # Remove any output targets. Since we use a build directory that # was previously used by another board, it may have produced an # SPL image. If we don't remove it (i.e. see do_config and # self.mrproper below) then it will appear to be the output of # this build, even if it does not produce SPL images. build_dir = self.builder.GetBuildDir(commit_upto, brd.target) for elf in BASE_ELF_FILENAMES: fname = os.path.join(out_dir, elf) if os.path.exists(fname): os.remove(fname) # If we need to reconfigure, do that now if do_config: config_out = '' if self.mrproper: result = self.Make(commit, brd, 'mrproper', cwd, 'mrproper', *args, env=env) config_out += result.combined result = self.Make(commit, brd, 'config', cwd, *(args + config_args), env=env) config_out += result.combined do_config = False # No need to configure next time if result.return_code == 0: if config_only: args.append('cfg') result = self.Make(commit, brd, 'build', cwd, *args, env=env) result.stderr = result.stderr.replace(src_dir + '/', '') if self.builder.verbose_build: result.stdout = config_out + result.stdout else: result.return_code = 1 result.stderr = 'No tool chain for %s\n' % brd.arch result.already_done = False result.toolchain = self.toolchain result.brd = brd result.commit_upto = commit_upto result.out_dir = out_dir return result, do_config
def _HandleCommandSize(self, args): return command.CommandResult(return_code=0)
def _HandleCommandObjcopy(self, args): return command.CommandResult(return_code=0)