summaryrefslogtreecommitdiff
path: root/tools/patman/func_test.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/patman/func_test.py')
-rw-r--r--tools/patman/func_test.py1342
1 files changed, 0 insertions, 1342 deletions
diff --git a/tools/patman/func_test.py b/tools/patman/func_test.py
deleted file mode 100644
index d029181765c..00000000000
--- a/tools/patman/func_test.py
+++ /dev/null
@@ -1,1342 +0,0 @@
-# -*- coding: utf-8 -*-
-# SPDX-License-Identifier: GPL-2.0+
-#
-# Copyright 2017 Google, Inc
-#
-
-"""Functional tests for checking that patman behaves correctly"""
-
-import asyncio
-import contextlib
-import os
-import pathlib
-import re
-import shutil
-import sys
-import unittest
-
-import pygit2
-
-from u_boot_pylib import command
-from u_boot_pylib import gitutil
-from u_boot_pylib import terminal
-from u_boot_pylib import tools
-
-from patman.commit import Commit
-from patman import control
-from patman import patchstream
-from patman.patchstream import PatchStream
-from patman import patchwork
-from patman import send
-from patman.series import Series
-from patman import status
-from patman.test_common import TestCommon
-
-PATMAN_DIR = pathlib.Path(__file__).parent
-TEST_DATA_DIR = PATMAN_DIR / 'test/'
-
-
-def directory_excursion(directory):
- """Change directory to `directory` for a limited to the context block."""
- current = os.getcwd()
- try:
- os.chdir(directory)
- yield
- finally:
- os.chdir(current)
-
-
-class TestFunctional(unittest.TestCase, TestCommon):
- """Functional tests for checking that patman behaves correctly"""
- fred = 'Fred Bloggs <[email protected]>'
- joe = 'Joe Bloggs <[email protected]>'
- mary = 'Mary Bloggs <[email protected]>'
- commits = None
- patches = None
-
- def setUp(self):
- TestCommon.setUp(self)
- self.repo = None
- self._patman_pathname = sys.argv[0]
- self._patman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
-
- def tearDown(self):
- TestCommon.tearDown(self)
-
- @staticmethod
- def _get_path(fname):
- """Get the path to a test file
-
- Args:
- fname (str): Filename to obtain
-
- Returns:
- str: Full path to file in the test directory
- """
- return TEST_DATA_DIR / fname
-
- @classmethod
- def _get_text(cls, fname):
- """Read a file as text
-
- Args:
- fname (str): Filename to read
-
- Returns:
- str: Contents of file
- """
- return open(cls._get_path(fname), encoding='utf-8').read()
-
- @classmethod
- def _get_patch_name(cls, subject):
- """Get the filename of a patch given its subject
-
- Args:
- subject (str): Patch subject
-
- Returns:
- str: Filename for that patch
- """
- fname = re.sub('[ :]', '-', subject)
- return fname.replace('--', '-')
-
- def _create_patches_for_test(self, series):
- """Create patch files for use by tests
-
- This copies patch files from the test directory as needed by the series
-
- Args:
- series (Series): Series containing commits to convert
-
- Returns:
- tuple:
- str: Cover-letter filename, or None if none
- fname_list: list of str, each a patch filename
- """
- cover_fname = None
- fname_list = []
- for i, commit in enumerate(series.commits):
- clean_subject = self._get_patch_name(commit.subject)
- src_fname = '%04d-%s.patch' % (i + 1, clean_subject[:52])
- fname = os.path.join(self.tmpdir, src_fname)
- shutil.copy(self._get_path(src_fname), fname)
- fname_list.append(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._get_path(src_fname), fname)
-
- return cover_fname, fname_list
-
- def test_basic(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-postfix: some-branch
- Series-cc: Stefan Brüns <[email protected]>
- Cover-letter-cc: Lord Mëlchett <[email protected]>
- Series-version: 3
- Patch-cc: fred
- Series-process-log: sort, uniq
- Series-changes: 4
- - Some changes
- - Multi
- line
- change
-
- Commit-changes: 2
- - Changes only for this commit
-
- Cover-changes: 4
- - Some notes for the cover letter
-
- Cover-letter:
- test: A test patch series
- This is a test of how the cover
- letter
- works
- END
-
- and this in the first commit:
-
- Commit-changes: 2
- - second revision change
-
- Series-notes:
- some notes
- about some things
- from the first commit
- END
-
- Commit-notes:
- Some notes about
- the first commit
- END
-
- 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, Series-postfix, Cover-letter
- - Cover-letter-cc, Series-version, Series-changes, Series-notes
- - Commit-notes
- """
- process_tags = True
- ignore_bad_tags = False
- stefan = (b'Stefan Br\xc3\xbcns <[email protected]>'
- .decode('utf-8'))
- rick = 'Richard III <[email protected]>'
- mel = b'Lord M\xc3\xablchett <[email protected]>'.decode('utf-8')
- add_maintainers = [stefan, rick]
- dry_run = True
- in_reply_to = mel
- count = 2
- alias = {
- 'fdt': ['simon'],
- 'u-boot': ['[email protected]'],
- 'simon': [self.leb],
- 'fred': [self.fred],
- 'joe': [self.joe],
- }
-
- text = self._get_text('test01.txt')
- series = patchstream.get_metadata_for_test(text)
- series.base_commit = Commit('1a44532')
- series.branch = 'mybranch'
- cover_fname, args = self._create_patches_for_test(series)
- get_maintainer_script = str(pathlib.Path(__file__).parent.parent.parent
- / 'get_maintainer.pl') + ' --norolestats'
- with terminal.capture() as out:
- patchstream.fix_patches(series, args)
- if cover_fname and series.get('cover'):
- patchstream.insert_cover_letter(cover_fname, series, count)
- series.DoChecks()
- cc_file = series.MakeCcFile(process_tags, cover_fname,
- not ignore_bad_tags, add_maintainers,
- None, get_maintainer_script, alias)
- cmd = gitutil.email_patches(
- series, cover_fname, args, dry_run, not ignore_bad_tags,
- cc_file, alias, in_reply_to=in_reply_to, thread=None)
- series.ShowActions(args, cmd, process_tags, alias)
- cc_lines = tools.read_file(cc_file, binary=False).splitlines()
- os.remove(cc_file)
-
- itr = iter(out[0].getvalue().splitlines())
- self.assertEqual('Cleaned %s patches' % len(series.commits),
- next(itr))
- self.assertEqual('Change log missing for v2', next(itr))
- self.assertEqual('Change log missing for v3', next(itr))
- self.assertEqual('Change log for unknown version v4', next(itr))
- self.assertEqual("Alias 'pci' not found", next(itr))
- while next(itr) != 'Cc processing complete':
- pass
- self.assertIn('Dry run', next(itr))
- self.assertEqual('', next(itr))
- self.assertIn('Send a total of %d patches' % count, next(itr))
- prev = next(itr)
- for i in range(len(series.commits)):
- self.assertEqual(' %s' % args[i], prev)
- while True:
- prev = next(itr)
- if 'Cc:' not in prev:
- break
- self.assertEqual('To: [email protected]', prev)
- self.assertEqual('Cc: %s' % stefan, next(itr))
- self.assertEqual('Version: 3', next(itr))
- self.assertEqual('Prefix:\t RFC', next(itr))
- self.assertEqual('Postfix:\t some-branch', next(itr))
- self.assertEqual('Cover: 4 lines', next(itr))
- self.assertEqual(' Cc: %s' % self.fred, next(itr))
- self.assertEqual(' Cc: %s' % self.joe, next(itr))
- self.assertEqual(' Cc: %s' % self.leb,
- next(itr))
- self.assertEqual(' Cc: %s' % mel, next(itr))
- self.assertEqual(' Cc: %s' % rick, next(itr))
- expected = ('Git command: git send-email --annotate '
- '--in-reply-to="%s" --to [email protected] '
- '--cc "%s" --cc-cmd "%s send --cc-cmd %s" %s %s'
- % (in_reply_to, stefan, sys.argv[0], cc_file, cover_fname,
- ' '.join(args)))
- self.assertEqual(expected, next(itr))
-
- self.assertEqual(('%s %s\0%s' % (args[0], rick, stefan)), cc_lines[0])
- self.assertEqual(
- '%s %s\0%s\0%s\0%s\0%s' % (args[1], self.fred, self.joe, self.leb,
- rick, stefan),
- cc_lines[1])
-
- expected = '''
-This is a test of how the cover
-letter
-works
-
-some notes
-about some things
-from the first commit
-
-Changes in v4:
-- Multi
- line
- change
-- Some changes
-- Some notes for the cover letter
-- fdt: Correct cast for sandbox in fdtdec_setup_mem_size_base()
-
-Simon Glass (2):
- pci: Correct cast for sandbox
- fdt: Correct cast for sandbox in fdtdec_setup_mem_size_base()
-
- 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(-)
-
---\x20
-2.7.4
-
-base-commit: 1a44532
-branch: mybranch
-'''
- lines = tools.read_file(cover_fname, binary=False).splitlines()
- self.assertEqual(
- 'Subject: [RFC PATCH some-branch v3 0/2] test: A test patch series',
- lines[3])
- self.assertEqual(expected.splitlines(), lines[7:])
-
- for i, fname in enumerate(args):
- lines = tools.read_file(fname, binary=False).splitlines()
- subject = [line for line in lines if line.startswith('Subject')]
- self.assertEqual('Subject: [RFC %d/%d]' % (i + 1, count),
- subject[0][:18])
-
- # Check that we got our commit notes
- start = 0
- expected = ''
-
- if i == 0:
- start = 17
- expected = '''---
-Some notes about
-the first commit
-
-(no changes since v2)
-
-Changes in v2:
-- second revision change'''
- elif i == 1:
- start = 17
- expected = '''---
-
-Changes in v4:
-- Multi
- line
- change
-- New
-- Some changes
-
-Changes in v2:
-- Changes only for this commit'''
-
- if expected:
- expected = expected.splitlines()
- self.assertEqual(expected, lines[start:(start+len(expected))])
-
- def test_base_commit(self):
- """Test adding a base commit with no cover letter"""
- orig_text = self._get_text('test01.txt')
- pos = orig_text.index(
- 'commit 5ab48490f03051875ab13d288a4bf32b507d76fd')
- text = orig_text[:pos]
- series = patchstream.get_metadata_for_test(text)
- series.base_commit = Commit('1a44532')
- series.branch = 'mybranch'
- cover_fname, args = self._create_patches_for_test(series)
- self.assertFalse(cover_fname)
- with terminal.capture() as out:
- patchstream.fix_patches(series, args, insert_base_commit=True)
- self.assertEqual('Cleaned 1 patch\n', out[0].getvalue())
- lines = tools.read_file(args[0], binary=False).splitlines()
- pos = lines.index('-- ')
-
- # We expect these lines at the end:
- # -- (with trailing space)
- # 2.7.4
- # (empty)
- # base-commit: xxx
- # branch: xxx
- self.assertEqual('base-commit: 1a44532', lines[pos + 3])
- self.assertEqual('branch: mybranch', lines[pos + 4])
-
- def test_branch(self):
- """Test creating patches from a branch"""
- repo = self.make_git_tree()
- target = repo.lookup_reference('refs/heads/first')
- # pylint doesn't seem to find this
- # pylint: disable=E1101
- self.repo.checkout(target, strategy=pygit2.GIT_CHECKOUT_FORCE)
- control.setup()
- orig_dir = os.getcwd()
- try:
- os.chdir(self.tmpdir)
-
- # Check that it can detect the current branch
- self.assertEqual(2, gitutil.count_commits_to_branch(None))
- col = terminal.Color()
- with terminal.capture() as _:
- _, cover_fname, patch_files = send.prepare_patches(
- col, branch=None, count=-1, start=0, end=0,
- ignore_binary=False, signoff=True)
- self.assertIsNone(cover_fname)
- self.assertEqual(2, len(patch_files))
-
- # Check that it can detect a different branch
- self.assertEqual(3, gitutil.count_commits_to_branch('second'))
- with terminal.capture() as _:
- _, cover_fname, patch_files = send.prepare_patches(
- col, branch='second', count=-1, start=0, end=0,
- ignore_binary=False, signoff=True)
- self.assertIsNotNone(cover_fname)
- self.assertEqual(3, len(patch_files))
-
- cover = tools.read_file(cover_fname, binary=False)
- lines = cover.splitlines()[-2:]
- base = repo.lookup_reference('refs/heads/base').target
- self.assertEqual(f'base-commit: {base}', lines[0])
- self.assertEqual('branch: second', lines[1])
-
- # Make sure that the base-commit is not present when it is in the
- # cover letter
- for fname in patch_files:
- self.assertNotIn(b'base-commit:', tools.read_file(fname))
-
- # Check that it can skip patches at the end
- with terminal.capture() as _:
- _, cover_fname, patch_files = send.prepare_patches(
- col, branch='second', count=-1, start=0, end=1,
- ignore_binary=False, signoff=True)
- self.assertIsNotNone(cover_fname)
- self.assertEqual(2, len(patch_files))
-
- cover = tools.read_file(cover_fname, binary=False)
- lines = cover.splitlines()[-2:]
- base2 = repo.lookup_reference('refs/heads/second')
- ref = base2.peel(pygit2.GIT_OBJ_COMMIT).parents[0].parents[0].id
- self.assertEqual(f'base-commit: {ref}', lines[0])
- self.assertEqual('branch: second', lines[1])
- finally:
- os.chdir(orig_dir)
-
- def test_custom_get_maintainer_script(self):
- """Validate that a custom get_maintainer script gets used."""
- self.make_git_tree()
- with directory_excursion(self.tmpdir):
- # Setup git.
- os.environ['GIT_CONFIG_GLOBAL'] = '/dev/null'
- os.environ['GIT_CONFIG_SYSTEM'] = '/dev/null'
- tools.run('git', 'config', 'user.name', 'Dummy')
- tools.run('git', 'config', 'user.email', '[email protected]')
- tools.run('git', 'branch', 'upstream')
- tools.run('git', 'branch', '--set-upstream-to=upstream')
-
- # Setup patman configuration.
- tools.write_file('.patman', '[settings]\n'
- 'get_maintainer_script: dummy-script.sh\n'
- 'check_patch: False\n'
- 'add_maintainers: True\n', binary=False)
- tools.write_file('dummy-script.sh',
- '#!/usr/bin/env python3\n'
- 'print("[email protected]")\n', binary=False)
- os.chmod('dummy-script.sh', 0x555)
- tools.run('git', 'add', '.')
- tools.run('git', 'commit', '-m', 'new commit')
-
- # Finally, do the test
- with terminal.capture():
- output = tools.run(PATMAN_DIR / 'patman', '--dry-run')
- # Assert the email address is part of the dry-run
- # output.
- self.assertIn('[email protected]', output)
-
- def test_tags(self):
- """Test collection of tags in a patchstream"""
- text = '''This is a patch
-
-Signed-off-by: Terminator
-Reviewed-by: %s
-Reviewed-by: %s
-Tested-by: %s
-''' % (self.joe, self.mary, self.leb)
- pstrm = PatchStream.process_text(text)
- self.assertEqual(pstrm.commit.rtags, {
- 'Reviewed-by': {self.joe, self.mary},
- 'Tested-by': {self.leb}})
-
- def test_invalid_tag(self):
- """Test invalid tag in a patchstream"""
- text = '''This is a patch
-
-Serie-version: 2
-'''
- with self.assertRaises(ValueError) as exc:
- PatchStream.process_text(text)
- self.assertEqual("Line 3: Invalid tag = 'Serie-version: 2'",
- str(exc.exception))
-
- def test_missing_end(self):
- """Test a missing END tag"""
- text = '''This is a patch
-
-Cover-letter:
-This is the title
-missing END after this line
-Signed-off-by: Fred
-'''
- pstrm = PatchStream.process_text(text)
- self.assertEqual(["Missing 'END' in section 'cover'"],
- pstrm.commit.warn)
-
- def test_missing_blank_line(self):
- """Test a missing blank line after a tag"""
- text = '''This is a patch
-
-Series-changes: 2
-- First line of changes
-- Missing blank line after this line
-Signed-off-by: Fred
-'''
- pstrm = PatchStream.process_text(text)
- self.assertEqual(["Missing 'blank line' in section 'Series-changes'"],
- pstrm.commit.warn)
-
- def test_invalid_commit_tag(self):
- """Test an invalid Commit-xxx tag"""
- text = '''This is a patch
-
-Commit-fred: testing
-'''
- pstrm = PatchStream.process_text(text)
- self.assertEqual(["Line 3: Ignoring Commit-fred"], pstrm.commit.warn)
-
- def test_self_test(self):
- """Test a tested by tag by this user"""
- test_line = 'Tested-by: %[email protected]' % os.getenv('USER')
- text = '''This is a patch
-
-%s
-''' % test_line
- pstrm = PatchStream.process_text(text)
- self.assertEqual(["Ignoring '%s'" % test_line], pstrm.commit.warn)
-
- def test_space_before_tab(self):
- """Test a space before a tab"""
- text = '''This is a patch
-
-+ \tSomething
-'''
- pstrm = PatchStream.process_text(text)
- self.assertEqual(["Line 3/0 has space before tab"], pstrm.commit.warn)
-
- def test_lines_after_test(self):
- """Test detecting lines after TEST= line"""
- text = '''This is a patch
-
-TEST=sometest
-more lines
-here
-'''
- pstrm = PatchStream.process_text(text)
- self.assertEqual(["Found 2 lines after TEST="], pstrm.commit.warn)
-
- def test_blank_line_at_end(self):
- """Test detecting a blank line at the end of a file"""
- text = '''This is a patch
-
-diff --git a/lib/fdtdec.c b/lib/fdtdec.c
-index c072e54..942244f 100644
---- a/lib/fdtdec.c
-+++ b/lib/fdtdec.c
-@@ -1200,7 +1200,8 @@ int fdtdec_setup_mem_size_base(void)
- \t}
-
- \tgd->ram_size = (phys_size_t)(res.end - res.start + 1);
-- debug("%s: Initial DRAM size %llx\n", __func__, (u64)gd->ram_size);
-+ debug("%s: Initial DRAM size %llx\n", __func__,
-+ (unsigned long long)gd->ram_size);
-+
-diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
-
---
-2.7.4
-
- '''
- pstrm = PatchStream.process_text(text)
- self.assertEqual(
- ["Found possible blank line(s) at end of file 'lib/fdtdec.c'"],
- pstrm.commit.warn)
-
- def test_no_upstream(self):
- """Test CountCommitsToBranch when there is no upstream"""
- repo = self.make_git_tree()
- target = repo.lookup_reference('refs/heads/base')
- # pylint doesn't seem to find this
- # pylint: disable=E1101
- self.repo.checkout(target, strategy=pygit2.GIT_CHECKOUT_FORCE)
-
- # Check that it can detect the current branch
- orig_dir = os.getcwd()
- try:
- os.chdir(self.gitdir)
- with self.assertRaises(ValueError) as exc:
- gitutil.count_commits_to_branch(None)
- self.assertIn(
- "Failed to determine upstream: fatal: no upstream configured for branch 'base'",
- str(exc.exception))
- finally:
- os.chdir(orig_dir)
-
- def run_patman(self, *args):
- """Run patman using the provided arguments
-
- This runs the patman executable from scratch, as opposed to calling
- the control.do_patman() function.
-
- Args:
- args (list of str): Arguments to pass (excluding argv[0])
-
- Return:
- CommandResult: Result of execution
- """
- all_args = [self._patman_pathname] + list(args)
- return command.run_one(*all_args, capture=True, capture_stderr=True)
-
- def test_full_help(self):
- """Test getting full help"""
- command.TEST_RESULT = None
- result = self.run_patman('-H')
- help_file = os.path.join(self._patman_dir, 'README.rst')
- # Remove possible extraneous strings
- extra = '::::::::::::::\n' + help_file + '\n::::::::::::::\n'
- gothelp = result.stdout.replace(extra, '')
- self.assertEqual(len(gothelp), os.path.getsize(help_file))
- self.assertEqual(0, len(result.stderr))
- self.assertEqual(0, result.return_code)
-
- def test_help(self):
- """Test getting help with commands and arguments"""
- command.TEST_RESULT = None
- result = self.run_patman('-h')
- self.assertTrue(len(result.stdout) > 1000)
- self.assertEqual(0, len(result.stderr))
- self.assertEqual(0, result.return_code)
-
- @staticmethod
- def _fake_patchwork(subpath):
- """Fake Patchwork server for the function below
-
- This handles accessing a series, providing a list consisting of a
- single patch
-
- Args:
- subpath (str): URL subpath to use
- """
- re_series = re.match(r'series/(\d*)/$', subpath)
- if re_series:
- series_num = re_series.group(1)
- if series_num == '1234':
- return {'patches': [
- {'id': '1', 'name': 'Some patch'}]}
- raise ValueError('Fake Patchwork does not understand: %s' % subpath)
-
- def test_status_mismatch(self):
- """Test Patchwork patches not matching the series"""
- pwork = patchwork.Patchwork.for_testing(self._fake_patchwork)
- with terminal.capture() as (_, err):
- loop = asyncio.get_event_loop()
- _, patches = loop.run_until_complete(status.check_status(1234,
- pwork))
- status.check_patch_count(0, len(patches))
- self.assertIn('Warning: Patchwork reports 1 patches, series has 0',
- err.getvalue())
-
- def test_status_read_patch(self):
- """Test handling a single patch in Patchwork"""
- pwork = patchwork.Patchwork.for_testing(self._fake_patchwork)
- loop = asyncio.get_event_loop()
- _, patches = loop.run_until_complete(status.check_status(1234, pwork))
- self.assertEqual(1, len(patches))
- patch = patches[0]
- self.assertEqual('1', patch.id)
- self.assertEqual('Some patch', patch.raw_subject)
-
- def test_parse_subject(self):
- """Test parsing of the patch subject"""
- patch = patchwork.Patch('1')
-
- # Simple patch not in a series
- patch.parse_subject('Testing')
- self.assertEqual('Testing', patch.raw_subject)
- self.assertEqual('Testing', patch.subject)
- self.assertEqual(1, patch.seq)
- self.assertEqual(1, patch.count)
- self.assertEqual(None, patch.prefix)
- self.assertEqual(None, patch.version)
-
- # First patch in a series
- patch.parse_subject('[1/2] Testing')
- self.assertEqual('[1/2] Testing', patch.raw_subject)
- self.assertEqual('Testing', patch.subject)
- self.assertEqual(1, patch.seq)
- self.assertEqual(2, patch.count)
- self.assertEqual(None, patch.prefix)
- self.assertEqual(None, patch.version)
-
- # Second patch in a series
- patch.parse_subject('[2/2] Testing')
- self.assertEqual('Testing', patch.subject)
- self.assertEqual(2, patch.seq)
- self.assertEqual(2, patch.count)
- self.assertEqual(None, patch.prefix)
- self.assertEqual(None, patch.version)
-
- # With PATCH prefix
- patch.parse_subject('[PATCH,2/5] Testing')
- self.assertEqual('Testing', patch.subject)
- self.assertEqual(2, patch.seq)
- self.assertEqual(5, patch.count)
- self.assertEqual('PATCH', patch.prefix)
- self.assertEqual(None, patch.version)
-
- # RFC patch
- patch.parse_subject('[RFC,3/7] Testing')
- self.assertEqual('Testing', patch.subject)
- self.assertEqual(3, patch.seq)
- self.assertEqual(7, patch.count)
- self.assertEqual('RFC', patch.prefix)
- self.assertEqual(None, patch.version)
-
- # Version patch
- patch.parse_subject('[v2,3/7] Testing')
- self.assertEqual('Testing', patch.subject)
- self.assertEqual(3, patch.seq)
- self.assertEqual(7, patch.count)
- self.assertEqual(None, patch.prefix)
- self.assertEqual('v2', patch.version)
-
- # All fields
- patch.parse_subject('[RESEND,v2,3/7] Testing')
- self.assertEqual('Testing', patch.subject)
- self.assertEqual(3, patch.seq)
- self.assertEqual(7, patch.count)
- self.assertEqual('RESEND', patch.prefix)
- self.assertEqual('v2', patch.version)
-
- # RFC only
- patch.parse_subject('[RESEND] Testing')
- self.assertEqual('Testing', patch.subject)
- self.assertEqual(1, patch.seq)
- self.assertEqual(1, patch.count)
- self.assertEqual('RESEND', patch.prefix)
- self.assertEqual(None, patch.version)
-
- def test_compare_series(self):
- """Test operation of compare_with_series()"""
- commit1 = Commit('abcd')
- commit1.subject = 'Subject 1'
- commit2 = Commit('ef12')
- commit2.subject = 'Subject 2'
- commit3 = Commit('3456')
- commit3.subject = 'Subject 2'
-
- patch1 = patchwork.Patch('1')
- patch1.subject = 'Subject 1'
- patch2 = patchwork.Patch('2')
- patch2.subject = 'Subject 2'
- patch3 = patchwork.Patch('3')
- patch3.subject = 'Subject 2'
-
- series = Series()
- series.commits = [commit1]
- patches = [patch1]
- patch_for_commit, commit_for_patch, warnings = (
- status.compare_with_series(series, patches))
- self.assertEqual(1, len(patch_for_commit))
- self.assertEqual(patch1, patch_for_commit[0])
- self.assertEqual(1, len(commit_for_patch))
- self.assertEqual(commit1, commit_for_patch[0])
-
- series.commits = [commit1]
- patches = [patch1, patch2]
- patch_for_commit, commit_for_patch, warnings = (
- status.compare_with_series(series, patches))
- self.assertEqual(1, len(patch_for_commit))
- self.assertEqual(patch1, patch_for_commit[0])
- self.assertEqual(1, len(commit_for_patch))
- self.assertEqual(commit1, commit_for_patch[0])
- self.assertEqual(["Cannot find commit for patch 2 ('Subject 2')"],
- warnings)
-
- series.commits = [commit1, commit2]
- patches = [patch1]
- patch_for_commit, commit_for_patch, warnings = (
- status.compare_with_series(series, patches))
- self.assertEqual(1, len(patch_for_commit))
- self.assertEqual(patch1, patch_for_commit[0])
- self.assertEqual(1, len(commit_for_patch))
- self.assertEqual(commit1, commit_for_patch[0])
- self.assertEqual(["Cannot find patch for commit 2 ('Subject 2')"],
- warnings)
-
- series.commits = [commit1, commit2, commit3]
- patches = [patch1, patch2]
- patch_for_commit, commit_for_patch, warnings = (
- status.compare_with_series(series, patches))
- self.assertEqual(2, len(patch_for_commit))
- self.assertEqual(patch1, patch_for_commit[0])
- self.assertEqual(patch2, patch_for_commit[1])
- self.assertEqual(1, len(commit_for_patch))
- self.assertEqual(commit1, commit_for_patch[0])
- self.assertEqual(["Cannot find patch for commit 3 ('Subject 2')",
- "Multiple commits match patch 2 ('Subject 2'):\n"
- ' Subject 2\n Subject 2'],
- warnings)
-
- series.commits = [commit1, commit2]
- patches = [patch1, patch2, patch3]
- patch_for_commit, commit_for_patch, warnings = (
- status.compare_with_series(series, patches))
- self.assertEqual(1, len(patch_for_commit))
- self.assertEqual(patch1, patch_for_commit[0])
- self.assertEqual(2, len(commit_for_patch))
- self.assertEqual(commit1, commit_for_patch[0])
- self.assertEqual(["Multiple patches match commit 2 ('Subject 2'):\n"
- ' Subject 2\n Subject 2',
- "Cannot find commit for patch 3 ('Subject 2')"],
- warnings)
-
- def _fake_patchwork2(self, subpath):
- """Fake Patchwork server for the function below
-
- This handles accessing series, patches and comments, providing the data
- in self.patches to the caller
-
- Args:
- subpath (str): URL subpath to use
- """
- re_series = re.match(r'series/(\d*)/$', subpath)
- re_patch = re.match(r'patches/(\d*)/$', subpath)
- re_comments = re.match(r'patches/(\d*)/comments/$', subpath)
- if re_series:
- series_num = re_series.group(1)
- if series_num == '1234':
- return {'patches': self.patches}
- elif re_patch:
- patch_num = int(re_patch.group(1))
- patch = self.patches[patch_num - 1]
- return patch
- elif re_comments:
- patch_num = int(re_comments.group(1))
- patch = self.patches[patch_num - 1]
- return patch.comments
- raise ValueError('Fake Patchwork does not understand: %s' % subpath)
-
- def test_find_new_responses(self):
- """Test operation of find_new_responses()"""
- commit1 = Commit('abcd')
- commit1.subject = 'Subject 1'
- commit2 = Commit('ef12')
- commit2.subject = 'Subject 2'
-
- patch1 = patchwork.Patch('1')
- patch1.parse_subject('[1/2] Subject 1')
- patch1.name = patch1.raw_subject
- patch1.content = 'This is my patch content'
- comment1a = {'content': 'Reviewed-by: %s\n' % self.joe}
-
- patch1.comments = [comment1a]
-
- patch2 = patchwork.Patch('2')
- patch2.parse_subject('[2/2] Subject 2')
- patch2.name = patch2.raw_subject
- patch2.content = 'Some other patch content'
- comment2a = {
- 'content': 'Reviewed-by: %s\nTested-by: %s\n' %
- (self.mary, self.leb)}
- comment2b = {'content': 'Reviewed-by: %s' % self.fred}
- patch2.comments = [comment2a, comment2b]
-
- # This test works by setting up commits and patch for use by the fake
- # Rest API function _fake_patchwork2(). It calls various functions in
- # the status module after setting up tags in the commits, checking that
- # things behaves as expected
- self.commits = [commit1, commit2]
- self.patches = [patch1, patch2]
-
- # Check that the tags are picked up on the first patch
- new_rtags, _ = status.process_reviews(patch1.content, patch1.comments,
- commit1.rtags)
- self.assertEqual(new_rtags, {'Reviewed-by': {self.joe}})
-
- # Now the second patch
- new_rtags, _ = status.process_reviews(patch2.content, patch2.comments,
- commit2.rtags)
- self.assertEqual(new_rtags, {
- 'Reviewed-by': {self.mary, self.fred},
- 'Tested-by': {self.leb}})
-
- # Now add some tags to the commit, which means they should not appear as
- # 'new' tags when scanning comments
- commit1.rtags = {'Reviewed-by': {self.joe}}
- new_rtags, _ = status.process_reviews(patch1.content, patch1.comments,
- commit1.rtags)
- self.assertEqual(new_rtags, {})
-
- # For the second commit, add Ed and Fred, so only Mary should be left
- commit2.rtags = {
- 'Tested-by': {self.leb},
- 'Reviewed-by': {self.fred}}
- new_rtags, _ = status.process_reviews(patch2.content, patch2.comments,
- commit2.rtags)
- self.assertEqual(new_rtags, {'Reviewed-by': {self.mary}})
-
- # Check that the output patches expectations:
- # 1 Subject 1
- # Reviewed-by: Joe Bloggs <[email protected]>
- # 2 Subject 2
- # Tested-by: Lord Edmund Blackaddër <[email protected]>
- # Reviewed-by: Fred Bloggs <[email protected]>
- # + Reviewed-by: Mary Bloggs <[email protected]>
- # 1 new response available in patchwork
-
- series = Series()
- series.commits = [commit1, commit2]
- terminal.set_print_test_mode()
- pwork = patchwork.Patchwork.for_testing(self._fake_patchwork2)
- status.check_and_show_status(series, '1234', None, None, False, False,
- False, pwork)
- itr = iter(terminal.get_print_test_lines())
- col = terminal.Color()
- self.assertEqual(terminal.PrintLine(' 1 Subject 1', col.YELLOW),
- next(itr))
- self.assertEqual(
- terminal.PrintLine(' Reviewed-by: ', col.GREEN, newline=False,
- bright=False),
- next(itr))
- self.assertEqual(terminal.PrintLine(self.joe, col.WHITE, bright=False),
- next(itr))
-
- self.assertEqual(terminal.PrintLine(' 2 Subject 2', col.YELLOW),
- next(itr))
- self.assertEqual(
- terminal.PrintLine(' Reviewed-by: ', col.GREEN, newline=False,
- bright=False),
- next(itr))
- self.assertEqual(terminal.PrintLine(self.fred, col.WHITE,
- bright=False), next(itr))
- self.assertEqual(
- terminal.PrintLine(' Tested-by: ', col.GREEN, newline=False,
- bright=False),
- next(itr))
- self.assertEqual(terminal.PrintLine(self.leb, col.WHITE, bright=False),
- next(itr))
- self.assertEqual(
- terminal.PrintLine(' + Reviewed-by: ', col.GREEN, newline=False),
- next(itr))
- self.assertEqual(terminal.PrintLine(self.mary, col.WHITE),
- next(itr))
- self.assertEqual(terminal.PrintLine(
- '1 new response available in patchwork (use -d to write them to a new branch)',
- None), next(itr))
-
- def _fake_patchwork3(self, subpath):
- """Fake Patchwork server for the function below
-
- This handles accessing series, patches and comments, providing the data
- in self.patches to the caller
-
- Args:
- subpath (str): URL subpath to use
- """
- re_series = re.match(r'series/(\d*)/$', subpath)
- re_patch = re.match(r'patches/(\d*)/$', subpath)
- re_comments = re.match(r'patches/(\d*)/comments/$', subpath)
- if re_series:
- series_num = re_series.group(1)
- if series_num == '1234':
- return {'patches': self.patches}
- elif re_patch:
- patch_num = int(re_patch.group(1))
- patch = self.patches[patch_num - 1]
- return patch
- elif re_comments:
- patch_num = int(re_comments.group(1))
- patch = self.patches[patch_num - 1]
- return patch.comments
- raise ValueError('Fake Patchwork does not understand: %s' % subpath)
-
- def test_create_branch(self):
- """Test operation of create_branch()"""
- repo = self.make_git_tree()
- branch = 'first'
- dest_branch = 'first2'
- count = 2
- gitdir = self.gitdir
-
- # Set up the test git tree. We use branch 'first' which has two commits
- # in it
- series = patchstream.get_metadata_for_list(branch, gitdir, count)
- self.assertEqual(2, len(series.commits))
-
- patch1 = patchwork.Patch('1')
- patch1.parse_subject('[1/2] %s' % series.commits[0].subject)
- patch1.name = patch1.raw_subject
- patch1.content = 'This is my patch content'
- comment1a = {'content': 'Reviewed-by: %s\n' % self.joe}
-
- patch1.comments = [comment1a]
-
- patch2 = patchwork.Patch('2')
- patch2.parse_subject('[2/2] %s' % series.commits[1].subject)
- patch2.name = patch2.raw_subject
- patch2.content = 'Some other patch content'
- comment2a = {
- 'content': 'Reviewed-by: %s\nTested-by: %s\n' %
- (self.mary, self.leb)}
- comment2b = {
- 'content': 'Reviewed-by: %s' % self.fred}
- patch2.comments = [comment2a, comment2b]
-
- # This test works by setting up patches for use by the fake Rest API
- # function _fake_patchwork3(). The fake patch comments above should
- # result in new review tags that are collected and added to the commits
- # created in the destination branch.
- self.patches = [patch1, patch2]
- count = 2
-
- # Expected output:
- # 1 i2c: I2C things
- # + Reviewed-by: Joe Bloggs <[email protected]>
- # 2 spi: SPI fixes
- # + Reviewed-by: Fred Bloggs <[email protected]>
- # + Reviewed-by: Mary Bloggs <[email protected]>
- # + Tested-by: Lord Edmund Blackaddër <[email protected]>
- # 4 new responses available in patchwork
- # 4 responses added from patchwork into new branch 'first2'
- # <unittest.result.TestResult run=8 errors=0 failures=0>
-
- terminal.set_print_test_mode()
- pwork = patchwork.Patchwork.for_testing(self._fake_patchwork3)
- status.check_and_show_status(
- series, '1234', branch, dest_branch, False, False, False, pwork,
- repo)
- lines = terminal.get_print_test_lines()
- self.assertEqual(12, len(lines))
- self.assertEqual(
- "4 responses added from patchwork into new branch 'first2'",
- lines[11].text)
-
- # Check that the destination branch has the new tags
- new_series = patchstream.get_metadata_for_list(dest_branch, gitdir,
- count)
- self.assertEqual(
- {'Reviewed-by': {self.joe}},
- new_series.commits[0].rtags)
- self.assertEqual(
- {'Tested-by': {self.leb},
- 'Reviewed-by': {self.fred, self.mary}},
- new_series.commits[1].rtags)
-
- # Now check the actual test of the first commit message. We expect to
- # see the new tags immediately below the old ones.
- stdout = patchstream.get_list(dest_branch, count=count, git_dir=gitdir)
- itr = iter([line.strip() for line in stdout.splitlines()
- if '-by:' in line])
-
- # First patch should have the review tag
- self.assertEqual('Reviewed-by: %s' % self.joe, next(itr))
-
- # Second patch should have the sign-off then the tested-by and two
- # reviewed-by tags
- self.assertEqual('Signed-off-by: %s' % self.leb, next(itr))
- self.assertEqual('Reviewed-by: %s' % self.fred, next(itr))
- self.assertEqual('Reviewed-by: %s' % self.mary, next(itr))
- self.assertEqual('Tested-by: %s' % self.leb, next(itr))
-
- def test_parse_snippets(self):
- """Test parsing of review snippets"""
- text = '''Hi Fred,
-
-This is a comment from someone.
-
-Something else
-
-On some recent date, Fred wrote:
-> This is why I wrote the patch
-> so here it is
-
-Now a comment about the commit message
-A little more to say
-
-Even more
-
-> diff --git a/file.c b/file.c
-> Some more code
-> Code line 2
-> Code line 3
-> Code line 4
-> Code line 5
-> Code line 6
-> Code line 7
-> Code line 8
-> Code line 9
-
-And another comment
-
-> @@ -153,8 +143,13 @@ def check_patch(fname, show_types=False):
-> further down on the file
-> and more code
-> +Addition here
-> +Another addition here
-> codey
-> more codey
-
-and another thing in same file
-
-> @@ -253,8 +243,13 @@
-> with no function context
-
-one more thing
-
-> diff --git a/tools/patman/main.py b/tools/patman/main.py
-> +line of code
-now a very long comment in a different file
-line2
-line3
-line4
-line5
-line6
-line7
-line8
-'''
- pstrm = PatchStream.process_text(text, True)
- self.assertEqual([], pstrm.commit.warn)
-
- # We expect to the filename and up to 5 lines of code context before
- # each comment. The 'On xxx wrote:' bit should be removed.
- self.assertEqual(
- [['Hi Fred,',
- 'This is a comment from someone.',
- 'Something else'],
- ['> This is why I wrote the patch',
- '> so here it is',
- 'Now a comment about the commit message',
- 'A little more to say', 'Even more'],
- ['> File: file.c', '> Code line 5', '> Code line 6',
- '> Code line 7', '> Code line 8', '> Code line 9',
- 'And another comment'],
- ['> File: file.c',
- '> Line: 153 / 143: def check_patch(fname, show_types=False):',
- '> and more code', '> +Addition here',
- '> +Another addition here', '> codey', '> more codey',
- 'and another thing in same file'],
- ['> File: file.c', '> Line: 253 / 243',
- '> with no function context', 'one more thing'],
- ['> File: tools/patman/main.py', '> +line of code',
- 'now a very long comment in a different file',
- 'line2', 'line3', 'line4', 'line5', 'line6', 'line7', 'line8']],
- pstrm.snippets)
-
- def test_review_snippets(self):
- """Test showing of review snippets"""
- def _to_submitter(who):
- m_who = re.match('(.*) <(.*)>', who)
- return {
- 'name': m_who.group(1),
- 'email': m_who.group(2)
- }
-
- commit1 = Commit('abcd')
- commit1.subject = 'Subject 1'
- commit2 = Commit('ef12')
- commit2.subject = 'Subject 2'
-
- patch1 = patchwork.Patch('1')
- patch1.parse_subject('[1/2] Subject 1')
- patch1.name = patch1.raw_subject
- patch1.content = 'This is my patch content'
- comment1a = {'submitter': _to_submitter(self.joe),
- 'content': '''Hi Fred,
-
-On some date Fred wrote:
-
-> diff --git a/file.c b/file.c
-> Some code
-> and more code
-
-Here is my comment above the above...
-
-
-Reviewed-by: %s
-''' % self.joe}
-
- patch1.comments = [comment1a]
-
- patch2 = patchwork.Patch('2')
- patch2.parse_subject('[2/2] Subject 2')
- patch2.name = patch2.raw_subject
- patch2.content = 'Some other patch content'
- comment2a = {
- 'content': 'Reviewed-by: %s\nTested-by: %s\n' %
- (self.mary, self.leb)}
- comment2b = {'submitter': _to_submitter(self.fred),
- 'content': '''Hi Fred,
-
-On some date Fred wrote:
-
-> diff --git a/tools/patman/commit.py b/tools/patman/commit.py
-> @@ -41,6 +41,9 @@ class Commit:
-> self.rtags = collections.defaultdict(set)
-> self.warn = []
->
-> + def __str__(self):
-> + return self.subject
-> +
-> def add_change(self, version, info):
-> """Add a new change line to the change list for a version.
->
-A comment
-
-Reviewed-by: %s
-''' % self.fred}
- patch2.comments = [comment2a, comment2b]
-
- # This test works by setting up commits and patch for use by the fake
- # Rest API function _fake_patchwork2(). It calls various functions in
- # the status module after setting up tags in the commits, checking that
- # things behaves as expected
- self.commits = [commit1, commit2]
- self.patches = [patch1, patch2]
-
- # Check that the output patches expectations:
- # 1 Subject 1
- # Reviewed-by: Joe Bloggs <[email protected]>
- # 2 Subject 2
- # Tested-by: Lord Edmund Blackaddër <[email protected]>
- # Reviewed-by: Fred Bloggs <[email protected]>
- # + Reviewed-by: Mary Bloggs <[email protected]>
- # 1 new response available in patchwork
-
- series = Series()
- series.commits = [commit1, commit2]
- terminal.set_print_test_mode()
- pwork = patchwork.Patchwork.for_testing(self._fake_patchwork2)
- status.check_and_show_status(
- series, '1234', None, None, False, True, False, pwork)
- itr = iter(terminal.get_print_test_lines())
- col = terminal.Color()
- self.assertEqual(terminal.PrintLine(' 1 Subject 1', col.YELLOW),
- next(itr))
- self.assertEqual(
- terminal.PrintLine(' + Reviewed-by: ', col.GREEN, newline=False),
- next(itr))
- self.assertEqual(terminal.PrintLine(self.joe, col.WHITE), next(itr))
-
- self.assertEqual(terminal.PrintLine('Review: %s' % self.joe, col.RED),
- next(itr))
- self.assertEqual(terminal.PrintLine(' Hi Fred,', None), next(itr))
- self.assertEqual(terminal.PrintLine('', None), next(itr))
- self.assertEqual(terminal.PrintLine(' > File: file.c', col.MAGENTA),
- next(itr))
- self.assertEqual(terminal.PrintLine(' > Some code', col.MAGENTA),
- next(itr))
- self.assertEqual(terminal.PrintLine(' > and more code',
- col.MAGENTA),
- next(itr))
- self.assertEqual(terminal.PrintLine(
- ' Here is my comment above the above...', None), next(itr))
- self.assertEqual(terminal.PrintLine('', None), next(itr))
-
- self.assertEqual(terminal.PrintLine(' 2 Subject 2', col.YELLOW),
- next(itr))
- self.assertEqual(
- terminal.PrintLine(' + Reviewed-by: ', col.GREEN, newline=False),
- next(itr))
- self.assertEqual(terminal.PrintLine(self.fred, col.WHITE),
- next(itr))
- self.assertEqual(
- terminal.PrintLine(' + Reviewed-by: ', col.GREEN, newline=False),
- next(itr))
- self.assertEqual(terminal.PrintLine(self.mary, col.WHITE),
- next(itr))
- self.assertEqual(
- terminal.PrintLine(' + Tested-by: ', col.GREEN, newline=False),
- next(itr))
- self.assertEqual(terminal.PrintLine(self.leb, col.WHITE),
- next(itr))
-
- self.assertEqual(terminal.PrintLine('Review: %s' % self.fred, col.RED),
- next(itr))
- self.assertEqual(terminal.PrintLine(' Hi Fred,', None), next(itr))
- self.assertEqual(terminal.PrintLine('', None), next(itr))
- self.assertEqual(terminal.PrintLine(
- ' > File: tools/patman/commit.py', col.MAGENTA), next(itr))
- self.assertEqual(terminal.PrintLine(
- ' > Line: 41 / 41: class Commit:', col.MAGENTA), next(itr))
- self.assertEqual(terminal.PrintLine(
- ' > + return self.subject', col.MAGENTA), next(itr))
- self.assertEqual(terminal.PrintLine(
- ' > +', col.MAGENTA), next(itr))
- self.assertEqual(
- terminal.PrintLine(
- ' > def add_change(self, version, info):',
- col.MAGENTA),
- next(itr))
- self.assertEqual(terminal.PrintLine(
- ' > """Add a new change line to the change list for a version.',
- col.MAGENTA), next(itr))
- self.assertEqual(terminal.PrintLine(
- ' >', col.MAGENTA), next(itr))
- self.assertEqual(terminal.PrintLine(
- ' A comment', None), next(itr))
- self.assertEqual(terminal.PrintLine('', None), next(itr))
-
- self.assertEqual(terminal.PrintLine(
- '4 new responses available in patchwork (use -d to write them to a new branch)',
- None), next(itr))
-
- def test_insert_tags(self):
- """Test inserting of review tags"""
- msg = '''first line
-second line.'''
- tags = [
- 'Reviewed-by: Bin Meng <[email protected]>',
- 'Tested-by: Bin Meng <[email protected]>'
- ]
- signoff = 'Signed-off-by: Simon Glass <[email protected]>'
- tag_str = '\n'.join(tags)
-
- new_msg = patchstream.insert_tags(msg, tags)
- self.assertEqual(msg + '\n\n' + tag_str, new_msg)
-
- new_msg = patchstream.insert_tags(msg + '\n', tags)
- self.assertEqual(msg + '\n\n' + tag_str, new_msg)
-
- msg += '\n\n' + signoff
- new_msg = patchstream.insert_tags(msg, tags)
- self.assertEqual(msg + '\n' + tag_str, new_msg)