xref: /openbmc/u-boot/tools/patman/func_test.py (revision 12308b12)
16e87ae1cSSimon Glass# -*- coding: utf-8 -*-
283d290c5STom Rini# SPDX-License-Identifier:	GPL-2.0+
36e87ae1cSSimon Glass#
46e87ae1cSSimon Glass# Copyright 2017 Google, Inc
56e87ae1cSSimon Glass#
66e87ae1cSSimon Glass
76e87ae1cSSimon Glassimport contextlib
86e87ae1cSSimon Glassimport os
96e87ae1cSSimon Glassimport re
106e87ae1cSSimon Glassimport shutil
116e87ae1cSSimon Glassimport sys
126e87ae1cSSimon Glassimport tempfile
136e87ae1cSSimon Glassimport unittest
146e87ae1cSSimon Glass
156e87ae1cSSimon Glassimport gitutil
166e87ae1cSSimon Glassimport patchstream
176e87ae1cSSimon Glassimport settings
186e87ae1cSSimon Glass
196e87ae1cSSimon Glass
206e87ae1cSSimon Glass@contextlib.contextmanager
216e87ae1cSSimon Glassdef capture():
226e87ae1cSSimon Glass    import sys
236e87ae1cSSimon Glass    from cStringIO import StringIO
246e87ae1cSSimon Glass    oldout,olderr = sys.stdout, sys.stderr
256e87ae1cSSimon Glass    try:
266e87ae1cSSimon Glass        out=[StringIO(), StringIO()]
276e87ae1cSSimon Glass        sys.stdout,sys.stderr = out
286e87ae1cSSimon Glass        yield out
296e87ae1cSSimon Glass    finally:
306e87ae1cSSimon Glass        sys.stdout,sys.stderr = oldout, olderr
316e87ae1cSSimon Glass        out[0] = out[0].getvalue()
326e87ae1cSSimon Glass        out[1] = out[1].getvalue()
336e87ae1cSSimon Glass
346e87ae1cSSimon Glass
356e87ae1cSSimon Glassclass TestFunctional(unittest.TestCase):
366e87ae1cSSimon Glass    def setUp(self):
376e87ae1cSSimon Glass        self.tmpdir = tempfile.mkdtemp(prefix='patman.')
386e87ae1cSSimon Glass
396e87ae1cSSimon Glass    def tearDown(self):
406e87ae1cSSimon Glass        shutil.rmtree(self.tmpdir)
416e87ae1cSSimon Glass
426e87ae1cSSimon Glass    @staticmethod
436e87ae1cSSimon Glass    def GetPath(fname):
446e87ae1cSSimon Glass        return os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),
456e87ae1cSSimon Glass                            'test', fname)
466e87ae1cSSimon Glass
476e87ae1cSSimon Glass    @classmethod
486e87ae1cSSimon Glass    def GetText(self, fname):
496e87ae1cSSimon Glass        return open(self.GetPath(fname)).read()
506e87ae1cSSimon Glass
516e87ae1cSSimon Glass    @classmethod
526e87ae1cSSimon Glass    def GetPatchName(self, subject):
536e87ae1cSSimon Glass        fname = re.sub('[ :]', '-', subject)
546e87ae1cSSimon Glass        return fname.replace('--', '-')
556e87ae1cSSimon Glass
566e87ae1cSSimon Glass    def CreatePatchesForTest(self, series):
576e87ae1cSSimon Glass        cover_fname = None
586e87ae1cSSimon Glass        fname_list = []
596e87ae1cSSimon Glass        for i, commit in enumerate(series.commits):
606e87ae1cSSimon Glass            clean_subject = self.GetPatchName(commit.subject)
616e87ae1cSSimon Glass            src_fname = '%04d-%s.patch' % (i + 1, clean_subject[:52])
626e87ae1cSSimon Glass            fname = os.path.join(self.tmpdir, src_fname)
636e87ae1cSSimon Glass            shutil.copy(self.GetPath(src_fname), fname)
646e87ae1cSSimon Glass            fname_list.append(fname)
656e87ae1cSSimon Glass        if series.get('cover'):
666e87ae1cSSimon Glass            src_fname = '0000-cover-letter.patch'
676e87ae1cSSimon Glass            cover_fname = os.path.join(self.tmpdir, src_fname)
686e87ae1cSSimon Glass            fname = os.path.join(self.tmpdir, src_fname)
696e87ae1cSSimon Glass            shutil.copy(self.GetPath(src_fname), fname)
706e87ae1cSSimon Glass
716e87ae1cSSimon Glass        return cover_fname, fname_list
726e87ae1cSSimon Glass
736e87ae1cSSimon Glass    def testBasic(self):
746e87ae1cSSimon Glass        """Tests the basic flow of patman
756e87ae1cSSimon Glass
766e87ae1cSSimon Glass        This creates a series from some hard-coded patches build from a simple
776e87ae1cSSimon Glass        tree with the following metadata in the top commit:
786e87ae1cSSimon Glass
796e87ae1cSSimon Glass            Series-to: u-boot
806e87ae1cSSimon Glass            Series-prefix: RFC
816e87ae1cSSimon Glass            Series-cc: Stefan Brüns <stefan.bruens@rwth-aachen.de>
826e87ae1cSSimon Glass            Cover-letter-cc: Lord Mëlchett <clergy@palace.gov>
836e87ae1cSSimon Glass            Series-version: 2
846e87ae1cSSimon Glass            Series-changes: 4
856e87ae1cSSimon Glass            - Some changes
866e87ae1cSSimon Glass
876e87ae1cSSimon Glass            Cover-letter:
886e87ae1cSSimon Glass            test: A test patch series
896e87ae1cSSimon Glass            This is a test of how the cover
906e87ae1cSSimon Glass            leter
916e87ae1cSSimon Glass            works
926e87ae1cSSimon Glass            END
936e87ae1cSSimon Glass
946e87ae1cSSimon Glass        and this in the first commit:
956e87ae1cSSimon Glass
966e87ae1cSSimon Glass            Series-notes:
976e87ae1cSSimon Glass            some notes
986e87ae1cSSimon Glass            about some things
996e87ae1cSSimon Glass            from the first commit
1006e87ae1cSSimon Glass            END
1016e87ae1cSSimon Glass
1026e87ae1cSSimon Glass            Commit-notes:
1036e87ae1cSSimon Glass            Some notes about
1046e87ae1cSSimon Glass            the first commit
1056e87ae1cSSimon Glass            END
1066e87ae1cSSimon Glass
1076e87ae1cSSimon Glass        with the following commands:
1086e87ae1cSSimon Glass
1096e87ae1cSSimon Glass           git log -n2 --reverse >/path/to/tools/patman/test/test01.txt
1106e87ae1cSSimon Glass           git format-patch --subject-prefix RFC --cover-letter HEAD~2
1116e87ae1cSSimon Glass           mv 00* /path/to/tools/patman/test
1126e87ae1cSSimon Glass
1136e87ae1cSSimon Glass        It checks these aspects:
1146e87ae1cSSimon Glass            - git log can be processed by patchstream
1156e87ae1cSSimon Glass            - emailing patches uses the correct command
1166e87ae1cSSimon Glass            - CC file has information on each commit
1176e87ae1cSSimon Glass            - cover letter has the expected text and subject
1186e87ae1cSSimon Glass            - each patch has the correct subject
1196e87ae1cSSimon Glass            - dry-run information prints out correctly
1206e87ae1cSSimon Glass            - unicode is handled correctly
1216e87ae1cSSimon Glass            - Series-to, Series-cc, Series-prefix, Cover-letter
1226e87ae1cSSimon Glass            - Cover-letter-cc, Series-version, Series-changes, Series-notes
1236e87ae1cSSimon Glass            - Commit-notes
1246e87ae1cSSimon Glass        """
1256e87ae1cSSimon Glass        process_tags = True
1266e87ae1cSSimon Glass        ignore_bad_tags = True
1276e87ae1cSSimon Glass        stefan = u'Stefan Brüns <stefan.bruens@rwth-aachen.de>'
1286e87ae1cSSimon Glass        rick = 'Richard III <richard@palace.gov>'
1296e87ae1cSSimon Glass        mel = u'Lord Mëlchett <clergy@palace.gov>'
1306e87ae1cSSimon Glass        ed = u'Lond Edmund Blackaddër <weasel@blackadder.org'
1316e87ae1cSSimon Glass        fred = 'Fred Bloggs <f.bloggs@napier.net>'
1326e87ae1cSSimon Glass        add_maintainers = [stefan, rick]
1336e87ae1cSSimon Glass        dry_run = True
1346e87ae1cSSimon Glass        in_reply_to = mel
1356e87ae1cSSimon Glass        count = 2
1366e87ae1cSSimon Glass        settings.alias = {
1376e87ae1cSSimon Glass                'fdt': ['simon'],
1386e87ae1cSSimon Glass                'u-boot': ['u-boot@lists.denx.de'],
1396e87ae1cSSimon Glass                'simon': [ed],
1406e87ae1cSSimon Glass                'fred': [fred],
1416e87ae1cSSimon Glass        }
1426e87ae1cSSimon Glass
1436e87ae1cSSimon Glass        text = self.GetText('test01.txt')
1446e87ae1cSSimon Glass        series = patchstream.GetMetaDataForTest(text)
1456e87ae1cSSimon Glass        cover_fname, args = self.CreatePatchesForTest(series)
1466e87ae1cSSimon Glass        with capture() as out:
1476e87ae1cSSimon Glass            patchstream.FixPatches(series, args)
1486e87ae1cSSimon Glass            if cover_fname and series.get('cover'):
1496e87ae1cSSimon Glass                patchstream.InsertCoverLetter(cover_fname, series, count)
1506e87ae1cSSimon Glass            series.DoChecks()
1516e87ae1cSSimon Glass            cc_file = series.MakeCcFile(process_tags, cover_fname,
1524fb35029SChris Packham                                        not ignore_bad_tags, add_maintainers,
1534fb35029SChris Packham                                        None)
1546e87ae1cSSimon Glass            cmd = gitutil.EmailPatches(series, cover_fname, args,
1556e87ae1cSSimon Glass                    dry_run, not ignore_bad_tags, cc_file,
1566e87ae1cSSimon Glass                    in_reply_to=in_reply_to, thread=None)
1576e87ae1cSSimon Glass            series.ShowActions(args, cmd, process_tags)
1586e87ae1cSSimon Glass        cc_lines = open(cc_file).read().splitlines()
1596e87ae1cSSimon Glass        os.remove(cc_file)
1606e87ae1cSSimon Glass
1616e87ae1cSSimon Glass        lines = out[0].splitlines()
1626e87ae1cSSimon Glass        #print '\n'.join(lines)
1636e87ae1cSSimon Glass        self.assertEqual('Cleaned %s patches' % len(series.commits), lines[0])
1646e87ae1cSSimon Glass        self.assertEqual('Change log missing for v2', lines[1])
1656e87ae1cSSimon Glass        self.assertEqual('Change log missing for v3', lines[2])
1666e87ae1cSSimon Glass        self.assertEqual('Change log for unknown version v4', lines[3])
1676e87ae1cSSimon Glass        self.assertEqual("Alias 'pci' not found", lines[4])
1686e87ae1cSSimon Glass        self.assertIn('Dry run', lines[5])
1696e87ae1cSSimon Glass        self.assertIn('Send a total of %d patches' % count, lines[7])
1706e87ae1cSSimon Glass        line = 8
1716e87ae1cSSimon Glass        for i, commit in enumerate(series.commits):
1726e87ae1cSSimon Glass            self.assertEqual('   %s' % args[i], lines[line + 0])
1736e87ae1cSSimon Glass            line += 1
1746e87ae1cSSimon Glass            while 'Cc:' in lines[line]:
1756e87ae1cSSimon Glass                line += 1
1766e87ae1cSSimon Glass        self.assertEqual('To:	  u-boot@lists.denx.de', lines[line])
1776e87ae1cSSimon Glass        self.assertEqual('Cc:	  %s' % stefan.encode('utf-8'), lines[line + 1])
1786e87ae1cSSimon Glass        self.assertEqual('Version:  3', lines[line + 2])
1796e87ae1cSSimon Glass        self.assertEqual('Prefix:\t  RFC', lines[line + 3])
1806e87ae1cSSimon Glass        self.assertEqual('Cover: 4 lines', lines[line + 4])
1816e87ae1cSSimon Glass        line += 5
1826e87ae1cSSimon Glass        self.assertEqual('      Cc:  %s' % mel.encode('utf-8'), lines[line + 0])
1836e87ae1cSSimon Glass        self.assertEqual('      Cc:  %s' % rick, lines[line + 1])
1846e87ae1cSSimon Glass        self.assertEqual('      Cc:  %s' % fred, lines[line + 2])
1856e87ae1cSSimon Glass        self.assertEqual('      Cc:  %s' % ed.encode('utf-8'), lines[line + 3])
1866e87ae1cSSimon Glass        expected = ('Git command: git send-email --annotate '
1876e87ae1cSSimon Glass                    '--in-reply-to="%s" --to "u-boot@lists.denx.de" '
1886e87ae1cSSimon Glass                    '--cc "%s" --cc-cmd "%s --cc-cmd %s" %s %s'
1896e87ae1cSSimon Glass                    % (in_reply_to, stefan, sys.argv[0], cc_file, cover_fname,
1906e87ae1cSSimon Glass                       ' '.join(args))).encode('utf-8')
1916e87ae1cSSimon Glass        line += 4
1926e87ae1cSSimon Glass        self.assertEqual(expected, lines[line])
1936e87ae1cSSimon Glass
1946e87ae1cSSimon Glass        self.assertEqual(('%s %s, %s' % (args[0], rick, stefan))
1956e87ae1cSSimon Glass                         .encode('utf-8'), cc_lines[0])
1966e87ae1cSSimon Glass        self.assertEqual(('%s %s, %s, %s, %s' % (args[1], fred, rick, stefan,
1976e87ae1cSSimon Glass                                            ed)).encode('utf-8'), cc_lines[1])
1986e87ae1cSSimon Glass
1996e87ae1cSSimon Glass        expected = '''
2006e87ae1cSSimon GlassThis is a test of how the cover
2016e87ae1cSSimon Glassleter
2026e87ae1cSSimon Glassworks
2036e87ae1cSSimon Glass
2046e87ae1cSSimon Glasssome notes
2056e87ae1cSSimon Glassabout some things
2066e87ae1cSSimon Glassfrom the first commit
2076e87ae1cSSimon Glass
2086e87ae1cSSimon GlassChanges in v4:
2096e87ae1cSSimon Glass- Some changes
2106e87ae1cSSimon Glass
2116e87ae1cSSimon GlassSimon Glass (2):
2126e87ae1cSSimon Glass  pci: Correct cast for sandbox
213*12308b12SSiva Durga Prasad Paladugu  fdt: Correct cast for sandbox in fdtdec_setup_mem_size_base()
2146e87ae1cSSimon Glass
2156e87ae1cSSimon Glass cmd/pci.c                   | 3 ++-
2166e87ae1cSSimon Glass fs/fat/fat.c                | 1 +
2176e87ae1cSSimon Glass lib/efi_loader/efi_memory.c | 1 +
2186e87ae1cSSimon Glass lib/fdtdec.c                | 3 ++-
2196e87ae1cSSimon Glass 4 files changed, 6 insertions(+), 2 deletions(-)
2206e87ae1cSSimon Glass
2216e87ae1cSSimon Glass--\x20
2226e87ae1cSSimon Glass2.7.4
2236e87ae1cSSimon Glass
2246e87ae1cSSimon Glass'''
2256e87ae1cSSimon Glass        lines = open(cover_fname).read().splitlines()
2266e87ae1cSSimon Glass        #print '\n'.join(lines)
2276e87ae1cSSimon Glass        self.assertEqual(
2286e87ae1cSSimon Glass                'Subject: [RFC PATCH v3 0/2] test: A test patch series',
2296e87ae1cSSimon Glass                lines[3])
2306e87ae1cSSimon Glass        self.assertEqual(expected.splitlines(), lines[7:])
2316e87ae1cSSimon Glass
2326e87ae1cSSimon Glass        for i, fname in enumerate(args):
2336e87ae1cSSimon Glass            lines = open(fname).read().splitlines()
2346e87ae1cSSimon Glass            #print '\n'.join(lines)
2356e87ae1cSSimon Glass            subject = [line for line in lines if line.startswith('Subject')]
2366e87ae1cSSimon Glass            self.assertEqual('Subject: [RFC %d/%d]' % (i + 1, count),
2376e87ae1cSSimon Glass                             subject[0][:18])
2386e87ae1cSSimon Glass            if i == 0:
2396e87ae1cSSimon Glass                # Check that we got our commit notes
2406e87ae1cSSimon Glass                self.assertEqual('---', lines[17])
2416e87ae1cSSimon Glass                self.assertEqual('Some notes about', lines[18])
2426e87ae1cSSimon Glass                self.assertEqual('the first commit', lines[19])
243