예제 #1
0
 def test_build_query_bug_list(self):
     ba = BugzillaAgent(self.logger, self.conf)
     options = {
         'product': 'Ant',
         'offset': 12,
         'limit': 10,
         'order': 'creation_time%20ASC'
     }
     self.assertEqual(
         'https://bz.apache.org/bugzilla/rest.cgi/bug?limit=10&offset=12&order=creation_time%20ASC&product=Ant',
         ba._build_query('bug', options))
예제 #2
0
    def test_build_query_bug_list_with_last_change_time(self):
        ba = BugzillaAgent(self.logger, self.conf)
        options = {
            'product': 'Ant',
            'offset': 12,
            'limit': 10,
            'order': 'creation_time%20ASC',
            'last_change_time': datetime.datetime(2012, 10, 1, 10, 5, 10)
        }

        self.assertEqual(
            'https://bz.apache.org/bugzilla/rest.cgi/bug?last_change_time=2012-10-01+10%3A05%3A10&limit=10'
            '&offset=12&order=creation_time%20ASC&product=Ant',
            ba._build_query('bug', options))
예제 #3
0
    def test_process_comments(self, get_user_mock):
        bugzilla_backend = BugzillaBackend(self.conf, self.issues_system_id,
                                           self.project_id)
        bugzilla_backend.bugzilla_agent = BugzillaAgent(None, self.conf)
        issue = Issue(external_id="TEST",
                      issue_system_id=self.issues_system_id).save()

        get_user_mock.side_effect = [self.dev_tomcat_file, self.conor_user]

        bugzilla_backend._process_comments(issue.id, self.issue_95_comments)

        all_comments = IssueComment.objects(issue_id=issue.id).all()
        self.assertEqual(2, len(all_comments))

        # comment 1
        commenter = People.objects(email="*****@*****.**").get()
        comment = all_comments[0]
        self.assertEqual(comment.created_at,
                         datetime.datetime(2001, 2, 4, 6, 20, 32))
        self.assertEqual(comment.author_id, commenter.id)
        self.assertEqual(
            comment.comment,
            "I have tested this on NT (JDK 1.1, 1.2.2, 1.3) and Linux "
            "(Redhat 6.2, JDK \n1.1.2) and could not reproduce this problem. ")

        # comment 2
        commenter = People.objects(email="*****@*****.**").get()
        comment = all_comments[1]
        self.assertEqual(comment.created_at,
                         datetime.datetime(2001, 2, 6, 19, 35, 1))
        self.assertEqual(comment.author_id, commenter.id)
        self.assertEqual(
            comment.comment,
            "For query purposes, mark as fixed for Tomcat 3.3:\nFixed in Tomcat 3.3\n"
        )
예제 #4
0
    def process(self):
        """
        Gets all the issues and their updates

        1. Gets the last stored issues updated_at field

        2. Gets all issues that was last change since this value

        3. Processes the results in 50-steps

        4. For each issue calls: :func:`issueshark.backends.bugzilla.BugzillaBackend._process_issue`
        """
        self.bugzilla_agent = BugzillaAgent(logger, self.config)
        # Get last modification date (since then, we will collect bugs)
        last_issue = Issue.objects(issue_system_id=self.issue_system_id).order_by('-updated_at') \
            .only('updated_at').first()
        starting_date = None
        if last_issue is not None:
            starting_date = last_issue.updated_at

        # Get all issues
        issues = self.bugzilla_agent.get_bug_list(
            last_change_time=starting_date, limit=50)

        # If no new bugs found, return
        if len(issues) == 0:
            logger.info('No new issues found. Exiting...')
            sys.exit(0)

        # Otherwise, go through all issues
        processed_results = 50
        while len(issues) > 0:
            logger.info("Processing %d issues..." % len(issues))
            for issue in issues:
                logger.info("Processing issue %s" % issue['id'])
                self._process_issue(issue)

            # Go through the next issues
            issues = self.bugzilla_agent.get_bug_list(
                last_change_time=starting_date,
                limit=50,
                offset=processed_results)
            processed_results += 50
