123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- #
- # Copyright (c) 2014 Google, Inc
- #
- # SPDX-License-Identifier: GPL-2.0+
- #
- import os
- import shutil
- import sys
- import tempfile
- import unittest
- import board
- import bsettings
- import cmdline
- import command
- import control
- import gitutil
- import terminal
- import toolchain
- settings_data = '''
- # Buildman settings file
- [toolchain]
- [toolchain-alias]
- [make-flags]
- src=/home/sjg/c/src
- chroot=/home/sjg/c/chroot
- vboot=USE_STDINT=1 VBOOT_DEBUG=1 MAKEFLAGS_VBOOT=DEBUG=1 CFLAGS_EXTRA_VBOOT=-DUNROLL_LOOPS VBOOT_SOURCE=${src}/platform/vboot_reference
- chromeos_coreboot=VBOOT=${chroot}/build/link/usr ${vboot}
- chromeos_daisy=VBOOT=${chroot}/build/daisy/usr ${vboot}
- chromeos_peach=VBOOT=${chroot}/build/peach_pit/usr ${vboot}
- '''
- boards = [
- ['Active', 'arm', 'armv7', '', 'Tester', 'ARM Board 1', 'board0', ''],
- ['Active', 'arm', 'armv7', '', 'Tester', 'ARM Board 2', 'board1', ''],
- ['Active', 'powerpc', 'powerpc', '', 'Tester', 'PowerPC board 1', 'board2', ''],
- ['Active', 'powerpc', 'mpc5xx', '', 'Tester', 'PowerPC board 2', 'board3', ''],
- ['Active', 'sandbox', 'sandbox', '', 'Tester', 'Sandbox board', 'board4', ''],
- ]
- class TestFunctional(unittest.TestCase):
- """Functional test for buildman.
- This aims to test from just below the invocation of buildman (parsing
- of arguments) to 'make' and 'git' invocation. It is not a true
- emd-to-end test, as it mocks git, make and the tool chain. But this
- makes it easier to detect when the builder is doing the wrong thing,
- since in many cases this test code will fail. For example, only a
- very limited subset of 'git' arguments is supported - anything
- unexpected will fail.
- """
- def setUp(self):
- self._base_dir = tempfile.mkdtemp()
- self._git_dir = os.path.join(self._base_dir, 'src')
- self._buildman_pathname = sys.argv[0]
- self._buildman_dir = os.path.dirname(sys.argv[0])
- command.test_result = self._HandleCommand
- self._toolchains = toolchain.Toolchains()
- self._toolchains.Add('gcc', test=False)
- bsettings.Setup(None)
- bsettings.AddFile(settings_data)
- self._boards = board.Boards()
- for brd in boards:
- self._boards.AddBoard(board.Board(*brd))
- def tearDown(self):
- shutil.rmtree(self._base_dir)
- def _RunBuildman(self, *args):
- return command.RunPipe([[self._buildman_pathname] + list(args)],
- capture=True, capture_stderr=True)
- def _RunControl(self, *args):
- sys.argv = [sys.argv[0]] + list(args)
- options, args = cmdline.ParseArgs()
- return control.DoBuildman(options, args, toolchains=self._toolchains,
- make_func=self._HandleMake, boards=self._boards)
- def testFullHelp(self):
- command.test_result = None
- result = self._RunBuildman('-H')
- help_file = os.path.join(self._buildman_dir, 'README')
- self.assertEqual(len(result.stdout), os.path.getsize(help_file))
- self.assertEqual(0, len(result.stderr))
- self.assertEqual(0, result.return_code)
- def testHelp(self):
- command.test_result = None
- result = self._RunBuildman('-h')
- help_file = os.path.join(self._buildman_dir, 'README')
- self.assertTrue(len(result.stdout) > 1000)
- self.assertEqual(0, len(result.stderr))
- self.assertEqual(0, result.return_code)
- 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 _HandleCommandGitLog(self, args):
- if '-n0' in args:
- return command.CommandResult(return_code=0)
- # Not handled, so abort
- print 'git log', args
- 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:
- sub_cmd = arg
- if sub_cmd == 'config':
- return command.CommandResult(return_code=0)
- elif sub_cmd == 'log':
- return self._HandleCommandGitLog(args)
- # Not handled, so abort
- print 'git', git_args, sub_cmd, args
- sys.exit(1)
- def _HandleCommandNm(self, args):
- return command.CommandResult(return_code=0)
- def _HandleCommandObjdump(self, args):
- return command.CommandResult(return_code=0)
- def _HandleCommandSize(self, args):
- return command.CommandResult(return_code=0)
- 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']
- if len(pipe_list) != 1:
- print 'invalid pipe', kwargs
- sys.exit(1)
- cmd = pipe_list[0][0]
- args = pipe_list[0][1:]
- if cmd == 'git':
- return self._HandleCommandGit(args)
- elif cmd == './scripts/show-gnu-make':
- return command.CommandResult(return_code=0, stdout='make')
- elif cmd == 'nm':
- return self._HandleCommandNm(args)
- elif cmd == 'objdump':
- return self._HandleCommandObjdump(args)
- elif cmd == 'size':
- return self._HandleCommandSize(args)
- # Not handled, so abort
- print 'unknown command', kwargs
- sys.exit(1)
- return command.CommandResult(return_code=0)
- 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.RunPipe()
- """
- 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':
- return command.CommandResult(return_code=0)
- # Not handled, so abort
- print 'make', stage
- sys.exit(1)
- def testNoBoards(self):
- """Test that buildman aborts when there are no boards"""
- self._boards = board.Boards()
- with self.assertRaises(SystemExit):
- self._RunControl()
- def testCurrentSource(self):
- """Very simple test to invoke buildman on the current source"""
- self._RunControl()
- lines = terminal.GetPrintTestLines()
- self.assertTrue(lines[0].text.startswith('Building current source'))
|