1# Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import glob, logging, os, shutil
6from autotest_lib.client.common_lib import error
7from autotest_lib.server import test, utils
8from optparse import OptionParser
9
10class platform_GCC(test.test):
11    """Class for running the GCC dejagnu tests."""
12    version = 1
13    results = {}
14
15    TEST_STATUSES = ('PASS', 'FAIL', 'UNRESOLVED', 'UNTESTED', 'UNSUPPORTED',
16                     'XFAIL', 'KFAIL', 'XPASS', 'KPASS')
17    TARBALL = '/usr/local/dejagnu/gcc/tests.tar.gz'
18
19    def parse_log(self, log):
20        results = {}
21        counts = {}
22        log_file = open(log, 'rb')
23        for line in log_file:
24            if line.startswith(self.TEST_STATUSES):
25                result, testname = line.split(': ', 1)
26                testname = testname.strip()
27                if testname in results:
28                    counts[testname] += 1
29                    unique_testname = '%s (%d)' % (testname, counts[testname])
30                else:
31                    counts[testname] = 1
32                    unique_testname = testname
33                results[unique_testname] = result
34        log_file.close()
35        return results
36
37
38    def compare_logs(self, baseline, new):
39        baseline_results = self.parse_log(baseline)
40        logging.info('%d results parsed in baseline (%s).' %
41                     (len(baseline_results), baseline))
42        new_results = self.parse_log(new)
43        logging.info('%d results parsed in new log (%s).' %
44                     (len(new_results), new))
45
46        differences = []
47        for testname in new_results.keys():
48            if testname not in baseline_results:
49                differences.append((testname, 'NOTEXECUTED',
50                                    new_results[testname]))
51            elif new_results[testname] != baseline_results[testname]:
52                differences.append((testname, baseline_results[testname],
53                                    new_results[testname]))
54        for testname in baseline_results.keys():
55            if testname not in new_results:
56                differences.append((testname, baseline_results[testname],
57                                    'NOTEXECUTED'))
58        return differences
59
60
61    def run_once(self, host=None, args=[]):
62        self.client = host
63
64        parser = OptionParser()
65        parser.add_option('--gcc_dir',
66                          dest='gcc_dir',
67                          default='/var/tmp/portage/cross-*/gcc-*/work/gcc-*build*',
68                          help='Path to the gcc build directory.')
69        parser.add_option('--test_flags',
70                          dest='test_flags',
71                          default='',
72                          help='Options to pass to dejagnu.')
73
74        options, args = parser.parse_args(args)
75
76        utils.system('%s %s' %
77                     (os.path.join(self.bindir, 'dejagnu_init_remote'),
78                      self.client.ip))
79
80        gcc_dirs = glob.glob(options.gcc_dir)
81        if len(gcc_dirs) == 0:
82            # If there is no directory present, try untarring the tarball
83            # installed by the gcc package.
84            logging.info('No gcc directory found, attempting to untar from %s'
85                         % self.TARBALL)
86            os.chdir('/')
87            os.system('tar -xzf %s' % self.TARBALL)
88            gcc_dirs = glob.glob(options.gcc_dir)
89            if len(gcc_dirs) == 0:
90                raise error.TestFail('No gcc directory to test was found')
91
92        gcc_dir = gcc_dirs[0]
93
94        logging.info('Testing gcc in the following directory: %s' % gcc_dir)
95        exp_file = os.path.join(self.bindir, 'site.exp')
96        client_hostname = str(self.client.ip)
97        test_flags = options.test_flags
98        test_command = ('cd %s; DEJAGNU="%s" DEJAGNU_SCRIPTS=%s '
99                        'DEJAGNU_HOSTNAME=%s make '
100                        'RUNTESTFLAGS="%s" check-gcc' % (gcc_dir, exp_file,
101                        self.bindir, client_hostname, test_flags))
102        utils.system(test_command)
103
104        error_messages = []
105        for log in ('gcc', 'g++'):
106            log_from = os.path.join(gcc_dir, 'gcc/testsuite/%s/%s.log' %
107                                    (log, log))
108            log_to = os.path.join(self.resultsdir, '%s.log' % (log))
109            shutil.copy(log_from, log_to)
110
111            baseline = os.path.join(self.bindir, '%s.log' % (log))
112
113            differences = self.compare_logs(baseline, log_to)
114            for difference in differences:
115                error_string = ('(%s) "%s" Expected: "%s" Actual: "%s"' %
116                                (log_to, difference[0],
117                                 difference[1], difference[2]))
118                error_messages.append(error_string)
119            keyname = log.replace('+', 'p')
120            self.results['%s_differences' % keyname] = len(differences)
121
122        self.write_perf_keyval(self.results)
123
124        if len(error_messages) != 0:
125            raise error.TestFail('\n'.join(error_messages))
126
127    def cleanup(self):
128        utils.system(os.path.join(self.bindir, 'dejagnu_cleanup_remote'))
129