runbot/runbot_merge/tests/test_patching.py

271 lines
6.8 KiB
Python
Raw Permalink Normal View History

import xmlrpc.client
import pytest
from utils import Commit, read_tracking_value, matches
# basic udiff / show style patch, updates `b` from `1` to `2`
BASIC_UDIFF = """\
commit 0000000000000000000000000000000000000000
Author: 3 Discos Down <bar@example.org>
Date: 2021-04-24T17:09:14Z
whop
whop whop
diff --git a/b b/b
index 000000000000..000000000000 100644
--- a/b
+++ b/b
@@ -1,1 +1,1 @@
-1
+2
"""
FORMAT_PATCH_XMO = """\
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: 3 Discos Down <bar@example.org>
Date: Sat, 24 Apr 2021 17:09:14 +0000
Subject: [PATCH] [I18N] whop
whop whop
---
b | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/b b/b
index 000000000000..000000000000 100644
--- a/b
+++ b/b
@@ -1,1 +1,1 @@
-1
+2
--
2.46.2
"""
# slightly different format than the one I got, possibly because older?
FORMAT_PATCH_MAT = """\
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: 3 Discos Down <bar@example.org>
Date: Sat, 24 Apr 2021 17:09:14 +0000
Subject: [PATCH 1/1] [I18N] whop
whop whop
---
b | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git b b
index 000000000000..000000000000 100644
--- b
+++ b
@@ -1,1 +1,1 @@
-1
+2
--
2.34.1
"""
@pytest.fixture(autouse=True)
def _setup(repo):
with repo:
[c, _] = repo.make_commits(
None,
Commit("a", tree={"a": "1", "b": "1\n"}),
Commit("b", tree={"a": "2"}),
ref="heads/master",
)
repo.make_ref("heads/x", c)
@pytest.mark.parametrize("group,access", [
('base.group_portal', False),
('base.group_user', False),
('runbot_merge.group_patcher', True),
('runbot_merge.group_admin', False),
('base.group_system', True),
])
def test_patch_acl(env, project, group, access):
g = env.ref(group)
assert g._name == 'res.groups'
env['res.users'].create({
'name': 'xxx',
'login': 'xxx',
'password': 'xxx',
'groups_id': [(6, 0, [g.id])],
})
env2 = env.with_user('xxx', 'xxx')
def create():
return env2['runbot_merge.patch'].create({
'target': project.branch_ids.id,
'repository': project.repo_ids.id,
'patch': BASIC_UDIFF,
})
if access:
create()
else:
pytest.raises(xmlrpc.client.Fault, create)\
.match("You are not allowed to create")
def test_apply_commit(env, project, repo, users):
with repo:
[c] = repo.make_commits("x", Commit("c", tree={"b": "2"}, author={
'name': "Henry Hoover",
"email": "dustsuckinghose@example.org",
}), ref="heads/abranch")
repo.delete_ref('heads/abranch')
p = env['runbot_merge.patch'].create({
'target': project.branch_ids.id,
'repository': project.repo_ids.id,
'commit': c,
})
env.run_crons()
HEAD = repo.commit('master')
assert repo.read_tree(HEAD) == {
'a': '2',
'b': '2',
}
assert HEAD.message == "c"
assert HEAD.author['name'] == "Henry Hoover"
assert HEAD.author['email'] == "dustsuckinghose@example.org"
assert not p.active
def test_commit_conflict(env, project, repo, users):
with repo:
[c] = repo.make_commits("x", Commit("x", tree={"b": "3"}))
repo.make_commits("master", Commit("c", tree={"b": "2"}), ref="heads/master", make=False)
p = env['runbot_merge.patch'].create({
'target': project.branch_ids.id,
'repository': project.repo_ids.id,
'commit': c,
})
env.run_crons()
HEAD = repo.commit('master')
assert repo.read_tree(HEAD) == {
'a': '2',
'b': '2',
}
assert not p.active
assert [(
m.subject,
m.body,
list(map(read_tracking_value, m.tracking_value_ids)),
)
for m in reversed(p.message_ids)
] == [
(False, '<p>Unstaged direct-application patch created</p>', []),
(
"Unable to apply patch",
"""\
<p>Auto-merging b<br>\
CONFLICT (content): Merge conflict in b<br></p>\
""",
[],
),
(False, '', [('active', 1, 0)]),
]
def test_apply_udiff(env, project, repo, users):
p = env['runbot_merge.patch'].create({
'target': project.branch_ids.id,
'repository': project.repo_ids.id,
'patch': BASIC_UDIFF,
})
env.run_crons()
HEAD = repo.commit('master')
assert repo.read_tree(HEAD) == {
'a': '2',
'b': '2\n',
}
assert HEAD.message == "whop\n\nwhop whop"
assert HEAD.author['name'] == "3 Discos Down"
assert HEAD.author['email'] == "bar@example.org"
assert not p.active
@pytest.mark.parametrize('patch', [
pytest.param(FORMAT_PATCH_XMO, id='xmo'),
pytest.param(FORMAT_PATCH_MAT, id='mat'),
pytest.param(
FORMAT_PATCH_XMO.replace('\n', '\r\n'),
id='windows',
),
pytest.param(
FORMAT_PATCH_XMO.rsplit('-- \n')[0],
id='no-signature',
)
])
def test_apply_format_patch(env, project, repo, users, patch):
p = env['runbot_merge.patch'].create({
'target': project.branch_ids.id,
'repository': project.repo_ids.id,
'patch': patch,
})
env.run_crons()
bot = env['res.users'].browse((1,))
assert p.message_ids[::-1].mapped(lambda m: (
m.author_id.display_name,
m.body,
list(map(read_tracking_value, m.tracking_value_ids)),
)) == [
(p.create_uid.partner_id.display_name, '<p>Unstaged direct-application patch created</p>', []),
(bot.partner_id.display_name, "", [('active', 1, 0)]),
]
HEAD = repo.commit('master')
assert repo.read_tree(HEAD) == {
'a': '2',
'b': '2\n',
}
assert HEAD.message == "[I18N] whop\n\nwhop whop"
assert HEAD.author['name'] == "3 Discos Down"
assert HEAD.author['email'] == "bar@example.org"
assert not p.active
def test_patch_conflict(env, project, repo, users):
p = env['runbot_merge.patch'].create({
'target': project.branch_ids.id,
'repository': project.repo_ids.id,
'patch': BASIC_UDIFF,
})
with repo:
repo.make_commits('master', Commit('cccombo breaker', tree={'b': '3'}), ref='heads/master', make=False)
env.run_crons()
HEAD = repo.commit('master')
assert HEAD.message == 'cccombo breaker'
assert repo.read_tree(HEAD) == {
'a': '2',
'b': '3',
}
assert not p.active
assert [(
m.subject,
m.body,
list(map(read_tracking_value, m.tracking_value_ids)),
)
for m in reversed(p.message_ids)
] == [(
False,
'<p>Unstaged direct-application patch created</p>',
[],
), (
"Unable to apply patch",
matches("$$"), # feedback from patch can vary
[],
), (
False, '', [('active', 1, 0)]
)]