blob: 85372f3c0ade0d333b4e4039ee1c8d2189123502 [file] [log] [blame]
# -*- coding: utf-8 -*-
# SPDX-License-Identifier: GPL-2.0+
# Copyright 2017 Google, Inc
import contextlib
import os
import re
import shutil
import sys
import tempfile
import unittest
import gitutil
import patchstream
import settings
def capture():
import sys
from cStringIO import StringIO
oldout,olderr = sys.stdout, sys.stderr
out=[StringIO(), StringIO()]
sys.stdout,sys.stderr = out
yield out
sys.stdout,sys.stderr = oldout, olderr
out[0] = out[0].getvalue()
out[1] = out[1].getvalue()
class TestFunctional(unittest.TestCase):
def setUp(self):
self.tmpdir = tempfile.mkdtemp(prefix='patman.')
def tearDown(self):
def GetPath(fname):
return os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),
'test', fname)
def GetText(self, fname):
return open(self.GetPath(fname)).read()
def GetPatchName(self, subject):
fname = re.sub('[ :]', '-', subject)
return fname.replace('--', '-')
def CreatePatchesForTest(self, series):
cover_fname = None
fname_list = []
for i, commit in enumerate(series.commits):
clean_subject = self.GetPatchName(commit.subject)
src_fname = '%04d-%s.patch' % (i + 1, clean_subject[:52])
fname = os.path.join(self.tmpdir, src_fname)
shutil.copy(self.GetPath(src_fname), fname)
if series.get('cover'):
src_fname = '0000-cover-letter.patch'
cover_fname = os.path.join(self.tmpdir, src_fname)
fname = os.path.join(self.tmpdir, src_fname)
shutil.copy(self.GetPath(src_fname), fname)
return cover_fname, fname_list
def testBasic(self):
"""Tests the basic flow of patman
This creates a series from some hard-coded patches build from a simple
tree with the following metadata in the top commit:
Series-to: u-boot
Series-prefix: RFC
Series-cc: Stefan Brüns <>
Cover-letter-cc: Lord Mëlchett <>
Series-version: 2
Series-changes: 4
- Some changes
test: A test patch series
This is a test of how the cover
and this in the first commit:
some notes
about some things
from the first commit
Some notes about
the first commit
with the following commands:
git log -n2 --reverse >/path/to/tools/patman/test/test01.txt
git format-patch --subject-prefix RFC --cover-letter HEAD~2
mv 00* /path/to/tools/patman/test
It checks these aspects:
- git log can be processed by patchstream
- emailing patches uses the correct command
- CC file has information on each commit
- cover letter has the expected text and subject
- each patch has the correct subject
- dry-run information prints out correctly
- unicode is handled correctly
- Series-to, Series-cc, Series-prefix, Cover-letter
- Cover-letter-cc, Series-version, Series-changes, Series-notes
- Commit-notes
process_tags = True
ignore_bad_tags = True
stefan = u'Stefan Brüns <>'
rick = 'Richard III <>'
mel = u'Lord Mëlchett <>'
ed = u'Lond Edmund Blackaddër <'
fred = 'Fred Bloggs <>'
add_maintainers = [stefan, rick]
dry_run = True
in_reply_to = mel
count = 2
settings.alias = {
'fdt': ['simon'],
'u-boot': [''],
'simon': [ed],
'fred': [fred],
text = self.GetText('test01.txt')
series = patchstream.GetMetaDataForTest(text)
cover_fname, args = self.CreatePatchesForTest(series)
with capture() as out:
patchstream.FixPatches(series, args)
if cover_fname and series.get('cover'):
patchstream.InsertCoverLetter(cover_fname, series, count)
cc_file = series.MakeCcFile(process_tags, cover_fname,
not ignore_bad_tags, add_maintainers)
cmd = gitutil.EmailPatches(series, cover_fname, args,
dry_run, not ignore_bad_tags, cc_file,
in_reply_to=in_reply_to, thread=None)
series.ShowActions(args, cmd, process_tags)
cc_lines = open(cc_file).read().splitlines()
lines = out[0].splitlines()
#print '\n'.join(lines)
self.assertEqual('Cleaned %s patches' % len(series.commits), lines[0])
self.assertEqual('Change log missing for v2', lines[1])
self.assertEqual('Change log missing for v3', lines[2])
self.assertEqual('Change log for unknown version v4', lines[3])
self.assertEqual("Alias 'pci' not found", lines[4])
self.assertIn('Dry run', lines[5])
self.assertIn('Send a total of %d patches' % count, lines[7])
line = 8
for i, commit in enumerate(series.commits):
self.assertEqual(' %s' % args[i], lines[line + 0])
line += 1
while 'Cc:' in lines[line]:
line += 1
self.assertEqual('To:', lines[line])
self.assertEqual('Cc: %s' % stefan.encode('utf-8'), lines[line + 1])
self.assertEqual('Version: 3', lines[line + 2])
self.assertEqual('Prefix:\t RFC', lines[line + 3])
self.assertEqual('Cover: 4 lines', lines[line + 4])
line += 5
self.assertEqual(' Cc: %s' % mel.encode('utf-8'), lines[line + 0])
self.assertEqual(' Cc: %s' % rick, lines[line + 1])
self.assertEqual(' Cc: %s' % fred, lines[line + 2])
self.assertEqual(' Cc: %s' % ed.encode('utf-8'), lines[line + 3])
expected = ('Git command: git send-email --annotate '
'--in-reply-to="%s" --to "" '
'--cc "%s" --cc-cmd "%s --cc-cmd %s" %s %s'
% (in_reply_to, stefan, sys.argv[0], cc_file, cover_fname,
' '.join(args))).encode('utf-8')
line += 4
self.assertEqual(expected, lines[line])
self.assertEqual(('%s %s, %s' % (args[0], rick, stefan))
.encode('utf-8'), cc_lines[0])
self.assertEqual(('%s %s, %s, %s, %s' % (args[1], fred, rick, stefan,
ed)).encode('utf-8'), cc_lines[1])
expected = '''
This is a test of how the cover
some notes
about some things
from the first commit
Changes in v4:
- Some changes
Simon Glass (2):
pci: Correct cast for sandbox
fdt: Correct cast for sandbox in fdtdec_setup_memory_size()
cmd/pci.c | 3 ++-
fs/fat/fat.c | 1 +
lib/efi_loader/efi_memory.c | 1 +
lib/fdtdec.c | 3 ++-
4 files changed, 6 insertions(+), 2 deletions(-)
lines = open(cover_fname).read().splitlines()
#print '\n'.join(lines)
'Subject: [RFC PATCH v3 0/2] test: A test patch series',
self.assertEqual(expected.splitlines(), lines[7:])
for i, fname in enumerate(args):
lines = open(fname).read().splitlines()
#print '\n'.join(lines)
subject = [line for line in lines if line.startswith('Subject')]
self.assertEqual('Subject: [RFC %d/%d]' % (i + 1, count),
if i == 0:
# Check that we got our commit notes
self.assertEqual('---', lines[17])
self.assertEqual('Some notes about', lines[18])
self.assertEqual('the first commit', lines[19])