Exemple #1
0
 def setUp(self, mock_config, mock_parser, mock_log):
     path = os.path.dirname(os.path.realpath(__file__ + '../../../'))
     self._path = os.path.join(path, os.path.join('tests', 'conf'))
     mock_config.return_value = [self._path]
     mock_parser.return_value = []
     mock_log.return_value = None
     Logger._instance = mock_log
     Configuration(filename='config_sections.json')
     self._thread_manager = ThreadManager()
Exemple #2
0
 def test_adding_filter_ignores_argument_validation_error_and_adds_to_self(self, mock_query, mock_load, mock_jira_client):
     mock_query.side_effect = ArgumentValidationError('1st', 'append', 'pyccata.core.filter.Filter', 'object')
     mock_jira_client.return_value = DataProviders._get_client()
     with patch('pyccata.core.configuration.Configuration.manager', new_callable=PropertyMock) as mock_manager:
         with patch('pyccata.core.configuration.Configuration._configuration', new_callable=PropertyMock) as mock_config:
             mock_config.return_value = DataProviders._get_config_for_test()
             mock_manager.return_value = 'jira'
             manager = ThreadManager()
             manager.append(TestObservableThread())
             self.assertEquals(1, len(manager))
Exemple #3
0
 def test_adding_filter_adds_project_manager(self, mock_load, mock_jira_client):
     mock_jira_client.return_value = DataProviders._get_client()
     with patch('pyccata.core.configuration.Configuration.manager', new_callable=PropertyMock) as mock_manager:
         with patch('pyccata.core.configuration.Configuration._configuration', new_callable=PropertyMock) as mock_config:
             mock_config.return_value = DataProviders._get_config_for_test()
             mock_manager.return_value = 'jira'
             manager = ThreadManager()
             self.assertIsInstance(manager.projectmanager, ProjectManager)
             self.assertIsInstance(manager.querymanager, QueryManager)
             self.assertIsInstance(manager.configuration, Configuration)
             mock_filter = Filter('assignee = "Foo"')
             manager.append(mock_filter)
             self.assertIsInstance(mock_filter.projectmanager, ProjectManager)
    def setUp(self, mock_config, mock_parser, mock_log):
        self.tearDown()
        mock_log.return_value = None
        Logger._instance = mock_log
        path = os.path.dirname(os.path.realpath(__file__ + '../../../../'))
        self._path = os.path.join(path, os.path.join('tests', 'conf'))
        mock_config.return_value = [self._path]
        mock_parser.return_value = []
        config = None

        with patch('argparse.ArgumentParser.add_argument'):
            config = Configuration(filename='valid_config.json')
        config.check = True
        self._report_manager = ReportManager()
        self._thread_manager = ThreadManager()
Exemple #5
0
    def setup(self, extractor, index, queries, results, primary_dataset,
              unique_columns):
        """
        Set up the partition runner

        :param pyccata.core.classes.DataExtraction: extractor
        :param int: index
        :param list: queries
        :param list: results
        :param string: primary_dataset
        :param list|string: unique_columns

        queries is a list of ``pyccata.core.parser.ExtractedResults`` objects
        results is a list of ``pandas.DataFrame`` objects
        primary_dataset dictates which frame to use for the left side of the join
        unique_columns determines which column to use for the join
        """
        # pylint: disable=arguments-differ,too-many-arguments
        self._extractor = extractor
        self._index = index
        self._queries = queries
        self._results = results
        self._names = [item.name for item in results]

        alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
        short_names = [letter for letter in alphabet[:len(self._results)]]
        self._mappings = {
            name: short
            for short, name in zip(short_names, self._names)
        }

        self._primary_dataset = primary_dataset
        self._unique_columns = unique_columns
        ThreadManager().append(self)
Exemple #6
0
 def threadmanager(self):
     """ Load the threadmanager """
     try:
         if self._thread_manager is None:
             return ThreadManager()
     except (ImportError, AttributeError, NotImplementedError,
             RequiredKeyError) as exception:
         ControllerAbstract._raise_and_terminate('ThreadManager', exception)
     return self._thread_manager
Exemple #7
0
    def setup(self, merge_table, query, unique_columns):
        """
        Set up a new data-filter as a threaded object

        :param merge_table: pandas.DataFrame object
        :param query: string
        """
        # pylint: disable=arguments-differ

        self._data = merge_table
        self._query = query
        self._unique_columns = unique_columns
        ThreadManager().append(self)
Exemple #8
0
    def test_execute_batches_pool_size_and_logs_on_error(self, mock_query, mock_load, mock_jira_client):
        mock_query.side_effect = ArgumentValidationError('1st', 'append', 'pyccata.core.filter.Filter', 'object')
        mock_jira_client.return_value = DataProviders._get_client()
        with patch('pyccata.core.configuration.Configuration.manager', new_callable=PropertyMock) as mock_manager:
            with patch('pyccata.core.configuration.Configuration._configuration', new_callable=PropertyMock) as mock_config:
                mock_config.return_value = DataProviders._get_config_for_test()
                mock_manager.return_value = 'jira'

                manager = ThreadManager()
                test_threads = DataProviders.some_threads_explode()
                for thread in test_threads:
                    manager.append(thread)
                manager.start()
Exemple #9
0
    def test_execute_batches_pool_size_and_fills_on_complete(self, mock_query, mock_load, mock_jira_client):
        mock_query.side_effect = ArgumentValidationError('1st', 'append', 'pyccata.core.filter.Filter', 'object')
        mock_jira_client.return_value = DataProviders._get_client()
        with patch('pyccata.core.configuration.Configuration.manager', new_callable=PropertyMock) as mock_manager:
            with patch('pyccata.core.configuration.Configuration._configuration', new_callable=PropertyMock) as mock_config:
                mock_config.return_value = DataProviders._get_config_for_test()
                mock_manager.return_value = 'jira'

                manager = ThreadManager()
                # start with 100 threads...
                for i in range(100):
                    manager.append(ViableTestThread())
                manager.start()
Exemple #10
0
    def test_execute_adds_to_failures_when_all_observers_fail(self, mock_load, mock_jira_client):
        mock_jira_client.return_value = None
        with patch('pyccata.core.configuration.Configuration.manager', new_callable=PropertyMock) as mock_manager:
            with patch('pyccata.core.configuration.Configuration._configuration', new_callable=PropertyMock) as mock_config:
                mock_config.return_value = DataProviders._get_config_for_test()
                mock_manager.return_value = 'jira'

                mock_broken = BrokenConnectionFilter('assignee = "Bob"')
                mock_filter = BrokenConnectionFilter('assignee = "Bob"')

                manager = ThreadManager()
                manager.append(mock_broken)
                manager.append(mock_filter)

                self.assertEquals(1, len(manager))
                self.assertEquals(1, len(manager[0]._observers))
                manager.start()
                self.assertEquals(1, len(manager._failed_threads))
