19750e409Sopenharmony_ciimport sys
29750e409Sopenharmony_ciimport os
39750e409Sopenharmony_cifrom glob import glob
49750e409Sopenharmony_ci
59750e409Sopenharmony_cifrom pyparsing import *
69750e409Sopenharmony_cifrom junit_xml import TestSuite, TestCase
79750e409Sopenharmony_ci
89750e409Sopenharmony_ci
99750e409Sopenharmony_ciclass UnityTestSummary:
109750e409Sopenharmony_ci    def __init__(self):
119750e409Sopenharmony_ci        self.report = ''
129750e409Sopenharmony_ci        self.total_tests = 0
139750e409Sopenharmony_ci        self.failures = 0
149750e409Sopenharmony_ci        self.ignored = 0
159750e409Sopenharmony_ci        self.targets = 0
169750e409Sopenharmony_ci        self.root = None
179750e409Sopenharmony_ci        self.test_suites = dict()
189750e409Sopenharmony_ci
199750e409Sopenharmony_ci    def run(self):
209750e409Sopenharmony_ci        # Clean up result file names
219750e409Sopenharmony_ci        results = []
229750e409Sopenharmony_ci        for target in self.targets:
239750e409Sopenharmony_ci            results.append(target.replace('\\', '/'))
249750e409Sopenharmony_ci
259750e409Sopenharmony_ci        # Dig through each result file, looking for details on pass/fail:
269750e409Sopenharmony_ci        for result_file in results:
279750e409Sopenharmony_ci            lines = list(map(lambda line: line.rstrip(), open(result_file, "r").read().split('\n')))
289750e409Sopenharmony_ci            if len(lines) == 0:
299750e409Sopenharmony_ci                raise Exception("Empty test result file: %s" % result_file)
309750e409Sopenharmony_ci
319750e409Sopenharmony_ci            # define an expression for your file reference
329750e409Sopenharmony_ci            entry_one = Combine(
339750e409Sopenharmony_ci                oneOf(list(alphas)) + ':/' +
349750e409Sopenharmony_ci                Word(alphanums + '_-./'))
359750e409Sopenharmony_ci
369750e409Sopenharmony_ci            entry_two = Word(printables + ' ', excludeChars=':')
379750e409Sopenharmony_ci            entry = entry_one | entry_two
389750e409Sopenharmony_ci
399750e409Sopenharmony_ci            delimiter = Literal(':').suppress()
409750e409Sopenharmony_ci            tc_result_line = Group(entry.setResultsName('tc_file_name') + delimiter + entry.setResultsName(
419750e409Sopenharmony_ci                'tc_line_nr') + delimiter + entry.setResultsName('tc_name') + delimiter + entry.setResultsName(
429750e409Sopenharmony_ci                'tc_status') + Optional(
439750e409Sopenharmony_ci                delimiter + entry.setResultsName('tc_msg'))).setResultsName("tc_line")
449750e409Sopenharmony_ci
459750e409Sopenharmony_ci            eol = LineEnd().suppress()
469750e409Sopenharmony_ci            sol = LineStart().suppress()
479750e409Sopenharmony_ci            blank_line = sol + eol
489750e409Sopenharmony_ci
499750e409Sopenharmony_ci            tc_summary_line = Group(Word(nums).setResultsName("num_of_tests") + "Tests" + Word(nums).setResultsName(
509750e409Sopenharmony_ci                "num_of_fail") + "Failures" + Word(nums).setResultsName("num_of_ignore") + "Ignored").setResultsName(
519750e409Sopenharmony_ci                "tc_summary")
529750e409Sopenharmony_ci            tc_end_line = Or(Literal("FAIL"), Literal('Ok')).setResultsName("tc_result")
539750e409Sopenharmony_ci
549750e409Sopenharmony_ci            # run it and see...
559750e409Sopenharmony_ci            pp1 = tc_result_line | Optional(tc_summary_line | tc_end_line)
569750e409Sopenharmony_ci            pp1.ignore(blank_line | OneOrMore("-"))
579750e409Sopenharmony_ci
589750e409Sopenharmony_ci            result = list()
599750e409Sopenharmony_ci            for l in lines:
609750e409Sopenharmony_ci                result.append((pp1.parseString(l)).asDict())
619750e409Sopenharmony_ci            # delete empty results
629750e409Sopenharmony_ci            result = filter(None, result)
639750e409Sopenharmony_ci
649750e409Sopenharmony_ci            tc_list = list()
659750e409Sopenharmony_ci            for r in result:
669750e409Sopenharmony_ci                if 'tc_line' in r:
679750e409Sopenharmony_ci                    tmp_tc_line = r['tc_line']
689750e409Sopenharmony_ci
699750e409Sopenharmony_ci                    # get only the file name which will be used as the classname
709750e409Sopenharmony_ci                    file_name = tmp_tc_line['tc_file_name'].split('\\').pop().split('/').pop().rsplit('.', 1)[0]
719750e409Sopenharmony_ci                    tmp_tc = TestCase(name=tmp_tc_line['tc_name'], classname=file_name)
729750e409Sopenharmony_ci                    if 'tc_status' in tmp_tc_line:
739750e409Sopenharmony_ci                        if str(tmp_tc_line['tc_status']) == 'IGNORE':
749750e409Sopenharmony_ci                            if 'tc_msg' in tmp_tc_line:
759750e409Sopenharmony_ci                                tmp_tc.add_skipped_info(message=tmp_tc_line['tc_msg'],
769750e409Sopenharmony_ci                                                        output=r'[File]={0}, [Line]={1}'.format(
779750e409Sopenharmony_ci                                                            tmp_tc_line['tc_file_name'], tmp_tc_line['tc_line_nr']))
789750e409Sopenharmony_ci                            else:
799750e409Sopenharmony_ci                                tmp_tc.add_skipped_info(message=" ")
809750e409Sopenharmony_ci                        elif str(tmp_tc_line['tc_status']) == 'FAIL':
819750e409Sopenharmony_ci                            if 'tc_msg' in tmp_tc_line:
829750e409Sopenharmony_ci                                tmp_tc.add_failure_info(message=tmp_tc_line['tc_msg'],
839750e409Sopenharmony_ci                                                        output=r'[File]={0}, [Line]={1}'.format(
849750e409Sopenharmony_ci                                                            tmp_tc_line['tc_file_name'], tmp_tc_line['tc_line_nr']))
859750e409Sopenharmony_ci                            else:
869750e409Sopenharmony_ci                                tmp_tc.add_failure_info(message=" ")
879750e409Sopenharmony_ci
889750e409Sopenharmony_ci                    tc_list.append((str(result_file), tmp_tc))
899750e409Sopenharmony_ci
909750e409Sopenharmony_ci            for k, v in tc_list:
919750e409Sopenharmony_ci                try:
929750e409Sopenharmony_ci                    self.test_suites[k].append(v)
939750e409Sopenharmony_ci                except KeyError:
949750e409Sopenharmony_ci                    self.test_suites[k] = [v]
959750e409Sopenharmony_ci        ts = []
969750e409Sopenharmony_ci        for suite_name in self.test_suites:
979750e409Sopenharmony_ci            ts.append(TestSuite(suite_name, self.test_suites[suite_name]))
989750e409Sopenharmony_ci
999750e409Sopenharmony_ci        with open('result.xml', 'w') as f:
1009750e409Sopenharmony_ci            TestSuite.to_file(f, ts, prettyprint='True', encoding='utf-8')
1019750e409Sopenharmony_ci
1029750e409Sopenharmony_ci        return self.report
1039750e409Sopenharmony_ci
1049750e409Sopenharmony_ci    def set_targets(self, target_array):
1059750e409Sopenharmony_ci        self.targets = target_array
1069750e409Sopenharmony_ci
1079750e409Sopenharmony_ci    def set_root_path(self, path):
1089750e409Sopenharmony_ci        self.root = path
1099750e409Sopenharmony_ci
1109750e409Sopenharmony_ci    @staticmethod
1119750e409Sopenharmony_ci    def usage(err_msg=None):
1129750e409Sopenharmony_ci        print("\nERROR: ")
1139750e409Sopenharmony_ci        if err_msg:
1149750e409Sopenharmony_ci            print(err_msg)
1159750e409Sopenharmony_ci        print("\nUsage: unity_test_summary.py result_file_directory/ root_path/")
1169750e409Sopenharmony_ci        print("     result_file_directory - The location of your results files.")
1179750e409Sopenharmony_ci        print("                             Defaults to current directory if not specified.")
1189750e409Sopenharmony_ci        print("                             Should end in / if specified.")
1199750e409Sopenharmony_ci        print("     root_path - Helpful for producing more verbose output if using relative paths.")
1209750e409Sopenharmony_ci        sys.exit(1)
1219750e409Sopenharmony_ci
1229750e409Sopenharmony_ci
1239750e409Sopenharmony_ciif __name__ == '__main__':
1249750e409Sopenharmony_ci    uts = UnityTestSummary()
1259750e409Sopenharmony_ci    try:
1269750e409Sopenharmony_ci        # look in the specified or current directory for result files
1279750e409Sopenharmony_ci        if len(sys.argv) > 1:
1289750e409Sopenharmony_ci            targets_dir = sys.argv[1]
1299750e409Sopenharmony_ci        else:
1309750e409Sopenharmony_ci            targets_dir = './'
1319750e409Sopenharmony_ci        targets = list(map(lambda x: x.replace('\\', '/'), glob(targets_dir + '*.test*')))
1329750e409Sopenharmony_ci        if len(targets) == 0:
1339750e409Sopenharmony_ci            raise Exception("No *.testpass or *.testfail files found in '%s'" % targets_dir)
1349750e409Sopenharmony_ci        uts.set_targets(targets)
1359750e409Sopenharmony_ci
1369750e409Sopenharmony_ci        # set the root path
1379750e409Sopenharmony_ci        if len(sys.argv) > 2:
1389750e409Sopenharmony_ci            root_path = sys.argv[2]
1399750e409Sopenharmony_ci        else:
1409750e409Sopenharmony_ci            root_path = os.path.split(__file__)[0]
1419750e409Sopenharmony_ci        uts.set_root_path(root_path)
1429750e409Sopenharmony_ci
1439750e409Sopenharmony_ci        # run the summarizer
1449750e409Sopenharmony_ci        print(uts.run())
1459750e409Sopenharmony_ci    except Exception as e:
1469750e409Sopenharmony_ci        UnityTestSummary.usage(e)
147