<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""Convert start_test log to jUnit XML report."""

# TODO: Collate multiple trials of a perf test into a single test case. If any
#       of the trials fail, mark the test as failed.

# TODO: If test is skipped during perf run because it does not include the
#       .perf configs, drop the test case. Otherwise, there are hundreds of
#       "skipped" tests, which we don't care to record. We only want to report
#       on the tests that were skipped because the environment, not because
#       they are missing performance config files.

# TODO: Support suppression files. Add flag to this script that takes the
#       suppression file. For each test in that file, swap the result in the
#       report (i.e. if the test has status=ERROR and is in suppression file,
#       swap to status=SUCCESS -- and vice versa). Pipe the flag through
#       start_test.

from __future__ import print_function, unicode_literals

import codecs
import getpass
import logging
import optparse
import os.path
import re
import sys
import xml.etree.ElementTree as XML

# Add the chplenv dir to the python path.
chplenv_dir = os.path.join(os.path.dirname(__file__), '..', 'chplenv')
sys.path.insert(0, os.path.abspath(chplenv_dir))

import chpl_platform


DEBUG = False


def main():
    """Parse cli arguments and convert a start_test log file to jUnit xml
    format.
    """
    args = _parse_args()
    _setup_logging(args.verbose)

    global DEBUG
    if args.debug:
        DEBUG = True

    test_cases = _parse_start_test_log(args.start_test_log)
    _create_junit_report(test_cases, args.junit_xml)


def _create_junit_report(test_cases, junit_file):
    """Create jUnit XML report from test info.

    :type test_cases: list of dicts
    :arg test_cases: list of dicts; each dict contains info about a single test case

    :type junit_file: str
    :arg junit_file: filename to write the jUnit XML report
    """
    logging.debug('Creating jUnit XML report at: {0}'.format(junit_file))
    test_suite = XML.Element('testsuite')

    for test_case in test_cases:
        case_elem = XML.SubElement(test_suite, 'testcase')
        case_elem.set('name', test_case['name'])
        case_elem.set('classname', test_case['classname'])
        case_elem.set('time', str(test_case['time']))

        test_error = test_case['error']

        if test_case['skipped']:
            skip_elem = XML.SubElement(case_elem, 'skipped')
        elif test_error is not None:
            error_elem = XML.SubElement(case_elem, 'error')
            error_elem.set('message', test_error['message'])
            error_elem.text = test_error['content']

        system_out = XML.SubElement(case_elem, 'system-out')
        system_out.text = test_case['system-out']

    xml_content = XML.tostring(test_suite)
    xml_content = _clean_xml(xml_content)
    with open(junit_file, 'w') as fp:
        fp.write(xml_content)
    logging.info('Wrote jUnit report to: {0}'.format(junit_file))


def _parse_start_test_log(start_test_log):
    """Parse start_test logfile and return results in python data structure.

    :type start_test_log: str
    :arg start_test_log: start_test log filename

    :rtype: list of dicts
    :returns: list of dicts; each dict contains info about a single test case
    """
    logging.debug('Parsing start_test log: {0}'.format(start_test_log))
    with codecs.open(start_test_log, 'r', encoding='utf-8', errors='ignore') as fp:
        start_test_lines = fp.readlines()
    logging.debug('Read {0} lines from "{1}".'.format(
        len(start_test_lines), start_test_log))

    test_cases = []
    while len(start_test_lines) > 0:
        subtest_start, subtest_end = _get_block(
            start_test_lines, '[Starting subtest - ', '[Finished subtest ')

        # No more sub_tests; delete the remaining lines and finish up.
        if subtest_start == -1:
            del start_test_lines[:]
            continue

        # Copy subtest lines into new list for further processing and delete
        # them from start_test_lines.
        sub_test_lines = start_test_lines[subtest_start:subtest_end+1:1]
        del start_test_lines[:subtest_end+1]

        while len(sub_test_lines) > 0:
            test_start, test_end = _get_block(
                sub_test_lines,
                '[test: ',
                '[Elapsed time to compile and execute all versions of "')
            test_start_skip, test_end_skip = _get_block(
                sub_test_lines,
                '[test: ',
                '[Skipping')

            test_skipped = False
            if test_end_skip != -1 and (test_end == -1 or test_end_skip < test_end):
                test_start, test_end = test_start_skip, test_end_skip
                test_skipped = True

            # If test_end is still -1 (i.e. not found), look for end of subtest
            # call (usually means subtest failed and did not tests).
            if test_start != -1 and test_end == -1:
                test_start, test_end = _get_block(
                    sub_test_lines,
                    '[test: ',
                    '[Finished subtest "')
                if test_end == -1:
                    raise ValueError('Failed to parse test case from: {0}'.format(
                        sub_test_lines))

            # No more test cases; delete remaining lines and finish up.
            if test_start == -1:
                del sub_test_lines[:]
                continue

            # Copy test lines into new list for further processing and delete
            # from sub_test_lines.
            test_case_lines = sub_test_lines[test_start:test_end+1:1]
            del sub_test_lines[:test_end+1]

            # Extract test name from "[test: <path to .chpl file>]" line.
            classname, test_name = _get_test_name(test_case_lines)
            if test_skipped:<commit_msg>Drop noperf tests, instead of skipping them.<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""Convert start_test log to jUnit XML report."""

# TODO: Collate multiple trials of a perf test into a single test case. If any
#       of the trials fail, mark the test as failed.