Exemple #11
0
class TestList(TestCase):

    _report_manager = None
    _thread_manager = None

    @patch('pyccata.core.log.Logger.log')
    @patch('argparse.ArgumentParser.parse_args')
    @patch('pyccata.core.configuration.Configuration._get_locations')
    def setUp(self, mock_config, mock_parser, mock_log):
        path = os.path.dirname(os.path.realpath(__file__ + '../../../../'))
        self._path = os.path.join(path, os.path.join('tests', 'conf'))
        mock_config.return_value = [self._path]
        mock_parser.return_value = []
        mock_log.return_value = None
        Logger._instance = mock_log
        Configuration(filename='config_sections.json')
        self._report_manager = ReportManager()
        self._thread_manager = ThreadManager()

    def tearDown(self):
        if ThreadManager._instance is not None:
            ThreadManager._instance = None
        if Configuration._instance is not None:
            Configuration._instance = None
        Configuration.NAMESPACE = 'pyccata.core'

    def test_get_item_raises_error_if_content_is_filter_and_filter_results_is_empty(
            self):
        list_contents = Filter('project=mssportal',
                               max_results=5,
                               fields=['id', 'description', 'priority'])
        Config = namedtuple('Config', 'content style field prepend')
        config = Config(content=list_contents,
                        style='unordered',
                        field='description',
                        prepend=None)
        unordered = List(self._thread_manager, config)
        with self.assertRaises(IndexError):
            item = unordered[0]

    def test_get_item_raises_error_if_content_is_list_and_results_is_none(
            self):
        list_contents = []
        Config = namedtuple('Config', 'content style field prepend')
        config = Config(content=list_contents,
                        style='unordered',
                        field='description',
                        prepend=None)
        unordered = List(self._thread_manager, config)
        with self.assertRaises(IndexError):
            item = unordered[0]

    def test_set_item_raises_error_if_content_is_filter_and_filter_results_is_none(
            self):
        list_contents = Filter('project=mssportal',
                               max_results=5,
                               fields=['id', 'description', 'priority'])
        Config = namedtuple('Config', 'content style field prepend')
        config = Config(content=list_contents,
                        style='unordered',
                        field='description',
                        prepend=None)
        unordered = List(self._thread_manager, config)
        with self.assertRaises(IndexError):
            unordered[0] = 'hello world'

    def test_set_item_raises_error_if_content_is_list_and_results_is_none(
            self):
        list_contents = []
        Config = namedtuple('Config', 'content style field prepend')
        config = Config(content=list_contents,
                        style='unordered',
                        field='description',
                        prepend=None)
        unordered = List(self._thread_manager, config)
        with self.assertRaises(IndexError):
            unordered[0] = 'hello world'

    def test_get_len_returns_length_of_self_if_content_is_list(self):
        list_contents = ['test 1', 'test 2', 'test 3']

        Config = namedtuple('Config', 'content style field prepend')
        config = Config(content=list_contents,
                        style='unordered',
                        field='description',
                        prepend=None)
        unordered = List(self._thread_manager, config)
        self.assertEqual(3, len(unordered))

    @patch('pyccata.core.managers.project.ProjectManager.search_issues')
    def test_get_len_returns_length_of_filter_results_if_content_is_filter(
            self, mock_manager):
        result_list = DataProviders(
        ).get_results_for_list_init_with_single_query_in_config()

        list_contents = Filter('project=msportal',
                               max_results=5,
                               fields=['id', 'description', 'priority'])

        mock_manager.return_value = result_list
        Config = namedtuple('Config', 'content style field prepend')
        config = Config(content=list_contents,
                        style='unordered',
                        field='description',
                        prepend=None)

        unordered = List(self._thread_manager, config)
        self._thread_manager.execute()
        self.assertEquals(5, len(unordered))

    def test_delete_item_if_content_is_list(self):
        list_contents = ['test 1', 'test 2', 'test 3']

        Config = namedtuple('Config', 'content style field prepend')
        config = Config(content=list_contents,
                        style='unordered',
                        field='description',
                        prepend=None)
        unordered = List(self._thread_manager, config)

        del unordered[2]
        self.assertEquals(2, len(unordered))

    @patch('pyccata.core.managers.project.ProjectManager.search_issues')
    def test_delete_item_if_content_is_filter(self, mock_manager):
        result_list = DataProviders(
        ).get_results_for_list_init_with_single_query_in_config()

        list_contents = Filter('project=msportal',
                               max_results=5,
                               fields=['id', 'description', 'priority'])
        mock_manager.return_value = result_list
        Config = namedtuple('Config', 'content style field prepend')
        config = Config(content=list_contents,
                        style='unordered',
                        field='description',
                        prepend=None)

        unordered = List(self._thread_manager, config)
        self._thread_manager.execute()

        del unordered[1]
        self.assertEquals(4, len(unordered))

    def test_reverse_list_if_content_is_list(self):
        list_contents = ['test 1', 'test 2', 'test 3']

        Config = namedtuple('Config', 'content style field prepend')
        config = Config(content=list_contents,
                        style='unordered',
                        field='description',
                        prepend=None)
        unordered = List(self._thread_manager, config)

        unordered = list(reversed(unordered))
        self.assertEquals('test 3', unordered[0])
        self.assertEquals('test 2', unordered[1])
        self.assertEquals('test 1', unordered[2])

    @patch('pyccata.core.managers.project.ProjectManager.search_issues')
    def test_reverse_list_if_content_is_filter(self, mock_manager):
        result_list = DataProviders(
        ).get_results_for_list_init_with_single_query_in_config()

        list_contents = Filter('project=msportal',
                               max_results=5,
                               fields=['id', 'description', 'priority'])
        mock_manager.return_value = result_list
        Config = namedtuple('Config', 'content style field prepend')
        config = Config(content=list_contents,
                        style='unordered',
                        field='description',
                        prepend=None)

        unordered = List(self._thread_manager, config)
        self._thread_manager.execute()

        unordered = list(reversed(unordered))
        self.assertEquals('This is test item 5', unordered[0].description)
        self.assertEquals('This is test item 4', unordered[1].description)
        self.assertEquals('This is test item 3', unordered[2].description)
        self.assertEquals('This is test item 2', unordered[3].description)
        self.assertEquals('This is test item 1', unordered[4].description)

    def test_list_contains_item_if_content_is_list(self):
        list_contents = ['test 1', 'test 2', 'test 3']

        Config = namedtuple('Config', 'content style field prepend')
        config = Config(content=list_contents,
                        style='unordered',
                        field='description',
                        prepend=None)
        unordered = List(self._thread_manager, config)

        self.assertTrue(('test 1' in unordered))

    @patch('pyccata.core.managers.project.ProjectManager.search_issues')
    def test_list_contains_item_if_content_is_filter(self, mock_manager):
        result_list = DataProviders(
        ).get_results_for_list_init_with_single_query_in_config()

        list_contents = Filter('project=msportal',
                               max_results=5,
                               fields=['id', 'description', 'priority'])
        mock_manager.return_value = result_list
        Config = namedtuple('Config', 'content style field prepend')
        config = Config(content=list_contents,
                        style='unordered',
                        field='description',
                        prepend=None)

        unordered = List(self._thread_manager, config)
        self._thread_manager.execute()

        self.assertTrue((result_list[3] in unordered))

    def test_setup_raises_argument_validation_error_if_style_is_invalid(self):
        Config = namedtuple('Config', 'content style field prepend')
        config = Config(content=[], style='IAmInvalid', field='', prepend=None)
        with self.assertRaises(ArgumentValidationError):
            unordered = List(self._thread_manager, config)

    @patch('pyccata.core.managers.report.ReportManager.add_list')
    def test_init_creates_list(self, mock_list):
        list_contents = ['test item 1', 'test item 2', 'test item 3']
        Config = namedtuple('Config', 'content style field prepend')
        config = Config(content=list_contents,
                        style='unordered',
                        field='',
                        prepend=None)

        calls = [call(item, style='ListBullet') for item in list_contents]
        unordered = List(self._thread_manager, config)
        unordered.run()
        unordered.render(self._report_manager)

        mock_list.assert_has_calls(calls)

    @patch('pyccata.core.managers.project.ProjectManager.search_issues')
    @patch('pyccata.core.managers.report.ReportManager.add_list')
    def test_init_using_list_of_queries_creates_list(self, mock_list,
                                                     mock_manager):
        result_list = DataProviders(
        ).get_results_for_list_init_with_list_of_queries_in_config()

        list_contents = [
            Filter('project=mssportal',
                   max_results=5,
                   fields=['id', 'description', 'priority']),
            Filter('project=svcdesk',
                   max_results=5,
                   fields=['id', 'description', 'priority']),
            Filter('project=mvs',
                   max_results=5,
                   fields=['id', 'description', 'priority']),
        ]

        mock_manager.side_effect = result_list
        Config = namedtuple('Config', 'content style field prepend')
        config = Config(content=list_contents,
                        style='unordered',
                        field='description',
                        prepend=None)

        calls = [
            call(item[0].description, style='ListBullet')
            for item in result_list
        ]

        unordered = List(self._thread_manager, config)
        self._thread_manager.execute()

        unordered.render(self._report_manager)

        mock_list.assert_has_calls(calls)

    @patch('pyccata.core.managers.project.ProjectManager.search_issues')
    @patch('pyccata.core.managers.report.ReportManager.add_list')
    def test_init_using_list_of_queries_and_strings_creates_list(
            self, mock_list, mock_manager):
        result_list = DataProviders(
        ).get_results_for_list_init_with_list_of_queries_and_strings_in_config(
        )

        list_contents = [
            Filter('project=msportal',
                   max_results=5,
                   fields=['id', 'description',
                           'priority']), "This is a string entry",
            Filter('project=svdesk',
                   max_results=5,
                   fields=['id', 'description', 'priority']),
            Filter('project=mvp',
                   max_results=5,
                   fields=['id', 'description', 'priority']),
            "This is another string entry"
        ]

        effect = [item for item in result_list if isinstance(item, ResultList)]

        mock_manager.side_effect = effect
        Config = namedtuple('Config', 'content style field prepend')
        config = Config(content=list_contents,
                        style='unordered',
                        field='description',
                        prepend=None)

        calls = [
            call(item[0].description if isinstance(item, list) else item,
                 style='ListBullet') for item in result_list
        ]

        unordered = List(self._thread_manager, config)
        self._thread_manager.execute()

        unordered.render(self._report_manager)

        mock_list.assert_has_calls(calls)

    @patch('pyccata.core.managers.project.ProjectManager.search_issues')
    @patch('pyccata.core.managers.report.ReportManager.add_list')
    def test_init_using_single_query_creates_list(self, mock_list,
                                                  mock_manager):
        result_list = DataProviders(
        ).get_results_for_list_init_with_single_query_in_config()

        list_contents = Filter('project=msportal',
                               max_results=5,
                               fields=['id', 'description', 'priority'])

        mock_manager.return_value = result_list
        Config = namedtuple('Config', 'content style field prepend')
        config = Config(content=list_contents,
                        style='unordered',
                        field='description',
                        prepend=None)

        calls = [
            call(item.description, style='ListBullet') for item in result_list
        ]

        unordered = List(self._thread_manager, config)
        self._thread_manager.execute()

        unordered.render(self._report_manager)

        mock_list.assert_has_calls(calls)

    @patch('pyccata.core.managers.project.ProjectManager.search_issues')
    @patch('pyccata.core.managers.report.ReportManager.add_list')
    def test_init_using_list_of_queries_and_strings_continues_if_query_errors(
            self, mock_list, mock_manager):
        result_list = DataProviders(
        ).get_results_for_list_init_with_list_of_queries_and_strings_continues(
        )

        list_contents = [
            Filter('project=msportal',
                   max_results=5,
                   fields=['id', 'description',
                           'priority']), "This is a string entry",
            Filter('project=svdesk',
                   max_results=5,
                   fields=['id', 'description', 'priority']),
            Filter('project=mvp',
                   max_results=5,
                   fields=['id', 'description', 'priority']),
            "This is another string entry"
        ]

        effect = [item for item in result_list if isinstance(item, ResultList)]
        effect[1] = InvalidQueryError('The query you have provided is invalid')

        mock_manager.side_effect = effect
        Config = namedtuple('Config', 'content style field prepend')
        config = Config(content=list_contents,
                        style='unordered',
                        field='description',
                        prepend=None)

        calls = [
            call(item[0].description if isinstance(item, list) else item,
                 style='ListBullet') for item in result_list
        ]
        del calls[2]

        unordered = List(self._thread_manager, config)
        self._thread_manager.execute()
        unordered.render(self._report_manager)
        mock_list.assert_has_calls(calls)

    @patch('pyccata.core.managers.project.ProjectManager.search_issues')
    def test_list_contains_item_if_content_is_tuple(self, mock_manager):
        result_list = DataProviders(
        ).get_results_for_list_init_with_single_query_in_config()

        ListContents = namedtuple('ListContents', 'query fields')
        list_contents = ListContents('project=msportal',
                                     fields=['id', 'description', 'priority'])
        mock_manager.return_value = result_list
        Config = namedtuple('Config', 'content style field prepend')
        config = Config(content=list_contents,
                        style='unordered',
                        field='description',
                        prepend=None)

        unordered = List(self._thread_manager, config)
        self._thread_manager.execute()

        self.assertTrue((result_list[3] in unordered))

    @patch('pyccata.core.managers.project.ProjectManager.search_issues')
    def test_list_fails_if_content_is_invalid_tuple(self, mock_manager):
        result_list = DataProviders(
        ).get_results_for_list_init_with_single_query_in_config()

        Filter = namedtuple('Filter', 'bob fields')
        list_contents = Filter('project=msportal',
                               fields=['id', 'description', 'priority'])
        mock_manager.return_value = result_list
        Config = namedtuple('Config', 'content style field prepend')
        config = Config(content=list_contents,
                        style='unordered',
                        field='description',
                        prepend=None)

        with self.assertRaises(ArgumentValidationError):
            unordered = List(self._thread_manager, config)

    def test_run_completes_if_filter_delays_in_completing(self):
        ListContents = namedtuple('ListContents', 'query fields')
        list_contents = ListContents('project=msportal',
                                     fields=['id', 'description', 'priority'])
        Config = namedtuple('Config', 'content style field prepend')
        config = Config(content=list_contents,
                        style='unordered',
                        field='description',
                        prepend=None)

        with patch('pyccata.core.filter.Filter.complete',
                   new_callable=PropertyMock) as mock_thread_complete:
            unordered = List(self._thread_manager, config)
            mock_thread_complete.side_effect = [False, False, True]
            unordered.run()
            self.assertTrue(unordered._complete)

    def test_run_completes_if_thread_fails(self):
        ListContents = namedtuple('ListContents', 'query fields')
        list_contents = ListContents('project=msportal',
                                     fields=['id', 'description', 'priority'])
        Config = namedtuple('Config', 'content style field prepend')
        config = Config(content=list_contents,
                        style='unordered',
                        field='description',
                        prepend=None)

        with patch('pyccata.core.threading.Threadable.complete',
                   new_callable=PropertyMock) as mock_thread_complete:
            unordered = List(self._thread_manager, config)
            mock_thread_complete.return_value = True
            unordered._content._failure = InvalidQueryError(
                'Your JQL contains an error before Pipeline')
            unordered.run()
            self.assertTrue(unordered._complete)

    @patch('pyccata.core.managers.project.ProjectManager.search_issues')
    @patch('pyccata.core.managers.report.ReportManager.add_list')
    def test_init_using_list_of_queries_and_strings_continues_if_query_is_delayed(
            self, mock_list, mock_manager):
        result_list = DataProviders(
        ).get_results_for_list_init_with_list_of_queries_and_strings_continues(
        )

        list_contents = [
            "This is a string entry",
            Filter('project=msportal',
                   max_results=5,
                   fields=['id', 'description', 'priority'])
        ]

        effect = [item for item in result_list if isinstance(item, ResultList)]
        effect[1] = InvalidQueryError('The query you have provided is invalid')

        mock_manager.side_effect = effect
        Config = namedtuple('Config', 'content style field prepend')
        config = Config(content=list_contents,
                        style='unordered',
                        field='description',
                        prepend=None)

        with patch('pyccata.core.filter.Filter.complete',
                   new_callable=PropertyMock) as mock_thread_complete:
            mock_thread_complete.side_effect = [False, False, True]
            unordered = List(self._thread_manager, config)
            unordered.run()
            self.assertTrue(unordered._complete)

    @patch('pyccata.core.filter.Filter.results', new_callable=PropertyMock)
    @patch('pyccata.core.managers.report.ReportManager.add_list')
    def test_init_using_single_query_creates_list_of_items(
            self, mock_list, mock_results):

        results = ["test 1", "test 2", "test 3", "test 4", "test 5"]

        resultset = Issue()
        resultset.pipelines = results

        list_contents = Filter('project=msportal',
                               max_results=5,
                               fields=['id', 'description', 'priority'])
        Config = namedtuple('Config', 'content style field prepend')
        config = Config(content=list_contents,
                        style='unordered',
                        field='pipelines',
                        prepend=None)

        calls = [call(item, style='ListBullet') for item in results]
        with patch('pyccata.core.filter.Filter.complete',
                   new_callable=PropertyMock):
            unordered = List(self._thread_manager, config)
            mock_results.return_value = [resultset]
            list_contents.complete.return_value = True
            unordered.run()
            unordered.render(self._report_manager)
            mock_list.assert_has_calls(calls)

    @patch('pyccata.core.managers.project.ProjectManager.search_issues')
    def test_list_completes_if_content_filter_fails(self, mock_manager):
        result_list = DataProviders(
        ).get_results_for_list_init_with_single_query_in_config()

        list_contents = Filter('project=msportal',
                               max_results=5,
                               fields=['id', 'description', 'priority'])
        mock_manager.return_value = result_list
        Config = namedtuple('Config', 'content style field prepend')
        config = Config(content=list_contents,
                        style='unordered',
                        field='description',
                        prepend=None)

        unordered = List(self._thread_manager, config)
        with patch('pyccata.core.filter.Filter.failure',
                   new_callable=PropertyMock) as mock_failure:
            mock_failure.return_value = RuntimeError('I blew up')
            self._thread_manager.execute()
