]> git.sur5r.net Git - u-boot/blob - tools/patman/func_test.py
Merge branch 'master' of git://git.denx.de/u-boot-sunxi
[u-boot] / tools / patman / func_test.py
1 # -*- coding: utf-8 -*-
2 #
3 # Copyright 2017 Google, Inc
4 #
5 # SPDX-License-Identifier:      GPL-2.0+
6 #
7
8 import contextlib
9 import os
10 import re
11 import shutil
12 import sys
13 import tempfile
14 import unittest
15
16 import gitutil
17 import patchstream
18 import settings
19
20
21 @contextlib.contextmanager
22 def capture():
23     import sys
24     from cStringIO import StringIO
25     oldout,olderr = sys.stdout, sys.stderr
26     try:
27         out=[StringIO(), StringIO()]
28         sys.stdout,sys.stderr = out
29         yield out
30     finally:
31         sys.stdout,sys.stderr = oldout, olderr
32         out[0] = out[0].getvalue()
33         out[1] = out[1].getvalue()
34
35
36 class TestFunctional(unittest.TestCase):
37     def setUp(self):
38         self.tmpdir = tempfile.mkdtemp(prefix='patman.')
39
40     def tearDown(self):
41         shutil.rmtree(self.tmpdir)
42
43     @staticmethod
44     def GetPath(fname):
45         return os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),
46                             'test', fname)
47
48     @classmethod
49     def GetText(self, fname):
50         return open(self.GetPath(fname)).read()
51
52     @classmethod
53     def GetPatchName(self, subject):
54         fname = re.sub('[ :]', '-', subject)
55         return fname.replace('--', '-')
56
57     def CreatePatchesForTest(self, series):
58         cover_fname = None
59         fname_list = []
60         for i, commit in enumerate(series.commits):
61             clean_subject = self.GetPatchName(commit.subject)
62             src_fname = '%04d-%s.patch' % (i + 1, clean_subject[:52])
63             fname = os.path.join(self.tmpdir, src_fname)
64             shutil.copy(self.GetPath(src_fname), fname)
65             fname_list.append(fname)
66         if series.get('cover'):
67             src_fname = '0000-cover-letter.patch'
68             cover_fname = os.path.join(self.tmpdir, src_fname)
69             fname = os.path.join(self.tmpdir, src_fname)
70             shutil.copy(self.GetPath(src_fname), fname)
71
72         return cover_fname, fname_list
73
74     def testBasic(self):
75         """Tests the basic flow of patman
76
77         This creates a series from some hard-coded patches build from a simple
78         tree with the following metadata in the top commit:
79
80             Series-to: u-boot
81             Series-prefix: RFC
82             Series-cc: Stefan Brüns <stefan.bruens@rwth-aachen.de>
83             Cover-letter-cc: Lord Mëlchett <clergy@palace.gov>
84             Series-version: 2
85             Series-changes: 4
86             - Some changes
87
88             Cover-letter:
89             test: A test patch series
90             This is a test of how the cover
91             leter
92             works
93             END
94
95         and this in the first commit:
96
97             Series-notes:
98             some notes
99             about some things
100             from the first commit
101             END
102
103             Commit-notes:
104             Some notes about
105             the first commit
106             END
107
108         with the following commands:
109
110            git log -n2 --reverse >/path/to/tools/patman/test/test01.txt
111            git format-patch --subject-prefix RFC --cover-letter HEAD~2
112            mv 00* /path/to/tools/patman/test
113
114         It checks these aspects:
115             - git log can be processed by patchstream
116             - emailing patches uses the correct command
117             - CC file has information on each commit
118             - cover letter has the expected text and subject
119             - each patch has the correct subject
120             - dry-run information prints out correctly
121             - unicode is handled correctly
122             - Series-to, Series-cc, Series-prefix, Cover-letter
123             - Cover-letter-cc, Series-version, Series-changes, Series-notes
124             - Commit-notes
125         """
126         process_tags = True
127         ignore_bad_tags = True
128         stefan = u'Stefan Brüns <stefan.bruens@rwth-aachen.de>'
129         rick = 'Richard III <richard@palace.gov>'
130         mel = u'Lord Mëlchett <clergy@palace.gov>'
131         ed = u'Lond Edmund Blackaddër <weasel@blackadder.org'
132         fred = 'Fred Bloggs <f.bloggs@napier.net>'
133         add_maintainers = [stefan, rick]
134         dry_run = True
135         in_reply_to = mel
136         count = 2
137         settings.alias = {
138                 'fdt': ['simon'],
139                 'u-boot': ['u-boot@lists.denx.de'],
140                 'simon': [ed],
141                 'fred': [fred],
142         }
143
144         text = self.GetText('test01.txt')
145         series = patchstream.GetMetaDataForTest(text)
146         cover_fname, args = self.CreatePatchesForTest(series)
147         with capture() as out:
148             patchstream.FixPatches(series, args)
149             if cover_fname and series.get('cover'):
150                 patchstream.InsertCoverLetter(cover_fname, series, count)
151             series.DoChecks()
152             cc_file = series.MakeCcFile(process_tags, cover_fname,
153                                         not ignore_bad_tags, add_maintainers)
154             cmd = gitutil.EmailPatches(series, cover_fname, args,
155                     dry_run, not ignore_bad_tags, cc_file,
156                     in_reply_to=in_reply_to, thread=None)
157             series.ShowActions(args, cmd, process_tags)
158         cc_lines = open(cc_file).read().splitlines()
159         os.remove(cc_file)
160
161         lines = out[0].splitlines()
162         #print '\n'.join(lines)
163         self.assertEqual('Cleaned %s patches' % len(series.commits), lines[0])
164         self.assertEqual('Change log missing for v2', lines[1])
165         self.assertEqual('Change log missing for v3', lines[2])
166         self.assertEqual('Change log for unknown version v4', lines[3])
167         self.assertEqual("Alias 'pci' not found", lines[4])
168         self.assertIn('Dry run', lines[5])
169         self.assertIn('Send a total of %d patches' % count, lines[7])
170         line = 8
171         for i, commit in enumerate(series.commits):
172             self.assertEqual('   %s' % args[i], lines[line + 0])
173             line += 1
174             while 'Cc:' in lines[line]:
175                 line += 1
176         self.assertEqual('To:     u-boot@lists.denx.de', lines[line])
177         self.assertEqual('Cc:     %s' % stefan.encode('utf-8'), lines[line + 1])
178         self.assertEqual('Version:  3', lines[line + 2])
179         self.assertEqual('Prefix:\t  RFC', lines[line + 3])
180         self.assertEqual('Cover: 4 lines', lines[line + 4])
181         line += 5
182         self.assertEqual('      Cc:  %s' % mel.encode('utf-8'), lines[line + 0])
183         self.assertEqual('      Cc:  %s' % rick, lines[line + 1])
184         self.assertEqual('      Cc:  %s' % fred, lines[line + 2])
185         self.assertEqual('      Cc:  %s' % ed.encode('utf-8'), lines[line + 3])
186         expected = ('Git command: git send-email --annotate '
187                     '--in-reply-to="%s" --to "u-boot@lists.denx.de" '
188                     '--cc "%s" --cc-cmd "%s --cc-cmd %s" %s %s'
189                     % (in_reply_to, stefan, sys.argv[0], cc_file, cover_fname,
190                        ' '.join(args))).encode('utf-8')
191         line += 4
192         self.assertEqual(expected, lines[line])
193
194         self.assertEqual(('%s %s, %s' % (args[0], rick, stefan))
195                          .encode('utf-8'), cc_lines[0])
196         self.assertEqual(('%s %s, %s, %s, %s' % (args[1], fred, rick, stefan,
197                                             ed)).encode('utf-8'), cc_lines[1])
198
199         expected = '''
200 This is a test of how the cover
201 leter
202 works
203
204 some notes
205 about some things
206 from the first commit
207
208 Changes in v4:
209 - Some changes
210
211 Simon Glass (2):
212   pci: Correct cast for sandbox
213   fdt: Correct cast for sandbox in fdtdec_setup_memory_size()
214
215  cmd/pci.c                   | 3 ++-
216  fs/fat/fat.c                | 1 +
217  lib/efi_loader/efi_memory.c | 1 +
218  lib/fdtdec.c                | 3 ++-
219  4 files changed, 6 insertions(+), 2 deletions(-)
220
221 --\x20
222 2.7.4
223
224 '''
225         lines = open(cover_fname).read().splitlines()
226         #print '\n'.join(lines)
227         self.assertEqual(
228                 'Subject: [RFC PATCH v3 0/2] test: A test patch series',
229                 lines[3])
230         self.assertEqual(expected.splitlines(), lines[7:])
231
232         for i, fname in enumerate(args):
233             lines = open(fname).read().splitlines()
234             #print '\n'.join(lines)
235             subject = [line for line in lines if line.startswith('Subject')]
236             self.assertEqual('Subject: [RFC %d/%d]' % (i + 1, count),
237                              subject[0][:18])
238             if i == 0:
239                 # Check that we got our commit notes
240                 self.assertEqual('---', lines[17])
241                 self.assertEqual('Some notes about', lines[18])
242                 self.assertEqual('the first commit', lines[19])