예제 #5
0
 def test_initialization_fails(self):
     conf = ConfigMock(
         None, None, None, None, None, None, 'Ant',
         'https://bz.apache.org/bugzilla/rest.cgi/bug?product=Ant',
         'github', None, None, None, None, 'user', None, 'DEBUG', None)
     with self.assertRaises(BugzillaApiException) as cm:
         ba = BugzillaAgent(self.logger, conf)
         self.assertEqual(
             'If a username is given, a password needs to be given too!',
             cm.msg)
예제 #6
0
    def test_process_comments_two_times(self, get_user_mock):
        bugzilla_backend = BugzillaBackend(self.conf, self.issues_system_id,
                                           self.project_id)
        bugzilla_backend.bugzilla_agent = BugzillaAgent(None, self.conf)
        issue = Issue(external_id="TEST",
                      issue_system_id=self.issues_system_id).save()

        get_user_mock.side_effect = [self.dev_tomcat_file, self.conor_user]

        bugzilla_backend._process_comments(issue.id, self.issue_95_comments)
        bugzilla_backend._process_comments(issue.id, self.issue_95_comments)

        self.assertEqual(2, len(IssueComment.objects.all()))
예제 #7
0
    def test_store_events_two_times(self, get_user_mock):
        bugzilla_backend = BugzillaBackend(self.conf, self.issues_system_id,
                                           self.project_id)
        bugzilla_backend.bugzilla_agent = BugzillaAgent(None, self.conf)
        issue = Issue(external_id="TEST",
                      issue_system_id=self.issues_system_id).save()

        get_user_mock.side_effect = [
            self.craig_user, self.conor_user, self.craig_user, self.conor_user,
            self.conor_user
        ]
        bugzilla_backend._store_events(self.issue_95_history, self.issue_95,
                                       issue)
        bugzilla_backend._store_events(self.issue_95_history, self.issue_95,
                                       issue)

        all_events = Event.objects.all()

        self.assertEqual(16, len(all_events))
