# -*- coding: utf-8 -*-
"""
(c) 2018 - Copyright Red Hat Inc
Authors:
Pierre-Yves Chibon <pingou@pingoured.fr>
"""
from __future__ import unicode_literals, absolute_import
import datetime
import os
import shutil
import sys
import tempfile
import time
import unittest
import pygit2
import six
from mock import ANY, patch, MagicMock, call
sys.path.insert(0, os.path.join(os.path.dirname(
os.path.abspath(__file__)), '..'))
import pagure.lib.tasks_services
import pagure.lib.query
import tests
import pagure.lib.tasks_services
class PagureLibTaskServicestests(tests.Modeltests):
""" Tests for pagure.lib.task_services """
maxDiff = None
def setUp(self):
""" Set up the environnment, ran before every tests. """
super(PagureLibTaskServicestests, self).setUp()
tests.create_projects(self.session)
# Create a fork of test for foo
item = pagure.lib.model.Project(
user_id=2, # foo
name='test',
is_fork=True,
parent_id=1,
description='test project #1',
hook_token='aaabbbccc_foo',
)
item.close_status = ['Invalid', 'Insufficient data', 'Fixed', 'Duplicate']
self.session.add(item)
self.session.commit()
def test_webhook_notification_invalid_project(self):
""" Test the webhook_notification method. """
self.assertRaises(
RuntimeError,
pagure.lib.tasks_services.webhook_notification,
topic='topic',
msg={'payload': ['a', 'b', 'c']},
namespace=None,
name='invalid',
user=None)
@patch('pagure.lib.tasks_services.call_web_hooks')
def test_webhook_notification_no_webhook(self, call_wh):
""" Test the webhook_notification method. """
output = pagure.lib.tasks_services.webhook_notification(
topic='topic',
msg={'payload': ['a', 'b', 'c']},
namespace=None,
name='test',
user=None)
self.assertIsNone(output)
call_wh.assert_not_called()
@patch('pagure.lib.git.log_commits_to_db')
def test_log_commit_send_notifications_invalid_project(self, log):
""" Test the log_commit_send_notifications method. """
output = pagure.lib.tasks_services.log_commit_send_notifications(
name='invalid',
commits=[],
abspath=None,
branch=None,
default_branch=None,
namespace=None,
username=None)
self.assertIsNone(output)
log.assert_not_called()
@patch('pagure.lib.notify.notify_new_commits')
@patch('pagure.lib.git.log_commits_to_db')
def test_log_commit_send_notifications_valid_project(self, log, notif):
""" Test the log_commit_send_notifications method. """
output = pagure.lib.tasks_services.log_commit_send_notifications(
name='test',
commits=['hash1', 'hash2'],
abspath='/path/to/git',
branch='master',
default_branch='master',
namespace=None,
username=None)
self.assertIsNone(output)
log.assert_called_once_with(
ANY, ANY, ['hash1', 'hash2'], '/path/to/git'
)
notif.assert_called_once_with(
'/path/to/git', ANY, 'master', ['hash1', 'hash2']
)
@patch('pagure.lib.tasks_services.trigger_jenkins_build')
def test_trigger_ci_build_invalid_project(self, trigger_jenk):
""" Test the trigger_ci_build method. """
output = pagure.lib.tasks_services.trigger_ci_build(
project_name='invalid',
cause='PR#ID',
branch='feature',
ci_type='jenkins')
self.assertIsNone(output)
trigger_jenk.assert_not_called()
@patch('pagure.lib.tasks_services.trigger_jenkins_build')
def test_trigger_ci_build_not_configured_project(self, trigger_jenk):
""" Test the trigger_ci_build method. """
self.assertRaises(
pagure.exceptions.PagureException,
pagure.lib.tasks_services.trigger_ci_build,
project_name='test',
cause='PR#ID',
branch='feature',
ci_type='jenkins')
trigger_jenk.assert_not_called()
@patch('pagure.lib.tasks_services.trigger_jenkins_build')
def test_trigger_ci_build_not_configured_project_fork(self, trigger_jenk):
""" Test the trigger_ci_build method. """
self.assertRaises(
pagure.exceptions.PagureException,
pagure.lib.tasks_services.trigger_ci_build,
project_name='forks/foo/test',
cause='PR#ID',
branch='feature',
ci_type='jenkins')
trigger_jenk.assert_not_called()
@patch('pagure.lib.query._get_project')
def test_load_json_commits_to_db_invalid_data_type(self, get_project):
""" Test the load_json_commits_to_db method. """
output = pagure.lib.tasks_services.load_json_commits_to_db(
name='test',
commits=['hash1', 'hash2'],
abspath='/path/to/git',
data_type='invalid',
agent='pingou',
namespace=None,
username=None)
self.assertIsNone(output)
get_project.assert_not_called()
@patch('pagure.lib.tasks_services.get_files_to_load')
def test_load_json_commits_to_db_invalid_project(self, get_files):
""" Test the load_json_commits_to_db method. """
output = pagure.lib.tasks_services.load_json_commits_to_db(
name='invalid',
commits=['hash1', 'hash2'],
abspath='/path/to/git',
data_type='ticket',
agent='pingou',
namespace=None,
username=None)
self.assertIsNone(output)
get_files.assert_not_called()
@patch('pagure.lib.git.update_request_from_git')
@patch('pagure.lib.git.update_ticket_from_git')
def test_load_json_commits_to_db_invalid_path(self, up_issue, up_pr):
""" Test the load_json_commits_to_db method. """
output = pagure.lib.tasks_services.load_json_commits_to_db(
name='test',
commits=['hash1', 'hash2'],
abspath=self.path,
data_type='ticket',
agent='pingou',
namespace=None,
username=None)
self.assertIsNone(output)
up_issue.assert_not_called()
up_pr.assert_not_called()
@patch('pagure.lib.git.update_request_from_git')
@patch('pagure.lib.git.update_ticket_from_git')
def test_load_json_commits_to_db_invalid_path_one_commit(self, up_issue, up_pr):
""" Test the load_json_commits_to_db method. """
output = pagure.lib.tasks_services.load_json_commits_to_db(
name='test',
commits=['hash1'],
abspath=self.path,
data_type='ticket',
agent='pingou',
namespace=None,
username=None)
self.assertIsNone(output)
up_issue.assert_not_called()
up_pr.assert_not_called()
@patch('pagure.lib.notify.send_email')
@patch('pagure.lib.git.update_request_from_git')
@patch('pagure.lib.git.update_ticket_from_git')
def test_load_json_commits_to_db_no_agent(self, up_issue, up_pr, send):
""" Test the load_json_commits_to_db method. """
output = pagure.lib.tasks_services.load_json_commits_to_db(
name='test',
commits=[],
abspath=None,
data_type='ticket',
agent=None,
namespace=None,
username=None)
self.assertIsNone(output)
up_issue.assert_not_called()
up_pr.assert_not_called()
send.assert_not_called()
@patch('pagure.lib.notify.send_email')
@patch('pagure.lib.git.update_request_from_git')
@patch('pagure.lib.git.update_ticket_from_git')
@patch('pagure.lib.git.read_git_lines')
def test_load_json_commits_to_db_no_agent(
self, git, up_issue, up_pr, send):
""" Test the load_json_commits_to_db method. """
git.side_effect = [
['file1'], ['file2'], ['files/image'], ['file1']]
output = pagure.lib.tasks_services.load_json_commits_to_db(
name='test',
commits=['hash1', 'hash2'],
abspath=self.path,
data_type='ticket',
agent=None,
namespace=None,
username=None)
self.assertIsNone(output)
up_issue.assert_not_called()
up_pr.assert_not_called()
send.assert_not_called()
@patch('json.loads')
@patch('pagure.lib.notify.send_email')
@patch('pagure.lib.git.update_request_from_git')
@patch('pagure.lib.git.update_ticket_from_git')
@patch('pagure.lib.git.read_git_lines')
def test_load_json_commits_to_db_tickets(
self, git, up_issue, up_pr, send, json_loads):
""" Test the load_json_commits_to_db method. """
git.side_effect = [
['file1'], ['file2'], ['files/image'], ['file1']]
json_loads.return_value = 'foobar'
output = pagure.lib.tasks_services.load_json_commits_to_db(
name='test',
commits=['hash1', 'hash2'],
abspath=self.path,
data_type='ticket',
agent=None,
namespace=None,
username=None)
self.assertIsNone(output)
calls = [
call(
ANY, agent=None, issue_uid=u'file1', json_data=u'foobar',
namespace=None, reponame=u'test', username=None
),
call(
ANY, agent=None, issue_uid=u'file2', json_data=u'foobar',
namespace=None, reponame=u'test', username=None
),
]
self.assertEqual(
calls,
up_issue.mock_calls
)
up_pr.assert_not_called()
send.assert_not_called()
@patch('json.loads')
@patch('pagure.lib.notify.send_email')
@patch('pagure.lib.git.update_request_from_git')
@patch('pagure.lib.git.update_ticket_from_git')
@patch('pagure.lib.git.read_git_lines')
def test_load_json_commits_to_db_prs(
self, git, up_issue, up_pr, send, json_loads):
""" Test the load_json_commits_to_db method. """
git.side_effect = [
['file1'], ['file2'], ['files/image'], ['file1']]
json_loads.return_value = 'foobar'
output = pagure.lib.tasks_services.load_json_commits_to_db(
name='test',
commits=['hash1', 'hash2'],
abspath=self.path,
data_type='pull-request',
agent='pingou',
namespace=None,
username=None)
self.assertIsNone(output)
calls = [
call(
ANY, json_data=u'foobar', namespace=None, reponame=u'test',
request_uid=u'file1', username=None
),
call(
ANY, json_data=u'foobar', namespace=None, reponame=u'test',
request_uid=u'file2', username=None
),
]
up_issue.assert_not_called()
self.assertEqual(
calls,
up_pr.mock_calls
)
calls = [
call(
u'Loading: file1 -- 1/2 ... ... Done\n'
u'Loading: file2 -- 2/2 ... ... Done',
u'Issue import report',
u'bar@pingou.com'
)
]
self.assertEqual(
calls,
send.mock_calls
)
@patch('json.loads')
@patch('pagure.lib.notify.send_email')
@patch('pagure.lib.git.update_request_from_git')
@patch('pagure.lib.git.update_ticket_from_git')
@patch('pagure.lib.git.read_git_lines')
def test_load_json_commits_to_db_prs_raises_error(
self, git, up_issue, up_pr, send, json_loads):
""" Test the load_json_commits_to_db method. """
git.side_effect = [
['file1'], ['file2'], ['files/image'], ['file1']]
json_loads.return_value = 'foobar'
up_pr.side_effect = Exception('foo error')
output = pagure.lib.tasks_services.load_json_commits_to_db(
name='test',
commits=['hash1', 'hash2'],
abspath=self.path,
data_type='pull-request',
agent='pingou',
namespace=None,
username=None)
self.assertIsNone(output)
calls = [
call(
ANY, json_data=u'foobar', namespace=None, reponame=u'test',
request_uid=u'file1', username=None
)
]
up_issue.assert_not_called()
self.assertEqual(
calls,
up_pr.mock_calls
)
calls = [
call(
u'Loading: file1 -- 1/2 ... ... FAILED\n',
u'Issue import report',
u'bar@pingou.com'
)
]
self.assertEqual(
calls,
send.mock_calls
)
class PagureLibTaskServicesWithWebHooktests(tests.Modeltests):
""" Tests for pagure.lib.task_services """
maxDiff = None
def setUp(self):
""" Set up the environnment, ran before every tests. """
super(PagureLibTaskServicesWithWebHooktests, self).setUp()
pagure.config.config['REQUESTS_FOLDER'] = None
self.sshkeydir = os.path.join(self.path, 'sshkeys')
pagure.config.config['MIRROR_SSHKEYS_FOLDER'] = self.sshkeydir
tests.create_projects(self.session)
project = pagure.lib.query._get_project(self.session, 'test')
settings = project.settings
settings['Web-hooks'] = 'http://foo.com/api/flag\nhttp://bar.org/bar'
project.settings = settings
self.session.add(project)
self.session.commit()
@patch('pagure.lib.tasks_services.call_web_hooks')
def test_webhook_notification_no_webhook(self, call_wh):
""" Test the webhook_notification method. """
output = pagure.lib.tasks_services.webhook_notification(
topic='topic',
msg={'payload': ['a', 'b', 'c']},
namespace=None,
name='test',
user=None)
self.assertIsNone(output)
project = pagure.lib.query._get_project(self.session, 'test')
call_wh.assert_called_once_with(
ANY, u'topic', {u'payload': [u'a', u'b', u'c']},
[u'http://foo.com/api/flag', u'http://bar.org/bar']
)
@patch('time.time', MagicMock(return_value=2))
@patch('uuid.uuid4', MagicMock(return_value='not_so_random'))
@patch('datetime.datetime')
@patch('requests.post')
def test_webhook_notification_no_webhook(self, post, dt):
""" Test the webhook_notification method. """
post.return_value = False
utcnow = MagicMock()
utcnow.year = 2018
dt.utcnow.return_value = utcnow
output = pagure.lib.tasks_services.webhook_notification(
topic='topic',
msg={'payload': ['a', 'b', 'c']},
namespace=None,
name='test',
user=None)
self.assertIsNone(output)
project = pagure.lib.query._get_project(self.session, 'test')
self.assertEqual(post.call_count, 2)
calls = [
call(
'http://bar.org/bar',
data='{'
'"i": 1, '
'"msg": {'
'"pagure_instance": "http://localhost.localdomain/", '
'"payload": ["a", "b", "c"], '
'"project_fullname": "test"}, '
'"msg_id": "2018-not_so_random", '
'"timestamp": 2, '
'"topic": "topic"}'
,
headers={
'X-Pagure': 'http://localhost.localdomain/',
'X-Pagure-project': 'test',
'X-Pagure-Signature': '74b12f0b25bf7767014a0c0de9f3c10'
'191e943d8',
'X-Pagure-Signature-256': 'f3d757796554466eac49a5282b2'
'4ee32a1ecfb65dedd6c6231fb207240a9fe58',
'X-Pagure-Topic': b'topic',
'Content-Type': 'application/json'
},
timeout=60
),
call(
'http://foo.com/api/flag',
data='{'
'"i": 1, '
'"msg": {'
'"pagure_instance": "http://localhost.localdomain/", '
'"payload": ["a", "b", "c"], '
'"project_fullname": "test"}, '
'"msg_id": "2018-not_so_random", '
'"timestamp": 2, '
'"topic": "topic"}'
,
headers={
'X-Pagure': 'http://localhost.localdomain/',
'X-Pagure-project': 'test',
'X-Pagure-Signature': '74b12f0b25bf7767014a0c0de9f3c10'
'191e943d8',
'X-Pagure-Signature-256': 'f3d757796554466eac49a5282b2'
'4ee32a1ecfb65dedd6c6231fb207240a9fe58',
'X-Pagure-Topic': b'topic',
'Content-Type': 'application/json'
},
timeout=60
)
]
print(post.mock_calls)
self.assertEqual(
calls,
post.mock_calls
)
class PagureLibTaskServicesJenkinsCItests(tests.Modeltests):
""" Tests for pagure.lib.task_services """
maxDiff = None
def setUp(self):
""" Set up the environnment, ran before every tests. """
super(PagureLibTaskServicesJenkinsCItests, self).setUp()
pagure.config.config['REQUESTS_FOLDER'] = None
self.sshkeydir = os.path.join(self.path, 'sshkeys')
pagure.config.config['MIRROR_SSHKEYS_FOLDER'] = self.sshkeydir
tests.create_projects(self.session)
project = pagure.lib.query.get_authorized_project(self.session, 'test')
# Install the plugin at the DB level
plugin = pagure.lib.plugins.get_plugin('Pagure CI')
dbobj = plugin.db_object()
dbobj.ci_url = 'https://ci.server.org/'
dbobj.ci_job = 'pagure'
dbobj.pagure_ci_token = 'random_token'
dbobj.project_id = project.id
self.session.add(dbobj)
self.session.commit()
# Create a fork of test for foo
item = pagure.lib.model.Project(
user_id=2, # foo
name='test',
is_fork=True,
parent_id=1,
description='test project #1',
hook_token='aaabbbccc_foo',
)
item.close_status = ['Invalid', 'Insufficient data', 'Fixed', 'Duplicate']
self.session.add(item)
self.session.commit()
@patch('pagure.lib.tasks_services.trigger_jenkins_build')
def test_trigger_ci_build_invalid_ci(self, trigger_jenk):
""" Test the trigger_ci_build method. """
output = pagure.lib.tasks_services.trigger_ci_build(
project_name='test',
cause='PR#ID',
branch='feature',
ci_type='travis')
self.assertIsNone(output)
trigger_jenk.assert_not_called()
@patch('pagure.lib.tasks_services.trigger_jenkins_build')
def test_trigger_ci_build_invalid_ci_fork(self, trigger_jenk):
""" Test the trigger_ci_build method. """
output = pagure.lib.tasks_services.trigger_ci_build(
project_name='forks/foo/test',
cause='PR#ID',
branch='feature',
ci_type='travis')
self.assertIsNone(output)
trigger_jenk.assert_not_called()
@patch('pagure.lib.tasks_services.trigger_jenkins_build')
def test_trigger_ci_build_valid_project(self, trigger_jenk):
""" Test the trigger_ci_build method. """
output = pagure.lib.tasks_services.trigger_ci_build(
project_name='test',
cause='PR#ID',
branch='feature',
ci_type='jenkins')
self.assertIsNone(output)
trigger_jenk.assert_called_once_with(
branch=u'feature',
cause=u'PR#ID',
job=u'pagure',
project_path=u'test.git',
token=u'random_token',
url=u'https://ci.server.org/'
)
@patch('pagure.lib.tasks_services.trigger_jenkins_build')
def test_trigger_ci_build_valid_project_fork(self, trigger_jenk):
""" Test the trigger_ci_build method. """
output = pagure.lib.tasks_services.trigger_ci_build(
project_name='forks/foo/test',
cause='PR#ID',
branch='feature',
ci_type='jenkins')
self.assertIsNone(output)
trigger_jenk.assert_called_once_with(
branch=u'feature',
cause=u'PR#ID',
job=u'pagure',
project_path=u'forks/foo/test.git',
token=u'random_token',
url=u'https://ci.server.org/'
)
class PagureLibTaskServicesLoadJsonTickettests(tests.Modeltests):
""" Tests for pagure.lib.task_services """
maxDiff = None
def setUp(self):
""" Set up the environnment, ran before every tests. """
super(PagureLibTaskServicesLoadJsonTickettests, self).setUp()
tests.create_projects(self.session)
self.gitrepo = os.path.join(self.path, 'repos', 'tickets', 'test.git')
repopath = os.path.join(self.path, 'repos', 'tickets')
os.makedirs(self.gitrepo)
self.repo_obj = pygit2.init_repository(self.gitrepo, bare=True)
project = pagure.lib.query.get_authorized_project(self.session, 'test')
# Create an issue to play with
msg = pagure.lib.query.new_issue(
session=self.session,
repo=project,
title='Test issue',
content='We should work on this',
user='pingou',
)
self.assertEqual(msg.title, 'Test issue')
issue = pagure.lib.query.search_issues(self.session, project, issueid=1)
# Add a couple of comment on the ticket
msg = pagure.lib.query.add_issue_comment(
session=self.session,
issue=issue,
comment='Hey look a comment!',
user='foo',
)
self.session.commit()
self.assertEqual(msg, 'Comment added')
commits = [
commit
for commit in self.repo_obj.walk(
self.repo_obj.head.target, pygit2.GIT_SORT_NONE)
]
# 2 commits: creation - new comment
self.assertEqual(len(commits), 2)
issue = pagure.lib.query.search_issues(self.session, project, issueid=1)
self.assertEqual(len(issue.comments), 1)
@patch('pagure.lib.notify.send_email')
@patch('pagure.lib.git.update_request_from_git')
def test_loading_issue_json(self, up_pr, send):
""" Test loading the JSON file of a ticket. """
project = pagure.lib.query.get_authorized_project(self.session, 'test')
issue = pagure.lib.query.search_issues(self.session, project, issueid=1)
commits = [
commit.oid.hex
for commit in self.repo_obj.walk(
self.repo_obj.head.target, pygit2.GIT_SORT_NONE)
]
output = pagure.lib.tasks_services.load_json_commits_to_db(
name='test',
commits=commits,
abspath=self.gitrepo,
data_type='ticket',
agent='pingou',
namespace=None,
username=None)
self.assertIsNone(output)
up_pr.assert_not_called()
calls = [
call(
u'Loading: %s -- 1/1 ... ... Done' % issue.uid,
u'Issue import report',
u'bar@pingou.com'
)
]
self.assertEqual(
calls,
send.mock_calls
)
project = pagure.lib.query.get_authorized_project(self.session, 'test')
issue = pagure.lib.query.search_issues(self.session, project, issueid=1)
self.assertEqual(len(issue.comments), 1)
if __name__ == '__main__':
unittest.main(verbosity=2)