xref: /rk3399_rockchip-uboot/tools/buildman/func_test.py (revision d4144e45b4245c60f50d456293cad2f53373efcd)
1*d4144e45SSimon Glass#
2*d4144e45SSimon Glass# Copyright (c) 2014 Google, Inc
3*d4144e45SSimon Glass#
4*d4144e45SSimon Glass# SPDX-License-Identifier:      GPL-2.0+
5*d4144e45SSimon Glass#
6*d4144e45SSimon Glass
7*d4144e45SSimon Glassimport os
8*d4144e45SSimon Glassimport shutil
9*d4144e45SSimon Glassimport sys
10*d4144e45SSimon Glassimport tempfile
11*d4144e45SSimon Glassimport unittest
12*d4144e45SSimon Glass
13*d4144e45SSimon Glassimport cmdline
14*d4144e45SSimon Glassimport command
15*d4144e45SSimon Glassimport control
16*d4144e45SSimon Glassimport gitutil
17*d4144e45SSimon Glassimport terminal
18*d4144e45SSimon Glassimport toolchain
19*d4144e45SSimon Glass
20*d4144e45SSimon Glassclass TestFunctional(unittest.TestCase):
21*d4144e45SSimon Glass    """Functional test for buildman.
22*d4144e45SSimon Glass
23*d4144e45SSimon Glass    This aims to test from just below the invocation of buildman (parsing
24*d4144e45SSimon Glass    of arguments) to 'make' and 'git' invocation. It is not a true
25*d4144e45SSimon Glass    emd-to-end test, as it mocks git, make and the tool chain. But this
26*d4144e45SSimon Glass    makes it easier to detect when the builder is doing the wrong thing,
27*d4144e45SSimon Glass    since in many cases this test code will fail. For example, only a
28*d4144e45SSimon Glass    very limited subset of 'git' arguments is supported - anything
29*d4144e45SSimon Glass    unexpected will fail.
30*d4144e45SSimon Glass    """
31*d4144e45SSimon Glass    def setUp(self):
32*d4144e45SSimon Glass        self._base_dir = tempfile.mkdtemp()
33*d4144e45SSimon Glass        self._git_dir = os.path.join(self._base_dir, 'src')
34*d4144e45SSimon Glass        self._buildman_pathname = sys.argv[0]
35*d4144e45SSimon Glass        self._buildman_dir = os.path.dirname(sys.argv[0])
36*d4144e45SSimon Glass        command.test_result = self._HandleCommand
37*d4144e45SSimon Glass        self._toolchains = toolchain.Toolchains()
38*d4144e45SSimon Glass        self._toolchains.Add('gcc', test=False)
39*d4144e45SSimon Glass
40*d4144e45SSimon Glass    def tearDown(self):
41*d4144e45SSimon Glass        shutil.rmtree(self._base_dir)
42*d4144e45SSimon Glass
43*d4144e45SSimon Glass    def _RunBuildman(self, *args):
44*d4144e45SSimon Glass        return command.RunPipe([[self._buildman_pathname] + list(args)],
45*d4144e45SSimon Glass                capture=True, capture_stderr=True)
46*d4144e45SSimon Glass
47*d4144e45SSimon Glass    def _RunControl(self, *args):
48*d4144e45SSimon Glass        sys.argv = [sys.argv[0]] + list(args)
49*d4144e45SSimon Glass        options, args = cmdline.ParseArgs()
50*d4144e45SSimon Glass        return control.DoBuildman(options, args, toolchains=self._toolchains,
51*d4144e45SSimon Glass                make_func=self._HandleMake)
52*d4144e45SSimon Glass
53*d4144e45SSimon Glass    def testFullHelp(self):
54*d4144e45SSimon Glass        command.test_result = None
55*d4144e45SSimon Glass        result = self._RunBuildman('-H')
56*d4144e45SSimon Glass        help_file = os.path.join(self._buildman_dir, 'README')
57*d4144e45SSimon Glass        self.assertEqual(len(result.stdout), os.path.getsize(help_file))
58*d4144e45SSimon Glass        self.assertEqual(0, len(result.stderr))
59*d4144e45SSimon Glass        self.assertEqual(0, result.return_code)
60*d4144e45SSimon Glass
61*d4144e45SSimon Glass    def testHelp(self):
62*d4144e45SSimon Glass        command.test_result = None
63*d4144e45SSimon Glass        result = self._RunBuildman('-h')
64*d4144e45SSimon Glass        help_file = os.path.join(self._buildman_dir, 'README')
65*d4144e45SSimon Glass        self.assertTrue(len(result.stdout) > 1000)
66*d4144e45SSimon Glass        self.assertEqual(0, len(result.stderr))
67*d4144e45SSimon Glass        self.assertEqual(0, result.return_code)
68*d4144e45SSimon Glass
69*d4144e45SSimon Glass    def testGitSetup(self):
70*d4144e45SSimon Glass        """Test gitutils.Setup(), from outside the module itself"""
71*d4144e45SSimon Glass        command.test_result = command.CommandResult(return_code=1)
72*d4144e45SSimon Glass        gitutil.Setup()
73*d4144e45SSimon Glass        self.assertEqual(gitutil.use_no_decorate, False)
74*d4144e45SSimon Glass
75*d4144e45SSimon Glass        command.test_result = command.CommandResult(return_code=0)
76*d4144e45SSimon Glass        gitutil.Setup()
77*d4144e45SSimon Glass        self.assertEqual(gitutil.use_no_decorate, True)
78*d4144e45SSimon Glass
79*d4144e45SSimon Glass    def _HandleCommandGitLog(self, args):
80*d4144e45SSimon Glass        if '-n0' in args:
81*d4144e45SSimon Glass            return command.CommandResult(return_code=0)
82*d4144e45SSimon Glass
83*d4144e45SSimon Glass        # Not handled, so abort
84*d4144e45SSimon Glass        print 'git log', args
85*d4144e45SSimon Glass        sys.exit(1)
86*d4144e45SSimon Glass
87*d4144e45SSimon Glass    def _HandleCommandGit(self, in_args):
88*d4144e45SSimon Glass        """Handle execution of a git command
89*d4144e45SSimon Glass
90*d4144e45SSimon Glass        This uses a hacked-up parser.
91*d4144e45SSimon Glass
92*d4144e45SSimon Glass        Args:
93*d4144e45SSimon Glass            in_args: Arguments after 'git' from the command line
94*d4144e45SSimon Glass        """
95*d4144e45SSimon Glass        git_args = []           # Top-level arguments to git itself
96*d4144e45SSimon Glass        sub_cmd = None          # Git sub-command selected
97*d4144e45SSimon Glass        args = []               # Arguments to the git sub-command
98*d4144e45SSimon Glass        for arg in in_args:
99*d4144e45SSimon Glass            if sub_cmd:
100*d4144e45SSimon Glass                args.append(arg)
101*d4144e45SSimon Glass            elif arg[0] == '-':
102*d4144e45SSimon Glass                git_args.append(arg)
103*d4144e45SSimon Glass            else:
104*d4144e45SSimon Glass                sub_cmd = arg
105*d4144e45SSimon Glass        if sub_cmd == 'config':
106*d4144e45SSimon Glass            return command.CommandResult(return_code=0)
107*d4144e45SSimon Glass        elif sub_cmd == 'log':
108*d4144e45SSimon Glass            return self._HandleCommandGitLog(args)
109*d4144e45SSimon Glass
110*d4144e45SSimon Glass        # Not handled, so abort
111*d4144e45SSimon Glass        print 'git', git_args, sub_cmd, args
112*d4144e45SSimon Glass        sys.exit(1)
113*d4144e45SSimon Glass
114*d4144e45SSimon Glass    def _HandleCommandNm(self, args):
115*d4144e45SSimon Glass        return command.CommandResult(return_code=0)
116*d4144e45SSimon Glass
117*d4144e45SSimon Glass    def _HandleCommandObjdump(self, args):
118*d4144e45SSimon Glass        return command.CommandResult(return_code=0)
119*d4144e45SSimon Glass
120*d4144e45SSimon Glass    def _HandleCommandSize(self, args):
121*d4144e45SSimon Glass        return command.CommandResult(return_code=0)
122*d4144e45SSimon Glass
123*d4144e45SSimon Glass    def _HandleCommand(self, **kwargs):
124*d4144e45SSimon Glass        """Handle a command execution.
125*d4144e45SSimon Glass
126*d4144e45SSimon Glass        The command is in kwargs['pipe-list'], as a list of pipes, each a
127*d4144e45SSimon Glass        list of commands. The command should be emulated as required for
128*d4144e45SSimon Glass        testing purposes.
129*d4144e45SSimon Glass
130*d4144e45SSimon Glass        Returns:
131*d4144e45SSimon Glass            A CommandResult object
132*d4144e45SSimon Glass        """
133*d4144e45SSimon Glass        pipe_list = kwargs['pipe_list']
134*d4144e45SSimon Glass        if len(pipe_list) != 1:
135*d4144e45SSimon Glass            print 'invalid pipe', kwargs
136*d4144e45SSimon Glass            sys.exit(1)
137*d4144e45SSimon Glass        cmd = pipe_list[0][0]
138*d4144e45SSimon Glass        args = pipe_list[0][1:]
139*d4144e45SSimon Glass        if cmd == 'git':
140*d4144e45SSimon Glass            return self._HandleCommandGit(args)
141*d4144e45SSimon Glass        elif cmd == './scripts/show-gnu-make':
142*d4144e45SSimon Glass            return command.CommandResult(return_code=0, stdout='make')
143*d4144e45SSimon Glass        elif cmd == 'nm':
144*d4144e45SSimon Glass            return self._HandleCommandNm(args)
145*d4144e45SSimon Glass        elif cmd == 'objdump':
146*d4144e45SSimon Glass            return self._HandleCommandObjdump(args)
147*d4144e45SSimon Glass        elif cmd == 'size':
148*d4144e45SSimon Glass            return self._HandleCommandSize(args)
149*d4144e45SSimon Glass
150*d4144e45SSimon Glass        # Not handled, so abort
151*d4144e45SSimon Glass        print 'unknown command', kwargs
152*d4144e45SSimon Glass        sys.exit(1)
153*d4144e45SSimon Glass        return command.CommandResult(return_code=0)
154*d4144e45SSimon Glass
155*d4144e45SSimon Glass    def _HandleMake(self, commit, brd, stage, cwd, *args, **kwargs):
156*d4144e45SSimon Glass        """Handle execution of 'make'
157*d4144e45SSimon Glass
158*d4144e45SSimon Glass        Args:
159*d4144e45SSimon Glass            commit: Commit object that is being built
160*d4144e45SSimon Glass            brd: Board object that is being built
161*d4144e45SSimon Glass            stage: Stage that we are at (mrproper, config, build)
162*d4144e45SSimon Glass            cwd: Directory where make should be run
163*d4144e45SSimon Glass            args: Arguments to pass to make
164*d4144e45SSimon Glass            kwargs: Arguments to pass to command.RunPipe()
165*d4144e45SSimon Glass        """
166*d4144e45SSimon Glass        if stage == 'mrproper':
167*d4144e45SSimon Glass            return command.CommandResult(return_code=0)
168*d4144e45SSimon Glass        elif stage == 'config':
169*d4144e45SSimon Glass            return command.CommandResult(return_code=0,
170*d4144e45SSimon Glass                    combined='Test configuration complete')
171*d4144e45SSimon Glass        elif stage == 'build':
172*d4144e45SSimon Glass            return command.CommandResult(return_code=0)
173*d4144e45SSimon Glass
174*d4144e45SSimon Glass        # Not handled, so abort
175*d4144e45SSimon Glass        print 'make', stage
176*d4144e45SSimon Glass        sys.exit(1)
177*d4144e45SSimon Glass
178*d4144e45SSimon Glass    def testCurrentSource(self):
179*d4144e45SSimon Glass        """Very simple test to invoke buildman on the current source"""
180*d4144e45SSimon Glass        self._RunControl()
181*d4144e45SSimon Glass        lines = terminal.GetPrintTestLines()
182*d4144e45SSimon Glass        self.assertTrue(lines[0].text.startswith('Building current source'))
183