1a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake# Copyright 2017 The Chromium Authors. All rights reserved. 2a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake# Use of this source code is governed by a BSD-style license that can be 3a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake# found in the LICENSE file. 40c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake 50c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peakeimport glob 6a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peakeimport json 7a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peakeimport os 8a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 959325d258052f28b10407f8adb500e0545764388Benny Peakeimport logging 1059325d258052f28b10407f8adb500e0545764388Benny Peake 11a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peakefrom autotest_lib.site_utils.sponge_lib import autotest_job_info 12a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 13a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 146ade820e4f4843cef1b6a4e086db769d6ef088edBenny PeakeUNKNOWN_EFFORT_NAME = 'UNKNOWN_BUILD' 156ade820e4f4843cef1b6a4e086db769d6ef088edBenny PeakeUNKNOWN_ENV_NAME = 'UNKNOWN_BOARD' 166ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake 176ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake 18a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peakeclass ACTSSummaryEnums(object): 19a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake """A class contains the attribute names used in a ACTS summary.""" 20a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 21a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake Requested = 'Requested' 22a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake Failed = 'Failed' 23a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake Unknown = 'Unknown' 24a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 25a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 26a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peakeclass ACTSRecordEnums(object): 27a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake """A class contains the attribute names used in an ACTS record.""" 28a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 29a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake BeginTime = 'Begin Time' 30a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake Details = 'Details' 31a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake EndTime = 'End Time' 32a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake Extras = 'Extras' 33a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake ExtraErrors = 'Extra Errors' 34a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake Result = 'Result' 35a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake TestClass = 'Test Class' 36a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake TestName = 'Test Name' 37a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake UID = 'UID' 38a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 39a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 40a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peakeclass ACTSTaskInfo(autotest_job_info.AutotestTaskInfo): 41a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake """Task info for an ACTS test.""" 42a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 43a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake tags = autotest_job_info.AutotestTaskInfo.tags + ['acts', 'testtracker'] 44a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake logs = autotest_job_info.AutotestTaskInfo.logs + ['results'] 45a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 46a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake def __init__(self, test, job): 47a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake """ 48a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake @param test: The autotest test for this ACTS test. 49a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake @param job: The job info that is the parent ot this task. 50a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake """ 51a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake super(ACTSTaskInfo, self).__init__(test, job) 52a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 53a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake summary_location = os.path.join( 540c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake self.results_dir, 'results/latest/test_run_summary.json') 550c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake 560c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake build_info_location = os.path.join(self.results_dir, 570c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake 'results/BUILD_INFO-*') 580c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake build_info_files = glob.iglob(build_info_location) 590c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake 600c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake try: 610c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake build_info_file = next(build_info_files) 620c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake logging.info('Using build info file: %s', build_info_file) 630c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake with open(build_info_file) as fd: 640c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake self.build_info = json.load(fd) 650c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake except Exception as e: 660c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake logging.exception(e) 670c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake logging.error('Bad build info file.') 680c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake self.build_info = {} 690c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake 700c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake try: 710c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake build_prop_str = self.build_info['build_prop'] 720c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake prop_dict = {} 730c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake self.build_info['build_prop'] = prop_dict 740c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake lines = build_prop_str.splitlines() 750c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake for line in lines: 760c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake parts = line.split('=') 770c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake 780c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake if len(parts) != 2: 790c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake continue 800c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake 810c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake prop_dict[parts[0]] = parts[1] 820c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake except Exception as e: 830c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake logging.exception(e) 840c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake logging.error('Bad build prop data, using default empty dict') 850c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake self.build_info['build_prop'] = {} 86a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 8759325d258052f28b10407f8adb500e0545764388Benny Peake try: 8859325d258052f28b10407f8adb500e0545764388Benny Peake with open(summary_location) as fd: 8959325d258052f28b10407f8adb500e0545764388Benny Peake self._acts_summary = json.load(fd) 90a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 9159325d258052f28b10407f8adb500e0545764388Benny Peake self._summary_block = self._acts_summary['Summary'] 92a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 9359325d258052f28b10407f8adb500e0545764388Benny Peake record_block = self._acts_summary['Results'] 9459325d258052f28b10407f8adb500e0545764388Benny Peake self._records = list(ACTSRecord(record) for record in record_block) 9559325d258052f28b10407f8adb500e0545764388Benny Peake self.is_valid = True 9659325d258052f28b10407f8adb500e0545764388Benny Peake except Exception as e: 970c4bbc47993f20b8d17a1f39d1d1b621ce6b8b6eBenny Peake logging.exception(e) 9859325d258052f28b10407f8adb500e0545764388Benny Peake logging.error('Bad acts data, reverting to autotest only.') 9959325d258052f28b10407f8adb500e0545764388Benny Peake self.is_valid = False 10059325d258052f28b10407f8adb500e0545764388Benny Peake self.tags = autotest_job_info.AutotestTaskInfo.tags 101a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 102a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake @property 103a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake def test_case_count(self): 104a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake """The number of test cases run.""" 105a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake return self._summary_block[ACTSSummaryEnums.Requested] 106a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 107a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake @property 108a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake def failed_case_count(self): 109a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake """The number of failed test cases.""" 110a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake return self._summary_block[ACTSSummaryEnums.Failed] 111a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 112a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake @property 113a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake def error_case_count(self): 114a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake """The number of errored test cases.""" 115a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake return self._summary_block[ACTSSummaryEnums.Unknown] 116a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 117a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake @property 118a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake def records(self): 119a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake """All records of test cases in the ACTS tests.""" 120a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake return self._records 121a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 122a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake @property 123405ac5e6f5c66beee3082304a1c0f22f2eb335bdBenny Peake def owner(self): 124405ac5e6f5c66beee3082304a1c0f22f2eb335bdBenny Peake """The owner of the task.""" 125405ac5e6f5c66beee3082304a1c0f22f2eb335bdBenny Peake if 'param-testtracker_owner' in self.keyvals: 12610fde0d929c0f2552060c69da01feff454050607Benny Peake return self.keyvals['param-testtracker_owner'].strip("'").strip('"') 127405ac5e6f5c66beee3082304a1c0f22f2eb335bdBenny Peake elif 'param-test_tracker_owner' in self.keyvals: 12810fde0d929c0f2552060c69da01feff454050607Benny Peake return self.keyvals['param-testtracker_owner'].strip("'").strip('"') 129405ac5e6f5c66beee3082304a1c0f22f2eb335bdBenny Peake else: 13010fde0d929c0f2552060c69da01feff454050607Benny Peake return self._job.user.strip("'").strip('"') 131405ac5e6f5c66beee3082304a1c0f22f2eb335bdBenny Peake 132405ac5e6f5c66beee3082304a1c0f22f2eb335bdBenny Peake @property 133a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake def effort_name(self): 134a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake """The test tracker effort name.""" 1356ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake build_id = self.build_info.get('build_prop', {}).get('ro.build.id') 1366ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake if build_id and any(c.isdigit() for c in build_id): 1376ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake return build_id 1386ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake else: 1396ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake build_version = self.build_info.get('build_prop', {}).get( 1406ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake 'ro.build.version.incremental', UNKNOWN_EFFORT_NAME) 1416ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake return build_version 1426ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake 143a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 144a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake @property 145a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake def project_id(self): 146a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake """The test tracker project id.""" 14745fa8a3818e928bd232ddb9bab6f2fc5f6d83681Benny Peake if 'param-testtracker_project_id' in self.keyvals: 1486ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake return self.keyvals.get('param-testtracker_project_id') 14945fa8a3818e928bd232ddb9bab6f2fc5f6d83681Benny Peake else: 1506ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake return self.keyvals.get('param-test_tracker_project_id') 151a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 152a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake @property 153a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake def environment(self): 154a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake """The name of the enviroment for test tracker.""" 1556057527518a23a0348d2bfaa4dcef2b537bdda3aBenny Peake build_props = self.build_info.get('build_prop', {}) 1566057527518a23a0348d2bfaa4dcef2b537bdda3aBenny Peake 1576057527518a23a0348d2bfaa4dcef2b537bdda3aBenny Peake if 'ro.product.board' in build_props: 1586057527518a23a0348d2bfaa4dcef2b537bdda3aBenny Peake board = build_props['ro.product.board'] 1596057527518a23a0348d2bfaa4dcef2b537bdda3aBenny Peake elif 'ro.build.product' in build_props: 1606057527518a23a0348d2bfaa4dcef2b537bdda3aBenny Peake board = build_props['ro.build.product'] 1616057527518a23a0348d2bfaa4dcef2b537bdda3aBenny Peake else: 1626057527518a23a0348d2bfaa4dcef2b537bdda3aBenny Peake board = UNKNOWN_ENV_NAME 1636057527518a23a0348d2bfaa4dcef2b537bdda3aBenny Peake 1646057527518a23a0348d2bfaa4dcef2b537bdda3aBenny Peake return board 165a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 16654f38a41e6676c65b741932e61cf139a95efd756Benny Peake @property 16754f38a41e6676c65b741932e61cf139a95efd756Benny Peake def extra_environment(self): 16854f38a41e6676c65b741932e61cf139a95efd756Benny Peake """Extra environment info about the task.""" 16954f38a41e6676c65b741932e61cf139a95efd756Benny Peake if 'param-testtracker_extra_env' in self.keyvals: 17054f38a41e6676c65b741932e61cf139a95efd756Benny Peake extra = self.keyvals.get('param-testtracker_extra_env', []) 17154f38a41e6676c65b741932e61cf139a95efd756Benny Peake else: 1726057527518a23a0348d2bfaa4dcef2b537bdda3aBenny Peake extra = self.keyvals.get('param-test_tracker_extra_env', []) 17354f38a41e6676c65b741932e61cf139a95efd756Benny Peake 17454f38a41e6676c65b741932e61cf139a95efd756Benny Peake if not isinstance(extra, list): 17554f38a41e6676c65b741932e61cf139a95efd756Benny Peake extra = [extra] 17654f38a41e6676c65b741932e61cf139a95efd756Benny Peake 17754f38a41e6676c65b741932e61cf139a95efd756Benny Peake return extra 17854f38a41e6676c65b741932e61cf139a95efd756Benny Peake 179a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 180a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peakeclass ACTSRecord(object): 181a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake """A single record of a test case in an ACTS test.""" 182a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 183a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake tags = ['acts', 'testtracker'] 184a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 185a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake def __init__(self, json_record): 186a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake """ 187a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake @param json_record: The json info for this record 188a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake """ 189a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake self._json_record = json_record 190a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 191a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake @property 192a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake def test_class(self): 193a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake """The test class that was run.""" 194a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake return self._json_record[ACTSRecordEnums.TestClass] 195a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 196a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake @property 197a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake def test_case(self): 198a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake """The test case that was run. None implies all in the class.""" 1996ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake return self._json_record.get(ACTSRecordEnums.TestName) 200a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 201a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake @property 202a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake def uid(self): 203a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake """The uid of the test case.""" 2046ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake return self._json_record.get(ACTSRecordEnums.UID) 205a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 206a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake @property 207a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake def status(self): 208a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake """The status of the test case.""" 209a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake return self._json_record[ACTSRecordEnums.Result] 210a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 211a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake @property 212a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake def start_time(self): 213a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake """The start time of the test case.""" 214a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake return self._json_record[ACTSRecordEnums.BeginTime] / 1000.0 215a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 216a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake @property 217a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake def end_time(self): 218a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake """The end time of the test case.""" 219a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake return self._json_record[ACTSRecordEnums.EndTime] / 1000.0 220a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 221a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake @property 222a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake def details(self): 223a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake """Details about the test case.""" 2246ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake return self._json_record.get(ACTSRecordEnums.Details) 225a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 226a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake @property 227a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake def extras(self): 228a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake """Extra info about the test case.""" 2296ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake return self._json_record.get(ACTSRecordEnums.Extras) 230a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 231a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake @property 232a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake def extra_errors(self): 233a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake """Extra errors about the test case.""" 2346ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake return self._json_record.get(ACTSRecordEnums.ExtraErrors) 2356ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake 2366ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake @property 2376ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake def extra_environment(self): 2386ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake """Extra details about the environment for this test.""" 2396ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake extras = self.extras 2406ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake if not extras: 2416ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake return None 2426ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake 2436ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake test_tracker_info = self.extras.get('test_tracker_info') 2446ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake if not test_tracker_info: 2456ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake return self.extras.get('test_tracker_environment_info') 2466ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake 2476ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake return test_tracker_info.get('extra_environment') 248a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 249a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake @property 250a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake def uuid(self): 251a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake """The test tracker uuid of the test case.""" 252a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake extras = self.extras 253a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake if not extras: 254a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake return None 255a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 2566ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake test_tracker_info = self.extras.get('test_tracker_info') 257a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake if not test_tracker_info: 2586ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake return self.extras.get('test_tracker_uuid') 259a6bcf7f18aded465d734820b73eef14a5ec10d46Benny Peake 2606ade820e4f4843cef1b6a4e086db769d6ef088edBenny Peake return test_tracker_info.get('test_tracker_uuid') 261