예제 #8
0
class BugzillaBackend(BaseBackend):
    """
    Backend that collects data from a Bugzilla REST API
    """
    @property
    def identifier(self):
        """
        Identifier (bugzilla)
        """
        return 'bugzilla'

    def __init__(self, cfg, issue_system_id, project_id):
        """
        Initialization
        Initializes the people dictionary see: :func:`~issueshark.backends.bugzilla.BugzillaBackend._get_people`
        Initializes the attribute mapping: Maps attributes from the bugzilla API to our database design


        :param cfg: holds als configuration. Object of class :class:`~issueshark.config.Config`
        :param issue_system_id: id of the issue system for which data should be collected. :class:`bson.objectid.ObjectId`
        :param project_id: id of the project to which the issue system belongs. :class:`bson.objectid.ObjectId`
        """
        super().__init__(cfg, issue_system_id, project_id)

        logger.setLevel(self.debug_level)
        self.bugzilla_agent = None
        self.people = {}

        self.at_mapping = {
            'assigned_to_detail': 'assignee_id',
            'blocks': 'issue_links',
            'component': 'components',
            'creation_time': 'created_at',
            'creator_detail': 'creator_id',
            'depends_on': 'issue_links',
            'dupe_of': 'issue_links',
            'keywords': 'labels',
            'last_change_time': 'updated_at',
            'op_sys': 'environment',
            'platform': 'platform',
            'resolution': 'resolution',
            'severity': 'priority',
            'status': 'status',
            'summary': 'title',
            'target_milestone': 'fix_versions',
            'version': 'affects_versions',
            'type': 'issue_type',
        }

    def process(self):
        """
        Gets all the issues and their updates

        1. Gets the last stored issues updated_at field

        2. Gets all issues that was last change since this value

        3. Processes the results in 50-steps

        4. For each issue calls: :func:`issueshark.backends.bugzilla.BugzillaBackend._process_issue`
        """
        self.bugzilla_agent = BugzillaAgent(logger, self.config)
        # Get last modification date (since then, we will collect bugs)
        last_issue = Issue.objects(issue_system_id=self.issue_system_id).order_by('-updated_at') \
            .only('updated_at').first()
        starting_date = None
        if last_issue is not None:
            starting_date = last_issue.updated_at

        # Get all issues
        issues = self.bugzilla_agent.get_bug_list(
            last_change_time=starting_date, limit=50)

        # If no new bugs found, return
        if len(issues) == 0:
            logger.info('No new issues found. Exiting...')
            sys.exit(0)

        # Otherwise, go through all issues
        processed_results = 50
        while len(issues) > 0:
            logger.info("Processing %d issues..." % len(issues))
            for issue in issues:
                logger.info("Processing issue %s" % issue['id'])
                self._process_issue(issue)

            # Go through the next issues
            issues = self.bugzilla_agent.get_bug_list(
                last_change_time=starting_date,
                limit=50,
                offset=processed_results)
            processed_results += 50

    def _process_issue(self, issue):
        """
        Processes the issue in several steps:

        1. Get all comments. See: :func:`issueshark.backends.helpers.bugzillaagent.BugzillaAgent.get_comments`

        2. Get the whole issue history.\
        See: :func:`issueshark.backends.helpers.bugzillaagent.BugzillaAgent.get_issue_history`

        3. Transforms the issue to our issue model. \
        See: :func:`issueshark.backends.bugzilla.BugzillaBackend._transform_issue`

        4. Go through the history of the issue (newest to oldes) and store the events. \
        See: :func:`issueshark.backends.bugzilla.BugzillaBackend._process_event`

        5. Process all comments. See: :func:`issueshark.backends.bugzilla.BugzillaBackend._process_comments`

        :param issue: issue that was got from the bugzilla REST API
        """
        # Transform issue
        comments = self.bugzilla_agent.get_comments(issue['id'])
        histories = self.bugzilla_agent.get_issue_history(issue['id'])
        mongo_issue = self._transform_issue(issue, comments)

        logger.debug('Transformed issue: %s', mongo_issue)

        self._store_events(histories, issue, mongo_issue)

        # Store comments
        self._process_comments(mongo_issue.id, comments)

    def _store_events(self, histories, issue, mongo_issue):
        # Store events
        j = 0
        events_to_insert = []
        for history in histories:
            i = 0
            change_date = dateutil.parser.parse(history['when'])
            author_id = self._get_people(history['who'])
            for bz_event in history['changes']:
                logger.debug("Processing event: %s" % bz_event)
                unique_event_id = str(
                    issue['id']) + "%%" + str(i) + "%%" + str(j)
                mongo_event, is_new_event = self._process_event(
                    unique_event_id, bz_event, mongo_issue, change_date,
                    author_id)
                logger.debug('Newly created?: %s, Resulting event: %s' %
                             (is_new_event, mongo_event))

                # Append to list if event is not stored in db
                if is_new_event:
                    events_to_insert.append(mongo_event)

                i += 1
            j += 1

        # Store events
        if events_to_insert:
            Event.objects.insert(events_to_insert, load_bulk=False)

    def _process_comments(self, mongo_issue_id, comments):
        """
        Processes the comments for an issue

        :param mongo_issue_id: Object of class :class:`bson.objectid.ObjectId`. Identifier of the document that holds \
        the issue information
        :param comments: comments that were received from the bugzilla API
        """
        # Go through all comments of the issue
        comments_to_insert = []
        logger.info('Processing %d comments...' % (len(comments) - 1))
        i = -1
        for comment in comments:
            # Comment with count 0 is the description of the bug
            if comment['count'] == 0:
                continue

            i += 1
            logger.debug('Processing comment: %s' % comment)
            unique_comment_id = "%s%%%s" % (mongo_issue_id, i)
            try:
                IssueComment.objects(external_id=unique_comment_id,
                                     issue_id=mongo_issue_id).get()
                continue
            except DoesNotExist:
                mongo_comment = IssueComment(
                    external_id=unique_comment_id,
                    issue_id=mongo_issue_id,
                    created_at=dateutil.parser.parse(comment['creation_time']),
                    author_id=self._get_people(comment['creator']),
                    comment=comment['text'],
                )
                logger.debug('Resulting comment: %s' % mongo_comment)
                comments_to_insert.append(mongo_comment)

        # If comments need to be inserted -> bulk insert
        if comments_to_insert:
            IssueComment.objects.insert(comments_to_insert, load_bulk=False)

    def _process_event(self, unique_event_id, bz_event, mongo_issue,
                       change_date, author_id):
        """
        Processes the event. During the event processing the Issue is set back to its original state
        before the event occured.

        :param unique_event_id: unique identifier of the event
        :param bz_event: event that was received from the bugzilla API
        :param mongo_issue: issue that is/should be stored in the mongodb
        :param change_date: date when the event was created
        :param author_id: :class:`bson.objectid.ObjectId` of the author of the event
        """
        try:
            mongo_event = Event.objects(external_id=unique_event_id,
                                        issue_id=mongo_issue.id).get()
            return mongo_event, False
        except DoesNotExist:
            mongo_event = Event(external_id=unique_event_id,
                                issue_id=mongo_issue.id,
                                created_at=change_date,
                                author_id=author_id)

        # We need to map back the status from the bz terminology to ours. Special: The assigned_to must be mapped to
        # assigned_to_detail beforehand, as we are using this for the issue parsing
        if bz_event['field_name'] == 'assigned_to':
            bz_at_name = 'assigned_to_detail'
        else:
            bz_at_name = bz_event['field_name']

        try:
            mongo_event.status = self.at_mapping[bz_at_name]
        except KeyError:
            logger.warning('Mapping for attribute %s not found.' % bz_at_name)
            mongo_event.status = bz_at_name

        if mongo_event.status == 'assignee_id':
            if bz_event['added'] is not None and bz_event['added']:
                people_id = self._get_people(bz_event['added'])
                mongo_event.new_value = people_id

            if bz_event['removed'] is not None and bz_event['removed']:
                people_id = self._get_people(bz_event['removed'])
                mongo_event.old_value = people_id
        elif bz_event['field_name'] == 'depends_on':
            if bz_event['added'] is not None and bz_event['added']:
                issue_id = self._get_issue_id_by_system_id(bz_event['added'])
                mongo_event.new_value = {
                    'issue_id': issue_id,
                    'type': 'Dependent',
                    'effect': 'depends on'
                }

            if bz_event['removed'] is not None and bz_event['removed']:
                issue_id = self._get_issue_id_by_system_id(bz_event['removed'])
                mongo_event.old_value = {
                    'issue_id': issue_id,
                    'type': 'Dependent',
                    'effect': 'depends on'
                }
        elif bz_event['field_name'] == 'blocks':
            if bz_event['added'] is not None and bz_event['added']:
                issue_id = self._get_issue_id_by_system_id(bz_event['added'])
                mongo_event.new_value = {
                    'issue_id': issue_id,
                    'type': 'Blocker',
                    'effect': 'blocks'
                }

            if bz_event['removed'] is not None and bz_event['removed']:
                issue_id = self._get_issue_id_by_system_id(bz_event['removed'])
                mongo_event.old_value = {
                    'issue_id': issue_id,
                    'type': 'Blocker',
                    'effect': 'blocks'
                }
        else:
            if bz_event['added'] is not None and bz_event['added']:
                mongo_event.new_value = bz_event['added']

            if bz_event['removed'] is not None and bz_event['removed']:
                mongo_event.old_value = bz_event['removed']

        return mongo_event, True

    def _parse_bz_field(self, bz_issue, at_name_bz):
        """
        Parses fields from the bugzilla issue

        :param bz_issue: bugzilla issue (returned by the API)
        :param at_name_bz: attribute name that should be parsed
        """
        field_mapping = {
            'assigned_to_detail': self._parse_author_details,
            'blocks': self._parse_issue_links,
            'component': self._parse_string_field,
            'creation_time': self._parse_date_field,
            'creator_detail': self._parse_author_details,
            'depends_on': self._parse_issue_links,
            'dupe_of': self._parse_issue_links,
            'keywords': self._parse_array_field,
            'last_change_time': self._parse_date_field,
            'op_sys': self._parse_string_field,
            'platform': self._parse_string_field,
            'resolution': self._parse_string_field,
            'severity': self._parse_string_field,
            'status': self._parse_string_field,
            'summary': self._parse_string_field,
            'target_milestone': self._parse_string_field,
            'version': self._parse_string_field,
            'type': self._parse_type_field,
        }

        correct_function = field_mapping.get(at_name_bz)
        return correct_function(bz_issue, at_name_bz)

    def _parse_author_details(self, bz_issue, at_name_bz):
        """
        Parses author details from the bugzilla issue

        :param bz_issue: bugzilla issue (returned by the API)
        :param at_name_bz: attribute name that should be parsed
        """
        if 'email' in bz_issue[at_name_bz]:
            return self._get_people(bz_issue[at_name_bz]['name'],
                                    bz_issue[at_name_bz]['email'],
                                    bz_issue[at_name_bz]['real_name'])
        else:
            return self._get_people(bz_issue[at_name_bz]['name'])

    def _parse_string_field(self, bz_issue, at_name_bz):
        """
        Parses string fields from the bugzilla issue

        :param bz_issue: bugzilla issue (returned by the API)
        :param at_name_bz: attribute name that should be parsed
        """
        return bz_issue[at_name_bz]

    def _parse_type_field(self, bz_issue, at_name_bz):
        """
        Parses type fields, provides fallback if type field is not available

        :param bz_issue: bugzilla issue (returned by the API)
        :param at_name_bz: attribute name that should be parsed
        """

        # Bugzilla does not have a separate field for the type. Therefore, we distinguish between bug an enhancement
        # based on the severity information
        if bz_issue['severity'] == 'enhancement':
            ret = 'Enhancement'
        else:
            ret = 'Bug'

        # in some versions of bugzilla a type is provided, we just try to make consistent
        if 'type' in bz_issue.keys():
            if bz_issue['type'].lower() == 'defect':
                ret = 'Bug'
            elif bz_issue['type'].lower() == 'enhancement':
                ret = 'Enhancement'
            else:
                ret = bz_issue['type']
        return ret

    def _parse_array_field(self, bz_issue, at_name_bz):
        """
        Parses array fields from the bugzilla issue

        :param bz_issue: bugzilla issue (returned by the API)
        :param at_name_bz: attribute name that should be parsed
        """
        return bz_issue[at_name_bz]

    def _parse_issue_links(self, bz_issue, at_name_bz):
        """
        Parses the issue links from the bugzilla issue

        :param bz_issue: bugzilla issue (returned by the API)
        :param at_name_bz: attribute name that should be parsed
        """
        type_mapping = {
            'blocks': 'Blocker',
            'dupe_of': 'Duplicate',
            'depends_on': 'Dependent',
        }

        effect_mapping = {
            'blocks': 'blocks',
            'dupe_of': 'duplicates',
            'depends_on': 'depends on'
        }

        issue_links = []
        if isinstance(bz_issue[at_name_bz], list):
            for link in bz_issue[at_name_bz]:
                issue_links.append({
                    'issue_id':
                    self._get_issue_id_by_system_id(link),
                    'type':
                    type_mapping[at_name_bz],
                    'effect':
                    effect_mapping[at_name_bz]
                })
        else:
            if bz_issue[at_name_bz] is not None:
                issue_links.append({
                    'issue_id':
                    self._get_issue_id_by_system_id(bz_issue[at_name_bz]),
                    'type':
                    type_mapping[at_name_bz],
                    'effect':
                    effect_mapping[at_name_bz]
                })

        return issue_links

    def _parse_date_field(self, bz_issue, at_name_bz):
        """
        Parses the date field from the bugzilla issue

        :param bz_issue: bugzilla issue (returned by the API)
        :param at_name_bz: attribute name that should be parsed
        """
        return dateutil.parser.parse(bz_issue[at_name_bz])

    def _transform_issue(self, bz_issue, bz_comments):
        """
        Transforms the issue from an bugzilla issue to our issue model

        :param bz_issue: bugzilla issue (returned by the API)
        :param bz_comments: comments to the bugzilla issue (as the first comment is the description of the issue)
        :return:
        """
        try:
            mongo_issue = Issue.objects(issue_system_id=self.issue_system_id,
                                        external_id=str(bz_issue['id'])).get()
        except DoesNotExist:
            mongo_issue = Issue(issue_system_id=self.issue_system_id,
                                external_id=str(bz_issue['id']))

        # Set fields that can be directly mapped
        for at_name_bz, at_name_mongo in self.at_mapping.items():
            if isinstance(getattr(mongo_issue, at_name_mongo), list):
                # Get the result and the current value and merge it together
                result = self._parse_bz_field(bz_issue, at_name_bz)
                current_value = getattr(mongo_issue, at_name_mongo, list())
                if not isinstance(result, list):
                    result = [result]

                # Extend
                current_value.extend(result)
                if len(current_value) > 0 and at_name_mongo == 'issue_links':
                    current_value = list(
                        {v['issue_id']: v
                         for v in current_value}.values())
                else:
                    current_value = list(set(current_value))

                # Set the attribute
                setattr(mongo_issue, at_name_mongo,
                        copy.deepcopy(current_value))
            else:
                setattr(mongo_issue, at_name_mongo,
                        self._parse_bz_field(bz_issue, at_name_bz))

        # The first comment is the description! Bugzilla does not have a separate description field. The comment
        # with the count == 0 is the description
        for comment in bz_comments:
            if comment['count'] == 0:
                mongo_issue.desc = comment['text']
                break

        # If we have a creator, its also the repoerter in bugzilla terminology
        if bz_issue['creator_detail'] is not None:
            mongo_issue.reporter_id = mongo_issue.creator_id

        # moved to its own function, can be deleted later
        # Bugzilla does not have a separate field for the type. Therefore, we distinguish between bug an enhancement
        # based on the severity information
        # if bz_issue['severity'] == 'enhancement':
        #     mongo_issue.issue_type = 'Enhancement'
        # else:
        #     mongo_issue.issue_type = 'Bug'

        return mongo_issue.save()

    def _get_mongo_attribute(self, field_name):
        """
        Maps the attirbutes of the bugzilla api to the attributes of the document stored in the mongodb

        :param field_name: field name that should be mapped
        """
        return self.at_mapping[field_name]

    def _get_people(self, username, email=None, name=None):
        """
        Gets people from the people collection

        :param username: username of the user
        :param email: email of the user
        :param name: name of the user
        """
        # Check if user was accessed before. This reduces the amount of API requests
        if username in self.people:
            return self.people[username]

        # If email and name are not set, make a request to get the user
        if email is None and name is None:
            user = self.bugzilla_agent.get_user(username)

            # If the user is not found, we must use the username name
            if user is None:
                email = None
                name = username
            else:
                email = user.get('email', None)
                name = user['real_name']

            # Check if email is none, this can happen as an email address may be excluded from the return value
            if email is None:
                # Check if the username is a valid email address, if yes use this
                if validate_email(username):
                    email = username
                else:
                    email = "*****@*****.**"

        # Replace the email address "anonymization"
        email = email.replace(' at ', '@').replace(' dot ', '.')
        people_id = People.objects(name=name, email=email).upsert_one(
            name=name, email=email, username=username).id
        self.people[username] = people_id
        return people_id

    def _get_issue_id_by_system_id(self, system_id):
        """
        Gets the issue by their id that was assigned by the bugzilla ITS

        :param system_id: id of the issue in the bugzilla ITS
        """
        try:
            issue_id = Issue.objects(
                issue_system_id=self.issue_system_id,
                external_id=str(system_id)).only('id').get().id
        except DoesNotExist:
            issue_id = Issue(issue_system_id=self.issue_system_id,
                             external_id=str(system_id)).save().id

        return issue_id