Exemple #12
0
class TestTable(TestCase):

    _report_manager = None
    _thread_manager = None

    @patch('pyccata.core.log.Logger.log')
    @patch('argparse.ArgumentParser.parse_args')
    @patch('pyccata.core.configuration.Configuration._get_locations')
    def setUp(self, mock_config, mock_parser, mock_log):
        path = os.path.dirname(os.path.realpath(__file__ + '../../../../'))
        self._path = os.path.join(path, os.path.join('tests', 'conf'))
        mock_config.return_value = [self._path]
        mock_parser.return_value = []
        mock_log.return_value = None
        Logger._instance = mock_log
        Configuration(filename='config_sections.json')
        self._report_manager = ReportManager()
        self._thread_manager = ThreadManager()

    def tearDown(self):
        if ThreadManager._instance is not None:
            ThreadManager._instance = None
        if Configuration._instance is not None:
            Configuration._instance = None
        Configuration.NAMESPACE = 'pyccata.core'

    @patch('pyccata.core.managers.report.ReportManager.add_table')
    def test_run_creates_table(self, mock_manager):
        Config = namedtuple('Config', 'rows columns style')

        rows = []
        for i in range(6):
            rows.append(
                ['Row ' + str((i + 1)), 'Test description ' + str((i + 1))])

        columns = ['Name', 'Description']
        config = Config(rows=rows, columns=columns, style='Light heading 1')
        table = Table(self._thread_manager, config)
        self._thread_manager.execute()
        table.render(self._report_manager)

        calls = [call(headings=columns, data=rows, style='Light heading 1')]
        mock_manager.assert_has_calls(calls)

    @patch('pyccata.core.managers.report.ReportManager.add_table')
    def test_create_table_manages_exception_if_filter_cannot_be_created(
            self, mock_manager):
        Config = namedtuple('Config', 'rows columns style')

        Filter = namedtuple('SubFilter', 'search_for bob')
        rows = Filter(search_for='project=mssportal', bob='fish')

        columns = ['Name', 'Description']
        config = Config(rows=rows, columns=columns, style='Light heading 1')
        table = Table(self._thread_manager, config)

    def test_run_completes_if_filter_fails(self):
        mock_filter = Filter('bob',
                             max_results=5,
                             fields=None,
                             namespace='pyccata.core')
        mock_filter._failure = InvalidQueryError('query is wrong')
        Config = namedtuple('Config', 'rows columns style')
        config = Config(rows=[['My search', mock_filter]],
                        columns=['Test column', 'Test Results'],
                        style=None)
        table = Table(self._thread_manager, config)
        table.run()
        self.assertTrue(table._complete)

    def test_run_completes_if_filter_delays_in_completing(self):
        mock_filter = Filter('bob',
                             max_results=5,
                             fields=None,
                             namespace='pyccata.core')
        Config = namedtuple('Config', 'rows columns style')
        config = Config(rows=[['My search', mock_filter]],
                        columns=['Test column', 'Test Results'],
                        style=None)
        with patch('pyccata.core.threading.Threadable.complete',
                   new_callable=PropertyMock) as mock_thread:
            table = Table(self._thread_manager, config)
            mock_thread.side_effect = [False, False, True]
            table.run()
            self.assertTrue(table._complete)

    @patch('pyccata.core.managers.report.ReportManager.add_table')
    @patch('pyccata.core.managers.report.ReportManager.add_heading')
    def test_table_doesnt_render_with_empty_filter_results(
            self, mock_heading, mock_table):
        self.tearDown()
        Config = namedtuple('Config', 'rows columns style')

        Filter = namedtuple('Filter', 'query max_results namespace')
        rows = Filter(query='project=mssportal',
                      max_results=5,
                      namespace='pyccata.core')

        columns = ['Name', 'Description']
        config = Config(rows=rows, columns=columns, style='Light heading 1')
        table = Table(self._thread_manager, config)

        document = ReportManager()
        table.render(document)
        mock_table.assert_not_called()
        mock_heading.assert_not_called()

    @patch('pyccata.core.managers.report.ReportManager.add_table')
    @patch('pyccata.core.managers.report.ReportManager.add_heading')
    def test_table_renders_filter_results(self, mock_heading, mock_table):
        self.tearDown()
        Config = namedtuple('Config', 'rows columns style')

        with patch('pyccata.core.filter.Filter.results',
                   new_callable=PropertyMock) as mock_results:
            ResultsList = namedtuple('ResultsList', 'total results')
            Result = namedtuple('Result',
                                'key release_text business_representative')
            mock_results.return_value = ResultsList(
                total=1,
                results=[
                    Result(key='testproj-123',
                           release_text='I am test text',
                           business_representative='Bob Smith')
                ])
            Filter = namedtuple('Filter', 'query max_results namespace')
            rows = Filter(query='project=mssportal',
                          max_results=5,
                          namespace='pyccata.core')

            columns = ['Name', 'Description']
            config = Config(rows=rows,
                            columns=columns,
                            style='Light heading 1')
            table = Table(self._thread_manager, config)

            document = ReportManager()
            table.render(document)
            self.assertEquals(1, mock_table.call_count)
            mock_heading.assert_not_called()

    @patch('pyccata.core.managers.report.ReportManager.add_table')
    @patch('pyccata.core.managers.report.ReportManager.add_heading')
    def test_table_renders_filter_results_from_cell_query(
            self, mock_heading, mock_table):
        self.tearDown()
        Config = namedtuple('Config', 'rows columns style')

        with patch('pyccata.core.filter.Filter.results',
                   new_callable=PropertyMock) as mock_results:
            ResultsList = namedtuple('ResultsList', 'total results')
            Result = namedtuple('Result',
                                'key release_text business_representative')
            mock_results.return_value = ResultsList(
                total=1,
                results=[
                    Result(key='testproj-123',
                           release_text='I am test text',
                           business_representative='Bob Smith')
                ])
            Filter = namedtuple('Filter', 'query max_results namespace')
            rows = Filter(query='project=mssportal',
                          max_results=5,
                          namespace='pyccata.core')

            columns = ['Name', 'Description']
            config = Config(rows=[['Data', rows]],
                            columns=columns,
                            style='Light heading 1')
            table = Table(self._thread_manager, config)
            table.title = 'Test Title'

            document = ReportManager()
            table.render(document)
            self.assertEquals(1, mock_table.call_count)
            self.assertEquals(1, mock_heading.call_count)
            mock_heading.assert_called_with('Test Title', 3)

    @patch('pyccata.core.managers.report.ReportManager.add_table')
    @patch('pyccata.core.managers.report.ReportManager.add_heading')
    def test_table_renders_filter_results_from_cell_query_continues_if_filter_errors(
            self, mock_heading, mock_table):
        self.tearDown()
        Config = namedtuple('Config', 'rows columns style')

        with patch('pyccata.core.filter.Filter.results',
                   new_callable=PropertyMock) as mock_results:
            ResultsList = namedtuple('ResultsList', 'total results')
            Result = namedtuple('Result',
                                'key release_text business_representative')
            mock_results.return_value = ResultsList(
                total=1,
                results=[
                    Result(key='testproj-123',
                           release_text='I am test text',
                           business_representative='Bob Smith')
                ])
            Filter = namedtuple('Filter', 'max_results namespace')
            rows = Filter(max_results=5, namespace='pyccata.core')

            columns = ['Name', 'Description']
            config = Config(rows=[['Data', rows]],
                            columns=columns,
                            style='Light heading 1')
            table = Table(self._thread_manager, config)
            table.title = 'Test Title'

            document = ReportManager()
            table.render(document)
            self.assertEquals(1, mock_table.call_count)
            self.assertEquals(1, mock_heading.call_count)
            mock_heading.assert_called_with('Test Title', 3)

    @patch('pyccata.core.managers.report.ReportManager.add_table')
    @patch('pyccata.core.managers.report.ReportManager.add_heading')
    def test_table_renders_filter_results_multi_results_with_combine(
            self, mock_heading, mock_table):
        self.tearDown()
        Config = namedtuple('Config', 'rows columns style')

        with patch('pyccata.core.filter.Filter.results',
                   new_callable=PropertyMock) as mock_results:
            results_set_one = ResultList(name='test results')
            result_issue = Issue()
            result_issue.description = 'This is a test item'
            results_set_one.append(result_issue)

            results_set_two = ResultList(name='another set of tests')
            another_result_issue = Issue()
            another_result_issue.description = 'This is a test item'
            results_set_two.append(another_result_issue)

            multi_results = MultiResultList()
            multi_results.combine = True
            multi_results.append(results_set_one)
            multi_results.append(results_set_two)

            mock_results.return_value = multi_results
            Filter = namedtuple('Filter', 'query max_results namespace')
            rows = Filter(query='project=mssportal',
                          max_results=5,
                          namespace='pyccata.core')

            columns = ['Name', 'Description']
            config = Config(rows=rows,
                            columns=columns,
                            style='Light heading 1')
            table = Table(self._thread_manager, config)

            document = ReportManager()
            table.render(document)
            self.assertEquals(1, mock_table.call_count)
            mock_heading.assert_not_called()

    @patch('pyccata.core.managers.report.ReportManager.add_table')
    @patch('pyccata.core.managers.report.ReportManager.add_heading')
    def test_table_renders_filter_results_multi_results_without_combine(
            self, mock_heading, mock_table):
        self.tearDown()
        Config = namedtuple('Config', 'rows columns style')

        with patch('pyccata.core.filter.Filter.results',
                   new_callable=PropertyMock) as mock_results:
            results_set_one = ResultList(name='test results')
            result_issue = Issue()
            result_issue.description = 'This is a test item'
            results_set_one.append(result_issue)

            results_set_two = ResultList(name='another set of tests')
            another_result_issue = Issue()
            another_result_issue.description = 'This is a test item'
            results_set_two.append(another_result_issue)

            multi_results = MultiResultList()
            multi_results.combine = False
            multi_results.append(results_set_one)
            multi_results.append(results_set_two)

            mock_results.return_value = multi_results
            Filter = namedtuple('Filter', 'query max_results namespace')
            rows = Filter(query='project=mssportal',
                          max_results=5,
                          namespace='pyccata.core')

            columns = ['Name', 'Description']
            config = Config(rows=rows,
                            columns=columns,
                            style='Light heading 1')
            table = Table(self._thread_manager, config)

            document = ReportManager()
            table.render(document)
            self.assertEquals(2, mock_table.call_count)
            self.assertEquals(2, mock_heading.call_count)
