Blame tests/test_pagure_lib_task_services.py

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