• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2017 The Chromium 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
6import json
7import os
8
9import logging
10
11from autotest_lib.site_utils.sponge_lib import autotest_job_info
12
13
14class ACTSSummaryEnums(object):
15    """A class contains the attribute names used in a ACTS summary."""
16
17    Requested = 'Requested'
18    Failed = 'Failed'
19    Unknown = 'Unknown'
20
21
22class ACTSRecordEnums(object):
23    """A class contains the attribute names used in an ACTS record."""
24
25    BeginTime = 'Begin Time'
26    Details = 'Details'
27    EndTime = 'End Time'
28    Extras = 'Extras'
29    ExtraErrors = 'Extra Errors'
30    Result = 'Result'
31    TestClass = 'Test Class'
32    TestName = 'Test Name'
33    UID = 'UID'
34
35
36class ACTSTaskInfo(autotest_job_info.AutotestTaskInfo):
37    """Task info for an ACTS test."""
38
39    tags = autotest_job_info.AutotestTaskInfo.tags + ['acts', 'testtracker']
40    logs = autotest_job_info.AutotestTaskInfo.logs + ['results']
41
42    def __init__(self, test, job):
43        """
44        @param test: The autotest test for this ACTS test.
45        @param job: The job info that is the parent ot this task.
46        """
47        super(ACTSTaskInfo, self).__init__(test, job)
48
49        summary_location = os.path.join(
50                self.results_dir, 'results/latest/test_run_summary.json')
51
52        build_info_location = os.path.join(self.results_dir,
53                'results/BUILD_INFO-*')
54        build_info_files = glob.iglob(build_info_location)
55
56        try:
57            build_info_file = next(build_info_files)
58            logging.info('Using build info file: %s', build_info_file)
59            with open(build_info_file) as fd:
60                self.build_info = json.load(fd)
61        except Exception as e:
62            logging.exception(e)
63            logging.error('Bad build info file.')
64            self.build_info = {}
65
66        try:
67            build_prop_str = self.build_info['build_prop']
68            prop_dict = {}
69            self.build_info['build_prop'] = prop_dict
70            lines = build_prop_str.splitlines()
71            for line in lines:
72                parts = line.split('=')
73
74                if len(parts) != 2:
75                    continue
76
77                prop_dict[parts[0]] = parts[1]
78        except Exception as e:
79            logging.exception(e)
80            logging.error('Bad build prop data, using default empty dict')
81            self.build_info['build_prop'] = {}
82
83        try:
84            with open(summary_location) as fd:
85                self._acts_summary = json.load(fd)
86
87            self._summary_block = self._acts_summary['Summary']
88
89            record_block = self._acts_summary['Results']
90            self._records = list(ACTSRecord(record) for record in record_block)
91            self.is_valid = True
92        except Exception as e:
93            logging.exception(e)
94            logging.error('Bad acts data, reverting to autotest only.')
95            self.is_valid = False
96            self.tags = autotest_job_info.AutotestTaskInfo.tags
97
98    @property
99    def test_case_count(self):
100        """The number of test cases run."""
101        return self._summary_block[ACTSSummaryEnums.Requested]
102
103    @property
104    def failed_case_count(self):
105        """The number of failed test cases."""
106        return self._summary_block[ACTSSummaryEnums.Failed]
107
108    @property
109    def error_case_count(self):
110        """The number of errored test cases."""
111        return self._summary_block[ACTSSummaryEnums.Unknown]
112
113    @property
114    def records(self):
115        """All records of test cases in the ACTS tests."""
116        return self._records
117
118    @property
119    def effort_name(self):
120        """The test tracker effort name."""
121        return self.build_info.get('build_prop', {}).get(
122            'ro.build.version.incremental', 'UNKNOWN_BUILD')
123
124    @property
125    def project_id(self):
126        """The test tracker project id."""
127        return self.keyvals.get('param-testtracker_project_id', None)
128
129    @property
130    def environment(self):
131        """The name of the enviroment for test tracker."""
132        return self.build_info.get('branch', 'UNKNOWN_BRANCH')
133
134
135class ACTSRecord(object):
136    """A single record of a test case in an ACTS test."""
137
138    tags = ['acts', 'testtracker']
139
140    def __init__(self, json_record):
141        """
142        @param json_record: The json info for this record
143        """
144        self._json_record = json_record
145
146    @property
147    def test_class(self):
148        """The test class that was run."""
149        return self._json_record[ACTSRecordEnums.TestClass]
150
151    @property
152    def test_case(self):
153        """The test case that was run. None implies all in the class."""
154        return self._json_record.get(ACTSRecordEnums.TestName, None)
155
156    @property
157    def uid(self):
158        """The uid of the test case."""
159        return self._json_record.get(ACTSRecordEnums.UID, None)
160
161    @property
162    def status(self):
163        """The status of the test case."""
164        return self._json_record[ACTSRecordEnums.Result]
165
166    @property
167    def start_time(self):
168        """The start time of the test case."""
169        return self._json_record[ACTSRecordEnums.BeginTime] / 1000.0
170
171    @property
172    def end_time(self):
173        """The end time of the test case."""
174        return self._json_record[ACTSRecordEnums.EndTime] / 1000.0
175
176    @property
177    def details(self):
178        """Details about the test case."""
179        return self._json_record.get(ACTSRecordEnums.Details, None)
180
181    @property
182    def extras(self):
183        """Extra info about the test case."""
184        return self._json_record.get(ACTSRecordEnums.Extras, None)
185
186    @property
187    def extra_errors(self):
188        """Extra errors about the test case."""
189        return self._json_record.get(ACTSRecordEnums.ExtraErrors, None)
190
191    @property
192    def uuid(self):
193        """The test tracker uuid of the test case."""
194        extras = self.extras
195        if not extras:
196            return None
197
198        test_tracker_info = self.extras.get('test_tracker_info', None)
199        if not test_tracker_info:
200            return None
201
202        return test_tracker_info.get('test_tracker_uuid', None)
203