Exemple #13
0
 def test_we_only_accept_threadable_objects(self, mock_load, mock_jira_client):
     with self.assertRaises(ArgumentValidationError):
         manager = ThreadManager()
         manager.append(object())
Exemple #14
0
class TestThreadableCommand(TestCase):

    @patch('pyccata.core.log.Logger.log')
    @patch('argparse.ArgumentParser.parse_args')
    @patch('pyccata.core.configuration.Configuration._get_locations')
    def setUp(self, mock_config, mock_parser, mock_log):
        path = os.path.dirname(os.path.realpath(__file__ + '../../../'))
        self._path = os.path.join(path, os.path.join('tests', 'conf'))
        mock_config.return_value = [self._path]
        mock_parser.return_value = []
        mock_log.return_value = None
        Logger._instance = mock_log
        Configuration(filename='config_sections.json')
        self._thread_manager = ThreadManager()

    def tearDown(self):
        if Configuration._instance is not None:
            Configuration._instance = None
        Configuration.NAMESPACE = 'pyccata.core'
        self._thread_manager.clear()
        self._thread_manager._instance = None
        del self._thread_manager

    @data(
        [
            "sed 's/24/25/g'",
            {
                'command':'sed',
                'args':['s/24/25/g']
            }
        ],
        [
            "sed 's/24/25/g' &>/dev/null",
            {
                'command':'sed',
                'args':['s/24/25/g'],
                'redirects': {'0': '/dev/null', '2':'/dev/null'}
            }
        ],
        [
            "sed 's/24/25/g' 1>&2",
            {
                'command':'sed',
                'args':['s/24/25/g'],
                'redirects': {'0':'1'}
            }
        ],
        [
            "sed 's/24/25/g' 2>&1 1>/dev/null",
            {
                'command':'sed',
                'args':['s/24/25/g'],
                'redirects': {'0': '/dev/null', '1':'0'}
            }
        ],
        [
            "sed 's/24/25/g' &>/dev/null < infile.txt",
            {
                'command':'sed',
                'args':['s/24/25/g'],
                'redirects': {'0': '/dev/null', '1':'/dev/null'}
            }
        ],
        [
            "grep -rin --col 'i < 24\|b>19' > /dev/null",
            {
                'command':'grep',
                'args':['-rin', '--col', 'i < 24\|b>19'],
                'redirects': {'0': '/dev/null'}
            }
        ],
        [
            "grep -rin --col 'i < 24\|b>19' 3>/dev/null",
            {
                'command':'grep',
                'args':['-rin', '--col', 'i < 24\|b>19'],
                'redirects': {'0': '0'}
            }
        ],
        [
            "grep -rin --col 'i < 24\|b>19' 3>4",
            {
                'command':'grep',
                'args':['-rin', '--col', 'i < 24\|b>19'],
                'redirects': {'0': '0'}
            }
        ]

    )
    @unpack
    def test_build_command_with_simple_commands(self, command, expected_return):
        configuration = namedtuple('Config', 'name command input_directory output_directory wait_for')
        config = configuration(
            name='Test command',
            command=command,
            input_directory='/tmp',
            output_directory='/tmp',
            wait_for=None
        )
        threadable = ThreadableCommand(self._thread_manager, config)
        commands = threadable._commands
        for command in commands:
            self.assertEquals(command.command, expected_return['command'])
            self.assertEquals(command.arguments, expected_return['args'])
            if not 'redirects' in expected_return.keys():
                continue
            for key in expected_return['redirects'].keys():
                for redirect in command.redirects:
                    if str(redirect.redirect_input) == str(int(key)-1):
                        out = redirect.redirect_output if isinstance(redirect.redirect_output, str) else str(redirect.redirect_output)
                        self.assertEquals(out, expected_return['redirects'][key])
    @data(
        "sed 's/24/25/g",
        "sed 's/24/ > /g' &>/dev/null"
    )
    def test_build_command_raises_error_if_command_wont_parse(self, command):
        configuration = namedtuple('Config', 'name command input_directory output_directory wait_for')
        config = configuration(
            name='Test command',
            command=command,
            input_directory='/tmp',
            output_directory='/tmp',
            wait_for=None
        )
        with self.assertRaises(ValueError):
            threadable = ThreadableCommand(self._thread_manager, config)

    """
    def test_build_command_assigns_observer_to_threadable(self):
        configuration = namedtuple('Config', 'name command input_directory output_directory wait_for')
        config_observing = configuration(
            name='Observing',
            command="sed 's/24/25/g'",
            input_directory='/tmp',
            output_directory='/tmp',
            wait_for=None
        )
        observing = ThreadableCommand(self._thread_manager, config_observing)

        config_observer = configuration(
            name='Observer',
            command="grep -rin --col 'bobjones'",
            input_directory='/tmp',
            output_directory='/tmp',
            wait_for=observing
        )
        observer = ThreadableCommand(self._thread_manager, config_observer)

        self.assertTrue(observing.hasobservers)
        self.assertEquals(1, len(observing.observers))
    """

    def test_run_method_forms_a_pipe_and_reads_output(self):
        configuration = namedtuple('Config', 'name command input_directory output_directory wait_for')
        config = configuration(
            name='GrepForTestsAndReplaceWithBuild',
            command="grep -rin --col 'def test_*' tests | sed 's/test/build/g'",
            input_directory=os.getcwd(),
            output_directory='/tmp',
            wait_for=None
        )
        thread = ThreadableCommand(self._thread_manager, config)
        self._thread_manager.append(thread)
        self._thread_manager.execute()
        self.assertGreater(len(thread.results), 0)

    def test_run_with_redirect(self):
        configuration = namedtuple('Config', 'name command input_directory output_directory wait_for')
        config = configuration(
            name='GrepForTestsAndReplaceWithBuild',
            command="grep 2>&1",
            input_directory=os.getcwd(),
            output_directory='/tmp',
            wait_for=None
        )
        thread = ThreadableCommand(self._thread_manager, config)
        self._thread_manager.append(thread)
        self._thread_manager.execute()
        self.assertGreater(len(thread.results), 0)

    def test_run_raises_error_on_stderr(self):
        configuration = namedtuple('Config', 'name command input_directory output_directory wait_for')
        config = configuration(
            name='GrepForTestsAndReplaceWithBuild',
            command="grep",
            input_directory=os.getcwd(),
            output_directory='/tmp',
            wait_for=None
        )
        thread = ThreadableCommand(self._thread_manager, config)
        self._thread_manager.append(thread)
        with self.assertRaises(ThreadFailedError):
            self._thread_manager.execute()

    @patch('builtins.open', create=True)
    @data(
        "grep -rin --col 'def test_*' tests | sed 's/test/build/g' 1>/tmp/test",
        "grep -rin --col 'def test_*' tests | sed 's/test/build/g' &>/tmp/test",
        "grep -rin --col 'def test_*' tests | sed 's/test/build/g' 2>/tmp/test",
        "grep -rin --col 'def test_*' tests | sed 's/test/build/g' 2>/tmp/test 1>&2"
    )
    def test_run_with_redirect_to_file(self, command, mock_open):
        mock_open.return_value = None
        configuration = namedtuple('Config', 'name command input_directory output_directory wait_for')
        config = configuration(
            name='GrepForTestsAndReplaceWithBuild',
            command=command,
            input_directory=os.getcwd(),
            output_directory='/tmp',
            wait_for=None
        )
        Configuration._instance = None
        thread = ThreadableCommand(self._thread_manager, config)
        self._thread_manager.append(thread)
        self._thread_manager.execute()
        if (len(thread._commands[1].redirects) == 2):
            self.assertEquals(thread._commands[1].stdout, thread._commands[1].stderr)
        self.assertGreater(mock_open.call_count, 0)
        mock_open.assert_called_with('/tmp/test', mode='a')
