xref: /rk3399_rockchip-uboot/tools/buildman/func_test.py (revision 823e60b62a98061a662536093d46f8f26f6d318f)
1d4144e45SSimon Glass#
2d4144e45SSimon Glass# Copyright (c) 2014 Google, Inc
3d4144e45SSimon Glass#
4d4144e45SSimon Glass# SPDX-License-Identifier:      GPL-2.0+
5d4144e45SSimon Glass#
6d4144e45SSimon Glass
7d4144e45SSimon Glassimport os
8d4144e45SSimon Glassimport shutil
9d4144e45SSimon Glassimport sys
10d4144e45SSimon Glassimport tempfile
11d4144e45SSimon Glassimport unittest
12d4144e45SSimon Glass
13*823e60b6SSimon Glassimport board
148b985eebSSimon Glassimport bsettings
15d4144e45SSimon Glassimport cmdline
16d4144e45SSimon Glassimport command
17d4144e45SSimon Glassimport control
18d4144e45SSimon Glassimport gitutil
19d4144e45SSimon Glassimport terminal
20d4144e45SSimon Glassimport toolchain
21d4144e45SSimon Glass
228b985eebSSimon Glasssettings_data = '''
238b985eebSSimon Glass# Buildman settings file
248b985eebSSimon Glass
258b985eebSSimon Glass[toolchain]
268b985eebSSimon Glass
278b985eebSSimon Glass[toolchain-alias]
288b985eebSSimon Glass
298b985eebSSimon Glass[make-flags]
308b985eebSSimon Glasssrc=/home/sjg/c/src
318b985eebSSimon Glasschroot=/home/sjg/c/chroot
328b985eebSSimon Glassvboot=USE_STDINT=1 VBOOT_DEBUG=1 MAKEFLAGS_VBOOT=DEBUG=1 CFLAGS_EXTRA_VBOOT=-DUNROLL_LOOPS VBOOT_SOURCE=${src}/platform/vboot_reference
338b985eebSSimon Glasschromeos_coreboot=VBOOT=${chroot}/build/link/usr ${vboot}
348b985eebSSimon Glasschromeos_daisy=VBOOT=${chroot}/build/daisy/usr ${vboot}
358b985eebSSimon Glasschromeos_peach=VBOOT=${chroot}/build/peach_pit/usr ${vboot}
368b985eebSSimon Glass'''
378b985eebSSimon Glass
38*823e60b6SSimon Glassboards = [
39*823e60b6SSimon Glass    ['Active', 'arm', 'armv7', '', 'Tester', 'ARM Board 1', 'board0',  ''],
40*823e60b6SSimon Glass    ['Active', 'arm', 'armv7', '', 'Tester', 'ARM Board 2', 'board1', ''],
41*823e60b6SSimon Glass    ['Active', 'powerpc', 'powerpc', '', 'Tester', 'PowerPC board 1', 'board2', ''],
42*823e60b6SSimon Glass    ['Active', 'powerpc', 'mpc5xx', '', 'Tester', 'PowerPC board 2', 'board3', ''],
43*823e60b6SSimon Glass    ['Active', 'sandbox', 'sandbox', '', 'Tester', 'Sandbox board', 'board4', ''],
44*823e60b6SSimon Glass]
45*823e60b6SSimon Glass
46d4144e45SSimon Glassclass TestFunctional(unittest.TestCase):
47d4144e45SSimon Glass    """Functional test for buildman.
48d4144e45SSimon Glass
49d4144e45SSimon Glass    This aims to test from just below the invocation of buildman (parsing
50d4144e45SSimon Glass    of arguments) to 'make' and 'git' invocation. It is not a true
51d4144e45SSimon Glass    emd-to-end test, as it mocks git, make and the tool chain. But this
52d4144e45SSimon Glass    makes it easier to detect when the builder is doing the wrong thing,
53d4144e45SSimon Glass    since in many cases this test code will fail. For example, only a
54d4144e45SSimon Glass    very limited subset of 'git' arguments is supported - anything
55d4144e45SSimon Glass    unexpected will fail.
56d4144e45SSimon Glass    """
57d4144e45SSimon Glass    def setUp(self):
58d4144e45SSimon Glass        self._base_dir = tempfile.mkdtemp()
59d4144e45SSimon Glass        self._git_dir = os.path.join(self._base_dir, 'src')
60d4144e45SSimon Glass        self._buildman_pathname = sys.argv[0]
61d4144e45SSimon Glass        self._buildman_dir = os.path.dirname(sys.argv[0])
62d4144e45SSimon Glass        command.test_result = self._HandleCommand
63d4144e45SSimon Glass        self._toolchains = toolchain.Toolchains()
64d4144e45SSimon Glass        self._toolchains.Add('gcc', test=False)
658b985eebSSimon Glass        bsettings.Setup(None)
668b985eebSSimon Glass        bsettings.AddFile(settings_data)
67*823e60b6SSimon Glass        self._boards = board.Boards()
68*823e60b6SSimon Glass        for brd in boards:
69*823e60b6SSimon Glass            self._boards.AddBoard(board.Board(*brd))
70d4144e45SSimon Glass
71d4144e45SSimon Glass    def tearDown(self):
72d4144e45SSimon Glass        shutil.rmtree(self._base_dir)
73d4144e45SSimon Glass
74d4144e45SSimon Glass    def _RunBuildman(self, *args):
75d4144e45SSimon Glass        return command.RunPipe([[self._buildman_pathname] + list(args)],
76d4144e45SSimon Glass                capture=True, capture_stderr=True)
77d4144e45SSimon Glass
78d4144e45SSimon Glass    def _RunControl(self, *args):
79d4144e45SSimon Glass        sys.argv = [sys.argv[0]] + list(args)
80d4144e45SSimon Glass        options, args = cmdline.ParseArgs()
81d4144e45SSimon Glass        return control.DoBuildman(options, args, toolchains=self._toolchains,
82*823e60b6SSimon Glass                make_func=self._HandleMake, boards=self._boards)
83d4144e45SSimon Glass
84d4144e45SSimon Glass    def testFullHelp(self):
85d4144e45SSimon Glass        command.test_result = None
86d4144e45SSimon Glass        result = self._RunBuildman('-H')
87d4144e45SSimon Glass        help_file = os.path.join(self._buildman_dir, 'README')
88d4144e45SSimon Glass        self.assertEqual(len(result.stdout), os.path.getsize(help_file))
89d4144e45SSimon Glass        self.assertEqual(0, len(result.stderr))
90d4144e45SSimon Glass        self.assertEqual(0, result.return_code)
91d4144e45SSimon Glass
92d4144e45SSimon Glass    def testHelp(self):
93d4144e45SSimon Glass        command.test_result = None
94d4144e45SSimon Glass        result = self._RunBuildman('-h')
95d4144e45SSimon Glass        help_file = os.path.join(self._buildman_dir, 'README')
96d4144e45SSimon Glass        self.assertTrue(len(result.stdout) > 1000)
97d4144e45SSimon Glass        self.assertEqual(0, len(result.stderr))
98d4144e45SSimon Glass        self.assertEqual(0, result.return_code)
99d4144e45SSimon Glass
100d4144e45SSimon Glass    def testGitSetup(self):
101d4144e45SSimon Glass        """Test gitutils.Setup(), from outside the module itself"""
102d4144e45SSimon Glass        command.test_result = command.CommandResult(return_code=1)
103d4144e45SSimon Glass        gitutil.Setup()
104d4144e45SSimon Glass        self.assertEqual(gitutil.use_no_decorate, False)
105d4144e45SSimon Glass
106d4144e45SSimon Glass        command.test_result = command.CommandResult(return_code=0)
107d4144e45SSimon Glass        gitutil.Setup()
108d4144e45SSimon Glass        self.assertEqual(gitutil.use_no_decorate, True)
109d4144e45SSimon Glass
110d4144e45SSimon Glass    def _HandleCommandGitLog(self, args):
111d4144e45SSimon Glass        if '-n0' in args:
112d4144e45SSimon Glass            return command.CommandResult(return_code=0)
113d4144e45SSimon Glass
114d4144e45SSimon Glass        # Not handled, so abort
115d4144e45SSimon Glass        print 'git log', args
116d4144e45SSimon Glass        sys.exit(1)
117d4144e45SSimon Glass
118d4144e45SSimon Glass    def _HandleCommandGit(self, in_args):
119d4144e45SSimon Glass        """Handle execution of a git command
120d4144e45SSimon Glass
121d4144e45SSimon Glass        This uses a hacked-up parser.
122d4144e45SSimon Glass
123d4144e45SSimon Glass        Args:
124d4144e45SSimon Glass            in_args: Arguments after 'git' from the command line
125d4144e45SSimon Glass        """
126d4144e45SSimon Glass        git_args = []           # Top-level arguments to git itself
127d4144e45SSimon Glass        sub_cmd = None          # Git sub-command selected
128d4144e45SSimon Glass        args = []               # Arguments to the git sub-command
129d4144e45SSimon Glass        for arg in in_args:
130d4144e45SSimon Glass            if sub_cmd:
131d4144e45SSimon Glass                args.append(arg)
132d4144e45SSimon Glass            elif arg[0] == '-':
133d4144e45SSimon Glass                git_args.append(arg)
134d4144e45SSimon Glass            else:
135d4144e45SSimon Glass                sub_cmd = arg
136d4144e45SSimon Glass        if sub_cmd == 'config':
137d4144e45SSimon Glass            return command.CommandResult(return_code=0)
138d4144e45SSimon Glass        elif sub_cmd == 'log':
139d4144e45SSimon Glass            return self._HandleCommandGitLog(args)
140d4144e45SSimon Glass
141d4144e45SSimon Glass        # Not handled, so abort
142d4144e45SSimon Glass        print 'git', git_args, sub_cmd, args
143d4144e45SSimon Glass        sys.exit(1)
144d4144e45SSimon Glass
145d4144e45SSimon Glass    def _HandleCommandNm(self, args):
146d4144e45SSimon Glass        return command.CommandResult(return_code=0)
147d4144e45SSimon Glass
148d4144e45SSimon Glass    def _HandleCommandObjdump(self, args):
149d4144e45SSimon Glass        return command.CommandResult(return_code=0)
150d4144e45SSimon Glass
151d4144e45SSimon Glass    def _HandleCommandSize(self, args):
152d4144e45SSimon Glass        return command.CommandResult(return_code=0)
153d4144e45SSimon Glass
154d4144e45SSimon Glass    def _HandleCommand(self, **kwargs):
155d4144e45SSimon Glass        """Handle a command execution.
156d4144e45SSimon Glass
157d4144e45SSimon Glass        The command is in kwargs['pipe-list'], as a list of pipes, each a
158d4144e45SSimon Glass        list of commands. The command should be emulated as required for
159d4144e45SSimon Glass        testing purposes.
160d4144e45SSimon Glass
161d4144e45SSimon Glass        Returns:
162d4144e45SSimon Glass            A CommandResult object
163d4144e45SSimon Glass        """
164d4144e45SSimon Glass        pipe_list = kwargs['pipe_list']
165d4144e45SSimon Glass        if len(pipe_list) != 1:
166d4144e45SSimon Glass            print 'invalid pipe', kwargs
167d4144e45SSimon Glass            sys.exit(1)
168d4144e45SSimon Glass        cmd = pipe_list[0][0]
169d4144e45SSimon Glass        args = pipe_list[0][1:]
170d4144e45SSimon Glass        if cmd == 'git':
171d4144e45SSimon Glass            return self._HandleCommandGit(args)
172d4144e45SSimon Glass        elif cmd == './scripts/show-gnu-make':
173d4144e45SSimon Glass            return command.CommandResult(return_code=0, stdout='make')
174d4144e45SSimon Glass        elif cmd == 'nm':
175d4144e45SSimon Glass            return self._HandleCommandNm(args)
176d4144e45SSimon Glass        elif cmd == 'objdump':
177d4144e45SSimon Glass            return self._HandleCommandObjdump(args)
178d4144e45SSimon Glass        elif cmd == 'size':
179d4144e45SSimon Glass            return self._HandleCommandSize(args)
180d4144e45SSimon Glass
181d4144e45SSimon Glass        # Not handled, so abort
182d4144e45SSimon Glass        print 'unknown command', kwargs
183d4144e45SSimon Glass        sys.exit(1)
184d4144e45SSimon Glass        return command.CommandResult(return_code=0)
185d4144e45SSimon Glass
186d4144e45SSimon Glass    def _HandleMake(self, commit, brd, stage, cwd, *args, **kwargs):
187d4144e45SSimon Glass        """Handle execution of 'make'
188d4144e45SSimon Glass
189d4144e45SSimon Glass        Args:
190d4144e45SSimon Glass            commit: Commit object that is being built
191d4144e45SSimon Glass            brd: Board object that is being built
192d4144e45SSimon Glass            stage: Stage that we are at (mrproper, config, build)
193d4144e45SSimon Glass            cwd: Directory where make should be run
194d4144e45SSimon Glass            args: Arguments to pass to make
195d4144e45SSimon Glass            kwargs: Arguments to pass to command.RunPipe()
196d4144e45SSimon Glass        """
197d4144e45SSimon Glass        if stage == 'mrproper':
198d4144e45SSimon Glass            return command.CommandResult(return_code=0)
199d4144e45SSimon Glass        elif stage == 'config':
200d4144e45SSimon Glass            return command.CommandResult(return_code=0,
201d4144e45SSimon Glass                    combined='Test configuration complete')
202d4144e45SSimon Glass        elif stage == 'build':
203d4144e45SSimon Glass            return command.CommandResult(return_code=0)
204d4144e45SSimon Glass
205d4144e45SSimon Glass        # Not handled, so abort
206d4144e45SSimon Glass        print 'make', stage
207d4144e45SSimon Glass        sys.exit(1)
208d4144e45SSimon Glass
209*823e60b6SSimon Glass    def testNoBoards(self):
210*823e60b6SSimon Glass        """Test that buildman aborts when there are no boards"""
211*823e60b6SSimon Glass        self._boards = board.Boards()
212*823e60b6SSimon Glass        with self.assertRaises(SystemExit):
213*823e60b6SSimon Glass            self._RunControl()
214*823e60b6SSimon Glass
215d4144e45SSimon Glass    def testCurrentSource(self):
216d4144e45SSimon Glass        """Very simple test to invoke buildman on the current source"""
217d4144e45SSimon Glass        self._RunControl()
218d4144e45SSimon Glass        lines = terminal.GetPrintTestLines()
219d4144e45SSimon Glass        self.assertTrue(lines[0].text.startswith('Building current source'))
220