1 # -*- coding: utf-8 -*-
2 # SPDX-License-Identifier: GPL-2.0+
4 # Copyright 2017 Google, Inc
15 from io import StringIO
17 from patman import gitutil
18 from patman import patchstream
19 from patman import settings
20 from patman import tools
23 @contextlib.contextmanager
26 oldout,olderr = sys.stdout, sys.stderr
28 out=[StringIO(), StringIO()]
29 sys.stdout,sys.stderr = out
32 sys.stdout,sys.stderr = oldout, olderr
33 out[0] = out[0].getvalue()
34 out[1] = out[1].getvalue()
37 class TestFunctional(unittest.TestCase):
39 self.tmpdir = tempfile.mkdtemp(prefix='patman.')
42 shutil.rmtree(self.tmpdir)
46 return os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),
50 def GetText(self, fname):
51 return open(self.GetPath(fname), encoding='utf-8').read()
54 def GetPatchName(self, subject):
55 fname = re.sub('[ :]', '-', subject)
56 return fname.replace('--', '-')
58 def CreatePatchesForTest(self, series):
61 for i, commit in enumerate(series.commits):
62 clean_subject = self.GetPatchName(commit.subject)
63 src_fname = '%04d-%s.patch' % (i + 1, clean_subject[:52])
64 fname = os.path.join(self.tmpdir, src_fname)
65 shutil.copy(self.GetPath(src_fname), fname)
66 fname_list.append(fname)
67 if series.get('cover'):
68 src_fname = '0000-cover-letter.patch'
69 cover_fname = os.path.join(self.tmpdir, src_fname)
70 fname = os.path.join(self.tmpdir, src_fname)
71 shutil.copy(self.GetPath(src_fname), fname)
73 return cover_fname, fname_list
76 """Tests the basic flow of patman
78 This creates a series from some hard-coded patches build from a simple
79 tree with the following metadata in the top commit:
83 Series-cc: Stefan Brüns <stefan.bruens@rwth-aachen.de>
84 Cover-letter-cc: Lord Mëlchett <clergy@palace.gov>
90 test: A test patch series
91 This is a test of how the cover
96 and this in the first commit:
101 from the first commit
109 with the following commands:
111 git log -n2 --reverse >/path/to/tools/patman/test/test01.txt
112 git format-patch --subject-prefix RFC --cover-letter HEAD~2
113 mv 00* /path/to/tools/patman/test
115 It checks these aspects:
116 - git log can be processed by patchstream
117 - emailing patches uses the correct command
118 - CC file has information on each commit
119 - cover letter has the expected text and subject
120 - each patch has the correct subject
121 - dry-run information prints out correctly
122 - unicode is handled correctly
123 - Series-to, Series-cc, Series-prefix, Cover-letter
124 - Cover-letter-cc, Series-version, Series-changes, Series-notes
128 ignore_bad_tags = True
129 stefan = b'Stefan Br\xc3\xbcns <stefan.bruens@rwth-aachen.de>'.decode('utf-8')
130 rick = 'Richard III <richard@palace.gov>'
131 mel = b'Lord M\xc3\xablchett <clergy@palace.gov>'.decode('utf-8')
132 ed = b'Lond Edmund Blackadd\xc3\xabr <weasel@blackadder.org'.decode('utf-8')
133 fred = 'Fred Bloggs <f.bloggs@napier.net>'
134 add_maintainers = [stefan, rick]
140 'u-boot': ['u-boot@lists.denx.de'],
145 text = self.GetText('test01.txt')
146 series = patchstream.GetMetaDataForTest(text)
147 cover_fname, args = self.CreatePatchesForTest(series)
148 with capture() as out:
149 patchstream.FixPatches(series, args)
150 if cover_fname and series.get('cover'):
151 patchstream.InsertCoverLetter(cover_fname, series, count)
153 cc_file = series.MakeCcFile(process_tags, cover_fname,
154 not ignore_bad_tags, add_maintainers,
156 cmd = gitutil.EmailPatches(series, cover_fname, args,
157 dry_run, not ignore_bad_tags, cc_file,
158 in_reply_to=in_reply_to, thread=None)
159 series.ShowActions(args, cmd, process_tags)
160 cc_lines = open(cc_file, encoding='utf-8').read().splitlines()
163 lines = out[0].splitlines()
164 self.assertEqual('Cleaned %s patches' % len(series.commits), lines[0])
165 self.assertEqual('Change log missing for v2', lines[1])
166 self.assertEqual('Change log missing for v3', lines[2])
167 self.assertEqual('Change log for unknown version v4', lines[3])
168 self.assertEqual("Alias 'pci' not found", lines[4])
169 self.assertIn('Dry run', lines[5])
170 self.assertIn('Send a total of %d patches' % count, lines[7])
172 for i, commit in enumerate(series.commits):
173 self.assertEqual(' %s' % args[i], lines[line + 0])
175 while 'Cc:' in lines[line]:
177 self.assertEqual('To: u-boot@lists.denx.de', lines[line])
178 self.assertEqual('Cc: %s' % tools.FromUnicode(stefan),
180 self.assertEqual('Version: 3', lines[line + 2])
181 self.assertEqual('Prefix:\t RFC', lines[line + 3])
182 self.assertEqual('Cover: 4 lines', lines[line + 4])
184 self.assertEqual(' Cc: %s' % fred, lines[line + 0])
185 self.assertEqual(' Cc: %s' % tools.FromUnicode(ed),
187 self.assertEqual(' Cc: %s' % tools.FromUnicode(mel),
189 self.assertEqual(' Cc: %s' % rick, lines[line + 3])
190 expected = ('Git command: git send-email --annotate '
191 '--in-reply-to="%s" --to "u-boot@lists.denx.de" '
192 '--cc "%s" --cc-cmd "%s --cc-cmd %s" %s %s'
193 % (in_reply_to, stefan, sys.argv[0], cc_file, cover_fname,
196 self.assertEqual(expected, tools.ToUnicode(lines[line]))
198 self.assertEqual(('%s %s\0%s' % (args[0], rick, stefan)),
199 tools.ToUnicode(cc_lines[0]))
200 self.assertEqual(('%s %s\0%s\0%s\0%s' % (args[1], fred, ed, rick,
201 stefan)), tools.ToUnicode(cc_lines[1]))
204 This is a test of how the cover
210 from the first commit
216 pci: Correct cast for sandbox
217 fdt: Correct cast for sandbox in fdtdec_setup_mem_size_base()
221 lib/efi_loader/efi_memory.c | 1 +
223 4 files changed, 6 insertions(+), 2 deletions(-)
229 lines = open(cover_fname, encoding='utf-8').read().splitlines()
231 'Subject: [RFC PATCH v3 0/2] test: A test patch series',
233 self.assertEqual(expected.splitlines(), lines[7:])
235 for i, fname in enumerate(args):
236 lines = open(fname, encoding='utf-8').read().splitlines()
237 subject = [line for line in lines if line.startswith('Subject')]
238 self.assertEqual('Subject: [RFC %d/%d]' % (i + 1, count),
241 # Check that we got our commit notes
242 self.assertEqual('---', lines[17])
243 self.assertEqual('Some notes about', lines[18])
244 self.assertEqual('the first commit', lines[19])