Exemple #15
0
class TestSection(TestCase):

    _thread_manager = None

    @patch('argparse.ArgumentParser.parse_args')
    @patch('pyccata.core.log.Logger.log')
    @patch('pyccata.core.configuration.Configuration._get_locations')
    def setUp(self, mock_config, mock_log, mock_parser):
        path = os.path.dirname(os.path.realpath(__file__ + '../../../../'))
        self._path = os.path.join(path, os.path.join('tests', 'conf'))
        mock_config.return_value = [self._path]
        mock_log.return_value = None
        mock_parser.return_value = []
        Logger._instance = mock_log
        Configuration('config_sections.json')
        self._thread_manager = ThreadManager()

    def tearDown(self):
        if Configuration._instance is not None:
            Configuration._instance = None
        Configuration.NAMESPACE = 'pyccata.core'

        if DocumentPartFactory._instance is not None:
            DocumentPartFactory._instance = None
        if ThreadManager._instance is not None:
            ThreadManager._instance = None

    def test_init_raises_argument_mismatch_error_if_keyword_args_differ(self):
        Config = namedtuple('Config', 'title, abstract config')
        config = Config(title='hello world',
                        abstract='This is a test paragraph',
                        config=['bob', 'marley', 'jimmy', 'hendrix'])

        with self.assertRaisesRegexp(
                ArgumentMismatchError,
                'Invalid arguments provided to .*\. Got .* expected .*'):
            Section(self._thread_manager, config)

    @patch('pyccata.core.parts.section.Section._parse_structure')
    def test_threadable_init_calls_section_setup(self, mock_parse):
        mock_parse.return_value = []
        Config = namedtuple('Config', 'title, abstract level structure')
        config = Config(title='hello world',
                        abstract='This is a test paragraph',
                        level=0,
                        structure=None)
        section = Section(self._thread_manager, config)
        self.assertEquals('hello world', section._title)
        self.assertEquals('This is a test paragraph',
                          section._abstract._content[0])

    def test_parse_structure_returns_empty_list_if_structure_is_none(self):
        Config = namedtuple('Config', 'title, abstract level structure')
        config = Config(title='hello world',
                        abstract='This is a test paragraph',
                        level=0,
                        structure=None)
        section = Section(self._thread_manager, config)
        self.assertIsInstance(section._structure, list)
        self.assertEquals(0, len(section._structure))

    def test_threadable_document_init_resets_priority_if_greater_than_max(
            self):
        Paragraph = namedtuple('Paragraph', 'text')
        Config = namedtuple('Config', 'title, abstract level structure')
        config = Config(title='hello world',
                        abstract='This is a test paragraph',
                        level=0,
                        structure=None)
        section = Section(self._thread_manager, config)
        self.assertIsInstance(section._structure, list)
        self.assertEquals(0, len(section._structure))
        section._structure.append(
            InvalidPriority(self._thread_manager,
                            Paragraph(text='hello world')))
        self.assertEquals(
            ThreadableDocument.MAX_DOCUMENT_PRIORITY,
            section._structure[len(section._structure) - 1].PRIORITY)

    def test_parse_structure_returns_list_of_paragraphs(self):
        config = DataProviders.get_paragraph_config_for_section()
        section = Section(self._thread_manager, config)
        self.assertEquals(4, len(section._structure))
        for item in section._structure:
            self.assertIsInstance(item, Paragraph)

    def test_section_abstract_reads_abstract_from_file(self):
        Configuration._instance = DataProviders._get_config_for_test()
        Config = namedtuple('Config', 'title, abstract level structure')
        config = Config(title='hello world',
                        abstract='section_test_text',
                        level=0,
                        structure=None)
        section = Section(self._thread_manager, config)
        self.assertEquals('hello world', section._title)
        self.assertEquals(3, len(section._abstract._content))

    @patch('pyccata.core.managers.report.ReportManager.add_paragraph')
    def test_section_render(self, mock_paragraph):
        Config = namedtuple('Config', 'title, abstract level structure')
        config = Config(title='hello world',
                        abstract='section_test_text',
                        level=0,
                        structure=None)
        section = Section(self._thread_manager, config)
        section.render(ReportManager())

    @patch('pyccata.core.managers.report.ReportManager.add_paragraph')
    def test_render_calls_report_manager_add_methods(self, mock_paragraph):
        Configuration.report_text = 'tests/pyccata.core/data'
        config = DataProviders.get_paragraph_config_for_section()
        section = Section(self._thread_manager, config)
        self.assertEquals(4, len(section._structure))
        for item in section._structure:
            self.assertIsInstance(item, Paragraph)
        section.render(ReportManager())
        calls = [
            call('This is paragraph number 1'),
            call('This is paragraph number 3'),
            call('This is paragraph number 4'),
            call('This is paragraph number 5')
        ]
        mock_paragraph.assert_has_calls(calls)

    @patch('pyccata.core.managers.clients.jira.Jira._client')
    @patch('pyccata.core.configuration.Configuration._load')
    def test_render_returns_if_section_contains_empty_table(
            self, mock_load, mock_jira_client):
        Rows = namedtuple('Row', 'query fields')

        row_config = Rows(query="project=bob and issuetype=Bug",
                          fields=["key", "description", "priority"])
        #rows = Filter(row_config.query, fields=row_config.fields)
        #self._thread_manager.append(rows)
        columns = ['Name', 'Description']

        TableConfig = namedtuple('TableConfig', 'rows columns style')
        table_config = TableConfig(rows=row_config,
                                   columns=columns,
                                   style='Light heading 1')

        StructureConfig = namedtuple('StructureConfig', 'type title content')
        structure_config = StructureConfig(type='table',
                                           title='Hello world',
                                           content=table_config)

        SectionConfig = namedtuple('SectionConfig',
                                   'title abstract level structure')
        section_config = SectionConfig(
            title='Test',
            abstract='This is a test for empty tables',
            level=1,
            structure=[structure_config])

        mock_jira_client.return_value = None
        with patch('pyccata.core.configuration.Configuration.manager',
                   new_callable=PropertyMock) as mock_manager:
            with patch(
                    'pyccata.core.configuration.Configuration._configuration',
                    new_callable=PropertyMock) as mock_config:
                mock_config.return_value = DataProviders._get_config_for_test()
                mock_manager.return_value = 'jira'
                section = Section(self._thread_manager, section_config)
                rows = section._structure[0].rows
                rows._thread_manager = self._thread_manager
                rows._project_manager = ProjectManager()
                rows.projectmanager._client._client = DataProviders._get_client_without_results(
                )

                document = ReportManager()
                self._thread_manager.execute()
                section.render(document)

                self.assertEquals(0, rows.results.total)