# TODO: Support suppression files. Add flag to this script that takes the
#       suppression file. For each test in that file, swap the result in the
#       report (i.e. if the test has status=ERROR and is in suppression file,
#       swap to status=SUCCESS -- and vice versa). Pipe the flag through
#       start_test.

from __future__ import print_function, unicode_literals

import codecs
import getpass
import logging
import optparse
import os.path
import re
import sys
import xml.etree.ElementTree as XML

# Add the chplenv dir to the python path.
chplenv_dir = os.path.join(os.path.dirname(__file__), '..', 'chplenv')
sys.path.insert(0, os.path.abspath(chplenv_dir))

import chpl_platform


DEBUG = False


def main():
    """Parse cli arguments and convert a start_test log file to jUnit xml
    format.
    """
    args = _parse_args()
    _setup_logging(args.verbose)

    global DEBUG
    if args.debug:
        DEBUG = True

    test_cases = _parse_start_test_log(args.start_test_log)
    _create_junit_report(test_cases, args.junit_xml)


def _create_junit_report(test_cases, junit_file):
    """Create jUnit XML report from test info.

    :type test_cases: list of dicts
    :arg test_cases: list of dicts; each dict contains info about a single test case

    :type junit_file: str
    :arg junit_file: filename to write the jUnit XML report
    """
    logging.debug('Creating jUnit XML report at: {0}'.format(junit_file))
    test_suite = XML.Element('testsuite')

    for test_case in test_cases:
        case_elem = XML.SubElement(test_suite, 'testcase')
        case_elem.set('name', test_case['name'])
        case_elem.set('classname', test_case['classname'])
        case_elem.set('time', str(test_case['time']))

        test_error = test_case['error']

        if test_case['skipped']:
            skip_elem = XML.SubElement(case_elem, 'skipped')
        elif test_error is not None:
            error_elem = XML.SubElement(case_elem, 'error')
            error_elem.set('message', test_error['message'])
            error_elem.text = test_error['content']

        system_out = XML.SubElement(case_elem, 'system-out')
        system_out.text = test_case['system-out']

    xml_content = XML.tostring(test_suite)
    xml_content = _clean_xml(xml_content)
    with open(junit_file, 'w') as fp:
        fp.write(xml_content)
    logging.info('Wrote jUnit report to: {0}'.format(junit_file))


def _parse_start_test_log(start_test_log):
    """Parse start_test logfile and return results in python data structure.

    :type start_test_log: str
    :arg start_test_log: start_test log filename

    :rtype: list of dicts
    :returns: list of dicts; each dict contains info about a single test case
    """
    logging.debug('Parsing start_test log: {0}'.format(start_test_log))
    with codecs.open(start_test_log, 'r', encoding='utf-8', errors='ignore') as fp:
        start_test_lines = fp.readlines()
    logging.debug('Read {0} lines from "{1}".'.format(
        len(start_test_lines), start_test_log))

    test_cases = []
    while len(start_test_lines) > 0:
        subtest_start, subtest_end = _get_block(
            start_test_lines, '[Starting subtest - ', '[Finished subtest ')

        # No more sub_tests; delete the remaining lines and finish up.
        if subtest_start == -1:
            del start_test_lines[:]
            continue

        # Copy subtest lines into new list for further processing and delete
        # them from start_test_lines.
        sub_test_lines = start_test_lines[subtest_start:subtest_end+1:1]
        del start_test_lines[:subtest_end+1]

        while len(sub_test_lines) > 0:
            test_start, test_end = _get_block(
                sub_test_lines,
                '[test: ',
                '[Elapsed time to compile and execute all versions of "')
            test_start_skip, test_end_skip = _get_block(
                sub_test_lines,
                '[test: ',
                '[Skipping')

            test_skipped = False
            if test_end_skip != -1 and (test_end == -1 or test_end_skip < test_end):
                test_start, test_end = test_start_skip, test_end_skip
                test_skipped = True

                noperf_start, noperf_end = _get_block(
                    sub_test_lines,
                    '[test: ',
                    '[Skipping noperf test:')

                # If the test was skipped because it did not have performance
                # configuration files, drop the lines and continue. We don't
                # care about these for performance tests (as opposed to real
                # perf tests that are skipped due to environment/etc).
                if noperf_end != -1:
                    del sub_test_lines[noperf_start:noperf_end+1]
                    continue

            # If test_end is still -1 (i.e. not found), look for end of subtest
            # call (usually means subtest failed and did not tests).
            if test_start != -1 and test_end == -1:
                test_start, test_end = _get_block(
                    sub_test_lines,
                    '[test: ',
                    '[Finished subtest "')
                if test_end == -1:
                    raise ValueError('Failed to parse test case from: {0}'.format(
                        sub_test_lines))

            # No more test cases; delete remaining lines and finish up.
            if test_start == -1:
                del sub_test_lines[:]
                continue

            # Copy test lines into new list for further processing and delete
            # from sub_test_lines.
            test_case_lines = sub_test_lines[test_start:test_end+1:1]
            del sub_test_lines[:test_end+1]

            # Extract test name from "[test: <path to .chpl file>]" line.
            classname, test_name = _get_test_name(test_case_lines)
            if test_skipped:
{'fraction_non_alphanumeric': 0.08884844473858372, 'fraction_numerical': 0.004301786896095301, 'mean_word_length': 2.430476730987514, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 16}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6713136', 'n_tokens_mistral': 3639, 'n_tokens_neox': 3531, 'n_words': 1092}