예제 #9
0
    def test_store_events(self, get_user_mock):
        bugzilla_backend = BugzillaBackend(self.conf, self.issues_system_id,
                                           self.project_id)
        bugzilla_backend.bugzilla_agent = BugzillaAgent(None, self.conf)
        issue = Issue(external_id="TEST",
                      issue_system_id=self.issues_system_id).save()

        get_user_mock.side_effect = [
            self.craig_user, self.conor_user, self.craig_user, self.conor_user,
            self.conor_user
        ]
        bugzilla_backend._store_events(self.issue_95_history, self.issue_95,
                                       issue)

        craig_user = People.objects(email="*****@*****.**").get()
        conor_user = People.objects(email="*****@*****.**").get()

        all_events = Event.objects.all()

        self.assertEqual(16, len(all_events))

        # assignee_id
        event = all_events[0]
        self.assertEqual(event.status, "assignee_id")
        self.assertEqual(event.old_value, craig_user.id)
        self.assertEqual(event.new_value, conor_user.id)
        self.assertEqual(event.created_at,
                         datetime.datetime(2001, 2, 3, 17, 48, 45))
        self.assertEqual(event.author_id, craig_user.id)

        # status
        event = all_events[1]
        self.assertEqual(event.status, "status")
        self.assertEqual(event.old_value, "NEW")
        self.assertEqual(event.new_value, "UNCONFIRMED")
        self.assertEqual(event.created_at,
                         datetime.datetime(2001, 2, 3, 17, 48, 45))
        self.assertEqual(event.author_id, craig_user.id)

        # component
        event = all_events[2]
        self.assertEqual(event.status, "components")
        self.assertEqual(event.old_value, "Other")
        self.assertEqual(event.new_value, "Core tasks")
        self.assertEqual(event.created_at,
                         datetime.datetime(2001, 2, 3, 17, 48, 45))
        self.assertEqual(event.author_id, craig_user.id)

        # labels
        event = all_events[3]
        self.assertEqual(event.status, "labels")
        self.assertEqual(event.old_value, "85")
        self.assertEqual(event.new_value, None)
        self.assertEqual(event.created_at,
                         datetime.datetime(2001, 2, 3, 17, 48, 45))
        self.assertEqual(event.author_id, craig_user.id)

        # labels
        event = all_events[4]
        self.assertEqual(event.status, "labels")
        self.assertEqual(event.old_value, None)
        self.assertEqual(event.new_value, "PatchAvailable")
        self.assertEqual(event.created_at,
                         datetime.datetime(2001, 2, 3, 17, 48, 45))
        self.assertEqual(event.author_id, craig_user.id)

        # environment
        event = all_events[5]
        self.assertEqual(event.status, "environment")
        self.assertEqual(event.old_value, "Windows")
        self.assertEqual(event.new_value, "All")
        self.assertEqual(event.created_at,
                         datetime.datetime(2001, 2, 3, 17, 48, 45))
        self.assertEqual(event.author_id, craig_user.id)

        # platform
        event = all_events[6]
        self.assertEqual(event.status, "platform")
        self.assertEqual(event.old_value, "OSX")
        self.assertEqual(event.new_value, "All")
        self.assertEqual(event.created_at,
                         datetime.datetime(2001, 2, 3, 17, 48, 45))
        self.assertEqual(event.author_id, craig_user.id)

        # affects versions
        event = all_events[7]
        self.assertEqual(event.status, "affects_versions")
        self.assertEqual(event.old_value, "3.1")
        self.assertEqual(event.new_value, "1.2")
        self.assertEqual(event.created_at,
                         datetime.datetime(2001, 2, 3, 17, 48, 45))
        self.assertEqual(event.author_id, craig_user.id)

        # resolution
        event = all_events[8]
        self.assertEqual(event.status, "resolution")
        self.assertEqual(event.old_value, "NOTHING")
        self.assertEqual(event.new_value, "WORKSFORME")
        self.assertEqual(event.created_at,
                         datetime.datetime(2001, 2, 3, 17, 48, 45))
        self.assertEqual(event.author_id, craig_user.id)

        # depends_on / issue_links
        related_issue_41817 = Issue.objects(external_id="41817").get()

        event = all_events[9]
        self.assertEqual(event.status, "issue_links")
        self.assertEqual(event.old_value, None)
        self.assertEqual(
            event.new_value, {
                'issue_id': related_issue_41817.id,
                'type': 'Dependent',
                'effect': 'depends on'
            })
        self.assertEqual(event.created_at,
                         datetime.datetime(2001, 2, 3, 17, 48, 45))
        self.assertEqual(event.author_id, craig_user.id)

        # depends_on / issue_links
        related_issue_41818 = Issue.objects(external_id="41818").get()

        event = all_events[10]
        self.assertEqual(event.status, "issue_links")
        self.assertEqual(
            event.old_value, {
                'issue_id': related_issue_41818.id,
                'type': 'Dependent',
                'effect': 'depends on'
            })
        self.assertEqual(event.new_value, None)
        self.assertEqual(event.created_at,
                         datetime.datetime(2001, 2, 3, 17, 48, 45))
        self.assertEqual(event.author_id, craig_user.id)

        # blocks / issue_links
        event = all_events[11]
        self.assertEqual(event.status, "issue_links")
        self.assertEqual(event.old_value, None)
        self.assertEqual(
            event.new_value, {
                'issue_id': related_issue_41817.id,
                'type': 'Blocker',
                'effect': 'blocks'
            })
        self.assertEqual(event.created_at,
                         datetime.datetime(2001, 2, 3, 17, 48, 45))
        self.assertEqual(event.author_id, craig_user.id)

        ############
        # blocks / issue_links
        event = all_events[12]
        self.assertEqual(event.status, "issue_links")
        self.assertEqual(
            event.old_value, {
                'issue_id': related_issue_41818.id,
                'type': 'Blocker',
                'effect': 'blocks'
            })
        self.assertEqual(event.new_value, None)
        self.assertEqual(event.created_at,
                         datetime.datetime(2001, 2, 4, 6, 20, 32))
        self.assertEqual(event.author_id, conor_user.id)

        #############
        # title
        event = all_events[13]
        self.assertEqual(event.status, "title")
        self.assertEqual(
            event.old_value,
            "cvschangelog task: CVS log date output format changed on CVS 1.12.9 "
        )
        self.assertEqual(
            event.new_value,
            "cvschangelog task: CVS log date output format changed on CVS 1.12.9"
        )
        self.assertEqual(event.created_at,
                         datetime.datetime(2001, 3, 2, 5, 0, 52))
        self.assertEqual(event.author_id, conor_user.id)

        # fix_versions
        event = all_events[14]
        self.assertEqual(event.status, "fix_versions")
        self.assertEqual(event.old_value, "---")
        self.assertEqual(event.new_value, "1.7")
        self.assertEqual(event.created_at,
                         datetime.datetime(2001, 3, 2, 5, 0, 52))
        self.assertEqual(event.author_id, conor_user.id)

        # priority
        event = all_events[15]
        self.assertEqual(event.status, "priority")
        self.assertEqual(event.old_value, "major")
        self.assertEqual(event.new_value, "enhancement")
        self.assertEqual(event.created_at,
                         datetime.datetime(2001, 3, 2, 5, 0, 52))
        self.assertEqual(event.author_id, conor_user.id)
예제 #10
0
 def test_build_query_issue_history(self):
     ba = BugzillaAgent(self.logger, self.conf)
     self.assertEqual(
         'https://bz.apache.org/bugzilla/rest.cgi/bug/1241/history',
         ba._build_query('bug/1241/history', None))
예제 #11
0
 def test_build_query_user(self):
     ba = BugzillaAgent(self.logger, self.conf)
     self.assertEqual('https://bz.apache.org/bugzilla/rest.cgi/user/hans',
                      ba._build_query('user/hans', None))
예제 #12
0
 def test_initialization_succeeds(self):
     ba = BugzillaAgent(self.logger, self.conf)
     self.assertEqual('https://bz.apache.org/bugzilla/rest.cgi',
                      ba.base_url)
     self.assertEqual('Ant', ba.project_name)
예제 #13
0
 def test_build_query_get_comments(self):
     ba = BugzillaAgent(self.logger, self.conf)
     self.assertEqual(
         'https://bz.apache.org/bugzilla/rest.cgi/bug/1241/comment',
         ba._build_query('bug/1241/comment', None))