Exemple #16
0
class TestAttachments(TestCase):

    _report_manager = None
    _thread_manager = None

    @patch('pyccata.core.log.Logger.log')
    @patch('argparse.ArgumentParser.parse_args')
    @patch('pyccata.core.configuration.Configuration._get_locations')
    def setUp(self, mock_config, mock_parser, mock_log):
        self.tearDown()
        mock_log.return_value = None
        Logger._instance = mock_log
        path = os.path.dirname(os.path.realpath(__file__ + '../../../../'))
        self._path = os.path.join(path, os.path.join('tests', 'conf'))
        mock_config.return_value = [self._path]
        mock_parser.return_value = []
        config = None

        with patch('argparse.ArgumentParser.add_argument'):
            config = Configuration(filename='valid_config.json')
        config.check = True
        self._report_manager = ReportManager()
        self._thread_manager = ThreadManager()

    def tearDown(self):
        if ThreadManager._instance is not None:
            ThreadManager._instance = None
        if Configuration._instance is not None:
            del Configuration._instance
            Configuration._instance = None
        Configuration.NAMESPACE = 'pyccata.core'

        if Replacements._instance is not None:
            del Replacements._instance
            Replacements._instance = None

    @data(
        ('zip', 1, '/tmp/28/Jul/2016/AnotherTestApplication.zip'),
        ('sql', 1, '/tmp/28/Jul/2016/TestApplication.sql'),
        ('zip,sql', 2, ['/tmp/28/Jul/2016/AnotherTestApplication.zip', '/tmp/28/Jul/2016/TestApplication.sql'])
    )
    @patch('builtins.open', create=True)
    @patch('jira.client.JIRA.__init__')
    @patch('jira.client.JIRA.search_issues')
    @patch('pyccata.core.configuration.Configuration._get_locations')
    @unpack
    def test_setup_and_run(
        self,
        collation,
        result_count,
        result_filename,
        mock_config_list,
        mock_results,
        mock_jira_client,
        mock_open
    ):
        mock_jira_client.return_value = None
        mock_config_list.return_value = [self._path]
        Configuration.NAMESPACE = 'pyccata.core'
        report = ReportManager()
        mock_results.return_value = DataProviders._test_data_for_attachments()

        report.add_callback('attachments', getattr(DataProviders, 'test_callback'))
        self.assertIsInstance(Configuration().replacements, Replacements)

        Config = namedtuple('Config', 'query fields collate output_path')
        config = Config(
            query='project=test and attachments is not empty',
            fields=[
                'key',
                'attachments'
            ],
            collate=collation,
            output_path='/tmp/{FIX_VERSION}'
        )
        Replacements().find('FIX_VERSION').value = '28/Jul/2016'

        attachments = None
        with patch('os.makedirs') as mock_os:
            attachments = Attachments(self._thread_manager, config)
            mock_os.assert_called_with('/tmp/28/Jul/2016')

        self._thread_manager.append(attachments)

        with patch('pycurl.Curl') as mock_curl:
            with patch('pycurl.Curl.setopt') as mock_setopt:
                with patch('pycurl.Curl.perform') as mock_perform:
                    with patch('pycurl.Curl.close') as mock_close:
                        Curl = namedtuple('Curl', 'URL WRITEDATA setopt perform close getinfo')
                        mock_curl.return_value = Curl(
                            URL=None,
                            WRITEDATA=None,
                            setopt=mock_setopt,
                            perform=mock_perform,
                            close=mock_close,
                            getinfo=lambda x: 200
                        )
                        self._thread_manager.execute()

                        self.assertEquals(result_count, len(attachments._content))
                        self.assertEquals((3 * result_count), mock_setopt.call_count)
                        self.assertEquals((1 * result_count), mock_perform.call_count)
                        self.assertEquals((1 * result_count), mock_close.call_count)
                        self.assertEquals((1 * result_count), mock_open.call_count)
                        calls = []
                        if isinstance(result_filename, list):
                            for filename in result_filename:
                                calls.append(call(filename, 'wb'))
                        else:
                            calls.append(call(result_filename, 'wb'))
                        mock_open.assert_has_calls(calls, any_order=True)

        with patch('pyccata.core.managers.report.ReportManager.add_paragraph') as mock_paragraph:
            with patch('pyccata.core.managers.report.ReportManager.add_list') as mock_list:
                attachments.render(report)
                mock_paragraph.assert_called_with('The following file(s) have been attached to this document:')
                mock_list.assert_called_with('TestFile.zip')

    @data(
        ('zip', 1, '/tmp/28/Jul/2016/AnotherTestApplication.zip'),
        ('sql', 1, '/tmp/28/Jul/2016/TestApplication.sql'),
        ('zip,sql', 2, ['/tmp/28/Jul/2016/AnotherTestApplication.zip', '/tmp/28/Jul/2016/TestApplication.sql'])
    )
    @patch('builtins.open', create=True)
    @patch('jira.client.JIRA.__init__')
    @patch('jira.client.JIRA.search_issues')
    @patch('pyccata.core.configuration.Configuration._get_locations')
    @unpack
    def test_setup_and_run_without_callback(
        self,
        collation,
        result_count,
        result_filename,
        mock_config_list,
        mock_results,
        mock_jira_client,
        mock_open
    ):
        mock_jira_client.return_value = None
        mock_config_list.return_value = [self._path]
        Configuration.NAMESPACE = 'pyccata.core'
        report = ReportManager()
        report.add_callback('attachments', None)
        mock_results.return_value = DataProviders._test_data_for_attachments()

        self.assertIsInstance(Configuration().replacements, Replacements)

        Config = namedtuple('Config', 'query fields collate output_path')
        config = Config(
            query='project=test and attachments is not empty',
            fields=[
                'key',
                'attachments'
            ],
            collate=collation,
            output_path='/tmp/{FIX_VERSION}'
        )
        Replacements().find('FIX_VERSION').value = '28/Jul/2016'

        attachments = None
        with patch('os.makedirs') as mock_os:
            attachments = Attachments(self._thread_manager, config)
            mock_os.assert_called_with('/tmp/28/Jul/2016')

        self._thread_manager.append(attachments)

        with patch('pycurl.Curl') as mock_curl:
            with patch('pycurl.Curl.setopt') as mock_setopt:
                with patch('pycurl.Curl.perform') as mock_perform:
                    with patch('pycurl.Curl.close') as mock_close:
                        Curl = namedtuple('Curl', 'URL WRITEDATA setopt perform close getinfo')
                        mock_curl.return_value = Curl(
                            URL=None,
                            WRITEDATA=None,
                            setopt=mock_setopt,
                            perform=mock_perform,
                            close=mock_close,
                            getinfo=lambda x: 200
                        )
                        self._thread_manager.execute()

                        self.assertEquals(result_count, len(attachments._content))
                        self.assertEquals((3 * result_count), mock_setopt.call_count)
                        self.assertEquals((1 * result_count), mock_perform.call_count)
                        self.assertEquals((1 * result_count), mock_close.call_count)
                        self.assertEquals((1 * result_count), mock_open.call_count)
                        calls = []
                        if isinstance(result_filename, list):
                            for filename in result_filename:
                                calls.append(call(filename, 'wb'))
                        else:
                            calls.append(call(result_filename, 'wb'))
                        mock_open.assert_has_calls(calls, any_order=True)

        with patch('pyccata.core.managers.report.ReportManager.add_paragraph') as mock_paragraph:
            with patch('pyccata.core.managers.report.ReportManager.add_list') as mock_list:
                attachments.render(report)
                mock_paragraph.assert_not_called()
                mock_list.assert_not_called()

    @data(
        ('zip', 1, '/tmp/28/Jul/2016/AnotherTestApplication.zip'),
        ('sql', 1, '/tmp/28/Jul/2016/TestApplication.sql'),
        ('zip,sql', 2, ['/tmp/28/Jul/2016/AnotherTestApplication.zip', '/tmp/28/Jul/2016/TestApplication.sql'])
    )
    @patch('builtins.open', create=True)
    @patch('jira.client.JIRA.__init__')
    @patch('jira.client.JIRA.search_issues')
    @patch('pyccata.core.configuration.Configuration._get_locations')
    @unpack
    def test_setup_and_run_where_callback_returns_string(
        self,
        collation,
        result_count,
        result_filename,
        mock_config_list,
        mock_results,
        mock_jira_client,
        mock_open
    ):
        mock_jira_client.return_value = None
        mock_config_list.return_value = [self._path]
        Configuration.NAMESPACE = 'pyccata.core'
        report = ReportManager()
        mock_results.return_value = DataProviders._test_data_for_attachments()

        report.add_callback('attachments', lambda x,y: 'TestFile.zip')
        self.assertIsInstance(Configuration().replacements, Replacements)

        Config = namedtuple('Config', 'query fields collate output_path')
        config = Config(
            query='project=test and attachments is not empty',
            fields=[
                'key',
                'attachments'
            ],
            collate=collation,
            output_path='/tmp/{FIX_VERSION}'
        )
        Replacements().find('FIX_VERSION').value = '28/Jul/2016'

        attachments = None
        with patch('os.makedirs') as mock_os:
            attachments = Attachments(self._thread_manager, config)
            mock_os.assert_called_with('/tmp/28/Jul/2016')

        self._thread_manager.append(attachments)

        with patch('pycurl.Curl') as mock_curl:
            with patch('pycurl.Curl.setopt') as mock_setopt:
                with patch('pycurl.Curl.perform') as mock_perform:
                    with patch('pycurl.Curl.close') as mock_close:
                        Curl = namedtuple('Curl', 'URL WRITEDATA setopt perform close getinfo')
                        mock_curl.return_value = Curl(
                            URL=None,
                            WRITEDATA=None,
                            setopt=mock_setopt,
                            perform=mock_perform,
                            close=mock_close,
                            getinfo=lambda x: 200
                        )
                        self._thread_manager.execute()

                        self.assertEquals(result_count, len(attachments._content))
                        self.assertEquals((3 * result_count), mock_setopt.call_count)
                        self.assertEquals((1 * result_count), mock_perform.call_count)
                        self.assertEquals((1 * result_count), mock_close.call_count)
                        self.assertEquals((1 * result_count), mock_open.call_count)
                        calls = []
                        if isinstance(result_filename, list):
                            for filename in result_filename:
                                calls.append(call(filename, 'wb'))
                        else:
                            calls.append(call(result_filename, 'wb'))
                        mock_open.assert_has_calls(calls, any_order=True)

        with patch('pyccata.core.managers.report.ReportManager.add_paragraph') as mock_paragraph:
            with patch('pyccata.core.managers.report.ReportManager.add_list') as mock_list:
                attachments.render(report)
                mock_paragraph.assert_called_with('The following file(s) have been attached to this document:')
                mock_list.assert_called_with('TestFile.zip')

    @data(
        ('zip,sql', 2, [])
    )
    @patch('builtins.open', create=True)
    @patch('jira.client.JIRA.__init__')
    @patch('jira.client.JIRA.search_issues')
    @patch('pyccata.core.configuration.Configuration._get_locations')
    @unpack
    def test_setup_and_run_doesnt_download_if_attachments_is_empty(
        self,
        collation,
        result_count,
        result_filename,
        mock_config_list,
        mock_results,
        mock_jira_client,
        mock_open
    ):
        mock_jira_client.return_value = None
        mock_config_list.return_value = [self._path]
        Configuration.NAMESPACE = 'pyccata.core'
        report = ReportManager()
        mock_results.return_value = []

        report.add_callback('attachments', lambda x,y: '')
        self.assertIsInstance(Configuration().replacements, Replacements)

        Config = namedtuple('Config', 'query fields collate output_path')
        config = Config(
            query='project=test and attachments is not empty',
            fields=[
                'key',
                'attachments'
            ],
            collate=collation,
            output_path='/tmp/{FIX_VERSION}'
        )
        Replacements().find('FIX_VERSION').value = '28/Jul/2016'

        attachments = None
        with patch('os.makedirs') as mock_os:
            attachments = Attachments(self._thread_manager, config)
            mock_os.assert_called_with('/tmp/28/Jul/2016')

        with patch('pyccata.core.parts.attachments.Attachments._download_attachments') as mock_download:
            self._thread_manager.execute()
            mock_download.assert_not_called()

    @patch('pyccata.core.filter.Filter.failure', new_callable=PropertyMock)
    @patch('argparse.ArgumentParser.parse_args')
    @patch('pyccata.core.configuration.Configuration._get_locations')
    def test_setup_and_run_handles_exception(self, mock_config_list, mock_parser, mock_failure):
        mock_parser.return_value = []
        mock_config_list.return_value = [self._path]
        Configuration.NAMESPACE = 'pyccata.core'
        report = ReportManager()
        # never actually thrown from the filter but useful for testing and coverage ;-)
        mock_failure.return_value = InvalidFilenameError('The specified file does not exist')

        report.add_callback('test', 'test_callback')
        self.assertEquals('test_callback', report.get_callback('test'))
        self.assertIsInstance(Configuration().replacements, Replacements)

        Config = namedtuple('Config', 'query fields collate output_path')
        config = Config(
            query='project=test and attachments is not empty',
            fields=[
                'key',
                'attachments'
            ],
            collate='zip',
            output_path='/tmp/{FIX_VERSION}'
        )
        Replacements().find('FIX_VERSION').value = '28/Jul/2016'

        attachments = None
        with patch('os.makedirs') as mock_os:
            attachments = Attachments(self._thread_manager, config)
            mock_os.assert_called_with('/tmp/28/Jul/2016')

        with patch('pyccata.core.filter.Filter.failed', return_value=True):
            attachments.run()
            self.assertEquals(str(attachments._content.failure), 'The specified file does not exist')

    @patch('builtins.open', create=True)
    @patch('jira.client.JIRA.__init__')
    @patch('jira.client.JIRA.search_issues')
    @patch('pyccata.core.managers.clients.jira.Jira.server', new_callable=PropertyMock)
    @patch('pyccata.core.configuration.Configuration._get_locations')
    @unpack
    def test_run_raises_type_error_if_attachments_callback_function_is_not_set(
        self,
        mock_config_list,
        mock_results,
        mock_jira_results,
        mock_jira_client,
        mock_open
    ):
        mock_jira_client.return_value = None
        mock_config_list.return_value = [self._path]
        Configuration.NAMESPACE = 'pyccata.core'
        report = ReportManager()
        report.add_callback('attachments', None)
        mock_jira_results.return_value = DataProviders._test_data_for_attachments()
        server = namedtuple('Server', 'server_address attachments')
        mock_results.return_value = server(server_address=None, attachments=None)

        self.assertIsInstance(Configuration().replacements, Replacements)

        Config = namedtuple('Config', 'query fields collate output_path')
        config = Config(
            query='project=test and attachments is not empty',
            fields=[
                'key',
                'attachments'
            ],
            collate='zip',
            output_path='/tmp/{FIX_VERSION}'
        )

        attachments = None
        with patch('os.path.exists') as mock_exists:
            mock_exists.return_value = False
            with patch('os.makedirs') as mock_os:
                attachments = Attachments(self._thread_manager, config)
                mock_os.assert_called_with('/tmp/' + Configuration().replacements.replace('{FIX_VERSION}'))

        self._thread_manager.append(attachments)

        with patch('pycurl.Curl') as mock_curl:
            with patch('pycurl.Curl.setopt') as mock_setopt:
                with patch('pycurl.Curl.perform') as mock_perform:
                    with patch('pycurl.Curl.close') as mock_close:
                        Curl = namedtuple('Curl', 'URL WRITEDATA setopt perform close getinfo')
                        mock_curl.return_value = Curl(
                            URL=None,
                            WRITEDATA=None,
                            setopt=mock_setopt,
                            perform=mock_perform,
                            close=mock_close,
                            getinfo=lambda x: 200
                        )
                        with self.assertRaises(InvalidCallbackError):
                            self._thread_manager.execute()
                        self.assertIsInstance(attachments.failure, InvalidCallbackError)
                        mock_setopt.assert_not_called()
                        mock_perform.assert_not_called()
                        mock_close.assert_not_called()
                        mock_open.assert_not_called()